fork download
  1.  
  2. module alice.arith.linear;
  3.  
  4. import std.algorithm;
  5. import std.stdio;
  6. import std.array;
  7. import std.conv:toImpl;
  8. import std.math;
  9. import std.typecons;
  10. import std.range;
  11.  
  12. //isCSVinはisCSVin(a,b)とすることでカンマ区切りされたbの要素の中にaが存在するかどうかを返す。
  13. import alice.file.csv : isCSVin;
  14.  
  15. private immutable BinArrayOp = "+,-,*,/,%,^,&,|";
  16. private immutable UnaArrayOp = "-,~";
  17. private immutable RiNotLeOp = "/,%,^^,<<,>>,>>>,~,in";
  18. private immutable RiEqLeOp = "+,-,*,&,|,^";
  19. private immutable VecMat7 = "Vector!,Matrix!";
  20. private immutable ArithOp = "+,-,*,/,%,^^,&,|,^,<<,>>,>>>";
  21.  
  22. version(unittest){
  23. import std.random;
  24. pragma(lib,"alice");
  25. unittest{
  26. writeln("Start Unittest ",__LINE__);
  27. Random ran = Random(unpredictableSeed);
  28. Matrix!real A = Matrix!real(3,3);A = 1;
  29. Matrix!real B = Matrix!real(3,3);B = 6;
  30. Matrix!real C = Matrix!real(3,3);C = 7;
  31. assert(C == (A+B));
  32. assert(A == C - 6);
  33. auto D = A[[0,1]..[0,3]];
  34. D[0][0] = 8;
  35. assert(A[0][0] == 8);
  36.  
  37. A.roop(cast(real)uniform(-1024,1024,ran));
  38.  
  39. auto lup = A.lupdec!(double);
  40. writeln("End Unittest ",__LINE__);
  41. }
  42.  
  43. void main(){
  44. writeln("Unittest Done.");
  45. }
  46. }
  47.  
  48.  
  49.  
  50. ///別名定義
  51. template PermMatrix(string RC){
  52. alias Matrix!("permutation",RC) PermMatrix;
  53. }
  54.  
  55. ///ditto
  56. template LUPTuple(T){
  57. alias Tuple!(PermMatrix!"row","p",Matrix!T,"l",Matrix!T,"u") LUPTuple;
  58. }
  59.  
  60. ///ditto
  61. template DiagMatrix(T)if(__traits(isArithmetic,T)){
  62. alias Matrix!("diagonal",T) DiagMatrix;
  63. }
  64.  
  65.  
  66. ///一般行列
  67. struct Matrix(T)if(__traits(isArithmetic,T)){
  68. private:
  69. T[][] _val;
  70.  
  71. /* 不変条件 速度低下が怖い場合は-releaseすること (dmd -O -release -inline で最高速度) */
  72. invariant(){
  73. //行の大きさはすべて同じ
  74. int x=-1 , y;
  75. for(int i=0;i<_val.length;i++){
  76. if(x < 0){
  77. x = _val[i].length;
  78. continue;
  79. }
  80. y = _val[i].length;
  81. assert(x == y);
  82. x = y;
  83. }
  84.  
  85. }
  86.  
  87. public:
  88.  
  89. ///r行c列の行列を作成
  90. this(size_t r,size_t c)
  91. in{
  92. assert(r > 0 && c > 0 );
  93. }
  94. body{
  95. _val.length = r;
  96. for(int i=0;i<r;i++)
  97. _val[i].length = c;
  98. }
  99.  
  100. ///r行c列でnで初期化された行列を作成する
  101. this(size_t r,size_t c,T n)
  102. in{
  103. assert(r > 0 && c > 0 );
  104. }
  105. body{
  106. _val.length = r;
  107. for(int i=0;i<r;i++){
  108. _val[i].length = c;
  109. _val[i][] = n;
  110. }
  111. }
  112.  
  113. ///配列vaaから行列を作る。
  114. this(T[][] vaa)
  115. in{
  116. assert(vaa.length > 0);
  117. assert(vaa[0].length > 0);
  118. }
  119. body{
  120. _val.length = vaa.length;
  121. for(int i=0;i<vaa.length;i++){
  122. _val[i].length = vaa[i].length;
  123. _val[i][] = vaa[i][];
  124. }
  125. }
  126. /*
  127.   ///代入。参照をコピー
  128.   ref Matrix!T opAssign(T n){
  129.   for(int i=0;i<_val.length;++i)
  130.   _val[i][] = n;
  131.   return this;
  132.   }
  133.  
  134.   ///ditto
  135.   ref Matrix!T opAssign(Matrix!T src){
  136.   _val = src._val;
  137.   return this;
  138.   }*/
  139.  
  140. ///行列の代入
  141. ref Matrix!T opAssign(E)(E src){
  142. static if(is(E:T)){
  143. for(int i=0;i<_val.length;++i)
  144. _val[i][] = src;
  145. return this;
  146. }else static if(is(E == Matrix!T)){
  147. _val = src._val.dup;
  148. return this;
  149. }else static if(E.stringof[0..6] == "Matrix" && is(typeof(E.det):T)){
  150. if(row != src.row || column != src.column)
  151. resize(src.row,src.column);
  152.  
  153. for(int i=0;i<_val.length;++i)
  154. for(int j=0;j<_val[i].length;++j)
  155. _val[i][j] = src[i][j];
  156. return this;
  157. }
  158. }
  159.  
  160. unittest{
  161. Matrix!int A = Matrix!int(3,3,1);
  162. auto D = A;
  163. D[0][0] = 0;
  164. assert(A[0][0] == 0);
  165. }
  166.  
  167. ///行列の積
  168. Matrix!T opBinary(string s:"*")(Matrix!T src)
  169. in{
  170. assert(_val[0].length == src._val.length);
  171. }
  172. body{
  173. Matrix!T dst = Matrix!T(_val.length,_val[0].length,0);
  174. for(int i=0;i<_val.length;++i)
  175. for(int j=0;j<_val[i].length;++j)
  176. for(int n=0;n<_val[i].length;++n)
  177. dst[i][j] += _val[i][n] * src[n][j];
  178.  
  179. return dst;
  180. }
  181.  
  182. ///ditto
  183. ref Matrix!T opOpAssign(string s:"*")(Matrix!T src)
  184. in{
  185. assert(_val[0].length == src._val.length);
  186. }
  187. body{
  188. Matrix!T Temp = Matrix!T(_val);
  189. for(int i=0;i<_val.length;++i)
  190. for(int j=0;j<_val[i].length;++j){
  191. _val[i][j] = 0;
  192. for(int n=0;n<_val[i].length;++n)
  193. _val[i][j] += Temp[i][n] * src[n][j];
  194. }
  195. return this;
  196. }
  197.  
  198. ///行列の+,-,/,<<,>>,>>>,&,|,^,%はそれぞれの要素をそれぞれ演算したものになる。
  199. Matrix!T opBinary(string s)(Matrix!T src)if(!s.isCSVin("*,^^,~,in"))
  200. in{
  201. assert(src._val.length == _val.length);
  202. assert(src._val[0].length == _val[0].length);
  203. }
  204. body{
  205. Matrix!T dst = Matrix!T(src._val.length , src._val[0].length);
  206. for(int i=0;i<_val.length;++i){
  207. static if(s.isCSVin("<<,>>,>>>")){
  208. for(int j=0;j<_val[i].length;++j)
  209. mixin(q{dst._val[i][j] = _val[i][j]}~s~q{src._val[i][j];});
  210. }else{
  211. mixin(q{dst._val[i][] = _val[i][]}~s~q{src._val[i][];});
  212. }
  213. }
  214. return dst;
  215. }
  216.  
  217. ///ditto
  218. ref Matrix!T opOpAssign(string s)(Matrix!T src)if(!s.isCSVin("*,^^,~,in"))
  219. in{
  220. assert(src._val.length == _val.length);
  221. assert(src._val[0].length == _val[0].length);
  222. }
  223. body{
  224. for(int i=0;i<_val.length;++i){
  225. static if(s.isCSVin("<<,>>,>>>")){ //配列演算が使えない場合
  226. for(int j=0;j<_val[i].length;++j)
  227. mixin(q{_val[i][j]}~s~q{= src._val[i][j];});
  228. }else{
  229. mixin("_val[i][]"~s~"= src._val[i][];");
  230. }
  231. }
  232. return this;
  233. }
  234.  
  235. ///行列とベクトルの積
  236. Vector!T opBinary(string s:"*")(Vector!T src)
  237. in{
  238. assert(src.length == _val[0].length);
  239. }
  240. body{
  241. Vector!T dst = Vector!T(_val[0].length,0);
  242. for(int i=0;i<dst.length;++i){
  243. for(int j=0;j<_val[i].length;++j)
  244. dst[i] += _val[i][j] * src[j];
  245. }
  246. return dst;
  247. }
  248.  
  249. ///ditto
  250. Vector!T opBinaryRight(string s:"*")(Vector!T src)
  251. in{
  252. assert(src.length == _val.length);
  253. }
  254. body{
  255. Vector!T dst = Vector!T(_val.length,0);
  256. for(int i=0;i<dst.length;++i){
  257. for(int j=0;j<_val.length;++j)
  258. dst[i] += src[j] * _val[j][i];
  259. }
  260. return dst;
  261. }
  262.  
  263. ///ただの数との演算+,-,*,/,^,&,|,<<,>>,>>>
  264. Matrix!T opBinary(string s,U)(U n)if(s.isCSVin("+,-,*,/,%,^,&,|,<<,>>,>>>")&&__traits(isArithmetic,U)){
  265. Matrix!T dst = Matrix!T(_val.length,_val[0].length);
  266. for(int i=0;i<_val.length;++i){
  267. static if(s.isCSVin("+,-,*,/,%,^,&,|")){
  268. mixin("dst._val[i][] = _val[i][] "~s~"n;");
  269. }else{
  270. for(int j=0;j<_val[i].length;++j)
  271. mixin("dst._val[i][j] = _val[i][j] "~s~" n;");
  272. }
  273. }
  274. return dst;
  275. }
  276.  
  277. ///ditto
  278. Matrix!T opBinaryRight(string s,U)(U n)if(s.isCSVin("+,*,^,&,|") && __traits(isArithmetic,U)){
  279. Matrix!T dst = Matrix!T(_val.length,_val[0].length);
  280. for(int i=0;i<_val.length;++i){
  281. static if(s.isCSVin("+,*,^,&,|")){
  282. mixin("dst._val[i][] = _val[i][] "~s~"n ;");
  283. }else{
  284. for(int j=0;j<_val[i].length;++j)
  285. mixin("dst._val[i][j] = n"~s~"_val[i][j];");
  286. }
  287. }
  288. return dst;
  289. }
  290.  
  291. ///ditto
  292. ref Matrix!T opOpAssign(string s,U)(U n)if(s.isCSVin("+,-,*,/,%,^,&,|,<<,>>,>>>") && __traits(isArithmetic,U)){
  293. for(int i=0;i<_val.length;++i){
  294. static if(s.isCSVin("+,-,*,/,%,^,&,|")){
  295. mixin("_val[i][] "~s~"= n");
  296. }else{
  297. for(int j=0;j<_val[i].length;++j)
  298. mixin("dst._val[i][j] "~s~"= n;");
  299. }
  300. }
  301. return this;
  302. }
  303.  
  304. ///単項演算++,--,-,~
  305. Matrix!T opUnary(string s)()if(/+s=="-"||s=="~"+/s.isCSVin("-,~,++,--")){
  306. Matrix!T dst = Matrix!T(_val);
  307. for(int i=0;i<_val.length;++i){
  308. static if(s.isCSVin("-,~")){
  309. dst._val[i][] = mixin(s~"_val[i][]");
  310. }else{
  311. for(int j=0;j<_val[i].length;++j)
  312. mixin(s~"_val[i][j];");
  313. }
  314. }
  315. return dst;
  316. }
  317.  
  318. ///等号演算子
  319. bool opEquals(Matrix!T src){
  320. if(src._val.length != _val.length)
  321. return false;
  322.  
  323. for(int i=0;i<_val.length;++i){
  324. if(_val[i].length != src._val[i].length)
  325. return false;
  326.  
  327. for(int j=0;j<_val[i].length;++j){
  328. if(_val[i][j] != src._val[i][j])
  329. return false;
  330. }
  331. }
  332. return true;
  333. }
  334.  
  335. ///インデックス演算子
  336. ref T[] opIndex(size_t r)
  337. in{
  338. assert(_val.length > r);
  339. }
  340. body{
  341. return _val[r];
  342. }
  343.  
  344. ///代入インデックス演算子
  345. ref T[] opIndexAssign(ref T[] x,size_t r)
  346. in{
  347. assert(_val.length > r);
  348. assert(x.length == _val.length);
  349. }
  350. body{
  351. _val[r][] = x[];
  352. return _val[r];
  353. }
  354.  
  355.  
  356. ///2次インデックス演算子
  357. ref T opIndex(size_t r,size_t c)
  358. in{
  359. assert(_val.length > r);
  360. assert(_val[r].length > c);
  361. }
  362. body{
  363. return _val[r][c];
  364. }
  365.  
  366.  
  367. ///2次代入インデックス演算子
  368. ref T opIndexAssign(T val, size_t r,size_t c)
  369. in{
  370. assert(_val.length > r);
  371. assert(_val[r].length > c);
  372. }
  373. body{
  374. _val[r][c] = val;
  375. return _val[r][c];
  376. }
  377.  
  378. ///スライス。コピーを返す。
  379. Matrix!T opSlice(){
  380. Matrix!T dst;
  381. dst._val.length = _val.length;
  382. for(int i=0;i<_val.length;++i)
  383. dst._val[i] = _val[i].dup;
  384. return dst;
  385. }
  386. unittest{
  387. Matrix!int A = Matrix!int(3,3,1);
  388. auto D = A[]; //コピーを返す。
  389. D[0][0] = 0;
  390. assert(A[0][0] == 1);
  391. }
  392.  
  393.  
  394. ///スライス。rとcに行,列の範囲を入れると参照で返す。
  395. Matrix!T opSlice(uint[2] r,uint[2] c)
  396. in{
  397. assert(r[0] < r[1]);
  398. assert(c[0] < c[1]);
  399. assert(r[1] <= _val.length);
  400. assert(c[1] <= _val[0].length);
  401. }
  402. body{
  403. Matrix!T dst;
  404. dst._val.length = r[1] - r[0];
  405. for(int i=r[0];i<r[1];++i){
  406. dst._val[i] = _val[i][c[0]..c[1]];
  407. }
  408. return dst;
  409. }
  410. unittest{
  411. Matrix!int A = Matrix!int(3,3,1);
  412. auto D = A[[0,3]..[0,1]]; //0列目を参照で返す
  413. D[1][0] = 0;
  414. assert(A[1][0] == 0);
  415. }
  416.  
  417.  
  418. ///"r"または"c"とstringに入れ込むと、そのidxの行又は列が配列として返ってくる。
  419. T[] opIndex(string s,size_t idx)
  420. in{
  421. assert(s=="r"||s=="c");
  422. if(s=="r"){
  423. assert(_val.length > idx);
  424. }else if(s=="c"){
  425. assert(_val[0].length > idx);
  426. }else
  427. assert(0);
  428. }
  429. body{
  430. if(s == "r"){
  431. return _val[idx];
  432. }else if(s == "c"){
  433. T[] dst;
  434. for(int i=0;i<_val.length;++i)
  435. dst ~= _val[i][idx];
  436. return dst;
  437. }else
  438. assert(0);
  439. }
  440.  
  441. ///"r"または"c"とstringに入れ込むと、そのidxの行又は列に配列を入れ込むことができる。
  442. ref Matrix!T opIndexAssign(ref T[] src, string s,size_t idx)
  443. in{
  444. assert(s=="r"||s=="c");
  445. if(s=="r"){
  446. assert(_val.length > idx);
  447. assert(_val[0].length == src.length);
  448. }else if(s=="c"){
  449. assert(_val[0].length > idx);
  450. assert(_val.length == src.length);
  451. }else
  452. assert(0);
  453. }
  454. body{
  455. if(s == "r"){
  456. _val[idx][] = src[];
  457. }else if(s == "c"){
  458. for(int i=0;i<_val.length;++i)
  459. _val[i][idx] = src[i];
  460. }else
  461. assert(0);
  462.  
  463. return this;
  464. }
  465.  
  466. ///キャスト cast(U)でMatrix!U型にキャストする。
  467. Matrix!U ElementCast(U)()if(__traits(compiles,cast(U)T.init) && __traits(isArithmetic,U) && !is(T == U)){
  468. Matrix!U dst = Matrix!U(_val.length,_val[0].length);
  469. for(int i=0;i<_val.length;++i)
  470. for(int j=0;j<_val[0].length;++j)
  471. dst[i][j] = cast(U)_val[i][j];
  472. return dst;
  473. }
  474.  
  475. ///逆行列を返す。
  476. Matrix!R inverse(R=T)()if(__traits(isFloating,R)&&__traits(compiles,cast(R)T.init))
  477. in{
  478. int rsize = _val.length;
  479. assert(rsize != 0);
  480. int csize = _val[0].length;
  481. assert(rsize == csize);
  482. }
  483. body{
  484. try{
  485. /*LUP分解からP,L,U行列をそれぞれ持ってくる。
  486.   * ここで、A*B=EとなるBを考えると、
  487.   * P*L*U*B=Eとなる。
  488.   * 両辺にPをかけて
  489.   * L*U*B=Pとなる。ここで、
  490.   * L*U*B[][i] = P[][i]となることに注目すると、
  491.   * 任意のB[][i]は
  492.   * UB[][i] = Z[][i]として
  493.   * LZ[][i] = P[][i]が成り立つ。
  494.   * ここで、Z[][i]について解くと、Z[i]が求まるので、
  495.   * UB[][i] = Z[][i] を使い、
  496.   * B[][i] も求まる。
  497.   * この操作をすべての列について行えば、B行列がもとまり、
  498.   * B行列はAの逆行列であることがわかる。
  499.   */
  500. auto lup = lupdec!R;
  501. Matrix!R dst = Matrix!R(_val.length,_val[0].length);
  502. Matrix!R Z = Matrix!R(_val.length,_val[0].length);
  503. auto p = cast(Matrix!real)lup[0];
  504.  
  505. //このループではZを求める。
  506. for(int k=0;k<_val.length;++k)
  507. for(int i=0;i<_val.length;++i){
  508. Z[i][k] = p[i][k];
  509. for(int j=0;j<i;++j)
  510. Z[i][k] -= lup[1][i][j] * Z[j][k];
  511. }
  512.  
  513. //このループではZから逆行列を求める
  514. for(int k=0;k<_val.length;++k)
  515. for(int i=_val.length-1;i>=0;--i){
  516. dst[i][k] = Z[i][k];
  517. for(int j=i+1;j<_val.length;++j)
  518. dst[i][k] -= lup[2][i][j] * dst[j][k];
  519. dst[i][k] /= lup[2][i][i];
  520. }
  521. return dst;
  522. }
  523. catch(Exception ex){
  524. /*余因子行列の転置行列の要素すべてを
  525.   * もとの行列の行列式の値でわれば
  526.   * 逆行列となる。
  527.   */
  528. R Det = cast(R)det();
  529. if(Det == 0)throw new Exception("this matrix is not regular matrix");
  530. static if(typeid(R) == typeid(T))
  531. return (adjoint().trans())/Det;
  532. else
  533. return (adjoint().trans().ElementCast!R)/Det;
  534. }
  535. }
  536.  
  537. ///行列式の値
  538. @property R det(R=T)()if(__traits(compiles,cast(R)T.init))
  539. in{
  540. int rsize = _val.length;
  541. assert(rsize != 0);
  542. int csize = _val[0].length;
  543. assert(rsize == csize);
  544. }
  545. body{
  546. static if(__traits(isFloating,R)){
  547. try{
  548. auto lup = lupdec!R;
  549. R dst = 1;
  550. for(int i=0;i<_val.length;++i)
  551. dst *= lup[2][i][i];
  552. return dst;
  553. }
  554. catch(Exception ex){
  555. //1行目(r=0)の余因子展開により求める。
  556. R dst = 0;
  557. for(int i=0;i<_val.length;++i)
  558. dst += _val[0][i] * confactor(0,i);
  559. return dst;
  560. }
  561. }else{
  562. R dst = 0;
  563. for(int i=0;i<_val.length;++i)
  564. dst += _val[0][i] * confactor(0,i);
  565. return dst;
  566. }
  567. }
  568.  
  569. ///i,j余因子
  570. T confactor(int x,int y)
  571. in{
  572. //不変条件invariantですべての行の大きさが等しいことは保証される
  573. int l1 = _val.length;
  574. assert(l1 != 0);
  575.  
  576. //正方行列かつ大きさは0でない
  577. assert(l1 == _val[0].length);
  578.  
  579. //x,yはl1以下である
  580. assert(l1 > x);
  581. assert(l1 > y);
  582. }
  583. body{
  584. Matrix!T Temp = Matrix!T(_val.length-1,_val[0].length-1);
  585.  
  586. for(int i=0,i1=0;i<_val.length;++i){
  587. if(i == x)continue;
  588.  
  589. for(int j=0,j1=0;j<_val[i].length;++j){
  590. if(j == y)continue;
  591.  
  592. Temp[i1][j1] = _val[i][j];
  593. ++j1;
  594. }
  595. ++i1;
  596. }
  597. return (Temp.det() * (((x+y)%2)?-1:1));
  598. }
  599.  
  600. ///余因子行列
  601. @property Matrix!T adjoint()
  602. in{
  603. //不変条件invariantですべての行の大きさが等しいことは保証される
  604. int l1 = _val.length;
  605.  
  606. //正方行列かつ大きさは0でない
  607. assert(l1 != 0);
  608. assert(l1 == _val[0].length);
  609. }
  610. body{
  611. Matrix!T dst = Matrix!T(_val.length,_val[0].length);
  612. for(int i=0;i<_val.length;++i)
  613. for(int j=0;j<_val[i].length;++j)
  614. dst[i][j] = confactor(j,i);
  615. return dst;
  616. }
  617.  
  618. /**
  619.   * LUP分解. Aに対して PA = LU となるLUPを返す.
  620.   *
  621.   * Example:
  622.   * --------------------------
  623.   * auto LUP = A.lupdec();
  624.   * assert(LUP[0]*LUP[1]*LUP[2]==A);
  625.   * --------------------------
  626.   *
  627.   * Return: P,L,Uの順番で入れられたTupleを返す
  628.   * Throw: 失敗時,Exception
  629.   *
  630.   */
  631. //浮動小数点でないと、LUP分解できないようにしておかないと正常にLUP分解できない
  632. //すべて整数値で結果が欲しい場合にはA.lupdec!(real).to!intというようにキャストする
  633. @property LUPTuple!R lupdec(R=T)()if(__traits(isFloating,R)&&__traits(compiles,cast(R)T.init))
  634. in{
  635. assert(_val.length != 0);
  636. assert(_val.length == _val[0].length);
  637. }
  638. body{
  639. //LU分解を行う
  640. Matrix!R L = Matrix!R(row,column,0);
  641. Matrix!R U = Matrix!R(row,column,0);
  642. PermMatrix!"row" P = PermMatrix!"row"(row);
  643. Matrix!R A = Matrix!R(row,column,0);
  644.  
  645. //Lの対角成分をすべて1に
  646. for(int i=0;i<row && i<column;++i)
  647. L[i][i] = 1;
  648.  
  649. //static ifを使うことにより、コンパイルを条件分岐。TとRが異なる型の場合にはelseがコンパイルされる。
  650. //本当はaliasを使ったほうが効率がいいが、なぜかコンパイラに怒られる
  651. static if(T.stringof == R.stringof){
  652. Matrix!R SRC = Matrix!R(_val);
  653. }else{
  654. Matrix!R SRC = ElementCast!R;
  655. }
  656. if(SRC[0][0] == 0){
  657. //置換を行う
  658. for(int i=1;i<row;++i){
  659. if(SRC[i][0] != 0){//入れ替え
  660. A._val[0] = SRC._val[i];
  661. A._val[i] = SRC._val[0];
  662.  
  663. P.swap(0,i);
  664. }else{
  665. A._val[i] = SRC._val[i];
  666. }
  667. }
  668. }else{
  669. for(int i=0;i<row;++i)
  670. A._val[i] = SRC._val[i];
  671. }
  672. //もし未だに(0,0)成分が0ならすべての0行目の成分は0であり、LUP分解は不可能。
  673. if(A[0][0] == 0)
  674. throw new Exception("all row:0 element are 0.");
  675.  
  676. //まずUの一列目の計算を行う
  677. for(int j=0;j<column;++j)
  678. U[0][j] = A[0][j];
  679.  
  680. //1行目のLについて計算を行う
  681. for(int i=1;i<row;++i)
  682. L[i][0] = A[i][0] / U[0][0];
  683.  
  684. //1列目(行目)以降のL,Uについて計算する
  685. for(int i=1;i<row;i++){
  686. //Uについて
  687. for(int j=i;j<column;++j){
  688. U[i][j] = A[i][j];
  689. //ここから引いていく
  690. for(int k=0;k<i;++k)
  691. U[i][j] -= L[i][k]*U[k][j];
  692. }
  693. //0なら入れ替え
  694. if(U[i][i] == 0){
  695. bool finish;
  696. if(i == row)throw new Exception("final diagonal element is 0."); //つまり最終成分が0なら例外
  697. for(int l=i+1;l<row;++l)
  698. if(_val[l][l] != _val[i][i]){//入れ替え
  699. R[] temp;
  700. temp = A._val[i];
  701. A._val[i] = A._val[l];
  702. A._val[l] = temp;
  703.  
  704. P.swap(i,l);
  705. finish = true;
  706. break;
  707. }
  708. if(!finish)
  709. throw new Exception("Can't LUPdecompose this Matrix.\n"~A.toString());
  710. --i;
  711. continue;
  712. }
  713.  
  714. //Lについて
  715. for(int j=i+1;j<row;j++){
  716. L[j][i] = A[j][i];
  717. //ここから引いていく
  718. for(int k=0;k<i;++k)
  719. L[j][i] -= L[j][k]*U[k][i];
  720. //最後に割ってやる
  721. L[j][i] /= U[i][i];
  722. }
  723. }
  724.  
  725. //Matrix!R[] dst;
  726. LUPTuple!R dst;
  727. dst[0] = P;
  728. dst[1] = L;
  729. dst[2] = U;
  730. return dst;
  731. }
  732. unittest{
  733. writeln("Start Unittest ",__LINE__);
  734. Matrix!real A = Matrix!real([[1,1,1],[11,13,23],[1,52,1]]);
  735. auto lup = A.lupdec!real;
  736. auto Adelta = lup[0] * lup[1] * lup[2];
  737. writeln("End Unittest ",__LINE__);
  738. }
  739.  
  740. ///転置行列を返す
  741. @property Matrix!T trans()
  742. in{
  743. assert(_val.length != 0);
  744. assert(_val[0].length != 0);
  745. }
  746. body{
  747. Matrix!T dst = Matrix!T(_val[0].length,_val.length);
  748. for(int i=0;i<_val.length;++i)
  749. for(int j=0;j<_val[i].length;++j)
  750. dst[j][i] = _val[i][j];
  751. return dst;
  752. }
  753.  
  754. ///行列のコピーを返す
  755. @property Matrix!T dup(){
  756. return Matrix!T(_val);
  757. }
  758.  
  759. ///行列の大きさを0x0にする.
  760. @property void clear(){
  761. for(int i=0;i<_val.length;++i)
  762. _val[i].length = 0;
  763. _val.length = 0;
  764. }
  765.  
  766. ///行列の大きさの変更
  767. void resize(size_t R,size_t C)
  768. in{
  769. assert(R > 0);
  770. assert(C > 0);
  771. }
  772. body{
  773. _val.length = R;
  774. for(int i=0;i<R;++i)
  775. _val[i].length = C;
  776. }
  777.  
  778. ///行の大きさ
  779. @property size_t row(){
  780. return _val.length;
  781. }
  782.  
  783. ///列の大きさ
  784. @property size_t column()
  785. in{assert(_val.length != 0);}
  786. body{
  787. return _val[0].length;
  788. }
  789.  
  790. ///文字列化
  791. string toString(){
  792. string dst;
  793. for(int i=0;i<_val.length;++i){
  794. for(int j=0;j<_val.length;++j)
  795. dst ~= toImpl!(string,T)(_val[i][j]) ~ "\t";
  796. dst ~= "\n";
  797. }
  798. return dst;
  799. }
  800. unittest{
  801. Matrix!int a = Matrix!int(3,3);
  802. //writeln(a);
  803. }
  804.  
  805. ///関数などを引数有りで入れてやると面白い事になるだけ
  806. void roop(lazy T dg){
  807. for(int i=0;i<_val.length;++i)
  808. for(int j=0;j<_val[i].length;++j)
  809. _val[i][j] = dg();
  810. }
  811.  
  812. }
  813.  
  814. ///n次置換行列
  815. struct Matrix(string MT:"permutation",string RC="row")if(RC == "row" || RC == "column"){
  816. private:
  817. size_t[] _val;
  818.  
  819. public:
  820.  
  821. ///size × sizeの大きさの置換行列を作る。
  822. this(size_t size){
  823. _val.length = size;
  824. for(int i=0;i<size;++i)
  825. _val[i] = i;
  826. }
  827.  
  828. ///a行(列)とb行(列)を入れ替える。
  829. void swap(size_t a,size_t b)
  830. in{
  831. assert(a < _val.length);
  832. assert(b < _val.length);
  833. }
  834. body{
  835. size_t temp = _val[a];
  836. _val[a] = _val[b];
  837. _val[b] = temp;
  838. }
  839.  
  840. ///大きさを返す
  841. @property size_t row(){return _val.length;}
  842. ///ditto
  843. alias row column;
  844.  
  845. static if(RC == "row"){
  846. ///一般行列との積。つまり一般行列を行について置換する。
  847. Matrix!T opBinary(string s:"*",T)(Matrix!T src)
  848. in{assert(_val.length == src.row);}
  849. body{
  850. Matrix!T dst = Matrix!T(src.row,src.column);
  851. for(int i=0;i<_val.length;++i)
  852. dst._val[i] = src._val[_val[i]].dup;
  853. return dst;
  854. }
  855. }else{
  856. ///一般行列との積。つまり一般行列を列について置換する。
  857. Matrix!T opBinaryRight(string s:"*",T)(Matrix!T src)
  858. in{assert(_val.length == src.column);}
  859. body{
  860. Matrix!T dst = Matrix!T(src._val);
  861. for(int j=0;j<_val.length;++j)
  862. if(j != _val[j])
  863. for(int i=0;i<src.row;++i)
  864. dst[i][j] = src[i][_val[j]];
  865. return dst;
  866. }
  867. }
  868.  
  869. ///基本行列型に変換する。
  870. U opCast(U)()if(U.stringof[0..7] == "Matrix!" ){
  871. static assert(is(U A:Matrix!V,V),"not cast to "~U.stringof);
  872. static assert(!is(typeof(V) == string),"not cast to "~U.stringof);
  873. U dst = U(_val.length,_val.length,0);
  874. for(int i=0;i<_val.length;++i){
  875. static if(RC == "row")
  876. dst[i][_val[i]] = 1;
  877. else
  878. dst[_val[i]][i] = 1;
  879. }
  880. return dst;
  881. }
  882.  
  883. ///置換行列同士のコピー
  884. ref typeof(this) opAssign(typeof(this) src){
  885. _val = src._val;
  886. return this;
  887. }
  888.  
  889. ///コピーを返す。
  890. typeof(this) opSlice(){
  891. Matrix!(MT,RC) dst;
  892. dst._val = _val.dup;
  893. return dst;
  894. }
  895.  
  896. ///インデックス演算子
  897. size_t opIndex(size_t s)
  898. in{assert(s < _val.length);}
  899. body{
  900. return _val[s];
  901. }
  902.  
  903. invariant(){
  904. bool[] ch;
  905. ch.length = _val.length;
  906. for(int i=0;i<_val.length;++i){
  907. assert(ch[_val[i]] == false);
  908. ch[_val[i]] = true;
  909. }
  910. }
  911. }
  912. unittest{
  913. //writeln("Start Unittest ",__LINE__);
  914. import std.algorithm;
  915. Matrix!int A = Matrix!int([[0,1,2],[3,4,5],[6,7,8]]);
  916.  
  917. auto Pr = Matrix!"permutation"(3);
  918. auto Pc = Matrix!("permutation","column")(3);
  919. assert(Pr.row == 3);
  920. assert(Pr.column == 3);
  921. Pr.swap(1,2);
  922. Pr.swap(0,1);
  923.  
  924. Pc.swap(1,2);
  925. Pc.swap(0,1);
  926. //(1,2)と(0,1)をすると、abcは最終的にはcabとなる。
  927. auto Ars = Pr * A;
  928. auto Acs = A * Pc;
  929.  
  930. assert(reduce!"a+b"(A[0]) == reduce!"a+b"(Ars[1]));
  931. assert(reduce!"a+b"(A[1]) == reduce!"a+b"(Ars[2]));
  932. assert(reduce!"a+b"(A[2]) == reduce!"a+b"(Ars[0]));
  933.  
  934. assert(reduce!"a+b"(A._val.transversal(0)) == reduce!"a+b"(Acs._val.transversal(1)));
  935. assert(reduce!"a+b"(A._val.transversal(1)) == reduce!"a+b"(Acs._val.transversal(2)));
  936. assert(reduce!"a+b"(A._val.transversal(2)) == reduce!"a+b"(Acs._val.transversal(0)));
  937.  
  938. //auto PrToInt = Pr.to!"row";
  939. //auto PcToInt = Pc.to!"column";
  940. auto PrToInt = cast(Matrix!int)Pr;
  941. auto PcToInt = cast(Matrix!int)Pc;
  942.  
  943. auto AIntPr = PrToInt * A;
  944. auto AIntPc = A * PcToInt;
  945. assert(AIntPr == Ars);
  946. assert(AIntPc == Acs);
  947. //writeln("End Unittest ",__LINE__);
  948. }
  949.  
  950. ///n次対角正方
  951. struct Matrix(string MT:"diagonal",T)if(isArithmetic,T){
  952. T[] _val;
  953.  
  954. ///sizeの大きさの対角行列(正方行列)
  955. this(size_t size){
  956. _val.length = size;
  957. _val[] = cast(T)1;
  958. }
  959. this(T[] src){
  960. _val = src.dup;
  961. }
  962.  
  963. ///行列の行の大きさ
  964. @property size_t row(){
  965. return _val.length;
  966. }
  967. ///行列の列の大きさ
  968. alias row column;
  969.  
  970. ///一般行列との積。つまり、それぞれの行をn倍する。
  971. Matrix!T opBinary(string s:"*")(Matrix!T src)
  972. in{
  973. assert(_val.length == src._val.length);
  974. assert(src._val[0].length != 0);
  975. }
  976. body{
  977. Matrix!T dst = Matrix!T(src._val.length,src._val[0].length);
  978. for(int i=0;i<_val.length;++i)
  979. dst._val[i][] = src._val[i][] * _val[i];
  980. return dst;
  981. }
  982. unittest{
  983. writeln("Unittest Start ",__LINE__);
  984. DiagMatrix!int d = DiagMatrix!int([1,2,3]);
  985. Matrix!int test = Matrix!int(3,3,1);
  986. Matrix!int check = Matrix!int([[1,1,1],[2,2,2],[3,3,3]]);
  987. assert(d*test == check);
  988. writeln("Unittest End ",__LINE__);
  989. }
  990.  
  991. ///一般行列との積。つまり、それぞれの列をn倍する。
  992. Matrix!T opBinaryRight(string s:"*")(Matrix!T src)
  993. in{
  994. assert(src._val.length != 0);
  995. assert(_val._val[0].length == src._val.length);
  996. }
  997. body{
  998. Matrix!T dst = Matrix!T(src._val.length,src._val[0].length);
  999. for(int i=0;i<src._val.length;++i)
  1000. dst._val[i][] = src._val[i][] * _val[];
  1001. return dst;
  1002. }
  1003. unittest{
  1004. writeln("Unittest Start ",__LINE__);
  1005. DiagMatrix!int d = DiagMatrix!int([1,2,3]);
  1006. Matrix!int test = Matrix!int(3,3,1);
  1007. Matrix!int check = Matrix!int([[1,2,3],[1,2,3],[1,2,3]]);
  1008. assert(test*d == check);
  1009. writeln("Unittest End ",__LINE__);
  1010. }
  1011.  
  1012. ///代入
  1013. ref typeof(this) opAssign(typeof(this) src){
  1014. _val = src._val;
  1015. return this;
  1016. }
  1017.  
  1018. ///インデックス演算子
  1019. T[] opIndex(size_t idx)
  1020. in{
  1021. assert(_val.length > idx);
  1022. }
  1023. body{
  1024. T[] dst;
  1025. static if(T.init == 0){
  1026. dst[idx] = _val[idx];
  1027. return dst;
  1028. }else{
  1029. dst[] = cast(T)0;
  1030. dst[idx] = _val[idx];
  1031. return dst;
  1032. }
  1033. }
  1034.  
  1035. T opIndex(size_t idx1,size_t idx2)
  1036. in{
  1037. assert(_val.length > idx1 && _val.length > idx2);
  1038. }
  1039. body{
  1040. if(idx1 == idx2)
  1041. return _val[idx1];
  1042. else
  1043. return cast(T)0;
  1044. }
  1045.  
  1046. ///コピーを返す。
  1047. typeof(this) opSlice(){
  1048. typeof(this) dst;
  1049. dst._val = _val.dup;
  1050. return dst;
  1051. }
  1052.  
  1053. ///T型からU型の対角行列に変換
  1054. @property Matrix!("diagonal",U) to(U)()if((U.stringof != T.stringof) && __traits(compiles,cast(U)T.init)){
  1055. Matrix!("diagonal",U) dst;
  1056. dst._val = cast(U)(_val.dup);
  1057. }
  1058.  
  1059. ///T型のMatrix!Tに変換する。
  1060. @property Matrix!T to(){
  1061. Matrix!T dst = Matrix!T(_val.length,_val.length);
  1062. for(int i=0;i<_val.length;++i)
  1063. dst._val[i][i] = _val[i];
  1064. return dst;
  1065. }
  1066. }
  1067.  
  1068. /+ 巡回行列
  1069. struct Matrix(string MT:"circulant",T)
  1070. +/
  1071.  
  1072. ///ベクトル
  1073. struct Vector(T)if(__traits(isArithmetic,T)){
  1074. private:
  1075. T[] _val;
  1076.  
  1077. public:
  1078. ///size次元のベクトルを作成
  1079. this(size_t size,T init = T.init)
  1080. in{assert(size > 0);}
  1081. body{
  1082. _val.length = size;
  1083. _val[] = init;
  1084. }
  1085.  
  1086. ///配列からベクトルを作成
  1087. this(T[] src){
  1088. _val = src.dup;
  1089. }
  1090.  
  1091. ///インデックス演算子
  1092. ref T opIndex(size_t idx)
  1093. in{assert(idx < _val.length);}
  1094. body{return _val[idx];}
  1095.  
  1096. ///ditto
  1097. ref T opIndexAssign(T v,size_t idx)
  1098. in{assert(idx < _val.length);}
  1099. body{_val[idx] = v;return _val[idx];}
  1100.  
  1101. ///スライス演算子。コピーを返す
  1102. Vector!T opSlice(){
  1103. return Vector!T(_val);
  1104. }
  1105.  
  1106. ///スライス演算子。組み込み配列のように動作する。
  1107. Vector!T opSlice(uint a,uint b)
  1108. in{
  1109. assert(b > a);
  1110. assert(b <= _val.length);
  1111. }
  1112. body{
  1113. Vector!T dst;
  1114. dst._val = _val[a..b];
  1115. return dst;
  1116. }
  1117.  
  1118. ///代入。ベクトルの場合は参照をコピーし、値の場合はすべての要素に値を代入する。
  1119. ref Vector!T opAssign(T n){
  1120. _val[] = n;
  1121. return this;
  1122. }
  1123. ///ditto
  1124. ref Vector!T opAssign(Vector!T V){
  1125. _val = V._val;
  1126. return this;
  1127. }
  1128.  
  1129. ///ベクトルの足し算、引き算
  1130. Vector!T opBinary(string s)(Vector!T V)if(s=="+"||s=="-")
  1131. in{
  1132. assert(_val.length == V.length);
  1133. }
  1134. body{
  1135. Vector!T dst = Vector!T(_val.length);
  1136. mixin("dst._val[] = _val[]"~s~"V._val[];");
  1137. return dst;
  1138. }
  1139.  
  1140. ///ditto
  1141. ref Vector!T opOpAssign(string s)(Vector!T V)if(s=="+"||s=="-")
  1142. in{
  1143. assert(_val.length == V.length);
  1144. }
  1145. body{
  1146. mixin("_val[] "~s~"= V._val[];");
  1147. return this;
  1148. }
  1149.  
  1150. ///ベクトルと数の+,-,*,/,%,^,&,|演算
  1151. Vector!T opBinary(string s,U)(U n)if(s.isCSVin("+,-,*,/,%,^,&,|")&&__traits(isArithmetic,U)){
  1152. Vector!T dst = Vector!T(_val.length);
  1153. mixin("dst._val[] = _val[] "~s~" n;");
  1154. return dst;
  1155. }
  1156.  
  1157. ///ditto
  1158. ref Vector!T opOpAssign(string s,U)(U n)if(s.isCSVin("+,-,*,/,%,^,&,|")&&__traits(isArithmetic,U)){
  1159. mixin("_val[] "~s~"= n;");
  1160. return this;
  1161. }
  1162.  
  1163. ///n op Vector という形での+,-,*,/,%,^,&,|演算
  1164. Vector!T opBinaryRight(string s,U)(U n)if(s.isCSVin("+,*,^,&,|")&&__traits(isArithmetic,U)){
  1165. Vector!T dst = Vector!T(_val.length);
  1166. mixin("dst._val[] = _val[]"~s~"n;");
  1167. return dst;
  1168. }
  1169.  
  1170. ///ditto
  1171. Vector!T opBinaryRight(string s,U)(U n)if(s.isCSVin("-,/,%")&&__traits(isArithmetic,U)){
  1172. Vector!T dst = Vector!T(_val.length);
  1173. mixin("dst._val[] = n"~s~"_val[]");
  1174. return dst;
  1175. }
  1176.  
  1177. ///等号演算子
  1178. bool opEquals(Vector!T v){
  1179. if(v.length != _val.length)return false;
  1180. for(int i=0;i<_val.length;++i)
  1181. if(_val[i] != v._val[i])return false;
  1182. return true;
  1183. }
  1184.  
  1185. ///大きさをリサイズする。
  1186. @property void resize(size_t size){_val.length = size;}
  1187.  
  1188. ///ベクトルの次元数
  1189. @property size_t length(){return _val.length;}
  1190. ///ditto
  1191. @property size_t length(size_t resize){_val.length = resize;return _val.length;}
  1192.  
  1193. ///ドル記号
  1194. @property size_t opDollar(){return _val.length;}
  1195.  
  1196. ///ベクトルが管理している配列を返す。
  1197. @property ref T[] array(){return _val;}
  1198.  
  1199. ///ベクトルの文字列表現
  1200. @property string toString(){return toImpl!(string,T[])(_val);}
  1201.  
  1202. ///ベクトルのノルムを返す。
  1203. @property U abs(U=T)()if(__traits(isFloating,U)){
  1204. U dst=0;
  1205. for(int i=0;i<_val.length;++i)
  1206. dst += _val[i]^^2;
  1207. return sqrt(dst);
  1208. }
  1209.  
  1210. ///ベクトルの大きさを返す
  1211. @property clear(){_val.length = 0;}
  1212.  
  1213. ///ベクトルのコピーを返す。
  1214. @property Vector!T dup(){return Vector!T(_val);}
  1215.  
  1216. ///要素のキャスト変換を行う
  1217. @property Vector!U ElementCast(U)()
  1218. if(__traits(compiles,cast(U)T.init) && __traits(isArithmetic,U) && !is(T == U)){
  1219. return Vector!U(std.array.array(map!(a => cast(U)a)(_val)));
  1220. }
  1221.  
  1222. ///キャスト:配列に変換可能
  1223. U opCast(U:T[])(){
  1224. return _val.dup;
  1225. }
  1226.  
  1227. ///スカラー積(内積) sはscalar,Scalar,sのいずれか
  1228. T prod(string s)(Vector!T src)if(s.isCSVin("scalar,Scalar,s"))
  1229. in{assert(_val.length == src._val.length);}
  1230. body{
  1231. T ret = 0;
  1232. for(int i=0;i<_val.length;++i)
  1233. ret += _val[i] * src._val[i];
  1234. return ret;
  1235. }
  1236.  
  1237. ///ベクトル積 sはvector,Vector,vのいずれか。さらに次元数が1,3,7しか定義されていない。
  1238. Vector!T prod(string s)(Vector!T src)if(s.isCSVin("vector,Vector,v"))
  1239. in{
  1240. assert(_val.length == src._val.length);
  1241. assert(_val.length == 1 || _val.length == 3 || _val.length == 7);
  1242. }
  1243. body{
  1244. Vector!T ret = Vector!T(_val.length,0);
  1245. switch(_val.length){
  1246. case 1:
  1247. return ret;
  1248.  
  1249. case 3:
  1250. ret[0] = _val[1] * src[2] - _val[2] * src[1];
  1251. ret[1] = _val[2] * src[0] - _val[0] * src[2];
  1252. ret[2] = _val[0] * src[1] - _val[1] * src[0];
  1253.  
  1254. case 7:
  1255. ret[0] = _val[1]*V[2] - _val[2]*V[1] - _val[3]*V[4] + _val[4]*V[3] - _val[5]*V[6] + _val[6]*V[5];
  1256. ret[1] =-_val[0]*V[2] + _val[2]*V[0] - _val[3]*V[5] + _val[4]*V[6] + _val[5]*V[3] - _val[6]*V[4];
  1257. ret[2] = _val[0]*V[1] - _val[1]*V[0] - _val[3]*V[6] - _val[4]*V[5] + _val[5]*V[4] + _val[6]*V[3];
  1258. ret[3] = _val[0]*V[4] + _val[1]*V[5] + _val[2]*V[6] - _val[4]*V[0] - _val[5]*V[1] - _val[6]*V[2];
  1259. ret[4] =-_val[0]*V[3] - _val[1]*V[6] + _val[2]*V[5] + _val[3]*V[0] - _val[5]*V[2] + _val[6]*V[1];
  1260. ret[5] = _val[0]*V[6] - _val[1]*V[3] - _val[2]*V[4] + _val[3]*V[1] + _val[4]*V[2] - _val[6]*V[0];
  1261. ret[6] =-_val[0]*V[5] + _val[1]*V[4] - _val[2]*V[3] + _val[3]*V[2] - _val[4]*V[1] + _val[5]*V[0];
  1262. return Ret;
  1263.  
  1264. default:
  1265. assert(0);
  1266. }
  1267. }
  1268.  
  1269. ///テンソル積 sはtensor,Tensor,tのいずれか
  1270. Matrix!T prod(string s)(Vector!T src)if(s.isCSVin("tensor,Tensor,t"))
  1271. in{assert(_val.length == src._val.length);}
  1272. body{
  1273. Matrix!T ret = Matrix!T(_val.length,src._val.length);
  1274. for(int i=0;i<_val.length;++i)
  1275. for(int j=0;j<src._val.length;++j)
  1276. ret[i][j] = _val[i] * src._val[j];
  1277. return ret;
  1278. }
  1279.  
  1280. ///外積 sはexterior,Exterior,eのいずれか
  1281. Matrix!T prod(string s)(Vector!T src)if(s.isCSVin("exterior,Exterior,e"))
  1282. in{assert(_val.length == src._val.length);}
  1283. body{
  1284. Matrix!T ret = Matrix!T(_val.length,src._val.length);
  1285. for(int i=0;i<_val.length;++i)
  1286. for(int j=0;j<src._val.length;++j)
  1287. ret._val[i][j] = _val[i]*src._val[j] - _val[j]*src._val[i];
  1288. return ret;
  1289. }
  1290.  
  1291. }
  1292.  
  1293. unittest{
  1294. writeln("Start Unittest ",__LINE__);
  1295. Vector!int A = Vector!int(3,3);
  1296. Vector!int B = Vector!int(3,4);
  1297. Vector!int C = Vector!int(3);
  1298. C = 7;
  1299. Vector!int D;
  1300. D = A+B;
  1301. assert(C==D);
  1302. writeln("End Unittest ",__LINE__);
  1303. //writeln(A[$-1]);
  1304. }
  1305.  
  1306. ///Ax = b型の連立一次方程式を解く。 O(n^2)
  1307. Vector!T lupsolve(T)(LUPTuple!T lup,Vector!T b)
  1308. in{
  1309. assert(lup[0].row == b.length);
  1310. }
  1311. body{
  1312. /*Ax = bという連立一次方程式でAをLUP分解すると
  1313.   * PLUx = y
  1314.   * LUx = Py
  1315.   * Lz = Py
  1316.   * これを解くと、ベクトルzが求まる
  1317.   * z = Uxなので、これを解くと、ベクトルxが求まる。
  1318.   */
  1319. Vector!T dst = Vector!T(b.length);
  1320. T[] z;
  1321. z.length = b.length;
  1322.  
  1323. for(int i=0;i<z.length;++i){
  1324. z[i] = b[lup[0][i]]; //ここで置換
  1325. for(int j=0;j<i;++j)
  1326. z[i] -= lup[1][i][j] * z[j];
  1327. }
  1328.  
  1329. for(int i=b.length-1;i>=0;--i){
  1330. dst[i] = z[i];
  1331. for(int j=i+1;j<b.length;++j)
  1332. dst[i] -= lup[2][i][j] * dst[j];
  1333. dst[i] /= lup[2][i][i];
  1334. }
  1335. return dst;
  1336. }
  1337.  
  1338. ///Cramerの公式から連立一次方程式の解を出す
  1339. Vector!T cramersolve(T)(Matrix!T src,Vector!T b)
  1340. in{
  1341. assert(src.row == b.length);
  1342. assert(src.row == src.column);
  1343. }
  1344. body{
  1345. auto dst = Vector!T(b.length,0);
  1346. Matrix!T temp;
  1347. auto srcdet = src.det!T;
  1348. for(int i=0;i<b.length;++i){
  1349. temp = src;
  1350. dst[i] = (temp["c",i] = b.array).det!T / srcdet;
  1351. }
  1352. return dst;
  1353. }
  1354.  
  1355.  
  1356. ///LUP分解の結果から行列の行列式の値を返す
  1357. @property T det(T)(LUPTuple!T lup){
  1358. T dst = 1;
  1359. for(int i=0;i<lup[2].row;++i)
  1360. dst *= lup[2][i][i];
  1361. return dst;
  1362. }
  1363.  
  1364. ///LUP分解の結果から行列の行列式の値を返す。
  1365. @property Matrix!T inverse(T)(LUPTuple!T lup){
  1366. int size = lup[1].row;
  1367. Matrix!T dst = Matrix!T(size,size);
  1368. Matrix!T Z = Matrix!T(size,size);
  1369. auto p = cast(Matrix!T)(lup[0]);
  1370.  
  1371. //このループではZを求める。
  1372. for(int k=0;k<size;++k)
  1373. for(int i=0;i<size;++i){
  1374. Z[i][k] = p[i][k];
  1375. for(int j=0;j<i;++j)
  1376. Z[i][k] -= lup[1][i][j] * Z[j][k];
  1377. }
  1378.  
  1379. //このループではZから逆行列を求める
  1380. for(int k=0;k<size;++k)
  1381. for(int i=size-1;i>=0;--i){
  1382. dst[i][k] = Z[i][k];
  1383. for(int j=i+1;j<size;++j)
  1384. dst[i][k] -= lup[2][i][j] * dst[j][k];
  1385. dst[i][k] /= lup[2][i][i];
  1386. }
  1387. return dst;
  1388. }
  1389. unittest{
  1390. Matrix!real A = Matrix!real([[2,1],[5,3]]);
  1391. assert(A.inverse!real == inverse!real(A.lupdec!real));
  1392. }
  1393. unittest{
  1394. import std.random;
  1395. Matrix!real A = Matrix!real(100,100);
  1396. A.roop(cast(real)uniform!"[]"(-1024,1024));
  1397. //writeln(A.inverse!real);
  1398. }
  1399.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty