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

com.io7m.jtensors.VectorI4F 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.ContextRelative;
import com.io7m.jaux.AlmostEqualFloat;
import com.io7m.jaux.functional.Pair;

/**
 * 

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

*

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

*/ @Immutable public class VectorI4F implements VectorReadable4F { /** * 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.getXF() + (v1.getXF() * r), v0.getYF() + (v1.getYF() * r), v0.getZF() + (v1.getZF() * r), v0.getWF() + (v1.getWF() * r)) */ public final static @Nonnull VectorI4F addScaled( final @Nonnull VectorReadable4F v0, final @Nonnull VectorReadable4F v1, final float r) { return VectorI4F.add(v0, VectorI4F.scale(v1, r)); } /** * 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. * * @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 VectorI4F clamp( final @Nonnull VectorReadable4F v, final float minimum, final float maximum) { final float x = Math.min(Math.max(v.getXF(), minimum), maximum); final float y = Math.min(Math.max(v.getYF(), minimum), maximum); final float z = Math.min(Math.max(v.getZF(), minimum), maximum); final float w = Math.min(Math.max(v.getWF(), minimum), maximum); return new VectorI4F(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.getXF(), minimum.getXF()), maximum.getXF()), min(max(v.getYF(), minimum.getYF()), maximum.getYF()), min(max(v.getZF(), minimum.getZF()), maximum.getZF()), min(max(v.getWF(), minimum.getWF()), maximum.getWF())) */ public final static @Nonnull VectorI4F clampByVector( final @Nonnull VectorReadable4F v, final @Nonnull VectorReadable4F minimum, final @Nonnull VectorReadable4F maximum) { 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()); return new VectorI4F(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 VectorI4F clampMaximum( final @Nonnull VectorReadable4F v, final float maximum) { 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); return new VectorI4F(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.getXF(), maximum.getXF()), min(v.getYF(), maximum.getYF()), min(v.getZF(), maximum.getZF()), min(v.getWF(), maximum.getWF())) */ public final static @Nonnull VectorI4F clampMaximumByVector( final @Nonnull VectorReadable4F v, final @Nonnull VectorReadable4F maximum) { 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()); return new VectorI4F(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 VectorI4F clampMinimum( final @Nonnull VectorReadable4F v, final float minimum) { 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); return new VectorI4F(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.getXF(), minimum.getXF()), max(v.getYF(), minimum.getYF()), max(v.getZF(), minimum.getZF()), max(v.getWF(), minimum.getWF())) */ public final static @Nonnull VectorI4F clampMinimumByVector( final @Nonnull VectorReadable4F v, final @Nonnull VectorReadable4F minimum) { 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()); return new VectorI4F(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 float distance( final @Nonnull VectorReadable4F v0, final @Nonnull VectorReadable4F v1) { return VectorI4F.magnitude(VectorI4F.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 float dotProduct( final @Nonnull VectorReadable4F v0, final @Nonnull VectorReadable4F v1) { 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(); 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 VectorI4F interpolateLinear( final @Nonnull VectorReadable4F v0, final @Nonnull VectorReadable4F v1, final float alpha) { final @Nonnull VectorReadable4F w0 = VectorI4F.scale(v0, 1.0f - alpha); final @Nonnull VectorReadable4F w1 = VectorI4F.scale(v1, alpha); return VectorI4F.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 float magnitude( final @Nonnull VectorReadable4F v) { return (float) Math.sqrt(VectorI4F.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 float magnitudeSquared( final @Nonnull VectorReadable4F v) { return VectorI4F.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 VectorI4F normalize( final @Nonnull VectorReadable4F v) { final float m = VectorI4F.magnitudeSquared(v); if (m > 0) { final float reciprocal = (float) (1.0f / Math.sqrt(m)); return VectorI4F.scale(v, reciprocal); } return new VectorI4F(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 VectorI4F v0n = VectorI4F.normalize(v0); final VectorI4F projection = VectorI4F.scale(v0n, VectorI4F.dotProduct(v1, v0n)); final VectorI4F vr = VectorI4F.normalize(VectorI4F.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 VectorI4F projection( final @Nonnull VectorReadable4F p, final @Nonnull VectorReadable4F q) { final float dot = VectorI4F.dotProduct(p, q); final float qms = VectorI4F.magnitudeSquared(q); final float s = dot / qms; return VectorI4F.scale(p, s); } /** * Scale the vector v by the scalar r. * * @param v * The input vector * @param r * The scaling value * * @return (v.getXF() * r, v.getYF() * r, v.getZF() * r, v.getWF() * r) */ public final static @Nonnull VectorI4F scale( final @Nonnull VectorReadable4F v, final float r) { return new VectorI4F( v.getXF() * r, v.getYF() * r, v.getZF() * r, v.getWF() * r); } /** * Subtract the vector v1 from the vector v0. * * @param v0 * The left input vector * @param v1 * The right input vector * * @return (v0.getXF() - v1.getXF(), v0.getYF() - v1.getYF(), v0.getZF() - v1.getZF()) */ public final static @Nonnull VectorI4F subtract( final @Nonnull VectorReadable4F v0, final @Nonnull VectorReadable4F v1) { return new VectorI4F( v0.getXF() - v1.getXF(), v0.getYF() - v1.getYF(), v0.getZF() - v1.getZF(), v0.getWF() - v1.getWF()); } public final float x; public final float y; public final float z; public final float w; /** * The zero vector. */ public static final @Nonnull VectorI4F ZERO = new VectorI4F( 0.0f, 0.0f, 0.0f, 0.0f); /** * Calculate the absolute value of the vector v. * * @param v * The input vector * * @return (abs v.getXF(), abs v.getYF(), abs v.getZF(), abs v.getWF()) */ public final static @Nonnull VectorI4F absolute( final @Nonnull VectorReadable4F v) { return new VectorI4F(Math.abs(v.getXF()), Math.abs(v.getYF()), Math.abs(v .getZF()), Math.abs(v.getWF())); } /** * 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.getXF() + v1.getXF(), v0.getYF() + v1.getYF(), v0.getZF() + v1.getZF(), v0.getWF() + v1.getWF()) */ public final static @Nonnull VectorI4F add( final @Nonnull VectorReadable4F v0, final @Nonnull VectorReadable4F v1) { return new VectorI4F( v0.getXF() + v1.getXF(), v0.getYF() + v1.getYF(), v0.getZF() + v1.getZF(), v0.getWF() + v1.getWF()); } /** * Default constructor, initializing the vector with values * [0.0, 0.0, 0.0, 1.0]. */ public VectorI4F() { this.x = 0.0f; this.y = 0.0f; this.z = 0.0f; this.w = 1.0f; } /** * Construct a vector initialized with the given values. */ public VectorI4F( 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 VectorI4F( final VectorReadable4F v) { this.x = v.getXF(); this.y = v.getYF(); this.z = v.getZF(); this.w = v.getWF(); } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @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 VectorReadable4F other = (VectorI4F) obj; if (Float.floatToIntBits(this.getWF()) != Float.floatToIntBits(other .getWF())) { return false; } if (Float.floatToIntBits(this.getXF()) != Float.floatToIntBits(other .getXF())) { return false; } if (Float.floatToIntBits(this.getYF()) != Float.floatToIntBits(other .getYF())) { return false; } if (Float.floatToIntBits(this.getZF()) != Float.floatToIntBits(other .getZF())) { 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; } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public final int hashCode() { final int prime = 31; int result = 1; result = (prime * result) + Float.floatToIntBits(this.getWF()); result = (prime * result) + Float.floatToIntBits(this.getXF()); result = (prime * result) + Float.floatToIntBits(this.getYF()); result = (prime * result) + Float.floatToIntBits(this.getZF()); return result; } @Override public final String toString() { final StringBuilder builder = new StringBuilder(); builder.append("[VectorI4F "); builder.append(this.getXF()); builder.append(" "); builder.append(this.getYF()); builder.append(" "); builder.append(this.getZF()); builder.append(" "); builder.append(this.getWF()); builder.append("]"); return builder.toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy