altavir/diff #494
@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.expressions
|
package space.kscience.kmath.expressions
|
||||||
|
|
||||||
|
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.MutableBuffer
|
import space.kscience.kmath.structures.MutableBuffer
|
||||||
import space.kscience.kmath.structures.MutableBufferFactory
|
import space.kscience.kmath.structures.MutableBufferFactory
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
internal fun <T> MutableBuffer<T>.fill(element: T, fromIndex: Int = 0, toIndex: Int = size) {
|
internal fun <T> MutableBuffer<T>.fill(element: T, fromIndex: Int = 0, toIndex: Int = size) {
|
||||||
@ -54,7 +54,7 @@ internal fun <T> MutableBuffer<T>.fill(element: T, fromIndex: Int = 0, toIndex:
|
|||||||
* @property order Derivation order.
|
* @property order Derivation order.
|
||||||
* @see DerivativeStructure
|
* @see DerivativeStructure
|
||||||
*/
|
*/
|
||||||
internal class DSCompiler<T, out A : Algebra<T>> internal constructor(
|
class DSCompiler<T, out A : Algebra<T>> internal constructor(
|
||||||
val algebra: A,
|
val algebra: A,
|
||||||
val bufferFactory: MutableBufferFactory<T>,
|
val bufferFactory: MutableBufferFactory<T>,
|
||||||
val freeParameters: Int,
|
val freeParameters: Int,
|
||||||
@ -120,8 +120,7 @@ internal class DSCompiler<T, out A : Algebra<T>> internal constructor(
|
|||||||
* This number includes the single 0 order derivative element, which is
|
* This number includes the single 0 order derivative element, which is
|
||||||
* guaranteed to be stored in the first element of the array.
|
* guaranteed to be stored in the first element of the array.
|
||||||
*/
|
*/
|
||||||
val size: Int
|
val size: Int get() = sizes[freeParameters][order]
|
||||||
get() = sizes[freeParameters][order]
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the index of a partial derivative in the array.
|
* Get the index of a partial derivative in the array.
|
||||||
@ -178,7 +177,7 @@ internal fun <T, A> DSCompiler<T, A>.ln(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Field<T>, A : ExponentialOperations<T> = algebra {
|
) where A : Field<T>, A : ExponentialOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
val function = bufferFactory(1 + order) { zero }
|
val function = bufferFactory(1 + order) { zero }
|
||||||
@ -211,7 +210,7 @@ internal fun <T, A> DSCompiler<T, A>.pow(
|
|||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
n: Int,
|
n: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Field<T>, A : PowerOperations<T> = algebra {
|
) where A : Field<T>, A : PowerOperations<T> = algebra {
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
// special case, x^0 = 1 for all x
|
// special case, x^0 = 1 for all x
|
||||||
@ -267,7 +266,7 @@ internal fun <T, A> DSCompiler<T, A>.exp(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Ring<T>, A : ScaleOperations<T>, A : ExponentialOperations<T> = algebra {
|
) where A : Ring<T>, A : ScaleOperations<T>, A : ExponentialOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
val function = bufferFactory(1 + order) { zero }
|
val function = bufferFactory(1 + order) { zero }
|
||||||
@ -290,7 +289,7 @@ internal fun <T, A> DSCompiler<T, A>.sqrt(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Field<T>, A : PowerOperations<T> = algebra {
|
) where A : Field<T>, A : PowerOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
// [x^(1/n), (1/n)x^((1/n)-1), (1-n)/n^2x^((1/n)-2), ... ]
|
// [x^(1/n), (1/n)x^((1/n)-1), (1-n)/n^2x^((1/n)-2), ... ]
|
||||||
@ -351,7 +350,7 @@ internal fun <T, A> DSCompiler<T, A>.pow(
|
|||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
p: Double,
|
p: Double,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Ring<T>, A : NumericAlgebra<T>, A : PowerOperations<T>, A : ScaleOperations<T> = algebra {
|
) where A : Ring<T>, A : NumericAlgebra<T>, A : PowerOperations<T>, A : ScaleOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
// [x^p, px^(p-1), p(p-1)x^(p-2), ... ]
|
// [x^p, px^(p-1), p(p-1)x^(p-2), ... ]
|
||||||
@ -387,7 +386,7 @@ internal fun <T, A> DSCompiler<T, A>.tan(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Ring<T>, A : TrigonometricOperations<T>, A : ScaleOperations<T> = algebra {
|
) where A : Ring<T>, A : TrigonometricOperations<T>, A : ScaleOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
val function = bufferFactory(1 + order) { zero }
|
val function = bufferFactory(1 + order) { zero }
|
||||||
@ -469,7 +468,7 @@ internal fun <T, A> DSCompiler<T, A>.sin(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Ring<T>, A : ScaleOperations<T>, A : TrigonometricOperations<T> = algebra {
|
) where A : Ring<T>, A : ScaleOperations<T>, A : TrigonometricOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
val function = bufferFactory(1 + order) { zero }
|
val function = bufferFactory(1 + order) { zero }
|
||||||
@ -497,7 +496,7 @@ internal fun <T, A> DSCompiler<T, A>.acos(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Field<T>, A : TrigonometricOperations<T>, A : PowerOperations<T> = algebra {
|
) where A : Field<T>, A : TrigonometricOperations<T>, A : PowerOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
val function = bufferFactory(1 + order) { zero }
|
val function = bufferFactory(1 + order) { zero }
|
||||||
@ -559,7 +558,7 @@ internal fun <T, A> DSCompiler<T, A>.asin(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Field<T>, A : TrigonometricOperations<T>, A : PowerOperations<T> = algebra {
|
) where A : Field<T>, A : TrigonometricOperations<T>, A : PowerOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
val function = bufferFactory(1 + order) { zero }
|
val function = bufferFactory(1 + order) { zero }
|
||||||
@ -618,7 +617,7 @@ internal fun <T, A> DSCompiler<T, A>.atan(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Field<T>, A : TrigonometricOperations<T> = algebra {
|
) where A : Field<T>, A : TrigonometricOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
val function = bufferFactory(1 + order) { zero }
|
val function = bufferFactory(1 + order) { zero }
|
||||||
@ -678,7 +677,7 @@ internal fun <T, A> DSCompiler<T, A>.cosh(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Ring<T>, A : ScaleOperations<T>, A : ExponentialOperations<T> = algebra {
|
) where A : Ring<T>, A : ScaleOperations<T>, A : ExponentialOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
val function = bufferFactory(1 + order) { zero }
|
val function = bufferFactory(1 + order) { zero }
|
||||||
@ -708,7 +707,7 @@ internal fun <T, A> DSCompiler<T, A>.tanh(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Field<T>, A : ExponentialOperations<T> = algebra {
|
) where A : Field<T>, A : ExponentialOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
val function = bufferFactory(1 + order) { zero }
|
val function = bufferFactory(1 + order) { zero }
|
||||||
@ -765,7 +764,7 @@ internal fun <T, A> DSCompiler<T, A>.acosh(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Field<T>, A : ExponentialOperations<T>, A : PowerOperations<T> = algebra {
|
) where A : Field<T>, A : ExponentialOperations<T>, A : PowerOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
val function = bufferFactory(1 + order) { zero }
|
val function = bufferFactory(1 + order) { zero }
|
||||||
@ -857,7 +856,7 @@ internal fun <T, A> DSCompiler<T, A>.sinh(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Field<T>, A : ExponentialOperations<T> = algebra {
|
) where A : Field<T>, A : ExponentialOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
val function = bufferFactory(1 + order) { zero }
|
val function = bufferFactory(1 + order) { zero }
|
||||||
@ -964,7 +963,7 @@ internal fun <T, A> DSCompiler<T, A>.asinh(
|
|||||||
operand: Buffer<T>,
|
operand: Buffer<T>,
|
||||||
operandOffset: Int,
|
operandOffset: Int,
|
||||||
result: MutableBuffer<T>,
|
result: MutableBuffer<T>,
|
||||||
resultOffset: Int
|
resultOffset: Int,
|
||||||
) where A : Field<T>, A : ExponentialOperations<T>, A : PowerOperations<T> = algebra {
|
) where A : Field<T>, A : ExponentialOperations<T>, A : PowerOperations<T> = algebra {
|
||||||
// create the function value and derivatives
|
// create the function value and derivatives
|
||||||
val function = bufferFactory(1 + order) { zero }
|
val function = bufferFactory(1 + order) { zero }
|
||||||
@ -1109,59 +1108,6 @@ internal fun <T, A> DSCompiler<T, A>.atanh(
|
|||||||
compose(operand, operandOffset, function, result, resultOffset)
|
compose(operand, operandOffset, function, result, resultOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the compiler for number of free parameters and order.
|
|
||||||
*
|
|
||||||
* @param parameters number of free parameters.
|
|
||||||
* @param order derivation order.
|
|
||||||
* @return cached rules set.
|
|
||||||
*/
|
|
||||||
internal fun <T, A : Algebra<T>> getCompiler(
|
|
||||||
algebra: A,
|
|
||||||
bufferFactory: MutableBufferFactory<T>,
|
|
||||||
parameters: Int,
|
|
||||||
order: Int
|
|
||||||
): DSCompiler<T, A> {
|
|
||||||
// get the cached compilers
|
|
||||||
val cache: Array<Array<DSCompiler<T, A>?>>? = null
|
|
||||||
|
|
||||||
// we need to create more compilers
|
|
||||||
val maxParameters: Int = max(parameters, cache?.size ?: 0)
|
|
||||||
val maxOrder: Int = max(order, if (cache == null) 0 else cache[0].size)
|
|
||||||
val newCache: Array<Array<DSCompiler<T, A>?>> = Array(maxParameters + 1) { arrayOfNulls(maxOrder + 1) }
|
|
||||||
|
|
||||||
if (cache != null) {
|
|
||||||
// preserve the already created compilers
|
|
||||||
for (i in cache.indices) {
|
|
||||||
cache[i].copyInto(newCache[i], endIndex = cache[i].size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the array in increasing diagonal order
|
|
||||||
|
|
||||||
// create the array in increasing diagonal order
|
|
||||||
for (diag in 0..parameters + order) {
|
|
||||||
for (o in max(0, diag - parameters)..min(order, diag)) {
|
|
||||||
val p: Int = diag - o
|
|
||||||
if (newCache[p][o] == null) {
|
|
||||||
val valueCompiler: DSCompiler<T, A>? = if (p == 0) null else newCache[p - 1][o]!!
|
|
||||||
val derivativeCompiler: DSCompiler<T, A>? = if (o == 0) null else newCache[p][o - 1]!!
|
|
||||||
|
|
||||||
newCache[p][o] = DSCompiler(
|
|
||||||
algebra,
|
|
||||||
bufferFactory,
|
|
||||||
p,
|
|
||||||
o,
|
|
||||||
valueCompiler,
|
|
||||||
derivativeCompiler,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newCache[parameters][order]!!
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile the sizes array.
|
* Compile the sizes array.
|
||||||
*
|
*
|
||||||
|
@ -6,10 +6,9 @@
|
|||||||
package space.kscience.kmath.expressions
|
package space.kscience.kmath.expressions
|
||||||
|
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.NumericAlgebra
|
|
||||||
import space.kscience.kmath.operations.Ring
|
import space.kscience.kmath.operations.Ring
|
||||||
import space.kscience.kmath.operations.ScaleOperations
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.MutableBuffer
|
import space.kscience.kmath.structures.asBuffer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class representing both the value and the differentials of a function.
|
* Class representing both the value and the differentials of a function.
|
||||||
@ -28,128 +27,29 @@ import space.kscience.kmath.structures.MutableBuffer
|
|||||||
* [Commons Math's `DerivativeStructure`](https://github.com/apache/commons-math/blob/924f6c357465b39beb50e3c916d5eb6662194175/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/differentiation/DerivativeStructure.java).
|
* [Commons Math's `DerivativeStructure`](https://github.com/apache/commons-math/blob/924f6c357465b39beb50e3c916d5eb6662194175/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/differentiation/DerivativeStructure.java).
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public open class DerivativeStructure<T, A> internal constructor(
|
public open class DerivativeStructure<T, A : Ring<T>> @PublishedApi internal constructor(
|
||||||
internal val derivativeAlgebra: DerivativeStructureRing<T, A>,
|
private val derivativeAlgebra: DerivativeStructureAlgebra<T, A>,
|
||||||
internal val compiler: DSCompiler<T, A>,
|
@PublishedApi internal val data: Buffer<T>,
|
||||||
) where A : Ring<T>, A : NumericAlgebra<T>, A : ScaleOperations<T> {
|
) {
|
||||||
/**
|
|
||||||
* Combined array holding all values.
|
|
||||||
*/
|
|
||||||
internal var data: MutableBuffer<T> =
|
|
||||||
derivativeAlgebra.bufferFactory(compiler.size) { derivativeAlgebra.algebra.zero }
|
|
||||||
|
|
||||||
/**
|
public val compiler: DSCompiler<T, A> get() = derivativeAlgebra.compiler
|
||||||
* Build an instance with all values and derivatives set to 0.
|
|
||||||
*
|
|
||||||
* @param parameters number of free parameters.
|
|
||||||
* @param order derivation order.
|
|
||||||
*/
|
|
||||||
public constructor (
|
|
||||||
derivativeAlgebra: DerivativeStructureRing<T, A>,
|
|
||||||
parameters: Int,
|
|
||||||
order: Int,
|
|
||||||
) : this(
|
|
||||||
derivativeAlgebra,
|
|
||||||
getCompiler<T, A>(derivativeAlgebra.algebra, derivativeAlgebra.bufferFactory, parameters, order),
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build an instance representing a constant value.
|
|
||||||
*
|
|
||||||
* @param parameters number of free parameters.
|
|
||||||
* @param order derivation order.
|
|
||||||
* @param value value of the constant.
|
|
||||||
* @see DerivativeStructure
|
|
||||||
*/
|
|
||||||
public constructor (
|
|
||||||
derivativeAlgebra: DerivativeStructureRing<T, A>,
|
|
||||||
parameters: Int,
|
|
||||||
order: Int,
|
|
||||||
value: T,
|
|
||||||
) : this(
|
|
||||||
derivativeAlgebra,
|
|
||||||
parameters,
|
|
||||||
order,
|
|
||||||
) {
|
|
||||||
data[0] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build an instance representing a variable.
|
|
||||||
*
|
|
||||||
* Instances built using this constructor are considered to be the free variables with respect to which
|
|
||||||
* differentials are computed. As such, their differential with respect to themselves is +1.
|
|
||||||
*
|
|
||||||
* @param parameters number of free parameters.
|
|
||||||
* @param order derivation order.
|
|
||||||
* @param index index of the variable (from 0 to `parameters - 1`).
|
|
||||||
* @param value value of the variable.
|
|
||||||
*/
|
|
||||||
public constructor (
|
|
||||||
derivativeAlgebra: DerivativeStructureRing<T, A>,
|
|
||||||
parameters: Int,
|
|
||||||
order: Int,
|
|
||||||
index: Int,
|
|
||||||
value: T,
|
|
||||||
) : this(derivativeAlgebra, parameters, order, value) {
|
|
||||||
require(index < parameters) { "number is too large: $index >= $parameters" }
|
|
||||||
|
|
||||||
if (order > 0) {
|
|
||||||
// the derivative of the variable with respect to itself is 1.
|
|
||||||
data[getCompiler(derivativeAlgebra.algebra, derivativeAlgebra.bufferFactory, index, order).size] =
|
|
||||||
derivativeAlgebra.algebra.one
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build an instance from all its derivatives.
|
|
||||||
*
|
|
||||||
* @param parameters number of free parameters.
|
|
||||||
* @param order derivation order.
|
|
||||||
* @param derivatives derivatives sorted according to [DSCompiler.getPartialDerivativeIndex].
|
|
||||||
*/
|
|
||||||
public constructor (
|
|
||||||
derivativeAlgebra: DerivativeStructureRing<T, A>,
|
|
||||||
parameters: Int,
|
|
||||||
order: Int,
|
|
||||||
vararg derivatives: T,
|
|
||||||
) : this(
|
|
||||||
derivativeAlgebra,
|
|
||||||
parameters,
|
|
||||||
order,
|
|
||||||
) {
|
|
||||||
require(derivatives.size == data.size) { "dimension mismatch: ${derivatives.size} and ${data.size}" }
|
|
||||||
data = derivativeAlgebra.bufferFactory(data.size) { derivatives[it] }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy constructor.
|
|
||||||
*
|
|
||||||
* @param ds instance to copy.
|
|
||||||
*/
|
|
||||||
internal constructor(ds: DerivativeStructure<T, A>) : this(ds.derivativeAlgebra, ds.compiler) {
|
|
||||||
this.data = ds.data.copy()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of free parameters.
|
* The number of free parameters.
|
||||||
*/
|
*/
|
||||||
public val freeParameters: Int
|
public val freeParameters: Int get() = compiler.freeParameters
|
||||||
get() = compiler.freeParameters
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The derivation order.
|
* The derivation order.
|
||||||
*/
|
*/
|
||||||
public val order: Int
|
public val order: Int get() = compiler.order
|
||||||
get() = compiler.order
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value part of the derivative structure.
|
* The value part of the derivative structure.
|
||||||
*
|
*
|
||||||
* @see getPartialDerivative
|
* @see getPartialDerivative
|
||||||
*/
|
*/
|
||||||
public val value: T
|
public val value: T get() = data[0]
|
||||||
get() = data[0]
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a partial derivative.
|
* Get a partial derivative.
|
||||||
@ -183,4 +83,75 @@ public open class DerivativeStructure<T, A> internal constructor(
|
|||||||
|
|
||||||
public override fun hashCode(): Int =
|
public override fun hashCode(): Int =
|
||||||
227 + 229 * freeParameters + 233 * order + 239 * data.hashCode()
|
227 + 229 * freeParameters + 233 * order + 239 * data.hashCode()
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an instance representing a variable.
|
||||||
|
*
|
||||||
|
* Instances built using this constructor are considered to be the free variables with respect to which
|
||||||
|
* differentials are computed. As such, their differential with respect to themselves is +1.
|
||||||
|
*/
|
||||||
|
public fun <T, A : Ring<T>> variable(
|
||||||
|
derivativeAlgebra: DerivativeStructureAlgebra<T, A>,
|
||||||
|
index: Int,
|
||||||
|
value: T,
|
||||||
|
): DerivativeStructure<T, A> {
|
||||||
|
val compiler = derivativeAlgebra.compiler
|
||||||
|
require(index < compiler.freeParameters) { "number is too large: $index >= ${compiler.freeParameters}" }
|
||||||
|
return DerivativeStructure(derivativeAlgebra, derivativeAlgebra.bufferForVariable(index, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an instance from all its derivatives.
|
||||||
|
*
|
||||||
|
* @param derivatives derivatives sorted according to [DSCompiler.getPartialDerivativeIndex].
|
||||||
|
*/
|
||||||
|
public fun <T, A : Ring<T>> ofDerivatives(
|
||||||
|
derivativeAlgebra: DerivativeStructureAlgebra<T, A>,
|
||||||
|
vararg derivatives: T,
|
||||||
|
): DerivativeStructure<T, A> {
|
||||||
|
val compiler = derivativeAlgebra.compiler
|
||||||
|
require(derivatives.size == compiler.size) { "dimension mismatch: ${derivatives.size} and ${compiler.size}" }
|
||||||
|
val data = derivatives.asBuffer()
|
||||||
|
|
||||||
|
return DerivativeStructure(
|
||||||
|
derivativeAlgebra,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(UnstableKMathAPI::class)
|
||||||
|
private fun <T, A : Ring<T>> DerivativeStructureAlgebra<T, A>.bufferForVariable(index: Int, value: T): Buffer<T> {
|
||||||
|
val buffer = bufferFactory(compiler.size) { algebra.zero }
|
||||||
|
buffer[0] = value
|
||||||
|
if (compiler.order > 0) {
|
||||||
|
// the derivative of the variable with respect to itself is 1.
|
||||||
|
|
||||||
|
val indexOfDerivative = compiler.getPartialDerivativeIndex(*IntArray(numberOfVariables).apply {
|
||||||
|
set(index, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
buffer[indexOfDerivative] = algebra.one
|
||||||
|
}
|
||||||
|
return buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class implementing both [DerivativeStructure] and [Symbol].
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public class DerivativeStructureSymbol<T, A : Ring<T>> internal constructor(
|
||||||
|
derivativeAlgebra: DerivativeStructureAlgebra<T, A>,
|
||||||
|
index: Int,
|
||||||
|
symbol: Symbol,
|
||||||
|
value: T,
|
||||||
|
) : Symbol by symbol, DerivativeStructure<T, A>(
|
||||||
|
derivativeAlgebra, derivativeAlgebra.bufferForVariable(index, value)
|
||||||
|
) {
|
||||||
|
override fun toString(): String = symbol.toString()
|
||||||
|
override fun equals(other: Any?): Boolean = (other as? Symbol) == symbol
|
||||||
|
override fun hashCode(): Int = symbol.hashCode()
|
||||||
}
|
}
|
||||||
|
@ -7,83 +7,89 @@ package space.kscience.kmath.expressions
|
|||||||
|
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
|
import space.kscience.kmath.structures.Buffer
|
||||||
|
import space.kscience.kmath.structures.MutableBuffer
|
||||||
import space.kscience.kmath.structures.MutableBufferFactory
|
import space.kscience.kmath.structures.MutableBufferFactory
|
||||||
import space.kscience.kmath.structures.indices
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
/**
|
|
||||||
* A class implementing both [DerivativeStructure] and [Symbol].
|
|
||||||
*/
|
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class DerivativeStructureSymbol<T, A>(
|
public abstract class DerivativeStructureAlgebra<T, A : Ring<T>>(
|
||||||
derivativeAlgebra: DerivativeStructureRing<T, A>,
|
|
||||||
size: Int,
|
|
||||||
order: Int,
|
|
||||||
index: Int,
|
|
||||||
symbol: Symbol,
|
|
||||||
value: T,
|
|
||||||
) : Symbol by symbol, DerivativeStructure<T, A>(
|
|
||||||
derivativeAlgebra,
|
|
||||||
size,
|
|
||||||
order,
|
|
||||||
index,
|
|
||||||
value
|
|
||||||
) where A : Ring<T>, A : NumericAlgebra<T>, A : ScaleOperations<T> {
|
|
||||||
override fun toString(): String = symbol.toString()
|
|
||||||
override fun equals(other: Any?): Boolean = (other as? Symbol) == symbol
|
|
||||||
override fun hashCode(): Int = symbol.hashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A ring over [DerivativeStructure].
|
|
||||||
*
|
|
||||||
* @property order The derivation order.
|
|
||||||
* @param bindings The map of bindings values. All bindings are considered free parameters.
|
|
||||||
*/
|
|
||||||
@UnstableKMathAPI
|
|
||||||
public open class DerivativeStructureRing<T, A>(
|
|
||||||
public val algebra: A,
|
public val algebra: A,
|
||||||
public val bufferFactory: MutableBufferFactory<T>,
|
public val bufferFactory: MutableBufferFactory<T>,
|
||||||
public val order: Int,
|
public val order: Int,
|
||||||
bindings: Map<Symbol, T>,
|
bindings: Map<Symbol, T>,
|
||||||
) : Ring<DerivativeStructure<T, A>>, ScaleOperations<DerivativeStructure<T, A>>,
|
) : ExpressionAlgebra<T, DerivativeStructure<T, A>> {
|
||||||
NumericAlgebra<DerivativeStructure<T, A>>,
|
|
||||||
ExpressionAlgebra<T, DerivativeStructure<T, A>>,
|
|
||||||
NumbersAddOps<DerivativeStructure<T, A>> where A : Ring<T>, A : NumericAlgebra<T>, A : ScaleOperations<T> {
|
|
||||||
public val numberOfVariables: Int = bindings.size
|
public val numberOfVariables: Int = bindings.size
|
||||||
|
|
||||||
override val zero: DerivativeStructure<T, A> by lazy {
|
|
||||||
DerivativeStructure(
|
/**
|
||||||
this,
|
* Get the compiler for number of free parameters and order.
|
||||||
numberOfVariables,
|
*
|
||||||
order,
|
* @return cached rules set.
|
||||||
)
|
*/
|
||||||
|
@PublishedApi
|
||||||
|
internal val compiler: DSCompiler<T, A> by lazy {
|
||||||
|
// get the cached compilers
|
||||||
|
val cache: Array<Array<DSCompiler<T, A>?>>? = null
|
||||||
|
|
||||||
|
// we need to create more compilers
|
||||||
|
val maxParameters: Int = max(numberOfVariables, cache?.size ?: 0)
|
||||||
|
val maxOrder: Int = max(order, if (cache == null) 0 else cache[0].size)
|
||||||
|
val newCache: Array<Array<DSCompiler<T, A>?>> = Array(maxParameters + 1) { arrayOfNulls(maxOrder + 1) }
|
||||||
|
|
||||||
|
if (cache != null) {
|
||||||
|
// preserve the already created compilers
|
||||||
|
for (i in cache.indices) {
|
||||||
|
cache[i].copyInto(newCache[i], endIndex = cache[i].size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val one: DerivativeStructure<T, A> by lazy {
|
// create the array in increasing diagonal order
|
||||||
DerivativeStructure(
|
for (diag in 0..numberOfVariables + order) {
|
||||||
this,
|
for (o in max(0, diag - numberOfVariables)..min(order, diag)) {
|
||||||
numberOfVariables,
|
val p: Int = diag - o
|
||||||
order,
|
if (newCache[p][o] == null) {
|
||||||
algebra.one,
|
val valueCompiler: DSCompiler<T, A>? = if (p == 0) null else newCache[p - 1][o]!!
|
||||||
|
val derivativeCompiler: DSCompiler<T, A>? = if (o == 0) null else newCache[p][o - 1]!!
|
||||||
|
|
||||||
|
newCache[p][o] = DSCompiler(
|
||||||
|
algebra,
|
||||||
|
bufferFactory,
|
||||||
|
p,
|
||||||
|
o,
|
||||||
|
valueCompiler,
|
||||||
|
derivativeCompiler,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun number(value: Number): DerivativeStructure<T, A> = const(algebra.number(value))
|
return@lazy newCache[numberOfVariables][order]!!
|
||||||
|
}
|
||||||
|
|
||||||
private val variables: Map<Symbol, DerivativeStructureSymbol<T, A>> =
|
private val variables: Map<Symbol, DerivativeStructureSymbol<T, A>> =
|
||||||
bindings.entries.mapIndexed { index, (key, value) ->
|
bindings.entries.mapIndexed { index, (key, value) ->
|
||||||
key to DerivativeStructureSymbol(
|
key to DerivativeStructureSymbol(
|
||||||
this,
|
this,
|
||||||
numberOfVariables,
|
|
||||||
order,
|
|
||||||
index,
|
index,
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
)
|
)
|
||||||
}.toMap()
|
}.toMap()
|
||||||
|
|
||||||
public override fun const(value: T): DerivativeStructure<T, A> =
|
|
||||||
DerivativeStructure(this, numberOfVariables, order, value)
|
|
||||||
|
public override fun const(value: T): DerivativeStructure<T, A> {
|
||||||
|
val buffer = bufferFactory(compiler.size) { algebra.zero }
|
||||||
|
buffer[0] = value
|
||||||
|
|
||||||
|
return DerivativeStructure(
|
||||||
|
this,
|
||||||
|
buffer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol<T, A>? = variables[StringSymbol(value)]
|
override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol<T, A>? = variables[StringSymbol(value)]
|
||||||
|
|
||||||
@ -103,54 +109,99 @@ public open class DerivativeStructureRing<T, A>(
|
|||||||
|
|
||||||
public fun DerivativeStructure<T, A>.derivative(vararg symbols: Symbol): T = derivative(symbols.toList())
|
public fun DerivativeStructure<T, A>.derivative(vararg symbols: Symbol): T = derivative(symbols.toList())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ring over [DerivativeStructure].
|
||||||
|
*
|
||||||
|
* @property order The derivation order.
|
||||||
|
* @param bindings The map of bindings values. All bindings are considered free parameters.
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public open class DerivativeStructureRing<T, A>(
|
||||||
|
algebra: A,
|
||||||
|
bufferFactory: MutableBufferFactory<T>,
|
||||||
|
order: Int,
|
||||||
|
bindings: Map<Symbol, T>,
|
||||||
|
) : DerivativeStructureAlgebra<T, A>(algebra, bufferFactory, order, bindings),
|
||||||
|
Ring<DerivativeStructure<T, A>>, ScaleOperations<DerivativeStructure<T, A>>,
|
||||||
|
NumericAlgebra<DerivativeStructure<T, A>>,
|
||||||
|
NumbersAddOps<DerivativeStructure<T, A>> where A : Ring<T>, A : NumericAlgebra<T>, A : ScaleOperations<T> {
|
||||||
|
|
||||||
|
override fun bindSymbolOrNull(value: String): DerivativeStructureSymbol<T, A>? =
|
||||||
|
super<DerivativeStructureAlgebra>.bindSymbolOrNull(value)
|
||||||
|
|
||||||
override fun DerivativeStructure<T, A>.unaryMinus(): DerivativeStructure<T, A> {
|
override fun DerivativeStructure<T, A>.unaryMinus(): DerivativeStructure<T, A> {
|
||||||
val ds = DerivativeStructure(this@DerivativeStructureRing, compiler)
|
val newData = algebra { data.map(bufferFactory) { -it } }
|
||||||
for (i in ds.data.indices) {
|
return DerivativeStructure(this@DerivativeStructureRing, newData)
|
||||||
ds.data[i] = algebra { -data[i] }
|
|
||||||
}
|
}
|
||||||
return ds
|
|
||||||
|
/**
|
||||||
|
* Create a copy of given [Buffer] and modify it according to [block]
|
||||||
|
*/
|
||||||
|
protected inline fun DerivativeStructure<T, A>.transformDataBuffer(block: DSCompiler<T, A>.(MutableBuffer<T>) -> Unit): DerivativeStructure<T, A> {
|
||||||
|
val newData = bufferFactory(compiler.size) { data[it] }
|
||||||
|
compiler.block(newData)
|
||||||
|
return DerivativeStructure(this@DerivativeStructureRing, newData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun DerivativeStructure<T, A>.mapData(block: (T) -> T): DerivativeStructure<T, A> {
|
||||||
|
val newData: Buffer<T> = data.map(bufferFactory, block)
|
||||||
|
return DerivativeStructure(this@DerivativeStructureRing, newData)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun DerivativeStructure<T, A>.mapDataIndexed(block: (Int, T) -> T): DerivativeStructure<T, A> {
|
||||||
|
val newData: Buffer<T> = data.mapIndexed(bufferFactory, block)
|
||||||
|
return DerivativeStructure(this@DerivativeStructureRing, newData)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val zero: DerivativeStructure<T, A> by lazy {
|
||||||
|
const(algebra.zero)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val one: DerivativeStructure<T, A> by lazy {
|
||||||
|
const(algebra.one)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun number(value: Number): DerivativeStructure<T, A> = const(algebra.number(value))
|
||||||
|
|
||||||
override fun add(left: DerivativeStructure<T, A>, right: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun add(left: DerivativeStructure<T, A>, right: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
||||||
left.compiler.checkCompatibility(right.compiler)
|
left.compiler.checkCompatibility(right.compiler)
|
||||||
val ds = DerivativeStructure(left)
|
return left.transformDataBuffer { result ->
|
||||||
left.compiler.add(left.data, 0, right.data, 0, ds.data, 0)
|
add(left.data, 0, right.data, 0, result, 0)
|
||||||
return ds
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun scale(a: DerivativeStructure<T, A>, value: Double): DerivativeStructure<T, A> {
|
override fun scale(a: DerivativeStructure<T, A>, value: Double): DerivativeStructure<T, A> = algebra {
|
||||||
val ds = DerivativeStructure(a)
|
a.mapData { it.times(value) }
|
||||||
for (i in ds.data.indices) {
|
|
||||||
ds.data[i] = algebra { ds.data[i].times(value) }
|
|
||||||
}
|
|
||||||
return ds
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun multiply(
|
override fun multiply(
|
||||||
left: DerivativeStructure<T, A>,
|
left: DerivativeStructure<T, A>,
|
||||||
right: DerivativeStructure<T, A>
|
right: DerivativeStructure<T, A>,
|
||||||
): DerivativeStructure<T, A> {
|
): DerivativeStructure<T, A> {
|
||||||
left.compiler.checkCompatibility(right.compiler)
|
left.compiler.checkCompatibility(right.compiler)
|
||||||
val result = DerivativeStructure(this, left.compiler)
|
return left.transformDataBuffer { result ->
|
||||||
left.compiler.multiply(left.data, 0, right.data, 0, result.data, 0)
|
multiply(left.data, 0, right.data, 0, result, 0)
|
||||||
return result
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun DerivativeStructure<T, A>.minus(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun DerivativeStructure<T, A>.minus(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
||||||
compiler.checkCompatibility(arg.compiler)
|
compiler.checkCompatibility(arg.compiler)
|
||||||
val ds = DerivativeStructure(this)
|
return transformDataBuffer { result ->
|
||||||
compiler.subtract(data, 0, arg.data, 0, ds.data, 0)
|
subtract(data, 0, arg.data, 0, result, 0)
|
||||||
return ds
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override operator fun DerivativeStructure<T, A>.plus(other: Number): DerivativeStructure<T, A> {
|
override operator fun DerivativeStructure<T, A>.plus(other: Number): DerivativeStructure<T, A> = algebra {
|
||||||
val ds = DerivativeStructure(this)
|
transformDataBuffer {
|
||||||
ds.data[0] = algebra { ds.data[0] + number(other) }
|
it[0] += number(other)
|
||||||
return ds
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override operator fun DerivativeStructure<T, A>.minus(other: Number): DerivativeStructure<T, A> =
|
override operator fun DerivativeStructure<T, A>.minus(other: Number): DerivativeStructure<T, A> =
|
||||||
this + -other.toDouble()
|
this + (-other.toDouble())
|
||||||
|
|
||||||
override operator fun Number.plus(other: DerivativeStructure<T, A>): DerivativeStructure<T, A> = other + this
|
override operator fun Number.plus(other: DerivativeStructure<T, A>): DerivativeStructure<T, A> = other + this
|
||||||
override operator fun Number.minus(other: DerivativeStructure<T, A>): DerivativeStructure<T, A> = other - this
|
override operator fun Number.minus(other: DerivativeStructure<T, A>): DerivativeStructure<T, A> = other - this
|
||||||
@ -194,119 +245,85 @@ public class DerivativeStructureField<T, A : ExtendedField<T>>(
|
|||||||
|
|
||||||
override fun divide(left: DerivativeStructure<T, A>, right: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun divide(left: DerivativeStructure<T, A>, right: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
||||||
left.compiler.checkCompatibility(right.compiler)
|
left.compiler.checkCompatibility(right.compiler)
|
||||||
val result = DerivativeStructure(this, left.compiler)
|
return left.transformDataBuffer { result ->
|
||||||
left.compiler.divide(left.data, 0, right.data, 0, result.data, 0)
|
left.compiler.divide(left.data, 0, right.data, 0, result, 0)
|
||||||
return result
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sin(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun sin(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
sin(arg.data, 0, result, 0)
|
||||||
arg.compiler.sin(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun cos(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun cos(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
cos(arg.data, 0, result, 0)
|
||||||
arg.compiler.cos(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tan(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun tan(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
tan(arg.data, 0, result, 0)
|
||||||
arg.compiler.tan(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun asin(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun asin(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
asin(arg.data, 0, result, 0)
|
||||||
arg.compiler.asin(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun acos(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun acos(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
acos(arg.data, 0, result, 0)
|
||||||
arg.compiler.acos(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun atan(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun atan(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
atan(arg.data, 0, result, 0)
|
||||||
arg.compiler.atan(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sinh(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun sinh(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
sinh(arg.data, 0, result, 0)
|
||||||
arg.compiler.sinh(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun cosh(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun cosh(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
cosh(arg.data, 0, result, 0)
|
||||||
arg.compiler.cosh(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tanh(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun tanh(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
tanh(arg.data, 0, result, 0)
|
||||||
arg.compiler.tanh(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun asinh(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun asinh(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
asinh(arg.data, 0, result, 0)
|
||||||
arg.compiler.asinh(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun acosh(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun acosh(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
acosh(arg.data, 0, result, 0)
|
||||||
arg.compiler.acosh(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun atanh(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun atanh(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
atanh(arg.data, 0, result, 0)
|
||||||
arg.compiler.atanh(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun power(arg: DerivativeStructure<T, A>, pow: Number): DerivativeStructure<T, A> = when (pow) {
|
override fun power(arg: DerivativeStructure<T, A>, pow: Number): DerivativeStructure<T, A> = when (pow) {
|
||||||
is Int -> {
|
is Int -> arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
pow(arg.data, 0, pow, result, 0)
|
||||||
arg.compiler.pow(arg.data, 0, pow, result.data, 0)
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
pow(arg.data, 0, pow.toDouble(), result, 0)
|
||||||
arg.compiler.pow(arg.data, 0, pow.toDouble(), result.data, 0)
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sqrt(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun sqrt(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
sqrt(arg.data, 0, result, 0)
|
||||||
arg.compiler.sqrt(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun power(arg: DerivativeStructure<T, A>, pow: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
public fun power(arg: DerivativeStructure<T, A>, pow: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
||||||
arg.compiler.checkCompatibility(pow.compiler)
|
arg.compiler.checkCompatibility(pow.compiler)
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
return arg.transformDataBuffer { result ->
|
||||||
arg.compiler.pow(arg.data, 0, pow.data, 0, result.data, 0)
|
pow(arg.data, 0, pow.data, 0, result, 0)
|
||||||
return result
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun exp(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun exp(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
exp(arg.data, 0, result, 0)
|
||||||
arg.compiler.exp(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ln(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> {
|
override fun ln(arg: DerivativeStructure<T, A>): DerivativeStructure<T, A> = arg.transformDataBuffer { result ->
|
||||||
val result = DerivativeStructure(this, arg.compiler)
|
ln(arg.data, 0, result, 0)
|
||||||
arg.compiler.ln(arg.data, 0, result.data, 0)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ public interface LinearSpace<T, out A : Ring<T>> {
|
|||||||
*/
|
*/
|
||||||
public fun <T : Any, A : Ring<T>> buffered(
|
public fun <T : Any, A : Ring<T>> buffered(
|
||||||
algebra: A,
|
algebra: A,
|
||||||
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
|
bufferFactory: BufferFactory<T> = BufferFactory(Buffer.Companion::boxing),
|
||||||
): LinearSpace<T, A> = BufferedLinearSpace(BufferRingOps(algebra, bufferFactory))
|
): LinearSpace<T, A> = BufferedLinearSpace(BufferRingOps(algebra, bufferFactory))
|
||||||
|
|
||||||
@Deprecated("use DoubleField.linearSpace")
|
@Deprecated("use DoubleField.linearSpace")
|
||||||
|
@ -27,5 +27,5 @@ public annotation class UnstableKMathAPI
|
|||||||
RequiresOptIn.Level.WARNING,
|
RequiresOptIn.Level.WARNING,
|
||||||
)
|
)
|
||||||
public annotation class PerformancePitfall(
|
public annotation class PerformancePitfall(
|
||||||
val message: String = "Potential performance problem"
|
val message: String = "Potential performance problem",
|
||||||
)
|
)
|
||||||
|
@ -69,7 +69,7 @@ public class MutableBufferND<T>(
|
|||||||
* Transform structure to a new structure using provided [MutableBufferFactory] and optimizing if argument is [MutableBufferND]
|
* Transform structure to a new structure using provided [MutableBufferFactory] and optimizing if argument is [MutableBufferND]
|
||||||
*/
|
*/
|
||||||
public inline fun <T, reified R : Any> MutableStructureND<T>.mapToMutableBuffer(
|
public inline fun <T, reified R : Any> MutableStructureND<T>.mapToMutableBuffer(
|
||||||
factory: MutableBufferFactory<R> = MutableBuffer.Companion::auto,
|
factory: MutableBufferFactory<R> = MutableBufferFactory(MutableBuffer.Companion::auto),
|
||||||
crossinline transform: (T) -> R,
|
crossinline transform: (T) -> R,
|
||||||
): MutableBufferND<R> {
|
): MutableBufferND<R> {
|
||||||
return if (this is MutableBufferND<T>)
|
return if (this is MutableBufferND<T>)
|
||||||
|
@ -120,7 +120,7 @@ public interface StructureND<out T> : Featured<StructureFeature>, WithShape {
|
|||||||
*/
|
*/
|
||||||
public fun <T> buffered(
|
public fun <T> buffered(
|
||||||
strides: Strides,
|
strides: Strides,
|
||||||
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
|
bufferFactory: BufferFactory<T> = BufferFactory(Buffer.Companion::boxing),
|
||||||
initializer: (IntArray) -> T,
|
initializer: (IntArray) -> T,
|
||||||
): BufferND<T> = BufferND(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) })
|
): BufferND<T> = BufferND(strides, bufferFactory(strides.linearSize) { i -> initializer(strides.index(i)) })
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ public interface StructureND<out T> : Featured<StructureFeature>, WithShape {
|
|||||||
|
|
||||||
public fun <T> buffered(
|
public fun <T> buffered(
|
||||||
shape: IntArray,
|
shape: IntArray,
|
||||||
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
|
bufferFactory: BufferFactory<T> = BufferFactory(Buffer.Companion::boxing),
|
||||||
initializer: (IntArray) -> T,
|
initializer: (IntArray) -> T,
|
||||||
): BufferND<T> = buffered(DefaultStrides(shape), bufferFactory, initializer)
|
): BufferND<T> = buffered(DefaultStrides(shape), bufferFactory, initializer)
|
||||||
|
|
||||||
|
@ -6,12 +6,10 @@
|
|||||||
package space.kscience.kmath.operations
|
package space.kscience.kmath.operations
|
||||||
|
|
||||||
import space.kscience.kmath.linear.Point
|
import space.kscience.kmath.linear.Point
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.BufferFactory
|
import space.kscience.kmath.structures.BufferFactory
|
||||||
import space.kscience.kmath.structures.DoubleBuffer
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
import space.kscience.kmath.structures.asBuffer
|
import space.kscience.kmath.structures.asBuffer
|
||||||
|
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,7 +19,7 @@ public abstract class DoubleBufferOps : BufferAlgebra<Double, DoubleField>, Exte
|
|||||||
Norm<Buffer<Double>, Double> {
|
Norm<Buffer<Double>, Double> {
|
||||||
|
|
||||||
override val elementAlgebra: DoubleField get() = DoubleField
|
override val elementAlgebra: DoubleField get() = DoubleField
|
||||||
override val bufferFactory: BufferFactory<Double> get() = ::DoubleBuffer
|
override val bufferFactory: BufferFactory<Double> get() = BufferFactory(::DoubleBuffer)
|
||||||
|
|
||||||
override fun Buffer<Double>.map(block: DoubleField.(Double) -> Double): DoubleBuffer =
|
override fun Buffer<Double>.map(block: DoubleField.(Double) -> Double): DoubleBuffer =
|
||||||
mapInline { DoubleField.block(it) }
|
mapInline { DoubleField.block(it) }
|
||||||
|
@ -61,31 +61,39 @@ public inline fun <reified T> Buffer<T>.toTypedArray(): Array<T> = Array(size, :
|
|||||||
/**
|
/**
|
||||||
* Create a new buffer from this one with the given mapping function and using [Buffer.Companion.auto] buffer factory.
|
* Create a new buffer from this one with the given mapping function and using [Buffer.Companion.auto] buffer factory.
|
||||||
*/
|
*/
|
||||||
public inline fun <T : Any, reified R : Any> Buffer<T>.map(block: (T) -> R): Buffer<R> =
|
public inline fun <T, reified R : Any> Buffer<T>.map(block: (T) -> R): Buffer<R> =
|
||||||
Buffer.auto(size) { block(get(it)) }
|
Buffer.auto(size) { block(get(it)) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new buffer from this one with the given mapping function.
|
* Create a new buffer from this one with the given mapping function.
|
||||||
* Provided [bufferFactory] is used to construct the new buffer.
|
* Provided [bufferFactory] is used to construct the new buffer.
|
||||||
*/
|
*/
|
||||||
public inline fun <T : Any, R : Any> Buffer<T>.map(
|
public inline fun <T, R> Buffer<T>.map(
|
||||||
bufferFactory: BufferFactory<R>,
|
bufferFactory: BufferFactory<R>,
|
||||||
crossinline block: (T) -> R,
|
crossinline block: (T) -> R,
|
||||||
): Buffer<R> = bufferFactory(size) { block(get(it)) }
|
): Buffer<R> = bufferFactory(size) { block(get(it)) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new buffer from this one with the given indexed mapping function.
|
* Create a new buffer from this one with the given mapping (indexed) function.
|
||||||
* Provided [BufferFactory] is used to construct the new buffer.
|
* Provided [bufferFactory] is used to construct the new buffer.
|
||||||
*/
|
*/
|
||||||
public inline fun <T : Any, reified R : Any> Buffer<T>.mapIndexed(
|
public inline fun <T, R> Buffer<T>.mapIndexed(
|
||||||
bufferFactory: BufferFactory<R> = Buffer.Companion::auto,
|
bufferFactory: BufferFactory<R>,
|
||||||
crossinline block: (index: Int, value: T) -> R,
|
crossinline block: (index: Int, value: T) -> R,
|
||||||
): Buffer<R> = bufferFactory(size) { block(it, get(it)) }
|
): Buffer<R> = bufferFactory(size) { block(it, 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 <T, reified R : Any> Buffer<T>.mapIndexed(
|
||||||
|
crossinline block: (index: Int, value: T) -> R,
|
||||||
|
): Buffer<R> = BufferFactory<R>(Buffer.Companion::auto).invoke(size) { block(it, get(it)) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fold given buffer according to [operation]
|
* Fold given buffer according to [operation]
|
||||||
*/
|
*/
|
||||||
public inline fun <T : Any, R> Buffer<T>.fold(initial: R, operation: (acc: R, T) -> R): R {
|
public inline fun <T, R> Buffer<T>.fold(initial: R, operation: (acc: R, T) -> R): R {
|
||||||
var accumulator = initial
|
var accumulator = initial
|
||||||
for (index in this.indices) accumulator = operation(accumulator, get(index))
|
for (index in this.indices) accumulator = operation(accumulator, get(index))
|
||||||
return accumulator
|
return accumulator
|
||||||
@ -95,9 +103,9 @@ public inline fun <T : Any, R> Buffer<T>.fold(initial: R, operation: (acc: R, T)
|
|||||||
* Zip two buffers using given [transform].
|
* Zip two buffers using given [transform].
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public inline fun <T1 : Any, T2 : Any, reified R : Any> Buffer<T1>.zip(
|
public inline fun <T1, T2 : Any, reified R : Any> Buffer<T1>.zip(
|
||||||
other: Buffer<T2>,
|
other: Buffer<T2>,
|
||||||
bufferFactory: BufferFactory<R> = Buffer.Companion::auto,
|
bufferFactory: BufferFactory<R> = BufferFactory(Buffer.Companion::auto),
|
||||||
crossinline transform: (T1, T2) -> R,
|
crossinline transform: (T1, T2) -> R,
|
||||||
): Buffer<R> {
|
): Buffer<R> {
|
||||||
require(size == other.size) { "Buffer size mismatch in zip: expected $size but found ${other.size}" }
|
require(size == other.size) { "Buffer size mismatch in zip: expected $size but found ${other.size}" }
|
||||||
|
@ -14,14 +14,18 @@ import kotlin.reflect.KClass
|
|||||||
*
|
*
|
||||||
* @param T the type of buffer.
|
* @param T the type of buffer.
|
||||||
*/
|
*/
|
||||||
public typealias BufferFactory<T> = (Int, (Int) -> T) -> Buffer<T>
|
public fun interface BufferFactory<T> {
|
||||||
|
public operator fun invoke(size: Int, builder: (Int) -> T): Buffer<T>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that produces [MutableBuffer] from its size and function that supplies values.
|
* Function that produces [MutableBuffer] from its size and function that supplies values.
|
||||||
*
|
*
|
||||||
* @param T the type of buffer.
|
* @param T the type of buffer.
|
||||||
*/
|
*/
|
||||||
public typealias MutableBufferFactory<T> = (Int, (Int) -> T) -> MutableBuffer<T>
|
public fun interface MutableBufferFactory<T>: BufferFactory<T>{
|
||||||
|
override fun invoke(size: Int, builder: (Int) -> T): MutableBuffer<T>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic read-only random-access structure for both primitives and objects.
|
* A generic read-only random-access structure for both primitives and objects.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,7 @@ public class UniformHistogramGroupND<V : Any, A : Field<V>>(
|
|||||||
private val lower: Buffer<Double>,
|
private val lower: Buffer<Double>,
|
||||||
private val upper: Buffer<Double>,
|
private val upper: Buffer<Double>,
|
||||||
private val binNums: IntArray = IntArray(lower.size) { 20 },
|
private val binNums: IntArray = IntArray(lower.size) { 20 },
|
||||||
private val bufferFactory: BufferFactory<V> = Buffer.Companion::boxing,
|
private val bufferFactory: BufferFactory<V> = BufferFactory(Buffer.Companion::boxing),
|
||||||
) : HistogramGroupND<Double, HyperSquareDomain, V> {
|
) : HistogramGroupND<Double, HyperSquareDomain, V> {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -114,7 +114,7 @@ public class UniformHistogramGroupND<V : Any, A : Field<V>>(
|
|||||||
public fun <V : Any, A : Field<V>> Histogram.Companion.uniformNDFromRanges(
|
public fun <V : Any, A : Field<V>> Histogram.Companion.uniformNDFromRanges(
|
||||||
valueAlgebraND: FieldOpsND<V, A>,
|
valueAlgebraND: FieldOpsND<V, A>,
|
||||||
vararg ranges: ClosedFloatingPointRange<Double>,
|
vararg ranges: ClosedFloatingPointRange<Double>,
|
||||||
bufferFactory: BufferFactory<V> = Buffer.Companion::boxing,
|
bufferFactory: BufferFactory<V> = BufferFactory(Buffer.Companion::boxing),
|
||||||
): UniformHistogramGroupND<V, A> = UniformHistogramGroupND(
|
): UniformHistogramGroupND<V, A> = UniformHistogramGroupND(
|
||||||
valueAlgebraND,
|
valueAlgebraND,
|
||||||
ranges.map(ClosedFloatingPointRange<Double>::start).asBuffer(),
|
ranges.map(ClosedFloatingPointRange<Double>::start).asBuffer(),
|
||||||
@ -140,7 +140,7 @@ public fun Histogram.Companion.uniformDoubleNDFromRanges(
|
|||||||
public fun <V : Any, A : Field<V>> Histogram.Companion.uniformNDFromRanges(
|
public fun <V : Any, A : Field<V>> Histogram.Companion.uniformNDFromRanges(
|
||||||
valueAlgebraND: FieldOpsND<V, A>,
|
valueAlgebraND: FieldOpsND<V, A>,
|
||||||
vararg ranges: Pair<ClosedFloatingPointRange<Double>, Int>,
|
vararg ranges: Pair<ClosedFloatingPointRange<Double>, Int>,
|
||||||
bufferFactory: BufferFactory<V> = Buffer.Companion::boxing,
|
bufferFactory: BufferFactory<V> = BufferFactory(Buffer.Companion::boxing),
|
||||||
): UniformHistogramGroupND<V, A> = UniformHistogramGroupND(
|
): UniformHistogramGroupND<V, A> = UniformHistogramGroupND(
|
||||||
valueAlgebraND,
|
valueAlgebraND,
|
||||||
ListBuffer(
|
ListBuffer(
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package space.kscience.kmath.multik
|
package space.kscience.kmath.multik
|
||||||
|
|
||||||
import org.jetbrains.kotlinx.multik.ndarray.data.DataType
|
import org.jetbrains.kotlinx.multik.ndarray.data.DataType
|
||||||
|
import space.kscience.kmath.misc.PerformancePitfall
|
||||||
import space.kscience.kmath.nd.StructureND
|
import space.kscience.kmath.nd.StructureND
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.ExponentialOperations
|
import space.kscience.kmath.operations.ExponentialOperations
|
||||||
@ -22,10 +23,13 @@ public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra<Double, DoubleFi
|
|||||||
|
|
||||||
override fun tan(arg: StructureND<Double>): MultikTensor<Double> = sin(arg) / cos(arg)
|
override fun tan(arg: StructureND<Double>): MultikTensor<Double> = sin(arg) / cos(arg)
|
||||||
|
|
||||||
|
@PerformancePitfall
|
||||||
override fun asin(arg: StructureND<Double>): MultikTensor<Double> = arg.map { asin(it) }
|
override fun asin(arg: StructureND<Double>): MultikTensor<Double> = arg.map { asin(it) }
|
||||||
|
|
||||||
|
@PerformancePitfall
|
||||||
override fun acos(arg: StructureND<Double>): MultikTensor<Double> = arg.map { acos(it) }
|
override fun acos(arg: StructureND<Double>): MultikTensor<Double> = arg.map { acos(it) }
|
||||||
|
|
||||||
|
@PerformancePitfall
|
||||||
override fun atan(arg: StructureND<Double>): MultikTensor<Double> = arg.map { atan(it) }
|
override fun atan(arg: StructureND<Double>): MultikTensor<Double> = arg.map { atan(it) }
|
||||||
|
|
||||||
override fun exp(arg: StructureND<Double>): MultikTensor<Double> = multikMath.mathEx.exp(arg.asMultik().array).wrap()
|
override fun exp(arg: StructureND<Double>): MultikTensor<Double> = multikMath.mathEx.exp(arg.asMultik().array).wrap()
|
||||||
@ -42,10 +46,13 @@ public object MultikDoubleAlgebra : MultikDivisionTensorAlgebra<Double, DoubleFi
|
|||||||
return (expPlus - expMinus) / (expPlus + expMinus)
|
return (expPlus - expMinus) / (expPlus + expMinus)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PerformancePitfall
|
||||||
override fun asinh(arg: StructureND<Double>): MultikTensor<Double> = arg.map { asinh(it) }
|
override fun asinh(arg: StructureND<Double>): MultikTensor<Double> = arg.map { asinh(it) }
|
||||||
|
|
||||||
|
@PerformancePitfall
|
||||||
override fun acosh(arg: StructureND<Double>): MultikTensor<Double> = arg.map { acosh(it) }
|
override fun acosh(arg: StructureND<Double>): MultikTensor<Double> = arg.map { acosh(it) }
|
||||||
|
|
||||||
|
@PerformancePitfall
|
||||||
override fun atanh(arg: StructureND<Double>): MultikTensor<Double> = arg.map { atanh(it) }
|
override fun atanh(arg: StructureND<Double>): MultikTensor<Double> = arg.map { atanh(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public fun interface Sampler<out T : Any> {
|
|||||||
public fun <T : Any> Sampler<T>.sampleBuffer(
|
public fun <T : Any> Sampler<T>.sampleBuffer(
|
||||||
generator: RandomGenerator,
|
generator: RandomGenerator,
|
||||||
size: Int,
|
size: Int,
|
||||||
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
|
bufferFactory: BufferFactory<T> = BufferFactory(Buffer.Companion::boxing),
|
||||||
): Chain<Buffer<T>> {
|
): Chain<Buffer<T>> {
|
||||||
require(size > 1)
|
require(size > 1)
|
||||||
//creating temporary storage once
|
//creating temporary storage once
|
||||||
|
Loading…
Reference in New Issue
Block a user