UNPKG

6.91 kBJavaScriptView Raw
1import { isArray, isMatrix, isString, typeOf } from '../../utils/is'
2import { clone } from '../../utils/object'
3import { factory } from '../../utils/factory'
4
5const name = 'ImmutableDenseMatrix'
6const dependencies = [
7 'smaller',
8 'DenseMatrix'
9]
10
11export const createImmutableDenseMatrixClass = /* #__PURE__ */ factory(name, dependencies, ({ smaller, DenseMatrix }) => {
12 function ImmutableDenseMatrix (data, datatype) {
13 if (!(this instanceof ImmutableDenseMatrix)) { throw new SyntaxError('Constructor must be called with the new operator') }
14 if (datatype && !isString(datatype)) { throw new Error('Invalid datatype: ' + datatype) }
15
16 if (isMatrix(data) || isArray(data)) {
17 // use DenseMatrix implementation
18 const matrix = new DenseMatrix(data, datatype)
19 // internal structures
20 this._data = matrix._data
21 this._size = matrix._size
22 this._datatype = matrix._datatype
23 this._min = null
24 this._max = null
25 } else if (data && isArray(data.data) && isArray(data.size)) {
26 // initialize fields from JSON representation
27 this._data = data.data
28 this._size = data.size
29 this._datatype = data.datatype
30 this._min = typeof data.min !== 'undefined' ? data.min : null
31 this._max = typeof data.max !== 'undefined' ? data.max : null
32 } else if (data) {
33 // unsupported type
34 throw new TypeError('Unsupported type of data (' + typeOf(data) + ')')
35 } else {
36 // nothing provided
37 this._data = []
38 this._size = [0]
39 this._datatype = datatype
40 this._min = null
41 this._max = null
42 }
43 }
44
45 ImmutableDenseMatrix.prototype = new DenseMatrix()
46
47 /**
48 * Attach type information
49 */
50 ImmutableDenseMatrix.prototype.type = 'ImmutableDenseMatrix'
51 ImmutableDenseMatrix.prototype.isImmutableDenseMatrix = true
52
53 /**
54 * Get a subset of the matrix, or replace a subset of the matrix.
55 *
56 * Usage:
57 * const subset = matrix.subset(index) // retrieve subset
58 * const value = matrix.subset(index, replacement) // replace subset
59 *
60 * @param {Index} index
61 * @param {Array | ImmutableDenseMatrix | *} [replacement]
62 * @param {*} [defaultValue=0] Default value, filled in on new entries when
63 * the matrix is resized. If not provided,
64 * new matrix elements will be filled with zeros.
65 */
66 ImmutableDenseMatrix.prototype.subset = function (index) {
67 switch (arguments.length) {
68 case 1:
69 {
70 // use base implementation
71 const m = DenseMatrix.prototype.subset.call(this, index)
72 // check result is a matrix
73 if (isMatrix(m)) {
74 // return immutable matrix
75 return new ImmutableDenseMatrix({
76 data: m._data,
77 size: m._size,
78 datatype: m._datatype
79 })
80 }
81 return m
82 }
83 // intentional fall through
84 case 2:
85 case 3:
86 throw new Error('Cannot invoke set subset on an Immutable Matrix instance')
87
88 default:
89 throw new SyntaxError('Wrong number of arguments')
90 }
91 }
92
93 /**
94 * Replace a single element in the matrix.
95 * @param {Number[]} index Zero-based index
96 * @param {*} value
97 * @param {*} [defaultValue] Default value, filled in on new entries when
98 * the matrix is resized. If not provided,
99 * new matrix elements will be left undefined.
100 * @return {ImmutableDenseMatrix} self
101 */
102 ImmutableDenseMatrix.prototype.set = function () {
103 throw new Error('Cannot invoke set on an Immutable Matrix instance')
104 }
105
106 /**
107 * Resize the matrix to the given size. Returns a copy of the matrix when
108 * `copy=true`, otherwise return the matrix itself (resize in place).
109 *
110 * @param {Number[]} size The new size the matrix should have.
111 * @param {*} [defaultValue=0] Default value, filled in on new entries.
112 * If not provided, the matrix elements will
113 * be filled with zeros.
114 * @param {boolean} [copy] Return a resized copy of the matrix
115 *
116 * @return {Matrix} The resized matrix
117 */
118 ImmutableDenseMatrix.prototype.resize = function () {
119 throw new Error('Cannot invoke resize on an Immutable Matrix instance')
120 }
121
122 /**
123 * Disallows reshaping in favor of immutability.
124 *
125 * @throws {Error} Operation not allowed
126 */
127 ImmutableDenseMatrix.prototype.reshape = function () {
128 throw new Error('Cannot invoke reshape on an Immutable Matrix instance')
129 }
130
131 /**
132 * Create a clone of the matrix
133 * @return {ImmutableDenseMatrix} clone
134 */
135 ImmutableDenseMatrix.prototype.clone = function () {
136 return new ImmutableDenseMatrix({
137 data: clone(this._data),
138 size: clone(this._size),
139 datatype: this._datatype
140 })
141 }
142
143 /**
144 * Get a JSON representation of the matrix
145 * @returns {Object}
146 */
147 ImmutableDenseMatrix.prototype.toJSON = function () {
148 return {
149 mathjs: 'ImmutableDenseMatrix',
150 data: this._data,
151 size: this._size,
152 datatype: this._datatype
153 }
154 }
155
156 /**
157 * Generate a matrix from a JSON object
158 * @param {Object} json An object structured like
159 * `{"mathjs": "ImmutableDenseMatrix", data: [], size: []}`,
160 * where mathjs is optional
161 * @returns {ImmutableDenseMatrix}
162 */
163 ImmutableDenseMatrix.fromJSON = function (json) {
164 return new ImmutableDenseMatrix(json)
165 }
166
167 /**
168 * Swap rows i and j in Matrix.
169 *
170 * @param {Number} i Matrix row index 1
171 * @param {Number} j Matrix row index 2
172 *
173 * @return {Matrix} The matrix reference
174 */
175 ImmutableDenseMatrix.prototype.swapRows = function () {
176 throw new Error('Cannot invoke swapRows on an Immutable Matrix instance')
177 }
178
179 /**
180 * Calculate the minimum value in the set
181 * @return {Number | undefined} min
182 */
183 ImmutableDenseMatrix.prototype.min = function () {
184 // check min has been calculated before
185 if (this._min === null) {
186 // minimum
187 let m = null
188 // compute min
189 this.forEach(function (v) {
190 if (m === null || smaller(v, m)) { m = v }
191 })
192 this._min = m !== null ? m : undefined
193 }
194 return this._min
195 }
196
197 /**
198 * Calculate the maximum value in the set
199 * @return {Number | undefined} max
200 */
201 ImmutableDenseMatrix.prototype.max = function () {
202 // check max has been calculated before
203 if (this._max === null) {
204 // maximum
205 let m = null
206 // compute max
207 this.forEach(function (v) {
208 if (m === null || smaller(m, v)) { m = v }
209 })
210 this._max = m !== null ? m : undefined
211 }
212 return this._max
213 }
214
215 return ImmutableDenseMatrix
216}, { isClass: true })