torture.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052
  1. /**************************************************************************
  2. **
  3. ** Copyright (C) 1993 David E. Stewart & 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, parts 1 and 2
  27. */
  28. static char rcsid[] = "$Id: torture.c,v 1.6 1994/08/25 15:22:11 des Exp $";
  29. #include <stdio.h>
  30. #include <math.h>
  31. #include "matrix2.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. static char *test_err_list[] = {
  36. "unknown error", /* 0 */
  37. "testing error messages", /* 1 */
  38. "unexpected end-of-file" /* 2 */
  39. };
  40. #define MAX_TEST_ERR (sizeof(test_err_list)/sizeof(char *))
  41. /* extern int malloc_chain_check(); */
  42. /* #define MEMCHK() if ( malloc_chain_check(0) ) \
  43. { printf("Error in malloc chain: \"%s\", line %d\n", \
  44. __FILE__, __LINE__); exit(0); } */
  45. #define MEMCHK()
  46. /* cmp_perm -- returns 1 if pi1 == pi2, 0 otherwise */
  47. int cmp_perm(pi1, pi2)
  48. PERM *pi1, *pi2;
  49. {
  50. int i;
  51. if ( ! pi1 || ! pi2 )
  52. error(E_NULL,"cmp_perm");
  53. if ( pi1->size != pi2->size )
  54. return 0;
  55. for ( i = 0; i < pi1->size; i++ )
  56. if ( pi1->pe[i] != pi2->pe[i] )
  57. return 0;
  58. return 1;
  59. }
  60. /* px_rand -- generates sort-of random permutation */
  61. PERM *px_rand(pi)
  62. PERM *pi;
  63. {
  64. int i, j, k;
  65. if ( ! pi )
  66. error(E_NULL,"px_rand");
  67. for ( i = 0; i < 3*pi->size; i++ )
  68. {
  69. j = (rand() >> 8) % pi->size;
  70. k = (rand() >> 8) % pi->size;
  71. px_transp(pi,j,k);
  72. }
  73. return pi;
  74. }
  75. #define SAVE_FILE "asx5213a.mat"
  76. #define MATLAB_NAME "alpha"
  77. char name[81] = MATLAB_NAME;
  78. int main(argc, argv)
  79. int argc;
  80. char *argv[];
  81. {
  82. VEC *x = VNULL, *y = VNULL, *z = VNULL, *u = VNULL, *v = VNULL,
  83. *w = VNULL;
  84. VEC *diag = VNULL, *beta = VNULL;
  85. PERM *pi1 = PNULL, *pi2 = PNULL, *pi3 = PNULL, *pivot = PNULL,
  86. *blocks = PNULL;
  87. MAT *A = MNULL, *B = MNULL, *C = MNULL, *D = MNULL, *Q = MNULL,
  88. *U = MNULL;
  89. BAND *bA, *bB, *bC;
  90. Real cond_est, s1, s2, s3;
  91. int i, j, seed;
  92. FILE *fp;
  93. char *cp;
  94. mem_info_on(TRUE);
  95. setbuf(stdout,(char *)NULL);
  96. seed = 1111;
  97. if ( argc > 2 )
  98. {
  99. printf("usage: %s [seed]\n",argv[0]);
  100. exit(0);
  101. }
  102. else if ( argc == 2 )
  103. sscanf(argv[1], "%d", &seed);
  104. /* set seed for rand() */
  105. smrand(seed);
  106. mem_stat_mark(1);
  107. /* print version information */
  108. m_version();
  109. printf("# grep \"^Error\" the output for a listing of errors\n");
  110. printf("# Don't panic if you see \"Error\" appearing; \n");
  111. printf("# Also check the reported size of error\n");
  112. printf("# This program uses randomly generated problems and therefore\n");
  113. printf("# may occasionally produce ill-conditioned problems\n");
  114. printf("# Therefore check the size of the error compared with MACHEPS\n");
  115. printf("# If the error is within 1000*MACHEPS then don't worry\n");
  116. printf("# If you get an error of size 0.1 or larger there is \n");
  117. printf("# probably a bug in the code or the compilation procedure\n\n");
  118. printf("# seed = %d\n",seed);
  119. printf("# Check: MACHEPS = %g\n",MACHEPS);
  120. /* allocate, initialise, copy and resize operations */
  121. /* VEC */
  122. notice("vector initialise, copy & resize");
  123. x = v_get(12);
  124. y = v_get(15);
  125. z = v_get(12);
  126. v_rand(x);
  127. v_rand(y);
  128. z = v_copy(x,z);
  129. if ( v_norm2(v_sub(x,z,z)) >= MACHEPS )
  130. errmesg("VEC copy");
  131. v_copy(x,y);
  132. x = v_resize(x,10);
  133. y = v_resize(y,10);
  134. if ( v_norm2(v_sub(x,y,z)) >= MACHEPS )
  135. errmesg("VEC copy/resize");
  136. x = v_resize(x,15);
  137. y = v_resize(y,15);
  138. if ( v_norm2(v_sub(x,y,z)) >= MACHEPS )
  139. errmesg("VEC resize");
  140. /* MAT */
  141. notice("matrix initialise, copy & resize");
  142. A = m_get(8,5);
  143. B = m_get(3,9);
  144. C = m_get(8,5);
  145. m_rand(A);
  146. m_rand(B);
  147. C = m_copy(A,C);
  148. if ( m_norm_inf(m_sub(A,C,C)) >= MACHEPS )
  149. errmesg("MAT copy");
  150. m_copy(A,B);
  151. A = m_resize(A,3,5);
  152. B = m_resize(B,3,5);
  153. if ( m_norm_inf(m_sub(A,B,C)) >= MACHEPS )
  154. errmesg("MAT copy/resize");
  155. A = m_resize(A,10,10);
  156. B = m_resize(B,10,10);
  157. if ( m_norm_inf(m_sub(A,B,C)) >= MACHEPS )
  158. errmesg("MAT resize");
  159. MEMCHK();
  160. /* PERM */
  161. notice("permutation initialise, inverting & permuting vectors");
  162. pi1 = px_get(15);
  163. pi2 = px_get(12);
  164. px_rand(pi1);
  165. v_rand(x);
  166. px_vec(pi1,x,z);
  167. y = v_resize(y,x->dim);
  168. pxinv_vec(pi1,z,y);
  169. if ( v_norm2(v_sub(x,y,z)) >= MACHEPS )
  170. errmesg("PERMute vector");
  171. pi2 = px_inv(pi1,pi2);
  172. pi3 = px_mlt(pi1,pi2,PNULL);
  173. for ( i = 0; i < pi3->size; i++ )
  174. if ( pi3->pe[i] != i )
  175. errmesg("PERM inverse/multiply");
  176. /* testing catch() etc */
  177. notice("error handling routines");
  178. catch(E_NULL,
  179. catchall(v_add(VNULL,VNULL,VNULL);
  180. errmesg("tracecatch() failure"),
  181. printf("# tracecatch() caught error\n");
  182. error(E_NULL,"main"));
  183. errmesg("catch() failure"),
  184. printf("# catch() caught E_NULL error\n"));
  185. /* testing attaching a new error list (error list 2) */
  186. notice("attaching error lists");
  187. printf("# IT IS NOT A REAL WARNING ... \n");
  188. err_list_attach(2,MAX_TEST_ERR,test_err_list,TRUE);
  189. if (!err_is_list_attached(2))
  190. errmesg("attaching the error list 2");
  191. ev_err(__FILE__,1,__LINE__,"main",2);
  192. err_list_free(2);
  193. if (err_is_list_attached(2))
  194. errmesg("detaching the error list 2");
  195. /* testing inner products and v_mltadd() etc */
  196. notice("inner products and linear combinations");
  197. u = v_get(x->dim);
  198. v_rand(u);
  199. v_rand(x);
  200. v_resize(y,x->dim);
  201. v_rand(y);
  202. v_mltadd(y,x,-in_prod(x,y)/in_prod(x,x),z);
  203. if ( fabs(in_prod(x,z)) >= MACHEPS*x->dim )
  204. errmesg("v_mltadd()/in_prod()");
  205. s1 = -in_prod(x,y)/(v_norm2(x)*v_norm2(x));
  206. sv_mlt(s1,x,u);
  207. v_add(y,u,u);
  208. if ( v_norm2(v_sub(u,z,u)) >= MACHEPS*x->dim )
  209. errmesg("sv_mlt()/v_norm2()");
  210. #ifdef ANSI_C
  211. v_linlist(u,x,s1,y,1.0,VNULL);
  212. if ( v_norm2(v_sub(u,z,u)) >= MACHEPS*x->dim )
  213. errmesg("v_linlist()");
  214. #endif
  215. #ifdef VARARGS
  216. v_linlist(u,x,s1,y,1.0,VNULL);
  217. if ( v_norm2(v_sub(u,z,u)) >= MACHEPS*x->dim )
  218. errmesg("v_linlist()");
  219. #endif
  220. MEMCHK();
  221. /* vector norms */
  222. notice("vector norms");
  223. x = v_resize(x,12);
  224. v_rand(x);
  225. for ( i = 0; i < x->dim; i++ )
  226. if ( v_entry(x,i) >= 0.5 )
  227. v_set_val(x,i,1.0);
  228. else
  229. v_set_val(x,i,-1.0);
  230. s1 = v_norm1(x);
  231. s2 = v_norm2(x);
  232. s3 = v_norm_inf(x);
  233. if ( fabs(s1 - x->dim) >= MACHEPS*x->dim ||
  234. fabs(s2 - sqrt((Real)(x->dim))) >= MACHEPS*x->dim ||
  235. fabs(s3 - 1.0) >= MACHEPS )
  236. errmesg("v_norm1/2/_inf()");
  237. /* test matrix multiply etc */
  238. notice("matrix multiply and invert");
  239. A = m_resize(A,10,10);
  240. B = m_resize(B,10,10);
  241. m_rand(A);
  242. m_inverse(A,B);
  243. m_mlt(A,B,C);
  244. for ( i = 0; i < C->m; i++ )
  245. m_set_val(C,i,i,m_entry(C,i,i)-1.0);
  246. if ( m_norm_inf(C) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 )
  247. errmesg("m_inverse()/m_mlt()");
  248. MEMCHK();
  249. /* ... and transposes */
  250. notice("transposes and transpose-multiplies");
  251. m_transp(A,A); /* can do square matrices in situ */
  252. mtrm_mlt(A,B,C);
  253. for ( i = 0; i < C->m; i++ )
  254. m_set_val(C,i,i,m_entry(C,i,i)-1.0);
  255. if ( m_norm_inf(C) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 )
  256. errmesg("m_transp()/mtrm_mlt()");
  257. m_transp(A,A);
  258. m_transp(B,B);
  259. mmtr_mlt(A,B,C);
  260. for ( i = 0; i < C->m; i++ )
  261. m_set_val(C,i,i,m_entry(C,i,i)-1.0);
  262. if ( m_norm_inf(C) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 )
  263. errmesg("m_transp()/mmtr_mlt()");
  264. sm_mlt(3.71,B,B);
  265. mmtr_mlt(A,B,C);
  266. for ( i = 0; i < C->m; i++ )
  267. m_set_val(C,i,i,m_entry(C,i,i)-3.71);
  268. if ( m_norm_inf(C) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 )
  269. errmesg("sm_mlt()/mmtr_mlt()");
  270. m_transp(B,B);
  271. sm_mlt(1.0/3.71,B,B);
  272. MEMCHK();
  273. /* ... and matrix-vector multiplies */
  274. notice("matrix-vector multiplies");
  275. x = v_resize(x,A->n);
  276. y = v_resize(y,A->m);
  277. z = v_resize(z,A->m);
  278. u = v_resize(u,A->n);
  279. v_rand(x);
  280. v_rand(y);
  281. mv_mlt(A,x,z);
  282. s1 = in_prod(y,z);
  283. vm_mlt(A,y,u);
  284. s2 = in_prod(u,x);
  285. if ( fabs(s1 - s2) >= (MACHEPS*x->dim)*x->dim )
  286. errmesg("mv_mlt()/vm_mlt()");
  287. mv_mlt(B,z,u);
  288. if ( v_norm2(v_sub(u,x,u)) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 )
  289. errmesg("mv_mlt()/m_inverse()");
  290. MEMCHK();
  291. /* get/set row/col */
  292. notice("getting and setting rows and cols");
  293. x = v_resize(x,A->n);
  294. y = v_resize(y,B->m);
  295. x = get_row(A,3,x);
  296. y = get_col(B,3,y);
  297. if ( fabs(in_prod(x,y) - 1.0) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 )
  298. errmesg("get_row()/get_col()");
  299. sv_mlt(-1.0,x,x);
  300. sv_mlt(-1.0,y,y);
  301. set_row(A,3,x);
  302. set_col(B,3,y);
  303. m_mlt(A,B,C);
  304. for ( i = 0; i < C->m; i++ )
  305. m_set_val(C,i,i,m_entry(C,i,i)-1.0);
  306. if ( m_norm_inf(C) >= MACHEPS*m_norm_inf(A)*m_norm_inf(B)*5 )
  307. errmesg("set_row()/set_col()");
  308. MEMCHK();
  309. /* matrix norms */
  310. notice("matrix norms");
  311. A = m_resize(A,11,15);
  312. m_rand(A);
  313. s1 = m_norm_inf(A);
  314. B = m_transp(A,B);
  315. s2 = m_norm1(B);
  316. if ( fabs(s1 - s2) >= MACHEPS*A->m )
  317. errmesg("m_norm1()/m_norm_inf()");
  318. C = mtrm_mlt(A,A,C);
  319. s1 = 0.0;
  320. for ( i = 0; i < C->m && i < C->n; i++ )
  321. s1 += m_entry(C,i,i);
  322. if ( fabs(sqrt(s1) - m_norm_frob(A)) >= MACHEPS*A->m*A->n )
  323. errmesg("m_norm_frob");
  324. MEMCHK();
  325. /* permuting rows and columns */
  326. notice("permuting rows & cols");
  327. A = m_resize(A,11,15);
  328. B = m_resize(B,11,15);
  329. pi1 = px_resize(pi1,A->m);
  330. px_rand(pi1);
  331. x = v_resize(x,A->n);
  332. y = mv_mlt(A,x,y);
  333. px_rows(pi1,A,B);
  334. px_vec(pi1,y,z);
  335. mv_mlt(B,x,u);
  336. if ( v_norm2(v_sub(z,u,u)) >= MACHEPS*A->m )
  337. errmesg("px_rows()");
  338. pi1 = px_resize(pi1,A->n);
  339. px_rand(pi1);
  340. px_cols(pi1,A,B);
  341. pxinv_vec(pi1,x,z);
  342. mv_mlt(B,z,u);
  343. if ( v_norm2(v_sub(y,u,u)) >= MACHEPS*A->n )
  344. errmesg("px_cols()");
  345. MEMCHK();
  346. /* MATLAB save/load */
  347. notice("MATLAB save/load");
  348. A = m_resize(A,12,11);
  349. if ( (fp=fopen(SAVE_FILE,"w")) == (FILE *)NULL )
  350. printf("Cannot perform MATLAB save/load test\n");
  351. else
  352. {
  353. m_rand(A);
  354. m_save(fp, A, name);
  355. fclose(fp);
  356. if ( (fp=fopen(SAVE_FILE,"r")) == (FILE *)NULL )
  357. printf("Cannot open save file \"%s\"\n",SAVE_FILE);
  358. else
  359. {
  360. M_FREE(B);
  361. B = m_load(fp,&cp);
  362. if ( strcmp(name,cp) || m_norm1(m_sub(A,B,B)) >= MACHEPS*A->m )
  363. errmesg("mload()/m_save()");
  364. }
  365. }
  366. MEMCHK();
  367. /* Now, onto matrix factorisations */
  368. A = m_resize(A,10,10);
  369. B = m_resize(B,A->m,A->n);
  370. m_copy(A,B);
  371. x = v_resize(x,A->n);
  372. y = v_resize(y,A->m);
  373. z = v_resize(z,A->n);
  374. u = v_resize(u,A->m);
  375. v_rand(x);
  376. mv_mlt(B,x,y);
  377. z = v_copy(x,z);
  378. notice("LU factor/solve");
  379. pivot = px_get(A->m);
  380. LUfactor(A,pivot);
  381. tracecatch(LUsolve(A,pivot,y,x),"main");
  382. tracecatch(cond_est = LUcondest(A,pivot),"main");
  383. printf("# cond(A) approx= %g\n", cond_est);
  384. if ( v_norm2(v_sub(x,z,u)) >= MACHEPS*v_norm2(x)*cond_est)
  385. {
  386. errmesg("LUfactor()/LUsolve()");
  387. printf("# LU solution error = %g [cf MACHEPS = %g]\n",
  388. v_norm2(v_sub(x,z,u)), MACHEPS);
  389. }
  390. v_copy(y,x);
  391. tracecatch(LUsolve(A,pivot,x,x),"main");
  392. tracecatch(cond_est = LUcondest(A,pivot),"main");
  393. if ( v_norm2(v_sub(x,z,u)) >= MACHEPS*v_norm2(x)*cond_est)
  394. {
  395. errmesg("LUfactor()/LUsolve()");
  396. printf("# LU solution error = %g [cf MACHEPS = %g]\n",
  397. v_norm2(v_sub(x,z,u)), MACHEPS);
  398. }
  399. vm_mlt(B,z,y);
  400. v_copy(y,x);
  401. tracecatch(LUTsolve(A,pivot,x,x),"main");
  402. if ( v_norm2(v_sub(x,z,u)) >= MACHEPS*v_norm2(x)*cond_est)
  403. {
  404. errmesg("LUfactor()/LUTsolve()");
  405. printf("# LU solution error = %g [cf MACHEPS = %g]\n",
  406. v_norm2(v_sub(x,z,u)), MACHEPS);
  407. }
  408. MEMCHK();
  409. /* QR factorisation */
  410. m_copy(B,A);
  411. mv_mlt(B,z,y);
  412. notice("QR factor/solve:");
  413. diag = v_get(A->m);
  414. beta = v_get(A->m);
  415. QRfactor(A,diag);
  416. QRsolve(A,diag,y,x);
  417. if ( v_norm2(v_sub(x,z,u)) >= MACHEPS*v_norm2(x)*cond_est )
  418. {
  419. errmesg("QRfactor()/QRsolve()");
  420. printf("# QR solution error = %g [cf MACHEPS = %g]\n",
  421. v_norm2(v_sub(x,z,u)), MACHEPS);
  422. }
  423. Q = m_get(A->m,A->m);
  424. makeQ(A,diag,Q);
  425. makeR(A,A);
  426. m_mlt(Q,A,C);
  427. m_sub(B,C,C);
  428. if ( m_norm1(C) >= MACHEPS*m_norm1(Q)*m_norm1(B) )
  429. {
  430. errmesg("QRfactor()/makeQ()/makeR()");
  431. printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n",
  432. m_norm1(C), MACHEPS);
  433. }
  434. MEMCHK();
  435. /* now try with a non-square matrix */
  436. A = m_resize(A,15,7);
  437. m_rand(A);
  438. B = m_copy(A,B);
  439. diag = v_resize(diag,A->n);
  440. beta = v_resize(beta,A->n);
  441. x = v_resize(x,A->n);
  442. y = v_resize(y,A->m);
  443. v_rand(y);
  444. QRfactor(A,diag);
  445. x = QRsolve(A,diag,y,x);
  446. /* z is the residual vector */
  447. mv_mlt(B,x,z); v_sub(z,y,z);
  448. /* check B^T.z = 0 */
  449. vm_mlt(B,z,u);
  450. if ( v_norm2(u) >= MACHEPS*m_norm1(B)*v_norm2(y) )
  451. {
  452. errmesg("QRfactor()/QRsolve()");
  453. printf("# QR solution error = %g [cf MACHEPS = %g]\n",
  454. v_norm2(u), MACHEPS);
  455. }
  456. Q = m_resize(Q,A->m,A->m);
  457. makeQ(A,diag,Q);
  458. makeR(A,A);
  459. m_mlt(Q,A,C);
  460. m_sub(B,C,C);
  461. if ( m_norm1(C) >= MACHEPS*m_norm1(Q)*m_norm1(B) )
  462. {
  463. errmesg("QRfactor()/makeQ()/makeR()");
  464. printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n",
  465. m_norm1(C), MACHEPS);
  466. }
  467. D = m_get(A->m,Q->m);
  468. mtrm_mlt(Q,Q,D);
  469. for ( i = 0; i < D->m; i++ )
  470. m_set_val(D,i,i,m_entry(D,i,i)-1.0);
  471. if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm_inf(Q) )
  472. {
  473. errmesg("QRfactor()/makeQ()/makeR()");
  474. printf("# QR orthogonality error = %g [cf MACHEPS = %g]\n",
  475. m_norm1(D), MACHEPS);
  476. }
  477. MEMCHK();
  478. /* QRCP factorisation */
  479. m_copy(B,A);
  480. notice("QR factor/solve with column pivoting");
  481. pivot = px_resize(pivot,A->n);
  482. QRCPfactor(A,diag,pivot);
  483. z = v_resize(z,A->n);
  484. QRCPsolve(A,diag,pivot,y,z);
  485. /* pxinv_vec(pivot,z,x); */
  486. /* now compute residual (z) vector */
  487. mv_mlt(B,x,z); v_sub(z,y,z);
  488. /* check B^T.z = 0 */
  489. vm_mlt(B,z,u);
  490. if ( v_norm2(u) >= MACHEPS*m_norm1(B)*v_norm2(y) )
  491. {
  492. errmesg("QRCPfactor()/QRsolve()");
  493. printf("# QR solution error = %g [cf MACHEPS = %g]\n",
  494. v_norm2(u), MACHEPS);
  495. }
  496. Q = m_resize(Q,A->m,A->m);
  497. makeQ(A,diag,Q);
  498. makeR(A,A);
  499. m_mlt(Q,A,C);
  500. M_FREE(D);
  501. D = m_get(B->m,B->n);
  502. px_cols(pivot,C,D);
  503. m_sub(B,D,D);
  504. if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm1(B) )
  505. {
  506. errmesg("QRCPfactor()/makeQ()/makeR()");
  507. printf("# QR reconstruction error = %g [cf MACHEPS = %g]\n",
  508. m_norm1(D), MACHEPS);
  509. }
  510. MEMCHK();
  511. /* Cholesky and LDL^T factorisation */
  512. /* Use these for normal equations approach */
  513. notice("Cholesky factor/solve");
  514. mtrm_mlt(B,B,A);
  515. CHfactor(A);
  516. u = v_resize(u,B->n);
  517. vm_mlt(B,y,u);
  518. z = v_resize(z,B->n);
  519. CHsolve(A,u,z);
  520. v_sub(x,z,z);
  521. if ( v_norm2(z) >= MACHEPS*v_norm2(x)*100 )
  522. {
  523. errmesg("CHfactor()/CHsolve()");
  524. printf("# Cholesky solution error = %g [cf MACHEPS = %g]\n",
  525. v_norm2(z), MACHEPS);
  526. }
  527. /* modified Cholesky factorisation should be identical with Cholesky
  528. factorisation provided the matrix is "sufficiently positive definite" */
  529. mtrm_mlt(B,B,C);
  530. MCHfactor(C,MACHEPS);
  531. m_sub(A,C,C);
  532. if ( m_norm1(C) >= MACHEPS*m_norm1(A) )
  533. {
  534. errmesg("MCHfactor()");
  535. printf("# Modified Cholesky error = %g [cf MACHEPS = %g]\n",
  536. m_norm1(C), MACHEPS);
  537. }
  538. /* now test the LDL^T factorisation -- using a negative def. matrix */
  539. mtrm_mlt(B,B,A);
  540. sm_mlt(-1.0,A,A);
  541. m_copy(A,C);
  542. LDLfactor(A);
  543. LDLsolve(A,u,z);
  544. w = v_get(A->m);
  545. mv_mlt(C,z,w);
  546. v_sub(w,u,w);
  547. if ( v_norm2(w) >= MACHEPS*v_norm2(u)*m_norm1(C) )
  548. {
  549. errmesg("LDLfactor()/LDLsolve()");
  550. printf("# LDL^T residual = %g [cf MACHEPS = %g]\n",
  551. v_norm2(w), MACHEPS);
  552. }
  553. v_add(x,z,z);
  554. if ( v_norm2(z) >= MACHEPS*v_norm2(x)*100 )
  555. {
  556. errmesg("LDLfactor()/LDLsolve()");
  557. printf("# LDL^T solution error = %g [cf MACHEPS = %g]\n",
  558. v_norm2(z), MACHEPS);
  559. }
  560. MEMCHK();
  561. /* and now the Bunch-Kaufman-Parlett method */
  562. /* set up D to be an indefinite diagonal matrix */
  563. notice("Bunch-Kaufman-Parlett factor/solve");
  564. D = m_resize(D,B->m,B->m);
  565. m_zero(D);
  566. w = v_resize(w,B->m);
  567. v_rand(w);
  568. for ( i = 0; i < w->dim; i++ )
  569. if ( v_entry(w,i) >= 0.5 )
  570. m_set_val(D,i,i,1.0);
  571. else
  572. m_set_val(D,i,i,-1.0);
  573. /* set A <- B^T.D.B */
  574. C = m_resize(C,B->n,B->n);
  575. C = mtrm_mlt(B,D,C);
  576. A = m_mlt(C,B,A);
  577. C = m_resize(C,B->n,B->n);
  578. C = m_copy(A,C);
  579. /* ... and use BKPfactor() */
  580. blocks = px_get(A->m);
  581. pivot = px_resize(pivot,A->m);
  582. x = v_resize(x,A->m);
  583. y = v_resize(y,A->m);
  584. z = v_resize(z,A->m);
  585. v_rand(x);
  586. mv_mlt(A,x,y);
  587. BKPfactor(A,pivot,blocks);
  588. printf("# BKP pivot =\n"); px_output(pivot);
  589. printf("# BKP blocks =\n"); px_output(blocks);
  590. BKPsolve(A,pivot,blocks,y,z);
  591. /* compute & check residual */
  592. mv_mlt(C,z,w);
  593. v_sub(w,y,w);
  594. if ( v_norm2(w) >= MACHEPS*m_norm1(C)*v_norm2(z) )
  595. {
  596. errmesg("BKPfactor()/BKPsolve()");
  597. printf("# BKP residual size = %g [cf MACHEPS = %g]\n",
  598. v_norm2(w), MACHEPS);
  599. }
  600. /* check update routines */
  601. /* check LDLupdate() first */
  602. notice("update L.D.L^T routine");
  603. A = mtrm_mlt(B,B,A);
  604. m_resize(C,A->m,A->n);
  605. C = m_copy(A,C);
  606. LDLfactor(A);
  607. s1 = 3.7;
  608. w = v_resize(w,A->m);
  609. v_rand(w);
  610. for ( i = 0; i < C->m; i++ )
  611. for ( j = 0; j < C->n; j++ )
  612. m_set_val(C,i,j,m_entry(C,i,j)+s1*v_entry(w,i)*v_entry(w,j));
  613. LDLfactor(C);
  614. LDLupdate(A,w,s1);
  615. /* zero out strictly upper triangular parts of A and C */
  616. for ( i = 0; i < A->m; i++ )
  617. for ( j = i+1; j < A->n; j++ )
  618. {
  619. m_set_val(A,i,j,0.0);
  620. m_set_val(C,i,j,0.0);
  621. }
  622. if ( m_norm1(m_sub(A,C,C)) >= sqrt(MACHEPS)*m_norm1(A) )
  623. {
  624. errmesg("LDLupdate()");
  625. printf("# LDL update matrix error = %g [cf MACHEPS = %g]\n",
  626. m_norm1(C), MACHEPS);
  627. }
  628. /* BAND MATRICES */
  629. #define COL 40
  630. #define UDIAG 5
  631. #define LDIAG 2
  632. smrand(101);
  633. bA = bd_get(LDIAG,UDIAG,COL);
  634. bB = bd_get(LDIAG,UDIAG,COL);
  635. bC = bd_get(LDIAG,UDIAG,COL);
  636. A = m_resize(A,COL,COL);
  637. B = m_resize(B,COL,COL);
  638. pivot = px_resize(pivot,COL);
  639. x = v_resize(x,COL);
  640. w = v_resize(w,COL);
  641. z = v_resize(z,COL);
  642. m_rand(A);
  643. /* generate band matrix */
  644. mat2band(A,LDIAG,UDIAG,bA);
  645. band2mat(bA,A); /* now A is banded */
  646. bB = bd_copy(bA,bB);
  647. v_rand(x);
  648. mv_mlt(A,x,w);
  649. /* test of bd_mv_mlt */
  650. notice("bd_mv_mlt");
  651. bd_mv_mlt(bA,x,z);
  652. v_sub(z,w,z);
  653. if (v_norm2(z) > v_norm2(x)*sqrt(MACHEPS)) {
  654. errmesg("incorrect vector (bd_mv_mlt)");
  655. printf(" ||exact vector. - computed vector.|| = %g [MACHEPS = %g]\n",
  656. v_norm2(z),MACHEPS);
  657. }
  658. z = v_copy(w,z);
  659. notice("band LU factorization");
  660. bdLUfactor(bA,pivot);
  661. /* pivot will be changed */
  662. bdLUsolve(bA,pivot,z,z);
  663. v_sub(x,z,z);
  664. if (v_norm2(z) > v_norm2(x)*sqrt(MACHEPS)) {
  665. errmesg("incorrect solution (band LU factorization)");
  666. printf(" ||exact sol. - computed sol.|| = %g [MACHEPS = %g]\n",
  667. v_norm2(z),MACHEPS);
  668. }
  669. /* solve transpose system */
  670. notice("band LU factorization for transpose system");
  671. m_transp(A,B);
  672. mv_mlt(B,x,w);
  673. bd_copy(bB,bA);
  674. bd_transp(bA,bA);
  675. /* transposition in situ */
  676. bd_transp(bA,bB);
  677. bd_transp(bB,bB);
  678. bdLUfactor(bB,pivot);
  679. bdLUsolve(bB,pivot,w,z);
  680. v_sub(x,z,z);
  681. if (v_norm2(z) > v_norm2(x)*sqrt(MACHEPS)) {
  682. errmesg("incorrect solution (band transposed LU factorization)");
  683. printf(" ||exact sol. - computed sol.|| = %g [MACHEPS = %g]\n",
  684. v_norm2(z),MACHEPS);
  685. }
  686. /* Cholesky factorization */
  687. notice("band Choleski LDL' factorization");
  688. m_add(A,B,A); /* symmetric matrix */
  689. for (i=0; i < COL; i++) /* positive definite */
  690. A->me[i][i] += 2*LDIAG;
  691. mat2band(A,LDIAG,LDIAG,bA);
  692. band2mat(bA,A); /* corresponding matrix A */
  693. v_rand(x);
  694. mv_mlt(A,x,w);
  695. z = v_copy(w,z);
  696. bdLDLfactor(bA);
  697. z = bdLDLsolve(bA,z,z);
  698. v_sub(x,z,z);
  699. if (v_norm2(z) > v_norm2(x)*sqrt(MACHEPS)) {
  700. errmesg("incorrect solution (band LDL' factorization)");
  701. printf(" ||exact sol. - computed sol.|| = %g [MACHEPS = %g]\n",
  702. v_norm2(z),MACHEPS);
  703. }
  704. /* new bandwidths */
  705. m_rand(A);
  706. bA = bd_resize(bA,UDIAG,LDIAG,COL);
  707. bB = bd_resize(bB,UDIAG,LDIAG,COL);
  708. mat2band(A,UDIAG,LDIAG,bA);
  709. band2mat(bA,A);
  710. bd_copy(bA,bB);
  711. mv_mlt(A,x,w);
  712. notice("band LU factorization (resized)");
  713. bdLUfactor(bA,pivot);
  714. /* pivot will be changed */
  715. bdLUsolve(bA,pivot,w,z);
  716. v_sub(x,z,z);
  717. if (v_norm2(z) > v_norm2(x)*sqrt(MACHEPS)) {
  718. errmesg("incorrect solution (band LU factorization)");
  719. printf(" ||exact sol. - computed sol.|| = %g [MACHEPS = %g]\n",
  720. v_norm2(z),MACHEPS);
  721. }
  722. /* testing transposition */
  723. notice("band matrix transposition");
  724. m_zero(bA->mat);
  725. bd_copy(bB,bA);
  726. m_zero(bB->mat);
  727. bd_copy(bA,bB);
  728. bd_transp(bB,bB);
  729. bd_transp(bB,bB);
  730. m_zero(bC->mat);
  731. bd_copy(bB,bC);
  732. m_sub(bA->mat,bC->mat,bC->mat);
  733. if (m_norm_inf(bC->mat) > MACHEPS*bC->mat->n) {
  734. errmesg("band transposition");
  735. printf(" difference ||A - (A')'|| = %g\n",m_norm_inf(bC->mat));
  736. }
  737. bd_free(bA);
  738. bd_free(bB);
  739. bd_free(bC);
  740. MEMCHK();
  741. /* now check QRupdate() routine */
  742. notice("update QR routine");
  743. B = m_resize(B,15,7);
  744. A = m_resize(A,B->m,B->n);
  745. m_copy(B,A);
  746. diag = v_resize(diag,A->n);
  747. beta = v_resize(beta,A->n);
  748. QRfactor(A,diag);
  749. Q = m_resize(Q,A->m,A->m);
  750. makeQ(A,diag,Q);
  751. makeR(A,A);
  752. m_resize(C,A->m,A->n);
  753. w = v_resize(w,A->m);
  754. v = v_resize(v,A->n);
  755. u = v_resize(u,A->m);
  756. v_rand(w);
  757. v_rand(v);
  758. vm_mlt(Q,w,u);
  759. QRupdate(Q,A,u,v);
  760. m_mlt(Q,A,C);
  761. for ( i = 0; i < B->m; i++ )
  762. for ( j = 0; j < B->n; j++ )
  763. m_set_val(B,i,j,m_entry(B,i,j)+v_entry(w,i)*v_entry(v,j));
  764. m_sub(B,C,C);
  765. if ( m_norm1(C) >= MACHEPS*m_norm1(A)*m_norm1(Q)*2 )
  766. {
  767. errmesg("QRupdate()");
  768. printf("# Reconstruction error in QR update = %g [cf MACHEPS = %g]\n",
  769. m_norm1(C), MACHEPS);
  770. }
  771. m_resize(D,Q->m,Q->n);
  772. mtrm_mlt(Q,Q,D);
  773. for ( i = 0; i < D->m; i++ )
  774. m_set_val(D,i,i,m_entry(D,i,i)-1.0);
  775. if ( m_norm1(D) >= 10*MACHEPS*m_norm1(Q)*m_norm_inf(Q) )
  776. {
  777. errmesg("QRupdate()");
  778. printf("# QR update orthogonality error = %g [cf MACHEPS = %g]\n",
  779. m_norm1(D), MACHEPS);
  780. }
  781. /* Now check eigenvalue/SVD routines */
  782. notice("eigenvalue and SVD routines");
  783. A = m_resize(A,11,11);
  784. B = m_resize(B,A->m,A->n);
  785. C = m_resize(C,A->m,A->n);
  786. D = m_resize(D,A->m,A->n);
  787. Q = m_resize(Q,A->m,A->n);
  788. m_rand(A);
  789. /* A <- A + A^T for symmetric case */
  790. m_add(A,m_transp(A,C),A);
  791. u = v_resize(u,A->m);
  792. u = symmeig(A,Q,u);
  793. m_zero(B);
  794. for ( i = 0; i < B->m; i++ )
  795. m_set_val(B,i,i,v_entry(u,i));
  796. m_mlt(Q,B,C);
  797. mmtr_mlt(C,Q,D);
  798. m_sub(A,D,D);
  799. if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm_inf(Q)*v_norm_inf(u)*3 )
  800. {
  801. errmesg("symmeig()");
  802. printf("# Reconstruction error = %g [cf MACHEPS = %g]\n",
  803. m_norm1(D), MACHEPS);
  804. }
  805. mtrm_mlt(Q,Q,D);
  806. for ( i = 0; i < D->m; i++ )
  807. m_set_val(D,i,i,m_entry(D,i,i)-1.0);
  808. if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm_inf(Q)*3 )
  809. {
  810. errmesg("symmeig()");
  811. printf("# symmeig() orthogonality error = %g [cf MACHEPS = %g]\n",
  812. m_norm1(D), MACHEPS);
  813. }
  814. MEMCHK();
  815. /* now test (real) Schur decomposition */
  816. /* m_copy(A,B); */
  817. M_FREE(A);
  818. A = m_get(11,11);
  819. m_rand(A);
  820. B = m_copy(A,B);
  821. MEMCHK();
  822. B = schur(B,Q);
  823. MEMCHK();
  824. m_mlt(Q,B,C);
  825. mmtr_mlt(C,Q,D);
  826. MEMCHK();
  827. m_sub(A,D,D);
  828. if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm_inf(Q)*m_norm1(B)*5 )
  829. {
  830. errmesg("schur()");
  831. printf("# Schur reconstruction error = %g [cf MACHEPS = %g]\n",
  832. m_norm1(D), MACHEPS);
  833. }
  834. /* orthogonality check */
  835. mmtr_mlt(Q,Q,D);
  836. for ( i = 0; i < D->m; i++ )
  837. m_set_val(D,i,i,m_entry(D,i,i)-1.0);
  838. if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm_inf(Q)*10 )
  839. {
  840. errmesg("schur()");
  841. printf("# Schur orthogonality error = %g [cf MACHEPS = %g]\n",
  842. m_norm1(D), MACHEPS);
  843. }
  844. MEMCHK();
  845. /* now test SVD */
  846. A = m_resize(A,11,7);
  847. m_rand(A);
  848. U = m_get(A->n,A->n);
  849. Q = m_resize(Q,A->m,A->m);
  850. u = v_resize(u,max(A->m,A->n));
  851. svd(A,Q,U,u);
  852. /* check reconstruction of A */
  853. D = m_resize(D,A->m,A->n);
  854. C = m_resize(C,A->m,A->n);
  855. m_zero(D);
  856. for ( i = 0; i < min(A->m,A->n); i++ )
  857. m_set_val(D,i,i,v_entry(u,i));
  858. mtrm_mlt(Q,D,C);
  859. m_mlt(C,U,D);
  860. m_sub(A,D,D);
  861. if ( m_norm1(D) >= MACHEPS*m_norm1(U)*m_norm_inf(Q)*m_norm1(A) )
  862. {
  863. errmesg("svd()");
  864. printf("# SVD reconstruction error = %g [cf MACHEPS = %g]\n",
  865. m_norm1(D), MACHEPS);
  866. }
  867. /* check orthogonality of Q and U */
  868. D = m_resize(D,Q->n,Q->n);
  869. mtrm_mlt(Q,Q,D);
  870. for ( i = 0; i < D->m; i++ )
  871. m_set_val(D,i,i,m_entry(D,i,i)-1.0);
  872. if ( m_norm1(D) >= MACHEPS*m_norm1(Q)*m_norm_inf(Q)*5 )
  873. {
  874. errmesg("svd()");
  875. printf("# SVD orthognality error (Q) = %g [cf MACHEPS = %g\n",
  876. m_norm1(D), MACHEPS);
  877. }
  878. D = m_resize(D,U->n,U->n);
  879. mtrm_mlt(U,U,D);
  880. for ( i = 0; i < D->m; i++ )
  881. m_set_val(D,i,i,m_entry(D,i,i)-1.0);
  882. if ( m_norm1(D) >= MACHEPS*m_norm1(U)*m_norm_inf(U)*5 )
  883. {
  884. errmesg("svd()");
  885. printf("# SVD orthognality error (U) = %g [cf MACHEPS = %g\n",
  886. m_norm1(D), MACHEPS);
  887. }
  888. for ( i = 0; i < u->dim; i++ )
  889. if ( v_entry(u,i) < 0 || (i < u->dim-1 &&
  890. v_entry(u,i+1) > v_entry(u,i)) )
  891. break;
  892. if ( i < u->dim )
  893. {
  894. errmesg("svd()");
  895. printf("# SVD sorting error\n");
  896. }
  897. /* test of long vectors */
  898. notice("Long vectors");
  899. x = v_resize(x,100000);
  900. y = v_resize(y,100000);
  901. z = v_resize(z,100000);
  902. v_rand(x);
  903. v_rand(y);
  904. v_mltadd(x,y,3.0,z);
  905. sv_mlt(1.0/3.0,z,z);
  906. v_mltadd(z,x,-1.0/3.0,z);
  907. v_sub(z,y,x);
  908. if (v_norm2(x) >= MACHEPS*(x->dim)) {
  909. errmesg("long vectors");
  910. printf(" norm = %g\n",v_norm2(x));
  911. }
  912. mem_stat_free(1);
  913. MEMCHK();
  914. /**************************************************
  915. VEC *x, *y, *z, *u, *v, *w;
  916. VEC *diag, *beta;
  917. PERM *pi1, *pi2, *pi3, *pivot, *blocks;
  918. MAT *A, *B, *C, *D, *Q, *U;
  919. **************************************************/
  920. V_FREE(x); V_FREE(y); V_FREE(z);
  921. V_FREE(u); V_FREE(v); V_FREE(w);
  922. V_FREE(diag); V_FREE(beta);
  923. PX_FREE(pi1); PX_FREE(pi2); PX_FREE(pi3);
  924. PX_FREE(pivot); PX_FREE(blocks);
  925. M_FREE(A); M_FREE(B); M_FREE(C);
  926. M_FREE(D); M_FREE(Q); M_FREE(U);
  927. MEMCHK();
  928. printf("# Finished torture test\n");
  929. mem_info();
  930. return 0;
  931. }