Version: SMASH-3.4
pdgcode.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2026
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #ifndef SRC_INCLUDE_SMASH_PDGCODE_H_
11 #define SRC_INCLUDE_SMASH_PDGCODE_H_
12 
13 #include <algorithm>
14 #include <array>
15 #include <cassert>
16 #include <cstdint>
17 #include <cstdlib>
18 #include <functional>
19 #include <iomanip>
20 #include <iosfwd>
21 #include <iostream>
22 #include <sstream>
23 #include <stdexcept>
24 #include <string>
25 #include <type_traits>
26 
27 #include "pdgcode_constants.h"
28 
29 namespace smash {
30 
31 /**
32  * \ingroup data
33  *
34  * PdgCode stores a Particle Data Group Particle Numbering Scheme
35  * particle type number.
36  *
37  * \see http://pdg.lbl.gov/2014/reviews/rpp2014-rev-monte-carlo-numbering.pdf
38  *
39  * <h2> Usage: </h2>
40  *
41  * \code
42  * #include "include/pdgcode.h"
43  *
44  * // initialize with an integer: make sure it is hex-encoded!
45  * PdgCode pi_plus(0x211);
46  * // you can also initialize from a string:
47  * PdgCode pi_minus("-211");
48  * // initialize a PDG Code that knows it is not set yet:
49  * PdgCode other_particle();
50  * // this is true:
51  * if (other_particle == PdgCode::invalid()) {
52  * printf("Invalid particle! Please enter PDG Code: ");
53  * // fill from stringstream:
54  * std::cin >> other_particle;
55  * }
56  * // is this a Kaon?
57  * if (other_particle.code() == 0x311) {
58  * printf("The particle is a K plus\n");
59  * }
60  * // what baryon number does the particle have?
61  * printf("The particle has a baryon number of %d\n",
62  * other_particle.baryon_number());
63  * \endcode
64  *
65  * This class contains a collection of smart accessors to the PDG code
66  * so that quantum numbers etc can easily be read off.
67  *
68  * <h2> Internals </h2>
69  *
70  * The content is stored in hexadecimal digits, i.e., the number '545'
71  * is interpreted as '0x221', i.e., an eta-meson. To check if a given
72  * particle is of a given type, make sure that you give the type in hex
73  * digits as well (see example above).
74  *
75  * The reason for that is that the concept of PdgCodes, especially for
76  * Hadrons, is not one of wholesale numbers, but one of concatenated
77  * digits. Using hexadecimally interpreted digits makes it numerically
78  * very easy to access the separate digits (there's no arithmetic
79  * involved with successive divisions by 10 and taking the remainder
80  * etc.).
81  *
82  * <h2> Representing nuclei </h2>
83  *
84  * Following PDG standard, nuclei are represented by codes ±10LZZZAAAI, where
85  * L is number of Lambdas inside the nucleus, ZZZ is charge, AAA is mass
86  * number and I is used for excitations. Internally nuclei are represented
87  * in a different way from hadrons, but all accessors (charge, baryon number,
88  * etc) work in the same way.
89  *
90  * Normally nuclei in SMASH are simulated as a collection of protons and
91  * neutrons, so there is no need in their PDG codes. However, it is
92  * interesting to study light nuclei production, considering them as single
93  * pointlike hadrons. This justifies introduction of nuclear PDG codes here.
94  *
95  * <h2> Limitations: </h2>
96  *
97  * The code is tuned to non-colored objects at the moment. That means
98  * that colored objects (Diquarks and Quarks) are not easily useable
99  * with this class; the behaviour of functions baryon_number, charge,
100  * is_hadron etc. is undefined. (This is mostly because these things are
101  * not well-defined, and/or because the charge and baryon number is not
102  * an integer anymore.)
103  *
104  * Also, tetra- and pentaquarks cannot be represented; that, though,
105  * is a problem of the PDG Numbering Scheme rather than of this class.
106  */
107 
108 class PdgCode {
109  public:
110  /**
111  * \ingroup exception
112  * thrown for invalid inputs
113  */
114  struct InvalidPdgCode : public std::invalid_argument {
115  using std::invalid_argument::invalid_argument;
116  };
117 
118  /****************************************************************************
119  * *
120  * First, the constructors *
121  * *
122  ****************************************************************************/
123 
124  /// Standard initializer
125  PdgCode() : dump_(0x0) {}
126  /**
127  * Initialize using a string
128  * The string is interpreted as a hexadecimal number, i.e., \c 211 is
129  * interpreted as \c 0x211 = \f$529_{10}\f$.
130  */
131  explicit PdgCode(const std::string& codestring) {
132  set_from_string(codestring);
133  }
134 
135  /**
136  * Receive a signed integer and process it into a PDG Code. The sign
137  * is taken as antiparticle boolean, while the absolute value of the
138  * integer is used as hexdigits.
139  * \param[in] codenumber a signed integer which represent the PDG code
140  * The number 0x221 is interpreted as an η meson,
141  * -0x211 is a "charged pi antiparticle", i.e., a \f$\pi^-\f$.
142  */
143  PdgCode(std::int32_t codenumber) : dump_(0x0) { // NOLINT(runtime/explicit)
144  digits_.antiparticle_ = false;
145  if (codenumber < 0) {
146  digits_.antiparticle_ = true;
147  codenumber = -codenumber;
148  }
149  set_fields(codenumber);
150  }
151  /**
152  * Receive an unsigned integer and process it into a PDG Code. The
153  * first bit is taken and used as antiparticle boolean.
154  */
155  explicit PdgCode(const std::uint32_t abscode) : dump_(0x0) {
156  // use the first bit for the antiparticle_ boolean.
157  digits_.antiparticle_ = ((abscode & 0x80000000u) != 0);
158  set_fields(abscode);
159  }
160 
161  /**
162  * The creation of \c PdgCode instances for nuclei that have a 10-digits code
163  * cannot be done using the integer constructors above, since a 10-digits
164  * hexadecimal number like 0x1000020030 exceeds the int32_t capacity. Nuclei
165  * instances can in principle either be created with the string constructor or
166  * via the \c PdgCode::from_decimal() static member, but offering a uniform
167  * interface for all cases is definitely user-friendly.
168  *
169  * Since the string constructor works, we delegate here the construction to
170  * it. In order to execute the needed code to built the string in the member
171  * initializer list, we use a common lambda idiom (IIFE) that consists in
172  * immediately invoking a lambda function. Using \c std::invoke makes it more
173  * explicit than using \c () after the lambda braces.
174  *
175  * \note
176  * One might wonder why a function template has been used instead of e.g.
177  * adding a constructor taking a \c int64_t argument. The reason is to
178  * facilitate the class usage. Having a fixed type would have required the
179  * users of this class to \b exactly match the argument type (and for
180  * \c int64_t there is no standard literal suffix), otherwise the call would
181  * have been ambiguous and compilation would have failed. Said differently, we
182  * would like
183  * \code
184  * PdgCode deuteron(0x1000010020);
185  * \endcode
186  * to work and not oblige the user to write
187  * \code
188  * PdgCode deuteron(INT64_C(0x1000010020));
189  * \endcode
190  * just because the constructor takes an \c int64_t number.
191  * The idea here is to offer a better matching to the compiler when the
192  * constructor is called with an integer type with size larger than 4 bytes.
193  * Type-traits are used to limit the template instantiation to reasonable
194  * cases, only.
195  *
196  * \warning
197  * In C++, it is more common to enable constructors template via a non-type
198  * template parameter, i.e.
199  * \code
200  * template <typename T,
201  * template <typename T,
202  * typename std::enable_if_t<
203  * std::is_integral_v<T> && 4 < sizeof(T), bool
204  * > = true>
205  * PdgCode(T codenumber) // ...
206  * \endcode
207  * but this breaks Doxygen documentation, because apparently multiple "nested"
208  * template parameters are not able to be correctly handled (possibly because
209  * of the additional less-than symbol). This limitation has been detected
210  * using Doxygen 1.9.X and might be solved in future versions.
211  *
212  * \param[in] codenumber The hexadecimal PDG code
213  * \tparam T The type of the PDG code, irrelevant for the user
214  * and deduced by the compiler
215  */
216  template <typename T>
217  PdgCode(T codenumber, // NOLINT(runtime/explicit)
218  typename std::enable_if_t<std::is_integral_v<T> && 4 < sizeof(T),
219  bool> = true)
220  : PdgCode{std::invoke([&codenumber]() {
221  std::stringstream stream;
222  char sign = '+';
223  if (codenumber < 0) {
224  sign = '-';
225  codenumber = -codenumber;
226  }
227  stream << sign << std::hex << codenumber;
228  return stream.str();
229  })} {}
230 
231  /****************************************************************************
232  * *
233  * test function and export functions *
234  * *
235  ****************************************************************************/
236 
237  /**
238  * Checks the integer for invalid hex digits.
239  *
240  * Usually all digits are at least <= 9. The n_q digits are even <= 6
241  * (because there are only six quarks). The only exception is n_J, where
242  * we allow f = 15, which is the largest hexadecimal digit.
243  * If one of the hex digits is not also a valid decimal digit,
244  * something possibly went wrong - maybe some user of this class forgot
245  * to prefix the input with '0x' and thus passed 221 instead of 0x221.
246  * \return a bitmask indicating the offending digits. In the above
247  * example, 221 = 0xd3, the second-to-last-digit is the offending one,
248  * to the return value is 0b10 = 0x2 = 2.
249  */
250  inline int test_code() const {
251  int fail = 0;
252  if (digits_.n_ > 9) {
253  fail |= 1 << 6;
254  }
255  if (digits_.n_R_ > 9) {
256  fail |= 1 << 5;
257  }
258  if (digits_.n_L_ > 9) {
259  fail |= 1 << 4;
260  }
261  if (digits_.n_q1_ > 6) {
262  fail |= 1 << 3;
263  }
264  if (digits_.n_q2_ > 6) {
265  fail |= 1 << 2;
266  }
267  if (digits_.n_q3_ > 6) {
268  fail |= 1 << 1;
269  }
270  if (digits_.n_J_ > 15) {
271  fail |= 1;
272  }
273  return fail;
274  }
275 
276  /**
277  * Do all sorts of validity checks.
278  * \throw InvalidPdgCode if meson has even n_J_ (fermionic spin)
279  * \throw InvalidPdgCode if baryon has odd n_J_ (bosonic spin)
280  * \throw InvalidPdgCode if n_J_ is 0 (spin is not defined.)
281  * \throw InvalidPdgCode if particle does not have antiparticle when
282  * it is supposed to do.
283  */
284  void check() const {
285  // n_J must be odd for mesons and even for baryons (and cannot be zero)
286  if (is_hadron()) {
287  if (baryon_number() == 0) {
288  // mesons: special cases K0_L=0x130 and K0_S=0x310
289  if ((digits_.n_J_ % 2 == 0) && dump() != 0x130 && dump() != 0x310) {
290  throw InvalidPdgCode("Invalid PDG code " + string() +
291  " (meson with even n_J)");
292  }
293  } else {
294  if ((digits_.n_J_ % 2 != 0) || digits_.n_J_ == 0) {
295  throw InvalidPdgCode("Invalid PDG code " + string() +
296  " (baryon with odd n_J)");
297  }
298  }
299  } else {
300  if (digits_.n_J_ == 0 && dump() != 0x0) {
301  throw InvalidPdgCode("Invalid PDG code " + string() + " (n_J==0)");
302  }
303  }
304  /* The antiparticle flag only makes sense for particle types
305  * that have an antiparticle. */
306  if (digits_.antiparticle_ && !has_antiparticle()) {
307  throw InvalidPdgCode("Invalid PDG code " + string() +
308  " (cannot be negative)");
309  }
310  }
311 
312  /// Dumps the bitfield into an unsigned integer.
313  inline std::uint32_t dump() const {
314  // this cuts the three unused bits.
315  return (dump_ & 0x8fffffff);
316  }
317 
318  /// \return a signed integer with the PDG code in hexadecimal.
319  inline std::int32_t code() const { return antiparticle_sign() * ucode(); }
320 
321  /// \return the PDG Code as a decimal string.
322  inline std::string string() const {
323  std::stringstream ss;
324  ss << get_decimal();
325  return ss.str();
326  }
327 
328  /// Construct the antiparticle to a given PDG code.
330  PdgCode result = *this;
331  result.digits_.antiparticle_ = !digits_.antiparticle_;
332  return result;
333  }
334 
335  /**
336  * Construct PDG code from decimal number.
337  * \param[in] pdgcode_decimal decimal integer representing the PDG code
338  */
339  static PdgCode from_decimal(const int pdgcode_decimal) {
340  // Nucleus and special codes with 2J+1 > 9
341  if (std::abs(pdgcode_decimal) > 1E7) {
342  return PdgCode(std::to_string(pdgcode_decimal));
343  }
344  int a = pdgcode_decimal;
345  int hex_pdg = 0, tmp = 1;
346  while (a) {
347  hex_pdg += (a % 10) * tmp;
348  tmp *= 16;
349  a = a / 10;
350  }
351  return PdgCode(hex_pdg);
352  }
353 
354  /****************************************************************************
355  * *
356  * accessors of various properties *
357  * *
358  ****************************************************************************/
359 
360  /// \return true if this is a nucleus, false otherwise
361  inline bool is_nucleus() const {
362  assert(digits_.is_nucleus_ == nucleus_.is_nucleus_);
363  return nucleus_.is_nucleus_;
364  }
365 
366  /// \return true if this is a baryon, antibaryon or meson.
367  inline bool is_hadron() const {
368  return (digits_.n_q3_ != 0 && digits_.n_q2_ != 0 && !is_nucleus());
369  }
370 
371  /// \return true if this is a lepton.
372  inline bool is_lepton() const {
373  return (digits_.n_q1_ == 0 && digits_.n_q2_ == 0 && digits_.n_q3_ == 1 &&
374  !is_nucleus());
375  }
376 
377  /// \return true if this is a neutrino.
378  inline bool is_neutrino() const {
379  return (is_lepton() && digits_.n_J_ % 2 == 0);
380  }
381 
382  /// \return whether this is a charmonia
383  inline bool is_charmonia() const {
384  return is_meson() && digits_.n_q2_ == 4 && digits_.n_q3_ == 4;
385  }
386 
387  /// \return the baryon number of the particle.
388  inline int baryon_number() const {
389  if (is_nucleus()) {
390  return static_cast<int>(nucleus_.A_) * antiparticle_sign();
391  }
392  if (!is_hadron() || digits_.n_q1_ == 0) {
393  return 0;
394  }
395  return antiparticle_sign();
396  }
397  /// \return whether this PDG code identifies a baryon.
398  inline bool is_baryon() const { return is_hadron() && digits_.n_q1_ != 0; }
399 
400  /// \return whether this PDG code identifies a meson.
401  inline bool is_meson() const { return is_hadron() && digits_.n_q1_ == 0; }
402 
403  /// \return whether this is a nucleon/anti-nucleon (p, n, -p, -n)
404  inline bool is_nucleon() const {
405  const auto abs_code = std::abs(code());
406  return (abs_code == pdg::p || abs_code == pdg::n);
407  }
408 
409  /// \return whether this is a proton/anti-proton
410  inline bool is_proton() const {
411  const auto abs_code = std::abs(code());
412  return (abs_code == pdg::p);
413  }
414 
415  /// \return whether this is a neutron/anti-neutron
416  inline bool is_neutron() const {
417  const auto abs_code = std::abs(code());
418  return (abs_code == pdg::n);
419  }
420 
421  /// \return whether this is a N*(1535) (+/0)
422  inline bool is_Nstar1535() const {
423  const auto abs_code = std::abs(code());
424  return (abs_code == pdg::N1535_p || abs_code == pdg::N1535_z);
425  }
426 
427  /// \return whether this is a Delta(1232) (with anti-delta)
428  inline bool is_Delta() const {
429  const auto abs_code = std::abs(code());
430  return (abs_code == pdg::Delta_pp || abs_code == pdg::Delta_p ||
431  abs_code == pdg::Delta_z || abs_code == pdg::Delta_m);
432  }
433 
434  /// \return whether this is a hyperon (Lambda, Sigma, Xi, Omega)
435  inline bool is_hyperon() const { return is_hadron() && digits_.n_q1_ == 3; }
436 
437  /// \return whether this is a Omega baryon
438  inline bool is_Omega() const {
439  return is_hyperon() && digits_.n_q2_ == 3 && digits_.n_q3_ == 3;
440  }
441 
442  /// \return whether this is a Xi baryon
443  inline bool is_Xi() const {
444  return is_hyperon() && digits_.n_q2_ == 3 && digits_.n_q3_ != 3;
445  }
446 
447  /// \return whether this is a Lambda baryon
448  inline bool is_Lambda() const {
449  return is_hyperon() && digits_.n_q2_ == 1 && digits_.n_q3_ == 2;
450  }
451 
452  /// \return whether this is a Sigma baryon
453  inline bool is_Sigma() const {
454  return is_hyperon() && digits_.n_q2_ != 3 && !is_Lambda();
455  }
456 
457  /// \return whether this is a Sigma* with pdgcodes 3224, 3214, 3114
458  inline bool is_Sigmastar() const {
459  const auto abs_code = std::abs(code());
460  return (abs_code == pdg::Sigma_star_m || abs_code == pdg::Sigma_star_z ||
461  abs_code == pdg::Sigma_star_p);
462  }
463 
464  /// \return whether this is a kaon (K+, K-, K0, Kbar0)
465  inline bool is_kaon() const {
466  const auto abs_code = std::abs(code());
467  return (abs_code == pdg::K_p) || (abs_code == pdg::K_z);
468  }
469 
470  /// \return whether this is a pion (pi+/pi0/pi-)
471  inline bool is_pion() const {
472  const auto c = code();
473  return (c == pdg::pi_z) || (c == pdg::pi_p) || (c == pdg::pi_m);
474  }
475 
476  /// \return whether this is an eta meson
477  inline bool is_eta() const { return code() == pdg::eta; }
478 
479  /// \return whether this is an omega meson
480  inline bool is_omega() const { return code() == pdg::omega; }
481 
482  /// \return whether this is a rho meson (rho+/rho0/rho-)
483  inline bool is_rho() const {
484  const auto c = code();
485  return (c == pdg::rho_z) || (c == pdg::rho_p) || (c == pdg::rho_m);
486  }
487 
488  /// \return whether this is a D meson (D+, D-, D0, Dbar0)
489  inline bool is_Dmeson() const {
490  const auto abs_code = std::abs(code());
491  return (abs_code == pdg::D_p) || (abs_code == pdg::D_z);
492  }
493 
494  /**
495  * \return whether this is a D* meson
496  * (D*(2010)⁺, D*(2010)⁻, D*(2007)⁰, D̄*(2007)⁰)
497  */
498  inline bool is_Dstar2007() const {
499  const auto abs_code = std::abs(code());
500  return (abs_code == pdg::Dstar_p) || (abs_code == pdg::Dstar_z);
501  }
502 
503  /// \return whether this is (anti-)deuteron
504  inline bool is_deuteron() const {
505  return is_nucleus() && nucleus_.A_ == 2 && nucleus_.Z_ == 1 &&
506  nucleus_.n_Lambda_ == 0 && nucleus_.I_ == 0;
507  }
508 
509  /// \return whether this is (anti-)triton
510  inline bool is_triton() const {
511  return is_nucleus() && nucleus_.A_ == 3 && nucleus_.Z_ == 1 &&
512  nucleus_.n_Lambda_ == 0 && nucleus_.I_ == 0;
513  }
514 
515  /**
516  * \return whether a particle has a distinct antiparticle
517  * (or whether it is its own antiparticle).
518  */
519  bool has_antiparticle() const {
520  if (is_nucleus()) {
521  return true;
522  }
523  if (is_hadron()) {
524  return (baryon_number() != 0) || (digits_.n_q2_ != digits_.n_q3_);
525  } else {
526  return digits_.n_q3_ == 1; // leptons!
527  }
528  }
529 
530  /**
531  * \return twice the isospin-3 component \f$I_3\f$.
532  *
533  * This is calculated from the sum of net_quark_number of up and down.
534  */
535  inline int isospin3() const {
536  /* net_quark_number(2) is the number of u quarks,
537  * net_quark_number(1) is the number of d quarks. */
538  return net_quark_number(2) - net_quark_number(1);
539  }
540 
541  /**
542  * \return the fraction number of strange quarks
543  * (strange + anti-strange) / total
544  *
545  * This is useful for the AQM cross-section scaling, and needs to
546  * be positive definite.
547  */
548  inline double frac_strange() const {
549  if (is_baryon()) {
550  return std::abs(strangeness()) / 3.;
551  } else if (is_meson()) {
552  /* The quarkonium state has 0 net strangeness
553  * but there are actually 2 strange quarks out of 2 total */
554  if (digits_.n_q3_ == 3 && digits_.n_q2_ == 3) {
555  return 1.;
556  } else {
557  return std::abs(strangeness()) / 2.;
558  }
559  } else {
560  /* If not baryon or meson, this should be 0, as AQM does not
561  * extend to non-hadrons */
562  return 0.;
563  }
564  }
565 
566  /**
567  * \return the fraction number of charm quarks
568  * (charm + anti-charm) / total
569  *
570  * This is useful for the AQM cross-section scaling, and needs to
571  * be positive definite.
572  */
573  inline double frac_charm() const {
574  if (is_baryon()) {
575  return std::abs(charmness()) / 3.;
576  } else if (is_meson()) {
577  /* The charmonium state has 0 net charmness
578  * but there are actually 2 charm quarks out of 2 total */
579  if (digits_.n_q3_ == 4 && digits_.n_q2_ == 4) {
580  return 1.;
581  } else {
582  return std::abs(charmness()) / 2.;
583  }
584  } else {
585  /* If not baryon or meson, this should be 0, as AQM does not
586  * extend to non-hadrons */
587  return 0.;
588  }
589  }
590 
591  /**
592  * \return the fraction number of bottom quarks
593  * (bottom + anti-bottom) / total
594  *
595  * This is useful for the AQM cross-section scaling, and needs to
596  * be positive definite.
597  */
598  inline double frac_bottom() const {
599  if (is_baryon()) {
600  return std::abs(bottomness()) / 3.;
601  } else if (is_meson()) {
602  /* The bottomonium state has 0 net bottomness
603  * but there are actually 2 bottom quarks out of 2 total */
604  if (digits_.n_q3_ == 5 && digits_.n_q2_ == 5) {
605  return 1.;
606  } else {
607  return std::abs(bottomness()) / 2.;
608  }
609  } else {
610  /* If not baryon or meson, this should be 0, as AQM does not
611  * extend to non-hadrons */
612  return 0.;
613  }
614  }
615 
616  /// \return whether the hadron contains a charm or bottom quark
617  inline bool is_heavy_flavor() const {
618  return (frac_charm() != 0) || (frac_bottom() != 0);
619  }
620 
621  /**
622  * \return the net number of \f$\bar s\f$ quarks.
623  *
624  * For particles with one strange quark, -1 is returned.
625  */
626  inline int strangeness() const { return -net_quark_number(3); }
627 
628  /**
629  * \return the net number of \f$c\f$ quarks
630  *
631  * For particles with one charm quark, +1 is returned.
632  */
633  inline int charmness() const { return +net_quark_number(4); }
634 
635  /**
636  * \return the net number of \f$\bar b\f$ quarks
637  *
638  * For particles with one bottom quark, -1 is returned.
639  */
640  inline int bottomness() const { return -net_quark_number(5); }
641 
642  /**
643  * The charge of the particle.
644  * The charge is calculated from the quark content (for hadrons) or
645  * basically tabulated; currently leptons, neutrinos and the standard
646  * model gauge bosons are known; unknown particles return a charge of
647  * 0.
648  * \return charge of the particle
649  */
650  int charge() const {
651  if (is_hadron() || is_nucleus()) {
652  // Q will accumulate 3*charge (please excuse the upper case. I
653  // want to distinguish this from q which might be interpreted as
654  // shorthand for "quark".)
655  int Q = 0;
656  /* This loops over d,u,s,c,b,t quarks (the latter can be safely ignored,
657  * but I don't think this will be a bottle neck. */
658  for (int i = 1; i < 7; i++) {
659  /* u,c,t quarks have charge = 2/3 e, while d,s,b quarks have -1/3 e.
660  * The antiparticle sign is already in net_quark_number. */
661  Q += (i % 2 == 0 ? 2 : -1) * net_quark_number(i);
662  }
663  return Q / 3;
664  }
665  /* non-hadron:
666  * Leptons: 11, 13, 15 are e, μ, τ and have a charge -1, while
667  * 12, 14, 16 are the neutrinos that have no charge. */
668  if (digits_.n_q3_ == 1) {
669  return -1 * (digits_.n_J_ % 2) * antiparticle_sign();
670  }
671  /* Bosons: 24 is the W+, all else is uncharged.
672  * we ignore the first digits so that this also finds strange gauge
673  * boson "resonances" (in particular, \f$\tilde \chi_1^+\f$ with PDG
674  * Code 1000024). */
675  if ((dump_ & 0x0000ffff) == 0x24) {
676  return antiparticle_sign();
677  }
678  // default (this includes all other Bosons) is 0.
679  return 0;
680  }
681 
682  /**
683  * \return twice the spin of a particle.
684  *
685  * The code is good for hadrons, leptons and spin-1-bosons. It returns
686  * 2 (meaning spin=1) for the Higgs, though.
687  *
688  * \throw runtime_error if a spin of a nucleus is not coded in
689  * and has to be guessed
690  */
691  inline unsigned int spin() const {
692  if (is_nucleus()) {
693  // Generally spin of a nucleus cannot be simply guessed, it should be
694  // provided from some table. However, here we only care about a
695  // limited set of light nuclei with A <= 4.
696  if (nucleus_.A_ == 2) {
697  // Deuteron spin is 1
698  return 2;
699  } else if (nucleus_.A_ == 3) {
700  // Tritium and He-3 spin are 1/2
701  // Hypertriton spin is not firmly determined, but decay branching ratios
702  // indicate spin 1/2
703  return 1;
704  } else if (nucleus_.A_ == 4) {
705  // He-4 spin is 0
706  return 0;
707  }
708  throw std::runtime_error("Unknown spin of nucleus.");
709  // Alternative possibility is to guess 1/2 for fermions and 0 for bosons
710  // as 2 * (nucleus_.A_ % 2).
711  }
712 
713  if (is_hadron()) {
714  if (digits_.n_J_ == 0) {
715  return 0; // special cases: K0_L=0x130 & K0_S=0x310
716  } else {
717  return digits_.n_J_ - 1;
718  }
719  }
720  /* this assumes that we only have white particles (no single
721  * quarks): Electroweak fermions have 11-17, so the
722  * second-to-last-digit is the spin. The same for the Bosons: they
723  * have 21-29 and 2spin = 2 (this fails for the Higgs). */
724  return digits_.n_q3_;
725  }
726  /// \return the spin degeneracy \f$2s + 1\f$ of a particle.
727  inline unsigned int spin_degeneracy() const {
728  if (is_hadron() && digits_.n_J_ > 0) {
729  return digits_.n_J_;
730  }
731  return spin() + 1;
732  }
733  /// \return -1 for antiparticles and +1 for particles.
734  inline int antiparticle_sign() const {
735  return (digits_.antiparticle_ ? -1 : +1);
736  }
737  /// \return an integer with only the quark numbers set.
738  inline std::int32_t quarks() const {
739  if (!is_hadron() || is_nucleus()) {
740  return 0;
741  }
742  return chunks_.quarks_;
743  }
744 
745  /**
746  * The return is always an array of three numbers, which are pdgcodes
747  * of quarks: 1 - d, 2 - u, 3 - s, 4 - c, 5 - b. Antiquarks get a negative
748  * sign. For mesons the first number in array is always 0.
749  * There is a difficulty with mesons that are a superposition, for example
750  * \f$ \pi^0 = \frac{1}{\sqrt{2}}(u \bar{u} + d \bar{d}) \f$. Currently for
751  * \f$ \pi^0 \f$ just {0, 1, -1} is returned.
752  * \return quark content as an array.
753  */
754  std::array<int, 3> quark_content() const {
755  std::array<int, 3> result = {static_cast<int>(digits_.n_q1_),
756  static_cast<int>(digits_.n_q2_),
757  static_cast<int>(digits_.n_q3_)};
758  if (is_hadron()) {
759  // Antibaryons
760  if (digits_.n_q1_ != 0 && digits_.antiparticle_) {
761  for (size_t i = 0; i < 3; i++) {
762  result[i] = -result[i];
763  }
764  }
765  // Mesons
766  if (digits_.n_q1_ == 0) {
767  // Own antiparticle
768  if (digits_.n_q2_ == digits_.n_q3_) {
769  result[2] = -result[2];
770  } else {
771  // Like pi-
772  if (digits_.antiparticle_) {
773  result[1] = -result[1];
774  // Like pi+
775  } else {
776  result[2] = -result[2];
777  }
778  }
779  // add extra minus sign according to the pdg convention
780  if (digits_.n_q2_ != digits_.n_q3_ && digits_.n_q2_ % 2 == 1) {
781  for (int i = 1; i <= 2; i++) {
782  result[i] = -result[i];
783  }
784  }
785  }
786  } else {
787  result = {0, 0, 0};
788  }
789  return result;
790  }
791 
792  /**
793  * \return whether a particle contains at least the given number of
794  * valence quarks.
795  * \param[in] valence_quarks_required number of valence quarks
796  * that particle is supposed to contain.
797  *
798  * \throw std::runtime_error if it is not a hadron
799  *
800  * This is necessary for string fragmentation.
801  */
802  bool contains_enough_valence_quarks(int valence_quarks_required) const;
803 
804  /****************************************************************************
805  * *
806  * operations with more than one PDG Code *
807  * *
808  ****************************************************************************/
809 
810  /**
811  * Sorts PDG Codes according to their numeric value.
812  * This is used by std::map
813  */
814  inline bool operator<(const PdgCode rhs) const {
815  return dump_ < rhs.dump_;
816  /* the complex thing to do here is to calculate:
817  * code() < rhs.code()
818  * but for getting a total order that's overkill. The uint32_t value in
819  * dump_ works just fine. */
820  }
821 
822  /// \return if the codes are equal
823  inline bool operator==(const PdgCode rhs) const { return dump_ == rhs.dump_; }
824 
825  /// \return if the codes are not equal.
826  inline bool operator!=(const PdgCode rhs) const { return !(*this == rhs); }
827 
828  /// \return if the code of rhs is the inverse of this one.
829  inline bool is_antiparticle_of(const PdgCode rhs) const {
830  return code() == -rhs.code();
831  }
832 
833  /// istream >> PdgCode assigns the PDG Code from an istream.
834  friend std::istream& operator>>(std::istream& is, PdgCode& code);
835 
836  /**
837  * PdgCode 0x0 is guaranteed not to be valid by the PDG standard, but
838  * it passes all tests here, so we can use it to show some code is not
839  * yet set.
840  */
841  static PdgCode invalid() { return PdgCode(0x0); }
842 
843  /**
844  * \return an integer with decimal representation of the code.
845  * If the spin is too large for the last digit, an additional digit at the
846  * beginning will be used, so that the sum of the first and the last digit is
847  * the spin.
848  * This is used for binary and ROOT output.
849  *
850  * \throw InvalidPdgCode if the spin degeneracy is larger than 9
851  */
852  int32_t get_decimal() const {
853  if (is_nucleus()) {
854  // ±10LZZZAAAI
855  return antiparticle_sign() *
856  (nucleus_.I_ + 10 * nucleus_.A_ + 10000 * nucleus_.Z_ +
857  10000000 * nucleus_.n_Lambda_ + 1000000000);
858  }
859  int n_J_1 = 0;
860  int n_J_2 = digits_.n_J_;
861  if (n_J_2 > 9) {
862  n_J_1 = n_J_2 - 9;
863  n_J_2 = 9;
864  }
865  return antiparticle_sign() *
866  (n_J_2 + digits_.n_q3_ * 10 + digits_.n_q2_ * 100 +
867  digits_.n_q1_ * 1000 + digits_.n_L_ * 10000 +
868  digits_.n_R_ * 100000 + digits_.n_ * 1000000 + n_J_1 * 10000000);
869  }
870 
871  /// Remove all excitation, except spin. Sign and quark content remains.
872  void deexcite() {
873  if (!is_nucleus()) {
874  chunks_.excitation_ = 0;
875  } else {
876  nucleus_.I_ = 0;
877  }
878  }
879 
880  /**
881  * Checks whether this hadron contains a quark (or antiquark) of a given
882  * flavour.
883  *
884  * The check is true if:
885  * - the particle is a hadron, and
886  * - the hadron contains at least one quark or antiquark of the specified
887  * flavour.
888  *
889  * For flavour-neutral mesons (e.g. π⁰, η, φ, J/ψ, ϒ), this returns true
890  * because such states contain a quark–antiquark pair of that flavour, even
891  * though the net flavour is zero.
892  *
893  * For baryons, only the net (valence) quark content is considered.
894  *
895  * \param[in] quark Signed PDG quark code.
896  *
897  * \return true if the hadron contains at least one quark (or antiquark)
898  * of the requested flavour with the requested sign; false otherwise.
899  */
900  bool contains_quark(int quark) const;
901 
902  /**
903  * Returns the net number of quarks with given flavour number
904  * For public use, see strangeness(), charmness(), bottomness() and
905  * isospin3().
906  * \param[in] quark PDG Code of quark: (1..6) = (d,u,s,c,b,t)
907  * \return for the net number of quarks (\#quarks - \#antiquarks)
908  *
909  * \throw std::invalid_argument
910  * if quark is not any of d, u, s, c, b and t quarks
911  */
912  int net_quark_number(const int quark) const;
913 
914  /// Number of protons in nucleus
915  int nucleus_p() const {
916  return (is_nucleus() && !nucleus_.antiparticle_) ? nucleus_.Z_ : 0;
917  }
918  /// Number of neutrons in nucleus
919  int nucleus_n() const {
920  return (is_nucleus() && !nucleus_.antiparticle_)
921  ? nucleus_.A_ - nucleus_.Z_ - nucleus_.n_Lambda_
922  : 0;
923  }
924  /// Number of Lambdas in nucleus
925  int nucleus_La() const {
926  return (is_nucleus() && !nucleus_.antiparticle_) ? nucleus_.n_Lambda_ : 0;
927  }
928  /// Number of antiprotons in nucleus
929  int nucleus_ap() const {
930  return (is_nucleus() && nucleus_.antiparticle_) ? nucleus_.Z_ : 0;
931  }
932  /// Number of antineutrons in nucleus
933  int nucleus_an() const {
934  return (is_nucleus() && nucleus_.antiparticle_)
935  ? nucleus_.A_ - nucleus_.Z_ - nucleus_.n_Lambda_
936  : 0;
937  }
938  /// Number of anti-Lambdas in nucleus
939  int nucleus_aLa() const {
940  return (is_nucleus() && nucleus_.antiparticle_) ? nucleus_.n_Lambda_ : 0;
941  }
942  /// Nucleus mass number
943  int nucleus_A() const { return is_nucleus() ? nucleus_.A_ : 0; }
944 
945  private:
946  /**
947  * The union holds the data; either as a single integer dump_, as a
948  * single-digit bitfield digits_ or as a multiple-digits bitfield
949  * chunks_.
950  */
951  union {
952  /**
953  * The single digits collection of the code. Here, every PDG code
954  * digits is directly accessible.
955  */
956  struct {
957 #if defined(LITTLE_ENDIAN_ARCHITECTURE) || defined(DOXYGEN)
958  /// spin quantum number \f$n_J = 2 J + 1\f$.
959  std::uint32_t n_J_ : 4;
960  /// third quark field
961  std::uint32_t n_q3_ : 4;
962  /// second quark field
963  std::uint32_t n_q2_ : 4;
964  /// first quark field. 0 for mesons.
965  std::uint32_t n_q1_ : 4;
966  /// "angular momentum"
967  std::uint32_t n_L_ : 4;
968  /// "radial excitation"
969  std::uint32_t n_R_ : 4;
970  /// first field: "counter"
971  std::uint32_t n_ : 4, : 2;
972  /// 1 for nuclei, 0 for the rest
973  bool is_nucleus_ : 1;
974  /// first bit: stores the sign.
975  bool antiparticle_ : 1;
976 #elif defined(BIG_ENDIAN_ARCHITECTURE) // reverse ordering
977  bool antiparticle_ : 1;
978  bool is_nucleus_ : 1, : 2;
979  std::uint32_t n_ : 4;
980  std::uint32_t n_R_ : 4;
981  std::uint32_t n_L_ : 4;
982  std::uint32_t n_q1_ : 4;
983  std::uint32_t n_q2_ : 4;
984  std::uint32_t n_q3_ : 4;
985  std::uint32_t n_J_ : 4;
986 #else
987 #error Endianness macro of the machine not defined.
988 #endif
989  } digits_;
990  /**
991  * The bitfield dumped into a single integer. Please note that the
992  * 2nd, 3rd and 4th highest bits are possibly undefined.
993  */
994  std::uint32_t dump_;
995  /**
996  * Chunk collection: here, the chunks with \f$nn_Rn_L\f$ and
997  * \f$n_{q_1}n_{q_2}n_{q_3}\f$ are directly accessible.
998  */
999  struct {
1000 #if defined(LITTLE_ENDIAN_ARCHITECTURE) || defined(DOXYGEN)
1001  std::uint32_t : 4;
1002  /// The quark digits n_q{1,2,3}_
1003  std::uint32_t quarks_ : 12;
1004  /// The excitation digits n_, n_R_, n_L_
1005  std::uint32_t excitation_ : 12, : 4;
1006 #elif defined(BIG_ENDIAN_ARCHITECTURE) // reverse ordering
1007  std::uint32_t : 4, excitation_ : 12;
1008  std::uint32_t quarks_ : 12, : 4;
1009 #else
1010 #error Endianness macro of the machine not defined.
1011 #endif
1012  } chunks_;
1013  /// Structure for the nuclei
1014  struct {
1015 #if defined(LITTLE_ENDIAN_ARCHITECTURE) || defined(DOXYGEN)
1016  std::uint32_t n_Lambda_ : 6;
1017  std::uint32_t Z_ : 10;
1018  std::uint32_t A_ : 10;
1019  std::uint32_t I_ : 4;
1020  bool is_nucleus_ : 1;
1021  bool antiparticle_ : 1;
1022 #elif defined(BIG_ENDIAN_ARCHITECTURE) // reverse ordering
1023  bool antiparticle_ : 1;
1024  bool is_nucleus_ : 1;
1025  std::uint32_t I_ : 4;
1026  std::uint32_t A_ : 10;
1027  std::uint32_t Z_ : 10;
1028  std::uint32_t n_Lambda_ : 6;
1029 #else
1030 #error Endianness macro of the machine not defined.
1031 #endif
1032  } nucleus_;
1033  };
1034 
1035  /**
1036  * \return an unsigned integer with the PDG code in hexadecimal
1037  * (disregarding the antiparticle flag).
1038  */
1039  inline std::uint32_t ucode() const { return (dump_ & 0x0fffffff); }
1040 
1041  /**
1042  * \return digits from a hexadecimal character.
1043  * \param[in] inp character which is translated into digit
1044  *
1045  * \throw InvalidPdgCode if character does not correspond to digit
1046  */
1047  inline std::uint32_t get_digit_from_char(const char inp) const {
1048  // Decimal digit
1049  if (48 <= inp && inp <= 57) {
1050  return inp - 48;
1051  }
1052  // Hexdecimal digit, uppercase
1053  if (65 <= inp && inp <= 70) {
1054  return inp - 65 + 10;
1055  }
1056  // Hexdecimal digit, lowercase
1057  if (97 <= inp && inp <= 102) {
1058  return inp - 97 + 10;
1059  }
1060  throw InvalidPdgCode("PdgCode: Invalid character " + std::string(&inp, 1) +
1061  " found.\n");
1062  }
1063 
1064  /**
1065  * Set the PDG code from the given string.
1066  * This supports hexdecimal digits. If the last digit is not enough to
1067  * represent the spin, a digit can be added at the beginning which will be
1068  * added to the total spin.
1069  * \param[in] codestring string which is translated into PdgCode
1070  *
1071  * \throw InvalidPdgCode if the input string is empty
1072  * \throw InvalidPdgCode
1073  * if it is a nucleus whose PDG code does not begin with 10
1074  * \throw InvalidPdgCode
1075  * if it is not a nucleus while number of digits is more than 8
1076  * \throw InvalidPdgCode
1077  * if the 1st quark field is not any of d, u, s, c, b and t quarks
1078  * \throw InvalidPdgCode
1079  * if the 2nd quark field is not any of d, u, s, c, b and t quarks
1080  * \throw InvalidPdgCode
1081  * if the 3rd quark field is not any of d, u, s, c, b and t quarks
1082  * \throw InvalidPdgCode
1083  * if there is nothing else but sign
1084  */
1085  inline void set_from_string(const std::string& codestring) {
1086  dump_ = 0;
1087  // Implicit with the above: digits_.antiparticle_ = false;
1088  digits_.n_ = digits_.n_R_ = digits_.n_L_ = digits_.n_q1_ = digits_.n_q2_ =
1089  digits_.n_q3_ = digits_.n_J_ = digits_.is_nucleus_ = 0;
1090  size_t length = codestring.size();
1091  if (length < 1) {
1092  throw InvalidPdgCode("Empty string does not contain PDG Code\n");
1093  }
1094  int c = 0;
1095  /* Look at current character; if it is a + or minus sign, read it
1096  * and advance to next char. */
1097  if (codestring[c] == '-') {
1098  digits_.antiparticle_ = true;
1099  ++c;
1100  } else if (codestring[c] == '+') {
1101  digits_.antiparticle_ = false;
1102  ++c;
1103  }
1104  // Save if the first character was a sign:
1105  unsigned int sign = c;
1106 
1107  // Nucleus
1108  if (length == 10 + sign) {
1109  nucleus_.is_nucleus_ = true;
1110  if (codestring[c] != '1' || codestring[c + 1] != '0') {
1111  throw InvalidPdgCode("Pdg code of nucleus \"" + codestring +
1112  "\" should start with 10\n");
1113  }
1114  c += 2;
1115  // ±10LZZZAAAI is the standard for nuclei
1116  std::array<int, 8> digits;
1117  for (int i = 0; i < 8; i++) {
1118  digits[i] = get_digit_from_char(codestring[c + i]);
1119  }
1120  nucleus_.n_Lambda_ = digits[0];
1121  nucleus_.Z_ = 100 * digits[1] + 10 * digits[2] + digits[3];
1122  nucleus_.A_ = 100 * digits[4] + 10 * digits[5] + digits[6];
1123  nucleus_.I_ = digits[7];
1124  return;
1125  }
1126 
1127  // Codestring shouldn't be longer than 8 + sign, except for nuclei
1128  if (length > 8 + sign) {
1129  throw InvalidPdgCode("String \"" + codestring +
1130  "\" too long for PDG Code\n");
1131  }
1132  /* Please note that in what follows, we actually need c++, not ++c.
1133  * first digit is used for n_J if the last digit is not enough. */
1134  if (length > 7 + sign) {
1135  digits_.n_J_ += get_digit_from_char(codestring[c++]);
1136  }
1137  // Codestring has 7 digits? 7th from last goes in n_.
1138  if (length > 6 + sign) {
1139  digits_.n_ = get_digit_from_char(codestring[c++]);
1140  }
1141  // It has 6 or 7 digits? 6th from last is n_R_.
1142  if (length > 5 + sign) {
1143  digits_.n_R_ = get_digit_from_char(codestring[c++]);
1144  }
1145  // 5th from last is n_L_.
1146  if (length > 4 + sign) {
1147  digits_.n_L_ = get_digit_from_char(codestring[c++]);
1148  }
1149  // 4th from last is n_q1_.
1150  if (length > 3 + sign) {
1151  digits_.n_q1_ = get_digit_from_char(codestring[c++]);
1152  if (digits_.n_q1_ > 6) {
1153  throw InvalidPdgCode("Invalid PDG code " + codestring + " (n_q1>6)");
1154  }
1155  }
1156  // 3rd from last is n_q2_.
1157  if (length > 2 + sign) {
1158  digits_.n_q2_ = get_digit_from_char(codestring[c++]);
1159  if (digits_.n_q2_ > 6) {
1160  throw InvalidPdgCode("Invalid PDG code " + codestring + " (n_q2>6)");
1161  }
1162  }
1163  // Next to last is n_q3_.
1164  if (length > 1 + sign) {
1165  digits_.n_q3_ = get_digit_from_char(codestring[c++]);
1166  if (digits_.n_q3_ > 6) {
1167  throw InvalidPdgCode("Invalid PDG code " + codestring + " (n_q3>6)");
1168  }
1169  }
1170  // Last digit is the spin degeneracy.
1171  if (length > sign) {
1172  digits_.n_J_ += get_digit_from_char(codestring[c++]);
1173  } else {
1174  throw InvalidPdgCode(
1175  "String \"" + codestring +
1176  "\" only consists of a sign, that is no valid PDG Code\n");
1177  }
1178  check();
1179  }
1180 
1181  /**
1182  * Sets the bitfield from an unsigned integer. Usually called from
1183  * the constructors.
1184  * \param[in] abscode integer which replace PDG code except sign
1185  *
1186  * \throw InvalidPdgCode if input is not a valid PDG code
1187  *
1188  * \see PdgCode::test_code
1189  */
1190  inline void set_fields(std::uint32_t abscode) {
1191  /* "dump_ =" overwrites antiparticle_, but this needs to have been set
1192  * already, so we carry it around the assignment. */
1193  bool ap = digits_.antiparticle_;
1194  dump_ = abscode & 0x0fffffff;
1195  digits_.antiparticle_ = ap;
1196  int test = test_code();
1197  if (test > 0) {
1198  throw InvalidPdgCode("Invalid digits " + std::to_string(test) +
1199  " in PDG Code " + string());
1200  }
1201  check();
1202  }
1203 };
1204 
1205 static_assert(sizeof(PdgCode) == 4, "should fit into 32 bit integer");
1206 
1207 /**
1208  * Sets the PDG code from the textual representation
1209  * in the input stream.
1210  * \param[in] is input string
1211  * \param[out] code PdgCode to be set
1212  */
1213 std::istream& operator>>(std::istream& is, PdgCode& code);
1214 /**
1215  * \ingroup logging
1216  * Writes the textual representation of the PDG code
1217  * to the output stream.
1218  */
1219 std::ostream& operator<<(std::ostream& is, const PdgCode& code);
1220 
1221 /// \return if two given particles represent a lepton pair (e+e- or mu+mu-).
1222 inline bool is_dilepton(const PdgCode pdg1, const PdgCode pdg2) {
1223  const auto c1 = pdg1.code();
1224  const auto c2 = pdg2.code();
1225  const auto min = std::min(c1, c2);
1226  const auto max = std::max(c1, c2);
1227  return (max == 0x11 && min == -0x11) || (max == 0x13 && min == -0x13) ||
1228  (max == 0x12 && min == -0x11) || (max == 0x11 && min == -0x12);
1229 }
1230 
1231 /**
1232  * \return if two of the three given particles represent a lepton pair
1233  * (e+e- or mu+mu-).
1234  */
1235 inline bool has_lepton_pair(const PdgCode pdg1, const PdgCode pdg2,
1236  const PdgCode pdg3) {
1237  return is_dilepton(pdg1, pdg2) || is_dilepton(pdg1, pdg3) ||
1238  is_dilepton(pdg2, pdg3);
1239 }
1240 
1241 } // namespace smash
1242 
1243 #endif // SRC_INCLUDE_SMASH_PDGCODE_H_
PdgCode stores a Particle Data Group Particle Numbering Scheme particle type number.
Definition: pdgcode.h:108
std::uint32_t quarks_
The quark digits n_q{1,2,3}_.
Definition: pdgcode.h:1003
bool is_Nstar1535() const
Definition: pdgcode.h:422
std::int32_t code() const
Definition: pdgcode.h:319
bool is_omega() const
Definition: pdgcode.h:480
bool is_Dmeson() const
Definition: pdgcode.h:489
bool is_rho() const
Definition: pdgcode.h:483
int antiparticle_sign() const
Definition: pdgcode.h:734
PdgCode(T codenumber, typename std::enable_if_t< std::is_integral_v< T > &&4< sizeof(T), bool >=true)
The creation of PdgCode instances for nuclei that have a 10-digits code cannot be done using the inte...
Definition: pdgcode.h:217
bool operator!=(const PdgCode rhs) const
Definition: pdgcode.h:826
int nucleus_n() const
Number of neutrons in nucleus.
Definition: pdgcode.h:919
int baryon_number() const
Definition: pdgcode.h:388
bool is_meson() const
Definition: pdgcode.h:401
PdgCode(const std::uint32_t abscode)
Receive an unsigned integer and process it into a PDG Code.
Definition: pdgcode.h:155
std::uint32_t n_q1_
first quark field. 0 for mesons.
Definition: pdgcode.h:965
bool is_Sigma() const
Definition: pdgcode.h:453
bool is_charmonia() const
Definition: pdgcode.h:383
bool is_Dstar2007() const
Definition: pdgcode.h:498
PdgCode(const std::string &codestring)
Initialize using a string The string is interpreted as a hexadecimal number, i.e.,...
Definition: pdgcode.h:131
int nucleus_ap() const
Number of antiprotons in nucleus.
Definition: pdgcode.h:929
int nucleus_an() const
Number of antineutrons in nucleus.
Definition: pdgcode.h:933
int bottomness() const
Definition: pdgcode.h:640
std::array< int, 3 > quark_content() const
The return is always an array of three numbers, which are pdgcodes of quarks: 1 - d,...
Definition: pdgcode.h:754
std::uint32_t n_q3_
third quark field
Definition: pdgcode.h:961
unsigned int spin() const
Definition: pdgcode.h:691
bool is_pion() const
Definition: pdgcode.h:471
bool is_kaon() const
Definition: pdgcode.h:465
bool antiparticle_
first bit: stores the sign.
Definition: pdgcode.h:975
bool is_Sigmastar() const
Definition: pdgcode.h:458
std::uint32_t dump() const
Dumps the bitfield into an unsigned integer.
Definition: pdgcode.h:313
std::uint32_t Z_
Definition: pdgcode.h:1017
std::uint32_t n_
first field: "counter"
Definition: pdgcode.h:971
bool is_lepton() const
Definition: pdgcode.h:372
double frac_charm() const
Definition: pdgcode.h:573
bool is_hyperon() const
Definition: pdgcode.h:435
std::uint32_t n_J_
spin quantum number .
Definition: pdgcode.h:959
bool is_nucleus() const
Definition: pdgcode.h:361
bool is_deuteron() const
Definition: pdgcode.h:504
bool is_proton() const
Definition: pdgcode.h:410
static PdgCode from_decimal(const int pdgcode_decimal)
Construct PDG code from decimal number.
Definition: pdgcode.h:339
bool is_nucleus_
Definition: pdgcode.h:1020
bool is_antiparticle_of(const PdgCode rhs) const
Definition: pdgcode.h:829
std::uint32_t bool is_nucleus_
1 for nuclei, 0 for the rest
Definition: pdgcode.h:971
int charmness() const
Definition: pdgcode.h:633
int strangeness() const
Definition: pdgcode.h:626
struct smash::PdgCode::@0::@2 digits_
The single digits collection of the code.
int nucleus_p() const
Number of protons in nucleus.
Definition: pdgcode.h:915
int32_t get_decimal() const
Definition: pdgcode.h:852
bool is_baryon() const
Definition: pdgcode.h:398
void set_fields(std::uint32_t abscode)
Sets the bitfield from an unsigned integer.
Definition: pdgcode.h:1190
int isospin3() const
Definition: pdgcode.h:535
void check() const
Do all sorts of validity checks.
Definition: pdgcode.h:284
bool is_nucleon() const
Definition: pdgcode.h:404
std::string string() const
Definition: pdgcode.h:322
int test_code() const
Checks the integer for invalid hex digits.
Definition: pdgcode.h:250
PdgCode get_antiparticle() const
Construct the antiparticle to a given PDG code.
Definition: pdgcode.h:329
int nucleus_La() const
Number of Lambdas in nucleus.
Definition: pdgcode.h:925
double frac_bottom() const
Definition: pdgcode.h:598
bool is_hadron() const
Definition: pdgcode.h:367
bool operator==(const PdgCode rhs) const
Definition: pdgcode.h:823
PdgCode()
Standard initializer.
Definition: pdgcode.h:125
bool is_eta() const
Definition: pdgcode.h:477
int nucleus_A() const
Nucleus mass number.
Definition: pdgcode.h:943
static PdgCode invalid()
PdgCode 0x0 is guaranteed not to be valid by the PDG standard, but it passes all tests here,...
Definition: pdgcode.h:841
int nucleus_aLa() const
Number of anti-Lambdas in nucleus.
Definition: pdgcode.h:939
bool operator<(const PdgCode rhs) const
Sorts PDG Codes according to their numeric value.
Definition: pdgcode.h:814
PdgCode(std::int32_t codenumber)
Receive a signed integer and process it into a PDG Code.
Definition: pdgcode.h:143
bool is_Omega() const
Definition: pdgcode.h:438
std::uint32_t A_
Definition: pdgcode.h:1018
bool is_neutron() const
Definition: pdgcode.h:416
void deexcite()
Remove all excitation, except spin. Sign and quark content remains.
Definition: pdgcode.h:872
std::uint32_t n_L_
"angular momentum"
Definition: pdgcode.h:967
void set_from_string(const std::string &codestring)
Set the PDG code from the given string.
Definition: pdgcode.h:1085
bool is_triton() const
Definition: pdgcode.h:510
std::uint32_t ucode() const
Definition: pdgcode.h:1039
std::uint32_t n_R_
"radial excitation"
Definition: pdgcode.h:969
std::uint32_t dump_
The bitfield dumped into a single integer.
Definition: pdgcode.h:994
bool is_neutrino() const
Definition: pdgcode.h:378
bool is_Delta() const
Definition: pdgcode.h:428
std::uint32_t n_Lambda_
Definition: pdgcode.h:1016
double frac_strange() const
Definition: pdgcode.h:548
bool has_antiparticle() const
Definition: pdgcode.h:519
bool is_Lambda() const
Definition: pdgcode.h:448
std::uint32_t get_digit_from_char(const char inp) const
Definition: pdgcode.h:1047
bool is_Xi() const
Definition: pdgcode.h:443
bool is_heavy_flavor() const
Definition: pdgcode.h:617
std::int32_t quarks() const
Definition: pdgcode.h:738
std::uint32_t I_
Definition: pdgcode.h:1019
std::uint32_t n_q2_
second quark field
Definition: pdgcode.h:963
unsigned int spin_degeneracy() const
Definition: pdgcode.h:727
std::uint32_t excitation_
The excitation digits n_, n_R_, n_L_.
Definition: pdgcode.h:1005
int charge() const
The charge of the particle.
Definition: pdgcode.h:650
std::ostream & operator<<(std::ostream &is, const PdgCode &code)
Writes the textual representation of the PDG code to the output stream.
Definition: pdgcode.cc:119
constexpr int pi_p
π⁺.
constexpr int rho_p
ρ⁺.
constexpr int Delta_p
Δ⁺.
constexpr int rho_m
ρ⁻.
constexpr int Delta_pp
Δ⁺⁺.
constexpr int Dstar_p
D*(2010)⁺.
constexpr int D_z
D⁰.
constexpr int K_p
K⁺.
constexpr int K_z
K⁰.
constexpr int Sigma_star_z
Σ*⁰
constexpr int p
Proton.
constexpr int omega
ω.
constexpr int N1535_z
N(1535)⁰.
constexpr int eta
η.
constexpr int Sigma_star_p
Σ*⁺
constexpr int pi_z
π⁰.
constexpr int n
Neutron.
constexpr int Delta_m
Δ⁻.
constexpr int Delta_z
Δ⁰.
constexpr int rho_z
ρ⁰.
constexpr int Sigma_star_m
Σ*⁻
constexpr int pi_m
π⁻.
constexpr int N1535_p
N(1535)⁺.
constexpr int Dstar_z
D*(2007)⁰.
constexpr int D_p
D⁺.
Definition: action.h:24
bool is_dilepton(const PdgCode pdg1, const PdgCode pdg2)
Definition: pdgcode.h:1222
std::istream & operator>>(std::istream &is, PdgCode &code)
Sets the PDG code from the textual representation in the input stream.
Definition: pdgcode.cc:14
bool has_lepton_pair(const PdgCode pdg1, const PdgCode pdg2, const PdgCode pdg3)
Definition: pdgcode.h:1235
std::string to_string(ThermodynamicQuantity quantity)
Convert a ThermodynamicQuantity enum value to its corresponding string.
Definition: stringify.cc:26
thrown for invalid inputs
Definition: pdgcode.h:114