Browse Source

math: reimplement min(), max(), abs() and fmod() in the lol:: namespace to

avoid conflicts with the C++ stdlib.
legacy
Sam Hocevar sam 12 years ago
parent
commit
57c2805351
5 changed files with 97 additions and 35 deletions
  1. +5
    -1
      src/lol/math/half.h
  2. +69
    -1
      src/lol/math/math.h
  3. +20
    -30
      src/lol/math/vector.h
  4. +2
    -2
      test/math/poly.cpp
  5. +1
    -1
      tutorial/11_fractal.cpp

+ 5
- 1
src/lol/math/half.h View File

@@ -120,7 +120,11 @@ public:

static inline half min(half a, half b) { return a < b ? a : b; }
static inline half max(half a, half b) { return a > b ? a : b; }
static inline half fmod(half a, half b) { return (half)fmod((float)a, (float)b); }
static inline half fmod(half a, half b)
{
using std::fmod;
return (half)fmod((float)a, (float)b);
}
static inline half abs(half a) { return half::makebits(a.bits & 0x7fffu); }

static inline half clamp(half x, half a, half b)


+ 69
- 1
src/lol/math/math.h View File

@@ -18,11 +18,23 @@

#include <cmath>
#include <cstdio>
#include <algorithm>

#include <stdint.h>

namespace lol
{

/* This is OUR namespace. Don't let Windows headers fuck with it. */
#undef min
#undef max

/* There are many reasons for wanting single-word type names, the most
* important one being compilation speedups in our vector.h: we can hide
* some global methods in namespaces that contain the name of the type,
* but namespaces cannot have spaces in their names. */
typedef long double ldouble;

/* Standard cmath functions */
static inline double sqrt(double const &x) { return std::sqrt(x); }
static inline float sqrt(float const &x) { return std::sqrt(x); }
@@ -64,11 +76,17 @@ static inline void sincos(float const &x, float *s, float *c)
*c = std::cos(x);
}

static inline float lerp(float const &a, float const &b, float const &x)
{
return a + (b - a) * x;
}

static inline double lerp(double const &a, double const &b, double const &x)
{
return a + (b - a) * x;
}
static inline float lerp(float const &a, float const &b, float const &x)

static inline ldouble lerp(ldouble const &a, ldouble const &b, ldouble const &x)
{
return a + (b - a) * x;
}
@@ -85,6 +103,56 @@ double lol_acos(double);
double lol_atan(double);
double lol_atan2(double, double);

/* C++ doesn't define abs() and fmod() for all types; we add these for
* convenience to avoid adding complexity to vector.h. */
static inline int8_t abs(int8_t x) { return std::abs(x); }
static inline uint8_t abs(uint8_t x) { return x; }
static inline int16_t abs(int16_t x) { return std::abs(x); }
static inline uint16_t abs(uint16_t x) { return x; }
static inline int32_t abs(int32_t x) { return std::abs(x); }
static inline uint32_t abs(uint32_t x) { return x; }
static inline int64_t abs(int64_t x) { return std::abs(x); }
static inline uint64_t abs(uint64_t x) { return x; }
static inline float abs(float x) { return std::abs(x); }
static inline double abs(double x) { return std::abs(x); }
static inline ldouble abs(ldouble x) { return std::abs(x); }

static inline uint8_t fmod(uint8_t x, uint8_t y) { return x % y; }
static inline int8_t fmod(int8_t x, int8_t y) { return x % y; }
static inline uint16_t fmod(uint16_t x, uint16_t y) { return x % y; }
static inline int16_t fmod(int16_t x, int16_t y) { return x % y; }
static inline uint32_t fmod(uint32_t x, uint32_t y) { return x % y; }
static inline int32_t fmod(int32_t x, int32_t y) { return x % y; }
static inline uint64_t fmod(uint64_t x, uint64_t y) { return x % y; }
static inline int64_t fmod(int64_t x, int64_t y) { return x % y; }
static inline float fmod(float x, float y) { return std::fmod(x, y); }
static inline double fmod(double x, double y) { return std::fmod(x, y); }
static inline ldouble fmod(ldouble x, ldouble y) { return std::fmod(x, y); }

static inline uint8_t min(uint8_t x, uint8_t y) { return std::min(x, y); }
static inline int8_t min(int8_t x, int8_t y) { return std::min(x, y); }
static inline uint16_t min(uint16_t x, uint16_t y) { return std::min(x, y); }
static inline int16_t min(int16_t x, int16_t y) { return std::min(x, y); }
static inline uint32_t min(uint32_t x, uint32_t y) { return std::min(x, y); }
static inline int32_t min(int32_t x, int32_t y) { return std::min(x, y); }
static inline uint64_t min(uint64_t x, uint64_t y) { return std::min(x, y); }
static inline int64_t min(int64_t x, int64_t y) { return std::min(x, y); }
static inline float min(float x, float y) { return std::min(x, y); }
static inline double min(double x, double y) { return std::min(x, y); }
static inline ldouble min(ldouble x, ldouble y) { return std::min(x, y); }

static inline uint8_t max(uint8_t x, uint8_t y) { return std::max(x, y); }
static inline int8_t max(int8_t x, int8_t y) { return std::max(x, y); }
static inline uint16_t max(uint16_t x, uint16_t y) { return std::max(x, y); }
static inline int16_t max(int16_t x, int16_t y) { return std::max(x, y); }
static inline uint32_t max(uint32_t x, uint32_t y) { return std::max(x, y); }
static inline int32_t max(int32_t x, int32_t y) { return std::max(x, y); }
static inline uint64_t max(uint64_t x, uint64_t y) { return std::max(x, y); }
static inline int64_t max(int64_t x, int64_t y) { return std::max(x, y); }
static inline float max(float x, float y) { return std::max(x, y); }
static inline double max(double x, double y) { return std::max(x, y); }
static inline ldouble max(ldouble x, ldouble y) { return std::max(x, y); }

} /* namespace lol */

#endif // __LOL_MATH_MATH_H__


+ 20
- 30
src/lol/math/vector.h View File

@@ -18,7 +18,6 @@

#include <stdint.h>
#include <ostream>
#include <algorithm>

#include "lol/math/math.h"
#include "lol/math/half.h"
@@ -27,10 +26,6 @@
namespace lol
{

/* This is OUR namespace. Don't let Windows headers fuck with it. */
#undef min
#undef max

/* Some compilers do not support const members in anonymous unions. So
* far, GCC (>= 4.6), CLang (3.0) and Visual Studio (>= 2010) appear to
* work properly. */
@@ -39,16 +34,12 @@ namespace lol
# define LOL_NO_CONST_MEMBERS_IN_ANONYMOUS_UNIONS 1
#endif

/* Hack for compilation speedups: we can hide some of our global methods in
* namespaces. We therefore want "long_double" to be a single-word name */
typedef long double long_double;

#define DECLARE_VECTOR_TYPEDEFS(tname, suffix) \
template <typename T> struct tname; \
typedef tname<half> f16##suffix; \
typedef tname<float> suffix; \
typedef tname<double> d##suffix; \
typedef tname<long_double> f128##suffix; \
typedef tname<ldouble> f128##suffix; \
typedef tname<int8_t> i8##suffix; \
typedef tname<uint8_t> u8##suffix; \
typedef tname<int16_t> i16##suffix; \
@@ -1073,7 +1064,7 @@ extern Quat<T> slerp(Quat<T> const &qa, Quat<T> const &qb, T f);
tprefix \
inline tname<type> op(tname<type> const &a, tname<type> const &b) \
{ \
using std::op; \
using lol::op; \
tname<type> ret; \
for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
ret[n] = op(a[n], b[n]); \
@@ -1083,7 +1074,7 @@ extern Quat<T> slerp(Quat<T> const &qa, Quat<T> const &qb, T f);
tprefix \
inline tname<type> op(tname<type> const &a, type const &b) \
{ \
using std::op; \
using lol::op; \
tname<type> ret; \
for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
ret[n] = op(a[n], b); \
@@ -1093,7 +1084,7 @@ extern Quat<T> slerp(Quat<T> const &qa, Quat<T> const &qb, T f);
tprefix \
inline tname<type> op(type const &a, tname<type> const &b) \
{ \
using std::op; \
using lol::op; \
tname<type> ret; \
for (size_t n = 0; n < sizeof(b) / sizeof(type); n++) \
ret[n] = op(a, b[n]); \
@@ -1227,10 +1218,9 @@ extern Quat<T> slerp(Quat<T> const &qa, Quat<T> const &qb, T f);
tprefix \
inline tname<type> abs(tname<type> const &a) \
{ \
using std::abs; \
tname<type> ret; \
for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
ret[n] = abs(a[n]); \
ret[n] = lol::abs(a[n]); \
return ret; \
}

@@ -1360,7 +1350,7 @@ DECLARE_ALL_NONVECTOR_OPS(Quat)
DECLARE_ALL_VECTOR_OPS(half)
DECLARE_ALL_VECTOR_OPS(float)
DECLARE_ALL_VECTOR_OPS(double)
DECLARE_ALL_VECTOR_OPS(long_double)
DECLARE_ALL_VECTOR_OPS(ldouble)
DECLARE_ALL_VECTOR_OPS(int8_t)
DECLARE_ALL_VECTOR_OPS(uint8_t)
DECLARE_ALL_VECTOR_OPS(int16_t)
@@ -1401,7 +1391,7 @@ DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, int64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, uint64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, float)
DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, double)
DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, long_double)
DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, ldouble)

DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, int16_t)
DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, uint16_t)
@@ -1411,7 +1401,7 @@ DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, int64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, uint64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, float)
DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, double)
DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, long_double)
DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, ldouble)

DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, uint16_t)
DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, int32_t)
@@ -1420,7 +1410,7 @@ DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, int64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, uint64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, float)
DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, double)
DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, long_double)
DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, ldouble)

DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, int32_t)
DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, uint32_t)
@@ -1428,34 +1418,34 @@ DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, int64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, uint64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, float)
DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, double)
DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, long_double)
DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, ldouble)

DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, uint32_t)
DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, int64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, uint64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, float)
DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, double)
DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, long_double)
DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, ldouble)

DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, int64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, uint64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, float)
DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, double)
DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, long_double)
DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, ldouble)

DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, uint64_t)
DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, float)
DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, double)
DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, long_double)
DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, ldouble)

DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, float)
DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, double)
DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, long_double)
DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, ldouble)

DECLARE_ALL_VECTOR_COERCE_OPS(float, double)
DECLARE_ALL_VECTOR_COERCE_OPS(float, long_double)
DECLARE_ALL_VECTOR_COERCE_OPS(float, ldouble)

DECLARE_ALL_VECTOR_COERCE_OPS(double, long_double)
DECLARE_ALL_VECTOR_COERCE_OPS(double, ldouble)

/* FIXME: vectors of "half" are deactivated for now, because they
* induce extremely long compilation times (about 17 seconds per TU). */
@@ -1474,7 +1464,7 @@ DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, half)

DECLARE_ALL_VECTOR_COERCE_OPS(half, float)
DECLARE_ALL_VECTOR_COERCE_OPS(half, double)
DECLARE_ALL_VECTOR_COERCE_OPS(half, long_double)
DECLARE_ALL_VECTOR_COERCE_OPS(half, ldouble)
#endif

/* FIXME: vectors of "real" are deactivated for now, because we do
@@ -1493,7 +1483,7 @@ DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, real)
DECLARE_ALL_VECTOR_COERCE_OPS(half, real)
DECLARE_ALL_VECTOR_COERCE_OPS(float, real)
DECLARE_ALL_VECTOR_COERCE_OPS(double, real)
DECLARE_ALL_VECTOR_COERCE_OPS(long_double, real)
DECLARE_ALL_VECTOR_COERCE_OPS(ldouble, real)
#endif

/* Activate all the namespaces that we created. Delaying this activation
@@ -1518,7 +1508,7 @@ DECLARE_ALL_VECTOR_COERCE_OPS(long_double, real)
ACTIVATE_COERCE_NAMESPACES_INNER(tlow, half) \
ACTIVATE_COERCE_NAMESPACES_INNER(tlow, float) \
ACTIVATE_COERCE_NAMESPACES_INNER(tlow, double) \
ACTIVATE_COERCE_NAMESPACES_INNER(tlow, long_double) \
ACTIVATE_COERCE_NAMESPACES_INNER(tlow, ldouble) \
ACTIVATE_COERCE_NAMESPACES_INNER(tlow, real)

ACTIVATE_COERCE_NAMESPACES(int8_t)
@@ -1532,7 +1522,7 @@ ACTIVATE_COERCE_NAMESPACES(uint64_t)
ACTIVATE_COERCE_NAMESPACES(half)
ACTIVATE_COERCE_NAMESPACES(float)
ACTIVATE_COERCE_NAMESPACES(double)
ACTIVATE_COERCE_NAMESPACES(long_double)
ACTIVATE_COERCE_NAMESPACES(ldouble)
ACTIVATE_COERCE_NAMESPACES(real)

#if defined __GNUC__ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))


+ 2
- 2
test/math/poly.cpp View File

@@ -123,7 +123,7 @@ printf("-- START --\n");
{
union { float f; uint32_t x; } s1 = { sinf(adjustf(u.f, 0)) };
union { float f; uint32_t x; } s2 = { floatsin(adjustf(u.f, 0)) };
int e = abs((int)(s1.x - s2.x));
int e = lol::abs((int)(s1.x - s2.x));
switch (e)
{
case 3:
@@ -132,7 +132,7 @@ printf("-- START --\n");
inspect(u.f);
printf("sinf: ");
inspect(sinf(u.f));
if (fabs((double)s1.f - (double)s2.f) > 1e-10 * fabs(s1.f))
if (lol::abs((double)s1.f - (double)s2.f) > 1e-10 * lol::abs(s1.f))
printf("%15.13g %08x: %15.13g %15.13g %08x %08x\n", u.f, u.x, s1.f, s2.f, s1.x, s2.x);
case 0:
error[e]++;


+ 1
- 1
tutorial/11_fractal.cpp View File

@@ -215,7 +215,7 @@ public:
else if (m_zoom_speed)
{
m_zoom_speed *= std::pow(2.0, -seconds * 5.0);
if (abs(m_zoom_speed) < 1e-5 || m_drag)
if (lol::abs(m_zoom_speed) < 1e-5 || m_drag)
m_zoom_speed = 0.0;
}
#endif


Loading…
Cancel
Save