UNPKG

25.2 kBJavaScriptView Raw
1'use strict'
2
3const util = require('../../utils/index')
4const DimensionError = require('../../error/DimensionError')
5
6const string = util.string
7const array = util.array
8const object = util.object
9const number = util.number
10
11const isArray = Array.isArray
12const isNumber = number.isNumber
13const isInteger = number.isInteger
14const isString = string.isString
15
16const validateIndex = array.validateIndex
17
18function factory (type, config, load, typed) {
19 const getArrayDataType = load(require('./utils/getArrayDataType'))
20 const Matrix = load(require('./Matrix')) // force loading Matrix (do not use via type.Matrix)
21
22 /**
23 * Dense Matrix implementation. A regular, dense matrix, supporting multi-dimensional matrices. This is the default matrix type.
24 * @class DenseMatrix
25 */
26 function DenseMatrix (data, datatype) {
27 if (!(this instanceof DenseMatrix)) { throw new SyntaxError('Constructor must be called with the new operator') }
28 if (datatype && !isString(datatype)) { throw new Error('Invalid datatype: ' + datatype) }
29
30 if (type.isMatrix(data)) {
31 // check data is a DenseMatrix
32 if (data.type === 'DenseMatrix') {
33 // clone data & size
34 this._data = object.clone(data._data)
35 this._size = object.clone(data._size)
36 this._datatype = datatype || data._datatype
37 } else {
38 // build data from existing matrix
39 this._data = data.toArray()
40 this._size = data.size()
41 this._datatype = datatype || data._datatype
42 }
43 } else if (data && isArray(data.data) && isArray(data.size)) {
44 // initialize fields from JSON representation
45 this._data = data.data
46 this._size = data.size
47 this._datatype = datatype || data.datatype
48 } else if (isArray(data)) {
49 // replace nested Matrices with Arrays
50 this._data = preprocess(data)
51 // get the dimensions of the array
52 this._size = array.size(this._data)
53 // verify the dimensions of the array, TODO: compute size while processing array
54 array.validate(this._data, this._size)
55 // data type unknown
56 this._datatype = datatype
57 } else if (data) {
58 // unsupported type
59 throw new TypeError('Unsupported type of data (' + util.types.type(data) + ')')
60 } else {
61 // nothing provided
62 this._data = []
63 this._size = [0]
64 this._datatype = datatype
65 }
66 }
67
68 DenseMatrix.prototype = new Matrix()
69
70 /**
71 * Attach type information
72 */
73 DenseMatrix.prototype.type = 'DenseMatrix'
74 DenseMatrix.prototype.isDenseMatrix = true
75
76 /**
77 * Get the matrix type
78 *
79 * Usage:
80 * const matrixType = matrix.getDataType() // retrieves the matrix type
81 *
82 * @memberOf DenseMatrix
83 * @return {string} type information; if multiple types are found from the Matrix, it will return "mixed"
84 */
85 DenseMatrix.prototype.getDataType = function () {
86 return getArrayDataType(this._data)
87 }
88
89 /**
90 * Get the storage format used by the matrix.
91 *
92 * Usage:
93 * const format = matrix.storage() // retrieve storage format
94 *
95 * @memberof DenseMatrix
96 * @return {string} The storage format.
97 */
98 DenseMatrix.prototype.storage = function () {
99 return 'dense'
100 }
101
102 /**
103 * Get the datatype of the data stored in the matrix.
104 *
105 * Usage:
106 * const format = matrix.datatype() // retrieve matrix datatype
107 *
108 * @memberof DenseMatrix
109 * @return {string} The datatype.
110 */
111 DenseMatrix.prototype.datatype = function () {
112 return this._datatype
113 }
114
115 /**
116 * Create a new DenseMatrix
117 * @memberof DenseMatrix
118 * @param {Array} data
119 * @param {string} [datatype]
120 */
121 DenseMatrix.prototype.create = function (data, datatype) {
122 return new DenseMatrix(data, datatype)
123 }
124
125 /**
126 * Get a subset of the matrix, or replace a subset of the matrix.
127 *
128 * Usage:
129 * const subset = matrix.subset(index) // retrieve subset
130 * const value = matrix.subset(index, replacement) // replace subset
131 *
132 * @memberof DenseMatrix
133 * @param {Index} index
134 * @param {Array | DenseMatrix | *} [replacement]
135 * @param {*} [defaultValue=0] Default value, filled in on new entries when
136 * the matrix is resized. If not provided,
137 * new matrix elements will be filled with zeros.
138 */
139 DenseMatrix.prototype.subset = function (index, replacement, defaultValue) {
140 switch (arguments.length) {
141 case 1:
142 return _get(this, index)
143
144 // intentional fall through
145 case 2:
146 case 3:
147 return _set(this, index, replacement, defaultValue)
148
149 default:
150 throw new SyntaxError('Wrong number of arguments')
151 }
152 }
153
154 /**
155 * Get a single element from the matrix.
156 * @memberof DenseMatrix
157 * @param {number[]} index Zero-based index
158 * @return {*} value
159 */
160 DenseMatrix.prototype.get = function (index) {
161 if (!isArray(index)) { throw new TypeError('Array expected') }
162 if (index.length !== this._size.length) { throw new DimensionError(index.length, this._size.length) }
163
164 // check index
165 for (let x = 0; x < index.length; x++) { validateIndex(index[x], this._size[x]) }
166
167 let data = this._data
168 for (let i = 0, ii = index.length; i < ii; i++) {
169 const indexI = index[i]
170 validateIndex(indexI, data.length)
171 data = data[indexI]
172 }
173
174 return data
175 }
176
177 /**
178 * Replace a single element in the matrix.
179 * @memberof DenseMatrix
180 * @param {number[]} index Zero-based index
181 * @param {*} value
182 * @param {*} [defaultValue] Default value, filled in on new entries when
183 * the matrix is resized. If not provided,
184 * new matrix elements will be left undefined.
185 * @return {DenseMatrix} self
186 */
187 DenseMatrix.prototype.set = function (index, value, defaultValue) {
188 if (!isArray(index)) { throw new TypeError('Array expected') }
189 if (index.length < this._size.length) { throw new DimensionError(index.length, this._size.length, '<') }
190
191 let i, ii, indexI
192
193 // enlarge matrix when needed
194 const size = index.map(function (i) {
195 return i + 1
196 })
197 _fit(this, size, defaultValue)
198
199 // traverse over the dimensions
200 let data = this._data
201 for (i = 0, ii = index.length - 1; i < ii; i++) {
202 indexI = index[i]
203 validateIndex(indexI, data.length)
204 data = data[indexI]
205 }
206
207 // set new value
208 indexI = index[index.length - 1]
209 validateIndex(indexI, data.length)
210 data[indexI] = value
211
212 return this
213 }
214
215 /**
216 * Get a submatrix of this matrix
217 * @memberof DenseMatrix
218 * @param {DenseMatrix} matrix
219 * @param {Index} index Zero-based index
220 * @private
221 */
222 function _get (matrix, index) {
223 if (!type.isIndex(index)) {
224 throw new TypeError('Invalid index')
225 }
226
227 const isScalar = index.isScalar()
228 if (isScalar) {
229 // return a scalar
230 return matrix.get(index.min())
231 } else {
232 // validate dimensions
233 const size = index.size()
234 if (size.length !== matrix._size.length) {
235 throw new DimensionError(size.length, matrix._size.length)
236 }
237
238 // validate if any of the ranges in the index is out of range
239 const min = index.min()
240 const max = index.max()
241 for (let i = 0, ii = matrix._size.length; i < ii; i++) {
242 validateIndex(min[i], matrix._size[i])
243 validateIndex(max[i], matrix._size[i])
244 }
245
246 // retrieve submatrix
247 // TODO: more efficient when creating an empty matrix and setting _data and _size manually
248 return new DenseMatrix(_getSubmatrix(matrix._data, index, size.length, 0), matrix._datatype)
249 }
250 }
251
252 /**
253 * Recursively get a submatrix of a multi dimensional matrix.
254 * Index is not checked for correct number or length of dimensions.
255 * @memberof DenseMatrix
256 * @param {Array} data
257 * @param {Index} index
258 * @param {number} dims Total number of dimensions
259 * @param {number} dim Current dimension
260 * @return {Array} submatrix
261 * @private
262 */
263 function _getSubmatrix (data, index, dims, dim) {
264 const last = (dim === dims - 1)
265 const range = index.dimension(dim)
266
267 if (last) {
268 return range.map(function (i) {
269 validateIndex(i, data.length)
270 return data[i]
271 }).valueOf()
272 } else {
273 return range.map(function (i) {
274 validateIndex(i, data.length)
275 const child = data[i]
276 return _getSubmatrix(child, index, dims, dim + 1)
277 }).valueOf()
278 }
279 }
280
281 /**
282 * Replace a submatrix in this matrix
283 * Indexes are zero-based.
284 * @memberof DenseMatrix
285 * @param {DenseMatrix} matrix
286 * @param {Index} index
287 * @param {DenseMatrix | Array | *} submatrix
288 * @param {*} defaultValue Default value, filled in on new entries when
289 * the matrix is resized.
290 * @return {DenseMatrix} matrix
291 * @private
292 */
293 function _set (matrix, index, submatrix, defaultValue) {
294 if (!index || index.isIndex !== true) {
295 throw new TypeError('Invalid index')
296 }
297
298 // get index size and check whether the index contains a single value
299 const iSize = index.size()
300 const isScalar = index.isScalar()
301
302 // calculate the size of the submatrix, and convert it into an Array if needed
303 let sSize
304 if (type.isMatrix(submatrix)) {
305 sSize = submatrix.size()
306 submatrix = submatrix.valueOf()
307 } else {
308 sSize = array.size(submatrix)
309 }
310
311 if (isScalar) {
312 // set a scalar
313
314 // check whether submatrix is a scalar
315 if (sSize.length !== 0) {
316 throw new TypeError('Scalar expected')
317 }
318
319 matrix.set(index.min(), submatrix, defaultValue)
320 } else {
321 // set a submatrix
322
323 // validate dimensions
324 if (iSize.length < matrix._size.length) {
325 throw new DimensionError(iSize.length, matrix._size.length, '<')
326 }
327
328 if (sSize.length < iSize.length) {
329 // calculate number of missing outer dimensions
330 let i = 0
331 let outer = 0
332 while (iSize[i] === 1 && sSize[i] === 1) {
333 i++
334 }
335 while (iSize[i] === 1) {
336 outer++
337 i++
338 }
339
340 // unsqueeze both outer and inner dimensions
341 submatrix = array.unsqueeze(submatrix, iSize.length, outer, sSize)
342 }
343
344 // check whether the size of the submatrix matches the index size
345 if (!object.deepEqual(iSize, sSize)) {
346 throw new DimensionError(iSize, sSize, '>')
347 }
348
349 // enlarge matrix when needed
350 const size = index.max().map(function (i) {
351 return i + 1
352 })
353 _fit(matrix, size, defaultValue)
354
355 // insert the sub matrix
356 const dims = iSize.length
357 const dim = 0
358 _setSubmatrix(matrix._data, index, submatrix, dims, dim)
359 }
360
361 return matrix
362 }
363
364 /**
365 * Replace a submatrix of a multi dimensional matrix.
366 * @memberof DenseMatrix
367 * @param {Array} data
368 * @param {Index} index
369 * @param {Array} submatrix
370 * @param {number} dims Total number of dimensions
371 * @param {number} dim
372 * @private
373 */
374 function _setSubmatrix (data, index, submatrix, dims, dim) {
375 const last = (dim === dims - 1)
376 const range = index.dimension(dim)
377
378 if (last) {
379 range.forEach(function (dataIndex, subIndex) {
380 validateIndex(dataIndex)
381 data[dataIndex] = submatrix[subIndex[0]]
382 })
383 } else {
384 range.forEach(function (dataIndex, subIndex) {
385 validateIndex(dataIndex)
386 _setSubmatrix(data[dataIndex], index, submatrix[subIndex[0]], dims, dim + 1)
387 })
388 }
389 }
390
391 /**
392 * Resize the matrix to the given size. Returns a copy of the matrix when
393 * `copy=true`, otherwise return the matrix itself (resize in place).
394 *
395 * @memberof DenseMatrix
396 * @param {number[]} size The new size the matrix should have.
397 * @param {*} [defaultValue=0] Default value, filled in on new entries.
398 * If not provided, the matrix elements will
399 * be filled with zeros.
400 * @param {boolean} [copy] Return a resized copy of the matrix
401 *
402 * @return {Matrix} The resized matrix
403 */
404 DenseMatrix.prototype.resize = function (size, defaultValue, copy) {
405 // validate arguments
406 if (!isArray(size)) { throw new TypeError('Array expected') }
407
408 // matrix to resize
409 const m = copy ? this.clone() : this
410 // resize matrix
411 return _resize(m, size, defaultValue)
412 }
413
414 function _resize (matrix, size, defaultValue) {
415 // check size
416 if (size.length === 0) {
417 // first value in matrix
418 let v = matrix._data
419 // go deep
420 while (isArray(v)) {
421 v = v[0]
422 }
423 return v
424 }
425 // resize matrix
426 matrix._size = size.slice(0) // copy the array
427 matrix._data = array.resize(matrix._data, matrix._size, defaultValue)
428 // return matrix
429 return matrix
430 }
431
432 /**
433 * Reshape the matrix to the given size. Returns a copy of the matrix when
434 * `copy=true`, otherwise return the matrix itself (reshape in place).
435 *
436 * NOTE: This might be better suited to copy by default, instead of modifying
437 * in place. For now, it operates in place to remain consistent with
438 * resize().
439 *
440 * @memberof DenseMatrix
441 * @param {number[]} size The new size the matrix should have.
442 * @param {boolean} [copy] Return a reshaped copy of the matrix
443 *
444 * @return {Matrix} The reshaped matrix
445 */
446 DenseMatrix.prototype.reshape = function (size, copy) {
447 const m = copy ? this.clone() : this
448
449 m._data = array.reshape(m._data, size)
450 m._size = size.slice(0)
451 return m
452 }
453
454 /**
455 * Enlarge the matrix when it is smaller than given size.
456 * If the matrix is larger or equal sized, nothing is done.
457 * @memberof DenseMatrix
458 * @param {DenseMatrix} matrix The matrix to be resized
459 * @param {number[]} size
460 * @param {*} defaultValue Default value, filled in on new entries.
461 * @private
462 */
463 function _fit (matrix, size, defaultValue) {
464 const // copy the array
465 newSize = matrix._size.slice(0)
466
467 let changed = false
468
469 // add dimensions when needed
470 while (newSize.length < size.length) {
471 newSize.push(0)
472 changed = true
473 }
474
475 // enlarge size when needed
476 for (let i = 0, ii = size.length; i < ii; i++) {
477 if (size[i] > newSize[i]) {
478 newSize[i] = size[i]
479 changed = true
480 }
481 }
482
483 if (changed) {
484 // resize only when size is changed
485 _resize(matrix, newSize, defaultValue)
486 }
487 }
488
489 /**
490 * Create a clone of the matrix
491 * @memberof DenseMatrix
492 * @return {DenseMatrix} clone
493 */
494 DenseMatrix.prototype.clone = function () {
495 const m = new DenseMatrix({
496 data: object.clone(this._data),
497 size: object.clone(this._size),
498 datatype: this._datatype
499 })
500 return m
501 }
502
503 /**
504 * Retrieve the size of the matrix.
505 * @memberof DenseMatrix
506 * @returns {number[]} size
507 */
508 DenseMatrix.prototype.size = function () {
509 return this._size.slice(0) // return a clone of _size
510 }
511
512 /**
513 * Create a new matrix with the results of the callback function executed on
514 * each entry of the matrix.
515 * @memberof DenseMatrix
516 * @param {Function} callback The callback function is invoked with three
517 * parameters: the value of the element, the index
518 * of the element, and the Matrix being traversed.
519 *
520 * @return {DenseMatrix} matrix
521 */
522 DenseMatrix.prototype.map = function (callback) {
523 // matrix instance
524 const me = this
525 const recurse = function (value, index) {
526 if (isArray(value)) {
527 return value.map(function (child, i) {
528 return recurse(child, index.concat(i))
529 })
530 } else {
531 return callback(value, index, me)
532 }
533 }
534 // return dense format
535 return new DenseMatrix({
536 data: recurse(this._data, []),
537 size: object.clone(this._size),
538 datatype: this._datatype
539 })
540 }
541
542 /**
543 * Execute a callback function on each entry of the matrix.
544 * @memberof DenseMatrix
545 * @param {Function} callback The callback function is invoked with three
546 * parameters: the value of the element, the index
547 * of the element, and the Matrix being traversed.
548 */
549 DenseMatrix.prototype.forEach = function (callback) {
550 // matrix instance
551 const me = this
552 const recurse = function (value, index) {
553 if (isArray(value)) {
554 value.forEach(function (child, i) {
555 recurse(child, index.concat(i))
556 })
557 } else {
558 callback(value, index, me)
559 }
560 }
561 recurse(this._data, [])
562 }
563
564 /**
565 * Create an Array with a copy of the data of the DenseMatrix
566 * @memberof DenseMatrix
567 * @returns {Array} array
568 */
569 DenseMatrix.prototype.toArray = function () {
570 return object.clone(this._data)
571 }
572
573 /**
574 * Get the primitive value of the DenseMatrix: a multidimensional array
575 * @memberof DenseMatrix
576 * @returns {Array} array
577 */
578 DenseMatrix.prototype.valueOf = function () {
579 return this._data
580 }
581
582 /**
583 * Get a string representation of the matrix, with optional formatting options.
584 * @memberof DenseMatrix
585 * @param {Object | number | Function} [options] Formatting options. See
586 * lib/utils/number:format for a
587 * description of the available
588 * options.
589 * @returns {string} str
590 */
591 DenseMatrix.prototype.format = function (options) {
592 return string.format(this._data, options)
593 }
594
595 /**
596 * Get a string representation of the matrix
597 * @memberof DenseMatrix
598 * @returns {string} str
599 */
600 DenseMatrix.prototype.toString = function () {
601 return string.format(this._data)
602 }
603
604 /**
605 * Get a JSON representation of the matrix
606 * @memberof DenseMatrix
607 * @returns {Object}
608 */
609 DenseMatrix.prototype.toJSON = function () {
610 return {
611 mathjs: 'DenseMatrix',
612 data: this._data,
613 size: this._size,
614 datatype: this._datatype
615 }
616 }
617
618 /**
619 * Get the kth Matrix diagonal.
620 *
621 * @memberof DenseMatrix
622 * @param {number | BigNumber} [k=0] The kth diagonal where the vector will retrieved.
623 *
624 * @returns {Array} The array vector with the diagonal values.
625 */
626 DenseMatrix.prototype.diagonal = function (k) {
627 // validate k if any
628 if (k) {
629 // convert BigNumber to a number
630 if (type.isBigNumber(k)) { k = k.toNumber() }
631 // is must be an integer
632 if (!isNumber(k) || !isInteger(k)) {
633 throw new TypeError('The parameter k must be an integer number')
634 }
635 } else {
636 // default value
637 k = 0
638 }
639
640 const kSuper = k > 0 ? k : 0
641 const kSub = k < 0 ? -k : 0
642
643 // rows & columns
644 const rows = this._size[0]
645 const columns = this._size[1]
646
647 // number diagonal values
648 const n = Math.min(rows - kSub, columns - kSuper)
649
650 // x is a matrix get diagonal from matrix
651 const data = []
652
653 // loop rows
654 for (let i = 0; i < n; i++) {
655 data[i] = this._data[i + kSub][i + kSuper]
656 }
657
658 // create DenseMatrix
659 return new DenseMatrix({
660 data: data,
661 size: [n],
662 datatype: this._datatype
663 })
664 }
665
666 /**
667 * Create a diagonal matrix.
668 *
669 * @memberof DenseMatrix
670 * @param {Array} size The matrix size.
671 * @param {number | Array} value The values for the diagonal.
672 * @param {number | BigNumber} [k=0] The kth diagonal where the vector will be filled in.
673 * @param {number} [defaultValue] The default value for non-diagonal
674 *
675 * @returns {DenseMatrix}
676 */
677 DenseMatrix.diagonal = function (size, value, k, defaultValue, datatype) {
678 if (!isArray(size)) { throw new TypeError('Array expected, size parameter') }
679 if (size.length !== 2) { throw new Error('Only two dimensions matrix are supported') }
680
681 // map size & validate
682 size = size.map(function (s) {
683 // check it is a big number
684 if (type.isBigNumber(s)) {
685 // convert it
686 s = s.toNumber()
687 }
688 // validate arguments
689 if (!isNumber(s) || !isInteger(s) || s < 1) {
690 throw new Error('Size values must be positive integers')
691 }
692 return s
693 })
694
695 // validate k if any
696 if (k) {
697 // convert BigNumber to a number
698 if (type.isBigNumber(k)) { k = k.toNumber() }
699 // is must be an integer
700 if (!isNumber(k) || !isInteger(k)) {
701 throw new TypeError('The parameter k must be an integer number')
702 }
703 } else {
704 // default value
705 k = 0
706 }
707
708 if (defaultValue && isString(datatype)) {
709 // convert defaultValue to the same datatype
710 defaultValue = typed.convert(defaultValue, datatype)
711 }
712
713 const kSuper = k > 0 ? k : 0
714 const kSub = k < 0 ? -k : 0
715
716 // rows and columns
717 const rows = size[0]
718 const columns = size[1]
719
720 // number of non-zero items
721 const n = Math.min(rows - kSub, columns - kSuper)
722
723 // value extraction function
724 let _value
725
726 // check value
727 if (isArray(value)) {
728 // validate array
729 if (value.length !== n) {
730 // number of values in array must be n
731 throw new Error('Invalid value array length')
732 }
733 // define function
734 _value = function (i) {
735 // return value @ i
736 return value[i]
737 }
738 } else if (type.isMatrix(value)) {
739 // matrix size
740 const ms = value.size()
741 // validate matrix
742 if (ms.length !== 1 || ms[0] !== n) {
743 // number of values in array must be n
744 throw new Error('Invalid matrix length')
745 }
746 // define function
747 _value = function (i) {
748 // return value @ i
749 return value.get([i])
750 }
751 } else {
752 // define function
753 _value = function () {
754 // return value
755 return value
756 }
757 }
758
759 // discover default value if needed
760 if (!defaultValue) {
761 // check first value in array
762 defaultValue = type.isBigNumber(_value(0)) ? new type.BigNumber(0) : 0
763 }
764
765 // empty array
766 let data = []
767
768 // check we need to resize array
769 if (size.length > 0) {
770 // resize array
771 data = array.resize(data, size, defaultValue)
772 // fill diagonal
773 for (let d = 0; d < n; d++) {
774 data[d + kSub][d + kSuper] = _value(d)
775 }
776 }
777
778 // create DenseMatrix
779 return new DenseMatrix({
780 data: data,
781 size: [rows, columns]
782 })
783 }
784
785 /**
786 * Generate a matrix from a JSON object
787 * @memberof DenseMatrix
788 * @param {Object} json An object structured like
789 * `{"mathjs": "DenseMatrix", data: [], size: []}`,
790 * where mathjs is optional
791 * @returns {DenseMatrix}
792 */
793 DenseMatrix.fromJSON = function (json) {
794 return new DenseMatrix(json)
795 }
796
797 /**
798 * Swap rows i and j in Matrix.
799 *
800 * @memberof DenseMatrix
801 * @param {number} i Matrix row index 1
802 * @param {number} j Matrix row index 2
803 *
804 * @return {Matrix} The matrix reference
805 */
806 DenseMatrix.prototype.swapRows = function (i, j) {
807 // check index
808 if (!isNumber(i) || !isInteger(i) || !isNumber(j) || !isInteger(j)) {
809 throw new Error('Row index must be positive integers')
810 }
811 // check dimensions
812 if (this._size.length !== 2) {
813 throw new Error('Only two dimensional matrix is supported')
814 }
815 // validate index
816 validateIndex(i, this._size[0])
817 validateIndex(j, this._size[0])
818
819 // swap rows
820 DenseMatrix._swapRows(i, j, this._data)
821 // return current instance
822 return this
823 }
824
825 /**
826 * Swap rows i and j in Dense Matrix data structure.
827 *
828 * @param {number} i Matrix row index 1
829 * @param {number} j Matrix row index 2
830 */
831 DenseMatrix._swapRows = function (i, j, data) {
832 // swap values i <-> j
833 const vi = data[i]
834 data[i] = data[j]
835 data[j] = vi
836 }
837
838 /**
839 * Preprocess data, which can be an Array or DenseMatrix with nested Arrays and
840 * Matrices. Replaces all nested Matrices with Arrays
841 * @memberof DenseMatrix
842 * @param {Array} data
843 * @return {Array} data
844 */
845 function preprocess (data) {
846 for (let i = 0, ii = data.length; i < ii; i++) {
847 const elem = data[i]
848 if (isArray(elem)) {
849 data[i] = preprocess(elem)
850 } else if (elem && elem.isMatrix === true) {
851 data[i] = preprocess(elem.valueOf())
852 }
853 }
854
855 return data
856 }
857
858 // register this type in the base class Matrix
859 type.Matrix._storage.dense = DenseMatrix
860 type.Matrix._storage['default'] = DenseMatrix
861
862 // exports
863 return DenseMatrix
864}
865
866exports.name = 'DenseMatrix'
867exports.path = 'type'
868exports.factory = factory
869exports.lazy = false // no lazy loading, as we alter type.Matrix._storage