1 /* Copyright (C) 2003 Jean-Marc Valin */
2 /**
3 @file fixed_debug.h
4 @brief Fixed-point operations with debugging
5 */
6 /*
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 - Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13
14 - Redistributions in binary form must reproduce the above copyright
15 notice, this list of conditions and the following disclaimer in the
16 documentation and/or other materials provided with the distribution.
17
18 - Neither the name of the Xiph.org Foundation nor the names of its
19 contributors may be used to endorse or promote products derived from
20 this software without specific prior written permission.
21
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
26 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #ifndef FIXED_DEBUG_H
36 #define FIXED_DEBUG_H
37
38 #include <stdio.h>
39
40 extern long long spx_mips;
41 #define MIPS_INC spx_mips++,
42
43 #define QCONST16(x,bits) ((spx_word16_t)((x)*(1<<(bits))+(1<<((bits)-1))))
44 #define QCONST32(x,bits) ((spx_word32_t)((x)*(1<<(bits))+(1<<((bits)-1))))
45
46 #define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
47 #define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
48
NEG16(int x)49 static inline short NEG16(int x)
50 {
51 int res;
52 if (!VERIFY_SHORT(x))
53 {
54 fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
55 }
56 res = -x;
57 if (!VERIFY_SHORT(res))
58 fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
59 spx_mips++;
60 return res;
61 }
NEG32(long long x)62 static inline int NEG32(long long x)
63 {
64 long long res;
65 if (!VERIFY_INT(x))
66 {
67 fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
68 }
69 res = -x;
70 if (!VERIFY_INT(res))
71 fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
72 spx_mips++;
73 return res;
74 }
75
EXTRACT16(int x)76 static inline short EXTRACT16(int x)
77 {
78 int res;
79 if (!VERIFY_SHORT(x))
80 {
81 fprintf (stderr, "EXTRACT16: input is not short: %d\n", x);
82 }
83 res = x;
84 spx_mips++;
85 return res;
86 }
87
EXTEND32(int x)88 static inline int EXTEND32(int x)
89 {
90 int res;
91 if (!VERIFY_SHORT(x))
92 {
93 fprintf (stderr, "EXTRACT16: input is not short: %d\n", x);
94 }
95 res = x;
96 spx_mips++;
97 return res;
98 }
99
SHR16(int a,int shift)100 static inline short SHR16(int a, int shift)
101 {
102 int res;
103 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
104 {
105 fprintf (stderr, "SHR16: inputs are not short: %d %d\n", a, shift);
106 }
107 res = a>>shift;
108 if (!VERIFY_SHORT(res))
109 fprintf (stderr, "SHR16: output is not short: %d\n", res);
110 spx_mips++;
111 return res;
112 }
SHL16(int a,int shift)113 static inline short SHL16(int a, int shift)
114 {
115 int res;
116 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
117 {
118 fprintf (stderr, "SHR16: inputs are not short: %d %d\n", a, shift);
119 }
120 res = a<<shift;
121 if (!VERIFY_SHORT(res))
122 fprintf (stderr, "SHR16: output is not short: %d\n", res);
123 spx_mips++;
124 return res;
125 }
126
SHR32(long long a,int shift)127 static inline int SHR32(long long a, int shift)
128 {
129 long long res;
130 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
131 {
132 fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
133 }
134 res = a>>shift;
135 if (!VERIFY_INT(res))
136 fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
137 spx_mips++;
138 return res;
139 }
SHL32(long long a,int shift)140 static inline int SHL32(long long a, int shift)
141 {
142 long long res;
143 if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
144 {
145 fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
146 }
147 res = a<<shift;
148 if (!VERIFY_INT(res))
149 fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
150 spx_mips++;
151 return res;
152 }
153
154
155 #define PSHR16(a,shift) (SHR16(ADD16(a,(1<<((shift)-1))),shift))
156 #define PSHR32(a,shift) (SHR32(ADD32(a,(1<<((shift)-1))),shift))
157 #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
158 #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
159
160 #define SHR(a,shift) ((a) >> (shift))
161 #define SHL(a,shift) ((a) << (shift))
162
ADD16(int a,int b)163 static inline short ADD16(int a, int b)
164 {
165 int res;
166 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
167 {
168 fprintf (stderr, "ADD16: inputs are not short: %d %d\n", a, b);
169 }
170 res = a+b;
171 if (!VERIFY_SHORT(res))
172 fprintf (stderr, "ADD16: output is not short: %d\n", res);
173 spx_mips++;
174 return res;
175 }
SUB16(int a,int b)176 static inline short SUB16(int a, int b)
177 {
178 int res;
179 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
180 {
181 fprintf (stderr, "SUB16: inputs are not short: %d %d\n", a, b);
182 }
183 res = a-b;
184 if (!VERIFY_SHORT(res))
185 fprintf (stderr, "SUB16: output is not short: %d\n", res);
186 spx_mips++;
187 return res;
188 }
189
ADD32(long long a,long long b)190 static inline int ADD32(long long a, long long b)
191 {
192 long long res;
193 if (!VERIFY_INT(a) || !VERIFY_INT(b))
194 {
195 fprintf (stderr, "ADD32: inputs are not int: %d %d\n", (int)a, (int)b);
196 }
197 res = a+b;
198 if (!VERIFY_INT(res))
199 fprintf (stderr, "ADD32: output is not int: %d\n", (int)res);
200 spx_mips++;
201 return res;
202 }
203
SUB32(long long a,long long b)204 static inline int SUB32(long long a, long long b)
205 {
206 long long res;
207 if (!VERIFY_INT(a) || !VERIFY_INT(b))
208 {
209 fprintf (stderr, "SUB32: inputs are not int: %d %d\n", (int)a, (int)b);
210 }
211 res = a-b;
212 if (!VERIFY_INT(res))
213 fprintf (stderr, "SUB32: output is not int: %d\n", (int)res);
214 spx_mips++;
215 return res;
216 }
217
218 #define ADD64(a,b) (MIPS_INC(a)+(b))
219
220 #define PSHR(a,shift) (SHR((a)+(1<<((shift)-1)),shift))
221
222 /* result fits in 16 bits */
MULT16_16_16(int a,int b)223 static inline short MULT16_16_16(int a, int b)
224 {
225 int res;
226 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
227 {
228 fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
229 }
230 res = a*b;
231 if (!VERIFY_SHORT(res))
232 fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
233 spx_mips++;
234 return res;
235 }
236
MULT16_16(int a,int b)237 static inline int MULT16_16(int a, int b)
238 {
239 long long res;
240 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
241 {
242 fprintf (stderr, "MULT16_16: inputs are not short: %d %d\n", a, b);
243 }
244 res = ((long long)a)*b;
245 if (!VERIFY_INT(res))
246 fprintf (stderr, "MULT16_16: output is not int: %d\n", (int)res);
247 spx_mips++;
248 return res;
249 }
250
251 #define MAC16_16(c,a,b) (spx_mips--,ADD32((c),MULT16_16((a),(b))))
252 #define MAC16_16_Q11(c,a,b) (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11))))
253 #define MAC16_16_Q13(c,a,b) (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13))))
254
MULT16_32_QX(int a,long long b,int Q)255 static inline int MULT16_32_QX(int a, long long b, int Q)
256 {
257 long long res;
258 if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
259 {
260 fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
261 }
262 res = (((long long)a)*(long long)b) >> Q;
263 if (!VERIFY_INT(res))
264 fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
265 spx_mips+=5;
266 return res;
267 }
268
269
270 #define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11)
271 #define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b)))
272 #define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12)
273 #define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13)
274 #define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14)
275 #define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
276 #define MAC16_32_Q15(c,a,b) ADD32((c),MULT16_32_Q15((a),(b)))
277
SATURATE(int a,int b)278 static inline int SATURATE(int a, int b)
279 {
280 if (a>b)
281 a=b;
282 if (a<-b)
283 a = -b;
284 return a;
285 }
286
MULT16_16_Q11_32(int a,int b)287 static inline int MULT16_16_Q11_32(int a, int b)
288 {
289 long long res;
290 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
291 {
292 fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
293 }
294 res = ((long long)a)*b;
295 res >>= 11;
296 if (!VERIFY_INT(res))
297 fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
298 spx_mips+=3;
299 return res;
300 }
MULT16_16_Q13(int a,int b)301 static inline short MULT16_16_Q13(int a, int b)
302 {
303 long long res;
304 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
305 {
306 fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
307 }
308 res = ((long long)a)*b;
309 res >>= 13;
310 if (!VERIFY_SHORT(res))
311 fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
312 spx_mips+=3;
313 return res;
314 }
MULT16_16_Q14(int a,int b)315 static inline short MULT16_16_Q14(int a, int b)
316 {
317 long long res;
318 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
319 {
320 fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
321 }
322 res = ((long long)a)*b;
323 res >>= 14;
324 if (!VERIFY_SHORT(res))
325 fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
326 spx_mips+=3;
327 return res;
328 }
MULT16_16_Q15(int a,int b)329 static inline short MULT16_16_Q15(int a, int b)
330 {
331 long long res;
332 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
333 {
334 fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d\n", a, b);
335 }
336 res = ((long long)a)*b;
337 res >>= 15;
338 if (!VERIFY_SHORT(res))
339 fprintf (stderr, "MULT16_16_Q15: output is not short: %d\n", (int)res);
340 spx_mips+=3;
341 return res;
342 }
343
MULT16_16_P13(int a,int b)344 static inline short MULT16_16_P13(int a, int b)
345 {
346 long long res;
347 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
348 {
349 fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
350 }
351 res = ((long long)a)*b;
352 res += 4096;
353 if (!VERIFY_INT(res))
354 fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
355 res >>= 13;
356 if (!VERIFY_SHORT(res))
357 fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
358 spx_mips+=4;
359 return res;
360 }
MULT16_16_P14(int a,int b)361 static inline short MULT16_16_P14(int a, int b)
362 {
363 long long res;
364 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
365 {
366 fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
367 }
368 res = ((long long)a)*b;
369 res += 8192;
370 if (!VERIFY_INT(res))
371 fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
372 res >>= 14;
373 if (!VERIFY_SHORT(res))
374 fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
375 spx_mips+=4;
376 return res;
377 }
MULT16_16_P15(int a,int b)378 static inline short MULT16_16_P15(int a, int b)
379 {
380 long long res;
381 if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
382 {
383 fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
384 }
385 res = ((long long)a)*b;
386 res += 16384;
387 if (!VERIFY_INT(res))
388 fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
389 res >>= 15;
390 if (!VERIFY_SHORT(res))
391 fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
392 spx_mips+=4;
393 return res;
394 }
395
396
DIV32_16(long long a,long long b)397 static inline int DIV32_16(long long a, long long b)
398 {
399 long long res;
400 if (b==0)
401 {
402 fprintf(stderr, "DIV32_16: divide by zero: %d/%d\n", (int)a, (int)b);
403 return 0;
404 }
405 if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
406 {
407 fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d\n", (int)a, (int)b);
408 }
409 res = a/b;
410 if (!VERIFY_SHORT(res))
411 {
412 fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d\n", (int)a,(int)b,(int)res);
413 if (res>32767)
414 res = 32767;
415 if (res<-32768)
416 res = -32768;
417 }
418 spx_mips+=20;
419 return res;
420 }
DIV32(long long a,long long b)421 static inline int DIV32(long long a, long long b)
422 {
423 long long res;
424 if (b==0)
425 {
426 fprintf(stderr, "DIV32: divide by zero: %d/%d\n", (int)a, (int)b);
427 return 0;
428 }
429
430 if (!VERIFY_INT(a) || !VERIFY_INT(b))
431 {
432 fprintf (stderr, "DIV32: inputs are not int/short: %d %d\n", (int)a, (int)b);
433 }
434 res = a/b;
435 if (!VERIFY_INT(res))
436 fprintf (stderr, "DIV32: output is not int: %d\n", (int)res);
437 spx_mips+=36;
438 return res;
439 }
440
441
442
443 #endif
444