CMATRIX.CPP
上传用户:zengbais
上传日期:2022-08-08
资源大小:49k
文件大小:17k
开发平台:

C++ Builder

  1. #include "stdio.h"
  2. #include "string.h"
  3. #include "complex.h"
  4. #include "cmatrix.h"
  5. #include "fstream.h"
  6. // 缺省的构造函数,产生0行0列空复矩阵
  7. cmatrix::cmatrix(cbuffer * b): rownum(0),colnum(0),
  8. isneg(0),istrans(0),isconj(0)
  9. {
  10. if(b){
  11. buf=b;
  12. buf->alloc(0);
  13. }
  14. else
  15. buf = getnewcbuffer(0); // 如果缺省的b没有给出,则产生一
  16. // 长度为行乘列个复数和缓存
  17. }
  18. // 构造一r行c列的复矩阵,可选的复缓存指向b
  19. cmatrix::cmatrix(size_t r, size_t c, cbuffer * b):
  20. rownum(r),colnum(c),istrans(0),isneg(0),isconj(0)
  21. {
  22. if(b){
  23. buf=b;
  24. buf->alloc(r*c);
  25. }
  26. else
  27. buf = getnewcbuffer(r*c); // 如果缺省的b没有给出,则产生一
  28. // 长度为行乘列个复数和缓存
  29. }
  30. cmatrix::cmatrix(size_t n, cbuffer * b):
  31. rownum(n),colnum(1),istrans(0),isneg(0),isconj(0)
  32. {
  33. if(b){
  34. buf=b;
  35. buf->alloc(n);
  36. }
  37. else
  38. buf = getnewcbuffer(n); // 如果缺省的b没有给出,则产生一
  39. // 长度为行乘列个复数和缓存
  40. }
  41. cmatrix cunit(size_t n) // 产生n阶单位矩阵
  42. {
  43. cmatrix m(n,n);
  44. for(size_t i=0; i<n; i++)
  45. for(size_t j=0; j<n; j++)
  46. if(i==j) m.set(i,i,1.0);
  47. else m.set(i,j,0.0);
  48. return m;
  49. }
  50. // 拷贝构造函数
  51. cmatrix::cmatrix(cmatrix& m)
  52. {
  53. rownum = m.rownum; // 复制行数和列数
  54. colnum = m.colnum;
  55. istrans = m.istrans; // 复制标志
  56. isneg = m.isneg;
  57. isconj = m.isconj;
  58. buf = m.buf; // 指向相同的缓存
  59. buf->refnum++; // 缓存的引用数增1
  60. }
  61. // 用数据文件构造复矩阵
  62. cmatrix::cmatrix(const char * filename, cbuffer * b) :
  63. istrans(0),isneg(0),isconj(0)
  64. {
  65. char label[10];
  66. ifstream in(filename); // 打开文件输入
  67. in >> label; // 文件以cmatrix关键词打头
  68. if(strcmp(label, "cmatrix")!=0) throw TMESSAGE("format error!");
  69. in >> rownum >> colnum; // 接着是行数和列数
  70. if(!in.good()) throw TMESSAGE("read file error!");
  71. if(b) { buf=b; // 产生所需长度的缓存
  72. buf->alloc(rownum*colnum);
  73. }
  74. else buf = getnewcbuffer(rownum*colnum);
  75. size_t line;
  76. for(size_t i=0; i<rownum; i++) { // 按行循环输入
  77. in >> line; // 每行以行号开始
  78. if(line != i+1) throw TMESSAGE("format error!");
  79. in.width(sizeof(label));
  80. in >> label; // 紧接着是冒号
  81. if(label[0] != ':') throw TMESSAGE("format error!");
  82. COMPLEX a;
  83. for(size_t j=0; j<colnum; j++) { // 随后是一行的内容
  84. in >> a;
  85. set(i,j,a);
  86. }
  87. if(!in.good()) throw TMESSAGE("read file error!");
  88. }
  89. }
  90. // 从内存数据块构造复矩阵。data指向内存数据块,构造完毕后data指向的内存可以释放
  91. cmatrix::cmatrix(void * data, size_t r, size_t c, cbuffer * b):
  92. rownum(r),colnum(c),istrans(0),isneg(0),isconj(0)
  93. {
  94. if(b){
  95. buf=b;
  96. buf->alloc(r*c);
  97. }
  98. else
  99. buf = getnewcbuffer(r*c);
  100. COMPLEX * d = (COMPLEX *)data;
  101. for(size_t i=0; i<r*c; i++)
  102. buf->set(i,d[i]);
  103. }
  104. cmatrix::cmatrix(matrix& m, cbuffer* b) : // 由实矩阵产生一个内容相同的复矩阵
  105. istrans(0),isneg(0),isconj(0)
  106. {
  107. rownum = m.rownum;
  108. colnum = m.colnum;
  109. if(b) { buf=b; // 产生所需长度的缓存
  110. buf->alloc(rownum*colnum);
  111. }
  112. else buf = getnewcbuffer(rownum*colnum);
  113. for(size_t i=0; i<rownum; i++)
  114. for(size_t j=0; j<colnum; j++)
  115. set(i,j,m.value(i,j));
  116. }
  117. cmatrix::cmatrix(matrix& mr, matrix& mi, cbuffer * b): // 两个实矩阵成为实部和虚部
  118. istrans(0),isneg(0),isconj(0)
  119. {
  120. if(mr.rownum != mi.rownum || mr.colnum != mi.colnum)
  121. throw TMESSAGE("dimension not same!");
  122. rownum = mi.rownum;
  123. colnum = mr.colnum;
  124. if(b) { buf=b; // 产生所需长度的缓存
  125. buf->alloc(rownum*colnum);
  126. }
  127. else buf = getnewcbuffer(rownum*colnum);
  128. for(size_t i=0; i<rownum; i++)
  129. for(size_t j=0; j<colnum; j++)
  130. set(i,j,COMPLEX(mr.value(i,j),mi.value(i,j)));
  131. }
  132. matrix cmatrix::real() // 由实部生成实矩阵
  133. {
  134. matrix m(rownum, colnum);
  135. for(size_t i=0; i<rownum; i++)
  136. for(size_t j=0; j<colnum; j++) {
  137. m.set(i,j,::real(value(i,j)));
  138. }
  139. return m;
  140. }
  141. matrix cmatrix::image() // 由虚部生成实矩阵
  142. {
  143. matrix m(rownum, colnum);
  144. for(size_t i=0; i<rownum; i++)
  145. for(size_t j=0; j<colnum; j++)
  146. m.set(i,j,imag(value(i,j)));
  147. return m;
  148. }
  149. // 矩阵赋值
  150. cmatrix& cmatrix::operator=(cmatrix& m)
  151. {
  152. rownum = m.rownum; // 复制行数和列数
  153. colnum = m.colnum;
  154. if(buf == m.buf) // 如果本来就指向相同的缓存,则返回
  155. return (*this);
  156. buf->refnum--; // 否则放弃原来的缓存,先将原缓存引用数减1
  157. // 如果不为0说明还有其它的矩阵引用数据
  158. if(!buf->refnum)delete buf; // 否则删除缓存
  159. istrans = m.istrans; // 复制标志
  160. isneg = m.isneg;
  161. isconj = m.isconj;
  162. buf = m.buf; // 复制缓存指针
  163. buf->refnum++; // 缓存引用数增1
  164. return (*this);
  165. }
  166. cmatrix& cmatrix::operator=(matrix& m)
  167. {
  168. rownum = m.rownum; // 复制行数和列数
  169. colnum = m.colnum;
  170. buf->refnum--;
  171. if(!buf->refnum) delete buf; // 放弃原来缓存
  172. istrans = isneg = isconj = 0; // 标志清零
  173. buf = getnewcbuffer(rownum*colnum); // 申请新的缓存
  174. for(size_t i=0; i<rownum; i++)
  175. for(size_t j=0; j<colnum; j++)
  176. set(i,j,m.value(i,j));
  177. return (*this);
  178. }
  179. cmatrix& cmatrix::operator=(COMPLEX a) // 将矩阵所有元素设为常数a
  180. {
  181. if(rownum == 0 || colnum==0 ) return (*this);
  182. istrans = isneg = isconj = 0; // 标志清零
  183. for(size_t i=0; i<rownum; i++)
  184. for(size_t j=0; j<colnum; j++)
  185. set(i,j,a);
  186. return (*this);
  187. }
  188. COMPLEX cmatrix::operator()(size_t r, size_t c)
  189.  // 重载函数运算符,返回第r行c列的值
  190. {
  191. if(r>= rownum || c >= colnum)
  192. throw TMESSAGE("range overflow");
  193. return value(r,c);
  194. }
  195. COMPLEX cmatrix::operator()(size_t r)
  196. // 重载函数运算符,返回第r行0列的值,用于向量
  197. {
  198. return (*this)(r,0);
  199. }
  200. // 流输出
  201. ostream& operator<<(ostream& o, cmatrix& m)
  202. { // 先输出关键词cmatrix,后跟行数和列数
  203. o << "cmatrix " << m.rownum << 't' << m.colnum << endl;
  204. // 每行由行号,冒号,后跟一行的复数构成
  205. for(size_t i=0; i<m.rownum; i++) {
  206. o<< (i+1) <<':';
  207. size_t k=8;
  208. for(size_t j=0; j<m.colnum; j++) {
  209. o<<'t'<<m.value(i,j);
  210. if(--k==0) {
  211. k=8;
  212. o<<endl;
  213. }
  214. }
  215. o<<endl;
  216. }
  217. return o;
  218. }
  219. // 流输入
  220. istream& operator>>(istream& in, cmatrix& m)
  221. {
  222. char label[10];
  223. in.width(sizeof(label));
  224. in >> label;
  225. if(strcmp(label, "cmatrix")!=0) // 以关键词cmatrix打到
  226. throw TMESSAGE("format error!");
  227. in >> m.rownum >> m.colnum; // 后跟行数和列数
  228. if(!in.good()) throw TMESSAGE("read file error!");
  229. m.buf->refnum--; // 放弃原来的缓存
  230. if(!m.buf->refnum) delete m.buf;
  231. m.buf = getnewcbuffer(m.rownum*m.colnum); // 申请新的缓存
  232. m.istrans = m.isneg = m.isconj = 0; // 标志清零
  233. size_t line;
  234. for(size_t i=0; i<m.rownum; i++) {
  235. in >> line;
  236. if(line != i+1) throw TMESSAGE("format error!"); // 每行以行号开始
  237. in.width(sizeof(label));
  238. in >> label;
  239. if(label[0] != ':') throw TMESSAGE("format error!"); // 后跟冒号
  240. COMPLEX a;
  241. for(size_t j=0; j<m.colnum; j++) { // 然后是这一行的数据
  242. in >> a;
  243. m.set(i,j,a);
  244. }
  245. if(!in.good()) throw TMESSAGE("read file error!");
  246. }
  247. return in;
  248. }
  249. // 数乘矩阵,原矩阵内容改变为结果
  250. cmatrix& cmatrix::operator*=(COMPLEX a)
  251. {
  252. for(size_t i=0; i<rownum; i++)
  253. for(size_t j=0; j<colnum; j++)
  254. set(i,j,a*value(i,j));
  255. return (*this);
  256. }
  257. // 数乘矩阵,原矩阵内容不变,返回结果矩阵
  258. cmatrix cmatrix::operator*(COMPLEX a)
  259. {
  260. cmatrix m(rownum, colnum);
  261. for(size_t i=0; i<rownum; i++)
  262. for(size_t j=0; j<colnum; j++)
  263. m.set(i,j,a*value(i,j));
  264. return m;
  265. }
  266. cmatrix cmatrix::operator+(COMPLEX a) // 矩阵加常数,产生新矩阵
  267. {
  268. cmatrix m(rownum, colnum);
  269. for(size_t i=0; i<rownum; i++)
  270. for(size_t j=0; j<colnum; j++)
  271. m.set(i,j,a+value(i,j));
  272. return m;
  273. }
  274. cmatrix& cmatrix::operator+=(COMPLEX a) // 矩阵加常数,更动原矩阵
  275. {
  276. for(size_t i=0; i<rownum; i++)
  277. for(size_t j=0; j<colnum; j++)
  278. set(i,j,a+value(i,j));
  279. return (*this);
  280. }
  281. // 矩阵相加
  282. cmatrix cmatrix::operator+(cmatrix& m)
  283. {
  284. if(rownum != m.rownum || colnum != m.colnum) // 行列必须对应相等
  285. throw TMESSAGE("can not do add of cmatrix");
  286. cmatrix mm(rownum, colnum);
  287. COMPLEX a;
  288. for(size_t i=0; i<rownum; i++)
  289. for(size_t j=0; j<colnum; j++)
  290. {
  291. a = value(i,j)+m.value(i,j);
  292. mm.set(i,j,a);
  293. }
  294. return mm;
  295. }
  296. // 矩阵相加,不产生新的矩阵,修改原矩阵的内容
  297. cmatrix& cmatrix::operator+=(cmatrix &m)
  298. {
  299. COMPLEX a;
  300. for(size_t i=0; i<rownum; i++)
  301. for(size_t j=0; j<colnum; j++)
  302. {
  303. a = value(i,j)+m.value(i,j);
  304. set(i,j,a);
  305. }
  306. return (*this);
  307. }
  308. cmatrix cmatrix::operator-(cmatrix& a) // 矩阵相减
  309. {
  310. return (*this)+(-a);
  311. }
  312. cmatrix& cmatrix::operator-=(cmatrix& a) // 矩阵自身减矩阵
  313. {
  314. (*this)+=(-a);
  315. return (*this);
  316. }
  317. // 矩阵相乘,返回新产生的结果矩阵
  318. cmatrix cmatrix::operator*(cmatrix& m)
  319. {
  320. if(colnum != m.rownum) // 前矩阵的列数必须等于后矩阵的行数
  321. throw TMESSAGE("can not multiply!");
  322. cmatrix mm(rownum,m.colnum);
  323. COMPLEX a;
  324. for(size_t i=0; i<rownum; i++)
  325. for(size_t j=0; j<m.colnum; j++){
  326. a = 0.0;
  327. for(size_t k=0; k<colnum; k++)
  328. a += value(i,k)*m.value(k,j);
  329. mm.set(i,j,a);
  330. }
  331. return mm;
  332. }
  333. // 矩阵相乘,改变原矩阵的内容
  334. cmatrix& cmatrix::operator*=(cmatrix& m)
  335. {
  336. (*this) = (*this)*m;
  337. return (*this);
  338. }
  339. cmatrix cmatrix::operator-() // 矩阵求负,产生新的矩阵
  340. {
  341. cmatrix m(*this);
  342. m.neg();
  343. return m;
  344. }
  345. cmatrix& cmatrix::neg() // 矩阵自身求负
  346. {
  347. isneg = !isneg; // 取负标志求反
  348. return (*this);
  349. }
  350. cmatrix cmatrix::t() // 矩阵转置,产生新的矩阵
  351. {
  352. cmatrix m(*this);
  353. m.trans();
  354. return m;
  355. }
  356. cmatrix cmatrix::operator!() // 矩阵共轭,产生新的矩阵
  357. {
  358. cmatrix m(*this);
  359. return m.conj();
  360. }
  361. cmatrix cmatrix::tc() // 矩阵共轭转置,产生新的矩阵
  362. {
  363. cmatrix m(*this);
  364. return m.transconj();
  365. };
  366. cmatrix& cmatrix::operator-=(COMPLEX a) // 矩阵自身减常数
  367. {
  368. (*this) += (-a);
  369. return (*this);
  370. }
  371. cmatrix cmatrix::operator-(COMPLEX a) // 矩阵减常数,产生新的矩阵
  372. {
  373. return (*this)+(-a);
  374. }
  375. cmatrix operator-(COMPLEX a, cmatrix m) // 常数减矩阵,产生新的矩阵
  376. {
  377. return (-m)+a;
  378. }
  379. void cmatrix::swapr(size_t r1, size_t r2, size_t k) // 交换矩阵r1和r2两行
  380. {
  381. COMPLEX a;
  382. for(size_t i=k; i<colnum; i++) {
  383. a = value(r1, i);
  384. set(r1, i, value(r2, i));
  385. set(r2, i, a);
  386. }
  387. }
  388. void cmatrix::swapc(size_t c1, size_t c2, size_t k) // 交换c1和c2两列
  389. {
  390. COMPLEX a;
  391. for(size_t i=k; i<colnum; i++) {
  392. a = value(i, c1);
  393. set(i, c1, value(i, c2));
  394. set(i, c2, a);
  395. }
  396. }
  397. DOUBLE cmatrix::maxabs(size_t &r, size_t &c, size_t k)
  398.  // 求第k行和第k列后的主元及位置
  399. {
  400. DOUBLE a=0.0;
  401. DOUBLE br,bi;
  402. for(size_t i=k;i<rownum;i++)
  403. for(size_t j=k;j<colnum;j++) {
  404. br = ::real(value(i,j));
  405. bi = ::imag(value(i,j));
  406. br = br*br+bi*bi;
  407. if(a < br) {
  408. r=i;c=j;a=br;
  409. }
  410. }
  411. return a;
  412. }
  413. size_t cmatrix::zgsxy(cmatrix & m, int fn) // 进行主高斯消元运算,fn为参数,缺省为0
  414.  /* 本矩阵其实是常数阵,而矩阵m必须是方阵
  415. 运算过程其实是对本矩阵和m同时作行初等变换,
  416. 运算结果m的对角线相乘将是行列式,而本矩阵则变换成
  417. 自己的原矩阵被m的逆阵左乘,m的秩被返回,如果秩等于阶数
  418. 则本矩阵中的内容已经是唯一解
  419.  */
  420. {
  421. if(rownum != m.rownum || m.rownum != m.colnum) // 本矩阵行数必须与m相等
  422. // 且m必须是方阵
  423. throw TMESSAGE("can not divide!");
  424. lbuffer * bb = getnewlbuffer(rownum); // 产生一维数为行数的长整数缓存区
  425. lbuffer & b = (*bb); // 用引用的办法使下面的程序容易懂
  426. size_t is;
  427. COMPLEX a;
  428. size_t i,j,rank=0;
  429. for(size_t k=0; k<rownum; k++) { // 从第0行到第k行进行主高斯消元
  430. if(m.maxabs(is, i, k)==0) // 求m中第k级主元,主元所在的行,列存在is,i中
  431. // 返回的主元值放在a中
  432. break; // 如果主元为零,则m不可逆,运算失败
  433. rank = k+1; // rank存放当前的阶数
  434. b.retrieve(k) = i;  // 将长整数缓存区的第k个值设为i
  435. if(i != k)
  436. m.swapc(k, i); // 交换m中i,k两列
  437. if(is != k) {
  438. m.swapr(k, is, k); // 交换m中i,k两行,从k列以后交换
  439. swapr(k, is); // 交换本矩阵中i,k两行
  440. }
  441. a = m.value(k,k); // 取出主元值
  442. for (j=k+1;j<rownum;j++) // 本意是将m的第k行除以主元
  443. // 但只需把第k行的第k+1列以上除以主元即可
  444. // 这样还保留了主元作行列式运算用
  445. m.set(k,j,m.value(k,j)/a);
  446. for (j=0;j<colnum;j++) // 将本矩阵的第k行除以主元
  447. set(k,j,value(k,j)/a);
  448. // 上面两步相当于将m和本矩阵构成的增广矩阵第k行除以主元
  449. // 下面对增广矩阵作行基本初等变换使第k行的其余列均为零
  450. // 但0值无必要计算,因此从第k+1列开始计算
  451. for(j=k+1;j<rownum;j++) // j代表列,本矩阵的行数就是m的列数
  452. for(i=0;i<rownum;i++) //i代表行,依次对各行计算,k行除外
  453. if(i!=k)
  454. m.set(i,j,m.value(i,j)-m.value(i,k)*m.value(k,j));
  455. // 对本矩阵亦作同样的计算
  456. for(j=0;j<colnum;j++)
  457. for(i=0;i<rownum;i++)
  458. if(i!=k)
  459. set(i,j,value(i,j)-m.value(i,k)*value(k,j));
  460. } // 主高斯消元循环k结束
  461. if(fn == 1) {
  462. for(j=0; j<rank; j++)
  463. for(i=0; i<rownum; i++)
  464. if(i==j) m.set(i,i,1.0);
  465. else
  466. m.set(i,j,0.0);
  467. for(k = rank; k>0; k--)
  468. m.swapc(k-1,(size_t)b[k-1]);
  469. }
  470. for(k = rank; k>0; k--) // 将本矩阵中的各行按b中内容进行调节
  471. if(b[k-1] != k-1)
  472. swapr(k-1,(size_t)b[k-1]); // 行交换
  473. delete bb; // 释放长整数缓存
  474. return rank; // 返回mm的秩
  475. }
  476. cmatrix& cmatrix::operator/=(cmatrix m) // 利用重载的除法符号/=来解方程
  477. // 本矩阵设为d,则方程为mx=d,考虑解写成x=d/m的形式,
  478. // 而方程的解也存放在d中,则实际编程时写d/=m
  479. {
  480. if(zgsxy(m)!=rownum) // 如秩不等于m的阶数,则方程无解
  481. throw TMESSAGE("can not divide!");
  482. return *this;
  483. }
  484. cmatrix& cmatrix::fft(int l)
  485. {
  486. if(colnum != 1) throw TMESSAGE("fft need vector!");
  487. size_t n,i;
  488. int k;
  489. n = 1;
  490. for(k=0;k<10000;k++) {
  491. if(n>=rownum) break;
  492. n*=2;
  493. }
  494. if(rownum < n) { // 将数组扩大为2的乘幂维
  495. cmatrix m(n);
  496. for(i=0; i<rownum; i++)
  497. m.set(i,value(i,0));
  498. for(i=rownum; i<n; i++)
  499. m.set(i,0.0);
  500. (*this)=m;
  501. }
  502. size_t it,m,is,j,nv;
  503. int l0;
  504. COMPLEX q,s,v,podd;
  505. DOUBLE p;
  506. cmatrix f(n);
  507. for (it=0; it<n; it++)
  508. { m=it; is=0;
  509.   for (i=0; i<k; i++)
  510.  { j=m/2; is=2*is+(m-2*j); m=j;}
  511.   f.set(it,value(is,0));
  512. }
  513. set(0,1.0);
  514. cbuffer & pp = *buf;
  515. cbuffer & ff = *(f.buf);
  516. p = 2.0*M_PI/n;
  517. pp[1] = COMPLEX(cos(p),-sin(p));
  518. if (l!=0) pp[1] = ::conj(pp[1]);
  519. for (i=2; i<n; i++)
  520. pp[i] = pp[1]*pp[i-1];
  521. for (it=0; it<n-1; it+=2)
  522. {  v = ff[it];
  523. ff[it] += ff[it+1];
  524. ff[it+1] = v - ff[it+1];
  525. }
  526. m=n/2; nv=2;
  527. for (l0=k-2; l0>=0; l0--)
  528. { m/=2; nv*=2;
  529.   for (it=0; it<=(m-1)*nv; it+=nv)
  530.  for (j=0; j<=(nv/2)-1; j++)
  531. {
  532. podd = pp[m*j]*ff[it+j+nv/2];
  533. ff[it+j+nv/2] = ff[it+j]-podd;
  534. ff[it+j] += podd;
  535. }
  536. }
  537.  if (l!=0)
  538. for (i=0; i<n; i++)
  539.   ff[i]/=n;
  540. (*this) = f;
  541. return (*this);
  542. }
  543. cmatrix fft(matrix& m)
  544. {
  545. cmatrix mm(m);
  546. return mm.fft();
  547. }
  548. matrix convolute(matrix&a, matrix& b) // 求矩阵a与b的离散卷积
  549. {
  550. if(a.colnum != 1 || b.colnum != 1)throw TMESSAGE("must be a vector");
  551. size_t nn = a.rownum+b.rownum;
  552. size_t n;
  553. int k;
  554. n = 1;
  555. for(k=0;k<10000;k++) {
  556. if(n>=nn) break;
  557. n*=2;
  558. }
  559. matrix aa(n),bb(n);
  560. size_t i;
  561. aa = 0.0;
  562. bb = 0.0;
  563. for(i=0; i<a.rownum; i++)
  564. aa.set(i,a(i));
  565. for(i=0; i<b.rownum; i++)
  566. bb.set(i,b(i));
  567. cmatrix aafft(fft(aa)),bbfft(fft(bb));
  568. for(i=0; i<n; i++)
  569. aafft.set(i,aafft(i)*bbfft(i));
  570. nn--;
  571. matrix c(nn),d;
  572. d = (aafft.fft(1)).real();
  573. for(i=0;i<nn;i++)
  574. c.set(i,0,d(i));
  575. return c;
  576. }
  577. cmatrix& cmatrix::inv() // 用全选主元高斯-约当法求逆矩阵
  578. {
  579. if(rownum != colnum) throw TMESSAGE("must be a square matrix");
  580. size_t n = rownum;
  581. lbuffer * isp = getnewlbuffer(n);
  582. lbuffer * jsp = getnewlbuffer(n);
  583. lbuffer& is = (*isp);
  584. lbuffer& js = (*jsp);
  585. size_t i,j,k,u,v;
  586. DOUBLE d;
  587. for (k=0; k<n; k++)
  588. {
  589. if((d=maxabs(u,v,k))== 0.0) {
  590. delete isp;
  591. delete jsp;
  592. throw TMESSAGE("can not inverse");
  593. }
  594. is[k]=u;
  595. js[k]=v;
  596. /*
  597.  d=0.0;
  598.   for (i=k; i<=n-1; i++)
  599.   for (j=k; j<=n-1; j++)
  600.  { u=i*n+j;
  601. p=ar[u]*ar[u]+ai[u]*ai[u];
  602. if (p>d) { d=p; is[k]=i; js[k]=j;}
  603.  }
  604.   if (d+1.0==1.0)
  605.  { free(is); free(js); printf("err**not invn");
  606. return(0);
  607.  }
  608.  */
  609.   if (is[k]!=k) swapr(k,(size_t)is[k]);
  610. /*
  611.  for (j=0; j<=n-1; j++)
  612. { u=k*n+j; v=is[k]*n+j;
  613.   t=ar[u]; ar[u]=ar[v]; ar[v]=t;
  614.   t=ai[u]; ai[u]=ai[v]; ai[v]=t;
  615. } */
  616.   if (js[k]!=k) swapc(k,(size_t)js[k]);
  617. /*  for (i=0; i<=n-1; i++)
  618. { u=i*n+k; v=i*n+js[k];
  619.   t=ar[u]; ar[u]=ar[v]; ar[v]=t;
  620.   t=ai[u]; ai[u]=ai[v]; ai[v]=t;
  621. } */
  622. //   l=k*n+k;
  623.   set(k,k,::conj(value(k,k))/d);
  624. //   ar[l]=ar[l]/d; ai[l]=-ai[l]/d;
  625.   for (j=0; j<n; j++)
  626.  if (j!=k)
  627. set(k,j,value(k,j)*value(k,k));
  628. /*
  629. { u=k*n+j;
  630.   p=ar[u]*ar[l]; q=ai[u]*ai[l];
  631.   s=(ar[u]+ai[u])*(ar[l]+ai[l]);
  632.   ar[u]=p-q; ai[u]=s-p-q;
  633. } */
  634.   for (i=0; i<n; i++)
  635.  if (i!=k)
  636. { // v=i*n+k;
  637.   for (j=0; j<n; j++)
  638.  if (j!=k)
  639. set(i,j,value(i,j)-value(k,j)*value(i,k));
  640. /*
  641. { u=k*n+j;  w=i*n+j;
  642.   p=ar[u]*ar[v]; q=ai[u]*ai[v];
  643.   s=(ar[u]+ai[u])*(ar[v]+ai[v]);
  644.   t=p-q; b=s-p-q;
  645.   ar[w]=ar[w]-t;
  646.   ai[w]=ai[w]-b;
  647. } */
  648. }
  649.   for (i=0; i<n; i++)
  650.  if (i!=k)
  651. set(i,k,-value(i,k)*value(k,k));
  652. /* { u=i*n+k;
  653.   p=ar[u]*ar[l]; q=ai[u]*ai[l];
  654.   s=(ar[u]+ai[u])*(ar[l]+ai[l]);
  655.   ar[u]=q-p; ai[u]=p+q-s;
  656. } */
  657. }
  658.  for (k=n; k>0; k--)
  659. { if (js[k-1]!=k-1) swapr((size_t)js[k-1],k-1);
  660. /*  for (j=0; j<n; j++) swapr((size_t)js[k-1],k-1);
  661. { u=k*n+j; v=js[k]*n+j;
  662.   t=ar[u]; ar[u]=ar[v]; ar[v]=t;
  663.   t=ai[u]; ai[u]=ai[v]; ai[v]=t;
  664. } */
  665.   if (is[k-1]!=k-1) swapc((size_t)is[k-1],k-1);
  666. /*  for (i=0; i<=n-1; i++)
  667. { u=i*n+k; v=i*n+is[k];
  668.   t=ar[u]; ar[u]=ar[v]; ar[v]=t;
  669.   t=ai[u]; ai[u]=ai[v]; ai[v]=t;
  670. } */
  671. }
  672. delete isp;
  673. delete jsp;
  674. return (*this);
  675. }
  676. cmatrix cmatrix::operator~() // 求逆矩阵,但产生新矩阵
  677. {
  678. cmatrix m(*this);
  679. m.inv();
  680. return m;
  681. }
  682. cmatrix operator/(COMPLEX a, cmatrix m) // 求逆矩阵再乘常数
  683. {
  684. return (~m)*a;
  685. }
  686. cmatrix& cmatrix::operator/=(COMPLEX a) // 所有元素乘a的倒数,自身改变
  687. {
  688. (*this)*=1.0/a;
  689. return (*this);
  690. }
  691. cmatrix cmatrix::operator/(COMPLEX a) // 所有元素乘a的倒数,产生新的矩阵
  692. {
  693. cmatrix m(*this);
  694. m/=a;
  695. return m;
  696. }