1 /* Copyright (c) 2002-2008 Jean-Marc Valin
2 Copyright (c) 2007-2008 CSIRO
3 Copyright (c) 2007-2009 Xiph.Org Foundation
4 Written by Jean-Marc Valin */
5 /**
6 @file mathops.h
7 @brief Various math functions
8 */
9 /*
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions
12 are met:
13
14 - Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
16
17 - Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
25 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #ifndef MATHOPS_H
35 #define MATHOPS_H
36
37 #include "arch.h"
38 #include "entcode.h"
39 #include "os_support.h"
40
41 /* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */
42 #define FRAC_MUL16(a,b) ((16384+((celt_int32)(celt_int16)(a)*(celt_int16)(b)))>>15)
43
44 unsigned isqrt32(celt_uint32 _val);
45
46 #ifndef FIXED_POINT
47
48 #define celt_sqrt(x) ((float)sqrt(x))
49 #define celt_rsqrt(x) (1.f/celt_sqrt(x))
50 #define celt_rsqrt_norm(x) (celt_rsqrt(x))
51 #define celt_acos acos
52 #define celt_exp exp
53 #define celt_cos_norm(x) ((float)cos((.5f*M_PI)*(x)))
54 #define celt_atan atan
55 #define celt_rcp(x) (1.f/(x))
56 #define celt_div(a,b) ((a)/(b))
57 #define frac_div32(a,b) ((float)(a)/(b))
58
59 #ifdef FLOAT_APPROX
60
61 /* Note: This assumes radix-2 floating point with the exponent at bits 23..30 and an offset of 127
62 denorm, +/- inf and NaN are *not* handled */
63
64 /** Base-2 log approximation (log2(x)). */
celt_log2(float x)65 static inline float celt_log2(float x)
66 {
67 int integer;
68 float frac;
69 union {
70 float f;
71 celt_uint32 i;
72 } in;
73 in.f = x;
74 integer = (in.i>>23)-127;
75 in.i -= integer<<23;
76 frac = in.f - 1.5f;
77 frac = -0.41445418f + frac*(0.95909232f
78 + frac*(-0.33951290f + frac*0.16541097f));
79 return 1+integer+frac;
80 }
81
82 /** Base-2 exponential approximation (2^x). */
celt_exp2(float x)83 static inline float celt_exp2(float x)
84 {
85 int integer;
86 float frac;
87 union {
88 float f;
89 celt_uint32 i;
90 } res;
91 integer = floor(x);
92 if (integer < -50)
93 return 0;
94 frac = x-integer;
95 /* K0 = 1, K1 = log(2), K2 = 3-4*log(2), K3 = 3*log(2) - 2 */
96 res.f = 0.99992522f + frac * (0.69583354f
97 + frac * (0.22606716f + 0.078024523f*frac));
98 res.i = (res.i + (integer<<23)) & 0x7fffffff;
99 return res.f;
100 }
101
102 #else
103 #define celt_log2(x) ((float)(1.442695040888963387*log(x)))
104 #define celt_exp2(x) ((float)exp(0.6931471805599453094*(x)))
105 #endif
106
107 #endif
108
109
110
111 #ifdef FIXED_POINT
112
113 #include "os_support.h"
114
115 #ifndef OVERRIDE_CELT_ILOG2
116 /** Integer log in base2. Undefined for zero and negative numbers */
celt_ilog2(celt_int32 x)117 static inline celt_int16 celt_ilog2(celt_int32 x)
118 {
119 celt_assert2(x>0, "celt_ilog2() only defined for strictly positive numbers");
120 return EC_ILOG(x)-1;
121 }
122 #endif
123
124
125 #ifndef OVERRIDE_CELT_MAXABS16
celt_maxabs16(celt_word16 * x,int len)126 static inline celt_word16 celt_maxabs16(celt_word16 *x, int len)
127 {
128 int i;
129 celt_word16 maxval = 0;
130 for (i=0;i<len;i++)
131 maxval = MAX16(maxval, ABS16(x[i]));
132 return maxval;
133 }
134 #endif
135
136 /** Integer log in base2. Defined for zero, but not for negative numbers */
celt_zlog2(celt_word32 x)137 static inline celt_int16 celt_zlog2(celt_word32 x)
138 {
139 return x <= 0 ? 0 : celt_ilog2(x);
140 }
141
142 celt_word16 celt_rsqrt_norm(celt_word32 x);
143
144 celt_word32 celt_sqrt(celt_word32 x);
145
146 celt_word16 celt_cos_norm(celt_word32 x);
147
148
celt_log2(celt_word32 x)149 static inline celt_word16 celt_log2(celt_word32 x)
150 {
151 int i;
152 celt_word16 n, frac;
153 /* -0.41509302963303146, 0.9609890551383969, -0.31836011537636605,
154 0.15530808010959576, -0.08556153059057618 */
155 static const celt_word16 C[5] = {-6801+(1<<13-DB_SHIFT), 15746, -5217, 2545, -1401};
156 if (x==0)
157 return -32767;
158 i = celt_ilog2(x);
159 n = VSHR32(x,i-15)-32768-16384;
160 frac = ADD16(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2], MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, C[4]))))))));
161 return SHL16(i-13,DB_SHIFT)+SHR16(frac,14-DB_SHIFT);
162 }
163
164 /*
165 K0 = 1
166 K1 = log(2)
167 K2 = 3-4*log(2)
168 K3 = 3*log(2) - 2
169 */
170 #define D0 16383
171 #define D1 22804
172 #define D2 14819
173 #define D3 10204
174 /** Base-2 exponential approximation (2^x). (Q10 input, Q16 output) */
celt_exp2(celt_word16 x)175 static inline celt_word32 celt_exp2(celt_word16 x)
176 {
177 int integer;
178 celt_word16 frac;
179 integer = SHR16(x,10);
180 if (integer>14)
181 return 0x7f000000;
182 else if (integer < -15)
183 return 0;
184 frac = SHL16(x-SHL16(integer,10),4);
185 frac = ADD16(D0, MULT16_16_Q15(frac, ADD16(D1, MULT16_16_Q15(frac, ADD16(D2 , MULT16_16_Q15(D3,frac))))));
186 return VSHR32(EXTEND32(frac), -integer-2);
187 }
188
189 celt_word32 celt_rcp(celt_word32 x);
190
191 #define celt_div(a,b) MULT32_32_Q31((celt_word32)(a),celt_rcp(b))
192
193 celt_word32 frac_div32(celt_word32 a, celt_word32 b);
194
195 #define M1 32767
196 #define M2 -21
197 #define M3 -11943
198 #define M4 4936
199
200 /* Atan approximation using a 4th order polynomial. Input is in Q15 format
201 and normalized by pi/4. Output is in Q15 format */
celt_atan01(celt_word16 x)202 static inline celt_word16 celt_atan01(celt_word16 x)
203 {
204 return MULT16_16_P15(x, ADD32(M1, MULT16_16_P15(x, ADD32(M2, MULT16_16_P15(x, ADD32(M3, MULT16_16_P15(M4, x)))))));
205 }
206
207 #undef M1
208 #undef M2
209 #undef M3
210 #undef M4
211
212 /* atan2() approximation valid for positive input values */
celt_atan2p(celt_word16 y,celt_word16 x)213 static inline celt_word16 celt_atan2p(celt_word16 y, celt_word16 x)
214 {
215 if (y < x)
216 {
217 celt_word32 arg;
218 arg = celt_div(SHL32(EXTEND32(y),15),x);
219 if (arg >= 32767)
220 arg = 32767;
221 return SHR16(celt_atan01(EXTRACT16(arg)),1);
222 } else {
223 celt_word32 arg;
224 arg = celt_div(SHL32(EXTEND32(x),15),y);
225 if (arg >= 32767)
226 arg = 32767;
227 return 25736-SHR16(celt_atan01(EXTRACT16(arg)),1);
228 }
229 }
230
231 #endif /* FIXED_POINT */
232
233
234 #endif /* MATHOPS_H */
235