123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- /*
- * Copyright (C) 2011 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.
- */
- #ifndef ANDROID_VEC_H
- #define ANDROID_VEC_H
- #include <math.h>
- #include <stdint.h>
- #include <stddef.h>
- #include "traits.h"
- // -----------------------------------------------------------------------
- #define PURE __attribute__((pure))
- namespace android {
- // -----------------------------------------------------------------------
- // non-inline helpers
- template <typename TYPE, size_t SIZE>
- class vec;
- template <typename TYPE, size_t SIZE>
- class vbase;
- namespace helpers {
- template <typename T> inline T min(T a, T b) { return a<b ? a : b; }
- template <typename T> inline T max(T a, T b) { return a>b ? a : b; }
- template < template<typename T, size_t S> class VEC,
- typename TYPE, size_t SIZE, size_t S>
- vec<TYPE, SIZE>& doAssign(
- vec<TYPE, SIZE>& lhs, const VEC<TYPE, S>& rhs) {
- const size_t minSize = min(SIZE, S);
- const size_t maxSize = max(SIZE, S);
- for (size_t i=0 ; i<minSize ; i++)
- lhs[i] = rhs[i];
- for (size_t i=minSize ; i<maxSize ; i++)
- lhs[i] = 0;
- return lhs;
- }
- template <
- template<typename T, size_t S> class VLHS,
- template<typename T, size_t S> class VRHS,
- typename TYPE,
- size_t SIZE
- >
- VLHS<TYPE, SIZE> PURE doAdd(
- const VLHS<TYPE, SIZE>& lhs,
- const VRHS<TYPE, SIZE>& rhs) {
- VLHS<TYPE, SIZE> r;
- for (size_t i=0 ; i<SIZE ; i++)
- r[i] = lhs[i] + rhs[i];
- return r;
- }
- template <
- template<typename T, size_t S> class VLHS,
- template<typename T, size_t S> class VRHS,
- typename TYPE,
- size_t SIZE
- >
- VLHS<TYPE, SIZE> PURE doSub(
- const VLHS<TYPE, SIZE>& lhs,
- const VRHS<TYPE, SIZE>& rhs) {
- VLHS<TYPE, SIZE> r;
- for (size_t i=0 ; i<SIZE ; i++)
- r[i] = lhs[i] - rhs[i];
- return r;
- }
- template <
- template<typename T, size_t S> class VEC,
- typename TYPE,
- size_t SIZE
- >
- VEC<TYPE, SIZE> PURE doMulScalar(
- const VEC<TYPE, SIZE>& lhs,
- typename TypeTraits<TYPE>::ParameterType rhs) {
- VEC<TYPE, SIZE> r;
- for (size_t i=0 ; i<SIZE ; i++)
- r[i] = lhs[i] * rhs;
- return r;
- }
- template <
- template<typename T, size_t S> class VEC,
- typename TYPE,
- size_t SIZE
- >
- VEC<TYPE, SIZE> PURE doScalarMul(
- typename TypeTraits<TYPE>::ParameterType lhs,
- const VEC<TYPE, SIZE>& rhs) {
- VEC<TYPE, SIZE> r;
- for (size_t i=0 ; i<SIZE ; i++)
- r[i] = lhs * rhs[i];
- return r;
- }
- }; // namespace helpers
- // -----------------------------------------------------------------------
- // Below we define the mathematical operators for vectors.
- // We use template template arguments so we can generically
- // handle the case where the right-hand-size and left-hand-side are
- // different vector types (but with same value_type and size).
- // This is needed for performance when using ".xy{z}" element access
- // on vec<>. Without this, an extra conversion to vec<> would be needed.
- //
- // example:
- // vec4_t a;
- // vec3_t b;
- // vec3_t c = a.xyz + b;
- //
- // "a.xyz + b" is a mixed-operation between a vbase<> and a vec<>, requiring
- // a conversion of vbase<> to vec<>. The template gunk below avoids this,
- // by allowing the addition on these different vector types directly
- //
- template <
- template<typename T, size_t S> class VLHS,
- template<typename T, size_t S> class VRHS,
- typename TYPE,
- size_t SIZE
- >
- inline VLHS<TYPE, SIZE> PURE operator + (
- const VLHS<TYPE, SIZE>& lhs,
- const VRHS<TYPE, SIZE>& rhs) {
- return helpers::doAdd(lhs, rhs);
- }
- template <
- template<typename T, size_t S> class VLHS,
- template<typename T, size_t S> class VRHS,
- typename TYPE,
- size_t SIZE
- >
- inline VLHS<TYPE, SIZE> PURE operator - (
- const VLHS<TYPE, SIZE>& lhs,
- const VRHS<TYPE, SIZE>& rhs) {
- return helpers::doSub(lhs, rhs);
- }
- template <
- template<typename T, size_t S> class VEC,
- typename TYPE,
- size_t SIZE
- >
- inline VEC<TYPE, SIZE> PURE operator * (
- const VEC<TYPE, SIZE>& lhs,
- typename TypeTraits<TYPE>::ParameterType rhs) {
- return helpers::doMulScalar(lhs, rhs);
- }
- template <
- template<typename T, size_t S> class VEC,
- typename TYPE,
- size_t SIZE
- >
- inline VEC<TYPE, SIZE> PURE operator * (
- typename TypeTraits<TYPE>::ParameterType lhs,
- const VEC<TYPE, SIZE>& rhs) {
- return helpers::doScalarMul(lhs, rhs);
- }
- template <
- template<typename T, size_t S> class VLHS,
- template<typename T, size_t S> class VRHS,
- typename TYPE,
- size_t SIZE
- >
- TYPE PURE dot_product(
- const VLHS<TYPE, SIZE>& lhs,
- const VRHS<TYPE, SIZE>& rhs) {
- TYPE r(0);
- for (size_t i=0 ; i<SIZE ; i++)
- r += lhs[i] * rhs[i];
- return r;
- }
- template <
- template<typename T, size_t S> class V,
- typename TYPE,
- size_t SIZE
- >
- TYPE PURE length(const V<TYPE, SIZE>& v) {
- return sqrt(dot_product(v, v));
- }
- template <
- template<typename T, size_t S> class V,
- typename TYPE,
- size_t SIZE
- >
- TYPE PURE length_squared(const V<TYPE, SIZE>& v) {
- return dot_product(v, v);
- }
- template <
- template<typename T, size_t S> class V,
- typename TYPE,
- size_t SIZE
- >
- V<TYPE, SIZE> PURE normalize(const V<TYPE, SIZE>& v) {
- return v * (1/length(v));
- }
- template <
- template<typename T, size_t S> class VLHS,
- template<typename T, size_t S> class VRHS,
- typename TYPE
- >
- VLHS<TYPE, 3> PURE cross_product(
- const VLHS<TYPE, 3>& u,
- const VRHS<TYPE, 3>& v) {
- VLHS<TYPE, 3> r;
- r.x = u.y*v.z - u.z*v.y;
- r.y = u.z*v.x - u.x*v.z;
- r.z = u.x*v.y - u.y*v.x;
- return r;
- }
- template <typename TYPE, size_t SIZE>
- vec<TYPE, SIZE> PURE operator - (const vec<TYPE, SIZE>& lhs) {
- vec<TYPE, SIZE> r;
- for (size_t i=0 ; i<SIZE ; i++)
- r[i] = -lhs[i];
- return r;
- }
- // -----------------------------------------------------------------------
- // This our basic vector type, it just implements the data storage
- // and accessors.
- template <typename TYPE, size_t SIZE>
- struct vbase {
- TYPE v[SIZE];
- inline const TYPE& operator[](size_t i) const { return v[i]; }
- inline TYPE& operator[](size_t i) { return v[i]; }
- };
- template<> struct vbase<float, 2> {
- union {
- float v[2];
- struct { float x, y; };
- struct { float s, t; };
- };
- inline const float& operator[](size_t i) const { return v[i]; }
- inline float& operator[](size_t i) { return v[i]; }
- };
- template<> struct vbase<float, 3> {
- union {
- float v[3];
- struct { float x, y, z; };
- struct { float s, t, r; };
- vbase<float, 2> xy;
- vbase<float, 2> st;
- };
- inline const float& operator[](size_t i) const { return v[i]; }
- inline float& operator[](size_t i) { return v[i]; }
- };
- template<> struct vbase<float, 4> {
- union {
- float v[4];
- struct { float x, y, z, w; };
- struct { float s, t, r, q; };
- vbase<float, 3> xyz;
- vbase<float, 3> str;
- vbase<float, 2> xy;
- vbase<float, 2> st;
- };
- inline const float& operator[](size_t i) const { return v[i]; }
- inline float& operator[](size_t i) { return v[i]; }
- };
- // -----------------------------------------------------------------------
- template <typename TYPE, size_t SIZE>
- class vec : public vbase<TYPE, SIZE>
- {
- typedef typename TypeTraits<TYPE>::ParameterType pTYPE;
- typedef vbase<TYPE, SIZE> base;
- public:
- // STL-like interface.
- typedef TYPE value_type;
- typedef TYPE& reference;
- typedef TYPE const& const_reference;
- typedef size_t size_type;
- typedef TYPE* iterator;
- typedef TYPE const* const_iterator;
- iterator begin() { return base::v; }
- iterator end() { return base::v + SIZE; }
- const_iterator begin() const { return base::v; }
- const_iterator end() const { return base::v + SIZE; }
- size_type size() const { return SIZE; }
- // -----------------------------------------------------------------------
- // default constructors
- vec() { }
- vec(const vec& rhs) : base(rhs) { }
- vec(const base& rhs) : base(rhs) { }
- // -----------------------------------------------------------------------
- // conversion constructors
- vec(pTYPE rhs) {
- for (size_t i=0 ; i<SIZE ; i++)
- base::operator[](i) = rhs;
- }
- template < template<typename T, size_t S> class VEC, size_t S>
- explicit vec(const VEC<TYPE, S>& rhs) {
- helpers::doAssign(*this, rhs);
- }
- explicit vec(TYPE const* array) {
- for (size_t i=0 ; i<SIZE ; i++)
- base::operator[](i) = array[i];
- }
- // -----------------------------------------------------------------------
- // Assignment
- vec& operator = (const vec& rhs) {
- base::operator=(rhs);
- return *this;
- }
- vec& operator = (const base& rhs) {
- base::operator=(rhs);
- return *this;
- }
- vec& operator = (pTYPE rhs) {
- for (size_t i=0 ; i<SIZE ; i++)
- base::operator[](i) = rhs;
- return *this;
- }
- template < template<typename T, size_t S> class VEC, size_t S>
- vec& operator = (const VEC<TYPE, S>& rhs) {
- return helpers::doAssign(*this, rhs);
- }
- // -----------------------------------------------------------------------
- // operation-assignment
- vec& operator += (const vec& rhs);
- vec& operator -= (const vec& rhs);
- vec& operator *= (pTYPE rhs);
- // -----------------------------------------------------------------------
- // non-member function declaration and definition
- // NOTE: we declare the non-member function as friend inside the class
- // so that they are known to the compiler when the class is instantiated.
- // This helps the compiler doing template argument deduction when the
- // passed types are not identical. Essentially this helps with
- // type conversion so that you can multiply a vec<float> by an scalar int
- // (for instance).
- friend inline vec PURE operator + (const vec& lhs, const vec& rhs) {
- return helpers::doAdd(lhs, rhs);
- }
- friend inline vec PURE operator - (const vec& lhs, const vec& rhs) {
- return helpers::doSub(lhs, rhs);
- }
- friend inline vec PURE operator * (const vec& lhs, pTYPE v) {
- return helpers::doMulScalar(lhs, v);
- }
- friend inline vec PURE operator * (pTYPE v, const vec& rhs) {
- return helpers::doScalarMul(v, rhs);
- }
- friend inline TYPE PURE dot_product(const vec& lhs, const vec& rhs) {
- return android::dot_product(lhs, rhs);
- }
- };
- // -----------------------------------------------------------------------
- template <typename TYPE, size_t SIZE>
- vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator += (const vec<TYPE, SIZE>& rhs) {
- vec<TYPE, SIZE>& lhs(*this);
- for (size_t i=0 ; i<SIZE ; i++)
- lhs[i] += rhs[i];
- return lhs;
- }
- template <typename TYPE, size_t SIZE>
- vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator -= (const vec<TYPE, SIZE>& rhs) {
- vec<TYPE, SIZE>& lhs(*this);
- for (size_t i=0 ; i<SIZE ; i++)
- lhs[i] -= rhs[i];
- return lhs;
- }
- template <typename TYPE, size_t SIZE>
- vec<TYPE, SIZE>& vec<TYPE, SIZE>::operator *= (vec<TYPE, SIZE>::pTYPE rhs) {
- vec<TYPE, SIZE>& lhs(*this);
- for (size_t i=0 ; i<SIZE ; i++)
- lhs[i] *= rhs;
- return lhs;
- }
- // -----------------------------------------------------------------------
- typedef vec<float, 2> vec2_t;
- typedef vec<float, 3> vec3_t;
- typedef vec<float, 4> vec4_t;
- // -----------------------------------------------------------------------
- }; // namespace android
- #endif /* ANDROID_VEC_H */
|