Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-06-18 23:26:44

0001 #ifndef CondFormats_JetMETObjects_Utilities_h
0002 #define CondFormats_JetMETObjects_Utilities_h
0003 
0004 #ifdef STANDALONE
0005 #include <stdexcept>
0006 #else
0007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0008 #endif
0009 
0010 #include <cstdlib>
0011 #include <sstream>
0012 #include <string>
0013 #include <vector>
0014 #include <tuple>
0015 #include <cmath>
0016 #include <utility>
0017 
0018 namespace std {
0019   //These functions print a tuple using a provided std::ostream
0020   template <typename Type, unsigned N, unsigned Last>
0021   struct tuple_printer {
0022     static void print(std::ostream& out, const Type& value) {
0023       out << std::get<N>(value) << ", ";
0024       tuple_printer<Type, N + 1, Last>::print(out, value);
0025     }
0026   };
0027   template <typename Type, unsigned N>
0028   struct tuple_printer<Type, N, N> {
0029     static void print(std::ostream& out, const Type& value) { out << std::get<N>(value); }
0030   };
0031   template <typename... Types>
0032   std::ostream& operator<<(std::ostream& out, const std::tuple<Types...>& value) {
0033     out << "(";
0034     tuple_printer<std::tuple<Types...>, 0, sizeof...(Types) - 1>::print(out, value);
0035     out << ")";
0036     return out;
0037   }
0038   //----------------------------------------------------------------------
0039   //Returns a list of type indices
0040   template <size_t... n>
0041   struct ct_integers_list {
0042     template <size_t m>
0043     struct push_back {
0044       typedef ct_integers_list<n..., m> type;
0045     };
0046   };
0047   template <size_t max>
0048   struct ct_iota_1 {
0049     typedef typename ct_iota_1<max - 1>::type::template push_back<max>::type type;
0050   };
0051   template <>
0052   struct ct_iota_1<0> {
0053     typedef ct_integers_list<> type;
0054   };
0055   //----------------------------------------------------------------------
0056   //Return a tuple which is a subset of the original tuple
0057   //This function pops an entry off the font of the tuple
0058   template <size_t... indices, typename Tuple>
0059   auto tuple_subset(const Tuple& tpl, ct_integers_list<indices...>)
0060       -> decltype(std::make_tuple(std::get<indices>(tpl)...)) {
0061     return std::make_tuple(std::get<indices>(tpl)...);
0062     // this means:
0063     //   make_tuple(get<indices[0]>(tpl), get<indices[1]>(tpl), ...)
0064   }
0065   template <typename Head, typename... Tail>
0066   std::tuple<Tail...> tuple_tail(const std::tuple<Head, Tail...>& tpl) {
0067     return tuple_subset(tpl, typename ct_iota_1<sizeof...(Tail)>::type());
0068     // this means:
0069     //   tuple_subset<1, 2, 3, ..., sizeof...(Tail)-1>(tpl, ..)
0070   }
0071   //----------------------------------------------------------------------
0072   //Recursive hashing function for tuples
0073   template <typename Head, typename... ndims>
0074   struct hash_specialization {
0075     typedef std::tuple<Head, ndims...> argument_type;
0076     typedef std::size_t result_type;
0077     result_type operator()(const argument_type& t) const {
0078       const uint32_t& b = reinterpret_cast<const uint32_t&>(std::get<0>(t));
0079       //const uint32_t& more = (*this)(tuple_tail(t));
0080       const uint32_t& more = hash_specialization<ndims...>()(tuple_tail(t));
0081       return b ^ more;
0082     }
0083   };
0084   //Base case
0085   template <>
0086   struct hash_specialization<float> {
0087     typedef std::tuple<float> argument_type;
0088     typedef std::size_t result_type;
0089     result_type operator()(const argument_type& t) const {
0090       const uint32_t& b = reinterpret_cast<const uint32_t&>(std::get<0>(t));
0091       return static_cast<result_type>(b);
0092     }
0093   };
0094   //Overloaded verions of std::hash for tuples
0095   template <typename Head, typename... ndims>
0096   struct hash<std::tuple<Head, ndims...>> {
0097     typedef std::tuple<Head, ndims...> argument_type;
0098     typedef std::size_t result_type;
0099     result_type operator()(const argument_type& t) const { return hash_specialization<Head, ndims...>()(t); }
0100   };
0101   template <>
0102   struct hash<std::tuple<>> {
0103     typedef std::tuple<> argument_type;
0104     typedef std::size_t result_type;
0105     result_type operator()(const argument_type& t) const { return -1; }
0106   };
0107 }  // namespace std
0108 
0109 namespace {
0110   inline void handleError(const std::string& fClass, const std::string& fMessage) {
0111 #ifdef STANDALONE
0112     std::stringstream sserr;
0113     sserr << fClass << " ERROR: " << fMessage;
0114     throw std::runtime_error(sserr.str());
0115 #else
0116     edm::LogError(fClass) << fMessage;
0117 #endif
0118   }
0119   //----------------------------------------------------------------------
0120   inline float getFloat(const std::string& token) {
0121     char* endptr;
0122     float result = strtod(token.c_str(), &endptr);
0123     if (endptr == token.c_str()) {
0124       std::stringstream sserr;
0125       sserr << "can't convert token " << token << " to float value";
0126       handleError("getFloat", sserr.str());
0127     }
0128     return result;
0129   }
0130   //----------------------------------------------------------------------
0131   inline unsigned getUnsigned(const std::string& token) {
0132     char* endptr;
0133     unsigned result = strtoul(token.c_str(), &endptr, 0);
0134     if (endptr == token.c_str()) {
0135       std::stringstream sserr;
0136       sserr << "can't convert token " << token << " to unsigned value";
0137       handleError("getUnsigned", sserr.str());
0138     }
0139     return result;
0140   }
0141   inline long int getSigned(const std::string& token) {
0142     char* endptr;
0143     unsigned result = strtol(token.c_str(), &endptr, 0);
0144     if (endptr == token.c_str()) {
0145       std::stringstream sserr;
0146       sserr << "can't convert token " << token << " to signed value";
0147       handleError("getSigned", sserr.str());
0148     }
0149     return result;
0150   }
0151   //----------------------------------------------------------------------
0152   inline std::string getSection(const std::string& token) {
0153     size_t iFirst = token.find('[');
0154     size_t iLast = token.find(']');
0155     if (iFirst != std::string::npos && iLast != std::string::npos && iFirst < iLast)
0156       return std::string(token, iFirst + 1, iLast - iFirst - 1);
0157     return "";
0158   }
0159   //----------------------------------------------------------------------
0160   inline std::vector<std::string> getTokens(const std::string& fLine) {
0161     std::vector<std::string> tokens;
0162     std::string currentToken;
0163     for (unsigned ipos = 0; ipos < fLine.length(); ++ipos) {
0164       char c = fLine[ipos];
0165       if (c == '#')
0166         break;              // ignore comments
0167       else if (c == ' ') {  // flush current token if any
0168         if (!currentToken.empty()) {
0169           tokens.push_back(currentToken);
0170           currentToken.clear();
0171         }
0172       } else
0173         currentToken += c;
0174     }
0175     if (!currentToken.empty())
0176       tokens.push_back(currentToken);  // flush end
0177     return tokens;
0178   }
0179   //----------------------------------------------------------------------
0180   inline std::string getDefinitions(const std::string& token) {
0181     size_t iFirst = token.find('{');
0182     size_t iLast = token.find('}');
0183     if (iFirst != std::string::npos && iLast != std::string::npos && iFirst < iLast)
0184       return std::string(token, iFirst + 1, iLast - iFirst - 1);
0185     return "";
0186   }
0187   //------------------------------------------------------------------------
0188   inline float quadraticInterpolation(float fZ, const float fX[3], const float fY[3]) {
0189     // Quadratic interpolation through the points (x[i],y[i]). First find the parabola that
0190     // is defined by the points and then calculate the y(z).
0191     float D[4], a[3];
0192     D[0] = fX[0] * fX[1] * (fX[0] - fX[1]) + fX[1] * fX[2] * (fX[1] - fX[2]) + fX[2] * fX[0] * (fX[2] - fX[0]);
0193     D[3] = fY[0] * (fX[1] - fX[2]) + fY[1] * (fX[2] - fX[0]) + fY[2] * (fX[0] - fX[1]);
0194     D[2] = fY[0] * (pow(fX[2], 2) - pow(fX[1], 2)) + fY[1] * (pow(fX[0], 2) - pow(fX[2], 2)) +
0195            fY[2] * (pow(fX[1], 2) - pow(fX[0], 2));
0196     D[1] = fY[0] * fX[1] * fX[2] * (fX[1] - fX[2]) + fY[1] * fX[0] * fX[2] * (fX[2] - fX[0]) +
0197            fY[2] * fX[0] * fX[1] * (fX[0] - fX[1]);
0198     if (D[0] != 0) {
0199       a[0] = D[1] / D[0];
0200       a[1] = D[2] / D[0];
0201       a[2] = D[3] / D[0];
0202     } else {
0203       a[0] = 0.0;
0204       a[1] = 0.0;
0205       a[2] = 0.0;
0206     }
0207     float r = a[0] + fZ * (a[1] + fZ * a[2]);
0208     return r;
0209   }
0210   //------------------------------------------------------------------------
0211   //Generates a std::tuple type based on a stored type and the number of
0212   // objects in the tuple.
0213   //Note: All of the objects will be of the same type
0214   template <typename /*LEFT_TUPLE*/, typename /*RIGHT_TUPLE*/>
0215   struct join_tuples {};
0216   template <typename... LEFT, typename... RIGHT>
0217   struct join_tuples<std::tuple<LEFT...>, std::tuple<RIGHT...>> {
0218     typedef std::tuple<LEFT..., RIGHT...> type;
0219   };
0220   template <typename T, unsigned N>
0221   struct generate_tuple_type {
0222     typedef typename generate_tuple_type<T, N / 2>::type left;
0223     typedef typename generate_tuple_type<T, N / 2 + N % 2>::type right;
0224     typedef typename join_tuples<left, right>::type type;
0225   };
0226   template <typename T>
0227   struct generate_tuple_type<T, 1> {
0228     typedef std::tuple<T> type;
0229   };
0230   template <typename T>
0231   struct generate_tuple_type<T, 0> {
0232     typedef std::tuple<> type;
0233   };
0234   //------------------------------------------------------------------------
0235   //C++11 implementation of make_index_sequence, which is a C++14 function
0236   // using aliases for cleaner syntax
0237   template <class T>
0238   using Invoke = typename T::type;
0239 
0240   template <unsigned...>
0241   struct seq {
0242     using type = seq;
0243   };
0244 
0245   template <class S1, class S2>
0246   struct concat;
0247 
0248   template <unsigned... I1, unsigned... I2>
0249   struct concat<seq<I1...>, seq<I2...>> : seq<I1..., (sizeof...(I1) + I2)...> {};
0250 
0251   template <class S1, class S2>
0252   using Concat = Invoke<concat<S1, S2>>;
0253 
0254   template <unsigned N>
0255   struct gen_seq;
0256   template <unsigned N>
0257   using GenSeq = Invoke<gen_seq<N>>;
0258 
0259   template <unsigned N>
0260   struct gen_seq : Concat<GenSeq<N / 2>, GenSeq<N - N / 2>> {};
0261 
0262   template <>
0263   struct gen_seq<0> : seq<> {};
0264   template <>
0265   struct gen_seq<1> : seq<0> {};
0266   //------------------------------------------------------------------------
0267   //Generates a tuple based on a given function (i.e. lambda expression)
0268   template <typename F, unsigned... Is>
0269   auto gen_tuple_impl(F func, seq<Is...>) -> decltype(std::make_tuple(func(Is)...)) {
0270     return std::make_tuple(func(Is)...);
0271   }
0272   template <unsigned N, typename F>
0273   auto gen_tuple(F func) -> decltype(gen_tuple_impl(func, GenSeq<N>())) {
0274     return gen_tuple_impl(func, GenSeq<N>());
0275   }
0276 }  // namespace
0277 #endif