diff --git a/src/approx_math.h b/src/approx_math.h index 48319ddfd7a86c132a1cd18b4a08fa849a36a15a..aa9ed2b4efa6e0542e2eb2432132f4b0232f7403 100644 --- a/src/approx_math.h +++ b/src/approx_math.h @@ -49,4 +49,16 @@ __attribute__((always_inline)) INLINE static float good_approx_expf(float x) { x * ((1.f / 120.f) + (1.f / 720.f) * x))))); } +/** + * @brief Approximate version of exp(x) using a 6th order Taylor expansion + */ +__attribute__((always_inline)) INLINE static double good_approx_exp(double x) { + return 1. + + x * (1. + + x * (0.5 + + x * ((1. / 6.) + + x * ((1. / 24.) + + x * ((1. / 120.) + (1. / 720.) * x))))); +} + #endif /* SWIFT_APPROX_MATH_H */ diff --git a/src/kernel_long_gravity.h b/src/kernel_long_gravity.h index 77bc7c17e2ab8038a4860c74daebd19a2d785070..578d7c2154f6801e21c004c01cade8bf6bd728ae 100644 --- a/src/kernel_long_gravity.h +++ b/src/kernel_long_gravity.h @@ -49,7 +49,7 @@ __attribute__((always_inline)) INLINE static void kernel_long_grav_pot_eval( #else const float x = 2.f * u; - const float exp_x = expf(x); + const float exp_x = good_approx_expf(x); const float alpha = 1.f / (1.f + exp_x); /* We want 2 - 2 exp(x) * alpha */ @@ -83,7 +83,7 @@ __attribute__((always_inline)) INLINE static void kernel_long_grav_force_eval( #else const float arg = 2.f * u; - const float exp_arg = expf(arg); + const float exp_arg = good_approx_expf(arg); const float term = 1.f / (1.f + exp_arg); *W = arg * exp_arg * term * term - exp_arg * term + 1.f; @@ -111,4 +111,4 @@ __attribute__((always_inline)) INLINE static void fourier_kernel_long_grav_eval( #endif } -#endif // SWIFT_KERNEL_LONG_GRAVITY_H +#endif /* SWIFT_KERNEL_LONG_GRAVITY_H */ diff --git a/tests/testPotentialSelf.c b/tests/testPotentialSelf.c index 246139ba243a37dbc5f6cafbc488cb1bf6cdd8eb..6d31f079fa79f7463637ec71dc2c75f37a10b129 100644 --- a/tests/testPotentialSelf.c +++ b/tests/testPotentialSelf.c @@ -41,15 +41,18 @@ const double eps = 0.02; * @param s String used to identify this check in messages */ void check_value(double a, double b, const char *s) { - if (fabs(a - b) / fabs(a + b) > 2e-6 && fabs(a - b) > 1.e-6) + if (fabs(a - b) / fabs(a + b) > 1e-6 && fabs(a - b) > 1.e-6) error("Values are inconsistent: %12.15e %12.15e (%s)!", a, b, s); } /* Definitions of the potential and force that match exactly the theory document */ -double S(double x) { return exp(x) / (1. + exp(x)); } +double S(double x) { return good_approx_exp(x) / (1. + good_approx_exp(x)); } -double S_prime(double x) { return exp(x) / ((1. + exp(x)) * (1. + exp(x))); } +double S_prime(double x) { + return good_approx_exp(x) / + ((1. + good_approx_exp(x)) * (1. + good_approx_exp(x))); +} double potential(double mass, double r, double H, double rlr) {