| #ifndef _TCUVECTOR_HPP |
| #define _TCUVECTOR_HPP |
| /*------------------------------------------------------------------------- |
| * drawElements Quality Program Tester Core |
| * ---------------------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Generic vector template. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "tcuDefs.hpp" |
| #include "tcuVectorType.hpp" |
| #include "deInt32.h" |
| |
| #include <ostream> |
| |
| namespace tcu |
| { |
| |
| // Accessor proxy class for Vectors. |
| template <typename T, int VecSize, int Size> |
| class VecAccess |
| { |
| public: |
| explicit VecAccess(Vector<T, VecSize> &v, int x, int y); |
| explicit VecAccess(Vector<T, VecSize> &v, int x, int y, int z); |
| explicit VecAccess(Vector<T, VecSize> &v, int x, int y, int z, int w); |
| |
| VecAccess &operator=(const Vector<T, Size> &v); |
| |
| operator Vector<T, Size>(void) const; |
| |
| private: |
| Vector<T, VecSize> &m_vector; |
| int m_index[Size]; |
| }; |
| |
| template <typename T, int VecSize, int Size> |
| VecAccess<T, VecSize, Size>::VecAccess(Vector<T, VecSize> &v, int x, int y) : m_vector(v) |
| { |
| DE_STATIC_ASSERT(Size == 2); |
| m_index[0] = x; |
| m_index[1] = y; |
| } |
| |
| template <typename T, int VecSize, int Size> |
| VecAccess<T, VecSize, Size>::VecAccess(Vector<T, VecSize> &v, int x, int y, int z) : m_vector(v) |
| { |
| DE_STATIC_ASSERT(Size == 3); |
| m_index[0] = x; |
| m_index[1] = y; |
| m_index[2] = z; |
| } |
| |
| template <typename T, int VecSize, int Size> |
| VecAccess<T, VecSize, Size>::VecAccess(Vector<T, VecSize> &v, int x, int y, int z, int w) : m_vector(v) |
| { |
| DE_STATIC_ASSERT(Size == 4); |
| m_index[0] = x; |
| m_index[1] = y; |
| m_index[2] = z; |
| m_index[3] = w; |
| } |
| |
| template <typename T, int VecSize, int Size> |
| VecAccess<T, VecSize, Size> &VecAccess<T, VecSize, Size>::operator=(const Vector<T, Size> &v) |
| { |
| for (int i = 0; i < Size; i++) |
| m_vector.m_data[m_index[i]] = v.m_data[i]; |
| return *this; |
| } |
| |
| // Vector class. |
| template <typename T, int Size> |
| class Vector |
| { |
| public: |
| typedef T Element; |
| enum |
| { |
| SIZE = Size, |
| }; |
| |
| T m_data[Size]; |
| |
| // Constructors. |
| explicit Vector(void); |
| explicit Vector(T s_); // replicate |
| Vector(T x_, T y_); |
| Vector(T x_, T y_, T z_); |
| Vector(T x_, T y_, T z_, T w_); |
| Vector(const Vector<T, Size> &v); |
| Vector(const T (&v)[Size]); |
| |
| const T *getPtr(void) const |
| { |
| return &m_data[0]; |
| } |
| T *getPtr(void) |
| { |
| return &m_data[0]; |
| } |
| |
| // Read-only access. |
| T x(void) const |
| { |
| return m_data[0]; |
| } |
| T y(void) const |
| { |
| DE_STATIC_ASSERT(Size >= 2); |
| return m_data[1]; |
| } |
| T z(void) const |
| { |
| DE_STATIC_ASSERT(Size >= 3); |
| return m_data[2]; |
| } |
| T w(void) const |
| { |
| DE_STATIC_ASSERT(Size >= 4); |
| return m_data[3]; |
| } |
| |
| // Read-write access. |
| T &x(void) |
| { |
| return m_data[0]; |
| } |
| T &y(void) |
| { |
| DE_STATIC_ASSERT(Size >= 2); |
| return m_data[1]; |
| } |
| T &z(void) |
| { |
| DE_STATIC_ASSERT(Size >= 3); |
| return m_data[2]; |
| } |
| T &w(void) |
| { |
| DE_STATIC_ASSERT(Size >= 4); |
| return m_data[3]; |
| } |
| |
| // Writable accessors. |
| VecAccess<T, Size, 2> xy(void) |
| { |
| DE_ASSERT(Size >= 2); |
| return VecAccess<T, Size, 2>(*this, 0, 1); |
| } |
| VecAccess<T, Size, 2> xz(void) |
| { |
| DE_ASSERT(Size >= 2); |
| return VecAccess<T, Size, 2>(*this, 0, 2); |
| } |
| VecAccess<T, Size, 2> xw(void) |
| { |
| DE_ASSERT(Size >= 2); |
| return VecAccess<T, Size, 2>(*this, 0, 3); |
| } |
| VecAccess<T, Size, 2> yz(void) |
| { |
| DE_ASSERT(Size >= 2); |
| return VecAccess<T, Size, 2>(*this, 1, 2); |
| } |
| VecAccess<T, Size, 2> yw(void) |
| { |
| DE_ASSERT(Size >= 2); |
| return VecAccess<T, Size, 2>(*this, 1, 3); |
| } |
| VecAccess<T, Size, 2> zw(void) |
| { |
| DE_ASSERT(Size >= 2); |
| return VecAccess<T, Size, 2>(*this, 2, 3); |
| } |
| VecAccess<T, Size, 3> xyz(void) |
| { |
| DE_ASSERT(Size >= 3); |
| return VecAccess<T, Size, 3>(*this, 0, 1, 2); |
| } |
| VecAccess<T, Size, 3> xyw(void) |
| { |
| DE_ASSERT(Size >= 3); |
| return VecAccess<T, Size, 3>(*this, 0, 1, 3); |
| } |
| VecAccess<T, Size, 3> xzw(void) |
| { |
| DE_ASSERT(Size >= 3); |
| return VecAccess<T, Size, 3>(*this, 0, 2, 3); |
| } |
| VecAccess<T, Size, 3> zyx(void) |
| { |
| DE_ASSERT(Size >= 3); |
| return VecAccess<T, Size, 3>(*this, 2, 1, 0); |
| } |
| VecAccess<T, Size, 3> yzw(void) |
| { |
| DE_ASSERT(Size >= 3); |
| return VecAccess<T, Size, 3>(*this, 1, 2, 3); |
| } |
| VecAccess<T, Size, 3> wzy(void) |
| { |
| DE_ASSERT(Size >= 3); |
| return VecAccess<T, Size, 3>(*this, 3, 2, 1); |
| } |
| VecAccess<T, Size, 4> xyzw(void) |
| { |
| DE_ASSERT(Size >= 4); |
| return VecAccess<T, Size, 4>(*this, 0, 1, 2, 3); |
| } |
| |
| // Swizzles. |
| Vector<T, 1> swizzle(int a) const |
| { |
| DE_ASSERT(a >= 0 && a < Size); |
| return Vector<T, 1>(m_data[a]); |
| } |
| Vector<T, 2> swizzle(int a, int b) const |
| { |
| DE_ASSERT(a >= 0 && a < Size); |
| DE_ASSERT(b >= 0 && b < Size); |
| return Vector<T, 2>(m_data[a], m_data[b]); |
| } |
| Vector<T, 3> swizzle(int a, int b, int c) const |
| { |
| DE_ASSERT(a >= 0 && a < Size); |
| DE_ASSERT(b >= 0 && b < Size); |
| DE_ASSERT(c >= 0 && c < Size); |
| return Vector<T, 3>(m_data[a], m_data[b], m_data[c]); |
| } |
| Vector<T, 4> swizzle(int a, int b, int c, int d) const |
| { |
| DE_ASSERT(a >= 0 && a < Size); |
| DE_ASSERT(b >= 0 && b < Size); |
| DE_ASSERT(c >= 0 && c < Size); |
| DE_ASSERT(d >= 0 && d < Size); |
| return Vector<T, 4>(m_data[a], m_data[b], m_data[c], m_data[d]); |
| } |
| |
| Vector<float, Size> asFloat(void) const |
| { |
| return cast<float>(); |
| } |
| Vector<int, Size> asInt(void) const |
| { |
| return cast<int>(); |
| } |
| Vector<uint32_t, Size> asUint(void) const |
| { |
| return cast<uint32_t>(); |
| } |
| Vector<bool, Size> asBool(void) const |
| { |
| return cast<bool>(); |
| } |
| |
| // Operators. |
| Vector<T, Size> &operator+=(const Vector<T, Size> &v); |
| Vector<T, Size> &operator-=(const Vector<T, Size> &v); |
| Vector<T, Size> &operator=(const Vector<T, Size> &v); |
| |
| const T &operator[](int ndx) const |
| { |
| DE_ASSERT(de::inBounds(ndx, 0, Size)); |
| return m_data[ndx]; |
| } |
| T &operator[](int ndx) |
| { |
| DE_ASSERT(de::inBounds(ndx, 0, Size)); |
| return m_data[ndx]; |
| } |
| |
| bool operator==(const Vector<T, Size> &v) const |
| { |
| for (int i = 0; i < Size; i++) |
| if (m_data[i] != v.m_data[i]) |
| return false; |
| return true; |
| } |
| bool operator!=(const Vector<T, Size> &v) const |
| { |
| return !(*this == v); |
| } |
| |
| // Miscellaneous conversions. |
| template <typename NewT> |
| Vector<NewT, Size> cast(void) const; |
| |
| template <typename NewT> |
| Vector<NewT, Size> bitCast(void) const; |
| |
| template <int NewSize> |
| Vector<T, NewSize> toWidth(void) const; |
| } DE_WARN_UNUSED_TYPE; |
| |
| template <typename T, int Size> |
| inline Vector<T, Size>::Vector(void) |
| { |
| for (int i = 0; i < Size; i++) |
| m_data[i] = T(); |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size>::Vector(T s) |
| { |
| for (int i = 0; i < Size; i++) |
| m_data[i] = s; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size>::Vector(T x_, T y_) |
| { |
| DE_STATIC_ASSERT(Size == 2); |
| m_data[0] = x_; |
| m_data[1] = y_; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size>::Vector(T x_, T y_, T z_) |
| { |
| DE_STATIC_ASSERT(Size == 3); |
| m_data[0] = x_; |
| m_data[1] = y_; |
| m_data[2] = z_; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size>::Vector(T x_, T y_, T z_, T w_) |
| { |
| DE_STATIC_ASSERT(Size == 4); |
| m_data[0] = x_; |
| m_data[1] = y_; |
| m_data[2] = z_; |
| m_data[3] = w_; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size>::Vector(const Vector<T, Size> &v) |
| { |
| for (int i = 0; i < Size; i++) |
| m_data[i] = v.m_data[i]; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> &Vector<T, Size>::operator=(const Vector<T, Size> &v) |
| { |
| for (int i = 0; i < Size; i++) |
| m_data[i] = v.m_data[i]; |
| return *this; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size>::Vector(const T (&v)[Size]) |
| { |
| for (int i = 0; i < Size; i++) |
| m_data[i] = v[i]; |
| } |
| |
| // VecAccess to Vector cast. |
| template <typename T, int VecSize, int Size> |
| VecAccess<T, VecSize, Size>::operator Vector<T, Size>(void) const |
| { |
| Vector<T, Size> vec; |
| for (int i = 0; i < Size; i++) |
| vec.m_data[i] = m_vector.m_data[m_index[i]]; |
| return vec; |
| } |
| |
| // Type cast. |
| template <typename T, int Size> |
| template <typename NewT> |
| inline Vector<NewT, Size> Vector<T, Size>::cast(void) const |
| { |
| Vector<NewT, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = NewT(m_data[i]); |
| return res; |
| } |
| |
| // Bit-exact reinterpret cast. |
| template <typename T, int Size> |
| template <typename NewT> |
| inline Vector<NewT, Size> Vector<T, Size>::bitCast(void) const |
| { |
| Vector<NewT, Size> res; |
| DE_STATIC_ASSERT(sizeof(res.m_data) == sizeof(m_data)); |
| memcpy(res.m_data, m_data, sizeof(m_data)); |
| return res; |
| } |
| |
| // Size cast. |
| template <typename T, int Size> |
| template <int NewSize> |
| inline Vector<T, NewSize> Vector<T, Size>::toWidth(void) const |
| { |
| Vector<T, NewSize> res; |
| int i; |
| for (i = 0; i < deMin32(Size, NewSize); i++) |
| res.m_data[i] = m_data[i]; |
| for (; i < NewSize; i++) |
| res.m_data[i] = T(0); |
| return res; |
| } |
| |
| // Operators. |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator-(const Vector<T, Size> &a) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = -a.m_data[i]; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator+(const Vector<T, Size> &a, const Vector<T, Size> &b) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = a.m_data[i] + b.m_data[i]; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator-(const Vector<T, Size> &a, const Vector<T, Size> &b) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = a.m_data[i] - b.m_data[i]; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator*(const Vector<T, Size> &a, const Vector<T, Size> &b) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = a.m_data[i] * b.m_data[i]; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator/(const Vector<T, Size> &a, const Vector<T, Size> &b) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = a.m_data[i] / b.m_data[i]; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator<<(const Vector<T, Size> &a, const Vector<T, Size> &b) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = a.m_data[i] << b.m_data[i]; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator>>(const Vector<T, Size> &a, const Vector<T, Size> &b) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = a.m_data[i] >> b.m_data[i]; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator*(T s, const Vector<T, Size> &a) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = s * a.m_data[i]; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator+(T s, const Vector<T, Size> &a) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = s + a.m_data[i]; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator-(T s, const Vector<T, Size> &a) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = s - a.m_data[i]; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator-(const Vector<T, Size> &a, T s) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = a.m_data[i] - s; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator/(T s, const Vector<T, Size> &a) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = s / a.m_data[i]; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator*(const Vector<T, Size> &a, T s) |
| { |
| return s * a; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator+(const Vector<T, Size> &a, T s) |
| { |
| return s + a; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> operator/(const Vector<T, Size> &a, T s) |
| { |
| Vector<T, Size> res; |
| for (int i = 0; i < Size; i++) |
| res.m_data[i] = a.m_data[i] / s; |
| return res; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> &Vector<T, Size>::operator+=(const Vector<T, Size> &v) |
| { |
| for (int i = 0; i < Size; i++) |
| m_data[i] += v.m_data[i]; |
| return *this; |
| } |
| |
| template <typename T, int Size> |
| inline Vector<T, Size> &Vector<T, Size>::operator-=(const Vector<T, Size> &v) |
| { |
| for (int i = 0; i < Size; i++) |
| m_data[i] -= v.m_data[i]; |
| return *this; |
| } |
| |
| // Stream operator. |
| template <typename T, int Size> |
| std::ostream &operator<<(std::ostream &stream, const tcu::Vector<T, Size> &vec) |
| { |
| stream << "("; |
| for (int i = 0; i < Size; i++) |
| { |
| if (i != 0) |
| stream << ", "; |
| stream << vec.m_data[i]; |
| } |
| stream << ")"; |
| return stream; |
| } |
| |
| } // namespace tcu |
| |
| #endif // _TCUVECTOR_HPP |