Dev #194
1
.space.kts
Normal file
1
.space.kts
Normal file
@ -0,0 +1 @@
|
|||||||
|
job("Build") { gradlew("openjdk:11", "build") }
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
|
- Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140).
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
@ -10,7 +10,7 @@
|
|||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140)
|
||||||
### Security
|
### Security
|
||||||
## [0.1.4]
|
## [0.1.4]
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val kmathVersion by extra("0.1.4")
|
val kmathVersion by extra("0.1.4")
|
||||||
|
|
||||||
val bintrayRepo by extra("scientifik")
|
val bintrayRepo by extra("scientifik")
|
||||||
val githubProject by extra("kmath")
|
val githubProject by extra("kmath")
|
||||||
|
|
||||||
@ -18,6 +17,14 @@ allprojects {
|
|||||||
|
|
||||||
group = "kscience.kmath"
|
group = "kscience.kmath"
|
||||||
version = kmathVersion
|
version = kmathVersion
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
extensions.findByType<KotlinProjectExtension>()?.run {
|
||||||
|
sourceSets.all {
|
||||||
|
languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects { if (name.startsWith("kmath")) apply(plugin = "ru.mipt.npm.publish") }
|
subprojects { if (name.startsWith("kmath")) apply(plugin = "ru.mipt.npm.publish") }
|
||||||
|
@ -3,7 +3,6 @@ package scientifik.kmath.structures
|
|||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import scientifik.kmath.operations.RealField
|
import scientifik.kmath.operations.RealField
|
||||||
import scientifik.kmath.operations.invoke
|
import scientifik.kmath.operations.invoke
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
plugins { id("ru.mipt.npm.mpp") }
|
plugins {
|
||||||
|
id("ru.mipt.npm.mpp")
|
||||||
|
}
|
||||||
|
|
||||||
kotlin.sourceSets {
|
kotlin.sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
|
@ -6,6 +6,8 @@ import scientifik.kmath.operations.RealField
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A Mathematical Syntax Tree node for mathematical expressions.
|
* A Mathematical Syntax Tree node for mathematical expressions.
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public sealed class MST {
|
public sealed class MST {
|
||||||
/**
|
/**
|
||||||
@ -48,6 +50,7 @@ public sealed class MST {
|
|||||||
* @receiver the algebra that provides operations.
|
* @receiver the algebra that provides operations.
|
||||||
* @param node the node to evaluate.
|
* @param node the node to evaluate.
|
||||||
* @return the value of expression.
|
* @return the value of expression.
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
|
public fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
|
||||||
is MST.Numeric -> (this as? NumericAlgebra<T>)?.number(node.value)
|
is MST.Numeric -> (this as? NumericAlgebra<T>)?.number(node.value)
|
||||||
|
@ -38,7 +38,8 @@ public object MstSpace : Space<MST>, NumericAlgebra<MST> {
|
|||||||
* [Ring] over [MST] nodes.
|
* [Ring] over [MST] nodes.
|
||||||
*/
|
*/
|
||||||
public object MstRing : Ring<MST>, NumericAlgebra<MST> {
|
public object MstRing : Ring<MST>, NumericAlgebra<MST> {
|
||||||
override val zero: MST = number(0.0)
|
override val zero: MST
|
||||||
|
get() = MstSpace.zero
|
||||||
override val one: MST = number(1.0)
|
override val one: MST = number(1.0)
|
||||||
|
|
||||||
override fun number(value: Number): MST = MstSpace.number(value)
|
override fun number(value: Number): MST = MstSpace.number(value)
|
||||||
@ -59,8 +60,11 @@ public object MstRing : Ring<MST>, NumericAlgebra<MST> {
|
|||||||
* [Field] over [MST] nodes.
|
* [Field] over [MST] nodes.
|
||||||
*/
|
*/
|
||||||
public object MstField : Field<MST> {
|
public object MstField : Field<MST> {
|
||||||
public override val zero: MST = number(0.0)
|
public override val zero: MST
|
||||||
public override val one: MST = number(1.0)
|
get() = MstRing.zero
|
||||||
|
|
||||||
|
public override val one: MST
|
||||||
|
get() = MstRing.one
|
||||||
|
|
||||||
public override fun symbol(value: String): MST = MstRing.symbol(value)
|
public override fun symbol(value: String): MST = MstRing.symbol(value)
|
||||||
public override fun number(value: Number): MST = MstRing.number(value)
|
public override fun number(value: Number): MST = MstRing.number(value)
|
||||||
@ -79,14 +83,25 @@ public object MstField : Field<MST> {
|
|||||||
* [ExtendedField] over [MST] nodes.
|
* [ExtendedField] over [MST] nodes.
|
||||||
*/
|
*/
|
||||||
public object MstExtendedField : ExtendedField<MST> {
|
public object MstExtendedField : ExtendedField<MST> {
|
||||||
override val zero: MST = number(0.0)
|
override val zero: MST
|
||||||
override val one: MST = number(1.0)
|
get() = MstField.zero
|
||||||
|
|
||||||
|
override val one: MST
|
||||||
|
get() = MstField.one
|
||||||
|
|
||||||
|
override fun symbol(value: String): MST = MstField.symbol(value)
|
||||||
override fun sin(arg: MST): MST = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg)
|
override fun sin(arg: MST): MST = unaryOperation(TrigonometricOperations.SIN_OPERATION, arg)
|
||||||
override fun cos(arg: MST): MST = unaryOperation(TrigonometricOperations.COS_OPERATION, arg)
|
override fun cos(arg: MST): MST = unaryOperation(TrigonometricOperations.COS_OPERATION, arg)
|
||||||
|
override fun tan(arg: MST): MST = unaryOperation(TrigonometricOperations.TAN_OPERATION, arg)
|
||||||
override fun asin(arg: MST): MST = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg)
|
override fun asin(arg: MST): MST = unaryOperation(TrigonometricOperations.ASIN_OPERATION, arg)
|
||||||
override fun acos(arg: MST): MST = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg)
|
override fun acos(arg: MST): MST = unaryOperation(TrigonometricOperations.ACOS_OPERATION, arg)
|
||||||
override fun atan(arg: MST): MST = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg)
|
override fun atan(arg: MST): MST = unaryOperation(TrigonometricOperations.ATAN_OPERATION, arg)
|
||||||
|
override fun sinh(arg: MST): MST = unaryOperation(HyperbolicOperations.SINH_OPERATION, arg)
|
||||||
|
override fun cosh(arg: MST): MST = unaryOperation(HyperbolicOperations.COSH_OPERATION, arg)
|
||||||
|
override fun tanh(arg: MST): MST = unaryOperation(HyperbolicOperations.TANH_OPERATION, arg)
|
||||||
|
override fun asinh(arg: MST): MST = unaryOperation(HyperbolicOperations.ASINH_OPERATION, arg)
|
||||||
|
override fun acosh(arg: MST): MST = unaryOperation(HyperbolicOperations.ACOSH_OPERATION, arg)
|
||||||
|
override fun atanh(arg: MST): MST = unaryOperation(HyperbolicOperations.ATANH_OPERATION, arg)
|
||||||
override fun add(a: MST, b: MST): MST = MstField.add(a, b)
|
override fun add(a: MST, b: MST): MST = MstField.add(a, b)
|
||||||
override fun multiply(a: MST, k: Number): MST = MstField.multiply(a, k)
|
override fun multiply(a: MST, k: Number): MST = MstField.multiply(a, k)
|
||||||
override fun multiply(a: MST, b: MST): MST = MstField.multiply(a, b)
|
override fun multiply(a: MST, b: MST): MST = MstField.multiply(a, b)
|
||||||
|
@ -11,6 +11,7 @@ import kotlin.contracts.contract
|
|||||||
*
|
*
|
||||||
* @property algebra the algebra that provides operations.
|
* @property algebra the algebra that provides operations.
|
||||||
* @property mst the [MST] node.
|
* @property mst the [MST] node.
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public class MstExpression<T>(public val algebra: Algebra<T>, public val mst: MST) : Expression<T> {
|
public class MstExpression<T>(public val algebra: Algebra<T>, public val mst: MST) : Expression<T> {
|
||||||
private inner class InnerAlgebra(val arguments: Map<String, T>) : NumericAlgebra<T> {
|
private inner class InnerAlgebra(val arguments: Map<String, T>) : NumericAlgebra<T> {
|
||||||
@ -31,6 +32,8 @@ public class MstExpression<T>(public val algebra: Algebra<T>, public val mst: MS
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds [MstExpression] over [Algebra].
|
* Builds [MstExpression] over [Algebra].
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T : Any, A : Algebra<T>, E : Algebra<MST>> A.mst(
|
public inline fun <reified T : Any, A : Algebra<T>, E : Algebra<MST>> A.mst(
|
||||||
mstAlgebra: E,
|
mstAlgebra: E,
|
||||||
@ -39,6 +42,8 @@ public inline fun <reified T : Any, A : Algebra<T>, E : Algebra<MST>> A.mst(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds [MstExpression] over [Space].
|
* Builds [MstExpression] over [Space].
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T : Any> Space<T>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T> {
|
public inline fun <reified T : Any> Space<T>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T> {
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
@ -47,6 +52,8 @@ public inline fun <reified T : Any> Space<T>.mstInSpace(block: MstSpace.() -> MS
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds [MstExpression] over [Ring].
|
* Builds [MstExpression] over [Ring].
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T : Any> Ring<T>.mstInRing(block: MstRing.() -> MST): MstExpression<T> {
|
public inline fun <reified T : Any> Ring<T>.mstInRing(block: MstRing.() -> MST): MstExpression<T> {
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
@ -55,6 +62,8 @@ public inline fun <reified T : Any> Ring<T>.mstInRing(block: MstRing.() -> MST):
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds [MstExpression] over [Field].
|
* Builds [MstExpression] over [Field].
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T : Any> Field<T>.mstInField(block: MstField.() -> MST): MstExpression<T> {
|
public inline fun <reified T : Any> Field<T>.mstInField(block: MstField.() -> MST): MstExpression<T> {
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
@ -63,6 +72,8 @@ public inline fun <reified T : Any> Field<T>.mstInField(block: MstField.() -> MS
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds [MstExpression] over [ExtendedField].
|
* Builds [MstExpression] over [ExtendedField].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T : Any> Field<T>.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression<T> {
|
public inline fun <reified T : Any> Field<T>.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression<T> {
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
@ -71,6 +82,8 @@ public inline fun <reified T : Any> Field<T>.mstInExtendedField(block: MstExtend
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds [MstExpression] over [FunctionalExpressionSpace].
|
* Builds [MstExpression] over [FunctionalExpressionSpace].
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T : Any, A : Space<T>> FunctionalExpressionSpace<T, A>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T> {
|
public inline fun <reified T : Any, A : Space<T>> FunctionalExpressionSpace<T, A>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T> {
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
@ -79,6 +92,8 @@ public inline fun <reified T : Any, A : Space<T>> FunctionalExpressionSpace<T, A
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds [MstExpression] over [FunctionalExpressionRing].
|
* Builds [MstExpression] over [FunctionalExpressionRing].
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T : Any, A : Ring<T>> FunctionalExpressionRing<T, A>.mstInRing(block: MstRing.() -> MST): MstExpression<T> {
|
public inline fun <reified T : Any, A : Ring<T>> FunctionalExpressionRing<T, A>.mstInRing(block: MstRing.() -> MST): MstExpression<T> {
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
@ -87,6 +102,8 @@ public inline fun <reified T : Any, A : Ring<T>> FunctionalExpressionRing<T, A>.
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds [MstExpression] over [FunctionalExpressionField].
|
* Builds [MstExpression] over [FunctionalExpressionField].
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T : Any, A : Field<T>> FunctionalExpressionField<T, A>.mstInField(block: MstField.() -> MST): MstExpression<T> {
|
public inline fun <reified T : Any, A : Field<T>> FunctionalExpressionField<T, A>.mstInField(block: MstField.() -> MST): MstExpression<T> {
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
@ -95,6 +112,8 @@ public inline fun <reified T : Any, A : Field<T>> FunctionalExpressionField<T, A
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds [MstExpression] over [FunctionalExpressionExtendedField].
|
* Builds [MstExpression] over [FunctionalExpressionExtendedField].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T : Any, A : ExtendedField<T>> FunctionalExpressionExtendedField<T, A>.mstInExtendedField(
|
public inline fun <reified T : Any, A : ExtendedField<T>> FunctionalExpressionExtendedField<T, A>.mstInExtendedField(
|
||||||
block: MstExtendedField.() -> MST
|
block: MstExtendedField.() -> MST
|
||||||
|
@ -17,6 +17,8 @@ import scientifik.kmath.operations.SpaceOperations
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO move to core
|
* TODO move to core
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik and Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public object ArithmeticsEvaluator : Grammar<MST>() {
|
public object ArithmeticsEvaluator : Grammar<MST>() {
|
||||||
// TODO replace with "...".toRegex() when better-parse 0.4.1 is released
|
// TODO replace with "...".toRegex() when better-parse 0.4.1 is released
|
||||||
@ -85,6 +87,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
|
|||||||
*
|
*
|
||||||
* @receiver the string to parse.
|
* @receiver the string to parse.
|
||||||
* @return the [MST] node.
|
* @return the [MST] node.
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public fun String.tryParseMath(): ParseResult<MST> = ArithmeticsEvaluator.tryParseToEnd(this)
|
public fun String.tryParseMath(): ParseResult<MST> = ArithmeticsEvaluator.tryParseToEnd(this)
|
||||||
|
|
||||||
@ -93,5 +96,6 @@ public fun String.tryParseMath(): ParseResult<MST> = ArithmeticsEvaluator.tryPar
|
|||||||
*
|
*
|
||||||
* @receiver the string to parse.
|
* @receiver the string to parse.
|
||||||
* @return the [MST] node.
|
* @return the [MST] node.
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public fun String.parseMath(): MST = ArithmeticsEvaluator.parseToEnd(this)
|
public fun String.parseMath(): MST = ArithmeticsEvaluator.parseToEnd(this)
|
||||||
|
@ -11,7 +11,12 @@ import scientifik.kmath.operations.Algebra
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile given MST to an Expression using AST compiler
|
* Compiles given MST to an Expression using AST compiler.
|
||||||
|
*
|
||||||
|
* @param type the target type.
|
||||||
|
* @param algebra the target algebra.
|
||||||
|
* @return the compiled expression.
|
||||||
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public fun <T : Any> MST.compileWith(type: KClass<T>, algebra: Algebra<T>): Expression<T> {
|
public fun <T : Any> MST.compileWith(type: KClass<T>, algebra: Algebra<T>): Expression<T> {
|
||||||
fun AsmBuilder<T>.visit(node: MST) {
|
fun AsmBuilder<T>.visit(node: MST) {
|
||||||
@ -54,11 +59,15 @@ public fun <T : Any> MST.compileWith(type: KClass<T>, algebra: Algebra<T>): Expr
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile an [MST] to ASM using given algebra
|
* Compiles an [MST] to ASM using given algebra.
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik.
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T : Any> Algebra<T>.expression(mst: MST): Expression<T> = mst.compileWith(T::class, this)
|
public inline fun <reified T : Any> Algebra<T>.expression(mst: MST): Expression<T> = mst.compileWith(T::class, this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimize performance of an [MstExpression] using ASM codegen
|
* Optimizes performance of an [MstExpression] using ASM codegen.
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik.
|
||||||
*/
|
*/
|
||||||
public inline fun <reified T : Any> MstExpression<T>.compile(): Expression<T> = mst.compileWith(T::class, algebra)
|
public inline fun <reified T : Any> MstExpression<T>.compile(): Expression<T> = mst.compileWith(T::class, algebra)
|
||||||
|
@ -20,6 +20,7 @@ import kotlin.reflect.KClass
|
|||||||
* @property algebra the algebra the applied AsmExpressions use.
|
* @property algebra the algebra the applied AsmExpressions use.
|
||||||
* @property className the unique class name of new loaded class.
|
* @property className the unique class name of new loaded class.
|
||||||
* @property invokeLabel0Visitor the function to apply to this object when generating invoke method, label 0.
|
* @property invokeLabel0Visitor the function to apply to this object when generating invoke method, label 0.
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
internal class AsmBuilder<T> internal constructor(
|
internal class AsmBuilder<T> internal constructor(
|
||||||
private val classOfT: KClass<*>,
|
private val classOfT: KClass<*>,
|
||||||
|
@ -2,6 +2,9 @@ package scientifik.kmath.asm.internal
|
|||||||
|
|
||||||
import scientifik.kmath.ast.MST
|
import scientifik.kmath.ast.MST
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents types known in [MST], numbers and general values.
|
||||||
|
*/
|
||||||
internal enum class MstType {
|
internal enum class MstType {
|
||||||
GENERAL,
|
GENERAL,
|
||||||
NUMBER;
|
NUMBER;
|
||||||
|
@ -6,28 +6,37 @@ import org.objectweb.asm.commons.InstructionAdapter
|
|||||||
import scientifik.kmath.ast.MST
|
import scientifik.kmath.ast.MST
|
||||||
import scientifik.kmath.expressions.Expression
|
import scientifik.kmath.expressions.Expression
|
||||||
import scientifik.kmath.operations.Algebra
|
import scientifik.kmath.operations.Algebra
|
||||||
|
import scientifik.kmath.operations.FieldOperations
|
||||||
|
import scientifik.kmath.operations.RingOperations
|
||||||
|
import scientifik.kmath.operations.SpaceOperations
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
private val methodNameAdapters: Map<Pair<String, Int>, String> by lazy {
|
private val methodNameAdapters: Map<Pair<String, Int>, String> by lazy {
|
||||||
hashMapOf(
|
hashMapOf(
|
||||||
"+" to 2 to "add",
|
SpaceOperations.PLUS_OPERATION to 2 to "add",
|
||||||
"*" to 2 to "multiply",
|
RingOperations.TIMES_OPERATION to 2 to "multiply",
|
||||||
"/" to 2 to "divide",
|
FieldOperations.DIV_OPERATION to 2 to "divide",
|
||||||
"+" to 1 to "unaryPlus",
|
SpaceOperations.PLUS_OPERATION to 1 to "unaryPlus",
|
||||||
"-" to 1 to "unaryMinus",
|
SpaceOperations.MINUS_OPERATION to 1 to "unaryMinus",
|
||||||
"-" to 2 to "minus"
|
SpaceOperations.MINUS_OPERATION to 2 to "minus"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns ASM [Type] for given [KClass].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
internal val KClass<*>.asm: Type
|
internal val KClass<*>.asm: Type
|
||||||
get() = Type.getType(java)
|
get() = Type.getType(java)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns singleton array with this value if the [predicate] is true, returns empty array otherwise.
|
* Returns singleton array with this value if the [predicate] is true, returns empty array otherwise.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
internal inline fun <reified T> T.wrapToArrayIf(predicate: (T) -> Boolean): Array<T> {
|
internal inline fun <reified T> T.wrapToArrayIf(predicate: (T) -> Boolean): Array<T> {
|
||||||
contract { callsInPlace(predicate, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(predicate, InvocationKind.EXACTLY_ONCE) }
|
||||||
@ -36,11 +45,15 @@ internal inline fun <reified T> T.wrapToArrayIf(predicate: (T) -> Boolean): Arra
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an [InstructionAdapter] from this [MethodVisitor].
|
* Creates an [InstructionAdapter] from this [MethodVisitor].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
private fun MethodVisitor.instructionAdapter(): InstructionAdapter = InstructionAdapter(this)
|
private fun MethodVisitor.instructionAdapter(): InstructionAdapter = InstructionAdapter(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an [InstructionAdapter] from this [MethodVisitor] and applies [block] to it.
|
* Creates an [InstructionAdapter] from this [MethodVisitor] and applies [block] to it.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.() -> Unit): InstructionAdapter {
|
internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.() -> Unit): InstructionAdapter {
|
||||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||||
@ -49,6 +62,8 @@ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a [Label], then applies it to this visitor.
|
* Constructs a [Label], then applies it to this visitor.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) }
|
internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) }
|
||||||
|
|
||||||
@ -57,6 +72,8 @@ internal fun MethodVisitor.label(): Label = Label().also { visitLabel(it) }
|
|||||||
*
|
*
|
||||||
* This methods helps to avoid collisions of class name to prevent loading several classes with the same name. If there
|
* This methods helps to avoid collisions of class name to prevent loading several classes with the same name. If there
|
||||||
* is a colliding class, change [collision] parameter or leave it `0` to check existing classes recursively.
|
* is a colliding class, change [collision] parameter or leave it `0` to check existing classes recursively.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
internal tailrec fun buildName(mst: MST, collision: Int = 0): String {
|
internal tailrec fun buildName(mst: MST, collision: Int = 0): String {
|
||||||
val name = "scientifik.kmath.asm.generated.AsmCompiledExpression_${mst.hashCode()}_$collision"
|
val name = "scientifik.kmath.asm.generated.AsmCompiledExpression_${mst.hashCode()}_$collision"
|
||||||
@ -76,6 +93,11 @@ internal inline fun ClassWriter(flags: Int, block: ClassWriter.() -> Unit): Clas
|
|||||||
return ClassWriter(flags).apply(block)
|
return ClassWriter(flags).apply(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes [visitField] and applies [block] to the [FieldVisitor].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
internal inline fun ClassWriter.visitField(
|
internal inline fun ClassWriter.visitField(
|
||||||
access: Int,
|
access: Int,
|
||||||
name: String,
|
name: String,
|
||||||
@ -105,7 +127,7 @@ private fun <T> AsmBuilder<T>.findSpecific(context: Algebra<T>, name: String, pa
|
|||||||
* Checks if the target [context] for code generation contains a method with needed [name] and arity, also builds
|
* Checks if the target [context] for code generation contains a method with needed [name] and arity, also builds
|
||||||
* type expectation stack for needed arity.
|
* type expectation stack for needed arity.
|
||||||
*
|
*
|
||||||
* @return `true` if contains, else `false`.
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
private fun <T> AsmBuilder<T>.buildExpectationStack(
|
private fun <T> AsmBuilder<T>.buildExpectationStack(
|
||||||
context: Algebra<T>,
|
context: Algebra<T>,
|
||||||
@ -137,7 +159,7 @@ private fun <T> AsmBuilder<T>.mapTypes(method: Method, parameterTypes: Array<Mst
|
|||||||
* Checks if the target [context] for code generation contains a method with needed [name] and arity and inserts
|
* Checks if the target [context] for code generation contains a method with needed [name] and arity and inserts
|
||||||
* [AsmBuilder.invokeAlgebraOperation] of this method.
|
* [AsmBuilder.invokeAlgebraOperation] of this method.
|
||||||
*
|
*
|
||||||
* @return `true` if contains, else `false`.
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
private fun <T> AsmBuilder<T>.tryInvokeSpecific(
|
private fun <T> AsmBuilder<T>.tryInvokeSpecific(
|
||||||
context: Algebra<T>,
|
context: Algebra<T>,
|
||||||
@ -161,7 +183,9 @@ private fun <T> AsmBuilder<T>.tryInvokeSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds specialized algebra call with option to fallback to generic algebra operation accepting String.
|
* Builds specialized [context] call with option to fallback to generic algebra operation accepting [String].
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
internal inline fun <T> AsmBuilder<T>.buildAlgebraOperationCall(
|
internal inline fun <T> AsmBuilder<T>.buildAlgebraOperationCall(
|
||||||
context: Algebra<T>,
|
context: Algebra<T>,
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
package scientifik.kmath.asm.internal
|
package scientifik.kmath.asm.internal
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets value with given [key] or throws [IllegalStateException] whenever it is not present.
|
||||||
|
*
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
internal fun <K, V> Map<K, V>.getOrFail(key: K, default: V? = null): V =
|
internal fun <K, V> Map<K, V>.getOrFail(key: K, default: V? = null): V =
|
||||||
this[key] ?: default ?: error("Parameter not found: $key")
|
this[key] ?: default ?: error("Parameter not found: $key")
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
plugins { id("ru.mipt.npm.jvm") }
|
plugins {
|
||||||
|
id("ru.mipt.npm.jvm")
|
||||||
|
}
|
||||||
description = "Commons math binding for kmath"
|
description = "Commons math binding for kmath"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -4,7 +4,6 @@ import scientifik.kmath.operations.ExtendedField
|
|||||||
import scientifik.kmath.operations.Field
|
import scientifik.kmath.operations.Field
|
||||||
import scientifik.kmath.operations.Ring
|
import scientifik.kmath.operations.Ring
|
||||||
import scientifik.kmath.operations.Space
|
import scientifik.kmath.operations.Space
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import scientifik.kmath.operations.Ring
|
|||||||
import scientifik.kmath.structures.Matrix
|
import scientifik.kmath.structures.Matrix
|
||||||
import scientifik.kmath.structures.Structure2D
|
import scientifik.kmath.structures.Structure2D
|
||||||
import scientifik.kmath.structures.asBuffer
|
import scientifik.kmath.structures.asBuffer
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import scientifik.kmath.operations.Field
|
|||||||
import scientifik.kmath.operations.invoke
|
import scientifik.kmath.operations.invoke
|
||||||
import scientifik.kmath.operations.sum
|
import scientifik.kmath.operations.sum
|
||||||
import scientifik.kmath.structures.asBuffer
|
import scientifik.kmath.structures.asBuffer
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
@ -209,3 +208,40 @@ public fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.sin(x: Variable<T
|
|||||||
// cos(x)
|
// cos(x)
|
||||||
public fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.cos(x: Variable<T>): Variable<T> =
|
public fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.cos(x: Variable<T>): Variable<T> =
|
||||||
derive(variable { cos(x.value) }) { z -> x.d -= z.d * sin(x.value) }
|
derive(variable { cos(x.value) }) { z -> x.d -= z.d * sin(x.value) }
|
||||||
|
|
||||||
|
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.tan(x: Variable<T>): Variable<T> =
|
||||||
|
derive(variable { tan(x.value) }) { z ->
|
||||||
|
val c = cos(x.value)
|
||||||
|
x.d += z.d / (c * c)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.asin(x: Variable<T>): Variable<T> =
|
||||||
|
derive(variable { asin(x.value) }) { z -> x.d += z.d / sqrt(one - x.value * x.value) }
|
||||||
|
|
||||||
|
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.acos(x: Variable<T>): Variable<T> =
|
||||||
|
derive(variable { acos(x.value) }) { z -> x.d -= z.d / sqrt(one - x.value * x.value) }
|
||||||
|
|
||||||
|
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.atan(x: Variable<T>): Variable<T> =
|
||||||
|
derive(variable { atan(x.value) }) { z -> x.d += z.d / (one + x.value * x.value) }
|
||||||
|
|
||||||
|
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.sinh(x: Variable<T>): Variable<T> =
|
||||||
|
derive(variable { sin(x.value) }) { z -> x.d += z.d * cosh(x.value) }
|
||||||
|
|
||||||
|
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.cosh(x: Variable<T>): Variable<T> =
|
||||||
|
derive(variable { cos(x.value) }) { z -> x.d += z.d * sinh(x.value) }
|
||||||
|
|
||||||
|
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.tanh(x: Variable<T>): Variable<T> =
|
||||||
|
derive(variable { tan(x.value) }) { z ->
|
||||||
|
val c = cosh(x.value)
|
||||||
|
x.d += z.d / (c * c)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.asinh(x: Variable<T>): Variable<T> =
|
||||||
|
derive(variable { asinh(x.value) }) { z -> x.d += z.d / sqrt(one + x.value * x.value) }
|
||||||
|
|
||||||
|
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.acosh(x: Variable<T>): Variable<T> =
|
||||||
|
derive(variable { acosh(x.value) }) { z -> x.d += z.d / (sqrt((x.value - one) * (x.value + one))) }
|
||||||
|
|
||||||
|
fun <T : Any, F : ExtendedField<T>> AutoDiffField<T, F>.atanh(x: Variable<T>): Variable<T> =
|
||||||
|
derive(variable { atanh(x.value) }) { z -> x.d += z.d / (one - x.value * x.value) }
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ public fun <T> Space<T>.sum(data: Sequence<T>): T = data.fold(zero) { left, righ
|
|||||||
* @receiver the algebra that provides addition and division.
|
* @receiver the algebra that provides addition and division.
|
||||||
* @param data the iterable to find average.
|
* @param data the iterable to find average.
|
||||||
* @return the average value.
|
* @return the average value.
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public fun <T> Space<T>.average(data: Iterable<T>): T = sum(data) / data.count()
|
public fun <T> Space<T>.average(data: Iterable<T>): T = sum(data) / data.count()
|
||||||
|
|
||||||
@ -33,6 +34,7 @@ public fun <T> Space<T>.average(data: Iterable<T>): T = sum(data) / data.count()
|
|||||||
* @receiver the algebra that provides addition and division.
|
* @receiver the algebra that provides addition and division.
|
||||||
* @param data the sequence to find average.
|
* @param data the sequence to find average.
|
||||||
* @return the average value.
|
* @return the average value.
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public fun <T> Space<T>.average(data: Sequence<T>): T = sum(data) / data.count()
|
public fun <T> Space<T>.average(data: Sequence<T>): T = sum(data) / data.count()
|
||||||
|
|
||||||
@ -60,6 +62,7 @@ public fun <T> Sequence<T>.sumWith(space: Space<T>): T = space.sum(this)
|
|||||||
* @receiver the iterable to find average.
|
* @receiver the iterable to find average.
|
||||||
* @param space the algebra that provides addition and division.
|
* @param space the algebra that provides addition and division.
|
||||||
* @return the average value.
|
* @return the average value.
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public fun <T> Iterable<T>.averageWith(space: Space<T>): T = space.average(this)
|
public fun <T> Iterable<T>.averageWith(space: Space<T>): T = space.average(this)
|
||||||
|
|
||||||
@ -69,6 +72,7 @@ public fun <T> Iterable<T>.averageWith(space: Space<T>): T = space.average(this)
|
|||||||
* @receiver the sequence to find average.
|
* @receiver the sequence to find average.
|
||||||
* @param space the algebra that provides addition and division.
|
* @param space the algebra that provides addition and division.
|
||||||
* @return the average value.
|
* @return the average value.
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public fun <T> Sequence<T>.averageWith(space: Space<T>): T = space.average(this)
|
public fun <T> Sequence<T>.averageWith(space: Space<T>): T = space.average(this)
|
||||||
|
|
||||||
@ -98,6 +102,7 @@ public fun <T> Ring<T>.power(arg: T, power: Int): T {
|
|||||||
* @param arg the base.
|
* @param arg the base.
|
||||||
* @param power the exponent.
|
* @param power the exponent.
|
||||||
* @return the base raised to the power.
|
* @return the base raised to the power.
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public fun <T> Field<T>.power(arg: T, power: Int): T {
|
public fun <T> Field<T>.power(arg: T, power: Int): T {
|
||||||
require(power != 0 || arg != zero) { "The $zero raised to $power is not defined." }
|
require(power != 0 || arg != zero) { "The $zero raised to $power is not defined." }
|
||||||
|
@ -6,6 +6,7 @@ import scientifik.kmath.structures.MutableBuffer
|
|||||||
import scientifik.memory.MemoryReader
|
import scientifik.memory.MemoryReader
|
||||||
import scientifik.memory.MemorySpec
|
import scientifik.memory.MemorySpec
|
||||||
import scientifik.memory.MemoryWriter
|
import scientifik.memory.MemoryWriter
|
||||||
|
import kotlin.contracts.contract
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,6 +2,7 @@ package scientifik.kmath.structures
|
|||||||
|
|
||||||
import scientifik.kmath.operations.Complex
|
import scientifik.kmath.operations.Complex
|
||||||
import scientifik.kmath.operations.complex
|
import scientifik.kmath.operations.complex
|
||||||
|
import kotlin.contracts.contract
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
|
import kotlin.contracts.contract
|
||||||
import kotlin.experimental.and
|
import kotlin.experimental.and
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specialized [MutableBuffer] implementation over [FloatArray].
|
* Specialized [MutableBuffer] implementation over [FloatArray].
|
||||||
*
|
*
|
||||||
* @property array the underlying array.
|
* @property array the underlying array.
|
||||||
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
public inline class FloatBuffer(public val array: FloatArray) : MutableBuffer<Float> {
|
public inline class FloatBuffer(public val array: FloatArray) : MutableBuffer<Float> {
|
||||||
override val size: Int get() = array.size
|
override val size: Int get() = array.size
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specialized [MutableBuffer] implementation over [IntArray].
|
* Specialized [MutableBuffer] implementation over [IntArray].
|
||||||
*
|
*
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specialized [MutableBuffer] implementation over [DoubleArray].
|
* Specialized [MutableBuffer] implementation over [DoubleArray].
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specialized [MutableBuffer] implementation over [ShortArray].
|
* Specialized [MutableBuffer] implementation over [ShortArray].
|
||||||
*
|
*
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
package scientifik.kmath.linear
|
package scientifik.kmath.linear
|
||||||
|
|
||||||
import scientifik.kmath.structures.Matrix
|
import scientifik.kmath.structures.Matrix
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
@ExperimentalContracts
|
|
||||||
class RealLUSolverTest {
|
class RealLUSolverTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -3,19 +3,19 @@ package scientifik.kmath.misc
|
|||||||
import scientifik.kmath.operations.RealField
|
import scientifik.kmath.operations.RealField
|
||||||
import scientifik.kmath.structures.asBuffer
|
import scientifik.kmath.structures.asBuffer
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
|
import kotlin.math.pow
|
||||||
|
import kotlin.math.sqrt
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class AutoDiffTest {
|
class AutoDiffTest {
|
||||||
fun Variable(int: Int): Variable<Double> = Variable(int.toDouble())
|
inline fun deriv(body: AutoDiffField<Double, RealField>.() -> Variable<Double>): DerivationResult<Double> =
|
||||||
|
|
||||||
fun deriv(body: AutoDiffField<Double, RealField>.() -> Variable<Double>): DerivationResult<Double> =
|
|
||||||
RealField.deriv(body)
|
RealField.deriv(body)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testPlusX2() {
|
fun testPlusX2() {
|
||||||
val x = Variable(3) // diff w.r.t this x at 3
|
val x = Variable(3.0) // diff w.r.t this x at 3
|
||||||
val y = deriv { x + x }
|
val y = deriv { x + x }
|
||||||
assertEquals(6.0, y.value) // y = x + x = 6
|
assertEquals(6.0, y.value) // y = x + x = 6
|
||||||
assertEquals(2.0, y.deriv(x)) // dy/dx = 2
|
assertEquals(2.0, y.deriv(x)) // dy/dx = 2
|
||||||
@ -24,8 +24,8 @@ class AutoDiffTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testPlus() {
|
fun testPlus() {
|
||||||
// two variables
|
// two variables
|
||||||
val x = Variable(2)
|
val x = Variable(2.0)
|
||||||
val y = Variable(3)
|
val y = Variable(3.0)
|
||||||
val z = deriv { x + y }
|
val z = deriv { x + y }
|
||||||
assertEquals(5.0, z.value) // z = x + y = 5
|
assertEquals(5.0, z.value) // z = x + y = 5
|
||||||
assertEquals(1.0, z.deriv(x)) // dz/dx = 1
|
assertEquals(1.0, z.deriv(x)) // dz/dx = 1
|
||||||
@ -35,8 +35,8 @@ class AutoDiffTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testMinus() {
|
fun testMinus() {
|
||||||
// two variables
|
// two variables
|
||||||
val x = Variable(7)
|
val x = Variable(7.0)
|
||||||
val y = Variable(3)
|
val y = Variable(3.0)
|
||||||
val z = deriv { x - y }
|
val z = deriv { x - y }
|
||||||
assertEquals(4.0, z.value) // z = x - y = 4
|
assertEquals(4.0, z.value) // z = x - y = 4
|
||||||
assertEquals(1.0, z.deriv(x)) // dz/dx = 1
|
assertEquals(1.0, z.deriv(x)) // dz/dx = 1
|
||||||
@ -45,7 +45,7 @@ class AutoDiffTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testMulX2() {
|
fun testMulX2() {
|
||||||
val x = Variable(3) // diff w.r.t this x at 3
|
val x = Variable(3.0) // diff w.r.t this x at 3
|
||||||
val y = deriv { x * x }
|
val y = deriv { x * x }
|
||||||
assertEquals(9.0, y.value) // y = x * x = 9
|
assertEquals(9.0, y.value) // y = x * x = 9
|
||||||
assertEquals(6.0, y.deriv(x)) // dy/dx = 2 * x = 7
|
assertEquals(6.0, y.deriv(x)) // dy/dx = 2 * x = 7
|
||||||
@ -53,7 +53,7 @@ class AutoDiffTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSqr() {
|
fun testSqr() {
|
||||||
val x = Variable(3)
|
val x = Variable(3.0)
|
||||||
val y = deriv { sqr(x) }
|
val y = deriv { sqr(x) }
|
||||||
assertEquals(9.0, y.value) // y = x ^ 2 = 9
|
assertEquals(9.0, y.value) // y = x ^ 2 = 9
|
||||||
assertEquals(6.0, y.deriv(x)) // dy/dx = 2 * x = 7
|
assertEquals(6.0, y.deriv(x)) // dy/dx = 2 * x = 7
|
||||||
@ -61,7 +61,7 @@ class AutoDiffTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSqrSqr() {
|
fun testSqrSqr() {
|
||||||
val x = Variable(2)
|
val x = Variable(2.0)
|
||||||
val y = deriv { sqr(sqr(x)) }
|
val y = deriv { sqr(sqr(x)) }
|
||||||
assertEquals(16.0, y.value) // y = x ^ 4 = 16
|
assertEquals(16.0, y.value) // y = x ^ 4 = 16
|
||||||
assertEquals(32.0, y.deriv(x)) // dy/dx = 4 * x^3 = 32
|
assertEquals(32.0, y.deriv(x)) // dy/dx = 4 * x^3 = 32
|
||||||
@ -69,7 +69,7 @@ class AutoDiffTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testX3() {
|
fun testX3() {
|
||||||
val x = Variable(2) // diff w.r.t this x at 2
|
val x = Variable(2.0) // diff w.r.t this x at 2
|
||||||
val y = deriv { x * x * x }
|
val y = deriv { x * x * x }
|
||||||
assertEquals(8.0, y.value) // y = x * x * x = 8
|
assertEquals(8.0, y.value) // y = x * x * x = 8
|
||||||
assertEquals(12.0, y.deriv(x)) // dy/dx = 3 * x * x = 12
|
assertEquals(12.0, y.deriv(x)) // dy/dx = 3 * x * x = 12
|
||||||
@ -77,8 +77,8 @@ class AutoDiffTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDiv() {
|
fun testDiv() {
|
||||||
val x = Variable(5)
|
val x = Variable(5.0)
|
||||||
val y = Variable(2)
|
val y = Variable(2.0)
|
||||||
val z = deriv { x / y }
|
val z = deriv { x / y }
|
||||||
assertEquals(2.5, z.value) // z = x / y = 2.5
|
assertEquals(2.5, z.value) // z = x / y = 2.5
|
||||||
assertEquals(0.5, z.deriv(x)) // dz/dx = 1 / y = 0.5
|
assertEquals(0.5, z.deriv(x)) // dz/dx = 1 / y = 0.5
|
||||||
@ -87,7 +87,7 @@ class AutoDiffTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testPow3() {
|
fun testPow3() {
|
||||||
val x = Variable(2) // diff w.r.t this x at 2
|
val x = Variable(2.0) // diff w.r.t this x at 2
|
||||||
val y = deriv { pow(x, 3) }
|
val y = deriv { pow(x, 3) }
|
||||||
assertEquals(8.0, y.value) // y = x ^ 3 = 8
|
assertEquals(8.0, y.value) // y = x ^ 3 = 8
|
||||||
assertEquals(12.0, y.deriv(x)) // dy/dx = 3 * x ^ 2 = 12
|
assertEquals(12.0, y.deriv(x)) // dy/dx = 3 * x ^ 2 = 12
|
||||||
@ -95,8 +95,8 @@ class AutoDiffTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testPowFull() {
|
fun testPowFull() {
|
||||||
val x = Variable(2)
|
val x = Variable(2.0)
|
||||||
val y = Variable(3)
|
val y = Variable(3.0)
|
||||||
val z = deriv { pow(x, y) }
|
val z = deriv { pow(x, y) }
|
||||||
assertApprox(8.0, z.value) // z = x ^ y = 8
|
assertApprox(8.0, z.value) // z = x ^ y = 8
|
||||||
assertApprox(12.0, z.deriv(x)) // dz/dx = y * x ^ (y - 1) = 12
|
assertApprox(12.0, z.deriv(x)) // dz/dx = y * x ^ (y - 1) = 12
|
||||||
@ -105,7 +105,7 @@ class AutoDiffTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testFromPaper() {
|
fun testFromPaper() {
|
||||||
val x = Variable(3)
|
val x = Variable(3.0)
|
||||||
val y = deriv { 2 * x + x * x * x }
|
val y = deriv { 2 * x + x * x * x }
|
||||||
assertEquals(33.0, y.value) // y = 2 * x + x * x * x = 33
|
assertEquals(33.0, y.value) // y = 2 * x + x * x * x = 33
|
||||||
assertEquals(29.0, y.deriv(x)) // dy/dx = 2 + 3 * x * x = 29
|
assertEquals(29.0, y.deriv(x)) // dy/dx = 2 + 3 * x * x = 29
|
||||||
@ -113,9 +113,9 @@ class AutoDiffTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testInnerVariable() {
|
fun testInnerVariable() {
|
||||||
val x = Variable(1)
|
val x = Variable(1.0)
|
||||||
val y = deriv {
|
val y = deriv {
|
||||||
Variable(1) * x
|
Variable(1.0) * x
|
||||||
}
|
}
|
||||||
assertEquals(1.0, y.value) // y = x ^ n = 1
|
assertEquals(1.0, y.value) // y = x ^ n = 1
|
||||||
assertEquals(1.0, y.deriv(x)) // dy/dx = n * x ^ (n - 1) = n - 1
|
assertEquals(1.0, y.deriv(x)) // dy/dx = n * x ^ (n - 1) = n - 1
|
||||||
@ -124,9 +124,9 @@ class AutoDiffTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testLongChain() {
|
fun testLongChain() {
|
||||||
val n = 10_000
|
val n = 10_000
|
||||||
val x = Variable(1)
|
val x = Variable(1.0)
|
||||||
val y = deriv {
|
val y = deriv {
|
||||||
var res = Variable(1)
|
var res = Variable(1.0)
|
||||||
for (i in 1..n) res *= x
|
for (i in 1..n) res *= x
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
@ -136,7 +136,7 @@ class AutoDiffTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testExample() {
|
fun testExample() {
|
||||||
val x = Variable(2)
|
val x = Variable(2.0)
|
||||||
val y = deriv { sqr(x) + 5 * x + 3 }
|
val y = deriv { sqr(x) + 5 * x + 3 }
|
||||||
assertEquals(17.0, y.value) // the value of result (y)
|
assertEquals(17.0, y.value) // the value of result (y)
|
||||||
assertEquals(9.0, y.deriv(x)) // dy/dx
|
assertEquals(9.0, y.deriv(x)) // dy/dx
|
||||||
@ -144,7 +144,7 @@ class AutoDiffTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSqrt() {
|
fun testSqrt() {
|
||||||
val x = Variable(16)
|
val x = Variable(16.0)
|
||||||
val y = deriv { sqrt(x) }
|
val y = deriv { sqrt(x) }
|
||||||
assertEquals(4.0, y.value) // y = x ^ 1/2 = 4
|
assertEquals(4.0, y.value) // y = x ^ 1/2 = 4
|
||||||
assertEquals(1.0 / 8, y.deriv(x)) // dy/dx = 1/2 / x ^ 1/4 = 1/8
|
assertEquals(1.0 / 8, y.deriv(x)) // dy/dx = 1/2 / x ^ 1/4 = 1/8
|
||||||
@ -152,18 +152,98 @@ class AutoDiffTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSin() {
|
fun testSin() {
|
||||||
val x = Variable(PI / 6)
|
val x = Variable(PI / 6.0)
|
||||||
val y = deriv { sin(x) }
|
val y = deriv { sin(x) }
|
||||||
assertApprox(0.5, y.value) // y = sin(PI/6) = 0.5
|
assertApprox(0.5, y.value) // y = sin(PI/6) = 0.5
|
||||||
assertApprox(kotlin.math.sqrt(3.0) / 2, y.deriv(x)) // dy/dx = cos(PI/6) = sqrt(3)/2
|
assertApprox(sqrt(3.0) / 2, y.deriv(x)) // dy/dx = cos(pi/6) = sqrt(3)/2
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCos() {
|
fun testCos() {
|
||||||
val x = Variable(PI / 6)
|
val x = Variable(PI / 6)
|
||||||
val y = deriv { cos(x) }
|
val y = deriv { cos(x) }
|
||||||
assertApprox(kotlin.math.sqrt(3.0) / 2, y.value) // y = cos(PI/6) = sqrt(3)/2
|
assertApprox(sqrt(3.0) / 2, y.value) //y = cos(pi/6) = sqrt(3)/2
|
||||||
assertApprox(-0.5, y.deriv(x)) // dy/dx = -sin(PI/6) = -0.5
|
assertApprox(-0.5, y.deriv(x)) // dy/dx = -sin(pi/6) = -0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTan() {
|
||||||
|
val x = Variable(PI / 6)
|
||||||
|
val y = deriv { tan(x) }
|
||||||
|
assertApprox(1.0 / sqrt(3.0), y.value) // y = tan(pi/6) = 1/sqrt(3)
|
||||||
|
assertApprox(4.0 / 3.0, y.deriv(x)) // dy/dx = sec(pi/6)^2 = 4/3
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAsin() {
|
||||||
|
val x = Variable(PI / 6)
|
||||||
|
val y = deriv { asin(x) }
|
||||||
|
assertApprox(kotlin.math.asin(PI / 6.0), y.value) // y = asin(pi/6)
|
||||||
|
assertApprox(6.0 / sqrt(36 - PI * PI), y.deriv(x)) // dy/dx = 6/sqrt(36-pi^2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAcos() {
|
||||||
|
val x = Variable(PI / 6)
|
||||||
|
val y = deriv { acos(x) }
|
||||||
|
assertApprox(kotlin.math.acos(PI / 6.0), y.value) // y = acos(pi/6)
|
||||||
|
assertApprox(-6.0 / sqrt(36.0 - PI * PI), y.deriv(x)) // dy/dx = -6/sqrt(36-pi^2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAtan() {
|
||||||
|
val x = Variable(PI / 6)
|
||||||
|
val y = deriv { atan(x) }
|
||||||
|
assertApprox(kotlin.math.atan(PI / 6.0), y.value) // y = atan(pi/6)
|
||||||
|
assertApprox(36.0 / (36.0 + PI * PI), y.deriv(x)) // dy/dx = 36/(36+pi^2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSinh() {
|
||||||
|
val x = Variable(0.0)
|
||||||
|
val y = deriv { sinh(x) }
|
||||||
|
assertApprox(kotlin.math.sinh(0.0), y.value) // y = sinh(0)
|
||||||
|
assertApprox(kotlin.math.cosh(0.0), y.deriv(x)) // dy/dx = cosh(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCosh() {
|
||||||
|
val x = Variable(0.0)
|
||||||
|
val y = deriv { cosh(x) }
|
||||||
|
assertApprox(1.0, y.value) //y = cosh(0)
|
||||||
|
assertApprox(0.0, y.deriv(x)) // dy/dx = sinh(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTanh() {
|
||||||
|
val x = Variable(PI / 6)
|
||||||
|
val y = deriv { tanh(x) }
|
||||||
|
assertApprox(1.0 / sqrt(3.0), y.value) // y = tanh(pi/6)
|
||||||
|
assertApprox(1.0 / kotlin.math.cosh(PI / 6.0).pow(2), y.deriv(x)) // dy/dx = sech(pi/6)^2
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAsinh() {
|
||||||
|
val x = Variable(PI / 6)
|
||||||
|
val y = deriv { asinh(x) }
|
||||||
|
assertApprox(kotlin.math.asinh(PI / 6.0), y.value) // y = asinh(pi/6)
|
||||||
|
assertApprox(6.0 / sqrt(36 + PI * PI), y.deriv(x)) // dy/dx = 6/sqrt(pi^2+36)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAcosh() {
|
||||||
|
val x = Variable(PI / 6)
|
||||||
|
val y = deriv { acosh(x) }
|
||||||
|
assertApprox(kotlin.math.acosh(PI / 6.0), y.value) // y = acosh(pi/6)
|
||||||
|
assertApprox(-6.0 / sqrt(36.0 - PI * PI), y.deriv(x)) // dy/dx = -6/sqrt(36-pi^2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAtanh() {
|
||||||
|
val x = Variable(PI / 6.0)
|
||||||
|
val y = deriv { atanh(x) }
|
||||||
|
assertApprox(kotlin.math.atanh(PI / 6.0), y.value) // y = atanh(pi/6)
|
||||||
|
assertApprox(-36.0 / (PI * PI - 36.0), y.deriv(x)) // dy/dx = -36/(pi^2-36)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
plugins { id("ru.mipt.npm.mpp") }
|
plugins {
|
||||||
|
id("ru.mipt.npm.mpp")
|
||||||
|
}
|
||||||
|
|
||||||
kotlin.sourceSets.commonMain {
|
kotlin.sourceSets.commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -9,7 +9,6 @@ import scientifik.kmath.structures.Buffer
|
|||||||
import scientifik.kmath.structures.Matrix
|
import scientifik.kmath.structures.Matrix
|
||||||
import scientifik.kmath.structures.RealBuffer
|
import scientifik.kmath.structures.RealBuffer
|
||||||
import scientifik.kmath.structures.asIterable
|
import scientifik.kmath.structures.asIterable
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
plugins { id("ru.mipt.npm.mpp") }
|
plugins {
|
||||||
|
id("ru.mipt.npm.mpp")
|
||||||
|
}
|
||||||
|
|
||||||
kotlin.sourceSets.commonMain {
|
kotlin.sourceSets.commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -4,9 +4,6 @@ import scientifik.kmath.domains.Domain
|
|||||||
import scientifik.kmath.linear.Point
|
import scientifik.kmath.linear.Point
|
||||||
import scientifik.kmath.structures.ArrayBuffer
|
import scientifik.kmath.structures.ArrayBuffer
|
||||||
import scientifik.kmath.structures.RealBuffer
|
import scientifik.kmath.structures.RealBuffer
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.InvocationKind
|
|
||||||
import kotlin.contracts.contract
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The bin in the histogram. The histogram is by definition always done in the real space
|
* The bin in the histogram. The histogram is by definition always done in the real space
|
||||||
|
@ -6,7 +6,6 @@ import java.nio.channels.FileChannel
|
|||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.StandardOpenOption
|
import java.nio.file.StandardOpenOption
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
|
@ -13,8 +13,4 @@ kotlin.sourceSets {
|
|||||||
api("org.apache.commons:commons-rng-simple:1.3")
|
api("org.apache.commons:commons-rng-simple:1.3")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jvmTest {
|
|
||||||
languageSettings.useExperimentalAnnotation("kotlinx.coroutines.FlowPreview")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user