#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 namespace tcu { // Accessor proxy class for Vectors. template class VecAccess { public: explicit VecAccess(Vector &v, int x, int y); explicit VecAccess(Vector &v, int x, int y, int z); explicit VecAccess(Vector &v, int x, int y, int z, int w); VecAccess &operator=(const Vector &v); operator Vector(void) const; private: Vector &m_vector; int m_index[Size]; }; template VecAccess::VecAccess(Vector &v, int x, int y) : m_vector(v) { DE_STATIC_ASSERT(Size == 2); m_index[0] = x; m_index[1] = y; } template VecAccess::VecAccess(Vector &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 VecAccess::VecAccess(Vector &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 VecAccess &VecAccess::operator=(const Vector &v) { for (int i = 0; i < Size; i++) m_vector.m_data[m_index[i]] = v.m_data[i]; return *this; } // Vector class. template 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 &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 xy(void) { DE_ASSERT(Size >= 2); return VecAccess(*this, 0, 1); } VecAccess xz(void) { DE_ASSERT(Size >= 2); return VecAccess(*this, 0, 2); } VecAccess xw(void) { DE_ASSERT(Size >= 2); return VecAccess(*this, 0, 3); } VecAccess yz(void) { DE_ASSERT(Size >= 2); return VecAccess(*this, 1, 2); } VecAccess yw(void) { DE_ASSERT(Size >= 2); return VecAccess(*this, 1, 3); } VecAccess zw(void) { DE_ASSERT(Size >= 2); return VecAccess(*this, 2, 3); } VecAccess xyz(void) { DE_ASSERT(Size >= 3); return VecAccess(*this, 0, 1, 2); } VecAccess xyw(void) { DE_ASSERT(Size >= 3); return VecAccess(*this, 0, 1, 3); } VecAccess xzw(void) { DE_ASSERT(Size >= 3); return VecAccess(*this, 0, 2, 3); } VecAccess zyx(void) { DE_ASSERT(Size >= 3); return VecAccess(*this, 2, 1, 0); } VecAccess yzw(void) { DE_ASSERT(Size >= 3); return VecAccess(*this, 1, 2, 3); } VecAccess wzy(void) { DE_ASSERT(Size >= 3); return VecAccess(*this, 3, 2, 1); } VecAccess xyzw(void) { DE_ASSERT(Size >= 4); return VecAccess(*this, 0, 1, 2, 3); } // Swizzles. Vector swizzle(int a) const { DE_ASSERT(a >= 0 && a < Size); return Vector(m_data[a]); } Vector swizzle(int a, int b) const { DE_ASSERT(a >= 0 && a < Size); DE_ASSERT(b >= 0 && b < Size); return Vector(m_data[a], m_data[b]); } Vector 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(m_data[a], m_data[b], m_data[c]); } Vector 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(m_data[a], m_data[b], m_data[c], m_data[d]); } Vector asFloat(void) const { return cast(); } Vector asInt(void) const { return cast(); } Vector asUint(void) const { return cast(); } Vector asBool(void) const { return cast(); } // Operators. Vector &operator+=(const Vector &v); Vector &operator-=(const Vector &v); Vector &operator=(const Vector &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 &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 &v) const { return !(*this == v); } // Miscellaneous conversions. template Vector cast(void) const; template Vector bitCast(void) const; template Vector toWidth(void) const; } DE_WARN_UNUSED_TYPE; template inline Vector::Vector(void) { for (int i = 0; i < Size; i++) m_data[i] = T(); } template inline Vector::Vector(T s) { for (int i = 0; i < Size; i++) m_data[i] = s; } template inline Vector::Vector(T x_, T y_) { DE_STATIC_ASSERT(Size == 2); m_data[0] = x_; m_data[1] = y_; } template inline Vector::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 inline Vector::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 inline Vector::Vector(const Vector &v) { for (int i = 0; i < Size; i++) m_data[i] = v.m_data[i]; } template inline Vector &Vector::operator=(const Vector &v) { for (int i = 0; i < Size; i++) m_data[i] = v.m_data[i]; return *this; } template inline Vector::Vector(const T (&v)[Size]) { for (int i = 0; i < Size; i++) m_data[i] = v[i]; } // VecAccess to Vector cast. template VecAccess::operator Vector(void) const { Vector vec; for (int i = 0; i < Size; i++) vec.m_data[i] = m_vector.m_data[m_index[i]]; return vec; } // Type cast. template template inline Vector Vector::cast(void) const { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = NewT(m_data[i]); return res; } // Bit-exact reinterpret cast. template template inline Vector Vector::bitCast(void) const { Vector 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 template inline Vector Vector::toWidth(void) const { Vector 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 inline Vector operator-(const Vector &a) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = -a.m_data[i]; return res; } template inline Vector operator+(const Vector &a, const Vector &b) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = a.m_data[i] + b.m_data[i]; return res; } template inline Vector operator-(const Vector &a, const Vector &b) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = a.m_data[i] - b.m_data[i]; return res; } template inline Vector operator*(const Vector &a, const Vector &b) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = a.m_data[i] * b.m_data[i]; return res; } template inline Vector operator/(const Vector &a, const Vector &b) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = a.m_data[i] / b.m_data[i]; return res; } template inline Vector operator<<(const Vector &a, const Vector &b) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = a.m_data[i] << b.m_data[i]; return res; } template inline Vector operator>>(const Vector &a, const Vector &b) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = a.m_data[i] >> b.m_data[i]; return res; } template inline Vector operator*(T s, const Vector &a) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = s * a.m_data[i]; return res; } template inline Vector operator+(T s, const Vector &a) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = s + a.m_data[i]; return res; } template inline Vector operator-(T s, const Vector &a) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = s - a.m_data[i]; return res; } template inline Vector operator-(const Vector &a, T s) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = a.m_data[i] - s; return res; } template inline Vector operator/(T s, const Vector &a) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = s / a.m_data[i]; return res; } template inline Vector operator*(const Vector &a, T s) { return s * a; } template inline Vector operator+(const Vector &a, T s) { return s + a; } template inline Vector operator/(const Vector &a, T s) { Vector res; for (int i = 0; i < Size; i++) res.m_data[i] = a.m_data[i] / s; return res; } template inline Vector &Vector::operator+=(const Vector &v) { for (int i = 0; i < Size; i++) m_data[i] += v.m_data[i]; return *this; } template inline Vector &Vector::operator-=(const Vector &v) { for (int i = 0; i < Size; i++) m_data[i] -= v.m_data[i]; return *this; } // Stream operator. template std::ostream &operator<<(std::ostream &stream, const tcu::Vector &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