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 "unary_q31.pat"
15
16 #define SNR_ERROR_THRESH ((float32_t)100)
17 #define ABS_ERROR_THRESH_Q31 ((q31_t)2)
18 #define ABS_ERROR_THRESH_Q63 ((q63_t)(1 << 16))
19
20 #define NUM_MATRICES (ARRAY_SIZE(in_dims) / 2)
21 #define MAX_MATRIX_DIM (40)
22
23 #define OP2_ADD (0)
24 #define OP2_SUB (1)
25 #define OP1_SCALE (0)
26 #define OP1_TRANS (1)
27 #define OP2V_VEC_MULT (0)
28 #define OP1C_CMPLX_TRANS (0)
29
test_op2(int op,const q31_t * ref,size_t length)30 static void test_op2(int op, const q31_t *ref, size_t length)
31 {
32 size_t index;
33 uint16_t *dims = (uint16_t *)in_dims;
34 q31_t *tmp1, *tmp2, *output;
35 uint16_t rows, columns;
36 arm_status status;
37
38 arm_matrix_instance_q31 mat_in1;
39 arm_matrix_instance_q31 mat_in2;
40 arm_matrix_instance_q31 mat_out;
41
42 /* Allocate buffers */
43 tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(q31_t));
44 zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
45
46 tmp2 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(q31_t));
47 zassert_not_null(tmp2, ASSERT_MSG_BUFFER_ALLOC_FAILED);
48
49 output = malloc(length * sizeof(q31_t));
50 zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
51
52 /* Initialise contexts */
53 mat_in1.pData = tmp1;
54 mat_in2.pData = tmp2;
55 mat_out.pData = output;
56
57 /* Iterate matrices */
58 for (index = 0; index < NUM_MATRICES; index++) {
59 rows = *dims++;
60 columns = *dims++;
61
62 /* Initialise matrix dimensions */
63 mat_in1.numRows = mat_in2.numRows = mat_out.numRows = rows;
64 mat_in1.numCols = mat_in2.numCols = mat_out.numCols = columns;
65
66 /* Load matrix data */
67 memcpy(mat_in1.pData, in_com1, rows * columns * sizeof(q31_t));
68 memcpy(mat_in2.pData, in_com2, rows * columns * sizeof(q31_t));
69
70 /* Run test function */
71 switch (op) {
72 case OP2_ADD:
73 status = arm_mat_add_q31(&mat_in1, &mat_in2,
74 &mat_out);
75 break;
76 case OP2_SUB:
77 status = arm_mat_sub_q31(&mat_in1, &mat_in2,
78 &mat_out);
79 break;
80 default:
81 zassert_unreachable("invalid operation");
82 }
83
84 /* Validate status */
85 zassert_equal(status, ARM_MATH_SUCCESS,
86 ASSERT_MSG_INCORRECT_COMP_RESULT);
87
88 /* Increment output pointer */
89 mat_out.pData += (rows * columns);
90 }
91
92 /* Validate output */
93 zassert_true(
94 test_snr_error_q31(length, output, ref, SNR_ERROR_THRESH),
95 ASSERT_MSG_SNR_LIMIT_EXCEED);
96
97 zassert_true(
98 test_near_equal_q31(length, output, ref, ABS_ERROR_THRESH_Q31),
99 ASSERT_MSG_ABS_ERROR_LIMIT_EXCEED);
100
101 /* Free buffers */
102 free(tmp1);
103 free(tmp2);
104 free(output);
105 }
106
107 DEFINE_TEST_VARIANT3(matrix_unary_q31,
108 op2, arm_mat_add_q31, OP2_ADD,
109 ref_add, ARRAY_SIZE(ref_add));
110 DEFINE_TEST_VARIANT3(matrix_unary_q31,
111 op2, arm_mat_sub_q31, OP2_SUB,
112 ref_sub, ARRAY_SIZE(ref_sub));
113
test_op1(int op,const q31_t * ref,size_t length,bool transpose)114 static void test_op1(int op, const q31_t *ref, size_t length, bool transpose)
115 {
116 size_t index;
117 uint16_t *dims = (uint16_t *)in_dims;
118 q31_t *tmp1, *output;
119 uint16_t rows, columns;
120 arm_status status;
121
122 arm_matrix_instance_q31 mat_in1;
123 arm_matrix_instance_q31 mat_out;
124
125 /* Allocate buffers */
126 tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(q31_t));
127 zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
128
129 output = malloc(length * sizeof(q31_t));
130 zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
131
132 /* Initialise contexts */
133 mat_in1.pData = tmp1;
134 mat_out.pData = output;
135
136 /* Iterate matrices */
137 for (index = 0; index < NUM_MATRICES; index++) {
138 rows = *dims++;
139 columns = *dims++;
140
141 /* Initialise matrix dimensions */
142 mat_in1.numRows = rows;
143 mat_in1.numCols = columns;
144 mat_out.numRows = transpose ? columns : rows;
145 mat_out.numCols = transpose ? rows : columns;
146
147 /* Load matrix data */
148 memcpy(mat_in1.pData, in_com1, rows * columns * sizeof(q31_t));
149
150 /* Run test function */
151 switch (op) {
152 case OP1_SCALE:
153 status = arm_mat_scale_q31(&mat_in1, 0x40000000, 0,
154 &mat_out);
155 break;
156 case OP1_TRANS:
157 status = arm_mat_trans_q31(&mat_in1, &mat_out);
158 break;
159 default:
160 zassert_unreachable("invalid operation");
161 }
162
163 /* Validate status */
164 zassert_equal(status, ARM_MATH_SUCCESS,
165 ASSERT_MSG_INCORRECT_COMP_RESULT);
166
167 /* Increment output pointer */
168 mat_out.pData += (rows * columns);
169 }
170
171 /* Validate output */
172 zassert_true(
173 test_snr_error_q31(length, output, ref, SNR_ERROR_THRESH),
174 ASSERT_MSG_SNR_LIMIT_EXCEED);
175
176 zassert_true(
177 test_near_equal_q31(length, output, ref, ABS_ERROR_THRESH_Q31),
178 ASSERT_MSG_ABS_ERROR_LIMIT_EXCEED);
179
180 /* Free buffers */
181 free(tmp1);
182 free(output);
183 }
184
185 DEFINE_TEST_VARIANT4(matrix_unary_q31,
186 op1, arm_mat_scale_q31, OP1_SCALE,
187 ref_scale, ARRAY_SIZE(ref_scale), false);
188 DEFINE_TEST_VARIANT4(matrix_unary_q31,
189 op1, arm_mat_trans_q31, OP1_TRANS,
190 ref_trans, ARRAY_SIZE(ref_trans), true);
191
test_op2v(int op,const q31_t * ref,size_t length)192 static void test_op2v(int op, const q31_t *ref, size_t length)
193 {
194 size_t index;
195 const uint16_t *dims = in_dims;
196 q31_t *tmp1, *vec, *output_buf, *output;
197 uint16_t rows, internal;
198
199 arm_matrix_instance_q31 mat_in1;
200
201 /* Allocate buffers */
202 tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(q31_t));
203 zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
204
205 vec = malloc(2 * MAX_MATRIX_DIM * sizeof(q31_t));
206 zassert_not_null(vec, ASSERT_MSG_BUFFER_ALLOC_FAILED);
207
208 output_buf = malloc(length * sizeof(q31_t));
209 zassert_not_null(output_buf, ASSERT_MSG_BUFFER_ALLOC_FAILED);
210
211 /* Initialise contexts */
212 mat_in1.pData = tmp1;
213 output = output_buf;
214
215 /* Iterate matrices */
216 for (index = 0; index < NUM_MATRICES; index++) {
217 rows = *dims++;
218 internal = *dims++;
219
220 /* Initialise matrix dimensions */
221 mat_in1.numRows = rows;
222 mat_in1.numCols = internal;
223
224 /* Load matrix data */
225 memcpy(mat_in1.pData, in_com1,
226 2 * rows * internal * sizeof(q31_t));
227 memcpy(vec, in_vec1, 2 * internal * sizeof(q31_t));
228
229 /* Run test function */
230 switch (op) {
231 case OP2V_VEC_MULT:
232 arm_mat_vec_mult_q31(&mat_in1, vec, output);
233 break;
234 default:
235 zassert_unreachable("invalid operation");
236 }
237
238 /* Increment output pointer */
239 output += rows;
240 }
241
242 /* Validate output */
243 zassert_true(
244 test_snr_error_q31(length, output_buf, ref, SNR_ERROR_THRESH),
245 ASSERT_MSG_SNR_LIMIT_EXCEED);
246
247 zassert_true(
248 test_near_equal_q31(length, output_buf, ref, ABS_ERROR_THRESH_Q31),
249 ASSERT_MSG_ABS_ERROR_LIMIT_EXCEED);
250
251 /* Free buffers */
252 free(tmp1);
253 free(vec);
254 free(output_buf);
255 }
256
257 DEFINE_TEST_VARIANT3(matrix_unary_q31,
258 op2v, arm_mat_vec_mult_q31, OP2V_VEC_MULT,
259 ref_vec_mult, ARRAY_SIZE(ref_vec_mult));
260
test_op1c(int op,const q31_t * ref,size_t length,bool transpose)261 static void test_op1c(int op, const q31_t *ref, size_t length, bool transpose)
262 {
263 size_t index;
264 const uint16_t *dims = in_dims;
265 q31_t *tmp1, *output;
266 uint16_t rows, columns;
267 arm_status status;
268
269 arm_matrix_instance_q31 mat_in1;
270 arm_matrix_instance_q31 mat_out;
271
272 /* Allocate buffers */
273 tmp1 = malloc(2 * MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(q31_t));
274 zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
275
276 output = malloc(2 * length * sizeof(q31_t));
277 zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
278
279 /* Initialise contexts */
280 mat_in1.pData = tmp1;
281 mat_out.pData = output;
282
283 /* Iterate matrices */
284 for (index = 0; index < NUM_MATRICES; index++) {
285 rows = *dims++;
286 columns = *dims++;
287
288 /* Initialise matrix dimensions */
289 mat_in1.numRows = rows;
290 mat_in1.numCols = columns;
291 mat_out.numRows = transpose ? columns : rows;
292 mat_out.numCols = transpose ? rows : columns;
293
294 /* Load matrix data */
295 memcpy(mat_in1.pData,
296 in_cmplx1, 2 * rows * columns * sizeof(q31_t));
297
298 /* Run test function */
299 switch (op) {
300 case OP1C_CMPLX_TRANS:
301 status = arm_mat_cmplx_trans_q31(&mat_in1, &mat_out);
302 break;
303 default:
304 zassert_unreachable("invalid operation");
305 }
306
307 /* Validate status */
308 zassert_equal(status, ARM_MATH_SUCCESS,
309 ASSERT_MSG_INCORRECT_COMP_RESULT);
310
311 /* Increment output pointer */
312 mat_out.pData += 2 * (rows * columns);
313 }
314
315 /* Validate output */
316 zassert_true(
317 test_snr_error_q31(2 * length, output, ref, SNR_ERROR_THRESH),
318 ASSERT_MSG_SNR_LIMIT_EXCEED);
319
320 zassert_true(
321 test_near_equal_q31(2 * length, output, ref, ABS_ERROR_THRESH_Q31),
322 ASSERT_MSG_ABS_ERROR_LIMIT_EXCEED);
323
324 /* Free buffers */
325 free(tmp1);
326 free(output);
327 }
328
329 DEFINE_TEST_VARIANT4(matrix_unary_q31,
330 op1c, arm_mat_cmplx_trans_q31, OP1C_CMPLX_TRANS,
331 ref_cmplx_trans, ARRAY_SIZE(ref_cmplx_trans) / 2, true);
332
333 ZTEST_SUITE(matrix_unary_q31, NULL, NULL, NULL, NULL, NULL);
334