Code

bea891742e7253c2cfc7b43c2dde5e5abeac86a2
[inkscape.git] / src / util / fixed_point.h
1 /*\r
2  * Inkscape::Util::FixedPoint - fixed point type\r
3  *\r
4  * Authors:\r
5  *   Jasper van de Gronde <th.v.d.gronde@hccnet.net>\r
6  *\r
7  * Copyright (C) 2006 Jasper van de Gronde\r
8  *\r
9  * Released under GNU GPL, read the file 'COPYING' for more information\r
10  */\r
11 \r
12 #ifndef SEEN_INKSCAPE_UTIL_FIXED_POINT_H\r
13 #define SEEN_INKSCAPE_UTIL_FIXED_POINT_H\r
14 \r
15 #include "traits/reference.h"\r
16 #include <math.h>\r
17 #include <algorithm>\r
18 #include <limits>\r
19 \r
20 namespace Inkscape {\r
21 \r
22 namespace Util {\r
23 \r
24 template <typename T, unsigned int precision>\r
25 class FixedPoint {\r
26 public:\r
27     FixedPoint() {}\r
28     FixedPoint(const FixedPoint& value) : v(value.v) {}\r
29     FixedPoint(char value) : v(static_cast<T>(value)<<precision) {}\r
30     FixedPoint(unsigned char value) : v(static_cast<T>(value)<<precision) {}\r
31     FixedPoint(short value) : v(static_cast<T>(value)<<precision) {}\r
32     FixedPoint(unsigned short value) : v(static_cast<T>(value)<<precision) {}\r
33     FixedPoint(int value) : v(static_cast<T>(value)<<precision) {}\r
34     FixedPoint(unsigned int value) : v(static_cast<T>(value)<<precision) {}\r
35     FixedPoint(double value) : v(static_cast<T>(floor(value*(1<<precision)))) {}\r
36 \r
37     FixedPoint& operator+=(FixedPoint val) { v += val.v; return *this; }\r
38     FixedPoint& operator-=(FixedPoint val) { v -= val.v; return *this; }\r
39     FixedPoint& operator*=(FixedPoint val) {\r
40         const unsigned int half_size = 8*sizeof(T)/2;\r
41         const T al = v&((1<<half_size)-1), bl = val.v&((1<<half_size)-1);\r
42         const T ah = v>>half_size, bh = val.v>>half_size;\r
43         v = static_cast<unsigned int>(al*bl)>>precision;\r
44         if ( half_size >= precision ) {\r
45             v += ((al*bh)+(ah*bl)+((ah*bh)<<half_size))<<(half_size-precision);\r
46         } else {\r
47             v += ((al*bh)+(ah*bl))>>(precision-half_size);\r
48             v += (ah*bh)<<(2*half_size-precision);\r
49         }\r
50         return *this;\r
51     }\r
52 \r
53     FixedPoint& operator*=(char val) { v *= val; return *this; }\r
54     FixedPoint& operator*=(unsigned char val) { v *= val; return *this; }\r
55     FixedPoint& operator*=(short val) { v *= val; return *this; }\r
56     FixedPoint& operator*=(unsigned short val) { v *= val; return *this; }\r
57     FixedPoint& operator*=(int val) { v *= val; return *this; }\r
58     FixedPoint& operator*=(unsigned int val) { v *= val; return *this; }\r
59 \r
60     FixedPoint operator+(FixedPoint val) const { FixedPoint r(*this); return r+=val; }\r
61     FixedPoint operator-(FixedPoint val) const { FixedPoint r(*this); return r-=val; }\r
62     FixedPoint operator*(FixedPoint val) const { FixedPoint r(*this); return r*=val; }\r
63 \r
64     FixedPoint operator*(char val) const { FixedPoint r(*this); return r*=val; }\r
65     FixedPoint operator*(unsigned char val) const { FixedPoint r(*this); return r*=val; }\r
66     FixedPoint operator*(short val) const { FixedPoint r(*this); return r*=val; }\r
67     FixedPoint operator*(unsigned short val) const { FixedPoint r(*this); return r*=val; }\r
68     FixedPoint operator*(int val) const { FixedPoint r(*this); return r*=val; }\r
69     FixedPoint operator*(unsigned int val) const { FixedPoint r(*this); return r*=val; }\r
70 \r
71     float operator*(float val) const { return static_cast<float>(*this)*val; }\r
72     double operator*(double val) const { return static_cast<double>(*this)*val; }\r
73 \r
74     operator char() const { return v>>precision; }\r
75     operator unsigned char() const { return v>>precision; }\r
76     operator short() const { return v>>precision; }\r
77     operator unsigned short() const { return v>>precision; }\r
78     operator int() const { return v>>precision; }\r
79     operator unsigned int() const { return v>>precision; }\r
80 \r
81     operator float() const { return ldexpf(v,-precision); }\r
82     operator double() const { return ldexp(v,-precision); }\r
83 private:\r
84     T v;\r
85 };\r
86 \r
87 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(char a, FixedPoint<T,precision> b) { return b*=a; }\r
88 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned char a, FixedPoint<T,precision> b) { return b*=a; }\r
89 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(short a, FixedPoint<T,precision> b) { return b*=a; }\r
90 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned short a, FixedPoint<T,precision> b) { return b*=a; }\r
91 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(int a, FixedPoint<T,precision> b) { return b*=a; }\r
92 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned int a, FixedPoint<T,precision> b) { return b*=a; }\r
93 \r
94 template<typename T, unsigned int precision> float operator *(float a, FixedPoint<T,precision> b) { return b*a; }\r
95 template<typename T, unsigned int precision> double operator *(double a, FixedPoint<T,precision> b) { return b*a; }\r
96 \r
97 }\r
98 \r
99 }\r
100 \r
101 #endif\r
102 /*\r
103   Local Variables:\r
104   mode:c++\r
105   c-file-style:"stroustrup"\r
106   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
107   indent-tabs-mode:nil\r
108   fill-column:99\r
109   End:\r
110 */\r
111 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
112 /*\r
113  * Inkscape::Util::FixedPoint - fixed point type\r
114  *\r
115  * Authors:\r
116  *   Jasper van de Gronde <th.v.d.gronde@hccnet.net>\r
117  *\r
118  * Copyright (C) 2006 Jasper van de Gronde\r
119  *\r
120  * Released under GNU GPL, read the file 'COPYING' for more information\r
121  */\r
122 \r
123 #ifndef SEEN_INKSCAPE_UTIL_FIXED_POINT_H\r
124 #define SEEN_INKSCAPE_UTIL_FIXED_POINT_H\r
125 \r
126 #include "traits/reference.h"\r
127 #include <math.h>\r
128 #include <algorithm>\r
129 #include <limits>\r
130 \r
131 namespace Inkscape {\r
132 \r
133 namespace Util {\r
134 \r
135 template <typename T, unsigned int precision>\r
136 class FixedPoint {\r
137 public:\r
138     FixedPoint() {}\r
139     FixedPoint(const FixedPoint& value) : v(value.v) {}\r
140     FixedPoint(char value) : v(static_cast<T>(value)<<precision) {}\r
141     FixedPoint(unsigned char value) : v(static_cast<T>(value)<<precision) {}\r
142     FixedPoint(short value) : v(static_cast<T>(value)<<precision) {}\r
143     FixedPoint(unsigned short value) : v(static_cast<T>(value)<<precision) {}\r
144     FixedPoint(int value) : v(static_cast<T>(value)<<precision) {}\r
145     FixedPoint(unsigned int value) : v(static_cast<T>(value)<<precision) {}\r
146     FixedPoint(double value) : v(static_cast<T>(floor(value*(1<<precision)))) {}\r
147 \r
148     FixedPoint& operator+=(FixedPoint val) { v += val.v; return *this; }\r
149     FixedPoint& operator-=(FixedPoint val) { v -= val.v; return *this; }\r
150     FixedPoint& operator*=(FixedPoint val) {\r
151         const unsigned int half_size = 8*sizeof(T)/2;\r
152         const T al = v&((1<<half_size)-1), bl = val.v&((1<<half_size)-1);\r
153         const T ah = v>>half_size, bh = val.v>>half_size;\r
154         v = static_cast<unsigned int>(al*bl)>>precision;\r
155         if ( half_size >= precision ) {\r
156             v += ((al*bh)+(ah*bl)+((ah*bh)<<half_size))<<(half_size-precision);\r
157         } else {\r
158             v += ((al*bh)+(ah*bl))>>(precision-half_size);\r
159             v += (ah*bh)<<(2*half_size-precision);\r
160         }\r
161         return *this;\r
162     }\r
163 \r
164     FixedPoint& operator*=(char val) { v *= val; return *this; }\r
165     FixedPoint& operator*=(unsigned char val) { v *= val; return *this; }\r
166     FixedPoint& operator*=(short val) { v *= val; return *this; }\r
167     FixedPoint& operator*=(unsigned short val) { v *= val; return *this; }\r
168     FixedPoint& operator*=(int val) { v *= val; return *this; }\r
169     FixedPoint& operator*=(unsigned int val) { v *= val; return *this; }\r
170 \r
171     FixedPoint operator+(FixedPoint val) const { FixedPoint r(*this); return r+=val; }\r
172     FixedPoint operator-(FixedPoint val) const { FixedPoint r(*this); return r-=val; }\r
173     FixedPoint operator*(FixedPoint val) const { FixedPoint r(*this); return r*=val; }\r
174 \r
175     FixedPoint operator*(char val) const { FixedPoint r(*this); return r*=val; }\r
176     FixedPoint operator*(unsigned char val) const { FixedPoint r(*this); return r*=val; }\r
177     FixedPoint operator*(short val) const { FixedPoint r(*this); return r*=val; }\r
178     FixedPoint operator*(unsigned short val) const { FixedPoint r(*this); return r*=val; }\r
179     FixedPoint operator*(int val) const { FixedPoint r(*this); return r*=val; }\r
180     FixedPoint operator*(unsigned int val) const { FixedPoint r(*this); return r*=val; }\r
181 \r
182     float operator*(float val) const { return static_cast<float>(*this)*val; }\r
183     double operator*(double val) const { return static_cast<double>(*this)*val; }\r
184 \r
185     operator char() const { return v>>precision; }\r
186     operator unsigned char() const { return v>>precision; }\r
187     operator short() const { return v>>precision; }\r
188     operator unsigned short() const { return v>>precision; }\r
189     operator int() const { return v>>precision; }\r
190     operator unsigned int() const { return v>>precision; }\r
191 \r
192     operator float() const { return ldexpf(v,-precision); }\r
193     operator double() const { return ldexp(v,-precision); }\r
194 private:\r
195     T v;\r
196 };\r
197 \r
198 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(char a, FixedPoint<T,precision> b) { return b*=a; }\r
199 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned char a, FixedPoint<T,precision> b) { return b*=a; }\r
200 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(short a, FixedPoint<T,precision> b) { return b*=a; }\r
201 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned short a, FixedPoint<T,precision> b) { return b*=a; }\r
202 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(int a, FixedPoint<T,precision> b) { return b*=a; }\r
203 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned int a, FixedPoint<T,precision> b) { return b*=a; }\r
204 \r
205 template<typename T, unsigned int precision> float operator *(float a, FixedPoint<T,precision> b) { return b*a; }\r
206 template<typename T, unsigned int precision> double operator *(double a, FixedPoint<T,precision> b) { return b*a; }\r
207 \r
208 }\r
209 \r
210 }\r
211 \r
212 #endif\r
213 /*\r
214   Local Variables:\r
215   mode:c++\r
216   c-file-style:"stroustrup"\r
217   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
218   indent-tabs-mode:nil\r
219   fill-column:99\r
220   End:\r
221 */\r
222 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
223 /*\r
224  * Inkscape::Util::FixedPoint - fixed point type\r
225  *\r
226  * Authors:\r
227  *   Jasper van de Gronde <th.v.d.gronde@hccnet.net>\r
228  *\r
229  * Copyright (C) 2006 Jasper van de Gronde\r
230  *\r
231  * Released under GNU GPL, read the file 'COPYING' for more information\r
232  */\r
233 \r
234 #ifndef SEEN_INKSCAPE_UTIL_FIXED_POINT_H\r
235 #define SEEN_INKSCAPE_UTIL_FIXED_POINT_H\r
236 \r
237 #include "traits/reference.h"\r
238 #include <math.h>\r
239 #include <algorithm>\r
240 #include <limits>\r
241 \r
242 namespace Inkscape {\r
243 \r
244 namespace Util {\r
245 \r
246 template <typename T, unsigned int precision>\r
247 class FixedPoint {\r
248 public:\r
249     FixedPoint() {}\r
250     FixedPoint(const FixedPoint& value) : v(value.v) {}\r
251     FixedPoint(char value) : v(static_cast<T>(value)<<precision) {}\r
252     FixedPoint(unsigned char value) : v(static_cast<T>(value)<<precision) {}\r
253     FixedPoint(short value) : v(static_cast<T>(value)<<precision) {}\r
254     FixedPoint(unsigned short value) : v(static_cast<T>(value)<<precision) {}\r
255     FixedPoint(int value) : v(static_cast<T>(value)<<precision) {}\r
256     FixedPoint(unsigned int value) : v(static_cast<T>(value)<<precision) {}\r
257     FixedPoint(double value) : v(static_cast<T>(floor(value*(1<<precision)))) {}\r
258 \r
259     FixedPoint& operator+=(FixedPoint val) { v += val.v; return *this; }\r
260     FixedPoint& operator-=(FixedPoint val) { v -= val.v; return *this; }\r
261     FixedPoint& operator*=(FixedPoint val) {\r
262         const unsigned int half_size = 8*sizeof(T)/2;\r
263         const T al = v&((1<<half_size)-1), bl = val.v&((1<<half_size)-1);\r
264         const T ah = v>>half_size, bh = val.v>>half_size;\r
265         v = static_cast<unsigned int>(al*bl)>>precision;\r
266         if ( half_size >= precision ) {\r
267             v += ((al*bh)+(ah*bl)+((ah*bh)<<half_size))<<(half_size-precision);\r
268         } else {\r
269             v += ((al*bh)+(ah*bl))>>(precision-half_size);\r
270             v += (ah*bh)<<(2*half_size-precision);\r
271         }\r
272         return *this;\r
273     }\r
274 \r
275     FixedPoint& operator*=(char val) { v *= val; return *this; }\r
276     FixedPoint& operator*=(unsigned char val) { v *= val; return *this; }\r
277     FixedPoint& operator*=(short val) { v *= val; return *this; }\r
278     FixedPoint& operator*=(unsigned short val) { v *= val; return *this; }\r
279     FixedPoint& operator*=(int val) { v *= val; return *this; }\r
280     FixedPoint& operator*=(unsigned int val) { v *= val; return *this; }\r
281 \r
282     FixedPoint operator+(FixedPoint val) const { FixedPoint r(*this); return r+=val; }\r
283     FixedPoint operator-(FixedPoint val) const { FixedPoint r(*this); return r-=val; }\r
284     FixedPoint operator*(FixedPoint val) const { FixedPoint r(*this); return r*=val; }\r
285 \r
286     FixedPoint operator*(char val) const { FixedPoint r(*this); return r*=val; }\r
287     FixedPoint operator*(unsigned char val) const { FixedPoint r(*this); return r*=val; }\r
288     FixedPoint operator*(short val) const { FixedPoint r(*this); return r*=val; }\r
289     FixedPoint operator*(unsigned short val) const { FixedPoint r(*this); return r*=val; }\r
290     FixedPoint operator*(int val) const { FixedPoint r(*this); return r*=val; }\r
291     FixedPoint operator*(unsigned int val) const { FixedPoint r(*this); return r*=val; }\r
292 \r
293     float operator*(float val) const { return static_cast<float>(*this)*val; }\r
294     double operator*(double val) const { return static_cast<double>(*this)*val; }\r
295 \r
296     operator char() const { return v>>precision; }\r
297     operator unsigned char() const { return v>>precision; }\r
298     operator short() const { return v>>precision; }\r
299     operator unsigned short() const { return v>>precision; }\r
300     operator int() const { return v>>precision; }\r
301     operator unsigned int() const { return v>>precision; }\r
302 \r
303     operator float() const { return ldexpf(v,-precision); }\r
304     operator double() const { return ldexp(v,-precision); }\r
305 private:\r
306     T v;\r
307 };\r
308 \r
309 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(char a, FixedPoint<T,precision> b) { return b*=a; }\r
310 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned char a, FixedPoint<T,precision> b) { return b*=a; }\r
311 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(short a, FixedPoint<T,precision> b) { return b*=a; }\r
312 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned short a, FixedPoint<T,precision> b) { return b*=a; }\r
313 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(int a, FixedPoint<T,precision> b) { return b*=a; }\r
314 template<typename T, unsigned int precision> FixedPoint<T,precision> operator *(unsigned int a, FixedPoint<T,precision> b) { return b*=a; }\r
315 \r
316 template<typename T, unsigned int precision> float operator *(float a, FixedPoint<T,precision> b) { return b*a; }\r
317 template<typename T, unsigned int precision> double operator *(double a, FixedPoint<T,precision> b) { return b*a; }\r
318 \r
319 }\r
320 \r
321 }\r
322 \r
323 #endif\r
324 /*\r
325   Local Variables:\r
326   mode:c++\r
327   c-file-style:"stroustrup"\r
328   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
329   indent-tabs-mode:nil\r
330   fill-column:99\r
331   End:\r
332 */\r
333 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r