itertort.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  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. /* iter_tort.c 16/09/93 */
  25. /*
  26. This file contains tests for the iterative part of Meschach
  27. */
  28. #include <stdio.h>
  29. #include "matrix2.h"
  30. #include "sparse2.h"
  31. #include "iter.h"
  32. #include <math.h>
  33. #define errmesg(mesg) printf("Error: %s error: line %d\n",mesg,__LINE__)
  34. #define notice(mesg) printf("# Testing %s...\n",mesg);
  35. /* for iterative methods */
  36. #if REAL == DOUBLE
  37. #define EPS 1e-7
  38. #define KK 20
  39. #elif REAL == FLOAT
  40. #define EPS 1e-5
  41. #define KK 8
  42. #endif
  43. #define ANON 513
  44. #define ASYM ANON
  45. static VEC *ex_sol = VNULL;
  46. /* new iter information */
  47. void iter_mod_info(ip,nres,res,Bres)
  48. ITER *ip;
  49. double nres;
  50. VEC *res, *Bres;
  51. {
  52. static VEC *tmp;
  53. if (ip->b == VNULL) return;
  54. tmp = v_resize(tmp,ip->b->dim);
  55. MEM_STAT_REG(tmp,TYPE_VEC);
  56. if (nres >= 0.0) {
  57. printf(" %d. residual = %g\n",ip->steps,nres);
  58. }
  59. else
  60. printf(" %d. residual = %g (WARNING !!! should be >= 0) \n",
  61. ip->steps,nres);
  62. if (ex_sol != VNULL)
  63. printf(" ||u_ex - u_approx||_2 = %g\n",
  64. v_norm2(v_sub(ip->x,ex_sol,tmp)));
  65. }
  66. /* out = A^T*A*x */
  67. VEC *norm_equ(A,x,out)
  68. SPMAT *A;
  69. VEC *x, *out;
  70. {
  71. static VEC * tmp;
  72. tmp = v_resize(tmp,x->dim);
  73. MEM_STAT_REG(tmp,TYPE_VEC);
  74. sp_mv_mlt(A,x,tmp);
  75. sp_vm_mlt(A,tmp,out);
  76. return out;
  77. }
  78. /*
  79. make symmetric preconditioner for nonsymmetric matrix A;
  80. B = 0.5*(A+A^T) and then B is factorized using
  81. incomplete Choleski factorization
  82. */
  83. SPMAT *gen_sym_precond(A)
  84. SPMAT *A;
  85. {
  86. SPMAT *B;
  87. SPROW *row;
  88. int i,j,k;
  89. Real val;
  90. B = sp_get(A->m,A->n,A->row[0].maxlen);
  91. for (i=0; i < A->m; i++) {
  92. row = &(A->row[i]);
  93. for (j = 0; j < row->len; j++) {
  94. k = row->elt[j].col;
  95. if (i != k) {
  96. val = 0.5*(sp_get_val(A,i,k) + sp_get_val(A,k,i));
  97. sp_set_val(B,i,k,val);
  98. sp_set_val(B,k,i,val);
  99. }
  100. else { /* i == k */
  101. val = sp_get_val(A,i,i);
  102. sp_set_val(B,i,i,val);
  103. }
  104. }
  105. }
  106. spICHfactor(B);
  107. return B;
  108. }
  109. /* Dv_mlt -- diagonal by vector multiply; the diagonal matrix is represented
  110. by a vector d */
  111. VEC *Dv_mlt(d, x, out)
  112. VEC *d, *x, *out;
  113. {
  114. int i;
  115. if ( ! d || ! x )
  116. error(E_NULL,"Dv_mlt");
  117. if ( d->dim != x->dim )
  118. error(E_SIZES,"Dv_mlt");
  119. out = v_resize(out,x->dim);
  120. for ( i = 0; i < x->dim; i++ )
  121. out->ve[i] = d->ve[i]*x->ve[i];
  122. return out;
  123. }
  124. /************************************************/
  125. void main(argc, argv)
  126. int argc;
  127. char *argv[];
  128. {
  129. VEC *x, *y, *z, *u, *v, *xn, *yn;
  130. SPMAT *A = NULL, *B = NULL;
  131. SPMAT *An = NULL, *Bn = NULL;
  132. int i, k, kk, j;
  133. ITER *ips, *ips1, *ipns, *ipns1;
  134. MAT *Q, *H, *Q1, *H1;
  135. VEC vt, vt1;
  136. Real hh;
  137. mem_info_on(TRUE);
  138. notice("allocating sparse matrices");
  139. printf(" dim of A = %dx%d\n",ASYM,ASYM);
  140. A = iter_gen_sym(ASYM,8);
  141. B = sp_copy(A);
  142. spICHfactor(B);
  143. u = v_get(A->n);
  144. x = v_get(A->n);
  145. y = v_get(A->n);
  146. v = v_get(A->n);
  147. v_rand(x);
  148. sp_mv_mlt(A,x,y);
  149. ex_sol = x;
  150. notice(" initialize ITER variables");
  151. /* ips for symmetric matrices with precondition */
  152. ips = iter_get(A->m,A->n);
  153. /* printf(" ips:\n");
  154. iter_dump(stdout,ips); */
  155. ips->limit = 500;
  156. ips->eps = EPS;
  157. iter_Ax(ips,sp_mv_mlt,A);
  158. iter_Bx(ips,spCHsolve,B);
  159. ips->b = v_copy(y,ips->b);
  160. v_rand(ips->x);
  161. /* test of iter_resize */
  162. ips = iter_resize(ips,2*A->m,2*A->n);
  163. ips = iter_resize(ips,A->m,A->n);
  164. /* printf(" ips:\n");
  165. iter_dump(stdout,ips); */
  166. /* ips1 for symmetric matrices without precondition */
  167. ips1 = iter_get(0,0);
  168. /* printf(" ips1:\n");
  169. iter_dump(stdout,ips1); */
  170. ITER_FREE(ips1);
  171. ips1 = iter_copy2(ips,ips1);
  172. iter_Bx(ips1,NULL,NULL);
  173. ips1->b = ips->b;
  174. ips1->shared_b = TRUE;
  175. /* printf(" ips1:\n");
  176. iter_dump(stdout,ips1); */
  177. /* ipns for nonsymetric matrices with precondition */
  178. ipns = iter_copy(ips,INULL);
  179. ipns->k = KK;
  180. ipns->limit = 500;
  181. ipns->info = NULL;
  182. An = iter_gen_nonsym_posdef(ANON,8);
  183. Bn = gen_sym_precond(An);
  184. xn = v_get(An->n);
  185. yn = v_get(An->n);
  186. v_rand(xn);
  187. sp_mv_mlt(An,xn,yn);
  188. ipns->b = v_copy(yn,ipns->b);
  189. iter_Ax(ipns, sp_mv_mlt,An);
  190. iter_ATx(ipns, sp_vm_mlt,An);
  191. iter_Bx(ipns, spCHsolve,Bn);
  192. /* printf(" ipns:\n");
  193. iter_dump(stdout,ipns); */
  194. /* ipns1 for nonsymmetric matrices without precondition */
  195. ipns1 = iter_copy2(ipns,INULL);
  196. ipns1->b = ipns->b;
  197. ipns1->shared_b = TRUE;
  198. iter_Bx(ipns1,NULL,NULL);
  199. /* printf(" ipns1:\n");
  200. iter_dump(stdout,ipns1); */
  201. /******* CG ********/
  202. notice(" CG method without preconditioning");
  203. ips1->info = NULL;
  204. mem_stat_mark(1);
  205. iter_cg(ips1);
  206. k = ips1->steps;
  207. z = ips1->x;
  208. printf(" cg: no. of iter.steps = %d\n",k);
  209. v_sub(z,x,u);
  210. printf(" (cg:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  211. v_norm2(u),EPS);
  212. notice(" CG method with ICH preconditioning");
  213. ips->info = NULL;
  214. v_zero(ips->x);
  215. iter_cg(ips);
  216. k = ips->steps;
  217. printf(" cg: no. of iter.steps = %d\n",k);
  218. v_sub(ips->x,x,u);
  219. printf(" (cg:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  220. v_norm2(u),EPS);
  221. V_FREE(v);
  222. if ((v = iter_spcg(A,B,y,EPS,VNULL,1000,&k)) == VNULL)
  223. errmesg("CG method with precond.: NULL solution");
  224. v_sub(ips->x,v,u);
  225. if (v_norm2(u) >= EPS) {
  226. errmesg("CG method with precond.: different solutions");
  227. printf(" diff. = %g\n",v_norm2(u));
  228. }
  229. mem_stat_free(1);
  230. printf(" spcg: # of iter. steps = %d\n",k);
  231. v_sub(v,x,u);
  232. printf(" (spcg:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  233. v_norm2(u),EPS);
  234. /*** CG FOR NORMAL EQUATION *****/
  235. notice("CGNE method with ICH preconditioning (nonsymmetric case)");
  236. /* ipns->info = iter_std_info; */
  237. ipns->info = NULL;
  238. v_zero(ipns->x);
  239. mem_stat_mark(1);
  240. iter_cgne(ipns);
  241. k = ipns->steps;
  242. z = ipns->x;
  243. printf(" cgne: no. of iter.steps = %d\n",k);
  244. v_sub(z,xn,u);
  245. printf(" (cgne:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  246. v_norm2(u),EPS);
  247. notice("CGNE method without preconditioning (nonsymmetric case)");
  248. v_rand(u);
  249. u = iter_spcgne(An,NULL,yn,EPS,u,1000,&k);
  250. mem_stat_free(1);
  251. printf(" spcgne: no. of iter.steps = %d\n",k);
  252. v_sub(u,xn,u);
  253. printf(" (spcgne:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  254. v_norm2(u),EPS);
  255. /*** CGS *****/
  256. notice("CGS method with ICH preconditioning (nonsymmetric case)");
  257. v_zero(ipns->x); /* new init guess == 0 */
  258. mem_stat_mark(1);
  259. ipns->info = NULL;
  260. v_rand(u);
  261. iter_cgs(ipns,u);
  262. k = ipns->steps;
  263. z = ipns->x;
  264. printf(" cgs: no. of iter.steps = %d\n",k);
  265. v_sub(z,xn,u);
  266. printf(" (cgs:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  267. v_norm2(u),EPS);
  268. notice("CGS method without preconditioning (nonsymmetric case)");
  269. v_rand(u);
  270. v_rand(v);
  271. v = iter_spcgs(An,NULL,yn,u,EPS,v,1000,&k);
  272. mem_stat_free(1);
  273. printf(" cgs: no. of iter.steps = %d\n",k);
  274. v_sub(v,xn,u);
  275. printf(" (cgs:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  276. v_norm2(u),EPS);
  277. /*** LSQR ***/
  278. notice("LSQR method (without preconditioning)");
  279. v_rand(u);
  280. v_free(ipns1->x);
  281. ipns1->x = u;
  282. ipns1->shared_x = TRUE;
  283. ipns1->info = NULL;
  284. mem_stat_mark(2);
  285. z = iter_lsqr(ipns1);
  286. v_sub(xn,z,v);
  287. k = ipns1->steps;
  288. printf(" lsqr: # of iter. steps = %d\n",k);
  289. printf(" (lsqr:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  290. v_norm2(v),EPS);
  291. v_rand(u);
  292. u = iter_splsqr(An,yn,EPS,u,1000,&k);
  293. mem_stat_free(2);
  294. v_sub(xn,u,v);
  295. printf(" splsqr: # of iter. steps = %d\n",k);
  296. printf(" (splsqr:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  297. v_norm2(v),EPS);
  298. /***** GMRES ********/
  299. notice("GMRES method with ICH preconditioning (nonsymmetric case)");
  300. v_zero(ipns->x);
  301. /* ipns->info = iter_std_info; */
  302. ipns->info = NULL;
  303. mem_stat_mark(2);
  304. z = iter_gmres(ipns);
  305. v_sub(xn,z,v);
  306. k = ipns->steps;
  307. printf(" gmres: # of iter. steps = %d\n",k);
  308. printf(" (gmres:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  309. v_norm2(v),EPS);
  310. notice("GMRES method without preconditioning (nonsymmetric case)");
  311. V_FREE(v);
  312. v = iter_spgmres(An,NULL,yn,EPS,VNULL,10,1004,&k);
  313. mem_stat_free(2);
  314. v_sub(xn,v,v);
  315. printf(" spgmres: # of iter. steps = %d\n",k);
  316. printf(" (spgmres:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  317. v_norm2(v),EPS);
  318. /**** MGCR *****/
  319. notice("MGCR method with ICH preconditioning (nonsymmetric case)");
  320. v_zero(ipns->x);
  321. mem_stat_mark(2);
  322. z = iter_mgcr(ipns);
  323. v_sub(xn,z,v);
  324. k = ipns->steps;
  325. printf(" mgcr: # of iter. steps = %d\n",k);
  326. printf(" (mgcr:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  327. v_norm2(v),EPS);
  328. notice("MGCR method without preconditioning (nonsymmetric case)");
  329. V_FREE(v);
  330. v = iter_spmgcr(An,NULL,yn,EPS,VNULL,10,1004,&k);
  331. mem_stat_free(2);
  332. v_sub(xn,v,v);
  333. printf(" spmgcr: # of iter. steps = %d\n",k);
  334. printf(" (spmgcr:) ||u_ex - u_approx||_2 = %g [EPS = %g]\n",
  335. v_norm2(v),EPS);
  336. /***** ARNOLDI METHOD ********/
  337. notice("arnoldi method");
  338. kk = ipns1->k = KK;
  339. Q = m_get(kk,x->dim);
  340. Q1 = m_get(kk,x->dim);
  341. H = m_get(kk,kk);
  342. v_rand(u);
  343. ipns1->x = u;
  344. ipns1->shared_x = TRUE;
  345. mem_stat_mark(3);
  346. iter_arnoldi_iref(ipns1,&hh,Q,H);
  347. mem_stat_free(3);
  348. /* check the equality:
  349. Q*A*Q^T = H; */
  350. vt.dim = vt.max_dim = x->dim;
  351. vt1.dim = vt1.max_dim = x->dim;
  352. for (j=0; j < kk; j++) {
  353. vt.ve = Q->me[j];
  354. vt1.ve = Q1->me[j];
  355. sp_mv_mlt(An,&vt,&vt1);
  356. }
  357. H1 = m_get(kk,kk);
  358. mmtr_mlt(Q,Q1,H1);
  359. m_sub(H,H1,H1);
  360. if (m_norm_inf(H1) > MACHEPS*x->dim)
  361. printf(" (arnoldi_iref) ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n",
  362. m_norm_inf(H1),MACHEPS);
  363. /* check Q*Q^T = I */
  364. mmtr_mlt(Q,Q,H1);
  365. for (j=0; j < kk; j++)
  366. H1->me[j][j] -= 1.0;
  367. if (m_norm_inf(H1) > MACHEPS*x->dim)
  368. printf(" (arnoldi_iref) ||Q*Q^T - I|| = %g [cf. MACHEPS = %g]\n",
  369. m_norm_inf(H1),MACHEPS);
  370. ipns1->x = u;
  371. ipns1->shared_x = TRUE;
  372. mem_stat_mark(3);
  373. iter_arnoldi(ipns1,&hh,Q,H);
  374. mem_stat_free(3);
  375. /* check the equality:
  376. Q*A*Q^T = H; */
  377. vt.dim = vt.max_dim = x->dim;
  378. vt1.dim = vt1.max_dim = x->dim;
  379. for (j=0; j < kk; j++) {
  380. vt.ve = Q->me[j];
  381. vt1.ve = Q1->me[j];
  382. sp_mv_mlt(An,&vt,&vt1);
  383. }
  384. mmtr_mlt(Q,Q1,H1);
  385. m_sub(H,H1,H1);
  386. if (m_norm_inf(H1) > MACHEPS*x->dim)
  387. printf(" (arnoldi) ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n",
  388. m_norm_inf(H1),MACHEPS);
  389. /* check Q*Q^T = I */
  390. mmtr_mlt(Q,Q,H1);
  391. for (j=0; j < kk; j++)
  392. H1->me[j][j] -= 1.0;
  393. if (m_norm_inf(H1) > MACHEPS*x->dim)
  394. printf(" (arnoldi) ||Q*Q^T - I|| = %g [cf. MACHEPS = %g]\n",
  395. m_norm_inf(H1),MACHEPS);
  396. v_rand(u);
  397. mem_stat_mark(3);
  398. iter_sparnoldi(An,u,kk,&hh,Q,H);
  399. mem_stat_free(3);
  400. /* check the equality:
  401. Q*A*Q^T = H; */
  402. vt.dim = vt.max_dim = x->dim;
  403. vt1.dim = vt1.max_dim = x->dim;
  404. for (j=0; j < kk; j++) {
  405. vt.ve = Q->me[j];
  406. vt1.ve = Q1->me[j];
  407. sp_mv_mlt(An,&vt,&vt1);
  408. }
  409. mmtr_mlt(Q,Q1,H1);
  410. m_sub(H,H1,H1);
  411. if (m_norm_inf(H1) > MACHEPS*x->dim)
  412. printf(" (sparnoldi) ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n",
  413. m_norm_inf(H1),MACHEPS);
  414. /* check Q*Q^T = I */
  415. mmtr_mlt(Q,Q,H1);
  416. for (j=0; j < kk; j++)
  417. H1->me[j][j] -= 1.0;
  418. if (m_norm_inf(H1) > MACHEPS*x->dim)
  419. printf(" (sparnoldi) ||Q*Q^T - I|| = %g [cf. MACHEPS = %g]\n",
  420. m_norm_inf(H1),MACHEPS);
  421. /****** LANCZOS METHOD ******/
  422. notice("lanczos method");
  423. kk = ipns1->k;
  424. Q = m_resize(Q,kk,x->dim);
  425. Q1 = m_resize(Q1,kk,x->dim);
  426. H = m_resize(H,kk,kk);
  427. ips1->k = kk;
  428. v_rand(u);
  429. v_free(ips1->x);
  430. ips1->x = u;
  431. ips1->shared_x = TRUE;
  432. mem_stat_mark(3);
  433. iter_lanczos(ips1,x,y,&hh,Q);
  434. mem_stat_free(3);
  435. /* check the equality:
  436. Q*A*Q^T = H; */
  437. vt.dim = vt1.dim = Q->n;
  438. vt.max_dim = vt1.max_dim = Q->max_n;
  439. Q1 = m_resize(Q1,Q->m,Q->n);
  440. for (j=0; j < Q->m; j++) {
  441. vt.ve = Q->me[j];
  442. vt1.ve = Q1->me[j];
  443. sp_mv_mlt(A,&vt,&vt1);
  444. }
  445. H1 = m_resize(H1,Q->m,Q->m);
  446. H = m_resize(H,Q->m,Q->m);
  447. mmtr_mlt(Q,Q1,H1);
  448. m_zero(H);
  449. for (j=0; j < Q->m-1; j++) {
  450. H->me[j][j] = x->ve[j];
  451. H->me[j][j+1] = H->me[j+1][j] = y->ve[j];
  452. }
  453. H->me[Q->m-1][Q->m-1] = x->ve[Q->m-1];
  454. m_sub(H,H1,H1);
  455. if (m_norm_inf(H1) > MACHEPS*x->dim)
  456. printf(" (lanczos) ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n",
  457. m_norm_inf(H1),MACHEPS);
  458. /* check Q*Q^T = I */
  459. mmtr_mlt(Q,Q,H1);
  460. for (j=0; j < Q->m; j++)
  461. H1->me[j][j] -= 1.0;
  462. if (m_norm_inf(H1) > MACHEPS*x->dim)
  463. printf(" (lanczos) ||Q*Q^T - I|| = %g [cf. MACHEPS = %g]\n",
  464. m_norm_inf(H1),MACHEPS);
  465. mem_stat_mark(3);
  466. v_rand(u);
  467. iter_splanczos(A,kk,u,x,y,&hh,Q);
  468. mem_stat_free(3);
  469. /* check the equality:
  470. Q*A*Q^T = H; */
  471. vt.dim = vt1.dim = Q->n;
  472. vt.max_dim = vt1.max_dim = Q->max_n;
  473. Q1 = m_resize(Q1,Q->m,Q->n);
  474. for (j=0; j < Q->m; j++) {
  475. vt.ve = Q->me[j];
  476. vt1.ve = Q1->me[j];
  477. sp_mv_mlt(A,&vt,&vt1);
  478. }
  479. H1 = m_resize(H1,Q->m,Q->m);
  480. H = m_resize(H,Q->m,Q->m);
  481. mmtr_mlt(Q,Q1,H1);
  482. for (j=0; j < Q->m-1; j++) {
  483. H->me[j][j] = x->ve[j];
  484. H->me[j][j+1] = H->me[j+1][j] = y->ve[j];
  485. }
  486. H->me[Q->m-1][Q->m-1] = x->ve[Q->m-1];
  487. m_sub(H,H1,H1);
  488. if (m_norm_inf(H1) > MACHEPS*x->dim)
  489. printf(" (splanczos) ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n",
  490. m_norm_inf(H1),MACHEPS);
  491. /* check Q*Q^T = I */
  492. mmtr_mlt(Q,Q,H1);
  493. for (j=0; j < Q->m; j++)
  494. H1->me[j][j] -= 1.0;
  495. if (m_norm_inf(H1) > MACHEPS*x->dim)
  496. printf(" (splanczos) ||Q*Q^T - I|| = %g [cf. MACHEPS = %g]\n",
  497. m_norm_inf(H1),MACHEPS);
  498. /***** LANCZOS2 ****/
  499. notice("lanczos2 method");
  500. kk = 50; /* # of dir. vectors */
  501. ips1->k = kk;
  502. v_rand(u);
  503. ips1->x = u;
  504. ips1->shared_x = TRUE;
  505. for ( i = 0; i < xn->dim; i++ )
  506. xn->ve[i] = i;
  507. iter_Ax(ips1,Dv_mlt,xn);
  508. mem_stat_mark(3);
  509. iter_lanczos2(ips1,y,v);
  510. mem_stat_free(3);
  511. printf("# Number of steps of Lanczos algorithm = %d\n", kk);
  512. printf("# Exact eigenvalues are 0, 1, 2, ..., %d\n",ANON-1);
  513. printf("# Extreme eigenvalues should be accurate; \n");
  514. printf("# interior values usually are not.\n");
  515. printf("# approx e-vals =\n"); v_output(y);
  516. printf("# Error in estimate of bottom e-vec (Lanczos) = %g\n",
  517. fabs(v->ve[0]));
  518. mem_stat_mark(3);
  519. v_rand(u);
  520. iter_splanczos2(A,kk,u,y,v);
  521. mem_stat_free(3);
  522. /***** FINISHING *******/
  523. notice("release ITER variables");
  524. M_FREE(Q);
  525. M_FREE(Q1);
  526. M_FREE(H);
  527. M_FREE(H1);
  528. ITER_FREE(ipns);
  529. ITER_FREE(ips);
  530. ITER_FREE(ipns1);
  531. ITER_FREE(ips1);
  532. SP_FREE(A);
  533. SP_FREE(B);
  534. SP_FREE(An);
  535. SP_FREE(Bn);
  536. V_FREE(x);
  537. V_FREE(y);
  538. V_FREE(u);
  539. V_FREE(v);
  540. V_FREE(xn);
  541. V_FREE(yn);
  542. printf("# Done testing (%s)\n",argv[0]);
  543. mem_info();
  544. }