Subversion Repositories Applications.papyrus

Rev

Rev 1318 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
        Copyright (c) 2004-2006, The Dojo Foundation
        All Rights Reserved.

        Licensed under the Academic Free License version 2.1 or above OR the
        modified BSD license. For more information on Dojo licensing, see:

                http://dojotoolkit.org/community/licensing.shtml
*/



dojo.provide("dojo.math.matrix");
dojo.math.matrix.iDF = 0;
dojo.math.matrix.ALMOST_ZERO = 1e-10;
dojo.math.matrix.multiply = function (a, b) {
        var ay = a.length;
        var ax = a[0].length;
        var by = b.length;
        var bx = b[0].length;
        if (ax != by) {
                dojo.debug("Can't multiply matricies of sizes " + ax + "," + ay + " and " + bx + "," + by);
                return [[0]];
        }
        var c = [];
        for (var k = 0; k < ay; k++) {
                c[k] = [];
                for (var i = 0; i < bx; i++) {
                        c[k][i] = 0;
                        for (var m = 0; m < ax; m++) {
                                c[k][i] += a[k][m] * b[m][i];
                        }
                }
        }
        return c;
};
dojo.math.matrix.product = function () {
        if (arguments.length == 0) {
                dojo.debug("can't multiply 0 matrices!");
                return 1;
        }
        var result = arguments[0];
        for (var i = 1; i < arguments.length; i++) {
                result = dojo.math.matrix.multiply(result, arguments[i]);
        }
        return result;
};
dojo.math.matrix.sum = function () {
        if (arguments.length == 0) {
                dojo.debug("can't sum 0 matrices!");
                return 0;
        }
        var result = dojo.math.matrix.copy(arguments[0]);
        var rows = result.length;
        if (rows == 0) {
                dojo.debug("can't deal with matrices of 0 rows!");
                return 0;
        }
        var cols = result[0].length;
        if (cols == 0) {
                dojo.debug("can't deal with matrices of 0 cols!");
                return 0;
        }
        for (var i = 1; i < arguments.length; ++i) {
                var arg = arguments[i];
                if (arg.length != rows || arg[0].length != cols) {
                        dojo.debug("can't add matrices of different dimensions: first dimensions were " + rows + "x" + cols + ", current dimensions are " + arg.length + "x" + arg[0].length);
                        return 0;
                }
                for (var r = 0; r < rows; r++) {
                        for (var c = 0; c < cols; c++) {
                                result[r][c] += arg[r][c];
                        }
                }
        }
        return result;
};
dojo.math.matrix.inverse = function (a) {
        if (a.length == 1 && a[0].length == 1) {
                return [[1 / a[0][0]]];
        }
        var tms = a.length;
        var m = dojo.math.matrix.create(tms, tms);
        var mm = dojo.math.matrix.adjoint(a);
        var det = dojo.math.matrix.determinant(a);
        var dd = 0;
        if (det == 0) {
                dojo.debug("Determinant Equals 0, Not Invertible.");
                return [[0]];
        } else {
                dd = 1 / det;
        }
        for (var i = 0; i < tms; i++) {
                for (var j = 0; j < tms; j++) {
                        m[i][j] = dd * mm[i][j];
                }
        }
        return m;
};
dojo.math.matrix.determinant = function (a) {
        if (a.length != a[0].length) {
                dojo.debug("Can't calculate the determiant of a non-squre matrix!");
                return 0;
        }
        var tms = a.length;
        var det = 1;
        var b = dojo.math.matrix.upperTriangle(a);
        for (var i = 0; i < tms; i++) {
                var bii = b[i][i];
                if (Math.abs(bii) < dojo.math.matrix.ALMOST_ZERO) {
                        return 0;
                }
                det *= bii;
        }
        det = det * dojo.math.matrix.iDF;
        return det;
};
dojo.math.matrix.upperTriangle = function (m) {
        m = dojo.math.matrix.copy(m);
        var f1 = 0;
        var temp = 0;
        var tms = m.length;
        var v = 1;
        dojo.math.matrix.iDF = 1;
        for (var col = 0; col < tms - 1; col++) {
                if (typeof m[col][col] != "number") {
                        dojo.debug("non-numeric entry found in a numeric matrix: m[" + col + "][" + col + "]=" + m[col][col]);
                }
                v = 1;
                var stop_loop = 0;
                while ((m[col][col] == 0) && !stop_loop) {
                        if (col + v >= tms) {
                                dojo.math.matrix.iDF = 0;
                                stop_loop = 1;
                        } else {
                                for (var r = 0; r < tms; r++) {
                                        temp = m[col][r];
                                        m[col][r] = m[col + v][r];
                                        m[col + v][r] = temp;
                                }
                                v++;
                                dojo.math.matrix.iDF *= -1;
                        }
                }
                for (var row = col + 1; row < tms; row++) {
                        if (typeof m[row][col] != "number") {
                                dojo.debug("non-numeric entry found in a numeric matrix: m[" + row + "][" + col + "]=" + m[row][col]);
                        }
                        if (typeof m[col][row] != "number") {
                                dojo.debug("non-numeric entry found in a numeric matrix: m[" + col + "][" + row + "]=" + m[col][row]);
                        }
                        if (m[col][col] != 0) {
                                var f1 = (-1) * m[row][col] / m[col][col];
                                for (var i = col; i < tms; i++) {
                                        m[row][i] = f1 * m[col][i] + m[row][i];
                                }
                        }
                }
        }
        return m;
};
dojo.math.matrix.create = function (a, b, value) {
        if (!value) {
                value = 0;
        }
        var m = [];
        for (var i = 0; i < b; i++) {
                m[i] = [];
                for (var j = 0; j < a; j++) {
                        m[i][j] = value;
                }
        }
        return m;
};
dojo.math.matrix.ones = function (a, b) {
        return dojo.math.matrix.create(a, b, 1);
};
dojo.math.matrix.zeros = function (a, b) {
        return dojo.math.matrix.create(a, b, 0);
};
dojo.math.matrix.identity = function (size, scale) {
        if (!scale) {
                scale = 1;
        }
        var m = [];
        for (var i = 0; i < size; i++) {
                m[i] = [];
                for (var j = 0; j < size; j++) {
                        m[i][j] = (i == j ? scale : 0);
                }
        }
        return m;
};
dojo.math.matrix.adjoint = function (a) {
        var tms = a.length;
        if (tms <= 1) {
                dojo.debug("Can't find the adjoint of a matrix with a dimension less than 2");
                return [[0]];
        }
        if (a.length != a[0].length) {
                dojo.debug("Can't find the adjoint of a non-square matrix");
                return [[0]];
        }
        var m = dojo.math.matrix.create(tms, tms);
        var ii = 0;
        var jj = 0;
        var ia = 0;
        var ja = 0;
        var det = 0;
        var ap = dojo.math.matrix.create(tms - 1, tms - 1);
        for (var i = 0; i < tms; i++) {
                for (var j = 0; j < tms; j++) {
                        ia = 0;
                        for (ii = 0; ii < tms; ii++) {
                                if (ii == i) {
                                        continue;
                                }
                                ja = 0;
                                for (jj = 0; jj < tms; jj++) {
                                        if (jj == j) {
                                                continue;
                                        }
                                        ap[ia][ja] = a[ii][jj];
                                        ja++;
                                }
                                ia++;
                        }
                        det = dojo.math.matrix.determinant(ap);
                        m[i][j] = Math.pow(-1, (i + j)) * det;
                }
        }
        m = dojo.math.matrix.transpose(m);
        return m;
};
dojo.math.matrix.transpose = function (a) {
        var m = dojo.math.matrix.create(a.length, a[0].length);
        for (var i = 0; i < a.length; i++) {
                for (var j = 0; j < a[i].length; j++) {
                        m[j][i] = a[i][j];
                }
        }
        return m;
};
dojo.math.matrix.format = function (a, decimal_points) {
        if (arguments.length <= 1) {
                decimal_points = 5;
        }
        function format_int(x, dp) {
                var fac = Math.pow(10, dp);
                var a = Math.round(x * fac) / fac;
                var b = a.toString();
                if (b.charAt(0) != "-") {
                        b = " " + b;
                }
                var has_dp = 0;
                for (var i = 1; i < b.length; i++) {
                        if (b.charAt(i) == ".") {
                                has_dp = 1;
                        }
                }
                if (!has_dp) {
                        b += ".";
                }
                while (b.length < dp + 3) {
                        b += "0";
                }
                return b;
        }
        var ya = a.length;
        var xa = ya > 0 ? a[0].length : 0;
        var buffer = "";
        for (var y = 0; y < ya; y++) {
                buffer += "| ";
                for (var x = 0; x < xa; x++) {
                        buffer += format_int(a[y][x], decimal_points) + " ";
                }
                buffer += "|\n";
        }
        return buffer;
};
dojo.math.matrix.copy = function (a) {
        var ya = a.length;
        var xa = a[0].length;
        var m = dojo.math.matrix.create(xa, ya);
        for (var y = 0; y < ya; y++) {
                for (var x = 0; x < xa; x++) {
                        m[y][x] = a[y][x];
                }
        }
        return m;
};
dojo.math.matrix.scale = function (k, a) {
        a = dojo.math.matrix.copy(a);
        var ya = a.length;
        var xa = a[0].length;
        for (var y = 0; y < ya; y++) {
                for (var x = 0; x < xa; x++) {
                        a[y][x] *= k;
                }
        }
        return a;
};