1/*
2 * Copyright (c) 2020
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <stdio.h>
22#include <string.h>
23#include <math.h>
24#include "libavfilter/dnn/dnn_backend_native_layer_mathunary.h"
25#include "libavutil/avassert.h"
26
27#define EPS 0.00001
28
29static float get_expected(float f, DNNMathUnaryOperation op)
30{
31    switch (op)
32    {
33    case DMUO_ABS:
34        return (f >= 0) ? f : -f;
35    case DMUO_SIN:
36        return sin(f);
37    case DMUO_COS:
38        return cos(f);
39    case DMUO_TAN:
40        return tan(f);
41    case DMUO_ASIN:
42        return asin(f);
43    case DMUO_ACOS:
44        return acos(f);
45    case DMUO_ATAN:
46        return atan(f);
47    case DMUO_SINH:
48        return sinh(f);
49    case DMUO_COSH:
50        return cosh(f);
51    case DMUO_TANH:
52        return tanh(f);
53    case DMUO_ASINH:
54        return asinh(f);
55    case DMUO_ACOSH:
56        return acosh(f);
57    case DMUO_ATANH:
58        return atanh(f);
59    case DMUO_CEIL:
60        return ceil(f);
61    case DMUO_FLOOR:
62        return floor(f);
63    case DMUO_ROUND:
64        return round(f);
65    default:
66        av_assert0(!"not supported yet");
67        return 0.f;
68    }
69}
70
71static int test(DNNMathUnaryOperation op)
72{
73    DnnLayerMathUnaryParams params;
74    DnnOperand operands[2];
75    int32_t input_indexes[1];
76    float input[1*1*3*3] = {
77        0.1, 0.5, 0.75, -3, 2.5, 2, -2.1, 7.8, 100};
78    float *output;
79
80    params.un_op = op;
81
82    operands[0].data = input;
83    operands[0].dims[0] = 1;
84    operands[0].dims[1] = 1;
85    operands[0].dims[2] = 3;
86    operands[0].dims[3] = 3;
87    operands[1].data = NULL;
88
89    input_indexes[0] = 0;
90    ff_dnn_execute_layer_math_unary(operands, input_indexes, 1, &params, NULL);
91
92    output = operands[1].data;
93    for (int i = 0; i < sizeof(input) / sizeof(float); ++i) {
94        float expected_output = get_expected(input[i], op);
95        int output_nan = isnan(output[i]);
96        int expected_nan = isnan(expected_output);
97        if ((!output_nan && !expected_nan && fabs(output[i] - expected_output) > EPS) ||
98            (output_nan && !expected_nan) || (!output_nan && expected_nan)) {
99            printf("at index %d, output: %f, expected_output: %f\n", i, output[i], expected_output);
100            av_freep(&output);
101            return 1;
102        }
103    }
104
105    av_freep(&output);
106    return 0;
107}
108
109int main(int agrc, char **argv)
110{
111    if (test(DMUO_ABS))
112        return 1;
113    if (test(DMUO_SIN))
114        return 1;
115    if (test(DMUO_COS))
116        return 1;
117    if (test(DMUO_TAN))
118        return 1;
119    if (test(DMUO_ASIN))
120        return 1;
121    if (test(DMUO_ACOS))
122        return 1;
123    if (test(DMUO_ATAN))
124        return 1;
125    if (test(DMUO_SINH))
126        return 1;
127    if (test(DMUO_COSH))
128        return 1;
129    if (test(DMUO_TANH))
130        return 1;
131    if (test(DMUO_ASINH))
132        return 1;
133    if (test(DMUO_ACOSH))
134        return 1;
135    if (test(DMUO_ATANH))
136        return 1;
137    if (test(DMUO_CEIL))
138        return 1;
139    if (test(DMUO_FLOOR))
140        return 1;
141    if (test(DMUO_ROUND))
142        return 1;
143    return 0;
144}
145