All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.io7m.jtensors.VectorI4D Maven / Gradle / Ivy

/*
 * Copyright © 2013  http://io7m.com
 * 
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jtensors;

import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;

import com.io7m.jaux.AlmostEqualDouble;
import com.io7m.jaux.AlmostEqualDouble.ContextRelative;
import com.io7m.jaux.functional.Pair;

/**
 * 

* A four-dimensional immutable vector type with double precision elements. *

*

* Values of this type are immutable and can therefore be safely accessed from * multiple threads. *

*/ @Immutable public class VectorI4D implements VectorReadable4D { /** * Calculate the element-wise sum of the vectors v0 and the * element-wise product of v1 and r. * * @param v0 * The left input vector * @param v1 * The right input vector * @param r * The scaling value * * @return (v0.x + (v1.x * r), v0.y + (v1.y * r), v0.z + (v1.z * r), v0.w + (v1.w * r)) */ public final static @Nonnull VectorI4D addScaled( final @Nonnull VectorReadable4D v0, final @Nonnull VectorReadable4D v1, final double r) { return VectorI4D.add(v0, VectorI4D.scale(v1, r)); } /** * Determine whether or not the vectors va and vb * are equal to within the degree of error given in context. * * @see AlmostEqualDouble#almostEqual(ContextRelative, double, double) * * @param context * The equality context * @param va * The left input vector * @param vb * The right input vector * @since 5.0.0 */ public final static boolean almostEqual( final @Nonnull AlmostEqualDouble.ContextRelative context, final @Nonnull VectorReadable4D va, final @Nonnull VectorReadable4D vb) { final boolean xs = AlmostEqualDouble.almostEqual(context, va.getXD(), vb.getXD()); final boolean ys = AlmostEqualDouble.almostEqual(context, va.getYD(), vb.getYD()); final boolean zs = AlmostEqualDouble.almostEqual(context, va.getZD(), vb.getZD()); final boolean ws = AlmostEqualDouble.almostEqual(context, va.getWD(), vb.getWD()); return xs && ys && zs && ws; } /** * Clamp the elements of the vector v to the range * [minimum .. maximum] inclusive. * * @param v * The input vector * @param minimum * The minimum allowed value * @param maximum * The maximum allowed value * * @return A vector with both elements equal to at most maximum * and at least minimum */ public final static @Nonnull VectorI4D clamp( final @Nonnull VectorReadable4D v, final double minimum, final double maximum) { final double x = Math.min(Math.max(v.getXD(), minimum), maximum); final double y = Math.min(Math.max(v.getYD(), minimum), maximum); final double z = Math.min(Math.max(v.getZD(), minimum), maximum); final double w = Math.min(Math.max(v.getWD(), minimum), maximum); return new VectorI4D(x, y, z, w); } /** * Clamp the elements of the vector v to the inclusive range * given by the corresponding elements in minimum and * maximum. * * @param v * The input vector * @param minimum * The vector containing the minimum acceptable values * @param maximum * The vector containing the maximum acceptable values * * @return (min(max(v.x, minimum.x), maximum.x), min(max(v.y, minimum.y), maximum.y), min(max(v.z, minimum.z), maximum.z), min(max(v.w, minimum.w), maximum.w)) */ public final static @Nonnull VectorI4D clampByVector( final @Nonnull VectorReadable4D v, final @Nonnull VectorReadable4D minimum, final @Nonnull VectorReadable4D maximum) { final double x = Math.min(Math.max(v.getXD(), minimum.getXD()), maximum.getXD()); final double y = Math.min(Math.max(v.getYD(), minimum.getYD()), maximum.getYD()); final double z = Math.min(Math.max(v.getZD(), minimum.getZD()), maximum.getZD()); final double w = Math.min(Math.max(v.getWD(), minimum.getWD()), maximum.getWD()); return new VectorI4D(x, y, z, w); } /** * Clamp the elements of the vector v to the range * [-Infinity .. maximum] inclusive. * * @param v * The input vector * @param maximum * The maximum allowed value * * @return A vector with both elements equal to at most maximum */ public final static @Nonnull VectorI4D clampMaximum( final @Nonnull VectorReadable4D v, final double maximum) { final double x = Math.min(v.getXD(), maximum); final double y = Math.min(v.getYD(), maximum); final double z = Math.min(v.getZD(), maximum); final double w = Math.min(v.getWD(), maximum); return new VectorI4D(x, y, z, w); } /** * Clamp the elements of the vector v to the inclusive range * given by the corresponding elements in maximum. * * @param v * The input vector * @param maximum * The vector containing the maximum acceptable values * * @return (min(v.x, maximum.x), min(v.y, maximum.y), min(v.z, maximum.z), min(v.w, maximum.w)) */ public final static @Nonnull VectorI4D clampMaximumByVector( final @Nonnull VectorReadable4D v, final @Nonnull VectorReadable4D maximum) { final double x = Math.min(v.getXD(), maximum.getXD()); final double y = Math.min(v.getYD(), maximum.getYD()); final double z = Math.min(v.getZD(), maximum.getZD()); final double w = Math.min(v.getWD(), maximum.getWD()); return new VectorI4D(x, y, z, w); } /** * Clamp the elements of the vector v to the range * [minimum .. Infinity] inclusive. * * @param v * The input vector * @param minimum * The minimum allowed value * * @return A vector with both elements equal to at least * minimum. */ public final static @Nonnull VectorI4D clampMinimum( final @Nonnull VectorReadable4D v, final double minimum) { final double x = Math.max(v.getXD(), minimum); final double y = Math.max(v.getYD(), minimum); final double z = Math.max(v.getZD(), minimum); final double w = Math.max(v.getWD(), minimum); return new VectorI4D(x, y, z, w); } /** * Clamp the elements of the vector v to the inclusive range * given by the corresponding elements in minimum. * * @param v * The input vector * @param minimum * The vector containing the minimum acceptable values * * @return (max(v.x, minimum.x), max(v.y, minimum.y), max(v.z, minimum.z), max(v.w, minimum.w)) */ public final static @Nonnull VectorI4D clampMinimumByVector( final @Nonnull VectorReadable4D v, final @Nonnull VectorReadable4D minimum) { final double x = Math.max(v.getXD(), minimum.getXD()); final double y = Math.max(v.getYD(), minimum.getYD()); final double z = Math.max(v.getZD(), minimum.getZD()); final double w = Math.max(v.getWD(), minimum.getWD()); return new VectorI4D(x, y, z, w); } /** * Calculate the distance between the two vectors v0 and * v1. * * @param v0 * The left input vector * @param v1 * The right input vector * * @return The distance between the two vectors. */ public final static double distance( final @Nonnull VectorReadable4D v0, final @Nonnull VectorReadable4D v1) { return VectorI4D.magnitude(VectorI4D.subtract(v0, v1)); } /** * Calculate the scalar product of the vectors v0 and * v1. * * @param v0 * The left input vector * @param v1 * The right input vector * * @return The scalar product of the two vectors */ public final static double dotProduct( final @Nonnull VectorReadable4D v0, final @Nonnull VectorReadable4D v1) { final double x = v0.getXD() * v1.getXD(); final double y = v0.getYD() * v1.getYD(); final double z = v0.getZD() * v1.getZD(); final double w = v0.getWD() * v1.getWD(); return x + y + z + w; } /** * Linearly interpolate between v0 and v1 by the * amount alpha. * * The alpha parameter controls the degree of interpolation, * such that: * *
    *
  • interpolateLinear(v0, v1, 0.0) = v0
  • *
  • interpolateLinear(v0, v1, 1.0) = v1
  • *
* * @param v0 * The left input vector. * @param v1 * The right input vector. * @param alpha * The interpolation value, between 0.0 and * 1.0. * * @return (1 - alpha) * v0 + alpha * v1 */ public final static @Nonnull VectorI4D interpolateLinear( final @Nonnull VectorReadable4D v0, final @Nonnull VectorReadable4D v1, final double alpha) { final @Nonnull VectorReadable4D w0 = VectorI4D.scale(v0, 1.0 - alpha); final @Nonnull VectorReadable4D w1 = VectorI4D.scale(v1, alpha); return VectorI4D.add(w0, w1); } /** * Calculate the magnitude of the vector v. * * Correspondingly, magnitude(normalize(v)) == 1.0. * * @param v * The input vector * * @return The magnitude of the input vector */ public final static double magnitude( final @Nonnull VectorReadable4D v) { return Math.sqrt(VectorI4D.magnitudeSquared(v)); } /** * Calculate the squared magnitude of the vector v. * * @param v * The input vector * * @return The squared magnitude of the input vector */ public final static double magnitudeSquared( final @Nonnull VectorReadable4D v) { return VectorI4D.dotProduct(v, v); } /** * Normalize the vector v, preserving its direction but * reducing it to unit length. * * @param v * The input vector * * @return A vector with the same orientation as v but with * magnitude equal to 1.0 */ public final static @Nonnull VectorI4D normalize( final @Nonnull VectorReadable4D v) { final double m = VectorI4D.magnitudeSquared(v); if (m > 0) { final double reciprocal = 1.0 / Math.sqrt(m); return VectorI4D.scale(v, reciprocal); } return new VectorI4D(v); } /** *

* Orthonormalize and return the vectors v0 and v1 * . *

*

* See GSP *

* * @return A pair (v0, v1), orthonormalized. * * @since 5.0.0 */ public final static @Nonnull Pair orthoNormalize( final @Nonnull VectorReadable4D v0, final @Nonnull VectorReadable4D v1) { final VectorI4D v0n = VectorI4D.normalize(v0); final VectorI4D projection = VectorI4D.scale(v0n, VectorI4D.dotProduct(v1, v0n)); final VectorI4D vr = VectorI4D.normalize(VectorI4D.subtract(v1, projection)); return new Pair(v0n, vr); } /** * Calculate the projection of the vector p onto the vector * q. * * @return ((dotProduct p q) / magnitudeSquared q) * q */ public final static @Nonnull VectorI4D projection( final @Nonnull VectorReadable4D p, final @Nonnull VectorReadable4D q) { final double dot = VectorI4D.dotProduct(p, q); final double qms = VectorI4D.magnitudeSquared(q); final double s = dot / qms; return VectorI4D.scale(p, s); } /** * Scale the vector v by the scalar r. * * @param v * The input vector * @param r * The scaling value * * @return (v.x * r, v.y * r, v.z * r, v.w * r) */ public final static @Nonnull VectorI4D scale( final @Nonnull VectorReadable4D v, final double r) { return new VectorI4D( v.getXD() * r, v.getYD() * r, v.getZD() * r, v.getWD() * r); } /** * Subtract the vector v1 from the vector v0. * * @param v0 * The left input vector * @param v1 * The right input vector * * @return (v0.x - v1.x, v0.y - v1.y, v0.z - v1.z) */ public final static @Nonnull VectorI4D subtract( final @Nonnull VectorReadable4D v0, final @Nonnull VectorReadable4D v1) { return new VectorI4D( v0.getXD() - v1.getXD(), v0.getYD() - v1.getYD(), v0.getZD() - v1.getZD(), v0.getWD() - v1.getWD()); } public final double x; public final double y; public final double z; public final double w; /** * The zero vector. */ public static final @Nonnull VectorI4D ZERO; static { ZERO = new VectorI4D(0.0, 0.0, 0.0, 0.0); } /** * Calculate the absolute value of the vector v. * * @param v * The input vector * * @return (abs v.x, abs v.y, abs v.z, abs v.w) */ public final static @Nonnull VectorI4D absolute( final @Nonnull VectorReadable4D v) { return new VectorI4D(Math.abs(v.getXD()), Math.abs(v.getYD()), Math.abs(v .getZD()), Math.abs(v.getWD())); } /** * Calculate the element-wise sum of the vectors v0 and * v1. * * @param v0 * The left input vector * @param v1 * The right input vector * * @return (v0.x + v1.x, v0.y + v1.y, v0.z + v1.z, v0.w + v1.w) */ public final static @Nonnull VectorI4D add( final @Nonnull VectorReadable4D v0, final @Nonnull VectorReadable4D v1) { return new VectorI4D( v0.getXD() + v1.getXD(), v0.getYD() + v1.getYD(), v0.getZD() + v1.getZD(), v0.getWD() + v1.getWD()); } /** * Default constructor, initializing the vector with values * [0.0, 0.0, 0.0, 1.0]. */ public VectorI4D() { this.x = 0.0; this.y = 0.0; this.z = 0.0; this.w = 1.0; } /** * Construct a vector initialized with the given values. */ public VectorI4D( final double x, final double y, final double z, final double w) { this.x = x; this.y = y; this.z = z; this.w = w; } /** * Construct a vector initialized with the values given in the vector * v. */ public VectorI4D( final VectorReadable4D v) { this.x = v.getXD(); this.y = v.getYD(); this.z = v.getZD(); this.w = v.getWD(); } @Override public final boolean equals( final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (this.getClass() != obj.getClass()) { return false; } final @Nonnull VectorI4D other = (VectorI4D) obj; if (Double.doubleToLongBits(this.w) != Double.doubleToLongBits(other.w)) { return false; } if (Double.doubleToLongBits(this.x) != Double.doubleToLongBits(other.x)) { return false; } if (Double.doubleToLongBits(this.y) != Double.doubleToLongBits(other.y)) { return false; } if (Double.doubleToLongBits(this.z) != Double.doubleToLongBits(other.z)) { return false; } return true; } @Override public final double getWD() { return this.w; } @Override public final double getXD() { return this.x; } @Override public final double getYD() { return this.y; } @Override public final double getZD() { return this.z; } @Override public final int hashCode() { final int prime = 31; int result = 1; long temp; temp = Double.doubleToLongBits(this.w); result = (prime * result) + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(this.x); result = (prime * result) + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(this.y); result = (prime * result) + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(this.z); result = (prime * result) + (int) (temp ^ (temp >>> 32)); return result; } @Override public final String toString() { final StringBuilder builder = new StringBuilder(); builder.append("[VectorI4D "); builder.append(this.x); builder.append(" "); builder.append(this.y); builder.append(" "); builder.append(this.z); builder.append(" "); builder.append(this.w); builder.append("]"); return builder.toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy