1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Copyright(c) 2022 Intel Corporation. All rights reserved.
4  *
5  * Author: Shriram Shastry <malladi.sastry@linux.intel.com>
6  */
7 
8 #include <stdio.h>
9 #include <stdint.h>
10 #include <stdarg.h>
11 #include <stddef.h>
12 #include <setjmp.h>
13 #include <math.h>
14 #include <cmocka.h>
15 #include <string.h>
16 #include <time.h>
17 #include <stdlib.h>
18 
19 #include <sof/math/exp_fcn.h>
20 #include <sof/audio/format.h>
21 #include <rtos/string.h>
22 #include <sof/common.h>
23 
24 #define ULP_TOLERANCE 5.60032793
25 #define ULP_SCALE 0.0000999999999749
26 
27 static void gen_exp_testvector(double a, double b, double *r, int32_t *b_i);
28 
29 /* testvector in Q4.28, -5 to +5 */
30 /*
31  * Arguments	:double a
32  *		 double b
33  *		 double *r
34  *		 int32_t *b_i
35  * Return Type	:void
36  */
gen_exp_testvector(double a,double b,double * r,int32_t * b_i)37 static void gen_exp_testvector(double a, double b, double *r, int32_t *b_i)
38 {
39 	double a2;
40 	double b2;
41 
42 	*r = a + rand() % (int32_t)(b - a + 1);
43 	a2 = *r * 268435456;
44 	b2 = fabs(a2);
45 	if (b2 < 4503599627370496LL)
46 		a2 = floor(a2 + 0.5);
47 
48 	if (a2 < 2147483648LL)
49 		*b_i = (a2 >= -2147483648LL) ? a2 : INT32_MIN;
50 	else
51 		*b_i = INT32_MAX;
52 }
53 
test_math_arithmetic_exponential_fixed(void ** state)54 static void test_math_arithmetic_exponential_fixed(void **state)
55 {
56 	(void)state;
57 
58 	int32_t accum;
59 	int i;
60 	double a_i;
61 	double max_ulp;
62 	double a_tmp = -5.0123456789;
63 	double b_tmp =  5.0123456789;
64 	double r;
65 	int32_t b_i;
66 
67 	srand((unsigned int)time(NULL));
68 	for (i = 0; i < 256; i++) {
69 		gen_exp_testvector(a_tmp, b_tmp, &r, &b_i);
70 		a_i = (double)b_i / (1 << 28);
71 		accum = sofm_exp_int32(b_i);
72 		max_ulp = fabs(exp(a_i) - (double)accum / (1 << 23)) / ULP_SCALE;
73 
74 		if (max_ulp > ULP_TOLERANCE) {
75 			printf("%s: ULP for %.16f: value = %.16f, Exp = %.16f\n", __func__,
76 			       max_ulp, (double)b_i / (1 << 28), (double)accum / (1 << 23));
77 			assert_true(max_ulp <= ULP_TOLERANCE);
78 		}
79 	}
80 }
81 
main(void)82 int main(void)
83 {
84 	const struct CMUnitTest tests[] = {
85 		cmocka_unit_test(test_math_arithmetic_exponential_fixed)
86 	};
87 
88 	cmocka_set_message_output(CM_OUTPUT_TAP);
89 
90 	return cmocka_run_group_tests(tests, NULL, NULL);
91 }
92