ztorture.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. /**************************************************************************
  2. **
  3. ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
  4. **
  5. ** Meschach Library
  6. **
  7. ** This Meschach Library is provided "as is" without any express
  8. ** or implied warranty of any kind with respect to this software.
  9. ** In particular the authors shall not be liable for any direct,
  10. ** indirect, special, incidental or consequential damages arising
  11. ** in any way from use of the software.
  12. **
  13. ** Everyone is granted permission to copy, modify and redistribute this
  14. ** Meschach Library, provided:
  15. ** 1. All copies contain this copyright notice.
  16. ** 2. All modified copies shall carry a notice stating who
  17. ** made the last modification and the date of such modification.
  18. ** 3. No charge is made for this software or works derived from it.
  19. ** This clause shall not be construed as constraining other software
  20. ** distributed on the same medium as this software, nor is a
  21. ** distribution fee considered a charge.
  22. **
  23. ***************************************************************************/
  24. /*
  25. This file contains a series of tests for the Meschach matrix
  26. library, complex routines
  27. */
  28. static char rcsid[] = "$Id: $";
  29. #include <stdio.h>
  30. #include <math.h>
  31. #include "zmatrix2.h"
  32. #include "matlab.h"
  33. #define errmesg(mesg) printf("Error: %s error: line %d\n",mesg,__LINE__)
  34. #define notice(mesg) printf("# Testing %s...\n",mesg);
  35. /* extern int malloc_chain_check(); */
  36. /* #define MEMCHK() if ( malloc_chain_check(0) ) \
  37. { printf("Error in malloc chain: \"%s\", line %d\n", \
  38. __FILE__, __LINE__); exit(0); } */
  39. #define MEMCHK()
  40. #define checkpt() printf("At line %d in file \"%s\"\n",__LINE__,__FILE__)
  41. /* cmp_perm -- returns 1 if pi1 == pi2, 0 otherwise */
  42. int cmp_perm(pi1, pi2)
  43. PERM *pi1, *pi2;
  44. {
  45. int i;
  46. if ( ! pi1 || ! pi2 )
  47. error(E_NULL,"cmp_perm");
  48. if ( pi1->size != pi2->size )
  49. return 0;
  50. for ( i = 0; i < pi1->size; i++ )
  51. if ( pi1->pe[i] != pi2->pe[i] )
  52. return 0;
  53. return 1;
  54. }
  55. /* px_rand -- generates sort-of random permutation */
  56. PERM *px_rand(pi)
  57. PERM *pi;
  58. {
  59. int i, j, k;
  60. if ( ! pi )
  61. error(E_NULL,"px_rand");
  62. for ( i = 0; i < 3*pi->size; i++ )
  63. {
  64. j = (rand() >> 8) % pi->size;
  65. k = (rand() >> 8) % pi->size;
  66. px_transp(pi,j,k);
  67. }
  68. return pi;
  69. }
  70. #define SAVE_FILE "asx5213a.mat"
  71. #define MATLAB_NAME "alpha"
  72. char name[81] = MATLAB_NAME;
  73. void main(argc, argv)
  74. int argc;
  75. char *argv[];
  76. {
  77. ZVEC *x = ZVNULL, *y = ZVNULL, *z = ZVNULL, *u = ZVNULL;
  78. ZVEC *diag = ZVNULL;
  79. PERM *pi1 = PNULL, *pi2 = PNULL, *pivot = PNULL;
  80. ZMAT *A = ZMNULL, *B = ZMNULL, *C = ZMNULL, *D = ZMNULL,
  81. *Q = ZMNULL;
  82. complex ONE;
  83. complex z1, z2, z3;
  84. Real cond_est, s1, s2, s3;
  85. int i, seed;
  86. FILE *fp;
  87. char *cp;
  88. mem_info_on(TRUE);
  89. setbuf(stdout,(char *)NULL);
  90. seed = 1111;
  91. if ( argc > 2 )
  92. {
  93. printf("usage: %s [seed]\n",argv[0]);
  94. exit(0);
  95. }
  96. else if ( argc == 2 )
  97. sscanf(argv[1], "%d", &seed);
  98. /* set seed for rand() */
  99. smrand(seed);
  100. /* print out version information */
  101. m_version();
  102. printf("# Meschach Complex numbers & vectors torture test\n\n");
  103. printf("# grep \"^Error\" the output for a listing of errors\n");
  104. printf("# Don't panic if you see \"Error\" appearing; \n");
  105. printf("# Also check the reported size of error\n");
  106. printf("# This program uses randomly generated problems and therefore\n");
  107. printf("# may occasionally produce ill-conditioned problems\n");
  108. printf("# Therefore check the size of the error compared with MACHEPS\n");
  109. printf("# If the error is within 1000*MACHEPS then don't worry\n");
  110. printf("# If you get an error of size 0.1 or larger there is \n");
  111. printf("# probably a bug in the code or the compilation procedure\n\n");
  112. printf("# seed = %d\n",seed);
  113. printf("\n");
  114. mem_stat_mark(1);
  115. notice("complex arithmetic & special functions");
  116. ONE = zmake(1.0,0.0);
  117. printf("# ONE = "); z_output(ONE);
  118. z1.re = mrand(); z1.im = mrand();
  119. z2.re = mrand(); z2.im = mrand();
  120. z3 = zadd(z1,z2);
  121. if ( fabs(z1.re+z2.re-z3.re) + fabs(z1.im+z2.im-z3.im) > 10*MACHEPS )
  122. errmesg("zadd");
  123. z3 = zsub(z1,z2);
  124. if ( fabs(z1.re-z2.re-z3.re) + fabs(z1.im-z2.im-z3.im) > 10*MACHEPS )
  125. errmesg("zadd");
  126. z3 = zmlt(z1,z2);
  127. if ( fabs(z1.re*z2.re - z1.im*z2.im - z3.re) +
  128. fabs(z1.im*z2.re + z1.re*z2.im - z3.im) > 10*MACHEPS )
  129. errmesg("zmlt");
  130. s1 = zabs(z1);
  131. if ( fabs(s1*s1 - (z1.re*z1.re+z1.im*z1.im)) > 10*MACHEPS )
  132. errmesg("zabs");
  133. if ( zabs(zsub(z1,zmlt(z2,zdiv(z1,z2)))) > 10*MACHEPS ||
  134. zabs(zsub(ONE,zdiv(z1,zmlt(z2,zdiv(z1,z2))))) > 10*MACHEPS )
  135. errmesg("zdiv");
  136. z3 = zsqrt(z1);
  137. if ( zabs(zsub(z1,zmlt(z3,z3))) > 10*MACHEPS )
  138. errmesg("zsqrt");
  139. if ( zabs(zsub(z1,zlog(zexp(z1)))) > 10*MACHEPS )
  140. errmesg("zexp/zlog");
  141. printf("# Check: MACHEPS = %g\n",MACHEPS);
  142. /* allocate, initialise, copy and resize operations */
  143. /* ZVEC */
  144. notice("vector initialise, copy & resize");
  145. x = zv_get(12);
  146. y = zv_get(15);
  147. z = zv_get(12);
  148. zv_rand(x);
  149. zv_rand(y);
  150. z = zv_copy(x,z);
  151. if ( zv_norm2(zv_sub(x,z,z)) >= MACHEPS )
  152. errmesg("ZVEC copy");
  153. zv_copy(x,y);
  154. x = zv_resize(x,10);
  155. y = zv_resize(y,10);
  156. if ( zv_norm2(zv_sub(x,y,z)) >= MACHEPS )
  157. errmesg("ZVEC copy/resize");
  158. x = zv_resize(x,15);
  159. y = zv_resize(y,15);
  160. if ( zv_norm2(zv_sub(x,y,z)) >= MACHEPS )
  161. errmesg("VZEC resize");
  162. /* ZMAT */
  163. notice("matrix initialise, copy & resize");
  164. A = zm_get(8,5);
  165. B = zm_get(3,9);
  166. C = zm_get(8,5);
  167. zm_rand(A);
  168. zm_rand(B);
  169. C = zm_copy(A,C);
  170. if ( zm_norm_inf(zm_sub(A,C,C)) >= MACHEPS )
  171. errmesg("ZMAT copy");
  172. zm_copy(A,B);
  173. A = zm_resize(A,3,5);
  174. B = zm_resize(B,3,5);
  175. if ( zm_norm_inf(zm_sub(A,B,C)) >= MACHEPS )
  176. errmesg("ZMAT copy/resize");
  177. A = zm_resize(A,10,10);
  178. B = zm_resize(B,10,10);
  179. if ( zm_norm_inf(zm_sub(A,B,C)) >= MACHEPS )
  180. errmesg("ZMAT resize");
  181. MEMCHK();
  182. /* PERM */
  183. notice("permutation initialise, inverting & permuting vectors");
  184. pi1 = px_get(15);
  185. pi2 = px_get(12);
  186. px_rand(pi1);
  187. zv_rand(x);
  188. px_zvec(pi1,x,z);
  189. y = zv_resize(y,x->dim);
  190. pxinv_zvec(pi1,z,y);
  191. if ( zv_norm2(zv_sub(x,y,z)) >= MACHEPS )
  192. errmesg("PERMute vector");
  193. /* testing catch() etc */
  194. notice("error handling routines");
  195. catch(E_NULL,
  196. catchall(zv_add(ZVNULL,ZVNULL,ZVNULL);
  197. errmesg("tracecatch() failure"),
  198. printf("# tracecatch() caught error\n");
  199. error(E_NULL,"main"));
  200. errmesg("catch() failure"),
  201. printf("# catch() caught E_NULL error\n"));
  202. /* testing inner products and v_mltadd() etc */
  203. notice("inner products and linear combinations");
  204. u = zv_get(x->dim);
  205. zv_rand(u);
  206. zv_rand(x);
  207. zv_resize(y,x->dim);
  208. zv_rand(y);
  209. zv_mltadd(y,x,zneg(zdiv(zin_prod(x,y),zin_prod(x,x))),z);
  210. if ( zabs(zin_prod(x,z)) >= 5*MACHEPS*x->dim )
  211. {
  212. errmesg("zv_mltadd()/zin_prod()");
  213. printf("# error norm = %g\n", zabs(zin_prod(x,z)));
  214. }
  215. z1 = zneg(zdiv(zin_prod(x,y),zmake(zv_norm2(x)*zv_norm2(x),0.0)));
  216. zv_mlt(z1,x,u);
  217. zv_add(y,u,u);
  218. if ( zv_norm2(zv_sub(u,z,u)) >= MACHEPS*x->dim )
  219. {
  220. errmesg("zv_mlt()/zv_norm2()");
  221. printf("# error norm = %g\n", zv_norm2(u));
  222. }
  223. #ifdef ANSI_C
  224. zv_linlist(u,x,z1,y,ONE,VNULL);
  225. if ( zv_norm2(zv_sub(u,z,u)) >= MACHEPS*x->dim )
  226. errmesg("zv_linlist()");
  227. #endif
  228. #ifdef VARARGS
  229. zv_linlist(u,x,z1,y,ONE,VNULL);
  230. if ( zv_norm2(zv_sub(u,z,u)) >= MACHEPS*x->dim )
  231. errmesg("zv_linlist()");
  232. #endif
  233. MEMCHK();
  234. /* vector norms */
  235. notice("vector norms");
  236. x = zv_resize(x,12);
  237. zv_rand(x);
  238. for ( i = 0; i < x->dim; i++ )
  239. if ( zabs(zv_entry(x,i)) >= 0.7 )
  240. zv_set_val(x,i,ONE);
  241. else
  242. zv_set_val(x,i,zneg(ONE));
  243. s1 = zv_norm1(x);
  244. s2 = zv_norm2(x);
  245. s3 = zv_norm_inf(x);
  246. if ( fabs(s1 - x->dim) >= MACHEPS*x->dim ||
  247. fabs(s2 - sqrt((double)(x->dim))) >= MACHEPS*x->dim ||
  248. fabs(s3 - 1.0) >= MACHEPS )
  249. errmesg("zv_norm1/2/_inf()");
  250. /* test matrix multiply etc */
  251. notice("matrix multiply and invert");
  252. A = zm_resize(A,10,10);
  253. B = zm_resize(B,10,10);
  254. zm_rand(A);
  255. zm_inverse(A,B);
  256. zm_mlt(A,B,C);
  257. for ( i = 0; i < C->m; i++ )
  258. zm_sub_val(C,i,i,ONE);
  259. if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
  260. errmesg("zm_inverse()/zm_mlt()");
  261. MEMCHK();
  262. /* ... and adjoints */
  263. notice("adjoints and adjoint-multiplies");
  264. zm_adjoint(A,A); /* can do square matrices in situ */
  265. zmam_mlt(A,B,C);
  266. for ( i = 0; i < C->m; i++ )
  267. zm_set_val(C,i,i,zsub(zm_entry(C,i,i),ONE));
  268. if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
  269. errmesg("zm_adjoint()/zmam_mlt()");
  270. zm_adjoint(A,A);
  271. zm_adjoint(B,B);
  272. zmma_mlt(A,B,C);
  273. for ( i = 0; i < C->m; i++ )
  274. zm_set_val(C,i,i,zsub(zm_entry(C,i,i),ONE));
  275. if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
  276. errmesg("zm_adjoint()/zmma_mlt()");
  277. zsm_mlt(zmake(3.71,2.753),B,B);
  278. zmma_mlt(A,B,C);
  279. for ( i = 0; i < C->m; i++ )
  280. zm_set_val(C,i,i,zsub(zm_entry(C,i,i),zmake(3.71,-2.753)));
  281. if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
  282. errmesg("szm_mlt()/zmma_mlt()");
  283. zm_adjoint(B,B);
  284. zsm_mlt(zdiv(ONE,zmake(3.71,-2.753)),B,B);
  285. MEMCHK();
  286. /* ... and matrix-vector multiplies */
  287. notice("matrix-vector multiplies");
  288. x = zv_resize(x,A->n);
  289. y = zv_resize(y,A->m);
  290. z = zv_resize(z,A->m);
  291. u = zv_resize(u,A->n);
  292. zv_rand(x);
  293. zv_rand(y);
  294. zmv_mlt(A,x,z);
  295. z1 = zin_prod(y,z);
  296. zvm_mlt(A,y,u);
  297. z2 = zin_prod(u,x);
  298. if ( zabs(zsub(z1,z2)) >= (MACHEPS*x->dim)*x->dim )
  299. {
  300. errmesg("zmv_mlt()/zvm_mlt()");
  301. printf("# difference between inner products is %g\n",
  302. zabs(zsub(z1,z2)));
  303. }
  304. zmv_mlt(B,z,u);
  305. if ( zv_norm2(zv_sub(u,x,u)) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
  306. errmesg("zmv_mlt()/zvm_mlt()");
  307. MEMCHK();
  308. /* get/set row/col */
  309. notice("getting and setting rows and cols");
  310. x = zv_resize(x,A->n);
  311. y = zv_resize(y,B->m);
  312. x = zget_row(A,3,x);
  313. y = zget_col(B,3,y);
  314. if ( zabs(zsub(_zin_prod(x,y,0,Z_NOCONJ),ONE)) >=
  315. MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
  316. errmesg("zget_row()/zget_col()");
  317. zv_mlt(zmake(-1.0,0.0),x,x);
  318. zv_mlt(zmake(-1.0,0.0),y,y);
  319. zset_row(A,3,x);
  320. zset_col(B,3,y);
  321. zm_mlt(A,B,C);
  322. for ( i = 0; i < C->m; i++ )
  323. zm_set_val(C,i,i,zsub(zm_entry(C,i,i),ONE));
  324. if ( zm_norm_inf(C) >= MACHEPS*zm_norm_inf(A)*zm_norm_inf(B)*5 )
  325. errmesg("zset_row()/zset_col()");
  326. MEMCHK();
  327. /* matrix norms */
  328. notice("matrix norms");
  329. A = zm_resize(A,11,15);
  330. zm_rand(A);
  331. s1 = zm_norm_inf(A);
  332. B = zm_adjoint(A,B);
  333. s2 = zm_norm1(B);
  334. if ( fabs(s1 - s2) >= MACHEPS*A->m )
  335. errmesg("zm_norm1()/zm_norm_inf()");
  336. C = zmam_mlt(A,A,C);
  337. z1.re = z1.im = 0.0;
  338. for ( i = 0; i < C->m && i < C->n; i++ )
  339. z1 = zadd(z1,zm_entry(C,i,i));
  340. if ( fabs(sqrt(z1.re) - zm_norm_frob(A)) >= MACHEPS*A->m*A->n )
  341. errmesg("zm_norm_frob");
  342. MEMCHK();
  343. /* permuting rows and columns */
  344. /******************************
  345. notice("permuting rows & cols");
  346. A = zm_resize(A,11,15);
  347. B = zm_resize(B,11,15);
  348. pi1 = px_resize(pi1,A->m);
  349. px_rand(pi1);
  350. x = zv_resize(x,A->n);
  351. y = zmv_mlt(A,x,y);
  352. px_rows(pi1,A,B);
  353. px_zvec(pi1,y,z);
  354. zmv_mlt(B,x,u);
  355. if ( zv_norm2(zv_sub(z,u,u)) >= MACHEPS*A->m )
  356. errmesg("px_rows()");
  357. pi1 = px_resize(pi1,A->n);
  358. px_rand(pi1);
  359. px_cols(pi1,A,B);
  360. pxinv_zvec(pi1,x,z);
  361. zmv_mlt(B,z,u);
  362. if ( zv_norm2(zv_sub(y,u,u)) >= MACHEPS*A->n )
  363. errmesg("px_cols()");
  364. ******************************/
  365. MEMCHK();
  366. /* MATLAB save/load */
  367. notice("MATLAB save/load");
  368. A = zm_resize(A,12,11);
  369. if ( (fp=fopen(SAVE_FILE,"w")) == (FILE *)NULL )
  370. printf("Cannot perform MATLAB save/load test\n");
  371. else
  372. {
  373. zm_rand(A);
  374. zm_save(fp, A, name);
  375. fclose(fp);
  376. if ( (fp=fopen(SAVE_FILE,"r")) == (FILE *)NULL )
  377. printf("Cannot open save file \"%s\"\n",SAVE_FILE);
  378. else
  379. {
  380. ZM_FREE(B);
  381. B = zm_load(fp,&cp);
  382. if ( strcmp(name,cp) || zm_norm1(zm_sub(A,B,C)) >=
  383. MACHEPS*A->m )
  384. {
  385. errmesg("zm_load()/zm_save()");
  386. printf("# orig. name = %s, restored name = %s\n", name, cp);
  387. printf("# orig. A =\n"); zm_output(A);
  388. printf("# restored A =\n"); zm_output(B);
  389. }
  390. }
  391. }
  392. MEMCHK();
  393. /* Now, onto matrix factorisations */
  394. A = zm_resize(A,10,10);
  395. B = zm_resize(B,A->m,A->n);
  396. zm_copy(A,B);
  397. x = zv_resize(x,A->n);
  398. y = zv_resize(y,A->m);
  399. z = zv_resize(z,A->n);
  400. u = zv_resize(u,A->m);
  401. zv_rand(x);
  402. zmv_mlt(B,x,y);
  403. z = zv_copy(x,z);
  404. notice("LU factor/solve");
  405. pivot = px_get(A->m);
  406. zLUfactor(A,pivot);
  407. tracecatch(zLUsolve(A,pivot,y,x),"main");
  408. tracecatch(cond_est = zLUcondest(A,pivot),"main");
  409. printf("# cond(A) approx= %g\n", cond_est);
  410. if ( zv_norm2(zv_sub(x,z,u)) >= MACHEPS*zv_norm2(x)*cond_est)
  411. {
  412. errmesg("zLUfactor()/zLUsolve()");
  413. printf("# LU solution error = %g [cf MACHEPS = %g]\n",
  414. zv_norm2(zv_sub(x,z,u)), MACHEPS);
  415. }
  416. zv_copy(y,x);
  417. tracecatch(zLUsolve(A,pivot,x,x),"main");
  418. tracecatch(cond_est = zLUcondest(A,pivot),"main");
  419. if ( zv_norm2(zv_sub(x,z,u)) >= MACHEPS*zv_norm2(x)*cond_est)
  420. {
  421. errmesg("zLUfactor()/zLUsolve()");
  422. printf("# LU solution error = %g [cf MACHEPS = %g]\n",
  423. zv_norm2(zv_sub(x,z,u)), MACHEPS);
  424. }
  425. zvm_mlt(B,z,y);
  426. zv_copy(y,x);
  427. tracecatch(zLUAsolve(A,pivot,x,x),"main");
  428. if ( zv_norm2(zv_sub(x,z,u)) >= MACHEPS*zv_norm2(x)*cond_est)
  429. {
  430. errmesg("zLUfactor()/zLUAsolve()");
  431. printf("# LU solution error = %g [cf MACHEPS = %g]\n",
  432. zv_norm2(zv_sub(x,z,u)), MACHEPS);
  433. }
  434. MEMCHK();
  435. /* QR factorisation */
  436. zm_copy(B,A);
  437. zmv_mlt(B,z,y);
  438. notice("QR factor/solve:");
  439. diag = zv_get(A->m);
  440. zQRfactor(A,diag);
  441. zQRsolve(A,diag,y,x);
  442. if ( zv_norm2(zv_sub(x,z,u)) >= MACHEPS*zv_norm2(x)*cond_est )
  443. {
  444. errmesg("zQRfactor()/zQRsolve()");
  445. printf("# QR solution error = %g [cf MACHEPS = %g]\n",
  446. zv_norm2(zv_sub(x,z,u)), MACHEPS);
  447. }
  448. printf("# QR cond(A) approx= %g\n", zQRcondest(A));
  449. Q = zm_get(A->m,A->m);
  450. zmakeQ(A,diag,Q);
  451. zmakeR(A,A);
  452. zm_mlt(Q,A,C);
  453. zm_sub(B,C,C);
  454. if ( zm_norm1(C) >= MACHEPS*zm_norm1(Q)*zm_norm1(B) )
  455. {
  456. errmesg("zQRfactor()/zmakeQ()/zmakeR()");
  457. printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n",
  458. zm_norm1(C), MACHEPS);
  459. }
  460. MEMCHK();
  461. /* now try with a non-square matrix */
  462. A = zm_resize(A,15,7);
  463. zm_rand(A);
  464. B = zm_copy(A,B);
  465. diag = zv_resize(diag,A->n);
  466. x = zv_resize(x,A->n);
  467. y = zv_resize(y,A->m);
  468. zv_rand(y);
  469. zQRfactor(A,diag);
  470. x = zQRsolve(A,diag,y,x);
  471. /* z is the residual vector */
  472. zmv_mlt(B,x,z); zv_sub(z,y,z);
  473. /* check B*.z = 0 */
  474. zvm_mlt(B,z,u);
  475. if ( zv_norm2(u) >= 100*MACHEPS*zm_norm1(B)*zv_norm2(y) )
  476. {
  477. errmesg("zQRfactor()/zQRsolve()");
  478. printf("# QR solution error = %g [cf MACHEPS = %g]\n",
  479. zv_norm2(u), MACHEPS);
  480. }
  481. Q = zm_resize(Q,A->m,A->m);
  482. zmakeQ(A,diag,Q);
  483. zmakeR(A,A);
  484. zm_mlt(Q,A,C);
  485. zm_sub(B,C,C);
  486. if ( zm_norm1(C) >= MACHEPS*zm_norm1(Q)*zm_norm1(B) )
  487. {
  488. errmesg("zQRfactor()/zmakeQ()/zmakeR()");
  489. printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n",
  490. zm_norm1(C), MACHEPS);
  491. }
  492. D = zm_get(A->m,Q->m);
  493. zmam_mlt(Q,Q,D);
  494. for ( i = 0; i < D->m; i++ )
  495. zm_set_val(D,i,i,zsub(zm_entry(D,i,i),ONE));
  496. if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm_inf(Q) )
  497. {
  498. errmesg("QRfactor()/makeQ()/makeR()");
  499. printf("# QR orthogonality error = %g [cf MACHEPS = %g]\n",
  500. zm_norm1(D), MACHEPS);
  501. }
  502. MEMCHK();
  503. /* QRCP factorisation */
  504. zm_copy(B,A);
  505. notice("QR factor/solve with column pivoting");
  506. pivot = px_resize(pivot,A->n);
  507. zQRCPfactor(A,diag,pivot);
  508. z = zv_resize(z,A->n);
  509. zQRCPsolve(A,diag,pivot,y,z);
  510. /* pxinv_zvec(pivot,z,x); */
  511. /* now compute residual (z) vector */
  512. zmv_mlt(B,x,z); zv_sub(z,y,z);
  513. /* check B^T.z = 0 */
  514. zvm_mlt(B,z,u);
  515. if ( zv_norm2(u) >= MACHEPS*zm_norm1(B)*zv_norm2(y) )
  516. {
  517. errmesg("QRCPfactor()/QRsolve()");
  518. printf("# QR solution error = %g [cf MACHEPS = %g]\n",
  519. zv_norm2(u), MACHEPS);
  520. }
  521. Q = zm_resize(Q,A->m,A->m);
  522. zmakeQ(A,diag,Q);
  523. zmakeR(A,A);
  524. zm_mlt(Q,A,C);
  525. ZM_FREE(D);
  526. D = zm_get(B->m,B->n);
  527. /******************************
  528. px_cols(pivot,C,D);
  529. zm_sub(B,D,D);
  530. if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm1(B) )
  531. {
  532. errmesg("QRCPfactor()/makeQ()/makeR()");
  533. printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n",
  534. zm_norm1(D), MACHEPS);
  535. }
  536. ******************************/
  537. /* Now check eigenvalue/SVD routines */
  538. notice("complex Schur routines");
  539. A = zm_resize(A,11,11);
  540. B = zm_resize(B,A->m,A->n);
  541. C = zm_resize(C,A->m,A->n);
  542. D = zm_resize(D,A->m,A->n);
  543. Q = zm_resize(Q,A->m,A->n);
  544. MEMCHK();
  545. /* now test complex Schur decomposition */
  546. /* zm_copy(A,B); */
  547. ZM_FREE(A);
  548. A = zm_get(11,11);
  549. zm_rand(A);
  550. B = zm_copy(A,B);
  551. MEMCHK();
  552. B = zschur(B,Q);
  553. checkpt();
  554. zm_mlt(Q,B,C);
  555. zmma_mlt(C,Q,D);
  556. MEMCHK();
  557. zm_sub(A,D,D);
  558. if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm_inf(Q)*zm_norm1(B)*5 )
  559. {
  560. errmesg("zschur()");
  561. printf("# Schur reconstruction error = %g [cf MACHEPS = %g]\n",
  562. zm_norm1(D), MACHEPS);
  563. }
  564. /* orthogonality check */
  565. zmma_mlt(Q,Q,D);
  566. for ( i = 0; i < D->m; i++ )
  567. zm_set_val(D,i,i,zsub(zm_entry(D,i,i),ONE));
  568. if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm_inf(Q)*10 )
  569. {
  570. errmesg("zschur()");
  571. printf("# Schur orthogonality error = %g [cf MACHEPS = %g]\n",
  572. zm_norm1(D), MACHEPS);
  573. }
  574. MEMCHK();
  575. /* now test SVD */
  576. /******************************
  577. A = zm_resize(A,11,7);
  578. zm_rand(A);
  579. U = zm_get(A->n,A->n);
  580. Q = zm_resize(Q,A->m,A->m);
  581. u = zv_resize(u,max(A->m,A->n));
  582. svd(A,Q,U,u);
  583. ******************************/
  584. /* check reconstruction of A */
  585. /******************************
  586. D = zm_resize(D,A->m,A->n);
  587. C = zm_resize(C,A->m,A->n);
  588. zm_zero(D);
  589. for ( i = 0; i < min(A->m,A->n); i++ )
  590. zm_set_val(D,i,i,v_entry(u,i));
  591. zmam_mlt(Q,D,C);
  592. zm_mlt(C,U,D);
  593. zm_sub(A,D,D);
  594. if ( zm_norm1(D) >= MACHEPS*zm_norm1(U)*zm_norm_inf(Q)*zm_norm1(A) )
  595. {
  596. errmesg("svd()");
  597. printf("# SVD reconstruction error = %g [cf MACHEPS = %g]\n",
  598. zm_norm1(D), MACHEPS);
  599. }
  600. ******************************/
  601. /* check orthogonality of Q and U */
  602. /******************************
  603. D = zm_resize(D,Q->n,Q->n);
  604. zmam_mlt(Q,Q,D);
  605. for ( i = 0; i < D->m; i++ )
  606. m_set_val(D,i,i,m_entry(D,i,i)-1.0);
  607. if ( zm_norm1(D) >= MACHEPS*zm_norm1(Q)*zm_norm_inf(Q)*5 )
  608. {
  609. errmesg("svd()");
  610. printf("# SVD orthognality error (Q) = %g [cf MACHEPS = %g\n",
  611. zm_norm1(D), MACHEPS);
  612. }
  613. D = zm_resize(D,U->n,U->n);
  614. zmam_mlt(U,U,D);
  615. for ( i = 0; i < D->m; i++ )
  616. m_set_val(D,i,i,m_entry(D,i,i)-1.0);
  617. if ( zm_norm1(D) >= MACHEPS*zm_norm1(U)*zm_norm_inf(U)*5 )
  618. {
  619. errmesg("svd()");
  620. printf("# SVD orthognality error (U) = %g [cf MACHEPS = %g\n",
  621. zm_norm1(D), MACHEPS);
  622. }
  623. for ( i = 0; i < u->dim; i++ )
  624. if ( v_entry(u,i) < 0 || (i < u->dim-1 &&
  625. v_entry(u,i+1) > v_entry(u,i)) )
  626. break;
  627. if ( i < u->dim )
  628. {
  629. errmesg("svd()");
  630. printf("# SVD sorting error\n");
  631. }
  632. ******************************/
  633. ZV_FREE(x); ZV_FREE(y); ZV_FREE(z);
  634. ZV_FREE(u); ZV_FREE(diag);
  635. PX_FREE(pi1); PX_FREE(pi2); PX_FREE(pivot);
  636. ZM_FREE(A); ZM_FREE(B); ZM_FREE(C);
  637. ZM_FREE(D); ZM_FREE(Q);
  638. mem_stat_free(1);
  639. MEMCHK();
  640. printf("# Finished torture test for complex numbers/vectors/matrices\n");
  641. mem_info();
  642. }