matrix.js 7.4 KB

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