home *** CD-ROM | disk | FTP | other *** search
-
- /**************************************************************************
- **
- ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
- **
- ** Meschach Library
- **
- ** This Meschach Library is provided "as is" without any express
- ** or implied warranty of any kind with respect to this software.
- ** In particular the authors shall not be liable for any direct,
- ** indirect, special, incidental or consequential damages arising
- ** in any way from use of the software.
- **
- ** Everyone is granted permission to copy, modify and redistribute this
- ** Meschach Library, provided:
- ** 1. All copies contain this copyright notice.
- ** 2. All modified copies shall carry a notice stating who
- ** made the last modification and the date of such modification.
- ** 3. No charge is made for this software or works derived from it.
- ** This clause shall not be construed as constraining other software
- ** distributed on the same medium as this software, nor is a
- ** distribution fee considered a charge.
- **
- ***************************************************************************/
-
-
- /*
- This file contains a series of tests for the Meschach matrix
- library, complex routines
- */
-
- static char rcsid[] = "$Id: $";
-
- #include <stdio.h>
- #include <math.h>
- #include "zmatrix2.h"
- #include "matlab.h"
-
-
- #define errmesg(mesg) printf("Error: %s error: line %d\n",mesg,__LINE__)
- #define notice(mesg) printf("# Testing %s...\n",mesg);
-
- /* extern int malloc_chain_check(); */
- /* #define MEMCHK() if ( malloc_chain_check(0) ) \
- { printf("Error in malloc chain: \"%s\", line %d\n", \
- __FILE__, __LINE__); exit(0); } */
- #define MEMCHK()
-
- /* cmp_perm -- returns 1 if pi1 == pi2, 0 otherwise */
- int cmp_perm(pi1, pi2)
- PERM *pi1, *pi2;
- {
- int i;
-
- if ( ! pi1 || ! pi2 )
- error(E_NULL,"cmp_perm");
- if ( pi1->size != pi2->size )
- return 0;
- for ( i = 0; i < pi1->size; i++ )
- if ( pi1->pe[i] != pi2->pe[i] )
- return 0;
- return 1;
- }
-
- /* px_rand -- generates sort-of random permutation */
- PERM *px_rand(pi)
- PERM *pi;
- {
- int i, j, k;
-
- if ( ! pi )
- error(E_NULL,"px_rand");
-
- for ( i = 0; i < 3*pi->size; i++ )
- {
- j = (rand() >> 8) % pi->size;
- k = (rand() >> 8) % pi->size;
- px_transp(pi,j,k);
- }
-
- return pi;
- }
- #ifdef RISC_OS
- #define SAVE_FILE "asx521_mat"
- #else
- #define SAVE_FILE "asx5213a.mat"
- #endif
- #define MATLAB_NAME "alpha"
- char name[81] = MATLAB_NAME;
-
- void main(argc, argv)
- int argc;
- char *argv[];
- {
- ZVEC *x = ZVNULL, *y = ZVNULL, *z = ZVNULL, *u = ZVNULL;
- ZVEC *diag = ZVNULL;
- PERM *pi1 = PNULL, *pi2 = PNULL, *pivot = PNULL;
- ZMAT *A = ZMNULL, *B = ZMNULL, *C = ZMNULL, *D = ZMNULL,
- *Q = ZMNULL;
- complex ONE;
- complex z1, z2, z3;
- Real cond_est, s1, s2, s3;
- int i, seed;
- FILE *fp;
- char *cp;
-
-
- mem_info_on(TRUE);
-
- setbuf(stdout,(char *)NULL);
-
- seed = 1111;
- if ( argc > 2 )
- {
- printf("usage: %s [seed]\n",argv[0]);
- exit(0);
- }
- else if ( argc == 2 )
- sscanf(argv[1], "%d", &seed);
-
- /* set seed for rand() */
- smrand(seed);
-
- /* print out version information */
- m_version();
-
- printf("# Meschach Complex numbers & vectors torture test\n\n");
- printf("# grep \"^Error\" the output for a listing of errors\n");
- printf("# Don't panic if you see \"Error\" appearing; \n");
- printf("# Also check the reported size of error\n");
- printf("# This program uses randomly generated problems and therefore\n");
- printf("# may occasionally produce ill-conditioned problems\n");
- printf("# Therefore check the size of the error compared with MACHEPS\n");
- printf("# If the error is within 1000*MACHEPS then don't worry\n");
- printf("# If you get an error of size 0.1 or larger there is \n");
- printf("# probably a bug in the code or the compilation procedure\n\n");
- printf("# seed = %d\n",seed);
-
- printf("\n");
-
- mem_stat_mark(1);
-
- notice("complex arithmetic & special functions");
-
- ONE = zmake(1.0,0.0);
- printf("# ONE = "); z_output(ONE);
- z1.re = mrand(); z1.im = mrand();
- z2.re = mrand(); z2.im = mrand();
- z3 = zadd(z1,z2);
- if ( fabs(z1.re+z2.re-z3.re) + fabs(z1.im+z2.im-z3.im) > 10*MACHEPS )
- errmesg("zadd");
- z3 = zsub(z1,z2);
- if ( fabs(z1.re-z2.re-z3.re) + fabs(z1.im-z2.im-z3.im) > 10*MACHEPS )
- errmesg("zadd");
- z3 = zmlt(z1,z2);
- if ( fabs(z1.re*z2.re - z1.im*z2.im - z3.re) +
- fabs(z1.im*z2.re + z1.re*z2.im - z3.im) > 10*MACHEPS )
- errmesg("zmlt");
- s1 = zabs(z1);
- if ( fabs(s1*s1 - (z1.re*z1.re+z1.im*z1.im)) > 10*MACHEPS )
- errmesg("zabs");
- if ( zabs(zsub(z1,zmlt(z2,zdiv(z1,z2)))) > 10*MACHEPS ||
- zabs(zsub(ONE,zdiv(z1,zmlt(z2,zdiv(z1,z2))))) > 10*MACHEPS )
- errmesg("zdiv");
-
- z3 = zsqrt(z1);
- if ( zabs(zsub(z1,zmlt(z3,z3))) > 10*MACHEPS )
- errmesg("zsqrt");
- if ( zabs(zsub(z1,zlog(zexp(z1)))) > 10*MACHEPS )
- errmesg("zexp/zlog");
-
-
- printf("# Check: MACHEPS = %g\n",MACHEPS);
- /* allocate, initialise, copy and resize operations */
- /* ZVEC */
- notice("vector initialise, copy & resize");
- x = zv_get(12);
- y = zv_get(15);
- z = zv_get(12);
- zv_rand(x);
- zv_rand(y);
- z = zv_copy(x,z);
- if ( zv_norm2(zv_sub(x,z,z)) >= MACHEPS )
- errmesg("ZVEC copy");
- zv_copy(x,y);
- x = zv_resize(x,10);
- y = zv_resize(y,10);
- if ( zv_norm2(zv_sub(x,y,z)) >= MACHEPS )
- errmesg("ZVEC copy/resize");
- x = zv_resize(x,15);
- y = zv_resize(y,15);
- if ( zv_norm2(zv_sub(x,y,z)) >= MACHEPS )
- errmesg("VZEC resize");
-
- /* ZMAT */
- notice("matrix initialise, copy & resize");
- A = zm_get(8,5);
- B = zm_get(3,9);
- C = zm_get(8,5);
- zm_rand(A);
- zm_rand(B);
- C = zm_copy(A,C);
- if ( zm_norm_inf(zm_sub(A,C,C)) >= MACHEPS )
- errmesg("ZMAT copy");
- zm_copy(A,B);
- A = zm_resize(A,3,5);
- B = zm_resize(B,3,5);
- if ( zm_norm_inf(zm_sub(A,B,C)) >= MACHEPS )
- errmesg("ZMAT copy/resize");
- A = zm_resize(A,10,10);
- B = zm_resize(B,10,10);
- if ( zm_norm_inf(zm_sub(A,B,C)) >= MACHEPS )
- errmesg("ZMAT resize");
-
- MEMCHK();
-
- /* PERM */
- notice("permutation initialise, inverting & permuting vectors");
- pi1 = px_get(15);
- pi2 = px_get(12);
- px_rand(pi1);
- zv_rand(x);
- px_zvec(pi1,x,z);
- y = zv_resize(y,x->dim);
- pxinv_zvec(pi1,z,y);
- if ( zv_norm2(zv_sub(x,y,z)) >= MACHEPS )
- errmesg("PERMute vector");
-
- /* testing catch() etc */
- notice("error handling routines");
- catch(E_NULL,
- catchall(zv_add(ZVNULL,ZVNULL,ZVNULL);
- errmesg("tracecatch() failure"),
- printf("# tracecatch() caught error\n");
- error(E_NULL,"main"));
- errmesg("catch() failure"),
- printf("# catch() caught E_NULL error\n"));
-
- /* testing inner products and v_mltadd() etc */
- notice("inner products and linear combinations");
- u = zv_get(x->dim);
- zv_rand(u);
- zv_rand(x);
- zv_resize(y,x->dim);
- zv_rand(y);
- zv_mltadd(y,x,zneg(zdiv(zin_prod(x,y),zin_prod(x,x))),z);
- if ( zabs(zin_prod(x,z)) >= 5*MACHEPS*x->dim )
- {
- errmesg("zv_mltadd()/zin_prod()");
- printf("# error norm = %g\n", zabs(zin_prod(x,z)));
- }
-
- z1 = zneg(zdiv(zin_prod(x,y),zmake(zv_norm2(x)*zv_norm2(x),0.0)));
- zv_mlt(z1,x,u);
- zv_add(y,u,u);
- if ( zv_norm2(zv_sub(u,z,u)) >= MACHEPS*x->dim )
- {
- errmesg("zv_mlt()/zv_norm2()");
- printf("# error norm = %g\n", zv_norm2(u));
- }
-
- #ifdef ANSI_C
- zv_linlist(u,x,z1,y,ONE,VNULL);
- if ( zv_norm2(zv_sub(u,z,u)) >= MACHEPS*x->dim )
- errmesg("zv_linlist()");
- #endif
- #ifdef VARARGS
- zv_linlist(u,x,z1,y,ONE,VNULL);
- if ( zv_norm2(zv_sub(u,z,u)) >= MACHEPS*x->dim )
- errmesg("zv_linlist()");
- #endif
-
- MEMCHK();
-
- /* vector norms */
- notice("vector norms");
- x = zv_resize(x,12);
- zv_rand(x);
- for ( i = 0; i < x->dim; i++ )
- if ( zabs(v_entry(x,i)) >= 0.7 )
- v_set_val(x,i,ONE);
- else
- v_set_val(x,i,zneg(ONE));
- s1 = zv_norm1(x);
- s2 = zv_norm2(x);
- s3 = zv_norm_inf(x);
- if ( fabs(s1 - x->dim) >= MACHEPS*x->dim ||
- fabs(s2 - sqrt((double)(x->dim))) >= MACHEPS*x->dim ||
- fabs(s3 - 1.0) >= MACHEPS )
- errmesg("zv_norm1/2/_inf()");
-
- /* test matrix multiply etc */
- notice("matrix multiply and invert");
- A = zm_resize(A,10,10);
- B = zm_resize(B,10,10);
- zm_rand(A);
- zm_inverse(A,B);
- zm_mlt(A,B,C);
- for ( i = 0; i < C->m; i++ )
- m_set_val(C,i,i,zsub(m_entry(C,i,i),ONE));
- if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
- errmesg("zm_inverse()/zm_mlt()");
-
- MEMCHK();
-
- /* ... and adjoints */
- notice("adjoints and adjoint-multiplies");
- zm_adjoint(A,A); /* can do square matrices in situ */
- zmam_mlt(A,B,C);
- for ( i = 0; i < C->m; i++ )
- m_set_val(C,i,i,zsub(m_entry(C,i,i),ONE));
- if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
- errmesg("zm_adjoint()/zmam_mlt()");
- zm_adjoint(A,A);
- zm_adjoint(B,B);
- zmma_mlt(A,B,C);
- for ( i = 0; i < C->m; i++ )
- m_set_val(C,i,i,zsub(m_entry(C,i,i),ONE));
- if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
- errmesg("zm_adjoint()/zmma_mlt()");
- zsm_mlt(zmake(3.71,2.753),B,B);
- zmma_mlt(A,B,C);
- for ( i = 0; i < C->m; i++ )
- m_set_val(C,i,i,zsub(m_entry(C,i,i),zmake(3.71,-2.753)));
- if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
- errmesg("szm_mlt()/zmma_mlt()");
- zm_adjoint(B,B);
- zsm_mlt(zdiv(ONE,zmake(3.71,-2.753)),B,B);
-
- MEMCHK();
-
- /* ... and matrix-vector multiplies */
- notice("matrix-vector multiplies");
- x = zv_resize(x,A->n);
- y = zv_resize(y,A->m);
- z = zv_resize(z,A->m);
- u = zv_resize(u,A->n);
- zv_rand(x);
- zv_rand(y);
- zmv_mlt(A,x,z);
- z1 = zin_prod(y,z);
- zvm_mlt(A,y,u);
- z2 = zin_prod(u,x);
- if ( zabs(zsub(z1,z2)) >= (MACHEPS*x->dim)*x->dim )
- {
- errmesg("zmv_mlt()/zvm_mlt()");
- printf("# difference between inner products is %g\n",
- zabs(zsub(z1,z2)));
- }
- zmv_mlt(B,z,u);
- if ( zv_norm2(zv_sub(u,x,u)) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
- errmesg("zmv_mlt()/zvm_mlt()");
-
- MEMCHK();
-
- /* get/set row/col */
- notice("getting and setting rows and cols");
- x = zv_resize(x,A->n);
- y = zv_resize(y,B->m);
- x = zget_row(A,3,x);
- y = zget_col(B,3,y);
- if ( zabs(zsub(_zin_prod(x,y,0,Z_NOCONJ),ONE)) >=
- MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
- errmesg("zget_row()/zget_col()");
- zv_mlt(zmake(-1.0,0.0),x,x);
- zv_mlt(zmake(-1.0,0.0),y,y);
- zset_row(A,3,x);
- zset_col(B,3,y);
- zm_mlt(A,B,C);
- for ( i = 0; i < C->m; i++ )
- m_set_val(C,i,i,zsub(m_entry(C,i,i),ONE));
- if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
- errmesg("zset_row()/zset_col()");
-
- MEMCHK();
-
- /* matrix norms */
- notice("matrix norms");
- A = zm_resize(A,11,15);
- zm_rand(A);
- s1 = zm_norm_inf(A);
- B = zm_adjoint(A,B);
- s2 = zm_norm1(B);
- if ( fabs(s1 - s2) >= MACHEPS*A->m )
- errmesg("zm_norm1()/zm_norm_inf()");
- C = zmam_mlt(A,A,C);
- z1.re = z1.im = 0.0;
- for ( i = 0; i < C->m && i < C->n; i++ )
- z1 = zadd(z1,m_entry(C,i,i));
- if ( fabs(sqrt(z1.re) - zm_norm_frob(A)) >= MACHEPS*A->m*A->n )
- errmesg("zm_norm_frob");
-
- MEMCHK();
-
- /* permuting rows and columns */
- /******************************
- notice("permuting rows & cols");
- A = zm_resize(A,11,15);
- B = zm_resize(B,11,15);
- pi1 = px_resize(pi1,A->m);
- px_rand(pi1);
- x = zv_resize(x,A->n);
- y = zmv_mlt(A,x,y);
- px_rows(pi1,A,B);
- px_zvec(pi1,y,z);
- zmv_mlt(B,x,u);
- if ( zv_norm2(zv_sub(z,u,u)) >= MACHEPS*A->m )
- errmesg("px_rows()");
- pi1 = px_resize(pi1,A->n);
- px_rand(pi1);
- px_cols(pi1,A,B);
- pxinv_zvec(pi1,x,z);
- zmv_mlt(B,z,u);
- if ( zv_norm2(zv_sub(y,u,u)) >= MACHEPS*A->n )
- errmesg("px_cols()");
- ******************************/
-
- MEMCHK();
-
- /* MATLAB save/load */
- notice("MATLAB save/load");
- A = zm_resize(A,12,11);
- if ( (fp=fopen(SAVE_FILE,"w")) == (FILE *)NULL )
- printf("Cannot perform MATLAB save/load test\n");
- else
- {
- zm_rand(A);
- zm_save(fp, A, name);
- fclose(fp);
- if ( (fp=fopen(SAVE_FILE,"r")) == (FILE *)NULL )
- printf("Cannot open save file \"%s\"\n",SAVE_FILE);
- else
- {
- ZM_FREE(B);
- B = zm_load(fp,&cp);
- if ( strcmp(name,cp) || zm_norm1(zm_sub(A,B,C)) >=
- MACHEPS*A->m )
- {
- errmesg("zm_load()/zm_save()");
- printf("# orig. name = %s, restored name = %s\n", name, cp);
- printf("# orig. A =\n"); zm_output(A);
- printf("# restored A =\n"); zm_output(B);
- }
- }
- }
-
- MEMCHK();
-
- /* Now, onto matrix factorisations */
- A = zm_resize(A,10,10);
- B = zm_resize(B,A->m,A->n);
- zm_copy(A,B);
- x = zv_resize(x,A->n);
- y = zv_resize(y,A->m);
- z = zv_resize(z,A->n);
- u = zv_resize(u,A->m);
- zv_rand(x);
- zmv_mlt(B,x,y);
- z = zv_copy(x,z);
-
- notice("LU factor/solve");
- pivot = px_get(A->m);
- zLUfactor(A,pivot);
- tracecatch(zLUsolve(A,pivot,y,x),"main");
- tracecatch(cond_est = zLUcondest(A,pivot),"main");
- printf("# cond(A) approx= %g\n", cond_est);
- if ( zv_norm2(zv_sub(x,z,u)) >= MACHEPS*zv_norm2(x)*cond_est)
- {
- errmesg("zLUfactor()/zLUsolve()");
- printf("# LU solution error = %g [cf MACHEPS = %g]\n",
- zv_norm2(zv_sub(x,z,u)), MACHEPS);
- }
-
-
- zv_copy(y,x);
- tracecatch(zLUsolve(A,pivot,x,x),"main");
- tracecatch(cond_est = zLUcondest(A,pivot),"main");
- if ( zv_norm2(zv_sub(x,z,u)) >= MACHEPS*zv_norm2(x)*cond_est)
- {
- errmesg("zLUfactor()/zLUsolve()");
- printf("# LU solution error = %g [cf MACHEPS = %g]\n",
- zv_norm2(zv_sub(x,z,u)), MACHEPS);
- }
-
- zvm_mlt(B,z,y);
- zv_copy(y,x);
- tracecatch(zLUAsolve(A,pivot,x,x),"main");
- if ( zv_norm2(zv_sub(x,z,u)) >= MACHEPS*zv_norm2(x)*cond_est)
- {
- errmesg("zLUfactor()/zLUAsolve()");
- printf("# LU solution error = %g [cf MACHEPS = %g]\n",
- zv_norm2(zv_sub(x,z,u)), MACHEPS);
- }
-
- MEMCHK();
-
- /* QR factorisation */
- zm_copy(B,A);
- zmv_mlt(B,z,y);
- notice("QR factor/solve:");
- diag = zv_get(A->m);
- zQRfactor(A,diag);
- zQRsolve(A,diag,y,x);
- if ( zv_norm2(zv_sub(x,z,u)) >= MACHEPS*zv_norm2(x)*cond_est )
- {
- errmesg("zQRfactor()/zQRsolve()");
- printf("# QR solution error = %g [cf MACHEPS = %g]\n",
- zv_norm2(zv_sub(x,z,u)), MACHEPS);
- }
- printf("# QR cond(A) approx= %g\n", zQRcondest(A));
- Q = zm_get(A->m,A->m);
- zmakeQ(A,diag,Q);
- zmakeR(A,A);
- zm_mlt(Q,A,C);
- zm_sub(B,C,C);
- if ( zm_norm1(C) >= MACHEPS*zm_norm1(Q)*zm_norm1(B) )
- {
- errmesg("zQRfactor()/zmakeQ()/zmakeR()");
- printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n",
- zm_norm1(C), MACHEPS);
- }
-
- MEMCHK();
-
- /* now try with a non-square matrix */
- A = zm_resize(A,15,7);
- zm_rand(A);
- B = zm_copy(A,B);
- diag = zv_resize(diag,A->n);
- x = zv_resize(x,A->n);
- y = zv_resize(y,A->m);
- zv_rand(y);
- zQRfactor(A,diag);
- x = zQRsolve(A,diag,y,x);
- /* z is the residual vector */
- zmv_mlt(B,x,z); zv_sub(z,y,z);
- /* check B*.z = 0 */
- zvm_mlt(B,z,u);
- if ( zv_norm2(u) >= 100*MACHEPS*zm_norm1(B)*zv_norm2(y) )
- {
- errmesg("zQRfactor()/zQRsolve()");
- printf("# QR solution error = %g [cf MACHEPS = %g]\n",
- zv_norm2(u), MACHEPS);
- }
- Q = zm_resize(Q,A->m,A->m);
- zmakeQ(A,diag,Q);
- zmakeR(A,A);
- zm_mlt(Q,A,C);
- zm_sub(B,C,C);
- if ( zm_norm1(C) >= MACHEPS*zm_norm1(Q)*zm_norm1(B) )
- {
- errmesg("zQRfactor()/zmakeQ()/zmakeR()");
- printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n",
- zm_norm1(C), MACHEPS);
- }
- D = zm_get(A->m,Q->m);
- zmam_mlt(Q,Q,D);
- for ( i = 0; i < D->m; i++ )
- m_set_val(D,i,i,zsub(m_entry(D,i,i),ONE));
- if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm_inf(Q) )
- {
- errmesg("QRfactor()/makeQ()/makeR()");
- printf("# QR orthogonality error = %g [cf MACHEPS = %g]\n",
- zm_norm1(D), MACHEPS);
- }
-
- MEMCHK();
-
- /* QRCP factorisation */
- zm_copy(B,A);
- notice("QR factor/solve with column pivoting");
- pivot = px_resize(pivot,A->n);
- zQRCPfactor(A,diag,pivot);
- z = zv_resize(z,A->n);
- zQRCPsolve(A,diag,pivot,y,z);
- /* pxinv_zvec(pivot,z,x); */
- /* now compute residual (z) vector */
- zmv_mlt(B,x,z); zv_sub(z,y,z);
- /* check B^T.z = 0 */
- zvm_mlt(B,z,u);
- if ( zv_norm2(u) >= MACHEPS*zm_norm1(B)*zv_norm2(y) )
- {
- errmesg("QRCPfactor()/QRsolve()");
- printf("# QR solution error = %g [cf MACHEPS = %g]\n",
- zv_norm2(u), MACHEPS);
- }
-
- Q = zm_resize(Q,A->m,A->m);
- zmakeQ(A,diag,Q);
- zmakeR(A,A);
- zm_mlt(Q,A,C);
- ZM_FREE(D);
- D = zm_get(B->m,B->n);
- /******************************
- px_cols(pivot,C,D);
- zm_sub(B,D,D);
- if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm1(B) )
- {
- errmesg("QRCPfactor()/makeQ()/makeR()");
- printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n",
- zm_norm1(D), MACHEPS);
- }
- ******************************/
-
- /* Now check eigenvalue/SVD routines */
- notice("complex Schur routines");
- A = zm_resize(A,11,11);
- B = zm_resize(B,A->m,A->n);
- C = zm_resize(C,A->m,A->n);
- D = zm_resize(D,A->m,A->n);
- Q = zm_resize(Q,A->m,A->n);
-
- MEMCHK();
-
- /* now test complex Schur decomposition */
- /* zm_copy(A,B); */
- ZM_FREE(A);
- A = zm_get(11,11);
- zm_rand(A);
- B = zm_copy(A,B);
- MEMCHK();
-
- B = zschur(B,Q);
- MEMCHK();
-
- zm_mlt(Q,B,C);
- zmma_mlt(C,Q,D);
- MEMCHK();
- zm_sub(A,D,D);
- if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm_inf(Q)*zm_norm1(B)*5 )
- {
- errmesg("zschur()");
- printf("# Schur reconstruction error = %g [cf MACHEPS = %g]\n",
- zm_norm1(D), MACHEPS);
- }
-
- /* orthogonality check */
- zmma_mlt(Q,Q,D);
- for ( i = 0; i < D->m; i++ )
- m_set_val(D,i,i,zsub(m_entry(D,i,i),ONE));
- if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm_inf(Q)*10 )
- {
- errmesg("zschur()");
- printf("# Schur orthogonality error = %g [cf MACHEPS = %g]\n",
- zm_norm1(D), MACHEPS);
- }
-
- MEMCHK();
-
- /* now test SVD */
- /******************************
- A = zm_resize(A,11,7);
- zm_rand(A);
- U = zm_get(A->n,A->n);
- Q = zm_resize(Q,A->m,A->m);
- u = zv_resize(u,max(A->m,A->n));
- svd(A,Q,U,u);
- ******************************/
- /* check reconstruction of A */
- /******************************
- D = zm_resize(D,A->m,A->n);
- C = zm_resize(C,A->m,A->n);
- zm_zero(D);
- for ( i = 0; i < min(A->m,A->n); i++ )
- zm_set_val(D,i,i,v_entry(u,i));
- zmam_mlt(Q,D,C);
- zm_mlt(C,U,D);
- zm_sub(A,D,D);
- if ( zm_norm1(D) >= MACHEPS*zm_norm1(U)*zm_norm_inf(Q)*zm_norm1(A) )
- {
- errmesg("svd()");
- printf("# SVD reconstruction error = %g [cf MACHEPS = %g]\n",
- zm_norm1(D), MACHEPS);
- }
- ******************************/
- /* check orthogonality of Q and U */
- /******************************
- D = zm_resize(D,Q->n,Q->n);
- zmam_mlt(Q,Q,D);
- for ( i = 0; i < D->m; i++ )
- m_set_val(D,i,i,m_entry(D,i,i)-1.0);
- if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm_inf(Q)*5 )
- {
- errmesg("svd()");
- printf("# SVD orthognality error (Q) = %g [cf MACHEPS = %g\n",
- zm_norm1(D), MACHEPS);
- }
- D = zm_resize(D,U->n,U->n);
- zmam_mlt(U,U,D);
- for ( i = 0; i < D->m; i++ )
- m_set_val(D,i,i,m_entry(D,i,i)-1.0);
- if ( zm_norm1(D) >= MACHEPS*zm_norm1(U)*zm_norm_inf(U)*5 )
- {
- errmesg("svd()");
- printf("# SVD orthognality error (U) = %g [cf MACHEPS = %g\n",
- zm_norm1(D), MACHEPS);
- }
- for ( i = 0; i < u->dim; i++ )
- if ( v_entry(u,i) < 0 || (i < u->dim-1 &&
- v_entry(u,i+1) > v_entry(u,i)) )
- break;
- if ( i < u->dim )
- {
- errmesg("svd()");
- printf("# SVD sorting error\n");
- }
- ******************************/
-
- ZV_FREE(x); ZV_FREE(y); ZV_FREE(z);
- ZV_FREE(u); ZV_FREE(diag);
- PX_FREE(pi1); PX_FREE(pi2); PX_FREE(pivot);
- ZM_FREE(A); ZM_FREE(B); ZM_FREE(C);
- ZM_FREE(D); ZM_FREE(Q);
-
- mem_stat_free(1);
-
- MEMCHK();
- printf("# Finished torture test for complex numbers/vectors/matrices\n");
- mem_info();
- }
-
-