matrix.js 7.1 KB

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