Skip to content

Commit

Permalink
Add propagators for __builtin_pow.
Browse files Browse the repository at this point in the history
  • Loading branch information
vgvassilev committed Jul 28, 2024
1 parent 7360354 commit d8374bb
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
55 changes: 55 additions & 0 deletions include/clad/Differentiator/BuiltinDerivatives.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,61 @@ ValueAndPushforward<int, int> cudaDeviceSynchronize_pushforward()
}
#endif

CUDA_HOST_DEVICE inline ValueAndPushforward<double, double>
__builtin_pow_pushforward(double x, double exponent, double d_x,
double d_exponent) {
auto val = __builtin_pow(x, exponent);
double derivative = (exponent * __builtin_pow(x, exponent - 1)) * d_x;
// Only add directional derivative of base^exp w.r.t exp if the directional
// seed d_exponent is non-zero. This is required because if base is less than
// or equal to 0, then log(base) is undefined, and therefore if user only
// requested directional derivative of base^exp w.r.t base -- which is valid
// --, the result would be undefined because as per C++ valid number + NaN * 0
// = NaN.
if (d_exponent)
derivative += (__builtin_pow(x, exponent) * __builtin_log(x)) * d_exponent;
return {val, derivative};
}

CUDA_HOST_DEVICE inline ValueAndPushforward<float, float>
__builtin_powf_pushforward(float x, float exponent, float d_x,
float d_exponent) {
auto val = __builtin_powf(x, exponent);
float derivative = (exponent * __builtin_powf(x, exponent - 1)) * d_x;
// Only add directional derivative of base^exp w.r.t exp if the directional
// seed d_exponent is non-zero. This is required because if base is less than
// or equal to 0, then log(base) is undefined, and therefore if user only
// requested directional derivative of base^exp w.r.t base -- which is valid
// --, the result would be undefined because as per C++ valid number + NaN * 0
// = NaN.
if (d_exponent)
derivative +=
(__builtin_powf(x, exponent) * __builtin_logf(x)) * d_exponent;
return {val, derivative};
}

CUDA_HOST_DEVICE inline void __builtin_pow_pullback(double x, double exponent,
double d_y, double* d_x,
double* d_exponent) {
auto t =
__builtin_pow_pushforward(x, exponent, /*d_x=*/1., /*d_exponent=*/0.);
*d_x += t.pushforward * d_y;
t = __builtin_pow_pushforward(x, exponent, /*d_x=*/0., /*d_exponent=*/1.);
*d_exponent += t.pushforward * d_y;
}

CUDA_HOST_DEVICE inline void __builtin_powf_pullback(float x, float exponent,
float d_y, float* d_x,
float* d_exponent) {
auto t =
__builtin_powf_pushforward(x, exponent, /*d_x=*/1., /*d_exponent=*/0.);
*d_x += t.pushforward * d_y;
t = __builtin_powf_pushforward(x, exponent, /*d_x=*/0., /*d_exponent=*/1.);
*d_exponent += t.pushforward * d_y;
}

// FIXME: Add the rest of the __builtin_ routines for log, sqrt, abs, etc.

namespace std {
template <typename T>
CUDA_HOST_DEVICE ValueAndPushforward<T, T> abs_pushforward(T x, T d_x) {
Expand Down
7 changes: 7 additions & 0 deletions test/FirstDerivative/BuiltinDerivatives.C
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,10 @@ double f13(double x) {
//CHECK-NEXT: return _d__t0.pushforward;
//CHECK-NEXT: }

double f14(double x) {
return __builtin_pow(x, 2);
}

int main () { //expected-no-diagnostics
float f_result[2];
double d_result[2];
Expand Down Expand Up @@ -319,5 +323,8 @@ int main () { //expected-no-diagnostics
auto f13_ddx = clad::differentiate<2>(f13);
printf("Result is = %.2f\n", f13_ddx.execute(1)); //CHECK-EXEC: Result is = 2.72

auto f14_darg0 = clad::differentiate(f14, 0);
printf("Result is = %f\n", f14_darg0.execute(1)); //CHECK-EXEC: Result is = 2.000000

return 0;
}

0 comments on commit d8374bb

Please sign in to comment.