/*! \file utils.hpp \author Ha NGUYEN \since 06 Oct 2014 \date 10 Feb 2015 \brief Some utils for Xios */ #ifndef __XIOS_UTILS_HPP__ #define __XIOS_UTILS_HPP__ #include #include #include "array_new.hpp" #include "exception.hpp" namespace xios { template struct CArrayTraits { typedef K ArrayType; }; template struct CArrayBoolTraits : public CArrayTraits { typedef bool Type; }; template<> struct CArrayBoolTraits > { static inline void resizeArray(CArray& boolArray, const std::vector& dimensionSize) { if (1 != dimensionSize.size()) ERROR("utils::CArrayBoolTraits", <<"Dimension of resized array mismatch"< struct CArrayBoolTraits > { static inline void resizeArray(CArray& boolArray, const std::vector& dimensionSize) { if (2 != dimensionSize.size()) ERROR("utils::CArrayBoolTraits", <<"Dimension of resized array mismatch"< struct CArrayBoolTraits > { static inline void resizeArray(CArray& boolArray, const std::vector& dimensionSize) { if (3 != dimensionSize.size()) ERROR("utils::CArrayBoolTraits", <<"Dimension of resized array mismatch"< struct CArrayBoolTraits > { static inline void resizeArray(CArray& boolArray, const std::vector& dimensionSize) { if (4 != dimensionSize.size()) ERROR("utils::CArrayBoolTraits", <<"Dimension of resized array mismatch"< struct CArrayBoolTraits > { static inline void resizeArray(CArray& boolArray, const std::vector& dimensionSize) { if (5 != dimensionSize.size()) ERROR("utils::CArrayBoolTraits", <<"Dimension of resized array mismatch"< struct CArrayBoolTraits > { static inline void resizeArray(CArray& boolArray, const std::vector& dimensionSize) { if (6 != dimensionSize.size()) ERROR("utils::CArrayBoolTraits", <<"Dimension of resized array mismatch"< struct CArrayBoolTraits > { static inline void resizeArray(CArray& boolArray, const std::vector& dimensionSize) { if (7 != dimensionSize.size()) ERROR("utils::CArrayBoolTraits", <<"Dimension of resized array mismatch"< struct Int2Type { enum { value = v }; }; template union TypeToBytes { T value; unsigned char bytes[sizeof(T)]; }; template struct HashAlgorithm { /*! Adapted version of one-at-a-time hash by Bob Jenkins, which is an expanded version of his Dr. Dobbs article. */ static inline size_t jenkins_hash(const T& value) { TypeToBytes u; (u.value) = value; size_t hash = 0; size_t length = sizeof(value); for (size_t i = 0; i < length; ++i) { hash += u.bytes[i]; hash += (hash << 10); hash ^= (hash >> 6); } hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15); return hash; } /*! Adatped version of (stupid) boost hash (but working) */ static inline size_t boost_hash(const std::vector& vec) { size_t hash = 0; int sizeVec = vec.size(); for(int i = 0; i < sizeVec; ++i) { hash ^= i + 0x9e3779b9 + (hash << 6) + (hash >> 2); } return hash; } }; template > struct HashXIOS { std::size_t operator()(const T& val) { Algo al; return hash_value(val, al); } std::size_t hashVec(const std::vector& vec) { return HashAlgorithm::boost_hash(vec); } private: size_t hash_value(const T& val, Int2Type<0>) { return HashAlgorithm::jenkins_hash(val); } }; template struct NumTraits { typedef K Type; }; template<> struct NumTraits { typedef unsigned long Scalar; typedef Scalar magnitudeType; static inline Scalar sfmin() { return std::numeric_limits::min(); } static inline Scalar sfmax() { return std::numeric_limits::max(); } static inline Scalar sflowest() { return -(std::numeric_limits::max()); } static inline Scalar epsilon() { return std::numeric_limits::epsilon(); } static inline Scalar dummy_precision() { return 0; } }; template<> struct NumTraits { typedef double Scalar; typedef Scalar magnitudeType; static inline Scalar sfmin() { return std::numeric_limits::min(); } static inline Scalar sfmax() { return std::numeric_limits::max(); } static inline Scalar sflowest() { return -(std::numeric_limits::max()); } static inline Scalar epsilon() { return std::numeric_limits::epsilon(); } static inline Scalar dummy_precision() { return 1e-12; } static inline bool isNan(const Scalar& v) { return (v != v); } }; template class CArrayStorage { public: typedef CArray StorageType; public: CArrayStorage(const CArray& arr) : values(arr) {} protected: const T& atIndex(int idx) const { return values(idx); } const StorageType& values; }; template class CVectorStorage { public: typedef std::vector StorageType; public: CVectorStorage(const std::vector& vec) : values(vec) {} protected: const T& atIndex(int idx) const { return values[idx]; } const StorageType& values; }; template< typename T, template class StoragePolicy = CVectorStorage > class XIOSComparatorWithIndex : public StoragePolicy { public: typedef typename StoragePolicy::StorageType StorageType; public: XIOSComparatorWithIndex(const StorageType& v) : StoragePolicy(v) {} bool operator()(int a, int b) { return this->atIndex(a) < this->atIndex(b); } }; template< typename T, template class StoragePolicy = CVectorStorage > class XIOSLowerBoundWithIndex : public StoragePolicy { public: typedef typename StoragePolicy::StorageType StorageType; public: XIOSLowerBoundWithIndex(const StorageType &v) : StoragePolicy(v) {} bool operator()(const int a, const T& b) { return this->atIndex(a) < b; } }; template< typename T, template class StoragePolicy = CVectorStorage > class XIOSBinarySearchWithIndex : public StoragePolicy { public: typedef typename StoragePolicy::StorageType StorageType; public: XIOSBinarySearchWithIndex(const StorageType& v) : StoragePolicy(v) {} template bool search(ForwardIterator first, ForwardIterator last, const T& val, ForwardIterator& position) { first = std::lower_bound(first, last, val, XIOSLowerBoundWithIndex(this->values)); position = first; return (first!=last && !(valatIndex(*first))); } }; struct XIOSAlgorithms { public: template class StoragePolicy> static void sortWithIndex(const typename StoragePolicy::StorageType& values, std::vector& rv) { std::sort(rv.begin(), rv.end(), XIOSComparatorWithIndex(values)); } //! Fill in an vector with index begin at 0 static void fillInIndex(int nbIndex, std::vector& rvIndex) { if ((0 < nbIndex) && (nbIndex != rvIndex.size())) rvIndex.resize(nbIndex); for (int idx = 0; idx < nbIndex; ++idx) rvIndex[idx] = idx; } }; } #endif // __UTILS_HPP__