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

google / vector_math.dart / 23308864078

19 Mar 2026 05:48PM UTC coverage: 27.129% (-0.06%) from 27.188%
23308864078

push

github

web-flow
Optimize creating an identity matrix (#365)

Since we're starting from zero, only update the needed elements

15 of 30 new or added lines in 6 files covered. (50.0%)

15 existing lines in 2 files now uncovered.

4440 of 16366 relevant lines covered (27.13%)

1.2 hits per line

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

0.0
/lib/src/vector_math_64/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_64.dart';
6

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

12
  /// The components of the matrix.
13
  Float64List get storage => _m2storage;
×
14

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

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

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

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

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

42
    return _m2storage[index(row, col)];
×
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) =>
×
55
      Matrix2.zero()..setValues(arg0, arg1, arg2, arg3);
×
56

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

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

64
  /// Identity matrix.
NEW
65
  factory Matrix2.identity() =>
×
NEW
66
      Matrix2.zero()
×
NEW
67
        .._m2storage[0] = 1.0
×
NEW
68
        .._m2storage[3] = 1.0;
×
69

70
  /// Copies values from [other].
71
  factory Matrix2.copy(Matrix2 other) => Matrix2.zero()..setFrom(other);
×
72

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

77
  /// Outer product of [u] and [v].
78
  factory Matrix2.outer(Vector2 u, Vector2 v) => Matrix2.zero()..setOuter(u, v);
×
79

80
  /// Rotation of [radians].
81
  factory Matrix2.rotation(double radians) =>
×
82
      Matrix2.zero()..setRotation(radians);
×
83

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

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

102
  /// Sets the entire matrix to the matrix in [arg].
103
  void setFrom(Matrix2 arg) {
×
104
    final argStorage = arg._m2storage;
×
105
    _m2storage[3] = argStorage[3];
×
106
    _m2storage[2] = argStorage[2];
×
107
    _m2storage[1] = argStorage[1];
×
108
    _m2storage[0] = argStorage[0];
×
109
  }
110

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

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

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

134
  /// Returns a printable string
135
  @override
×
136
  String toString() => '[0] ${getRow(0)}\n[1] ${getRow(1)}\n';
×
137

138
  /// Dimension of the matrix.
139
  int get dimension => 2;
×
140

141
  /// Access the element of the matrix at the index [i].
142
  double operator [](int i) => _m2storage[i];
×
143

144
  /// Set the element of the matrix at the index [i].
145
  void operator []=(int i, double v) {
×
146
    _m2storage[i] = v;
×
147
  }
148

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

158
  @override
×
159
  int get hashCode => Object.hashAll(_m2storage);
×
160

161
  /// Returns row 0
162
  Vector2 get row0 => getRow(0);
×
163

164
  /// Returns row 1
165
  Vector2 get row1 => getRow(1);
×
166

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

170
  /// Sets row 1 to [arg]
171
  set row1(Vector2 arg) => setRow(1, arg);
×
172

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

180
  /// Gets the [row] of the matrix
181
  Vector2 getRow(int row) {
×
182
    final r = Vector2.zero();
×
183
    final rStorage = r._v2storage;
×
184
    rStorage[0] = _m2storage[index(row, 0)];
×
185
    rStorage[1] = _m2storage[index(row, 1)];
×
186
    return r;
187
  }
188

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

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

207
  /// Create a copy of this.
208
  Matrix2 clone() => Matrix2.copy(this);
×
209

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

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

238
  /// Returns new matrix after component wise this + [arg]
239
  Matrix2 operator +(Matrix2 arg) => clone()..add(arg);
×
240

241
  /// Returns new matrix after component wise this - [arg]
242
  Matrix2 operator -(Matrix2 arg) => clone()..sub(arg);
×
243

244
  /// Returns new matrix -this
245
  Matrix2 operator -() => clone()..negate();
×
246

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

255
  /// Makes this into the identity matrix.
256
  void setIdentity() {
×
257
    _m2storage[0] = 1.0;
×
258
    _m2storage[1] = 0.0;
×
259
    _m2storage[2] = 0.0;
×
260
    _m2storage[3] = 1.0;
×
261
  }
262

263
  /// Returns the tranpose of this.
264
  Matrix2 transposed() => clone()..transpose();
×
265

266
  void transpose() {
×
267
    final temp = _m2storage[2];
×
268
    _m2storage[2] = _m2storage[1];
×
269
    _m2storage[1] = temp;
×
270
  }
271

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

283
  /// Returns the determinant of this matrix.
284
  double determinant() =>
×
285
      (_m2storage[0] * _m2storage[3]) - (_m2storage[1] * _m2storage[2]);
×
286

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

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

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

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

326
  /// Returns relative error between this and [correct]
327
  double relativeError(Matrix2 correct) {
×
328
    final diff = correct - this;
×
329
    final correctNorm = correct.infinityNorm();
×
330
    final diff_norm = diff.infinityNorm();
×
331
    return diff_norm / correctNorm;
×
332
  }
333

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

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

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

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

383
  /// Converts into Adjugate matrix and scales by [scale]
384
  void scaleAdjoint(double scale) {
×
385
    final temp = _m2storage[0];
×
386
    _m2storage[0] = _m2storage[3] * scale;
×
387
    _m2storage[2] = -_m2storage[2] * scale;
×
388
    _m2storage[1] = -_m2storage[1] * scale;
×
389
    _m2storage[3] = temp * scale;
×
390
  }
391

392
  /// Scale this by [scale].
393
  void scale(double scale) {
×
394
    _m2storage[0] = _m2storage[0] * scale;
×
395
    _m2storage[1] = _m2storage[1] * scale;
×
396
    _m2storage[2] = _m2storage[2] * scale;
×
397
    _m2storage[3] = _m2storage[3] * scale;
×
398
  }
399

400
  /// Create a copy of this scaled by [scale].
401
  Matrix2 scaled(double scale) => clone()..scale(scale);
×
402

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

412
  /// Subtract [o] from this.
413
  void sub(Matrix2 o) {
×
414
    final oStorage = o._m2storage;
×
415
    _m2storage[0] = _m2storage[0] - oStorage[0];
×
416
    _m2storage[1] = _m2storage[1] - oStorage[1];
×
417
    _m2storage[2] = _m2storage[2] - oStorage[2];
×
418
    _m2storage[3] = _m2storage[3] - oStorage[3];
×
419
  }
420

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

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

446
  /// Multiply this with [arg] and return the product.
447
  Matrix2 multiplied(Matrix2 arg) => clone()..multiply(arg);
×
448

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

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

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

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

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

507
  /// Copies elements from [array] into this starting at [offset].
508
  void copyFromArray(List<double> array, [int offset = 0]) {
×
509
    final i = offset;
510
    _m2storage[3] = array[i + 3];
×
511
    _m2storage[2] = array[i + 2];
×
512
    _m2storage[1] = array[i + 1];
×
513
    _m2storage[0] = array[i + 0];
×
514
  }
515
}
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