source: trunk/src/lol/math/real.h @ 1667

Last change on this file since 1667 was 1667, checked in by sam, 8 years ago

math: add an sprintf() method to real numbers, and ensure they are always
fully initialised.

  • Property svn:keywords set to Id
File size: 10.7 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11//
12// The Real class
13// --------------
14//
15
16#if !defined __LOL_MATH_REAL_H__
17#define __LOL_MATH_REAL_H__
18
19#include <stdint.h>
20
21namespace lol
22{
23
24/* This is OUR namespace. Don't let Windows headers fuck with it. */
25#undef min
26#undef max
27
28/* Avoid issues with NaCl headers */
29#undef log2
30
31/*
32 * The base class for reals. The only real reason for making this a template
33 * class is so we can have implicit constructors ("real x = 1" works) but
34 * avoid accidental implicit conversions ("int x = 1; sqrt(x)" will never
35 * call real::sqrt).
36 */
37template<int N> class Real
38{
39public:
40    Real();
41    Real(Real<N> const &x);
42    Real const &operator =(Real<N> const &x);
43    ~Real();
44
45    Real(float f);
46    Real(double f);
47    Real(int i);
48    Real(unsigned int i);
49
50    Real(char const *str);
51
52    operator float() const;
53    operator double() const;
54    operator int() const;
55    operator unsigned int() const;
56
57    Real<N> operator +() const;
58    Real<N> operator -() const;
59    Real<N> operator +(Real<N> const &x) const;
60    Real<N> operator -(Real<N> const &x) const;
61    Real<N> operator *(Real<N> const &x) const;
62    Real<N> operator /(Real<N> const &x) const;
63    Real<N> const &operator +=(Real<N> const &x);
64    Real<N> const &operator -=(Real<N> const &x);
65    Real<N> const &operator *=(Real<N> const &x);
66    Real<N> const &operator /=(Real<N> const &x);
67
68    bool operator ==(Real<N> const &x) const;
69    bool operator !=(Real<N> const &x) const;
70    bool operator <(Real<N> const &x) const;
71    bool operator >(Real<N> const &x) const;
72    bool operator <=(Real<N> const &x) const;
73    bool operator >=(Real<N> const &x) const;
74
75    bool operator !() const;
76    operator bool() const;
77
78    /* Comparison functions */
79    template<int M> friend Real<M> min(Real<M> const &a, Real<M> const &b);
80    template<int M> friend Real<M> max(Real<M> const &a, Real<M> const &b);
81    template<int M> friend Real<M> clamp(Real<M> const &x,
82                                         Real<M> const &a, Real<M> const &b);
83
84    /* Trigonometric functions */
85    template<int M> friend Real<M> sin(Real<M> const &x);
86    template<int M> friend Real<M> cos(Real<M> const &x);
87    template<int M> friend Real<M> tan(Real<M> const &x);
88    template<int M> friend Real<M> asin(Real<M> const &x);
89    template<int M> friend Real<M> acos(Real<M> const &x);
90    template<int M> friend Real<M> atan(Real<M> const &x);
91    template<int M> friend Real<M> atan2(Real<M> const &y, Real<M> const &x);
92
93    /* Hyperbolic functions */
94    template<int M> friend Real<M> sinh(Real<M> const &x);
95    template<int M> friend Real<M> cosh(Real<M> const &x);
96    template<int M> friend Real<M> tanh(Real<M> const &x);
97
98    /* Exponential and logarithmic functions */
99    template<int M> friend Real<M> exp(Real<M> const &x);
100    template<int M> friend Real<M> exp2(Real<M> const &x);
101    template<int M> friend Real<M> log(Real<M> const &x);
102    template<int M> friend Real<M> log2(Real<M> const &x);
103    template<int M> friend Real<M> log10(Real<M> const &x);
104    template<int M> friend Real<M> frexp(Real<M> const &x, int *exp);
105    template<int M> friend Real<M> ldexp(Real<M> const &x, int exp);
106    template<int M> friend Real<M> modf(Real<M> const &x, Real<M> *iptr);
107    template<int M> friend Real<M> ulp(Real<M> const &x);
108    template<int M> friend Real<M> nextafter(Real<M> const &x, Real<M> const &y);
109
110    /* Power functions */
111    template<int M> friend Real<M> re(Real<M> const &x);
112    template<int M> friend Real<M> sqrt(Real<M> const &x);
113    template<int M> friend Real<M> cbrt(Real<M> const &x);
114    template<int M> friend Real<M> pow(Real<M> const &x, Real<M> const &y);
115    template<int M> friend Real<M> gamma(Real<M> const &x);
116
117    /* Rounding, absolute value, remainder etc. */
118    template<int M> friend Real<M> ceil(Real<M> const &x);
119    template<int M> friend Real<M> copysign(Real<M> const &x, Real<M> const &y);
120    template<int M> friend Real<M> floor(Real<M> const &x);
121    template<int M> friend Real<M> fabs(Real<M> const &x);
122    template<int M> friend Real<M> round(Real<M> const &x);
123    template<int M> friend Real<M> fmod(Real<M> const &x, Real<N> const &y);
124
125    void hexprint() const;
126    void print(int ndigits = 150) const;
127    void sprintf(char *str, int ndigits = 150) const;
128
129    /* Additional operators using base C++ types */
130#define __LOL_REAL_OP_HELPER_GENERIC(op, type) \
131    inline Real<N> operator op(type x) const { return *this op (Real<N>)x; } \
132    inline Real<N> const &operator op##=(type x) { return *this = (*this op x); }
133#define __LOL_REAL_OP_HELPER_FASTMULDIV(op, type) \
134    inline Real<N> operator op(type x) const \
135    { \
136        Real<N> tmp = *this; return tmp op##= x; \
137    } \
138    inline Real<N> const &operator op##=(type x) \
139    { \
140        /* If multiplying or dividing by a power of two, take a shortcut */ \
141        if ((m_signexp << 1) && x && !(x & (x - 1))) \
142        { \
143            while (x >>= 1) \
144                m_signexp += 1 op 2 - 1; /* 1 if op is *, -1 if op is / */ \
145        } \
146        else \
147            *this = *this op (Real<N>)x; \
148        return *this; \
149    }
150#define __LOL_REAL_OP_HELPER_INT(type) \
151    __LOL_REAL_OP_HELPER_GENERIC(+, type) \
152    __LOL_REAL_OP_HELPER_GENERIC(-, type) \
153    __LOL_REAL_OP_HELPER_FASTMULDIV(*, type) \
154    __LOL_REAL_OP_HELPER_FASTMULDIV(/, type)
155#define __LOL_REAL_OP_HELPER_FLOAT(type) \
156    __LOL_REAL_OP_HELPER_GENERIC(+, type) \
157    __LOL_REAL_OP_HELPER_GENERIC(-, type) \
158    __LOL_REAL_OP_HELPER_GENERIC(*, type) \
159    __LOL_REAL_OP_HELPER_GENERIC(/, type)
160
161    __LOL_REAL_OP_HELPER_INT(int)
162    __LOL_REAL_OP_HELPER_INT(unsigned int)
163    __LOL_REAL_OP_HELPER_FLOAT(float)
164    __LOL_REAL_OP_HELPER_FLOAT(double)
165
166    /* Constants */
167    static Real<N> const R_0;
168    static Real<N> const R_1;
169    static Real<N> const R_2;
170    static Real<N> const R_3;
171    static Real<N> const R_10;
172
173    static Real<N> const R_E;
174    static Real<N> const R_LOG2E;
175    static Real<N> const R_LOG10E;
176    static Real<N> const R_LN2;
177    static Real<N> const R_LN10;
178    static Real<N> const R_PI;
179    static Real<N> const R_PI_2;
180    static Real<N> const R_PI_3;
181    static Real<N> const R_PI_4;
182    static Real<N> const R_1_PI;
183    static Real<N> const R_2_PI;
184    static Real<N> const R_2_SQRTPI;
185    static Real<N> const R_SQRT2;
186    static Real<N> const R_SQRT3;
187    static Real<N> const R_SQRT1_2;
188
189    /* XXX: changing this requires tuning real::fres (the number of
190     * Newton-Raphson iterations) and real::print (the number of printed
191     * digits) */
192    static int const BIGITS = N;
193    static int const BIGIT_BITS = 32;
194
195private:
196    uint32_t *m_mantissa;
197    uint32_t m_signexp;
198};
199
200/*
201 * The real type used for real numbers
202 */
203typedef Real<16> real;
204
205/*
206 * Mandatory forward declarations of template specialisations
207 */
208template<> real::Real();
209template<> real::Real(real const &x);
210template<> real const &real::operator =(real const &x);
211template<> real::~Real();
212template<> real::Real(float f);
213template<> real::Real(double f);
214template<> real::Real(int i);
215template<> real::Real(unsigned int i);
216template<> real::Real(char const *str);
217
218template<> real::operator float() const;
219template<> real::operator double() const;
220template<> real::operator int() const;
221template<> real::operator unsigned int() const;
222template<> real real::operator +() const;
223template<> real real::operator -() const;
224template<> real real::operator +(real const &x) const;
225template<> real real::operator -(real const &x) const;
226template<> real real::operator *(real const &x) const;
227template<> real real::operator /(real const &x) const;
228template<> real const &real::operator +=(real const &x);
229template<> real const &real::operator -=(real const &x);
230template<> real const &real::operator *=(real const &x);
231template<> real const &real::operator /=(real const &x);
232template<> bool real::operator ==(real const &x) const;
233template<> bool real::operator !=(real const &x) const;
234template<> bool real::operator <(real const &x) const;
235template<> bool real::operator >(real const &x) const;
236template<> bool real::operator <=(real const &x) const;
237template<> bool real::operator >=(real const &x) const;
238template<> bool real::operator !() const;
239template<> real::operator bool() const;
240
241template<> real min(real const &a, real const &b);
242template<> real max(real const &a, real const &b);
243template<> real clamp(real const &x, real const &a, real const &b);
244
245template<> real sin(real const &x);
246template<> real cos(real const &x);
247template<> real tan(real const &x);
248template<> real asin(real const &x);
249template<> real acos(real const &x);
250template<> real atan(real const &x);
251template<> real atan2(real const &y, real const &x);
252template<> real sinh(real const &x);
253template<> real cosh(real const &x);
254template<> real tanh(real const &x);
255template<> real exp(real const &x);
256template<> real exp2(real const &x);
257template<> real log(real const &x);
258template<> real log2(real const &x);
259template<> real log10(real const &x);
260template<> real frexp(real const &x, int *exp);
261template<> real ldexp(real const &x, int exp);
262template<> real modf(real const &x, real *iptr);
263template<> real ulp(real const &x);
264template<> real nextafter(real const &x, real const &y);
265template<> real re(real const &x);
266template<> real sqrt(real const &x);
267template<> real cbrt(real const &x);
268template<> real pow(real const &x, real const &y);
269template<> real gamma(real const &x);
270template<> real ceil(real const &x);
271template<> real copysign(real const &x, real const &y);
272template<> real floor(real const &x);
273template<> real fabs(real const &x);
274template<> real round(real const &x);
275template<> real fmod(real const &x, real const &y);
276
277template<> void real::hexprint() const;
278template<> void real::print(int ndigits) const;
279
280/* FIXME: why doesn't this work on Visual Studio? */
281#if !defined _MSC_VER
282template<> real const real::R_0;
283template<> real const real::R_1;
284template<> real const real::R_2;
285template<> real const real::R_3;
286template<> real const real::R_10;
287
288template<> real const real::R_LN2;
289template<> real const real::R_LN10;
290template<> real const real::R_LOG2E;
291template<> real const real::R_LOG10E;
292template<> real const real::R_E;
293template<> real const real::R_PI;
294template<> real const real::R_PI_2;
295template<> real const real::R_PI_3;
296template<> real const real::R_PI_4;
297template<> real const real::R_1_PI;
298template<> real const real::R_2_PI;
299template<> real const real::R_2_SQRTPI;
300template<> real const real::R_SQRT2;
301template<> real const real::R_SQRT3;
302template<> real const real::R_SQRT1_2;
303#endif
304
305} /* namespace lol */
306
307#endif // __LOL_MATH_REAL_H__
308
Note: See TracBrowser for help on using the repository browser.