FFmpeg
float_dsp.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #include <float.h>
20 #include <stdint.h>
21 #include <string.h>
22 
23 #include "libavutil/float_dsp.h"
24 #include "libavutil/internal.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/mem_internal.h"
27 
28 #include "checkasm.h"
29 
30 #define LEN 256
31 
32 static void test_vector_fmul(const float *src0, const float *src1)
33 {
34  LOCAL_ALIGNED_32(float, cdst, [LEN]);
35  LOCAL_ALIGNED_32(float, odst, [LEN]);
36  int i;
37 
38  declare_func(void, float *dst, const float *src0, const float *src1,
39  int len);
40 
41  call_ref(cdst, src0, src1, LEN);
42  call_new(odst, src0, src1, LEN);
43  for (i = 0; i < LEN; i++) {
44  double t = fabs(src0[i]) + fabs(src1[i]) + fabs(src0[i] * src1[i]) + 1.0;
45  if (!float_near_abs_eps(cdst[i], odst[i], t * 2 * FLT_EPSILON)) {
46  fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n",
47  i, cdst[i], odst[i], cdst[i] - odst[i]);
48  fail();
49  break;
50  }
51  }
52  bench_new(odst, src0, src1, LEN);
53 }
54 
55 static void test_vector_dmul(const double *src0, const double *src1)
56 {
57  LOCAL_ALIGNED_32(double, cdst, [LEN]);
58  LOCAL_ALIGNED_32(double, odst, [LEN]);
59  int i;
60 
61  declare_func(void, double *dst, const double *src0, const double *src1,
62  int len);
63 
64  call_ref(cdst, src0, src1, LEN);
65  call_new(odst, src0, src1, LEN);
66  for (i = 0; i < LEN; i++) {
67  double t = fabs(src0[i]) + fabs(src1[i]) + fabs(src0[i] * src1[i]) + 1.0;
68  if (!double_near_abs_eps(cdst[i], odst[i], t * 2 * DBL_EPSILON)) {
69  fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n",
70  i, cdst[i], odst[i], cdst[i] - odst[i]);
71  fail();
72  break;
73  }
74  }
75  bench_new(odst, src0, src1, LEN);
76 }
77 
78 #define ARBITRARY_FMUL_ADD_CONST 0.005
79 static void test_vector_fmul_add(const float *src0, const float *src1, const float *src2)
80 {
81  LOCAL_ALIGNED_32(float, cdst, [LEN]);
82  LOCAL_ALIGNED_32(float, odst, [LEN]);
83  int i;
84 
85  declare_func(void, float *dst, const float *src0, const float *src1,
86  const float *src2, int len);
87 
88  call_ref(cdst, src0, src1, src2, LEN);
89  call_new(odst, src0, src1, src2, LEN);
90  for (i = 0; i < LEN; i++) {
91  if (!float_near_abs_eps(cdst[i], odst[i], ARBITRARY_FMUL_ADD_CONST)) {
92  fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n",
93  i, cdst[i], odst[i], cdst[i] - odst[i]);
94  fail();
95  break;
96  }
97  }
98  bench_new(odst, src0, src1, src2, LEN);
99 }
100 
101 static void test_vector_fmul_scalar(const float *src0, const float *src1)
102 {
103  LOCAL_ALIGNED_16(float, cdst, [LEN]);
104  LOCAL_ALIGNED_16(float, odst, [LEN]);
105  int i;
106 
107  declare_func(void, float *dst, const float *src, float mul, int len);
108 
109  call_ref(cdst, src0, src1[0], LEN);
110  call_new(odst, src0, src1[0], LEN);
111  for (i = 0; i < LEN; i++) {
112  double t = fabs(src0[i]) + fabs(src1[0]) + fabs(src0[i] * src1[0]) + 1.0;
113  if (!float_near_abs_eps(cdst[i], odst[i], t * 2 * FLT_EPSILON)) {
114  fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n",
115  i, cdst[i], odst[i], cdst[i] - odst[i]);
116  fail();
117  break;
118  }
119  }
120  bench_new(odst, src0, src1[0], LEN);
121 }
122 
123 #define ARBITRARY_FMUL_WINDOW_CONST 0.008
124 static void test_vector_fmul_window(const float *src0, const float *src1, const float *win)
125 {
126  LOCAL_ALIGNED_16(float, cdst, [LEN]);
127  LOCAL_ALIGNED_16(float, odst, [LEN]);
128  int i;
129 
130  declare_func(void, float *dst, const float *src0, const float *src1,
131  const float *win, int len);
132 
133  call_ref(cdst, src0, src1, win, LEN / 2);
134  call_new(odst, src0, src1, win, LEN / 2);
135  for (i = 0; i < LEN; i++) {
136  if (!float_near_abs_eps(cdst[i], odst[i], ARBITRARY_FMUL_WINDOW_CONST)) {
137  fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n",
138  i, cdst[i], odst[i], cdst[i] - odst[i]);
139  fail();
140  break;
141  }
142  }
143  bench_new(odst, src0, src1, win, LEN / 2);
144 }
145 
146 #define ARBITRARY_FMAC_SCALAR_CONST 0.005
147 static void test_vector_fmac_scalar(const float *src0, const float *src1, const float *src2)
148 {
149  LOCAL_ALIGNED_32(float, cdst, [LEN]);
150  LOCAL_ALIGNED_32(float, odst, [LEN]);
151  int i;
152 
153  declare_func(void, float *dst, const float *src, float mul, int len);
154 
155  memcpy(cdst, src2, LEN * sizeof(*src2));
156  memcpy(odst, src2, LEN * sizeof(*src2));
157 
158  call_ref(cdst, src0, src1[0], LEN);
159  call_new(odst, src0, src1[0], LEN);
160  for (i = 0; i < LEN; i++) {
161  if (!float_near_abs_eps(cdst[i], odst[i], ARBITRARY_FMAC_SCALAR_CONST)) {
162  fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n",
163  i, cdst[i], odst[i], cdst[i] - odst[i]);
164  fail();
165  break;
166  }
167  }
168  memcpy(odst, src2, LEN * sizeof(*src2));
169  bench_new(odst, src0, src1[0], LEN);
170 }
171 
172 static void test_vector_dmul_scalar(const double *src0, const double *src1)
173 {
174  LOCAL_ALIGNED_32(double, cdst, [LEN]);
175  LOCAL_ALIGNED_32(double, odst, [LEN]);
176  int i;
177 
178  declare_func(void, double *dst, const double *src, double mul, int len);
179 
180  call_ref(cdst, src0, src1[0], LEN);
181  call_new(odst, src0, src1[0], LEN);
182  for (i = 0; i < LEN; i++) {
183  double t = fabs(src1[0]) + fabs(src0[i]) + fabs(src1[0] * src0[i]) + 1.0;
184  if (!double_near_abs_eps(cdst[i], odst[i], t * 2 * DBL_EPSILON)) {
185  fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n", i,
186  cdst[i], odst[i], cdst[i] - odst[i]);
187  fail();
188  break;
189  }
190  }
191  bench_new(odst, src0, src1[0], LEN);
192 }
193 
194 #define ARBITRARY_DMAC_SCALAR_CONST 0.005
195 static void test_vector_dmac_scalar(const double *src0, const double *src1, const double *src2)
196 {
197  LOCAL_ALIGNED_32(double, cdst, [LEN]);
198  LOCAL_ALIGNED_32(double, odst, [LEN]);
199  int i;
200 
201  declare_func(void, double *dst, const double *src, double mul, int len);
202 
203  memcpy(cdst, src2, LEN * sizeof(*src2));
204  memcpy(odst, src2, LEN * sizeof(*src2));
205  call_ref(cdst, src0, src1[0], LEN);
206  call_new(odst, src0, src1[0], LEN);
207  for (i = 0; i < LEN; i++) {
208  if (!double_near_abs_eps(cdst[i], odst[i], ARBITRARY_DMAC_SCALAR_CONST)) {
209  fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n",
210  i, cdst[i], odst[i], cdst[i] - odst[i]);
211  fail();
212  break;
213  }
214  }
215  memcpy(odst, src2, LEN * sizeof(*src2));
216  bench_new(odst, src0, src1[0], LEN);
217 }
218 
219 static void test_butterflies_float(const float *src0, const float *src1)
220 {
221  LOCAL_ALIGNED_16(float, cdst, [LEN]);
222  LOCAL_ALIGNED_16(float, odst, [LEN]);
223  LOCAL_ALIGNED_16(float, cdst1, [LEN]);
224  LOCAL_ALIGNED_16(float, odst1, [LEN]);
225  int i;
226 
227  declare_func(void, float *restrict src0, float *restrict src1,
228  int len);
229 
230  memcpy(cdst, src0, LEN * sizeof(*src0));
231  memcpy(cdst1, src1, LEN * sizeof(*src1));
232  memcpy(odst, src0, LEN * sizeof(*src0));
233  memcpy(odst1, src1, LEN * sizeof(*src1));
234 
235  call_ref(cdst, cdst1, LEN);
236  call_new(odst, odst1, LEN);
237  for (i = 0; i < LEN; i++) {
238  if (!float_near_abs_eps(cdst[i], odst[i], FLT_EPSILON) ||
239  !float_near_abs_eps(cdst1[i], odst1[i], FLT_EPSILON)) {
240  fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n",
241  i, cdst[i], odst[i], cdst[i] - odst[i]);
242  fprintf(stderr, "%d: %- .12f - %- .12f = % .12g\n",
243  i, cdst1[i], odst1[i], cdst1[i] - odst1[i]);
244  fail();
245  break;
246  }
247  }
248  memcpy(odst, src0, LEN * sizeof(*src0));
249  memcpy(odst1, src1, LEN * sizeof(*src1));
250  bench_new(odst, odst1, LEN);
251 }
252 
253 #define ARBITRARY_SCALARPRODUCT_CONST 0.2
254 static void test_scalarproduct_float(const float *src0, const float *src1)
255 {
256  float cprod, oprod;
257 
258  declare_func_float(float, const float *src0, const float *src1, int len);
259 
260  cprod = call_ref(src0, src1, LEN);
261  oprod = call_new(src0, src1, LEN);
263  fprintf(stderr, "%- .12f - %- .12f = % .12g\n",
264  cprod, oprod, cprod - oprod);
265  fail();
266  }
267  bench_new(src0, src1, LEN);
268 }
269 
270 static void test_scalarproduct_double(const double *src0, const double *src1)
271 {
272  double cprod, oprod;
273 
274  declare_func_float(double, const double *, const double *, size_t);
275 
276  cprod = call_ref(src0, src1, LEN);
277  oprod = call_new(src0, src1, LEN);
279  fprintf(stderr, "%- .12f - %- .12f = % .12g\n",
280  cprod, oprod, cprod - oprod);
281  fail();
282  }
283  bench_new(src0, src1, LEN);
284 }
285 
287 {
288  LOCAL_ALIGNED_32(float, src0, [LEN]);
289  LOCAL_ALIGNED_32(float, src1, [LEN]);
290  LOCAL_ALIGNED_32(float, src2, [LEN]);
291  LOCAL_ALIGNED_16(float, src3, [LEN]);
292  LOCAL_ALIGNED_16(float, src4, [LEN]);
293  LOCAL_ALIGNED_16(float, src5, [LEN]);
294  LOCAL_ALIGNED_32(double, dbl_src0, [LEN]);
295  LOCAL_ALIGNED_32(double, dbl_src1, [LEN]);
296  LOCAL_ALIGNED_32(double, dbl_src2, [LEN]);
298 
299  if (!fdsp) {
300  fprintf(stderr, "floatdsp: Out of memory error\n");
301  return;
302  }
303 
304  randomize_stddev(src0, LEN, 10.0);
305  randomize_stddev(src1, LEN, 10.0);
306  randomize_stddev(src2, LEN, 10.0);
307  randomize_stddev(src3, LEN, 10.0);
308  randomize_stddev(src4, LEN, 10.0);
309  randomize_stddev(src5, LEN, 10.0);
310  randomize_stddev_dbl(dbl_src0, LEN, 10.0);
311  randomize_stddev_dbl(dbl_src1, LEN, 10.0);
312  randomize_stddev_dbl(dbl_src2, LEN, 10.0);
313 
314  if (check_func(fdsp->vector_fmul, "vector_fmul"))
316  if (check_func(fdsp->vector_fmul_add, "vector_fmul_add"))
318  if (check_func(fdsp->vector_fmul_scalar, "vector_fmul_scalar"))
319  test_vector_fmul_scalar(src3, src4);
320  if (check_func(fdsp->vector_fmul_reverse, "vector_fmul_reverse"))
322  if (check_func(fdsp->vector_fmul_window, "vector_fmul_window"))
323  test_vector_fmul_window(src3, src4, src5);
324  report("vector_fmul");
325  if (check_func(fdsp->vector_fmac_scalar, "vector_fmac_scalar"))
327  report("vector_fmac");
328  if (check_func(fdsp->vector_dmul, "vector_dmul"))
329  test_vector_dmul(dbl_src0, dbl_src1);
330  if (check_func(fdsp->vector_dmul_scalar, "vector_dmul_scalar"))
331  test_vector_dmul_scalar(dbl_src0, dbl_src1);
332  report("vector_dmul");
333  if (check_func(fdsp->vector_dmac_scalar, "vector_dmac_scalar"))
334  test_vector_dmac_scalar(dbl_src0, dbl_src1, dbl_src2);
335  report("vector_dmac");
336  if (check_func(fdsp->butterflies_float, "butterflies_float"))
337  test_butterflies_float(src3, src4);
338  report("butterflies_float");
339  if (check_func(fdsp->scalarproduct_float, "scalarproduct_float"))
340  test_scalarproduct_float(src3, src4);
341  report("scalarproduct_float");
342  if (check_func(fdsp->scalarproduct_double, "scalarproduct_double"))
343  test_scalarproduct_double(dbl_src0, dbl_src1);
344  report("scalarproduct_double");
345 
346  av_freep(&fdsp);
347 }
AVFloatDSPContext::butterflies_float
void(* butterflies_float)(float *restrict v1, float *restrict v2, int len)
Calculate the sum and difference of two vectors of floats.
Definition: float_dsp.h:164
mem_internal.h
src1
const pixel * src1
Definition: h264pred_template.c:420
AVFloatDSPContext::vector_fmul_reverse
void(* vector_fmul_reverse)(float *dst, const float *src0, const float *src1, int len)
Calculate the entry wise product of two vectors of floats, and store the result in a vector of floats...
Definition: float_dsp.h:154
test_scalarproduct_double
static void test_scalarproduct_double(const double *src0, const double *src1)
Definition: float_dsp.c:270
check_func
#define check_func
Definition: test.h:481
float.h
test_vector_dmac_scalar
static void test_vector_dmac_scalar(const double *src0, const double *src1, const double *src2)
Definition: float_dsp.c:195
AVFloatDSPContext::vector_dmul
void(* vector_dmul)(double *dst, const double *src0, const double *src1, int len)
Calculate the entry wise product of two vectors of doubles and store the result in a vector of double...
Definition: float_dsp.h:190
bench_new
#define bench_new
Definition: test.h:487
win
static float win(SuperEqualizerContext *s, float n, int N)
Definition: af_superequalizer.c:119
call_ref
#define call_ref
Definition: test.h:485
ARBITRARY_FMUL_ADD_CONST
#define ARBITRARY_FMUL_ADD_CONST
Definition: float_dsp.c:78
checkasm.h
checkasm_check_float_dsp
void checkasm_check_float_dsp(void)
Definition: float_dsp.c:286
AVFloatDSPContext::scalarproduct_float
float(* scalarproduct_float)(const float *v1, const float *v2, int len)
Calculate the scalar product of two vectors of floats.
Definition: float_dsp.h:175
test_butterflies_float
static void test_butterflies_float(const float *src0, const float *src1)
Definition: float_dsp.c:219
test_vector_fmul_scalar
static void test_vector_fmul_scalar(const float *src0, const float *src1)
Definition: float_dsp.c:101
declare_func
#define declare_func
Definition: test.h:489
LOCAL_ALIGNED_16
#define LOCAL_ALIGNED_16(t, v,...)
Definition: mem_internal.h:130
fail
#define fail
Definition: test.h:479
float_near_abs_eps
#define float_near_abs_eps
Definition: utils.h:449
fabs
static __device__ float fabs(float a)
Definition: cuda_runtime.h:182
LOCAL_ALIGNED_32
#define LOCAL_ALIGNED_32(t, v,...)
Definition: mem_internal.h:132
test_vector_fmul
static void test_vector_fmul(const float *src0, const float *src1)
Definition: float_dsp.c:32
AVFloatDSPContext::vector_fmul_scalar
void(* vector_fmul_scalar)(float *dst, const float *src, float mul, int len)
Multiply a vector of floats by a scalar float.
Definition: float_dsp.h:85
ARBITRARY_FMAC_SCALAR_CONST
#define ARBITRARY_FMAC_SCALAR_CONST
Definition: float_dsp.c:146
AVFloatDSPContext::scalarproduct_double
double(* scalarproduct_double)(const double *v1, const double *v2, size_t len)
Calculate the scalar product of two vectors of doubles.
Definition: float_dsp.h:205
randomize_stddev_dbl
#define randomize_stddev_dbl(buf, size, stddev)
Definition: checkasm.h:142
float_dsp.h
AVFloatDSPContext::vector_fmul
void(* vector_fmul)(float *dst, const float *src0, const float *src1, int len)
Calculate the entry wise product of two vectors of floats and store the result in a vector of floats.
Definition: float_dsp.h:38
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
ARBITRARY_FMUL_WINDOW_CONST
#define ARBITRARY_FMUL_WINDOW_CONST
Definition: float_dsp.c:123
test_vector_dmul_scalar
static void test_vector_dmul_scalar(const double *src0, const double *src1)
Definition: float_dsp.c:172
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
AVFloatDSPContext
Definition: float_dsp.h:24
test_vector_fmul_add
static void test_vector_fmul_add(const float *src0, const float *src1, const float *src2)
Definition: float_dsp.c:79
LEN
#define LEN
Definition: float_dsp.c:30
ARBITRARY_SCALARPRODUCT_CONST
#define ARBITRARY_SCALARPRODUCT_CONST
Definition: float_dsp.c:253
AVFloatDSPContext::vector_fmac_scalar
void(* vector_fmac_scalar)(float *dst, const float *src, float mul, int len)
Multiply a vector of floats by a scalar float and add to destination vector.
Definition: float_dsp.h:54
declare_func_float
#define declare_func_float
Definition: checkasm.h:137
internal.h
src2
const pixel * src2
Definition: h264pred_template.c:421
AVFloatDSPContext::vector_fmul_add
void(* vector_fmul_add)(float *dst, const float *src0, const float *src1, const float *src2, int len)
Calculate the entry wise product of two vectors of floats, add a third vector of floats and store the...
Definition: float_dsp.h:137
len
int len
Definition: vorbis_enc_data.h:426
call_new
#define call_new
Definition: test.h:486
double_near_abs_eps
#define double_near_abs_eps
Definition: utils.h:454
ARBITRARY_DMAC_SCALAR_CONST
#define ARBITRARY_DMAC_SCALAR_CONST
Definition: float_dsp.c:194
test_vector_fmul_window
static void test_vector_fmul_window(const float *src0, const float *src1, const float *win)
Definition: float_dsp.c:124
AVFloatDSPContext::vector_dmul_scalar
void(* vector_dmul_scalar)(double *dst, const double *src, double mul, int len)
Multiply a vector of double by a scalar double.
Definition: float_dsp.h:100
test_scalarproduct_float
static void test_scalarproduct_float(const float *src0, const float *src1)
Definition: float_dsp.c:254
src0
const pixel *const src0
Definition: h264pred_template.c:419
report
#define report
Definition: test.h:480
mem.h
AVFloatDSPContext::vector_fmul_window
void(* vector_fmul_window)(float *dst, const float *src0, const float *src1, const float *win, int len)
Overlap/add with window function.
Definition: float_dsp.h:119
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
avpriv_float_dsp_alloc
av_cold AVFloatDSPContext * avpriv_float_dsp_alloc(int bit_exact)
Allocate a float DSP context.
Definition: float_dsp.c:135
AVFloatDSPContext::vector_dmac_scalar
void(* vector_dmac_scalar)(double *dst, const double *src, double mul, int len)
Multiply a vector of doubles by a scalar double and add to destination vector.
Definition: float_dsp.h:70
test_vector_dmul
static void test_vector_dmul(const double *src0, const double *src1)
Definition: float_dsp.c:55
src
#define src
Definition: vp8dsp.c:248
test_vector_fmac_scalar
static void test_vector_fmac_scalar(const float *src0, const float *src1, const float *src2)
Definition: float_dsp.c:147
randomize_stddev
#define randomize_stddev(buf, size, stddev)
Definition: checkasm.h:140