Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (c) 2002-2008 Jean-Marc Valin |
2 | | Copyright (c) 2007-2008 CSIRO |
3 | | Copyright (c) 2007-2009 Xiph.Org Foundation |
4 | | Copyright (c) 2024 Arm Limited |
5 | | Written by Jean-Marc Valin, and Yunho Huh */ |
6 | | /** |
7 | | @file mathops.h |
8 | | @brief Various math functions |
9 | | */ |
10 | | /* |
11 | | Redistribution and use in source and binary forms, with or without |
12 | | modification, are permitted provided that the following conditions |
13 | | are met: |
14 | | |
15 | | - Redistributions of source code must retain the above copyright |
16 | | notice, this list of conditions and the following disclaimer. |
17 | | |
18 | | - Redistributions in binary form must reproduce the above copyright |
19 | | notice, this list of conditions and the following disclaimer in the |
20 | | documentation and/or other materials provided with the distribution. |
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 COPYRIGHT OWNER |
26 | | OR 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 MATHOPS_H |
36 | | #define MATHOPS_H |
37 | | |
38 | | #include "arch.h" |
39 | | #include "entcode.h" |
40 | | #include "os_support.h" |
41 | | |
42 | | #if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) |
43 | | #include "arm/mathops_arm.h" |
44 | | #endif |
45 | | |
46 | 151k | #define PI 3.141592653f |
47 | | |
48 | | /* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */ |
49 | 2.42M | #define FRAC_MUL16(a,b) ((16384+((opus_int32)(opus_int16)(a)*(opus_int16)(b)))>>15) |
50 | | |
51 | | unsigned isqrt32(opus_uint32 _val); |
52 | | |
53 | | /* CELT doesn't need it for fixed-point, by analysis.c does. */ |
54 | | #if !defined(FIXED_POINT) || defined(ANALYSIS_C) |
55 | 0 | #define cA 0.43157974f |
56 | 0 | #define cB 0.67848403f |
57 | 0 | #define cC 0.08595542f |
58 | 0 | #define cE ((float)PI/2) |
59 | 0 | static OPUS_INLINE float fast_atan2f(float y, float x) { |
60 | 0 | float x2, y2; |
61 | 0 | x2 = x*x; |
62 | 0 | y2 = y*y; |
63 | | /* For very small values, we don't care about the answer, so |
64 | | we can just return 0. */ |
65 | 0 | if (x2 + y2 < 1e-18f) |
66 | 0 | { |
67 | 0 | return 0; |
68 | 0 | } |
69 | 0 | if(x2<y2){ |
70 | 0 | float den = (y2 + cB*x2) * (y2 + cC*x2); |
71 | 0 | return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE); |
72 | 0 | }else{ |
73 | 0 | float den = (x2 + cB*y2) * (x2 + cC*y2); |
74 | 0 | return x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE); |
75 | 0 | } |
76 | 0 | } Unexecuted instantiation: celt.c:fast_atan2f Unexecuted instantiation: pitch_sse.c:fast_atan2f Unexecuted instantiation: opus.c:fast_atan2f Unexecuted instantiation: opus_decoder.c:fast_atan2f Unexecuted instantiation: celt_decoder.c:fast_atan2f Unexecuted instantiation: mathops.c:fast_atan2f Unexecuted instantiation: mdct.c:fast_atan2f Unexecuted instantiation: modes.c:fast_atan2f Unexecuted instantiation: pitch.c:fast_atan2f Unexecuted instantiation: celt_lpc.c:fast_atan2f Unexecuted instantiation: quant_bands.c:fast_atan2f Unexecuted instantiation: vq.c:fast_atan2f Unexecuted instantiation: vq_sse2.c:fast_atan2f Unexecuted instantiation: bands.c:fast_atan2f Unexecuted instantiation: cwrs.c:fast_atan2f Unexecuted instantiation: kiss_fft.c:fast_atan2f Unexecuted instantiation: laplace.c:fast_atan2f Unexecuted instantiation: opus_multistream_encoder.c:fast_atan2f Unexecuted instantiation: celt_encoder.c:fast_atan2f Unexecuted instantiation: opus_encoder.c:fast_atan2f Unexecuted instantiation: analysis.c:fast_atan2f |
77 | | #undef cA |
78 | | #undef cB |
79 | | #undef cC |
80 | | #undef cE |
81 | | #endif |
82 | | |
83 | | |
84 | | #ifndef OVERRIDE_CELT_MAXABS16 |
85 | | static OPUS_INLINE opus_val32 celt_maxabs16(const opus_val16 *x, int len) |
86 | 0 | { |
87 | 0 | int i; |
88 | 0 | opus_val16 maxval = 0; |
89 | 0 | opus_val16 minval = 0; |
90 | 0 | for (i=0;i<len;i++) |
91 | 0 | { |
92 | 0 | maxval = MAX16(maxval, x[i]); |
93 | 0 | minval = MIN16(minval, x[i]); |
94 | 0 | } |
95 | 0 | return MAX32(EXTEND32(maxval),-EXTEND32(minval)); |
96 | 0 | } Unexecuted instantiation: celt.c:celt_maxabs16 Unexecuted instantiation: pitch_sse.c:celt_maxabs16 Unexecuted instantiation: opus.c:celt_maxabs16 Unexecuted instantiation: opus_decoder.c:celt_maxabs16 Unexecuted instantiation: celt_decoder.c:celt_maxabs16 Unexecuted instantiation: mathops.c:celt_maxabs16 Unexecuted instantiation: mdct.c:celt_maxabs16 Unexecuted instantiation: modes.c:celt_maxabs16 Unexecuted instantiation: pitch.c:celt_maxabs16 Unexecuted instantiation: celt_lpc.c:celt_maxabs16 Unexecuted instantiation: quant_bands.c:celt_maxabs16 Unexecuted instantiation: vq.c:celt_maxabs16 Unexecuted instantiation: vq_sse2.c:celt_maxabs16 Unexecuted instantiation: bands.c:celt_maxabs16 Unexecuted instantiation: cwrs.c:celt_maxabs16 Unexecuted instantiation: kiss_fft.c:celt_maxabs16 Unexecuted instantiation: laplace.c:celt_maxabs16 Unexecuted instantiation: opus_multistream_encoder.c:celt_maxabs16 Unexecuted instantiation: celt_encoder.c:celt_maxabs16 Unexecuted instantiation: opus_encoder.c:celt_maxabs16 Unexecuted instantiation: analysis.c:celt_maxabs16 |
97 | | #endif |
98 | | |
99 | | #ifdef ENABLE_RES24 |
100 | | static OPUS_INLINE opus_res celt_maxabs_res(const opus_res *x, int len) |
101 | | { |
102 | | int i; |
103 | | opus_res maxval = 0; |
104 | | opus_res minval = 0; |
105 | | for (i=0;i<len;i++) |
106 | | { |
107 | | maxval = MAX32(maxval, x[i]); |
108 | | minval = MIN32(minval, x[i]); |
109 | | } |
110 | | /* opus_res should never reach such amplitude, so we should be safe. */ |
111 | | celt_sig_assert(minval != -2147483648); |
112 | | return MAX32(maxval,-minval); |
113 | | } |
114 | | #else |
115 | 0 | #define celt_maxabs_res celt_maxabs16 |
116 | | #endif |
117 | | |
118 | | |
119 | | #ifndef OVERRIDE_CELT_MAXABS32 |
120 | | #ifdef FIXED_POINT |
121 | | static OPUS_INLINE opus_val32 celt_maxabs32(const opus_val32 *x, int len) |
122 | | { |
123 | | int i; |
124 | | opus_val32 maxval = 0; |
125 | | opus_val32 minval = 0; |
126 | | for (i=0;i<len;i++) |
127 | | { |
128 | | maxval = MAX32(maxval, x[i]); |
129 | | minval = MIN32(minval, x[i]); |
130 | | } |
131 | | return MAX32(maxval, -minval); |
132 | | } |
133 | | #else |
134 | | #define celt_maxabs32(x,len) celt_maxabs16(x,len) |
135 | | #endif |
136 | | #endif |
137 | | |
138 | | |
139 | | #ifndef FIXED_POINT |
140 | | |
141 | 1.68M | #define celt_sqrt(x) ((float)sqrt(x)) |
142 | 390k | #define celt_rsqrt(x) (1.f/celt_sqrt(x)) |
143 | 357k | #define celt_rsqrt_norm(x) (celt_rsqrt(x)) |
144 | 151k | #define celt_cos_norm(x) ((float)cos((.5f*PI)*(x))) |
145 | 0 | #define celt_rcp(x) (1.f/(x)) |
146 | 75.8k | #define celt_div(a,b) ((a)/(b)) |
147 | 336k | #define frac_div32(a,b) ((float)(a)/(b)) |
148 | 0 | #define frac_div32_q29(a,b) frac_div32(a,b) |
149 | | |
150 | | #ifdef FLOAT_APPROX |
151 | | /* Calculates the base-2 logarithm (log2(x)) of a number. It is designed for |
152 | | * systems using radix-2 floating-point representation, with the exponent |
153 | | * located at bits 23 to 30 and an offset of 127. Note that special cases like |
154 | | * denormalized numbers, positive/negative infinity, and NaN are not handled. |
155 | | * log2(x) = log2(x^exponent * mantissa) |
156 | | * = exponent + log2(mantissa) */ |
157 | | |
158 | | /* Log2 x normalization single precision coefficients calculated by |
159 | | * 1 / (1 + 0.125 * index). |
160 | | * Coefficients in Double Precision |
161 | | * double log2_x_norm_coeff[8] = { |
162 | | * 1.0000000000000000000, 8.888888888888888e-01, |
163 | | * 8.000000000000000e-01, 7.272727272727273e-01, |
164 | | * 6.666666666666666e-01, 6.153846153846154e-01, |
165 | | * 5.714285714285714e-01, 5.333333333333333e-01} */ |
166 | | static const float log2_x_norm_coeff[8] = { |
167 | | 1.000000000000000000000000000f, 8.88888895511627197265625e-01f, |
168 | | 8.00000000000000000000000e-01f, 7.27272748947143554687500e-01f, |
169 | | 6.66666686534881591796875e-01f, 6.15384638309478759765625e-01f, |
170 | | 5.71428596973419189453125e-01f, 5.33333361148834228515625e-01f}; |
171 | | |
172 | | /* Log2 y normalization single precision coefficients calculated by |
173 | | * log2(1 + 0.125 * index). |
174 | | * Coefficients in Double Precision |
175 | | * double log2_y_norm_coeff[8] = { |
176 | | * 0.0000000000000000000, 1.699250014423124e-01, |
177 | | * 3.219280948873623e-01, 4.594316186372973e-01, |
178 | | * 5.849625007211562e-01, 7.004397181410922e-01, |
179 | | * 8.073549220576041e-01, 9.068905956085185e-01}; */ |
180 | | static const float log2_y_norm_coeff[8] = { |
181 | | 0.0000000000000000000000000000f, 1.699250042438507080078125e-01f, |
182 | | 3.219280838966369628906250e-01f, 4.594316184520721435546875e-01f, |
183 | | 5.849624872207641601562500e-01f, 7.004396915435791015625000e-01f, |
184 | | 8.073549270629882812500000e-01f, 9.068905711174011230468750e-01f}; |
185 | | |
186 | | static OPUS_INLINE float celt_log2(float x) |
187 | 0 | { |
188 | 0 | opus_int32 integer; |
189 | 0 | opus_int32 range_idx; |
190 | 0 | union { |
191 | 0 | float f; |
192 | 0 | opus_uint32 i; |
193 | 0 | } in; |
194 | 0 | in.f = x; |
195 | 0 | integer = (opus_int32)(in.i>>23)-127; |
196 | 0 | in.i = (opus_int32)in.i - (opus_int32)((opus_uint32)integer<<23); |
197 | | |
198 | | /* Normalize the mantissa range from [1, 2] to [1,1.125], and then shift x |
199 | | * by 1.0625 to [-0.0625, 0.0625]. */ |
200 | 0 | range_idx = (in.i >> 20) & 0x7; |
201 | 0 | in.f = in.f * log2_x_norm_coeff[range_idx] - 1.0625f; |
202 | | |
203 | | /* Polynomial coefficients approximated in the [1, 1.125] range. |
204 | | * Lolremez command: lolremez --degree 4 --range -0.0625:0.0625 |
205 | | * "log(x+1.0625)/log(2)" |
206 | | * Coefficients in Double Precision |
207 | | * A0: 8.7462840624502679e-2 A1: 1.3578296070972002 |
208 | | * A2: -6.3897703690210047e-1 A3: 4.0197125617419959e-1 |
209 | | * A4: -2.8415445877832832e-1 */ |
210 | 0 | #define LOG2_COEFF_A0 8.74628424644470214843750000e-02f |
211 | 0 | #define LOG2_COEFF_A1 1.357829570770263671875000000000f |
212 | 0 | #define LOG2_COEFF_A2 -6.3897705078125000000000000e-01f |
213 | 0 | #define LOG2_COEFF_A3 4.01971250772476196289062500e-01f |
214 | 0 | #define LOG2_COEFF_A4 -2.8415444493293762207031250e-01f |
215 | 0 | in.f = LOG2_COEFF_A0 + in.f * (LOG2_COEFF_A1 |
216 | 0 | + in.f * (LOG2_COEFF_A2 |
217 | 0 | + in.f * (LOG2_COEFF_A3 |
218 | 0 | + in.f * (LOG2_COEFF_A4)))); |
219 | 0 | return integer + in.f + log2_y_norm_coeff[range_idx]; |
220 | 0 | } Unexecuted instantiation: celt.c:celt_log2 Unexecuted instantiation: pitch_sse.c:celt_log2 Unexecuted instantiation: opus.c:celt_log2 Unexecuted instantiation: opus_decoder.c:celt_log2 Unexecuted instantiation: celt_decoder.c:celt_log2 Unexecuted instantiation: mathops.c:celt_log2 Unexecuted instantiation: mdct.c:celt_log2 Unexecuted instantiation: modes.c:celt_log2 Unexecuted instantiation: pitch.c:celt_log2 Unexecuted instantiation: celt_lpc.c:celt_log2 Unexecuted instantiation: quant_bands.c:celt_log2 Unexecuted instantiation: vq.c:celt_log2 Unexecuted instantiation: vq_sse2.c:celt_log2 Unexecuted instantiation: bands.c:celt_log2 Unexecuted instantiation: cwrs.c:celt_log2 Unexecuted instantiation: kiss_fft.c:celt_log2 Unexecuted instantiation: laplace.c:celt_log2 Unexecuted instantiation: opus_multistream_encoder.c:celt_log2 Unexecuted instantiation: celt_encoder.c:celt_log2 Unexecuted instantiation: opus_encoder.c:celt_log2 Unexecuted instantiation: analysis.c:celt_log2 |
221 | | |
222 | | /* Calculates an approximation of 2^x. The approximation was achieved by |
223 | | * employing a base-2 exponential function and utilizing a Remez approximation |
224 | | * of order 5, ensuring a controlled relative error. |
225 | | * exp2(x) = exp2(integer + fraction) |
226 | | * = exp2(integer) * exp2(fraction) */ |
227 | | static OPUS_INLINE float celt_exp2(float x) |
228 | 4.16M | { |
229 | 4.16M | opus_int32 integer; |
230 | 4.16M | float frac; |
231 | 4.16M | union { |
232 | 4.16M | float f; |
233 | 4.16M | opus_uint32 i; |
234 | 4.16M | } res; |
235 | 4.16M | integer = (int)floor(x); |
236 | 4.16M | if (integer < -50) |
237 | 893 | return 0; |
238 | 4.16M | frac = x-integer; |
239 | | |
240 | | /* Polynomial coefficients approximated in the [0, 1] range. |
241 | | * Lolremez command: lolremez --degree 5 --range 0:1 |
242 | | * "exp(x*0.693147180559945)" "exp(x*0.693147180559945)" |
243 | | * NOTE: log(2) ~ 0.693147180559945 */ |
244 | 4.16M | #define EXP2_COEFF_A0 9.999999403953552246093750000000e-01f |
245 | 4.16M | #define EXP2_COEFF_A1 6.931530833244323730468750000000e-01f |
246 | 4.16M | #define EXP2_COEFF_A2 2.401536107063293457031250000000e-01f |
247 | 4.16M | #define EXP2_COEFF_A3 5.582631751894950866699218750000e-02f |
248 | 4.16M | #define EXP2_COEFF_A4 8.989339694380760192871093750000e-03f |
249 | 4.16M | #define EXP2_COEFF_A5 1.877576694823801517486572265625e-03f |
250 | 4.16M | res.f = EXP2_COEFF_A0 + frac * (EXP2_COEFF_A1 |
251 | 4.16M | + frac * (EXP2_COEFF_A2 |
252 | 4.16M | + frac * (EXP2_COEFF_A3 |
253 | 4.16M | + frac * (EXP2_COEFF_A4 |
254 | 4.16M | + frac * (EXP2_COEFF_A5))))); |
255 | 4.16M | res.i = (opus_uint32)((opus_int32)res.i + (opus_int32)((opus_uint32)integer<<23)) & 0x7fffffff; |
256 | 4.16M | return res.f; |
257 | 4.16M | } Unexecuted instantiation: celt.c:celt_exp2 Unexecuted instantiation: pitch_sse.c:celt_exp2 Unexecuted instantiation: opus.c:celt_exp2 Line | Count | Source | 228 | 11.9k | { | 229 | 11.9k | opus_int32 integer; | 230 | 11.9k | float frac; | 231 | 11.9k | union { | 232 | 11.9k | float f; | 233 | 11.9k | opus_uint32 i; | 234 | 11.9k | } res; | 235 | 11.9k | integer = (int)floor(x); | 236 | 11.9k | if (integer < -50) | 237 | 0 | return 0; | 238 | 11.9k | frac = x-integer; | 239 | | | 240 | | /* Polynomial coefficients approximated in the [0, 1] range. | 241 | | * Lolremez command: lolremez --degree 5 --range 0:1 | 242 | | * "exp(x*0.693147180559945)" "exp(x*0.693147180559945)" | 243 | | * NOTE: log(2) ~ 0.693147180559945 */ | 244 | 11.9k | #define EXP2_COEFF_A0 9.999999403953552246093750000000e-01f | 245 | 11.9k | #define EXP2_COEFF_A1 6.931530833244323730468750000000e-01f | 246 | 11.9k | #define EXP2_COEFF_A2 2.401536107063293457031250000000e-01f | 247 | 11.9k | #define EXP2_COEFF_A3 5.582631751894950866699218750000e-02f | 248 | 11.9k | #define EXP2_COEFF_A4 8.989339694380760192871093750000e-03f | 249 | 11.9k | #define EXP2_COEFF_A5 1.877576694823801517486572265625e-03f | 250 | 11.9k | res.f = EXP2_COEFF_A0 + frac * (EXP2_COEFF_A1 | 251 | 11.9k | + frac * (EXP2_COEFF_A2 | 252 | 11.9k | + frac * (EXP2_COEFF_A3 | 253 | 11.9k | + frac * (EXP2_COEFF_A4 | 254 | 11.9k | + frac * (EXP2_COEFF_A5))))); | 255 | 11.9k | res.i = (opus_uint32)((opus_int32)res.i + (opus_int32)((opus_uint32)integer<<23)) & 0x7fffffff; | 256 | 11.9k | return res.f; | 257 | 11.9k | } |
Unexecuted instantiation: celt_decoder.c:celt_exp2 Unexecuted instantiation: mathops.c:celt_exp2 Unexecuted instantiation: mdct.c:celt_exp2 Unexecuted instantiation: modes.c:celt_exp2 Unexecuted instantiation: pitch.c:celt_exp2 Unexecuted instantiation: celt_lpc.c:celt_exp2 Unexecuted instantiation: quant_bands.c:celt_exp2 Unexecuted instantiation: vq.c:celt_exp2 Unexecuted instantiation: vq_sse2.c:celt_exp2 Line | Count | Source | 228 | 4.15M | { | 229 | 4.15M | opus_int32 integer; | 230 | 4.15M | float frac; | 231 | 4.15M | union { | 232 | 4.15M | float f; | 233 | 4.15M | opus_uint32 i; | 234 | 4.15M | } res; | 235 | 4.15M | integer = (int)floor(x); | 236 | 4.15M | if (integer < -50) | 237 | 893 | return 0; | 238 | 4.14M | frac = x-integer; | 239 | | | 240 | | /* Polynomial coefficients approximated in the [0, 1] range. | 241 | | * Lolremez command: lolremez --degree 5 --range 0:1 | 242 | | * "exp(x*0.693147180559945)" "exp(x*0.693147180559945)" | 243 | | * NOTE: log(2) ~ 0.693147180559945 */ | 244 | 4.14M | #define EXP2_COEFF_A0 9.999999403953552246093750000000e-01f | 245 | 4.14M | #define EXP2_COEFF_A1 6.931530833244323730468750000000e-01f | 246 | 4.14M | #define EXP2_COEFF_A2 2.401536107063293457031250000000e-01f | 247 | 4.14M | #define EXP2_COEFF_A3 5.582631751894950866699218750000e-02f | 248 | 4.14M | #define EXP2_COEFF_A4 8.989339694380760192871093750000e-03f | 249 | 4.14M | #define EXP2_COEFF_A5 1.877576694823801517486572265625e-03f | 250 | 4.14M | res.f = EXP2_COEFF_A0 + frac * (EXP2_COEFF_A1 | 251 | 4.14M | + frac * (EXP2_COEFF_A2 | 252 | 4.14M | + frac * (EXP2_COEFF_A3 | 253 | 4.14M | + frac * (EXP2_COEFF_A4 | 254 | 4.14M | + frac * (EXP2_COEFF_A5))))); | 255 | 4.14M | res.i = (opus_uint32)((opus_int32)res.i + (opus_int32)((opus_uint32)integer<<23)) & 0x7fffffff; | 256 | 4.14M | return res.f; | 257 | 4.15M | } |
Unexecuted instantiation: cwrs.c:celt_exp2 Unexecuted instantiation: kiss_fft.c:celt_exp2 Unexecuted instantiation: laplace.c:celt_exp2 Unexecuted instantiation: opus_multistream_encoder.c:celt_exp2 Unexecuted instantiation: celt_encoder.c:celt_exp2 Unexecuted instantiation: opus_encoder.c:celt_exp2 Unexecuted instantiation: analysis.c:celt_exp2 |
258 | | |
259 | | #else |
260 | | #define celt_log2(x) ((float)(1.442695040888963387*log(x))) |
261 | | #define celt_exp2(x) ((float)exp(0.6931471805599453094*(x))) |
262 | | #endif |
263 | | |
264 | 4.11M | #define celt_exp2_db celt_exp2 |
265 | 0 | #define celt_log2_db celt_log2 |
266 | | |
267 | | #endif |
268 | | |
269 | | #ifdef FIXED_POINT |
270 | | |
271 | | #include "os_support.h" |
272 | | |
273 | | #ifndef OVERRIDE_CELT_ILOG2 |
274 | | /** Integer log in base2. Undefined for zero and negative numbers */ |
275 | | static OPUS_INLINE opus_int16 celt_ilog2(opus_int32 x) |
276 | | { |
277 | | celt_sig_assert(x>0); |
278 | | return EC_ILOG(x)-1; |
279 | | } |
280 | | #endif |
281 | | |
282 | | |
283 | | /** Integer log in base2. Defined for zero, but not for negative numbers */ |
284 | | static OPUS_INLINE opus_int16 celt_zlog2(opus_val32 x) |
285 | | { |
286 | | return x <= 0 ? 0 : celt_ilog2(x); |
287 | | } |
288 | | |
289 | | opus_val16 celt_rsqrt_norm(opus_val32 x); |
290 | | |
291 | | opus_val32 celt_sqrt(opus_val32 x); |
292 | | |
293 | | opus_val16 celt_cos_norm(opus_val32 x); |
294 | | |
295 | | /** Base-2 logarithm approximation (log2(x)). (Q14 input, Q10 output) */ |
296 | | static OPUS_INLINE opus_val16 celt_log2(opus_val32 x) |
297 | | { |
298 | | int i; |
299 | | opus_val16 n, frac; |
300 | | /* -0.41509302963303146, 0.9609890551383969, -0.31836011537636605, |
301 | | 0.15530808010959576, -0.08556153059057618 */ |
302 | | static const opus_val16 C[5] = {-6801+(1<<(13-10)), 15746, -5217, 2545, -1401}; |
303 | | if (x==0) |
304 | | return -32767; |
305 | | i = celt_ilog2(x); |
306 | | n = VSHR32(x,i-15)-32768-16384; |
307 | | 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])))))))); |
308 | | return SHL32(i-13,10)+SHR32(frac,14-10); |
309 | | } |
310 | | |
311 | | /* |
312 | | K0 = 1 |
313 | | K1 = log(2) |
314 | | K2 = 3-4*log(2) |
315 | | K3 = 3*log(2) - 2 |
316 | | */ |
317 | | #define D0 16383 |
318 | | #define D1 22804 |
319 | | #define D2 14819 |
320 | | #define D3 10204 |
321 | | |
322 | | static OPUS_INLINE opus_val32 celt_exp2_frac(opus_val16 x) |
323 | | { |
324 | | opus_val16 frac; |
325 | | frac = SHL16(x, 4); |
326 | | return ADD16(D0, MULT16_16_Q15(frac, ADD16(D1, MULT16_16_Q15(frac, ADD16(D2 , MULT16_16_Q15(D3,frac)))))); |
327 | | } |
328 | | |
329 | | #undef D0 |
330 | | #undef D1 |
331 | | #undef D2 |
332 | | #undef D3 |
333 | | |
334 | | /** Base-2 exponential approximation (2^x). (Q10 input, Q16 output) */ |
335 | | static OPUS_INLINE opus_val32 celt_exp2(opus_val16 x) |
336 | | { |
337 | | int integer; |
338 | | opus_val16 frac; |
339 | | integer = SHR16(x,10); |
340 | | if (integer>14) |
341 | | return 0x7f000000; |
342 | | else if (integer < -15) |
343 | | return 0; |
344 | | frac = celt_exp2_frac(x-SHL16(integer,10)); |
345 | | return VSHR32(EXTEND32(frac), -integer-2); |
346 | | } |
347 | | |
348 | | #ifdef ENABLE_QEXT |
349 | | |
350 | | /* Calculates the base-2 logarithm of a Q14 input value. The result is returned |
351 | | * in Q(DB_SHIFT). If the input value is 0, the function will output -32.0f. */ |
352 | | static OPUS_INLINE opus_val32 celt_log2_db(opus_val32 x) { |
353 | | /* Q30 */ |
354 | | static const opus_val32 log2_x_norm_coeff[8] = { |
355 | | 1073741824, 954437184, 858993472, 780903168, |
356 | | 715827904, 660764224, 613566784, 572662336}; |
357 | | /* Q24 */ |
358 | | static const opus_val32 log2_y_norm_coeff[8] = { |
359 | | 0, 2850868, 5401057, 7707983, |
360 | | 9814042, 11751428, 13545168, 15215099}; |
361 | | static const opus_val32 LOG2_COEFF_A0 = 1467383; /* Q24 */ |
362 | | static const opus_val32 LOG2_COEFF_A1 = 182244800; /* Q27 */ |
363 | | static const opus_val32 LOG2_COEFF_A2 = -21440512; /* Q25 */ |
364 | | static const opus_val32 LOG2_COEFF_A3 = 107903336; /* Q28 */ |
365 | | static const opus_val32 LOG2_COEFF_A4 = -610217024; /* Q31 */ |
366 | | |
367 | | opus_int32 integer, norm_coeff_idx, tmp; |
368 | | opus_val32 mantissa; |
369 | | if (x==0) { |
370 | | return -536870912; /* -32.0f */ |
371 | | } |
372 | | integer = SUB32(celt_ilog2(x), 14); /* Q0 */ |
373 | | mantissa = VSHR32(x, integer + 14 - 29); /* Q29 */ |
374 | | norm_coeff_idx = SHR32(mantissa, 29 - 3) & 0x7; |
375 | | /* mantissa is in Q28 (29 + Q_NORM_CONST - 31 where Q_NORM_CONST is Q30) |
376 | | * 285212672 (Q28) is 1.0625f. */ |
377 | | mantissa = SUB32(MULT32_32_Q31(mantissa, log2_x_norm_coeff[norm_coeff_idx]), |
378 | | 285212672); |
379 | | |
380 | | /* q_a3(Q28): q_mantissa + q_a4 - 31 |
381 | | * q_a2(Q25): q_mantissa + q_a3 - 31 |
382 | | * q_a1(Q27): q_mantissa + q_a2 - 31 + 5 |
383 | | * q_a0(Q24): q_mantissa + q_a1 - 31 |
384 | | * where q_mantissa is Q28 */ |
385 | | /* Split evaluation in steps to avoid exploding macro expansion. */ |
386 | | tmp = MULT32_32_Q31(mantissa, LOG2_COEFF_A4); |
387 | | tmp = MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A3, tmp)); |
388 | | tmp = SHL32(MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A2, tmp)), 5 /* SHL32 for LOG2_COEFF_A1 */); |
389 | | tmp = MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A1, tmp)); |
390 | | return ADD32(log2_y_norm_coeff[norm_coeff_idx], |
391 | | ADD32(SHL32(integer, DB_SHIFT), |
392 | | ADD32(LOG2_COEFF_A0, tmp))); |
393 | | } |
394 | | |
395 | | /* Calculates exp2 for Q28 within a specific range (0 to 1.0) using fixed-point |
396 | | * arithmetic. The input number must be adjusted for Q DB_SHIFT. */ |
397 | | static OPUS_INLINE opus_val32 celt_exp2_db_frac(opus_val32 x) |
398 | | { |
399 | | /* Approximation constants. */ |
400 | | static const opus_int32 EXP2_COEFF_A0 = 268435440; /* Q28 */ |
401 | | static const opus_int32 EXP2_COEFF_A1 = 744267456; /* Q30 */ |
402 | | static const opus_int32 EXP2_COEFF_A2 = 1031451904; /* Q32 */ |
403 | | static const opus_int32 EXP2_COEFF_A3 = 959088832; /* Q34 */ |
404 | | static const opus_int32 EXP2_COEFF_A4 = 617742720; /* Q36 */ |
405 | | static const opus_int32 EXP2_COEFF_A5 = 516104352; /* Q38 */ |
406 | | opus_int32 tmp; |
407 | | /* Converts input value from Q24 to Q29. */ |
408 | | opus_val32 x_q29 = SHL32(x, 29 - 24); |
409 | | /* Split evaluation in steps to avoid exploding macro expansion. */ |
410 | | tmp = ADD32(EXP2_COEFF_A4, MULT32_32_Q31(x_q29, EXP2_COEFF_A5)); |
411 | | tmp = ADD32(EXP2_COEFF_A3, MULT32_32_Q31(x_q29, tmp)); |
412 | | tmp = ADD32(EXP2_COEFF_A2, MULT32_32_Q31(x_q29, tmp)); |
413 | | tmp = ADD32(EXP2_COEFF_A1, MULT32_32_Q31(x_q29, tmp)); |
414 | | return ADD32(EXP2_COEFF_A0, MULT32_32_Q31(x_q29, tmp)); |
415 | | } |
416 | | |
417 | | /* Calculates exp2 for Q16 using fixed-point arithmetic. The input number must |
418 | | * be adjusted for Q DB_SHIFT. */ |
419 | | static OPUS_INLINE opus_val32 celt_exp2_db(opus_val32 x) |
420 | | { |
421 | | int integer; |
422 | | opus_val32 frac; |
423 | | integer = SHR32(x,DB_SHIFT); |
424 | | if (integer>14) |
425 | | return 0x7f000000; |
426 | | else if (integer <= -17) |
427 | | return 0; |
428 | | frac = celt_exp2_db_frac(x-SHL32(integer, DB_SHIFT)); /* Q28 */ |
429 | | return VSHR32(frac, -integer + 28 - 16); /* Q16 */ |
430 | | } |
431 | | #else |
432 | | |
433 | | #define celt_log2_db(x) SHL32(EXTEND32(celt_log2(x)), DB_SHIFT-10) |
434 | | #define celt_exp2_db_frac(x) SHL32(celt_exp2_frac(PSHR32(x, DB_SHIFT-10)), 14) |
435 | | #define celt_exp2_db(x) celt_exp2(PSHR32(x, DB_SHIFT-10)) |
436 | | |
437 | | #endif |
438 | | |
439 | | |
440 | | opus_val32 celt_rcp(opus_val32 x); |
441 | | |
442 | | #define celt_div(a,b) MULT32_32_Q31((opus_val32)(a),celt_rcp(b)) |
443 | | |
444 | | opus_val32 frac_div32_q29(opus_val32 a, opus_val32 b); |
445 | | opus_val32 frac_div32(opus_val32 a, opus_val32 b); |
446 | | |
447 | | #define M1 32767 |
448 | | #define M2 -21 |
449 | | #define M3 -11943 |
450 | | #define M4 4936 |
451 | | |
452 | | /* Atan approximation using a 4th order polynomial. Input is in Q15 format |
453 | | and normalized by pi/4. Output is in Q15 format */ |
454 | | static OPUS_INLINE opus_val16 celt_atan01(opus_val16 x) |
455 | | { |
456 | | return MULT16_16_P15(x, ADD32(M1, MULT16_16_P15(x, ADD32(M2, MULT16_16_P15(x, ADD32(M3, MULT16_16_P15(M4, x))))))); |
457 | | } |
458 | | |
459 | | #undef M1 |
460 | | #undef M2 |
461 | | #undef M3 |
462 | | #undef M4 |
463 | | |
464 | | /* atan2() approximation valid for positive input values */ |
465 | | static OPUS_INLINE opus_val16 celt_atan2p(opus_val16 y, opus_val16 x) |
466 | | { |
467 | | if (y < x) |
468 | | { |
469 | | opus_val32 arg; |
470 | | arg = celt_div(SHL32(EXTEND32(y),15),x); |
471 | | if (arg >= 32767) |
472 | | arg = 32767; |
473 | | return SHR16(celt_atan01(EXTRACT16(arg)),1); |
474 | | } else { |
475 | | opus_val32 arg; |
476 | | arg = celt_div(SHL32(EXTEND32(x),15),y); |
477 | | if (arg >= 32767) |
478 | | arg = 32767; |
479 | | return 25736-SHR16(celt_atan01(EXTRACT16(arg)),1); |
480 | | } |
481 | | } |
482 | | |
483 | | #endif /* FIXED_POINT */ |
484 | | |
485 | | #ifndef DISABLE_FLOAT_API |
486 | | |
487 | | void celt_float2int16_c(const float * OPUS_RESTRICT in, short * OPUS_RESTRICT out, int cnt); |
488 | | |
489 | | #ifndef OVERRIDE_FLOAT2INT16 |
490 | 0 | #define celt_float2int16(in, out, cnt, arch) ((void)(arch), celt_float2int16_c(in, out, cnt)) |
491 | | #endif |
492 | | |
493 | | int opus_limit2_checkwithin1_c(float *samples, int cnt); |
494 | | |
495 | | #ifndef OVERRIDE_LIMIT2_CHECKWITHIN1 |
496 | 312k | #define opus_limit2_checkwithin1(samples, cnt, arch) ((void)(arch), opus_limit2_checkwithin1_c(samples, cnt)) |
497 | | #endif |
498 | | |
499 | | #endif /* DISABLE_FLOAT_API */ |
500 | | |
501 | | #endif /* MATHOPS_H */ |