BUILTIN_METHODS = \
{
    "Namespace_ROOT_VecOps": "using namespace ROOT::VecOps;", 
    "Namespace_ROOT_Math": "using namespace ROOT::Math;",
    "SizeOf" : "template<typename T>\n"
               "auto SizeOf(T vec)\n"
               "{return vec.size();}",
    "CosineThetaStar": "template<typename T1, typename T2>\n"
                       "auto CosineThetaStar(T1 P1, T2 P2){\n"
                       "auto P12 = P1 + P2;\n"
                       "double P1_plus  = (P1.E() + P1.Pz())/1.41421356;\n"
                       "double P2_plus  = (P2.E() + P2.Pz())/1.41421356;\n"
                       "double P1_minus = (P1.E() - P1.Pz())/1.41421356;\n"
                       "double P2_minus = (P2.E() - P2.Pz())/1.41421356;\n"
                       "double M12_squared = pow(P12.M(),2);\n"
                       "double PT12_squared = pow(P12.Pt(),2);\n"
                       "return 2*((P1_plus*P2_minus -P1_minus*P2_plus)/"
                       "sqrt(M12_squared*(M12_squared+PT12_squared)))*(P12.Pz()/abs(P12.Pz()));}\n",
    "LVUtils": "LorentzVector<PtEtaPhiM4D<double>> getLV_PtEtaPhiM(const float &pt, const float &eta, const float &phi, const float &M){\n"
               "    LorentzVector<PtEtaPhiM4D<double>> result{pt, eta, phi, M};\n"
               "    return result;\n"
               "}\n"
               "LorentzVector<PtEtaPhiE4D<double>> getLV_PtEtaPhiE(const float &pt, const float &eta, const float &phi, const float &E){\n"
               "    LorentzVector<PtEtaPhiE4D<double>> result{pt, eta, phi, E};\n"
               "    return result;\n"
               "}\n"
               "RVec<LorentzVector<PtEtaPhiM4D<double>>> getLVArray_PtEtaPhiM(const RVec<float> &pt, const RVec<float> &eta, \n"
               "                                                             const RVec<float> &phi, const RVec<float> &M){\n"
               "    RVec<LorentzVector<PtEtaPhiM4D<double>>> result;\n"
               "    for (size_t i=0; i<pt.size(); i++){\n"
               "        LorentzVector<PtEtaPhiM4D<double>> lv{pt[i], eta[i], phi[i], M[i]};\n"
               "        result.push_back(lv);\n"
               "    }\n"
               "    return result;\n"
               "}\n"
               "RVec<LorentzVector<PtEtaPhiM4D<double>>> getLVArray_PtEtaPhiM(const RVec<float> &pt, const RVec<float> &eta, \n"
               "                                                             const RVec<float> &phi, const float &M){\n"
               "    RVec<LorentzVector<PtEtaPhiM4D<double>>> result;\n"
               "    for (size_t i=0; i<pt.size(); i++){\n"
               "        LorentzVector<PtEtaPhiM4D<double>> lv{pt[i], eta[i], phi[i], M};\n"
               "        result.push_back(lv);\n"
               "    }\n"
               "    return result;\n"
               "}\n"
               "RVec<LorentzVector<PtEtaPhiE4D<double>>> getLVArray_PtEtaPhiE(const RVec<float> &pt, const RVec<float> &eta, \n"
               "                                                             const RVec<float> &phi, const RVec<float> &E){\n"
               "    RVec<LorentzVector<PtEtaPhiE4D<double>>> result;\n"
               "    for (size_t i=0; i<pt.size(); i++){\n"
               "        LorentzVector<PtEtaPhiE4D<double>> lv{pt[i], eta[i], phi[i], E[i]};\n"
               "        result.push_back(lv);\n"
               "    }\n"
               "    return result;\n"
               "}\n"
               "template<typename T>\n"
               "LorentzVector<PtEtaPhiE4D<double>> getLVSum_PtEtaPhiE(const RVec<LorentzVector<T>> &lv_vec, int n=0){\n"
               "    LorentzVector<PtEtaPhiE4D<double>> result;\n"
               "    if ((n==0)||(n>lv_vec.size()))\n"
               "        n = (int)lv_vec.size();\n"
               "    for (size_t i=0; i<n; i++)\n"
               "        result += lv_vec[i];\n"
               "    return result;\n"
               "}\n"
               "template<typename T>\n"
               "LorentzVector<PtEtaPhiM4D<double>> getLVSum_PtEtaPhiM(const RVec<LorentzVector<T>> &lv_vec, int n=0){\n"
               "    LorentzVector<PtEtaPhiM4D<double>> result;\n"
               "    if ((n==0)||(n>lv_vec.size()))\n"
               "        n = (int)lv_vec.size();\n"
               "    for (size_t i=0; i<n; i++)\n"
               "        result += lv_vec[i];\n"
               "    return result;\n"
               "}\n"
               "template<typename T>\n"
               "RVec<float> getArrayPt(const RVec<LorentzVector<T>> &lv_vec){\n"
               "    RVec<float> result;\n"
               "    for (auto &lv: lv_vec)\n"
               "        result.push_back(lv.pt());\n"
               "    return result;\n"
               "}\n"
               "template<typename T>\n"
               "RVec<float> getArrayEta(const RVec<LorentzVector<T>> &lv_vec){\n"
               "    RVec<float> result;\n"
               "    for (auto &lv: lv_vec)\n"
               "        result.push_back(lv.eta());\n"
               "    return result;\n"
               "}\n"
               "template<typename T>\n"
               "RVec<float> getArrayPhi(const RVec<LorentzVector<T>> &lv_vec){\n"
               "    RVec<float> result;\n"
               "    for (auto &lv: lv_vec)\n"
               "        result.push_back(lv.phi());\n"
               "    return result;\n"
               "}\n"
               "template<typename T>\n"
               "RVec<float> getArrayE(const RVec<LorentzVector<T>> &lv_vec){\n"
               "    RVec<float> result;\n"
               "    for (auto &lv: lv_vec)\n"
               "        result.push_back(lv.E());\n"
               "    return result;\n"
               "}\n"
               "template<typename T>\n"
               "RVec<float> getArrayM(const RVec<LorentzVector<T>> &lv_vec){\n"
               "    RVec<float> result;\n"
               "    for (auto &lv: lv_vec)\n"
               "        result.push_back(lv.M());\n"
               "    return result;\n"
               "}\n"
               "template<typename T>\n"
               "float getPt(const LorentzVector<T> &lv_vec){\n"
               "    return lv_vec.pt();\n"
               "}\n"
               "template<typename T>\n"
               "float getEta(const LorentzVector<T> &lv_vec){\n"
               "    return lv_vec.eta();\n"
               "}\n"
               "template<typename T>\n"
               "float getPhi(const LorentzVector<T> &lv_vec){\n"
               "    return lv_vec.phi();\n"
               "}\n"
               "template<typename T>\n"
               "float getM(const LorentzVector<T> &lv_vec){\n"
               "    return lv_vec.M();\n"
               "}\n"
               "template<typename T>\n"
               "float getE(const LorentzVector<T> &lv_vec){\n"
               "    return lv_vec.E();\n"
               "}\n"
               "template<typename T>\n"
               "std::vector<T> RVec2Vec(const RVec<T> v){\n"
               "    return std::vector<T>{v.begin(), v.end()};\n"
               "}\n"
}