make util::normalize_angle reasonably fast on large values

Because it simply calculates the remainder after division by full turn,
it shouldn't take time proportional to the magnitude of its operand.
This commit is contained in:
Mickey Rose 2016-03-01 18:47:53 +01:00
parent 354be41811
commit 7c4ccf0209
2 changed files with 20 additions and 6 deletions

View file

@ -27,9 +27,11 @@
namespace mapnik { namespace util {
constexpr double pi = 3.1415926535897932384626433832795;
constexpr double tau = 6.283185307179586476925286766559;
MAPNIK_DECL double normalize_angle(double angle);
}}
#endif

View file

@ -22,7 +22,6 @@
// mapnik
#include <mapnik/util/math.hpp>
#include <mapnik/global.hpp>
// stl
#include <cmath>
@ -33,13 +32,26 @@ namespace util {
double normalize_angle(double angle)
{
while (angle >= M_PI)
if (angle > pi)
{
angle -= 2.0 * M_PI;
if (angle > 16 * tau)
{
// the angle is too large; better compute the remainder
// directly to avoid subtracting circles ad infinitum
return std::remainder(angle, tau);
}
// std::remainder would take longer than a few subtractions
while ((angle -= tau) > pi)
;
}
while (angle < -M_PI)
else if (angle < -pi)
{
angle += 2.0 * M_PI;
if (angle < -16 * tau)
{
return std::remainder(angle, tau);
}
while ((angle += tau) < -pi)
;
}
return angle;
}