// // test Cholesky decomposition // void autotest_matrixcf_chol() { float tol = 1e-3f; // error tolerance // lower triangular matrix with positive values on diagonal float complex L[16]= { 1.01, 0, 0, 0, -1.42 + _Complex_I*0.25, 0.50, 0, 0, 0.32 - _Complex_I*1.23, 2.01 + _Complex_I*0.78, 0.30, 0, -1.02 + _Complex_I*1.02, -0.32 - _Complex_I*0.03, -1.65 + _Complex_I*2.01, 1.07}; float complex A[16]; // A = L * L^T float complex Lp[16]; // output Cholesky decomposition unsigned int i; // compute A matrixcf_mul_transpose(L,4,4,A); // force A to be positive definite for (i=0; i<4; i++) matrix_access(A,4,4,i,i) = creal(matrix_access(A,4,4,i,i)); // run decomposition matrixcf_chol(A,4,Lp); if (liquid_autotest_verbose) { printf("L :\n"); matrixcf_print(L,4,4); printf("A :\n"); matrixcf_print(A,4,4); printf("Lp:\n"); matrixcf_print(Lp,4,4); } for (i=0; i<16; i++) { CONTEND_DELTA( crealf(L[i]), crealf(Lp[i]), tol ); CONTEND_DELTA( cimagf(L[i]), cimagf(Lp[i]), tol ); } }
// // AUTOTEST: Test matrixcf multiply/transpose // void autotest_matrixcf_transmul() { // error tolerance float tol = 1e-4f; // 3 x 2 complex matrix float complex x[6] = { -1.984187180846 - _I*1.160899576428, -0.094097208353 - _I*1.664868369484, 1.444228871367 - _I*1.830348997497, -2.157958848569 - _I*0.672986734466, -0.889198235505 - _I*2.191307103110, -0.532344808521 - _I*1.384544279335}; // computation vectors float complex xxT[9]; float complex xTx[4]; float complex xxH[9]; float complex xHx[4]; // test vectors float complex xxT_test[9] = { 8.06533 + _I*0.00000, 0.58272 - _I*1.77897, 6.66340 - _I*2.55969, 0.58272 + _I*1.77897, 10.54567 + _I*0.00000, 4.80721 + _I*2.16276, 6.66340 + _I*2.55969, 4.80721 - _I*2.16276, 7.79285 + _I*0.00000}; float complex xTx_test[4] = { 16.3132 + _I*0.0000, 3.7420 - _I*1.6630, 3.7420 + _I*1.6630, 10.0907 + _I*0.0000}; float complex xxH_test[9] = { -0.1736 + _I*4.9202, -5.9078 + _I*5.6112, -3.0345 + _I*6.3968, -5.9078 + _I*5.6112, 2.9395 - _I*2.3823, -5.0781 + _I*1.8088, -3.0345 + _I*6.3968, -5.0781 + _I*1.8088, -5.6447 + _I*5.3711}; float complex xHx_test[4] = { -2.6862 + _I*3.2170, -8.6550 + _I*8.7882, -8.6550 + _I*8.7882, -0.1926 + _I*4.6920}; // run computations matrixcf_mul_transpose(x,3,2,xxT); matrixcf_transpose_mul(x,3,2,xTx); matrixcf_mul_hermitian(x,3,2,xxH); matrixcf_hermitian_mul(x,3,2,xHx); // test results unsigned int i; for (i=0; i<9; i++) { CONTEND_DELTA( crealf(xxT[i]), crealf(xxT_test[i]), tol ); CONTEND_DELTA( cimagf(xxT[i]), cimagf(xxT_test[i]), tol ); } for (i=0; i<4; i++) { CONTEND_DELTA( crealf(xTx[i]), crealf(xTx_test[i]), tol ); CONTEND_DELTA( cimagf(xTx[i]), cimagf(xTx_test[i]), tol ); } for (i=0; i<9; i++) { CONTEND_DELTA( crealf(xxH[i]), crealf(xxH_test[i]), tol ); CONTEND_DELTA( cimagf(xxH[i]), cimagf(xxH_test[i]), tol ); } for (i=0; i<4; i++) { CONTEND_DELTA( crealf(xHx[i]), crealf(xHx_test[i]), tol ); CONTEND_DELTA( cimagf(xHx[i]), cimagf(xHx_test[i]), tol ); } }
// // AUTOTEST: Q/R decomp (Gram-Schmidt) // void autotest_matrixcf_qrdecomp() { float tol = 1e-4f; // error tolerance float complex A[16]= { 2.11402 - 0.57604*_I, 0.41750 + 1.00833*_I, -0.96264 - 3.62196*_I, -0.20679 - 1.02668*_I, 0.00854 + 1.61626*_I, 0.84695 - 0.32736*_I, -1.01862 - 1.10786*_I, -1.78877 + 1.84456*_I, -2.97901 - 1.30384*_I, 0.52289 + 1.89110*_I, 1.32576 - 0.36737*_I, 0.04717 + 0.20628*_I, 0.28970 + 0.64247*_I, -0.55916 + 0.68302*_I, 1.40615 + 0.62398*_I, -0.12767 - 0.53997*_I}; float complex Q[16]; float complex R[16]; float complex Q_test[16] = { 0.4917069 - 0.1339829*_I, 0.4296604 + 0.5598343*_I, -0.3093337 - 0.2783187*_I, 0.2152058 - 0.1509579*_I, 0.0019872 + 0.3759317*_I, 0.2427682 + 0.0092564*_I, -0.4223052 - 0.0325125*_I, -0.5035680 + 0.6055326*_I, -0.6928955 - 0.3032643*_I, 0.0541098 + 0.4680729*_I, -0.0821501 + 0.0696538*_I, 0.2796678 + 0.3407228*_I, 0.0673832 + 0.1494333*_I, -0.2704656 + 0.3844264*_I, -0.2850673 + 0.7447073*_I, -0.1735849 - 0.2936151*_I}; float complex R_test[16] = { 4.29936 + 0.00000*_I, -0.92262 - 0.78948*_I, -1.02577 - 1.04067*_I, 0.54122 - 0.00234*_I, 0.00000 + 0.00000*_I, 2.27373 + 0.00000*_I, -2.93951 - 2.62657*_I, -1.15474 + 0.32321*_I, 0.00000 + 0.00000*_I, 0.00000 + 0.00000*_I, 1.70137 + 0.00000*_I, 0.68991 - 0.34832*_I, 0.00000 + 0.00000*_I, 0.00000 + 0.00000*_I, 0.00000 + 0.00000*_I, 2.39237 + 0.00000*_I}; unsigned int i; // run decomposition matrixcf_qrdecomp_gramschmidt(A,4,4,Q,R); if (liquid_autotest_verbose) { printf("Q :\n"); matrixcf_print(Q,4,4); printf("expected Q :\n"); matrixcf_print(Q_test,4,4); printf("\n\n"); printf("R :\n"); matrixcf_print(R,4,4); printf("expected R :\n"); matrixcf_print(R_test,4,4); } for (i=0; i<16; i++) { CONTEND_DELTA( crealf(Q[i]), crealf(Q_test[i]), tol ); CONTEND_DELTA( cimagf(Q[i]), cimagf(Q_test[i]), tol ); CONTEND_DELTA( crealf(R[i]), crealf(R_test[i]), tol ); CONTEND_DELTA( cimagf(R[i]), cimagf(R_test[i]), tol ); } // test Q*R == A float complex QR_test[16]; matrixcf_mul(Q,4,4, R,4,4, QR_test,4,4); for (i=0; i<16; i++) CONTEND_DELTA( A[i], QR_test[i], tol ); // test Q*Q' == eye(4) float complex QQT_test[16]; matrixcf_mul_transpose(Q,4,4, QQT_test); float complex I4[16]; matrixcf_eye(I4,4); for (i=0; i<16; i++) CONTEND_DELTA( QQT_test[i], I4[i], tol ); }
int main() { float x[6] = { 1, 2, 3, 4, 5, 6 }; float y[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; float z[6]; // compute z = x * y printf("z = x * y :\n"); matrixf_mul(x,2,3,y,3,3,z,2,3); matrixf_print(z,2,3); /* // compute z = y * x' matrixf_transpose(x); printf("x' : \n"); matrixf_print(x); matrixf_transpose(z); matrixf_multiply(y,x,z); printf("z = y * x' :\n"); matrixf_print(z); matrixf_destroy(x); matrixf_destroy(y); matrixf_destroy(z); */ float s[16] = { 1,2,3,4, 5,5,7,8, 6,4,8,7, 1,0,3,1 }; float s_inv[16]; memmove(s_inv,s,16*sizeof(float)); matrixf_inv(s_inv,4,4); float i4[16]; matrixf_mul(s,4,4,s_inv,4,4,i4,4,4); printf("\ns:\n"); matrixf_print(s,4,4); printf("\ninv(s):\n"); matrixf_print(s_inv,4,4); printf("\ns*inv(s):\n"); matrixf_print(i4,4,4); printf("\n"); float det = matrixf_det(s,4,4); printf("det(s) = %12.8f\n", det); #if 0 // pivot test (matrix inversion) float t[32] = { 1,2,3,4, 1,0,0,0, 5,5,7,8, 0,1,0,0, 6,4,8,7, 0,0,1,0, 1,0,3,1, 0,0,0,1 }; unsigned int i; for (i=0; i<4; i++) { matrixf_pivot(t,4,8,i,i); matrixf_print(t,4,8); } unsigned int j; for (i=0; i<4; i++) { float v = matrix_access(t,4,8,i,i); for (j=0; j<8; j++) matrix_access(t,4,8,i,j) /= v; } matrixf_print(t,4,8); #endif printf("\n"); printf("testing L/U decomposition [Crout's method]\n"); float L[16], U[16], P[16]; matrixf_ludecomp_crout(s,4,4,L,U,P); matrixf_print(L,4,4); matrixf_print(U,4,4); printf("\n"); printf("testing L/U decomposition [Doolittle's method]\n"); matrixf_ludecomp_doolittle(s,4,4,L,U,P); matrixf_print(L,4,4); matrixf_print(U,4,4); printf("\n\n"); float X[16] = { 0.84382, -2.38304, 1.43061, -1.66604, 3.99475, 0.88066, 4.69373, 0.44563, 7.28072, -2.06608, 0.67074, 9.80657, 6.07741, -3.93099, 1.22826, -0.42142 }; float Y[16]; printf("\nX:\n"); matrixf_print(X,4,4); // swaprows memmove(Y,X,16*sizeof(float)); matrixf_swaprows(Y,4,4,0,2); printf("\nmatrixf_swaprows(X,4,4,0,2):\n"); matrixf_print(Y,4,4); // pivot test memmove(Y,X,16*sizeof(float)); matrixf_pivot(Y,4,4,1,2); printf("\nmatrixf_pivot(X,4,4,1,2):\n"); matrixf_print(Y,4,4); // inverse test memmove(Y,X,16*sizeof(float)); matrixf_inv(Y,4,4); printf("\nmatrixf_inv(X,4,4):\n"); matrixf_print(Y,4,4); // determinant test float D = matrixf_det(X,4,4); printf("\nmatrixf_det(X,4) = %12.8f\n", D); // L/U decomp (Crout's method) matrixf_ludecomp_crout(X,4,4,L,U,P); printf("\nmatrixf_ludecomp_crout(X,4,4,L,U,P)\n"); printf("L:\n"); matrixf_print(L,4,4); printf("U:\n"); matrixf_print(U,4,4); // L/U decomp (Doolittle's method) matrixf_ludecomp_doolittle(X,4,4,L,U,P); printf("\nmatrixf_ludecomp_doolittle(X,4,4,L,U,P)\n"); printf("L:\n"); matrixf_print(L,4,4); printf("U:\n"); matrixf_print(U,4,4); printf("\n"); printf("testing Q/R decomposition [Gram-Schmidt]\n"); float Q[16], R[16]; matrixf_qrdecomp_gramschmidt(X,4,4,Q,R); matrixf_print(Q,4,4); matrixf_print(R,4,4); /* float b[4] = { 0.91489, 0.71789, 1.06553, -0.81707}; */ float Xb[20] = { 0.84382, -2.38304, 1.43061, -1.66604, 0.91489, 3.99475, 0.88066, 4.69373, 0.44563, 0.71789, 7.28072, -2.06608, 0.67074, 9.80657, 1.06553, 6.07741, -3.93099, 1.22826, -0.42142, -0.81707 }; printf("\n[X b] =\n"); matrixf_print(Xb,4,5); matrixf_gjelim(Xb,4,5); printf("\nmatrixf_gjelim(Xb,4,5)\n"); matrixf_print(Xb,4,5); // compute a*a' float a[20] = { -0.24655, -1.78843, 0.39477, 0.43735, -1.08998, -0.42751, 0.62496, 1.43802, 0.19814, 0.78155, -0.35658, -0.81875, -1.09984, 1.87006, -0.94191, 0.39553, -2.02036, 1.17393, 1.54591, 1.29663 }; printf("\na =\n"); matrixf_print(a,4,5); printf("\n\n"); printf("computing a*a'\n"); float aaT[16]; matrixf_mul_transpose(a,4,5,aaT); matrixf_print(aaT,4,4); printf("\n\n"); printf("computing a'*a\n"); float aTa[25]; matrixf_transpose_mul(a,4,5,aTa); matrixf_print(aTa,5,5); printf("\n"); printf("testing Gram-Schmidt\n"); float Xgs[12] = { 1., 2., 1., 0., 2., 0., 2., 3., 1., 1., 1., 0. }; float Ugs[12]; float Ugs_test[12] = { sqrtf(6.)/6., sqrtf(2.)/6., 2./3., 0., 2.*sqrtf(2.)/3.,-1./3., sqrtf(6.)/3., 0., 0., sqrtf(6.)/6., -sqrtf(2.)/6., -2./3. }; matrixf_gramschmidt(Xgs,4,3,Ugs); printf("X:\n"); matrixf_print(Xgs,4,3); printf("normalized X:\n"); matrixf_print(Ugs,4,3); printf("expected:\n"); matrixf_print(Ugs_test,4,3); // // test Cholesky decomposition // printf("\n"); printf("testing Cholesky decomposition\n"); // generate input matrix float complex Lp[9] = { 1.0, 0.0, 0.0, -3.1 + 0.2*_Complex_I, 0.3, 0.0, 1.7 + 0.5*_Complex_I, -0.6 - 0.3*_Complex_I, 2.9 }; float complex Ap[9]; matrixcf_mul_transpose(Lp, 3, 3, Ap); float complex Lc[9]; matrixcf_chol(Ap, 3, Lc); printf("Lp:\n"); matrixcf_print(Lp, 3, 3); printf("Ap:\n"); matrixcf_print(Ap, 3, 3); printf("Lc:\n"); matrixcf_print(Lc, 3, 3); printf("done.\n"); return 0; }