1 /*
2  * Copyright (c) 2019-2020 Kevin Townsend (KTOWN)
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdio.h>
8 #include <string.h>
9 #include <errno.h>
10 #include "zsl/matrices.h"
11 #include "zsl/vectors.h"
12 
13 #define EPSILON 1e-4
14 
svd_test()15 int svd_test()
16 {
17 	size_t q = 18;
18 	size_t p = 3;
19 
20 	zsl_real_t vi[3 * 18] = { 3.2, 5.0, -4.2, -3.1, 5.4, -2.2, 7.7, 8.7,
21 				  9.9, 8.9, 0.6, 5.4, 3.7, -3.3, 7.2, -5.4,
22 				  -0.6, 8.4, 2.4, 5.1, -5.7, 6.9, -2.1, 0.4,
23 				  6.4, -9.1, -4.4, 0.1, 7.4, 0.0, 6.1, -2.3,
24 				  5.5, 6.1, -8.4, -6.6, 7.1, 2.3, 4.1, -0.8,
25 				  -4.7, 9.9, -3.1, 1.2, 5.2, 6.4, -6.3, 5.2,
26 				  8.8, 7.3, 4.2, -4.7, 0.0, -0.4 };
27 
28 	/* Define the 18x3 matrix, assigning the values from 'vi'. */
29 	ZSL_MATRIX_DEF(mep, q, p);
30 	zsl_mtx_from_arr(&mep, vi);
31 
32 	/* Define the three SVD output matrices. */
33 	ZSL_MATRIX_DEF(u, mep.sz_rows, mep.sz_rows);
34 	ZSL_MATRIX_DEF(e, mep.sz_rows, mep.sz_cols);
35 	ZSL_MATRIX_DEF(v, mep.sz_cols, mep.sz_cols);
36 
37 	/* Define placeholder matrices for SVD and related operations. */
38 	ZSL_MATRIX_DEF(ue, mep.sz_rows, mep.sz_cols);
39 	ZSL_MATRIX_DEF(vt, mep.sz_cols, mep.sz_cols);
40 	ZSL_MATRIX_DEF(uevt, mep.sz_rows, mep.sz_cols);
41 
42 	/* Display the input matrix for reference. */
43 	printf("INPUT (18x3 MATRIX)\n");
44 	printf("-------------------\n");
45 	zsl_mtx_print(&mep);
46 	printf("\n");
47 
48 	/* Calculate and display the SVD using 150 iterations. */
49 	zsl_mtx_svd(&mep, &u, &e, &v, 150);
50 	printf("SVD OUTPUT\n");
51 	printf("----------\n");
52 	printf("U matrix (18x18):\n");
53 	zsl_mtx_print(&u);
54 	printf("\n");
55 	printf("Sigma matrix (18x3):\n");
56 	zsl_mtx_print(&e);
57 	printf("\n");
58 	printf("V matrix: (3x3)\n");
59 	zsl_mtx_print(&v);
60 	printf("\n");
61 
62 	/* Multiply u, sigma and v(transposed) from the SVD calculations,
63 	 * which shoud return the original matrix. */
64 	printf("VERIFICATION\n");
65 	printf("------------\n");
66 	zsl_mtx_mult(&u, &e, &ue);
67 	zsl_mtx_trans(&v, &vt);
68 	zsl_mtx_mult(&ue, &vt, &uevt);
69 	printf("U * Sigma * V^t:\n");
70 	zsl_mtx_print(&uevt);
71 	printf("\n");
72 
73 	return 0;
74 }
75 
pinv_test()76 int pinv_test()
77 {
78 	size_t q = 18;
79 	size_t p = 3;
80 
81 	zsl_real_t vi[3 * 18] = { 3.2, 5.0, -4.2, -3.1, 5.4, -2.2, 7.7, 8.7,
82 				  9.9, 8.9, 0.6, 5.4, 3.7, -3.3, 7.2, -5.4,
83 				  -0.6, 8.4, 2.4, 5.1, -5.7, 6.9, -2.1, 0.4,
84 				  6.4, -9.1, -4.4, 0.1, 7.4, 0.0, 6.1, -2.3,
85 				  5.5, 6.1, -8.4, -6.6, 7.1, 2.3, 4.1, -0.8,
86 				  -4.7, 9.9, -3.1, 1.2, 5.2, 6.4, -6.3, 5.2,
87 				  8.8, 7.3, 4.2, -4.7, 0.0, -0.4 };
88 
89 	/* Define the 18x3 matrix, assigning the chosen values. */
90 	ZSL_MATRIX_DEF(mep, q, p);
91 	zsl_mtx_from_arr(&mep, vi);
92 
93 	/* Define the pseudoinverse output matrix. */
94 	ZSL_MATRIX_DEF(pinv, p, q);
95 
96 	/* Display the input matrix for reference. */
97 	printf("INPUT (18x3 MATRIX)\n");
98 	printf("-------------------\n");
99 	zsl_mtx_print(&mep);
100 	printf("\n");
101 
102 	/* Calculate and display the pseudoinverse using 150 iterations. */
103 	zsl_mtx_pinv(&mep, &pinv, 150);
104 	printf("PSEUDOINVERSE (3x18 MATRIX)\n");
105 	printf("--------------------------\n");
106 	zsl_mtx_print(&pinv);
107 	printf("\n");
108 
109 	return 0;
110 }
111 
112 int
main(void)113 main(void)
114 {
115 	printf("Hello, zscilib!\n\n");
116 
117 	printf("SVD TEST\n");
118 	printf("--------\n");
119 	svd_test();
120 
121 	printf("PSEUDOINVERSE TEST\n");
122 	printf("------------------\n");
123 	pinv_test();
124 
125 	return 0;
126 }
127