1 /*
2  * Copyright (c) 2021 Stephanos Ioannidis <root@stephanos.io>
3  * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/ztest.h>
9 #include <zephyr/kernel.h>
10 #include <stdlib.h>
11 #include <arm_math.h>
12 #include "../../common/test_common.h"
13 
14 #include "binary_f32.pat"
15 
16 #define SNR_ERROR_THRESH	((float32_t)120)
17 #define REL_ERROR_THRESH	(1.0e-6)
18 #define ABS_ERROR_THRESH	(1.0e-5)
19 
20 #define NUM_MATRICES		(ARRAY_SIZE(in_dims) / 3)
21 #define MAX_MATRIX_DIM		(40)
22 
23 #define OP2_MULT		(0)
24 #define OP2C_CMPLX_MULT		(0)
25 
test_op2(int op,const uint32_t * input1,const uint32_t * input2,const uint32_t * ref,size_t length)26 static void test_op2(int op, const uint32_t *input1, const uint32_t *input2,
27 	const uint32_t *ref, size_t length)
28 {
29 	size_t index;
30 	uint16_t *dims = (uint16_t *)in_dims;
31 	float32_t *tmp1, *tmp2, *output;
32 	uint16_t rows, internal, columns;
33 	arm_status status;
34 
35 	arm_matrix_instance_f32 mat_in1;
36 	arm_matrix_instance_f32 mat_in2;
37 	arm_matrix_instance_f32 mat_out;
38 
39 	/* Allocate buffers */
40 	tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float32_t));
41 	zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
42 
43 	tmp2 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float32_t));
44 	zassert_not_null(tmp2, ASSERT_MSG_BUFFER_ALLOC_FAILED);
45 
46 	output = malloc(length * sizeof(float32_t));
47 	zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
48 
49 	/* Initialise contexts */
50 	mat_in1.pData = tmp1;
51 	mat_in2.pData = tmp2;
52 	mat_out.pData = output;
53 
54 	/* Iterate matrices */
55 	for (index = 0; index < NUM_MATRICES; index++) {
56 		rows = *dims++;
57 		internal = *dims++;
58 		columns = *dims++;
59 
60 		/* Initialise matrix dimensions */
61 		mat_in1.numRows = rows;
62 		mat_in1.numCols = internal;
63 
64 		mat_in2.numRows = internal;
65 		mat_in2.numCols = columns;
66 
67 		mat_out.numRows = rows;
68 		mat_out.numCols = columns;
69 
70 		/* Load matrix data */
71 		memcpy(mat_in1.pData, input1,
72 		       rows * internal * sizeof(float32_t));
73 
74 		memcpy(mat_in2.pData, input2,
75 		       internal * columns * sizeof(float32_t));
76 
77 		/* Run test function */
78 		switch (op) {
79 		case OP2_MULT:
80 			status = arm_mat_mult_f32(&mat_in1, &mat_in2,
81 						  &mat_out);
82 			break;
83 		default:
84 			zassert_unreachable("invalid operation");
85 		}
86 
87 		/* Validate status */
88 		zassert_equal(status, ARM_MATH_SUCCESS,
89 			      ASSERT_MSG_INCORRECT_COMP_RESULT);
90 
91 		/* Increment output pointer */
92 		mat_out.pData += (rows * columns);
93 	}
94 
95 	/* Validate output */
96 	zassert_true(
97 		test_snr_error_f32(length, output, (float32_t *)ref,
98 			SNR_ERROR_THRESH),
99 		ASSERT_MSG_SNR_LIMIT_EXCEED);
100 
101 	zassert_true(
102 		test_close_error_f32(length, output, (float32_t *)ref,
103 			ABS_ERROR_THRESH, REL_ERROR_THRESH),
104 		ASSERT_MSG_ERROR_LIMIT_EXCEED);
105 
106 	/* Free buffers */
107 	free(tmp1);
108 	free(tmp2);
109 	free(output);
110 }
111 
112 DEFINE_TEST_VARIANT5(matrix_binary_f32,
113 	op2, arm_mat_mult_f32, OP2_MULT,
114 	in_mult1, in_mult2, ref_mult,
115 	ARRAY_SIZE(ref_mult));
116 
test_op2c(int op,const uint32_t * input1,const uint32_t * input2,const uint32_t * ref,size_t length)117 static void test_op2c(int op, const uint32_t *input1, const uint32_t *input2,
118 	const uint32_t *ref, size_t length)
119 {
120 	size_t index;
121 	uint16_t *dims = (uint16_t *)in_dims;
122 	float32_t *tmp1, *tmp2, *output;
123 	uint16_t rows, internal, columns;
124 	arm_status status;
125 
126 	arm_matrix_instance_f32 mat_in1;
127 	arm_matrix_instance_f32 mat_in2;
128 	arm_matrix_instance_f32 mat_out;
129 
130 	/* Allocate buffers */
131 	tmp1 = malloc(2 * MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float32_t));
132 	zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
133 
134 	tmp2 = malloc(2 * MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float32_t));
135 	zassert_not_null(tmp2, ASSERT_MSG_BUFFER_ALLOC_FAILED);
136 
137 	output = malloc(2 * length * sizeof(float32_t));
138 	zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
139 
140 	/* Initialise contexts */
141 	mat_in1.pData = tmp1;
142 	mat_in2.pData = tmp2;
143 	mat_out.pData = output;
144 
145 	/* Iterate matrices */
146 	for (index = 0; index < NUM_MATRICES; index++) {
147 		rows = *dims++;
148 		internal = *dims++;
149 		columns = *dims++;
150 
151 		/* Initialise matrix dimensions */
152 		mat_in1.numRows = rows;
153 		mat_in1.numCols = internal;
154 
155 		mat_in2.numRows = internal;
156 		mat_in2.numCols = columns;
157 
158 		mat_out.numRows = rows;
159 		mat_out.numCols = columns;
160 
161 		/* Load matrix data */
162 		memcpy(mat_in1.pData, input1,
163 		       2 * rows * internal * sizeof(float32_t));
164 
165 		memcpy(mat_in2.pData, input2,
166 		       2 * internal * columns * sizeof(float32_t));
167 
168 		/* Run test function */
169 		switch (op) {
170 		case OP2C_CMPLX_MULT:
171 			status = arm_mat_cmplx_mult_f32(&mat_in1, &mat_in2,
172 							&mat_out);
173 			break;
174 		default:
175 			zassert_unreachable("invalid operation");
176 		}
177 
178 		/* Validate status */
179 		zassert_equal(status, ARM_MATH_SUCCESS,
180 			      ASSERT_MSG_INCORRECT_COMP_RESULT);
181 
182 		/* Increment output pointer */
183 		mat_out.pData += (2 * rows * columns);
184 	}
185 
186 	/* Validate output */
187 	zassert_true(
188 		test_snr_error_f32(2 * length, output, (float32_t *)ref,
189 			SNR_ERROR_THRESH),
190 		ASSERT_MSG_SNR_LIMIT_EXCEED);
191 
192 	zassert_true(
193 		test_close_error_f32(length, output, (float32_t *)ref,
194 			ABS_ERROR_THRESH, REL_ERROR_THRESH),
195 		ASSERT_MSG_ERROR_LIMIT_EXCEED);
196 
197 	/* Free buffers */
198 	free(tmp1);
199 	free(tmp2);
200 	free(output);
201 }
202 
203 DEFINE_TEST_VARIANT5(matrix_binary_f32,
204 	op2c, arm_mat_cmplx_mult_f32, OP2C_CMPLX_MULT,
205 	in_cmplx_mult1, in_cmplx_mult2, ref_cmplx_mult,
206 	ARRAY_SIZE(ref_cmplx_mult) / 2);
207 
208 ZTEST_SUITE(matrix_binary_f32, NULL, NULL, NULL, NULL, NULL);
209