See More

package ptjava; import java.util.concurrent.ThreadLocalRandom; import jdk.incubator.vector.DoubleVector; import jdk.incubator.vector.VectorMask; import jdk.incubator.vector.VectorOperators; import jdk.incubator.vector.VectorShuffle; import jdk.incubator.vector.VectorSpecies; public class Vector { private static final VectorSpecies SPECIES = DoubleVector.SPECIES_256; private static final VectorMask XYZ_MASK = SPECIES.indexInRange(0, 3); private static final VectorShuffle YZX = VectorShuffle.fromValues(SPECIES, 1, 2, 0, 3); private static final VectorShuffle ZXY = VectorShuffle.fromValues(SPECIES, 2, 0, 1, 3); public final DoubleVector vec; public static final Vector ZERO = new Vector(0, 0, 0); public static final Vector UP = new Vector(0, 1, 0); public static final Vector RIGHT = new Vector(1, 0, 0); public static final Vector FORWARD = new Vector(0, 0, 1); public Vector() { vec = DoubleVector.zero(SPECIES); } public double getX() { return vec.lane(0); } public double getY() { return vec.lane(1); } public double getZ() { return vec.lane(2); } public Vector withX(double x) { return new Vector(vec.withLane(0, x)); } public Vector withY(double y) { return new Vector(vec.withLane(1, y)); } public Vector withZ(double z) { return new Vector(vec.withLane(2, z)); } private Vector(DoubleVector vec) { this.vec = vec; } public Vector(double x, double y, double z) { vec = DoubleVector.zero(SPECIES).withLane(0, x).withLane(1, y).withLane(2, z); } public static Vector RandomUnitVector(ThreadLocalRandom rnd) { double z = rnd.nextDouble() * 2.0 - 1.0; double a = rnd.nextDouble() * 2.0 * Math.PI; double r = Math.sqrt(1.0 - z * z); double x = Math.sin(a); double y = Math.cos(a); return new Vector(r * x, r * y, z); } public double Length() { return Math.sqrt(this.vec.mul(this.vec).reduceLanes(VectorOperators.ADD, XYZ_MASK)); } public double LengthN(double n) { if (n == 2) { return this.Length(); } DoubleVector absVec = this.vec.abs(); double x = Math.pow(absVec.lane(0), n); double y = Math.pow(absVec.lane(1), n); double z = Math.pow(absVec.lane(2), n); return Math.pow(x + y + z, 1.0 / n); } public double Dot(Vector b) { return this.vec.mul(b.vec).reduceLanes(VectorOperators.ADD, XYZ_MASK); } public Vector Cross(Vector b) { DoubleVector a_yzx = this.vec.rearrange(YZX); DoubleVector b_zxy = b.vec.rearrange(ZXY); DoubleVector a_zxy = this.vec.rearrange(ZXY); DoubleVector b_yzx = b.vec.rearrange(YZX); return new Vector(a_yzx.mul(b_zxy).sub(a_zxy.mul(b_yzx))); } public Vector Normalize() { return new Vector(this.vec.div(this.Length())); } public Vector Negate() { return new Vector(this.vec.neg()); } public Vector Abs() { return new Vector(this.vec.abs()); } public Vector Add(Vector b) { return new Vector(this.vec.add(b.vec)); } public Vector Sub(Vector b) { return new Vector(this.vec.sub(b.vec)); } public Vector Mul(Vector b) { return new Vector(this.vec.mul(b.vec)); } public Vector Div(Vector b) { return new Vector(this.vec.div(b.vec)); } public Vector Mod(Vector b) { double x = this.getX() % b.getX(); double y = this.getY() % b.getY(); double z = this.getZ() % b.getZ(); return new Vector(x, y, z); } public Vector AddScalar(double b) { return new Vector(this.vec.add(DoubleVector.broadcast(SPECIES, b), XYZ_MASK)); } public Vector SubScalar(double b) { return new Vector(this.vec.sub(DoubleVector.broadcast(SPECIES, b), XYZ_MASK)); } public Vector MulScalar(double b) { return new Vector(this.vec.mul(b)); } public Vector DivScalar(double b) { return new Vector(this.vec.div(b)); } public Vector Min(Vector b) { return new Vector(this.vec.min(b.vec)); } public static Vector Min(Vector a, Vector b) { return new Vector(a.vec.min(b.vec)); } public Vector Max(Vector b) { return new Vector(this.vec.max(b.vec)); } public static Vector Max(Vector a, Vector b) { return new Vector(a.vec.max(b.vec)); } public Vector MinAxis() { double x = Math.abs(vec.lane(0)); double y = Math.abs(vec.lane(1)); double z = Math.abs(vec.lane(2)); if (x <= y && x <= z) { return new Vector(1, 0, 0); } else if (y <= x && y <= z) { return new Vector(0, 1, 0); } return new Vector(0, 0, 1); } public double MinComponent() { return Math.min(Math.min(vec.lane(0), vec.lane(1)), vec.lane(2)); } public double MaxComponent() { return Math.max(Math.max(vec.lane(0), vec.lane(1)), vec.lane(2)); } public Vector Reflect(Vector i) { return i.Sub(this.MulScalar(2 * this.Dot(i))); } public Vector Refract(Vector i, double n1, double n2) { double nr = n1 / n2; double cosI = -this.Dot(i); double sinT2 = nr * nr * (1 - cosI * cosI); if (sinT2 > 1) { return new Vector(); } double cosT = Math.sqrt(1 - sinT2); return i.MulScalar(nr).Add(this.MulScalar(nr * cosI - cosT)); } public double Reflectance(Vector i, double n1, double n2) { double nr = n1 / n2; double cosI = -this.Dot(i); double sinT2 = nr * nr * (1 - cosI * cosI); if (sinT2 > 1) { return 1; } double cosT = Math.sqrt(1 - sinT2); double rOrth = (n1 * cosI - n2 * cosT) / (n1 * cosI + n2 * cosT); double rPar = (n2 * cosI - n1 * cosT) / (n2 * cosI + n1 * cosT); return (rOrth * rOrth + rPar * rPar) / 2; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Vector)) return false; Vector other = (Vector) obj; return Double.compare(getX(), other.getX()) == 0 && Double.compare(getY(), other.getY()) == 0 && Double.compare(getZ(), other.getZ()) == 0; } @Override public int hashCode() { long bits = Double.doubleToLongBits(getX()); bits = 31 * bits + Double.doubleToLongBits(getY()); bits = 31 * bits + Double.doubleToLongBits(getZ()); return (int)(bits ^ (bits >>> 32)); } }