430 lines
12 KiB
C++
430 lines
12 KiB
C++
#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
|