Branch data Line data Source code
1 : : /* ______ ___ ___
2 : : * /\ _ \ /\_ \ /\_ \
3 : : * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 : : * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 : : * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 : : * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 : : * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 : : * /\____/
9 : : * \_/__/
10 : : *
11 : : * Fixed point math inline functions (generic C).
12 : : *
13 : : * By Shawn Hargreaves.
14 : : *
15 : : * See readme.txt for copyright information.
16 : : */
17 : :
18 : :
19 : : #ifndef __al_included_allegro5_inline_fmaths_inl
20 : : #define __al_included_allegro5_inline_fmaths_inl
21 : :
22 : : #include "allegro5/error.h"
23 : :
24 : : #ifdef __cplusplus
25 : : extern "C" {
26 : : #endif
27 : :
28 : :
29 : : /* al_ftofix and al_fixtof are used in generic C versions of al_fixmul and al_fixdiv */
30 [ - + ][ - + ]: 213242 : AL_INLINE(al_fixed, al_ftofix, (double x),
[ + - ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ - + ][ - + ]
[ + + ][ - + ]
[ - + ][ + + ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + + ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + + ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + + ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ - + ][ - + ]
[ + - ][ - + ]
[ - + ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
31 : : {
32 : : if (x > 32767.0) {
33 : : al_set_errno(ERANGE);
34 : : return 0x7FFFFFFF;
35 : : }
36 : :
37 : : if (x < -32767.0) {
38 : : al_set_errno(ERANGE);
39 : : return -0x7FFFFFFF;
40 : : }
41 : :
42 : : return (al_fixed)(x * 65536.0 + (x < 0 ? -0.5 : 0.5));
43 : : })
44 : :
45 : :
46 : 0 : AL_INLINE(double, al_fixtof, (al_fixed x),
47 : : {
48 : : return (double)x / 65536.0;
49 : : })
50 : :
51 : :
52 : : #ifdef ALLEGRO_NO_ASM
53 : :
54 : : /* use generic C versions */
55 : :
56 [ # # ][ # # ]: 0 : AL_INLINE(al_fixed, al_fixadd, (al_fixed x, al_fixed y),
[ # # ]
57 : : {
58 : : al_fixed result = x + y;
59 : :
60 : : if (result >= 0) {
61 : : if ((x < 0) && (y < 0)) {
62 : : al_set_errno(ERANGE);
63 : : return -0x7FFFFFFF;
64 : : }
65 : : else
66 : : return result;
67 : : }
68 : : else {
69 : : if ((x > 0) && (y > 0)) {
70 : : al_set_errno(ERANGE);
71 : : return 0x7FFFFFFF;
72 : : }
73 : : else
74 : : return result;
75 : : }
76 : : })
77 : :
78 : :
79 [ # # ][ # # ]: 0 : AL_INLINE(al_fixed, al_fixsub, (al_fixed x, al_fixed y),
[ # # ]
80 : : {
81 : : al_fixed result = x - y;
82 : :
83 : : if (result >= 0) {
84 : : if ((x < 0) && (y > 0)) {
85 : : al_set_errno(ERANGE);
86 : : return -0x7FFFFFFF;
87 : : }
88 : : else
89 : : return result;
90 : : }
91 : : else {
92 : : if ((x > 0) && (y < 0)) {
93 : : al_set_errno(ERANGE);
94 : : return 0x7FFFFFFF;
95 : : }
96 : : else
97 : : return result;
98 : : }
99 : : })
100 : :
101 : :
102 : : /* In benchmarks conducted circa May 2005 we found that, in the main:
103 : : * - IA32 machines performed faster with one implementation;
104 : : * - AMD64 and G4 machines performed faster with another implementation.
105 : : *
106 : : * Benchmarks were mainly done with differing versions of gcc.
107 : : * Results varied with other compilers, optimisation levels, etc.
108 : : * so this is not optimal, though a tenable compromise.
109 : : *
110 : : * Note that the following implementation are NOT what were benchmarked.
111 : : * We had forgotten to put in overflow detection in those versions.
112 : : * If you don't need overflow detection then previous versions in the
113 : : * CVS tree might be worth looking at.
114 : : *
115 : : * PS. Don't move the #ifs inside the AL_INLINE; BCC doesn't like it.
116 : : */
117 : : #if (defined ALLEGRO_I386) || (!defined LONG_LONG)
118 : : AL_INLINE(al_fixed, al_fixmul, (al_fixed x, al_fixed y),
119 : : {
120 : : return al_ftofix(al_fixtof(x) * al_fixtof(y));
121 : : })
122 : : #else
123 [ # # ][ # # ]: 0 : AL_INLINE(al_fixed, al_fixmul, (al_fixed x, al_fixed y),
124 : : {
125 : : LONG_LONG lx = x;
126 : : LONG_LONG ly = y;
127 : : LONG_LONG lres = (lx*ly);
128 : :
129 : : if (lres > 0x7FFFFFFF0000LL) {
130 : : al_set_errno(ERANGE);
131 : : return 0x7FFFFFFF;
132 : : }
133 : : else if (lres < -0x7FFFFFFF0000LL) {
134 : : al_set_errno(ERANGE);
135 : : return 0x80000000;
136 : : }
137 : : else {
138 : : int res = lres >> 16;
139 : : return res;
140 : : }
141 : : })
142 : : #endif /* al_fixmul() C implementations */
143 : :
144 : :
145 : : #if (defined ALLEGRO_CFG_NO_FPU) && (defined LONG_LONG)
146 : : AL_INLINE(al_fixed, al_fixdiv, (al_fixed x, al_fixed y),
147 : : {
148 : : LONG_LONG lres = x;
149 : : if (y == 0) {
150 : : al_set_errno(ERANGE);
151 : : return (x < 0) ? -0x7FFFFFFF : 0x7FFFFFFF;
152 : : }
153 : : lres <<= 16;
154 : : lres /= y;
155 : : if (lres > 0x7FFFFFFF) {
156 : : al_set_errno(ERANGE);
157 : : return 0x7FFFFFFF;
158 : : }
159 : : else if (lres < -0x7FFFFFFF) {
160 : : al_set_errno(ERANGE);
161 : : return 0x80000000;
162 : : }
163 : : else {
164 : : return (al_fixed)(lres);
165 : : }
166 : : })
167 : : #else
168 [ # # ][ # # ]: 0 : AL_INLINE(al_fixed, al_fixdiv, (al_fixed x, al_fixed y),
[ # # ][ # # ]
169 : : {
170 : : if (y == 0) {
171 : : al_set_errno(ERANGE);
172 : : return (x < 0) ? -0x7FFFFFFF : 0x7FFFFFFF;
173 : : }
174 : : else
175 : : return al_ftofix(al_fixtof(x) / al_fixtof(y));
176 : : })
177 : : #endif
178 : :
179 : :
180 [ # # ]: 0 : AL_INLINE(int, al_fixfloor, (al_fixed x),
181 : : {
182 : : /* (x >> 16) is not portable */
183 : : if (x >= 0)
184 : : return (x >> 16);
185 : : else
186 : : return ~((~x) >> 16);
187 : : })
188 : :
189 : :
190 [ # # ]: 0 : AL_INLINE(int, al_fixceil, (al_fixed x),
191 : : {
192 : : if (x > 0x7FFF0000) {
193 : : al_set_errno(ERANGE);
194 : : return 0x7FFF;
195 : : }
196 : :
197 : : return al_fixfloor(x + 0xFFFF);
198 : : })
199 : :
200 : : #endif /* C vs. inline asm */
201 : :
202 : :
203 : 0 : AL_INLINE(al_fixed, al_itofix, (int x),
204 : : {
205 : : return x << 16;
206 : : })
207 : :
208 : :
209 : 0 : AL_INLINE(int, al_fixtoi, (al_fixed x),
210 : : {
211 : : return al_fixfloor(x) + ((x & 0x8000) >> 15);
212 : : })
213 : :
214 : :
215 : 0 : AL_INLINE(al_fixed, al_fixcos, (al_fixed x),
216 : : {
217 : : return _al_fix_cos_tbl[((x + 0x4000) >> 15) & 0x1FF];
218 : : })
219 : :
220 : :
221 : 0 : AL_INLINE(al_fixed, al_fixsin, (al_fixed x),
222 : : {
223 : : return _al_fix_cos_tbl[((x - 0x400000 + 0x4000) >> 15) & 0x1FF];
224 : : })
225 : :
226 : :
227 : 0 : AL_INLINE(al_fixed, al_fixtan, (al_fixed x),
228 : : {
229 : : return _al_fix_tan_tbl[((x + 0x4000) >> 15) & 0xFF];
230 : : })
231 : :
232 : :
233 [ # # ]: 0 : AL_INLINE(al_fixed, al_fixacos, (al_fixed x),
234 : : {
235 : : if ((x < -65536) || (x > 65536)) {
236 : : al_set_errno(EDOM);
237 : : return 0;
238 : : }
239 : :
240 : : return _al_fix_acos_tbl[(x+65536+127)>>8];
241 : : })
242 : :
243 : :
244 [ # # ]: 0 : AL_INLINE(al_fixed, al_fixasin, (al_fixed x),
245 : : {
246 : : if ((x < -65536) || (x > 65536)) {
247 : : al_set_errno(EDOM);
248 : : return 0;
249 : : }
250 : :
251 : : return 0x00400000 - _al_fix_acos_tbl[(x+65536+127)>>8];
252 : : })
253 : :
254 : : #ifdef __cplusplus
255 : : }
256 : : #endif
257 : :
258 : : #endif
259 : :
260 : :
|