Home | History | Annotate | Download | only in gl-matrix
      1 /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
      2 
      3 Permission is hereby granted, free of charge, to any person obtaining a copy
      4 of this software and associated documentation files (the "Software"), to deal
      5 in the Software without restriction, including without limitation the rights
      6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      7 copies of the Software, and to permit persons to whom the Software is
      8 furnished to do so, subject to the following conditions:
      9 
     10 The above copyright notice and this permission notice shall be included in
     11 all copies or substantial portions of the Software.
     12 
     13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     19 THE SOFTWARE. */
     20 
     21 var glMatrix = require("./common.js");
     22 
     23 /**
     24  * @class 2x2 Matrix
     25  * @name mat2
     26  */
     27 var mat2 = {};
     28 
     29 /**
     30  * Creates a new identity mat2
     31  *
     32  * @returns {mat2} a new 2x2 matrix
     33  */
     34 mat2.create = function() {
     35     var out = new glMatrix.ARRAY_TYPE(4);
     36     out[0] = 1;
     37     out[1] = 0;
     38     out[2] = 0;
     39     out[3] = 1;
     40     return out;
     41 };
     42 
     43 /**
     44  * Creates a new mat2 initialized with values from an existing matrix
     45  *
     46  * @param {mat2} a matrix to clone
     47  * @returns {mat2} a new 2x2 matrix
     48  */
     49 mat2.clone = function(a) {
     50     var out = new glMatrix.ARRAY_TYPE(4);
     51     out[0] = a[0];
     52     out[1] = a[1];
     53     out[2] = a[2];
     54     out[3] = a[3];
     55     return out;
     56 };
     57 
     58 /**
     59  * Copy the values from one mat2 to another
     60  *
     61  * @param {mat2} out the receiving matrix
     62  * @param {mat2} a the source matrix
     63  * @returns {mat2} out
     64  */
     65 mat2.copy = function(out, a) {
     66     out[0] = a[0];
     67     out[1] = a[1];
     68     out[2] = a[2];
     69     out[3] = a[3];
     70     return out;
     71 };
     72 
     73 /**
     74  * Set a mat2 to the identity matrix
     75  *
     76  * @param {mat2} out the receiving matrix
     77  * @returns {mat2} out
     78  */
     79 mat2.identity = function(out) {
     80     out[0] = 1;
     81     out[1] = 0;
     82     out[2] = 0;
     83     out[3] = 1;
     84     return out;
     85 };
     86 
     87 /**
     88  * Transpose the values of a mat2
     89  *
     90  * @param {mat2} out the receiving matrix
     91  * @param {mat2} a the source matrix
     92  * @returns {mat2} out
     93  */
     94 mat2.transpose = function(out, a) {
     95     // If we are transposing ourselves we can skip a few steps but have to cache some values
     96     if (out === a) {
     97         var a1 = a[1];
     98         out[1] = a[2];
     99         out[2] = a1;
    100     } else {
    101         out[0] = a[0];
    102         out[1] = a[2];
    103         out[2] = a[1];
    104         out[3] = a[3];
    105     }
    106 
    107     return out;
    108 };
    109 
    110 /**
    111  * Inverts a mat2
    112  *
    113  * @param {mat2} out the receiving matrix
    114  * @param {mat2} a the source matrix
    115  * @returns {mat2} out
    116  */
    117 mat2.invert = function(out, a) {
    118     var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
    119 
    120         // Calculate the determinant
    121         det = a0 * a3 - a2 * a1;
    122 
    123     if (!det) {
    124         return null;
    125     }
    126     det = 1.0 / det;
    127 
    128     out[0] =  a3 * det;
    129     out[1] = -a1 * det;
    130     out[2] = -a2 * det;
    131     out[3] =  a0 * det;
    132 
    133     return out;
    134 };
    135 
    136 /**
    137  * Calculates the adjugate of a mat2
    138  *
    139  * @param {mat2} out the receiving matrix
    140  * @param {mat2} a the source matrix
    141  * @returns {mat2} out
    142  */
    143 mat2.adjoint = function(out, a) {
    144     // Caching this value is nessecary if out == a
    145     var a0 = a[0];
    146     out[0] =  a[3];
    147     out[1] = -a[1];
    148     out[2] = -a[2];
    149     out[3] =  a0;
    150 
    151     return out;
    152 };
    153 
    154 /**
    155  * Calculates the determinant of a mat2
    156  *
    157  * @param {mat2} a the source matrix
    158  * @returns {Number} determinant of a
    159  */
    160 mat2.determinant = function (a) {
    161     return a[0] * a[3] - a[2] * a[1];
    162 };
    163 
    164 /**
    165  * Multiplies two mat2's
    166  *
    167  * @param {mat2} out the receiving matrix
    168  * @param {mat2} a the first operand
    169  * @param {mat2} b the second operand
    170  * @returns {mat2} out
    171  */
    172 mat2.multiply = function (out, a, b) {
    173     var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
    174     var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
    175     out[0] = a0 * b0 + a2 * b1;
    176     out[1] = a1 * b0 + a3 * b1;
    177     out[2] = a0 * b2 + a2 * b3;
    178     out[3] = a1 * b2 + a3 * b3;
    179     return out;
    180 };
    181 
    182 /**
    183  * Alias for {@link mat2.multiply}
    184  * @function
    185  */
    186 mat2.mul = mat2.multiply;
    187 
    188 /**
    189  * Rotates a mat2 by the given angle
    190  *
    191  * @param {mat2} out the receiving matrix
    192  * @param {mat2} a the matrix to rotate
    193  * @param {Number} rad the angle to rotate the matrix by
    194  * @returns {mat2} out
    195  */
    196 mat2.rotate = function (out, a, rad) {
    197     var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
    198         s = Math.sin(rad),
    199         c = Math.cos(rad);
    200     out[0] = a0 *  c + a2 * s;
    201     out[1] = a1 *  c + a3 * s;
    202     out[2] = a0 * -s + a2 * c;
    203     out[3] = a1 * -s + a3 * c;
    204     return out;
    205 };
    206 
    207 /**
    208  * Scales the mat2 by the dimensions in the given vec2
    209  *
    210  * @param {mat2} out the receiving matrix
    211  * @param {mat2} a the matrix to rotate
    212  * @param {vec2} v the vec2 to scale the matrix by
    213  * @returns {mat2} out
    214  **/
    215 mat2.scale = function(out, a, v) {
    216     var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
    217         v0 = v[0], v1 = v[1];
    218     out[0] = a0 * v0;
    219     out[1] = a1 * v0;
    220     out[2] = a2 * v1;
    221     out[3] = a3 * v1;
    222     return out;
    223 };
    224 
    225 /**
    226  * Creates a matrix from a given angle
    227  * This is equivalent to (but much faster than):
    228  *
    229  *     mat2.identity(dest);
    230  *     mat2.rotate(dest, dest, rad);
    231  *
    232  * @param {mat2} out mat2 receiving operation result
    233  * @param {Number} rad the angle to rotate the matrix by
    234  * @returns {mat2} out
    235  */
    236 mat2.fromRotation = function(out, rad) {
    237     var s = Math.sin(rad),
    238         c = Math.cos(rad);
    239     out[0] = c;
    240     out[1] = s;
    241     out[2] = -s;
    242     out[3] = c;
    243     return out;
    244 }
    245 
    246 /**
    247  * Creates a matrix from a vector scaling
    248  * This is equivalent to (but much faster than):
    249  *
    250  *     mat2.identity(dest);
    251  *     mat2.scale(dest, dest, vec);
    252  *
    253  * @param {mat2} out mat2 receiving operation result
    254  * @param {vec2} v Scaling vector
    255  * @returns {mat2} out
    256  */
    257 mat2.fromScaling = function(out, v) {
    258     out[0] = v[0];
    259     out[1] = 0;
    260     out[2] = 0;
    261     out[3] = v[1];
    262     return out;
    263 }
    264 
    265 /**
    266  * Returns a string representation of a mat2
    267  *
    268  * @param {mat2} mat matrix to represent as a string
    269  * @returns {String} string representation of the matrix
    270  */
    271 mat2.str = function (a) {
    272     return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
    273 };
    274 
    275 /**
    276  * Returns Frobenius norm of a mat2
    277  *
    278  * @param {mat2} a the matrix to calculate Frobenius norm of
    279  * @returns {Number} Frobenius norm
    280  */
    281 mat2.frob = function (a) {
    282     return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2)))
    283 };
    284 
    285 /**
    286  * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix
    287  * @param {mat2} L the lower triangular matrix
    288  * @param {mat2} D the diagonal matrix
    289  * @param {mat2} U the upper triangular matrix
    290  * @param {mat2} a the input matrix to factorize
    291  */
    292 
    293 mat2.LDU = function (L, D, U, a) {
    294     L[2] = a[2]/a[0];
    295     U[0] = a[0];
    296     U[1] = a[1];
    297     U[3] = a[3] - L[2] * U[1];
    298     return [L, D, U];
    299 };
    300 
    301 
    302 module.exports = mat2;
    303