diff --git a/.space.kts b/.space.kts new file mode 100644 index 000000000..9dda0cbf7 --- /dev/null +++ b/.space.kts @@ -0,0 +1 @@ +job("Build") { gradlew("openjdk:11", "build") } diff --git a/CHANGELOG.md b/CHANGELOG.md index ba3c5ad89..386e1277e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## [Unreleased] ### Added - +- Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140). ### Changed ### Deprecated @@ -10,7 +10,7 @@ ### Removed ### Fixed - +- `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140) ### Security ## [0.1.4] diff --git a/build.gradle.kts b/build.gradle.kts index aaef0059f..384db5385 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,6 @@ plugins { } val kmathVersion by extra("0.1.4") - val bintrayRepo by extra("scientifik") val githubProject by extra("kmath") @@ -18,6 +17,14 @@ allprojects { group = "kscience.kmath" version = kmathVersion + + afterEvaluate { + extensions.findByType()?.run { + sourceSets.all { + languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") + } + } + } } subprojects { if (name.startsWith("kmath")) apply(plugin = "ru.mipt.npm.publish") } diff --git a/examples/src/main/kotlin/scientifik/kmath/structures/NDField.kt b/examples/src/main/kotlin/scientifik/kmath/structures/NDField.kt index 1bc0ed7c8..54ffcb67c 100644 --- a/examples/src/main/kotlin/scientifik/kmath/structures/NDField.kt +++ b/examples/src/main/kotlin/scientifik/kmath/structures/NDField.kt @@ -3,7 +3,6 @@ package scientifik.kmath.structures import kotlinx.coroutines.GlobalScope import scientifik.kmath.operations.RealField import scientifik.kmath.operations.invoke -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.system.measureTimeMillis diff --git a/kmath-ast/build.gradle.kts b/kmath-ast/build.gradle.kts index c376154b5..3e0a441b7 100644 --- a/kmath-ast/build.gradle.kts +++ b/kmath-ast/build.gradle.kts @@ -1,4 +1,6 @@ -plugins { id("ru.mipt.npm.mpp") } +plugins { + id("ru.mipt.npm.mpp") +} kotlin.sourceSets { commonMain { diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt index 798172799..283a20649 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MST.kt @@ -6,6 +6,8 @@ import scientifik.kmath.operations.RealField /** * A Mathematical Syntax Tree node for mathematical expressions. + * + * @author Alexander Nozik */ public sealed class MST { /** @@ -48,6 +50,7 @@ public sealed class MST { * @receiver the algebra that provides operations. * @param node the node to evaluate. * @return the value of expression. + * @author Alexander Nozik */ public fun Algebra.evaluate(node: MST): T = when (node) { is MST.Numeric -> (this as? NumericAlgebra)?.number(node.value) diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt index 7d13a2b25..8cee0ea0b 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstAlgebra.kt @@ -38,7 +38,8 @@ public object MstSpace : Space, NumericAlgebra { * [Ring] over [MST] nodes. */ public object MstRing : Ring, NumericAlgebra { - override val zero: MST = number(0.0) + override val zero: MST + get() = MstSpace.zero override val one: MST = number(1.0) override fun number(value: Number): MST = MstSpace.number(value) @@ -59,8 +60,11 @@ public object MstRing : Ring, NumericAlgebra { * [Field] over [MST] nodes. */ public object MstField : Field { - public override val zero: MST = number(0.0) - public override val one: MST = number(1.0) + public override val zero: MST + get() = MstRing.zero + + public override val one: MST + get() = MstRing.one public override fun symbol(value: String): MST = MstRing.symbol(value) public override fun number(value: Number): MST = MstRing.number(value) @@ -79,14 +83,25 @@ public object MstField : Field { * [ExtendedField] over [MST] nodes. */ public object MstExtendedField : ExtendedField { - override val zero: MST = number(0.0) - override val one: MST = number(1.0) + override val zero: MST + 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 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 acos(arg: MST): MST = unaryOperation(TrigonometricOperations.ACOS_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 multiply(a: MST, k: Number): MST = MstField.multiply(a, k) override fun multiply(a: MST, b: MST): MST = MstField.multiply(a, b) diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt index 9d8a6a804..d094e2fee 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/MstExpression.kt @@ -11,6 +11,7 @@ import kotlin.contracts.contract * * @property algebra the algebra that provides operations. * @property mst the [MST] node. + * @author Alexander Nozik */ public class MstExpression(public val algebra: Algebra, public val mst: MST) : Expression { private inner class InnerAlgebra(val arguments: Map) : NumericAlgebra { @@ -31,6 +32,8 @@ public class MstExpression(public val algebra: Algebra, public val mst: MS /** * Builds [MstExpression] over [Algebra]. + * + * @author Alexander Nozik */ public inline fun , E : Algebra> A.mst( mstAlgebra: E, @@ -39,6 +42,8 @@ public inline fun , E : Algebra> A.mst( /** * Builds [MstExpression] over [Space]. + * + * @author Alexander Nozik */ public inline fun Space.mstInSpace(block: MstSpace.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -47,6 +52,8 @@ public inline fun Space.mstInSpace(block: MstSpace.() -> MS /** * Builds [MstExpression] over [Ring]. + * + * @author Alexander Nozik */ public inline fun Ring.mstInRing(block: MstRing.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -55,6 +62,8 @@ public inline fun Ring.mstInRing(block: MstRing.() -> MST): /** * Builds [MstExpression] over [Field]. + * + * @author Alexander Nozik */ public inline fun Field.mstInField(block: MstField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -63,6 +72,8 @@ public inline fun Field.mstInField(block: MstField.() -> MS /** * Builds [MstExpression] over [ExtendedField]. + * + * @author Iaroslav Postovalov */ public inline fun Field.mstInExtendedField(block: MstExtendedField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -71,6 +82,8 @@ public inline fun Field.mstInExtendedField(block: MstExtend /** * Builds [MstExpression] over [FunctionalExpressionSpace]. + * + * @author Alexander Nozik */ public inline fun > FunctionalExpressionSpace.mstInSpace(block: MstSpace.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -79,6 +92,8 @@ public inline fun > FunctionalExpressionSpace> FunctionalExpressionRing.mstInRing(block: MstRing.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -87,6 +102,8 @@ public inline fun > FunctionalExpressionRing. /** * Builds [MstExpression] over [FunctionalExpressionField]. + * + * @author Alexander Nozik */ public inline fun > FunctionalExpressionField.mstInField(block: MstField.() -> MST): MstExpression { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } @@ -95,6 +112,8 @@ public inline fun > FunctionalExpressionField> FunctionalExpressionExtendedField.mstInExtendedField( block: MstExtendedField.() -> MST diff --git a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt index 5733649e4..e48b2817f 100644 --- a/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt +++ b/kmath-ast/src/commonMain/kotlin/scientifik/kmath/ast/parser.kt @@ -17,6 +17,8 @@ import scientifik.kmath.operations.SpaceOperations /** * TODO move to core + * + * @author Alexander Nozik and Iaroslav Postovalov */ public object ArithmeticsEvaluator : Grammar() { // TODO replace with "...".toRegex() when better-parse 0.4.1 is released @@ -85,6 +87,7 @@ public object ArithmeticsEvaluator : Grammar() { * * @receiver the string to parse. * @return the [MST] node. + * @author Alexander Nozik */ public fun String.tryParseMath(): ParseResult = ArithmeticsEvaluator.tryParseToEnd(this) @@ -93,5 +96,6 @@ public fun String.tryParseMath(): ParseResult = ArithmeticsEvaluator.tryPar * * @receiver the string to parse. * @return the [MST] node. + * @author Alexander Nozik */ public fun String.parseMath(): MST = ArithmeticsEvaluator.parseToEnd(this) diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt index 5d563aceb..3ca817b63 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/asm.kt @@ -11,7 +11,12 @@ import scientifik.kmath.operations.Algebra 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 MST.compileWith(type: KClass, algebra: Algebra): Expression { fun AsmBuilder.visit(node: MST) { @@ -54,11 +59,15 @@ public fun MST.compileWith(type: KClass, algebra: Algebra): Expr } /** - * Compile an [MST] to ASM using given algebra + * Compiles an [MST] to ASM using given algebra. + * + * @author Alexander Nozik. */ public inline fun Algebra.expression(mst: MST): Expression = 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 MstExpression.compile(): Expression = mst.compileWith(T::class, algebra) diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt index f8c159baf..1cf49a251 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/AsmBuilder.kt @@ -20,6 +20,7 @@ import kotlin.reflect.KClass * @property algebra the algebra the applied AsmExpressions use. * @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. + * @author Iaroslav Postovalov */ internal class AsmBuilder internal constructor( private val classOfT: KClass<*>, diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MstType.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MstType.kt index bf73d304b..81e6791c1 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MstType.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/MstType.kt @@ -2,6 +2,9 @@ package scientifik.kmath.asm.internal import scientifik.kmath.ast.MST +/** + * Represents types known in [MST], numbers and general values. + */ internal enum class MstType { GENERAL, NUMBER; diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt index 6f51fe855..ab29d3614 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/codegenUtils.kt @@ -6,28 +6,37 @@ import org.objectweb.asm.commons.InstructionAdapter import scientifik.kmath.ast.MST import scientifik.kmath.expressions.Expression 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 kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.reflect.KClass private val methodNameAdapters: Map, String> by lazy { hashMapOf( - "+" to 2 to "add", - "*" to 2 to "multiply", - "/" to 2 to "divide", - "+" to 1 to "unaryPlus", - "-" to 1 to "unaryMinus", - "-" to 2 to "minus" + SpaceOperations.PLUS_OPERATION to 2 to "add", + RingOperations.TIMES_OPERATION to 2 to "multiply", + FieldOperations.DIV_OPERATION to 2 to "divide", + SpaceOperations.PLUS_OPERATION to 1 to "unaryPlus", + SpaceOperations.MINUS_OPERATION to 1 to "unaryMinus", + SpaceOperations.MINUS_OPERATION to 2 to "minus" ) } +/** + * Returns ASM [Type] for given [KClass]. + * + * @author Iaroslav Postovalov + */ internal val KClass<*>.asm: Type get() = Type.getType(java) /** * Returns singleton array with this value if the [predicate] is true, returns empty array otherwise. + * + * @author Iaroslav Postovalov */ internal inline fun T.wrapToArrayIf(predicate: (T) -> Boolean): Array { contract { callsInPlace(predicate, InvocationKind.EXACTLY_ONCE) } @@ -36,11 +45,15 @@ internal inline fun T.wrapToArrayIf(predicate: (T) -> Boolean): Arra /** * Creates an [InstructionAdapter] from this [MethodVisitor]. + * + * @author Iaroslav Postovalov */ private fun MethodVisitor.instructionAdapter(): InstructionAdapter = InstructionAdapter(this) /** * Creates an [InstructionAdapter] from this [MethodVisitor] and applies [block] to it. + * + * @author Iaroslav Postovalov */ internal inline fun MethodVisitor.instructionAdapter(block: InstructionAdapter.() -> Unit): InstructionAdapter { 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. + * + * @author Iaroslav Postovalov */ 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 * 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 { 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) } +/** + * Invokes [visitField] and applies [block] to the [FieldVisitor]. + * + * @author Iaroslav Postovalov + */ internal inline fun ClassWriter.visitField( access: Int, name: String, @@ -105,7 +127,7 @@ private fun AsmBuilder.findSpecific(context: Algebra, name: String, pa * Checks if the target [context] for code generation contains a method with needed [name] and arity, also builds * type expectation stack for needed arity. * - * @return `true` if contains, else `false`. + * @author Iaroslav Postovalov */ private fun AsmBuilder.buildExpectationStack( context: Algebra, @@ -137,7 +159,7 @@ private fun AsmBuilder.mapTypes(method: Method, parameterTypes: Array AsmBuilder.tryInvokeSpecific( context: Algebra, @@ -161,7 +183,9 @@ private fun AsmBuilder.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 AsmBuilder.buildAlgebraOperationCall( context: Algebra, diff --git a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/mapIntrinsics.kt b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/mapIntrinsics.kt index 80e83c1bf..997dbbfe5 100644 --- a/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/mapIntrinsics.kt +++ b/kmath-ast/src/jvmMain/kotlin/scientifik/kmath/asm/internal/mapIntrinsics.kt @@ -2,6 +2,11 @@ package scientifik.kmath.asm.internal +/** + * Gets value with given [key] or throws [IllegalStateException] whenever it is not present. + * + * @author Iaroslav Postovalov + */ @JvmOverloads internal fun Map.getOrFail(key: K, default: V? = null): V = this[key] ?: default ?: error("Parameter not found: $key") diff --git a/kmath-commons/build.gradle.kts b/kmath-commons/build.gradle.kts index b64b855a4..ed6452ad8 100644 --- a/kmath-commons/build.gradle.kts +++ b/kmath-commons/build.gradle.kts @@ -1,4 +1,6 @@ -plugins { id("ru.mipt.npm.jvm") } +plugins { + id("ru.mipt.npm.jvm") +} description = "Commons math binding for kmath" dependencies { diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/expressionBuilders.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/expressionBuilders.kt index 737f94b38..3af24b595 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/expressionBuilders.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/expressions/expressionBuilders.kt @@ -4,7 +4,6 @@ import scientifik.kmath.operations.ExtendedField import scientifik.kmath.operations.Field import scientifik.kmath.operations.Ring import scientifik.kmath.operations.Space -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt index 2cd507078..d5f8f8e20 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/FeaturedMatrix.kt @@ -4,7 +4,6 @@ import scientifik.kmath.operations.Ring import scientifik.kmath.structures.Matrix import scientifik.kmath.structures.Structure2D import scientifik.kmath.structures.asBuffer -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.math.sqrt diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt index 6bed19456..1c4cc63b6 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt @@ -6,7 +6,6 @@ import scientifik.kmath.operations.Field import scientifik.kmath.operations.invoke import scientifik.kmath.operations.sum import scientifik.kmath.structures.asBuffer -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -209,3 +208,40 @@ public fun > AutoDiffField.sin(x: Variable> AutoDiffField.cos(x: Variable): Variable = derive(variable { cos(x.value) }) { z -> x.d -= z.d * sin(x.value) } + +fun > AutoDiffField.tan(x: Variable): Variable = + derive(variable { tan(x.value) }) { z -> + val c = cos(x.value) + x.d += z.d / (c * c) + } + +fun > AutoDiffField.asin(x: Variable): Variable = + derive(variable { asin(x.value) }) { z -> x.d += z.d / sqrt(one - x.value * x.value) } + +fun > AutoDiffField.acos(x: Variable): Variable = + derive(variable { acos(x.value) }) { z -> x.d -= z.d / sqrt(one - x.value * x.value) } + +fun > AutoDiffField.atan(x: Variable): Variable = + derive(variable { atan(x.value) }) { z -> x.d += z.d / (one + x.value * x.value) } + +fun > AutoDiffField.sinh(x: Variable): Variable = + derive(variable { sin(x.value) }) { z -> x.d += z.d * cosh(x.value) } + +fun > AutoDiffField.cosh(x: Variable): Variable = + derive(variable { cos(x.value) }) { z -> x.d += z.d * sinh(x.value) } + +fun > AutoDiffField.tanh(x: Variable): Variable = + derive(variable { tan(x.value) }) { z -> + val c = cosh(x.value) + x.d += z.d / (c * c) + } + +fun > AutoDiffField.asinh(x: Variable): Variable = + derive(variable { asinh(x.value) }) { z -> x.d += z.d / sqrt(one + x.value * x.value) } + +fun > AutoDiffField.acosh(x: Variable): Variable = + derive(variable { acosh(x.value) }) { z -> x.d += z.d / (sqrt((x.value - one) * (x.value + one))) } + +fun > AutoDiffField.atanh(x: Variable): Variable = + derive(variable { atanh(x.value) }) { z -> x.d += z.d / (one - x.value * x.value) } + diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt index b80e7582d..1020df7d9 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/AlgebraExtensions.kt @@ -24,6 +24,7 @@ public fun Space.sum(data: Sequence): T = data.fold(zero) { left, righ * @receiver the algebra that provides addition and division. * @param data the iterable to find average. * @return the average value. + * @author Iaroslav Postovalov */ public fun Space.average(data: Iterable): T = sum(data) / data.count() @@ -33,6 +34,7 @@ public fun Space.average(data: Iterable): T = sum(data) / data.count() * @receiver the algebra that provides addition and division. * @param data the sequence to find average. * @return the average value. + * @author Iaroslav Postovalov */ public fun Space.average(data: Sequence): T = sum(data) / data.count() @@ -60,6 +62,7 @@ public fun Sequence.sumWith(space: Space): T = space.sum(this) * @receiver the iterable to find average. * @param space the algebra that provides addition and division. * @return the average value. + * @author Iaroslav Postovalov */ public fun Iterable.averageWith(space: Space): T = space.average(this) @@ -69,6 +72,7 @@ public fun Iterable.averageWith(space: Space): T = space.average(this) * @receiver the sequence to find average. * @param space the algebra that provides addition and division. * @return the average value. + * @author Iaroslav Postovalov */ public fun Sequence.averageWith(space: Space): T = space.average(this) @@ -98,6 +102,7 @@ public fun Ring.power(arg: T, power: Int): T { * @param arg the base. * @param power the exponent. * @return the base raised to the power. + * @author Iaroslav Postovalov */ public fun Field.power(arg: T, power: Int): T { require(power != 0 || arg != zero) { "The $zero raised to $power is not defined." } diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt index 20decf0e0..05a592e97 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Complex.kt @@ -6,6 +6,7 @@ import scientifik.kmath.structures.MutableBuffer import scientifik.memory.MemoryReader import scientifik.memory.MemorySpec import scientifik.memory.MemoryWriter +import kotlin.contracts.contract import kotlin.math.* /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt index d44100037..4326159d3 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/Buffers.kt @@ -2,6 +2,7 @@ package scientifik.kmath.structures import scientifik.kmath.operations.Complex import scientifik.kmath.operations.complex +import kotlin.contracts.contract import kotlin.reflect.KClass /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt index d1165b895..f627ede07 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FlaggedBuffer.kt @@ -1,5 +1,6 @@ package scientifik.kmath.structures +import kotlin.contracts.contract import kotlin.experimental.and /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt index 48947b8d7..4bf7d6ad2 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/FloatBuffer.kt @@ -1,12 +1,12 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract /** * Specialized [MutableBuffer] implementation over [FloatArray]. * * @property array the underlying array. + * @author Iaroslav Postovalov */ public inline class FloatBuffer(public val array: FloatArray) : MutableBuffer { override val size: Int get() = array.size diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt index 49cc06755..7daa48201 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/IntBuffer.kt @@ -1,5 +1,7 @@ package scientifik.kmath.structures +import kotlin.contracts.contract + /** * Specialized [MutableBuffer] implementation over [IntArray]. * diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt index f6c3421cd..f87fdc705 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/LongBuffer.kt @@ -1,6 +1,5 @@ package scientifik.kmath.structures -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract /** diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt index 050e5eddb..dbb599c85 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/RealBuffer.kt @@ -1,5 +1,7 @@ package scientifik.kmath.structures +import kotlin.contracts.contract + /** * Specialized [MutableBuffer] implementation over [DoubleArray]. * diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt index de26da460..b364630f7 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/structures/ShortBuffer.kt @@ -1,5 +1,7 @@ package scientifik.kmath.structures +import kotlin.contracts.contract + /** * Specialized [MutableBuffer] implementation over [ShortArray]. * diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt index 34bd8a0e3..9de9fb575 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt +++ b/kmath-core/src/commonTest/kotlin/scientifik/kmath/linear/RealLUSolverTest.kt @@ -1,11 +1,9 @@ package scientifik.kmath.linear import scientifik.kmath.structures.Matrix -import kotlin.contracts.ExperimentalContracts import kotlin.test.Test import kotlin.test.assertEquals -@ExperimentalContracts class RealLUSolverTest { @Test diff --git a/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt b/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt index c08a63ccb..91d32cf8e 100644 --- a/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt +++ b/kmath-core/src/commonTest/kotlin/scientifik/kmath/misc/AutoDiffTest.kt @@ -3,19 +3,19 @@ package scientifik.kmath.misc import scientifik.kmath.operations.RealField import scientifik.kmath.structures.asBuffer import kotlin.math.PI +import kotlin.math.pow +import kotlin.math.sqrt import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue class AutoDiffTest { - fun Variable(int: Int): Variable = Variable(int.toDouble()) - - fun deriv(body: AutoDiffField.() -> Variable): DerivationResult = + inline fun deriv(body: AutoDiffField.() -> Variable): DerivationResult = RealField.deriv(body) @Test 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 } assertEquals(6.0, y.value) // y = x + x = 6 assertEquals(2.0, y.deriv(x)) // dy/dx = 2 @@ -24,8 +24,8 @@ class AutoDiffTest { @Test fun testPlus() { // two variables - val x = Variable(2) - val y = Variable(3) + val x = Variable(2.0) + val y = Variable(3.0) val z = deriv { x + y } assertEquals(5.0, z.value) // z = x + y = 5 assertEquals(1.0, z.deriv(x)) // dz/dx = 1 @@ -35,8 +35,8 @@ class AutoDiffTest { @Test fun testMinus() { // two variables - val x = Variable(7) - val y = Variable(3) + val x = Variable(7.0) + val y = Variable(3.0) val z = deriv { x - y } assertEquals(4.0, z.value) // z = x - y = 4 assertEquals(1.0, z.deriv(x)) // dz/dx = 1 @@ -45,7 +45,7 @@ class AutoDiffTest { @Test 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 } assertEquals(9.0, y.value) // y = x * x = 9 assertEquals(6.0, y.deriv(x)) // dy/dx = 2 * x = 7 @@ -53,7 +53,7 @@ class AutoDiffTest { @Test fun testSqr() { - val x = Variable(3) + val x = Variable(3.0) val y = deriv { sqr(x) } assertEquals(9.0, y.value) // y = x ^ 2 = 9 assertEquals(6.0, y.deriv(x)) // dy/dx = 2 * x = 7 @@ -61,7 +61,7 @@ class AutoDiffTest { @Test fun testSqrSqr() { - val x = Variable(2) + val x = Variable(2.0) val y = deriv { sqr(sqr(x)) } assertEquals(16.0, y.value) // y = x ^ 4 = 16 assertEquals(32.0, y.deriv(x)) // dy/dx = 4 * x^3 = 32 @@ -69,7 +69,7 @@ class AutoDiffTest { @Test 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 } assertEquals(8.0, y.value) // y = x * x * x = 8 assertEquals(12.0, y.deriv(x)) // dy/dx = 3 * x * x = 12 @@ -77,8 +77,8 @@ class AutoDiffTest { @Test fun testDiv() { - val x = Variable(5) - val y = Variable(2) + val x = Variable(5.0) + val y = Variable(2.0) val z = deriv { x / y } assertEquals(2.5, z.value) // z = x / y = 2.5 assertEquals(0.5, z.deriv(x)) // dz/dx = 1 / y = 0.5 @@ -87,7 +87,7 @@ class AutoDiffTest { @Test 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) } assertEquals(8.0, y.value) // y = x ^ 3 = 8 assertEquals(12.0, y.deriv(x)) // dy/dx = 3 * x ^ 2 = 12 @@ -95,8 +95,8 @@ class AutoDiffTest { @Test fun testPowFull() { - val x = Variable(2) - val y = Variable(3) + val x = Variable(2.0) + val y = Variable(3.0) val z = deriv { pow(x, y) } assertApprox(8.0, z.value) // z = x ^ y = 8 assertApprox(12.0, z.deriv(x)) // dz/dx = y * x ^ (y - 1) = 12 @@ -105,7 +105,7 @@ class AutoDiffTest { @Test fun testFromPaper() { - val x = Variable(3) + val x = Variable(3.0) val y = deriv { 2 * x + x * x * x } 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 @@ -113,9 +113,9 @@ class AutoDiffTest { @Test fun testInnerVariable() { - val x = Variable(1) + val x = Variable(1.0) val y = deriv { - Variable(1) * x + Variable(1.0) * x } assertEquals(1.0, y.value) // y = x ^ n = 1 assertEquals(1.0, y.deriv(x)) // dy/dx = n * x ^ (n - 1) = n - 1 @@ -124,9 +124,9 @@ class AutoDiffTest { @Test fun testLongChain() { val n = 10_000 - val x = Variable(1) + val x = Variable(1.0) val y = deriv { - var res = Variable(1) + var res = Variable(1.0) for (i in 1..n) res *= x res } @@ -136,7 +136,7 @@ class AutoDiffTest { @Test fun testExample() { - val x = Variable(2) + val x = Variable(2.0) val y = deriv { sqr(x) + 5 * x + 3 } assertEquals(17.0, y.value) // the value of result (y) assertEquals(9.0, y.deriv(x)) // dy/dx @@ -144,7 +144,7 @@ class AutoDiffTest { @Test fun testSqrt() { - val x = Variable(16) + val x = Variable(16.0) val y = deriv { sqrt(x) } 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 @@ -152,18 +152,98 @@ class AutoDiffTest { @Test fun testSin() { - val x = Variable(PI / 6) + val x = Variable(PI / 6.0) val y = deriv { sin(x) } - 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(0.5, y.value) // y = sin(PI/6) = 0.5 + assertApprox(sqrt(3.0) / 2, y.deriv(x)) // dy/dx = cos(pi/6) = sqrt(3)/2 } @Test fun testCos() { val x = Variable(PI / 6) val y = deriv { cos(x) } - assertApprox(kotlin.math.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(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 + } + + @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 diff --git a/kmath-for-real/build.gradle.kts b/kmath-for-real/build.gradle.kts index 00abcb934..2a4539c10 100644 --- a/kmath-for-real/build.gradle.kts +++ b/kmath-for-real/build.gradle.kts @@ -1,4 +1,6 @@ -plugins { id("ru.mipt.npm.mpp") } +plugins { + id("ru.mipt.npm.mpp") +} kotlin.sourceSets.commonMain { dependencies { diff --git a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt index f406c0aad..1bc5f0a5b 100644 --- a/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt +++ b/kmath-for-real/src/commonMain/kotlin/scientifik/kmath/real/realMatrix.kt @@ -9,7 +9,6 @@ import scientifik.kmath.structures.Buffer import scientifik.kmath.structures.Matrix import scientifik.kmath.structures.RealBuffer import scientifik.kmath.structures.asIterable -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.math.pow diff --git a/kmath-functions/build.gradle.kts b/kmath-functions/build.gradle.kts index 00abcb934..2a4539c10 100644 --- a/kmath-functions/build.gradle.kts +++ b/kmath-functions/build.gradle.kts @@ -1,4 +1,6 @@ -plugins { id("ru.mipt.npm.mpp") } +plugins { + id("ru.mipt.npm.mpp") +} kotlin.sourceSets.commonMain { dependencies { diff --git a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt b/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt index 530dee4f2..4ecd62809 100644 --- a/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt +++ b/kmath-histograms/src/commonMain/kotlin/scientifik/kmath/histogram/Histogram.kt @@ -4,9 +4,6 @@ import scientifik.kmath.domains.Domain import scientifik.kmath.linear.Point import scientifik.kmath.structures.ArrayBuffer 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 diff --git a/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt b/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt index e98340a44..0e7c49c74 100644 --- a/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt +++ b/kmath-memory/src/jvmMain/kotlin/scientifik/memory/ByteBufferMemory.kt @@ -6,7 +6,6 @@ import java.nio.channels.FileChannel import java.nio.file.Files import java.nio.file.Path import java.nio.file.StandardOpenOption -import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract diff --git a/kmath-prob/build.gradle.kts b/kmath-prob/build.gradle.kts index 795a8760e..4c9663e5f 100644 --- a/kmath-prob/build.gradle.kts +++ b/kmath-prob/build.gradle.kts @@ -13,8 +13,4 @@ kotlin.sourceSets { api("org.apache.commons:commons-rng-simple:1.3") } } - - jvmTest { - languageSettings.useExperimentalAnnotation("kotlinx.coroutines.FlowPreview") - } }