|  | /* | 
|  | * Copyright 2013 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. | 
|  | */ | 
|  |  | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #include <math.h> | 
|  | #include <stdint.h> | 
|  | #include <math/HashCombine.h> | 
|  | #include <sys/types.h> | 
|  |  | 
|  | #include <cmath> | 
|  | #include <functional> | 
|  | #include <limits> | 
|  | #include <iostream> | 
|  |  | 
|  | #define PURE __attribute__((pure)) | 
|  |  | 
|  | #if __cplusplus >= 201402L | 
|  | #define CONSTEXPR constexpr | 
|  | #else | 
|  | #define CONSTEXPR | 
|  | #endif | 
|  |  | 
|  | namespace android { | 
|  | namespace details { | 
|  | // ------------------------------------------------------------------------------------- | 
|  |  | 
|  | /* | 
|  | * No user serviceable parts here. | 
|  | * | 
|  | * Don't use this file directly, instead include ui/vec{2|3|4}.h | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * TVec{Add|Product}Operators implements basic arithmetic and basic compound assignments | 
|  | * operators on a vector of type BASE<T>. | 
|  | * | 
|  | * BASE only needs to implement operator[] and size(). | 
|  | * By simply inheriting from TVec{Add|Product}Operators<BASE, T> BASE will automatically | 
|  | * get all the functionality here. | 
|  | */ | 
|  |  | 
|  | template <template<typename T> class VECTOR, typename T> | 
|  | class TVecAddOperators { | 
|  | public: | 
|  | /* compound assignment from a another vector of the same size but different | 
|  | * element type. | 
|  | */ | 
|  | template<typename OTHER> | 
|  | VECTOR<T>& operator +=(const VECTOR<OTHER>& v) { | 
|  | VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); | 
|  | for (size_t i = 0; i < lhs.size(); i++) { | 
|  | lhs[i] += v[i]; | 
|  | } | 
|  | return lhs; | 
|  | } | 
|  | template<typename OTHER> | 
|  | VECTOR<T>& operator -=(const VECTOR<OTHER>& v) { | 
|  | VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); | 
|  | for (size_t i = 0; i < lhs.size(); i++) { | 
|  | lhs[i] -= v[i]; | 
|  | } | 
|  | return lhs; | 
|  | } | 
|  |  | 
|  | /* compound assignment from a another vector of the same type. | 
|  | * These operators can be used for implicit conversion and  handle operations | 
|  | * like "vector *= scalar" by letting the compiler implicitly convert a scalar | 
|  | * to a vector (assuming the BASE<T> allows it). | 
|  | */ | 
|  | VECTOR<T>& operator +=(const VECTOR<T>& v) { | 
|  | VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); | 
|  | for (size_t i = 0; i < lhs.size(); i++) { | 
|  | lhs[i] += v[i]; | 
|  | } | 
|  | return lhs; | 
|  | } | 
|  | VECTOR<T>& operator -=(const VECTOR<T>& v) { | 
|  | VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); | 
|  | for (size_t i = 0; i < lhs.size(); i++) { | 
|  | lhs[i] -= v[i]; | 
|  | } | 
|  | return lhs; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * NOTE: the functions below ARE NOT member methods. They are friend functions | 
|  | * with they definition inlined with their declaration. This makes these | 
|  | * template functions available to the compiler when (and only when) this class | 
|  | * is instantiated, at which point they're only templated on the 2nd parameter | 
|  | * (the first one, BASE<T> being known). | 
|  | */ | 
|  |  | 
|  | /* The operators below handle operation between vectors of the same size | 
|  | * but of a different element type. | 
|  | */ | 
|  | template<typename RT> | 
|  | friend inline constexpr VECTOR<T> PURE operator +(VECTOR<T> lv, const VECTOR<RT>& rv) { | 
|  | // don't pass lv by reference because we need a copy anyways | 
|  | return lv += rv; | 
|  | } | 
|  | template<typename RT> | 
|  | friend inline constexpr VECTOR<T> PURE operator -(VECTOR<T> lv, const VECTOR<RT>& rv) { | 
|  | // don't pass lv by reference because we need a copy anyways | 
|  | return lv -= rv; | 
|  | } | 
|  |  | 
|  | /* The operators below (which are not templates once this class is instanced, | 
|  | * i.e.: BASE<T> is known) can be used for implicit conversion on both sides. | 
|  | * These handle operations like "vector + scalar" and "scalar + vector" by | 
|  | * letting the compiler implicitly convert a scalar to a vector (assuming | 
|  | * the BASE<T> allows it). | 
|  | */ | 
|  | friend inline constexpr VECTOR<T> PURE operator +(VECTOR<T> lv, const VECTOR<T>& rv) { | 
|  | // don't pass lv by reference because we need a copy anyways | 
|  | return lv += rv; | 
|  | } | 
|  | friend inline constexpr VECTOR<T> PURE operator -(VECTOR<T> lv, const VECTOR<T>& rv) { | 
|  | // don't pass lv by reference because we need a copy anyways | 
|  | return lv -= rv; | 
|  | } | 
|  | }; | 
|  |  | 
|  | template<template<typename T> class VECTOR, typename T> | 
|  | class TVecProductOperators { | 
|  | public: | 
|  | /* compound assignment from a another vector of the same size but different | 
|  | * element type. | 
|  | */ | 
|  | template<typename OTHER> | 
|  | VECTOR<T>& operator *=(const VECTOR<OTHER>& v) { | 
|  | VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); | 
|  | for (size_t i = 0; i < lhs.size(); i++) { | 
|  | lhs[i] *= v[i]; | 
|  | } | 
|  | return lhs; | 
|  | } | 
|  | template<typename OTHER> | 
|  | VECTOR<T>& operator /=(const VECTOR<OTHER>& v) { | 
|  | VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); | 
|  | for (size_t i = 0; i < lhs.size(); i++) { | 
|  | lhs[i] /= v[i]; | 
|  | } | 
|  | return lhs; | 
|  | } | 
|  |  | 
|  | /* compound assignment from a another vector of the same type. | 
|  | * These operators can be used for implicit conversion and  handle operations | 
|  | * like "vector *= scalar" by letting the compiler implicitly convert a scalar | 
|  | * to a vector (assuming the BASE<T> allows it). | 
|  | */ | 
|  | VECTOR<T>& operator *=(const VECTOR<T>& v) { | 
|  | VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); | 
|  | for (size_t i = 0; i < lhs.size(); i++) { | 
|  | lhs[i] *= v[i]; | 
|  | } | 
|  | return lhs; | 
|  | } | 
|  | VECTOR<T>& operator /=(const VECTOR<T>& v) { | 
|  | VECTOR<T>& lhs = static_cast<VECTOR<T>&>(*this); | 
|  | for (size_t i = 0; i < lhs.size(); i++) { | 
|  | lhs[i] /= v[i]; | 
|  | } | 
|  | return lhs; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * NOTE: the functions below ARE NOT member methods. They are friend functions | 
|  | * with they definition inlined with their declaration. This makes these | 
|  | * template functions available to the compiler when (and only when) this class | 
|  | * is instantiated, at which point they're only templated on the 2nd parameter | 
|  | * (the first one, BASE<T> being known). | 
|  | */ | 
|  |  | 
|  | /* The operators below handle operation between vectors of the same size | 
|  | * but of a different element type. | 
|  | */ | 
|  | template<typename RT> | 
|  | friend inline constexpr VECTOR<T> PURE operator *(VECTOR<T> lv, const VECTOR<RT>& rv) { | 
|  | // don't pass lv by reference because we need a copy anyways | 
|  | return lv *= rv; | 
|  | } | 
|  | template<typename RT> | 
|  | friend inline constexpr VECTOR<T> PURE operator /(VECTOR<T> lv, const VECTOR<RT>& rv) { | 
|  | // don't pass lv by reference because we need a copy anyways | 
|  | return lv /= rv; | 
|  | } | 
|  |  | 
|  | /* The operators below (which are not templates once this class is instanced, | 
|  | * i.e.: BASE<T> is known) can be used for implicit conversion on both sides. | 
|  | * These handle operations like "vector * scalar" and "scalar * vector" by | 
|  | * letting the compiler implicitly convert a scalar to a vector (assuming | 
|  | * the BASE<T> allows it). | 
|  | */ | 
|  | friend inline constexpr VECTOR<T> PURE operator *(VECTOR<T> lv, const VECTOR<T>& rv) { | 
|  | // don't pass lv by reference because we need a copy anyways | 
|  | return lv *= rv; | 
|  | } | 
|  | friend inline constexpr VECTOR<T> PURE operator /(VECTOR<T> lv, const VECTOR<T>& rv) { | 
|  | // don't pass lv by reference because we need a copy anyways | 
|  | return lv /= rv; | 
|  | } | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * TVecUnaryOperators implements unary operators on a vector of type BASE<T>. | 
|  | * | 
|  | * BASE only needs to implement operator[] and size(). | 
|  | * By simply inheriting from TVecUnaryOperators<BASE, T> BASE will automatically | 
|  | * get all the functionality here. | 
|  | * | 
|  | * These operators are implemented as friend functions of TVecUnaryOperators<BASE, T> | 
|  | */ | 
|  | template<template<typename T> class VECTOR, typename T> | 
|  | class TVecUnaryOperators { | 
|  | public: | 
|  | VECTOR<T>& operator ++() { | 
|  | VECTOR<T>& rhs = static_cast<VECTOR<T>&>(*this); | 
|  | for (size_t i = 0; i < rhs.size(); i++) { | 
|  | ++rhs[i]; | 
|  | } | 
|  | return rhs; | 
|  | } | 
|  |  | 
|  | VECTOR<T>& operator --() { | 
|  | VECTOR<T>& rhs = static_cast<VECTOR<T>&>(*this); | 
|  | for (size_t i = 0; i < rhs.size(); i++) { | 
|  | --rhs[i]; | 
|  | } | 
|  | return rhs; | 
|  | } | 
|  |  | 
|  | CONSTEXPR VECTOR<T> operator -() const { | 
|  | VECTOR<T> r(VECTOR<T>::NO_INIT); | 
|  | VECTOR<T> const& rv(static_cast<VECTOR<T> const&>(*this)); | 
|  | for (size_t i = 0; i < r.size(); i++) { | 
|  | r[i] = -rv[i]; | 
|  | } | 
|  | return r; | 
|  | } | 
|  |  | 
|  | // This isn't strictly a unary operator, but it is a common place shared between both | 
|  | // matrix and vector classes | 
|  | size_t hash() const { | 
|  | VECTOR<T> const& rv(static_cast<VECTOR<T> const&>(*this)); | 
|  | size_t hashed = 0; | 
|  | for (size_t i = 0; i < rv.size(); i++) { | 
|  | android::hashCombineSingle(hashed, rv[i]); | 
|  | } | 
|  | return hashed; | 
|  | } | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * TVecComparisonOperators implements relational/comparison operators | 
|  | * on a vector of type BASE<T>. | 
|  | * | 
|  | * BASE only needs to implement operator[] and size(). | 
|  | * By simply inheriting from TVecComparisonOperators<BASE, T> BASE will automatically | 
|  | * get all the functionality here. | 
|  | */ | 
|  | template<template<typename T> class VECTOR, typename T> | 
|  | class TVecComparisonOperators { | 
|  | public: | 
|  | /* | 
|  | * NOTE: the functions below ARE NOT member methods. They are friend functions | 
|  | * with they definition inlined with their declaration. This makes these | 
|  | * template functions available to the compiler when (and only when) this class | 
|  | * is instantiated, at which point they're only templated on the 2nd parameter | 
|  | * (the first one, BASE<T> being known). | 
|  | */ | 
|  | template<typename RT> | 
|  | friend inline | 
|  | bool PURE operator ==(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | for (size_t i = 0; i < lv.size(); i++) | 
|  | if (lv[i] != rv[i]) | 
|  | return false; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline | 
|  | bool PURE operator !=(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | return !operator ==(lv, rv); | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline | 
|  | bool PURE operator >(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | for (size_t i = 0; i < lv.size(); i++) { | 
|  | if (lv[i] == rv[i]) { | 
|  | continue; | 
|  | } | 
|  | return lv[i] > rv[i]; | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline | 
|  | constexpr bool PURE operator <=(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | return !(lv > rv); | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline | 
|  | bool PURE operator <(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | for (size_t i = 0; i < lv.size(); i++) { | 
|  | if (lv[i] == rv[i]) { | 
|  | continue; | 
|  | } | 
|  | return lv[i] < rv[i]; | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline | 
|  | constexpr bool PURE operator >=(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | return !(lv < rv); | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline | 
|  | CONSTEXPR VECTOR<bool> PURE equal(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | VECTOR<bool> r; | 
|  | for (size_t i = 0; i < lv.size(); i++) { | 
|  | r[i] = lv[i] == rv[i]; | 
|  | } | 
|  | return r; | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline | 
|  | CONSTEXPR VECTOR<bool> PURE notEqual(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | VECTOR<bool> r; | 
|  | for (size_t i = 0; i < lv.size(); i++) { | 
|  | r[i] = lv[i] != rv[i]; | 
|  | } | 
|  | return r; | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline | 
|  | CONSTEXPR VECTOR<bool> PURE lessThan(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | VECTOR<bool> r; | 
|  | for (size_t i = 0; i < lv.size(); i++) { | 
|  | r[i] = lv[i] < rv[i]; | 
|  | } | 
|  | return r; | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline | 
|  | CONSTEXPR VECTOR<bool> PURE lessThanEqual(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | VECTOR<bool> r; | 
|  | for (size_t i = 0; i < lv.size(); i++) { | 
|  | r[i] = lv[i] <= rv[i]; | 
|  | } | 
|  | return r; | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline | 
|  | CONSTEXPR VECTOR<bool> PURE greaterThan(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | VECTOR<bool> r; | 
|  | for (size_t i = 0; i < lv.size(); i++) { | 
|  | r[i] = lv[i] > rv[i]; | 
|  | } | 
|  | return r; | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline | 
|  | CONSTEXPR VECTOR<bool> PURE greaterThanEqual(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | VECTOR<bool> r; | 
|  | for (size_t i = 0; i < lv.size(); i++) { | 
|  | r[i] = lv[i] >= rv[i]; | 
|  | } | 
|  | return r; | 
|  | } | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * TVecFunctions implements functions on a vector of type BASE<T>. | 
|  | * | 
|  | * BASE only needs to implement operator[] and size(). | 
|  | * By simply inheriting from TVecFunctions<BASE, T> BASE will automatically | 
|  | * get all the functionality here. | 
|  | */ | 
|  | template<template<typename T> class VECTOR, typename T> | 
|  | class TVecFunctions { | 
|  | public: | 
|  | /* | 
|  | * NOTE: the functions below ARE NOT member methods. They are friend functions | 
|  | * with they definition inlined with their declaration. This makes these | 
|  | * template functions available to the compiler when (and only when) this class | 
|  | * is instantiated, at which point they're only templated on the 2nd parameter | 
|  | * (the first one, BASE<T> being known). | 
|  | */ | 
|  | template<typename RT> | 
|  | friend inline CONSTEXPR T PURE dot(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | T r(0); | 
|  | for (size_t i = 0; i < lv.size(); i++) { | 
|  | //r = std::fma(lv[i], rv[i], r); | 
|  | r += lv[i] * rv[i]; | 
|  | } | 
|  | return r; | 
|  | } | 
|  |  | 
|  | friend inline constexpr T PURE norm(const VECTOR<T>& lv) { | 
|  | return std::sqrt(dot(lv, lv)); | 
|  | } | 
|  |  | 
|  | friend inline constexpr T PURE length(const VECTOR<T>& lv) { | 
|  | return norm(lv); | 
|  | } | 
|  |  | 
|  | friend inline constexpr T PURE norm2(const VECTOR<T>& lv) { | 
|  | return dot(lv, lv); | 
|  | } | 
|  |  | 
|  | friend inline constexpr T PURE length2(const VECTOR<T>& lv) { | 
|  | return norm2(lv); | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline constexpr T PURE distance(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | return length(rv - lv); | 
|  | } | 
|  |  | 
|  | template<typename RT> | 
|  | friend inline constexpr T PURE distance2(const VECTOR<T>& lv, const VECTOR<RT>& rv) { | 
|  | return length2(rv - lv); | 
|  | } | 
|  |  | 
|  | friend inline constexpr VECTOR<T> PURE normalize(const VECTOR<T>& lv) { | 
|  | return lv * (T(1) / length(lv)); | 
|  | } | 
|  |  | 
|  | friend inline constexpr VECTOR<T> PURE rcp(VECTOR<T> v) { | 
|  | return T(1) / v; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE abs(VECTOR<T> v) { | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | v[i] = std::abs(v[i]); | 
|  | } | 
|  | return v; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE floor(VECTOR<T> v) { | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | v[i] = std::floor(v[i]); | 
|  | } | 
|  | return v; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE ceil(VECTOR<T> v) { | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | v[i] = std::ceil(v[i]); | 
|  | } | 
|  | return v; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE round(VECTOR<T> v) { | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | v[i] = std::round(v[i]); | 
|  | } | 
|  | return v; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE inversesqrt(VECTOR<T> v) { | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | v[i] = T(1) / std::sqrt(v[i]); | 
|  | } | 
|  | return v; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE sqrt(VECTOR<T> v) { | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | v[i] = std::sqrt(v[i]); | 
|  | } | 
|  | return v; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE pow(VECTOR<T> v, T p) { | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | v[i] = std::pow(v[i], p); | 
|  | } | 
|  | return v; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE saturate(const VECTOR<T>& lv) { | 
|  | return clamp(lv, T(0), T(1)); | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE clamp(VECTOR<T> v, T min, T max) { | 
|  | for (size_t i = 0; i< v.size(); i++) { | 
|  | v[i] = std::min(max, std::max(min, v[i])); | 
|  | } | 
|  | return v; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE fma(const VECTOR<T>& lv, const VECTOR<T>& rv, VECTOR<T> a) { | 
|  | for (size_t i = 0; i<lv.size(); i++) { | 
|  | //a[i] = std::fma(lv[i], rv[i], a[i]); | 
|  | a[i] += (lv[i] * rv[i]); | 
|  | } | 
|  | return a; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE min(const VECTOR<T>& u, VECTOR<T> v) { | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | v[i] = std::min(u[i], v[i]); | 
|  | } | 
|  | return v; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE max(const VECTOR<T>& u, VECTOR<T> v) { | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | v[i] = std::max(u[i], v[i]); | 
|  | } | 
|  | return v; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR T PURE max(const VECTOR<T>& v) { | 
|  | T r(std::numeric_limits<T>::lowest()); | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | r = std::max(r, v[i]); | 
|  | } | 
|  | return r; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR T PURE min(const VECTOR<T>& v) { | 
|  | T r(std::numeric_limits<T>::max()); | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | r = std::min(r, v[i]); | 
|  | } | 
|  | return r; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR VECTOR<T> PURE apply(VECTOR<T> v, const std::function<T(T)>& f) { | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | v[i] = f(v[i]); | 
|  | } | 
|  | return v; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR bool PURE any(const VECTOR<T>& v) { | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | if (v[i] != T(0)) return true; | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | friend inline CONSTEXPR bool PURE all(const VECTOR<T>& v) { | 
|  | bool result = true; | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | result &= (v[i] != T(0)); | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | template<typename R> | 
|  | friend inline CONSTEXPR VECTOR<R> PURE map(VECTOR<T> v, const std::function<R(T)>& f) { | 
|  | VECTOR<R> result; | 
|  | for (size_t i = 0; i < v.size(); i++) { | 
|  | result[i] = f(v[i]); | 
|  | } | 
|  | return result; | 
|  | } | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * TVecDebug implements functions on a vector of type BASE<T>. | 
|  | * | 
|  | * BASE only needs to implement operator[] and size(). | 
|  | * By simply inheriting from TVecDebug<BASE, T> BASE will automatically | 
|  | * get all the functionality here. | 
|  | */ | 
|  | template<template<typename T> class VECTOR, typename T> | 
|  | class TVecDebug { | 
|  | public: | 
|  | /* | 
|  | * NOTE: the functions below ARE NOT member methods. They are friend functions | 
|  | * with they definition inlined with their declaration. This makes these | 
|  | * template functions available to the compiler when (and only when) this class | 
|  | * is instantiated, at which point they're only templated on the 2nd parameter | 
|  | * (the first one, BASE<T> being known). | 
|  | */ | 
|  | friend std::ostream& operator<<(std::ostream& stream, const VECTOR<T>& v) { | 
|  | stream << "< "; | 
|  | for (size_t i = 0; i < v.size() - 1; i++) { | 
|  | stream << T(v[i]) << ", "; | 
|  | } | 
|  | stream << T(v[v.size() - 1]) << " >"; | 
|  | return stream; | 
|  | } | 
|  | }; | 
|  |  | 
|  | #undef CONSTEXPR | 
|  | #undef PURE | 
|  |  | 
|  | // ------------------------------------------------------------------------------------- | 
|  | }  // namespace details | 
|  | }  // namespace android | 
|  |  | 
|  | namespace std { | 
|  | template<template<typename T> class VECTOR, typename T> | 
|  | struct hash<VECTOR<T>> { | 
|  | static constexpr bool IS_VECTOR = | 
|  | std::is_base_of<android::details::TVecUnaryOperators<VECTOR, T>, VECTOR<T>>::value; | 
|  |  | 
|  | typename std::enable_if<IS_VECTOR, size_t>::type | 
|  | operator()(const VECTOR<T>& v) const { | 
|  | return v.hash(); | 
|  | } | 
|  | }; | 
|  | } |