• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

google / vector_math.dart / 14778564080

01 May 2025 03:57PM UTC coverage: 26.388% (+0.02%) from 26.372%
14778564080

push

github

web-flow
Improve performance of functions with dynamic arguments (#345)

* Deprecated functions with dynamic arguments
* Bump version, update changelog

54 of 164 new or added lines in 8 files covered. (32.93%)

5 existing lines in 2 files now uncovered.

4335 of 16428 relevant lines covered (26.39%)

1.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

51.42
/lib/src/vector_math/matrix2.dart
1
// Copyright (c) 2015, Google Inc. Please see the AUTHORS file for details.
2
// All rights reserved. Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4

5
part of '../../vector_math.dart';
6

7
/// 2D Matrix.
8
/// Values are stored in column major order.
9
class Matrix2 {
10
  final Float32List _m2storage;
11

12
  /// The components of the matrix.
13
  Float32List get storage => _m2storage;
4✔
14

15
  /// Solve [A] * [x] = [b].
16
  static void solve(Matrix2 A, Vector2 x, Vector2 b) {
1✔
17
    final a11 = A.entry(0, 0);
1✔
18
    final a12 = A.entry(0, 1);
1✔
19
    final a21 = A.entry(1, 0);
1✔
20
    final a22 = A.entry(1, 1);
1✔
21
    final bx = b.x;
1✔
22
    final by = b.y;
1✔
23
    var det = a11 * a22 - a12 * a21;
3✔
24

25
    if (det != 0.0) {
1✔
26
      det = 1.0 / det;
1✔
27
    }
28

29
    x
30
      ..x = det * (a22 * bx - a12 * by)
5✔
31
      ..y = det * (a11 * by - a21 * bx);
5✔
32
  }
33

34
  /// Return index in storage for [row], [col] value.
35
  int index(int row, int col) => (col * 2) + row;
3✔
36

37
  /// Value at [row], [col].
38
  double entry(int row, int col) {
1✔
39
    assert((row >= 0) && (row < dimension));
4✔
40
    assert((col >= 0) && (col < dimension));
4✔
41

42
    return _m2storage[index(row, col)];
3✔
43
  }
44

45
  /// Set value at [row], [col] to be [v].
46
  void setEntry(int row, int col, double v) {
×
47
    assert((row >= 0) && (row < dimension));
×
48
    assert((col >= 0) && (col < dimension));
×
49

50
    _m2storage[index(row, col)] = v;
×
51
  }
52

53
  /// New matrix with specified values.
54
  factory Matrix2(double arg0, double arg1, double arg2, double arg3) =>
1✔
55
      Matrix2.zero()..setValues(arg0, arg1, arg2, arg3);
2✔
56

57
  /// New matrix from [values].
58
  factory Matrix2.fromList(List<double> values) =>
1✔
59
      Matrix2.zero()..setValues(values[0], values[1], values[2], values[3]);
6✔
60

61
  /// Zero matrix.
62
  Matrix2.zero() : _m2storage = Float32List(4);
4✔
63

64
  /// Identity matrix.
65
  factory Matrix2.identity() => Matrix2.zero()..setIdentity();
3✔
66

67
  /// Copies values from [other].
68
  factory Matrix2.copy(Matrix2 other) => Matrix2.zero()..setFrom(other);
6✔
69

70
  /// Matrix with values from column arguments.
71
  factory Matrix2.columns(Vector2 arg0, Vector2 arg1) =>
×
72
      Matrix2.zero()..setColumns(arg0, arg1);
×
73

74
  /// Outer product of [u] and [v].
75
  factory Matrix2.outer(Vector2 u, Vector2 v) => Matrix2.zero()..setOuter(u, v);
×
76

77
  /// Rotation of [radians].
78
  factory Matrix2.rotation(double radians) =>
2✔
79
      Matrix2.zero()..setRotation(radians);
4✔
80

81
  /// Sets the matrix with specified values.
82
  void setValues(double arg0, double arg1, double arg2, double arg3) {
1✔
83
    _m2storage[3] = arg3;
2✔
84
    _m2storage[2] = arg2;
2✔
85
    _m2storage[1] = arg1;
2✔
86
    _m2storage[0] = arg0;
2✔
87
  }
88

89
  /// Sets the entire matrix to the column values.
90
  void setColumns(Vector2 arg0, Vector2 arg1) {
×
91
    final arg0Storage = arg0._v2storage;
×
92
    final arg1Storage = arg1._v2storage;
×
93
    _m2storage[0] = arg0Storage[0];
×
94
    _m2storage[1] = arg0Storage[1];
×
95
    _m2storage[2] = arg1Storage[0];
×
96
    _m2storage[3] = arg1Storage[1];
×
97
  }
98

99
  /// Sets the entire matrix to the matrix in [arg].
100
  void setFrom(Matrix2 arg) {
2✔
101
    final argStorage = arg._m2storage;
2✔
102
    _m2storage[3] = argStorage[3];
6✔
103
    _m2storage[2] = argStorage[2];
6✔
104
    _m2storage[1] = argStorage[1];
6✔
105
    _m2storage[0] = argStorage[0];
6✔
106
  }
107

108
  /// Set this to the outer product of [u] and [v].
109
  void setOuter(Vector2 u, Vector2 v) {
×
110
    final uStorage = u._v2storage;
×
111
    final vStorage = v._v2storage;
×
112
    _m2storage[0] = uStorage[0] * vStorage[0];
×
113
    _m2storage[1] = uStorage[0] * vStorage[1];
×
114
    _m2storage[2] = uStorage[1] * vStorage[0];
×
115
    _m2storage[3] = uStorage[1] * vStorage[1];
×
116
  }
117

118
  /// Sets the diagonal to [arg].
119
  void splatDiagonal(double arg) {
×
120
    _m2storage[0] = arg;
×
121
    _m2storage[3] = arg;
×
122
  }
123

124
  /// Sets the diagonal of the matrix to be [arg].
125
  void setDiagonal(Vector2 arg) {
×
126
    final argStorage = arg._v2storage;
×
127
    _m2storage[0] = argStorage[0];
×
128
    _m2storage[3] = argStorage[1];
×
129
  }
130

131
  /// Returns a printable string
132
  @override
1✔
133
  String toString() => '[0] ${getRow(0)}\n[1] ${getRow(1)}\n';
3✔
134

135
  /// Dimension of the matrix.
136
  int get dimension => 2;
1✔
137

138
  /// Access the element of the matrix at the index [i].
139
  double operator [](int i) => _m2storage[i];
×
140

141
  /// Set the element of the matrix at the index [i].
142
  void operator []=(int i, double v) {
1✔
143
    _m2storage[i] = v;
2✔
144
  }
145

146
  /// Check if two matrices are the same.
147
  @override
1✔
148
  bool operator ==(Object other) =>
149
      (other is Matrix2) &&
1✔
150
      (_m2storage[0] == other._m2storage[0]) &&
5✔
151
      (_m2storage[1] == other._m2storage[1]) &&
5✔
152
      (_m2storage[2] == other._m2storage[2]) &&
5✔
153
      (_m2storage[3] == other._m2storage[3]);
5✔
154

155
  @override
1✔
156
  int get hashCode => Object.hashAll(_m2storage);
2✔
157

158
  /// Returns row 0
159
  Vector2 get row0 => getRow(0);
×
160

161
  /// Returns row 1
162
  Vector2 get row1 => getRow(1);
×
163

164
  /// Sets row 0 to [arg]
165
  set row0(Vector2 arg) => setRow(0, arg);
×
166

167
  /// Sets row 1 to [arg]
168
  set row1(Vector2 arg) => setRow(1, arg);
×
169

170
  /// Sets [row] of the matrix to values in [arg]
171
  void setRow(int row, Vector2 arg) {
×
172
    final argStorage = arg._v2storage;
×
173
    _m2storage[index(row, 0)] = argStorage[0];
×
174
    _m2storage[index(row, 1)] = argStorage[1];
×
175
  }
176

177
  /// Gets the [row] of the matrix
178
  Vector2 getRow(int row) {
1✔
179
    final r = Vector2.zero();
1✔
180
    final rStorage = r._v2storage;
1✔
181
    rStorage[0] = _m2storage[index(row, 0)];
4✔
182
    rStorage[1] = _m2storage[index(row, 1)];
4✔
183
    return r;
184
  }
185

186
  /// Assigns the [column] of the matrix [arg]
187
  void setColumn(int column, Vector2 arg) {
×
188
    final argStorage = arg._v2storage;
×
189
    final entry = column * 2;
×
190
    _m2storage[entry + 1] = argStorage[1];
×
191
    _m2storage[entry + 0] = argStorage[0];
×
192
  }
193

194
  /// Gets the [column] of the matrix
195
  Vector2 getColumn(int column) {
×
196
    final r = Vector2.zero();
×
197
    final entry = column * 2;
×
198
    final rStorage = r._v2storage;
×
199
    rStorage[1] = _m2storage[entry + 1];
×
200
    rStorage[0] = _m2storage[entry + 0];
×
201
    return r;
202
  }
203

204
  /// Create a copy of this.
205
  Matrix2 clone() => Matrix2.copy(this);
4✔
206

207
  /// Copy this into [arg].
208
  Matrix2 copyInto(Matrix2 arg) {
×
209
    final argStorage = arg._m2storage;
×
210
    argStorage[0] = _m2storage[0];
×
211
    argStorage[1] = _m2storage[1];
×
212
    argStorage[2] = _m2storage[2];
×
213
    argStorage[3] = _m2storage[3];
×
214
    return arg;
215
  }
216

217
  /// Returns a new vector or matrix by multiplying this with [arg].
218
  @pragma('wasm:prefer-inline')
1✔
219
  @pragma('vm:prefer-inline')
220
  @pragma('dart2js:prefer-inline')
221
  dynamic operator *(dynamic arg) {
222
    final Object result;
223
    if (arg is double) {
1✔
NEW
224
      result = scaled(arg);
×
225
    } else if (arg is Vector2) {
1✔
226
      result = transformed(arg);
1✔
NEW
227
    } else if (arg is Matrix2) {
×
NEW
228
      result = multiplied(arg);
×
229
    } else {
NEW
230
      throw ArgumentError(arg);
×
231
    }
232
    return result;
233
  }
234

235
  /// Returns new matrix after component wise this + [arg]
236
  Matrix2 operator +(Matrix2 arg) => clone()..add(arg);
×
237

238
  /// Returns new matrix after component wise this - [arg]
239
  Matrix2 operator -(Matrix2 arg) => clone()..sub(arg);
3✔
240

241
  /// Returns new matrix -this
242
  Matrix2 operator -() => clone()..negate();
×
243

244
  /// Zeros this.
245
  void setZero() {
×
246
    _m2storage[0] = 0.0;
×
247
    _m2storage[1] = 0.0;
×
248
    _m2storage[2] = 0.0;
×
249
    _m2storage[3] = 0.0;
×
250
  }
251

252
  /// Makes this into the identity matrix.
253
  void setIdentity() {
1✔
254
    _m2storage[0] = 1.0;
2✔
255
    _m2storage[1] = 0.0;
2✔
256
    _m2storage[2] = 0.0;
2✔
257
    _m2storage[3] = 1.0;
2✔
258
  }
259

260
  /// Returns the tranpose of this.
261
  Matrix2 transposed() => clone()..transpose();
6✔
262

263
  void transpose() {
2✔
264
    final temp = _m2storage[2];
4✔
265
    _m2storage[2] = _m2storage[1];
8✔
266
    _m2storage[1] = temp;
4✔
267
  }
268

269
  /// Returns the component wise absolute value of this.
270
  Matrix2 absolute() {
×
271
    final r = Matrix2.zero();
×
272
    final rStorage = r._m2storage;
×
273
    rStorage[0] = _m2storage[0].abs();
×
274
    rStorage[1] = _m2storage[1].abs();
×
275
    rStorage[2] = _m2storage[2].abs();
×
276
    rStorage[3] = _m2storage[3].abs();
×
277
    return r;
278
  }
279

280
  /// Returns the determinant of this matrix.
281
  double determinant() =>
2✔
282
      (_m2storage[0] * _m2storage[3]) - (_m2storage[1] * _m2storage[2]);
22✔
283

284
  /// Returns the dot product of row [i] and [v].
285
  double dotRow(int i, Vector2 v) {
1✔
286
    final vStorage = v._v2storage;
1✔
287
    return _m2storage[i] * vStorage[0] + _m2storage[2 + i] * vStorage[1];
10✔
288
  }
289

290
  /// Returns the dot product of column [j] and [v].
291
  double dotColumn(int j, Vector2 v) {
1✔
292
    final vStorage = v._v2storage;
1✔
293
    return _m2storage[j * 2] * vStorage[0] +
6✔
294
        _m2storage[(j * 2) + 1] * vStorage[1];
6✔
295
  }
296

297
  /// Trace of the matrix.
298
  double trace() {
×
299
    var t = 0.0;
300
    t += _m2storage[0];
×
301
    t += _m2storage[3];
×
302
    return t;
303
  }
304

305
  /// Returns infinity norm of the matrix. Used for numerical analysis.
306
  double infinityNorm() {
1✔
307
    var norm = 0.0;
308
    {
309
      var rowNorm = 0.0;
310
      rowNorm += _m2storage[0].abs();
4✔
311
      rowNorm += _m2storage[1].abs();
4✔
312
      norm = rowNorm > norm ? rowNorm : norm;
1✔
313
    }
314
    {
315
      var rowNorm = 0.0;
316
      rowNorm += _m2storage[2].abs();
4✔
317
      rowNorm += _m2storage[3].abs();
4✔
318
      norm = rowNorm > norm ? rowNorm : norm;
1✔
319
    }
320
    return norm;
321
  }
322

323
  /// Returns relative error between this and [correct]
324
  double relativeError(Matrix2 correct) {
1✔
325
    final diff = correct - this;
1✔
326
    final correctNorm = correct.infinityNorm();
1✔
327
    final diff_norm = diff.infinityNorm();
1✔
328
    return diff_norm / correctNorm;
1✔
329
  }
330

331
  /// Returns absolute error between this and [correct]
332
  double absoluteError(Matrix2 correct) {
×
333
    final this_norm = infinityNorm();
×
334
    final correct_norm = correct.infinityNorm();
×
335
    final diff_norm = (this_norm - correct_norm).abs();
×
336
    return diff_norm;
337
  }
338

339
  /// Invert the matrix. Returns the determinant.
340
  double invert() {
1✔
341
    final det = determinant();
1✔
342
    if (det == 0.0) {
1✔
343
      return 0.0;
344
    }
345
    final invDet = 1.0 / det;
1✔
346
    final temp = _m2storage[0];
2✔
347
    _m2storage[0] = _m2storage[3] * invDet;
5✔
348
    _m2storage[1] = -_m2storage[1] * invDet;
6✔
349
    _m2storage[2] = -_m2storage[2] * invDet;
6✔
350
    _m2storage[3] = temp * invDet;
3✔
351
    return det;
352
  }
353

354
  /// Set this matrix to be the inverse of [arg]
355
  double copyInverse(Matrix2 arg) {
1✔
356
    final det = arg.determinant();
1✔
357
    if (det == 0.0) {
1✔
358
      setFrom(arg);
×
359
      return 0.0;
360
    }
361
    final invDet = 1.0 / det;
1✔
362
    final argStorage = arg._m2storage;
1✔
363
    _m2storage[0] = argStorage[3] * invDet;
4✔
364
    _m2storage[1] = -argStorage[1] * invDet;
5✔
365
    _m2storage[2] = -argStorage[2] * invDet;
5✔
366
    _m2storage[3] = argStorage[0] * invDet;
4✔
367
    return det;
368
  }
369

370
  /// Turns the matrix into a rotation of [radians]
371
  void setRotation(double radians) {
2✔
372
    final c = math.cos(radians);
2✔
373
    final s = math.sin(radians);
2✔
374
    _m2storage[0] = c;
4✔
375
    _m2storage[1] = s;
4✔
376
    _m2storage[2] = -s;
6✔
377
    _m2storage[3] = c;
4✔
378
  }
379

380
  /// Converts into Adjugate matrix and scales by [scale]
381
  void scaleAdjoint(double scale) {
1✔
382
    final temp = _m2storage[0];
2✔
383
    _m2storage[0] = _m2storage[3] * scale;
5✔
384
    _m2storage[2] = -_m2storage[2] * scale;
6✔
385
    _m2storage[1] = -_m2storage[1] * scale;
6✔
386
    _m2storage[3] = temp * scale;
3✔
387
  }
388

389
  /// Scale this by [scale].
390
  void scale(double scale) {
1✔
391
    _m2storage[0] = _m2storage[0] * scale;
5✔
392
    _m2storage[1] = _m2storage[1] * scale;
5✔
393
    _m2storage[2] = _m2storage[2] * scale;
5✔
394
    _m2storage[3] = _m2storage[3] * scale;
5✔
395
  }
396

397
  /// Create a copy of this scaled by [scale].
398
  Matrix2 scaled(double scale) => clone()..scale(scale);
3✔
399

400
  /// Add [o] to this.
401
  void add(Matrix2 o) {
×
402
    final oStorage = o._m2storage;
×
403
    _m2storage[0] = _m2storage[0] + oStorage[0];
×
404
    _m2storage[1] = _m2storage[1] + oStorage[1];
×
405
    _m2storage[2] = _m2storage[2] + oStorage[2];
×
406
    _m2storage[3] = _m2storage[3] + oStorage[3];
×
407
  }
408

409
  /// Subtract [o] from this.
410
  void sub(Matrix2 o) {
1✔
411
    final oStorage = o._m2storage;
1✔
412
    _m2storage[0] = _m2storage[0] - oStorage[0];
6✔
413
    _m2storage[1] = _m2storage[1] - oStorage[1];
6✔
414
    _m2storage[2] = _m2storage[2] - oStorage[2];
6✔
415
    _m2storage[3] = _m2storage[3] - oStorage[3];
6✔
416
  }
417

418
  /// Negate this.
419
  void negate() {
×
420
    _m2storage[0] = -_m2storage[0];
×
421
    _m2storage[1] = -_m2storage[1];
×
422
    _m2storage[2] = -_m2storage[2];
×
423
    _m2storage[3] = -_m2storage[3];
×
424
  }
425

426
  /// Multiply this with [arg] and store it in this.
427
  void multiply(Matrix2 arg) {
×
428
    final m00 = _m2storage[0];
×
429
    final m01 = _m2storage[2];
×
430
    final m10 = _m2storage[1];
×
431
    final m11 = _m2storage[3];
×
432
    final argStorage = arg._m2storage;
×
433
    final n00 = argStorage[0];
×
434
    final n01 = argStorage[2];
×
435
    final n10 = argStorage[1];
×
436
    final n11 = argStorage[3];
×
437
    _m2storage[0] = (m00 * n00) + (m01 * n10);
×
438
    _m2storage[2] = (m00 * n01) + (m01 * n11);
×
439
    _m2storage[1] = (m10 * n00) + (m11 * n10);
×
440
    _m2storage[3] = (m10 * n01) + (m11 * n11);
×
441
  }
442

443
  /// Multiply this with [arg] and return the product.
444
  Matrix2 multiplied(Matrix2 arg) => clone()..multiply(arg);
×
445

446
  /// Multiply a transposed this with [arg].
447
  void transposeMultiply(Matrix2 arg) {
×
448
    final m00 = _m2storage[0];
×
449
    final m01 = _m2storage[1];
×
450
    final m10 = _m2storage[2];
×
451
    final m11 = _m2storage[3];
×
452
    final argStorage = arg._m2storage;
×
453
    _m2storage[0] = (m00 * argStorage[0]) + (m01 * argStorage[1]);
×
454
    _m2storage[2] = (m00 * argStorage[2]) + (m01 * argStorage[3]);
×
455
    _m2storage[1] = (m10 * argStorage[0]) + (m11 * argStorage[1]);
×
456
    _m2storage[3] = (m10 * argStorage[2]) + (m11 * argStorage[3]);
×
457
  }
458

459
  /// Multiply this with a transposed [arg].
460
  void multiplyTranspose(Matrix2 arg) {
×
461
    final m00 = _m2storage[0];
×
462
    final m01 = _m2storage[2];
×
463
    final m10 = _m2storage[1];
×
464
    final m11 = _m2storage[3];
×
465
    final argStorage = arg._m2storage;
×
466
    _m2storage[0] = (m00 * argStorage[0]) + (m01 * argStorage[2]);
×
467
    _m2storage[2] = (m00 * argStorage[1]) + (m01 * argStorage[3]);
×
468
    _m2storage[1] = (m10 * argStorage[0]) + (m11 * argStorage[2]);
×
469
    _m2storage[3] = (m10 * argStorage[1]) + (m11 * argStorage[3]);
×
470
  }
471

472
  /// Transform [arg] of type [Vector2] using the transformation defined by
473
  /// this.
474
  Vector2 transform(Vector2 arg) {
2✔
475
    final argStorage = arg._v2storage;
2✔
476
    final x = (_m2storage[0] * argStorage[0]) + (_m2storage[2] * argStorage[1]);
18✔
477
    final y = (_m2storage[1] * argStorage[0]) + (_m2storage[3] * argStorage[1]);
18✔
478
    argStorage[0] = x;
2✔
479
    argStorage[1] = y;
2✔
480
    return arg;
481
  }
482

483
  /// Transform a copy of [arg] of type [Vector2] using the transformation
484
  /// defined by this. If a [out] parameter is supplied, the copy is stored in
485
  /// [out].
486
  Vector2 transformed(Vector2 arg, [Vector2? out]) {
2✔
487
    if (out == null) {
488
      out = Vector2.copy(arg);
2✔
489
    } else {
490
      out.setFrom(arg);
×
491
    }
492
    return transform(out);
2✔
493
  }
494

495
  /// Copies this into [array] starting at [offset].
496
  void copyIntoArray(List<num> array, [int offset = 0]) {
×
497
    final i = offset;
498
    array[i + 3] = _m2storage[3];
×
499
    array[i + 2] = _m2storage[2];
×
500
    array[i + 1] = _m2storage[1];
×
501
    array[i + 0] = _m2storage[0];
×
502
  }
503

504
  /// Copies elements from [array] into this starting at [offset].
505
  void copyFromArray(List<double> array, [int offset = 0]) {
×
506
    final i = offset;
507
    _m2storage[3] = array[i + 3];
×
508
    _m2storage[2] = array[i + 2];
×
509
    _m2storage[1] = array[i + 1];
×
510
    _m2storage[0] = array[i + 0];
×
511
  }
512
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc