Unit tests for bitexact_cos() and bitexact_log2tan().
[opus.git] / libcelt / tests / mathops-test.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "mathops.c"
6 #include "entenc.c"
7 #include "entdec.c"
8 #include "entcode.c"
9 #include "bands.c"
10 #include "vq.c"
11 #include "cwrs.c"
12 #include <stdio.h>
13 #include <math.h>
14
15 #ifdef FIXED_POINT
16 #define WORD "%d"
17 #else
18 #define WORD "%f"
19 #endif
20
21 #ifdef FIXED_DEBUG
22 long long celt_mips=0;
23 #endif
24 int ret = 0;
25
26 void testdiv(void)
27 {
28    opus_int32 i;
29    for (i=1;i<=327670;i++)
30    {
31       double prod;
32       opus_val32 val;
33       val = celt_rcp(i);
34 #ifdef FIXED_POINT
35       prod = (1./32768./65526.)*val*i;
36 #else
37       prod = val*i;
38 #endif
39       if (fabs(prod-1) > .00025)
40       {
41          fprintf (stderr, "div failed: 1/%d="WORD" (product = %f)\n", i, val, prod);
42          ret = 1;
43       }
44    }
45 }
46
47 void testsqrt(void)
48 {
49    opus_int32 i;
50    for (i=1;i<=1000000000;i++)
51    {
52       double ratio;
53       opus_val16 val;
54       val = celt_sqrt(i);
55       ratio = val/sqrt(i);
56       if (fabs(ratio - 1) > .0005 && fabs(val-sqrt(i)) > 2)
57       {
58          fprintf (stderr, "sqrt failed: sqrt(%d)="WORD" (ratio = %f)\n", i, val, ratio);
59          ret = 1;
60       }
61       i+= i>>10;
62    }
63 }
64
65 void testbitexactcos(void)
66 {
67    int i;
68    opus_int32 min_d,max_d,last,chk;
69    chk=max_d=0;
70    last=min_d=32767;
71    for(i=0;i<16385;i++)
72    {
73       opus_int32 d;
74       opus_int32 q=bitexact_cos(i);
75       chk ^= q*i;
76       d = last - q;
77       if (d>max_d)max_d=d;
78       if (d<min_d)min_d=d;
79       last = q;
80    }
81    if ((chk!=91017006)||(max_d!=5)||(min_d!=0)||(bitexact_cos(0)!=32767)||
82        (bitexact_cos(16384)!=1)||(bitexact_cos(8192)!=23171))
83    {
84       fprintf (stderr, "bitexact_cos failed\n");
85       ret = 1;
86    }
87 }
88
89 void testbitexactlog2tan(void)
90 {
91    int i,fail;
92    opus_int32 min_d,max_d,last,chk;
93    fail=chk=max_d=0;
94    last=min_d=30690;
95    for(i=0;i<8193;i++)
96    {
97       opus_int32 d;
98       opus_int32 mid=bitexact_cos(i);
99       opus_int32 side=bitexact_cos(16384-i);
100       opus_int32 q=bitexact_log2tan(mid,side);
101       chk ^= q*i;
102       d = last - q;
103       if (q!=-1*bitexact_log2tan(side,mid))
104         fail = 1;
105       if (d>max_d)max_d=d;
106       if (d<min_d)min_d=d;
107       last = q;
108    }
109    if ((chk!=16578548)||(max_d!=3219)||(min_d!=-2)||fail||
110        (bitexact_log2tan(32767,1)!=30690)||(bitexact_log2tan(30274,12540)!=2611)||
111        (bitexact_log2tan(23171,23171)!=0))
112    {
113       fprintf (stderr, "bitexact_log2tan failed\n");
114       ret = 1;
115    }
116 }
117
118 #ifndef FIXED_POINT
119 void testlog2(void)
120 {
121    float x;
122    for (x=0.001;x<1677700.0;x+=(x/8.0))
123    {
124       float error = fabs((1.442695040888963387*log(x))-celt_log2(x));
125       if (error>0.0009)
126       {
127          fprintf (stderr, "celt_log2 failed: fabs((1.442695040888963387*log(x))-celt_log2(x))>0.001 (x = %f, error = %f)\n", x,error);
128          ret = 1;
129       }
130    }
131 }
132
133 void testexp2(void)
134 {
135    float x;
136    for (x=-11.0;x<24.0;x+=0.0007)
137    {
138       float error = fabs(x-(1.442695040888963387*log(celt_exp2(x))));
139       if (error>0.0002)
140       {
141          fprintf (stderr, "celt_exp2 failed: fabs(x-(1.442695040888963387*log(celt_exp2(x))))>0.0005 (x = %f, error = %f)\n", x,error);
142          ret = 1;
143       }
144    }
145 }
146
147 void testexp2log2(void)
148 {
149    float x;
150    for (x=-11.0;x<24.0;x+=0.0007)
151    {
152       float error = fabs(x-(celt_log2(celt_exp2(x))));
153       if (error>0.001)
154       {
155          fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_log2(celt_exp2(x))))>0.001 (x = %f, error = %f)\n", x,error);
156          ret = 1;
157       }
158    }
159 }
160 #else
161 void testlog2(void)
162 {
163    opus_val32 x;
164    for (x=8;x<1073741824;x+=(x>>3))
165    {
166       float error = fabs((1.442695040888963387*log(x/16384.0))-celt_log2(x)/1024.0);
167       if (error>0.003)
168       {
169          fprintf (stderr, "celt_log2 failed: x = %ld, error = %f\n", (long)x,error);
170          ret = 1;
171       }
172    }
173 }
174
175 void testexp2(void)
176 {
177    opus_val16 x;
178    for (x=-32768;x<15360;x++)
179    {
180       float error1 = fabs(x/1024.0-(1.442695040888963387*log(celt_exp2(x)/65536.0)));
181       float error2 = fabs(exp(0.6931471805599453094*x/1024.0)-celt_exp2(x)/65536.0);
182       if (error1>0.0002&&error2>0.00004)
183       {
184          fprintf (stderr, "celt_exp2 failed: x = "WORD", error1 = %f, error2 = %f\n", x,error1,error2);
185          ret = 1;
186       }
187    }
188 }
189
190 void testexp2log2(void)
191 {
192    opus_val32 x;
193    for (x=8;x<65536;x+=(x>>3))
194    {
195       float error = fabs(x-0.25*celt_exp2(celt_log2(x)))/16384;
196       if (error>0.004)
197       {
198          fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_exp2(celt_log2(x))))>0.001 (x = %ld, error = %f)\n", (long)x,error);
199          ret = 1;
200       }
201    }
202 }
203
204 void testilog2(void)
205 {
206    opus_val32 x;
207    for (x=1;x<=268435455;x+=127)
208    {
209       opus_val32 error = abs(celt_ilog2(x)-(int)floor(log2(x)));
210       if (error!=0)
211       {
212          printf("celt_ilog2 failed: celt_ilog2(x)!=floor(log2(x)) (x = %d, error = %d)\n",x,error);
213          ret = 1;
214       }
215    }
216 }
217 #endif
218
219 int main(void)
220 {
221    testbitexactcos();
222    testbitexactlog2tan();
223    testdiv();
224    testsqrt();
225    testlog2();
226    testexp2();
227    testexp2log2();
228 #ifdef FIXED_POINT
229    testilog2();
230 #endif
231    return ret;
232 }