From 4041166c56e4831456408b1134a2b95d897fb296 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Wed, 12 Oct 2011 01:16:03 +0000 Subject: [PATCH] core: improve sin() and exp() performance by replacing divisions with multiplications where appropriate. --- src/real.cpp | 18 ++++++++++++------ test/benchmark/real.cpp | 12 ++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/real.cpp b/src/real.cpp index a8369a4f..aae114e5 100644 --- a/src/real.cpp +++ b/src/real.cpp @@ -668,13 +668,16 @@ static real fast_exp(real const &x) for (int i = 1; ; i++) { - fact *= (real)i; - real newret = ret + xn / fact; + real newret = ret + xn; if (newret == ret) break; ret = newret; + real mul = (i + 1); + fact *= mul; + ret *= mul; xn *= x; } + ret /= fact; return ret; } @@ -802,16 +805,19 @@ real sin(real const &x) if (absx > real::R_PI_2) absx = real::R_PI - absx; - real ret = real::R_0, fact = real::R_1, xn = absx, x2 = absx * absx; + real ret = real::R_0, fact = real::R_1, xn = absx, mx2 = -absx * absx; for (int i = 1; ; i += 2) { - real newret = ret + xn / fact; + real newret = ret + xn; if (newret == ret) break; ret = newret; - xn *= x2; - fact *= (real)(-(i + 1) * (i + 2)); + real mul = (i + 1) * (i + 2); + fact *= mul; + ret *= mul; + xn *= mx2; } + ret /= fact; /* Propagate sign */ if (switch_sign) diff --git a/test/benchmark/real.cpp b/test/benchmark/real.cpp index d37781d7..3a3b1e50 100644 --- a/test/benchmark/real.cpp +++ b/test/benchmark/real.cpp @@ -56,6 +56,16 @@ void bench_real(int mode) for (size_t i = 0; i < REAL_TABLE_SIZE; i++) invfact = invfact / real(1.0 + i); result[2] += timer.GetMs(); + + timer.GetMs(); + for (size_t i = 0; i < REAL_TABLE_SIZE / 128; i++) + sin(real(0.01 * i)); + result[3] += timer.GetMs() * 128; + + timer.GetMs(); + for (size_t i = 0; i < REAL_TABLE_SIZE / 128; i++) + exp((real)(int)(i - REAL_TABLE_SIZE / 256)); + result[4] += timer.GetMs() * 128; } for (size_t i = 0; i < sizeof(result) / sizeof(*result); i++) @@ -65,5 +75,7 @@ void bench_real(int mode) Log::Info("real = real + real %7.3f\n", result[0]); Log::Info("real = real * real %7.3f\n", result[1]); Log::Info("real = real / real %7.3f\n", result[2]); + Log::Info("real = sin(real) %7.3f\n", result[3]); + Log::Info("real = exp(real) %7.3f\n", result[4]); }