ex

Fork of mbed-os-example-mbed5-blinky by mbed-os-examples

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fixed_debug.h Source File

fixed_debug.h

Go to the documentation of this file.
00001 /* Copyright (C) 2003 Jean-Marc Valin */
00002 /**
00003    @file fixed_debug.h
00004    @brief Fixed-point operations with debugging
00005 */
00006 /*
00007    Redistribution and use in source and binary forms, with or without
00008    modification, are permitted provided that the following conditions
00009    are met:
00010    
00011    - Redistributions of source code must retain the above copyright
00012    notice, this list of conditions and the following disclaimer.
00013    
00014    - Redistributions in binary form must reproduce the above copyright
00015    notice, this list of conditions and the following disclaimer in the
00016    documentation and/or other materials provided with the distribution.
00017    
00018    - Neither the name of the Xiph.org Foundation nor the names of its
00019    contributors may be used to endorse or promote products derived from
00020    this software without specific prior written permission.
00021    
00022    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00025    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
00026    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00027    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00028    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00029    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00030    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00031    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 */
00034 
00035 #ifndef FIXED_DEBUG_H
00036 #define FIXED_DEBUG_H
00037 
00038 #include <stdio.h>
00039 
00040 extern long long spx_mips;
00041 #define MIPS_INC spx_mips++,
00042 
00043 #define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
00044 #define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits))))
00045 
00046 
00047 #define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
00048 #define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
00049 
00050 static inline short NEG16(int x)
00051 {
00052    int res;
00053    if (!VERIFY_SHORT(x))
00054    {
00055       fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
00056    }
00057    res = -x;
00058    if (!VERIFY_SHORT(res))
00059       fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
00060    spx_mips++;
00061    return res;
00062 }
00063 static inline int NEG32(long long x)
00064 {
00065    long long res;
00066    if (!VERIFY_INT(x))
00067    {
00068       fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
00069    }
00070    res = -x;
00071    if (!VERIFY_INT(res))
00072       fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
00073    spx_mips++;
00074    return res;
00075 }
00076 
00077 #define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__)
00078 static inline short _EXTRACT16(int x, char *file, int line)
00079 {
00080    int res;
00081    if (!VERIFY_SHORT(x))
00082    {
00083       fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line);
00084    }
00085    res = x;
00086    spx_mips++;
00087    return res;
00088 }
00089 
00090 #define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__)
00091 static inline int _EXTEND32(int x, char *file, int line)
00092 {
00093    int res;
00094    if (!VERIFY_SHORT(x))
00095    {
00096       fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line);
00097    }
00098    res = x;
00099    spx_mips++;
00100    return res;
00101 }
00102 
00103 #define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__)
00104 static inline short _SHR16(int a, int shift, char *file, int line) 
00105 {
00106    int res;
00107    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
00108    {
00109       fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line);
00110    }
00111    res = a>>shift;
00112    if (!VERIFY_SHORT(res))
00113       fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line);
00114    spx_mips++;
00115    return res;
00116 }
00117 #define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__)
00118 static inline short _SHL16(int a, int shift, char *file, int line) 
00119 {
00120    int res;
00121    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
00122    {
00123       fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line);
00124    }
00125    res = a<<shift;
00126    if (!VERIFY_SHORT(res))
00127       fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
00128    spx_mips++;
00129    return res;
00130 }
00131 
00132 static inline int SHR32(long long a, int shift) 
00133 {
00134    long long  res;
00135    if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
00136    {
00137       fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
00138    }
00139    res = a>>shift;
00140    if (!VERIFY_INT(res))
00141    {
00142       fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
00143    }
00144    spx_mips++;
00145    return res;
00146 }
00147 static inline int SHL32(long long a, int shift) 
00148 {
00149    long long  res;
00150    if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
00151    {
00152       fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift);
00153    }
00154    res = a<<shift;
00155    if (!VERIFY_INT(res))
00156    {
00157       fprintf (stderr, "SHL32: output is not int: %d\n", (int)res);
00158    }
00159    spx_mips++;
00160    return res;
00161 }
00162 
00163 #define PSHR16(a,shift) (SHR16(ADD16((a),((1<<((shift))>>1))),shift))
00164 #define PSHR32(a,shift) (SHR32(ADD32((a),((1<<((shift))>>1))),shift))
00165 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
00166 
00167 #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
00168 #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
00169 
00170 //#define SHR(a,shift) ((a) >> (shift))
00171 //#define SHL(a,shift) ((a) << (shift))
00172 
00173 #define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__)
00174 static inline short _ADD16(int a, int b, char *file, int line) 
00175 {
00176    int res;
00177    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
00178    {
00179       fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
00180    }
00181    res = a+b;
00182    if (!VERIFY_SHORT(res))
00183    {
00184       fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
00185    }
00186    spx_mips++;
00187    return res;
00188 }
00189 
00190 #define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__)
00191 static inline short _SUB16(int a, int b, char *file, int line) 
00192 {
00193    int res;
00194    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
00195    {
00196       fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
00197    }
00198    res = a-b;
00199    if (!VERIFY_SHORT(res))
00200       fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
00201    spx_mips++;
00202    return res;
00203 }
00204 
00205 #define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__)
00206 static inline int _ADD32(long long a, long long b, char *file, int line) 
00207 {
00208    long long res;
00209    if (!VERIFY_INT(a) || !VERIFY_INT(b))
00210    {
00211       fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
00212    }
00213    res = a+b;
00214    if (!VERIFY_INT(res))
00215    {
00216       fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
00217    }
00218    spx_mips++;
00219    return res;
00220 }
00221 
00222 static inline int SUB32(long long a, long long b) 
00223 {
00224    long long res;
00225    if (!VERIFY_INT(a) || !VERIFY_INT(b))
00226    {
00227       fprintf (stderr, "SUB32: inputs are not int: %d %d\n", (int)a, (int)b);
00228    }
00229    res = a-b;
00230    if (!VERIFY_INT(res))
00231       fprintf (stderr, "SUB32: output is not int: %d\n", (int)res);
00232    spx_mips++;
00233    return res;
00234 }
00235 
00236 #define ADD64(a,b) (MIPS_INC(a)+(b))
00237 
00238 /* result fits in 16 bits */
00239 static inline short MULT16_16_16(int a, int b) 
00240 {
00241    int res;
00242    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
00243    {
00244       fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
00245    }
00246    res = a*b;
00247    if (!VERIFY_SHORT(res))
00248       fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
00249    spx_mips++;
00250    return res;
00251 }
00252 
00253 #define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__)
00254 static inline int _MULT16_16(int a, int b, char *file, int line) 
00255 {
00256    long long res;
00257    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
00258    {
00259       fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
00260    }
00261    res = ((long long)a)*b;
00262    if (!VERIFY_INT(res))
00263       fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
00264    spx_mips++;
00265    return res;
00266 }
00267 
00268 #define MAC16_16(c,a,b)     (spx_mips--,ADD32((c),MULT16_16((a),(b))))
00269 #define MAC16_16_Q11(c,a,b)     (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11)))))
00270 #define MAC16_16_Q13(c,a,b)     (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13)))))
00271 #define MAC16_16_P13(c,a,b)     (EXTRACT16(ADD32((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13))))
00272 
00273 
00274 #define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__)
00275 static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line)
00276 {
00277    long long res;
00278    if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
00279    {
00280       fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
00281    }
00282    if (ABS32(b)>=(1<<(15+Q)))
00283       fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);      
00284    res = (((long long)a)*(long long)b) >> Q;
00285    if (!VERIFY_INT(res))
00286       fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line);
00287    spx_mips+=5;
00288    return res;
00289 }
00290 
00291 static inline int MULT16_32_PX(int a, long long b, int Q)
00292 {
00293    long long res;
00294    if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
00295    {
00296       fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
00297    }
00298    if (ABS32(b)>=(1<<(15+Q)))
00299       fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);      
00300    res = ((((long long)a)*(long long)b) + ((1<<Q)>>1))>> Q;
00301    if (!VERIFY_INT(res))
00302       fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
00303    spx_mips+=5;
00304    return res;
00305 }
00306 
00307 
00308 #define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11)
00309 #define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b)))
00310 #define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12)
00311 #define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13)
00312 #define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14)
00313 #define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
00314 #define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15)
00315 #define MAC16_32_Q15(c,a,b) ADD32((c),MULT16_32_Q15((a),(b)))
00316 
00317 static inline int SATURATE(int a, int b)
00318 {
00319    if (a>b)
00320       a=b;
00321    if (a<-b)
00322       a = -b;
00323    return a;
00324 }
00325 
00326 static inline int MULT16_16_Q11_32(int a, int b) 
00327 {
00328    long long res;
00329    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
00330    {
00331       fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
00332    }
00333    res = ((long long)a)*b;
00334    res >>= 11;
00335    if (!VERIFY_INT(res))
00336       fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
00337    spx_mips+=3;
00338    return res;
00339 }
00340 static inline short MULT16_16_Q13(int a, int b) 
00341 {
00342    long long res;
00343    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
00344    {
00345       fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
00346    }
00347    res = ((long long)a)*b;
00348    res >>= 13;
00349    if (!VERIFY_SHORT(res))
00350       fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
00351    spx_mips+=3;
00352    return res;
00353 }
00354 static inline short MULT16_16_Q14(int a, int b) 
00355 {
00356    long long res;
00357    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
00358    {
00359       fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
00360    }
00361    res = ((long long)a)*b;
00362    res >>= 14;
00363    if (!VERIFY_SHORT(res))
00364       fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
00365    spx_mips+=3;
00366    return res;
00367 }
00368 static inline short MULT16_16_Q15(int a, int b) 
00369 {
00370    long long res;
00371    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
00372    {
00373       fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d\n", a, b);
00374    }
00375    res = ((long long)a)*b;
00376    res >>= 15;
00377    if (!VERIFY_SHORT(res))
00378    {
00379       fprintf (stderr, "MULT16_16_Q15: output is not short: %d\n", (int)res);
00380    }
00381    spx_mips+=3;
00382    return res;
00383 }
00384 
00385 static inline short MULT16_16_P13(int a, int b) 
00386 {
00387    long long res;
00388    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
00389    {
00390       fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
00391    }
00392    res = ((long long)a)*b;
00393    res += 4096;
00394    if (!VERIFY_INT(res))
00395       fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
00396    res >>= 13;
00397    if (!VERIFY_SHORT(res))
00398       fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
00399    spx_mips+=4;
00400    return res;
00401 }
00402 static inline short MULT16_16_P14(int a, int b) 
00403 {
00404    long long res;
00405    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
00406    {
00407       fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
00408    }
00409    res = ((long long)a)*b;
00410    res += 8192;
00411    if (!VERIFY_INT(res))
00412       fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
00413    res >>= 14;
00414    if (!VERIFY_SHORT(res))
00415       fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
00416    spx_mips+=4;
00417    return res;
00418 }
00419 static inline short MULT16_16_P15(int a, int b) 
00420 {
00421    long long res;
00422    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
00423    {
00424       fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
00425    }
00426    res = ((long long)a)*b;
00427    res += 16384;
00428    if (!VERIFY_INT(res))
00429       fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
00430    res >>= 15;
00431    if (!VERIFY_SHORT(res))
00432       fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
00433    spx_mips+=4;
00434    return res;
00435 }
00436 
00437 #define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
00438 
00439 static inline int _DIV32_16(long long a, long long b, char *file, int line) 
00440 {
00441    long long res;
00442    if (b==0)
00443    {
00444       fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
00445       return 0;
00446    }
00447    if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
00448    {
00449       fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
00450    }
00451    res = a/b;
00452    if (!VERIFY_SHORT(res))
00453    {
00454       fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
00455       if (res>32767)
00456          res = 32767;
00457       if (res<-32768)
00458          res = -32768;
00459    }
00460    spx_mips+=20;
00461    return res;
00462 }
00463 
00464 #define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
00465 static inline int _DIV32(long long a, long long b, char *file, int line) 
00466 {
00467    long long res;
00468    if (b==0)
00469    {
00470       fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
00471       return 0;
00472    }
00473 
00474    if (!VERIFY_INT(a) || !VERIFY_INT(b))
00475    {
00476       fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
00477    }
00478    res = a/b;
00479    if (!VERIFY_INT(res))
00480       fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
00481    spx_mips+=36;
00482    return res;
00483 }
00484 #define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b)
00485 #define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b)
00486 
00487 #endif