aboutsummaryrefslogtreecommitdiffstats
path: root/libFDK/include/fixpoint_math.h
diff options
context:
space:
mode:
Diffstat (limited to 'libFDK/include/fixpoint_math.h')
-rw-r--r--libFDK/include/fixpoint_math.h902
1 files changed, 664 insertions, 238 deletions
diff --git a/libFDK/include/fixpoint_math.h b/libFDK/include/fixpoint_math.h
index 0d50f0a..3805892 100644
--- a/libFDK/include/fixpoint_math.h
+++ b/libFDK/include/fixpoint_math.h
@@ -1,74 +1,85 @@
-
-/* -----------------------------------------------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
- All rights reserved.
+© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+Forschung e.V. All rights reserved.
1. INTRODUCTION
-The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
-the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
-This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
-
-AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
-audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
-independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
-of the MPEG specifications.
-
-Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
-may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
-individually for the purpose of encoding or decoding bit streams in products that are compliant with
-the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
-these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
-software may already be covered under those patent licenses when it is used for those licensed purposes only.
-
-Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
-are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
-applications information and documentation.
+The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
+that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
+scheme for digital audio. This FDK AAC Codec software is intended to be used on
+a wide variety of Android devices.
+
+AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
+general perceptual audio codecs. AAC-ELD is considered the best-performing
+full-bandwidth communications codec by independent studies and is widely
+deployed. AAC has been standardized by ISO and IEC as part of the MPEG
+specifications.
+
+Patent licenses for necessary patent claims for the FDK AAC Codec (including
+those of Fraunhofer) may be obtained through Via Licensing
+(www.vialicensing.com) or through the respective patent owners individually for
+the purpose of encoding or decoding bit streams in products that are compliant
+with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
+Android devices already license these patent claims through Via Licensing or
+directly from the patent owners, and therefore FDK AAC Codec software may
+already be covered under those patent licenses when it is used for those
+licensed purposes only.
+
+Commercially-licensed AAC software libraries, including floating-point versions
+with enhanced sound quality, are also available from Fraunhofer. Users are
+encouraged to check the Fraunhofer website for additional applications
+information and documentation.
2. COPYRIGHT LICENSE
-Redistribution and use in source and binary forms, with or without modification, are permitted without
-payment of copyright license fees provided that you satisfy the following conditions:
+Redistribution and use in source and binary forms, with or without modification,
+are permitted without payment of copyright license fees provided that you
+satisfy the following conditions:
-You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
-your modifications thereto in source code form.
+You must retain the complete text of this software license in redistributions of
+the FDK AAC Codec or your modifications thereto in source code form.
-You must retain the complete text of this software license in the documentation and/or other materials
-provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
-You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
+You must retain the complete text of this software license in the documentation
+and/or other materials provided with redistributions of the FDK AAC Codec or
+your modifications thereto in binary form. You must make available free of
+charge copies of the complete source code of the FDK AAC Codec and your
modifications thereto to recipients of copies in binary form.
-The name of Fraunhofer may not be used to endorse or promote products derived from this library without
-prior written permission.
+The name of Fraunhofer may not be used to endorse or promote products derived
+from this library without prior written permission.
-You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
-software or your modifications thereto.
+You may not charge copyright license fees for anyone to use, copy or distribute
+the FDK AAC Codec software or your modifications thereto.
-Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
-and the date of any change. For modified versions of the FDK AAC Codec, the term
-"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
-"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
+Your modified versions of the FDK AAC Codec must carry prominent notices stating
+that you changed the software and the date of any change. For modified versions
+of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
+must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
+AAC Codec Library for Android."
3. NO PATENT LICENSE
-NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
-ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
-respect to this software.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
+limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
+Fraunhofer provides no warranty of patent non-infringement with respect to this
+software.
-You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
-by appropriate patent licenses.
+You may use this FDK AAC Codec software or modifications thereto only for
+purposes that are authorized by appropriate patent licenses.
4. DISCLAIMER
-This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
-"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
-of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
-including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
-or business interruption, however caused and on any theory of liability, whether in contract, strict
-liability, or tort (including negligence), arising in any way out of the use of this software, even if
-advised of the possibility of such damage.
+This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
+holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+including but not limited to the implied warranties of merchantability and
+fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
+or consequential damages, including but not limited to procurement of substitute
+goods or services; loss of use, data, or profits, or business interruption,
+however caused and on any theory of liability, whether in contract, strict
+liability, or tort (including negligence), arising in any way out of the use of
+this software, even if advised of the possibility of such damage.
5. CONTACT INFORMATION
@@ -79,21 +90,77 @@ Am Wolfsmantel 33
www.iis.fraunhofer.de/amm
amm-info@iis.fraunhofer.de
------------------------------------------------------------------------------------------------------------ */
+----------------------------------------------------------------------------- */
-/*************************** Fraunhofer IIS FDK Tools **********************
+/******************* Library for basic calculation routines ********************
Author(s): M. Gayer
- Description: Fixed point specific mathematical functions
-******************************************************************************/
+ Description: Fixed point specific mathematical functions
-#ifndef __fixpoint_math_H
-#define __fixpoint_math_H
+*******************************************************************************/
+#ifndef FIXPOINT_MATH_H
+#define FIXPOINT_MATH_H
#include "common_fix.h"
+#include "scale.h"
+
+/*
+ * Data definitions
+ */
+
+#define LD_DATA_SCALING (64.0f)
+#define LD_DATA_SHIFT 6 /* pow(2, LD_DATA_SHIFT) = LD_DATA_SCALING */
+
+#define MAX_LD_PRECISION 10
+#define LD_PRECISION 10
+
+/* Taylor series coefficients for ln(1-x), centered at 0 (MacLaurin polynomial).
+ */
+#ifndef LDCOEFF_16BIT
+LNK_SECTION_CONSTDATA_L1
+static const FIXP_DBL ldCoeff[MAX_LD_PRECISION] = {
+ FL2FXCONST_DBL(-1.0), FL2FXCONST_DBL(-1.0 / 2.0),
+ FL2FXCONST_DBL(-1.0 / 3.0), FL2FXCONST_DBL(-1.0 / 4.0),
+ FL2FXCONST_DBL(-1.0 / 5.0), FL2FXCONST_DBL(-1.0 / 6.0),
+ FL2FXCONST_DBL(-1.0 / 7.0), FL2FXCONST_DBL(-1.0 / 8.0),
+ FL2FXCONST_DBL(-1.0 / 9.0), FL2FXCONST_DBL(-1.0 / 10.0)};
+#else /* LDCOEFF_16BIT */
+LNK_SECTION_CONSTDATA_L1
+static const FIXP_SGL ldCoeff[MAX_LD_PRECISION] = {
+ FL2FXCONST_SGL(-1.0), FL2FXCONST_SGL(-1.0 / 2.0),
+ FL2FXCONST_SGL(-1.0 / 3.0), FL2FXCONST_SGL(-1.0 / 4.0),
+ FL2FXCONST_SGL(-1.0 / 5.0), FL2FXCONST_SGL(-1.0 / 6.0),
+ FL2FXCONST_SGL(-1.0 / 7.0), FL2FXCONST_SGL(-1.0 / 8.0),
+ FL2FXCONST_SGL(-1.0 / 9.0), FL2FXCONST_SGL(-1.0 / 10.0)};
+#endif /* LDCOEFF_16BIT */
+
+/*****************************************************************************
+ functionname: invSqrtNorm2
+ description: delivers 1/sqrt(op) normalized to .5...1 and the shift value
+of the OUTPUT
+
+*****************************************************************************/
+#define SQRT_BITS 7
+#define SQRT_VALUES (128 + 2)
+#define SQRT_BITS_MASK 0x7f
+#define SQRT_FRACT_BITS_MASK 0x007FFFFF
+
+extern const FIXP_DBL invSqrtTab[SQRT_VALUES];
+
+/*
+ * Hardware specific implementations
+ */
+
+#if defined(__x86__)
+#include "x86/fixpoint_math_x86.h"
+#endif /* target architecture selector */
+
+/*
+ * Fallback implementations
+ */
#if !defined(FUNCTION_fIsLessThan)
/**
* \brief Compares two fixpoint values incl. scaling.
@@ -103,61 +170,83 @@ amm-info@iis.fraunhofer.de
* \param b_e exponent of the second input value.
* \return non-zero if (a_m*2^a_e) < (b_m*2^b_e), 0 otherwise
*/
-FDK_INLINE INT fIsLessThan(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e)
-{
+FDK_INLINE INT fIsLessThan(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e) {
if (a_e > b_e) {
- return (b_m >> fMin(a_e-b_e, DFRACT_BITS-1) > a_m);
+ return ((b_m >> fMin(a_e - b_e, DFRACT_BITS - 1)) > a_m);
} else {
- return (a_m >> fMin(b_e-a_e, DFRACT_BITS-1) < b_m);
+ return ((a_m >> fMin(b_e - a_e, DFRACT_BITS - 1)) < b_m);
}
}
-FDK_INLINE INT fIsLessThan(FIXP_SGL a_m, INT a_e, FIXP_SGL b_m, INT b_e)
-{
+FDK_INLINE INT fIsLessThan(FIXP_SGL a_m, INT a_e, FIXP_SGL b_m, INT b_e) {
if (a_e > b_e) {
- return (b_m >> fMin(a_e-b_e, FRACT_BITS-1) > a_m);
+ return ((b_m >> fMin(a_e - b_e, FRACT_BITS - 1)) > a_m);
} else {
- return (a_m >> fMin(b_e-a_e, FRACT_BITS-1) < b_m);
+ return ((a_m >> fMin(b_e - a_e, FRACT_BITS - 1)) < b_m);
}
}
#endif
-
-
-#define LD_DATA_SCALING (64.0f)
-#define LD_DATA_SHIFT 6 /* pow(2, LD_DATA_SHIFT) = LD_DATA_SCALING */
-
/**
* \brief deprecated. Use fLog2() instead.
*/
-FIXP_DBL CalcLdData(FIXP_DBL op);
+#define CalcLdData(op) fLog2(op, 0)
void LdDataVector(FIXP_DBL *srcVector, FIXP_DBL *destVector, INT number);
-FIXP_DBL CalcInvLdData(FIXP_DBL op);
+extern const UINT exp2_tab_long[32];
+extern const UINT exp2w_tab_long[32];
+extern const UINT exp2x_tab_long[32];
+
+LNK_SECTION_CODE_L1
+FDK_INLINE FIXP_DBL CalcInvLdData(const FIXP_DBL x) {
+ int set_zero = (x < FL2FXCONST_DBL(-31.0 / 64.0)) ? 0 : 1;
+ int set_max = (x >= FL2FXCONST_DBL(31.0 / 64.0)) | (x == FL2FXCONST_DBL(0.0));
+
+ FIXP_SGL frac = (FIXP_SGL)((LONG)x & 0x3FF);
+ UINT index3 = (UINT)(LONG)(x >> 10) & 0x1F;
+ UINT index2 = (UINT)(LONG)(x >> 15) & 0x1F;
+ UINT index1 = (UINT)(LONG)(x >> 20) & 0x1F;
+ int exp = fMin(31, ((x > FL2FXCONST_DBL(0.0f)) ? (31 - (int)(x >> 25))
+ : (int)(-(x >> 25))));
+
+ UINT lookup1 = exp2_tab_long[index1] * set_zero;
+ UINT lookup2 = exp2w_tab_long[index2];
+ UINT lookup3 = exp2x_tab_long[index3];
+ UINT lookup3f =
+ lookup3 + (UINT)(LONG)fMultDiv2((FIXP_DBL)(0x0016302F), (FIXP_SGL)frac);
+
+ UINT lookup12 = (UINT)(LONG)fMult((FIXP_DBL)lookup1, (FIXP_DBL)lookup2);
+ UINT lookup = (UINT)(LONG)fMult((FIXP_DBL)lookup12, (FIXP_DBL)lookup3f);
+ FIXP_DBL retVal = (lookup << 3) >> exp;
-void InitLdInt();
+ if (set_max) {
+ retVal = (FIXP_DBL)MAXVAL_DBL;
+ }
+
+ return retVal;
+}
+
+void InitLdInt();
FIXP_DBL CalcLdInt(INT i);
extern const USHORT sqrt_tab[49];
-inline FIXP_DBL sqrtFixp_lookup(FIXP_DBL x)
-{
+inline FIXP_DBL sqrtFixp_lookup(FIXP_DBL x) {
UINT y = (INT)x;
- UCHAR is_zero=(y==0);
- INT zeros=fixnormz_D(y) & 0x1e;
- y<<=zeros;
- UINT idx=(y>>26)-16;
- USHORT frac=(y>>10)&0xffff;
- USHORT nfrac=0xffff^frac;
- UINT t=nfrac*sqrt_tab[idx]+frac*sqrt_tab[idx+1];
- t=t>>(zeros>>1);
- return(is_zero ? 0 : t);
+ UCHAR is_zero = (y == 0);
+ INT zeros = fixnormz_D(y) & 0x1e;
+ y <<= zeros;
+ UINT idx = (y >> 26) - 16;
+ USHORT frac = (y >> 10) & 0xffff;
+ USHORT nfrac = 0xffff ^ frac;
+ UINT t = (UINT)nfrac * sqrt_tab[idx] + (UINT)frac * sqrt_tab[idx + 1];
+ t = t >> (zeros >> 1);
+ return (is_zero ? 0 : t);
}
-inline FIXP_DBL sqrtFixp_lookup(FIXP_DBL x, INT *x_e)
-{
+inline FIXP_DBL sqrtFixp_lookup(FIXP_DBL x, INT *x_e) {
UINT y = (INT)x;
INT e;
@@ -166,106 +255,153 @@ inline FIXP_DBL sqrtFixp_lookup(FIXP_DBL x, INT *x_e)
}
/* Normalize */
- e=fixnormz_D(y);
- y<<=e;
- e = *x_e - e + 2;
+ e = fixnormz_D(y);
+ y <<= e;
+ e = *x_e - e + 2;
/* Correct odd exponent. */
if (e & 1) {
y >>= 1;
- e ++;
+ e++;
}
/* Get square root */
- UINT idx=(y>>26)-16;
- USHORT frac=(y>>10)&0xffff;
- USHORT nfrac=0xffff^frac;
- UINT t=nfrac*sqrt_tab[idx]+frac*sqrt_tab[idx+1];
+ UINT idx = (y >> 26) - 16;
+ USHORT frac = (y >> 10) & 0xffff;
+ USHORT nfrac = 0xffff ^ frac;
+ UINT t = (UINT)nfrac * sqrt_tab[idx] + (UINT)frac * sqrt_tab[idx + 1];
/* Write back exponent */
*x_e = e >> 1;
- return (FIXP_DBL)(LONG)(t>>1);
+ return (FIXP_DBL)(LONG)(t >> 1);
}
-
-
-FIXP_DBL sqrtFixp(FIXP_DBL op);
-
void InitInvSqrtTab();
-FIXP_DBL invSqrtNorm2(FIXP_DBL op, INT *shift);
-
+#ifndef FUNCTION_invSqrtNorm2
+/**
+ * \brief calculate 1.0/sqrt(op)
+ * \param op_m mantissa of input value.
+ * \param result_e pointer to return the exponent of the result
+ * \return mantissa of the result
+ */
/*****************************************************************************
-
- functionname: invFixp
- description: delivers 1/(op)
-
+ delivers 1/sqrt(op) normalized to .5...1 and the shift value of the OUTPUT,
+ i.e. the denormalized result is 1/sqrt(op) = invSqrtNorm(op) * 2^(shift)
+ uses Newton-iteration for approximation
+ Q(n+1) = Q(n) + Q(n) * (0.5 - 2 * V * Q(n)^2)
+ with Q = 0.5* V ^-0.5; 0.5 <= V < 1.0
*****************************************************************************/
-inline FIXP_DBL invFixp(FIXP_DBL op)
-{
- INT tmp_exp ;
- FIXP_DBL tmp_inv = invSqrtNorm2(op, &tmp_exp) ;
- FDK_ASSERT((31-(2*tmp_exp+1))>=0) ;
- return ( fPow2Div2( (FIXP_DBL)tmp_inv ) >> (31-(2*tmp_exp+1)) ) ;
-}
+static FDK_FORCEINLINE FIXP_DBL invSqrtNorm2(FIXP_DBL op, INT *shift) {
+ FIXP_DBL val = op;
+ FIXP_DBL reg1, reg2;
+ if (val == FL2FXCONST_DBL(0.0)) {
+ *shift = 16;
+ return ((LONG)MAXVAL_DBL); /* maximum positive value */
+ }
+#define INVSQRTNORM2_LINEAR_INTERPOLATE
+#define INVSQRTNORM2_LINEAR_INTERPOLATE_HQ
+
+ /* normalize input, calculate shift value */
+ FDK_ASSERT(val > FL2FXCONST_DBL(0.0));
+ *shift = fNormz(val) - 1; /* CountLeadingBits() is not necessary here since
+ test value is always > 0 */
+ val <<= *shift; /* normalized input V */
+ *shift += 2; /* bias for exponent */
+
+#if defined(INVSQRTNORM2_LINEAR_INTERPOLATE)
+ INT index =
+ (INT)(val >> (DFRACT_BITS - 1 - (SQRT_BITS + 1))) & SQRT_BITS_MASK;
+ FIXP_DBL Fract =
+ (FIXP_DBL)(((INT)val & SQRT_FRACT_BITS_MASK) << (SQRT_BITS + 1));
+ FIXP_DBL diff = invSqrtTab[index + 1] - invSqrtTab[index];
+ reg1 = invSqrtTab[index] + (fMultDiv2(diff, Fract) << 1);
+#if defined(INVSQRTNORM2_LINEAR_INTERPOLATE_HQ)
+ /* reg1 = t[i] + (t[i+1]-t[i])*fract ... already computed ...
+ + (1-fract)fract*(t[i+2]-t[i+1])/2 */
+ if (Fract != (FIXP_DBL)0) {
+ /* fract = fract * (1 - fract) */
+ Fract = fMultDiv2(Fract, (FIXP_DBL)((ULONG)0x80000000 - (ULONG)Fract)) << 1;
+ diff = diff - (invSqrtTab[index + 2] - invSqrtTab[index + 1]);
+ reg1 = fMultAddDiv2(reg1, Fract, diff);
+ }
+#endif /* INVSQRTNORM2_LINEAR_INTERPOLATE_HQ */
+#else
+#error \
+ "Either define INVSQRTNORM2_NEWTON_ITERATE or INVSQRTNORM2_LINEAR_INTERPOLATE"
+#endif
+ /* calculate the output exponent = input exp/2 */
+ if (*shift & 0x00000001) { /* odd shift values ? */
+ /* Note: Do not use rounded value 0x5A82799A to avoid overflow with
+ * shift-by-2 */
+ reg2 = (FIXP_DBL)0x5A827999;
+ /* FL2FXCONST_DBL(0.707106781186547524400844362104849f);*/ /* 1/sqrt(2);
+ */
+ reg1 = fMultDiv2(reg1, reg2) << 2;
+ }
-#if defined(__mips__) && (__GNUC__==2)
+ *shift = *shift >> 1;
-#define FUNCTION_schur_div
-inline FIXP_DBL schur_div(FIXP_DBL num,FIXP_DBL denum, INT count)
-{
- INT result, tmp ;
- __asm__ ("srl %1, %2, 15\n"
- "div %3, %1\n" : "=lo" (result)
- : "%d" (tmp), "d" (denum) , "d" (num)
- : "hi" ) ;
- return result<<16 ;
+ return (reg1);
}
+#endif /* FUNCTION_invSqrtNorm2 */
-/*###########################################################################################*/
-#elif defined(__mips__) && (__GNUC__==3)
-
-#define FUNCTION_schur_div
-inline FIXP_DBL schur_div(FIXP_DBL num,FIXP_DBL denum, INT count)
-{
- INT result, tmp;
+#ifndef FUNCTION_sqrtFixp
+static FDK_FORCEINLINE FIXP_DBL sqrtFixp(FIXP_DBL op) {
+ INT tmp_exp = 0;
+ FIXP_DBL tmp_inv = invSqrtNorm2(op, &tmp_exp);
- __asm__ ("srl %[tmp], %[denum], 15\n"
- "div %[result], %[num], %[tmp]\n"
- : [tmp] "+r" (tmp), [result]"=r"(result)
- : [denum]"r"(denum), [num]"r"(num)
- : "hi", "lo");
- return result << (DFRACT_BITS-16);
+ FDK_ASSERT(tmp_exp > 0);
+ return ((FIXP_DBL)(fMultDiv2((op << (tmp_exp - 1)), tmp_inv) << 2));
}
+#endif /* FUNCTION_sqrtFixp */
-/*###########################################################################################*/
-#elif defined(SIMULATE_MIPS_DIV)
-
-#define FUNCTION_schur_div
-inline FIXP_DBL schur_div(FIXP_DBL num, FIXP_DBL denum, INT count)
-{
- FDK_ASSERT (count<=DFRACT_BITS-1);
- FDK_ASSERT (num>=(FIXP_DBL)0);
- FDK_ASSERT (denum>(FIXP_DBL)0);
- FDK_ASSERT (num <= denum);
+#ifndef FUNCTION_invFixp
+/**
+ * \brief calculate 1.0/op
+ * \param op mantissa of the input value.
+ * \return mantissa of the result with implicit exponent of 31
+ * \exceptions are provided for op=0,1 setting max. positive value
+ */
+static inline FIXP_DBL invFixp(FIXP_DBL op) {
+ if ((op == (FIXP_DBL)0x00000000) || (op == (FIXP_DBL)0x00000001)) {
+ return ((LONG)MAXVAL_DBL);
+ }
+ INT tmp_exp;
+ FIXP_DBL tmp_inv = invSqrtNorm2(op, &tmp_exp);
+ FDK_ASSERT((31 - (2 * tmp_exp + 1)) >= 0);
+ int shift = 31 - (2 * tmp_exp + 1);
+ tmp_inv = fPow2Div2(tmp_inv);
+ if (shift) {
+ tmp_inv = ((tmp_inv >> (shift - 1)) + (FIXP_DBL)1) >> 1;
+ }
+ return tmp_inv;
+}
- INT tmp = denum >> (count-1);
- INT result = 0;
+/**
+ * \brief calculate 1.0/(op_m * 2^op_e)
+ * \param op_m mantissa of the input value.
+ * \param op_e pointer into were the exponent of the input value is stored, and
+ * the result will be stored into.
+ * \return mantissa of the result
+ */
+static inline FIXP_DBL invFixp(FIXP_DBL op_m, int *op_e) {
+ if ((op_m == (FIXP_DBL)0x00000000) || (op_m == (FIXP_DBL)0x00000001)) {
+ *op_e = 31 - *op_e;
+ return ((LONG)MAXVAL_DBL);
+ }
- while (num > tmp)
- {
- num -= tmp;
- result++;
- }
+ INT tmp_exp;
+ FIXP_DBL tmp_inv = invSqrtNorm2(op_m, &tmp_exp);
- return result << (DFRACT_BITS-count);
+ *op_e = (tmp_exp << 1) - *op_e + 1;
+ return fPow2Div2(tmp_inv);
}
+#endif /* FUNCTION_invFixp */
-/*###########################################################################################*/
-#endif /* target architecture selector */
+#ifndef FUNCTION_schur_div
-#if !defined(FUNCTION_schur_div)
/**
* \brief Divide two FIXP_DBL values with given precision.
* \param num dividend
@@ -273,31 +409,34 @@ inline FIXP_DBL schur_div(FIXP_DBL num, FIXP_DBL denum, INT count)
* \param count amount of significant bits of the result (starting to the MSB)
* \return num/divisor
*/
-FIXP_DBL schur_div(FIXP_DBL num,FIXP_DBL denum, INT count);
-#endif
+FIXP_DBL schur_div(FIXP_DBL num, FIXP_DBL denum, INT count);
+#endif /* FUNCTION_schur_div */
-FIXP_DBL mul_dbl_sgl_rnd (const FIXP_DBL op1,
- const FIXP_SGL op2);
+FIXP_DBL mul_dbl_sgl_rnd(const FIXP_DBL op1, const FIXP_SGL op2);
+#ifndef FUNCTION_fMultNorm
/**
* \brief multiply two values with normalization, thus max precision.
* Author: Robert Weidner
*
* \param f1 first factor
- * \param f2 secod factor
- * \param result_e pointer to an INT where the exponent of the result is stored into
+ * \param f2 second factor
+ * \param result_e pointer to an INT where the exponent of the result is stored
+ * into
* \return mantissa of the product f1*f2
*/
-FIXP_DBL fMultNorm(
- FIXP_DBL f1,
- FIXP_DBL f2,
- INT *result_e
- );
+FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2, INT *result_e);
-inline FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2)
-{
+/**
+ * \brief Multiply 2 values using maximum precision. The exponent of the result
+ * is 0.
+ * \param f1_m mantissa of factor 1
+ * \param f2_m mantissa of factor 2
+ * \return mantissa of the result with exponent equal to 0
+ */
+inline FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2) {
FIXP_DBL m;
INT e;
@@ -309,51 +448,252 @@ inline FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2)
}
/**
+ * \brief Multiply 2 values with exponent and use given exponent for the
+ * mantissa of the result.
+ * \param f1_m mantissa of factor 1
+ * \param f1_e exponent of factor 1
+ * \param f2_m mantissa of factor 2
+ * \param f2_e exponent of factor 2
+ * \param result_e exponent for the returned mantissa of the result
+ * \return mantissa of the result with exponent equal to result_e
+ */
+inline FIXP_DBL fMultNorm(FIXP_DBL f1_m, INT f1_e, FIXP_DBL f2_m, INT f2_e,
+ INT result_e) {
+ FIXP_DBL m;
+ INT e;
+
+ m = fMultNorm(f1_m, f2_m, &e);
+
+ m = scaleValueSaturate(m, e + f1_e + f2_e - result_e);
+
+ return m;
+}
+#endif /* FUNCTION_fMultNorm */
+
+#ifndef FUNCTION_fMultI
+/**
+ * \brief Multiplies a fractional value and a integer value and performs
+ * rounding to nearest
+ * \param a fractional value
+ * \param b integer value
+ * \return integer value
+ */
+inline INT fMultI(FIXP_DBL a, INT b) {
+ FIXP_DBL m, mi;
+ INT m_e;
+
+ m = fMultNorm(a, (FIXP_DBL)b, &m_e);
+
+ if (m_e < (INT)0) {
+ if (m_e > (INT)-DFRACT_BITS) {
+ m = m >> ((-m_e) - 1);
+ mi = (m + (FIXP_DBL)1) >> 1;
+ } else {
+ mi = (FIXP_DBL)0;
+ }
+ } else {
+ mi = scaleValueSaturate(m, m_e);
+ }
+
+ return ((INT)mi);
+}
+#endif /* FUNCTION_fMultI */
+
+#ifndef FUNCTION_fMultIfloor
+/**
+ * \brief Multiplies a fractional value and a integer value and performs floor
+ * rounding
+ * \param a fractional value
+ * \param b integer value
+ * \return integer value
+ */
+inline INT fMultIfloor(FIXP_DBL a, INT b) {
+ FIXP_DBL m, mi;
+ INT m_e;
+
+ m = fMultNorm(a, (FIXP_DBL)b, &m_e);
+
+ if (m_e < (INT)0) {
+ if (m_e > (INT)-DFRACT_BITS) {
+ mi = m >> (-m_e);
+ } else {
+ mi = (FIXP_DBL)0;
+ if (m < (FIXP_DBL)0) {
+ mi = (FIXP_DBL)-1;
+ }
+ }
+ } else {
+ mi = scaleValueSaturate(m, m_e);
+ }
+
+ return ((INT)mi);
+}
+#endif /* FUNCTION_fMultIfloor */
+
+#ifndef FUNCTION_fMultIceil
+/**
+ * \brief Multiplies a fractional value and a integer value and performs ceil
+ * rounding
+ * \param a fractional value
+ * \param b integer value
+ * \return integer value
+ */
+inline INT fMultIceil(FIXP_DBL a, INT b) {
+ FIXP_DBL m, mi;
+ INT m_e;
+
+ m = fMultNorm(a, (FIXP_DBL)b, &m_e);
+
+ if (m_e < (INT)0) {
+ if (m_e > (INT)-DFRACT_BITS) {
+ mi = (m >> (-m_e));
+ if ((LONG)m & ((1 << (-m_e)) - 1)) {
+ mi = mi + (FIXP_DBL)1;
+ }
+ } else {
+ mi = (FIXP_DBL)1;
+ if (m < (FIXP_DBL)0) {
+ mi = (FIXP_DBL)0;
+ }
+ }
+ } else {
+ mi = scaleValueSaturate(m, m_e);
+ }
+
+ return ((INT)mi);
+}
+#endif /* FUNCTION_fMultIceil */
+
+#ifndef FUNCTION_fDivNorm
+/**
* \brief Divide 2 FIXP_DBL values with normalization of input values.
* \param num numerator
- * \param denum denomintator
- * \return num/denum with exponent = 0
+ * \param denum denominator
+ * \param result_e pointer to an INT where the exponent of the result is stored
+ * into
+ * \return num/denum with exponent = *result_e
*/
FIXP_DBL fDivNorm(FIXP_DBL num, FIXP_DBL denom, INT *result_e);
/**
- * \brief Divide 2 FIXP_DBL values with normalization of input values.
+ * \brief Divide 2 positive FIXP_DBL values with normalization of input values.
* \param num numerator
- * \param denum denomintator
- * \param result_e pointer to an INT where the exponent of the result is stored into
- * \return num/denum with exponent = *result_e
+ * \param denum denominator
+ * \return num/denum with exponent = 0
*/
FIXP_DBL fDivNorm(FIXP_DBL num, FIXP_DBL denom);
/**
- * \brief Divide 2 FIXP_DBL values with normalization of input values.
+ * \brief Divide 2 signed FIXP_DBL values with normalization of input values.
* \param num numerator
- * \param denum denomintator
+ * \param denum denominator
+ * \param result_e pointer to an INT where the exponent of the result is stored
+ * into
+ * \return num/denum with exponent = *result_e
+ */
+FIXP_DBL fDivNormSigned(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e);
+
+/**
+ * \brief Divide 2 signed FIXP_DBL values with normalization of input values.
+ * \param num numerator
+ * \param denum denominator
* \return num/denum with exponent = 0
*/
-FIXP_DBL fDivNormHighPrec(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e);
+FIXP_DBL fDivNormSigned(FIXP_DBL num, FIXP_DBL denom);
+#endif /* FUNCTION_fDivNorm */
/**
- * \brief Calculate log(argument)/log(2) (logarithm with base 2). deprecated. Use fLog2() instead.
- * \param arg mantissa of the argument
- * \param arg_e exponent of the argument
- * \param result_e pointer to an INT to store the exponent of the result
- * \return the mantissa of the result.
- * \param
+ * \brief Adjust mantissa to exponent -1
+ * \param a_m mantissa of value to be adjusted
+ * \param pA_e pointer to the exponen of a_m
+ * \return adjusted mantissa
*/
-FIXP_DBL CalcLog2(FIXP_DBL arg, INT arg_e, INT *result_e);
+inline FIXP_DBL fAdjust(FIXP_DBL a_m, INT *pA_e) {
+ INT shift;
+ shift = fNorm(a_m) - 1;
+ *pA_e -= shift;
+
+ return scaleValue(a_m, shift);
+}
+
+#ifndef FUNCTION_fAddNorm
/**
- * \brief return 2 ^ (exp * 2^exp_e)
+ * \brief Add two values with normalization
+ * \param a_m mantissa of first summand
+ * \param a_e exponent of first summand
+ * \param a_m mantissa of second summand
+ * \param a_e exponent of second summand
+ * \param pResult_e pointer to where the exponent of the result will be stored
+ * to.
+ * \return mantissa of result
+ */
+inline FIXP_DBL fAddNorm(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e,
+ INT *pResult_e) {
+ INT result_e;
+ FIXP_DBL result_m;
+
+ /* If one of the summands is zero, return the other.
+ This is necessary for the summation of a very small number to zero */
+ if (a_m == (FIXP_DBL)0) {
+ *pResult_e = b_e;
+ return b_m;
+ }
+ if (b_m == (FIXP_DBL)0) {
+ *pResult_e = a_e;
+ return a_m;
+ }
+
+ a_m = fAdjust(a_m, &a_e);
+ b_m = fAdjust(b_m, &b_e);
+
+ if (a_e > b_e) {
+ result_m = a_m + (b_m >> fMin(a_e - b_e, DFRACT_BITS - 1));
+ result_e = a_e;
+ } else {
+ result_m = (a_m >> fMin(b_e - a_e, DFRACT_BITS - 1)) + b_m;
+ result_e = b_e;
+ }
+
+ *pResult_e = result_e;
+ return result_m;
+}
+
+inline FIXP_DBL fAddNorm(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e,
+ INT result_e) {
+ FIXP_DBL result_m;
+
+ a_m = scaleValue(a_m, a_e - result_e);
+ b_m = scaleValue(b_m, b_e - result_e);
+
+ result_m = a_m + b_m;
+
+ return result_m;
+}
+#endif /* FUNCTION_fAddNorm */
+
+/**
+ * \brief Divide 2 FIXP_DBL values with normalization of input values.
+ * \param num numerator
+ * \param denum denomintator
+ * \return num/denum with exponent = 0
+ */
+FIXP_DBL fDivNormHighPrec(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e);
+
+#ifndef FUNCTION_fPow
+/**
+ * \brief return 2 ^ (exp_m * 2^exp_e)
* \param exp_m mantissa of the exponent to 2.0f
* \param exp_e exponent of the exponent to 2.0f
- * \param result_e pointer to a INT where the exponent of the result will be stored into
+ * \param result_e pointer to a INT where the exponent of the result will be
+ * stored into
* \return mantissa of the result
*/
FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e, INT *result_e);
/**
- * \brief return 2 ^ (exp_m * 2^exp_e). This version returns only the mantissa with implicit exponent of zero.
+ * \brief return 2 ^ (exp_m * 2^exp_e). This version returns only the mantissa
+ * with implicit exponent of zero.
* \param exp_m mantissa of the exponent to 2.0f
* \param exp_e exponent of the exponent to 2.0f
* \return mantissa of the result
@@ -361,57 +701,70 @@ FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e, INT *result_e);
FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e);
/**
- * \brief return x ^ (exp * 2^exp_e), where log2(x) = baseLd_m * 2^(baseLd_e). This saves
- * the need to compute log2() of constant values (when x is a constant).
- * \param ldx_m mantissa of log2() of x.
- * \param ldx_e exponent of log2() of x.
+ * \brief return x ^ (exp_m * 2^exp_e), where log2(x) = baseLd_m * 2^(baseLd_e).
+ * This saves the need to compute log2() of constant values (when x is a
+ * constant).
+ * \param baseLd_m mantissa of log2() of x.
+ * \param baseLd_e exponent of log2() of x.
* \param exp_m mantissa of the exponent to 2.0f
* \param exp_e exponent of the exponent to 2.0f
- * \param result_e pointer to a INT where the exponent of the result will be stored into
+ * \param result_e pointer to a INT where the exponent of the result will be
+ * stored into
* \return mantissa of the result
*/
-FIXP_DBL fLdPow(
- FIXP_DBL baseLd_m,
- INT baseLd_e,
- FIXP_DBL exp_m, INT exp_e,
- INT *result_e
- );
+FIXP_DBL fLdPow(FIXP_DBL baseLd_m, INT baseLd_e, FIXP_DBL exp_m, INT exp_e,
+ INT *result_e);
/**
- * \brief return x ^ (exp * 2^exp_e), where log2(x) = baseLd_m * 2^(baseLd_e). This saves
- * the need to compute log2() of constant values (when x is a constant). This version
- * does not return an exponent, which is implicitly 0.
- * \param ldx_m mantissa of log2() of x.
- * \param ldx_e exponent of log2() of x.
+ * \brief return x ^ (exp_m * 2^exp_e), where log2(x) = baseLd_m * 2^(baseLd_e).
+ * This saves the need to compute log2() of constant values (when x is a
+ * constant). This version does not return an exponent, which is
+ * implicitly 0.
+ * \param baseLd_m mantissa of log2() of x.
+ * \param baseLd_e exponent of log2() of x.
* \param exp_m mantissa of the exponent to 2.0f
* \param exp_e exponent of the exponent to 2.0f
* \return mantissa of the result
*/
-FIXP_DBL fLdPow(
- FIXP_DBL baseLd_m, INT baseLd_e,
- FIXP_DBL exp_m, INT exp_e
- );
+FIXP_DBL fLdPow(FIXP_DBL baseLd_m, INT baseLd_e, FIXP_DBL exp_m, INT exp_e);
/**
- * \brief return (base * 2^base_e) ^ (exp * 2^exp_e). Use fLdPow() instead whenever possible.
+ * \brief return (base_m * 2^base_e) ^ (exp * 2^exp_e). Use fLdPow() instead
+ * whenever possible.
* \param base_m mantissa of the base.
* \param base_e exponent of the base.
* \param exp_m mantissa of power to be calculated of the base.
* \param exp_e exponent of power to be calculated of the base.
- * \param result_e pointer to a INT where the exponent of the result will be stored into.
+ * \param result_e pointer to a INT where the exponent of the result will be
+ * stored into.
* \return mantissa of the result.
*/
-FIXP_DBL fPow(FIXP_DBL base_m, INT base_e, FIXP_DBL exp_m, INT exp_e, INT *result_e);
+FIXP_DBL fPow(FIXP_DBL base_m, INT base_e, FIXP_DBL exp_m, INT exp_e,
+ INT *result_e);
/**
- * \brief return (base * 2^base_e) ^ N
- * \param base mantissa of the base
+ * \brief return (base_m * 2^base_e) ^ N
+ * \param base_m mantissa of the base
* \param base_e exponent of the base
- * \param power to be calculated of the base
- * \param result_e pointer to a INT where the exponent of the result will be stored into
+ * \param N power to be calculated of the base
+ * \param result_e pointer to a INT where the exponent of the result will be
+ * stored into
* \return mantissa of the result
*/
FIXP_DBL fPowInt(FIXP_DBL base_m, INT base_e, INT N, INT *result_e);
+#endif /* #ifndef FUNCTION_fPow */
+
+#ifndef FUNCTION_fLog2
+/**
+ * \brief Calculate log(argument)/log(2) (logarithm with base 2). deprecated.
+ * Use fLog2() instead.
+ * \param arg mantissa of the argument
+ * \param arg_e exponent of the argument
+ * \param result_e pointer to an INT to store the exponent of the result
+ * \return the mantissa of the result.
+ * \param
+ */
+FIXP_DBL CalcLog2(FIXP_DBL arg, INT arg_e, INT *result_e);
/**
* \brief calculate logarithm of base 2 of x_m * 2^(x_e)
@@ -420,7 +773,68 @@ FIXP_DBL fPowInt(FIXP_DBL base_m, INT base_e, INT N, INT *result_e);
* \param pointer to an INT where the exponent of the result is returned into.
* \return mantissa of the result.
*/
-FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e, INT *result_e);
+FDK_INLINE FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e, INT *result_e) {
+ FIXP_DBL result_m;
+
+ /* Short cut for zero and negative numbers. */
+ if (x_m <= FL2FXCONST_DBL(0.0f)) {
+ *result_e = DFRACT_BITS - 1;
+ return FL2FXCONST_DBL(-1.0f);
+ }
+
+ /* Calculate log2() */
+ {
+ FIXP_DBL x2_m;
+
+ /* Move input value x_m * 2^x_e toward 1.0, where the taylor approximation
+ of the function log(1-x) centered at 0 is most accurate. */
+ {
+ INT b_norm;
+
+ b_norm = fNormz(x_m) - 1;
+ x2_m = x_m << b_norm;
+ x_e = x_e - b_norm;
+ }
+
+ /* map x from log(x) domain to log(1-x) domain. */
+ x2_m = -(x2_m + FL2FXCONST_DBL(-1.0));
+
+ /* Taylor polynomial approximation of ln(1-x) */
+ {
+ FIXP_DBL px2_m;
+ result_m = FL2FXCONST_DBL(0.0);
+ px2_m = x2_m;
+ for (int i = 0; i < LD_PRECISION; i++) {
+ result_m = fMultAddDiv2(result_m, ldCoeff[i], px2_m);
+ px2_m = fMult(px2_m, x2_m);
+ }
+ }
+ /* Multiply result with 1/ln(2) = 1.0 + 0.442695040888 (get log2(x) from
+ * ln(x) result). */
+ result_m =
+ fMultAddDiv2(result_m, result_m,
+ FL2FXCONST_DBL(2.0 * 0.4426950408889634073599246810019));
+
+ /* Add exponent part. log2(x_m * 2^x_e) = log2(x_m) + x_e */
+ if (x_e != 0) {
+ int enorm;
+
+ enorm = DFRACT_BITS - fNorm((FIXP_DBL)x_e);
+ /* The -1 in the right shift of result_m compensates the fMultDiv2() above
+ * in the taylor polynomial evaluation loop.*/
+ result_m = (result_m >> (enorm - 1)) +
+ ((FIXP_DBL)x_e << (DFRACT_BITS - 1 - enorm));
+
+ *result_e = enorm;
+ } else {
+ /* 1 compensates the fMultDiv2() above in the taylor polynomial evaluation
+ * loop.*/
+ *result_e = 1;
+ }
+ }
+
+ return result_m;
+}
/**
* \brief calculate logarithm of base 2 of x_m * 2^(x_e)
@@ -428,16 +842,27 @@ FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e, INT *result_e);
* \param x_e exponent of the input value.
* \return mantissa of the result with implicit exponent of LD_DATA_SHIFT.
*/
-FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e);
+FDK_INLINE FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e) {
+ if (x_m <= FL2FXCONST_DBL(0.0f)) {
+ x_m = FL2FXCONST_DBL(-1.0f);
+ } else {
+ INT result_e;
+ x_m = fLog2(x_m, x_e, &result_e);
+ x_m = scaleValue(x_m, result_e - LD_DATA_SHIFT);
+ }
+ return x_m;
+}
+#endif /* FUNCTION_fLog2 */
+
+#ifndef FUNCTION_fAddSaturate
/**
* \brief Add with saturation of the result.
* \param a first summand
* \param b second summand
* \return saturated sum of a and b.
*/
-inline FIXP_SGL fAddSaturate(const FIXP_SGL a, const FIXP_SGL b)
-{
+inline FIXP_SGL fAddSaturate(const FIXP_SGL a, const FIXP_SGL b) {
LONG sum;
sum = (LONG)(SHORT)a + (LONG)(SHORT)b;
@@ -451,19 +876,26 @@ inline FIXP_SGL fAddSaturate(const FIXP_SGL a, const FIXP_SGL b)
* \param b second summand
* \return saturated sum of a and b.
*/
-inline FIXP_DBL fAddSaturate(const FIXP_DBL a, const FIXP_DBL b)
-{
+inline FIXP_DBL fAddSaturate(const FIXP_DBL a, const FIXP_DBL b) {
LONG sum;
- sum = (LONG)(a>>1) + (LONG)(b>>1);
- sum = fMax(fMin((INT)sum, (INT)(MAXVAL_DBL>>1)), (INT)(MINVAL_DBL>>1));
- return (FIXP_DBL)(LONG)(sum<<1);
+ sum = (LONG)(a >> 1) + (LONG)(b >> 1);
+ sum = fMax(fMin((INT)sum, (INT)(MAXVAL_DBL >> 1)), (INT)(MINVAL_DBL >> 1));
+ return (FIXP_DBL)(LONG)(sum << 1);
}
+#endif /* FUNCTION_fAddSaturate */
-//#define TEST_ROUNDING
+INT fixp_floorToInt(FIXP_DBL f_inp, INT sf);
+FIXP_DBL fixp_floor(FIXP_DBL f_inp, INT sf);
+INT fixp_ceilToInt(FIXP_DBL f_inp, INT sf);
+FIXP_DBL fixp_ceil(FIXP_DBL f_inp, INT sf);
+INT fixp_truncateToInt(FIXP_DBL f_inp, INT sf);
+FIXP_DBL fixp_truncate(FIXP_DBL f_inp, INT sf);
+INT fixp_roundToInt(FIXP_DBL f_inp, INT sf);
+FIXP_DBL fixp_round(FIXP_DBL f_inp, INT sf);
/*****************************************************************************
@@ -471,25 +903,19 @@ inline FIXP_DBL fAddSaturate(const FIXP_DBL a, const FIXP_DBL b)
****************************************************************************/
- extern const FIXP_DBL invCount[80];
-
- LNK_SECTION_INITCODE
- inline void InitInvInt(void) {}
+extern const FIXP_DBL invCount[80];
+LNK_SECTION_INITCODE
+inline void InitInvInt(void) {}
/**
* \brief Calculate the value of 1/i where i is a integer value. It supports
- * input values from 1 upto 80.
+ * input values from 1 upto (80-1).
* \param intValue Integer input value.
* \param FIXP_DBL representation of 1/intValue
*/
-inline FIXP_DBL GetInvInt(int intValue)
-{
- FDK_ASSERT((intValue > 0) && (intValue < 80));
- FDK_ASSERT(intValue<80);
- return invCount[intValue];
+inline FIXP_DBL GetInvInt(int intValue) {
+ return invCount[fMin(fMax(intValue, 0), 80 - 1)];
}
-
-#endif
-
+#endif /* FIXPOINT_MATH_H */