4 #ifndef TRUTHUTILS_ATLASPID_H 
    5 #define TRUTHUTILS_ATLASPID_H 
   16 class DecodedPID: 
public std::pair<int,std::vector<int>> {
 
   22     for(; 
ap; 
ap/=10) this->
second.push_back( ap%10 );
 
   27   inline const int& 
last()
 const { 
return this->
second.back();}
 
   28   inline const int& 
pid()
 const { 
return this->
first;}
 
   34 static const int TABLESIZE = 100;
 
   35 static const std::array<int,TABLESIZE> triple_charge = {
 
   36   +0, -1, +2, -1, +2, -1, +2, -1, +2, +0,
 
   37   +0, -3, +0, -3, +0, -3, +0, -3, +0, +0,
 
   38   +0, +0, +0, +0, +3, +0, +0, +0, +0, +0,
 
   39   +0, +0, +0, +0, +3, +0, +0, +3, +6, +0,
 
   40   +0, +0, -1, +0, +0, +0, +0, +0, +0, +0,
 
   41   +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
 
   42   +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
 
   43   +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
 
   44   +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
 
   45   +0, +0, +0, +0, +0, +0, +0, +0, +0, +0
 
   50 static const std::array<int,TABLESIZE> double_spin = {
 
   51   +0, +1, +1, +1, +1, +1, +1, +1, +1, +0,
 
   52   +0, +1, +1, +1, +1, +1, +1, +1, +1, +0,
 
   53   +2, +2, +2, +2, +2, +0, +0, +0, +0, +0,
 
   54   +0, +0, +2, +2, +2, +0, +0, +0, +0, +4,
 
   55   +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
 
   56   +0, +0, +1, +2, +0, +2, +0, +1, +2, +0, 
 
   57   +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
 
   58   +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
 
   59   +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
 
   60   +0, +0, +0, +0, +0, +0, +0, +0, +0, +0
 
   64 static const int DQUARK = 1;
 
   65 static const int UQUARK = 2;
 
   66 static const int SQUARK = 3;
 
   67 static const int CQUARK = 4;
 
   68 static const int BQUARK = 5;
 
   69 static const int TQUARK = 6;
 
   70 static const int BPRIME = 7; 
 
   71 static const int TPRIME = 8; 
 
   72 static const int QUARK_LIMIT = BPRIME; 
 
   74 static const int ELECTRON = 11;
 
   75 static const int POSITRON = -ELECTRON;
 
   76 static const int NU_E = 12;
 
   77 static const int MUON = 13;
 
   78 static const int NU_MU = 14;
 
   79 static const int TAU = 15;
 
   80 static const int NU_TAU = 16;
 
   81 static const int LPRIME = 17; 
 
   82 static const int NUPRIME = 18; 
 
   84 static const int GLUON = 21;
 
   86 static const int COMPOSITEGLUON = 9;
 
   87 static const int PHOTON = 22;
 
   88 static const int Z0BOSON = 23;
 
   89 static const int WPLUSBOSON = 24;
 
   90 static const int HIGGSBOSON = 25;
 
   91 static const int ZPRIME = 32; 
 
   92 static const int ZDBLPRIME = 33; 
 
   93 static const int WPLUSPRIME = 34; 
 
   94 static const int HIGGS2 = 35; 
 
   95 static const int HIGGS3 = 36; 
 
   96 static const int HIGGSPLUS = 37; 
 
   97 static const int HIGGSPLUSPLUS = 38; 
 
   98 static const int GRAVITON = 39;
 
   99 static const int HIGGS4 = 40; 
 
  100 static const int LEPTOQUARK = 42;
 
  106 static const int DARKPHOTON = 60000;
 
  107 static const int MAVTOP = 60001;
 
  109 static const int PIPLUS = 211;
 
  110 static const int PIMINUS = -PIPLUS;
 
  111 static const int PI0 = 111;
 
  112 static const int K0L = 130;
 
  114 static const int K0S = 310;
 
  115 static const int K0 = 311;
 
  116 static const int KPLUS = 321;
 
  117 static const int DPLUS = 411;
 
  118 static const int DSTAR = 413;
 
  119 static const int D0 = 421;
 
  120 static const int DSPLUS = 431;
 
  121 static const int JPSI = 443;
 
  122 static const int B0 = 511;
 
  123 static const int BCPLUS = 541;
 
  124 static const int PROTON = 2212;
 
  125 static const int NEUTRON = 2112;
 
  126 static const int LAMBDA0 = 3122;
 
  127 static const int LAMBDACPLUS = 4122;
 
  128 static const int LAMBDAB0 = 5122;
 
  129 static const int PSI2S = 20443;
 
  136 static const int  RH_NU_E = 9900012;
 
  137 static const int  RH_NU_MU = 9900014;
 
  138 static const int  RH_NU_TAU = 9900016;
 
  139 static const int  WBOSON_LRSM = 9900024;
 
  141 static const int LEAD = 1000822080;
 
  142 static const int OXYGEN = 1000080160;
 
  143 static const int NEON = 1000100200;
 
  144 static const int HELIUM =  1000020040;
 
  149 static const int POMERON = 990;
 
  150 static const int ODDERON = 9990;
 
  151 static const int REGGEON = 110;
 
  158 static const int GEANTINOPLUS = 998;
 
  159 static const int GEANTINO0 = 999;
 
  168 template<> 
inline bool isQuark(
const int& 
p) { 
return p != 0 && (std::abs(
p) <= TPRIME || std::abs(
p) == MAVTOP);}
 
  173 template<> 
inline bool isSMQuark(
const int& 
p) { 
return p != 0 && std::abs(
p) <= TQUARK;}
 
  177 template<> 
inline bool isStrange(
const int& 
p){ 
return std::abs(
p) == SQUARK;}
 
  180 template<> 
inline bool isCharm(
const int& 
p){ 
return std::abs(
p) == CQUARK;}
 
  183 template<> 
inline bool isBottom(
const int& 
p){ 
return std::abs(
p) == BQUARK;}
 
  186 template<> 
inline bool isTop(
const int& 
p){ 
return std::abs(
p) == TQUARK;}
 
  190 template<> 
inline bool isLepton(
const int& 
p){ 
auto sp = std::abs(
p); 
return sp >= ELECTRON && sp <= NUPRIME; }
 
  195 template<> 
inline bool isSMLepton(
const int& 
p){ 
auto sp = std::abs(
p); 
return sp >= ELECTRON && sp <= NU_TAU; }
 
  200 template<> 
inline bool isChLepton(
const int& 
p){ 
auto sp = std::abs(
p); 
return sp >= ELECTRON && sp <= LPRIME && sp%2 == 1; }
 
  203 template<> 
inline bool isElectron(
const int& 
p){ 
return std::abs(
p) == ELECTRON;}
 
  206 template<> 
inline bool isMuon(
const int& 
p){ 
return std::abs(
p) == 
MUON;}
 
  209 template<> 
inline bool isTau(
const int& 
p){ 
return std::abs(
p) == TAU;}
 
  213 template<> 
inline bool isNeutrino(
const int& 
p){ 
auto sp = std::abs(
p); 
return sp == NU_E || sp == NU_MU || sp == NU_TAU || sp == NUPRIME;  }
 
  216 template<> 
inline bool isSMNeutrino(
const int& 
p){ 
auto sp = std::abs(
p); 
return sp == NU_E || sp == NU_MU || sp == NU_TAU;  }
 
  221 template<> 
inline bool isFourthGeneration(
const int& 
p) {
return std::abs(
p) == BPRIME || std::abs(
p) == TPRIME || std::abs(
p) == LPRIME || std::abs(
p) == NUPRIME;}
 
  229   if ( 
p.ndigits() == 4 && 
p(0) >= 
p(1) && 
p(1) !=0 && 
p(2) == 0 && (
p.last() == 1 || 
p.last() == 3)
 
  230        && 
p.max_digit(2,4) < QUARK_LIMIT
 
  246   if (
p.ndigits() < 3 ) 
return false;
 
  247   if (
p.ndigits() == 7 && (
p(0) == 1 || 
p(0) == 2)) 
return false; 
 
  248   if (std::abs(
p.pid()) == K0S) 
return true;
 
  249   if (std::abs(
p.pid()) == K0L) 
return true;
 
  250   if (std::abs(
p.pid()) == K0) 
return true;
 
  251   if (
p.last() % 2 != 1 ) 
return false;
 
  252   if (
p.max_digit(1,3) >= QUARK_LIMIT ) 
return false; 
 
  253   if (
p.min_digit(1,3) == 0 ) 
return false;
 
  254   if (*(
p.second.rbegin() + 2) < *(
p.second.rbegin() + 1) ) 
return false; 
 
  255   if (*(
p.second.rbegin() + 2) == *(
p.second.rbegin() + 1) && 
p.pid() < 0 ) 
return false; 
 
  256   if (
p.ndigits() == 3 ) 
return true;
 
  257   if (*(
p.second.rbegin() + 3) != 0 ) 
return false; 
 
  258   if (
p.ndigits() == 5 && 
p(0) == 1 ) 
return true;
 
  259   if (
p.ndigits() == 5 && 
p(0) == 2 && 
p.last() > 1 ) 
return true;
 
  260   if (
p.ndigits() == 5 && 
p(0) == 3 && 
p.last() > 1 ) 
return true;
 
  261   if (
p.ndigits() == 6 && 
p.last() % 2 == 1 ) 
return true;
 
  262   if (
p.ndigits() == 7 && 
p(0) == 9 && 
p(1) == 0 ) 
return true;
 
  276   return (*(
p.second.rbegin() + 2) > SQUARK && 
p.last() > 0 && *(
p.second.rbegin() + 1) == *(
p.second.rbegin() + 2));
 
  284   if (
p.ndigits() < 4 ) 
return false;
 
  285   if (
p.max_digit(1,4) >= QUARK_LIMIT ) 
return false; 
 
  286   if (
p.min_digit(1,4) == 0) 
return false; 
 
  287   if (
p.ndigits() == 4 && (
p.last() == 2 || 
p.last() == 4|| 
p.last() == 6|| 
p.last() == 8) ) 
return true;
 
  289   if (
p.ndigits() == 5 && 
p(0) == 1 &&  (
p.last() == 2 || 
p.last() == 4) ) 
return true;
 
  290   if (
p.ndigits() == 5 && 
p(0) == 3 &&  (
p.last() == 2 || 
p.last() == 4) ) 
return true;
 
  292   if (
p.ndigits() == 6 ) {
 
  293     if (
p(0) == 1 && 
p(1) == 0 && 
p.last() == 2 ) 
return true;
 
  294     if (
p(0) == 1 && 
p(1) == 0 && 
p.last() == 4 ) 
return true;
 
  295     if (
p(0) == 1 && 
p(1) == 0 && 
p.last() == 6 ) 
return true;
 
  296     if (
p(0) == 1 && 
p(1) == 1 && 
p.last() == 2 ) 
return true;
 
  297     if (
p(0) == 1 && 
p(1) == 2 && 
p.last() == 4 ) 
return true;
 
  299     if (
p(0) == 2 && 
p(1) == 0 && 
p.last() == 2 ) 
return true;
 
  300     if (
p(0) == 2 && 
p(1) == 0 && 
p.last() == 4 ) 
return true;
 
  301     if (
p(0) == 2 && 
p(1) == 0 && 
p.last() == 6 ) 
return true;
 
  302     if (
p(0) == 2 && 
p(1) == 0 && 
p.last() == 8 ) 
return true;
 
  303     if (
p(0) == 2 && 
p(1) == 1 && 
p.last() == 2 ) 
return true;
 
  306   if (
p.ndigits() == 5 ) {
 
  307     if (
p(0) == 2 && 
p.last() == 2 ) 
return true;
 
  308     if (
p(0) == 2 && 
p.last() == 4 ) 
return true;
 
  309     if (
p(0) == 2 && 
p.last() == 6 ) 
return true;
 
  310     if (
p(0) == 5 && 
p.last() == 2 ) 
return true;
 
  311     if (
p(0) == 1 && 
p.last() == 6 ) 
return true;
 
  312     if (
p(0) == 4 && 
p.last() == 2 ) 
return true;
 
  327   return (
p.ndigits() == 9 && 
p(0) == 1 && 
p(5) == 0 &&
 
  328           p.max_digit(1,3) < QUARK_LIMIT && 
p.min_digit(1,3) > 0 && 
 
  329           p.max_digit(4,6) < QUARK_LIMIT && 
p.min_digit(4,6) > 0 && 
 
  330           ( 
p(3) >= 
p(4) && 
p(6) >= 
p(7) ) && ( ( 
p(3) > 
p(6) ) || ( 
p(3) == 
p(6) && (
p(4) >= 
p(7))))
 
  344   return (
p.ndigits() == 9 && 
p(0) == 1 &&
 
  345           p.max_digit(1,6) < QUARK_LIMIT && 
p.min_digit(1,6) > 0 && 
 
  346           ( 
p(3) >= 
p(4) && 
p(4) >= 
p(5) && 
p(5) >= 
p(6)) );
 
  360 template<> 
inline bool isTrajectory(
const int& 
p){ 
return std::abs(
p) == POMERON || std::abs(
p) == ODDERON || std::abs(
p) == REGGEON; }
 
  370 template<> 
inline bool isBoson(
const int& 
p){ 
auto sp = std::abs(
p); 
return sp > 20 && sp < 41; }
 
  374 template<> 
inline bool isGluon(
const int& 
p){ 
return p == GLUON; }
 
  377 template<> 
inline bool isPhoton(
const int& 
p){ 
return p == PHOTON; }
 
  379 template<
class T> 
inline bool isZ(
const T& 
p){
return isZ(
p->pdg_id());}
 
  380 template<> 
inline bool isZ(
const int& 
p){ 
return p == Z0BOSON; }
 
  382 template<
class T> 
inline bool isW(
const T& 
p){
return isW(
p->pdg_id());}
 
  383 template<> 
inline bool isW(
const int& 
p){ 
return std::abs(
p) == WPLUSBOSON; }
 
  387 template<> 
inline bool isHeavyBoson(
const int& 
p){ 
return p == ZPRIME || 
p == ZDBLPRIME || std::abs(
p) == WPLUSPRIME; }
 
  391 template<> 
inline bool isHiggs(
const int& 
p){ 
return p == HIGGSBOSON; }
 
  395 template<> 
inline bool isMSSMHiggs(
const int& 
p){ 
return p == HIGGS2 || 
p == HIGGS3 || std::abs(
p) == HIGGSPLUS; }
 
  398 template<> 
inline bool isGraviton(
const int& 
p){ 
return p == GRAVITON; }
 
  409 template<> 
inline bool isLeptoQuark(
const int& 
p){ 
return std::abs(
p) == LEPTOQUARK; }
 
  421 template<> 
inline bool isNeutrinoRH(
const int& 
p){ 
return (std::abs(
p) ==  RH_NU_E || std::abs(
p) ==  RH_NU_MU|| std::abs(
p) ==  RH_NU_TAU);}
 
  427   int ap = std::abs(
p);
 
  428   if (
ap >= 81 && 
ap <= 100) 
return true;
 
  429   if (
ap >= 901 && 
ap <= 930) 
return true;
 
  430   if (
ap >= 998 && 
ap <= 999) 
return true;
 
  431   if (
ap >= 1901 && 
ap <= 1930) 
return true;
 
  432   if (
ap >= 2901 && 
ap <= 2930) 
return true;
 
  433   if (
ap >= 3901 && 
ap <= 3930) 
return true;
 
  438 template<> 
inline bool isGeantino(
const int& 
p){ 
return (std::abs(
p) ==  GEANTINO0 || std::abs(
p) ==  GEANTINOPLUS);}
 
  443   if (
p.ndigits() > 4) 
return false; 
 
  445     ( ( 
p.ndigits() == 3 && 
p(0) == COMPOSITEGLUON && 
p(1) == COMPOSITEGLUON && (
p.last() == 1 || 
p.last() == 5) ) ||
 
  446       ( 
p.ndigits() == 4 && 
p(0) == COMPOSITEGLUON && 
p(1) == COMPOSITEGLUON && 
p(2) == COMPOSITEGLUON &&  (
p.last() == 3 || 
p.last() == 7) )  );
 
  460   auto pp = 
p.shift(1); 
return (
p.ndigits() == 7 && (
p(0) == 1 || 
p(0) == 2) && 
isSMQuark(pp));
 
  468   auto pp = 
p.shift(1); 
return (
p.ndigits() == 7 && 
p(0) == 1 && 
isSMQuark(pp));
 
  476   auto pp = 
p.shift(1); 
return (
p.ndigits() == 7 && 
p(0) == 2 && 
isSMQuark(pp));
 
  490   auto pp = 
p.shift(1); 
return (
p.ndigits() == 7 && 
p(0) == 1 && 
isSMLepton(pp));
 
  498   auto pp = 
p.shift(1); 
return (
p.ndigits() == 7 && 
p(0) == 2 && 
isSMLepton(pp));
 
  506   auto pp = 
p.shift(1); 
return (
p.ndigits() == 7 && 
p(0) == 1 && 
isBoson(pp.pid()));
 
  527   const auto& pp = (
p.ndigits() == 7) ? 
p.shift(2) : 
DecodedPID(0);
 
  528   return (
p.ndigits() == 7 && 
p(0) == 3 && (
p(1) == 0 || 
p(1) == 1) &&
 
  539   const auto& pp = (
p.ndigits() == 7) ? 
p.shift(2) : 
DecodedPID(0);
 
  540   return (
p.ndigits() == 7 && (
p(0) == 4 && 
p(1) == 0) &&
 
  564   if (
p.ndigits() != 7 || 
p(0) != 1) 
return false;
 
  565   auto pp = 
p.shift(1);
 
  567     ( ( pp.ndigits() == 3 && pp(0) == COMPOSITEGLUON && pp(1) == COMPOSITEGLUON && (pp.last() == 1 || pp.last() == 3) ) ||
 
  568       ( pp.ndigits() == 4 && pp(0) == COMPOSITEGLUON && pp(1) == COMPOSITEGLUON && pp(2) == COMPOSITEGLUON && (pp.last() == 1 || pp.last() == 5) )  );
 
  576   if (!(
p.ndigits() == 7 && (
p(0) == 1 || 
p(0) == 2))) 
return false;
 
  577   auto pp = 
p.shift(1);
 
  580           (pp.ndigits() == 4 && 
p(0) == 1 && pp(0) == COMPOSITEGLUON && pp.min_digit(1,3) > 0 && pp.max_digit(1,3) < QUARK_LIMIT && pp(2) <= pp(1) && (pp.last() == 1 || pp.last() == 3)) ||
 
  582           (pp.ndigits() == 3 && pp.min_digit(1,3) > 0 && pp.max_digit(1,3) < QUARK_LIMIT && pp(1) <= pp(0) && pp.last() == 2)
 
  591   if (!(
p.ndigits() == 7 && (
p(0) == 1 || 
p(0) == 2))) 
return false;
 
  592   auto pp = 
p.shift(1);
 
  595           (pp.ndigits() == 5 && 
p(0) == 1 && pp(0) == COMPOSITEGLUON && pp.min_digit(1,4) > 0 && pp.max_digit(1,4) < QUARK_LIMIT && pp(2) <= pp(1) && pp(3) <= pp(2) && (pp.last() == 2 || pp.last() == 4)) ||
 
  597           (pp.ndigits() == 4 && pp.min_digit(1,4) > 0 && pp.max_digit(1,4) < QUARK_LIMIT && pp(1) <= pp(0) && pp(2) <= pp(1) && (pp.last() == 1 || pp.last() == 3))
 
  612   auto pp = 
p.shift(1); 
return (
 
  635 template<
class T> 
inline bool isKK(
const T& 
p){
return isKK(
p->pdg_id());}
 
  636 template<> 
inline bool isKK(
const DecodedPID& 
p){
return (
p.ndigits() == 7 && (
p(0) == 5 || 
p(0) == 6 ) && (
p(1) != 9) );}
 
  646 template<> 
inline bool isMonopole(
const DecodedPID& 
p){
return (
p.ndigits() == 7 && 
p(0) == 4 && 
p(1) == 1  && (
p(2) == 1 || 
p(2) == 2 ) && 
p(6) == 0);}
 
  658 template<
class T> 
inline bool isDM(
const T& 
p){
return isDM(
p->pdg_id());}
 
  659 template<> 
inline bool isDM(
const int& 
p){
 
  660   auto sp = std::abs(
p);
 
  662   return (sp >= 51 && sp <= 60) || (value_digits.ndigits() == 7 && value_digits(0) == 5 && value_digits(1) == 9) || sp == DARKPHOTON; }
 
  671   const auto& pp = (
p.ndigits() == 7) ? 
p.shift(2) : 
DecodedPID(0);
 
  672   return (
p.ndigits() == 7 && 
p(0) == 4 && 
p(1) == 9 &&
 
  704   if (std::abs(
p.pid()) == PROTON) 
return true;
 
  705   if (
p.ndigits() != 10) 
return false;
 
  708   const int A = 
p(8) + 10*
p(7) + 100*
p(6);
 
  709   const int Z = 
p(5) + 10*
p(4) + 100*
p(3);
 
  710   return ( 
A >= 
Z &&  
p(0) == 1 &&  
p(1) == 0 );
 
  717   if (
isQuark(
p.pid())) { 
return (std::abs(
p.pid()) == 
q );}
 
  718   if (
isMeson(
p)) { 
return *(
p.second.rbegin() + 1) == 
q ||*(
p.second.rbegin()+2) ==
q;}
 
  720   if (
isBaryon(
p)) { 
auto i = 
std::find(
p.second.rbegin() + 1,
p.second.rbegin()+4,
q); 
return (
i!=
p.second.rbegin()+4);}
 
  723   if (
isNucleus(
p) && std::abs(
p.pid()) != PROTON) { 
return (
q == 1 || 
q == 2 || (
q==3 && 
p(2) > 0));}
 
  725     auto pp = 
p.shift(1);
 
  726     if ( pp.ndigits() == 1 ) { 
return false; } 
 
  727     if ( pp.ndigits() == 3 ) { 
return (pp(1) == 
q); } 
 
  728     if ( pp.ndigits() == 4 ) { 
return (pp(1) == 
q || pp(2) == 
q); } 
 
  729     if ( pp.ndigits() == 5 ) {  
return (pp(1) == 
q || pp(2) == 
q || pp(3) == 
q); } 
 
  730     if ( pp.ndigits() > 5 ) { pp = pp.shift(1); } 
 
  750   if (
isQuark(
p.pid())) { 
return (
p.pid() > 0) ? 1 : - 1;}
 
  751   if (
isDiquark(
p)) { 
return (
p.pid() > 0) ? 2 : -2; }
 
  755     const int result = 3*
p(8) + 30*
p(7) + 300*
p(6);
 
  759     auto pp = 
p.shift(1);
 
  761     if (pp(0) == COMPOSITEGLUON) {
 
  762       if (pp(1) == COMPOSITEGLUON) { 
return 0; } 
 
  763       if ( pp.ndigits() == 4 ) { 
return 0; }  
 
  764       if ( pp.ndigits() == 5) { 
return (
p.pid() > 0) ? 3 : -3; } 
 
  766     if (pp.ndigits() == 3) { 
return 0; } 
 
  767     if (pp.ndigits() == 4) { 
return (
p.pid() > 0) ? 3 : -3; } 
 
  784 static const std::array<int,10> is_strange = {
 
  785   +0, +0, +0, -1, +0, +0, +0, +0, +0, +0 };
 
  788   if (
isNucleus(
p) && 
p.ndigits() == 10) { 
return (
p.pid() > 0) ? -
p(2) : 
p(2); }
 
  789   if (
isStrange(
p.pid())) { 
return (
p.pid() > 0) ? -1 : 1; }
 
  791   if (std::abs(
p.pid()) == K0) { 
return (
p.pid() > 0) ? 1 : -1; }
 
  796   bool classified = 
false;
 
  797   if (!classified && 
isMeson(
p)) { classified = 
true; nq = 2; 
if ((*(
p.second.rbegin()+2)) == 2||(*(
p.second.rbegin()+2)) == 4 ) { 
sign=-1;} signmult =-1; }
 
  798   if (!classified && 
isDiquark(
p)) {
return is_strange.at(
p(0))+is_strange.at(
p(1)); }
 
  799   if (!classified && 
isBaryon(
p)) { classified = 
true; nq = 3; }
 
  800   if (!classified && 
isTetraquark(
p)){ 
return is_strange.at(
p(3)) + is_strange.at(
p(4)) - is_strange.at(
p(6)) - is_strange.at(
p(7)); }
 
  801   if (!classified && 
isPentaquark(
p)){ 
return is_strange.at(
p(3)) + is_strange.at(
p(4)) + is_strange.at(
p(5)) + is_strange.at(
p(6)) - is_strange.at(
p(7)); }
 
  802   if (!classified && 
isSUSY(
p)) {
 
  804     auto pp = 
p.shift(1);
 
  806     if (pp(0) == COMPOSITEGLUON) {
 
  807       if (pp(1) == COMPOSITEGLUON) { 
return 0; } 
 
  808       if ( pp.ndigits() == 4 || pp.ndigits() == 5) {
 
  812     if (pp.ndigits() == 3) { classified = 
true; nq = 2; 
if (
p.last()%2==0) {
sign = -1;} signmult = -1; } 
 
  813     if (pp.ndigits() == 4) { classified = 
true; nq = 3; } 
 
  815   for (
auto r = 
p.second.rbegin() + 1; 
r != 
p.second.rbegin() + 1 + nq; ++
r) {
 
  826   if (std::abs(
p.pid()) == LAMBDA0) { 
return  (
p.pid() > 0) ? 1 : -1; }
 
  827   if (
isNucleus(
p) && 
p.ndigits() == 10) { 
return (
p.pid() > 0) ? 
p(2) : -
p(2); }
 
  835   if (std::abs(
p.pid()) == PROTON) { 
return  (
p.pid() > 0) ? 1 : -1; }
 
  837     const int result = 
p(5) + 10*
p(4) + 100*
p(3);
 
  848   if (
p.pid() == GRAVITON || std::abs(
p.pid()) == MAVTOP || 
p.pid() == DARKPHOTON) 
return true;
 
  849   if (std::abs(
p.pid()) > 16 && std::abs(
p.pid()) < 19) 
return true;
 
  850   if (std::abs(
p.pid()) > 31 && std::abs(
p.pid()) < 39) 
return true;
 
  851   if (std::abs(
p.pid()) > 39 && std::abs(
p.pid()) < 81) 
return true;
 
  852   if (std::abs(
p.pid()) > 6 && std::abs(
p.pid()) < 9) 
return true;
 
  858   if (
isKK(
p)) 
return true;
 
  861   if (
isDM(
p.pid())) 
return true;
 
  864 template<> 
inline bool isBSM(
const int& 
p){
 
  865   if (
p == GRAVITON || std::abs(
p) == MAVTOP || 
p == DARKPHOTON) 
return true;
 
  866   if (std::abs(
p) > 16 && std::abs(
p) < 19) 
return true;
 
  867   if (std::abs(
p) > 31 && std::abs(
p) < 38) 
return true;
 
  868   if (std::abs(
p) > 39 && std::abs(
p) < 81) 
return true;
 
  869   if (std::abs(
p) > 6 && std::abs(
p) < 9) 
return true;
 
  884 template<> 
inline bool isValid(
const int& 
p){ 
if (!
p) 
return false; 
if (std::abs(
p) < 42) 
return true;
 
  891   if (
isQuark(
p.pid())) { 
return std::abs(
p.pid());}
 
  892   if (
isMeson(
p)) { 
return p.max_digit(1,3);}
 
  898     auto pp = 
p.shift(1);
 
  899     if ( pp.ndigits() == 1 ) { 
return 0; } 
 
  900     if ( pp.ndigits() == 3 ) { pp = 
DecodedPID(pp(1)); } 
 
  901     if ( pp.ndigits()  > 3 ) { pp = pp.shift(1); } 
 
  944   const int pid = std::abs(
p);
 
  945   return ( 
pid == 511   || 
 
  979   const int pid = std::abs(
p);
 
  980   return ( 
pid == 411   || 
 
  997 template<
class T> 
inline double charge( 
const T& 
p){
 
 1008   auto ap = std::abs(
p.pid());
 
 1009   if (
ap < TABLESIZE ) 
return p.pid() > 0 ? triple_charge.at(
ap) : -triple_charge.at(
ap);
 
 1010   if (
ap == K0) 
return 0;
 
 1011   if (
ap == GEANTINO0) 
return 0;
 
 1012   if (
ap == GEANTINOPLUS) 
return p.pid() > 0 ? 3 : -3;
 
 1013   if (
ap == MAVTOP) 
return p.pid() > 0 ? 2 : -2;
 
 1018   bool classified = 
false;
 
 1019   if (!classified && 
isMeson(
p)) { classified = 
true; nq = 2; 
if ((*(
p.second.rbegin()+2)) == 2||(*(
p.second.rbegin()+2)) == 4 ) { 
sign=-1;} signmult =-1; }
 
 1020   if (!classified && 
isDiquark(
p)) {
return triple_charge.at(
p(0))+triple_charge.at(
p(1)); }
 
 1021   if (!classified && 
isBaryon(
p)) { classified = 
true; nq = 3; }
 
 1022   if (!classified && 
isTetraquark(
p)){ 
return triple_charge.at(
p(3)) + triple_charge.at(
p(4)) - triple_charge.at(
p(6)) - triple_charge.at(
p(7)); }
 
 1023   if (!classified && 
isPentaquark(
p)){ 
return triple_charge.at(
p(3)) + triple_charge.at(
p(4)) + triple_charge.at(
p(5)) + triple_charge.at(
p(6)) - triple_charge.at(
p(7)); }
 
 1025   if (!classified && 
isSUSY(
p)) {
 
 1027     auto pp = 
p.shift(1);
 
 1028     if (pp.ndigits() < 3 ) { 
return charge3(pp); } 
 
 1029     if (pp(0) == COMPOSITEGLUON) {
 
 1030       if (pp(1) == COMPOSITEGLUON) { 
return 0; } 
 
 1031       if ( pp.ndigits() == 4 || pp.ndigits() == 5) {
 
 1035     if (pp.ndigits() == 3) { classified = 
true; nq = 2; 
if (
p.last()%2==0) {
sign = -1;} signmult = -1; } 
 
 1036     if (pp.ndigits() == 4) { classified = 
true; nq = 3; } 
 
 1039     auto pp = 
p.shift(2);
 
 1040     if (!classified && 
isMeson(pp)) { classified = 
true; nq = 2; 
if ((*(pp.second.rbegin()+2)) == 2||(*(pp.second.rbegin()+2)) == 4 ) { 
sign=-1;} signmult =-1; }
 
 1041     if (!classified && 
isDiquark(pp)) {
return triple_charge.at(pp(0))+triple_charge.at(pp(1)); }
 
 1042     if (!classified && 
isBaryon(pp)) { classified = 
true; nq = 3; }
 
 1045   if (!classified && 
isKK(
p)) { 
 
 1046     auto pp = 
p.shift(2);
 
 1047     auto ap = std::abs(pp.pid());
 
 1048     if (
ap < TABLESIZE ) 
return pp.pid() > 0 ? triple_charge.at(
ap) : -triple_charge.at(
ap);
 
 1051   if (!classified && 
isDM(
p.pid())) { 
 
 1052     if (
p.ndigits() == 7){ 
 
 1053       auto pp = 
p.shift(3); 
 
 1054       auto ap = std::abs(pp.pid());
 
 1055       if (
ap < TABLESIZE ) 
return pp.pid() > 0 ? triple_charge.at(
ap) : -triple_charge.at(
ap);
 
 1056     }
else if (std::abs(
p.pid()) < TABLESIZE) 
return p.pid() > 0 ? triple_charge.at(
ap) : -triple_charge.at(
ap);  
 
 1062     return ( (
p.pid() > 0 && 
p(2) == 1) ||  (
p.pid() < 0 && 
p(2) == 2) ) ? 
result : -
result;
 
 1065     double abs_charge = 0.0;
 
 1066     if (
p(0) == 1) abs_charge = 
p(3)*100. + 
p(4)*10. + 
p(5)*1 + 
p(6)*0.1; 
 
 1067     if (
p(0) == 2) abs_charge = (
p(3)*10. + 
p(4))/(
p(5)*10.0 + 
p(6)); 
 
 1068     int abs_threecharge = 
static_cast<int>(
std::round(abs_charge * 3.)); 
 
 1069     return p.pid() > 0 ? abs_threecharge : -1 * abs_threecharge;
 
 1071   for (
auto r = 
p.second.rbegin() + 1; 
r != 
p.second.rbegin() + 1 + nq; ++
r) {
 
 1078   int ap = std::abs(
p);
 
 1079   if (
ap < TABLESIZE) 
return p > 0 ? triple_charge.at(
ap):-triple_charge.at(
ap);
 
 1092   double abs_charge = 0;
 
 1093   if (
p(0) == 1) abs_charge = 
p(3)*100. + 
p(4)*10. + 
p(5)*1 + 
p(6)*0.1; 
 
 1094   if (
p(0) == 2) abs_charge = (
p(3)*10. + 
p(4))/(
p(5)*10.0 + 
p(6)); 
 
 1095   return p.pid() > 0 ? abs_charge : -1 * abs_charge;
 
 1110     auto pp = 
p.shift(1);
 
 1111     auto ap = std::abs(pp.pid());
 
 1112     if (
ap < TABLESIZE ) { 
return std::abs(double_spin.at(
ap)-1); } 
 
 1116     auto pp = 
p.shift(2);
 
 1117     if (
isHadron(pp)) { 
return pp.last()-1; } 
 
 1120     auto pp = 
p.shift(2);
 
 1121     auto ap = std::abs(pp.pid());
 
 1122     if (
ap < TABLESIZE ) { 
return double_spin.at(
ap); } 
 
 1124   if (
isDM(std::abs(
p.pid()))) { 
 
 1125     if (
p.ndigits() == 7) { 
 
 1126       auto pp = 
p.shift(3); 
 
 1127       auto ap = std::abs(pp.pid());
 
 1128       if (
ap < TABLESIZE) { 
return double_spin.at(
ap); } 
 
 1129     }
else if (std::abs(
p.pid()) < TABLESIZE) { 
 
 1130       return std::abs(double_spin.at(std::abs(
p.pid())));
 
 1133   auto ap = std::abs(
p.pid());
 
 1134   if (
ap == K0S) { 
return 0; }
 
 1135   if (
ap == K0L) { 
return 0; }
 
 1136   if (
ap == MAVTOP) { 
return 1; } 
 
 1137   if (
ap == DARKPHOTON) { 
return 2; } 
 
 1138   if (
ap < TABLESIZE ) { 
return double_spin.at(
ap); } 
 
 1143   return p.last() > 0 ? 1 : 0; 
 
 1147 template<
class T> 
inline double spin(
const T& 
p) { 
return spin(
p->pdg_id()); }
 
 1156   std::vector<int> quarks;
 
 1157   if (
isQuark(pp.pid())) { quarks.push_back(std::abs(pp.pid())); }
 
 1158   else if (
isDiquark(pp)) { quarks.push_back(pp(0)); quarks.push_back(pp(1)); }
 
 1159   else if (
isMeson(pp)) { quarks.push_back(*(pp.second.rbegin() + 1)); quarks.push_back(*(pp.second.rbegin()+2)); }
 
 1164     const int n_uquarks = 
A + 
Z; 
const int n_dquarks = 2*
A - 
Z - 
L; 
const int n_squarks = 
L;
 
 1165     quarks.reserve(3*
A); quarks.insert(quarks.end(), n_dquarks, 1); quarks.insert(quarks.end(), n_uquarks, 2); quarks.insert(quarks.end(), n_squarks, 3); }
 
 1168     if ( pp.ndigits() > 1 ) { 
 
 1169       if ( pp.ndigits() == 3 ) { pp = 
DecodedPID(pp(1)); } 
 
 1170       if ( pp.ndigits()  > 3 ) { pp = pp.shift(1); }