1 /* Copyright (C) 2002 Jean-Marc Valin
2 File: math_approx.c
3 Various math approximation functions for Speex
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 - Neither the name of the Xiph.org Foundation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
24 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #ifdef _WIN32
38 #pragma warning(disable:4244)
39 #endif
40
41 #include "math_approx.h"
42 #include "misc.h"
43
44 #ifdef FIXED_POINT
45
46 /* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25723*x^3 (for .25 < x < 1) */
47 #define C0 3634
48 #define C1 21173
49 #define C2 -12627
50 #define C3 4215
51
spx_sqrt(spx_word32_t x)52 spx_word16_t spx_sqrt(spx_word32_t x)
53 {
54 int k=0;
55 spx_word32_t rt;
56
57 if (x==0)
58 return 0;
59 #if 1
60 if (x>16777216)
61 {
62 x>>=10;
63 k+=5;
64 }
65 if (x>1048576)
66 {
67 x>>=6;
68 k+=3;
69 }
70 if (x>262144)
71 {
72 x>>=4;
73 k+=2;
74 }
75 if (x>32768)
76 {
77 x>>=2;
78 k+=1;
79 }
80 if (x>16384)
81 {
82 x>>=2;
83 k+=1;
84 }
85 #else
86 while (x>16384)
87 {
88 x>>=2;
89 k++;
90 }
91 #endif
92 while (x<4096)
93 {
94 x<<=2;
95 k--;
96 }
97 rt = ADD16(C0, MULT16_16_Q14(x, ADD16(C1, MULT16_16_Q14(x, ADD16(C2, MULT16_16_Q14(x, (C3)))))));
98 if (k>0)
99 rt <<= k;
100 else
101 rt >>= -k;
102 rt >>=7;
103 return rt;
104 }
105
106 /* log(x) ~= -2.18151 + 4.20592*x - 2.88938*x^2 + 0.86535*x^3 (for .5 < x < 1) */
107
108
109 #define A1 16469
110 #define A2 2242
111 #define A3 1486
112
spx_acos(spx_word16_t x)113 spx_word16_t spx_acos(spx_word16_t x)
114 {
115 int s=0;
116 spx_word16_t ret;
117 spx_word16_t sq;
118 if (x<0)
119 {
120 s=1;
121 x = NEG16(x);
122 }
123 x = SUB16(16384,x);
124
125 x = x >> 1;
126 sq = MULT16_16_Q13(x, ADD16(A1, MULT16_16_Q13(x, ADD16(A2, MULT16_16_Q13(x, (A3))))));
127 ret = spx_sqrt(SHL32(EXTEND32(sq),13));
128
129 /*ret = spx_sqrt(67108864*(-1.6129e-04 + 2.0104e+00*f + 2.7373e-01*f*f + 1.8136e-01*f*f*f));*/
130 if (s)
131 ret = SUB16(25736,ret);
132 return ret;
133 }
134
135
136 #define K1 8192
137 #define K2 -4096
138 #define K3 340
139 #define K4 -10
140
spx_cos(spx_word16_t x)141 spx_word16_t spx_cos(spx_word16_t x)
142 {
143 spx_word16_t x2;
144
145 if (x<12868)
146 {
147 x2 = MULT16_16_P13(x,x);
148 return ADD32(K1, MULT16_16_P13(x2, ADD32(K2, MULT16_16_P13(x2, ADD32(K3, MULT16_16_P13(K4, x2))))));
149 } else {
150 x = SUB16(25736,x);
151 x2 = MULT16_16_P13(x,x);
152 return SUB32(-K1, MULT16_16_P13(x2, ADD32(K2, MULT16_16_P13(x2, ADD32(K3, MULT16_16_P13(K4, x2))))));
153 }
154 }
155
156 #else
157
158 #ifndef M_PI
159 #define M_PI 3.14159265358979323846 /* pi */
160 #endif
161
162 #define C1 0.9999932946f
163 #define C2 -0.4999124376f
164 #define C3 0.0414877472f
165 #define C4 -0.0012712095f
166
167
168 #define SPX_PI_2 1.5707963268
spx_cos(spx_word16_t x)169 spx_word16_t spx_cos(spx_word16_t x)
170 {
171 if (x<SPX_PI_2)
172 {
173 x *= x;
174 return C1 + x*(C2+x*(C3+C4*x));
175 } else {
176 x = M_PI-x;
177 x *= x;
178 return NEG16(C1 + x*(C2+x*(C3+C4*x)));
179 }
180 }
181
182
183 #endif
184