Skip to content

Add specialized Vector4.translate methods based on argument types #345

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions benchmark/matrix_bench.dart
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,148 @@ class Matrix3TransposeMultiplyBenchmark extends BenchmarkBase {
}
}

class Matrix4TranslateByDoubleGenericBenchmark extends BenchmarkBase {
Matrix4TranslateByDoubleGenericBenchmark()
: super('Matrix4.translateByDoubleGeneric');

final temp = Matrix4.zero()..setIdentity();

static void main() {
Matrix4TranslateByDoubleGenericBenchmark().report();
}

@override
void run() {
for (var i = 0; i < 100; i++) {
temp.translate(10.0, 20.0, 30.0);
}
}
}

class Matrix4TranslateByVector3GenericBenchmark extends BenchmarkBase {
Matrix4TranslateByVector3GenericBenchmark()
: super('Matrix4.translateByVector3Generic');

final temp = Matrix4.zero()..setIdentity();
final vec = Vector3(10.0, 20.0, 30.0);

static void main() {
Matrix4TranslateByVector3GenericBenchmark().report();
}

@override
void run() {
for (var i = 0; i < 100; i++) {
temp.translate(vec);
}
}
}

class Matrix4TranslateByVector4GenericBenchmark extends BenchmarkBase {
Matrix4TranslateByVector4GenericBenchmark()
: super('Matrix4.translateByVector4Generic');

final temp = Matrix4.zero()..setIdentity();
final vec = Vector4(10.0, 20.0, 30.0, 40.0);

static void main() {
Matrix4TranslateByVector4GenericBenchmark().report();
}

@override
void run() {
for (var i = 0; i < 100; i++) {
temp.translate(vec);
}
}
}

class Matrix4TranslateByDoubleBenchmark extends BenchmarkBase {
Matrix4TranslateByDoubleBenchmark() : super('Matrix4.translateByDouble');

final temp = Matrix4.zero()..setIdentity();

static void main() {
Matrix4TranslateByDoubleBenchmark().report();
}

// Call the benchmarked method with random arguments to make sure TFA won't
// specialize it based on the arguments passed and wasm-opt won't inline it,
// for fair comparison with the generic case.
@override
void setup() {
for (var i = 0; i < 10; i++) {
temp.translateByDouble(
i.toDouble(), (i * 10).toDouble(), (i * 5).toDouble());
}
}

@override
void run() {
for (var i = 0; i < 100; i++) {
temp.translateByDouble(10.0, 20.0, 30.0);
}
}
}

class Matrix4TranslateByVector3Benchmark extends BenchmarkBase {
Matrix4TranslateByVector3Benchmark() : super('Matrix4.translateByVector3');

final temp = Matrix4.zero()..setIdentity();
final vec = Vector3(10.0, 20.0, 30.0);

static void main() {
Matrix4TranslateByVector3Benchmark().report();
}

// Call the benchmarked method with random arguments to make sure TFA won't
// specialize it based on the arguments passed and wasm-opt won't inline it,
// for fair comparison with the generic case.
@override
void setup() {
for (var i = 0; i < 10; i++) {
temp.translateByVector3(
Vector3(i.toDouble(), (i * 10).toDouble(), (i * 5).toDouble()));
}
}

@override
void run() {
for (var i = 0; i < 100; i++) {
temp.translateByVector3(vec);
}
}
}

class Matrix4TranslateByVector4Benchmark extends BenchmarkBase {
Matrix4TranslateByVector4Benchmark() : super('Matrix4.translateByVector4');

final temp = Matrix4.zero()..setIdentity();
final vec = Vector4(10.0, 20.0, 30.0, 40.0);

static void main() {
Matrix4TranslateByVector4Benchmark().report();
}

// Call the benchmarked method with random arguments to make sure TFA won't
// specialize it based on the arguments passed and wasm-opt won't inline it,
// for fair comparison with the generic case.
@override
void setup() {
for (var i = 0; i < 10; i++) {
temp.translateByVector4(Vector4(i.toDouble(), (i * 10).toDouble(),
(i * 5).toDouble(), (i * 20).toDouble()));
}
}

@override
void run() {
for (var i = 0; i < 100; i++) {
temp.translateByVector4(vec);
}
}
}

void main() {
MatrixMultiplyBenchmark.main();
SIMDMatrixMultiplyBenchmark.main();
Expand All @@ -335,4 +477,10 @@ void main() {
Matrix3TransformVector3Benchmark.main();
Matrix3TransformVector2Benchmark.main();
Matrix3TransposeMultiplyBenchmark.main();
Matrix4TranslateByDoubleGenericBenchmark.main();
Matrix4TranslateByVector3GenericBenchmark.main();
Matrix4TranslateByVector4GenericBenchmark.main();
Matrix4TranslateByDoubleBenchmark.main();
Matrix4TranslateByVector3Benchmark.main();
Matrix4TranslateByVector4Benchmark.main();
}
84 changes: 84 additions & 0 deletions lib/src/vector_math/matrix4.dart
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,9 @@ class Matrix4 {
Matrix4 operator -(Matrix4 arg) => clone()..sub(arg);

/// Translate this matrix by a [Vector3], [Vector4], or x,y,z
///
/// If you know the argument types in a call site, prefer [translateByDouble],
/// [translateByVector3], or [translateByVector4] for performance.
void translate(dynamic x, [double y = 0.0, double z = 0.0]) {
double tx;
double ty;
Expand Down Expand Up @@ -703,6 +706,87 @@ class Matrix4 {
_m4storage[15] = t4;
}

/// Translate this matrix by x, y, z.
void translateByDouble(double tx, double ty, double tz) {
final tw = 1.0;
final t1 = _m4storage[0] * tx +
_m4storage[4] * ty +
_m4storage[8] * tz +
_m4storage[12] * tw;
final t2 = _m4storage[1] * tx +
_m4storage[5] * ty +
_m4storage[9] * tz +
_m4storage[13] * tw;
final t3 = _m4storage[2] * tx +
_m4storage[6] * ty +
_m4storage[10] * tz +
_m4storage[14] * tw;
final t4 = _m4storage[3] * tx +
_m4storage[7] * ty +
_m4storage[11] * tz +
_m4storage[15] * tw;
_m4storage[12] = t1;
_m4storage[13] = t2;
_m4storage[14] = t3;
_m4storage[15] = t4;
}

/// Translate this matrix by a [Vector3].
void translateByVector3(Vector3 v3) {
final tx = v3.x;
final ty = v3.y;
final tz = v3.z;
final tw = 1.0;
final t1 = _m4storage[0] * tx +
_m4storage[4] * ty +
_m4storage[8] * tz +
_m4storage[12] * tw;
final t2 = _m4storage[1] * tx +
_m4storage[5] * ty +
_m4storage[9] * tz +
_m4storage[13] * tw;
final t3 = _m4storage[2] * tx +
_m4storage[6] * ty +
_m4storage[10] * tz +
_m4storage[14] * tw;
final t4 = _m4storage[3] * tx +
_m4storage[7] * ty +
_m4storage[11] * tz +
_m4storage[15] * tw;
_m4storage[12] = t1;
_m4storage[13] = t2;
_m4storage[14] = t3;
_m4storage[15] = t4;
}

/// Translate this matrix by a [Vector4].
void translateByVector4(Vector4 v4) {
final tx = v4.x;
final ty = v4.y;
final tz = v4.z;
final tw = v4.w;
final t1 = _m4storage[0] * tx +
_m4storage[4] * ty +
_m4storage[8] * tz +
_m4storage[12] * tw;
final t2 = _m4storage[1] * tx +
_m4storage[5] * ty +
_m4storage[9] * tz +
_m4storage[13] * tw;
final t3 = _m4storage[2] * tx +
_m4storage[6] * ty +
_m4storage[10] * tz +
_m4storage[14] * tw;
final t4 = _m4storage[3] * tx +
_m4storage[7] * ty +
_m4storage[11] * tz +
_m4storage[15] * tw;
_m4storage[12] = t1;
_m4storage[13] = t2;
_m4storage[14] = t3;
_m4storage[15] = t4;
}

/// Multiply this by a translation from the left.
/// The translation can be specified with a [Vector3], [Vector4], or x, y, z.
void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) {
Expand Down
84 changes: 84 additions & 0 deletions lib/src/vector_math_64/matrix4.dart
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,9 @@ class Matrix4 {
Matrix4 operator -(Matrix4 arg) => clone()..sub(arg);

/// Translate this matrix by a [Vector3], [Vector4], or x,y,z
///
/// If you know the argument types in a call site, prefer [translateByDouble],
/// [translateByVector3], or [translateByVector4] for performance.
void translate(dynamic x, [double y = 0.0, double z = 0.0]) {
double tx;
double ty;
Expand Down Expand Up @@ -703,6 +706,87 @@ class Matrix4 {
_m4storage[15] = t4;
}

/// Translate this matrix by x, y, z.
void translateByDouble(double tx, double ty, double tz) {
final tw = 1.0;
final t1 = _m4storage[0] * tx +
_m4storage[4] * ty +
_m4storage[8] * tz +
_m4storage[12] * tw;
final t2 = _m4storage[1] * tx +
_m4storage[5] * ty +
_m4storage[9] * tz +
_m4storage[13] * tw;
final t3 = _m4storage[2] * tx +
_m4storage[6] * ty +
_m4storage[10] * tz +
_m4storage[14] * tw;
final t4 = _m4storage[3] * tx +
_m4storage[7] * ty +
_m4storage[11] * tz +
_m4storage[15] * tw;
_m4storage[12] = t1;
_m4storage[13] = t2;
_m4storage[14] = t3;
_m4storage[15] = t4;
}

/// Translate this matrix by a [Vector3].
void translateByVector3(Vector3 v3) {
final tx = v3.x;
final ty = v3.y;
final tz = v3.z;
final tw = 1.0;
final t1 = _m4storage[0] * tx +
_m4storage[4] * ty +
_m4storage[8] * tz +
_m4storage[12] * tw;
final t2 = _m4storage[1] * tx +
_m4storage[5] * ty +
_m4storage[9] * tz +
_m4storage[13] * tw;
final t3 = _m4storage[2] * tx +
_m4storage[6] * ty +
_m4storage[10] * tz +
_m4storage[14] * tw;
final t4 = _m4storage[3] * tx +
_m4storage[7] * ty +
_m4storage[11] * tz +
_m4storage[15] * tw;
_m4storage[12] = t1;
_m4storage[13] = t2;
_m4storage[14] = t3;
_m4storage[15] = t4;
}

/// Translate this matrix by a [Vector4].
void translateByVector4(Vector4 v4) {
final tx = v4.x;
final ty = v4.y;
final tz = v4.z;
final tw = v4.w;
final t1 = _m4storage[0] * tx +
_m4storage[4] * ty +
_m4storage[8] * tz +
_m4storage[12] * tw;
final t2 = _m4storage[1] * tx +
_m4storage[5] * ty +
_m4storage[9] * tz +
_m4storage[13] * tw;
final t3 = _m4storage[2] * tx +
_m4storage[6] * ty +
_m4storage[10] * tz +
_m4storage[14] * tw;
final t4 = _m4storage[3] * tx +
_m4storage[7] * ty +
_m4storage[11] * tz +
_m4storage[15] * tw;
_m4storage[12] = t1;
_m4storage[13] = t2;
_m4storage[14] = t3;
_m4storage[15] = t4;
}

/// Multiply this by a translation from the left.
/// The translation can be specified with a [Vector3], [Vector4], or x, y, z.
void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) {
Expand Down