LCOV - code coverage report
Current view: top level - src/libavutil/tests - float_dsp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 132 162 81.5 %
Date: 2017-01-22 02:20:28 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /*
       2             :  * This file is part of FFmpeg.
       3             :  *
       4             :  * FFmpeg is free software; you can redistribute it and/or
       5             :  * modify it under the terms of the GNU Lesser General Public
       6             :  * License as published by the Free Software Foundation; either
       7             :  * version 2.1 of the License, or (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 GNU
      12             :  * Lesser General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public
      15             :  * License along with FFmpeg; if not, write to the Free Software
      16             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      17             :  */
      18             : 
      19             : #include "config.h"
      20             : 
      21             : #include <float.h>
      22             : #include <math.h>
      23             : #include <stdint.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : #if HAVE_UNISTD_H
      27             : #include <unistd.h> /* for getopt */
      28             : #endif
      29             : #if !HAVE_GETOPT
      30             : #include "compat/getopt.c"
      31             : #endif
      32             : 
      33             : #include "libavutil/common.h"
      34             : #include "libavutil/cpu.h"
      35             : #include "libavutil/internal.h"
      36             : #include "libavutil/lfg.h"
      37             : #include "libavutil/log.h"
      38             : #include "libavutil/random_seed.h"
      39             : #include "libavutil/float_dsp.h"
      40             : 
      41             : #define LEN 240
      42             : 
      43           3 : static void fill_float_array(AVLFG *lfg, float *a, int len)
      44             : {
      45             :     int i;
      46           3 :     double bmg[2], stddev = 10.0, mean = 0.0;
      47             : 
      48         363 :     for (i = 0; i < len; i += 2) {
      49         360 :         av_bmg_get(lfg, bmg);
      50         360 :         a[i]     = bmg[0] * stddev + mean;
      51         360 :         a[i + 1] = bmg[1] * stddev + mean;
      52             :     }
      53           3 : }
      54           9 : static int compare_floats(const float *a, const float *b, int len,
      55             :                           float max_diff)
      56             : {
      57             :     int i;
      58        1930 :     for (i = 0; i < len; i++) {
      59        1921 :         if (fabsf(a[i] - b[i]) > max_diff) {
      60           0 :             av_log(NULL, AV_LOG_ERROR, "%d: %- .12f - %- .12f = % .12g\n",
      61           0 :                    i, a[i], b[i], a[i] - b[i]);
      62           0 :             return -1;
      63             :         }
      64             :     }
      65           9 :     return 0;
      66             : }
      67             : 
      68           2 : static void fill_double_array(AVLFG *lfg, double *a, int len)
      69             : {
      70             :     int i;
      71           2 :     double bmg[2], stddev = 10.0, mean = 0.0;
      72             : 
      73         242 :     for (i = 0; i < len; i += 2) {
      74         240 :         av_bmg_get(lfg, bmg);
      75         240 :         a[i]     = bmg[0] * stddev + mean;
      76         240 :         a[i + 1] = bmg[1] * stddev + mean;
      77             :     }
      78           2 : }
      79             : 
      80           1 : static int compare_doubles(const double *a, const double *b, int len,
      81             :                            double max_diff)
      82             : {
      83             :     int i;
      84             : 
      85         241 :     for (i = 0; i < len; i++) {
      86         240 :         if (fabs(a[i] - b[i]) > max_diff) {
      87           0 :             av_log(NULL, AV_LOG_ERROR, "%d: %- .12f - %- .12f = % .12g\n",
      88           0 :                    i, a[i], b[i], a[i] - b[i]);
      89           0 :             return -1;
      90             :         }
      91             :     }
      92           1 :     return 0;
      93             : }
      94             : 
      95           1 : static int test_vector_fmul(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
      96             :                             const float *v1, const float *v2)
      97             : {
      98           1 :     LOCAL_ALIGNED(32, float, cdst, [LEN]);
      99           1 :     LOCAL_ALIGNED(32, float, odst, [LEN]);
     100             :     int ret;
     101             : 
     102           1 :     cdsp->vector_fmul(cdst, v1, v2, LEN);
     103           1 :     fdsp->vector_fmul(odst, v1, v2, LEN);
     104             : 
     105           1 :     if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON))
     106           0 :         av_log(NULL, AV_LOG_ERROR, "vector_fmul failed\n");
     107             : 
     108           1 :     return ret;
     109             : }
     110             : 
     111             : #define ARBITRARY_FMAC_SCALAR_CONST 0.005
     112           1 : static int test_vector_fmac_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
     113             :                                    const float *v1, const float *src0, float scale)
     114             : {
     115           1 :     LOCAL_ALIGNED(32, float, cdst, [LEN]);
     116           1 :     LOCAL_ALIGNED(32, float, odst, [LEN]);
     117             :     int ret;
     118             : 
     119           1 :     memcpy(cdst, v1, LEN * sizeof(*v1));
     120           1 :     memcpy(odst, v1, LEN * sizeof(*v1));
     121             : 
     122           1 :     cdsp->vector_fmac_scalar(cdst, src0, scale, LEN);
     123           1 :     fdsp->vector_fmac_scalar(odst, src0, scale, LEN);
     124             : 
     125           1 :     if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMAC_SCALAR_CONST))
     126           0 :         av_log(NULL, AV_LOG_ERROR, "vector_fmac_scalar failed\n");
     127             : 
     128           1 :     return ret;
     129             : }
     130             : 
     131           1 : static int test_vector_fmul_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
     132             :                                    const float *v1, float scale)
     133             : {
     134           1 :     LOCAL_ALIGNED(32, float, cdst, [LEN]);
     135           1 :     LOCAL_ALIGNED(32, float, odst, [LEN]);
     136             :     int ret;
     137             : 
     138           1 :     cdsp->vector_fmul_scalar(cdst, v1, scale, LEN);
     139           1 :     fdsp->vector_fmul_scalar(odst, v1, scale, LEN);
     140             : 
     141           1 :     if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON))
     142           0 :         av_log(NULL, AV_LOG_ERROR, "vector_fmul_scalar failed\n");
     143             : 
     144           1 :     return ret;
     145             : }
     146             : 
     147           1 : static int test_vector_dmul_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
     148             :                                    const double *v1, double scale)
     149             : {
     150           1 :     LOCAL_ALIGNED(32, double, cdst, [LEN]);
     151           1 :     LOCAL_ALIGNED(32, double, odst, [LEN]);
     152             :     int ret;
     153             : 
     154           1 :     cdsp->vector_dmul_scalar(cdst, v1, scale, LEN);
     155           1 :     fdsp->vector_dmul_scalar(odst, v1, scale, LEN);
     156             : 
     157           1 :     if (ret = compare_doubles(cdst, odst, LEN, DBL_EPSILON))
     158           0 :         av_log(NULL, AV_LOG_ERROR, "vector_dmul_scalar failed\n");
     159             : 
     160           1 :     return ret;
     161             : }
     162             : 
     163             : #define ARBITRARY_FMUL_WINDOW_CONST 0.008
     164           1 : static int test_vector_fmul_window(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
     165             :                                    const float *v1, const float *v2, const float *v3)
     166             : {
     167           1 :     LOCAL_ALIGNED(32, float, cdst, [LEN]);
     168           1 :     LOCAL_ALIGNED(32, float, odst, [LEN]);
     169             :     int ret;
     170             : 
     171           1 :     cdsp->vector_fmul_window(cdst, v1, v2, v3, LEN / 2);
     172           1 :     fdsp->vector_fmul_window(odst, v1, v2, v3, LEN / 2);
     173             : 
     174           1 :     if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMUL_WINDOW_CONST))
     175           0 :         av_log(NULL, AV_LOG_ERROR, "vector_fmul_window failed\n");
     176             : 
     177           1 :     return ret;
     178             : }
     179             : 
     180             : #define ARBITRARY_FMUL_ADD_CONST 0.005
     181           1 : static int test_vector_fmul_add(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
     182             :                                 const float *v1, const float *v2, const float *v3)
     183             : {
     184           1 :     LOCAL_ALIGNED(32, float, cdst, [LEN]);
     185           1 :     LOCAL_ALIGNED(32, float, odst, [LEN]);
     186             :     int ret;
     187             : 
     188           1 :     cdsp->vector_fmul_add(cdst, v1, v2, v3, LEN);
     189           1 :     fdsp->vector_fmul_add(odst, v1, v2, v3, LEN);
     190             : 
     191           1 :     if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMUL_ADD_CONST))
     192           0 :         av_log(NULL, AV_LOG_ERROR, "vector_fmul_add failed\n");
     193             : 
     194           1 :     return ret;
     195             : }
     196             : 
     197           1 : static int test_vector_fmul_reverse(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
     198             :                                     const float *v1, const float *v2)
     199             : {
     200           1 :     LOCAL_ALIGNED(32, float, cdst, [LEN]);
     201           1 :     LOCAL_ALIGNED(32, float, odst, [LEN]);
     202             :     int ret;
     203             : 
     204           1 :     cdsp->vector_fmul_reverse(cdst, v1, v2, LEN);
     205           1 :     fdsp->vector_fmul_reverse(odst, v1, v2, LEN);
     206             : 
     207           1 :     if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON))
     208           0 :         av_log(NULL, AV_LOG_ERROR, "vector_fmul_reverse failed\n");
     209             : 
     210           1 :     return ret;
     211             : }
     212             : 
     213           1 : static int test_butterflies_float(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
     214             :                                   const float *v1, const float *v2)
     215             : {
     216           1 :     LOCAL_ALIGNED(32, float, cv1, [LEN]);
     217           1 :     LOCAL_ALIGNED(32, float, cv2, [LEN]);
     218           1 :     LOCAL_ALIGNED(32, float, ov1, [LEN]);
     219           1 :     LOCAL_ALIGNED(32, float, ov2, [LEN]);
     220             :     int ret;
     221             : 
     222           1 :     memcpy(cv1, v1, LEN * sizeof(*v1));
     223           1 :     memcpy(cv2, v2, LEN * sizeof(*v2));
     224           1 :     memcpy(ov1, v1, LEN * sizeof(*v1));
     225           1 :     memcpy(ov2, v2, LEN * sizeof(*v2));
     226             : 
     227           1 :     cdsp->butterflies_float(cv1, cv2, LEN);
     228           1 :     fdsp->butterflies_float(ov1, ov2, LEN);
     229             : 
     230           1 :     if ((ret = compare_floats(cv1, ov1, LEN, FLT_EPSILON)) ||
     231             :         (ret = compare_floats(cv2, ov2, LEN, FLT_EPSILON)))
     232           0 :         av_log(NULL, AV_LOG_ERROR, "butterflies_float failed\n");
     233             : 
     234           1 :     return ret;
     235             : }
     236             : 
     237             : #define ARBITRARY_SCALARPRODUCT_CONST 0.2
     238           1 : static int test_scalarproduct_float(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
     239             :                                     const float *v1, const float *v2)
     240             : {
     241             :     float cprod, oprod;
     242             :     int ret;
     243             : 
     244           1 :     cprod = cdsp->scalarproduct_float(v1, v2, LEN);
     245           1 :     oprod = fdsp->scalarproduct_float(v1, v2, LEN);
     246             : 
     247           1 :     if (ret = compare_floats(&cprod, &oprod, 1, ARBITRARY_SCALARPRODUCT_CONST))
     248           0 :         av_log(NULL, AV_LOG_ERROR, "scalarproduct_float failed\n");
     249             : 
     250           1 :     return ret;
     251             : }
     252             : 
     253           1 : int main(int argc, char **argv)
     254             : {
     255           1 :     int ret = 0, seeded = 0;
     256             :     uint32_t seed;
     257             :     AVFloatDSPContext *fdsp, *cdsp;
     258             :     AVLFG lfg;
     259             : 
     260           1 :     LOCAL_ALIGNED(32, float, src0, [LEN]);
     261           1 :     LOCAL_ALIGNED(32, float, src1, [LEN]);
     262           1 :     LOCAL_ALIGNED(32, float, src2, [LEN]);
     263           1 :     LOCAL_ALIGNED(32, double, dbl_src0, [LEN]);
     264           1 :     LOCAL_ALIGNED(32, double, dbl_src1, [LEN]);
     265             : 
     266           1 :     for (;;) {
     267           2 :         int arg = getopt(argc, argv, "s:c:");
     268           2 :         if (arg == -1)
     269           1 :             break;
     270           1 :         switch (arg) {
     271             :         case 's':
     272           0 :             seed = strtoul(optarg, NULL, 10);
     273           0 :             seeded = 1;
     274           0 :             break;
     275             :         case 'c':
     276             :         {
     277           1 :             int cpuflags = av_get_cpu_flags();
     278             : 
     279           1 :             if (av_parse_cpu_caps(&cpuflags, optarg) < 0)
     280           0 :                 return 1;
     281             : 
     282           1 :             av_force_cpu_flags(cpuflags);
     283           1 :             break;
     284             :         }
     285             :         }
     286             :     }
     287           1 :     if (!seeded)
     288           1 :         seed = av_get_random_seed();
     289             : 
     290           1 :     av_log(NULL, AV_LOG_INFO, "float_dsp-test: %s %u\n", seeded ? "seed" : "random seed", seed);
     291             : 
     292           1 :     fdsp = avpriv_float_dsp_alloc(1);
     293           1 :     av_force_cpu_flags(0);
     294           1 :     cdsp = avpriv_float_dsp_alloc(1);
     295             : 
     296           1 :     if (!fdsp || !cdsp) {
     297           0 :         ret = 1;
     298           0 :         goto end;
     299             :     }
     300             : 
     301           1 :     av_lfg_init(&lfg, seed);
     302             : 
     303           1 :     fill_float_array(&lfg, src0, LEN);
     304           1 :     fill_float_array(&lfg, src1, LEN);
     305           1 :     fill_float_array(&lfg, src2, LEN);
     306             : 
     307           1 :     fill_double_array(&lfg, dbl_src0, LEN);
     308           1 :     fill_double_array(&lfg, dbl_src1, LEN);
     309             : 
     310           1 :     if (test_vector_fmul(fdsp, cdsp, src0, src1))
     311           0 :         ret -= 1 << 0;
     312           1 :     if (test_vector_fmac_scalar(fdsp, cdsp, src2, src0, src1[0]))
     313           0 :         ret -= 1 << 1;
     314           1 :     if (test_vector_fmul_scalar(fdsp, cdsp, src0, src1[0]))
     315           0 :         ret -= 1 << 2;
     316           1 :     if (test_vector_fmul_window(fdsp, cdsp, src0, src1, src2))
     317           0 :         ret -= 1 << 3;
     318           1 :     if (test_vector_fmul_add(fdsp, cdsp, src0, src1, src2))
     319           0 :         ret -= 1 << 4;
     320           1 :     if (test_vector_fmul_reverse(fdsp, cdsp, src0, src1))
     321           0 :         ret -= 1 << 5;
     322           1 :     if (test_butterflies_float(fdsp, cdsp, src0, src1))
     323           0 :         ret -= 1 << 6;
     324           1 :     if (test_scalarproduct_float(fdsp, cdsp, src0, src1))
     325           0 :         ret -= 1 << 7;
     326           1 :     if (test_vector_dmul_scalar(fdsp, cdsp, dbl_src0, dbl_src1[0]))
     327           0 :         ret -= 1 << 8;
     328             : 
     329             : end:
     330           1 :     av_freep(&fdsp);
     331           1 :     av_freep(&cdsp);
     332           1 :     return ret;
     333             : }

Generated by: LCOV version 1.12