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_f16.h>
12 #include "../../common/test_common.h"
13 
14 #include "unary_f16.pat"
15 
16 #define SNR_ERROR_THRESH	((float32_t)59)
17 #define REL_ERROR_THRESH	(1.1e-3)
18 #define ABS_ERROR_THRESH	(1.1e-3)
19 
20 #define SNR_ERROR_THRESH_INV	((float32_t)45)
21 #define REL_ERROR_THRESH_INV	(3.0e-2)
22 #define ABS_ERROR_THRESH_INV	(3.0e-2)
23 
24 #define SNR_ERROR_THRESH_CHOL	((float32_t)45)
25 #define REL_ERROR_THRESH_CHOL	(3.0e-3)
26 #define ABS_ERROR_THRESH_CHOL	(3.0e-2)
27 
28 #define SNR_ERROR_THRESH_SOLVE	((float32_t)45)
29 #define REL_ERROR_THRESH_SOLVE	(6.0e-3)
30 #define ABS_ERROR_THRESH_SOLVE	(6.0e-2)
31 
32 #define NUM_MATRICES		(ARRAY_SIZE(in_dims) / 2)
33 #define MAX_MATRIX_DIM		(40)
34 
35 #define OP2_ADD			(0)
36 #define OP2_SUB			(1)
37 #define OP1_SCALE		(0)
38 #define OP1_TRANS		(1)
39 #define OP2V_VEC_MULT		(0)
40 #define OP1C_CMPLX_TRANS	(0)
41 
test_op2(int op,const uint16_t * ref,size_t length)42 static void test_op2(int op, const uint16_t *ref, size_t length)
43 {
44 	size_t index;
45 	uint16_t *dims = (uint16_t *)in_dims;
46 	float16_t *tmp1, *tmp2, *output;
47 	uint16_t rows, columns;
48 	arm_status status;
49 
50 	arm_matrix_instance_f16 mat_in1;
51 	arm_matrix_instance_f16 mat_in2;
52 	arm_matrix_instance_f16 mat_out;
53 
54 	/* Allocate buffers */
55 	tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float16_t));
56 	zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
57 
58 	tmp2 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float16_t));
59 	zassert_not_null(tmp2, ASSERT_MSG_BUFFER_ALLOC_FAILED);
60 
61 	output = malloc(length * sizeof(float16_t));
62 	zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
63 
64 	/* Initialise contexts */
65 	mat_in1.pData = tmp1;
66 	mat_in2.pData = tmp2;
67 	mat_out.pData = output;
68 
69 	/* Iterate matrices */
70 	for (index = 0; index < NUM_MATRICES; index++) {
71 		rows = *dims++;
72 		columns = *dims++;
73 
74 		/* Initialise matrix dimensions */
75 		mat_in1.numRows = mat_in2.numRows = mat_out.numRows = rows;
76 		mat_in1.numCols = mat_in2.numCols = mat_out.numCols = columns;
77 
78 		/* Load matrix data */
79 		memcpy(mat_in1.pData, in_com1,
80 		       rows * columns * sizeof(float16_t));
81 
82 		memcpy(mat_in2.pData, in_com2,
83 		       rows * columns * sizeof(float16_t));
84 
85 		/* Run test function */
86 		switch (op) {
87 		case OP2_ADD:
88 			status = arm_mat_add_f16(&mat_in1, &mat_in2,
89 						 &mat_out);
90 			break;
91 		case OP2_SUB:
92 			status = arm_mat_sub_f16(&mat_in1, &mat_in2,
93 						 &mat_out);
94 			break;
95 		default:
96 			zassert_unreachable("invalid operation");
97 		}
98 
99 		/* Validate status */
100 		zassert_equal(status, ARM_MATH_SUCCESS,
101 			      ASSERT_MSG_INCORRECT_COMP_RESULT);
102 
103 		/* Increment output pointer */
104 		mat_out.pData += (rows * columns);
105 	}
106 
107 	/* Validate output */
108 	zassert_true(
109 		test_snr_error_f16(length, output, (float16_t *)ref,
110 			SNR_ERROR_THRESH),
111 		ASSERT_MSG_SNR_LIMIT_EXCEED);
112 
113 	zassert_true(
114 		test_close_error_f16(length, output, (float16_t *)ref,
115 			ABS_ERROR_THRESH, REL_ERROR_THRESH),
116 		ASSERT_MSG_ERROR_LIMIT_EXCEED);
117 
118 	/* Free buffers */
119 	free(tmp1);
120 	free(tmp2);
121 	free(output);
122 }
123 
124 DEFINE_TEST_VARIANT3(matrix_unary_f16,
125 	op2, arm_mat_add_f16, OP2_ADD,
126 	ref_add, ARRAY_SIZE(ref_add));
127 DEFINE_TEST_VARIANT3(matrix_unary_f16,
128 	op2, arm_mat_sub_f16, OP2_SUB,
129 	ref_sub, ARRAY_SIZE(ref_sub));
130 
test_op1(int op,const uint16_t * ref,size_t length,bool transpose)131 static void test_op1(int op, const uint16_t *ref, size_t length,
132 	bool transpose)
133 {
134 	size_t index;
135 	uint16_t *dims = (uint16_t *)in_dims;
136 	float16_t *tmp1, *output;
137 	uint16_t rows, columns;
138 	arm_status status;
139 
140 	arm_matrix_instance_f16 mat_in1;
141 	arm_matrix_instance_f16 mat_out;
142 
143 	/* Allocate buffers */
144 	tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float16_t));
145 	zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
146 
147 	output = malloc(length * sizeof(float16_t));
148 	zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
149 
150 	/* Initialise contexts */
151 	mat_in1.pData = tmp1;
152 	mat_out.pData = output;
153 
154 	/* Iterate matrices */
155 	for (index = 0; index < NUM_MATRICES; index++) {
156 		rows = *dims++;
157 		columns = *dims++;
158 
159 		/* Initialise matrix dimensions */
160 		mat_in1.numRows = rows;
161 		mat_in1.numCols = columns;
162 		mat_out.numRows = transpose ? columns : rows;
163 		mat_out.numCols = transpose ? rows : columns;
164 
165 		/* Load matrix data */
166 		memcpy(mat_in1.pData, in_com1,
167 		       rows * columns * sizeof(float16_t));
168 
169 		/* Run test function */
170 		switch (op) {
171 		case OP1_SCALE:
172 			status = arm_mat_scale_f16(&mat_in1, 0.5f, &mat_out);
173 			break;
174 		case OP1_TRANS:
175 			status = arm_mat_trans_f16(&mat_in1, &mat_out);
176 			break;
177 		default:
178 			zassert_unreachable("invalid operation");
179 		}
180 
181 		/* Validate status */
182 		zassert_equal(status, ARM_MATH_SUCCESS,
183 			      ASSERT_MSG_INCORRECT_COMP_RESULT);
184 
185 		/* Increment output pointer */
186 		mat_out.pData += (rows * columns);
187 	}
188 
189 	/* Validate output */
190 	zassert_true(
191 		test_snr_error_f16(length, output, (float16_t *)ref,
192 			SNR_ERROR_THRESH),
193 		ASSERT_MSG_SNR_LIMIT_EXCEED);
194 
195 	zassert_true(
196 		test_close_error_f16(length, output, (float16_t *)ref,
197 			ABS_ERROR_THRESH, REL_ERROR_THRESH),
198 		ASSERT_MSG_ERROR_LIMIT_EXCEED);
199 
200 	/* Free buffers */
201 	free(tmp1);
202 	free(output);
203 }
204 
205 DEFINE_TEST_VARIANT4(matrix_unary_f16,
206 	op1, arm_mat_scale_f16, OP1_SCALE,
207 	ref_scale, ARRAY_SIZE(ref_scale), false);
208 DEFINE_TEST_VARIANT4(matrix_unary_f16,
209 	op1, arm_mat_trans_f16, OP1_TRANS,
210 	ref_trans, ARRAY_SIZE(ref_trans), true);
211 
ZTEST(matrix_unary_f16,test_arm_mat_inverse_f16)212 ZTEST(matrix_unary_f16, test_arm_mat_inverse_f16)
213 {
214 	size_t index;
215 	size_t length = ARRAY_SIZE(ref_inv);
216 	uint16_t *dims = (uint16_t *)in_inv_dims;
217 	float16_t *input, *tmp1, *output;
218 	arm_status status;
219 	uint16_t rows, columns;
220 
221 	arm_matrix_instance_f16 mat_in1;
222 	arm_matrix_instance_f16 mat_out;
223 
224 	/* Allocate buffers */
225 	tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float16_t));
226 	zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
227 
228 	output = malloc(length * sizeof(float16_t));
229 	zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
230 
231 	/* Initialise contexts */
232 	input = (float16_t *)in_inv;
233 	mat_in1.pData = tmp1;
234 	mat_out.pData = output;
235 
236 	/* Iterate matrices */
237 	for (index = 0; index < ARRAY_SIZE(in_inv_dims); index++) {
238 		rows = columns = *dims++;
239 
240 		/* Initialise matrix dimensions */
241 		mat_in1.numRows = mat_out.numRows = rows;
242 		mat_in1.numCols = mat_out.numCols = columns;
243 
244 		/* Load matrix data */
245 		memcpy(mat_in1.pData,
246 		       input, rows * columns * sizeof(float16_t));
247 
248 		/* Run test function */
249 		status = arm_mat_inverse_f16(&mat_in1, &mat_out);
250 
251 		zassert_equal(status, ARM_MATH_SUCCESS,
252 			ASSERT_MSG_INCORRECT_COMP_RESULT);
253 
254 		/* Increment pointers */
255 		input += (rows * columns);
256 		mat_out.pData += (rows * columns);
257 	}
258 
259 	/* Validate output */
260 	zassert_true(
261 		test_snr_error_f16(length, output, (float16_t *)ref_inv,
262 			SNR_ERROR_THRESH_INV),
263 		ASSERT_MSG_SNR_LIMIT_EXCEED);
264 
265 	zassert_true(
266 		test_close_error_f16(length, output, (float16_t *)ref_inv,
267 			ABS_ERROR_THRESH_INV, REL_ERROR_THRESH_INV),
268 		ASSERT_MSG_ERROR_LIMIT_EXCEED);
269 
270 	/* Free buffers */
271 	free(tmp1);
272 	free(output);
273 }
274 
test_op2v(int op,const uint16_t * ref,size_t length)275 static void test_op2v(int op, const uint16_t *ref, size_t length)
276 {
277 	size_t index;
278 	const uint16_t *dims = in_dims;
279 	float16_t *tmp1, *vec, *output_buf, *output;
280 	uint16_t rows, internal;
281 
282 	arm_matrix_instance_f16 mat_in1;
283 
284 	/* Allocate buffers */
285 	tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float16_t));
286 	zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
287 
288 	vec = malloc(2 * MAX_MATRIX_DIM * sizeof(float16_t));
289 	zassert_not_null(vec, ASSERT_MSG_BUFFER_ALLOC_FAILED);
290 
291 	output_buf = malloc(length * sizeof(float16_t));
292 	zassert_not_null(output_buf, ASSERT_MSG_BUFFER_ALLOC_FAILED);
293 
294 	/* Initialise contexts */
295 	mat_in1.pData = tmp1;
296 	output = output_buf;
297 
298 	/* Iterate matrices */
299 	for (index = 0; index < NUM_MATRICES; index++) {
300 		rows = *dims++;
301 		internal = *dims++;
302 
303 		/* Initialise matrix dimensions */
304 		mat_in1.numRows = rows;
305 		mat_in1.numCols = internal;
306 
307 		/* Load matrix data */
308 		memcpy(mat_in1.pData, in_com1,
309 		       2 * rows * internal * sizeof(float16_t));
310 		memcpy(vec, in_vec1, 2 * internal * sizeof(float16_t));
311 
312 		/* Run test function */
313 		switch (op) {
314 		case OP2V_VEC_MULT:
315 			arm_mat_vec_mult_f16(&mat_in1, vec, output);
316 			break;
317 		default:
318 			zassert_unreachable("invalid operation");
319 		}
320 
321 		/* Increment output pointer */
322 		output += rows;
323 	}
324 
325 	/* Validate output */
326 	zassert_true(
327 		test_snr_error_f16(length, output_buf, (float16_t *)ref,
328 				   SNR_ERROR_THRESH),
329 		ASSERT_MSG_SNR_LIMIT_EXCEED);
330 
331 	zassert_true(
332 		test_close_error_f16(length, output_buf, (float16_t *)ref,
333 				     ABS_ERROR_THRESH, REL_ERROR_THRESH),
334 		ASSERT_MSG_ERROR_LIMIT_EXCEED);
335 
336 	/* Free buffers */
337 	free(tmp1);
338 	free(vec);
339 	free(output_buf);
340 }
341 
342 DEFINE_TEST_VARIANT3(matrix_unary_f16,
343 	op2v, arm_mat_vec_mult_f16, OP2V_VEC_MULT,
344 	ref_vec_mult, ARRAY_SIZE(ref_vec_mult));
345 
test_op1c(int op,const uint16_t * ref,size_t length,bool transpose)346 static void test_op1c(int op, const uint16_t *ref, size_t length, bool transpose)
347 {
348 	size_t index;
349 	const uint16_t *dims = in_dims;
350 	float16_t *tmp1, *output;
351 	uint16_t rows, columns;
352 	arm_status status;
353 
354 	arm_matrix_instance_f16 mat_in1;
355 	arm_matrix_instance_f16 mat_out;
356 
357 	/* Allocate buffers */
358 	tmp1 = malloc(2 * MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float16_t));
359 	zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
360 
361 	output = malloc(2 * length * sizeof(float16_t));
362 	zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
363 
364 	/* Initialise contexts */
365 	mat_in1.pData = tmp1;
366 	mat_out.pData = output;
367 
368 	/* Iterate matrices */
369 	for (index = 0; index < NUM_MATRICES; index++) {
370 		rows = *dims++;
371 		columns = *dims++;
372 
373 		/* Initialise matrix dimensions */
374 		mat_in1.numRows = rows;
375 		mat_in1.numCols = columns;
376 		mat_out.numRows = transpose ? columns : rows;
377 		mat_out.numCols = transpose ? rows : columns;
378 
379 		/* Load matrix data */
380 		memcpy(mat_in1.pData,
381 		       in_cmplx1, 2 * rows * columns * sizeof(float16_t));
382 
383 		/* Run test function */
384 		switch (op) {
385 		case OP1C_CMPLX_TRANS:
386 			status = arm_mat_cmplx_trans_f16(&mat_in1, &mat_out);
387 			break;
388 		default:
389 			zassert_unreachable("invalid operation");
390 		}
391 
392 		/* Validate status */
393 		zassert_equal(status, ARM_MATH_SUCCESS,
394 			      ASSERT_MSG_INCORRECT_COMP_RESULT);
395 
396 		/* Increment output pointer */
397 		mat_out.pData += 2 * (rows * columns);
398 	}
399 
400 	/* Validate output */
401 	zassert_true(
402 		test_snr_error_f16(2 * length, output, (float16_t *)ref,
403 				   SNR_ERROR_THRESH),
404 		ASSERT_MSG_SNR_LIMIT_EXCEED);
405 
406 	zassert_true(
407 		test_close_error_f16(2 * length, output, (float16_t *)ref,
408 				     ABS_ERROR_THRESH, REL_ERROR_THRESH),
409 		ASSERT_MSG_ERROR_LIMIT_EXCEED);
410 
411 	/* Free buffers */
412 	free(tmp1);
413 	free(output);
414 }
415 
416 DEFINE_TEST_VARIANT4(matrix_unary_f16,
417 	op1c, arm_mat_cmplx_trans_f16, OP1C_CMPLX_TRANS,
418 	ref_cmplx_trans, ARRAY_SIZE(ref_cmplx_trans) / 2, true);
419 
ZTEST(matrix_unary_f16,test_arm_mat_cholesky_f16)420 ZTEST(matrix_unary_f16, test_arm_mat_cholesky_f16)
421 {
422 	size_t index;
423 	size_t length = ARRAY_SIZE(ref_cholesky_dpo);
424 	const uint16_t *dims = in_cholesky_dpo_dims;
425 	float16_t *input, *tmp1, *output;
426 	uint16_t rows, columns;
427 	arm_status status;
428 
429 	arm_matrix_instance_f16 mat_in1;
430 	arm_matrix_instance_f16 mat_out;
431 
432 	/* Allocate buffers */
433 	tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float16_t));
434 	zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
435 
436 	output = calloc(length, sizeof(float16_t));
437 	zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
438 
439 	/* Initialise contexts */
440 	input = (float16_t *)in_cholesky_dpo;
441 	mat_in1.pData = tmp1;
442 	mat_out.pData = output;
443 
444 	/* Iterate matrices */
445 	for (index = 0; index < ARRAY_SIZE(in_cholesky_dpo_dims); index++) {
446 		rows = columns = *dims++;
447 
448 		/* Initialise matrix dimensions */
449 		mat_in1.numRows = mat_out.numRows = rows;
450 		mat_in1.numCols = mat_out.numCols = columns;
451 
452 		/* Load matrix data */
453 		memcpy(mat_in1.pData,
454 		       input, rows * columns * sizeof(float16_t));
455 
456 		/* Run test function */
457 		status = arm_mat_cholesky_f16(&mat_in1, &mat_out);
458 
459 		zassert_equal(status, ARM_MATH_SUCCESS,
460 			ASSERT_MSG_INCORRECT_COMP_RESULT);
461 
462 		/* Increment pointers */
463 		input += (rows * columns);
464 		mat_out.pData += (rows * columns);
465 	}
466 
467 	/* Validate output */
468 	zassert_true(
469 		test_snr_error_f16(length, output, (float16_t *)ref_cholesky_dpo,
470 			SNR_ERROR_THRESH_CHOL),
471 		ASSERT_MSG_SNR_LIMIT_EXCEED);
472 
473 	zassert_true(
474 		test_close_error_f16(length, output, (float16_t *)ref_cholesky_dpo,
475 			ABS_ERROR_THRESH_CHOL, REL_ERROR_THRESH_CHOL),
476 		ASSERT_MSG_ERROR_LIMIT_EXCEED);
477 
478 	/* Free buffers */
479 	free(tmp1);
480 	free(output);
481 }
482 
ZTEST(matrix_unary_f16,test_arm_mat_solve_upper_triangular_f16)483 ZTEST(matrix_unary_f16, test_arm_mat_solve_upper_triangular_f16)
484 {
485 	size_t index;
486 	size_t length = ARRAY_SIZE(ref_uptriangular_dpo);
487 	const uint16_t *dims = in_cholesky_dpo_dims;
488 	float16_t *input1, *input2, *tmp1, *tmp2, *output;
489 	uint16_t rows, columns;
490 	arm_status status;
491 
492 	arm_matrix_instance_f16 mat_in1;
493 	arm_matrix_instance_f16 mat_in2;
494 	arm_matrix_instance_f16 mat_out;
495 
496 	/* Allocate buffers */
497 	tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float16_t));
498 	zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
499 
500 	tmp2 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float16_t));
501 	zassert_not_null(tmp2, ASSERT_MSG_BUFFER_ALLOC_FAILED);
502 
503 	output = calloc(length, sizeof(float16_t));
504 	zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
505 
506 	/* Initialise contexts */
507 	input1 = (float16_t *)in_uptriangular_dpo;
508 	input2 = (float16_t *)in_rnda_dpo;
509 	mat_in1.pData = tmp1;
510 	mat_in2.pData = tmp2;
511 	mat_out.pData = output;
512 
513 	/* Iterate matrices */
514 	for (index = 0; index < ARRAY_SIZE(in_cholesky_dpo_dims); index++) {
515 		rows = columns = *dims++;
516 
517 		/* Initialise matrix dimensions */
518 		mat_in1.numRows = mat_in2.numRows = mat_out.numRows = rows;
519 		mat_in1.numCols = mat_in2.numCols = mat_out.numCols = columns;
520 
521 		/* Load matrix data */
522 		memcpy(mat_in1.pData, input1,
523 		       rows * columns * sizeof(float16_t));
524 
525 		memcpy(mat_in2.pData, input2,
526 		       rows * columns * sizeof(float16_t));
527 
528 		/* Run test function */
529 		status = arm_mat_solve_upper_triangular_f16(&mat_in1, &mat_in2,
530 							    &mat_out);
531 
532 		zassert_equal(status, ARM_MATH_SUCCESS,
533 			      ASSERT_MSG_INCORRECT_COMP_RESULT);
534 
535 		/* Increment output pointer */
536 		input1 += (rows * columns);
537 		input2 += (rows * columns);
538 		mat_out.pData += (rows * columns);
539 	}
540 
541 	/* Validate output */
542 	zassert_true(
543 		test_snr_error_f16(length, output,
544 			(float16_t *)ref_uptriangular_dpo,
545 			SNR_ERROR_THRESH_SOLVE),
546 		ASSERT_MSG_SNR_LIMIT_EXCEED);
547 
548 	zassert_true(
549 		test_close_error_f16(length, output,
550 			(float16_t *)ref_uptriangular_dpo,
551 			ABS_ERROR_THRESH_SOLVE, REL_ERROR_THRESH_SOLVE),
552 		ASSERT_MSG_ERROR_LIMIT_EXCEED);
553 
554 	/* Free buffers */
555 	free(tmp1);
556 	free(tmp2);
557 	free(output);
558 }
559 
ZTEST(matrix_unary_f16,test_arm_mat_solve_lower_triangular_f16)560 ZTEST(matrix_unary_f16, test_arm_mat_solve_lower_triangular_f16)
561 {
562 	size_t index;
563 	size_t length = ARRAY_SIZE(ref_lotriangular_dpo);
564 	const uint16_t *dims = in_cholesky_dpo_dims;
565 	float16_t *input1, *input2, *tmp1, *tmp2, *output;
566 	uint16_t rows, columns;
567 	arm_status status;
568 
569 	arm_matrix_instance_f16 mat_in1;
570 	arm_matrix_instance_f16 mat_in2;
571 	arm_matrix_instance_f16 mat_out;
572 
573 	/* Allocate buffers */
574 	tmp1 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float16_t));
575 	zassert_not_null(tmp1, ASSERT_MSG_BUFFER_ALLOC_FAILED);
576 
577 	tmp2 = malloc(MAX_MATRIX_DIM * MAX_MATRIX_DIM * sizeof(float16_t));
578 	zassert_not_null(tmp2, ASSERT_MSG_BUFFER_ALLOC_FAILED);
579 
580 	output = calloc(length, sizeof(float16_t));
581 	zassert_not_null(output, ASSERT_MSG_BUFFER_ALLOC_FAILED);
582 
583 	/* Initialise contexts */
584 	input1 = (float16_t *)in_lotriangular_dpo;
585 	input2 = (float16_t *)in_rnda_dpo;
586 	mat_in1.pData = tmp1;
587 	mat_in2.pData = tmp2;
588 	mat_out.pData = output;
589 
590 	/* Iterate matrices */
591 	for (index = 0; index < ARRAY_SIZE(in_cholesky_dpo_dims); index++) {
592 		rows = columns = *dims++;
593 
594 		/* Initialise matrix dimensions */
595 		mat_in1.numRows = mat_in2.numRows = mat_out.numRows = rows;
596 		mat_in1.numCols = mat_in2.numCols = mat_out.numCols = columns;
597 
598 		/* Load matrix data */
599 		memcpy(mat_in1.pData, input1,
600 		       rows * columns * sizeof(float16_t));
601 
602 		memcpy(mat_in2.pData, input2,
603 		       rows * columns * sizeof(float16_t));
604 
605 		/* Run test function */
606 		status = arm_mat_solve_lower_triangular_f16(&mat_in1, &mat_in2,
607 							    &mat_out);
608 
609 		zassert_equal(status, ARM_MATH_SUCCESS,
610 			      ASSERT_MSG_INCORRECT_COMP_RESULT);
611 
612 		/* Increment output pointer */
613 		input1 += (rows * columns);
614 		input2 += (rows * columns);
615 		mat_out.pData += (rows * columns);
616 	}
617 
618 	/* Validate output */
619 	zassert_true(
620 		test_snr_error_f16(length, output,
621 			(float16_t *)ref_lotriangular_dpo,
622 			SNR_ERROR_THRESH_SOLVE),
623 		ASSERT_MSG_SNR_LIMIT_EXCEED);
624 
625 	zassert_true(
626 		test_close_error_f16(length, output,
627 			(float16_t *)ref_lotriangular_dpo,
628 			ABS_ERROR_THRESH_SOLVE, REL_ERROR_THRESH_SOLVE),
629 		ASSERT_MSG_ERROR_LIMIT_EXCEED);
630 
631 	/* Free buffers */
632 	free(tmp1);
633 	free(tmp2);
634 	free(output);
635 }
636 
637 ZTEST_SUITE(matrix_unary_f16, NULL, NULL, NULL, NULL, NULL);
638