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_f64.pat"
15
16 #define SNR_ERROR_THRESH ((float64_t)120)
17 #define REL_ERROR_THRESH (1.0e-6)
18 #define ABS_ERROR_THRESH (1.0e-5)
19
20 #define SNR_ERROR_THRESH_CHOL ((float64_t)270)
21 #define REL_ERROR_THRESH_CHOL (1.0e-9)
22 #define ABS_ERROR_THRESH_CHOL (1.0e-9)
23
24 #define NUM_MATRICES (ARRAY_SIZE(in_dims) / 2)
25 #define MAX_MATRIX_DIM (40)
26
27 #define OP2_SUB (1)
28 #define OP1_TRANS (1)
29
test_op2(int op,const uint64_t * ref,size_t length)30 static void test_op2(int op, const uint64_t *ref, size_t length)
31 {
32 size_t index;
33 uint16_t *dims = (uint16_t *)in_dims;
34 float64_t *tmp1, *tmp2, *output;
35 uint16_t rows, columns;
36 arm_status status;
37
38 arm_matrix_instance_f64 mat_in1;
39 arm_matrix_instance_f64 mat_in2;
40 arm_matrix_instance_f64 mat_out;
41
42 /* Allocate buffers */
43 tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float64_t));
44 zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
45
46 tmp2 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float64_t));
47 zassert_not_null(tmp2, ASSERT_MSG_BUFFER_ALLOC_FAILED);
48
49 output = malloc(length * sizeof(float64_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,
68 rows * columns * sizeof(float64_t));
69
70 memcpy(mat_in2.pData, in_com2,
71 rows * columns * sizeof(float64_t));
72
73 /* Run test function */
74 switch (op) {
75 case OP2_SUB:
76 status = arm_mat_sub_f64(&mat_in1, &mat_in2,
77 &mat_out);
78 break;
79 default:
80 zassert_unreachable("invalid operation");
81 }
82
83 /* Validate status */
84 zassert_equal(status, ARM_MATH_SUCCESS,
85 ASSERT_MSG_INCORRECT_COMP_RESULT);
86
87 /* Increment output pointer */
88 mat_out.pData += (rows * columns);
89 }
90
91 /* Validate output */
92 zassert_true(
93 test_snr_error_f64(length, output, (float64_t *)ref,
94 SNR_ERROR_THRESH),
95 ASSERT_MSG_SNR_LIMIT_EXCEED);
96
97 zassert_true(
98 test_close_error_f64(length, output, (float64_t *)ref,
99 ABS_ERROR_THRESH, REL_ERROR_THRESH),
100 ASSERT_MSG_ERROR_LIMIT_EXCEED);
101
102 /* Free buffers */
103 free(tmp1);
104 free(tmp2);
105 free(output);
106 }
107
108 DEFINE_TEST_VARIANT3(matrix_unary_f64,
109 op2, arm_mat_sub_f64, OP2_SUB,
110 ref_sub, ARRAY_SIZE(ref_sub));
111
test_op1(int op,const uint64_t * ref,size_t length,bool transpose)112 static void test_op1(int op, const uint64_t *ref, size_t length,
113 bool transpose)
114 {
115 size_t index;
116 uint16_t *dims = (uint16_t *)in_dims;
117 float64_t *tmp1, *output;
118 uint16_t rows, columns;
119 arm_status status;
120
121 arm_matrix_instance_f64 mat_in1;
122 arm_matrix_instance_f64 mat_out;
123
124 /* Allocate buffers */
125 tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float64_t));
126 zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
127
128 output = malloc(length * sizeof(float64_t));
129 zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
130
131 /* Initialise contexts */
132 mat_in1.pData = tmp1;
133 mat_out.pData = output;
134
135 /* Iterate matrices */
136 for (index = 0; index < NUM_MATRICES; index++) {
137 rows = *dims++;
138 columns = *dims++;
139
140 /* Initialise matrix dimensions */
141 mat_in1.numRows = rows;
142 mat_in1.numCols = columns;
143 mat_out.numRows = transpose ? columns : rows;
144 mat_out.numCols = transpose ? rows : columns;
145
146 /* Load matrix data */
147 memcpy(mat_in1.pData, in_com1,
148 rows * columns * sizeof(float64_t));
149
150 /* Run test function */
151 switch (op) {
152 case OP1_TRANS:
153 status = arm_mat_trans_f64(&mat_in1, &mat_out);
154 break;
155 default:
156 zassert_unreachable("invalid operation");
157 }
158
159 /* Validate status */
160 zassert_equal(status, ARM_MATH_SUCCESS,
161 ASSERT_MSG_INCORRECT_COMP_RESULT);
162
163 /* Increment output pointer */
164 mat_out.pData += (rows * columns);
165 }
166
167 /* Validate output */
168 zassert_true(
169 test_snr_error_f64(length, output, (float64_t *)ref,
170 SNR_ERROR_THRESH),
171 ASSERT_MSG_SNR_LIMIT_EXCEED);
172
173 zassert_true(
174 test_close_error_f64(length, output, (float64_t *)ref,
175 ABS_ERROR_THRESH, REL_ERROR_THRESH),
176 ASSERT_MSG_ERROR_LIMIT_EXCEED);
177
178 /* Free buffers */
179 free(tmp1);
180 free(output);
181 }
182
183 DEFINE_TEST_VARIANT4(matrix_unary_f64,
184 op1, arm_mat_trans_f64, OP1_TRANS,
185 ref_trans, ARRAY_SIZE(ref_trans), true);
186
ZTEST(matrix_unary_f64,test_arm_mat_inverse_f64)187 ZTEST(matrix_unary_f64, test_arm_mat_inverse_f64)
188 {
189 size_t index;
190 size_t length = ARRAY_SIZE(ref_inv);
191 uint16_t *dims = (uint16_t *)in_inv_dims;
192 float64_t *input, *tmp1, *output;
193 arm_status status;
194 uint16_t rows, columns;
195
196 arm_matrix_instance_f64 mat_in1;
197 arm_matrix_instance_f64 mat_out;
198
199 /* Allocate buffers */
200 tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float64_t));
201 zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
202
203 output = malloc(length * sizeof(float64_t));
204 zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
205
206 /* Initialise contexts */
207 input = (float64_t *)in_inv;
208 mat_in1.pData = tmp1;
209 mat_out.pData = output;
210
211 /* Iterate matrices */
212 for (index = 0; index < ARRAY_SIZE(in_inv_dims); index++) {
213 rows = columns = *dims++;
214
215 /* Initialise matrix dimensions */
216 mat_in1.numRows = mat_out.numRows = rows;
217 mat_in1.numCols = mat_out.numCols = columns;
218
219 /* Load matrix data */
220 memcpy(mat_in1.pData, input,
221 rows * columns * sizeof(float64_t));
222
223 /* Run test function */
224 status = arm_mat_inverse_f64(&mat_in1, &mat_out);
225
226 zassert_equal(status, ARM_MATH_SUCCESS,
227 ASSERT_MSG_INCORRECT_COMP_RESULT);
228
229 /* Increment pointers */
230 input += (rows * columns);
231 mat_out.pData += (rows * columns);
232 }
233
234 /* Validate output */
235 zassert_true(
236 test_snr_error_f64(length, output, (float64_t *)ref_inv,
237 SNR_ERROR_THRESH),
238 ASSERT_MSG_SNR_LIMIT_EXCEED);
239
240 zassert_true(
241 test_close_error_f64(length, output, (float64_t *)ref_inv,
242 ABS_ERROR_THRESH, REL_ERROR_THRESH),
243 ASSERT_MSG_ERROR_LIMIT_EXCEED);
244
245 /* Free buffers */
246 free(tmp1);
247 free(output);
248 }
249
ZTEST(matrix_unary_f64,test_arm_mat_cholesky_f64)250 ZTEST(matrix_unary_f64, test_arm_mat_cholesky_f64)
251 {
252 size_t index;
253 size_t length = ARRAY_SIZE(ref_cholesky_dpo);
254 const uint16_t *dims = in_cholesky_dpo_dims;
255 float64_t *input, *tmp1, *output;
256 uint16_t rows, columns;
257 arm_status status;
258
259 arm_matrix_instance_f64 mat_in1;
260 arm_matrix_instance_f64 mat_out;
261
262 /* Allocate buffers */
263 tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float64_t));
264 zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
265
266 output = calloc(length, sizeof(float64_t));
267 zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
268
269 /* Initialise contexts */
270 input = (float64_t *)in_cholesky_dpo;
271 mat_in1.pData = tmp1;
272 mat_out.pData = output;
273
274 /* Iterate matrices */
275 for (index = 0; index < ARRAY_SIZE(in_cholesky_dpo_dims); index++) {
276 rows = columns = *dims++;
277
278 /* Initialise matrix dimensions */
279 mat_in1.numRows = mat_out.numRows = rows;
280 mat_in1.numCols = mat_out.numCols = columns;
281
282 /* Load matrix data */
283 memcpy(mat_in1.pData,
284 input, rows * columns * sizeof(float64_t));
285
286 /* Run test function */
287 status = arm_mat_cholesky_f64(&mat_in1, &mat_out);
288
289 zassert_equal(status, ARM_MATH_SUCCESS,
290 ASSERT_MSG_INCORRECT_COMP_RESULT);
291
292 /* Increment pointers */
293 input += (rows * columns);
294 mat_out.pData += (rows * columns);
295 }
296
297 /* Validate output */
298 zassert_true(
299 test_snr_error_f64(length, output, (float64_t *)ref_cholesky_dpo,
300 SNR_ERROR_THRESH_CHOL),
301 ASSERT_MSG_SNR_LIMIT_EXCEED);
302
303 zassert_true(
304 test_close_error_f64(length, output, (float64_t *)ref_cholesky_dpo,
305 ABS_ERROR_THRESH_CHOL, REL_ERROR_THRESH_CHOL),
306 ASSERT_MSG_ERROR_LIMIT_EXCEED);
307
308 /* Free buffers */
309 free(tmp1);
310 free(output);
311 }
312
ZTEST(matrix_unary_f64,test_arm_mat_solve_upper_triangular_f64)313 ZTEST(matrix_unary_f64, test_arm_mat_solve_upper_triangular_f64)
314 {
315 size_t index;
316 size_t length = ARRAY_SIZE(ref_uptriangular_dpo);
317 const uint16_t *dims = in_cholesky_dpo_dims;
318 float64_t *input1, *input2, *tmp1, *tmp2, *output;
319 uint16_t rows, columns;
320 arm_status status;
321
322 arm_matrix_instance_f64 mat_in1;
323 arm_matrix_instance_f64 mat_in2;
324 arm_matrix_instance_f64 mat_out;
325
326 /* Allocate buffers */
327 tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float64_t));
328 zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
329
330 tmp2 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float64_t));
331 zassert_not_null(tmp2, ASSERT_MSG_BUFFER_ALLOC_FAILED);
332
333 output = calloc(length, sizeof(float64_t));
334 zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
335
336 /* Initialise contexts */
337 input1 = (float64_t *)in_uptriangular_dpo;
338 input2 = (float64_t *)in_rnda_dpo;
339 mat_in1.pData = tmp1;
340 mat_in2.pData = tmp2;
341 mat_out.pData = output;
342
343 /* Iterate matrices */
344 for (index = 0; index < ARRAY_SIZE(in_cholesky_dpo_dims); index++) {
345 rows = columns = *dims++;
346
347 /* Initialise matrix dimensions */
348 mat_in1.numRows = mat_in2.numRows = mat_out.numRows = rows;
349 mat_in1.numCols = mat_in2.numCols = mat_out.numCols = columns;
350
351 /* Load matrix data */
352 memcpy(mat_in1.pData, input1,
353 rows * columns * sizeof(float64_t));
354
355 memcpy(mat_in2.pData, input2,
356 rows * columns * sizeof(float64_t));
357
358 /* Run test function */
359 status = arm_mat_solve_upper_triangular_f64(&mat_in1, &mat_in2,
360 &mat_out);
361
362 zassert_equal(status, ARM_MATH_SUCCESS,
363 ASSERT_MSG_INCORRECT_COMP_RESULT);
364
365 /* Increment output pointer */
366 input1 += (rows * columns);
367 input2 += (rows * columns);
368 mat_out.pData += (rows * columns);
369 }
370
371 /* Validate output */
372 zassert_true(
373 test_snr_error_f64(length, output,
374 (float64_t *)ref_uptriangular_dpo,
375 SNR_ERROR_THRESH),
376 ASSERT_MSG_SNR_LIMIT_EXCEED);
377
378 zassert_true(
379 test_close_error_f64(length, output,
380 (float64_t *)ref_uptriangular_dpo,
381 ABS_ERROR_THRESH, REL_ERROR_THRESH),
382 ASSERT_MSG_ERROR_LIMIT_EXCEED);
383
384 /* Free buffers */
385 free(tmp1);
386 free(tmp2);
387 free(output);
388 }
389
ZTEST(matrix_unary_f64,test_arm_mat_solve_lower_triangular_f64)390 ZTEST(matrix_unary_f64, test_arm_mat_solve_lower_triangular_f64)
391 {
392 size_t index;
393 size_t length = ARRAY_SIZE(ref_lotriangular_dpo);
394 const uint16_t *dims = in_cholesky_dpo_dims;
395 float64_t *input1, *input2, *tmp1, *tmp2, *output;
396 uint16_t rows, columns;
397 arm_status status;
398
399 arm_matrix_instance_f64 mat_in1;
400 arm_matrix_instance_f64 mat_in2;
401 arm_matrix_instance_f64 mat_out;
402
403 /* Allocate buffers */
404 tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float64_t));
405 zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
406
407 tmp2 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float64_t));
408 zassert_not_null(tmp2, ASSERT_MSG_BUFFER_ALLOC_FAILED);
409
410 output = calloc(length, sizeof(float64_t));
411 zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
412
413 /* Initialise contexts */
414 input1 = (float64_t *)in_lotriangular_dpo;
415 input2 = (float64_t *)in_rnda_dpo;
416 mat_in1.pData = tmp1;
417 mat_in2.pData = tmp2;
418 mat_out.pData = output;
419
420 /* Iterate matrices */
421 for (index = 0; index < ARRAY_SIZE(in_cholesky_dpo_dims); index++) {
422 rows = columns = *dims++;
423
424 /* Initialise matrix dimensions */
425 mat_in1.numRows = mat_in2.numRows = mat_out.numRows = rows;
426 mat_in1.numCols = mat_in2.numCols = mat_out.numCols = columns;
427
428 /* Load matrix data */
429 memcpy(mat_in1.pData, input1,
430 rows * columns * sizeof(float64_t));
431
432 memcpy(mat_in2.pData, input2,
433 rows * columns * sizeof(float64_t));
434
435 /* Run test function */
436 status = arm_mat_solve_lower_triangular_f64(&mat_in1, &mat_in2,
437 &mat_out);
438
439 zassert_equal(status, ARM_MATH_SUCCESS,
440 ASSERT_MSG_INCORRECT_COMP_RESULT);
441
442 /* Increment output pointer */
443 input1 += (rows * columns);
444 input2 += (rows * columns);
445 mat_out.pData += (rows * columns);
446 }
447
448 /* Validate output */
449 zassert_true(
450 test_snr_error_f64(length, output,
451 (float64_t *)ref_lotriangular_dpo,
452 SNR_ERROR_THRESH),
453 ASSERT_MSG_SNR_LIMIT_EXCEED);
454
455 zassert_true(
456 test_close_error_f64(length, output,
457 (float64_t *)ref_lotriangular_dpo,
458 ABS_ERROR_THRESH, REL_ERROR_THRESH),
459 ASSERT_MSG_ERROR_LIMIT_EXCEED);
460
461 /* Free buffers */
462 free(tmp1);
463 free(tmp2);
464 free(output);
465 }
466
467 /*
468 * NOTE: arm_mat_ldlt_f64 tests are not implemented for now because they
469 * require on-device test pattern generation which defeats the purpose
470 * of on-device testing. Add these tests when the upstream testsuite is
471 * updated to use pre-generated test patterns.
472 */
473
474 ZTEST_SUITE(matrix_unary_f64, NULL, NULL, NULL, NULL, NULL);
475