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 808312877..3ff5fb557 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/misc/AutoDiff.kt @@ -65,7 +65,6 @@ inline fun > F.deriv(body: AutoDiffField.() -> Varia } } - abstract class AutoDiffField> : Field> { abstract val context: F @@ -152,7 +151,6 @@ internal class AutoDiffContext>(override val context: F) : // Basic math (+, -, *, /) - override fun add(a: Variable, b: Variable): Variable = derive(variable { a.value + b.value }) { z -> a.d += z.d b.d += z.d @@ -173,38 +171,66 @@ internal class AutoDiffContext>(override val context: F) : } } -// Extensions for differentiation of various basic mathematical functions - -// x ^ 2 fun > AutoDiffField.sqr(x: Variable): Variable = derive(variable { x.value * x.value }) { z -> x.d += z.d * 2 * x.value } -// x ^ 1/2 fun > AutoDiffField.sqrt(x: Variable): Variable = derive(variable { sqrt(x.value) }) { z -> x.d += z.d * 0.5 / z.value } -// x ^ y (const) fun > AutoDiffField.pow(x: Variable, y: Double): Variable = derive(variable { power(x.value, y) }) { z -> x.d += z.d * y * power(x.value, y - 1) } -fun > AutoDiffField.pow(x: Variable, y: Int): Variable = pow(x, y.toDouble()) +fun > AutoDiffField.pow(x: Variable, y: Int): Variable = + pow(x, y.toDouble()) -// exp(x) fun > AutoDiffField.exp(x: Variable): Variable = derive(variable { exp(x.value) }) { z -> x.d += z.d * z.value } -// ln(x) fun > AutoDiffField.ln(x: Variable): Variable = derive(variable { ln(x.value) }) { z -> x.d += z.d / x.value } -// x ^ y (any) fun > AutoDiffField.pow(x: Variable, y: Variable): Variable = exp(y * ln(x)) -// sin(x) fun > AutoDiffField.sin(x: Variable): Variable = derive(variable { sin(x.value) }) { z -> x.d += z.d * cos(x.value) } -// cos(x) fun > 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 { asin(x.value) }) { z -> x.d += z.d / sqrt(one + x.value * x.value) } + +fun > AutoDiffField.acosh(x: Variable): Variable = + derive(variable { acos(x.value) }) { z -> x.d += z.d / (sqrt((x.value - one) * (x.value + one))) } + +fun > AutoDiffField.atanh(x: Variable): Variable = + derive(variable { atan(x.value) }) { z -> x.d += z.d / (one - x.value * x.value) } +