
com.io7m.jtensors.VectorM4L 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.CheckedMath;
/**
*
* A four-dimensional mutable vector type with integer elements.
*
*
* Values of this type cannot be accessed safely from multiple threads without
* explicit synchronization.
*
*
* @since 5.3.0
*/
@NotThreadSafe public class VectorM4L implements VectorReadable4L
{
/**
* 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)
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorM4L absolute(
final @Nonnull VectorReadable4L v,
final @Nonnull VectorM4L out)
{
final long x = CheckedMath.absolute(v.getXL());
final long y = CheckedMath.absolute(v.getYL());
final long z = CheckedMath.absolute(v.getZL());
final long w = CheckedMath.absolute(v.getWL());
out.x = x;
out.y = y;
out.z = z;
out.w = w;
return out;
}
/**
* Calculate the absolute values of the elements in vector v
,
* saving the result to v
.
*
* @param v
* The input vector
*
* @return (abs v.x, abs v.y, abs v.z, abs.w)
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorM4L absoluteInPlace(
final @Nonnull VectorM4L v)
{
return VectorM4L.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)
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorM4L add(
final @Nonnull VectorReadable4L v0,
final @Nonnull VectorReadable4L v1,
final @Nonnull VectorM4L out)
{
final long x = CheckedMath.add(v0.getXL(), v1.getXL());
final long y = CheckedMath.add(v0.getYL(), v1.getYL());
final long z = CheckedMath.add(v0.getZL(), v1.getZL());
final long w = CheckedMath.add(v0.getWL(), v1.getWL());
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)
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorM4L addInPlace(
final @Nonnull VectorM4L v0,
final @Nonnull VectorReadable4L v1)
{
return VectorM4L.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))
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorM4L addScaled(
final @Nonnull VectorReadable4L v0,
final @Nonnull VectorReadable4L v1,
final double r,
final @Nonnull VectorM4L out)
{
final long mx = CheckedMath.multiply(v1.getXL(), r);
final long my = CheckedMath.multiply(v1.getYL(), r);
final long mz = CheckedMath.multiply(v1.getZL(), r);
final long mw = CheckedMath.multiply(v1.getWL(), r);
final long x = CheckedMath.add(v0.getXL(), mx);
final long y = CheckedMath.add(v0.getYL(), my);
final long z = CheckedMath.add(v0.getZL(), mz);
final long w = CheckedMath.add(v0.getWL(), mw);
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))
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorM4L addScaledInPlace(
final @Nonnull VectorM4L v0,
final @Nonnull VectorReadable4L v1,
final double r)
{
return VectorM4L.addScaled(v0, v1, r, v0);
}
private final static long cast(
final double x)
{
return Math.round(x);
}
/**
* 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 VectorM4L clamp(
final @Nonnull VectorReadable4L v,
final long minimum,
final long maximum,
final @Nonnull VectorM4L out)
{
final long x = Math.min(Math.max(v.getXL(), minimum), maximum);
final long y = Math.min(Math.max(v.getYL(), minimum), maximum);
final long z = Math.min(Math.max(v.getZL(), minimum), maximum);
final long w = Math.min(Math.max(v.getWL(), 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 VectorM4L clampByVector(
final @Nonnull VectorReadable4L v,
final @Nonnull VectorReadable4L minimum,
final @Nonnull VectorReadable4L maximum,
final @Nonnull VectorM4L out)
{
final long x =
Math.min(Math.max(v.getXL(), minimum.getXL()), maximum.getXL());
final long y =
Math.min(Math.max(v.getYL(), minimum.getYL()), maximum.getYL());
final long z =
Math.min(Math.max(v.getZL(), minimum.getZL()), maximum.getZL());
final long w =
Math.min(Math.max(v.getWL(), minimum.getWL()), maximum.getWL());
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 VectorM4L clampByVectorInPlace(
final @Nonnull VectorM4L v,
final @Nonnull VectorReadable4L minimum,
final @Nonnull VectorReadable4L maximum)
{
return VectorM4L.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 VectorM4L clampInPlace(
final @Nonnull VectorM4L v,
final long minimum,
final long maximum)
{
return VectorM4L.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 VectorM4L clampMaximum(
final @Nonnull VectorReadable4L v,
final long maximum,
final @Nonnull VectorM4L out)
{
final long x = Math.min(v.getXL(), maximum);
final long y = Math.min(v.getYL(), maximum);
final long z = Math.min(v.getZL(), maximum);
final long w = Math.min(v.getWL(), 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 VectorM4L clampMaximumByVector(
final @Nonnull VectorReadable4L v,
final @Nonnull VectorReadable4L maximum,
final @Nonnull VectorM4L out)
{
final long x = Math.min(v.getXL(), maximum.getXL());
final long y = Math.min(v.getYL(), maximum.getYL());
final long z = Math.min(v.getZL(), maximum.getZL());
final long w = Math.min(v.getWL(), maximum.getWL());
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 VectorM4L clampMaximumByVectorInPlace(
final @Nonnull VectorM4L v,
final @Nonnull VectorReadable4L maximum)
{
return VectorM4L.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 VectorM4L clampMaximumInPlace(
final @Nonnull VectorM4L v,
final long maximum)
{
return VectorM4L.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 VectorM4L clampMinimum(
final @Nonnull VectorReadable4L v,
final long minimum,
final @Nonnull VectorM4L out)
{
final long x = Math.max(v.getXL(), minimum);
final long y = Math.max(v.getYL(), minimum);
final long z = Math.max(v.getZL(), minimum);
final long w = Math.max(v.getWL(), 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 VectorM4L clampMinimumByVector(
final @Nonnull VectorReadable4L v,
final @Nonnull VectorReadable4L minimum,
final @Nonnull VectorM4L out)
{
final long x = Math.max(v.getXL(), minimum.getXL());
final long y = Math.max(v.getYL(), minimum.getYL());
final long z = Math.max(v.getZL(), minimum.getZL());
final long w = Math.max(v.getWL(), minimum.getWL());
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 VectorM4L clampMinimumByVectorInPlace(
final @Nonnull VectorM4L v,
final @Nonnull VectorReadable4L minimum)
{
return VectorM4L.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 VectorM4L clampMinimumInPlace(
final @Nonnull VectorM4L v,
final long minimum)
{
return VectorM4L.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 VectorM4L copy(
final @Nonnull VectorReadable4L input,
final @Nonnull VectorM4L output)
{
output.x = input.getXL();
output.y = input.getYL();
output.z = input.getZL();
output.w = input.getWL();
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.
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static long distance(
final @Nonnull VectorReadable4L v0,
final @Nonnull VectorReadable4L v1)
{
final @Nonnull VectorM4L vr = new VectorM4L();
return VectorM4L.magnitude(VectorM4L.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
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static long dotProduct(
final @Nonnull VectorReadable4L v0,
final @Nonnull VectorReadable4L v1)
{
final long mx = CheckedMath.multiply(v0.getXL(), v1.getXL());
final long my = CheckedMath.multiply(v0.getYL(), v1.getYL());
final long mz = CheckedMath.multiply(v0.getZL(), v1.getZL());
final long mw = CheckedMath.multiply(v0.getWL(), v1.getWL());
return CheckedMath.add(CheckedMath.add(CheckedMath.add(mx, my), mz), mw);
}
/**
* 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
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorM4L interpolateLinear(
final @Nonnull VectorReadable4L v0,
final @Nonnull VectorReadable4L v1,
final double alpha,
final @Nonnull VectorM4L r)
{
final @Nonnull VectorM4L w0 = new VectorM4L();
final @Nonnull VectorM4L w1 = new VectorM4L();
VectorM4L.scale(v0, 1.0 - alpha, w0);
VectorM4L.scale(v1, alpha, w1);
return VectorM4L.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
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static long magnitude(
final @Nonnull VectorReadable4L v)
{
return VectorM4L.cast(Math.sqrt(VectorM4L.magnitudeSquared(v)));
}
/**
* Calculate the squared magnitude of the vector v
.
*
* @param v
* The input vector
*
* @return The squared magnitude of the input vector
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static long magnitudeSquared(
final @Nonnull VectorReadable4L v)
{
return VectorM4L.dotProduct(v, v);
}
/**
* Calculate the projection of the vector p
onto the vector
* q
, saving the result in r
.
*
* @return ((dotProduct p q) / magnitudeSquared q) * q
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorM4L projection(
final @Nonnull VectorReadable4L p,
final @Nonnull VectorReadable4L q,
final @Nonnull VectorM4L r)
{
final long dot = VectorM4L.dotProduct(p, q);
final long qms = VectorM4L.magnitudeSquared(q);
final long s = dot / qms;
return VectorM4L.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)
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorM4L scale(
final @Nonnull VectorReadable4L v,
final double r,
final @Nonnull VectorM4L out)
{
final long mx = CheckedMath.multiply(v.getXL(), r);
final long my = CheckedMath.multiply(v.getYL(), r);
final long mz = CheckedMath.multiply(v.getZL(), r);
final long mw = CheckedMath.multiply(v.getWL(), r);
out.x = mx;
out.y = my;
out.z = mz;
out.w = mw;
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)
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorM4L scaleInPlace(
final @Nonnull VectorM4L v,
final long r)
{
return VectorM4L.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)
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorM4L subtract(
final @Nonnull VectorReadable4L v0,
final @Nonnull VectorReadable4L v1,
final @Nonnull VectorM4L out)
{
final long mx = CheckedMath.subtract(v0.getXL(), v1.getXL());
final long my = CheckedMath.subtract(v0.getYL(), v1.getYL());
final long mz = CheckedMath.subtract(v0.getZL(), v1.getZL());
final long mw = CheckedMath.subtract(v0.getWL(), v1.getWL());
out.x = mx;
out.y = my;
out.z = mz;
out.w = mw;
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)
*
* @throws ArithmeticException
* Iff an internal arithmetic operation causes an integer overflow
*/
public final static @Nonnull VectorM4L subtractInPlace(
final @Nonnull VectorM4L v0,
final @Nonnull VectorReadable4L v1)
{
return VectorM4L.subtract(v0, v1, v0);
}
public long x = 0;
public long y = 0;
public long z = 0;
public long w = 1;
/**
* Default constructor, initializing the vector with values
* [0, 0, 0, 1]
.
*/
public VectorM4L()
{
}
/**
* Construct a vector initialized with the given values.
*/
public VectorM4L(
final long x,
final long y,
final long z,
final long 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 VectorM4L(
final @Nonnull VectorReadable4L v)
{
this.x = v.getXL();
this.y = v.getYL();
this.z = v.getZL();
this.w = v.getWL();
}
@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 VectorM4L other = (VectorM4L) obj;
if (this.w != other.w) {
return false;
}
if (this.x != other.x) {
return false;
}
if (this.y != other.y) {
return false;
}
if (this.z != other.z) {
return false;
}
return true;
}
@Override public final long getWL()
{
return this.w;
}
@Override public final long getXL()
{
return this.x;
}
@Override public final long getYL()
{
return this.y;
}
@Override public final long getZL()
{
return this.z;
}
@Override public final int hashCode()
{
final long prime = 31;
long result = 1;
result = (prime * result) + this.w;
result = (prime * result) + this.x;
result = (prime * result) + this.y;
result = (prime * result) + this.z;
return (int) result;
}
@Override public final String toString()
{
final StringBuilder builder = new StringBuilder();
builder.append("[VectorM4L ");
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