Merge lp:~gang65/ubuntu-calculator-app/reboot-upgrade-math-js-to-1.5 into lp:ubuntu-calculator-app

Proposed by Bartosz Kosiorek
Status: Merged
Approved by: Riccardo Padovani
Approved revision: 155
Merged at revision: 161
Proposed branch: lp:~gang65/ubuntu-calculator-app/reboot-upgrade-math-js-to-1.5
Merge into: lp:ubuntu-calculator-app
Diff against target: 18755 lines (+9023/-4994)
1 file modified
app/engine/math.js (+9023/-4994)
To merge this branch: bzr merge lp:~gang65/ubuntu-calculator-app/reboot-upgrade-math-js-to-1.5
Reviewer Review Type Date Requested Status
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Riccardo Padovani Approve
Bartosz Kosiorek Needs Information
Review via email: mp+255315@code.launchpad.net

Commit message

Upgrade math.js to 1.5.2

Description of the change

Upgrade math.js to 1.5.2

To post a comment you must log in.
Revision history for this message
Bartosz Kosiorek (gang65) wrote :

Unfortunately with math.js1.5.0 I noticed regression with complex numbers:
With math.js 1.4.0:
   66i*i = -66

With math.js 1.5.0:
   66i*i = -6.6

Bug already submitted:
https://github.com/josdejong/mathjs/issues/319

review: Needs Fixing
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
153. By Bartosz Kosiorek

Upgrade math.js to 1.5.1 to fix regression

Revision history for this message
Bartosz Kosiorek (gang65) wrote :

I upgraded to fixed math.js version 1.5.1.
Now everything should be fine.

review: Approve
154. By Bartosz Kosiorek

Comment fix

Revision history for this message
Bartosz Kosiorek (gang65) :
review: Needs Information
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
155. By Bartosz Kosiorek

Upgrade math.js to 1.5.2

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Riccardo Padovani (rpadovani) wrote :

Looks good to me, thanks :-)

review: Approve
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'app/engine/math.js'
2--- app/engine/math.js 2015-03-02 09:15:57 +0000
3+++ app/engine/math.js 2015-04-10 14:51:16 +0000
4@@ -14,11 +14,11 @@
5 * It features real and complex numbers, units, matrices, a large set of
6 * mathematical functions, and a flexible expression parser.
7 *
8- * @version 1.2.0
9- * @date 2014-12-25
10+ * @version 1.5.2
11+ * @date 2015-04-09
12 *
13 * @license
14- * Copyright (C) 2013-2014 Jos de Jong <wjosdejong@gmail.com>
15+ * Copyright (C) 2013-2015 Jos de Jong <wjosdejong@gmail.com>
16 *
17 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
18 * use this file except in compliance with the License. You may obtain a copy
19@@ -35,46 +35,45 @@
20
21 (function webpackUniversalModuleDefinition(root, factory) {
22 // UCA: we delete all exports, we don't need them, and we keep only our var
23- mathJs = factory();
24-})(this, function() {
25+ mathJs = factory();})(this, function() {
26 return /******/ (function(modules) { // webpackBootstrap
27 /******/ // The module cache
28 /******/ var installedModules = {};
29-/******/
30+
31 /******/ // The require function
32 /******/ function __webpack_require__(moduleId) {
33-/******/
34+
35 /******/ // Check if module is in cache
36 /******/ if(installedModules[moduleId])
37 /******/ return installedModules[moduleId].exports;
38-/******/
39+
40 /******/ // Create a new module (and put it into the cache)
41 /******/ var module = installedModules[moduleId] = {
42 /******/ exports: {},
43 /******/ id: moduleId,
44 /******/ loaded: false
45 /******/ };
46-/******/
47+
48 /******/ // Execute the module function
49 /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
50-/******/
51+
52 /******/ // Flag the module as loaded
53 /******/ module.loaded = true;
54-/******/
55+
56 /******/ // Return the exports of the module
57 /******/ return module.exports;
58 /******/ }
59-/******/
60-/******/
61+
62+
63 /******/ // expose the modules object (__webpack_modules__)
64 /******/ __webpack_require__.m = modules;
65-/******/
66+
67 /******/ // expose the module cache
68 /******/ __webpack_require__.c = installedModules;
69-/******/
70+
71 /******/ // __webpack_public_path__
72 /******/ __webpack_require__.p = "";
73-/******/
74+
75 /******/ // Load entry module and return exports
76 /******/ return __webpack_require__(0);
77 /******/ })
78@@ -162,27 +161,27 @@
79
80 // TODO: remove deprecated setting some day (deprecated since version 0.17.0)
81 if (options.number && options.number.defaultType) {
82- throw new Error('setting `number.defaultType` is deprecated. Use `number` instead.')
83+ throw new Error('setting `number.defaultType` is deprecated. Use `number` instead.');
84 }
85
86 // TODO: remove deprecated setting some day (deprecated since version 0.17.0)
87 if (options.number && options.number.precision) {
88- throw new Error('setting `number.precision` is deprecated. Use `precision` instead.')
89+ throw new Error('setting `number.precision` is deprecated. Use `precision` instead.');
90 }
91
92 // TODO: remove deprecated setting some day (deprecated since version 0.17.0)
93 if (options.matrix && options.matrix.defaultType) {
94- throw new Error('setting `matrix.defaultType` is deprecated. Use `matrix` instead.')
95+ throw new Error('setting `matrix.defaultType` is deprecated. Use `matrix` instead.');
96 }
97
98 // TODO: remove deprecated setting some day (deprecated since version 0.15.0)
99 if (options.matrix && options.matrix['default']) {
100- throw new Error('setting `matrix.default` is deprecated. Use `matrix` instead.')
101+ throw new Error('setting `matrix.default` is deprecated. Use `matrix` instead.');
102 }
103
104 // TODO: remove deprecated setting some day (deprecated since version 0.20.0)
105 if (options.decimals) {
106- throw new Error('setting `decimals` is deprecated. Use `precision` instead.')
107+ throw new Error('setting `decimals` is deprecated. Use `precision` instead.');
108 }
109 }
110
111@@ -207,6 +206,29 @@
112 // create a new BigNumber factory for this instance of math.js
113 var BigNumber = __webpack_require__(5).constructor();
114
115+ /**
116+ * Get a JSON representation of a BigNumber containing
117+ * type information
118+ * @returns {Object} Returns a JSON object structured as:
119+ * `{"mathjs": "BigNumber", "value": "0.2"}`
120+ */
121+ BigNumber.prototype.toJSON = function () {
122+ return {
123+ mathjs: 'BigNumber',
124+ value: this.toString()
125+ };
126+ };
127+
128+ /**
129+ * Instantiate a BigNumber from a JSON object
130+ * @param {Object} json a JSON object structured as:
131+ * `{"mathjs": "BigNumber", "value": "0.2"}`
132+ * @return {BigNumber}
133+ */
134+ BigNumber.fromJSON = function (json) {
135+ return new BigNumber(json.value);
136+ };
137+
138 // extend BigNumber with a function clone
139 if (typeof BigNumber.prototype.clone !== 'function') {
140 /**
141@@ -248,33 +270,39 @@
142 math.type.Complex = __webpack_require__(7);
143 math.type.Range = __webpack_require__(8);
144 math.type.Index = __webpack_require__(9);
145- math.type.Matrix = __webpack_require__(10);
146+ math.type.Matrix = __webpack_require__(10)(_config);
147 math.type.Unit = __webpack_require__(11);
148 math.type.Help = __webpack_require__(12);
149 math.type.ResultSet = __webpack_require__(13);
150 math.type.BigNumber = BigNumber;
151
152- math.collection = __webpack_require__(14);
153+ math.collection = __webpack_require__(14)(math, _config);
154+
155+ // matrix storage formats
156+ math.type.CcsMatrix = __webpack_require__(15)(math, _config);
157+ math.type.CrsMatrix = __webpack_require__(16)(math, _config);
158+ math.type.DenseMatrix = __webpack_require__(17)(math, _config);
159+
160+ // matrix storage format registry
161+ math.type.Matrix._storage.ccs = math.type.CcsMatrix;
162+ math.type.Matrix._storage.crs = math.type.CrsMatrix;
163+ math.type.Matrix._storage.dense = math.type.DenseMatrix;
164+ math.type.Matrix._storage['default'] = math.type.DenseMatrix;
165
166 // expression (parse, Parser, nodes, docs)
167 math.expression = {};
168- math.expression.node = __webpack_require__(15);
169- math.expression.parse = __webpack_require__(16);
170- math.expression.Parser = __webpack_require__(17);
171- math.expression.docs = __webpack_require__(18);
172+ math.expression.node = __webpack_require__(18);
173+ math.expression.parse = __webpack_require__(19)(math, _config);
174+ math.expression.Parser = __webpack_require__(20)(math, _config);
175+ math.expression.docs = __webpack_require__(21);
176
177 // serialization utilities
178 math.json = {
179- reviver: __webpack_require__(19)
180+ reviver: __webpack_require__(22)(math, _config)
181 };
182-
183- // expression parser
184- __webpack_require__(31)(math, _config);
185- __webpack_require__(32)(math, _config);
186- __webpack_require__(33)(math, _config);
187+
188+ // functions - construction (must be defined before the rest of functions)
189 __webpack_require__(34)(math, _config);
190-
191- // functions - arithmetic
192 __webpack_require__(35)(math, _config);
193 __webpack_require__(36)(math, _config);
194 __webpack_require__(37)(math, _config);
195@@ -284,10 +312,14 @@
196 __webpack_require__(41)(math, _config);
197 __webpack_require__(42)(math, _config);
198 __webpack_require__(43)(math, _config);
199+
200+ // expression parser
201 __webpack_require__(44)(math, _config);
202 __webpack_require__(45)(math, _config);
203 __webpack_require__(46)(math, _config);
204 __webpack_require__(47)(math, _config);
205+
206+ // functions - arithmetic
207 __webpack_require__(48)(math, _config);
208 __webpack_require__(49)(math, _config);
209 __webpack_require__(50)(math, _config);
210@@ -304,8 +336,6 @@
211 __webpack_require__(61)(math, _config);
212 __webpack_require__(62)(math, _config);
213 __webpack_require__(63)(math, _config);
214-
215- // functions - bitwise
216 __webpack_require__(64)(math, _config);
217 __webpack_require__(65)(math, _config);
218 __webpack_require__(66)(math, _config);
219@@ -313,16 +343,14 @@
220 __webpack_require__(68)(math, _config);
221 __webpack_require__(69)(math, _config);
222 __webpack_require__(70)(math, _config);
223-
224- // functions - complex
225 __webpack_require__(71)(math, _config);
226 __webpack_require__(72)(math, _config);
227 __webpack_require__(73)(math, _config);
228 __webpack_require__(74)(math, _config);
229-
230- // functions - construction
231 __webpack_require__(75)(math, _config);
232 __webpack_require__(76)(math, _config);
233+
234+ // functions - bitwise
235 __webpack_require__(77)(math, _config);
236 __webpack_require__(78)(math, _config);
237 __webpack_require__(79)(math, _config);
238@@ -330,18 +358,20 @@
239 __webpack_require__(81)(math, _config);
240 __webpack_require__(82)(math, _config);
241 __webpack_require__(83)(math, _config);
242+
243+ // functions - complex
244 __webpack_require__(84)(math, _config);
245-
246- // functions - logical
247 __webpack_require__(85)(math, _config);
248 __webpack_require__(86)(math, _config);
249 __webpack_require__(87)(math, _config);
250+
251+ // functions - logical
252 __webpack_require__(88)(math, _config);
253-
254- // functions - matrix
255 __webpack_require__(89)(math, _config);
256 __webpack_require__(90)(math, _config);
257 __webpack_require__(91)(math, _config);
258+
259+ // functions - matrix
260 __webpack_require__(92)(math, _config);
261 __webpack_require__(93)(math, _config);
262 __webpack_require__(94)(math, _config);
263@@ -356,41 +386,41 @@
264 __webpack_require__(103)(math, _config);
265 __webpack_require__(104)(math, _config);
266 __webpack_require__(105)(math, _config);
267-
268- // functions - probability
269- //require('./function/probability/distribution')(math, _config); // TODO: rethink math.distribution
270 __webpack_require__(106)(math, _config);
271 __webpack_require__(107)(math, _config);
272 __webpack_require__(108)(math, _config);
273+
274+ // functions - probability
275+ //require('./function/probability/distribution')(math, _config); // TODO: rethink math.distribution
276 __webpack_require__(109)(math, _config);
277 __webpack_require__(110)(math, _config);
278 __webpack_require__(111)(math, _config);
279 __webpack_require__(112)(math, _config);
280-
281- // functions - relational
282 __webpack_require__(113)(math, _config);
283 __webpack_require__(114)(math, _config);
284 __webpack_require__(115)(math, _config);
285+
286+ // functions - relational
287 __webpack_require__(116)(math, _config);
288 __webpack_require__(117)(math, _config);
289 __webpack_require__(118)(math, _config);
290 __webpack_require__(119)(math, _config);
291 __webpack_require__(120)(math, _config);
292-
293- // functions - statistics
294 __webpack_require__(121)(math, _config);
295 __webpack_require__(122)(math, _config);
296 __webpack_require__(123)(math, _config);
297+
298+ // functions - statistics
299 __webpack_require__(124)(math, _config);
300 __webpack_require__(125)(math, _config);
301 __webpack_require__(126)(math, _config);
302 __webpack_require__(127)(math, _config);
303 __webpack_require__(128)(math, _config);
304-
305- // functions - trigonometry
306 __webpack_require__(129)(math, _config);
307 __webpack_require__(130)(math, _config);
308 __webpack_require__(131)(math, _config);
309+
310+ // functions - trigonometry
311 __webpack_require__(132)(math, _config);
312 __webpack_require__(133)(math, _config);
313 __webpack_require__(134)(math, _config);
314@@ -413,20 +443,23 @@
315 __webpack_require__(151)(math, _config);
316 __webpack_require__(152)(math, _config);
317 __webpack_require__(153)(math, _config);
318-
319- // functions - units
320 __webpack_require__(154)(math, _config);
321-
322- // functions - utils
323 __webpack_require__(155)(math, _config);
324 __webpack_require__(156)(math, _config);
325+
326+ // functions - units
327 __webpack_require__(157)(math, _config);
328+
329+ // functions - utils
330 __webpack_require__(158)(math, _config);
331 __webpack_require__(159)(math, _config);
332 __webpack_require__(160)(math, _config);
333 __webpack_require__(161)(math, _config);
334 __webpack_require__(162)(math, _config);
335 __webpack_require__(163)(math, _config);
336+ __webpack_require__(164)(math, _config);
337+ __webpack_require__(165)(math, _config);
338+ __webpack_require__(166)(math, _config);
339
340 // TODO: deprecated since version 0.25.0, remove some day.
341 math.ifElse = function () {
342@@ -438,21 +471,21 @@
343
344 // attach transform functions (for converting one-based indices to zero-based)
345 math.expression.transform = {
346- concat: __webpack_require__(20)(math, _config),
347- filter: __webpack_require__(21)(math, _config),
348- forEach:__webpack_require__(22)(math, _config),
349- index: __webpack_require__(23)(math, _config),
350- map: __webpack_require__(24)(math, _config),
351- max: __webpack_require__(25)(math, _config),
352- mean: __webpack_require__(26)(math, _config),
353- min: __webpack_require__(27)(math, _config),
354- range: __webpack_require__(28)(math, _config),
355- subset: __webpack_require__(29)(math, _config)
356+ concat: __webpack_require__(23)(math, _config),
357+ filter: __webpack_require__(24)(math, _config),
358+ forEach:__webpack_require__(25)(math, _config),
359+ index: __webpack_require__(26)(math, _config),
360+ map: __webpack_require__(27)(math, _config),
361+ max: __webpack_require__(28)(math, _config),
362+ mean: __webpack_require__(29)(math, _config),
363+ min: __webpack_require__(30)(math, _config),
364+ range: __webpack_require__(31)(math, _config),
365+ subset: __webpack_require__(32)(math, _config)
366 };
367
368 // selector (we initialize after all functions are loaded)
369 math.chaining = {};
370- math.chaining.Chain = __webpack_require__(30)(math, _config);
371+ math.chaining.Chain = __webpack_require__(33)(math, _config);
372 math.chaining.Selector = math.chaining.Chain; // TODO: deprecate in v2.0
373
374 // apply provided configuration options
375@@ -684,6 +717,8 @@
376
377 'use strict';
378
379+ var NumberFormatter = __webpack_require__(167);
380+
381 /**
382 * Test whether value is a Number
383 * @param {*} value
384@@ -829,44 +864,15 @@
385 return exports.toExponential(value, precision);
386
387 case 'auto':
388- // determine lower and upper bound for exponential notation.
389- // TODO: implement support for upper and lower to be BigNumbers themselves
390- var lower = 1e-3;
391- var upper = 1e5;
392- if (options && options.exponential) {
393- if (options.exponential.lower !== undefined) {
394- lower = options.exponential.lower;
395- }
396- if (options.exponential.upper !== undefined) {
397- upper = options.exponential.upper;
398- }
399- }
400-
401- // handle special case zero
402- if (value === 0) return '0';
403-
404- // determine whether or not to output exponential notation
405- var str;
406- var abs = Math.abs(value);
407- if (abs >= lower && abs < upper) {
408- // normal number notation
409- // Note: IE7 does not allow value.toPrecision(undefined)
410- var valueStr = precision ?
411- value.toPrecision(Math.min(precision, 21)) :
412- value.toPrecision();
413- str = parseFloat(valueStr) + '';
414- }
415- else {
416- // exponential notation
417- str = exports.toExponential(value, precision);
418- }
419-
420- // remove trailing zeros after the decimal point
421- return str.replace(/((\.\d*?)(0+))($|e)/, function () {
422- var digits = arguments[2];
423- var e = arguments[4];
424- return (digits !== '.') ? digits + e : e;
425- });
426+ return exports
427+ .toPrecision(value, precision, options && options.exponential)
428+
429+ // remove trailing zeros after the decimal point
430+ .replace(/((\.\d*?)(0+))($|e)/, function () {
431+ var digits = arguments[2];
432+ var e = arguments[4];
433+ return (digits !== '.') ? digits + e : e;
434+ });
435
436 default:
437 throw new Error('Unknown notation "' + notation + '". ' +
438@@ -883,12 +889,7 @@
439 * @returns {string} str
440 */
441 exports.toExponential = function(value, precision) {
442- if (precision !== undefined) {
443- return value.toExponential(Math.min(precision - 1, 20));
444- }
445- else {
446- return value.toExponential();
447- }
448+ return new NumberFormatter(value).toExponential(precision);
449 };
450
451 /**
452@@ -898,7 +899,20 @@
453 * decimal point. Zero by default.
454 */
455 exports.toFixed = function(value, precision) {
456- return value.toFixed(Math.min(precision, 20));
457+ return new NumberFormatter(value).toFixed(precision);
458+ };
459+
460+ /**
461+ * Format a number with a certain precision
462+ * @param {Number} value
463+ * @param {Number} [precision=undefined] Optional number of digits.
464+ * @param {{lower: number, upper: number}} [options] By default:
465+ * lower = 1e-3 (excl)
466+ * upper = 1e+5 (incl)
467+ * @return {string}
468+ */
469+ exports.toPrecision = function(value, precision, options) {
470+ return new NumberFormatter(value).toPrecision(precision, options);
471 };
472
473 /**
474@@ -970,14 +984,14 @@
475
476 module.exports = function (math, config) {
477 var object = __webpack_require__(2);
478- var bignumber = __webpack_require__(164);
479+ var bignumber = __webpack_require__(168);
480 var Complex = __webpack_require__(7);
481 var BigNumber = math.type.BigNumber;
482
483 math['true'] = true;
484 math['false'] = false;
485 math['null'] = null;
486- math['uninitialized'] = __webpack_require__(165).UNINITIALIZED;
487+ math['uninitialized'] = __webpack_require__(169).UNINITIALIZED;
488
489 if (config.number === 'bignumber') {
490 math['Infinity'] = new BigNumber(Infinity);
491@@ -1022,7 +1036,7 @@
492 math.i = new Complex(0, 1);
493
494 // meta information
495- math.version = __webpack_require__(166);
496+ math.version = __webpack_require__(170);
497 };
498
499
500@@ -1030,33 +1044,10 @@
501 /* 5 */
502 /***/ function(module, exports, __webpack_require__) {
503
504- var BigNumber = __webpack_require__(336);
505+ var BigNumber = __webpack_require__(340);
506
507 // FIXME: replace all require('decimal.js') with require('./BigNumber').
508
509- /**
510- * Get a JSON representation of a BigNumber containing
511- * type information
512- * @returns {Object} Returns a JSON object structured as:
513- * `{"mathjs": "BigNumber", "value": "0.2"}`
514- */
515- BigNumber.prototype.toJSON = function () {
516- return {
517- mathjs: 'BigNumber',
518- value: this.toString()
519- };
520- };
521-
522- /**
523- * Instantiate a BigNumber from a JSON object
524- * @param {Object} json a JSON object structured as:
525- * `{"mathjs": "BigNumber", "value": "0.2"}`
526- * @return {BigNumber}
527- */
528- BigNumber.fromJSON = function (json) {
529- return new BigNumber(json.value);
530- };
531-
532 module.exports = BigNumber;
533
534
535@@ -1066,10 +1057,10 @@
536
537 'use strict';
538
539- exports.ArgumentsError = __webpack_require__(167);
540- exports.DimensionError = __webpack_require__(168);
541- exports.IndexError = __webpack_require__(169);
542- exports.UnsupportedTypeError = __webpack_require__(170);
543+ exports.ArgumentsError = __webpack_require__(171);
544+ exports.DimensionError = __webpack_require__(172);
545+ exports.IndexError = __webpack_require__(173);
546+ exports.UnsupportedTypeError = __webpack_require__(174);
547
548 // TODO: implement an InvalidValueError?
549
550@@ -1080,7 +1071,7 @@
551
552 'use strict';
553
554- var util = __webpack_require__(171),
555+ var util = __webpack_require__(175),
556 Unit = __webpack_require__(11),
557 number = util.number,
558
559@@ -1559,7 +1550,7 @@
560
561 'use strict';
562
563- var util = __webpack_require__(171);
564+ var util = __webpack_require__(175);
565
566 var number = util.number;
567 var string = util.string;
568@@ -1858,7 +1849,7 @@
569
570 'use strict';
571
572- var util = __webpack_require__(171),
573+ var util = __webpack_require__(175),
574
575 Range = __webpack_require__(8),
576
577@@ -2155,542 +2146,268 @@
578
579 'use strict';
580
581- var util = __webpack_require__(171);
582- var DimensionError = __webpack_require__(168);
583-
584- var Index = __webpack_require__(9);
585-
586- var number = util.number;
587- var string = util.string;
588- var array = util.array;
589- var object = util.object;
590-
591- var isArray = Array.isArray;
592- var validateIndex = array.validateIndex;
593-
594- /**
595- * @constructor Matrix
596- *
597- * A Matrix is a wrapper around an Array. A matrix can hold a multi dimensional
598- * array. A matrix can be constructed as:
599- * var matrix = new Matrix(data)
600- *
601- * Matrix contains the functions to resize, get and set values, get the size,
602- * clone the matrix and to convert the matrix to a vector, array, or scalar.
603- * Furthermore, one can iterate over the matrix using map and forEach.
604- * The internal Array of the Matrix can be accessed using the function valueOf.
605- *
606- * Example usage:
607- * var matrix = new Matrix([[1, 2], [3, 4]);
608- * matix.size(); // [2, 2]
609- * matrix.resize([3, 2], 5);
610- * matrix.valueOf(); // [[1, 2], [3, 4], [5, 5]]
611- * matrix.subset([1,2]) // 3 (indexes are zero-based)
612- *
613- * @param {Array | Matrix} [data] A multi dimensional array
614- */
615- function Matrix(data) {
616- if (!(this instanceof Matrix)) {
617- throw new SyntaxError('Constructor must be called with the new operator');
618- }
619-
620- if (data instanceof Matrix) {
621- // clone data from a Matrix
622- this._data = data.clone()._data;
623- }
624- else if (isArray(data)) {
625- // use array
626- // replace nested Matrices with Arrays
627- this._data = preprocess(data);
628- }
629- else if (data != null) {
630- // unsupported type
631- throw new TypeError('Unsupported type of data (' + util.types.type(data) + ')');
632- }
633- else {
634- // nothing provided
635- this._data = [];
636- }
637-
638- // verify the size of the array
639- this._size = array.size(this._data);
640- }
641-
642- /**
643- * Test whether an object is a Matrix
644- * @param {*} object
645- * @return {Boolean} isMatrix
646- */
647- Matrix.isMatrix = function (object) {
648- return (object instanceof Matrix);
649- };
650-
651- /**
652- * Get a subset of the matrix, or replace a subset of the matrix.
653- *
654- * Usage:
655- * var subset = matrix.subset(index) // retrieve subset
656- * var value = matrix.subset(index, replacement) // replace subset
657- *
658- * @param {Index} index
659- * @param {Array | Matrix | *} [replacement]
660- * @param {*} [defaultValue=0] Default value, filled in on new entries when
661- * the matrix is resized. If not provided,
662- * new matrix elements will be filled with zeros.
663- */
664- Matrix.prototype.subset = function (index, replacement, defaultValue) {
665- switch (arguments.length) {
666- case 1:
667- return _get(this, index);
668-
669- // intentional fall through
670- case 2:
671- case 3:
672- return _set(this, index, replacement, defaultValue);
673-
674- default:
675- throw new SyntaxError('Wrong number of arguments');
676- }
677- };
678-
679- /**
680- * Get a single element from the matrix.
681- * @param {Number[]} index Zero-based index
682- * @return {*} value
683- */
684- Matrix.prototype.get = function (index) {
685- if (!isArray(index)) {
686- throw new TypeError('Array expected');
687- }
688- if (index.length != this._size.length) {
689- throw new DimensionError(index.length, this._size.length);
690- }
691-
692- var data = this._data;
693- for (var i = 0, ii = index.length; i < ii; i++) {
694- var index_i = index[i];
695- validateIndex(index_i, data.length);
696- data = data[index_i];
697- }
698-
699- return object.clone(data);
700- };
701-
702- /**
703- * Replace a single element in the matrix.
704- * @param {Number[]} index Zero-based index
705- * @param {*} value
706- * @param {*} [defaultValue] Default value, filled in on new entries when
707- * the matrix is resized. If not provided,
708- * new matrix elements will be left undefined.
709- * @return {Matrix} self
710- */
711- Matrix.prototype.set = function (index, value, defaultValue) {
712- var i, ii;
713-
714- // validate input type and dimensions
715- if (!isArray(index)) {
716- throw new Error('Array expected');
717- }
718- if (index.length < this._size.length) {
719- throw new DimensionError(index.length, this._size.length, '<');
720- }
721-
722- // enlarge matrix when needed
723- var size = index.map(function (i) {
724- return i + 1;
725- });
726- _fit(this, size, defaultValue);
727-
728- // traverse over the dimensions
729- var data = this._data;
730- for (i = 0, ii = index.length - 1; i < ii; i++) {
731- var index_i = index[i];
732- validateIndex(index_i, data.length);
733- data = data[index_i];
734- }
735-
736- // set new value
737- index_i = index[index.length - 1];
738- validateIndex(index_i, data.length);
739- data[index_i] = value;
740-
741- return this;
742- };
743-
744- /**
745- * Get a submatrix of this matrix
746- * @param {Matrix} matrix
747- * @param {Index} index Zero-based index
748- * @private
749- */
750- function _get (matrix, index) {
751- if (!(index instanceof Index)) {
752- throw new TypeError('Invalid index');
753- }
754-
755- var isScalar = index.isScalar();
756- if (isScalar) {
757- // return a scalar
758- return matrix.get(index.min());
759- }
760- else {
761- // validate dimensions
762- var size = index.size();
763- if (size.length != matrix._size.length) {
764- throw new DimensionError(size.length, matrix._size.length);
765- }
766-
767- // validate if any of the ranges in the index is out of range
768- var min = index.min();
769- var max = index.max();
770- for (var i = 0, ii = matrix._size.length; i < ii; i++) {
771- validateIndex(min[i], matrix._size[i]);
772- validateIndex(max[i], matrix._size[i]);
773- }
774-
775- // retrieve submatrix
776- // TODO: more efficient when creating an empty matrix and setting _data and _size manually
777- return new Matrix(_getSubmatrix(matrix._data, index, size.length, 0));
778- }
779- }
780-
781- /**
782- * Recursively get a submatrix of a multi dimensional matrix.
783- * Index is not checked for correct number or length of dimensions.
784- * @param {Array} data
785- * @param {Index} index
786- * @param {number} dims Total number of dimensions
787- * @param {number} dim Current dimension
788- * @return {Array} submatrix
789- * @private
790- */
791- function _getSubmatrix (data, index, dims, dim) {
792- var last = (dim == dims - 1);
793- var range = index.range(dim);
794-
795- if (last) {
796- return range.map(function (i) {
797- return data[i];
798- });
799- }
800- else {
801- return range.map(function (i) {
802- var child = data[i];
803- return _getSubmatrix(child, index, dims, dim + 1);
804- });
805- }
806- }
807-
808- /**
809- * Replace a submatrix in this matrix
810- * Indexes are zero-based.
811- * @param {Matrix} matrix
812- * @param {Index} index
813- * @param {Matrix | Array | *} submatrix
814- * @param {*} defaultValue Default value, filled in on new entries when
815- * the matrix is resized.
816- * @return {Matrix} matrix
817- * @private
818- */
819- function _set (matrix, index, submatrix, defaultValue) {
820- if (!(index instanceof Index)) {
821- throw new TypeError('Invalid index');
822- }
823-
824- // get index size and check whether the index contains a single value
825- var iSize = index.size(),
826- isScalar = index.isScalar();
827-
828- // calculate the size of the submatrix, and convert it into an Array if needed
829- var sSize;
830- if (submatrix instanceof Matrix) {
831- sSize = submatrix.size();
832- submatrix = submatrix.valueOf();
833- }
834- else {
835- sSize = array.size(submatrix);
836- }
837-
838- if (isScalar) {
839- // set a scalar
840-
841- // check whether submatrix is a scalar
842- if (sSize.length != 0) {
843- throw new TypeError('Scalar expected');
844- }
845-
846- matrix.set(index.min(), submatrix, defaultValue);
847- }
848- else {
849- // set a submatrix
850-
851- // validate dimensions
852- if (iSize.length < matrix._size.length) {
853- throw new DimensionError(iSize.length, matrix._size.length, '<');
854- }
855-
856- if (sSize.length < iSize.length) {
857- // calculate number of missing outer dimensions
858- var i = 0;
859- var outer = 0;
860- while (iSize[i] === 1 && sSize[i] === 1) {
861- i++;
862- }
863- while (iSize[i] === 1) {
864- outer++;
865- i++;
866- }
867-
868- // unsqueeze both outer and inner dimensions
869- submatrix = array.unsqueeze(submatrix, iSize.length, outer, sSize);
870- }
871-
872- // check whether the size of the submatrix matches the index size
873- if (!object.deepEqual(iSize, sSize)) {
874- throw new DimensionError(iSize, sSize, '>');
875- }
876-
877- // enlarge matrix when needed
878- var size = index.max().map(function (i) {
879- return i + 1;
880- });
881- _fit(matrix, size, defaultValue);
882-
883- // insert the sub matrix
884- var dims = iSize.length,
885- dim = 0;
886- _setSubmatrix (matrix._data, index, submatrix, dims, dim);
887- }
888-
889- return matrix;
890- }
891-
892- /**
893- * Replace a submatrix of a multi dimensional matrix.
894- * @param {Array} data
895- * @param {Index} index
896- * @param {Array} submatrix
897- * @param {number} dims Total number of dimensions
898- * @param {number} dim
899- * @private
900- */
901- function _setSubmatrix (data, index, submatrix, dims, dim) {
902- var last = (dim == dims - 1),
903- range = index.range(dim);
904-
905- if (last) {
906- range.forEach(function (dataIndex, subIndex) {
907- validateIndex(dataIndex);
908- data[dataIndex] = submatrix[subIndex];
909- });
910- }
911- else {
912- range.forEach(function (dataIndex, subIndex) {
913- validateIndex(dataIndex);
914- _setSubmatrix(data[dataIndex], index, submatrix[subIndex], dims, dim + 1);
915- });
916- }
917- }
918-
919- /**
920- * Resize the matrix
921- * @param {Number[]} size
922- * @param {*} [defaultValue=0] Default value, filled in on new entries.
923- * If not provided, the matrix elements will
924- * be filled with zeros.
925- * @return {Matrix} self The matrix itself is returned
926- */
927- Matrix.prototype.resize = function (size, defaultValue) {
928- this._size = object.clone(size);
929- this._data = array.resize(this._data, this._size, defaultValue);
930-
931- // return the matrix itself
932- return this;
933- };
934-
935- /**
936- * Enlarge the matrix when it is smaller than given size.
937- * If the matrix is larger or equal sized, nothing is done.
938- * @param {Matrix} matrix The matrix to be resized
939- * @param {Number[]} size
940- * @param {*} defaultValue Default value, filled in on new entries.
941- * @private
942- */
943- function _fit(matrix, size, defaultValue) {
944- var newSize = object.clone(matrix._size),
945- changed = false;
946-
947- // add dimensions when needed
948- while (newSize.length < size.length) {
949- newSize.push(0);
950- changed = true;
951- }
952-
953- // enlarge size when needed
954- for (var i = 0, ii = size.length; i < ii; i++) {
955- if (size[i] > newSize[i]) {
956- newSize[i] = size[i];
957- changed = true;
958- }
959- }
960-
961- if (changed) {
962- // resize only when size is changed
963- matrix.resize(newSize, defaultValue);
964- }
965- }
966-
967- /**
968- * Create a clone of the matrix
969- * @return {Matrix} clone
970- */
971- Matrix.prototype.clone = function () {
972- var matrix = new Matrix();
973- matrix._data = object.clone(this._data);
974- matrix._size = object.clone(this._size);
975- return matrix;
976- };
977-
978- /**
979- * Retrieve the size of the matrix.
980- * @returns {Number[]} size
981- */
982- Matrix.prototype.size = function() {
983- return this._size;
984- };
985-
986- /**
987- * Create a new matrix with the results of the callback function executed on
988- * each entry of the matrix.
989- * @param {function} callback The callback function is invoked with three
990- * parameters: the value of the element, the index
991- * of the element, and the Matrix being traversed.
992- * @return {Matrix} matrix
993- */
994- Matrix.prototype.map = function (callback) {
995- var me = this;
996- var matrix = new Matrix();
997-
998- var recurse = function (value, index) {
999- if (isArray(value)) {
1000- return value.map(function (child, i) {
1001- return recurse(child, index.concat(i));
1002- });
1003- }
1004- else {
1005- return callback(value, index, me);
1006- }
1007- };
1008- matrix._data = recurse(this._data, []);
1009- matrix._size = object.clone(this._size);
1010-
1011- return matrix;
1012- };
1013-
1014- /**
1015- * Execute a callback function on each entry of the matrix.
1016- * @param {function} callback The callback function is invoked with three
1017- * parameters: the value of the element, the index
1018- * of the element, and the Matrix being traversed.
1019- */
1020- Matrix.prototype.forEach = function (callback) {
1021- var me = this;
1022-
1023- var recurse = function (value, index) {
1024- if (isArray(value)) {
1025- value.forEach(function (child, i) {
1026- recurse(child, index.concat(i));
1027- });
1028- }
1029- else {
1030- callback(value, index, me);
1031- }
1032- };
1033- recurse(this._data, []);
1034- };
1035-
1036- /**
1037- * Create an Array with a copy of the data of the Matrix
1038- * @returns {Array} array
1039- */
1040- Matrix.prototype.toArray = function () {
1041- return object.clone(this._data);
1042- };
1043-
1044- /**
1045- * Get the primitive value of the Matrix: a multidimensional array
1046- * @returns {Array} array
1047- */
1048- Matrix.prototype.valueOf = function () {
1049- return this._data;
1050- };
1051-
1052- /**
1053- * Get a string representation of the matrix, with optional formatting options.
1054- * @param {Object | Number | Function} [options] Formatting options. See
1055- * lib/util/number:format for a
1056- * description of the available
1057- * options.
1058- * @returns {String} str
1059- */
1060- Matrix.prototype.format = function (options) {
1061- return string.format(this._data, options);
1062- };
1063-
1064- /**
1065- * Get a string representation of the matrix
1066- * @returns {String} str
1067- */
1068- Matrix.prototype.toString = function () {
1069- return string.format(this._data);
1070- };
1071-
1072- /**
1073- * Get a JSON representation of the matrix
1074- * @returns {Object}
1075- */
1076- Matrix.prototype.toJSON = function () {
1077- return {
1078- mathjs: 'Matrix',
1079- data: this._data
1080- }
1081- };
1082-
1083- /**
1084- * Generate a matrix from a JSON object
1085- * @param {Object} json An object structured like
1086- * `{"mathjs": "Matrix", data: []}`,
1087- * where mathjs is optional
1088- * @returns {Matrix}
1089- */
1090- Matrix.fromJSON = function (json) {
1091- return new Matrix(json.data);
1092- };
1093-
1094- /**
1095- * Preprocess data, which can be an Array or Matrix with nested Arrays and
1096- * Matrices. Replaces all nested Matrices with Arrays
1097- * @param {Array} data
1098- * @return {Array} data
1099- */
1100- function preprocess(data) {
1101- for (var i = 0, ii = data.length; i < ii; i++) {
1102- var elem = data[i];
1103- if (isArray(elem)) {
1104- data[i] = preprocess(elem);
1105- }
1106- else if (elem instanceof Matrix) {
1107- data[i] = preprocess(elem._data);
1108- }
1109- }
1110-
1111- return data;
1112- }
1113-
1114- // exports
1115- module.exports = Matrix;
1116-
1117+ var string = __webpack_require__(176),
1118+
1119+ isString = string.isString;
1120+
1121+ module.exports = function (config) {
1122+
1123+ /**
1124+ * @constructor Matrix
1125+ *
1126+ * A Matrix is a wrapper around an Array. A matrix can hold a multi dimensional
1127+ * array. A matrix can be constructed as:
1128+ * var matrix = math.matrix(data)
1129+ *
1130+ * Matrix contains the functions to resize, get and set values, get the size,
1131+ * clone the matrix and to convert the matrix to a vector, array, or scalar.
1132+ * Furthermore, one can iterate over the matrix using map and forEach.
1133+ * The internal Array of the Matrix can be accessed using the function valueOf.
1134+ *
1135+ * Example usage:
1136+ * var matrix = math.matrix([[1, 2], [3, 4]]);
1137+ * matix.size(); // [2, 2]
1138+ * matrix.resize([3, 2], 5);
1139+ * matrix.valueOf(); // [[1, 2], [3, 4], [5, 5]]
1140+ * matrix.subset([1,2]) // 3 (indexes are zero-based)
1141+ *
1142+ */
1143+ function Matrix() {
1144+ if (!(this instanceof Matrix)) {
1145+ throw new SyntaxError('Constructor must be called with the new operator');
1146+ }
1147+ }
1148+
1149+ /**
1150+ * Test whether an object is a Matrix
1151+ * @param {*} object
1152+ * @return {Boolean} isMatrix
1153+ */
1154+ Matrix.isMatrix = function (object) {
1155+ return (object instanceof Matrix);
1156+ };
1157+
1158+ /**
1159+ * Get the Matrix storage constructor for the given format.
1160+ *
1161+ * @param {string} format The Matrix storage format.
1162+ *
1163+ * @return {Function} The Matrix storage constructor.
1164+ */
1165+ Matrix.storage = function (format) {
1166+ // check storage format is a string
1167+ if (!isString(format)) {
1168+ throw new TypeError('format must be a string value');
1169+ }
1170+
1171+ // get storage format constructor
1172+ var constructor = Matrix._storage[format];
1173+ if (!constructor) {
1174+ throw new SyntaxError('Unsupported matrix storage format: ' + format);
1175+ }
1176+
1177+ // return storage constructor
1178+ return constructor;
1179+ };
1180+
1181+ // a map with all constructors for all storage types
1182+ Matrix._storage = {};
1183+
1184+ /**
1185+ * Get the storage format used by the matrix.
1186+ *
1187+ * Usage:
1188+ * var format = matrix.storage() // retrieve storage format
1189+ *
1190+ * @return {string} The storage format.
1191+ */
1192+ Matrix.prototype.storage = function () {
1193+ // must be implemented by each of the Matrix implementations
1194+ throw new Error('Cannot invoke storage on a Matrix interface');
1195+ };
1196+
1197+ /**
1198+ * Get a subset of the matrix, or replace a subset of the matrix.
1199+ *
1200+ * Usage:
1201+ * var subset = matrix.subset(index) // retrieve subset
1202+ * var value = matrix.subset(index, replacement) // replace subset
1203+ *
1204+ * @param {Index} index
1205+ * @param {Array | Matrix | *} [replacement]
1206+ * @param {*} [defaultValue=0] Default value, filled in on new entries when
1207+ * the matrix is resized. If not provided,
1208+ * new matrix elements will be filled with zeros.
1209+ */
1210+ Matrix.prototype.subset = function (index, replacement, defaultValue) {
1211+ // must be implemented by each of the Matrix implementations
1212+ throw new Error('Cannot invoke subset on a Matrix interface');
1213+ };
1214+
1215+ /**
1216+ * Get a single element from the matrix.
1217+ * @param {Number[]} index Zero-based index
1218+ * @return {*} value
1219+ */
1220+ Matrix.prototype.get = function (index) {
1221+ // must be implemented by each of the Matrix implementations
1222+ throw new Error('Cannot invoke get on a Matrix interface');
1223+ };
1224+
1225+ /**
1226+ * Replace a single element in the matrix.
1227+ * @param {Number[]} index Zero-based index
1228+ * @param {*} value
1229+ * @param {*} [defaultValue] Default value, filled in on new entries when
1230+ * the matrix is resized. If not provided,
1231+ * new matrix elements will be left undefined.
1232+ * @return {Matrix} self
1233+ */
1234+ Matrix.prototype.set = function (index, value, defaultValue) {
1235+ // must be implemented by each of the Matrix implementations
1236+ throw new Error('Cannot invoke set on a Matrix interface');
1237+ };
1238+
1239+ /**
1240+ * Resize the matrix to the given size. Returns a copy of the matrix when
1241+ * `copy=true`, otherwise return the matrix itself (resize in place).
1242+ *
1243+ * @param {Number[]} size The new size the matrix should have.
1244+ * @param {*} [defaultValue=0] Default value, filled in on new entries.
1245+ * If not provided, the matrix elements will
1246+ * be filled with zeros.
1247+ * @param {boolean} [copy] Return a resized copy of the matrix
1248+ *
1249+ * @return {Matrix} The resized matrix
1250+ */
1251+ Matrix.prototype.resize = function (size, defaultValue) {
1252+ // must be implemented by each of the Matrix implementations
1253+ throw new Error('Cannot invoke resize on a Matrix interface');
1254+ };
1255+
1256+ /**
1257+ * Create a clone of the matrix
1258+ * @return {Matrix} clone
1259+ */
1260+ Matrix.prototype.clone = function () {
1261+ // must be implemented by each of the Matrix implementations
1262+ throw new Error('Cannot invoke clone on a Matrix interface');
1263+ };
1264+
1265+ /**
1266+ * Retrieve the size of the matrix.
1267+ * @returns {Number[]} size
1268+ */
1269+ Matrix.prototype.size = function() {
1270+ // must be implemented by each of the Matrix implementations
1271+ throw new Error('Cannot invoke size on a Matrix interface');
1272+ };
1273+
1274+ /**
1275+ * Create a new matrix with the results of the callback function executed on
1276+ * each entry of the matrix.
1277+ * @param {function} callback The callback function is invoked with three
1278+ * parameters: the value of the element, the index
1279+ * of the element, and the Matrix being traversed.
1280+ * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
1281+ *
1282+ * @return {Matrix} matrix
1283+ */
1284+ Matrix.prototype.map = function (callback, skipZeros) {
1285+ // must be implemented by each of the Matrix implementations
1286+ throw new Error('Cannot invoke map on a Matrix interface');
1287+ };
1288+
1289+ /**
1290+ * Execute a callback function on each entry of the matrix.
1291+ * @param {function} callback The callback function is invoked with three
1292+ * parameters: the value of the element, the index
1293+ * of the element, and the Matrix being traversed.
1294+ */
1295+ Matrix.prototype.forEach = function (callback) {
1296+ // must be implemented by each of the Matrix implementations
1297+ throw new Error('Cannot invoke forEach on a Matrix interface');
1298+ };
1299+
1300+ /**
1301+ * Create an Array with a copy of the data of the Matrix
1302+ * @returns {Array} array
1303+ */
1304+ Matrix.prototype.toArray = function () {
1305+ // must be implemented by each of the Matrix implementations
1306+ throw new Error('Cannot invoke toArray on a Matrix interface');
1307+ };
1308+
1309+ /**
1310+ * Get the primitive value of the Matrix: a multidimensional array
1311+ * @returns {Array} array
1312+ */
1313+ Matrix.prototype.valueOf = function () {
1314+ // must be implemented by each of the Matrix implementations
1315+ throw new Error('Cannot invoke valueOf on a Matrix interface');
1316+ };
1317+
1318+ /**
1319+ * Get a string representation of the matrix, with optional formatting options.
1320+ * @param {Object | Number | Function} [options] Formatting options. See
1321+ * lib/util/number:format for a
1322+ * description of the available
1323+ * options.
1324+ * @returns {String} str
1325+ */
1326+ Matrix.prototype.format = function (options) {
1327+ // must be implemented by each of the Matrix implementations
1328+ throw new Error('Cannot invoke format on a Matrix interface');
1329+ };
1330+
1331+ /**
1332+ * Get a string representation of the matrix
1333+ * @returns {String} str
1334+ */
1335+ Matrix.prototype.toString = function () {
1336+ // must be implemented by each of the Matrix implementations
1337+ throw new Error('Cannot invoke toString on a Matrix interface');
1338+ };
1339+
1340+ /**
1341+ * Calculates the transpose of the matrix
1342+ * @returns {Matrix}
1343+ */
1344+ Matrix.prototype.transpose = function () {
1345+ // must be implemented by each of the Matrix implementations
1346+ throw new Error('Cannot invoke transpose on a Matrix interface');
1347+ };
1348+
1349+ /**
1350+ * Calculate the trace of a matrix: the sum of the elements on the main
1351+ * diagonal of a square matrix.
1352+ *
1353+ * See also:
1354+ *
1355+ * diagonal
1356+ *
1357+ * @returns {Number} The matrix trace
1358+ */
1359+ Matrix.prototype.trace = function () {
1360+ // must be implemented by each of the Matrix implementations
1361+ throw new Error('Cannot invoke transpose on a Matrix interface');
1362+ };
1363+
1364+ /**
1365+ * Multiply the matrix values times the argument.
1366+ *
1367+ * @param {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} Value to multiply.
1368+ *
1369+ * @return {Number | BigNumber | Complex | Unit | Matrix}
1370+ */
1371+ Matrix.prototype.multiply = function (value) {
1372+ // must be implemented by each of the Matrix implementations
1373+ throw new Error('Cannot invoke multiply on a Matrix interface');
1374+ };
1375+
1376+ // exports
1377+ return Matrix;
1378+ };
1379
1380 /***/ },
1381 /* 11 */
1382@@ -2698,7 +2415,7 @@
1383
1384 'use strict';
1385
1386- var util = __webpack_require__(171),
1387+ var util = __webpack_require__(175),
1388
1389 number = util.number,
1390 string = util.string,
1391@@ -3293,14 +3010,14 @@
1392 },
1393 BINARY_SHORT: {
1394 '': {name: '', value: 1, scientific: true},
1395- 'k': {name: 'k', value: 1024, scientific: true},
1396- 'M': {name: 'M', value: Math.pow(1024, 2), scientific: true},
1397- 'G': {name: 'G', value: Math.pow(1024, 3), scientific: true},
1398- 'T': {name: 'T', value: Math.pow(1024, 4), scientific: true},
1399- 'P': {name: 'P', value: Math.pow(1024, 5), scientific: true},
1400- 'E': {name: 'E', value: Math.pow(1024, 6), scientific: true},
1401- 'Z': {name: 'Z', value: Math.pow(1024, 7), scientific: true},
1402- 'Y': {name: 'Y', value: Math.pow(1024, 8), scientific: true},
1403+ 'k': {name: 'k', value: 1e3, scientific: true},
1404+ 'M': {name: 'M', value: 1e6, scientific: true},
1405+ 'G': {name: 'G', value: 1e9, scientific: true},
1406+ 'T': {name: 'T', value: 1e12, scientific: true},
1407+ 'P': {name: 'P', value: 1e15, scientific: true},
1408+ 'E': {name: 'E', value: 1e18, scientific: true},
1409+ 'Z': {name: 'Z', value: 1e21, scientific: true},
1410+ 'Y': {name: 'Y', value: 1e24, scientific: true},
1411
1412 'Ki': {name: 'Ki', value: 1024, scientific: true},
1413 'Mi': {name: 'Mi', value: Math.pow(1024, 2), scientific: true},
1414@@ -3313,21 +3030,21 @@
1415 },
1416 BINARY_LONG: {
1417 '': {name: '', value: 1, scientific: true},
1418- 'kilo': {name: 'kilo', value: 1024, scientific: true},
1419- 'mega': {name: 'mega', value: Math.pow(1024, 2), scientific: true},
1420- 'giga': {name: 'giga', value: Math.pow(1024, 3), scientific: true},
1421- 'tera': {name: 'tera', value: Math.pow(1024, 4), scientific: true},
1422- 'peta': {name: 'peta', value: Math.pow(1024, 5), scientific: true},
1423- 'exa': {name: 'exa', value: Math.pow(1024, 6), scientific: true},
1424- 'zetta': {name: 'zetta', value: Math.pow(1024, 7), scientific: true},
1425- 'yotta': {name: 'yotta', value: Math.pow(1024, 8), scientific: true},
1426+ 'kilo': {name: 'kilo', value: 1e3, scientific: true},
1427+ 'mega': {name: 'mega', value: 1e6, scientific: true},
1428+ 'giga': {name: 'giga', value: 1e9, scientific: true},
1429+ 'tera': {name: 'tera', value: 1e12, scientific: true},
1430+ 'peta': {name: 'peta', value: 1e15, scientific: true},
1431+ 'exa': {name: 'exa', value: 1e18, scientific: true},
1432+ 'zetta': {name: 'zetta', value: 1e21, scientific: true},
1433+ 'yotta': {name: 'yotta', value: 1e24, scientific: true},
1434
1435 'kibi': {name: 'kibi', value: 1024, scientific: true},
1436 'mebi': {name: 'mebi', value: Math.pow(1024, 2), scientific: true},
1437 'gibi': {name: 'gibi', value: Math.pow(1024, 3), scientific: true},
1438 'tebi': {name: 'tebi', value: Math.pow(1024, 4), scientific: true},
1439 'pebi': {name: 'pebi', value: Math.pow(1024, 5), scientific: true},
1440- 'exi': {name: 'exi', value: Math.pow(1024, 6), scientific: true},
1441+ 'exi': {name: 'exi', value: Math.pow(1024, 6), scientific: true},
1442 'zebi': {name: 'zebi', value: Math.pow(1024, 7), scientific: true},
1443 'yobi': {name: 'yobi', value: Math.pow(1024, 8), scientific: true}
1444 }
1445@@ -3442,6 +3159,7 @@
1446 poundmass: {name: 'poundmass', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 453.59237e-3, offset: 0},
1447 hundredweight: {name: 'hundredweight', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 45.359237, offset: 0},
1448 stick: {name: 'stick', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 115e-3, offset: 0},
1449+ stone: {name: 'stone', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 6350, offset: 0},
1450
1451 gr: {name: 'gr', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 64.79891e-6, offset: 0},
1452 dr: {name: 'dr', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 1.7718451953125e-3, offset: 0},
1453@@ -3473,9 +3191,9 @@
1454 ampere: {name: 'ampere', base: BASE_UNITS.CURRENT, prefixes: PREFIXES.LONG, value: 1, offset: 0},
1455
1456 // Temperature
1457- // K(C) = °C + 273.15
1458- // K(F) = (°F + 459.67) / 1.8
1459- // K(R) = °R / 1.8
1460+ // K(C) = °C + 273.15
1461+ // K(F) = (°F + 459.67) / 1.8
1462+ // K(R) = °R / 1.8
1463 K: {name: 'K', base: BASE_UNITS.TEMPERATURE, prefixes: PREFIXES.NONE, value: 1, offset: 0},
1464 degC: {name: 'degC', base: BASE_UNITS.TEMPERATURE, prefixes: PREFIXES.NONE, value: 1, offset: 273.15},
1465 degF: {name: 'degF', base: BASE_UNITS.TEMPERATURE, prefixes: PREFIXES.NONE, value: 1/1.8, offset: 459.67},
1466@@ -3596,7 +3314,7 @@
1467
1468 'use strict';
1469
1470- var util = __webpack_require__(171);
1471+ var util = __webpack_require__(175);
1472 var object = util.object;
1473 var string = util.string;
1474
1475@@ -3790,265 +3508,272 @@
1476 // utility methods for arrays and matrices
1477 'use strict';
1478
1479- var util = __webpack_require__(171),
1480-
1481- IndexError = __webpack_require__(169),
1482- DimensionError = __webpack_require__(168),
1483-
1484- Matrix = __webpack_require__(10),
1485+ var util = __webpack_require__(175),
1486+
1487+ IndexError = __webpack_require__(173),
1488+ DimensionError = __webpack_require__(172),
1489
1490 array = util.array,
1491- isArray = util.array.isArray,
1492- isString = util.string.isString;
1493-
1494- /**
1495- * Convert function arguments to an array. Arguments can have the following
1496- * signature:
1497- * fn()
1498- * fn(n)
1499- * fn(m, n, p, ...)
1500- * fn([m, n, p, ...])
1501- * @param {...Number | Array | Matrix} args
1502- * @returns {Array} array
1503- */
1504- exports.argsToArray = function(args) {
1505- if (args.length == 0) {
1506- // fn()
1507- return [];
1508- }
1509- else if (args.length == 1) {
1510- // fn(n)
1511- // fn([m, n, p, ...])
1512- var array = args[0];
1513+ isArray = util.array.isArray;
1514+
1515+ module.exports = function (math) {
1516+
1517+ var Matrix = math.type.Matrix;
1518+
1519+ var collection = {};
1520+
1521+ /**
1522+ * Convert function arguments to an array. Arguments can have the following
1523+ * signature:
1524+ * fn()
1525+ * fn(n)
1526+ * fn(m, n, p, ...)
1527+ * fn([m, n, p, ...])
1528+ * @param {...Number | Array | Matrix} args
1529+ * @returns {Array} array
1530+ */
1531+ collection.argsToArray = function(args) {
1532+ if (args.length === 0) {
1533+ // fn()
1534+ return [];
1535+ }
1536+ else if (args.length == 1) {
1537+ // fn(n)
1538+ // fn([m, n, p, ...])
1539+ var array = args[0];
1540+ if (array instanceof Matrix) {
1541+ array = array.valueOf();
1542+ }
1543+ if (!isArray(array)) {
1544+ array = [array];
1545+ }
1546+ return array;
1547+ }
1548+ else {
1549+ // fn(m, n, p, ...)
1550+ return util.array.argsToArray(args);
1551+ }
1552+ };
1553+
1554+
1555+ /**
1556+ * Test whether a value is a collection: an Array or Matrix
1557+ * @param {*} x
1558+ * @returns {boolean} isCollection
1559+ */
1560+ collection.isCollection = function(x) {
1561+ return (isArray(x) || (x instanceof Matrix));
1562+ };
1563+
1564+ /**
1565+ * Execute the callback function element wise for each element in array and any
1566+ * nested array
1567+ * Returns an array with the results
1568+ * @param {Array | Matrix} array
1569+ * @param {function} callback The callback is called with two parameters:
1570+ * value1 and value2, which contain the current
1571+ * element of both arrays.
1572+ * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
1573+ *
1574+ * @return {Array | Matrix} res
1575+ */
1576+ collection.deepMap = function deepMap(array, callback, skipZeros) {
1577+ if (array && (typeof array.map === 'function')) {
1578+ return array.map(function (x) {
1579+ return deepMap(x, callback, skipZeros);
1580+ });
1581+ }
1582+ else {
1583+ return callback(array);
1584+ }
1585+ };
1586+
1587+ /**
1588+ * Execute the callback function element wise for each entry in two given arrays,
1589+ * and for any nested array. Objects can also be scalar objects.
1590+ * Returns an array with the results.
1591+ * @param {Array | Matrix | Object} array1
1592+ * @param {Array | Matrix | Object} array2
1593+ * @param {function} callback The callback is called with two parameters:
1594+ * value1 and value2, which contain the current
1595+ * element of both arrays.
1596+ * @return {Array | Matrix} res
1597+ */
1598+ collection.deepMap2 = function deepMap2(array1, array2, callback) {
1599+ var res, len, i;
1600+
1601+ if (isArray(array1)) {
1602+ if (isArray(array2)) {
1603+ // callback(array, array)
1604+ if (array1.length != array2.length) {
1605+ throw new DimensionError(array1.length, array2.length);
1606+ }
1607+
1608+ res = [];
1609+ len = array1.length;
1610+ for (i = 0; i < len; i++) {
1611+ res[i] = deepMap2(array1[i], array2[i], callback);
1612+ }
1613+ }
1614+ else if (array2 instanceof Matrix) {
1615+ // callback(array, matrix)
1616+ res = deepMap2(array1, array2.valueOf(), callback);
1617+ return math.matrix(res);
1618+ }
1619+ else {
1620+ // callback(array, object)
1621+ res = [];
1622+ len = array1.length;
1623+ for (i = 0; i < len; i++) {
1624+ res[i] = deepMap2(array1[i], array2, callback);
1625+ }
1626+ }
1627+ }
1628+ else if (array1 instanceof Matrix) {
1629+ if (array2 instanceof Matrix) {
1630+ // callback(matrix, matrix)
1631+ res = deepMap2(array1.valueOf(), array2.valueOf(), callback);
1632+ return math.matrix(res);
1633+ }
1634+ else {
1635+ // callback(matrix, array)
1636+ // callback(matrix, object)
1637+ res = deepMap2(array1.valueOf(), array2, callback);
1638+ return math.matrix(res);
1639+ }
1640+ }
1641+ else {
1642+ if (isArray(array2)) {
1643+ // callback(object, array)
1644+ res = [];
1645+ len = array2.length;
1646+ for (i = 0; i < len; i++) {
1647+ res[i] = deepMap2(array1, array2[i], callback);
1648+ }
1649+ }
1650+ else if (array2 instanceof Matrix) {
1651+ // callback(object, matrix)
1652+ res = deepMap2(array1, array2.valueOf(), callback);
1653+ return math.matrix(res);
1654+ }
1655+ else {
1656+ // callback(object, object)
1657+ res = callback(array1, array2);
1658+ }
1659+ }
1660+
1661+ return res;
1662+ };
1663+
1664+ /**
1665+ * Reduce a given matrix or array to a new matrix or
1666+ * array with one less dimension, applying the given
1667+ * callback in the selected dimension.
1668+ * @param {Array | Matrix} mat
1669+ * @param {Number} dim
1670+ * @param {function} callback
1671+ * @return {Array | Matrix} res
1672+ */
1673+ collection.reduce = function(mat, dim, callback) {
1674+ var size = isArray(mat) ? array.size(mat) : mat.size();
1675+ if (dim < 0) {
1676+ // TODO: would be more clear when throwing a DimensionError here
1677+ throw new IndexError(dim);
1678+ }
1679+ if (dim >= size.length) {
1680+ // TODO: would be more clear when throwing a DimensionError here
1681+ throw new IndexError(dim, size.length);
1682+ }
1683+
1684+ if (mat instanceof Matrix) {
1685+ return math.matrix(_reduce(mat.valueOf(), dim, callback));
1686+ }else {
1687+ return _reduce(mat, dim, callback);
1688+ }
1689+ };
1690+
1691+ /**
1692+ * Recursively reduce a matrix
1693+ * @param {Array} mat
1694+ * @param {Number} dim
1695+ * @param {Function} callback
1696+ * @returns {Array} ret
1697+ * @private
1698+ */
1699+ function _reduce(mat, dim, callback){
1700+ var i, ret, val, tran;
1701+
1702+ if(dim<=0){
1703+ if( !isArray(mat[0]) ){
1704+ val = mat[0];
1705+ for(i=1; i<mat.length; i++){
1706+ val = callback(val, mat[i]);
1707+ }
1708+ return val;
1709+ }else{
1710+ tran = _switch(mat);
1711+ ret = [];
1712+ for(i=0; i<tran.length; i++){
1713+ ret[i] = _reduce(tran[i], dim-1, callback);
1714+ }
1715+ return ret;
1716+ }
1717+ }else{
1718+ ret = [];
1719+ for(i=0; i<mat.length; i++){
1720+ ret[i] = _reduce(mat[i], dim-1, callback);
1721+ }
1722+ return ret;
1723+ }
1724+ }
1725+
1726+ /**
1727+ * Transpose a matrix
1728+ * @param {Array} mat
1729+ * @returns {Array} ret
1730+ * @private
1731+ */
1732+ function _switch(mat){
1733+ var I = mat.length;
1734+ var J = mat[0].length;
1735+ var i, j;
1736+ var ret = [];
1737+ for( j=0; j<J; j++) {
1738+ var tmp = [];
1739+ for( i=0; i<I; i++) {
1740+ tmp.push(mat[i][j]);
1741+ }
1742+ ret.push(tmp);
1743+ }
1744+ return ret;
1745+ }
1746+
1747+ /**
1748+ * Recursively loop over all elements in a given multi dimensional array
1749+ * and invoke the callback on each of the elements.
1750+ * @param {Array | Matrix} array
1751+ * @param {function} callback The callback method is invoked with one
1752+ * parameter: the current element in the array
1753+ */
1754+ collection.deepForEach = function deepForEach (array, callback) {
1755 if (array instanceof Matrix) {
1756 array = array.valueOf();
1757 }
1758- if (!isArray(array)) {
1759- array = [array];
1760- }
1761- return array;
1762- }
1763- else {
1764- // fn(m, n, p, ...)
1765- return util.array.argsToArray(args);
1766- }
1767- };
1768-
1769-
1770- /**
1771- * Test whether a value is a collection: an Array or Matrix
1772- * @param {*} x
1773- * @returns {boolean} isCollection
1774- */
1775- exports.isCollection = function(x) {
1776- return (isArray(x) || (x instanceof Matrix));
1777- };
1778-
1779- /**
1780- * Execute the callback function element wise for each element in array and any
1781- * nested array
1782- * Returns an array with the results
1783- * @param {Array | Matrix} array
1784- * @param {function} callback The callback is called with two parameters:
1785- * value1 and value2, which contain the current
1786- * element of both arrays.
1787- * @return {Array | Matrix} res
1788- */
1789- exports.deepMap = function deepMap(array, callback) {
1790- if (array && (typeof array.map === 'function')) {
1791- return array.map(function (x) {
1792- return deepMap(x, callback);
1793- });
1794- }
1795- else {
1796- return callback(array);
1797- }
1798- };
1799-
1800- /**
1801- * Execute the callback function element wise for each entry in two given arrays,
1802- * and for any nested array. Objects can also be scalar objects.
1803- * Returns an array with the results.
1804- * @param {Array | Matrix | Object} array1
1805- * @param {Array | Matrix | Object} array2
1806- * @param {function} callback The callback is called with two parameters:
1807- * value1 and value2, which contain the current
1808- * element of both arrays.
1809- * @return {Array | Matrix} res
1810- */
1811- exports.deepMap2 = function deepMap2(array1, array2, callback) {
1812- var res, len, i;
1813-
1814- if (isArray(array1)) {
1815- if (isArray(array2)) {
1816- // callback(array, array)
1817- if (array1.length != array2.length) {
1818- throw new DimensionError(array1.length, array2.length);
1819- }
1820-
1821- res = [];
1822- len = array1.length;
1823- for (i = 0; i < len; i++) {
1824- res[i] = deepMap2(array1[i], array2[i], callback);
1825- }
1826- }
1827- else if (array2 instanceof Matrix) {
1828- // callback(array, matrix)
1829- res = deepMap2(array1, array2.valueOf(), callback);
1830- return new Matrix(res);
1831- }
1832- else {
1833- // callback(array, object)
1834- res = [];
1835- len = array1.length;
1836- for (i = 0; i < len; i++) {
1837- res[i] = deepMap2(array1[i], array2, callback);
1838- }
1839- }
1840- }
1841- else if (array1 instanceof Matrix) {
1842- if (array2 instanceof Matrix) {
1843- // callback(matrix, matrix)
1844- res = deepMap2(array1.valueOf(), array2.valueOf(), callback);
1845- return new Matrix(res);
1846- }
1847- else {
1848- // callback(matrix, array)
1849- // callback(matrix, object)
1850- res = deepMap2(array1.valueOf(), array2, callback);
1851- return new Matrix(res);
1852- }
1853- }
1854- else {
1855- if (isArray(array2)) {
1856- // callback(object, array)
1857- res = [];
1858- len = array2.length;
1859- for (i = 0; i < len; i++) {
1860- res[i] = deepMap2(array1, array2[i], callback);
1861- }
1862- }
1863- else if (array2 instanceof Matrix) {
1864- // callback(object, matrix)
1865- res = deepMap2(array1, array2.valueOf(), callback);
1866- return new Matrix(res);
1867- }
1868- else {
1869- // callback(object, object)
1870- res = callback(array1, array2);
1871- }
1872- }
1873-
1874- return res;
1875- };
1876-
1877- /**
1878- * Reduce a given matrix or array to a new matrix or
1879- * array with one less dimension, applying the given
1880- * callback in the selected dimension.
1881- * @param {Array | Matrix} mat
1882- * @param {Number} dim
1883- * @param {function} callback
1884- * @return {Array | Matrix} res
1885- */
1886- exports.reduce = function(mat, dim, callback) {
1887- var size = isArray(mat) ? array.size(mat) : mat.size();
1888- if (dim < 0) {
1889- // TODO: would be more clear when throwing a DimensionError here
1890- throw new IndexError(dim);
1891- }
1892- if (dim >= size.length) {
1893- // TODO: would be more clear when throwing a DimensionError here
1894- throw new IndexError(dim, size.length);
1895- }
1896-
1897- if (mat instanceof Matrix) {
1898- return new Matrix(_reduce(mat.valueOf(), dim, callback));
1899- }else {
1900- return _reduce(mat, dim, callback);
1901- }
1902- };
1903-
1904- /**
1905- * Recursively reduce a matrix
1906- * @param {Array} mat
1907- * @param {Number} dim
1908- * @param {Function} callback
1909- * @returns {Array} ret
1910- * @private
1911- */
1912- function _reduce(mat, dim, callback){
1913- var i, ret, val, tran;
1914-
1915- if(dim<=0){
1916- if( !isArray(mat[0]) ){
1917- val = mat[0];
1918- for(i=1; i<mat.length; i++){
1919- val = callback(val, mat[i]);
1920- }
1921- return val;
1922- }else{
1923- tran = _switch(mat);
1924- ret = [];
1925- for(i=0; i<tran.length; i++){
1926- ret[i] = _reduce(tran[i], dim-1, callback);
1927- }
1928- return ret
1929- }
1930- }else{
1931- ret = [];
1932- for(i=0; i<mat.length; i++){
1933- ret[i] = _reduce(mat[i], dim-1, callback);
1934- }
1935- return ret;
1936- }
1937- }
1938-
1939- /**
1940- * Transpose a matrix
1941- * @param {Array} mat
1942- * @returns {Array} ret
1943- * @private
1944- */
1945- function _switch(mat){
1946- var I = mat.length;
1947- var J = mat[0].length;
1948- var i, j;
1949- var ret = [];
1950- for( j=0; j<J; j++) {
1951- var tmp = [];
1952- for( i=0; i<I; i++) {
1953- tmp.push(mat[i][j]);
1954- }
1955- ret.push(tmp);
1956- }
1957- return ret;
1958- }
1959-
1960- /**
1961- * Recursively loop over all elements in a given multi dimensional array
1962- * and invoke the callback on each of the elements.
1963- * @param {Array | Matrix} array
1964- * @param {function} callback The callback method is invoked with one
1965- * parameter: the current element in the array
1966- */
1967- exports.deepForEach = function deepForEach (array, callback) {
1968- if (array instanceof Matrix) {
1969- array = array.valueOf();
1970- }
1971-
1972- for (var i = 0, ii = array.length; i < ii; i++) {
1973- var value = array[i];
1974-
1975- if (isArray(value)) {
1976- deepForEach(value, callback);
1977- }
1978- else {
1979- callback(value);
1980- }
1981- }
1982- };
1983-
1984+
1985+ for (var i = 0, ii = array.length; i < ii; i++) {
1986+ var value = array[i];
1987+
1988+ if (isArray(value)) {
1989+ deepForEach(value, callback);
1990+ }
1991+ else {
1992+ callback(value);
1993+ }
1994+ }
1995+ };
1996+
1997+ return collection;
1998+ };
1999
2000 /***/ },
2001 /* 15 */
2002@@ -4056,20 +3781,1214 @@
2003
2004 'use strict';
2005
2006- exports.ArrayNode = __webpack_require__(172);
2007- exports.AssignmentNode = __webpack_require__(173);
2008- exports.BlockNode = __webpack_require__(174);
2009- exports.ConditionalNode = __webpack_require__(175);
2010- exports.ConstantNode = __webpack_require__(176);
2011- exports.IndexNode = __webpack_require__(177);
2012- exports.FunctionAssignmentNode = __webpack_require__(178);
2013- exports.FunctionNode = __webpack_require__(179);
2014- exports.Node = __webpack_require__(180);
2015- exports.OperatorNode = __webpack_require__(181);
2016- exports.RangeNode = __webpack_require__(182);
2017- exports.SymbolNode = __webpack_require__(183);
2018- exports.UpdateNode = __webpack_require__(184);
2019-
2020+ var util = __webpack_require__(175);
2021+ var DimensionError = __webpack_require__(172);
2022+
2023+ var array = util.array;
2024+ var object = util.object;
2025+ var string = util.string;
2026+ var number = util.number;
2027+
2028+ var isArray = Array.isArray;
2029+ var isNumber = util.number.isNumber;
2030+ var isInteger = util.number.isInteger;
2031+
2032+ var validateIndex = array.validateIndex;
2033+
2034+ module.exports = function (math) {
2035+
2036+ var Index = math.type.Index,
2037+ BigNumber = math.type.BigNumber,
2038+ Matrix = math.type.Matrix;
2039+
2040+ function CcsMatrix(data) {
2041+ if (!(this instanceof CcsMatrix))
2042+ throw new SyntaxError('Constructor must be called with the new operator');
2043+
2044+ if (data instanceof Matrix) {
2045+ // check data is a CcsMatrix
2046+ if (data.type === 'CcsMatrix') {
2047+ // clone arrays
2048+ this._values = object.clone(data._values);
2049+ this._index = object.clone(data._index);
2050+ this._ptr = object.clone(data._ptr);
2051+ this._size = object.clone(data._size);
2052+ }
2053+ else {
2054+ // build from matrix data
2055+ _createFromArray(this, data.valueOf());
2056+ }
2057+ }
2058+ else if (data && isArray(data.values) && isArray(data.index) && isArray(data.ptr) && isArray(data.size)) {
2059+ // initialize fields
2060+ this._values = data.values;
2061+ this._index = data.index;
2062+ this._ptr = data.ptr;
2063+ this._size = data.size;
2064+ }
2065+ else if (isArray(data)) {
2066+ // create from array
2067+ _createFromArray(this, data);
2068+ }
2069+ else if (data) {
2070+ // unsupported type
2071+ throw new TypeError('Unsupported type of data (' + util.types.type(data) + ')');
2072+ }
2073+ else {
2074+ // nothing provided
2075+ this._values = [];
2076+ this._index = [];
2077+ this._ptr = [0];
2078+ this._size = [0];
2079+ }
2080+ }
2081+
2082+ var _createFromArray = function (matrix, data) {
2083+ // initialize fields
2084+ matrix._values = [];
2085+ matrix._index = [];
2086+ matrix._ptr = [];
2087+ // discover rows & columns, do not use math.size() to avoid looping array twice
2088+ var rows = data.length;
2089+ var columns = 0;
2090+
2091+ // check we have rows (empty array)
2092+ if (rows > 0) {
2093+ // column index
2094+ var j = 0;
2095+ do {
2096+ // store pointer to values index
2097+ matrix._ptr.push(matrix._values.length);
2098+ // loop rows
2099+ for (var i = 0; i < rows; i++) {
2100+ // current row
2101+ var row = data[i];
2102+ // check row is an array
2103+ if (isArray(row)) {
2104+ // update columns if needed (only on first column)
2105+ if (j ===0 && columns < row.length)
2106+ columns = row.length;
2107+ // check row has column
2108+ if (j < row.length) {
2109+ // value
2110+ var v = row[j];
2111+ // check value != 0
2112+ if (!math.equal(v, 0)) {
2113+ // store value
2114+ matrix._values.push(v);
2115+ // index
2116+ matrix._index.push(i);
2117+ }
2118+ }
2119+ }
2120+ else {
2121+ // update columns if needed (only on first column)
2122+ if (j === 0 && columns < 1)
2123+ columns = 1;
2124+ // check value != 0 (row is a scalar)
2125+ if (!math.equal(row, 0)) {
2126+ // store value
2127+ matrix._values.push(row);
2128+ // index
2129+ matrix._index.push(i);
2130+ }
2131+ }
2132+ }
2133+ // increment index
2134+ j++;
2135+ }
2136+ while (j < columns);
2137+ }
2138+ // store number of values in ptr
2139+ matrix._ptr.push(matrix._values.length);
2140+ // size
2141+ matrix._size = [rows, columns];
2142+ };
2143+
2144+ CcsMatrix.prototype = new math.type.Matrix();
2145+
2146+ CcsMatrix.prototype.type = 'CcsMatrix';
2147+
2148+ /**
2149+ * Get the storage format used by the matrix.
2150+ *
2151+ * Usage:
2152+ * var format = matrix.storage() // retrieve storage format
2153+ *
2154+ * @return {string} The storage format.
2155+ */
2156+ CcsMatrix.prototype.storage = function () {
2157+ return 'ccs';
2158+ };
2159+
2160+ /**
2161+ * Get a subset of the matrix, or replace a subset of the matrix.
2162+ *
2163+ * Usage:
2164+ * var subset = matrix.subset(index) // retrieve subset
2165+ * var value = matrix.subset(index, replacement) // replace subset
2166+ *
2167+ * @param {Index} index
2168+ * @param {Array | Maytrix | *} [replacement]
2169+ * @param {*} [defaultValue=0] Default value, filled in on new entries when
2170+ * the matrix is resized. If not provided,
2171+ * new matrix elements will be filled with zeros.
2172+ */
2173+ CcsMatrix.prototype.subset = function (index, replacement, defaultValue) {
2174+ // check arguments
2175+ switch (arguments.length) {
2176+ case 1:
2177+ return _getsubset(this, index);
2178+
2179+ // intentional fall through
2180+ case 2:
2181+ case 3:
2182+ return _setsubset(this, index, replacement, defaultValue);
2183+
2184+ default:
2185+ throw new SyntaxError('Wrong number of arguments');
2186+ }
2187+ };
2188+
2189+ var _getsubset = function (matrix, index) {
2190+ // check index
2191+ if (!(index instanceof Index)) {
2192+ throw new TypeError('Invalid index');
2193+ }
2194+
2195+ var isScalar = index.isScalar();
2196+ if (isScalar) {
2197+ // return a scalar
2198+ return matrix.get(index.min());
2199+ }
2200+ // validate dimensions
2201+ var size = index.size();
2202+ if (size.length != matrix._size.length) {
2203+ throw new DimensionError(size.length, matrix._size.length);
2204+ }
2205+
2206+ // validate if any of the ranges in the index is out of range
2207+ var min = index.min();
2208+ var max = index.max();
2209+ for (var i = 0, ii = matrix._size.length; i < ii; i++) {
2210+ validateIndex(min[i], matrix._size[i]);
2211+ validateIndex(max[i], matrix._size[i]);
2212+ }
2213+
2214+ // map callback
2215+ var callback = function (v) {
2216+ // return value
2217+ return v;
2218+ };
2219+ // get sub-matrix
2220+ return _map(matrix, min[0], max[0], min[1], max[1], callback, false);
2221+ };
2222+
2223+ var _setsubset = function (matrix, index, submatrix, defaultValue) {
2224+ // check index
2225+ if (!(index instanceof Index)) {
2226+ throw new TypeError('Invalid index');
2227+ }
2228+
2229+ // get index size and check whether the index contains a single value
2230+ var iSize = index.size(),
2231+ isScalar = index.isScalar();
2232+
2233+ // calculate the size of the submatrix, and convert it into an Array if needed
2234+ var sSize;
2235+ if (submatrix instanceof Matrix) {
2236+ // submatrix size
2237+ sSize = submatrix.size();
2238+ // use array representation
2239+ submatrix = submatrix.toArray();
2240+ }
2241+ else {
2242+ // get submatrix size (array, scalar)
2243+ sSize = array.size(submatrix);
2244+ }
2245+
2246+ // check index is a scalar
2247+ if (isScalar) {
2248+ // verify submatrix is a scalar
2249+ if (sSize.length !== 0) {
2250+ throw new TypeError('Scalar expected');
2251+ }
2252+ // set value
2253+ matrix.set(index.min(), submatrix, defaultValue);
2254+ }
2255+ else {
2256+ // validate dimensions, index size must be one or two dimensions
2257+ if (iSize.length !== 1 && iSize.length !== 2) {
2258+ throw new DimensionError(iSize.length, matrix._size.length, '<');
2259+ }
2260+
2261+ // check submatrix and index have the same dimensions
2262+ if (sSize.length < iSize.length) {
2263+ // calculate number of missing outer dimensions
2264+ var i = 0;
2265+ var outer = 0;
2266+ while (iSize[i] === 1 && sSize[i] === 1) {
2267+ i++;
2268+ }
2269+ while (iSize[i] === 1) {
2270+ outer++;
2271+ i++;
2272+ }
2273+ // unsqueeze both outer and inner dimensions
2274+ submatrix = array.unsqueeze(submatrix, iSize.length, outer, sSize);
2275+ }
2276+
2277+ // check whether the size of the submatrix matches the index size
2278+ if (!object.deepEqual(iSize, sSize)) {
2279+ throw new DimensionError(iSize, sSize, '>');
2280+ }
2281+
2282+ // offsets
2283+ var x0 = index.min()[0];
2284+ var y0 = index.min()[1];
2285+
2286+ // submatrix rows and columns
2287+ var m = sSize[0];
2288+ var n = sSize[1];
2289+
2290+ // loop submatrix
2291+ for (var x = 0; x < m; x++) {
2292+ // loop columns
2293+ for (var y = 0; y < n; y++) {
2294+ // value at i, j
2295+ var v = submatrix[x][y];
2296+ // invoke set (zero value will remove entry from matrix)
2297+ matrix.set([x + x0, y + y0], v, defaultValue);
2298+ }
2299+ }
2300+ }
2301+ return matrix;
2302+ };
2303+
2304+ /**
2305+ * Get a single element from the matrix.
2306+ * @param {Number[]} index Zero-based index
2307+ * @return {*} value
2308+ */
2309+ CcsMatrix.prototype.get = function (index) {
2310+ if (!isArray(index))
2311+ throw new TypeError('Array expected');
2312+ if (index.length != this._size.length)
2313+ throw new DimensionError(index.length, this._size.length);
2314+
2315+ // row and column
2316+ var i = index[0];
2317+ var j = index[1];
2318+
2319+ // check i, j are valid
2320+ validateIndex(i, this._size[0]);
2321+ validateIndex(j, this._size[1]);
2322+
2323+ // find value index
2324+ var k = _getValueIndex(i, this._ptr[j], this._ptr[j + 1], this._index);
2325+ // check k is prior to next column k and it is in the correct row
2326+ if (k < this._ptr[j + 1] && this._index[k] === i)
2327+ return object.clone(this._values[k]);
2328+
2329+ return 0;
2330+ };
2331+
2332+ /**
2333+ * Replace a single element in the matrix.
2334+ * @param {Number[]} index Zero-based index
2335+ * @param {*} value
2336+ * @param {*} [defaultValue] Default value, filled in on new entries when
2337+ * the matrix is resized. If not provided,
2338+ * new matrix elements will be set to zero.
2339+ * @return {CcsMatrix} self
2340+ */
2341+ CcsMatrix.prototype.set = function (index, v, defaultValue) {
2342+ if (!isArray(index))
2343+ throw new TypeError('Array expected');
2344+ if (index.length != this._size.length)
2345+ throw new DimensionError(index.length, this._size.length);
2346+
2347+ // row and column
2348+ var i = index[0];
2349+ var j = index[1];
2350+
2351+ // rows & columns
2352+ var rows = this._size[0];
2353+ var columns = this._size[1];
2354+
2355+ // check we need to resize matrix
2356+ if (i > rows - 1 || j > columns - 1) {
2357+ // resize matrix
2358+ _resize(this, Math.max(i + 1, rows), Math.max(j + 1, columns), defaultValue);
2359+ // update rows & columns
2360+ rows = this._size[0];
2361+ columns = this._size[1];
2362+ }
2363+
2364+ // check i, j are valid
2365+ validateIndex(i, rows);
2366+ validateIndex(j, columns);
2367+
2368+ // find value index
2369+ var k = _getValueIndex(i, this._ptr[j], this._ptr[j + 1], this._index);
2370+ // check k is prior to next column k and it is in the correct row
2371+ if (k < this._ptr[j + 1] && this._index[k] === i) {
2372+ // check value != 0
2373+ if (!math.equal(v, 0)) {
2374+ // update value
2375+ this._values[k] = v;
2376+ }
2377+ else {
2378+ // remove value from matrix
2379+ _remove(k, j, this._values, this._index, this._ptr);
2380+ }
2381+ }
2382+ else {
2383+ // insert value @ (i, j)
2384+ _insert(k, i, j, v, this._values, this._index, this._ptr);
2385+ }
2386+
2387+ return this;
2388+ };
2389+
2390+ var _getValueIndex = function(i, top, bottom, index) {
2391+ // check row is on the bottom side
2392+ if (bottom - top === 0 || i > index[bottom - 1])
2393+ return bottom;
2394+ // loop until we find row index
2395+ while (top < bottom) {
2396+ // point in the middle (fast integer division)
2397+ var p = ~~((top + bottom) / 2);
2398+ // row @ p
2399+ var r = index[p];
2400+ // check we have to look on the top side, bottom side or we found the row
2401+ if (i < r)
2402+ bottom = p;
2403+ else if (i > r)
2404+ top = p + 1;
2405+ else
2406+ return p;
2407+ }
2408+ return top;
2409+ };
2410+
2411+ var _remove = function (k, j, values, index, ptr) {
2412+ // remove value @ k
2413+ values.splice(k, 1);
2414+ index.splice(k, 1);
2415+ // update pointers
2416+ for (var x = j + 1; x < ptr.length; x++)
2417+ ptr[x]--;
2418+ };
2419+
2420+ var _insert = function (k, i, j, v, values, index, ptr) {
2421+ // insert value
2422+ values.splice(k, 0, v);
2423+ // update row for k
2424+ index.splice(k, 0, i);
2425+ // update column pointers
2426+ for (var x = j + 1; x < ptr.length; x++)
2427+ ptr[x]++;
2428+ };
2429+
2430+ /**
2431+ * Resize the matrix to the given size. Returns a copy of the matrix when
2432+ * `copy=true`, otherwise return the matrix itself (resize in place).
2433+ *
2434+ * @param {Number[]} size The new size the matrix should have.
2435+ * @param {*} [defaultValue=0] Default value, filled in on new entries.
2436+ * If not provided, the matrix elements will
2437+ * be filled with zeros.
2438+ * @param {boolean} [copy] Return a resized copy of the matrix
2439+ *
2440+ * @return {Matrix} The resized matrix
2441+ */
2442+ CcsMatrix.prototype.resize = function (size, defaultValue, copy) {
2443+ // validate arguments
2444+ if (!isArray(size))
2445+ throw new TypeError('Array expected');
2446+ if (size.length !== 2)
2447+ throw new Error('Only two dimensions matrix are supported');
2448+
2449+ // check sizes
2450+ size.forEach(function (value) {
2451+ if (!number.isNumber(value) || !number.isInteger(value) || value < 0) {
2452+ throw new TypeError('Invalid size, must contain positive integers ' +
2453+ '(size: ' + string.format(size) + ')');
2454+ }
2455+ });
2456+
2457+ // matrix to resize
2458+ var m = copy ? this.clone() : this;
2459+ // resize matrix
2460+ return _resize(m, size[0], size[1], defaultValue);
2461+ };
2462+
2463+ var _resize = function (matrix, rows, columns, defaultValue) {
2464+ // value to insert at the time of growing matrix
2465+ var value = defaultValue || 0;
2466+ // should we insert the value?
2467+ var ins = !math.equal(value, 0);
2468+
2469+ // old columns and rows
2470+ var r = matrix._size[0];
2471+ var c = matrix._size[1];
2472+
2473+ var i, j, k;
2474+
2475+ // check we need to increase columns
2476+ if (columns > c) {
2477+ // loop new columns
2478+ for (j = c; j < columns; j++) {
2479+ // update matrix._ptr for current column
2480+ matrix._ptr[j] = matrix._values.length;
2481+ // check we need to insert matrix._values
2482+ if (ins) {
2483+ // loop rows
2484+ for (i = 0; i < r; i++) {
2485+ // add new matrix._values
2486+ matrix._values.push(value);
2487+ // update matrix._index
2488+ matrix._index.push(i);
2489+ }
2490+ }
2491+ }
2492+ // store number of matrix._values in matrix._ptr
2493+ matrix._ptr[columns] = matrix._values.length;
2494+ }
2495+ else if (columns < c) {
2496+ // truncate matrix._ptr
2497+ matrix._ptr.splice(columns + 1, c - columns);
2498+ // truncate matrix._values and matrix._index
2499+ matrix._values.splice(matrix._ptr[columns], matrix._values.length);
2500+ matrix._index.splice(matrix._ptr[columns], matrix._index.length);
2501+ }
2502+ // update columns
2503+ c = columns;
2504+
2505+ // check we need to increase rows
2506+ if (rows > r) {
2507+ // check we have to insert values
2508+ if (ins) {
2509+ // inserts
2510+ var n = 0;
2511+ // loop columns
2512+ for (j = 0; j < c; j++) {
2513+ // update matrix._ptr for current column
2514+ matrix._ptr[j] = matrix._ptr[j] + n;
2515+ // where to insert matrix._values
2516+ k = matrix._ptr[j + 1] + n;
2517+ // pointer
2518+ var p = 0;
2519+ // loop new rows, initialize pointer
2520+ for (i = r; i < rows; i++, p++) {
2521+ // add value
2522+ matrix._values.splice(k + p, 0, value);
2523+ // update matrix._index
2524+ matrix._index.splice(k + p, 0, i);
2525+ // increment inserts
2526+ n++;
2527+ }
2528+ }
2529+ // store number of matrix._values in matrix._ptr
2530+ matrix._ptr[c] = matrix._values.length;
2531+ }
2532+ }
2533+ else if (rows < r) {
2534+ // deletes
2535+ var d = 0;
2536+ // loop columns
2537+ for (j = 0; j < c; j++) {
2538+ // update matrix._ptr for current column
2539+ matrix._ptr[j] = matrix._ptr[j] - d;
2540+ // where matrix._values start for next column
2541+ var k0 = matrix._ptr[j];
2542+ var k1 = matrix._ptr[j + 1] - d;
2543+ // loop matrix._index
2544+ for (k = k0; k < k1; k++) {
2545+ // row
2546+ i = matrix._index[k];
2547+ // check we need to delete value and matrix._index
2548+ if (i > rows - 1) {
2549+ // remove value
2550+ matrix._values.splice(k, 1);
2551+ // remove item from matrix._index
2552+ matrix._index.splice(k, 1);
2553+ // increase deletes
2554+ d++;
2555+ }
2556+ }
2557+ }
2558+ // update matrix._ptr for current column
2559+ matrix._ptr[j] = matrix._values.length;
2560+ }
2561+ // update matrix._size
2562+ matrix._size[0] = rows;
2563+ matrix._size[1] = columns;
2564+ // return matrix
2565+ return matrix;
2566+ };
2567+
2568+ /**
2569+ * Create a clone of the matrix
2570+ * @return {CcsMatrix} clone
2571+ */
2572+ CcsMatrix.prototype.clone = function () {
2573+ var m = new CcsMatrix({
2574+ values: object.clone(this._values),
2575+ index: object.clone(this._index),
2576+ ptr: object.clone(this._ptr),
2577+ size: object.clone(this._size)
2578+ });
2579+ return m;
2580+ };
2581+
2582+ /**
2583+ * Retrieve the size of the matrix.
2584+ * @returns {Number[]} size
2585+ */
2586+ CcsMatrix.prototype.size = function() {
2587+ return object.clone(this._size);
2588+ };
2589+
2590+ /**
2591+ * Create a new matrix with the results of the callback function executed on
2592+ * each entry of the matrix.
2593+ * @param {function} callback The callback function is invoked with three
2594+ * parameters: the value of the element, the index
2595+ * of the element, and the Matrix being traversed.
2596+ * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
2597+ *
2598+ * @return {CcsMatrix} matrix
2599+ */
2600+ CcsMatrix.prototype.map = function (callback, skipZeros) {
2601+ // matrix instance
2602+ var me = this;
2603+ // rows and columns
2604+ var rows = this._size[0];
2605+ var columns = this._size[1];
2606+ // invoke callback
2607+ var invoke = function (v, i, j) {
2608+ // invoke callback
2609+ return callback(v, [i, j], me);
2610+ };
2611+ // invoke _map
2612+ return _map(this, 0, rows - 1, 0, columns - 1, invoke, skipZeros);
2613+ };
2614+
2615+ /**
2616+ * Create a new matrix with the results of the callback function executed on the interval
2617+ * [minRow..maxRow, minColumn..maxColumn].
2618+ */
2619+ var _map = function (matrix, minRow, maxRow, minColumn, maxColumn, callback, skipZeros) {
2620+ // result arrays
2621+ var values = [];
2622+ var index = [];
2623+ var ptr = [];
2624+ // invoke callback
2625+ var invoke = function (v, x, y) {
2626+ // invoke callback
2627+ v = callback(v, x, y);
2628+ // check value != 0
2629+ if (!math.equal(v, 0)) {
2630+ // store value
2631+ values.push(v);
2632+ // index
2633+ index.push(x);
2634+ }
2635+ };
2636+ // loop columns
2637+ for (var j = minColumn; j <= maxColumn; j++) {
2638+ // store pointer to values index
2639+ ptr.push(values.length);
2640+ // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
2641+ var k0 = matrix._ptr[j];
2642+ var k1 = matrix._ptr[j + 1];
2643+ // row pointer
2644+ var p = minRow;
2645+ // loop k within [k0, k1[
2646+ for (var k = k0; k < k1; k++) {
2647+ // row index
2648+ var i = matrix._index[k];
2649+ // check i is in range
2650+ if (i >= minRow && i <= maxRow) {
2651+ // zero values
2652+ if (!skipZeros) {
2653+ for (var x = p; x < i; x++)
2654+ invoke(0, x - minRow, j - minColumn);
2655+ }
2656+ // value @ k
2657+ invoke(matrix._values[k], i - minRow, j - minColumn);
2658+ }
2659+ // update pointer
2660+ p = i + 1;
2661+ }
2662+ // zero values
2663+ if (!skipZeros) {
2664+ for (var y = p; y <= maxRow; y++)
2665+ invoke(0, y - minRow, j - minColumn);
2666+ }
2667+ }
2668+ // store number of values in ptr
2669+ ptr.push(values.length);
2670+ // return ccs
2671+ return new CcsMatrix({
2672+ values: values,
2673+ index: index,
2674+ ptr: ptr,
2675+ size: [maxRow - minRow + 1, maxColumn - minColumn + 1]
2676+ });
2677+ };
2678+
2679+ /**
2680+ * Execute a callback function on each entry of the matrix.
2681+ * @param {function} callback The callback function is invoked with three
2682+ * parameters: the value of the element, the index
2683+ * of the element, and the Matrix being traversed.
2684+ * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
2685+ */
2686+ CcsMatrix.prototype.forEach = function (callback, skipZeros) {
2687+ // matrix instance
2688+ var me = this;
2689+ // rows and columns
2690+ var rows = this._size[0];
2691+ var columns = this._size[1];
2692+ // loop columns
2693+ for (var j = 0; j < columns; j++) {
2694+ // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
2695+ var k0 = this._ptr[j];
2696+ var k1 = this._ptr[j + 1];
2697+ // column pointer
2698+ var p = 0;
2699+ // loop k within [k0, k1[
2700+ for (var k = k0; k < k1; k++) {
2701+ // row index
2702+ var i = this._index[k];
2703+ // check we need to process zeros
2704+ if (!skipZeros) {
2705+ // zero values
2706+ for (var x = p; x < i; x++)
2707+ callback(0, [x, j], me);
2708+ }
2709+ // value @ k
2710+ callback(this._values[k], [i, j], me);
2711+ // update pointer
2712+ p = i + 1;
2713+ }
2714+ // check we need to process zeros
2715+ if (!skipZeros) {
2716+ // zero values
2717+ for (var y = p; y < rows; y++)
2718+ callback(0, [y, j], me);
2719+ }
2720+ }
2721+ };
2722+
2723+ /**
2724+ * Create an Array with a copy of the data of the CcsMatrix
2725+ * @returns {Array} array
2726+ */
2727+ CcsMatrix.prototype.toArray = function () {
2728+ return _toArray(this, true);
2729+ };
2730+
2731+ /**
2732+ * Get the primitive value of the CcsMatrix: a two dimensions array
2733+ * @returns {Array} array
2734+ */
2735+ CcsMatrix.prototype.valueOf = function () {
2736+ return _toArray(this, false);
2737+ };
2738+
2739+ var _toArray = function (matrix, copy) {
2740+ // result
2741+ var a = [];
2742+ // rows and columns
2743+ var rows = matrix._size[0];
2744+ var columns = matrix._size[1];
2745+ // loop columns
2746+ for (var j = 0; j < columns; j++) {
2747+ // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
2748+ var k0 = matrix._ptr[j];
2749+ var k1 = matrix._ptr[j + 1];
2750+ // row pointer
2751+ var p = 0;
2752+ // loop k within [k0, k1[
2753+ for (var k = k0; k < k1; k++) {
2754+ // row index
2755+ var i = matrix._index[k];
2756+ // zeros
2757+ for (var x = p; x < i; x++)
2758+ (a[x] = (a[x] || []))[j] = 0;
2759+ // set value
2760+ (a[i] = (a[i] || []))[j] = copy ? object.clone(matrix._values[k]) : matrix._values[k];
2761+ // update pointer
2762+ p = i + 1;
2763+ }
2764+ // zero values
2765+ for (var y = p; y < rows; y++)
2766+ (a[y] = (a[y] || []))[j] = 0;
2767+ }
2768+ return a;
2769+ };
2770+
2771+ /**
2772+ * Get a string representation of the matrix, with optional formatting options.
2773+ * @param {Object | Number | Function} [options] Formatting options. See
2774+ * lib/util/number:format for a
2775+ * description of the available
2776+ * options.
2777+ * @returns {String} str
2778+ */
2779+ CcsMatrix.prototype.format = function (options) {
2780+ // rows and columns
2781+ var rows = this._size[0];
2782+ var columns = this._size[1];
2783+ // rows & columns
2784+ var str = 'CCS [' + string.format(rows, options) + ' x ' + string.format(columns, options) + '] density: ' + string.format(this._values.length / (rows * columns), options) + '\n';
2785+ // loop columns
2786+ for (var j = 0; j < columns; j++) {
2787+ // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
2788+ var k0 = this._ptr[j];
2789+ var k1 = this._ptr[j + 1];
2790+ // loop k within [k0, k1[
2791+ for (var k = k0; k < k1; k++) {
2792+ // row index
2793+ var i = this._index[k];
2794+ // append value
2795+ str += '\n (' + string.format(i, options) + ', ' + string.format(j, options) + ') ==> ' + string.format(this._values[k], options);
2796+ }
2797+ }
2798+ return str;
2799+ };
2800+
2801+ /**
2802+ * Get a string representation of the matrix
2803+ * @returns {String} str
2804+ */
2805+ CcsMatrix.prototype.toString = function () {
2806+ return string.format(this.toArray());
2807+ };
2808+
2809+ /**
2810+ * Get a JSON representation of the matrix
2811+ * @returns {Object}
2812+ */
2813+ CcsMatrix.prototype.toJSON = function () {
2814+ return {
2815+ mathjs: 'CcsMatrix',
2816+ values: this._values,
2817+ index: this._index,
2818+ ptr: this._ptr,
2819+ size: this._size
2820+ };
2821+ };
2822+
2823+ /**
2824+ * Calculates the transpose of the matrix
2825+ * @returns {Matrix}
2826+ */
2827+ CcsMatrix.prototype.transpose = function () {
2828+ // rows and columns
2829+ var rows = this._size[0];
2830+ var columns = this._size[1];
2831+ // check columns
2832+ if (columns === 0) {
2833+ // throw exception
2834+ throw new RangeError('Cannot transpose a 2D matrix with no columns (size: ' + string.format(this._size) + ')');
2835+ }
2836+ // ccs transpose is a crs matrix with the same structure
2837+ return new math.type.CrsMatrix({
2838+ values: object.clone(this._values),
2839+ index: object.clone(this._index),
2840+ ptr: object.clone(this._ptr),
2841+ size: [columns, rows]
2842+ });
2843+ };
2844+
2845+ /**
2846+ * Get the kth Matrix diagonal.
2847+ *
2848+ * @param {Number | BigNumber} [k=0] The kth diagonal where the vector will retrieved.
2849+ *
2850+ * @returns {Array} The array vector with the diagonal values.
2851+ */
2852+ CcsMatrix.prototype.diagonal = function(k) {
2853+ // validate k if any
2854+ if (k) {
2855+ // convert BigNumber to a number
2856+ if (k instanceof BigNumber)
2857+ k = k.toNumber();
2858+ // is must be an integer
2859+ if (!isNumber(k) || !isInteger(k)) {
2860+ throw new TypeError ('The parameter k must be an integer number');
2861+ }
2862+ }
2863+ else {
2864+ // default value
2865+ k = 0;
2866+ }
2867+
2868+ var kSuper = k > 0 ? k : 0;
2869+ var kSub = k < 0 ? -k : 0;
2870+
2871+ // rows & columns
2872+ var rows = this._size[0];
2873+ var columns = this._size[1];
2874+
2875+ // number diagonal values
2876+ var n = Math.min(rows - kSub, columns - kSuper);
2877+
2878+ // diagonal
2879+ var values = [];
2880+ // loop columns
2881+ for (var j = kSuper; j < columns && values.length < n; j++) {
2882+ // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
2883+ var k0 = this._ptr[j];
2884+ var k1 = this._ptr[j + 1];
2885+ // column value flag
2886+ var cv = false;
2887+ // loop x within [k0, k1[
2888+ for (var x = k0; x < k1; x++) {
2889+ // row index
2890+ var i = this._index[x];
2891+ // check row
2892+ if (i === j - kSuper + kSub) {
2893+ // set flag
2894+ cv = true;
2895+ // value on this column
2896+ values.push(object.clone(this._values[x]));
2897+ // exit loop
2898+ break;
2899+ }
2900+ else if (i > j - kSuper + kSub) {
2901+ // exit loop, no value on the diagonal for column j
2902+ break;
2903+ }
2904+ }
2905+ // check this column has a value set
2906+ if (!cv && values.length < n) {
2907+ // zero on this column
2908+ values.push(0);
2909+ }
2910+ }
2911+ return values;
2912+ };
2913+
2914+ /**
2915+ * Generate a matrix from a JSON object
2916+ * @param {Object} json An object structured like
2917+ * `{"mathjs": "CcsMatrix", "values": [], "index": [], "ptr": [], "size": []}`,
2918+ * where mathjs is optional
2919+ * @returns {CcsMatrix}
2920+ */
2921+ CcsMatrix.fromJSON = function (json) {
2922+ return new CcsMatrix(json);
2923+ };
2924+
2925+ /**
2926+ * Create a diagonal matrix.
2927+ *
2928+ * @param {Array} size The matrix size.
2929+ * @param {Number, Array} value The values for the diagonal.
2930+ * @param {Number | BigNumber} [k=0] The kth diagonal where the vector will be filled in.
2931+ *
2932+ * @returns {CcsMatrix}
2933+ */
2934+ CcsMatrix.diagonal = function (size, value, k) {
2935+ if (!isArray(size))
2936+ throw new TypeError('Array expected, size parameter');
2937+ if (size.length !== 2)
2938+ throw new Error('Only two dimensions matrix are supported');
2939+
2940+ // map size & validate
2941+ size = size.map(function (s) {
2942+ // check it is a big number
2943+ if (s instanceof BigNumber) {
2944+ // convert it
2945+ s = s.toNumber();
2946+ }
2947+ // validate arguments
2948+ if (!isNumber(s) || !isInteger(s) || s < 1) {
2949+ throw new Error('Size values must be positive integers');
2950+ }
2951+ return s;
2952+ });
2953+
2954+ // validate k if any
2955+ if (k) {
2956+ // convert BigNumber to a number
2957+ if (k instanceof BigNumber)
2958+ k = k.toNumber();
2959+ // is must be an integer
2960+ if (!isNumber(k) || !isInteger(k)) {
2961+ throw new TypeError ('The parameter k must be an integer number');
2962+ }
2963+ }
2964+ else {
2965+ // default value
2966+ k = 0;
2967+ }
2968+
2969+ var kSuper = k > 0 ? k : 0;
2970+ var kSub = k < 0 ? -k : 0;
2971+
2972+ // rows and columns
2973+ var rows = size[0];
2974+ var columns = size[1];
2975+
2976+ // number of non-zero items
2977+ var n = Math.min(rows - kSub, columns - kSuper);
2978+
2979+ // value extraction function
2980+ var _value;
2981+
2982+ // check value
2983+ if (isArray(value)) {
2984+ // validate array
2985+ if (value.length !== n) {
2986+ // number of values in array must be n
2987+ throw new Error('Invalid value array length');
2988+ }
2989+ // define function
2990+ _value = function (i) {
2991+ // return value @ i
2992+ return value[i];
2993+ };
2994+ }
2995+ else {
2996+ // define function
2997+ _value = function () {
2998+ // return value
2999+ return value;
3000+ };
3001+ }
3002+
3003+ // create arrays
3004+ var values = [];
3005+ var index = [];
3006+ var ptr = [];
3007+
3008+ // loop items
3009+ for (var j = 0; j < columns; j++) {
3010+ // number of rows with value
3011+ ptr.push(values.length);
3012+ // diagonal index
3013+ var i = j - kSuper;
3014+ // check we need to set diagonal value
3015+ if (i >= 0 && i < n) {
3016+ // get value @ i
3017+ var v = _value(i);
3018+ // check for zero
3019+ if (!math.equal(v, 0)) {
3020+ // column
3021+ index.push(i + kSub);
3022+ // add value
3023+ values.push(v);
3024+ }
3025+ }
3026+ }
3027+ // last value should be number of values
3028+ ptr.push(values.length);
3029+ // create CcsMatrix
3030+ return new CcsMatrix({
3031+ values: values,
3032+ index: index,
3033+ ptr: ptr,
3034+ size: [rows, columns]
3035+ });
3036+ };
3037+
3038+ /**
3039+ * Calculate the trace of a matrix: the sum of the elements on the main
3040+ * diagonal of a square matrix.
3041+ *
3042+ * See also:
3043+ *
3044+ * diagonal
3045+ *
3046+ * @returns {Number} The matrix trace
3047+ */
3048+ CcsMatrix.prototype.trace = function () {
3049+ // size
3050+ var size = this._size;
3051+ // check dimensions
3052+ var rows = size[0];
3053+ var columns = size[1];
3054+ // matrix must be square
3055+ if (rows === columns) {
3056+ // calulate sum
3057+ var sum = 0;
3058+ // check we have data (avoid looping columns)
3059+ if (this._values.length > 0) {
3060+ // loop columns
3061+ for (var j = 0; j < columns; j++) {
3062+ // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
3063+ var k0 = this._ptr[j];
3064+ var k1 = this._ptr[j + 1];
3065+ // loop k within [k0, k1[
3066+ for (var k = k0; k < k1; k++) {
3067+ // row index
3068+ var i = this._index[k];
3069+ // check row
3070+ if (i === j) {
3071+ // accumulate value
3072+ sum = math.add(sum, this._values[k]);
3073+ // exit loop
3074+ break;
3075+ }
3076+ if (i > j) {
3077+ // exit loop, no value on the diagonal for column j
3078+ break;
3079+ }
3080+ }
3081+ }
3082+ }
3083+ // return trace
3084+ return sum;
3085+ }
3086+ throw new RangeError('Matrix must be square (size: ' + string.format(size) + ')');
3087+ };
3088+
3089+ /**
3090+ * Multiply the matrix values times the argument.
3091+ *
3092+ * @param {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} Value to multiply.
3093+ *
3094+ * @return {Number | BigNumber | Complex | Unit | Matrix}
3095+ */
3096+ CcsMatrix.prototype.multiply = function (value) {
3097+ // check dimensions
3098+ var rows = this._size[0];
3099+ var columns = this._size[1];
3100+
3101+ // check value is a matrix
3102+ if (value instanceof Matrix) {
3103+ // matrix size
3104+ var z = value.size();
3105+ // check value is a vector
3106+ if (z.length === 1) {
3107+ // mutiply matrix x vector array
3108+ return _multiply(this, z[0], 1, function (i) {
3109+ // value[i]
3110+ return value.get([i]);
3111+ });
3112+ }
3113+ // check two dimensions matrix
3114+ if (z.length === 2) {
3115+ // mutiply matrix x matrix
3116+ return _multiply(this, z[0], z[1], function (i, j) {
3117+ // value[i, j]
3118+ return value.get([i, j]);
3119+ });
3120+ }
3121+ throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
3122+ '(value has ' + z.length + ' dimensions)');
3123+ }
3124+
3125+ // check value is an array
3126+ if (isArray(value)) {
3127+ // array size
3128+ var s = array.size(value);
3129+ // check value is a vector
3130+ if (s.length === 1) {
3131+ // mutiply matrix x vector array
3132+ return _multiply(this, s[0], 1, function (i) {
3133+ // value[i]
3134+ return value[i];
3135+ });
3136+ }
3137+ if (s.length === 2) {
3138+ // mutiply matrix x array
3139+ return _multiply(this, s[0], s[1], function (i, j) {
3140+ // value[i, j]
3141+ return value[i][j];
3142+ });
3143+ }
3144+ throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
3145+ '(value has ' + s.length + ' dimensions)');
3146+ }
3147+
3148+ var callback = function (v) {
3149+ return math.multiply(v, value);
3150+ };
3151+
3152+ // map non zero elements
3153+ return _map(this, 0, rows - 1, 0, columns - 1, callback, false);
3154+ };
3155+
3156+ var _multiply = function (matrix, r, c, get) {
3157+
3158+ // matrix dimensions
3159+ var rows = matrix._size[0];
3160+ var columns = matrix._size[1];
3161+
3162+ // check dimensions match
3163+ if (columns !== r) {
3164+ // throw error
3165+ throw new RangeError('Dimension mismatch in multiplication. ' +
3166+ 'Columns of A must match length of B ' +
3167+ '(A is ' + rows + 'x' + columns +
3168+ ', B is ' + r + ', ' +
3169+ columns + ' != ' + r + ')');
3170+ }
3171+
3172+ // result arrays
3173+ var values = [];
3174+ var index = [];
3175+ var ptr = [];
3176+
3177+ // create array with rows entries
3178+ var data = [];
3179+ for (var x = 0; x < rows; x++)
3180+ data[x] = 0;
3181+ // loop value columns
3182+ for (var z = 0; z < c; z++) {
3183+ // update ptr
3184+ ptr.push(values.length);
3185+ // do not traverse rows in matrix, it is not efficient in CCS
3186+ for (var j = 0; j < columns; j++) {
3187+ // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
3188+ var k0 = matrix._ptr[j];
3189+ var k1 = matrix._ptr[j + 1];
3190+ // loop k within [k0, k1[
3191+ for (var k = k0; k < k1; k++) {
3192+ // row
3193+ var i = matrix._index[k];
3194+ // multiply & aggregate
3195+ data[i] = math.add(data[i], math.multiply(matrix._values[k], get(j, z)));
3196+ }
3197+ }
3198+ // finished processing column z, compress results
3199+ for (var y = 0; y < rows; y++) {
3200+ // check value is different than zero
3201+ if (!math.equal(data[y], 0)) {
3202+ // push value
3203+ values.push(data[y]);
3204+ index.push(y);
3205+ }
3206+ // reset value
3207+ data[y] = 0;
3208+ }
3209+ }
3210+ // update ptr
3211+ ptr.push(values.length);
3212+
3213+ // check we need to squeeze the result into a scalar
3214+ if (rows === 1 && c === 1)
3215+ return values.length === 1 ? values[0] : 0;
3216+
3217+ // return CCS matrix
3218+ return new CcsMatrix({
3219+ values: values,
3220+ index: index,
3221+ ptr: ptr,
3222+ size: [rows, c]
3223+ });
3224+ };
3225+
3226+ return CcsMatrix;
3227+ };
3228
3229 /***/ },
3230 /* 16 */
3231@@ -4077,1769 +4996,4033 @@
3232
3233 'use strict';
3234
3235- var util = __webpack_require__(171),
3236-
3237- ArgumentsError = __webpack_require__(167),
3238+ var util = __webpack_require__(175);
3239+ var DimensionError = __webpack_require__(172);
3240+
3241+ var array = util.array;
3242+ var object = util.object;
3243+ var string = util.string;
3244+ var number = util.number;
3245+
3246+ var isArray = Array.isArray;
3247+ var isNumber = util.number.isNumber;
3248+ var isInteger = util.number.isInteger;
3249+
3250+ var validateIndex = array.validateIndex;
3251+
3252+ module.exports = function (math) {
3253+
3254+ var Index = math.type.Index,
3255+ BigNumber = math.type.BigNumber,
3256+ Matrix = math.type.Matrix;
3257+
3258+ function CrsMatrix(data) {
3259+ if (!(this instanceof CrsMatrix))
3260+ throw new SyntaxError('Constructor must be called with the new operator');
3261+
3262+ if (data instanceof Matrix) {
3263+ // check data is a CrsMatrix
3264+ if (data.type === 'CrsMatrix') {
3265+ // clone arrays
3266+ this._values = object.clone(data._values);
3267+ this._index = object.clone(data._index);
3268+ this._ptr = object.clone(data._ptr);
3269+ this._size = object.clone(data._size);
3270+ }
3271+ else {
3272+ // build from matrix data
3273+ _createFromArray(this, data.valueOf());
3274+ }
3275+ }
3276+ else if (data && isArray(data.values) && isArray(data.index) && isArray(data.ptr) && isArray(data.size)) {
3277+ // initialize fields
3278+ this._values = data.values;
3279+ this._index = data.index;
3280+ this._ptr = data.ptr;
3281+ this._size = data.size;
3282+ }
3283+ else if (isArray(data)) {
3284+ // create from array
3285+ _createFromArray(this, data);
3286+ }
3287+ else if (data) {
3288+ // unsupported type
3289+ throw new TypeError('Unsupported type of data (' + util.types.type(data) + ')');
3290+ }
3291+ else {
3292+ // nothing provided
3293+ this._values = [];
3294+ this._index = [];
3295+ this._ptr = [0];
3296+ this._size = [0];
3297+ }
3298+ }
3299+
3300+ var _createFromArray = function (matrix, data) {
3301+ // initialize fields
3302+ matrix._values = [];
3303+ matrix._index = [];
3304+ matrix._ptr = [];
3305+ // discover rows & columns, do not use math.size() to avoid looping array twice
3306+ var rows = data.length;
3307+ var columns = 0;
3308+
3309+ // loop rows
3310+ for (var i = 0; i < rows; i++) {
3311+ // store value index in ptr
3312+ matrix._ptr.push(matrix._values.length);
3313+ // current row
3314+ var row = data[i];
3315+ // check row is an array
3316+ if (isArray(row)) {
3317+ // update columns if needed
3318+ if (row.length > columns)
3319+ columns = row.length;
3320+ // loop columns
3321+ for (var j = 0; j < row.length; j++) {
3322+ // value at data[i][j]
3323+ var v = row[j];
3324+ // check value != 0
3325+ if (!math.equal(v, 0)) {
3326+ // store value
3327+ matrix._values.push(v);
3328+ // add column index
3329+ matrix._index.push(j);
3330+ }
3331+ }
3332+ }
3333+ else {
3334+ // update columns if needed (only on first row)
3335+ if (i === 0 && columns < 1)
3336+ columns = 1;
3337+ // check value != 0 (row is a scalar)
3338+ if (!math.equal(row, 0)) {
3339+ // store value
3340+ matrix._values.push(row);
3341+ // index
3342+ matrix._index.push(0);
3343+ }
3344+ }
3345+ }
3346+ // store number of values in ptr
3347+ matrix._ptr.push(matrix._values.length);
3348+ // size
3349+ matrix._size = [rows, columns];
3350+ };
3351+
3352+ CrsMatrix.prototype = new math.type.Matrix();
3353+
3354+ CrsMatrix.prototype.type = 'CrsMatrix';
3355+
3356+ /**
3357+ * Get the storage format used by the matrix.
3358+ *
3359+ * Usage:
3360+ * var format = matrix.storage() // retrieve storage format
3361+ *
3362+ * @return {string} The storage format.
3363+ */
3364+ CrsMatrix.prototype.storage = function () {
3365+ return 'crs';
3366+ };
3367+
3368+ /**
3369+ * Get a subset of the matrix, or replace a subset of the matrix.
3370+ *
3371+ * Usage:
3372+ * var subset = matrix.subset(index) // retrieve subset
3373+ * var value = matrix.subset(index, replacement) // replace subset
3374+ *
3375+ * @param {Index} index
3376+ * @param {Array | Maytrix | *} [replacement]
3377+ * @param {*} [defaultValue=0] Default value, filled in on new entries when
3378+ * the matrix is resized. If not provided,
3379+ * new matrix elements will be filled with zeros.
3380+ */
3381+ CrsMatrix.prototype.subset = function (index, replacement, defaultValue) {
3382+ // check arguments
3383+ switch (arguments.length) {
3384+ case 1:
3385+ return _getsubset(this, index);
3386+
3387+ // intentional fall through
3388+ case 2:
3389+ case 3:
3390+ return _setsubset(this, index, replacement, defaultValue);
3391+
3392+ default:
3393+ throw new SyntaxError('Wrong number of arguments');
3394+ }
3395+ };
3396+
3397+ var _getsubset = function (matrix, index) {
3398+ // check index
3399+ if (!(index instanceof Index)) {
3400+ throw new TypeError('Invalid index');
3401+ }
3402+
3403+ var isScalar = index.isScalar();
3404+ if (isScalar) {
3405+ // return a scalar
3406+ return matrix.get(index.min());
3407+ }
3408+ // validate dimensions
3409+ var size = index.size();
3410+ if (size.length != matrix._size.length) {
3411+ throw new DimensionError(size.length, matrix._size.length);
3412+ }
3413+
3414+ // validate if any of the ranges in the index is out of range
3415+ var min = index.min();
3416+ var max = index.max();
3417+ for (var i = 0, ii = matrix._size.length; i < ii; i++) {
3418+ validateIndex(min[i], matrix._size[i]);
3419+ validateIndex(max[i], matrix._size[i]);
3420+ }
3421+
3422+ // map callback
3423+ var callback = function (v) {
3424+ // return value
3425+ return v;
3426+ };
3427+ // get sub-matrix
3428+ return _map(matrix, min[0], max[0], min[1], max[1], callback, false);
3429+ };
3430+
3431+ var _setsubset = function (matrix, index, submatrix, defaultValue) {
3432+ // check index
3433+ if (!(index instanceof Index)) {
3434+ throw new TypeError('Invalid index');
3435+ }
3436+
3437+ // get index size and check whether the index contains a single value
3438+ var iSize = index.size(),
3439+ isScalar = index.isScalar();
3440+
3441+ // calculate the size of the submatrix, and convert it into an Array if needed
3442+ var sSize;
3443+ if (submatrix instanceof Matrix) {
3444+ // submatrix size
3445+ sSize = submatrix.size();
3446+ // use array representation
3447+ submatrix = submatrix.toArray();
3448+ }
3449+ else {
3450+ // get submatrix size (array, scalar)
3451+ sSize = array.size(submatrix);
3452+ }
3453+
3454+ // check index is a scalar
3455+ if (isScalar) {
3456+ // verify submatrix is a scalar
3457+ if (sSize.length !== 0) {
3458+ throw new TypeError('Scalar expected');
3459+ }
3460+ // set value
3461+ matrix.set(index.min(), submatrix, defaultValue);
3462+ }
3463+ else {
3464+ // validate dimensions, index size must be one or two dimensions
3465+ if (iSize.length !== 1 && iSize.length !== 2) {
3466+ throw new DimensionError(iSize.length, matrix._size.length, '<');
3467+ }
3468+
3469+ // check submatrix and index have the same dimensions
3470+ if (sSize.length < iSize.length) {
3471+ // calculate number of missing outer dimensions
3472+ var i = 0;
3473+ var outer = 0;
3474+ while (iSize[i] === 1 && sSize[i] === 1) {
3475+ i++;
3476+ }
3477+ while (iSize[i] === 1) {
3478+ outer++;
3479+ i++;
3480+ }
3481+ // unsqueeze both outer and inner dimensions
3482+ submatrix = array.unsqueeze(submatrix, iSize.length, outer, sSize);
3483+ }
3484+
3485+ // check whether the size of the submatrix matches the index size
3486+ if (!object.deepEqual(iSize, sSize)) {
3487+ throw new DimensionError(iSize, sSize, '>');
3488+ }
3489+
3490+ // offsets
3491+ var x0 = index.min()[0];
3492+ var y0 = index.min()[1];
3493+
3494+ // submatrix rows and columns
3495+ var m = sSize[0];
3496+ var n = sSize[1];
3497+
3498+ // loop submatrix
3499+ for (var x = 0; x < m; x++) {
3500+ // loop columns
3501+ for (var y = 0; y < n; y++) {
3502+ // value at i, j
3503+ var v = submatrix[x][y];
3504+ // invoke set (zero value will remove entry from matrix)
3505+ matrix.set([x + x0, y + y0], v, defaultValue);
3506+ }
3507+ }
3508+ }
3509+ return matrix;
3510+ };
3511+
3512+ /**
3513+ * Get a single element from the matrix.
3514+ * @param {Number[]} index Zero-based index
3515+ * @return {*} value
3516+ */
3517+ CrsMatrix.prototype.get = function (index) {
3518+ if (!isArray(index))
3519+ throw new TypeError('Array expected');
3520+ if (index.length != this._size.length)
3521+ throw new DimensionError(index.length, this._size.length);
3522+
3523+ // row and column
3524+ var i = index[0];
3525+ var j = index[1];
3526+
3527+ // check i, j are valid
3528+ validateIndex(i, this._size[0]);
3529+ validateIndex(j, this._size[1]);
3530+
3531+ // find value index
3532+ var k = _getValueIndex(j, this._ptr[i], this._ptr[i + 1], this._index);
3533+ // check k is prior to next row k and it is in the correct row
3534+ if (k < this._ptr[i + 1] && this._index[k] === j)
3535+ return object.clone(this._values[k]);
3536+
3537+ return 0;
3538+ };
3539+
3540+ /**
3541+ * Replace a single element in the matrix.
3542+ * @param {Number[]} index Zero-based index
3543+ * @param {*} value
3544+ * @param {*} [defaultValue] Default value, filled in on new entries when
3545+ * the matrix is resized. If not provided,
3546+ * new matrix elements will be set to zero.
3547+ * @return {CrsMatrix} self
3548+ */
3549+ CrsMatrix.prototype.set = function (index, v, defaultValue) {
3550+ if (!isArray(index))
3551+ throw new TypeError('Array expected');
3552+ if (index.length != this._size.length)
3553+ throw new DimensionError(index.length, this._size.length);
3554+
3555+ // row and column
3556+ var i = index[0];
3557+ var j = index[1];
3558+
3559+ // rows & columns
3560+ var rows = this._size[0];
3561+ var columns = this._size[1];
3562+
3563+ // check we need to resize matrix
3564+ if (i > rows - 1 || j > columns - 1) {
3565+ // resize matrix
3566+ _resize(this, Math.max(i + 1, rows), Math.max(j + 1, columns), defaultValue);
3567+ // update rows & columns
3568+ rows = this._size[0];
3569+ columns = this._size[1];
3570+ }
3571+
3572+ // check i, j are valid
3573+ validateIndex(i, rows);
3574+ validateIndex(j, columns);
3575+
3576+ // find value index
3577+ var k = _getValueIndex(j, this._ptr[i], this._ptr[i + 1], this._index);
3578+ // check k is prior to next row k and it is in the correct column
3579+ if (k < this._ptr[i + 1] && this._index[k] === j) {
3580+ // check value != 0
3581+ if (!math.equal(v, 0)) {
3582+ // update value
3583+ this._values[k] = v;
3584+ }
3585+ else {
3586+ // remove value from matrix
3587+ _remove(k, i, this._values, this._index, this._ptr);
3588+ }
3589+ }
3590+ else {
3591+ // insert value @ (i, j)
3592+ _insert(k, i, j, v, this._values, this._index, this._ptr);
3593+ }
3594+
3595+ return this;
3596+ };
3597+
3598+ var _getValueIndex = function(j, left, right, index) {
3599+ // check column is on the right side
3600+ if (right - left === 0 || j > index[right - 1])
3601+ return right;
3602+ // loop until we find row index
3603+ while (left < right) {
3604+ // point in the middle (fast integer division)
3605+ var p = ~~((left + right) / 2);
3606+ // column @ p
3607+ var c = index[p];
3608+ // check we have to look on the left side, right side or we found the column
3609+ if (j < c)
3610+ right = p;
3611+ else if (j > c)
3612+ left = p + 1;
3613+ else
3614+ return p;
3615+ }
3616+ return left;
3617+ };
3618+
3619+ var _remove = function (k, i, values, index, ptr) {
3620+ // remove value @ k
3621+ values.splice(k, 1);
3622+ index.splice(k, 1);
3623+ // update pointers
3624+ for (var x = i + 1; x < ptr.length; x++)
3625+ ptr[x]--;
3626+ };
3627+
3628+ var _insert = function (k, i, j, v, values, index, ptr) {
3629+ // insert value
3630+ values.splice(k, 0, v);
3631+ // update column for k
3632+ index.splice(k, 0, j);
3633+ // update row pointers
3634+ for (var x = i + 1; x < ptr.length; x++)
3635+ ptr[x]++;
3636+ };
3637+
3638+ /**
3639+ * Resize the matrix to the given size. Returns a copy of the matrix when
3640+ * `copy=true`, otherwise return the matrix itself (resize in place).
3641+ *
3642+ * @param {Number[]} size The new size the matrix should have.
3643+ * @param {*} [defaultValue=0] Default value, filled in on new entries.
3644+ * If not provided, the matrix elements will
3645+ * be filled with zeros.
3646+ * @param {boolean} [copy] Return a resized copy of the matrix
3647+ *
3648+ * @return {Matrix} The resized matrix
3649+ */
3650+ CrsMatrix.prototype.resize = function (size, defaultValue, copy) {
3651+ // validate arguments
3652+ if (!isArray(size))
3653+ throw new TypeError('Array expected');
3654+ if (size.length !== 2)
3655+ throw new Error('Only two dimensions matrix are supported');
3656+
3657+ // check sizes
3658+ size.forEach(function (value) {
3659+ if (!number.isNumber(value) || !number.isInteger(value) || value < 0) {
3660+ throw new TypeError('Invalid size, must contain positive integers ' +
3661+ '(size: ' + string.format(size) + ')');
3662+ }
3663+ });
3664+
3665+ // matrix to resize
3666+ var m = copy ? this.clone() : this;
3667+ // resize matrix
3668+ return _resize(m, size[0], size[1], defaultValue);
3669+ };
3670+
3671+ var _resize = function (matrix, rows, columns, defaultValue) {
3672+ // value to insert at the time of growing matrix
3673+ var value = defaultValue || 0;
3674+ // should we insert the value?
3675+ var ins = !math.equal(value, 0);
3676+
3677+ // old columns and rows
3678+ var r = matrix._size[0];
3679+ var c = matrix._size[1];
3680+
3681+ var i, j, k;
3682+
3683+ // check we need to increase rows
3684+ if (rows > r) {
3685+ // loop new rows
3686+ for (i = r; i < rows; i++) {
3687+ // update matrix._ptr for current column
3688+ matrix._ptr[i] = matrix._values.length;
3689+ // check we need to insert matrix._values
3690+ if (ins) {
3691+ // loop columns
3692+ for (j = 0; j < c; j++) {
3693+ // add new matrix._values
3694+ matrix._values.push(value);
3695+ // update matrix._index
3696+ matrix._index.push(j);
3697+ }
3698+ }
3699+ }
3700+ // store number of matrix._values in matrix._ptr
3701+ matrix._ptr[rows] = matrix._values.length;
3702+ }
3703+ else if (rows < r) {
3704+ // truncate matrix._ptr
3705+ matrix._ptr.splice(rows + 1, r - rows);
3706+ // truncate matrix._values and matrix._index
3707+ matrix._values.splice(matrix._ptr[rows], matrix._values.length);
3708+ matrix._index.splice(matrix._ptr[rows], matrix._index.length);
3709+ }
3710+ // update rows
3711+ r = rows;
3712+
3713+ // check we need to increase columns
3714+ if (columns > c) {
3715+ // check we have to insert values
3716+ if (ins) {
3717+ // inserts
3718+ var n = 0;
3719+ // loop rows
3720+ for (i = 0; i < r; i++) {
3721+ // update matrix._ptr for current row
3722+ matrix._ptr[i] = matrix._ptr[i] + n;
3723+ // where to insert matrix._values
3724+ k = matrix._ptr[i + 1] + n;
3725+ // pointer
3726+ var p = 0;
3727+ // loop new columns, initialize pointer
3728+ for (j = c; j < columns; j++, p++) {
3729+ // add value
3730+ matrix._values.splice(k + p, 0, value);
3731+ // update matrix._index
3732+ matrix._index.splice(k + p, 0, j);
3733+ // increment inserts
3734+ n++;
3735+ }
3736+ }
3737+ // store number of matrix._values in matrix._ptr
3738+ matrix._ptr[r] = matrix._values.length;
3739+ }
3740+ }
3741+ else if (columns < c) {
3742+ // deletes
3743+ var d = 0;
3744+ // loop rows
3745+ for (i = 0; i < r; i++) {
3746+ // update matrix._ptr for current row
3747+ matrix._ptr[i] = matrix._ptr[i] - d;
3748+ // where matrix._values start for next column
3749+ var k0 = matrix._ptr[i];
3750+ var k1 = matrix._ptr[i + 1] - d;
3751+ // loop matrix._index
3752+ for (k = k0; k < k1; k++) {
3753+ // column
3754+ j = matrix._index[k];
3755+ // check we need to delete value and matrix._index
3756+ if (j > columns - 1) {
3757+ // remove value
3758+ matrix._values.splice(k, 1);
3759+ // remove item from matrix._index
3760+ matrix._index.splice(k, 1);
3761+ // increase deletes
3762+ d++;
3763+ }
3764+ }
3765+ }
3766+ // update matrix._ptr for current column
3767+ matrix._ptr[i] = matrix._values.length;
3768+ }
3769+ // update matrix._size
3770+ matrix._size[0] = rows;
3771+ matrix._size[1] = columns;
3772+ // return matrix
3773+ return matrix;
3774+ };
3775+
3776+ /**
3777+ * Create a clone of the matrix
3778+ * @return {CrsMatrix} clone
3779+ */
3780+ CrsMatrix.prototype.clone = function () {
3781+ var m = new CrsMatrix({
3782+ values: object.clone(this._values),
3783+ index: object.clone(this._index),
3784+ ptr: object.clone(this._ptr),
3785+ size: object.clone(this._size)
3786+ });
3787+ return m;
3788+ };
3789+
3790+ /**
3791+ * Retrieve the size of the matrix.
3792+ * @returns {Number[]} size
3793+ */
3794+ CrsMatrix.prototype.size = function() {
3795+ return object.clone(this._size);
3796+ };
3797+
3798+ /**
3799+ * Create a new matrix with the results of the callback function executed on
3800+ * each entry of the matrix.
3801+ * @param {function} callback The callback function is invoked with three
3802+ * parameters: the value of the element, the index
3803+ * of the element, and the Matrix being traversed.
3804+ * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
3805+ *
3806+ * @return {Matrix} matrix
3807+ */
3808+ CrsMatrix.prototype.map = function (callback, skipZeros) {
3809+ // matrix instance
3810+ var me = this;
3811+ // rows and columns
3812+ var rows = this._size[0];
3813+ var columns = this._size[1];
3814+ // invoke callback
3815+ var invoke = function (v, i, j) {
3816+ // invoke callback
3817+ return callback(v, [i, j], me);
3818+ };
3819+ // invoke _map
3820+ return _map(this, 0, rows - 1, 0, columns - 1, invoke, skipZeros);
3821+ };
3822+
3823+ /**
3824+ * Create a new matrix with the results of the callback function executed on the interval
3825+ * [minRow..maxRow, minColumn..maxColumn].
3826+ */
3827+ var _map = function (matrix, minRow, maxRow, minColumn, maxColumn, callback, skipZeros) {
3828+ // result arrays
3829+ var values = [];
3830+ var index = [];
3831+ var ptr = [];
3832+ // invoke callback
3833+ var invoke = function (v, x, y) {
3834+ // invoke callback
3835+ v = callback(v, x, y);
3836+ // check value != 0
3837+ if (!math.equal(v, 0)) {
3838+ // store value
3839+ values.push(v);
3840+ // index
3841+ index.push(y);
3842+ }
3843+ };
3844+ // loop rows
3845+ for (var i = minRow; i <= maxRow; i++) {
3846+ // store pointer to values index
3847+ ptr.push(values.length);
3848+ // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
3849+ var k0 = matrix._ptr[i];
3850+ var k1 = matrix._ptr[i + 1];
3851+ // column pointer
3852+ var p = minColumn;
3853+ // loop k within [k0, k1[
3854+ for (var k = k0; k < k1; k++) {
3855+ // column index
3856+ var j = matrix._index[k];
3857+ // check j is in range
3858+ if (j >= minColumn && j <= maxColumn) {
3859+ // zero values
3860+ if (!skipZeros) {
3861+ // write zeros from column p to j
3862+ for (var x = p; x < j; x++)
3863+ invoke(0, i - minRow, x - minColumn);
3864+ }
3865+ // value @ k
3866+ invoke(matrix._values[k], i - minRow, j - minColumn);
3867+ }
3868+ // update pointer
3869+ p = j + 1;
3870+ }
3871+ // zero values
3872+ if (!skipZeros) {
3873+ // write zeros from column p to maxColumn
3874+ for (var y = p; y <= maxColumn; y++)
3875+ invoke(0, i - minRow, y - minColumn);
3876+ }
3877+ }
3878+ // store number of values in ptr
3879+ ptr.push(values.length);
3880+ // return ccs
3881+ return new CrsMatrix({
3882+ values: values,
3883+ index: index,
3884+ ptr: ptr,
3885+ size: [maxRow - minRow + 1, maxColumn - minColumn + 1]
3886+ });
3887+ };
3888+
3889+ /**
3890+ * Execute a callback function on each entry of the matrix.
3891+ * @param {function} callback The callback function is invoked with three
3892+ * parameters: the value of the element, the index
3893+ * of the element, and the Matrix being traversed.
3894+ * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
3895+ */
3896+ CrsMatrix.prototype.forEach = function (callback, skipZeros) {
3897+ // matrix instance
3898+ var me = this;
3899+ // rows and columns
3900+ var rows = this._size[0];
3901+ var columns = this._size[1];
3902+ // loop rows
3903+ for (var i = 0; i < rows; i++) {
3904+ // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
3905+ var k0 = this._ptr[i];
3906+ var k1 = this._ptr[i + 1];
3907+ // column pointer
3908+ var p = 0;
3909+ // loop k within [k0, k1[
3910+ for (var k = k0; k < k1; k++) {
3911+ // column index
3912+ var j = this._index[k];
3913+ // check we need to process zeros
3914+ if (!skipZeros) {
3915+ // zero values
3916+ for (var x = p; x < j; x++)
3917+ callback(0, [i, x], me);
3918+ }
3919+ // value @ k
3920+ callback(this._values[k], [i, j], me);
3921+ // update pointer
3922+ p = j + 1;
3923+ }
3924+ // check we need to process zeros
3925+ if (!skipZeros) {
3926+ // zero values
3927+ for (var y = p; y < columns; y++)
3928+ callback(0, [i, y], me);
3929+ }
3930+ }
3931+ };
3932+
3933+ /**
3934+ * Create an Array with a copy of the data of the CrsMatrix
3935+ * @returns {Array} array
3936+ */
3937+ CrsMatrix.prototype.toArray = function () {
3938+ return _toArray(this, true);
3939+ };
3940+
3941+ /**
3942+ * Get the primitive value of the CrsMatrix: a two dimensions array
3943+ * @returns {Array} array
3944+ */
3945+ CrsMatrix.prototype.valueOf = function () {
3946+ return _toArray(this, false);
3947+ };
3948+
3949+ var _toArray = function (matrix, copy) {
3950+ // result
3951+ var a = [];
3952+ // rows and columns
3953+ var rows = matrix._size[0];
3954+ var columns = matrix._size[1];
3955+ // loop rows
3956+ for (var i = 0; i < rows; i++) {
3957+ // push row
3958+ var r = a[i] = [];
3959+ // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
3960+ var k0 = matrix._ptr[i];
3961+ var k1 = matrix._ptr[i + 1];
3962+ // column pointer
3963+ var p = 0;
3964+ // loop k is within [k0, k1[
3965+ for (var k = k0; k < k1; k++) {
3966+ // column index
3967+ var j = matrix._index[k];
3968+ // zero values
3969+ for (var x = p; x < j; x++)
3970+ r[x] = 0;
3971+ // set value
3972+ r[j] = copy ? object.clone(matrix._values[k]) : matrix._values[k];
3973+ // update pointer
3974+ p = j + 1;
3975+ }
3976+ // zero values
3977+ for (var y = p; y < columns; y++)
3978+ r[y] = 0;
3979+ }
3980+ return a;
3981+ };
3982+
3983+ /**
3984+ * Get a string representation of the matrix, with optional formatting options.
3985+ * @param {Object | Number | Function} [options] Formatting options. See
3986+ * lib/util/number:format for a
3987+ * description of the available
3988+ * options.
3989+ * @returns {String} str
3990+ */
3991+ CrsMatrix.prototype.format = function (options) {
3992+ // rows and columns
3993+ var rows = this._size[0];
3994+ var columns = this._size[1];
3995+ // rows & columns
3996+ var str = 'CRS [' + string.format(rows, options) + ' x ' + string.format(columns, options) + '] density: ' + string.format(this._values.length / (rows * columns), options) + '\n';
3997+ // loop rows
3998+ for (var i = 0; i < rows; i++) {
3999+ // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
4000+ var k0 = this._ptr[i];
4001+ var k1 = this._ptr[i + 1];
4002+ // loop k within [k0, k1[
4003+ for (var k = k0; k < k1; k++) {
4004+ // column index
4005+ var j = this._index[k];
4006+ // append value
4007+ str += '\n (' + string.format(i, options) + ', ' + string.format(j, options) + ') ==> ' + string.format(this._values[k], options);
4008+ }
4009+ }
4010+ return str;
4011+ };
4012+
4013+ /**
4014+ * Get a string representation of the matrix
4015+ * @returns {String} str
4016+ */
4017+ CrsMatrix.prototype.toString = function () {
4018+ return string.format(this.toArray());
4019+ };
4020+
4021+ /**
4022+ * Get a JSON representation of the matrix
4023+ * @returns {Object}
4024+ */
4025+ CrsMatrix.prototype.toJSON = function () {
4026+ return {
4027+ mathjs: 'CrsMatrix',
4028+ values: this._values,
4029+ index: this._index,
4030+ ptr: this._ptr,
4031+ size: this._size
4032+ };
4033+ };
4034+
4035+ /**
4036+ * Calculates the transpose of the matrix
4037+ * @returns {Matrix}
4038+ */
4039+ CrsMatrix.prototype.transpose = function () {
4040+ // rows and columns
4041+ var rows = this._size[0];
4042+ var columns = this._size[1];
4043+ // check columns
4044+ if (columns === 0) {
4045+ // throw exception
4046+ throw new RangeError('Cannot transpose a 2D matrix with no columns (size: ' + string.format(this._size) + ')');
4047+ }
4048+ // crs transpose is a ccs matrix with the same structure
4049+ return new math.type.CcsMatrix({
4050+ values: object.clone(this._values),
4051+ index: object.clone(this._index),
4052+ ptr: object.clone(this._ptr),
4053+ size: [columns, rows]
4054+ });
4055+ };
4056+
4057+ /**
4058+ * Get the kth Matrix diagonal.
4059+ *
4060+ * @param {Number | BigNumber} [k=0] The kth diagonal where the vector will retrieved.
4061+ *
4062+ * @returns {Array} The array vector with the diagonal values.
4063+ */
4064+ CrsMatrix.prototype.diagonal = function(k) {
4065+ // validate k if any
4066+ if (k) {
4067+ // convert BigNumber to a number
4068+ if (k instanceof BigNumber)
4069+ k = k.toNumber();
4070+ // is must be an integer
4071+ if (!isNumber(k) || !isInteger(k)) {
4072+ throw new TypeError ('The parameter k must be an integer number');
4073+ }
4074+ }
4075+ else {
4076+ // default value
4077+ k = 0;
4078+ }
4079+
4080+ var kSuper = k > 0 ? k : 0;
4081+ var kSub = k < 0 ? -k : 0;
4082+
4083+ // rows & columns
4084+ var rows = this._size[0];
4085+ var columns = this._size[1];
4086+
4087+ // number diagonal values
4088+ var n = Math.min(rows - kSub, columns - kSuper);
4089+
4090+ // diagonal
4091+ var values = [];
4092+ // loop rows
4093+ for (var i = kSub; i < rows && values.length < n; i++) {
4094+ // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
4095+ var k0 = this._ptr[i];
4096+ var k1 = this._ptr[i + 1];
4097+ // row value flag
4098+ var rv = false;
4099+ // loop x within [k0, k1[
4100+ for (var x = k0; x < k1; x++) {
4101+ // column index
4102+ var j = this._index[x];
4103+ // check column
4104+ if (j === i + kSuper - kSub) {
4105+ // set flag
4106+ rv = true;
4107+ // value on this column
4108+ values.push(object.clone(this._values[x]));
4109+ // exit loop
4110+ break;
4111+ }
4112+ else if (j > i + kSuper - kSub) {
4113+ // exit loop, no value on the diagonal for row i
4114+ break;
4115+ }
4116+ }
4117+ // check this row has a value set
4118+ if (!rv && values.length < n) {
4119+ // zero on this column
4120+ values.push(0);
4121+ }
4122+ }
4123+ return values;
4124+ };
4125+
4126+ /**
4127+ * Generate a matrix from a JSON object
4128+ * @param {Object} json An object structured like
4129+ * `{"mathjs": "CrsMatrix", "values": [], "index": [], "ptr": [], "size": []}`,
4130+ * where mathjs is optional
4131+ * @returns {CrsMatrix}
4132+ */
4133+ CrsMatrix.fromJSON = function (json) {
4134+ return new CrsMatrix(json);
4135+ };
4136+
4137+ /**
4138+ * Create a diagonal matrix.
4139+ *
4140+ * @param {Array} size The matrix size.
4141+ * @param {Number, Array} value The values for the diagonal.
4142+ * @param {Number | BigNumber} [k=0] The kth diagonal where the vector will be filled in.
4143+ *
4144+ * @returns {CrsMatrix}
4145+ */
4146+ CrsMatrix.diagonal = function (size, value, k) {
4147+ if (!isArray(size))
4148+ throw new TypeError('Array expected, size parameter');
4149+ if (size.length !== 2)
4150+ throw new Error('Only two dimensions matrix are supported');
4151+
4152+ // map size & validate
4153+ size = size.map(function (s) {
4154+ // check it is a big number
4155+ if (s instanceof BigNumber) {
4156+ // convert it
4157+ s = s.toNumber();
4158+ }
4159+ // validate arguments
4160+ if (!isNumber(s) || !isInteger(s) || s < 1) {
4161+ throw new Error('Size values must be positive integers');
4162+ }
4163+ return s;
4164+ });
4165+
4166+ // validate k if any
4167+ if (k) {
4168+ // convert BigNumber to a number
4169+ if (k instanceof BigNumber)
4170+ k = k.toNumber();
4171+ // is must be an integer
4172+ if (!isNumber(k) || !isInteger(k)) {
4173+ throw new TypeError ('The parameter k must be an integer number');
4174+ }
4175+ }
4176+ else {
4177+ // default value
4178+ k = 0;
4179+ }
4180+
4181+ var kSuper = k > 0 ? k : 0;
4182+ var kSub = k < 0 ? -k : 0;
4183+
4184+ // rows and columns
4185+ var rows = size[0];
4186+ var columns = size[1];
4187+
4188+ // number of non-zero items
4189+ var n = Math.min(rows - kSub, columns - kSuper);
4190+
4191+ // value extraction function
4192+ var _value;
4193+
4194+ // check value
4195+ if (isArray(value)) {
4196+ // validate array
4197+ if (value.length !== n) {
4198+ // number of values in array must be n
4199+ throw new Error('Invalid value array length');
4200+ }
4201+ // define function
4202+ _value = function (i) {
4203+ // return value @ i
4204+ return value[i];
4205+ };
4206+ }
4207+ else {
4208+ // define function
4209+ _value = function () {
4210+ // return value
4211+ return value;
4212+ };
4213+ }
4214+
4215+ // create arrays
4216+ var values = [];
4217+ var index = [];
4218+ var ptr = [];
4219+
4220+ // loop items
4221+ for (var i = 0; i < rows; i++) {
4222+ // number of rows with value
4223+ ptr.push(values.length);
4224+ // diagonal index
4225+ var j = i - kSub;
4226+ // check we need to set diagonal value
4227+ if (j >= 0 && j < n) {
4228+ // get value @ j
4229+ var v = _value(j);
4230+ // check for zero
4231+ if (!math.equal(v, 0)) {
4232+ // column
4233+ index.push(j + kSuper);
4234+ // add value
4235+ values.push(v);
4236+ }
4237+ }
4238+ }
4239+ // last value should be number of values
4240+ ptr.push(values.length);
4241+ // create CrsMatrix
4242+ return new CrsMatrix({
4243+ values: values,
4244+ index: index,
4245+ ptr: ptr,
4246+ size: [rows, columns]
4247+ });
4248+ };
4249+
4250+ /**
4251+ * Calculate the trace of a matrix: the sum of the elements on the main
4252+ * diagonal of a square matrix.
4253+ *
4254+ * See also:
4255+ *
4256+ * diagonal
4257+ *
4258+ * @returns {Number} The matrix trace
4259+ */
4260+ CrsMatrix.prototype.trace = function () {
4261+ // size
4262+ var size = this._size;
4263+ // check dimensions
4264+ var rows = size[0];
4265+ var columns = size[1];
4266+ // matrix must be square
4267+ if (rows === columns) {
4268+ // calulate sum
4269+ var sum = 0;
4270+ // check we have data (avoid looping rows)
4271+ if (this._values.length > 0) {
4272+ // loop rows
4273+ for (var i = 0; i < rows; i++) {
4274+ // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
4275+ var k0 = this._ptr[i];
4276+ var k1 = this._ptr[i + 1];
4277+ // loop k within [k0, k1[
4278+ for (var k = k0; k < k1; k++) {
4279+ // column index
4280+ var j = this._index[k];
4281+ // check row
4282+ if (i === j) {
4283+ // accumulate value
4284+ sum = math.add(sum, this._values[k]);
4285+ // exit loop
4286+ break;
4287+ }
4288+ if (j > i) {
4289+ // exit loop, no value on the diagonal for column j
4290+ break;
4291+ }
4292+ }
4293+ }
4294+ }
4295+ // return trace
4296+ return sum;
4297+ }
4298+ throw new RangeError('Matrix must be square (size: ' + string.format(size) + ')');
4299+ };
4300+
4301+ /**
4302+ * Multiply the matrix values times the argument.
4303+ *
4304+ * @param {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} Value to multiply.
4305+ *
4306+ * @return {Number | BigNumber | Complex | Unit | Matrix}
4307+ */
4308+ CrsMatrix.prototype.multiply = function (value) {
4309+ // check dimensions
4310+ var rows = this._size[0];
4311+ var columns = this._size[1];
4312+
4313+ // check value is a matrix
4314+ if (value instanceof Matrix) {
4315+ // matrix size
4316+ var z = value.size();
4317+ // check value is a vector
4318+ if (z.length === 1) {
4319+ // mutiply matrix x vector array
4320+ return _multiply(this, z[0], 1, function (i) {
4321+ // value[i]
4322+ return value.get([i]);
4323+ });
4324+ }
4325+ // check two dimensions matrix
4326+ if (z.length === 2) {
4327+ // mutiply matrix x matrix
4328+ return _multiply(this, z[0], z[1], function (i, j) {
4329+ // value[i, j]
4330+ return value.get([i, j]);
4331+ });
4332+ }
4333+ throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
4334+ '(value has ' + z.length + ' dimensions)');
4335+ }
4336+
4337+ // check value is an array
4338+ if (isArray(value)) {
4339+ // array size
4340+ var s = array.size(value);
4341+ // check value is a vector
4342+ if (s.length === 1) {
4343+ // mutiply matrix x vector array
4344+ return _multiply(this, s[0], 1, function (i) {
4345+ // value[i]
4346+ return value[i];
4347+ });
4348+ }
4349+ if (s.length === 2) {
4350+ // mutiply matrix x array
4351+ return _multiply(this, s[0], s[1], function (i, j) {
4352+ // value[i, j]
4353+ return value[i][j];
4354+ });
4355+ }
4356+ throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
4357+ '(value has ' + s.length + ' dimensions)');
4358+ }
4359+
4360+ var callback = function (v) {
4361+ return math.multiply(v, value);
4362+ };
4363+
4364+ // map non zero elements
4365+ return _map(this, 0, rows - 1, 0, columns - 1, callback, false);
4366+ };
4367+
4368+ var _multiply = function (matrix, r, c, get) {
4369+
4370+ // matrix dimensions
4371+ var rows = matrix._size[0];
4372+ var columns = matrix._size[1];
4373+
4374+ // check dimensions match
4375+ if (columns !== r) {
4376+ // throw error
4377+ throw new RangeError('Dimension mismatch in multiplication. ' +
4378+ 'Columns of A must match length of B ' +
4379+ '(A is ' + rows + 'x' + columns +
4380+ ', B is ' + r + ', ' +
4381+ columns + ' != ' + r + ')');
4382+ }
4383+
4384+ // result arrays
4385+ var values = [];
4386+ var index = [];
4387+ var ptr = [];
4388+
4389+ // loop rows
4390+ for (var i = 0; i < rows; i++) {
4391+ // update ptr
4392+ ptr.push(values.length);
4393+ // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
4394+ var k0 = matrix._ptr[i];
4395+ var k1 = matrix._ptr[i + 1];
4396+ // loop value columns
4397+ for (var z = 0; z < c; z++) {
4398+ // value @ (i, x)
4399+ var value = 0;
4400+ // loop k within [k0, k1[
4401+ for (var k = k0; k < k1; k++) {
4402+ // column
4403+ var j = matrix._index[k];
4404+ // multiply & aggregate
4405+ value = math.add(value, math.multiply(matrix._values[k], get(j, z)));
4406+ }
4407+ // check value is different than zero
4408+ if (!math.equal(value, 0)) {
4409+ // push value & column
4410+ values.push(value);
4411+ index.push(z);
4412+ }
4413+ }
4414+ }
4415+ // update ptr
4416+ ptr.push(values.length);
4417+
4418+ // check we need to squeeze the result into a scalar
4419+ if (rows === 1 && c === 1)
4420+ return values.length === 1 ? values[0] : 0;
4421+
4422+ // return CRS matrix
4423+ return new CrsMatrix({
4424+ values: values,
4425+ index: index,
4426+ ptr: ptr,
4427+ size: [rows, c]
4428+ });
4429+ };
4430+
4431+ return CrsMatrix;
4432+ };
4433+
4434+/***/ },
4435+/* 17 */
4436+/***/ function(module, exports, __webpack_require__) {
4437+
4438+ 'use strict';
4439+
4440+ var util = __webpack_require__(175);
4441+ var DimensionError = __webpack_require__(172);
4442+
4443+ var string = util.string;
4444+ var array = util.array;
4445+ var object = util.object;
4446+
4447+ var isArray = Array.isArray;
4448+ var isNumber = util.number.isNumber;
4449+ var isInteger = util.number.isInteger;
4450+
4451+ var validateIndex = array.validateIndex;
4452+
4453+ module.exports = function (math) {
4454+
4455+ var Index = math.type.Index,
4456+ BigNumber = math.type.BigNumber,
4457+ Matrix = math.type.Matrix;
4458+
4459+ function DenseMatrix(data) {
4460+ if (!(this instanceof DenseMatrix))
4461+ throw new SyntaxError('Constructor must be called with the new operator');
4462+
4463+ if (data instanceof Matrix) {
4464+ // check data is a DenseMatrix
4465+ if (data.type === 'DenseMatrix') {
4466+ // clone data & size
4467+ this._data = object.clone(data._data);
4468+ this._size = object.clone(data._size);
4469+ }
4470+ else {
4471+ // build data from existing matrix
4472+ this._data = data.toArray();
4473+ this._size = data.size();
4474+ }
4475+ }
4476+ else if (data && isArray(data.data) && isArray(data.size)) {
4477+ // initialize fields from JSON representation
4478+ this._data = data.data;
4479+ this._size = data.size;
4480+ }
4481+ else if (isArray(data)) {
4482+ // replace nested Matrices with Arrays
4483+ this._data = preprocess(data);
4484+ // verify the size of the array, TODO: compute size while processing array
4485+ this._size = array.size(this._data);
4486+ }
4487+ else if (data) {
4488+ // unsupported type
4489+ throw new TypeError('Unsupported type of data (' + util.types.type(data) + ')');
4490+ }
4491+ else {
4492+ // nothing provided
4493+ this._data = [];
4494+ this._size = [0];
4495+ }
4496+ }
4497+
4498+ DenseMatrix.prototype = new math.type.Matrix();
4499+
4500+ DenseMatrix.prototype.type = 'DenseMatrix';
4501+
4502+ /**
4503+ * Get the storage format used by the matrix.
4504+ *
4505+ * Usage:
4506+ * var format = matrix.storage() // retrieve storage format
4507+ *
4508+ * @return {string} The storage format.
4509+ */
4510+ DenseMatrix.prototype.storage = function () {
4511+ return 'dense';
4512+ };
4513+
4514+ /**
4515+ * Get a subset of the matrix, or replace a subset of the matrix.
4516+ *
4517+ * Usage:
4518+ * var subset = matrix.subset(index) // retrieve subset
4519+ * var value = matrix.subset(index, replacement) // replace subset
4520+ *
4521+ * @param {Index} index
4522+ * @param {Array | DenseMatrix | *} [replacement]
4523+ * @param {*} [defaultValue=0] Default value, filled in on new entries when
4524+ * the matrix is resized. If not provided,
4525+ * new matrix elements will be filled with zeros.
4526+ */
4527+ DenseMatrix.prototype.subset = function (index, replacement, defaultValue) {
4528+ switch (arguments.length) {
4529+ case 1:
4530+ return _get(this, index);
4531+
4532+ // intentional fall through
4533+ case 2:
4534+ case 3:
4535+ return _set(this, index, replacement, defaultValue);
4536+
4537+ default:
4538+ throw new SyntaxError('Wrong number of arguments');
4539+ }
4540+ };
4541+
4542+ /**
4543+ * Get a single element from the matrix.
4544+ * @param {Number[]} index Zero-based index
4545+ * @return {*} value
4546+ */
4547+ DenseMatrix.prototype.get = function (index) {
4548+ if (!isArray(index))
4549+ throw new TypeError('Array expected');
4550+ if (index.length != this._size.length)
4551+ throw new DimensionError(index.length, this._size.length);
4552+
4553+ // check index
4554+ for (var x = 0; x < index.length; x++)
4555+ validateIndex(index[x], this._size[x]);
4556+
4557+ var data = this._data;
4558+ for (var i = 0, ii = index.length; i < ii; i++) {
4559+ var index_i = index[i];
4560+ validateIndex(index_i, data.length);
4561+ data = data[index_i];
4562+ }
4563+
4564+ return object.clone(data);
4565+ };
4566+
4567+ /**
4568+ * Replace a single element in the matrix.
4569+ * @param {Number[]} index Zero-based index
4570+ * @param {*} value
4571+ * @param {*} [defaultValue] Default value, filled in on new entries when
4572+ * the matrix is resized. If not provided,
4573+ * new matrix elements will be left undefined.
4574+ * @return {DenseMatrix} self
4575+ */
4576+ DenseMatrix.prototype.set = function (index, value, defaultValue) {
4577+ if (!isArray(index))
4578+ throw new TypeError('Array expected');
4579+ if (index.length < this._size.length)
4580+ throw new DimensionError(index.length, this._size.length, '<');
4581+
4582+ var i, ii, index_i;
4583+
4584+ // enlarge matrix when needed
4585+ var size = index.map(function (i) {
4586+ return i + 1;
4587+ });
4588+ _fit(this, size, defaultValue);
4589+
4590+ // traverse over the dimensions
4591+ var data = this._data;
4592+ for (i = 0, ii = index.length - 1; i < ii; i++) {
4593+ index_i = index[i];
4594+ validateIndex(index_i, data.length);
4595+ data = data[index_i];
4596+ }
4597+
4598+ // set new value
4599+ index_i = index[index.length - 1];
4600+ validateIndex(index_i, data.length);
4601+ data[index_i] = value;
4602+
4603+ return this;
4604+ };
4605+
4606+ /**
4607+ * Get a submatrix of this matrix
4608+ * @param {DenseMatrix} matrix
4609+ * @param {Index} index Zero-based index
4610+ * @private
4611+ */
4612+ function _get (matrix, index) {
4613+ if (!(index instanceof Index)) {
4614+ throw new TypeError('Invalid index');
4615+ }
4616+
4617+ var isScalar = index.isScalar();
4618+ if (isScalar) {
4619+ // return a scalar
4620+ return matrix.get(index.min());
4621+ }
4622+ else {
4623+ // validate dimensions
4624+ var size = index.size();
4625+ if (size.length != matrix._size.length) {
4626+ throw new DimensionError(size.length, matrix._size.length);
4627+ }
4628+
4629+ // validate if any of the ranges in the index is out of range
4630+ var min = index.min();
4631+ var max = index.max();
4632+ for (var i = 0, ii = matrix._size.length; i < ii; i++) {
4633+ validateIndex(min[i], matrix._size[i]);
4634+ validateIndex(max[i], matrix._size[i]);
4635+ }
4636+
4637+ // retrieve submatrix
4638+ // TODO: more efficient when creating an empty matrix and setting _data and _size manually
4639+ return new DenseMatrix(_getSubmatrix(matrix._data, index, size.length, 0));
4640+ }
4641+ }
4642+
4643+ /**
4644+ * Recursively get a submatrix of a multi dimensional matrix.
4645+ * Index is not checked for correct number or length of dimensions.
4646+ * @param {Array} data
4647+ * @param {Index} index
4648+ * @param {number} dims Total number of dimensions
4649+ * @param {number} dim Current dimension
4650+ * @return {Array} submatrix
4651+ * @private
4652+ */
4653+ function _getSubmatrix (data, index, dims, dim) {
4654+ var last = (dim == dims - 1);
4655+ var range = index.range(dim);
4656+
4657+ if (last) {
4658+ return range.map(function (i) {
4659+ return data[i];
4660+ });
4661+ }
4662+ else {
4663+ return range.map(function (i) {
4664+ var child = data[i];
4665+ return _getSubmatrix(child, index, dims, dim + 1);
4666+ });
4667+ }
4668+ }
4669+
4670+ /**
4671+ * Replace a submatrix in this matrix
4672+ * Indexes are zero-based.
4673+ * @param {DenseMatrix} matrix
4674+ * @param {Index} index
4675+ * @param {DenseMatrix | Array | *} submatrix
4676+ * @param {*} defaultValue Default value, filled in on new entries when
4677+ * the matrix is resized.
4678+ * @return {DenseMatrix} matrix
4679+ * @private
4680+ */
4681+ function _set (matrix, index, submatrix, defaultValue) {
4682+ if (!(index instanceof Index)) {
4683+ throw new TypeError('Invalid index');
4684+ }
4685+
4686+ // get index size and check whether the index contains a single value
4687+ var iSize = index.size(),
4688+ isScalar = index.isScalar();
4689+
4690+ // calculate the size of the submatrix, and convert it into an Array if needed
4691+ var sSize;
4692+ if (submatrix instanceof math.type.Matrix) {
4693+ sSize = submatrix.size();
4694+ submatrix = submatrix.valueOf();
4695+ }
4696+ else {
4697+ sSize = array.size(submatrix);
4698+ }
4699+
4700+ if (isScalar) {
4701+ // set a scalar
4702+
4703+ // check whether submatrix is a scalar
4704+ if (sSize.length !== 0) {
4705+ throw new TypeError('Scalar expected');
4706+ }
4707+
4708+ matrix.set(index.min(), submatrix, defaultValue);
4709+ }
4710+ else {
4711+ // set a submatrix
4712+
4713+ // validate dimensions
4714+ if (iSize.length < matrix._size.length) {
4715+ throw new DimensionError(iSize.length, matrix._size.length, '<');
4716+ }
4717+
4718+ if (sSize.length < iSize.length) {
4719+ // calculate number of missing outer dimensions
4720+ var i = 0;
4721+ var outer = 0;
4722+ while (iSize[i] === 1 && sSize[i] === 1) {
4723+ i++;
4724+ }
4725+ while (iSize[i] === 1) {
4726+ outer++;
4727+ i++;
4728+ }
4729+
4730+ // unsqueeze both outer and inner dimensions
4731+ submatrix = array.unsqueeze(submatrix, iSize.length, outer, sSize);
4732+ }
4733+
4734+ // check whether the size of the submatrix matches the index size
4735+ if (!object.deepEqual(iSize, sSize)) {
4736+ throw new DimensionError(iSize, sSize, '>');
4737+ }
4738+
4739+ // enlarge matrix when needed
4740+ var size = index.max().map(function (i) {
4741+ return i + 1;
4742+ });
4743+ _fit(matrix, size, defaultValue);
4744+
4745+ // insert the sub matrix
4746+ var dims = iSize.length,
4747+ dim = 0;
4748+ _setSubmatrix (matrix._data, index, submatrix, dims, dim);
4749+ }
4750+
4751+ return matrix;
4752+ }
4753+
4754+ /**
4755+ * Replace a submatrix of a multi dimensional matrix.
4756+ * @param {Array} data
4757+ * @param {Index} index
4758+ * @param {Array} submatrix
4759+ * @param {number} dims Total number of dimensions
4760+ * @param {number} dim
4761+ * @private
4762+ */
4763+ function _setSubmatrix (data, index, submatrix, dims, dim) {
4764+ var last = (dim == dims - 1),
4765+ range = index.range(dim);
4766+
4767+ if (last) {
4768+ range.forEach(function (dataIndex, subIndex) {
4769+ validateIndex(dataIndex);
4770+ data[dataIndex] = submatrix[subIndex];
4771+ });
4772+ }
4773+ else {
4774+ range.forEach(function (dataIndex, subIndex) {
4775+ validateIndex(dataIndex);
4776+ _setSubmatrix(data[dataIndex], index, submatrix[subIndex], dims, dim + 1);
4777+ });
4778+ }
4779+ }
4780+
4781+ /**
4782+ * Resize the matrix to the given size. Returns a copy of the matrix when
4783+ * `copy=true`, otherwise return the matrix itself (resize in place).
4784+ *
4785+ * @param {Number[]} size The new size the matrix should have.
4786+ * @param {*} [defaultValue=0] Default value, filled in on new entries.
4787+ * If not provided, the matrix elements will
4788+ * be filled with zeros.
4789+ * @param {boolean} [copy] Return a resized copy of the matrix
4790+ *
4791+ * @return {Matrix} The resized matrix
4792+ */
4793+ DenseMatrix.prototype.resize = function (size, defaultValue, copy) {
4794+ // validate arguments
4795+ if (!isArray(size))
4796+ throw new TypeError('Array expected');
4797+
4798+ // matrix to resize
4799+ var m = copy ? this.clone() : this;
4800+ // resize matrix
4801+ return _resize(m, size, defaultValue);
4802+ };
4803+
4804+ var _resize = function (matrix, size, defaultValue) {
4805+ // check size
4806+ if (size.length === 0) {
4807+ // first value in matrix
4808+ var v = matrix._data;
4809+ // go deep
4810+ while (isArray(v)) {
4811+ v = v[0];
4812+ }
4813+ return object.clone(v);
4814+ }
4815+ // resize matrix
4816+ matrix._size = object.clone(size);
4817+ matrix._data = array.resize(matrix._data, matrix._size, defaultValue);
4818+ // return matrix
4819+ return matrix;
4820+ };
4821+
4822+ /**
4823+ * Enlarge the matrix when it is smaller than given size.
4824+ * If the matrix is larger or equal sized, nothing is done.
4825+ * @param {DenseMatrix} matrix The matrix to be resized
4826+ * @param {Number[]} size
4827+ * @param {*} defaultValue Default value, filled in on new entries.
4828+ * @private
4829+ */
4830+ function _fit(matrix, size, defaultValue) {
4831+ var newSize = object.clone(matrix._size),
4832+ changed = false;
4833+
4834+ // add dimensions when needed
4835+ while (newSize.length < size.length) {
4836+ newSize.push(0);
4837+ changed = true;
4838+ }
4839+
4840+ // enlarge size when needed
4841+ for (var i = 0, ii = size.length; i < ii; i++) {
4842+ if (size[i] > newSize[i]) {
4843+ newSize[i] = size[i];
4844+ changed = true;
4845+ }
4846+ }
4847+
4848+ if (changed) {
4849+ // resize only when size is changed
4850+ _resize(matrix, newSize, defaultValue);
4851+ }
4852+ }
4853+
4854+ /**
4855+ * Create a clone of the matrix
4856+ * @return {DenseMatrix} clone
4857+ */
4858+ DenseMatrix.prototype.clone = function () {
4859+ var m = new DenseMatrix({
4860+ data: object.clone(this._data),
4861+ size: object.clone(this._size)
4862+ });
4863+ return m;
4864+ };
4865+
4866+ /**
4867+ * Retrieve the size of the matrix.
4868+ * @returns {Number[]} size
4869+ */
4870+ DenseMatrix.prototype.size = function() {
4871+ return this._size;
4872+ };
4873+
4874+ /**
4875+ * Create a new matrix with the results of the callback function executed on
4876+ * each entry of the matrix.
4877+ * @param {function} callback The callback function is invoked with three
4878+ * parameters: the value of the element, the index
4879+ * of the element, and the Matrix being traversed.
4880+ *
4881+ * @return {DenseMatrix} matrix
4882+ */
4883+ DenseMatrix.prototype.map = function (callback) {
4884+ // matrix instance
4885+ var me = this;
4886+ var recurse = function (value, index) {
4887+ if (isArray(value)) {
4888+ return value.map(function (child, i) {
4889+ return recurse(child, index.concat(i));
4890+ });
4891+ }
4892+ else {
4893+ return callback(value, index, me);
4894+ }
4895+ };
4896+ // return dense format
4897+ return new DenseMatrix({
4898+ data: recurse(this._data, []),
4899+ size: object.clone(this._size)
4900+ });
4901+ };
4902+
4903+ /**
4904+ * Execute a callback function on each entry of the matrix.
4905+ * @param {function} callback The callback function is invoked with three
4906+ * parameters: the value of the element, the index
4907+ * of the element, and the Matrix being traversed.
4908+ */
4909+ DenseMatrix.prototype.forEach = function (callback) {
4910+ // matrix instance
4911+ var me = this;
4912+ var recurse = function (value, index) {
4913+ if (isArray(value)) {
4914+ value.forEach(function (child, i) {
4915+ recurse(child, index.concat(i));
4916+ });
4917+ }
4918+ else {
4919+ callback(value, index, me);
4920+ }
4921+ };
4922+ recurse(this._data, []);
4923+ };
4924+
4925+ /**
4926+ * Create an Array with a copy of the data of the DenseMatrix
4927+ * @returns {Array} array
4928+ */
4929+ DenseMatrix.prototype.toArray = function () {
4930+ return object.clone(this._data);
4931+ };
4932+
4933+ /**
4934+ * Get the primitive value of the DenseMatrix: a multidimensional array
4935+ * @returns {Array} array
4936+ */
4937+ DenseMatrix.prototype.valueOf = function () {
4938+ return this._data;
4939+ };
4940+
4941+ /**
4942+ * Get a string representation of the matrix, with optional formatting options.
4943+ * @param {Object | Number | Function} [options] Formatting options. See
4944+ * lib/util/number:format for a
4945+ * description of the available
4946+ * options.
4947+ * @returns {String} str
4948+ */
4949+ DenseMatrix.prototype.format = function (options) {
4950+ return string.format(this._data, options);
4951+ };
4952+
4953+ /**
4954+ * Get a string representation of the matrix
4955+ * @returns {String} str
4956+ */
4957+ DenseMatrix.prototype.toString = function () {
4958+ return string.format(this._data);
4959+ };
4960+
4961+ /**
4962+ * Get a JSON representation of the matrix
4963+ * @returns {Object}
4964+ */
4965+ DenseMatrix.prototype.toJSON = function () {
4966+ return {
4967+ mathjs: 'DenseMatrix',
4968+ data: this._data,
4969+ size: this._size
4970+ };
4971+ };
4972+
4973+ /**
4974+ * Calculates the transpose of the matrix
4975+ * @returns {Matrix}
4976+ */
4977+ DenseMatrix.prototype.transpose = function () {
4978+ // check dimensions
4979+ switch (this._size.length) {
4980+ case 1:
4981+ // vector
4982+ return this.clone();
4983+ case 2:
4984+ // rows and columns
4985+ var rows = this._size[0];
4986+ var columns = this._size[1];
4987+ // check columns
4988+ if (columns === 0) {
4989+ // throw exception
4990+ throw new RangeError('Cannot transpose a 2D matrix with no columns (size: ' + string.format(this._size) + ')');
4991+ }
4992+ // transposed matrix data
4993+ var transposed = [];
4994+ var transposedRow;
4995+ // loop columns
4996+ for (var j = 0; j < columns; j++) {
4997+ // initialize row
4998+ transposedRow = transposed[j] = [];
4999+ // loop rows
5000+ for (var i = 0; i < rows; i++) {
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches