
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