Sample

Schnappinger/aoi/artofillusion.math.Mat4

Human rating uses the original dataset scale.

Human3
Lines330

Scores

MethodScoreScaleDataset rank
(0–100)
Posnett00–1; higher is more readable
12.0Δ 14.0
Scalabrino0.8230–1; higher is more readable
68.5Δ 42.4
Dorn0.0050–1; higher is more readable
15.8Δ 10.2
Mi0.2940–1; higher is more readable
19.8Δ 6.3
LLOC123Logical lines; fewer is more readable
20.6Δ 5.4
DeepSeek V4 Pro14.670–20; mean of three runs
34.8Δ 8.7
GPT-6.1 Sol160–20; mean of three runs
38.9Δ 12.9
BTTF0.3110–1; higher is more readable
21.8Δ 4.3
Human31–4; original rating
26.1

Views

Source code

/* Copyright (C) 1999,2000,2003 by Peter Eastman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ package artofillusion.math; import java.io.*; /** This class represents a 4x4 matrix. It is typically used for representing coordinate transformations. */ public class Mat4 { public final double m11, m12, m13, m14; public final double m21, m22, m23, m24; public final double m31, m32, m33, m34; public final double m41, m42, m43, m44; /** Create a new Mat4 by explicitly setting its components. */ public Mat4 (double e11, double e12, double e13, double e14, double e21, double e22, double e23, double e24, double e31, double e32, double e33, double e34, double e41, double e42, double e43, double e44) { m11 = e11; m12 = e12; m13 = e13; m14 = e14; m21 = e21; m22 = e22; m23 = e23; m24 = e24; m31 = e31; m32 = e32; m33 = e33; m34 = e34; m41 = e41; m42 = e42; m43 = e43; m44 = e44; } /** Create a new Mat4 by multiplying two matrices. */ public final Mat4 times(Mat4 a) { return new Mat4(m11*a.m11 + m12*a.m21 + m13*a.m31 + m14*a.m41, m11*a.m12 + m12*a.m22 + m13*a.m32 + m14*a.m42, m11*a.m13 + m12*a.m23 + m13*a.m33 + m14*a.m43, m11*a.m14 + m12*a.m24 + m13*a.m34 + m14*a.m44, m21*a.m11 + m22*a.m21 + m23*a.m31 + m24*a.m41, m21*a.m12 + m22*a.m22 + m23*a.m32 + m24*a.m42, m21*a.m13 + m22*a.m23 + m23*a.m33 + m24*a.m43, m21*a.m14 + m22*a.m24 + m23*a.m34 + m24*a.m44, m31*a.m11 + m32*a.m21 + m33*a.m31 + m34*a.m41, m31*a.m12 + m32*a.m22 + m33*a.m32 + m34*a.m42, m31*a.m13 + m32*a.m23 + m33*a.m33 + m34*a.m43, m31*a.m14 + m32*a.m24 + m33*a.m34 + m34*a.m44, m41*a.m11 + m42*a.m21 + m43*a.m31 + m44*a.m41, m41*a.m12 + m42*a.m22 + m43*a.m32 + m44*a.m42, m41*a.m13 + m42*a.m23 + m43*a.m33 + m44*a.m43, m41*a.m14 + m42*a.m24 + m43*a.m34 + m44*a.m44); } /** Multiply this matrix (M) by a vector (v) and return the product Mv. Both the input and output vectors are assumed to be in homogeneous coordinates, and to have an implicit fourth element equal to 1. */ public final Vec3 times(Vec3 v) { double w = m41*v.x + m42*v.y + m43*v.z + m44; return new Vec3((m11*v.x + m12*v.y + m13*v.z + m14)/w, (m21*v.x + m22*v.y + m23*v.z + m24)/w, (m31*v.x + m32*v.y + m33*v.z + m34)/w); } /** This method is identical to times(), except that v is assumed to be a direction vector. That is, the implicit fourth element is assumed to be 0. */ public final Vec3 timesDirection(Vec3 v) { return new Vec3(m11*v.x + m12*v.y + m13*v.z, m21*v.x + m22*v.y + m23*v.z, m31*v.x + m32*v.y + m33*v.z); } /** This method works exactly like the times() method, except that it only calculates the x and y components of the output vector. This can save several operations when the z component is not of interest, for example, when applying a perspective projection. */ public final Vec2 timesXY(Vec3 v) { double w = m41*v.x + m42*v.y + m43*v.z + m44; return new Vec2((m11*v.x + m12*v.y + m13*v.z + m14)/w, (m21*v.x + m22*v.y + m23*v.z + m24)/w); } /** This method works exactly like the times() method, except that it only calculates the x and y components of the output vector. This can save several operations when the z component is not of interest, for example, when applying a perspective projection. Also, rather than creating a new object, it allows you to pass in an existing object to receive the results. */ public final Vec2 timesXY(Vec3 v, Vec2 result) { double w = m41*v.x + m42*v.y + m43*v.z + m44; result.set((m11*v.x + m12*v.y + m13*v.z + m14)/w, (m21*v.x + m22*v.y + m23*v.z + m24)/w); return result; } /** This method works like the times() method, except that it only calculates the z component of the output vector. This is useful, for example, for determining whether a point lies in front of or behind the viewer. */ public final double timesZ(Vec3 v) { double w = m41*v.x + m42*v.y + m43*v.z + m44; return (m31*v.x + m32*v.y + m33*v.z + m34)/w; } /** This method works like times(), except that the calculation is done in place. */ public final void transform(Vec3 v) { double w = m41*v.x + m42*v.y + m43*v.z + m44; v.set((m11*v.x + m12*v.y + m13*v.z + m14)/w, (m21*v.x + m22*v.y + m23*v.z + m24)/w, (m31*v.x + m32*v.y + m33*v.z + m34)/w); } /** This method works like timesDirection(), except that the calculation is done in place. */ public final void transformDirection(Vec3 v) { v.set(m11*v.x + m12*v.y + m13*v.z, m21*v.x + m22*v.y + m23*v.z, m31*v.x + m32*v.y + m33*v.z); } /** Create an identity matrix. */ public static Mat4 identity() { return new Mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0); } /** Create a matrix to scale x, y, and z by sx, sy, and sz respectively. */ public static Mat4 scale(double sx, double sy, double sz) { return new Mat4(sx, 0.0, 0.0, 0.0, 0.0, sy, 0.0, 0.0, 0.0, 0.0, sz, 0.0, 0.0, 0.0, 0.0, 1.0); } /** Create a matrix to translate a vector by (dx, dy, dz). */ public static Mat4 translation(double dx, double dy, double dz) { return new Mat4(1.0, 0.0, 0.0, dx, 0.0, 1.0, 0.0, dy, 0.0, 0.0, 1.0, dz, 0.0, 0.0, 0.0, 1.0); } /** Create a matrix that rotates a vector around the X axis. @param angle the rotation angle, in radians */ public static Mat4 xrotation(double angle) { double c = Math.cos(angle), s = Math.sin(angle); return new Mat4(1.0, 0.0, 0.0, 0.0, 0.0, c, -s, 0.0, 0.0, s, c, 0.0, 0.0, 0.0, 0.0, 1.0); } /** Create a matrix that rotates a vector around the Y axis. @param angle the rotation angle, in radians */ public static Mat4 yrotation(double angle) { double c = Math.cos(angle), s = Math.sin(angle); return new Mat4(c, 0.0, s, 0.0, 0.0, 1.0, 0.0, 0.0, -s, 0.0, c, 0.0, 0.0, 0.0, 0.0, 1.0); } /** Create a matrix that rotates a vector around the Z axis. @param angle the rotation angle, in radians */ public static Mat4 zrotation(double angle) { double c = Math.cos(angle), s = Math.sin(angle); return new Mat4(c, -s, 0.0, 0.0, s, c, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0); } /** This routine creates a matrix to rotate a vector around an arbitrary axis. @param axis the axis around which to rotate @param angle the rotation angle, in radians */ public static Mat4 axisRotation(Vec3 axis, double angle) { double c = Math.cos(angle), s = Math.sin(angle); double t = 1.0 - c; return new Mat4(t*axis.x*axis.x + c, t*axis.x*axis.y - s*axis.z, t*axis.x*axis.z + s*axis.y, 0.0, t*axis.x*axis.y + s*axis.z, t*axis.y*axis.y + c, t*axis.y*axis.z - s*axis.x, 0.0, t*axis.x*axis.z - s*axis.y, t*axis.y*axis.z + s*axis.x, t*axis.z*axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0); } /** Create a matrix for transforming from world coordinates to viewing coordinates. This matrix transforms coordinates such that the position vector orig is translated to the origin, the direction vector zdir lies along the positive z axis, and the direction vection updir lies the positive y half of the yz plane. */ public static Mat4 viewTransform(Vec3 orig, Vec3 zdir, Vec3 updir) { Vec3 rx, ry, rz; rz = zdir.times(1.0/zdir.length()); rx = updir.cross(zdir); rx.normalize(); ry = rz.cross(rx); return new Mat4(rx.x, rx.y, rx.z, -(rx.x*orig.x + rx.y*orig.y + rx.z*orig.z), ry.x, ry.y, ry.z, -(ry.x*orig.x + ry.y*orig.y + ry.z*orig.z), rz.x, rz.y, rz.z, -(rz.x*orig.x + rz.y*orig.y + rz.z*orig.z), 0.0, 0.0, 0.0, 1.0); } /** Create a matrix which is the inverse of the viewTransform matrix. That is, it first rotates the rotates the z axis to lie along the direction of zdir and the y axis to lie in the updir direction, then translates the origin to the point orig. This is useful for transforming from object coordinates to world coordinates. */ public static Mat4 objectTransform(Vec3 orig, Vec3 zdir, Vec3 updir) { Vec3 rx, ry, rz; rz = zdir.times(1.0/zdir.length()); rx = updir.cross(zdir); rx.normalize(); ry = rz.cross(rx); return new Mat4(rx.x, ry.x, rz.x, orig.x, rx.y, ry.y, rz.y, orig.y, rx.z, ry.z, rz.z, orig.z, 0.0, 0.0, 0.0, 1.0); } /** Create a matrix to implement a perspective projection. The center of projection is at (0, 0, -d), and the projection plane is given by z=1. */ public static Mat4 perspective(double d) { double e33 = 1.0/((d+1.0)*(d+1.0)); return new Mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, e33, 1.0-e33, 0.0, 0.0, e33, 1.0-e33); } public String toString() { return "Mat4: {"+m11+", "+m12 +", "+m13+", "+m14+"}, {"+m21+", "+m22 +", "+m23+", "+m24+"}, {"+m31+", "+m32 +", "+m33+", "+m34+"}, {"+m41+", "+m42 +", "+m43+", "+m44+"}"; } public boolean equals(Object o) { if (!(o instanceof Mat4)) return false; Mat4 m = (Mat4) o; return (m11 == m.m11 && m12 == m.m12 && m13 == m.m13 && m14 == m.m14 && m21 == m.m21 && m22 == m.m22 && m23 == m.m23 && m24 == m.m24 && m31 == m.m31 && m32 == m.m32 && m33 == m.m33 && m34 == m.m34 && m41 == m.m41 && m42 == m.m42 && m43 == m.m43 && m44 == m.m44); } public int hashCode() { double d = (m11+m12+m13+m14) + 2.2*(m21+m22+m23+m24) + 3.3*(m31+m32+m33+m34) + 4.4*(m41+m42+m43+m44); return Float.floatToIntBits((float) d); } /** Create a Mat4 by reading in information that was written by writeToFile(). */ public Mat4(DataInputStream in) throws IOException { m11 = in.readDouble(); m12 = in.readDouble(); m13 = in.readDouble(); m14 = in.readDouble(); m21 = in.readDouble(); m22 = in.readDouble(); m23 = in.readDouble(); m24 = in.readDouble(); m31 = in.readDouble(); m32 = in.readDouble(); m33 = in.readDouble(); m34 = in.readDouble(); m41 = in.readDouble(); m42 = in.readDouble(); m43 = in.readDouble(); m44 = in.readDouble(); } /** Write out a serialized representation of this object. */ public void writeToFile(DataOutputStream out) throws IOException { out.writeDouble(m11); out.writeDouble(m12); out.writeDouble(m13); out.writeDouble(m14); out.writeDouble(m21); out.writeDouble(m22); out.writeDouble(m23); out.writeDouble(m24); out.writeDouble(m31); out.writeDouble(m32); out.writeDouble(m33); out.writeDouble(m34); out.writeDouble(m41); out.writeDouble(m42); out.writeDouble(m43); out.writeDouble(m44); } }

Loading feature diagnosis…

Source regions

Feature contributions

Feature contributions

FeatureValueContribution
(log-odds)
Halstead volumeHow much symbolic information the code contains. It combines the total number of operators and values with the number of distinct ones.18868.801−622.67
Source linesThe number of non-empty source lines.330+132
Byte entropyHow varied the bytes in the source text are. Repeated bytes give a lower value; a more even mixture gives a higher value.4.922−7.383

Intercept 8.87 + feature contributions = -489.184 (log-odds).
Score = sigmoid(-489.184) = 0.

Score0.823

Feature contributions

FeatureValueContribution
(log-odds)
Comment layout frequencyHow frequently the layout switches between lines containing only comments or whitespace and lines containing code.330−10.648
Indentation frequencyHow rapidly indentation changes from line to line.294+9.432
Number layout frequencyHow rapidly the number of numeric values per line changes through the code.294−6.326
Identifier layout (vertical)How rapidly the visual pattern of identifier characters changes from top to bottom.328.931+4.188
Identifier layout (horizontal)How rapidly the visual pattern of identifier characters changes from left to right. It measures spatial frequency, not the meaning of the names.173.976−3.704
Comment layout (horizontal)How rapidly the visual pattern of comment characters changes from left to right.173.994+2.003
Operator visual areaThe share of the code’s visual area occupied by operators such as +, =, and *.0.126−0.281

Intercept 0.07 + feature contributions = -5.265 (log-odds).
Score = sigmoid(-5.265) = 0.005.

Score0.294
Score123
Run 1

The code is well-structured and readable overall. It uses a clear class organization with logical method grouping and good Javadoc comments explaining intent. Names are descriptive (e.g., xrotation, viewTransform). Nesting is minimal—no deep conditionals or loops. Most lines perform one action, and matrix construction formatting is consistent, aiding readability. However, the times(Mat4) method is extremely long and repetitive, with 16 dense arithmetic expressions; it would benefit from helper methods or loops. Some long lines (toString, serialization) hurt scanning clarity. Constructor and serialization methods are concise but could be more compact. Overall, clear purpose and solid structure, but certain long methods reduce natural reading flow.

Run 2

The code is generally well-structured with clear method separation and helpful Javadoc comments. The matrix multiplication 'times' method is quite long and involves many repetitive, dense mathematical expressions, reducing readability. Nesting is minimal and flat. Action granularity in the constructor and serialization methods is good (one line per row), but the 'times' method packs multiple operations per line. Reading flow is mostly natural, but the alignment and formatting of matrix arguments are inconsistent in places (e.g., 'perspective' uses different indentation). Overall, the class is understandable for experienced developers but could benefit from helper methods or formatting improvements.

Run 3

The code is well-structured, with clear separation of concerns: fields, constructors, transformation methods, factory methods, and serialization. Nesting is minimal, and each method serves a single, clear purpose. The matrix multiplication method is long and repetitive, but this is inherent to 4x4 matrix math and is formatted consistently. Naming conventions are strong, and Javadoc comments explain intent. However, the code loses points for action granularity: many lines bundle two or four statements together (e.g., constructor assignments and serialization reads/writes), and the toString and equals methods are dense. Overall, readability is high for experienced Java developers, though a novice might find the domain-specific math intimidating.

Run 1

1. Code Structure: Cohesive matrix class with focused methods and sensible grouping of transformations, utilities, and serialization. 2. Nesting: Almost entirely flat, with only a simple guard in equals(), making control flow easy to follow. 3. Clarity of intent: Descriptive method names and documentation explain most operations; conventional matrix indices help, but terse intermediate variables and unexplained hash constants reduce clarity. 4. Code length: Most methods are concise; explicit matrix arithmetic and serialization introduce substantial repetition, though much reflects the fixed-size mathematical representation. 5. Action granularity: Constructors and serialization frequently place four assignments or calls on one line, reducing individual-action readability. 6. Reading flow: Consistent method patterns and matrix-row formatting support natural reading, but inconsistent indentation, dense expressions, and the very long toString() line interrupt it. Overall, readable and well documented, with formatting and repetition preventing a higher score.

Run 2

Code Structure: Cohesive matrix class with logically grouped operations, transformation factories, and serialization methods. Nesting: Almost entirely flat, with only a simple guard in equals(). Clarity of intent: Descriptive method names and documentation explain most operations; conventional matrix indices help, but terse intermediate names and unexplained hash constants reduce clarity. Code length: Methods are generally concise; explicit matrix arithmetic is appropriate but repetitive, and some documentation duplicates explanations. Action granularity: Constructors and serialization methods pack multiple assignments or calls onto each line, making individual actions harder to scan, though row grouping preserves matrix structure. Reading flow: Consistent method patterns and row-oriented layouts support natural reading, but uneven indentation, dense arithmetic, the lengthy toString() line, and inconsistent matrix formatting interrupt it.

Run 3

Code Structure: Cohesive matrix class with well-separated operations and logically grouped transformation factories. Nesting: Almost entirely flat, making control flow easy to follow. Clarity of intent: Descriptive method names and helpful documentation explain most operations; terse mathematical variables, undocumented axis assumptions, and unexplained hash constants reduce clarity. Code length: Most methods are concise, although repeated transformation formulas and explicitly expanded matrix operations make the class lengthy. Action granularity: Constructor assignments and serialization calls frequently place multiple actions on one line, reducing scanability, though row grouping reflects matrix structure. Reading flow: Consistent method patterns and matrix-shaped formatting support natural reading, but uneven indentation, dense arithmetic, the very long toString expression, and minor documentation errors interrupt it.