matrix.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. if (!dojo._hasResource["dojox.math.matrix"]) { // _hasResource checks added by
  2. // build. Do not use
  3. // _hasResource directly in your
  4. // code.
  5. dojo._hasResource["dojox.math.matrix"] = true;
  6. dojo.provide("dojox.math.matrix");
  7. dojo.mixin(dojox.math.matrix, {
  8. iDF : 0,
  9. ALMOST_ZERO : 1e-10,
  10. multiply : function(/* Array */a, /* Array */b) {
  11. // summary
  12. // Multiply matrix a by matrix b.
  13. var ay = a.length, ax = a[0].length, by = b.length, bx = b[0].length;
  14. if (ax != by) {
  15. console.warn("Can't multiply matricies of sizes " + ax + ","
  16. + ay + " and " + bx + "," + by);
  17. return [[0]];
  18. }
  19. var c = [];
  20. for (var k = 0; k < ay; k++) {
  21. c[k] = [];
  22. for (var i = 0; i < bx; i++) {
  23. c[k][i] = 0;
  24. for (var m = 0; m < ax; m++) {
  25. c[k][i] += a[k][m] * b[m][i];
  26. }
  27. }
  28. }
  29. return c; // Array
  30. },
  31. product : function(/* Array... */) {
  32. // summary
  33. // Return the product of N matrices
  34. if (arguments.length == 0) {
  35. console.warn("can't multiply 0 matrices!");
  36. return 1;
  37. }
  38. var m = arguments[0];
  39. for (var i = 1; i < arguments.length; i++) {
  40. m = this.multiply(m, arguments[i]);
  41. }
  42. return m; // Array
  43. },
  44. sum : function(/* Array... */) {
  45. // summary
  46. // Return the sum of N matrices
  47. if (arguments.length == 0) {
  48. console.warn("can't sum 0 matrices!");
  49. return 0; // Number
  50. }
  51. var m = this.copy(arguments[0]);
  52. var rows = m.length;
  53. if (rows == 0) {
  54. console.warn("can't deal with matrices of 0 rows!");
  55. return 0;
  56. }
  57. var cols = m[0].length;
  58. if (cols == 0) {
  59. console.warn("can't deal with matrices of 0 cols!");
  60. return 0;
  61. }
  62. for (var i = 1; i < arguments.length; ++i) {
  63. var arg = arguments[i];
  64. if (arg.length != rows || arg[0].length != cols) {
  65. console
  66. .warn("can't add matrices of different dimensions: first dimensions were "
  67. + rows
  68. + "x"
  69. + cols
  70. + ", current dimensions are "
  71. + arg.length
  72. + "x" + arg[0].length);
  73. return 0;
  74. }
  75. for (var r = 0; r < rows; r++) {
  76. for (var c = 0; c < cols; c++) {
  77. m[r][c] += arg[r][c];
  78. }
  79. }
  80. }
  81. return m; // Array
  82. },
  83. inverse : function(/* Array */a) {
  84. // summary
  85. // Return the inversion of the passed matrix
  86. if (a.length == 1 && a[0].length == 1) {
  87. return [[1 / a[0][0]]]; // Array
  88. }
  89. var tms = a.length, m = this.create(tms, tms), mm = this.adjoint(a), det = this
  90. .determinant(a), dd = 0;
  91. if (det == 0) {
  92. console.warn("Determinant Equals 0, Not Invertible.");
  93. return [[0]];
  94. } else {
  95. dd = 1 / det;
  96. }
  97. for (var i = 0; i < tms; i++) {
  98. for (var j = 0; j < tms; j++) {
  99. m[i][j] = dd * mm[i][j];
  100. }
  101. }
  102. return m; // Array
  103. },
  104. determinant : function(/* Array */a) {
  105. // summary
  106. // Calculate the determinant of the passed square matrix.
  107. if (a.length != a[0].length) {
  108. console
  109. .warn("Can't calculate the determinant of a non-squre matrix!");
  110. return 0;
  111. }
  112. var tms = a.length, det = 1, b = this.upperTriangle(a);
  113. for (var i = 0; i < tms; i++) {
  114. var bii = b[i][i];
  115. if (Math.abs(bii) < this.ALMOST_ZERO) {
  116. return 0; // Number
  117. }
  118. det *= bii;
  119. }
  120. det *= this.iDF;
  121. return det; // Number
  122. },
  123. upperTriangle : function(/* Array */m) {
  124. // Summary
  125. // Find the upper triangle of the passed matrix and return it.
  126. m = this.copy(m);
  127. var f1 = 0, temp = 0, tms = m.length, v = 1;
  128. this.iDF = 1;
  129. for (var col = 0; col < tms - 1; col++) {
  130. if (typeof m[col][col] != "number") {
  131. console
  132. .warn("non-numeric entry found in a numeric matrix: m["
  133. + col + "][" + col + "]=" + m[col][col]);
  134. }
  135. v = 1;
  136. var stop_loop = 0;
  137. while ((m[col][col] == 0) && !stop_loop) {
  138. if (col + v >= tms) {
  139. this.iDF = 0;
  140. stop_loop = 1;
  141. } else {
  142. for (var r = 0; r < tms; r++) {
  143. temp = m[col][r];
  144. m[col][r] = m[col + v][r];
  145. m[col + v][r] = temp;
  146. }
  147. v++;
  148. this.iDF *= -1;
  149. }
  150. }
  151. for (var row = col + 1; row < tms; row++) {
  152. if (typeof m[row][col] != "number") {
  153. console
  154. .warn("non-numeric entry found in a numeric matrix: m["
  155. + row + "][" + col + "]=" + m[row][col]);
  156. }
  157. if (typeof m[col][row] != "number") {
  158. console
  159. .warn("non-numeric entry found in a numeric matrix: m["
  160. + col + "][" + row + "]=" + m[col][row]);
  161. }
  162. if (m[col][col] != 0) {
  163. var f1 = (-1) * m[row][col] / m[col][col];
  164. for (var i = col; i < tms; i++) {
  165. m[row][i] = f1 * m[col][i] + m[row][i];
  166. }
  167. }
  168. }
  169. }
  170. return m; // Array
  171. },
  172. create : function(/* Number */a, /* Number */b, /* Number? */value) {
  173. // summary
  174. // Create a new matrix with rows a and cols b, and pre-populate with
  175. // value.
  176. value = value || 0;
  177. var m = [];
  178. for (var i = 0; i < b; i++) {
  179. m[i] = [];
  180. for (var j = 0; j < a; j++) {
  181. m[i][j] = value;
  182. }
  183. }
  184. return m; // Array
  185. },
  186. ones : function(/* Number */a, /* Number */b) {
  187. // summary
  188. // Create a matrix pre-populated with ones
  189. return this.create(a, b, 1); // Array
  190. },
  191. zeros : function(/* Number */a, /* Number */b) {
  192. // summary
  193. // Create a matrix pre-populated with zeros
  194. return this.create(a, b); // Array
  195. },
  196. identity : function(/* Number */size, /* Number? */scale) {
  197. // summary
  198. // Create an identity matrix based on the size and scale.
  199. scale = scale || 1;
  200. var m = [];
  201. for (var i = 0; i < size; i++) {
  202. m[i] = [];
  203. for (var j = 0; j < size; j++) {
  204. m[i][j] = (i == j ? scale : 0);
  205. }
  206. }
  207. return m; // Array
  208. },
  209. adjoint : function(/* Array */a) {
  210. // summary
  211. // Find the adjoint of the passed matrix
  212. var tms = a.length;
  213. if (tms <= 1) {
  214. console
  215. .warn("Can't find the adjoint of a matrix with a dimension less than 2");
  216. return [[0]];
  217. }
  218. if (a.length != a[0].length) {
  219. console.warn("Can't find the adjoint of a non-square matrix");
  220. return [[0]];
  221. }
  222. var m = this.create(tms, tms), ap = this.create(tms - 1, tms - 1);
  223. var ii = 0, jj = 0, ia = 0, ja = 0, det = 0;
  224. for (var i = 0; i < tms; i++) {
  225. for (var j = 0; j < tms; j++) {
  226. ia = 0;
  227. for (ii = 0; ii < tms; ii++) {
  228. if (ii == i) {
  229. continue;
  230. }
  231. ja = 0;
  232. for (jj = 0; jj < tms; jj++) {
  233. if (jj == j) {
  234. continue;
  235. }
  236. ap[ia][ja] = a[ii][jj];
  237. ja++;
  238. }
  239. ia++;
  240. }
  241. det = this.determinant(ap);
  242. m[i][j] = Math.pow(-1, (i + j)) * det;
  243. }
  244. }
  245. return this.transpose(m); // Array
  246. },
  247. transpose : function(/* Array */a) {
  248. // summary
  249. // Transpose the passed matrix (i.e. rows to columns)
  250. var m = this.create(a.length, a[0].length);
  251. for (var i = 0; i < a.length; i++) {
  252. for (var j = 0; j < a[i].length; j++) {
  253. m[j][i] = a[i][j];
  254. }
  255. }
  256. return m; // Array
  257. },
  258. format : function(/* Array */a, /* Number? */points) {
  259. // summary
  260. // Return a string representation of the matrix, rounded to points
  261. // (if needed)
  262. points = points || 5;
  263. function format_int(x, dp) {
  264. var fac = Math.pow(10, dp);
  265. var a = Math.round(x * fac) / fac;
  266. var b = a.toString();
  267. if (b.charAt(0) != "-") {
  268. b = " " + b;
  269. }
  270. if (b.indexOf(".") > -1) {
  271. b += ".";
  272. }
  273. while (b.length < dp + 3) {
  274. b += "0";
  275. }
  276. return b;
  277. }
  278. var ya = a.length;
  279. var xa = ya > 0 ? a[0].length : 0;
  280. var buffer = "";
  281. for (var y = 0; y < ya; y++) {
  282. buffer += "| ";
  283. for (var x = 0; x < xa; x++) {
  284. buffer += format_int(a[y][x], points) + " ";
  285. }
  286. buffer += "|\n";
  287. }
  288. return buffer; // string
  289. },
  290. copy : function(/* Array */a) {
  291. // summary
  292. // Create a copy of the passed matrix
  293. var ya = a.length, xa = a[0].length, m = this.create(xa, ya);
  294. for (var y = 0; y < ya; y++) {
  295. for (var x = 0; x < xa; x++) {
  296. m[y][x] = a[y][x];
  297. }
  298. }
  299. return m; // Array
  300. },
  301. scale : function(/* Array */a, /* Number */factor) {
  302. // summary
  303. // Create a copy of passed matrix and scale each member by factor.
  304. a = this.copy(a);
  305. var ya = a.length, xa = a[0].length;
  306. for (var y = 0; y < ya; y++) {
  307. for (var x = 0; x < xa; x++) {
  308. a[y][x] *= factor;
  309. }
  310. }
  311. return a;
  312. }
  313. });
  314. }