Skip to content

Commit

Permalink
Optimize Vector4d matrix multiply methods taking into account matrix …
Browse files Browse the repository at this point in the history
…properties (#337)

- mul() now takes into account identity, translation and affine
- new method mulTranslation() when assuming translation
- new method mulGeneric() when not assuming (and also not testing for) properties
- mulProject() now takes into account identity, translation and affine
- new method mulProjectTranslation() when assuming translation
- new method mulProjectAffine() when assuming affine
- new method mulProjectGeneric() when not assuming (and also not testing for) properties
- new method mulGenericTranspose() when not assuming (and also not testing for) properties
  • Loading branch information
httpdigest committed Jul 25, 2023
1 parent f830b0c commit d3912cf
Show file tree
Hide file tree
Showing 2 changed files with 430 additions and 27 deletions.
165 changes: 146 additions & 19 deletions src/main/java/org/joml/Vector4d.java
Original file line number Diff line number Diff line change
Expand Up @@ -1091,13 +1091,15 @@ public Vector4d mul(Vector4fc v, Vector4d dest) {
* @return this
*/
public Vector4d mul(Matrix4dc mat) {
if ((mat.properties() & Matrix4fc.PROPERTY_AFFINE) != 0)
return mulAffine(mat, this);
return mulGeneric(mat, this);
return mul(mat, this);
}

public Vector4d mul(Matrix4dc mat, Vector4d dest) {
if ((mat.properties() & Matrix4fc.PROPERTY_AFFINE) != 0)
int prop = mat.properties();
if ((prop & Matrix4dc.PROPERTY_IDENTITY) != 0)
return dest.set(this);
if ((prop & Matrix4dc.PROPERTY_TRANSLATION) != 0)
return mulTranslation(mat, dest);
if ((prop & Matrix4dc.PROPERTY_AFFINE) != 0)
return mulAffine(mat, dest);
return mulGeneric(mat, dest);
}
Expand All @@ -1117,11 +1119,31 @@ public Vector4d mulTranspose(Matrix4dc mat) {
return mulTranspose(mat, this);
}
public Vector4d mulTranspose(Matrix4dc mat, Vector4d dest) {
if ((mat.properties() & Matrix4dc.PROPERTY_AFFINE) != 0)
int prop = mat.properties();
if ((prop & Matrix4dc.PROPERTY_IDENTITY) != 0)
return dest.set(this);
if ((prop & Matrix4dc.PROPERTY_AFFINE) != 0)
return mulAffineTranspose(mat, dest);
return mulGenericTranspose(mat, dest);
}

public Vector4d mulTranslation(Matrix4dc mat, Vector4d dest) {
double x = this.x, y = this.y, z = this.z, w = this.w;
dest.x = Math.fma(mat.m30(), w, x);
dest.y = Math.fma(mat.m31(), w, y);
dest.z = Math.fma(mat.m32(), w, z);
dest.w = w;
return dest;
}
public Vector4d mulTranslation(Matrix4fc mat, Vector4d dest) {
double x = this.x, y = this.y, z = this.z, w = this.w;
dest.x = Math.fma(mat.m30(), w, x);
dest.y = Math.fma(mat.m31(), w, y);
dest.z = Math.fma(mat.m32(), w, z);
dest.w = w;
return dest;
}

public Vector4d mulAffine(Matrix4dc mat, Vector4d dest) {
double rx = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w)));
double ry = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w)));
Expand All @@ -1133,7 +1155,19 @@ public Vector4d mulAffine(Matrix4dc mat, Vector4d dest) {
return dest;
}

private Vector4d mulGeneric(Matrix4dc mat, Vector4d dest) {
/**
* Multiply the given matrix <code>mat</code> with this vector.
* <p>
* This method does not make any assumptions or optimizations about the properties of the specified matrix.
*
* @param mat
* the matrix whose transpose to multiply the vector with
* @return this
*/
public Vector4d mulGeneric(Matrix4dc mat) {
return mulGeneric(mat, this);
}
public Vector4d mulGeneric(Matrix4dc mat, Vector4d dest) {
double rx = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w)));
double ry = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w)));
double rz = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w)));
Expand All @@ -1153,7 +1187,7 @@ public Vector4d mulAffineTranspose(Matrix4dc mat, Vector4d dest) {
dest.w = Math.fma(mat.m30(), x, Math.fma(mat.m31(), y, mat.m32() * z + w));
return dest;
}
private Vector4d mulGenericTranspose(Matrix4dc mat, Vector4d dest) {
public Vector4d mulGenericTranspose(Matrix4dc mat, Vector4d dest) {
double x = this.x, y = this.y, z = this.z, w = this.w;
dest.x = Math.fma(mat.m00(), x, Math.fma(mat.m01(), y, Math.fma(mat.m02(), z, mat.m03() * w)));
dest.y = Math.fma(mat.m10(), x, Math.fma(mat.m11(), y, Math.fma(mat.m12(), z, mat.m13() * w)));
Expand All @@ -1173,8 +1207,15 @@ private Vector4d mulGenericTranspose(Matrix4dc mat, Vector4d dest) {
public Vector4d mul(Matrix4x3dc mat) {
return mul(mat, this);
}

public Vector4d mul(Matrix4x3dc mat, Vector4d dest) {
int prop = mat.properties();
if ((prop & Matrix4x3dc.PROPERTY_IDENTITY) != 0)
return dest.set(this);
if ((prop & Matrix4x3dc.PROPERTY_TRANSLATION) != 0)
return mulTranslation(mat, dest);
return mulGeneric(mat, dest);
}
public Vector4d mulGeneric(Matrix4x3dc mat, Vector4d dest) {
double rx = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w)));
double ry = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w)));
double rz = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w)));
Expand All @@ -1184,6 +1225,13 @@ public Vector4d mul(Matrix4x3dc mat, Vector4d dest) {
dest.w = w;
return dest;
}
public Vector4d mulTranslation(Matrix4x3dc mat, Vector4d dest) {
dest.x = Math.fma(mat.m30(), w, x);
dest.y = Math.fma(mat.m31(), w, y);
dest.z = Math.fma(mat.m32(), w, z);
dest.w = w;
return dest;
}

/**
* Multiply the given matrix mat with this vector and store the result in
Expand All @@ -1196,8 +1244,15 @@ public Vector4d mul(Matrix4x3dc mat, Vector4d dest) {
public Vector4d mul(Matrix4x3fc mat) {
return mul(mat, this);
}

public Vector4d mul(Matrix4x3fc mat, Vector4d dest) {
int prop = mat.properties();
if ((prop & Matrix4x3dc.PROPERTY_IDENTITY) != 0)
return dest.set(this);
if ((prop & Matrix4x3dc.PROPERTY_TRANSLATION) != 0)
return mulTranslation(mat, dest);
return mulGeneric(mat, dest);
}
public Vector4d mulGeneric(Matrix4x3fc mat, Vector4d dest) {
double rx = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w)));
double ry = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w)));
double rz = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w)));
Expand All @@ -1207,6 +1262,13 @@ public Vector4d mul(Matrix4x3fc mat, Vector4d dest) {
dest.w = w;
return dest;
}
public Vector4d mulTranslation(Matrix4x3fc mat, Vector4d dest) {
dest.x = Math.fma(mat.m30(), w, x);
dest.y = Math.fma(mat.m31(), w, y);
dest.z = Math.fma(mat.m32(), w, z);
dest.w = w;
return dest;
}

/**
* Multiply the given matrix <code>mat</code> with this {@link Vector4d}.
Expand All @@ -1216,17 +1278,19 @@ public Vector4d mul(Matrix4x3fc mat, Vector4d dest) {
* @return this
*/
public Vector4d mul(Matrix4fc mat) {
if ((mat.properties() & Matrix4fc.PROPERTY_AFFINE) != 0)
return mulAffine(mat, this);
return mulGeneric(mat, this);
return mul(mat, this);
}

public Vector4d mul(Matrix4fc mat, Vector4d dest) {
if ((mat.properties() & Matrix4fc.PROPERTY_AFFINE) != 0)
int prop = mat.properties();
if ((prop & Matrix4fc.PROPERTY_IDENTITY) != 0)
return dest.set(this);
if ((prop & Matrix4fc.PROPERTY_TRANSLATION) != 0)
return mulTranslation(mat, dest);
if ((prop & Matrix4fc.PROPERTY_AFFINE) != 0)
return mulAffine(mat, dest);
return mulGeneric(mat, dest);
}
private Vector4d mulAffine(Matrix4fc mat, Vector4d dest) {
public Vector4d mulAffine(Matrix4fc mat, Vector4d dest) {
double rx = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w)));
double ry = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w)));
double rz = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w)));
Expand All @@ -1236,7 +1300,7 @@ private Vector4d mulAffine(Matrix4fc mat, Vector4d dest) {
dest.w = w;
return dest;
}
private Vector4d mulGeneric(Matrix4fc mat, Vector4d dest) {
public Vector4d mulGeneric(Matrix4fc mat, Vector4d dest) {
double rx = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w)));
double ry = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w)));
double rz = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w)));
Expand All @@ -1248,7 +1312,7 @@ private Vector4d mulGeneric(Matrix4fc mat, Vector4d dest) {
return dest;
}

public Vector4d mulProject(Matrix4dc mat, Vector4d dest) {
public Vector4d mulProjectGeneric(Matrix4dc mat, Vector4d dest) {
double invW = 1.0 / Math.fma(mat.m03(), x, Math.fma(mat.m13(), y, Math.fma(mat.m23(), z, mat.m33() * w)));
double rx = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w))) * invW;
double ry = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w))) * invW;
Expand All @@ -1260,6 +1324,50 @@ public Vector4d mulProject(Matrix4dc mat, Vector4d dest) {
return dest;
}

public Vector4d mulProjectTranslation(Matrix4dc mat, Vector4d dest) {
double invW = 1.0 / w;
double rx = Math.fma(mat.m00(), x, mat.m30() * w) * invW;
double ry = Math.fma(mat.m11(), y, mat.m31() * w) * invW;
double rz = Math.fma(mat.m22(), z, mat.m32() * w) * invW;
dest.x = rx;
dest.y = ry;
dest.z = rz;
dest.w = 1.0;
return dest;
}
public Vector3d mulProjectTranslation(Matrix4dc mat, Vector3d dest) {
double invW = 1.0 / w;
double rx = Math.fma(mat.m00(), x, mat.m30() * w) * invW;
double ry = Math.fma(mat.m11(), y, mat.m31() * w) * invW;
double rz = Math.fma(mat.m22(), z, mat.m32() * w) * invW;
dest.x = rx;
dest.y = ry;
dest.z = rz;
return dest;
}

public Vector4d mulProjectAffine(Matrix4dc mat, Vector4d dest) {
double invW = 1.0 / w;
double rx = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w))) * invW;
double ry = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w))) * invW;
double rz = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w))) * invW;
dest.x = rx;
dest.y = ry;
dest.z = rz;
dest.w = 1.0;
return dest;
}
public Vector3d mulProjectAffine(Matrix4dc mat, Vector3d dest) {
double invW = 1.0 / w;
double rx = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w))) * invW;
double ry = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w))) * invW;
double rz = Math.fma(mat.m02(), x, Math.fma(mat.m12(), y, Math.fma(mat.m22(), z, mat.m32() * w))) * invW;
dest.x = rx;
dest.y = ry;
dest.z = rz;
return dest;
}

/**
* Multiply the given matrix <code>mat</code> with this vector, perform perspective division.
*
Expand All @@ -1270,8 +1378,27 @@ public Vector4d mulProject(Matrix4dc mat, Vector4d dest) {
public Vector4d mulProject(Matrix4dc mat) {
return mulProject(mat, this);
}

public Vector4d mulProject(Matrix4dc mat, Vector4d dest) {
int prop = mat.properties();
if ((prop & Matrix4dc.PROPERTY_IDENTITY) != 0)
return dest.set(this);
if ((prop & Matrix4dc.PROPERTY_TRANSLATION) != 0)
return mulProjectTranslation(mat, dest);
if ((prop & Matrix4dc.PROPERTY_AFFINE) != 0)
return mulProjectAffine(mat, dest);
return mulProjectGeneric(mat, dest);
}
public Vector3d mulProject(Matrix4dc mat, Vector3d dest) {
int prop = mat.properties();
if ((prop & Matrix4dc.PROPERTY_IDENTITY) != 0)
return dest.set(this);
if ((prop & Matrix4dc.PROPERTY_TRANSLATION) != 0)
return mulProjectTranslation(mat, dest);
if ((prop & Matrix4dc.PROPERTY_AFFINE) != 0)
return mulProjectAffine(mat, dest);
return mulProjectGeneric(mat, dest);
}
public Vector3d mulProjectGeneric(Matrix4dc mat, Vector3d dest) {
double invW = 1.0 / Math.fma(mat.m03(), x, Math.fma(mat.m13(), y, Math.fma(mat.m23(), z, mat.m33() * w)));
double rx = Math.fma(mat.m00(), x, Math.fma(mat.m10(), y, Math.fma(mat.m20(), z, mat.m30() * w))) * invW;
double ry = Math.fma(mat.m01(), x, Math.fma(mat.m11(), y, Math.fma(mat.m21(), z, mat.m31() * w))) * invW;
Expand Down
Loading

0 comments on commit d3912cf

Please sign in to comment.