| #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<deUint32, Size> asUint (void) const { return cast<deUint32>(); } |
| 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 <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; |
| } |
| |
| // 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; |
| } |
| |
| } // tcu |
| |
| #endif // _TCUVECTOR_HPP |