zmatop.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  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. #include <stdio.h>
  25. #include "zmatrix.h"
  26. static char rcsid[] = "$Id: zmatop.c,v 1.2 1995/03/27 15:49:03 des Exp $";
  27. #define is_zero(z) ((z).re == 0.0 && (z).im == 0.0)
  28. /* zm_add -- matrix addition -- may be in-situ */
  29. ZMAT *zm_add(mat1,mat2,out)
  30. ZMAT *mat1,*mat2,*out;
  31. {
  32. unsigned int m,n,i;
  33. if ( mat1==ZMNULL || mat2==ZMNULL )
  34. error(E_NULL,"zm_add");
  35. if ( mat1->m != mat2->m || mat1->n != mat2->n )
  36. error(E_SIZES,"zm_add");
  37. if ( out==ZMNULL || out->m != mat1->m || out->n != mat1->n )
  38. out = zm_resize(out,mat1->m,mat1->n);
  39. m = mat1->m; n = mat1->n;
  40. for ( i=0; i<m; i++ )
  41. {
  42. __zadd__(mat1->me[i],mat2->me[i],out->me[i],(int)n);
  43. /**************************************************
  44. for ( j=0; j<n; j++ )
  45. out->me[i][j] = mat1->me[i][j]+mat2->me[i][j];
  46. **************************************************/
  47. }
  48. return (out);
  49. }
  50. /* zm_sub -- matrix subtraction -- may be in-situ */
  51. ZMAT *zm_sub(mat1,mat2,out)
  52. ZMAT *mat1,*mat2,*out;
  53. {
  54. unsigned int m,n,i;
  55. if ( mat1==ZMNULL || mat2==ZMNULL )
  56. error(E_NULL,"zm_sub");
  57. if ( mat1->m != mat2->m || mat1->n != mat2->n )
  58. error(E_SIZES,"zm_sub");
  59. if ( out==ZMNULL || out->m != mat1->m || out->n != mat1->n )
  60. out = zm_resize(out,mat1->m,mat1->n);
  61. m = mat1->m; n = mat1->n;
  62. for ( i=0; i<m; i++ )
  63. {
  64. __zsub__(mat1->me[i],mat2->me[i],out->me[i],(int)n);
  65. /**************************************************
  66. for ( j=0; j<n; j++ )
  67. out->me[i][j] = mat1->me[i][j]-mat2->me[i][j];
  68. **************************************************/
  69. }
  70. return (out);
  71. }
  72. /*
  73. Note: In the following routines, "adjoint" means complex conjugate
  74. transpose:
  75. A* = conjugate(A^T)
  76. */
  77. /* zm_mlt -- matrix-matrix multiplication */
  78. ZMAT *zm_mlt(A,B,OUT)
  79. ZMAT *A,*B,*OUT;
  80. {
  81. unsigned int i, /* j, */ k, m, n, p;
  82. complex **A_v, **B_v /*, *B_row, *OUT_row, sum, tmp */;
  83. if ( A==ZMNULL || B==ZMNULL )
  84. error(E_NULL,"zm_mlt");
  85. if ( A->n != B->m )
  86. error(E_SIZES,"zm_mlt");
  87. if ( A == OUT || B == OUT )
  88. error(E_INSITU,"zm_mlt");
  89. m = A->m; n = A->n; p = B->n;
  90. A_v = A->me; B_v = B->me;
  91. if ( OUT==ZMNULL || OUT->m != A->m || OUT->n != B->n )
  92. OUT = zm_resize(OUT,A->m,B->n);
  93. /****************************************************************
  94. for ( i=0; i<m; i++ )
  95. for ( j=0; j<p; j++ )
  96. {
  97. sum = 0.0;
  98. for ( k=0; k<n; k++ )
  99. sum += A_v[i][k]*B_v[k][j];
  100. OUT->me[i][j] = sum;
  101. }
  102. ****************************************************************/
  103. zm_zero(OUT);
  104. for ( i=0; i<m; i++ )
  105. for ( k=0; k<n; k++ )
  106. {
  107. if ( ! is_zero(A_v[i][k]) )
  108. __zmltadd__(OUT->me[i],B_v[k],A_v[i][k],(int)p,Z_NOCONJ);
  109. /**************************************************
  110. B_row = B_v[k]; OUT_row = OUT->me[i];
  111. for ( j=0; j<p; j++ )
  112. (*OUT_row++) += tmp*(*B_row++);
  113. **************************************************/
  114. }
  115. return OUT;
  116. }
  117. /* zmma_mlt -- matrix-matrix adjoint multiplication
  118. -- A.B* is returned, and stored in OUT */
  119. ZMAT *zmma_mlt(A,B,OUT)
  120. ZMAT *A, *B, *OUT;
  121. {
  122. int i, j, limit;
  123. /* complex *A_row, *B_row, sum; */
  124. if ( ! A || ! B )
  125. error(E_NULL,"zmma_mlt");
  126. if ( A == OUT || B == OUT )
  127. error(E_INSITU,"zmma_mlt");
  128. if ( A->n != B->n )
  129. error(E_SIZES,"zmma_mlt");
  130. if ( ! OUT || OUT->m != A->m || OUT->n != B->m )
  131. OUT = zm_resize(OUT,A->m,B->m);
  132. limit = A->n;
  133. for ( i = 0; i < A->m; i++ )
  134. for ( j = 0; j < B->m; j++ )
  135. {
  136. OUT->me[i][j] = __zip__(B->me[j],A->me[i],(int)limit,Z_CONJ);
  137. /**************************************************
  138. sum = 0.0;
  139. A_row = A->me[i];
  140. B_row = B->me[j];
  141. for ( k = 0; k < limit; k++ )
  142. sum += (*A_row++)*(*B_row++);
  143. OUT->me[i][j] = sum;
  144. **************************************************/
  145. }
  146. return OUT;
  147. }
  148. /* zmam_mlt -- matrix adjoint-matrix multiplication
  149. -- A*.B is returned, result stored in OUT */
  150. ZMAT *zmam_mlt(A,B,OUT)
  151. ZMAT *A, *B, *OUT;
  152. {
  153. int i, k, limit;
  154. /* complex *B_row, *OUT_row, multiplier; */
  155. complex tmp;
  156. if ( ! A || ! B )
  157. error(E_NULL,"zmam_mlt");
  158. if ( A == OUT || B == OUT )
  159. error(E_INSITU,"zmam_mlt");
  160. if ( A->m != B->m )
  161. error(E_SIZES,"zmam_mlt");
  162. if ( ! OUT || OUT->m != A->n || OUT->n != B->n )
  163. OUT = zm_resize(OUT,A->n,B->n);
  164. limit = B->n;
  165. zm_zero(OUT);
  166. for ( k = 0; k < A->m; k++ )
  167. for ( i = 0; i < A->n; i++ )
  168. {
  169. tmp.re = A->me[k][i].re;
  170. tmp.im = - A->me[k][i].im;
  171. if ( ! is_zero(tmp) )
  172. __zmltadd__(OUT->me[i],B->me[k],tmp,(int)limit,Z_NOCONJ);
  173. }
  174. return OUT;
  175. }
  176. /* zmv_mlt -- matrix-vector multiplication
  177. -- Note: b is treated as a column vector */
  178. ZVEC *zmv_mlt(A,b,out)
  179. ZMAT *A;
  180. ZVEC *b,*out;
  181. {
  182. unsigned int i, m, n;
  183. complex **A_v, *b_v /*, *A_row */;
  184. /* register complex sum; */
  185. if ( A==ZMNULL || b==ZVNULL )
  186. error(E_NULL,"zmv_mlt");
  187. if ( A->n != b->dim )
  188. error(E_SIZES,"zmv_mlt");
  189. if ( b == out )
  190. error(E_INSITU,"zmv_mlt");
  191. if ( out == ZVNULL || out->dim != A->m )
  192. out = zv_resize(out,A->m);
  193. m = A->m; n = A->n;
  194. A_v = A->me; b_v = b->ve;
  195. for ( i=0; i<m; i++ )
  196. {
  197. /* for ( j=0; j<n; j++ )
  198. sum += A_v[i][j]*b_v[j]; */
  199. out->ve[i] = __zip__(A_v[i],b_v,(int)n,Z_NOCONJ);
  200. /**************************************************
  201. A_row = A_v[i]; b_v = b->ve;
  202. for ( j=0; j<n; j++ )
  203. sum += (*A_row++)*(*b_v++);
  204. out->ve[i] = sum;
  205. **************************************************/
  206. }
  207. return out;
  208. }
  209. /* zsm_mlt -- scalar-matrix multiply -- may be in-situ */
  210. ZMAT *zsm_mlt(scalar,matrix,out)
  211. complex scalar;
  212. ZMAT *matrix,*out;
  213. {
  214. unsigned int m,n,i;
  215. if ( matrix==ZMNULL )
  216. error(E_NULL,"zsm_mlt");
  217. if ( out==ZMNULL || out->m != matrix->m || out->n != matrix->n )
  218. out = zm_resize(out,matrix->m,matrix->n);
  219. m = matrix->m; n = matrix->n;
  220. for ( i=0; i<m; i++ )
  221. __zmlt__(matrix->me[i],scalar,out->me[i],(int)n);
  222. /**************************************************
  223. for ( j=0; j<n; j++ )
  224. out->me[i][j] = scalar*matrix->me[i][j];
  225. **************************************************/
  226. return (out);
  227. }
  228. /* zvm_mlt -- vector adjoint-matrix multiplication */
  229. ZVEC *zvm_mlt(A,b,out)
  230. ZMAT *A;
  231. ZVEC *b,*out;
  232. {
  233. unsigned int j,m,n;
  234. /* complex sum,**A_v,*b_v; */
  235. if ( A==ZMNULL || b==ZVNULL )
  236. error(E_NULL,"zvm_mlt");
  237. if ( A->m != b->dim )
  238. error(E_SIZES,"zvm_mlt");
  239. if ( b == out )
  240. error(E_INSITU,"zvm_mlt");
  241. if ( out == ZVNULL || out->dim != A->n )
  242. out = zv_resize(out,A->n);
  243. m = A->m; n = A->n;
  244. zv_zero(out);
  245. for ( j = 0; j < m; j++ )
  246. if ( b->ve[j].re != 0.0 || b->ve[j].im != 0.0 )
  247. __zmltadd__(out->ve,A->me[j],b->ve[j],(int)n,Z_CONJ);
  248. /**************************************************
  249. A_v = A->me; b_v = b->ve;
  250. for ( j=0; j<n; j++ )
  251. {
  252. sum = 0.0;
  253. for ( i=0; i<m; i++ )
  254. sum += b_v[i]*A_v[i][j];
  255. out->ve[j] = sum;
  256. }
  257. **************************************************/
  258. return out;
  259. }
  260. /* zm_adjoint -- adjoint matrix */
  261. ZMAT *zm_adjoint(in,out)
  262. ZMAT *in, *out;
  263. {
  264. int i, j;
  265. int in_situ;
  266. complex tmp;
  267. if ( in == ZMNULL )
  268. error(E_NULL,"zm_adjoint");
  269. if ( in == out && in->n != in->m )
  270. error(E_INSITU2,"zm_adjoint");
  271. in_situ = ( in == out );
  272. if ( out == ZMNULL || out->m != in->n || out->n != in->m )
  273. out = zm_resize(out,in->n,in->m);
  274. if ( ! in_situ )
  275. {
  276. for ( i = 0; i < in->m; i++ )
  277. for ( j = 0; j < in->n; j++ )
  278. {
  279. out->me[j][i].re = in->me[i][j].re;
  280. out->me[j][i].im = - in->me[i][j].im;
  281. }
  282. }
  283. else
  284. {
  285. for ( i = 0 ; i < in->m; i++ )
  286. {
  287. for ( j = 0; j < i; j++ )
  288. {
  289. tmp.re = in->me[i][j].re;
  290. tmp.im = in->me[i][j].im;
  291. in->me[i][j].re = in->me[j][i].re;
  292. in->me[i][j].im = - in->me[j][i].im;
  293. in->me[j][i].re = tmp.re;
  294. in->me[j][i].im = - tmp.im;
  295. }
  296. in->me[i][i].im = - in->me[i][i].im;
  297. }
  298. }
  299. return out;
  300. }
  301. /* zswap_rows -- swaps rows i and j of matrix A upto column lim */
  302. ZMAT *zswap_rows(A,i,j,lo,hi)
  303. ZMAT *A;
  304. int i, j, lo, hi;
  305. {
  306. int k;
  307. complex **A_me, tmp;
  308. if ( ! A )
  309. error(E_NULL,"swap_rows");
  310. if ( i < 0 || j < 0 || i >= A->m || j >= A->m )
  311. error(E_SIZES,"swap_rows");
  312. lo = max(0,lo);
  313. hi = min(hi,A->n-1);
  314. A_me = A->me;
  315. for ( k = lo; k <= hi; k++ )
  316. {
  317. tmp = A_me[k][i];
  318. A_me[k][i] = A_me[k][j];
  319. A_me[k][j] = tmp;
  320. }
  321. return A;
  322. }
  323. /* zswap_cols -- swap columns i and j of matrix A upto row lim */
  324. ZMAT *zswap_cols(A,i,j,lo,hi)
  325. ZMAT *A;
  326. int i, j, lo, hi;
  327. {
  328. int k;
  329. complex **A_me, tmp;
  330. if ( ! A )
  331. error(E_NULL,"swap_cols");
  332. if ( i < 0 || j < 0 || i >= A->n || j >= A->n )
  333. error(E_SIZES,"swap_cols");
  334. lo = max(0,lo);
  335. hi = min(hi,A->m-1);
  336. A_me = A->me;
  337. for ( k = lo; k <= hi; k++ )
  338. {
  339. tmp = A_me[i][k];
  340. A_me[i][k] = A_me[j][k];
  341. A_me[j][k] = tmp;
  342. }
  343. return A;
  344. }
  345. /* mz_mltadd -- matrix-scalar multiply and add
  346. -- may be in situ
  347. -- returns out == A1 + s*A2 */
  348. ZMAT *mz_mltadd(A1,A2,s,out)
  349. ZMAT *A1, *A2, *out;
  350. complex s;
  351. {
  352. /* register complex *A1_e, *A2_e, *out_e; */
  353. /* register int j; */
  354. int i, m, n;
  355. if ( ! A1 || ! A2 )
  356. error(E_NULL,"mz_mltadd");
  357. if ( A1->m != A2->m || A1->n != A2->n )
  358. error(E_SIZES,"mz_mltadd");
  359. if ( out != A1 && out != A2 )
  360. out = zm_resize(out,A1->m,A1->n);
  361. if ( s.re == 0.0 && s.im == 0.0 )
  362. return zm_copy(A1,out);
  363. if ( s.re == 1.0 && s.im == 0.0 )
  364. return zm_add(A1,A2,out);
  365. out = zm_copy(A1,out);
  366. m = A1->m; n = A1->n;
  367. for ( i = 0; i < m; i++ )
  368. {
  369. __zmltadd__(out->me[i],A2->me[i],s,(int)n,Z_NOCONJ);
  370. /**************************************************
  371. A1_e = A1->me[i];
  372. A2_e = A2->me[i];
  373. out_e = out->me[i];
  374. for ( j = 0; j < n; j++ )
  375. out_e[j] = A1_e[j] + s*A2_e[j];
  376. **************************************************/
  377. }
  378. return out;
  379. }
  380. /* zmv_mltadd -- matrix-vector multiply and add
  381. -- may not be in situ
  382. -- returns out == v1 + alpha*A*v2 */
  383. ZVEC *zmv_mltadd(v1,v2,A,alpha,out)
  384. ZVEC *v1, *v2, *out;
  385. ZMAT *A;
  386. complex alpha;
  387. {
  388. /* register int j; */
  389. int i, m, n;
  390. complex tmp, *v2_ve, *out_ve;
  391. if ( ! v1 || ! v2 || ! A )
  392. error(E_NULL,"zmv_mltadd");
  393. if ( out == v2 )
  394. error(E_INSITU,"zmv_mltadd");
  395. if ( v1->dim != A->m || v2->dim != A-> n )
  396. error(E_SIZES,"zmv_mltadd");
  397. tracecatch(out = zv_copy(v1,out),"zmv_mltadd");
  398. v2_ve = v2->ve; out_ve = out->ve;
  399. m = A->m; n = A->n;
  400. if ( alpha.re == 0.0 && alpha.im == 0.0 )
  401. return out;
  402. for ( i = 0; i < m; i++ )
  403. {
  404. tmp = __zip__(A->me[i],v2_ve,(int)n,Z_NOCONJ);
  405. out_ve[i].re += alpha.re*tmp.re - alpha.im*tmp.im;
  406. out_ve[i].im += alpha.re*tmp.im + alpha.im*tmp.re;
  407. /**************************************************
  408. A_e = A->me[i];
  409. sum = 0.0;
  410. for ( j = 0; j < n; j++ )
  411. sum += A_e[j]*v2_ve[j];
  412. out_ve[i] = v1->ve[i] + alpha*sum;
  413. **************************************************/
  414. }
  415. return out;
  416. }
  417. /* zvm_mltadd -- vector-matrix multiply and add a la zvm_mlt()
  418. -- may not be in situ
  419. -- returns out == v1 + v2*.A */
  420. ZVEC *zvm_mltadd(v1,v2,A,alpha,out)
  421. ZVEC *v1, *v2, *out;
  422. ZMAT *A;
  423. complex alpha;
  424. {
  425. int /* i, */ j, m, n;
  426. complex tmp, /* *A_e, */ *out_ve;
  427. if ( ! v1 || ! v2 || ! A )
  428. error(E_NULL,"zvm_mltadd");
  429. if ( v2 == out )
  430. error(E_INSITU,"zvm_mltadd");
  431. if ( v1->dim != A->n || A->m != v2->dim )
  432. error(E_SIZES,"zvm_mltadd");
  433. tracecatch(out = zv_copy(v1,out),"zvm_mltadd");
  434. out_ve = out->ve; m = A->m; n = A->n;
  435. for ( j = 0; j < m; j++ )
  436. {
  437. /* tmp = zmlt(v2->ve[j],alpha); */
  438. tmp.re = v2->ve[j].re*alpha.re - v2->ve[j].im*alpha.im;
  439. tmp.im = v2->ve[j].re*alpha.im + v2->ve[j].im*alpha.re;
  440. if ( tmp.re != 0.0 || tmp.im != 0.0 )
  441. __zmltadd__(out_ve,A->me[j],tmp,(int)n,Z_CONJ);
  442. /**************************************************
  443. A_e = A->me[j];
  444. for ( i = 0; i < n; i++ )
  445. out_ve[i] += A_e[i]*tmp;
  446. **************************************************/
  447. }
  448. return out;
  449. }
  450. /* zget_col -- gets a specified column of a matrix; returned as a vector */
  451. ZVEC *zget_col(mat,col,vec)
  452. int col;
  453. ZMAT *mat;
  454. ZVEC *vec;
  455. {
  456. unsigned int i;
  457. if ( mat==ZMNULL )
  458. error(E_NULL,"zget_col");
  459. if ( col < 0 || col >= mat->n )
  460. error(E_RANGE,"zget_col");
  461. if ( vec==ZVNULL || vec->dim<mat->m )
  462. vec = zv_resize(vec,mat->m);
  463. for ( i=0; i<mat->m; i++ )
  464. vec->ve[i] = mat->me[i][col];
  465. return (vec);
  466. }
  467. /* zget_row -- gets a specified row of a matrix and retruns it as a vector */
  468. ZVEC *zget_row(mat,row,vec)
  469. int row;
  470. ZMAT *mat;
  471. ZVEC *vec;
  472. {
  473. int /* i, */ lim;
  474. if ( mat==ZMNULL )
  475. error(E_NULL,"zget_row");
  476. if ( row < 0 || row >= mat->m )
  477. error(E_RANGE,"zget_row");
  478. if ( vec==ZVNULL || vec->dim<mat->n )
  479. vec = zv_resize(vec,mat->n);
  480. lim = min(mat->n,vec->dim);
  481. /* for ( i=0; i<mat->n; i++ ) */
  482. /* vec->ve[i] = mat->me[row][i]; */
  483. MEMCOPY(mat->me[row],vec->ve,lim,complex);
  484. return (vec);
  485. }
  486. /* zset_col -- sets column of matrix to values given in vec (in situ) */
  487. ZMAT *zset_col(mat,col,vec)
  488. ZMAT *mat;
  489. ZVEC *vec;
  490. int col;
  491. {
  492. unsigned int i,lim;
  493. if ( mat==ZMNULL || vec==ZVNULL )
  494. error(E_NULL,"zset_col");
  495. if ( col < 0 || col >= mat->n )
  496. error(E_RANGE,"zset_col");
  497. lim = min(mat->m,vec->dim);
  498. for ( i=0; i<lim; i++ )
  499. mat->me[i][col] = vec->ve[i];
  500. return (mat);
  501. }
  502. /* zset_row -- sets row of matrix to values given in vec (in situ) */
  503. ZMAT *zset_row(mat,row,vec)
  504. ZMAT *mat;
  505. ZVEC *vec;
  506. int row;
  507. {
  508. unsigned int /* j, */ lim;
  509. if ( mat==ZMNULL || vec==ZVNULL )
  510. error(E_NULL,"zset_row");
  511. if ( row < 0 || row >= mat->m )
  512. error(E_RANGE,"zset_row");
  513. lim = min(mat->n,vec->dim);
  514. /* for ( j=j0; j<lim; j++ ) */
  515. /* mat->me[row][j] = vec->ve[j]; */
  516. MEMCOPY(vec->ve,mat->me[row],lim,complex);
  517. return (mat);
  518. }
  519. /* zm_rand -- randomise a complex matrix; uniform in [0,1)+[0,1)*i */
  520. ZMAT *zm_rand(A)
  521. ZMAT *A;
  522. {
  523. int i;
  524. if ( ! A )
  525. error(E_NULL,"zm_rand");
  526. for ( i = 0; i < A->m; i++ )
  527. mrandlist((Real *)(A->me[i]),2*A->n);
  528. return A;
  529. }