Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/cpp/cseval/cseval.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ right path of the derivative");
// exponentiation for the computation of the derivative (left path)
static Real _pow1(Real a, Real b) { return (b * _pow(a, b - ONE)); }
// exponentiation for the computation of the derivative (right path)
// TODO test log()
static Real _pow2(Real a, Real b) { return (_log(a) * _pow(a, b)); }
//- general static methods

Expand Down Expand Up @@ -282,7 +281,6 @@ the natural logarithm derivative");
}
// "sqrt" - square root
static Real _sqrt(Real a) { return sqrt(a); }
// TODO test _sqrt_d()
// "sqrt" for the derivative
static Real _sqrt_d(Real a, Real) {
if (sqrt(a) == ZERO) {
Expand Down
2 changes: 0 additions & 2 deletions src/cpp/cseval/cseval_complex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ right path of the derivative");
// exponentiation for the computation of the derivative (left path)
static Complex _pow1(Complex a, Complex b) { return (b * _pow(a, b - ONE)); }
// exponentiation for the computation of the derivative (right path)
// TODO test log()
static Complex _pow2(Complex a, Complex b) { return (_log(a) * _pow(a, b)); }
//- general static methods

Expand Down Expand Up @@ -283,7 +282,6 @@ the natural logarithm derivative");
}
// "sqrt" - square root
static Complex _sqrt(Complex a) { return sqrt(a); }
// TODO test _sqrt_d()
// "sqrt" for the derivative
static Complex _sqrt_d(Complex a, Complex) {
if (sqrt(a) == ZERO) {
Expand Down
45 changes: 45 additions & 0 deletions tests/test_derivative_coverage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Regression: derivative-of-^ uses log(), derivative-of-sqrt fires.

Closes TODOs:
src/cpp/cseval/cseval.hpp:212 (// TODO test log())
src/cpp/cseval/cseval.hpp:285 (// TODO test _sqrt_d())
src/cpp/cseval/cseval_complex.hpp:213 (// TODO test log())
src/cpp/cseval/cseval_complex.hpp:286 (// TODO test _sqrt_d())

The `^` derivative's right path is `_pow2(a, b) = log(a) * pow(a, b)`,
which is only reached when the exponent is itself a function of the
differentiation variable. The `_sqrt_d` path is reached for d(sqrt(x))/dx.
Both fire on the real and complex evaluation paths.
"""

from formula import Solver


def test_pow_derivative_via_log_real():
# d(x^y)/dy = log(x) * x^y. At x=2, y=3: log(2)*8 = 5.5451774444795625...
result = Solver("x^y", precision=24)(
{"x": "2", "y": "3"}, derivative="y"
)
assert result.startswith("5.545177444479562475337856")


def test_pow_derivative_via_log_complex():
# Same identity through the complex path. The presence of 'i' in the
# expression forces complex evaluation, so _pow2 in cseval_complex.hpp
# runs instead of the real twin.
result = Solver("(2+i*0)^y", precision=24)(
{"y": "3"}, derivative="y"
)
assert result.startswith("5.5451774444795624753378")


def test_sqrt_derivative_real():
# d(sqrt(x))/dx = 1/(2*sqrt(x)). At x=4: 1/(2*2) = 0.25.
result = Solver("sqrt(x)", precision=24)({"x": "4"}, derivative="x")
assert result == "0.25"


def test_sqrt_derivative_complex():
# Same identity through the complex path (forced by 'i' in the expression).
result = Solver("sqrt(x+i*0)", precision=24)({"x": "4"}, derivative="x")
assert result.startswith("0.25")
Loading