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

com.io7m.jtensors.VectorM4F 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.NotThreadSafe;

import com.io7m.jaux.AlmostEqualFloat;
import com.io7m.jaux.functional.Pair;

/**
 * 

* A four-dimensional mutable vector type with single precision elements. *

* *

* Values of this type cannot be accessed safely from multiple threads without * explicit synchronization. *

*/ @NotThreadSafe public class VectorM4F implements VectorReadable4F { /** * Calculate the absolute values of the elements in vector v, * saving the result to out. * * @param v * The input vector * @param out * The output vector * * @return (abs v.x, abs v.y, abs v.z, abs.w) */ public final static @Nonnull VectorM4F absolute( final @Nonnull VectorReadable4F v, final @Nonnull VectorM4F out) { final float x = Math.abs(v.getXF()); final float y = Math.abs(v.getYF()); final float z = Math.abs(v.getZF()); final float w = Math.abs(v.getWF()); out.x = x; out.y = y; out.z = z; out.w = w; return out; } /** * Calculate the absolute values of the elements in vector v, * modifying the vector in-place. * * @param v * The input vector * * @return (abs v.x, abs v.y, abs v.z, abs v.w) */ public final static @Nonnull VectorM4F absoluteInPlace( final @Nonnull VectorM4F v) { return VectorM4F.absolute(v, v); } /** * Calculate the element-wise sum of the vectors v0 and * v1, saving the result to out. * * @param v0 * The left input vector * @param v1 * The right input vector * @param out * The output vector * * @return (v0.x + v1.x, v0.y + v1.y, v0.z + v1.z, v0.w + v1.w) */ public final static @Nonnull VectorM4F add( final @Nonnull VectorReadable4F v0, final @Nonnull VectorReadable4F v1, final @Nonnull VectorM4F out) { final float x = v0.getXF() + v1.getXF(); final float y = v0.getYF() + v1.getYF(); final float z = v0.getZF() + v1.getZF(); final float w = v0.getWF() + v1.getWF(); out.x = x; out.y = y; out.z = z; out.w = w; return out; } /** * Calculate the element-wise sum of the vectors v0 and * v1, saving the result to 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, v0.w + v1.w) */ public final static @Nonnull VectorM4F addInPlace( final @Nonnull VectorM4F v0, final @Nonnull VectorReadable4F v1) { return VectorM4F.add(v0, v1, v0); } /** * Calculate the element-wise sum of the vectors v0 and the * element-wise product of v1 and r, saving the * result to out. * * @param v0 * The left input vector * @param v1 * The right input vector * @param out * The output 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 VectorM4F addScaled( final @Nonnull VectorReadable4F v0, final @Nonnull VectorReadable4F v1, final double r, final @Nonnull VectorM4F out) { final float x = (float) (v0.getXF() + (v1.getXF() * r)); final float y = (float) (v0.getYF() + (v1.getYF() * r)); final float z = (float) (v0.getZF() + (v1.getZF() * r)); final float w = (float) (v0.getWF() + (v1.getWF() * r)); out.x = x; out.y = y; out.z = z; out.w = w; return out; } /** * Calculate the element-wise sum of the vectors v0 and the * element-wise product of v1 and r, saving the * result to v0. * * @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 VectorM4F addScaledInPlace( final @Nonnull VectorM4F v0, final @Nonnull VectorReadable4F v1, final double r) { return VectorM4F.addScaled(v0, v1, r, v0); } /** * Determine whether or not the vectors va and vb * are equal to within the degree of error given in context. * * @see AlmostEqualFloat#almostEqual(ContextRelative, float, float) * * @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 AlmostEqualFloat.ContextRelative context, final @Nonnull VectorReadable4F va, final @Nonnull VectorReadable4F vb) { final boolean xs = AlmostEqualFloat.almostEqual(context, va.getXF(), vb.getXF()); final boolean ys = AlmostEqualFloat.almostEqual(context, va.getYF(), vb.getYF()); final boolean zs = AlmostEqualFloat.almostEqual(context, va.getZF(), vb.getZF()); final boolean ws = AlmostEqualFloat.almostEqual(context, va.getWF(), vb.getWF()); return xs && ys && zs && ws; } /** * Clamp the elements of the vector v to the range * [minimum .. maximum] inclusive, saving the result to * out. * * @param v * The input vector * @param minimum * The minimum allowed value * @param maximum * The maximum allowed value * @param out * The output vector * * @return A vector with both elements equal to at most maximum * and at least minimum */ public final static @Nonnull VectorM4F clamp( final @Nonnull VectorReadable4F v, final double minimum, final double maximum, final @Nonnull VectorM4F out) { final float x = (float) Math.min(Math.max(v.getXF(), minimum), maximum); final float y = (float) Math.min(Math.max(v.getYF(), minimum), maximum); final float z = (float) Math.min(Math.max(v.getZF(), minimum), maximum); final float w = (float) Math.min(Math.max(v.getWF(), minimum), maximum); out.x = x; out.y = y; out.z = z; out.w = w; return out; } /** * Clamp the elements of the vector v to the inclusive range * given by the corresponding elements in minimum and * maximum, saving the result to out. * * @param v * The input vector * @param minimum * The vector containing the minimum acceptable values * @param maximum * The vector containing the maximum acceptable values * @param out * The output vector * * @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 VectorM4F clampByVector( final @Nonnull VectorReadable4F v, final @Nonnull VectorReadable4F minimum, final @Nonnull VectorReadable4F maximum, final @Nonnull VectorM4F out) { final float x = Math.min(Math.max(v.getXF(), minimum.getXF()), maximum.getXF()); final float y = Math.min(Math.max(v.getYF(), minimum.getYF()), maximum.getYF()); final float z = Math.min(Math.max(v.getZF(), minimum.getZF()), maximum.getZF()); final float w = Math.min(Math.max(v.getWF(), minimum.getWF()), maximum.getWF()); out.x = x; out.y = y; out.z = z; out.w = w; return out; } /** * Clamp the elements of the vector v to the inclusive range * given by the corresponding elements in minimum and * maximum, saving the result to v. * * @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 VectorM4F clampByVectorInPlace( final @Nonnull VectorM4F v, final @Nonnull VectorReadable4F minimum, final @Nonnull VectorReadable4F maximum) { return VectorM4F.clampByVector(v, minimum, maximum, v); } /** * Clamp the elements of the vector v to the range * [minimum .. maximum] inclusive, saving the result to * v. * * @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, in v */ public final static @Nonnull VectorM4F clampInPlace( final @Nonnull VectorM4F v, final float minimum, final float maximum) { return VectorM4F.clamp(v, minimum, maximum, v); } /** * Clamp the elements of the vector v to the range * [-Infinity .. maximum] inclusive, saving the result to * out. * * @param v * The input vector * @param out * The output vector * @param maximum * The maximum allowed value * * @return A vector with both elements equal to at most maximum */ public final static @Nonnull VectorM4F clampMaximum( final @Nonnull VectorReadable4F v, final float maximum, final @Nonnull VectorM4F out) { final float x = Math.min(v.getXF(), maximum); final float y = Math.min(v.getYF(), maximum); final float z = Math.min(v.getZF(), maximum); final float w = Math.min(v.getWF(), maximum); out.x = x; out.y = y; out.z = z; out.w = w; return out; } /** * Clamp the elements of the vector v to the inclusive range * given by the corresponding elements in maximum, saving the * result to out. * * @param v * The input vector * @param maximum * The vector containing the maximum acceptable values * @param out * The output vector * * @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 VectorM4F clampMaximumByVector( final @Nonnull VectorReadable4F v, final @Nonnull VectorReadable4F maximum, final @Nonnull VectorM4F out) { final float x = Math.min(v.getXF(), maximum.getXF()); final float y = Math.min(v.getYF(), maximum.getYF()); final float z = Math.min(v.getZF(), maximum.getZF()); final float w = Math.min(v.getWF(), maximum.getWF()); out.x = x; out.y = y; out.z = z; out.w = w; return out; } /** * Clamp the elements of the vector v to the inclusive range * given by the corresponding elements in maximum, saving the * result to v. * * @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 VectorM4F clampMaximumByVectorInPlace( final @Nonnull VectorM4F v, final @Nonnull VectorReadable4F maximum) { return VectorM4F.clampMaximumByVector(v, maximum, v); } /** * Clamp the elements of the vector v to the range * [-Infinity .. maximum] inclusive, saving the result to * v. * * @param v * The input vector * @param maximum * The maximum allowed value * * @return A vector with both elements equal to at most maximum * , in v */ public final static @Nonnull VectorM4F clampMaximumInPlace( final @Nonnull VectorM4F v, final float maximum) { return VectorM4F.clampMaximum(v, maximum, v); } /** * Clamp the elements of the vector v to the range * [minimum .. Infinity] inclusive, saving the result to * out. * * @param v * The input vector * @param out * The output vector * @param minimum * The minimum allowed value * * @return A vector with both elements equal to at least * minimum */ public final static @Nonnull VectorM4F clampMinimum( final @Nonnull VectorReadable4F v, final float minimum, final @Nonnull VectorM4F out) { final float x = Math.max(v.getXF(), minimum); final float y = Math.max(v.getYF(), minimum); final float z = Math.max(v.getZF(), minimum); final float w = Math.max(v.getWF(), minimum); out.x = x; out.y = y; out.z = z; out.w = w; return out; } /** * Clamp the elements of the vector v to the inclusive range * given by the corresponding elements in minimum, saving the * result to out. * * @param v * The input vector * @param out * The output 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 VectorM4F clampMinimumByVector( final @Nonnull VectorReadable4F v, final @Nonnull VectorReadable4F minimum, final @Nonnull VectorM4F out) { final float x = Math.max(v.getXF(), minimum.getXF()); final float y = Math.max(v.getYF(), minimum.getYF()); final float z = Math.max(v.getZF(), minimum.getZF()); final float w = Math.max(v.getWF(), minimum.getWF()); out.x = x; out.y = y; out.z = z; out.w = w; return out; } /** * Clamp the elements of the vector v to the inclusive range * given by the corresponding elements in minimum, saving the * result to v. * * @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)) * , in v */ public final static @Nonnull VectorM4F clampMinimumByVectorInPlace( final @Nonnull VectorM4F v, final @Nonnull VectorReadable4F minimum) { return VectorM4F.clampMinimumByVector(v, minimum, v); } /** * Clamp the elements of the vector v to the range * [minimum .. Infinity] inclusive, saving the result to * v. * * @param v * The input vector * @param minimum * The minimum allowed value * * @return A vector with both elements equal to at least * minimum, in v. */ public final static @Nonnull VectorM4F clampMinimumInPlace( final @Nonnull VectorM4F v, final float minimum) { return VectorM4F.clampMinimum(v, minimum, v); } /** * Copy all elements of the vector input to the vector * output. * * @param input * The input vector * @param output * The output vector * * @return output */ public final static @Nonnull VectorM4F copy( final @Nonnull VectorReadable4F input, final @Nonnull VectorM4F output) { output.x = input.getXF(); output.y = input.getYF(); output.z = input.getZF(); output.w = input.getWF(); return output; } /** * 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 VectorReadable4F v0, final @Nonnull VectorReadable4F v1) { final @Nonnull VectorM4F vr = new VectorM4F(); return VectorM4F.magnitude(VectorM4F.subtract(v0, v1, vr)); } /** * 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 VectorReadable4F v0, final @Nonnull VectorReadable4F v1) { final double x = v0.getXF() * v1.getXF(); final double y = v0.getYF() * v1.getYF(); final double z = v0.getZF() * v1.getZF(); final double w = v0.getWF() * v1.getWF(); return x + y + z + w; } /** * Linearly interpolate between v0 and v1 by the * amount alpha, saving the result to r. * * The alpha parameter controls the degree of interpolation, * such that: * *
    *
  • interpolateLinear(v0, v1, 0.0, r) -> r = v0
  • *
  • interpolateLinear(v0, v1, 1.0, r) -> r = v1
  • *
* * @param v0 * The left input vector. * @param v1 * The right input vector. * @param alpha * The interpolation value, between 0.0 and * 1.0. * @param r * The result vector. * * @return r */ public final static @Nonnull VectorM4F interpolateLinear( final @Nonnull VectorReadable4F v0, final @Nonnull VectorReadable4F v1, final double alpha, final @Nonnull VectorM4F r) { final @Nonnull VectorM4F w0 = new VectorM4F(); final @Nonnull VectorM4F w1 = new VectorM4F(); VectorM4F.scale(v0, 1.0f - alpha, w0); VectorM4F.scale(v1, alpha, w1); return VectorM4F.add(w0, w1, r); } /** * 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 VectorReadable4F v) { return Math.sqrt(VectorM4F.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 VectorReadable4F v) { return VectorM4F.dotProduct(v, v); } /** * Returns a vector with the same orientation as v but with * magnitude equal to 1.0 in out. The function * returns the zero vector iff the input is the zero vector. * * @param v * The input vector * @param out * The output vector * * @return out */ public final static @Nonnull VectorM4F normalize( final @Nonnull VectorReadable4F v, final @Nonnull VectorM4F out) { final double m = VectorM4F.magnitudeSquared(v); if (m > 0.0) { final double reciprocal = 1.0 / Math.sqrt(m); return VectorM4F.scale(v, reciprocal, out); } out.x = v.getXF(); out.y = v.getYF(); out.z = v.getZF(); out.w = v.getWF(); return out; } /** * Returns a vector with the same orientation as v but with * magnitude equal to 1.0 in v. The function * returns the zero vector iff the input is the zero vector. * * @param v * The input vector * * @return v */ public final static @Nonnull VectorM4F normalizeInPlace( final @Nonnull VectorM4F v) { return VectorM4F.normalize(v, 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 VectorReadable4F v0, final @Nonnull VectorReadable4F v1) { final VectorM4F v0n = new VectorM4F(); final VectorM4F vr = new VectorM4F(); final VectorM4F vp = new VectorM4F(); VectorM4F.normalize(v0, v0n); VectorM4F.scale(v0n, VectorM4F.dotProduct(v1, v0n), vp); VectorM4F.normalizeInPlace(VectorM4F.subtract(v1, vp, vr)); return new Pair(v0n, vr); } /** *

* Orthonormalize and the vectors v0 and v1. *

*

* See GSP *

* * @since 5.0.0 */ public final static void orthoNormalizeInPlace( final @Nonnull VectorM4F v0, final @Nonnull VectorM4F v1) { final VectorM4F projection = new VectorM4F(); VectorM4F.normalizeInPlace(v0); VectorM4F.scale(v0, VectorM4F.dotProduct(v1, v0), projection); VectorM4F.subtractInPlace(v1, projection); VectorM4F.normalizeInPlace(v1); } /** * Calculate the projection of the vector p onto the vector * q, saving the result in r. * * @return ((dotProduct p q) / magnitudeSquared q) * q */ public final static @Nonnull VectorM4F projection( final @Nonnull VectorReadable4F p, final @Nonnull VectorReadable4F q, final @Nonnull VectorM4F r) { final double dot = VectorM4F.dotProduct(p, q); final double qms = VectorM4F.magnitudeSquared(q); final double s = dot / qms; return VectorM4F.scale(p, s, r); } /** * Scale the vector v by the scalar r, saving the * result to out. * * @param v * The input vector * @param r * The scaling value * @param out * The output vector * * @return (v.x * r, v.y * r, v.z * r, v.w * r) */ public final static @Nonnull VectorM4F scale( final @Nonnull VectorReadable4F v, final double r, final @Nonnull VectorM4F out) { final float x = (float) (v.getXF() * r); final float y = (float) (v.getYF() * r); final float z = (float) (v.getZF() * r); final float w = (float) (v.getWF() * r); out.x = x; out.y = y; out.z = z; out.w = w; return out; } /** * Scale the vector v by the scalar r, saving the * result to v. * * @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 VectorM4F scaleInPlace( final @Nonnull VectorM4F v, final double r) { return VectorM4F.scale(v, r, v); } /** * Subtract the vector v1 from the vector v0, * saving the result to out. * * @param v0 * The left input vector * @param v1 * The right input vector * @param out * The output vector * * @return (v0.x - v1.x, v0.y - v1.y, v0.z - v1.z, v0.w - v1.w) */ public final static @Nonnull VectorM4F subtract( final @Nonnull VectorReadable4F v0, final @Nonnull VectorReadable4F v1, final @Nonnull VectorM4F out) { final float x = v0.getXF() - v1.getXF(); final float y = v0.getYF() - v1.getYF(); final float z = v0.getZF() - v1.getZF(); final float w = v0.getWF() - v1.getWF(); out.x = x; out.y = y; out.z = z; out.w = w; return out; } /** * Subtract the vector v1 from the vector v0, * saving the result to 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, v0.w - v1.w) */ public final static @Nonnull VectorM4F subtractInPlace( final @Nonnull VectorM4F v0, final @Nonnull VectorReadable4F v1) { return VectorM4F.subtract(v0, v1, v0); } public float x = 0.0f; public float y = 0.0f; public float z = 0.0f; public float w = 1.0f; /** * Default constructor, initializing the vector with values * [0.0, 0.0, 0.0, 1.0]. */ public VectorM4F() { } /** * Construct a vector initialized with the given values. */ public VectorM4F( final float x, final float y, final float z, final float 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 VectorM4F( final @Nonnull VectorReadable4F v) { this.x = v.getXF(); this.y = v.getYF(); this.z = v.getZF(); this.w = v.getWF(); } @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 VectorM4F other = (VectorM4F) obj; if (Float.floatToIntBits(this.w) != Float.floatToIntBits(other.w)) { return false; } if (Float.floatToIntBits(this.x) != Float.floatToIntBits(other.x)) { return false; } if (Float.floatToIntBits(this.y) != Float.floatToIntBits(other.y)) { return false; } if (Float.floatToIntBits(this.z) != Float.floatToIntBits(other.z)) { return false; } return true; } @Override public final float getWF() { return this.w; } @Override public final float getXF() { return this.x; } @Override public final float getYF() { return this.y; } @Override public final float getZF() { return this.z; } @Override public final int hashCode() { final int prime = 31; int result = 1; result = (prime * result) + Float.floatToIntBits(this.w); result = (prime * result) + Float.floatToIntBits(this.x); result = (prime * result) + Float.floatToIntBits(this.y); result = (prime * result) + Float.floatToIntBits(this.z); return result; } @Override public final String toString() { final StringBuilder builder = new StringBuilder(); builder.append("[VectorM4F "); 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