From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- gfx/angle/checkout/src/common/vector_utils.h | 523 +++++++++++++++++++++++++++ 1 file changed, 523 insertions(+) create mode 100644 gfx/angle/checkout/src/common/vector_utils.h (limited to 'gfx/angle/checkout/src/common/vector_utils.h') diff --git a/gfx/angle/checkout/src/common/vector_utils.h b/gfx/angle/checkout/src/common/vector_utils.h new file mode 100644 index 0000000000..88c7492e72 --- /dev/null +++ b/gfx/angle/checkout/src/common/vector_utils.h @@ -0,0 +1,523 @@ +// +// Copyright 2016 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// vector_utils.h: Utility classes implementing various vector operations + +#ifndef COMMON_VECTOR_UTILS_H_ +#define COMMON_VECTOR_UTILS_H_ + +#include +#include +#include +#include + +namespace angle +{ + +template +class Vector; + +using Vector2 = Vector<2, float>; +using Vector3 = Vector<3, float>; +using Vector4 = Vector<4, float>; + +using Vector2I = Vector<2, int>; +using Vector3I = Vector<3, int>; +using Vector4I = Vector<4, int>; + +using Vector2U = Vector<2, unsigned int>; +using Vector3U = Vector<3, unsigned int>; +using Vector4U = Vector<4, unsigned int>; + +template +class VectorBase +{ + public: + using VectorN = Vector; + + // Constructors + VectorBase() = default; + explicit VectorBase(Type element); + + template + VectorBase(const VectorBase &other); + + template + VectorBase(const Arg1 &arg1, const Arg2 &arg2, const Args &...args); + + // Access the vector backing storage directly + const Type *data() const { return mData; } + Type *data() { return mData; } + constexpr size_t size() const { return Dimension; } + + // Load or store the pointer from / to raw data + static VectorN Load(const Type *source); + static void Store(const VectorN &source, Type *destination); + + // Index the vector + Type &operator[](size_t i) { return mData[i]; } + const Type &operator[](size_t i) const { return mData[i]; } + + // Basic arithmetic operations + VectorN operator+() const; + VectorN operator-() const; + VectorN operator+(const VectorN &other) const; + VectorN operator-(const VectorN &other) const; + VectorN operator*(const VectorN &other) const; + VectorN operator/(const VectorN &other) const; + VectorN operator*(Type other) const; + VectorN operator/(Type other) const; + friend VectorN operator*(Type a, const VectorN &b) { return b * a; } + + // Compound arithmetic operations + VectorN &operator+=(const VectorN &other); + VectorN &operator-=(const VectorN &other); + VectorN &operator*=(const VectorN &other); + VectorN &operator/=(const VectorN &other); + VectorN &operator*=(Type other); + VectorN &operator/=(Type other); + + // Comparison operators + bool operator==(const VectorBase &other) const; + bool operator!=(const VectorBase &other) const; + + // Other arithmetic operations + Type length() const; + Type lengthSquared() const; + Type dot(const VectorBase &other) const; + VectorN normalized() const; + + protected: + template + void initWithList(const Vector &arg1, const Args &...args); + + // Some old compilers consider this function an alternative for initWithList(Vector) + // when the variant above is more precise. Use SFINAE on the return value to hide + // this variant for non-arithmetic types. The return value is still void. + template + typename std::enable_if::value>::type initWithList( + OtherType arg1, + const Args &...args); + + template + void initWithList() const; + + template + friend class VectorBase; + + Type mData[Dimension]; +}; + +template +std::ostream &operator<<(std::ostream &ostream, const VectorBase &vector); + +template +class Vector<2, Type> : public VectorBase<2, Type> +{ + public: + // Import the constructors defined in VectorBase + using VectorBase<2, Type>::VectorBase; + + // Element shorthands + Type &x() { return this->mData[0]; } + Type &y() { return this->mData[1]; } + + const Type &x() const { return this->mData[0]; } + const Type &y() const { return this->mData[1]; } +}; + +template +std::ostream &operator<<(std::ostream &ostream, const Vector<2, Type> &vector); + +template +class Vector<3, Type> : public VectorBase<3, Type> +{ + public: + // Import the constructors defined in VectorBase + using VectorBase<3, Type>::VectorBase; + + // Additional operations + Vector<3, Type> cross(const Vector<3, Type> &other) const; + + // Element shorthands + Type &x() { return this->mData[0]; } + Type &y() { return this->mData[1]; } + Type &z() { return this->mData[2]; } + + const Type &x() const { return this->mData[0]; } + const Type &y() const { return this->mData[1]; } + const Type &z() const { return this->mData[2]; } +}; + +template +std::ostream &operator<<(std::ostream &ostream, const Vector<3, Type> &vector); + +template +class Vector<4, Type> : public VectorBase<4, Type> +{ + public: + // Import the constructors defined in VectorBase + using VectorBase<4, Type>::VectorBase; + + // Element shorthands + Type &x() { return this->mData[0]; } + Type &y() { return this->mData[1]; } + Type &z() { return this->mData[2]; } + Type &w() { return this->mData[3]; } + + const Type &x() const { return this->mData[0]; } + const Type &y() const { return this->mData[1]; } + const Type &z() const { return this->mData[2]; } + const Type &w() const { return this->mData[3]; } +}; + +template +std::ostream &operator<<(std::ostream &ostream, const Vector<4, Type> &vector); + +// Implementation of constructors and misc operations + +template +VectorBase::VectorBase(Type element) +{ + for (size_t i = 0; i < Dimension; ++i) + { + mData[i] = element; + } +} + +template +template +VectorBase::VectorBase(const VectorBase &other) +{ + for (size_t i = 0; i < Dimension; ++i) + { + mData[i] = static_cast(other.mData[i]); + } +} + +// Ideally we would like to have only two constructors: +// - a scalar constructor that takes Type as a parameter +// - a compound constructor +// However if we define the compound constructor for when it has a single arguments, then calling +// Vector2(0.0) will be ambiguous. To solve this we take advantage of there being a single compound +// constructor with a single argument, which is the copy constructor. We end up with three +// constructors: +// - the scalar constructor +// - the copy constructor +// - the compound constructor for two or more arguments, hence the arg1, and arg2 here. +template +template +VectorBase::VectorBase(const Arg1 &arg1, const Arg2 &arg2, const Args &...args) +{ + initWithList<0>(arg1, arg2, args...); +} + +template +template +void VectorBase::initWithList(const Vector &arg1, + const Args &...args) +{ + static_assert(CurrentIndex + OtherDimension <= Dimension, + "Too much data in the vector constructor."); + for (size_t i = 0; i < OtherDimension; ++i) + { + mData[CurrentIndex + i] = static_cast(arg1.mData[i]); + } + initWithList(args...); +} + +template +template +typename std::enable_if::value>::type +VectorBase::initWithList(OtherType arg1, const Args &...args) +{ + static_assert(CurrentIndex + 1 <= Dimension, "Too much data in the vector constructor."); + mData[CurrentIndex] = static_cast(arg1); + initWithList(args...); +} + +template +template +void VectorBase::initWithList() const +{ + static_assert(CurrentIndex == Dimension, "Not enough data in the vector constructor."); +} + +template +Vector VectorBase::Load(const Type *source) +{ + Vector result; + for (size_t i = 0; i < Dimension; ++i) + { + result.mData[i] = source[i]; + } + return result; +} + +template +void VectorBase::Store(const Vector &source, Type *destination) +{ + for (size_t i = 0; i < Dimension; ++i) + { + destination[i] = source.mData[i]; + } +} + +// Implementation of basic arithmetic operations +template +Vector VectorBase::operator+() const +{ + Vector result; + for (size_t i = 0; i < Dimension; ++i) + { + result.mData[i] = +mData[i]; + } + return result; +} + +template +Vector VectorBase::operator-() const +{ + Vector result; + for (size_t i = 0; i < Dimension; ++i) + { + result.mData[i] = -mData[i]; + } + return result; +} + +template +Vector VectorBase::operator+( + const Vector &other) const +{ + Vector result; + for (size_t i = 0; i < Dimension; ++i) + { + result.mData[i] = mData[i] + other.mData[i]; + } + return result; +} + +template +Vector VectorBase::operator-( + const Vector &other) const +{ + Vector result; + for (size_t i = 0; i < Dimension; ++i) + { + result.mData[i] = mData[i] - other.mData[i]; + } + return result; +} + +template +Vector VectorBase::operator*( + const Vector &other) const +{ + Vector result; + for (size_t i = 0; i < Dimension; ++i) + { + result.mData[i] = mData[i] * other.mData[i]; + } + return result; +} + +template +Vector VectorBase::operator/( + const Vector &other) const +{ + Vector result; + for (size_t i = 0; i < Dimension; ++i) + { + result.mData[i] = mData[i] / other.mData[i]; + } + return result; +} + +template +Vector VectorBase::operator*(Type other) const +{ + Vector result; + for (size_t i = 0; i < Dimension; ++i) + { + result.mData[i] = mData[i] * other; + } + return result; +} + +template +Vector VectorBase::operator/(Type other) const +{ + Vector result; + for (size_t i = 0; i < Dimension; ++i) + { + result.mData[i] = mData[i] / other; + } + return result; +} + +// Implementation of compound arithmetic operations +template +Vector &VectorBase::operator+=( + const Vector &other) +{ + for (size_t i = 0; i < Dimension; ++i) + { + mData[i] += other.mData[i]; + } + return *static_cast *>(this); +} + +template +Vector &VectorBase::operator-=( + const Vector &other) +{ + for (size_t i = 0; i < Dimension; ++i) + { + mData[i] -= other.mData[i]; + } + return *static_cast *>(this); +} + +template +Vector &VectorBase::operator*=( + const Vector &other) +{ + for (size_t i = 0; i < Dimension; ++i) + { + mData[i] *= other.mData[i]; + } + return *static_cast *>(this); +} + +template +Vector &VectorBase::operator/=( + const Vector &other) +{ + for (size_t i = 0; i < Dimension; ++i) + { + mData[i] /= other.mData[i]; + } + return *static_cast *>(this); +} + +template +Vector &VectorBase::operator*=(Type other) +{ + for (size_t i = 0; i < Dimension; ++i) + { + mData[i] *= other; + } + return *static_cast *>(this); +} + +template +Vector &VectorBase::operator/=(Type other) +{ + for (size_t i = 0; i < Dimension; ++i) + { + mData[i] /= other; + } + return *static_cast *>(this); +} + +// Implementation of comparison operators +template +bool VectorBase::operator==(const VectorBase &other) const +{ + for (size_t i = 0; i < Dimension; ++i) + { + if (mData[i] != other.mData[i]) + { + return false; + } + } + return true; +} + +template +bool VectorBase::operator!=(const VectorBase &other) const +{ + return !(*this == other); +} + +// Implementation of other arithmetic operations +template +Type VectorBase::length() const +{ + static_assert(std::is_floating_point::value, + "VectorN::length is only defined for floating point vectors"); + return std::sqrt(lengthSquared()); +} + +template +Type VectorBase::lengthSquared() const +{ + return dot(*this); +} + +template +Type VectorBase::dot(const VectorBase &other) const +{ + Type sum = Type(); + for (size_t i = 0; i < Dimension; ++i) + { + sum += mData[i] * other.mData[i]; + } + return sum; +} + +template +std::ostream &operator<<(std::ostream &ostream, const VectorBase &vector) +{ + ostream << "[ "; + for (size_t elementIdx = 0; elementIdx < Dimension; elementIdx++) + { + if (elementIdx > 0) + { + ostream << ", "; + } + ostream << vector.data()[elementIdx]; + } + ostream << " ]"; + return ostream; +} + +template +Vector VectorBase::normalized() const +{ + static_assert(std::is_floating_point::value, + "VectorN::normalized is only defined for floating point vectors"); + return *this / length(); +} + +template +std::ostream &operator<<(std::ostream &ostream, const Vector<2, Type> &vector) +{ + return ostream << static_cast &>(vector); +} + +template +Vector<3, Type> Vector<3, Type>::cross(const Vector<3, Type> &other) const +{ + return Vector<3, Type>(y() * other.z() - z() * other.y(), z() * other.x() - x() * other.z(), + x() * other.y() - y() * other.x()); +} + +template +std::ostream &operator<<(std::ostream &ostream, const Vector<3, Type> &vector) +{ + return ostream << static_cast &>(vector); +} + +template +std::ostream &operator<<(std::ostream &ostream, const Vector<4, Type> &vector) +{ + return ostream << static_cast &>(vector); +} + +} // namespace angle + +#endif // COMMON_VECTOR_UTILS_H_ -- cgit v1.2.3