Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
fixed.h
00001 /* 00002 * libmad - MPEG audio decoder library 00003 * Copyright (C) 2000-2004 Underbit Technologies, Inc. 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 * 00019 * $Id: fixed.h,v 1.1 2010/11/23 20:12:57 andy Exp $ 00020 */ 00021 00022 # ifndef LIBMAD_FIXED_H 00023 # define LIBMAD_FIXED_H 00024 00025 #include "config.h" 00026 00027 # if SIZEOF_INT >= 4 00028 typedef signed int mad_fixed_t; 00029 00030 typedef signed int mad_fixed64hi_t; 00031 typedef unsigned int mad_fixed64lo_t; 00032 # else 00033 typedef signed long mad_fixed_t; 00034 00035 typedef signed long mad_fixed64hi_t; 00036 typedef unsigned long mad_fixed64lo_t; 00037 # endif 00038 00039 # if defined(_MSC_VER) 00040 # define mad_fixed64_t signed __int64 00041 # elif 1 || defined(__GNUC__) 00042 # define mad_fixed64_t signed long long 00043 # endif 00044 00045 # if defined(FPM_FLOAT) 00046 typedef double mad_sample_t; 00047 # else 00048 typedef mad_fixed_t mad_sample_t; 00049 # endif 00050 00051 /* 00052 * Fixed-point format: 0xABBBBBBB 00053 * A == whole part (sign + 3 bits) 00054 * B == fractional part (28 bits) 00055 * 00056 * Values are signed two's complement, so the effective range is: 00057 * 0x80000000 to 0x7fffffff 00058 * -8.0 to +7.9999999962747097015380859375 00059 * 00060 * The smallest representable value is: 00061 * 0x00000001 == 0.0000000037252902984619140625 (i.e. about 3.725e-9) 00062 * 00063 * 28 bits of fractional accuracy represent about 00064 * 8.6 digits of decimal accuracy. 00065 * 00066 * Fixed-point numbers can be added or subtracted as normal 00067 * integers, but multiplication requires shifting the 64-bit result 00068 * from 56 fractional bits back to 28 (and rounding.) 00069 * 00070 * Changing the definition of MAD_F_FRACBITS is only partially 00071 * supported, and must be done with care. 00072 */ 00073 00074 # define MAD_F_FRACBITS 28 00075 00076 # if MAD_F_FRACBITS == 28 00077 # define MAD_F(x) ((mad_fixed_t) (x##L)) 00078 # else 00079 # if MAD_F_FRACBITS < 28 00080 # warning "MAD_F_FRACBITS < 28" 00081 # define MAD_F(x) ((mad_fixed_t) \ 00082 (((x##L) + \ 00083 (1L << (28 - MAD_F_FRACBITS - 1))) >> \ 00084 (28 - MAD_F_FRACBITS))) 00085 # elif MAD_F_FRACBITS > 28 00086 # error "MAD_F_FRACBITS > 28 not currently supported" 00087 # define MAD_F(x) ((mad_fixed_t) \ 00088 ((x##L) << (MAD_F_FRACBITS - 28))) 00089 # endif 00090 # endif 00091 00092 # define MAD_F_MIN ((mad_fixed_t) -0x80000000L) 00093 # define MAD_F_MAX ((mad_fixed_t) +0x7fffffffL) 00094 00095 # define MAD_F_ONE MAD_F(0x10000000) 00096 00097 # define mad_f_tofixed(x) ((mad_fixed_t) \ 00098 ((x) * (double) (1L << MAD_F_FRACBITS) + 0.5)) 00099 # define mad_f_todouble(x) ((double) \ 00100 ((x) / (double) (1L << MAD_F_FRACBITS))) 00101 00102 # define mad_f_intpart(x) ((x) >> MAD_F_FRACBITS) 00103 # define mad_f_fracpart(x) ((x) & ((1L << MAD_F_FRACBITS) - 1)) 00104 /* (x should be positive) */ 00105 00106 # define mad_f_fromint(x) ((x) << MAD_F_FRACBITS) 00107 00108 # define mad_f_add(x, y) ((x) + (y)) 00109 # define mad_f_sub(x, y) ((x) - (y)) 00110 00111 # if defined(FPM_FLOAT) 00112 # error "FPM_FLOAT not yet supported" 00113 00114 # undef MAD_F 00115 # define MAD_F(x) mad_f_todouble(x) 00116 00117 # define mad_f_mul(x, y) ((x) * (y)) 00118 # define mad_f_scale64 00119 00120 # undef ASO_ZEROCHECK 00121 00122 # elif defined(FPM_64BIT) 00123 00124 /* 00125 * This version should be the most accurate if 64-bit types are supported by 00126 * the compiler, although it may not be the most efficient. 00127 */ 00128 # if defined(OPT_ACCURACY) 00129 # define mad_f_mul(x, y) \ 00130 ((mad_fixed_t) \ 00131 ((((mad_fixed64_t) (x) * (y)) + \ 00132 (1L << (MAD_F_SCALEBITS - 1))) >> MAD_F_SCALEBITS)) 00133 # else 00134 # define mad_f_mul(x, y) \ 00135 ((mad_fixed_t) (((mad_fixed64_t) (x) * (y)) >> MAD_F_SCALEBITS)) 00136 # endif 00137 00138 # define MAD_F_SCALEBITS MAD_F_FRACBITS 00139 00140 /* --- Intel --------------------------------------------------------------- */ 00141 00142 # elif defined(FPM_INTEL) 00143 00144 # if defined(_MSC_VER) 00145 # pragma warning(push) 00146 # pragma warning(disable: 4035) /* no return value */ 00147 static __forceinline 00148 mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y) 00149 { 00150 enum { 00151 fracbits = MAD_F_FRACBITS 00152 }; 00153 00154 __asm { 00155 mov eax, x 00156 imul y 00157 shrd eax, edx, fracbits 00158 } 00159 00160 /* implicit return of eax */ 00161 } 00162 # pragma warning(pop) 00163 00164 # define mad_f_mul mad_f_mul_inline 00165 # define mad_f_scale64 00166 # else 00167 /* 00168 * This Intel version is fast and accurate; the disposition of the least 00169 * significant bit depends on OPT_ACCURACY via mad_f_scale64(). 00170 */ 00171 # define MAD_F_MLX(hi, lo, x, y) \ 00172 asm ("imull %3" \ 00173 : "=a" (lo), "=d" (hi) \ 00174 : "%a" (x), "rm" (y) \ 00175 : "cc") 00176 00177 # if defined(OPT_ACCURACY) 00178 /* 00179 * This gives best accuracy but is not very fast. 00180 */ 00181 # define MAD_F_MLA(hi, lo, x, y) \ 00182 ({ mad_fixed64hi_t __hi; \ 00183 mad_fixed64lo_t __lo; \ 00184 MAD_F_MLX(__hi, __lo, (x), (y)); \ 00185 asm ("addl %2,%0\n\t" \ 00186 "adcl %3,%1" \ 00187 : "=rm" (lo), "=rm" (hi) \ 00188 : "r" (__lo), "r" (__hi), "0" (lo), "1" (hi) \ 00189 : "cc"); \ 00190 }) 00191 # endif /* OPT_ACCURACY */ 00192 00193 # if defined(OPT_ACCURACY) 00194 /* 00195 * Surprisingly, this is faster than SHRD followed by ADC. 00196 */ 00197 # define mad_f_scale64(hi, lo) \ 00198 ({ mad_fixed64hi_t __hi_; \ 00199 mad_fixed64lo_t __lo_; \ 00200 mad_fixed_t __result; \ 00201 asm ("addl %4,%2\n\t" \ 00202 "adcl %5,%3" \ 00203 : "=rm" (__lo_), "=rm" (__hi_) \ 00204 : "0" (lo), "1" (hi), \ 00205 "ir" (1L << (MAD_F_SCALEBITS - 1)), "ir" (0) \ 00206 : "cc"); \ 00207 asm ("shrdl %3,%2,%1" \ 00208 : "=rm" (__result) \ 00209 : "0" (__lo_), "r" (__hi_), "I" (MAD_F_SCALEBITS) \ 00210 : "cc"); \ 00211 __result; \ 00212 }) 00213 # elif defined(OPT_INTEL) 00214 /* 00215 * Alternate Intel scaling that may or may not perform better. 00216 */ 00217 # define mad_f_scale64(hi, lo) \ 00218 ({ mad_fixed_t __result; \ 00219 asm ("shrl %3,%1\n\t" \ 00220 "shll %4,%2\n\t" \ 00221 "orl %2,%1" \ 00222 : "=rm" (__result) \ 00223 : "0" (lo), "r" (hi), \ 00224 "I" (MAD_F_SCALEBITS), "I" (32 - MAD_F_SCALEBITS) \ 00225 : "cc"); \ 00226 __result; \ 00227 }) 00228 # else 00229 # define mad_f_scale64(hi, lo) \ 00230 ({ mad_fixed_t __result; \ 00231 asm ("shrdl %3,%2,%1" \ 00232 : "=rm" (__result) \ 00233 : "0" (lo), "r" (hi), "I" (MAD_F_SCALEBITS) \ 00234 : "cc"); \ 00235 __result; \ 00236 }) 00237 # endif /* OPT_ACCURACY */ 00238 00239 # define MAD_F_SCALEBITS MAD_F_FRACBITS 00240 # endif 00241 00242 /* --- ARM ----------------------------------------------------------------- */ 00243 00244 # elif defined(FPM_ARM) 00245 00246 /* 00247 * This ARM V4 version is as accurate as FPM_64BIT but much faster. The 00248 * least significant bit is properly rounded at no CPU cycle cost! 00249 */ 00250 # if 1 00251 /* 00252 * This is faster than the default implementation via MAD_F_MLX() and 00253 * mad_f_scale64(). 00254 */ 00255 # define mad_f_mul(x, y) \ 00256 ({ mad_fixed64hi_t __hi; \ 00257 mad_fixed64lo_t __lo; \ 00258 mad_fixed_t __result; \ 00259 asm ("smull %0, %1, %3, %4\n\t" \ 00260 "movs %0, %0, lsr %5\n\t" \ 00261 "adc %2, %0, %1, lsl %6" \ 00262 : "=&r" (__lo), "=&r" (__hi), "=r" (__result) \ 00263 : "%r" (x), "r" (y), \ 00264 "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ 00265 : "cc"); \ 00266 __result; \ 00267 }) 00268 # endif 00269 00270 # define MAD_F_MLX(hi, lo, x, y) \ 00271 asm ("smull %0, %1, %2, %3" \ 00272 : "=&r" (lo), "=&r" (hi) \ 00273 : "%r" (x), "r" (y)) 00274 00275 # define MAD_F_MLA(hi, lo, x, y) \ 00276 asm ("smlal %0, %1, %2, %3" \ 00277 : "+r" (lo), "+r" (hi) \ 00278 : "%r" (x), "r" (y)) 00279 00280 # define MAD_F_MLN(hi, lo) \ 00281 asm ("rsbs %0, %2, #0\n\t" \ 00282 "rsc %1, %3, #0" \ 00283 : "=r" (lo), "=r" (hi) \ 00284 : "0" (lo), "1" (hi) \ 00285 : "cc") 00286 00287 # define mad_f_scale64(hi, lo) \ 00288 ({ mad_fixed_t __result; \ 00289 asm ("movs %0, %1, lsr %3\n\t" \ 00290 "adc %0, %0, %2, lsl %4" \ 00291 : "=&r" (__result) \ 00292 : "r" (lo), "r" (hi), \ 00293 "M" (MAD_F_SCALEBITS), "M" (32 - MAD_F_SCALEBITS) \ 00294 : "cc"); \ 00295 __result; \ 00296 }) 00297 00298 # define MAD_F_SCALEBITS MAD_F_FRACBITS 00299 00300 /* --- MIPS ---------------------------------------------------------------- */ 00301 00302 # elif defined(FPM_MIPS) 00303 00304 /* 00305 * This MIPS version is fast and accurate; the disposition of the least 00306 * significant bit depends on OPT_ACCURACY via mad_f_scale64(). 00307 */ 00308 # define MAD_F_MLX(hi, lo, x, y) \ 00309 asm ("mult %2,%3" \ 00310 : "=l" (lo), "=h" (hi) \ 00311 : "%r" (x), "r" (y)) 00312 00313 # if defined(HAVE_MADD_ASM) 00314 # define MAD_F_MLA(hi, lo, x, y) \ 00315 asm ("madd %2,%3" \ 00316 : "+l" (lo), "+h" (hi) \ 00317 : "%r" (x), "r" (y)) 00318 # elif defined(HAVE_MADD16_ASM) 00319 /* 00320 * This loses significant accuracy due to the 16-bit integer limit in the 00321 * multiply/accumulate instruction. 00322 */ 00323 # define MAD_F_ML0(hi, lo, x, y) \ 00324 asm ("mult %2,%3" \ 00325 : "=l" (lo), "=h" (hi) \ 00326 : "%r" ((x) >> 12), "r" ((y) >> 16)) 00327 # define MAD_F_MLA(hi, lo, x, y) \ 00328 asm ("madd16 %2,%3" \ 00329 : "+l" (lo), "+h" (hi) \ 00330 : "%r" ((x) >> 12), "r" ((y) >> 16)) 00331 # define MAD_F_MLZ(hi, lo) ((mad_fixed_t) (lo)) 00332 # endif 00333 00334 # if defined(OPT_SPEED) 00335 # define mad_f_scale64(hi, lo) \ 00336 ((mad_fixed_t) ((hi) << (32 - MAD_F_SCALEBITS))) 00337 # define MAD_F_SCALEBITS MAD_F_FRACBITS 00338 # endif 00339 00340 /* --- SPARC --------------------------------------------------------------- */ 00341 00342 # elif defined(FPM_SPARC) 00343 00344 /* 00345 * This SPARC V8 version is fast and accurate; the disposition of the least 00346 * significant bit depends on OPT_ACCURACY via mad_f_scale64(). 00347 */ 00348 # define MAD_F_MLX(hi, lo, x, y) \ 00349 asm ("smul %2, %3, %0\n\t" \ 00350 "rd %%y, %1" \ 00351 : "=r" (lo), "=r" (hi) \ 00352 : "%r" (x), "rI" (y)) 00353 00354 /* --- PowerPC ------------------------------------------------------------- */ 00355 00356 # elif defined(FPM_PPC) 00357 00358 /* 00359 * This PowerPC version is fast and accurate; the disposition of the least 00360 * significant bit depends on OPT_ACCURACY via mad_f_scale64(). 00361 */ 00362 # define MAD_F_MLX(hi, lo, x, y) \ 00363 do { \ 00364 asm ("mullw %0,%1,%2" \ 00365 : "=r" (lo) \ 00366 : "%r" (x), "r" (y)); \ 00367 asm ("mulhw %0,%1,%2" \ 00368 : "=r" (hi) \ 00369 : "%r" (x), "r" (y)); \ 00370 } \ 00371 while (0) 00372 00373 # if defined(OPT_ACCURACY) 00374 /* 00375 * This gives best accuracy but is not very fast. 00376 */ 00377 # define MAD_F_MLA(hi, lo, x, y) \ 00378 ({ mad_fixed64hi_t __hi; \ 00379 mad_fixed64lo_t __lo; \ 00380 MAD_F_MLX(__hi, __lo, (x), (y)); \ 00381 asm ("addc %0,%2,%3\n\t" \ 00382 "adde %1,%4,%5" \ 00383 : "=r" (lo), "=r" (hi) \ 00384 : "%r" (lo), "r" (__lo), \ 00385 "%r" (hi), "r" (__hi) \ 00386 : "xer"); \ 00387 }) 00388 # endif 00389 00390 # if defined(OPT_ACCURACY) 00391 /* 00392 * This is slower than the truncating version below it. 00393 */ 00394 # define mad_f_scale64(hi, lo) \ 00395 ({ mad_fixed_t __result, __round; \ 00396 asm ("rotrwi %0,%1,%2" \ 00397 : "=r" (__result) \ 00398 : "r" (lo), "i" (MAD_F_SCALEBITS)); \ 00399 asm ("extrwi %0,%1,1,0" \ 00400 : "=r" (__round) \ 00401 : "r" (__result)); \ 00402 asm ("insrwi %0,%1,%2,0" \ 00403 : "+r" (__result) \ 00404 : "r" (hi), "i" (MAD_F_SCALEBITS)); \ 00405 asm ("add %0,%1,%2" \ 00406 : "=r" (__result) \ 00407 : "%r" (__result), "r" (__round)); \ 00408 __result; \ 00409 }) 00410 # else 00411 # define mad_f_scale64(hi, lo) \ 00412 ({ mad_fixed_t __result; \ 00413 asm ("rotrwi %0,%1,%2" \ 00414 : "=r" (__result) \ 00415 : "r" (lo), "i" (MAD_F_SCALEBITS)); \ 00416 asm ("insrwi %0,%1,%2,0" \ 00417 : "+r" (__result) \ 00418 : "r" (hi), "i" (MAD_F_SCALEBITS)); \ 00419 __result; \ 00420 }) 00421 # endif 00422 00423 # define MAD_F_SCALEBITS MAD_F_FRACBITS 00424 00425 /* --- Default ------------------------------------------------------------- */ 00426 00427 # elif defined(FPM_DEFAULT) 00428 00429 /* 00430 * This version is the most portable but it loses significant accuracy. 00431 * Furthermore, accuracy is biased against the second argument, so care 00432 * should be taken when ordering operands. 00433 * 00434 * The scale factors are constant as this is not used with SSO. 00435 * 00436 * Pre-rounding is required to stay within the limits of compliance. 00437 */ 00438 # if defined(OPT_SPEED) 00439 # define mad_f_mul(x, y) (((x) >> 12) * ((y) >> 16)) 00440 # else 00441 # define mad_f_mul(x, y) ((((x) + (1L << 11)) >> 12) * \ 00442 (((y) + (1L << 15)) >> 16)) 00443 # endif 00444 00445 /* ------------------------------------------------------------------------- */ 00446 00447 # else 00448 # error "no FPM selected" 00449 # endif 00450 00451 /* default implementations */ 00452 00453 # if !defined(mad_f_mul) 00454 # define mad_f_mul(x, y) \ 00455 ({ register mad_fixed64hi_t __hi; \ 00456 register mad_fixed64lo_t __lo; \ 00457 MAD_F_MLX(__hi, __lo, (x), (y)); \ 00458 mad_f_scale64(__hi, __lo); \ 00459 }) 00460 # endif 00461 00462 # if !defined(MAD_F_MLA) 00463 # define MAD_F_ML0(hi, lo, x, y) ((lo) = mad_f_mul((x), (y))) 00464 # define MAD_F_MLA(hi, lo, x, y) ((lo) += mad_f_mul((x), (y))) 00465 # define MAD_F_MLN(hi, lo) ((lo) = -(lo)) 00466 # define MAD_F_MLZ(hi, lo) ((void) (hi), (mad_fixed_t) (lo)) 00467 # endif 00468 00469 # if !defined(MAD_F_ML0) 00470 # define MAD_F_ML0(hi, lo, x, y) MAD_F_MLX((hi), (lo), (x), (y)) 00471 # endif 00472 00473 # if !defined(MAD_F_MLN) 00474 # define MAD_F_MLN(hi, lo) ((hi) = ((lo) = -(lo)) ? ~(hi) : -(hi)) 00475 # endif 00476 00477 # if !defined(MAD_F_MLZ) 00478 # define MAD_F_MLZ(hi, lo) mad_f_scale64((hi), (lo)) 00479 # endif 00480 00481 # if !defined(mad_f_scale64) 00482 # if defined(OPT_ACCURACY) 00483 # define mad_f_scale64(hi, lo) \ 00484 ((((mad_fixed_t) \ 00485 (((hi) << (32 - (MAD_F_SCALEBITS - 1))) | \ 00486 ((lo) >> (MAD_F_SCALEBITS - 1)))) + 1) >> 1) 00487 # else 00488 # define mad_f_scale64(hi, lo) \ 00489 ((mad_fixed_t) \ 00490 (((hi) << (32 - MAD_F_SCALEBITS)) | \ 00491 ((lo) >> MAD_F_SCALEBITS))) 00492 # endif 00493 # define MAD_F_SCALEBITS MAD_F_FRACBITS 00494 # endif 00495 00496 /* C routines */ 00497 00498 mad_fixed_t mad_f_abs(mad_fixed_t); 00499 mad_fixed_t mad_f_div(mad_fixed_t, mad_fixed_t); 00500 00501 # endif
Generated on Tue Jul 12 2022 23:11:09 by
