PageRenderTime 43ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/source/library/Interlace/LinearAlgebra/Matrix.cs

https://bitbucket.org/VahidN/interlace
C# | 1237 lines | 681 code | 138 blank | 418 comment | 93 complexity | f08db36f718e014689d318ef639b135e MD5 | raw file
  1. #region Using Directives and Copyright Notice
  2. // Copyright (c) 2007-2010, Computer Consultancy Pty Ltd
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. // * Redistributions of source code must retain the above copyright
  8. // notice, this list of conditions and the following disclaimer.
  9. // * Redistributions in binary form must reproduce the above copyright
  10. // notice, this list of conditions and the following disclaimer in the
  11. // documentation and/or other materials provided with the distribution.
  12. // * Neither the name of the Computer Consultancy Pty Ltd nor the
  13. // names of its contributors may be used to endorse or promote products
  14. // derived from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. // ARE DISCLAIMED. IN NO EVENT SHALL COMPUTER CONSULTANCY PTY LTD BE LIABLE
  20. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  23. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  26. // DAMAGE.
  27. using System;
  28. using Interlace.LinearAlgebra.Utilities;
  29. #endregion
  30. namespace Interlace.LinearAlgebra
  31. {
  32. /// <summary>Jama = Java Matrix class.
  33. /// <P>
  34. /// The Java Matrix Class provides the fundamental operations of numerical
  35. /// linear algebra. Various constructors create Matrices from two dimensional
  36. /// arrays of double precision floating point numbers. Various "gets" and
  37. /// "sets" provide access to submatrices and matrix elements. Several methods
  38. /// implement basic matrix arithmetic, including matrix addition and
  39. /// multiplication, matrix norms, and element-by-element array operations.
  40. /// Methods for reading and printing matrices are also included. All the
  41. /// operations in this version of the Matrix Class involve real matrices.
  42. /// Complex matrices may be handled in a future version.
  43. /// <P>
  44. /// Five fundamental matrix decompositions, which consist of pairs or triples
  45. /// of matrices, permutation vectors, and the like, produce results in five
  46. /// decomposition classes. These decompositions are accessed by the Matrix
  47. /// class to compute solutions of simultaneous linear equations, determinants,
  48. /// inverses and other matrix functions. The five decompositions are:
  49. /// <P><UL>
  50. /// <LI>Cholesky Decomposition of symmetric, positive definite matrices.
  51. /// <LI>LU Decomposition of rectangular matrices.
  52. /// <LI>QR Decomposition of rectangular matrices.
  53. /// <LI>Singular Value Decomposition of rectangular matrices.
  54. /// <LI>Eigenvalue Decomposition of both symmetric and nonsymmetric square matrices.
  55. /// </UL>
  56. /// <DL>
  57. /// <DT><B>Example of use:</B></DT>
  58. /// <P>
  59. /// <DD>Solve a linear system A x = b and compute the residual norm, ||b - A x||.
  60. /// <P><PRE>
  61. /// double[][] vals = {{1.,2.,3},{4.,5.,6.},{7.,8.,10.}};
  62. /// Matrix A = new Matrix(vals);
  63. /// Matrix b = Matrix.random(3,1);
  64. /// Matrix x = A.solve(b);
  65. /// Matrix r = A.times(x).minus(b);
  66. /// double rnorm = r.normInf();
  67. /// </PRE></DD>
  68. /// </DL>
  69. /// </summary>
  70. /// <author> The MathWorks, Inc. and the National Institute of Standards and Technology.
  71. /// </author>
  72. /// <version> 5 August 1998
  73. /// </version>
  74. [Serializable]
  75. public class Matrix : System.ICloneable
  76. {
  77. /// <summary>Access the internal two-dimensional array.</summary>
  78. /// <returns> Pointer to the two-dimensional array of matrix elements.
  79. /// </returns>
  80. virtual public double[][] Array
  81. {
  82. get
  83. {
  84. return A;
  85. }
  86. }
  87. /// <summary>Copy the internal two-dimensional array.</summary>
  88. /// <returns> Two-dimensional array copy of matrix elements.
  89. /// </returns>
  90. virtual public double[][] ArrayCopy
  91. {
  92. get
  93. {
  94. double[][] C = new double[m][];
  95. for (int i = 0; i < m; i++)
  96. {
  97. C[i] = new double[n];
  98. }
  99. for (int i = 0; i < m; i++)
  100. {
  101. for (int j = 0; j < n; j++)
  102. {
  103. C[i][j] = A[i][j];
  104. }
  105. }
  106. return C;
  107. }
  108. }
  109. /// <summary>Make a one-dimensional column packed copy of the internal array.</summary>
  110. /// <returns> Matrix elements packed in a one-dimensional array by columns.
  111. /// </returns>
  112. virtual public double[] ColumnPackedCopy
  113. {
  114. get
  115. {
  116. double[] vals = new double[m * n];
  117. for (int i = 0; i < m; i++)
  118. {
  119. for (int j = 0; j < n; j++)
  120. {
  121. vals[i + j * m] = A[i][j];
  122. }
  123. }
  124. return vals;
  125. }
  126. }
  127. /// <summary>Make a one-dimensional row packed copy of the internal array.</summary>
  128. /// <returns> Matrix elements packed in a one-dimensional array by rows.
  129. /// </returns>
  130. virtual public double[] RowPackedCopy
  131. {
  132. get
  133. {
  134. double[] vals = new double[m * n];
  135. for (int i = 0; i < m; i++)
  136. {
  137. for (int j = 0; j < n; j++)
  138. {
  139. vals[i * n + j] = A[i][j];
  140. }
  141. }
  142. return vals;
  143. }
  144. }
  145. /// <summary>Get row dimension.</summary>
  146. /// <returns> m, the number of rows.
  147. /// </returns>
  148. virtual public int RowDimension
  149. {
  150. get
  151. {
  152. return m;
  153. }
  154. }
  155. /// <summary>Get column dimension.</summary>
  156. /// <returns> n, the number of columns.
  157. /// </returns>
  158. virtual public int ColumnDimension
  159. {
  160. get
  161. {
  162. return n;
  163. }
  164. }
  165. /* ------------------------
  166. Class variables
  167. * ------------------------ */
  168. /// <summary>Array for internal storage of elements.</summary>
  169. /// <serial> internal array storage.
  170. /// </serial>
  171. private double[][] A;
  172. /// <summary>Row and column dimensions.</summary>
  173. /// <serial> row dimension.
  174. /// </serial>
  175. /// <serial> column dimension.
  176. /// </serial>
  177. private int m, n;
  178. /* ------------------------
  179. Constructors
  180. * ------------------------ */
  181. /// <summary>Construct an m-by-n matrix of zeros. </summary>
  182. /// <param name="m"> Number of rows.
  183. /// </param>
  184. /// <param name="n"> Number of colums.
  185. /// </param>
  186. public Matrix(int m, int n)
  187. {
  188. this.m = m;
  189. this.n = n;
  190. A = new double[m][];
  191. for (int i = 0; i < m; i++)
  192. {
  193. A[i] = new double[n];
  194. }
  195. }
  196. /// <summary>Construct an m-by-n constant matrix.</summary>
  197. /// <param name="m"> Number of rows.
  198. /// </param>
  199. /// <param name="n"> Number of colums.
  200. /// </param>
  201. /// <param name="s"> Fill the matrix with this scalar value.
  202. /// </param>
  203. public Matrix(int m, int n, double s)
  204. {
  205. this.m = m;
  206. this.n = n;
  207. A = new double[m][];
  208. for (int i = 0; i < m; i++)
  209. {
  210. A[i] = new double[n];
  211. }
  212. for (int i = 0; i < m; i++)
  213. {
  214. for (int j = 0; j < n; j++)
  215. {
  216. A[i][j] = s;
  217. }
  218. }
  219. }
  220. /// <summary>Construct a matrix from a 2-D array.</summary>
  221. /// <param name="A"> Two-dimensional array of doubles.
  222. /// </param>
  223. /// <exception cref="IllegalArgumentException">All rows must have the same length
  224. /// </exception>
  225. /// <seealso cref="constructWithCopy">
  226. /// </seealso>
  227. public Matrix(double[][] A)
  228. {
  229. m = A.Length;
  230. n = A[0].Length;
  231. for (int i = 0; i < m; i++)
  232. {
  233. if (A[i].Length != n)
  234. {
  235. throw new System.ArgumentException("All rows must have the same length.");
  236. }
  237. }
  238. this.A = A;
  239. }
  240. /// <summary>Construct a matrix quickly without checking arguments.</summary>
  241. /// <param name="A"> Two-dimensional array of doubles.
  242. /// </param>
  243. /// <param name="m"> Number of rows.
  244. /// </param>
  245. /// <param name="n"> Number of colums.
  246. /// </param>
  247. public Matrix(double[][] A, int m, int n)
  248. {
  249. this.A = A;
  250. this.m = m;
  251. this.n = n;
  252. }
  253. /// <summary>Construct a matrix from a one-dimensional packed array</summary>
  254. /// <param name="vals">One-dimensional array of doubles, packed by columns (ala Fortran).
  255. /// </param>
  256. /// <param name="m"> Number of rows.
  257. /// </param>
  258. /// <exception cref="IllegalArgumentException">Array length must be a multiple of m.
  259. /// </exception>
  260. public Matrix(double[] vals, int m)
  261. {
  262. this.m = m;
  263. n = (m != 0?vals.Length / m:0);
  264. if (m * n != vals.Length)
  265. {
  266. throw new System.ArgumentException("Array length must be a multiple of m.");
  267. }
  268. A = new double[m][];
  269. for (int i = 0; i < m; i++)
  270. {
  271. A[i] = new double[n];
  272. }
  273. for (int i = 0; i < m; i++)
  274. {
  275. for (int j = 0; j < n; j++)
  276. {
  277. A[i][j] = vals[i + j * m];
  278. }
  279. }
  280. }
  281. /* ------------------------
  282. Public Methods
  283. * ------------------------ */
  284. /// <summary>Construct a matrix from a copy of a 2-D array.</summary>
  285. /// <param name="A"> Two-dimensional array of doubles.
  286. /// </param>
  287. /// <exception cref="IllegalArgumentException">All rows must have the same length
  288. /// </exception>
  289. public static Matrix constructWithCopy(double[][] A)
  290. {
  291. int m = A.Length;
  292. int n = A[0].Length;
  293. Matrix X = new Matrix(m, n);
  294. double[][] C = X.Array;
  295. for (int i = 0; i < m; i++)
  296. {
  297. if (A[i].Length != n)
  298. {
  299. throw new System.ArgumentException("All rows must have the same length.");
  300. }
  301. for (int j = 0; j < n; j++)
  302. {
  303. C[i][j] = A[i][j];
  304. }
  305. }
  306. return X;
  307. }
  308. /// <summary>Make a deep copy of a matrix</summary>
  309. public virtual Matrix copy()
  310. {
  311. Matrix X = new Matrix(m, n);
  312. double[][] C = X.Array;
  313. for (int i = 0; i < m; i++)
  314. {
  315. for (int j = 0; j < n; j++)
  316. {
  317. C[i][j] = A[i][j];
  318. }
  319. }
  320. return X;
  321. }
  322. /// <summary>Clone the Matrix object.</summary>
  323. public virtual System.Object Clone()
  324. {
  325. return this.copy();
  326. }
  327. /// <summary>Get a single element.</summary>
  328. /// <param name="i"> Row index.
  329. /// </param>
  330. /// <param name="j"> Column index.
  331. /// </param>
  332. /// <returns> A(i,j)
  333. /// </returns>
  334. /// <exception cref="ArrayIndexOutOfBoundsException">
  335. /// </exception>
  336. public virtual double get_Renamed(int i, int j)
  337. {
  338. return A[i][j];
  339. }
  340. /// <summary>Get a submatrix.</summary>
  341. /// <param name="i0"> Initial row index
  342. /// </param>
  343. /// <param name="i1"> Final row index
  344. /// </param>
  345. /// <param name="j0"> Initial column index
  346. /// </param>
  347. /// <param name="j1"> Final column index
  348. /// </param>
  349. /// <returns> A(i0:i1,j0:j1)
  350. /// </returns>
  351. /// <exception cref="ArrayIndexOutOfBoundsException">Submatrix indices
  352. /// </exception>
  353. public virtual Matrix getMatrix(int i0, int i1, int j0, int j1)
  354. {
  355. Matrix X = new Matrix(i1 - i0 + 1, j1 - j0 + 1);
  356. double[][] B = X.Array;
  357. try
  358. {
  359. for (int i = i0; i <= i1; i++)
  360. {
  361. for (int j = j0; j <= j1; j++)
  362. {
  363. B[i - i0][j - j0] = A[i][j];
  364. }
  365. }
  366. }
  367. catch (System.IndexOutOfRangeException)
  368. {
  369. throw new System.IndexOutOfRangeException("Submatrix indices");
  370. }
  371. return X;
  372. }
  373. /// <summary>Get a submatrix.</summary>
  374. /// <param name="r"> Array of row indices.
  375. /// </param>
  376. /// <param name="c"> Array of column indices.
  377. /// </param>
  378. /// <returns> A(r(:),c(:))
  379. /// </returns>
  380. /// <exception cref="ArrayIndexOutOfBoundsException">Submatrix indices
  381. /// </exception>
  382. public virtual Matrix getMatrix(int[] r, int[] c)
  383. {
  384. Matrix X = new Matrix(r.Length, c.Length);
  385. double[][] B = X.Array;
  386. try
  387. {
  388. for (int i = 0; i < r.Length; i++)
  389. {
  390. for (int j = 0; j < c.Length; j++)
  391. {
  392. B[i][j] = A[r[i]][c[j]];
  393. }
  394. }
  395. }
  396. catch (System.IndexOutOfRangeException)
  397. {
  398. throw new System.IndexOutOfRangeException("Submatrix indices");
  399. }
  400. return X;
  401. }
  402. /// <summary>Get a submatrix.</summary>
  403. /// <param name="i0"> Initial row index
  404. /// </param>
  405. /// <param name="i1"> Final row index
  406. /// </param>
  407. /// <param name="c"> Array of column indices.
  408. /// </param>
  409. /// <returns> A(i0:i1,c(:))
  410. /// </returns>
  411. /// <exception cref="ArrayIndexOutOfBoundsException">Submatrix indices
  412. /// </exception>
  413. public virtual Matrix getMatrix(int i0, int i1, int[] c)
  414. {
  415. Matrix X = new Matrix(i1 - i0 + 1, c.Length);
  416. double[][] B = X.Array;
  417. try
  418. {
  419. for (int i = i0; i <= i1; i++)
  420. {
  421. for (int j = 0; j < c.Length; j++)
  422. {
  423. B[i - i0][j] = A[i][c[j]];
  424. }
  425. }
  426. }
  427. catch (System.IndexOutOfRangeException)
  428. {
  429. throw new System.IndexOutOfRangeException("Submatrix indices");
  430. }
  431. return X;
  432. }
  433. /// <summary>Get a submatrix.</summary>
  434. /// <param name="r"> Array of row indices.
  435. /// </param>
  436. /// <param name="i0"> Initial column index
  437. /// </param>
  438. /// <param name="i1"> Final column index
  439. /// </param>
  440. /// <returns> A(r(:),j0:j1)
  441. /// </returns>
  442. /// <exception cref="ArrayIndexOutOfBoundsException">Submatrix indices
  443. /// </exception>
  444. public virtual Matrix getMatrix(int[] r, int j0, int j1)
  445. {
  446. Matrix X = new Matrix(r.Length, j1 - j0 + 1);
  447. double[][] B = X.Array;
  448. try
  449. {
  450. for (int i = 0; i < r.Length; i++)
  451. {
  452. for (int j = j0; j <= j1; j++)
  453. {
  454. B[i][j - j0] = A[r[i]][j];
  455. }
  456. }
  457. }
  458. catch (System.IndexOutOfRangeException)
  459. {
  460. throw new System.IndexOutOfRangeException("Submatrix indices");
  461. }
  462. return X;
  463. }
  464. /// <summary>Set a single element.</summary>
  465. /// <param name="i"> Row index.
  466. /// </param>
  467. /// <param name="j"> Column index.
  468. /// </param>
  469. /// <param name="s"> A(i,j).
  470. /// </param>
  471. /// <exception cref="ArrayIndexOutOfBoundsException">
  472. /// </exception>
  473. public virtual void set_Renamed(int i, int j, double s)
  474. {
  475. A[i][j] = s;
  476. }
  477. /// <summary>Set a submatrix.</summary>
  478. /// <param name="i0"> Initial row index
  479. /// </param>
  480. /// <param name="i1"> Final row index
  481. /// </param>
  482. /// <param name="j0"> Initial column index
  483. /// </param>
  484. /// <param name="j1"> Final column index
  485. /// </param>
  486. /// <param name="X"> A(i0:i1,j0:j1)
  487. /// </param>
  488. /// <exception cref="ArrayIndexOutOfBoundsException">Submatrix indices
  489. /// </exception>
  490. public virtual void setMatrix(int i0, int i1, int j0, int j1, Matrix X)
  491. {
  492. try
  493. {
  494. for (int i = i0; i <= i1; i++)
  495. {
  496. for (int j = j0; j <= j1; j++)
  497. {
  498. A[i][j] = X.get_Renamed(i - i0, j - j0);
  499. }
  500. }
  501. }
  502. catch (System.IndexOutOfRangeException)
  503. {
  504. throw new System.IndexOutOfRangeException("Submatrix indices");
  505. }
  506. }
  507. /// <summary>Set a submatrix.</summary>
  508. /// <param name="r"> Array of row indices.
  509. /// </param>
  510. /// <param name="c"> Array of column indices.
  511. /// </param>
  512. /// <param name="X"> A(r(:),c(:))
  513. /// </param>
  514. /// <exception cref="ArrayIndexOutOfBoundsException">Submatrix indices
  515. /// </exception>
  516. public virtual void setMatrix(int[] r, int[] c, Matrix X)
  517. {
  518. try
  519. {
  520. for (int i = 0; i < r.Length; i++)
  521. {
  522. for (int j = 0; j < c.Length; j++)
  523. {
  524. A[r[i]][c[j]] = X.get_Renamed(i, j);
  525. }
  526. }
  527. }
  528. catch (System.IndexOutOfRangeException)
  529. {
  530. throw new System.IndexOutOfRangeException("Submatrix indices");
  531. }
  532. }
  533. /// <summary>Set a submatrix.</summary>
  534. /// <param name="r"> Array of row indices.
  535. /// </param>
  536. /// <param name="j0"> Initial column index
  537. /// </param>
  538. /// <param name="j1"> Final column index
  539. /// </param>
  540. /// <param name="X"> A(r(:),j0:j1)
  541. /// </param>
  542. /// <exception cref="ArrayIndexOutOfBoundsException">Submatrix indices
  543. /// </exception>
  544. public virtual void setMatrix(int[] r, int j0, int j1, Matrix X)
  545. {
  546. try
  547. {
  548. for (int i = 0; i < r.Length; i++)
  549. {
  550. for (int j = j0; j <= j1; j++)
  551. {
  552. A[r[i]][j] = X.get_Renamed(i, j - j0);
  553. }
  554. }
  555. }
  556. catch (System.IndexOutOfRangeException)
  557. {
  558. throw new System.IndexOutOfRangeException("Submatrix indices");
  559. }
  560. }
  561. /// <summary>Set a submatrix.</summary>
  562. /// <param name="i0"> Initial row index
  563. /// </param>
  564. /// <param name="i1"> Final row index
  565. /// </param>
  566. /// <param name="c"> Array of column indices.
  567. /// </param>
  568. /// <param name="X"> A(i0:i1,c(:))
  569. /// </param>
  570. /// <exception cref="ArrayIndexOutOfBoundsException">Submatrix indices
  571. /// </exception>
  572. public virtual void setMatrix(int i0, int i1, int[] c, Matrix X)
  573. {
  574. try
  575. {
  576. for (int i = i0; i <= i1; i++)
  577. {
  578. for (int j = 0; j < c.Length; j++)
  579. {
  580. A[i][c[j]] = X.get_Renamed(i - i0, j);
  581. }
  582. }
  583. }
  584. catch (System.IndexOutOfRangeException)
  585. {
  586. throw new System.IndexOutOfRangeException("Submatrix indices");
  587. }
  588. }
  589. /// <summary>Matrix transpose.</summary>
  590. /// <returns> A'
  591. /// </returns>
  592. public virtual Matrix transpose()
  593. {
  594. Matrix X = new Matrix(n, m);
  595. double[][] C = X.Array;
  596. for (int i = 0; i < m; i++)
  597. {
  598. for (int j = 0; j < n; j++)
  599. {
  600. C[j][i] = A[i][j];
  601. }
  602. }
  603. return X;
  604. }
  605. /// <summary>One norm</summary>
  606. /// <returns> maximum column sum.
  607. /// </returns>
  608. public virtual double norm1()
  609. {
  610. double f = 0;
  611. for (int j = 0; j < n; j++)
  612. {
  613. double s = 0;
  614. for (int i = 0; i < m; i++)
  615. {
  616. s += System.Math.Abs(A[i][j]);
  617. }
  618. f = System.Math.Max(f, s);
  619. }
  620. return f;
  621. }
  622. /// <summary>Two norm</summary>
  623. /// <returns> maximum singular value.
  624. /// </returns>
  625. public virtual double norm2()
  626. {
  627. return (new SingularValueDecomposition(this).norm2());
  628. }
  629. /// <summary>Infinity norm</summary>
  630. /// <returns> maximum row sum.
  631. /// </returns>
  632. public virtual double normInf()
  633. {
  634. double f = 0;
  635. for (int i = 0; i < m; i++)
  636. {
  637. double s = 0;
  638. for (int j = 0; j < n; j++)
  639. {
  640. s += System.Math.Abs(A[i][j]);
  641. }
  642. f = System.Math.Max(f, s);
  643. }
  644. return f;
  645. }
  646. /// <summary>Frobenius norm</summary>
  647. /// <returns> sqrt of sum of squares of all elements.
  648. /// </returns>
  649. public virtual double normF()
  650. {
  651. double f = 0;
  652. for (int i = 0; i < m; i++)
  653. {
  654. for (int j = 0; j < n; j++)
  655. {
  656. f = Maths.hypot(f, A[i][j]);
  657. }
  658. }
  659. return f;
  660. }
  661. /// <summary>Unary minus</summary>
  662. /// <returns> -A
  663. /// </returns>
  664. public virtual Matrix uminus()
  665. {
  666. Matrix X = new Matrix(m, n);
  667. double[][] C = X.Array;
  668. for (int i = 0; i < m; i++)
  669. {
  670. for (int j = 0; j < n; j++)
  671. {
  672. C[i][j] = - A[i][j];
  673. }
  674. }
  675. return X;
  676. }
  677. /// <summary>C = A + B</summary>
  678. /// <param name="B"> another matrix
  679. /// </param>
  680. /// <returns> A + B
  681. /// </returns>
  682. public virtual Matrix plus(Matrix B)
  683. {
  684. checkMatrixDimensions(B);
  685. Matrix X = new Matrix(m, n);
  686. double[][] C = X.Array;
  687. for (int i = 0; i < m; i++)
  688. {
  689. for (int j = 0; j < n; j++)
  690. {
  691. C[i][j] = A[i][j] + B.A[i][j];
  692. }
  693. }
  694. return X;
  695. }
  696. /// <summary>A = A + B</summary>
  697. /// <param name="B"> another matrix
  698. /// </param>
  699. /// <returns> A + B
  700. /// </returns>
  701. public virtual Matrix plusEquals(Matrix B)
  702. {
  703. checkMatrixDimensions(B);
  704. for (int i = 0; i < m; i++)
  705. {
  706. for (int j = 0; j < n; j++)
  707. {
  708. A[i][j] = A[i][j] + B.A[i][j];
  709. }
  710. }
  711. return this;
  712. }
  713. /// <summary>C = A - B</summary>
  714. /// <param name="B"> another matrix
  715. /// </param>
  716. /// <returns> A - B
  717. /// </returns>
  718. public virtual Matrix minus(Matrix B)
  719. {
  720. checkMatrixDimensions(B);
  721. Matrix X = new Matrix(m, n);
  722. double[][] C = X.Array;
  723. for (int i = 0; i < m; i++)
  724. {
  725. for (int j = 0; j < n; j++)
  726. {
  727. C[i][j] = A[i][j] - B.A[i][j];
  728. }
  729. }
  730. return X;
  731. }
  732. /// <summary>A = A - B</summary>
  733. /// <param name="B"> another matrix
  734. /// </param>
  735. /// <returns> A - B
  736. /// </returns>
  737. public virtual Matrix minusEquals(Matrix B)
  738. {
  739. checkMatrixDimensions(B);
  740. for (int i = 0; i < m; i++)
  741. {
  742. for (int j = 0; j < n; j++)
  743. {
  744. A[i][j] = A[i][j] - B.A[i][j];
  745. }
  746. }
  747. return this;
  748. }
  749. /// <summary>Element-by-element multiplication, C = A.*B</summary>
  750. /// <param name="B"> another matrix
  751. /// </param>
  752. /// <returns> A.*B
  753. /// </returns>
  754. public virtual Matrix arrayTimes(Matrix B)
  755. {
  756. checkMatrixDimensions(B);
  757. Matrix X = new Matrix(m, n);
  758. double[][] C = X.Array;
  759. for (int i = 0; i < m; i++)
  760. {
  761. for (int j = 0; j < n; j++)
  762. {
  763. C[i][j] = A[i][j] * B.A[i][j];
  764. }
  765. }
  766. return X;
  767. }
  768. /// <summary>Element-by-element multiplication in place, A = A.*B</summary>
  769. /// <param name="B"> another matrix
  770. /// </param>
  771. /// <returns> A.*B
  772. /// </returns>
  773. public virtual Matrix arrayTimesEquals(Matrix B)
  774. {
  775. checkMatrixDimensions(B);
  776. for (int i = 0; i < m; i++)
  777. {
  778. for (int j = 0; j < n; j++)
  779. {
  780. A[i][j] = A[i][j] * B.A[i][j];
  781. }
  782. }
  783. return this;
  784. }
  785. /// <summary>Element-by-element right division, C = A./B</summary>
  786. /// <param name="B"> another matrix
  787. /// </param>
  788. /// <returns> A./B
  789. /// </returns>
  790. public virtual Matrix arrayRightDivide(Matrix B)
  791. {
  792. checkMatrixDimensions(B);
  793. Matrix X = new Matrix(m, n);
  794. double[][] C = X.Array;
  795. for (int i = 0; i < m; i++)
  796. {
  797. for (int j = 0; j < n; j++)
  798. {
  799. C[i][j] = A[i][j] / B.A[i][j];
  800. }
  801. }
  802. return X;
  803. }
  804. /// <summary>Element-by-element right division in place, A = A./B</summary>
  805. /// <param name="B"> another matrix
  806. /// </param>
  807. /// <returns> A./B
  808. /// </returns>
  809. public virtual Matrix arrayRightDivideEquals(Matrix B)
  810. {
  811. checkMatrixDimensions(B);
  812. for (int i = 0; i < m; i++)
  813. {
  814. for (int j = 0; j < n; j++)
  815. {
  816. A[i][j] = A[i][j] / B.A[i][j];
  817. }
  818. }
  819. return this;
  820. }
  821. /// <summary>Element-by-element left division, C = A.\B</summary>
  822. /// <param name="B"> another matrix
  823. /// </param>
  824. /// <returns> A.\B
  825. /// </returns>
  826. public virtual Matrix arrayLeftDivide(Matrix B)
  827. {
  828. checkMatrixDimensions(B);
  829. Matrix X = new Matrix(m, n);
  830. double[][] C = X.Array;
  831. for (int i = 0; i < m; i++)
  832. {
  833. for (int j = 0; j < n; j++)
  834. {
  835. C[i][j] = B.A[i][j] / A[i][j];
  836. }
  837. }
  838. return X;
  839. }
  840. /// <summary>Element-by-element left division in place, A = A.\B</summary>
  841. /// <param name="B"> another matrix
  842. /// </param>
  843. /// <returns> A.\B
  844. /// </returns>
  845. public virtual Matrix arrayLeftDivideEquals(Matrix B)
  846. {
  847. checkMatrixDimensions(B);
  848. for (int i = 0; i < m; i++)
  849. {
  850. for (int j = 0; j < n; j++)
  851. {
  852. A[i][j] = B.A[i][j] / A[i][j];
  853. }
  854. }
  855. return this;
  856. }
  857. /// <summary>Multiply a matrix by a scalar, C = s*A</summary>
  858. /// <param name="s"> scalar
  859. /// </param>
  860. /// <returns> s*A
  861. /// </returns>
  862. public virtual Matrix times(double s)
  863. {
  864. Matrix X = new Matrix(m, n);
  865. double[][] C = X.Array;
  866. for (int i = 0; i < m; i++)
  867. {
  868. for (int j = 0; j < n; j++)
  869. {
  870. C[i][j] = s * A[i][j];
  871. }
  872. }
  873. return X;
  874. }
  875. /// <summary>Multiply a matrix by a scalar in place, A = s*A</summary>
  876. /// <param name="s"> scalar
  877. /// </param>
  878. /// <returns> replace A by s*A
  879. /// </returns>
  880. public virtual Matrix timesEquals(double s)
  881. {
  882. for (int i = 0; i < m; i++)
  883. {
  884. for (int j = 0; j < n; j++)
  885. {
  886. A[i][j] = s * A[i][j];
  887. }
  888. }
  889. return this;
  890. }
  891. /// <summary>Linear algebraic matrix multiplication, A * B</summary>
  892. /// <param name="B"> another matrix
  893. /// </param>
  894. /// <returns> Matrix product, A * B
  895. /// </returns>
  896. /// <exception cref="IllegalArgumentException">Matrix inner dimensions must agree.
  897. /// </exception>
  898. public virtual Matrix times(Matrix B)
  899. {
  900. if (B.m != n)
  901. {
  902. throw new System.ArgumentException("Matrix inner dimensions must agree.");
  903. }
  904. Matrix X = new Matrix(m, B.n);
  905. double[][] C = X.Array;
  906. double[] Bcolj = new double[n];
  907. for (int j = 0; j < B.n; j++)
  908. {
  909. for (int k = 0; k < n; k++)
  910. {
  911. Bcolj[k] = B.A[k][j];
  912. }
  913. for (int i = 0; i < m; i++)
  914. {
  915. double[] Arowi = A[i];
  916. double s = 0;
  917. for (int k = 0; k < n; k++)
  918. {
  919. s += Arowi[k] * Bcolj[k];
  920. }
  921. C[i][j] = s;
  922. }
  923. }
  924. return X;
  925. }
  926. /// <summary>LU Decomposition</summary>
  927. /// <returns> LUDecomposition
  928. /// </returns>
  929. /// <seealso cref="LUDecomposition">
  930. /// </seealso>
  931. public virtual LUDecomposition lu()
  932. {
  933. return new LUDecomposition(this);
  934. }
  935. /// <summary>QR Decomposition</summary>
  936. /// <returns> QRDecomposition
  937. /// </returns>
  938. /// <seealso cref="QRDecomposition">
  939. /// </seealso>
  940. public virtual QRDecomposition qr()
  941. {
  942. return new QRDecomposition(this);
  943. }
  944. /// <summary>Cholesky Decomposition</summary>
  945. /// <returns> CholeskyDecomposition
  946. /// </returns>
  947. /// <seealso cref="CholeskyDecomposition">
  948. /// </seealso>
  949. public virtual CholeskyDecomposition chol()
  950. {
  951. return new CholeskyDecomposition(this);
  952. }
  953. /// <summary>Singular Value Decomposition</summary>
  954. /// <returns> SingularValueDecomposition
  955. /// </returns>
  956. /// <seealso cref="SingularValueDecomposition">
  957. /// </seealso>
  958. public virtual SingularValueDecomposition svd()
  959. {
  960. return new SingularValueDecomposition(this);
  961. }
  962. /// <summary>Eigenvalue Decomposition</summary>
  963. /// <returns> EigenvalueDecomposition
  964. /// </returns>
  965. /// <seealso cref="EigenvalueDecomposition">
  966. /// </seealso>
  967. public virtual EigenvalueDecomposition eig()
  968. {
  969. return new EigenvalueDecomposition(this);
  970. }
  971. /// <summary>Solve A*X = B</summary>
  972. /// <param name="B"> right hand side
  973. /// </param>
  974. /// <returns> solution if A is square, least squares solution otherwise
  975. /// </returns>
  976. public virtual Matrix solve(Matrix B)
  977. {
  978. return (m == n?(new LUDecomposition(this)).solve(B):(new QRDecomposition(this)).solve(B));
  979. }
  980. /// <summary>Solve X*A = B, which is also A'*X' = B'</summary>
  981. /// <param name="B"> right hand side
  982. /// </param>
  983. /// <returns> solution if A is square, least squares solution otherwise.
  984. /// </returns>
  985. public virtual Matrix solveTranspose(Matrix B)
  986. {
  987. return transpose().solve(B.transpose());
  988. }
  989. /// <summary>Matrix inverse or pseudoinverse</summary>
  990. /// <returns> inverse(A) if A is square, pseudoinverse otherwise.
  991. /// </returns>
  992. public virtual Matrix inverse()
  993. {
  994. return solve(identity(m, m));
  995. }
  996. /// <summary>Matrix determinant</summary>
  997. /// <returns> determinant
  998. /// </returns>
  999. public virtual double det()
  1000. {
  1001. return new LUDecomposition(this).det();
  1002. }
  1003. /// <summary>Matrix rank</summary>
  1004. /// <returns> effective numerical rank, obtained from SVD.
  1005. /// </returns>
  1006. public virtual int rank()
  1007. {
  1008. return new SingularValueDecomposition(this).rank();
  1009. }
  1010. /// <summary>Matrix condition (2 norm)</summary>
  1011. /// <returns> ratio of largest to smallest singular value.
  1012. /// </returns>
  1013. public virtual double cond()
  1014. {
  1015. return new SingularValueDecomposition(this).cond();
  1016. }
  1017. /// <summary>Matrix trace.</summary>
  1018. /// <returns> sum of the diagonal elements.
  1019. /// </returns>
  1020. public virtual double trace()
  1021. {
  1022. double t = 0;
  1023. for (int i = 0; i < System.Math.Min(m, n); i++)
  1024. {
  1025. t += A[i][i];
  1026. }
  1027. return t;
  1028. }
  1029. /// <summary>Generate matrix with random elements</summary>
  1030. /// <param name="m"> Number of rows.
  1031. /// </param>
  1032. /// <param name="n"> Number of colums.
  1033. /// </param>
  1034. /// <returns> An m-by-n matrix with uniformly distributed random elements.
  1035. /// </returns>
  1036. public static Matrix random(int m, int n)
  1037. {
  1038. Random random = new Random();
  1039. Matrix A = new Matrix(m, n);
  1040. double[][] X = A.Array;
  1041. for (int i = 0; i < m; i++)
  1042. {
  1043. for (int j = 0; j < n; j++)
  1044. {
  1045. X[i][j] = random.NextDouble();
  1046. }
  1047. }
  1048. return A;
  1049. }
  1050. /// <summary>Generate identity matrix</summary>
  1051. /// <param name="m"> Number of rows.
  1052. /// </param>
  1053. /// <param name="n"> Number of colums.
  1054. /// </param>
  1055. /// <returns> An m-by-n matrix with ones on the diagonal and zeros elsewhere.
  1056. /// </returns>
  1057. public static Matrix identity(int m, int n)
  1058. {
  1059. Matrix A = new Matrix(m, n);
  1060. double[][] X = A.Array;
  1061. for (int i = 0; i < m; i++)
  1062. {
  1063. for (int j = 0; j < n; j++)
  1064. {
  1065. X[i][j] = (i == j?1.0:0.0);
  1066. }
  1067. }
  1068. return A;
  1069. }
  1070. /// <summary>Print the matrix to the output stream. Line the elements up in
  1071. /// columns with a Fortran-like 'Fw.d' style format.
  1072. /// </summary>
  1073. /// <param name="output">Output stream.
  1074. /// </param>
  1075. /// <param name="w"> Column width.
  1076. /// </param>
  1077. /// <param name="d"> Number of digits after the decimal.
  1078. /// </param>
  1079. /// <summary>Read a matrix from a stream. The format is the same the print method,
  1080. /// so printed matrices can be read back in (provided they were printed using
  1081. /// US Locale). Elements are separated by
  1082. /// whitespace, all the elements for each row appear on a single line,
  1083. /// the last row is followed by a blank line.
  1084. /// </summary>
  1085. /// <param name="input">the input stream.
  1086. /// </param>
  1087. /* ------------------------
  1088. Private Methods
  1089. * ------------------------ */
  1090. /// <summary>Check if size(A) == size(B) *</summary>
  1091. private void checkMatrixDimensions(Matrix B)
  1092. {
  1093. if (B.m != m || B.n != n)
  1094. {
  1095. throw new System.ArgumentException("Matrix dimensions must agree.");
  1096. }
  1097. }
  1098. }
  1099. }