Merge lp:~gang65/ubuntu-calculator-app/reboot-upgrade-math-js-to-1.5 into lp:ubuntu-calculator-app
- reboot-upgrade-math-js-to-1.5
- Merge into trunk
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 | ||||
Related bugs: |
|
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
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:152
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 153. By Bartosz Kosiorek
-
Upgrade math.js to 1.5.1 to fix regression
Bartosz Kosiorek (gang65) wrote : | # |
I upgraded to fixed math.js version 1.5.1.
Now everything should be fine.
- 154. By Bartosz Kosiorek
-
Comment fix
Bartosz Kosiorek (gang65) : | # |
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:154
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 155. By Bartosz Kosiorek
-
Upgrade math.js to 1.5.2
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:155
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Riccardo Padovani (rpadovani) wrote : | # |
Looks good to me, thanks :-)
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) : | # |
Preview Diff
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++) { |
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: /github. com/josdejong/ mathjs/ issues/ 319
https:/