Repository: josdejong/mathjs
Pull request #311 (2015-04-01 15:08:37)

Matrix updates, v2


Patch:
diff --git a/lib/function/arithmetic/abs.js b/lib/function/arithmetic/abs.js
index 1888904d6..36d91918f 100644
--- a/lib/function/arithmetic/abs.js
+++ b/lib/function/arithmetic/abs.js
@@ -35,8 +35,8 @@ function factory (type, config, load, typed) {
       var re = Math.abs(x.re);
       var im = Math.abs(x.im);
       if (re >= im) {
-        var x = im / re;
-        return re * Math.sqrt(1 + x * x);
+        var i = im / re;
+        return re * Math.sqrt(1 + i * i);
       }
       var y = re / im;
       return im * Math.sqrt(1 + y * y);
diff --git a/lib/function/arithmetic/cube.js b/lib/function/arithmetic/cube.js
index e7c2a52e6..2ecb84ed0 100644
--- a/lib/function/arithmetic/cube.js
+++ b/lib/function/arithmetic/cube.js
@@ -42,7 +42,8 @@ function factory (type, config, load, typed) {
     },
 
     'Array | Matrix': function (x) {
-      return collection.deepMap(x, cube);
+      // deep map collection, skip zeros since cube(0) = 0
+      return collection.deepMap(x, cube, true);
     }
   });
 
diff --git a/lib/function/arithmetic/norm.js b/lib/function/arithmetic/norm.js
index 30c7b7f47..ee4a45c3d 100644
--- a/lib/function/arithmetic/norm.js
+++ b/lib/function/arithmetic/norm.js
@@ -1,22 +1,16 @@
 'use strict';
 
-var size = require('../../../lib/util/array').size;
-
 function factory (type, config, load, typed) {
-  var collection = load(require('../../type/collection'));
+  
   var abs       = load(require('../arithmetic/abs'));
   var add       = load(require('../arithmetic/add'));
-  var multiply  = load(require('../arithmetic/multiply'));
   var pow       = load(require('../arithmetic/pow'));
   var sqrt      = load(require('../arithmetic/sqrt'));
   var equal     = load(require('../relational/equal'));
   var larger    = load(require('../relational/larger'));
   var smaller   = load(require('../relational/smaller'));
-  var max       = load(require('../statistics/max'));
-  var sum       = load(require('../statistics/sum'));
-  var diag      = load(require('../matrix/diag'));
-  var transpose = load(require('../matrix/transpose'));
-
+  var matrix    = load(require('../construction/matrix'));
+  
   var complexAbs = abs.signatures['Complex'];
 
   /**
@@ -63,19 +57,34 @@ function factory (type, config, load, typed) {
     'Complex': complexAbs,
 
     'BigNumber': function (x) {
+      // norm(x) = abs(x)
       return x.abs();
     },
+    
+    'boolean | null' : function (x) {
+      // norm(x) = abs(x)
+      return Math.abs(x);
+    },
 
-    'Array | Matrix': function (x) {
-      return _norm(x.valueOf(), 2);
+    'Array': function (x) {
+      return _norm(matrix(x), 2);
+    },
+    
+    'Matrix': function (x) {
+      return _norm(x, 2);
     },
 
-    'number | Complex | BigNumber, number | BigNumber | string': function (x, p) {
+    'number | Complex | BigNumber | boolean | null, number | BigNumber | string': function (x) {
+      // ignore second parameter, TODO: remove the option of second parameter for these types
       return norm(x);
     },
 
-    'Array | Matrix, number | BigNumber | string': function (x, p) {
-      return _norm(x.valueOf(), p.valueOf());
+    'Array, number | BigNumber | string': function (x, p) {
+      return _norm(matrix(x), p);
+    },
+    
+    'Matrix, number | BigNumber | string': function (x, p) {
+      return _norm(x, p);
     }
   });
 
@@ -88,97 +97,105 @@ function factory (type, config, load, typed) {
    */
   function _norm (x, p) {
     // size
-    var sizeX = size(x);
-
+    var sizeX = x.size();
+    
     // check if it is a vector
     if (sizeX.length == 1) {
       // check p
       if (p === Number.POSITIVE_INFINITY || p === 'inf') {
         // norm(x, Infinity) = max(abs(x))
-        var n;
-        for (var i = 0; i < x.length; i++) {
-          var v = abs(x[i]);
-          if (!n || larger(v, n)) {
-            n = v;
-          }
-        }
-        return n;
+        var pinf = 0;
+        // skip zeros since abs(0) == 0
+        x.forEach(
+          function (value) {
+            var v = abs(value);
+            if (larger(v, pinf))
+              pinf = v;
+          },
+          true);
+        return pinf;
       }
-      else if (p === Number.NEGATIVE_INFINITY || p === '-inf') {
+      if (p === Number.NEGATIVE_INFINITY || p === '-inf') {
         // norm(x, -Infinity) = min(abs(x))
-        var n;
-        for (var i = 0; i < x.length; i++) {
-          var v = abs(x[i]);
-          if (!n || smaller(v, n)) {
-            n = v;
-          }
-        }
-        return n;
+        var ninf;
+        // skip zeros since abs(0) == 0
+        x.forEach(
+          function (value) {
+            var v = abs(value);
+            if (!ninf || smaller(v, ninf))
+              ninf = v;
+          },
+          true);
+        return ninf || 0;
       }
-      else if (p === 'fro') {
+      if (p === 'fro') {
         return _norm(x, 2);
       }
-      else if (typeof p === 'number' && !isNaN(p)) {
+      if (typeof p === 'number' && !isNaN(p)) {
         // check p != 0
         if (!equal(p, 0)) {
           // norm(x, p) = sum(abs(xi) ^ p) ^ 1/p
           var n = 0;
-          for (var i = 0; i < x.length; i++) {
-            n = add(pow(abs(x[i]), p), n);
-          }
+          // skip zeros since abs(0) == 0
+          x.forEach(
+            function (value) {
+              n = add(pow(abs(value), p), n);
+            },
+            true);
           return pow(n, 1 / p);
         }
         return Number.POSITIVE_INFINITY;
       }
-      else {
-        // invalid parameter value
-        throw new Error('Unsupported parameter value');
-      }
+      // invalid parameter value
+      throw new Error('Unsupported parameter value');
     }
-    else if (sizeX.length == 2) {
+    // MxN matrix
+    if (sizeX.length == 2) {
       // check p
       if (p === 1) {
         // norm(x) = the largest column sum
         var c = [];
-        // loop rows
-        for (var i = 0; i < x.length; i++) {
-          var r = x[i];
-          // loop columns
-          for (var j = 0; j < r.length; j++) {
-            c[j] = add(c[j] || 0, abs(r[j]));
-          }
-        }
-        return max(c); // TODO: improve performance by immediately calculating the max in the for loops
+        // result
+        var maxc = 0;
+        // skip zeros since abs(0) == 0
+        x.forEach(
+          function (value, index) {
+            var j = index[1];
+            var cj = add(c[j] || 0, abs(value));
+            if (larger(cj, maxc))
+              maxc = cj;
+            c[j] = cj;
+          },
+          true);
+        return maxc;
       }
-      else if (p === Number.POSITIVE_INFINITY || p === 'inf') {
+      if (p === Number.POSITIVE_INFINITY || p === 'inf') {
         // norm(x) = the largest row sum
-        var n = 0;
-        // loop rows
-        for (var i = 0; i < x.length; i++) {
-          var rs = 0;
-          var r = x[i];
-          // loop columns
-          for (var j = 0; j < r.length; j++) {
-            rs = add(rs, abs(r[j]));
-          }
-          if (larger(rs, n)) {
-            n = rs;
-          }
-        }
-        return n;
+        var r = [];
+        // result
+        var maxr = 0;
+        // skip zeros since abs(0) == 0
+        x.forEach(
+          function (value, index) {
+            var i = index[0];
+            var ri = add(r[i] || 0, abs(value));
+            if (larger(ri, maxr))
+              maxr = ri;
+            r[i] = ri;
+          },
+          true);
+        return maxr;
       }
-      else if (p === 'fro') {
+      if (p === 'fro') {
         // norm(x) = sqrt(sum(diag(x'x)))
-        return sqrt(sum(diag(multiply(transpose(x), x))));
+        return sqrt(x.transpose().multiply(x).trace());
       }
-      else if (p === 2) {
+      if (p === 2) {
         // not implemented
         throw new Error('Unsupported parameter value, missing implementation of matrix singular value decomposition');
       }
-      else {
-        // invalid parameter value
-        throw new Error('Unsupported parameter value');
-      }
+      // invalid parameter value
+      throw new Error('Unsupported parameter value');
     }
   }
 
diff --git a/lib/function/arithmetic/round.js b/lib/function/arithmetic/round.js
index ef4c34972..2801fa1b3 100644
--- a/lib/function/arithmetic/round.js
+++ b/lib/function/arithmetic/round.js
@@ -79,7 +79,8 @@ function factory (type, config, load, typed) {
     },
 
     'Array | Matrix': function (x) {
-      return collection.deepMap(x, round);
+      // deep map collection, skip zeros since round(0) = 0
+      return collection.deepMap(x, round, true);
     },
 
     'Array | Matrix, number | BigNumber': function (x, n) {
diff --git a/lib/function/arithmetic/sign.js b/lib/function/arithmetic/sign.js
index b1c09b84a..2cb512406 100644
--- a/lib/function/arithmetic/sign.js
+++ b/lib/function/arithmetic/sign.js
@@ -48,7 +48,8 @@ function factory (type, config, load, typed) {
     },
 
     'Array | Matrix': function (x) {
-      return collection.deepMap(x, sign);
+      // deep map collection, skip zeros since sign(0) = 0
+      return collection.deepMap(x, sign, true);
     }
   });
 
diff --git a/lib/function/matrix/diag.js b/lib/function/matrix/diag.js
index bf4657b59..3bcd0e357 100644
--- a/lib/function/matrix/diag.js
+++ b/lib/function/matrix/diag.js
@@ -2,10 +2,10 @@
 
 var array     = require('../../util/array');
 var clone     = require('../../util/object').clone;
-var isNumber  = require('../../util/number').isNumber;
 var isInteger = require('../../util/number').isInteger;
 
 function factory (type, config, load, typed) {
+
   var matrix = load(require('../construction/matrix'));
   
   /**
@@ -49,88 +49,116 @@ function factory (type, config, load, typed) {
     // FIXME: simplify this huge amount of signatures as soon as typed-function supports optional arguments
 
     'Array': function (x) {
-      return _diag(x, 0, array.size(x));
+      return _diag(x, 0, array.size(x), null);
     },
+
     'Array, number': function (x, k) {
-      return _diag(x, k, array.size(x));
+      return _diag(x, k, array.size(x), null);
     },
+    
     'Array, BigNumber': function (x, k) {
-      return _diag(x, k.toNumber(), array.size(x));
+      return _diag(x, k.toNumber(), array.size(x), null);
     },
+
     'Array, string': function (x, format) {
       return _diag(x, 0, array.size(x), format);
     },
+
     'Array, number, string': function (x, k, format) {
       return _diag(x, k, array.size(x), format);
     },
+
     'Array, BigNumber, string': function (x, k, format) {
       return _diag(x, k.toNumber(), array.size(x), format);
     },
 
     'Matrix': function (x) {
-      return _diag(x.toArray(), 0, x.size(), x.storage());
+      return _diag(x, 0, x.size(), x.storage());
     },
+
     'Matrix, number': function (x, k) {
-      return _diag(x.toArray(), k, x.size(), x.format());
+      return _diag(x, k, x.size(), x.storage());
     },
+
     'Matrix, BigNumber': function (x, k) {
-      return _diag(x.toArray(), k.toNumber(), x.size(), x.storage());
+      return _diag(x, k.toNumber(), x.size(), x.storage());
     },
+
     'Matrix, string': function (x, format) {
-      return _diag(x.toArray(), 0, x.size(), format);
+      return _diag(x, 0, x.size(), format);
     },
+
     'Matrix, number, string': function (x, k, format) {
-      return _diag(x.toArray(), k, x.size(), format);
+      return _diag(x, k, x.size(), format);
     },
+
     'Matrix, BigNumber, string': function (x, k, format) {
-      return _diag(x.toArray(), k.toNumber(), x.size(), format);
+      return _diag(x, k.toNumber(), x.size(), format);
     }
   });
 
   /**
    * Creeate diagonal matrix from a vector or vice versa
-   * @param {Array} x
+   * @param {Array | Matrix} x
    * @param {number} k
-   * @param {Array} size
-   * @param {string} [format] Storage format for matrix. If undefined,
+   * @param {string} format Storage format for matrix. If null,
    *                          an Array is returned
    * @returns {Array | Matrix}
    * @private
    */
   function _diag (x, k, size, format) {
-    var vector, i, iMax;
-
-    if (!isNumber(k) || !isInteger(k)) {
+    if (!isInteger(k)) {
       throw new TypeError ('Second parameter in function diag must be an integer');
     }
-
+    
     var kSuper = k > 0 ? k : 0;
     var kSub = k < 0 ? -k : 0;
-    
-    // FIXME: reimplement optimization for sparse matrices
-    
+
+    // check dimensions
     switch (size.length) {
       case 1:
-        // x is a vector. create diagonal matrix
-        var defaultValue = (x[0] instanceof type.BigNumber) ? new type.BigNumber(0) : 0;
-        var mat = array.resize([], [x.length + kSub, x.length + kSuper], defaultValue);
-        for (i = 0; i < x.length; i++) {
-          mat[i + kSub][i + kSuper] = clone(x[i]);
-        }
-        return format ? matrix(mat, format) : mat;
-
+        return _createDiagonalMatrix(x, k, format, size[0], kSub, kSuper);
       case 2:
-        // x is a matrix get diagonal from matrix
-        vector = [];
-        iMax = Math.min(size[0] - kSub, size[1] - kSuper);
-        for (i = 0; i < iMax; i++) {
-          vector[i] = clone(x[i + kSub][i + kSuper]);
-        }
-        return format ? matrix(vector, format) : vector;
-
-      default:
-        throw new RangeError('Matrix for function diag must be 2 dimensional');
+        return _getDiagonal(x, k, format, size, kSub, kSuper);
+    }
+    throw new RangeError('Matrix for function diag must be 2 dimensional');
+  }
+  
+  function _createDiagonalMatrix(x, k, format, l, kSub, kSuper) {
+    // matrix size
+    var ms = [l + kSub, l + kSuper];
+    // get matrix constructor
+    var F = type.Matrix.storage(format || 'dense');
+    // create diagonal matrix
+    var m = F.diagonal(ms, x, k);
+    // check we need to return a matrix
+    return format !== null ? m : m.valueOf();
+  }
+  
+  function _getDiagonal(x, k, format, s, kSub, kSuper) {
+    // check x is a Matrix
+    if (x instanceof type.Matrix) {
+      // get diagonal matrix
+      var dm = x.diagonal(k);
+      // check we need to return a matrix
+      if (format !== null) {
+        // check we need to change matrix format
+        if (format !== dm.storage())
+          return matrix(dm, format);
+        return dm;
+      }
+      return dm.valueOf();
+    }
+    // vector size
+    var n = Math.min(s[0] - kSub, s[1] - kSuper);
+    // diagonal values
+    var vector = new Array(n);
+    // loop diagonal
+    for (var i = 0; i < n; i++) {
+      vector[i] = clone(x[i + kSub][i + kSuper]);
     }
+    // check we need to return a matrix
+    return format !== null ? matrix(vector) : vector;
   }
 }
 
diff --git a/lib/function/matrix/eye.js b/lib/function/matrix/eye.js
index eb90f2b94..b1cc17cf9 100644
--- a/lib/function/matrix/eye.js
+++ b/lib/function/matrix/eye.js
@@ -1,8 +1,10 @@
 'use strict';
 
+var array = require('../../util/array');
 var isInteger = require('../../util/number').isInteger;
 
 function factory (type, config, load, typed) {
+  
   var matrix = load(require('../construction/matrix'));
   
   /**
@@ -45,31 +47,43 @@ function factory (type, config, load, typed) {
     },
 
     'number | BigNumber': function (rows) {
-      var matrix = _eye(rows, rows);
-      return (config.matrix === 'matrix') ? matrix : matrix.valueOf();
+      return _eye(rows, rows, config.matrix === 'matrix' ? 'default' : undefined);
+    },
+    
+    'number | BigNumber, string': function (rows, format) {
+      return _eye(rows, rows, format);
     },
 
     'number | BigNumber, number | BigNumber': function (rows, cols) {
-      var matrix = _eye(rows, cols);
-      return (config.matrix === 'matrix') ? matrix : matrix.valueOf();
+      return _eye(rows, cols, config.matrix === 'matrix' ? 'default' : undefined);
+    },
+    
+    'number | BigNumber, number | BigNumber, string': function (rows, cols, format) {
+      return _eye(rows, cols, format);
     },
 
     'Array':  function (size) {
-      return _eyeVector(size).valueOf();
+      return _eyeVector(size);
+    },
+    
+    'Array, string':  function (size, format) {
+      return _eyeVector(size, format);
     },
 
     'Matrix': function (size) {
-      return _eyeVector(size.valueOf());
+      return _eyeVector(size.valueOf(), size.storage());
     },
-
-    // FIXME: re-implement support for format in eye
+    
+    'Matrix, string': function (size, format) {
+      return _eyeVector(size.valueOf(), format);
+    }
   });
 
-  function _eyeVector (size) {
+  function _eyeVector (size, format) {
     switch (size.length) {
-      case 0: return (config.matrix === 'matrix') ? new matrix([]) : [];
-      case 1: return _eye(size[0], size[0]);
-      case 2: return _eye(size[0], size[1]);
+      case 0: return format ? matrix(format) : [];
+      case 1: return _eye(size[0], size[0], format);
+      case 2: return _eye(size[0], size[1], format);
       default: throw new Error('Vector containing two values expected');
     }
   }
@@ -96,23 +110,28 @@ function factory (type, config, load, typed) {
     if (!isInteger(cols) || cols < 1) {
       throw new Error('Parameters in function eye must be positive integers');
     }
-
-    // FIXME: re-implement support for format in eye
-
-    // create the matrix
-    var m = matrix();
+    
     var one = Big ? new type.BigNumber(1) : 1;
     var defaultValue = Big ? new Big(0) : 0;
-    m.resize([rows, cols], defaultValue);
-
+    var size = [rows, cols];
+    
+    // check we need to return a matrix
+    if (format) {
+      // get matrix storage constructor
+      var F = type.Matrix.storage(format);
+      // create diagonal matrix (use optimized implementation for storage format)
+      return F.diagonal(size, one, 0, defaultValue);
+    }
+    
+    // create and resize array
+    var res = array.resize([], size, defaultValue);
     // fill in ones on the diagonal
-    var minimum = Math.min(rows, cols);
-    var data = m.valueOf();
+    var minimum = rows < cols ? rows : cols;
+    // fill diagonal
     for (var d = 0; d < minimum; d++) {
-      data[d][d] = one;
+      res[d][d] = one;
     }
-
-    return m;
+    return res;
   }
 }
 
diff --git a/lib/function/trigonometry/tan.js b/lib/function/trigonometry/tan.js
index 5a47cb9c9..3f397f305 100644
--- a/lib/function/trigonometry/tan.js
+++ b/lib/function/trigonometry/tan.js
@@ -55,7 +55,8 @@ function factory (type, config, load, typed) {
     },
 
     'Array | Matrix': function (x) {
-      return collection.deepMap(x, tan);
+      // deep map collection, skip zeros since tan(0) = 0
+      return collection.deepMap(x, tan, true);
     }
   });
 
diff --git a/lib/type/matrix/CcsMatrix.js b/lib/type/matrix/CcsMatrix.js
index 1c881cb50..543fde767 100644
--- a/lib/type/matrix/CcsMatrix.js
+++ b/lib/type/matrix/CcsMatrix.js
@@ -15,9 +15,9 @@ var isInteger = util.number.isInteger;
 var validateIndex = array.validateIndex;
 
 function factory (type, config, load, typed) {
-  var add = load(require('../../function/arithmetic/add'))
-  var multiply = load(require('../../function/arithmetic/multiply'))
-  var equal = load(require('../../function/relational/equal'))
+  var add = load(require('../../function/arithmetic/add'));
+  var multiply = load(require('../../function/arithmetic/multiply'));
+  var equal = load(require('../../function/relational/equal'));
 
   var Index = type.Index;
   var BigNumber = type.BigNumber;
@@ -833,7 +833,7 @@ function factory (type, config, load, typed) {
    *
    * @param {Number | BigNumber} [k=0]     The kth diagonal where the vector will retrieved.
    *
-   * @returns {Array}                      The array vector with the diagonal values.
+   * @returns {Matrix}                     The matrix vector with the diagonal values.
    */
   CcsMatrix.prototype.diagonal = function(k) {
     // validate k if any
@@ -861,40 +861,41 @@ function factory (type, config, load, typed) {
     // number diagonal values
     var n = Math.min(rows - kSub, columns -  kSuper);
     
-    // diagonal
+    // diagonal arrays
     var values = [];
+    var index = [];
+    var ptr = [];
+    // initial ptr value
+    ptr[0] = 0;
     // loop columns
     for (var j = kSuper; j < columns && values.length < n; j++) {
       // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
       var k0 = this._ptr[j];
       var k1 = this._ptr[j + 1];
-      // column value flag
-      var cv = false;
       // loop x within [k0, k1[
       for (var x = k0; x < k1; x++) {
         // row index
         var i = this._index[x];
         // check row
         if (i === j - kSuper + kSub) {
-          // set flag
-          cv = true;
           // value on this column
           values.push(object.clone(this._values[x]));
+          // store row
+          index[values.length - 1] = i - kSub;
           // exit loop
           break;
         }
-        else if (i > j - kSuper + kSub) {
-          // exit loop, no value on the diagonal for column j
-          break;
-        }
-      }
-      // check this column has a value set
-      if (!cv && values.length < n) {
-        // zero on this column
-        values.push(0);
       }
     }
-    return values;
+    // close ptr
+    ptr.push(values.length);
+    // return matrix
+    return new CcsMatrix({
+      values: values,
+      index: index,
+      ptr: ptr,
+      size: [n, 1]
+    });
   };
   
   /**
@@ -911,9 +912,9 @@ function factory (type, config, load, typed) {
   /**
    * Create a diagonal matrix.
    *
-   * @param {Array} size                   The matrix size.
-   * @param {Number, Array} value          The values for the diagonal.
-   * @param {Number | BigNumber} [k=0]     The kth diagonal where the vector will be filled in.
+   * @param {Array} size                       The matrix size.
+   * @param {Number | Array | Matrix } value   The values for the diagonal.
+   * @param {Number | BigNumber} [k=0]         The kth diagonal where the vector will be filled in.
    *
    * @returns {CcsMatrix}
    */
@@ -978,6 +979,20 @@ function factory (type, config, load, typed) {
         return value[i];
       };
     }
+    else if (value instanceof Matrix) {
+      // matrix size
+      var ms = value.size();
+      // validate matrix
+      if (ms.length !== 1 || ms[0] !== n) {
+        // number of values in array must be n
+        throw new Error('Invalid matrix length');
+      }
+      // define function
+      _value = function (i) {
+        // return value @ i
+        return value.get([i]);
+      };
+    }
     else {
       // define function
       _value = function () {
diff --git a/lib/type/matrix/CrsMatrix.js b/lib/type/matrix/CrsMatrix.js
index ce1697184..471959800 100644
--- a/lib/type/matrix/CrsMatrix.js
+++ b/lib/type/matrix/CrsMatrix.js
@@ -15,9 +15,9 @@ var isInteger = util.number.isInteger;
 var validateIndex = array.validateIndex;
 
 function factory (type, config, load, typed) {
-  var add = load(require('../../function/arithmetic/add'))
-  var multiply = load(require('../../function/arithmetic/multiply'))
-  var equal = load(require('../../function/relational/equal'))
+  var add = load(require('../../function/arithmetic/add'));
+  var multiply = load(require('../../function/arithmetic/multiply'));
+  var equal = load(require('../../function/relational/equal'));
 
   var Index = type.Index;
   var BigNumber = type.BigNumber;
@@ -855,40 +855,41 @@ function factory (type, config, load, typed) {
     // number diagonal values
     var n = Math.min(rows - kSub, columns -  kSuper);
 
-    // diagonal
+    // diagonal arrays
     var values = [];
+    var index = [];
+    var ptr = [];
     // loop rows
     for (var i = kSub; i < rows && values.length < n; i++) {
+      // number of rows with value
+      ptr.push(values.length);
       // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
       var k0 = this._ptr[i];
       var k1 = this._ptr[i + 1];
-      // row value flag
-      var rv = false;
       // loop x within [k0, k1[
       for (var x = k0; x < k1; x++) {
         // column index
         var j = this._index[x];
         // check column
         if (j === i + kSuper - kSub) {
-          // set flag
-          rv = true;
           // value on this column
           values.push(object.clone(this._values[x]));
+          // store column (always first column)
+          index[values.length - 1] = 0;
           // exit loop
           break;
         }
-        else if (j > i + kSuper - kSub) {
-          // exit loop, no value on the diagonal for row i
-          break;
-        }
-      }
-      // check this row has a value set
-      if (!rv && values.length < n) {
-        // zero on this column
-        values.push(0);
       }
     }
-    return values;
+    // last value should be number of values
+    ptr.push(values.length);
+    // return matrix
+    return new CrsMatrix({
+      values: values,
+      index: index,
+      ptr: ptr,
+      size: [n, 1]
+    });
   };
 
   /**
@@ -972,6 +973,20 @@ function factory (type, config, load, typed) {
         return value[i];
       };
     }
+    else if (value instanceof Matrix) {
+      // matrix size
+      var ms = value.size();
+      // validate matrix
+      if (ms.length !== 1 || ms[0] !== n) {
+        // number of values in array must be n
+        throw new Error('Invalid matrix length');
+      }
+      // define function
+      _value = function (i) {
+        // return value @ i
+        return value.get([i]);
+      };
+    }
     else {
       // define function
       _value = function () {
diff --git a/lib/type/matrix/DenseMatrix.js b/lib/type/matrix/DenseMatrix.js
index a03c03a43..9b2296ee2 100644
--- a/lib/type/matrix/DenseMatrix.js
+++ b/lib/type/matrix/DenseMatrix.js
@@ -14,8 +14,8 @@ var isInteger = util.number.isInteger;
 var validateIndex = array.validateIndex;
 
 function factory (type, config, load, typed) {
-  var add = load(require('../../function/arithmetic/add'))
-  var multiply = load(require('../../function/arithmetic/multiply'))
+  var add = load(require('../../function/arithmetic/add'));
+  var multiply = load(require('../../function/arithmetic/multiply'));
 
   var Index = type.Index;
   var BigNumber = type.BigNumber;
@@ -612,13 +612,18 @@ function factory (type, config, load, typed) {
     var n = Math.min(rows - kSub, columns -  kSuper);
     
     // x is a matrix get diagonal from matrix
-    var vector = [];
+    var data = [];
     
     // loop rows
     for (var i = 0; i < n; i++) {
-      vector[i] = object.clone(this._data[i + kSub][i + kSuper]);
+      data[i] = object.clone(this._data[i + kSub][i + kSuper]);
     }
-    return vector;
+
+    // create DenseMatrix
+    return new DenseMatrix({
+      data: data,
+      size: [n]
+    });
   };
   
   /**
@@ -690,6 +695,20 @@ function factory (type, config, load, typed) {
       _value = function (i) {
         // return value @ i
         return value[i];
+      };      
+    }
+    else if (value instanceof Matrix) {
+      // matrix size
+      var ms = value.size();
+      // validate matrix
+      if (ms.length !== 1 || ms[0] !== n) {
+        // number of values in array must be n
+        throw new Error('Invalid matrix length');
+      }
+      // define function
+      _value = function (i) {
+        // return value @ i
+        return value.get([i]);
       };
     }
     else {
@@ -699,6 +718,12 @@ function factory (type, config, load, typed) {
         return value;
       };
     }
+    
+    // discover default value if needed
+    if (!defaultValue) {
+      // check first value in array
+      defaultValue = (_value(0) instanceof type.BigNumber) ? new type.BigNumber(0) : 0;  
+    }
 
     // empty array
     var data = [];


Test patch:
diff --git a/test/function/arithmetic/norm.test.js b/test/function/arithmetic/norm.test.js
index d8925bc82..50cd26b61 100644
--- a/test/function/arithmetic/norm.test.js
+++ b/test/function/arithmetic/norm.test.js
@@ -1,6 +1,5 @@
 // test norm
 var assert = require('assert'),
-    error = require('../../../lib/error/index'),
     math = require('../../../index');
 
 describe('norm', function () {
@@ -75,14 +74,22 @@ describe('norm', function () {
     // p = 1
     assert.equal(math.norm([[1, 2], [3, 4]], 1), 6);
     assert.equal(math.norm(math.matrix([[1, 2], [3, 4]]), 1), 6);
+    assert.equal(math.norm(math.matrix([[1, 2], [3, 4]], 'ccs'), 1), 6);
+    assert.equal(math.norm(math.matrix([[1, 2], [3, 4]], 'crs'), 1), 6);
     // p = Infinity
     assert.equal(math.norm([[1, 2], [3, 4]], Number.POSITIVE_INFINITY), 7);
     assert.equal(math.norm(math.matrix([[1, 2], [3, 4]]), Number.POSITIVE_INFINITY), 7);
+    assert.equal(math.norm(math.matrix([[1, 2], [3, 4]], 'ccs'), Number.POSITIVE_INFINITY), 7);
+    assert.equal(math.norm(math.matrix([[1, 2], [3, 4]], 'crs'), Number.POSITIVE_INFINITY), 7);
     assert.equal(math.norm([[1, 2], [3, 4]], 'inf'), 7);
     assert.equal(math.norm(math.matrix([[1, 2], [3, 4]]), 'inf'), 7);
+    assert.equal(math.norm(math.matrix([[1, 2], [3, 4]], 'ccs'), 'inf'), 7);
+    assert.equal(math.norm(math.matrix([[1, 2], [3, 4]], 'crs'), 'inf'), 7);
     // p = 'fro'
     assert.equal(math.norm([[1, 2], [-3, -4]], 'fro'), math.sqrt(30));
     assert.equal(math.norm(math.matrix([[1, 2], [-3, -4]]), 'fro'), math.sqrt(30));
+    assert.equal(math.norm(math.matrix([[1, 2], [-3, -4]], 'ccs'), 'fro'), math.sqrt(30));
+    assert.equal(math.norm(math.matrix([[1, 2], [-3, -4]], 'crs'), 'fro'), math.sqrt(30));
     // p - not implemented yet!
     assert.throws(function() {
       math.norm(math.norm([[1, 2], [3, 4]], 2), 6);
@@ -90,8 +97,8 @@ describe('norm', function () {
   });
 
   it('should throw an error in case of invalid number of arguments', function() {
-    assert.throws(function () {math.norm()}, /TypeError: Too few arguments/);
-    assert.throws(function () {math.norm(1, 2, 3)}, /TypeError: Too many arguments/);
+    assert.throws(function () {math.norm();}, /TypeError: Too few arguments/);
+    assert.throws(function () {math.norm(1, 2, 3);}, /TypeError: Too many arguments/);
   });
 
   it('should throw an error with a string', function () {
diff --git a/test/function/matrix/diag.test.js b/test/function/matrix/diag.test.js
index 98b82784f..f1574c879 100644
--- a/test/function/matrix/diag.test.js
+++ b/test/function/matrix/diag.test.js
@@ -1,5 +1,4 @@
 var assert = require('assert'),
-    error = require('../../../lib/error/index'),
     math = require('../../../index'),
     bignumber = math.bignumber;
 
@@ -115,13 +114,13 @@ describe('diag', function() {
   });
 
   it('should throw an error in case of wrong number of arguments', function() {
-    assert.throws(function () {math.diag()}, /TypeError: Too few arguments/);
-    assert.throws(function () {math.diag([], 2, 3, 4)}, /TypeError: Too many arguments/);
+    assert.throws(function () {math.diag();}, /TypeError: Too few arguments/);
+    assert.throws(function () {math.diag([], 2, 3, 4);}, /TypeError: Too many arguments/);
   });
 
   it('should throw an error in case of invalid type of arguments', function() {
-    assert.throws(function () {math.diag(2)}, /TypeError: Unexpected type of argument/);
-    assert.throws(function () {math.diag([], new Date())}, /TypeError: Unexpected type of argument/);
+    assert.throws(function () {math.diag(2);}, /TypeError: Unexpected type of argument/);
+    assert.throws(function () {math.diag([], new Date());}, /TypeError: Unexpected type of argument/);
   });
 
 });
\ No newline at end of file
diff --git a/test/function/matrix/eye.test.js b/test/function/matrix/eye.test.js
index afbcb1d48..254983666 100644
--- a/test/function/matrix/eye.test.js
+++ b/test/function/matrix/eye.test.js
@@ -11,8 +11,7 @@ describe('eye', function() {
     assert.deepEqual(eye(matrix([])), matrix());
   });
 
-  // FIXME: create an empty matrix with ccs storage type
-  it.skip('should create an empty matrix with ccs storage type', function () {
+  it('should create an empty matrix with ccs storage type', function () {
     assert.deepEqual(eye('ccs'), matrix('ccs'));
     assert.deepEqual(eye(matrix([], 'ccs')), matrix('ccs'));
   });
@@ -28,8 +27,7 @@ describe('eye', function() {
     assert.deepEqual(eye(3,3), matrix([[1,0,0],[0,1,0],[0,0,1]]));
   });
 
-  // FIXME: create a matrix with ccs storage type
-  it.skip('should create an identity matrix with storage type css of the given size', function() {
+  it('should create an identity matrix with storage type css of the given size', function() {
     assert.deepEqual(eye(1, 'ccs'), matrix([[1]], 'ccs'));
     assert.deepEqual(eye(2, 'ccs'), matrix([[1,0],[0,1]], 'ccs'));
     assert.deepEqual(eye(2,3, 'ccs'), matrix([[1,0,0],[0,1,0]], 'ccs'));
diff --git a/test/type/matrix/CcsMatrix.test.js b/test/type/matrix/CcsMatrix.test.js
index df50ee6c7..1a25e2b8d 100644
--- a/test/type/matrix/CcsMatrix.test.js
+++ b/test/type/matrix/CcsMatrix.test.js
@@ -1327,6 +1327,60 @@ describe('CcsMatrix', function() {
         ]);
     });
     
+    it('should create CCS matrix (n x n), matrix vector value', function () {
+
+      var m = CcsMatrix.diagonal([3, 3], math.matrix([1, 2, 3]));
+
+      assert.deepEqual(m._size, [3, 3]);
+      assert.deepEqual(m._values, [1, 2, 3]);
+      assert.deepEqual(m._index, [0, 1, 2]);
+      assert.deepEqual(m._ptr, [0, 1, 2, 3]);
+
+      assert.deepEqual(
+        m.toArray(), 
+        [
+          [1, 0, 0],
+          [0, 2, 0],
+          [0, 0, 3]
+        ]);
+    });
+
+    it('should create CCS matrix (n x n), matrix vector value, k > 0', function () {
+
+      var m = CcsMatrix.diagonal([3, 3], math.matrix([1, 2]), 1);
+
+      assert.deepEqual(m._size, [3, 3]);
+      assert.deepEqual(m._values, [1, 2]);
+      assert.deepEqual(m._index, [0, 1]);
+      assert.deepEqual(m._ptr, [0, 0, 1, 2]);
+
+      assert.deepEqual(
+        m.toArray(), 
+        [
+          [0, 1, 0],
+          [0, 0, 2],
+          [0, 0, 0]
+        ]);
+    });
+
+    it('should create CCS matrix (n x n), matrix vector value, k < 0', function () {
+
+      var m = CcsMatrix.diagonal([3, 3], math.matrix([1, 2]), -1);
+
+      assert.deepEqual(m._size, [3, 3]);
+      assert.deepEqual(m._values, [1, 2]);
+      assert.deepEqual(m._index, [1, 2]);
+      assert.deepEqual(m._ptr, [0, 1, 2, 2]);
+
+      assert.deepEqual(
+        m.toArray(), 
+        [
+          [0, 0, 0],
+          [1, 0, 0],
+          [0, 2, 0]
+        ]);
+    });
+      
     it('should create CCS matrix (n x n), complex number', function () {
 
       var m = CcsMatrix.diagonal([3, 3], new Complex(1, 1));
@@ -1568,7 +1622,7 @@ describe('CcsMatrix', function() {
           [0, 0, 1]
         ]);
 
-      assert.deepEqual(m.diagonal(), [1, 1, 1]);
+      assert.deepEqual(m.diagonal(), new CcsMatrix([1, 1, 1]));
     });
     
     it('should get CCS matrix diagonal (n x n), k > 0', function () {
@@ -1580,7 +1634,7 @@ describe('CcsMatrix', function() {
           [0, 0, 1]
         ]);
 
-      assert.deepEqual(m.diagonal(1), [2, 3]);
+      assert.deepEqual(m.diagonal(1), new CcsMatrix([2, 3]));
     });
     
     it('should get CCS matrix diagonal (n x n), k < 0', function () {
@@ -1592,7 +1646,7 @@ describe('CcsMatrix', function() {
           [0, 3, 1]
         ]);
 
-      assert.deepEqual(m.diagonal(-1), [2, 3]);
+      assert.deepEqual(m.diagonal(-1), new CcsMatrix([2, 3]));
     });
     
     it('should get CCS matrix diagonal (m x n), m > n', function () {
@@ -1605,7 +1659,7 @@ describe('CcsMatrix', function() {
           [0, 0, 0]
         ]);
 
-      assert.deepEqual(m.diagonal(), [1, 1, 1]);
+      assert.deepEqual(m.diagonal(), new CcsMatrix([1, 1, 1]));
     });
 
     it('should get CCS matrix diagonal (m x n), m > n, k > 0', function () {
@@ -1618,7 +1672,7 @@ describe('CcsMatrix', function() {
           [0, 0, 0]
         ]);
 
-      assert.deepEqual(m.diagonal(1), [2, 3]);
+      assert.deepEqual(m.diagonal(1), new CcsMatrix([2, 3]));
     });
     
     it('should get CCS matrix diagonal (m x n), m > n, k < 0', function () {
@@ -1631,7 +1685,7 @@ describe('CcsMatrix', function() {
           [0, 0, 4]
         ]);
 
-      assert.deepEqual(m.diagonal(-1), [2, 3, 4]);
+      assert.deepEqual(m.diagonal(-1), new CcsMatrix([2, 3, 4]));
     });
     
     it('should get CCS matrix diagonal (m x n), m < n', function () {
@@ -1643,7 +1697,7 @@ describe('CcsMatrix', function() {
           [0, 0, 1, 0]
         ]);
 
-      assert.deepEqual(m.diagonal(), [1, 1, 1]);
+      assert.deepEqual(m.diagonal(), new CcsMatrix([1, 1, 1]));
     });
     
     it('should get CCS matrix diagonal (m x n), m < n, k > 0', function () {
@@ -1655,7 +1709,7 @@ describe('CcsMatrix', function() {
           [0, 0, 1, 4]
         ]);
       
-      assert.deepEqual(m.diagonal(1), [2, 3, 4]);
+      assert.deepEqual(m.diagonal(1), new CcsMatrix([2, 3, 4]));
     });
     
     it('should get CCS matrix diagonal (m x n), m < n, k < 0', function () {
@@ -1667,9 +1721,9 @@ describe('CcsMatrix', function() {
           [4, 3, 1, 0]
         ]);
 
-      assert.deepEqual(m.diagonal(-1), [2, 3]);
+      assert.deepEqual(m.diagonal(-1), new CcsMatrix([2, 3]));
       
-      assert.deepEqual(m.diagonal(-2), [4]);
+      assert.deepEqual(m.diagonal(-2), new CcsMatrix([4]));
     });
   });
   
diff --git a/test/type/matrix/CrsMatrix.test.js b/test/type/matrix/CrsMatrix.test.js
index 4da4a1ad1..ffcb0459a 100644
--- a/test/type/matrix/CrsMatrix.test.js
+++ b/test/type/matrix/CrsMatrix.test.js
@@ -1306,6 +1306,62 @@ describe('CrsMatrix', function() {
           [0, 2, 0]
         ]);
     });
+    
+    it('should create CRS matrix (n x n), matrix vector value', function () {
+
+      var m = CrsMatrix.diagonal([3, 3], math.matrix([1, 2, 3]));
+
+      assert.deepEqual(m._size, [3, 3]);
+      assert.deepEqual(m._values, [1, 2, 3]);
+      assert.deepEqual(m._index, [0, 1, 2]);
+      assert.deepEqual(m._ptr, [0, 1, 2, 3]);
+
+      assert.deepEqual(
+        m.toArray(), 
+        [
+          [1, 0, 0],
+          [0, 2, 0],
+          [0, 0, 3]
+        ]);
+    });
+
+    it('should create CRS matrix (n x n), matrix vector value, k > 0', function () {
+
+      var m = CrsMatrix.diagonal([3, 3], math.matrix([1, 2]), 1);
+
+      assert.deepEqual(m._size, [3, 3]);
+      assert.deepEqual(m._values, [1, 2]);
+      assert.deepEqual(m._index, [1, 2]);
+      assert.deepEqual(m._ptr, [0, 1, 2, 2]);
+
+      assert.deepEqual(
+        m.toArray(), 
+        [
+          [0, 1, 0],
+          [0, 0, 2],
+          [0, 0, 0]
+        ]);
+    });
+
+    it('should create CRS matrix (n x n), matrix vector value, k < 0', function () {
+
+      var m = CrsMatrix.diagonal([3, 3], math.matrix([1, 2]), -1);
+
+      assert.deepEqual(m._size, [3, 3]);
+      assert.deepEqual(m._values, [1, 2]);
+      assert.deepEqual(m._index, [0, 1]);
+      assert.deepEqual(m._ptr, [0, 0, 1, 2]);
+
+      assert.deepEqual(
+        m.toArray(), 
+        [
+          [0, 0, 0],
+          [1, 0, 0],
+          [0, 2, 0]
+        ]);
+    });
+    
+    
 
     it('should create CRS matrix (n x n), complex number', function () {
 
@@ -1548,7 +1604,7 @@ describe('CrsMatrix', function() {
           [0, 0, 1]
         ]);
 
-      assert.deepEqual(m.diagonal(), [1, 1, 1]);
+      assert.deepEqual(m.diagonal(), new CrsMatrix([1, 1, 1]));
     });
 
     it('should get CRS matrix diagonal (n x n), k > 0', function () {
@@ -1560,7 +1616,7 @@ describe('CrsMatrix', function() {
           [0, 0, 1]
         ]);
 
-      assert.deepEqual(m.diagonal(1), [2, 3]);
+      assert.deepEqual(m.diagonal(1), new CrsMatrix([2, 3]));
     });
 
     it('should get CRS matrix diagonal (n x n), k < 0', function () {
@@ -1572,7 +1628,7 @@ describe('CrsMatrix', function() {
           [0, 3, 1]
         ]);
 
-      assert.deepEqual(m.diagonal(-1), [2, 3]);
+      assert.deepEqual(m.diagonal(-1), new CrsMatrix([2, 3]));
     });
 
     it('should get CRS matrix diagonal (m x n), m > n', function () {
@@ -1585,7 +1641,7 @@ describe('CrsMatrix', function() {
           [0, 0, 0]
         ]);
 
-      assert.deepEqual(m.diagonal(), [1, 1, 1]);
+      assert.deepEqual(m.diagonal(), new CrsMatrix([1, 1, 1]));
     });
 
     it('should get CRS matrix diagonal (m x n), m > n, k > 0', function () {
@@ -1598,7 +1654,7 @@ describe('CrsMatrix', function() {
           [0, 0, 0]
         ]);
 
-      assert.deepEqual(m.diagonal(1), [2, 3]);
+      assert.deepEqual(m.diagonal(1), new CrsMatrix([2, 3]));
     });
 
     it('should get CRS matrix diagonal (m x n), m > n, k < 0', function () {
@@ -1611,7 +1667,7 @@ describe('CrsMatrix', function() {
           [0, 0, 4]
         ]);
 
-      assert.deepEqual(m.diagonal(-1), [2, 3, 4]);
+      assert.deepEqual(m.diagonal(-1), new CrsMatrix([2, 3, 4]));
     });
 
     it('should get CRS matrix diagonal (m x n), m < n', function () {
@@ -1623,7 +1679,7 @@ describe('CrsMatrix', function() {
           [0, 0, 1, 0]
         ]);
 
-      assert.deepEqual(m.diagonal(), [1, 1, 1]);
+      assert.deepEqual(m.diagonal(), new CrsMatrix([1, 1, 1]));
     });
 
     it('should get CRS matrix diagonal (m x n), m < n, k > 0', function () {
@@ -1635,7 +1691,7 @@ describe('CrsMatrix', function() {
           [0, 0, 1, 4]
         ]);
 
-      assert.deepEqual(m.diagonal(1), [2, 3, 4]);
+      assert.deepEqual(m.diagonal(1), new CrsMatrix([2, 3, 4]));
     });
 
     it('should get CRS matrix diagonal (m x n), m < n, k < 0', function () {
@@ -1647,9 +1703,9 @@ describe('CrsMatrix', function() {
           [4, 3, 1, 0]
         ]);
 
-      assert.deepEqual(m.diagonal(-1), [2, 3]);
+      assert.deepEqual(m.diagonal(-1), new CrsMatrix([2, 3]));
 
-      assert.deepEqual(m.diagonal(-2), [4]);
+      assert.deepEqual(m.diagonal(-2), new CrsMatrix([4]));
     });
   });
   
diff --git a/test/type/matrix/DenseMatrix.test.js b/test/type/matrix/DenseMatrix.test.js
index 9ab974fe7..bab8985b7 100644
--- a/test/type/matrix/DenseMatrix.test.js
+++ b/test/type/matrix/DenseMatrix.test.js
@@ -733,6 +733,48 @@ describe('DenseMatrix', function() {
           [0, 2, 0]
         ]);
     });
+    
+    it('should create matrix (n x n), matrix vector value', function () {
+
+      var m = DenseMatrix.diagonal([3, 3], math.matrix([1, 2, 3]));
+
+      assert.deepEqual(m._size, [3, 3]);
+      assert.deepEqual(
+        m.toArray(), 
+        [
+          [1, 0, 0],
+          [0, 2, 0],
+          [0, 0, 3]
+        ]);
+    });
+
+    it('should create matrix (n x n), matrix vector value, k > 0', function () {
+
+      var m = DenseMatrix.diagonal([3, 3], math.matrix([1, 2]), 1);
+
+      assert.deepEqual(m._size, [3, 3]);
+      assert.deepEqual(
+        m.toArray(), 
+        [
+          [0, 1, 0],
+          [0, 0, 2],
+          [0, 0, 0]
+        ]);
+    });
+
+    it('should create matrix (n x n), matrix vector value, k < 0', function () {
+
+      var m = DenseMatrix.diagonal([3, 3], math.matrix([1, 2]), -1);
+
+      assert.deepEqual(m._size, [3, 3]);
+      assert.deepEqual(
+        m.toArray(), 
+        [
+          [0, 0, 0],
+          [1, 0, 0],
+          [0, 2, 0]
+        ]);
+    });
 
     it('should create matrix (m x n), m > n', function () {
 
@@ -917,7 +959,7 @@ describe('DenseMatrix', function() {
           [0, 0, 1]
         ]);
 
-      assert.deepEqual(m.diagonal(), [1, 1, 1]);
+      assert.deepEqual(m.diagonal(), new DenseMatrix([1, 1, 1]));
     });
 
     it('should get matrix diagonal (n x n), k > 0', function () {
@@ -929,7 +971,7 @@ describe('DenseMatrix', function() {
           [0, 0, 1]
         ]);
 
-      assert.deepEqual(m.diagonal(1), [2, 3]);
+      assert.deepEqual(m.diagonal(1), new DenseMatrix([2, 3]));
     });
 
     it('should get matrix diagonal (n x n), k < 0', function () {
@@ -941,7 +983,7 @@ describe('DenseMatrix', function() {
           [0, 3, 1]
         ]);
 
-      assert.deepEqual(m.diagonal(-1), [2, 3]);
+      assert.deepEqual(m.diagonal(-1), new DenseMatrix([2, 3]));
     });
 
     it('should get matrix diagonal (m x n), m > n', function () {
@@ -954,7 +996,7 @@ describe('DenseMatrix', function() {
           [0, 0, 0]
         ]);
 
-      assert.deepEqual(m.diagonal(), [1, 1, 1]);
+      assert.deepEqual(m.diagonal(), new DenseMatrix([1, 1, 1]));
     });
 
     it('should get matrix diagonal (m x n), m > n, k > 0', function () {
@@ -967,7 +1009,7 @@ describe('DenseMatrix', function() {
           [0, 0, 0]
         ]);
 
-      assert.deepEqual(m.diagonal(1), [2, 3]);
+      assert.deepEqual(m.diagonal(1), new DenseMatrix([2, 3]));
     });
 
     it('should get matrix diagonal (m x n), m > n, k < 0', function () {
@@ -980,7 +1022,7 @@ describe('DenseMatrix', function() {
           [0, 0, 4]
         ]);
 
-      assert.deepEqual(m.diagonal(-1), [2, 3, 4]);
+      assert.deepEqual(m.diagonal(-1), new DenseMatrix([2, 3, 4]));
     });
 
     it('should get matrix diagonal (m x n), m < n', function () {
@@ -992,7 +1034,7 @@ describe('DenseMatrix', function() {
           [0, 0, 1, 0]
         ]);
 
-      assert.deepEqual(m.diagonal(), [1, 1, 1]);
+      assert.deepEqual(m.diagonal(), new DenseMatrix([1, 1, 1]));
     });
 
     it('should get matrix diagonal (m x n), m < n, k > 0', function () {
@@ -1004,7 +1046,7 @@ describe('DenseMatrix', function() {
           [0, 0, 1, 4]
         ]);
 
-      assert.deepEqual(m.diagonal(1), [2, 3, 4]);
+      assert.deepEqual(m.diagonal(1), new DenseMatrix([2, 3, 4]));
     });
 
     it('should get matrix diagonal (m x n), m < n, k < 0', function () {
@@ -1016,9 +1058,9 @@ describe('DenseMatrix', function() {
           [4, 3, 1, 0]
         ]);
 
-      assert.deepEqual(m.diagonal(-1), [2, 3]);
+      assert.deepEqual(m.diagonal(-1), new DenseMatrix([2, 3]));
 
-      assert.deepEqual(m.diagonal(-2), [4]);
+      assert.deepEqual(m.diagonal(-2), new DenseMatrix([4]));
     });
   });