diff --git a/Documentation/Examples/cascade_example.cc b/Documentation/Examples/cascade_example.cc
index 9167ffcd5aafd01f047c046dd093b7928fcc0ad8..49e2c11b77e2704c84297600a21f5e1933594227 100644
--- a/Documentation/Examples/cascade_example.cc
+++ b/Documentation/Examples/cascade_example.cc
@@ -34,6 +34,7 @@
 #include <boost/type_index.hpp>
 using boost::typeindex::type_id_with_cvr;
 
+#include <fenv.h>
 #include <iostream>
 #include <limits>
 #include <typeinfo>
@@ -48,25 +49,26 @@ using namespace corsika::geometry;
 using namespace corsika::environment;
 
 using namespace std;
-using namespace corsika::units::hep;
+using namespace corsika::units::si;
 
 class ProcessCut : public corsika::process::ContinuousProcess<ProcessCut> {
 
-  EnergyType fECut;
+  HEPEnergyType fECut;
 
-  EnergyType fEnergy = 0_GeV;
-  EnergyType fEmEnergy = 0_GeV;
+  HEPEnergyType fEnergy = 0_GeV;
+  HEPEnergyType fEmEnergy = 0_GeV;
   int fEmCount = 0;
-  EnergyType fInvEnergy = 0_GeV;
+  HEPEnergyType fInvEnergy = 0_GeV;
   int fInvCount = 0;
 
 public:
-  ProcessCut(const EnergyType v)
-      : fECut(v) {}
+  ProcessCut(const HEPEnergyType cut)
+      : fECut(cut) {}
+
   template <typename Particle>
   bool isBelowEnergyCut(Particle& p) const {
     // FOR NOW: center-of-mass energy hard coded
-    const EnergyType Ecm = sqrt(2. * p.GetEnergy() * 0.93827_GeV);
+    const HEPEnergyType Ecm = sqrt(2. * p.GetEnergy() * 0.93827_GeV);
     if (p.GetEnergy() < fECut || Ecm < 10_GeV)
       return true;
     else
@@ -143,7 +145,7 @@ public:
   template <typename Particle, typename Stack>
   EProcessReturn DoContinuous(Particle& p, setup::Trajectory&, Stack&) {
     const Code pid = p.GetPID();
-    EnergyType energy = p.GetEnergy();
+    HEPEnergyType energy = p.GetEnergy();
     cout << "ProcessCut: DoContinuous: " << pid << " E= " << energy
          << ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV" << endl;
     EProcessReturn ret = EProcessReturn::eOk;
@@ -188,15 +190,16 @@ public:
          << " ******************************" << endl;
   }
 
-  EnergyType GetInvEnergy() const { return fInvEnergy; }
-  EnergyType GetCutEnergy() const { return fEnergy; }
-  EnergyType GetEmEnergy() const { return fEmEnergy; }
+  HEPEnergyType GetInvEnergy() const { return fInvEnergy; }
+  HEPEnergyType GetCutEnergy() const { return fEnergy; }
+  HEPEnergyType GetEmEnergy() const { return fEmEnergy; }
 };
 
 //
 // The example main program for a particle cascade
 //
 int main() {
+  feenableexcept(FE_INVALID);
   // initialize random number sequence(s)
   corsika::random::RNGManager::GetInstance().RegisterRandomStream("cascade");
 
@@ -237,14 +240,14 @@ int main() {
   // setup particle stack, and add primary particle
   setup::Stack stack;
   stack.Clear();
-  const hep::EnergyType E0 = 100_TeV;
+  const HEPEnergyType E0 = 100_TeV;
   double theta = 0.;
   double phi = 0.;
   {
     auto particle = stack.NewParticle();
     particle.SetPID(Code::Proton);
-    hep::MomentumType P0 = sqrt(E0 * E0 - Proton::GetMass() * Proton::GetMass());
-    auto momentumComponents = [](double theta, double phi, MomentumType& ptot) {
+    HEPMomentumType P0 = sqrt(E0 * E0 - Proton::GetMass() * Proton::GetMass());
+    auto momentumComponents = [](double theta, double phi, HEPMomentumType ptot) {
       return std::make_tuple(ptot * sin(theta) * cos(phi), ptot * sin(theta) * sin(phi),
                              -ptot * cos(theta));
     };
diff --git a/Documentation/Examples/stack_example.cc b/Documentation/Examples/stack_example.cc
index fbe4cd9da69440c48d345c17a1affc52d6c0f150..33ebc230af244932375c904747b127b0b5c240ab 100644
--- a/Documentation/Examples/stack_example.cc
+++ b/Documentation/Examples/stack_example.cc
@@ -30,7 +30,7 @@ void fill(corsika::stack::super_stupid::SuperStupidStack& s) {
 void read(corsika::stack::super_stupid::SuperStupidStack& s) {
   assert(s.GetSize() == 11); // stack has 11 particles
 
-  EnergyType total_energy;
+  HEPEnergyType total_energy;
   int i = 0;
   for (auto& p : s) {
     total_energy += p.GetEnergy();
diff --git a/Framework/Cascade/testCascade.cc b/Framework/Cascade/testCascade.cc
index e1b742624010bdf549008c82669ff637de54443b..12885054b18cafdb1312818418f0bf46e95c9a88 100644
--- a/Framework/Cascade/testCascade.cc
+++ b/Framework/Cascade/testCascade.cc
@@ -81,7 +81,7 @@ public:
 
   template <typename Particle, typename T, typename Stack>
   EProcessReturn DoContinuous(Particle& p, T&, Stack& s) const {
-    EnergyType E = p.GetEnergy();
+    HEPEnergyType E = p.GetEnergy();
     if (E < 85_MeV) {
       p.Delete();
       fCount++;
@@ -123,7 +123,7 @@ TEST_CASE("Cascade", "[Cascade]") {
 
   stack.Clear();
   auto particle = stack.NewParticle();
-  EnergyType E0 = 100_GeV;
+  HEPEnergyType E0 = 100_GeV;
   particle.SetPID(particles::Code::Electron);
   particle.SetEnergy(E0);
   particle.SetPosition(Point(rootCS, {0_m, 0_m, 10_km}));
@@ -138,7 +138,7 @@ TEST_CASE("Cascade", "[Cascade]") {
     for (int i = 0; i < 0; ++i) {
       stack.Clear();
       auto particle = stack.NewParticle();
-      EnergyType E0 = 100_GeV * pow(10, i);
+      HEPEnergyType E0 = 100_GeV * pow(10, i);
       particle.SetEnergy(E0);
       EAS.Init();
       EAS.Run();
diff --git a/Framework/Particles/ParticleProperties.h b/Framework/Particles/ParticleProperties.h
index 44b9b55ed70cfb00e6ed34e3d5a0ceb55da8907b..959c27a6be0028c607d9114d4577adcd6e791c3c 100644
--- a/Framework/Particles/ParticleProperties.h
+++ b/Framework/Particles/ParticleProperties.h
@@ -44,7 +44,7 @@ namespace corsika::particles {
   // forward declarations to be used in GeneratedParticleProperties
   int16_t constexpr GetElectricChargeNumber(Code const);
   corsika::units::si::ElectricChargeType constexpr GetElectricCharge(Code const);
-  corsika::units::hep::MassType constexpr GetMass(Code const);
+  corsika::units::si::HEPMassType constexpr GetMass(Code const);
   PDGCodeType constexpr GetPDG(Code const);
   constexpr std::string const& GetName(Code const);
   corsika::units::si::TimeType constexpr GetLifetime(Code const);
@@ -58,7 +58,7 @@ namespace corsika::particles {
   /*!
    * returns mass of particle
    */
-  corsika::units::hep::MassType constexpr GetMass(Code const p) {
+  corsika::units::si::HEPMassType constexpr GetMass(Code const p) {
     return detail::masses[static_cast<CodeIntType const>(p)];
   }
 
diff --git a/Framework/Particles/pdxml_reader.py b/Framework/Particles/pdxml_reader.py
index b1a11ae8ecedb9898348dfa27c26a24a8b389221..2e463a0e1d7c9a227d9f49160d4916ecf3390761 100755
--- a/Framework/Particles/pdxml_reader.py
+++ b/Framework/Particles/pdxml_reader.py
@@ -290,9 +290,9 @@ def gen_properties(particle_db):
     string += "\n"
     
     # particle masses table
-    string += "static constexpr std::array<corsika::units::hep::MassType const, size> masses = {\n"    
+    string += "static constexpr std::array<corsika::units::si::HEPMassType const, size> masses = {\n"    
     for p in particle_db.values():
-        string += "  {mass:e} * (1e9 * corsika::units::constants::eV), // {name:s}\n".format(mass = p['mass'], name = p['name'])
+        string += "  {mass:e} * 1e9 * corsika::units::si::electronvolt, // {name:s}\n".format(mass = p['mass'], name = p['name'])
     string += "};\n\n"
                    
     # PDG code table
@@ -343,7 +343,7 @@ def gen_properties(particle_db):
     string += "};\n"
 
     # nucleus mass number A
-    string += "static constexpr std::array<int, size> nucleusA = {\n"
+    string += "static constexpr std::array<int16_t, size> nucleusA = {\n"
     for p in particle_db.values():
         A = 0
         if p['isNucleus']:
@@ -352,7 +352,7 @@ def gen_properties(particle_db):
     string += "};\n"
     
     # nucleus charge number Z
-    string += "static constexpr std::array<int, size> nucleusZ = {\n"
+    string += "static constexpr std::array<int16_t, size> nucleusZ = {\n"
     for p in particle_db.values():
         Z = 0
         if p['isNucleus']:
@@ -396,14 +396,14 @@ def gen_classes(particle_db):
         string += "class " + cname + " {\n"
         string += "  public:\n"
         string += "   static constexpr Code GetCode() { return Type; }\n"
-        string += "   static constexpr corsika::units::hep::MassType GetMass() { return corsika::particles::GetMass(Type); }\n"
+        string += "   static constexpr corsika::units::si::HEPMassType GetMass() { return corsika::particles::GetMass(Type); }\n"
         string += "   static constexpr corsika::units::si::ElectricChargeType GetCharge() { return corsika::particles::GetElectricCharge(Type); }\n"
         string += "   static constexpr int16_t GetChargeNumber() { return corsika::particles::GetElectricChargeNumber(Type); }\n"
         string += "   static std::string const& GetName() { return corsika::particles::GetName(Type); }\n"
         string += "   static constexpr Code GetAntiParticle() { return AntiType; }\n"
         string += "   static constexpr bool IsNucleus() { return corsika::particles::IsNucleus(Type); }\n"
-        string += "   static constexpr int GetNucleusA() { return corsika::particles::GetNucleusA(Type); }\n"
-        string += "   static constexpr int GetNucleusZ() { return corsika::particles::GetNucleusZ(Type); }\n"
+        string += "   static constexpr int16_t GetNucleusA() { return corsika::particles::GetNucleusA(Type); }\n"
+        string += "   static constexpr int16_t GetNucleusZ() { return corsika::particles::GetNucleusZ(Type); }\n"
         string += "   static constexpr Code Type = Code::" + cname + ";\n"
         string += "   static constexpr Code AntiType = Code::" + antiP + ";\n"
         string += " private:\n"
@@ -463,7 +463,7 @@ if __name__ == "__main__":
         print("usage: {:s} <Pythia8.xml> <Nuclei.xml> <ClassNames.xml>".format(sys.argv[0]), file=sys.stderr)
         sys.exit(1)
         
-    print("\n       pdxml_reader.py: Automatically produce particle-properties from input files\n")
+    print("\n       pdxml_reader.py: automatically produce particle properties from input files\n")
     
     names = class_names(sys.argv[3])
     particle_db = OrderedDict()
diff --git a/Framework/Particles/testParticles.cc b/Framework/Particles/testParticles.cc
index f211260541665a426fd641eb506ef444869f92d1..bdd07d8370592da981e59672c8b7a50ef92df9e4 100644
--- a/Framework/Particles/testParticles.cc
+++ b/Framework/Particles/testParticles.cc
@@ -17,7 +17,7 @@
 #include <catch2/catch.hpp>
 
 using namespace corsika::units;
-using namespace corsika::units::hep;
+using namespace corsika::units::si;
 using namespace corsika::particles;
 
 TEST_CASE("ParticleProperties", "[Particles]") {
diff --git a/Framework/Units/PhysicalConstants.h b/Framework/Units/PhysicalConstants.h
index 9aef04ee6fa63d6818d5d471f342d7a8e2b3a729..95436959107ebee231450d5fb0b237a08b0886e6 100644
--- a/Framework/Units/PhysicalConstants.h
+++ b/Framework/Units/PhysicalConstants.h
@@ -43,7 +43,7 @@ namespace corsika::units::constants {
   constexpr quantity<electric_charge_d> e{Rep(1.6021766208e-19L) * coulomb};
 
   // electronvolt
-  constexpr quantity<energy_d> eV{e / coulomb * joule};
+  // constexpr quantity<hepenergy_d> eV{e / coulomb * joule};
 
   // Planck constant
   constexpr quantity<dimensions<2, 1, -1> > h{Rep(6.62606876e-34L) * joule * second};
@@ -55,9 +55,6 @@ namespace corsika::units::constants {
   // unified atomic mass unit
   constexpr quantity<mass_d> u{Rep(1.6605402e-27L) * kilogram};
 
-  // barn moved to PhysicalUnits
-  //  constexpr quantity<area_d> barn{Rep(1.e-28L) * meter * meter};
-
   // etc.
 
 } // namespace corsika::units::constants
diff --git a/Framework/Units/PhysicalUnits.h b/Framework/Units/PhysicalUnits.h
index fe4e284acd7f039147acebb39512390bcef1431c..262e55d1c52070e36add9404f0d2ba67bae347bc 100644
--- a/Framework/Units/PhysicalUnits.h
+++ b/Framework/Units/PhysicalUnits.h
@@ -23,7 +23,7 @@ namespace phys::units {
  * optimal coding style.
  *
  */
-
+/*
 namespace corsika::units::hep {
   using namespace phys::units;
   using namespace phys::units::literals;
@@ -39,7 +39,7 @@ namespace corsika::units::hep {
   using EnergyType = phys::units::quantity<energy_hep_d, double>;
 
 } // namespace corsika::units::hep
-
+*/
 namespace corsika::units::si {
   using namespace phys::units;
   using namespace phys::units::literals;
@@ -48,15 +48,11 @@ namespace corsika::units::si {
 
   /// defining momentum you suckers
   /// dimensions, i.e. composition in base SI dimensions
-  using momentum_d = phys::units::dimensions<1, 1, -1>;
-  // defining the unit of momentum, so far newton-meter, maybe go to HEP?
-  constexpr phys::units::quantity<momentum_d> newton_second{
-      phys::units::meter * phys::units::kilogram / phys::units::second};
+  using hepmomentum_d = phys::units::hepenergy_d;
+  using hepmass_d = phys::units::hepenergy_d;
 
   /// defining cross section
-  using sigma_d = phys::units::dimensions<2, 0, 0>;
-  constexpr phys::units::quantity<sigma_d> barn{phys::units::Rep(1.e-28L) *
-                                                phys::units::meter * phys::units::meter};
+  using sigma_d = phys::units::area_d;
 
   /// add the unit-types
   using LengthType = phys::units::quantity<phys::units::length_d, double>;
@@ -65,11 +61,12 @@ namespace corsika::units::si {
   using FrequencyType = phys::units::quantity<phys::units::frequency_d, double>;
   using ElectricChargeType =
       phys::units::quantity<phys::units::electric_charge_d, double>;
-  using EnergyType = phys::units::quantity<phys::units::energy_d, double>;
+  using HEPEnergyType = phys::units::quantity<phys::units::hepenergy_d, double>;
   using MassType = phys::units::quantity<phys::units::mass_d, double>;
+  using HEPMassType = phys::units::quantity<hepmass_d, double>;
   using MassDensityType = phys::units::quantity<phys::units::mass_density_d, double>;
   using GrammageType = phys::units::quantity<phys::units::dimensions<-2, 1, 0>, double>;
-  using MomentumType = phys::units::quantity<momentum_d, double>;
+  using HEPMomentumType = phys::units::quantity<hepmomentum_d, double>;
   using CrossSectionType = phys::units::quantity<area_d, double>;
   using InverseLengthType =
       phys::units::quantity<phys::units::dimensions<-1, 0, 0>, double>;
@@ -83,28 +80,19 @@ namespace corsika::units::si {
  * @file PhysicalUnits
  *
  * Define _XeV literals, alowing 10_GeV in the code.
- * Define _meter literal
  * Define _barn literal
- * Define _newton_second literal for SI momenta
  */
 
 namespace phys {
   namespace units {
     namespace literals {
-      QUANTITY_DEFINE_SCALING_LITERALS(eV, energy_d,
-                                       magnitude(corsika::units::constants::eV))
-
-      //      QUANTITY_DEFINE_SCALING_LITERALS(barn, corsika::units::si::area_d,
-      //                             magnitude(corsika::units::si::constants::barn))
+      QUANTITY_DEFINE_SCALING_LITERALS(eV, hepenergy_d, 1)
 
       QUANTITY_DEFINE_SCALING_LITERALS(barn, corsika::units::si::sigma_d,
                                        magnitude(corsika::units::constants::barn))
 
-      QUANTITY_DEFINE_SCALING_LITERALS(meter, length_d,
-                                       magnitude(corsika::units::constants::meter))
-
-      QUANTITY_DEFINE_SCALING_LITERALS(Ns, corsika::units::si::momentum_d,
-                                       magnitude(1_m * 1_kg / 1_s))
+      // QUANTITY_DEFINE_SCALING_LITERALS(Ns, corsika::units::si::momentum_d,
+      //                                 magnitude(1_m * 1_kg / 1_s))
 
     } // namespace literals
   }   // namespace units
diff --git a/Framework/Units/testUnits.cc b/Framework/Units/testUnits.cc
index 4dc6316e1cdaf63170475d417199a2736b11d1a9..38b3b299e151274bc8c03a99ebf750ec4ee46bcd 100644
--- a/Framework/Units/testUnits.cc
+++ b/Framework/Units/testUnits.cc
@@ -1,4 +1,3 @@
-
 /**
  * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
  *
@@ -16,6 +15,7 @@
 #include <corsika/units/PhysicalUnits.h>
 
 #include <array>
+#include <sstream>
 
 using namespace corsika;
 using namespace corsika::units::si;
@@ -39,12 +39,12 @@ TEST_CASE("PhysicalUnits", "[Units]") {
 
     [[maybe_unused]] LengthType arr1[2] = {{1_mm}, {2_cm}};
 
-    [[maybe_unused]] std::array<EnergyType, 4> arr2; // empty array
+    [[maybe_unused]] std::array<HEPEnergyType, 4> arr2; // empty array
 
-    [[maybe_unused]] std::array<EnergyType, 4> arr3 = {1_GeV, 1_eV, 5_MeV};
+    [[maybe_unused]] std::array<HEPEnergyType, 4> arr3 = {1_GeV, 1_eV, 5_MeV};
 
-    auto p1 = 10_Ns;
-    REQUIRE(p1 == 10_Ns);
+    auto p1 = 10_s * newton;
+    REQUIRE(p1 == 10_s * newton);
   }
 
   SECTION("Powers in literal units") {
@@ -79,13 +79,13 @@ TEST_CASE("PhysicalUnits", "[Units]") {
   }
 
   SECTION("Formulas") {
-    const EnergyType E2 = 20_GeV * 2;
+    const HEPEnergyType E2 = 20_GeV * 2;
     REQUIRE(E2 == 40_GeV);
     REQUIRE(E2 / 1_GeV == Approx(40));
 
     const MassType m = 1_kg;
     const SpeedType v = 1_m / 1_s;
-    REQUIRE(m * v == 1_Ns);
+    REQUIRE(m * v == 1_s * newton);
 
     const double lgE = log10(E2 / 1_GeV);
     REQUIRE(lgE == Approx(log10(40.)));
@@ -94,21 +94,19 @@ TEST_CASE("PhysicalUnits", "[Units]") {
     REQUIRE(E3 == 180_GeV);
   }
 
-  SECTION("Unit system conversion") {
-
-    const units::hep::MassType m_hep = 3_GeV;
-    std::cout << m_hep << std::endl;
-
-    const units::si::MassType m_hep2 = 3_kg;
-    std::cout << m_hep2 << std::endl;
-
-    REQUIRE(m_hep == 3_GeV); // hep::mass identical to si::energy
-    auto type_check = m_hep / units::constants::cSquared;
-    REQUIRE(dynamic_cast<units::si::MassType*>(&type_check)); // hep::mass*c2 is mass unit
-
-    const units::hep::EnergyType e_hep = 4_GeV;
-
-    REQUIRE(sqrt(m_hep * m_hep + e_hep * e_hep) == 5_GeV);
+  SECTION("Output") {
+    {
+      const HEPEnergyType E = 5_eV;
+      std::stringstream stream;
+      stream << E;
+      REQUIRE(stream.str() == std::string("5 eV"));
+    }
+    {
+      const HEPEnergyType E = 5_EeV;
+      std::stringstream stream;
+      stream << E;
+      REQUIRE(stream.str() == std::string("5e+18 eV"));
+    }
   }
 
   SECTION("Special") {
diff --git a/Framework/Utilities/COMBoost.cc b/Framework/Utilities/COMBoost.cc
index 42d5995d2e54c01ef0ca5468dd98b1005d70fb3a..1bf8f839f1818fb12aa5c813ee166504e3351bd1 100644
--- a/Framework/Utilities/COMBoost.cc
+++ b/Framework/Utilities/COMBoost.cc
@@ -13,8 +13,8 @@
 using namespace corsika::utl;
 using namespace corsika::units::si;
 
-COMBoost::COMBoost(EnergyType eProjectile, COMBoost::MomentumVector const& pProjectile,
-                   MassType mTarget)
+COMBoost::COMBoost(HEPEnergyType eProjectile, COMBoost::MomentumVector const& pProjectile,
+                   HEPMassType mTarget)
     : fRotation(Eigen::Matrix3d::Identity())
     , fCS(pProjectile.GetCoordinateSystem()) {
   // calculate matrix for rotating pProjectile to z-axis first
@@ -37,8 +37,7 @@ COMBoost::COMBoost(EnergyType eProjectile, COMBoost::MomentumVector const& pProj
   }
 
   // calculate boost
-  double const x = pProjNorm * units::constants::c /
-                   (eProjectile + mTarget * units::constants::cSquared);
+  double const x = pProjNorm / (eProjectile + mTarget);
 
   /* Accurracy matters here, x = 1 - epsilon for ultra-relativistic boosts */
   double const coshEta = 1 / std::sqrt((1 + x) * (1 - x));
@@ -50,34 +49,34 @@ COMBoost::COMBoost(EnergyType eProjectile, COMBoost::MomentumVector const& pProj
   fInverseBoost << coshEta, -sinhEta, -sinhEta, coshEta;
 }
 
-std::tuple<EnergyType, corsika::geometry::QuantityVector<momentum_d>> COMBoost::toCoM(
-    EnergyType E, COMBoost::MomentumVector p) const {
-  corsika::geometry::QuantityVector<momentum_d> pComponents = p.GetComponents(fCS);
+std::tuple<HEPEnergyType, corsika::geometry::QuantityVector<hepmomentum_d>>
+COMBoost::toCoM(HEPEnergyType E, COMBoost::MomentumVector p) const {
+  corsika::geometry::QuantityVector<hepmomentum_d> pComponents = p.GetComponents(fCS);
   Eigen::Vector3d eVecRotated = fRotation * pComponents.eVector;
   Eigen::Vector2d lab;
 
-  lab << (E * (1 / 1_GeV)), (eVecRotated(2) * (units::constants::c / 1_GeV).magnitude());
+  lab << (E * (1 / 1_GeV)), (eVecRotated(2) * (1 / 1_GeV).magnitude());
 
   auto const boostedZ = fBoost * lab;
   auto const E_CoM = boostedZ(0) * 1_GeV;
 
-  eVecRotated(2) = boostedZ(1) * (1_GeV / units::constants::c).magnitude();
+  eVecRotated(2) = boostedZ(1) * (1_GeV).magnitude();
 
   return std::make_tuple(E_CoM,
-                         corsika::geometry::QuantityVector<momentum_d>{eVecRotated});
+                         corsika::geometry::QuantityVector<hepmomentum_d>{eVecRotated});
 }
 
-std::tuple<EnergyType, COMBoost::MomentumVector> COMBoost::fromCoM(
-    EnergyType E, corsika::geometry::QuantityVector<units::si::momentum_d> pCoM) const {
+std::tuple<HEPEnergyType, COMBoost::MomentumVector> COMBoost::fromCoM(
+    HEPEnergyType E,
+    corsika::geometry::QuantityVector<units::si::hepmomentum_d> pCoM) const {
   Eigen::Vector2d com;
-  com << (E * (1 / (units::constants::c * 1_Ns))),
-      (pCoM.eVector(2) * (1 / 1_Ns).magnitude());
+  com << (E * (1 / 1_GeV)), (pCoM.eVector(2) * (1 / 1_GeV).magnitude());
 
   auto const boostedZ = fInverseBoost * com;
-  auto const E_CoM = boostedZ(0) * (1_Ns * units::constants::c);
+  auto const E_CoM = boostedZ(0) * 1_GeV;
 
   auto pLab = pCoM;
-  pLab.eVector(2) = boostedZ(1) * (1_Ns).magnitude();
+  pLab.eVector(2) = boostedZ(1) * (1_GeV).magnitude();
   pLab.eVector = fRotation.transpose() * pLab.eVector;
 
   return std::make_tuple(E_CoM, MomentumVector(fCS, pLab));
diff --git a/Framework/Utilities/COMBoost.h b/Framework/Utilities/COMBoost.h
index 6250d422dc256c4cad102bb93bd596e9a0df2a30..fa57d8f3fa56c6c34432ed2dbdbbec3db14c5a14 100644
--- a/Framework/Utilities/COMBoost.h
+++ b/Framework/Utilities/COMBoost.h
@@ -23,21 +23,22 @@ namespace corsika::utl {
     Eigen::Matrix3d fRotation;
     Eigen::Matrix2d fBoost, fInverseBoost;
     corsika::geometry::CoordinateSystem const& fCS;
-    using MomentumVector = corsika::geometry::Vector<units::si::momentum_d>;
+    using MomentumVector = corsika::geometry::Vector<units::si::hepmomentum_d>;
 
   public:
     //! construct a COMBoost given energy and momentum of projectile and mass of target
-    COMBoost(units::si::EnergyType eProjectile, MomentumVector const& pProjectile,
-             units::si::MassType mTarget);
+    COMBoost(units::si::HEPEnergyType eProjectile, MomentumVector const& pProjectile,
+             units::si::HEPMassType mTarget);
 
     //! transforms a 4-momentum from lab frame to the center-of-mass frame
-    std::tuple<units::si::EnergyType, geometry::QuantityVector<units::si::momentum_d>>
-    toCoM(units::si::EnergyType E, MomentumVector p) const;
+    std::tuple<units::si::HEPEnergyType,
+               geometry::QuantityVector<units::si::hepmomentum_d>>
+    toCoM(units::si::HEPEnergyType E, MomentumVector p) const;
 
     //! transforms a 4-momentum from the center-of-mass frame back to lab frame
-    std::tuple<units::si::EnergyType, MomentumVector> fromCoM(
-        units::si::EnergyType E,
-        geometry::QuantityVector<units::si::momentum_d> pCoM) const;
+    std::tuple<units::si::HEPEnergyType, MomentumVector> fromCoM(
+        units::si::HEPEnergyType E,
+        geometry::QuantityVector<units::si::hepmomentum_d> pCoM) const;
   };
 } // namespace corsika::utl
 
diff --git a/Framework/Utilities/testCOMBoost.cc b/Framework/Utilities/testCOMBoost.cc
index 3af2585630be330acd547c1087b55c174732fcc0..6b3b950518bd5a488910bbbd3538f93f1cda8721 100644
--- a/Framework/Utilities/testCOMBoost.cc
+++ b/Framework/Utilities/testCOMBoost.cc
@@ -30,57 +30,52 @@ TEST_CASE("boosts") {
       RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
 
   // relativistic energy
-  auto energy = [](MassType m, Vector<momentum_d> const& p) {
-    return sqrt(m * m * cSquared * cSquared + p.squaredNorm() * cSquared);
+  auto energy = [](HEPMassType m, Vector<hepmomentum_d> const& p) {
+    return sqrt(m * m + p.squaredNorm());
   };
 
   // mandelstam-s
-  auto s = [](EnergyType E, QuantityVector<momentum_d> const& p) {
-    return E * E / cSquared - p.squaredNorm();
+  auto s = [](HEPEnergyType E, QuantityVector<hepmomentum_d> const& p) {
+    return E * E - p.squaredNorm();
   };
 
   // define projectile kinematics in lab frame
-  MassType const projectileMass = 1._GeV / cSquared;
-  std::vector<Vector<momentum_d>> labProjectiles{
-      {rootCS, {0_GeV / c, 1_PeV / c, 0_GeV / c}},   // standard case
-      {rootCS, {0_GeV / c, 0_GeV / c, -1_GeV / c}}}; // "special" case
-
-  for (auto const& pProjectileLab : labProjectiles) {
-    EnergyType const eProjectileLab = energy(projectileMass, pProjectileLab);
-
-    // define target kinematics in lab frame
-    MassType const targetMass = 1_GeV / cSquared;
-    Vector<momentum_d> pTargetLab{rootCS, {0_Ns, 0_Ns, 0_Ns}};
-    EnergyType const eTargetLab = energy(targetMass, pTargetLab);
-
-    // define boost to com frame
-    COMBoost boost(eProjectileLab, pProjectileLab, targetMass);
-
-    // boost projecticle
-    auto const [eProjectileCoM, pProjectileCoM] =
-        boost.toCoM(eProjectileLab, pProjectileLab);
-
-    // boost target
-    auto const [eTargetCoM, pTargetCoM] = boost.toCoM(eTargetLab, pTargetLab);
-
-    // sum of momenta in CoM, should be 0
-    auto const sumPCoM = pProjectileCoM + pTargetCoM;
-    CHECK(sumPCoM[2] / (1_GeV / c) == Approx(0).margin(absMargin));
-
-    // mandelstam-s should be invariant under transformation
-    CHECK(s(eProjectileLab + eTargetLab,
-            pProjectileLab.GetComponents() + pTargetLab.GetComponents()) /
-              (1_GeV / c) / (1_GeV / c) ==
-          Approx(s(eProjectileCoM + eTargetCoM, pProjectileCoM + pTargetCoM) /
-                 (1_GeV / c) / (1_GeV / c)));
-
-    // boost back...
-    auto const [eProjectileBack, pProjectileBack] =
-        boost.fromCoM(eProjectileCoM, pProjectileCoM);
-
-    // ...should yield original values before the boosts
-    CHECK(eProjectileBack / eProjectileLab == Approx(1));
-    CHECK((pProjectileBack - pProjectileLab).norm() / pProjectileLab.norm() ==
-          Approx(0).margin(absMargin));
-  }
+  HEPMassType const projectileMass = 1._GeV;
+  Vector<hepmomentum_d> pProjectileLab{rootCS, {0_GeV, 1_PeV, 0_GeV}};
+  HEPEnergyType const eProjectileLab = energy(projectileMass, pProjectileLab);
+
+  // define target kinematics in lab frame
+  HEPMassType const targetMass = 1_GeV;
+  Vector<hepmomentum_d> pTargetLab{rootCS, {0_eV, 0_eV, 0_eV}};
+  HEPEnergyType const eTargetLab = energy(targetMass, pTargetLab);
+
+  // define boost to com frame
+  COMBoost boost(eProjectileLab, pProjectileLab, targetMass);
+
+  // boost projecticle
+  auto const [eProjectileCoM, pProjectileCoM] =
+      boost.toCoM(eProjectileLab, pProjectileLab);
+
+  // boost target
+  auto const [eTargetCoM, pTargetCoM] = boost.toCoM(eTargetLab, pTargetLab);
+
+  // sum of momenta in CoM, should be 0
+  auto const sumPCoM = pProjectileCoM + pTargetCoM;
+  CHECK(sumPCoM[2] / 1_GeV == Approx(0).margin(absMargin));
+
+  // mandelstam-s should be invariant under transformation
+  CHECK(s(eProjectileLab + eTargetLab,
+          pProjectileLab.GetComponents() + pTargetLab.GetComponents()) /
+            1_GeV / 1_GeV ==
+        Approx(s(eProjectileCoM + eTargetCoM, pProjectileCoM + pTargetCoM) / 1_GeV /
+               1_GeV));
+
+  // boost back...
+  auto const [eProjectileBack, pProjectileBack] =
+      boost.fromCoM(eProjectileCoM, pProjectileCoM);
+
+  // ...should yield original values before the boosts
+  CHECK(eProjectileBack / eProjectileLab == Approx(1));
+  CHECK((pProjectileBack - pProjectileLab).norm() / pProjectileLab.norm() ==
+        Approx(0).margin(absMargin));
 }
diff --git a/Processes/Sibyll/Decay.h b/Processes/Sibyll/Decay.h
index 13c6a3ebc094b7618ca694fb7b2b74786571cdcc..a798f318db53e994ba7a1edff828e9010dec979d 100644
--- a/Processes/Sibyll/Decay.h
+++ b/Processes/Sibyll/Decay.h
@@ -136,8 +136,8 @@ namespace corsika::process {
         using std::endl;
         using namespace corsika::units::si;
 
-        corsika::units::hep::EnergyType E = p.GetEnergy();
-        corsika::units::hep::MassType m = corsika::particles::GetMass(p.GetPID());
+        corsika::units::si::HEPEnergyType E = p.GetEnergy();
+        corsika::units::si::HEPMassType m = corsika::particles::GetMass(p.GetPID());
 
         const double gamma = E / m;
 
diff --git a/Processes/Sibyll/Interaction.h b/Processes/Sibyll/Interaction.h
index fef98eb924f2a0a2d537766eebc3cfa309742aa1..fac0dd578b77cfea776b1b942b6a42b9e899f809 100644
--- a/Processes/Sibyll/Interaction.h
+++ b/Processes/Sibyll/Interaction.h
@@ -53,7 +53,6 @@ namespace corsika::process::sibyll {
     corsika::units::si::GrammageType GetInteractionLength(Particle& p, Track&) {
 
       using namespace corsika::units;
-      using namespace corsika::units::hep;
       using namespace corsika::units::si;
       using namespace corsika::geometry;
       using std::cout;
@@ -79,26 +78,27 @@ namespace corsika::process::sibyll {
       // FOR NOW: assume target is oxygen
       const int kTarget = corsika::particles::Oxygen::GetNucleusA();
 
-      const hep::MassType nucleon_mass = 0.5 * (corsika::particles::Proton::GetMass() +
-                                                corsika::particles::Neutron::GetMass());
-      hep::EnergyType Etot = p.GetEnergy() + nucleon_mass;
+      const HEPMassType nucleon_mass = 0.5 * (corsika::particles::Proton::GetMass() +
+                                              corsika::particles::Neutron::GetMass());
+      HEPEnergyType const Elab = p.GetEnergy();
+      HEPEnergyType const Etot = Elab + nucleon_mass;
       MomentumVector Ptot(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV});
       // FOR NOW: assume target is at rest
       MomentumVector pTarget(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV});
       Ptot += p.GetMomentum();
       Ptot += pTarget;
       // calculate cm. energy
-      const hep::EnergyType sqs = sqrt(Etot * Etot - Ptot.squaredNorm());
+      const HEPEnergyType sqs = sqrt(Etot * Etot - Ptot.squaredNorm());
       const double Ecm = sqs / 1_GeV;
 
       std::cout << "Interaction: LambdaInt: \n"
-                << " input energy: " << p.GetEnergy() / 1_GeV << endl
+                << " input energy: " << Elab / 1_GeV << endl
                 << " beam can interact:" << kBeam << endl
                 << " beam XS code:" << kBeam << endl
                 << " beam pid:" << p.GetPID() << endl
                 << " target mass number:" << kTarget << std::endl;
 
-      if (kInteraction) {
+      if (kInteraction && Elab >= 8.5_GeV && sqs >= 10_GeV) {
 
         double prodCrossSection, dummy, dum1, dum2, dum3, dum4;
         double dumdif[3];
@@ -114,12 +114,10 @@ namespace corsika::process::sibyll {
         std::cout << "Interaction: "
                   << "MinStep: CrossSection (mb): " << sig / 1_mbarn << std::endl;
 
-        const si::MassType nucleon_mass =
-            0.93827_GeV / corsika::units::constants::cSquared;
         std::cout << "Interaction: "
                   << "nucleon mass " << nucleon_mass << std::endl;
         // calculate interaction length in medium
-        GrammageType int_length = kTarget * nucleon_mass / sig;
+        GrammageType int_length = kTarget * corsika::units::constants::u / sig;
         std::cout << "Interaction: "
                   << "interaction length (g/cm2): " << int_length << std::endl;
 
@@ -134,7 +132,6 @@ namespace corsika::process::sibyll {
 
       using namespace corsika::units;
       using namespace corsika::utl;
-      using namespace corsika::units::hep;
       using namespace corsika::units::si;
       using namespace corsika::geometry;
       using std::cout;
@@ -188,9 +185,9 @@ namespace corsika::process::sibyll {
             GetNucleusA(); // env.GetTargetParticle().GetPID();
 
         // FOR NOW: target is always at rest
-        const hep::MassType nucleon_mass = 0.5 * (corsika::particles::Proton::GetMass() +
-                                                  corsika::particles::Neutron::GetMass());
-        const EnergyType Etarget = 0_GeV + nucleon_mass;
+        auto constexpr nucleon_mass = 0.5 * (corsika::particles::Proton::GetMass() +
+                                         corsika::particles::Neutron::GetMass());
+        const auto Etarget = 0_GeV + nucleon_mass;
         const auto pTarget = MomentumVector(rootCS, 0_GeV, 0_GeV, 0_GeV);
         cout << "target momentum (GeV/c): " << pTarget.GetComponents() / 1_GeV << endl;
         cout << "beam momentum (GeV/c): " << p.GetMomentum().GetComponents() / 1_GeV
@@ -210,12 +207,12 @@ namespace corsika::process::sibyll {
         */
         // total energy: E_beam + E_target
         // in lab. frame: E_beam + m_target*c**2
-        EnergyType E = p.GetEnergy();
-        EnergyType Etot = E + Etarget;
+        HEPEnergyType E = p.GetEnergy();
+        HEPEnergyType Etot = E + Etarget;
         // total momentum
         MomentumVector Ptot = p.GetMomentum();
         // invariant mass, i.e. cm. energy
-        EnergyType Ecm = sqrt(Etot * Etot - Ptot.squaredNorm());
+        HEPEnergyType Ecm = sqrt(Etot * Etot - Ptot.squaredNorm());
         /*
          get transformation between Stack-frame and SibStack-frame
          for EAS Stack-frame is lab. frame, could be different for CRMC-mode
@@ -229,25 +226,25 @@ namespace corsika::process::sibyll {
         std::cout << "Interaction: "
                   << " DoDiscrete: gambet:" << gambet.GetComponents() << endl;
 
-	Vector<si::momentum_d> pProjectileLab = p.GetMomentum() / constants::c;
+	auto const pProjectileLab = p.GetMomentum();
 	//{rootCS, {0_GeV / c, 1_PeV / c, 0_GeV / c}};
-	EnergyType const eProjectileLab = p.GetEnergy();
+	HEPEnergyType const eProjectileLab = p.GetEnergy();
 	  //energy(projectileMass, pProjectileLab);
 
 	// define target kinematics in lab frame
-	si::MassType const targetMass = nucleon_mass / constants::cSquared;
+	HEPMassType const targetMass = nucleon_mass;
 	// define boost to com frame
-	COMBoost boost(eProjectileLab, pProjectileLab, targetMass);
+	COMBoost const boost(eProjectileLab, pProjectileLab, targetMass);
 
 	cout << "Interaction: new boost: ebeam lab: " << eProjectileLab / 1_GeV << endl
-	     << "Interaction: new boost: pbeam lab: " << pProjectileLab.GetComponents() / ( 1_GeV / constants::c ) << endl;
+	     << "Interaction: new boost: pbeam lab: " << pProjectileLab.GetComponents() / 1_GeV << endl;
 
 	// boost projecticle
 	auto const [eProjectileCoM, pProjectileCoM] =
 	  boost.toCoM(eProjectileLab, pProjectileLab);
 
 	cout << "Interaction: new boost: ebeam com: " << eProjectileCoM / 1_GeV << endl
-	     << "Interaction: new boost: pbeam com: " << pProjectileCoM / ( 1_GeV / constants::c ) << endl;
+	     << "Interaction: new boost: pbeam com: " << pProjectileCoM / 1_GeV << endl;
 	
         int kBeam = process::sibyll::ConvertToSibyllRaw(p.GetPID());
 
@@ -283,7 +280,7 @@ namespace corsika::process::sibyll {
 
           // momentum array in Sibyll
           MomentumVector Plab_final(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV});
-          EnergyType E_final = 0_GeV, Ecm_final = 0_GeV;
+          HEPEnergyType E_final = 0_GeV, Ecm_final = 0_GeV;
           for (auto& psib : ss) {
 
             // skip particles that have decayed in Sibyll
@@ -302,10 +299,10 @@ namespace corsika::process::sibyll {
             // rotatate to rootCS
             const auto pSibyllComponents = SibVector.GetComponents(rootCS);
             // boost to lab. frame
-            hep::EnergyType en_lab = 0. * 1_GeV;
-            hep::MomentumType p_lab_components[3];
+            HEPEnergyType en_lab = 0. * 1_GeV;
+            HEPMomentumType p_lab_components[3];
             en_lab = psib.GetEnergy() * gamma;
-            hep::EnergyType pnorm = 0. * 1_GeV;
+            HEPEnergyType pnorm = 0. * 1_GeV;
             for (int j = 0; j < 3; ++j)
               pnorm += (pSibyllComponents[j] * gammaBetaComponents[j]) / (gamma + 1.);
             pnorm += psib.GetEnergy();
@@ -320,7 +317,7 @@ namespace corsika::process::sibyll {
             auto pnew = s.NewParticle();
             pnew.SetEnergy(en_lab);
             pnew.SetPID(process::sibyll::ConvertFromSibyll(psib.GetPID()));
-            corsika::geometry::QuantityVector<energy_hep_d> p_lab_c{
+            corsika::geometry::QuantityVector<hepmomentum_d> p_lab_c{
                 p_lab_components[0], p_lab_components[1], p_lab_components[2]};
             pnew.SetMomentum(MomentumVector(rootCS, p_lab_c));
             pnew.SetPosition(pOrig);
diff --git a/Processes/Sibyll/SibStack.h b/Processes/Sibyll/SibStack.h
index bc3dc4c0fba66fadba4e277c0e305f01b65b1131..83d902f5c2b030ed455afbbe38867fa8b50dbf3c 100644
--- a/Processes/Sibyll/SibStack.h
+++ b/Processes/Sibyll/SibStack.h
@@ -21,7 +21,7 @@
 
 namespace corsika::process::sibyll {
 
-  typedef corsika::geometry::Vector<corsika::units::hep::energy_hep_d> MomentumVector;
+  typedef corsika::geometry::Vector<corsika::units::si::hepmomentum_d> MomentumVector;
 
   class SibStackData {
 
@@ -35,30 +35,29 @@ namespace corsika::process::sibyll {
     int GetCapacity() const { return 8000; }
 
     void SetId(const int i, const int v) { s_plist_.llist[i] = v; }
-    void SetEnergy(const int i, const corsika::units::hep::EnergyType v) {
-      using namespace corsika::units::hep;
+    void SetEnergy(const int i, const corsika::units::si::HEPEnergyType v) {
+      using namespace corsika::units::si;
       s_plist_.p[3][i] = v / 1_GeV;
     }
-    void SetMass(const int i, const corsika::units::hep::MassType v) {
-      using namespace corsika::units::hep;
+    void SetMass(const int i, const corsika::units::si::HEPMassType v) {
+      using namespace corsika::units::si;
       s_plist_.p[4][i] = v / 1_GeV;
     }
 
     void SetMomentum(const int i, const MomentumVector& v) {
-      using namespace corsika::units;
-      using namespace corsika::units::hep;
+      using namespace corsika::units::si;
       auto tmp = v.GetComponents();
       for (int idx = 0; idx < 3; ++idx) s_plist_.p[idx][i] = tmp[idx] / 1_GeV;
     }
 
     int GetId(const int i) const { return s_plist_.llist[i]; }
 
-    corsika::units::hep::EnergyType GetEnergy(const int i) const {
-      using namespace corsika::units::hep;
+    corsika::units::si::HEPEnergyType GetEnergy(const int i) const {
+      using namespace corsika::units::si;
       return s_plist_.p[3][i] * 1_GeV;
     }
-    corsika::units::hep::EnergyType GetMass(const int i) const {
-      using namespace corsika::units::hep;
+    corsika::units::si::HEPEnergyType GetMass(const int i) const {
+      using namespace corsika::units::si;
       return s_plist_.p[4][i] * 1_GeV;
     }
 
@@ -66,10 +65,10 @@ namespace corsika::process::sibyll {
       using corsika::geometry::CoordinateSystem;
       using corsika::geometry::QuantityVector;
       using corsika::geometry::RootCoordinateSystem;
-      using namespace corsika::units::hep;
+      using namespace corsika::units::si;
       CoordinateSystem& rootCS =
           RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
-      QuantityVector<energy_hep_d> components = {
+      QuantityVector<hepmomentum_d> components = {
           s_plist_.p[0][i] * 1_GeV, s_plist_.p[1][i] * 1_GeV, s_plist_.p[2][i] * 1_GeV};
       MomentumVector v1(rootCS, components);
       return v1;
@@ -94,29 +93,33 @@ namespace corsika::process::sibyll {
     using corsika::stack::ParticleBase<StackIteratorInterface>::GetIndex;
 
   public:
-    void SetEnergy(const corsika::units::hep::EnergyType v) {
+    void SetEnergy(const corsika::units::si::HEPEnergyType v) {
       GetStackData().SetEnergy(GetIndex(), v);
     }
-    corsika::units::hep::EnergyType GetEnergy() const {
+
+    corsika::units::si::HEPEnergyType GetEnergy() const {
       return GetStackData().GetEnergy(GetIndex());
     }
 
-    void SetMass(const corsika::units::hep::MassType v) {
+    bool HasDecayed() const { return abs(GetStackData().GetId(GetIndex())) > 100; }
+
+    void SetMass(const corsika::units::si::HEPMassType v) {
       GetStackData().SetMass(GetIndex(), v);
     }
-    corsika::units::hep::EnergyType GetMass() const {
+
+    corsika::units::si::HEPEnergyType GetMass() const {
       return GetStackData().GetMass(GetIndex());
     }
 
-    bool HasDecayed() const {
-      return abs(GetStackData().GetId(GetIndex())) > 100 ? true : false;
-    }
     void SetPID(const int v) { GetStackData().SetId(GetIndex(), v); }
+
     corsika::process::sibyll::SibyllCode GetPID() const {
       return static_cast<corsika::process::sibyll::SibyllCode>(
           GetStackData().GetId(GetIndex()));
     }
+
     MomentumVector GetMomentum() const { return GetStackData().GetMomentum(GetIndex()); }
+
     void SetMomentum(const MomentumVector& v) {
       GetStackData().SetMomentum(GetIndex(), v);
     }
diff --git a/Processes/Sibyll/testSibyll.cc b/Processes/Sibyll/testSibyll.cc
index 8c171cdce00edf619cd0fbd968d3495233ca66f9..3d7d425d9c63aaacf5ffcef5723dfac730283b7e 100644
--- a/Processes/Sibyll/testSibyll.cc
+++ b/Processes/Sibyll/testSibyll.cc
@@ -106,9 +106,9 @@ TEST_CASE("SibyllInterface", "[processes]") {
     setup::Stack stack;
     auto particle = stack.NewParticle();
     {
-      const hep::EnergyType E0 = 10_GeV;
+      const HEPEnergyType E0 = 10_GeV;
       particle.SetPID(particles::Code::Proton);
-      hep::MomentumType P0 = sqrt(E0 * E0 - particles::Proton::GetMass() * particles::Proton::GetMass());
+      HEPMomentumType P0 = sqrt(E0 * E0 - particles::Proton::GetMass() * particles::Proton::GetMass());
       auto plab = stack::super_stupid::MomentumVector(cs, {0_GeV, 0_GeV, -P0});
       particle.SetEnergy(E0);
       particle.SetMomentum(plab);
diff --git a/Processes/StackInspector/StackInspector.cc b/Processes/StackInspector/StackInspector.cc
index 39b59505eaba16853a06807d42ed91a56dcb9750..184eae5b543b9779696ccbd5b45036ed95edcfe4 100644
--- a/Processes/StackInspector/StackInspector.cc
+++ b/Processes/StackInspector/StackInspector.cc
@@ -41,10 +41,10 @@ process::EProcessReturn StackInspector<Stack>::DoContinuous(Particle&, setup::Tr
 
   if (!fReport) return process::EProcessReturn::eOk;
   [[maybe_unused]] int i = 0;
-  EnergyType Etot = 0_GeV;
+  HEPEnergyType Etot = 0_GeV;
 
   for (auto& iterP : s) {
-    EnergyType E = iterP.GetEnergy();
+    HEPEnergyType E = iterP.GetEnergy();
     Etot += E;
     geometry::CoordinateSystem& rootCS = geometry::RootCoordinateSystem::GetInstance()
                                              .GetRootCoordinateSystem(); // for printout
diff --git a/Processes/TrackingLine/testTrackingLine.cc b/Processes/TrackingLine/testTrackingLine.cc
index 285f275c0ae53ab2b6b128be270860819326cac6..845d3268b619b919e2197298c13ea625bf8113d8 100644
--- a/Processes/TrackingLine/testTrackingLine.cc
+++ b/Processes/TrackingLine/testTrackingLine.cc
@@ -33,14 +33,14 @@ using namespace corsika::geometry;
 using namespace std;
 using namespace corsika::units::si;
 
-typedef corsika::units::hep::energy_hep_d MOMENTUM;
+typedef corsika::units::si::hepmomentum_d MOMENTUM;
 
 struct DummyParticle {
-  EnergyType fEnergy;
+  HEPEnergyType fEnergy;
   Vector<MOMENTUM> fMomentum;
   Point fPosition;
 
-  DummyParticle(EnergyType pEnergy, Vector<MOMENTUM> pMomentum, Point pPosition)
+  DummyParticle(HEPEnergyType pEnergy, Vector<MOMENTUM> pMomentum, Point pPosition)
       : fEnergy(pEnergy)
       , fMomentum(pMomentum)
       , fPosition(pPosition) {}
@@ -89,7 +89,7 @@ TEST_CASE("TrackingLine") {
 
     //~ std::cout << env.GetUniverse().get() << std::endl;
 
-    DummyParticle p(1_J, Vector<MOMENTUM>(cs, 0_GeV, 0_GeV, 1_GeV),
+    DummyParticle p(1_GeV, Vector<MOMENTUM>(cs, 0_GeV, 0_GeV, 1_GeV),
                     Point(cs, 0_m, 0_m, 0_m));
 
     auto const radius = 20_m;
diff --git a/Stack/SuperStupidStack/SuperStupidStack.h b/Stack/SuperStupidStack/SuperStupidStack.h
index 481f8d48dc1abab991086e63d1f3b0962313844f..044ae32a1ae5adcabe5adaf9b5bc5b149d85aca1 100644
--- a/Stack/SuperStupidStack/SuperStupidStack.h
+++ b/Stack/SuperStupidStack/SuperStupidStack.h
@@ -29,7 +29,7 @@ namespace corsika::stack {
 
   namespace super_stupid {
 
-    typedef corsika::geometry::Vector<corsika::units::hep::energy_hep_d> MomentumVector;
+    typedef corsika::geometry::Vector<corsika::units::si::hepmomentum_d> MomentumVector;
 
     /**
      * Example of a particle object on the stack.
@@ -46,7 +46,7 @@ namespace corsika::stack {
         GetStackData().SetPID(GetIndex(), id);
       }
 
-      void SetEnergy(const corsika::units::hep::EnergyType& e) {
+      void SetEnergy(const corsika::units::si::HEPEnergyType& e) {
         GetStackData().SetEnergy(GetIndex(), e);
       }
 
@@ -66,7 +66,7 @@ namespace corsika::stack {
         return GetStackData().GetPID(GetIndex());
       }
 
-      corsika::units::hep::EnergyType GetEnergy() const {
+      corsika::units::si::HEPEnergyType GetEnergy() const {
         return GetStackData().GetEnergy(GetIndex());
       }
 
@@ -82,9 +82,9 @@ namespace corsika::stack {
         return GetStackData().GetTime(GetIndex());
       }
 
-      corsika::geometry::Vector<corsika::units::si::SpeedType::dimension_type>
-      GetDirection() const {
-        return GetMomentum() / GetEnergy() * corsika::units::constants::c;
+      corsika::geometry::Vector<corsika::units::si::dimensionless_d> GetDirection()
+          const {
+        return GetMomentum() / GetEnergy();
       }
     };
 
@@ -112,7 +112,7 @@ namespace corsika::stack {
 
       void SetPID(const int i, const corsika::particles::Code id) { fDataPID[i] = id; }
 
-      void SetEnergy(const int i, const corsika::units::hep::EnergyType e) {
+      void SetEnergy(const int i, const corsika::units::si::HEPEnergyType e) {
         fDataE[i] = e;
       }
       void SetMomentum(const int i, const MomentumVector& v) { fMomentum[i] = v; }
@@ -125,7 +125,7 @@ namespace corsika::stack {
 
       corsika::particles::Code GetPID(const int i) const { return fDataPID[i]; }
 
-      corsika::units::hep::EnergyType GetEnergy(const int i) const { return fDataE[i]; }
+      corsika::units::si::HEPEnergyType GetEnergy(const int i) const { return fDataE[i]; }
 
       MomentumVector GetMomentum(const int i) const { return fMomentum[i]; }
 
@@ -160,13 +160,14 @@ namespace corsika::stack {
         using corsika::geometry::Point;
         using corsika::particles::Code;
         fDataPID.push_back(Code::Unknown);
-        fDataE.push_back(0 * corsika::units::si::joule);
+        fDataE.push_back(0 * corsika::units::si::electronvolt);
         //#TODO this here makes no sense: see issue #48
         geometry::CoordinateSystem& dummyCS =
             geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
         fMomentum.push_back(MomentumVector(
-            dummyCS, {0 * corsika::units::si::joule, 0 * corsika::units::si::joule,
-                      0 * corsika::units::si::joule}));
+            dummyCS,
+            {0 * corsika::units::si::electronvolt, 0 * corsika::units::si::electronvolt,
+             0 * corsika::units::si::electronvolt}));
         fPosition.push_back(
             Point(dummyCS, {0 * corsika::units::si::meter, 0 * corsika::units::si::meter,
                             0 * corsika::units::si::meter}));
@@ -187,7 +188,7 @@ namespace corsika::stack {
       /// the actual memory to store particle data
 
       std::vector<corsika::particles::Code> fDataPID;
-      std::vector<corsika::units::hep::EnergyType> fDataE;
+      std::vector<corsika::units::si::HEPEnergyType> fDataE;
       std::vector<MomentumVector> fMomentum;
       std::vector<corsika::geometry::Point> fPosition;
       std::vector<corsika::units::si::TimeType> fTime;
diff --git a/ThirdParty/phys/units/physical_constants.hpp b/ThirdParty/phys/units/physical_constants.hpp
index 8a5669d57908974c8e3d850892299ee6935ced87..131dfb03c1ee8497254f7d39f50bc3373136331d 100644
--- a/ThirdParty/phys/units/physical_constants.hpp
+++ b/ThirdParty/phys/units/physical_constants.hpp
@@ -24,35 +24,34 @@
 
 #include "phys/units/quantity.hpp"
 
-namespace phys { namespace units {
+namespace phys {
+  namespace units {
 
-// acceleration of free-fall, standard
-constexpr quantity< acceleration_d >
-                                g_sub_n { Rep( 9.80665L ) * meter / square( second ) };
+    // acceleration of free-fall, standard
+    constexpr quantity<acceleration_d> g_sub_n{Rep(9.80665L) * meter / square(second)};
 
-// Avogadro constant
-constexpr quantity< dimensions< 0, 0, 0, 0, 0, -1 > >
-                                N_sub_A { Rep( 6.02214199e+23L ) / mole };
-// electronvolt
-constexpr quantity< energy_d >  eV { Rep( 1.60217733e-19L ) * joule };
+    // Avogadro constant
+    constexpr quantity<dimensions<0, 0, 0, 0, 0, -1> > N_sub_A{Rep(6.02214199e+23L) /
+                                                               mole};
+    // electronvolt
+    // constexpr quantity< energy_d >  eV { Rep( 1.60217733e-19L ) * joule };
 
-// elementary charge
-constexpr quantity< electric_charge_d >
-                                e { Rep( 1.602176462e-19L ) * coulomb };
+    // elementary charge
+    constexpr quantity<electric_charge_d> e{Rep(1.602176462e-19L) * coulomb};
 
-// Planck constant
-constexpr quantity< dimensions< 2, 1, -1 > >
-                                h { Rep( 6.62606876e-34L ) * joule * second };
+    // Planck constant
+    constexpr quantity<dimensions<2, 1, -1> > h{Rep(6.62606876e-34L) * joule * second};
 
-// speed of light in a vacuum
-constexpr quantity< speed_d >   c { Rep( 299792458L ) * meter / second };
+    // speed of light in a vacuum
+    constexpr quantity<speed_d> c{Rep(299792458L) * meter / second};
 
-// unified atomic mass unit
-constexpr quantity< mass_d >    u { Rep( 1.6605402e-27L ) * kilogram };
+    // unified atomic mass unit
+    constexpr quantity<mass_d> u{Rep(1.6605402e-27L) * kilogram};
 
-// etc.
+    // etc.
 
-}} // namespace phys { namespace units {
+  } // namespace units
+} // namespace phys
 
 #endif // PHYS_UNITS_PHYSICAL_CONSTANTS_HPP_INCLUDED
 
diff --git a/ThirdParty/phys/units/quantity.hpp b/ThirdParty/phys/units/quantity.hpp
index 5f764409d6939ea43c393e254f2f62208c192f87..890061b950a0bb84903a271115eed9e89016b3e8 100644
--- a/ThirdParty/phys/units/quantity.hpp
+++ b/ThirdParty/phys/units/quantity.hpp
@@ -1,9 +1,8 @@
 /**
  * \file quantity.hpp
  *
- * \brief   Zero-overhead dimensional analysis and unit/quantity manipulation and conversion.
- * \author  Michael S. Kenniston, Martin Moene
- * \date    7 September 2013
+ * \brief   Zero-overhead dimensional analysis and unit/quantity manipulation and
+ * conversion. \author  Michael S. Kenniston, Martin Moene \date    7 September 2013
  * \since   0.4
  *
  * Copyright 2013 Universiteit Leiden. All rights reserved.
@@ -31,36 +30,36 @@
 
 #include <cmath>
 #include <cstdlib>
-#include <utility>  // std::declval
+#include <utility> // std::declval
 
 /// namespace phys.
 
 namespace phys {
 
-/// namespace units.
+  /// namespace units.
 
-namespace units {
+  namespace units {
 
 #ifdef PHYS_UNITS_REP_TYPE
-   using Rep = PHYS_UNITS_REP_TYPE;
+    using Rep = PHYS_UNITS_REP_TYPE;
 #else
-   using Rep = double;
+    using Rep = double;
 #endif
 
-/*
- * declare now, define later.
- */
-template< typename Dims, typename T = Rep >
-class quantity;
+    /*
+     * declare now, define later.
+     */
+    template <typename Dims, typename T = Rep>
+    class quantity;
 
-/**
- * We could drag dimensions around individually, but it's much more convenient to package them.
- */
-template< int D1, int D2, int D3, int D4 = 0, int D5 = 0, int D6 = 0, int D7 = 0 >
-struct dimensions
-{
-    enum
-    {
+    /**
+     * We could drag dimensions around individually, but it's much more convenient to
+     * package them.
+     */
+    template <int D1, int D2, int D3, int D4 = 0, int D5 = 0, int D6 = 0, int D7 = 0,
+              int D8 = 0>
+    struct dimensions {
+      enum {
         dim1 = D1,
         dim2 = D2,
         dim3 = D3,
@@ -68,897 +67,835 @@ struct dimensions
         dim5 = D5,
         dim6 = D6,
         dim7 = D7,
+        dim8 = D8,
+
+        is_all_zero = D1 == 0 && D2 == 0 && D3 == 0 && D4 == 0 && D5 == 0 && D6 == 0 &&
+                      D7 == 0 && D8 == 0,
+
+        is_base = 1 == (D1 != 0) + (D2 != 0) + (D3 != 0) + (D4 != 0) + (D5 != 0) +
+                           (D6 != 0) + (D7 != 0) + (D8 != 0) &&
+                  1 == D1 + D2 + D3 + D4 + D5 + D6 + D7 + D8,
+      };
+
+      template <int R1, int R2, int R3, int R4, int R5, int R6, int R7, int R8>
+      constexpr bool operator==(dimensions<R1, R2, R3, R4, R5, R6, R7, R8> const&) const {
+        return D1 == R1 && D2 == R2 && D3 == R3 && D4 == R4 && D5 == R5 && D6 == R6 &&
+               D7 == R7 && D8 == R8;
+      }
+
+      template <int R1, int R2, int R3, int R4, int R5, int R6, int R7, int R8>
+      constexpr bool operator!=(
+          dimensions<R1, R2, R3, R4, R5, R6, R7, R8> const& rhs) const {
+        return !(*this == rhs);
+      }
+    };
 
-        is_all_zero =
-            D1 == 0 && D2 == 0 && D3 == 0 && D4 == 0 && D5 == 0 && D6 == 0 && D7 == 0,
+    /// demensionless 'dimension'.
+
+    typedef dimensions<0, 0, 0> dimensionless_d;
+
+    /// namespace detail.
+
+    namespace detail {
+
+      /**
+       * \brief The "collapse" template is used to avoid quantity< dimensions< 0, 0, 0 >
+       * >, i.e. to make dimensionless results come out as type "Rep".
+       */
+      template <typename D, typename T>
+      struct collapse {
+        typedef quantity<D, T> type;
+      };
+
+      template <typename T>
+      struct collapse<dimensionless_d, T> {
+        typedef T type;
+      };
+
+      template <typename D, typename T>
+      using Collapse = typename collapse<D, T>::type;
+
+      // promote types of expression to result type.
+
+      template <typename X, typename Y>
+      using PromoteAdd = decltype(std::declval<X>() + std::declval<Y>());
+
+      template <typename X, typename Y>
+      using PromoteMul = decltype(std::declval<X>() * std::declval<Y>());
+
+      /*
+       * The following batch of structs are type generators to calculate
+       * the correct type of the result of various operations.
+       */
+
+      /**
+       * product type generator.
+       */
+      template <typename DX, typename DY, typename T>
+      struct product {
+        enum {
+          d1 = DX::dim1 + DY::dim1,
+          d2 = DX::dim2 + DY::dim2,
+          d3 = DX::dim3 + DY::dim3,
+          d4 = DX::dim4 + DY::dim4,
+          d5 = DX::dim5 + DY::dim5,
+          d6 = DX::dim6 + DY::dim6,
+          d7 = DX::dim7 + DY::dim7,
+          d8 = DX::dim8 + DY::dim8
+        };
+
+        typedef Collapse<dimensions<d1, d2, d3, d4, d5, d6, d7, d8>, T> type;
+      };
+
+      template <typename DX, typename DY, typename X, typename Y>
+      using Product = typename product<DX, DY, PromoteMul<X, Y>>::type;
+
+      /**
+       * quotient type generator.
+       */
+      template <typename DX, typename DY, typename T>
+      struct quotient {
+        enum {
+          d1 = DX::dim1 - DY::dim1,
+          d2 = DX::dim2 - DY::dim2,
+          d3 = DX::dim3 - DY::dim3,
+          d4 = DX::dim4 - DY::dim4,
+          d5 = DX::dim5 - DY::dim5,
+          d6 = DX::dim6 - DY::dim6,
+          d7 = DX::dim7 - DY::dim7,
+          d8 = DX::dim8 - DY::dim8
+        };
+
+        typedef Collapse<dimensions<d1, d2, d3, d4, d5, d6, d7, d8>, T> type;
+      };
+
+      template <typename DX, typename DY, typename X, typename Y>
+      using Quotient = typename quotient<DX, DY, PromoteMul<X, Y>>::type;
+
+      /**
+       * reciprocal type generator.
+       */
+      template <typename D, typename T>
+      struct reciprocal {
+        enum {
+          d1 = -D::dim1,
+          d2 = -D::dim2,
+          d3 = -D::dim3,
+          d4 = -D::dim4,
+          d5 = -D::dim5,
+          d6 = -D::dim6,
+          d7 = -D::dim7,
+          d8 = -D::dim8
+        };
+
+        typedef Collapse<dimensions<d1, d2, d3, d4, d5, d6, d7, d8>, T> type;
+      };
+
+      template <typename D, typename X, typename Y>
+      using Reciprocal = typename reciprocal<D, PromoteMul<X, Y>>::type;
+
+      /**
+       * power type generator.
+       */
+      template <typename D, int N, typename T>
+      struct power {
+        enum {
+          d1 = N * D::dim1,
+          d2 = N * D::dim2,
+          d3 = N * D::dim3,
+          d4 = N * D::dim4,
+          d5 = N * D::dim5,
+          d6 = N * D::dim6,
+          d7 = N * D::dim7,
+          d8 = N * D::dim8
+        };
+
+        typedef Collapse<dimensions<d1, d2, d3, d4, d5, d6, d7, d8>, T> type;
+      };
+
+      template <typename D, int N, typename T>
+      using Power = typename detail::power<D, N, T>::type;
+
+      /**
+       * root type generator.
+       */
+      template <typename D, int N, typename T>
+      struct root {
+        enum {
+          all_even_multiples = D::dim1 % N == 0 && D::dim2 % N == 0 && D::dim3 % N == 0 &&
+                               D::dim4 % N == 0 && D::dim5 % N == 0 && D::dim6 % N == 0 &&
+                               D::dim7 % N == 0 && D::dim8 % N == 0
+        };
+
+        enum {
+          d1 = D::dim1 / N,
+          d2 = D::dim2 / N,
+          d3 = D::dim3 / N,
+          d4 = D::dim4 / N,
+          d5 = D::dim5 / N,
+          d6 = D::dim6 / N,
+          d7 = D::dim7 / N,
+          d8 = D::dim8 / N
+        };
+
+        typedef Collapse<dimensions<d1, d2, d3, d4, d5, d6, d7, d8>, T> type;
+      };
+
+      template <typename D, int N, typename T>
+      using Root = typename detail::root<D, N, T>::type;
+
+      /**
+       * tag to construct a quantity from a magnitude.
+       */
+      constexpr struct magnitude_tag_t { } magnitude_tag{}; } // namespace detail
 
-        is_base =
-            1 == (D1 != 0) + (D2 != 0) + (D3 != 0) + (D4 != 0) + (D5 != 0) + (D6 != 0) + (D7 != 0)  &&
-            1 ==  D1 + D2 + D3 + D4 + D5 + D6 + D7,
-    };
+    /**
+     * \brief class "quantity" is the heart of the library. It associates
+     * dimensions  with a single "Rep" data member and protects it from
+     * dimensionally inconsistent use.
+     */
+    template <typename Dims, typename T /*= Rep */>
+    class quantity {
+    public:
+      typedef Dims dimension_type;
+
+      typedef T value_type;
+
+      typedef quantity<Dims, T> this_type;
+
+      constexpr quantity()
+          : m_value{} {}
+
+      /**
+       * public converting initializing constructor;
+       * requires magnitude_tag to prevent constructing a quantity from a raw magnitude.
+       */
+      template <typename X>
+      constexpr explicit quantity(detail::magnitude_tag_t, X x)
+          : m_value(x) {}
+
+      /**
+       * converting copy-assignment constructor.
+       */
+      template <typename X>
+      constexpr quantity(quantity<Dims, X> const& x)
+          : m_value(x.magnitude()) {}
+
+      //    /**
+      //     * convert to compatible unit, for example: (3._dm).to(meter) gives 0.3;
+      //     */
+      //    constexpr value_type to( quantity const & x ) const {  return *this / x; }
+
+      /**
+       * convert to given unit, for example: (3._dm).to(meter) gives 0.3;
+       */
+      template <typename DX, typename X>
+      constexpr auto to(quantity<DX, X> const& x) const
+          -> detail::Quotient<Dims, DX, T, X> {
+        return *this / x;
+      }
 
-    template< int R1, int R2, int R3, int R4, int R5, int R6, int R7 >
-    constexpr bool operator==( dimensions<R1, R2, R3, R4, R5, R6, R7> const & ) const
-    {
-        return D1==R1 && D2==R2 && D3==R3 && D4==R4 && D5==R5 && D6==R6 && D7==R7;
-    }
+      /**
+       * the quantity's magnitude.
+       */
+      constexpr value_type magnitude() const { return m_value; }
 
-    template< int R1, int R2, int R3, int R4, int R5, int R6, int R7 >
-    constexpr bool operator!=( dimensions<R1, R2, R3, R4, R5, R6, R7> const & rhs ) const
-    {
-        return !( *this == rhs );
-    }
-};
+      /**
+       * the quantity's dimensions.
+       */
+      constexpr dimension_type dimension() const { return dimension_type{}; }
 
-/// demensionless 'dimension'.
+      /**
+       * We need a "zero" of each type -- for comparisons, to initialize running
+       * totals, etc.  Note:  0 m != 0 kg, since they are of different dimensionality.
+       * zero is really just defined for convenience, since
+       * quantity< length_d >::zero == 0 * meter, etc.
+       */
+      static constexpr quantity zero() { return quantity{value_type(0.0)}; }
+      //    static constexpr quantity zero = quantity{ value_type( 0.0 ) };
 
-typedef dimensions< 0, 0, 0 > dimensionless_d;
+    private:
+      /**
+       * private initializing constructor.
+       */
+      constexpr explicit quantity(value_type x)
+          : m_value{x} {}
 
-/// namespace detail.
+    private:
+      value_type m_value;
 
-namespace detail {
+      enum { has_dimension = !Dims::is_all_zero };
 
-/**
- * \brief The "collapse" template is used to avoid quantity< dimensions< 0, 0, 0 > >,
- * i.e. to make dimensionless results come out as type "Rep".
- */
-template< typename D, typename T >
-struct collapse
-{
-    typedef quantity< D, T > type;
-};
+      // static_assert( has_dimension, "quantity dimensions must not all be zero" ); //
+      // MR: removed
 
-template< typename T >
-struct collapse< dimensionless_d, T >
-{
-    typedef T type;
-};
+    private:
+      // friends:
 
-template< typename D, typename T >
-using Collapse = typename collapse<D,T>::type;
+      // arithmetic
 
-// promote types of expression to result type.
+      template <typename D, typename X, typename Y>
+      friend constexpr quantity<D, X>& operator+=(quantity<D, X>& x,
+                                                  quantity<D, Y> const& y);
 
-template < typename X, typename Y >
-using PromoteAdd = decltype( std::declval<X>() + std::declval<Y>() );
+      template <typename D, typename X>
+      friend constexpr quantity<D, X> operator+(quantity<D, X> const& x);
 
-template < typename X, typename Y >
-using PromoteMul = decltype( std::declval<X>() * std::declval<Y>() );
+      template <typename D, typename X, typename Y>
+      friend constexpr quantity<D, detail::PromoteAdd<X, Y>> operator+(
+          quantity<D, X> const& x, quantity<D, Y> const& y);
 
-/*
- * The following batch of structs are type generators to calculate
- * the correct type of the result of various operations.
- */
+      template <typename D, typename X, typename Y>
+      friend constexpr quantity<D, X>& operator-=(quantity<D, X>& x,
+                                                  quantity<D, Y> const& y);
 
-/**
- * product type generator.
- */
-template< typename DX, typename DY, typename T >
-struct product
-{
-    enum
-    {
-        d1 = DX::dim1 + DY::dim1,
-        d2 = DX::dim2 + DY::dim2,
-        d3 = DX::dim3 + DY::dim3,
-        d4 = DX::dim4 + DY::dim4,
-        d5 = DX::dim5 + DY::dim5,
-        d6 = DX::dim6 + DY::dim6,
-        d7 = DX::dim7 + DY::dim7,
-    };
+      template <typename D, typename X>
+      friend constexpr quantity<D, X> operator-(quantity<D, X> const& x);
 
-    typedef Collapse< dimensions< d1, d2, d3, d4, d5, d6, d7 >, T > type;
-};
+      template <typename D, typename X, typename Y>
+      friend constexpr quantity<D, detail::PromoteAdd<X, Y>> operator-(
+          quantity<D, X> const& x, quantity<D, Y> const& y);
 
-template< typename DX, typename DY, typename X, typename Y>
-using Product = typename product<DX, DY, PromoteMul<X,Y>>::type;
+      template <typename D, typename X, typename Y>
+      friend constexpr quantity<D, X>& operator*=(quantity<D, X>& x, const Y& y);
 
-/**
- * quotient type generator.
- */
-template< typename DX, typename DY, typename T >
-struct quotient
-{
-    enum
-    {
-        d1 = DX::dim1 - DY::dim1,
-        d2 = DX::dim2 - DY::dim2,
-        d3 = DX::dim3 - DY::dim3,
-        d4 = DX::dim4 - DY::dim4,
-        d5 = DX::dim5 - DY::dim5,
-        d6 = DX::dim6 - DY::dim6,
-        d7 = DX::dim7 - DY::dim7,
-    };
+      template <typename D, typename X, typename Y>
+      friend constexpr quantity<D, detail::PromoteMul<X, Y>> operator*(
+          quantity<D, X> const& x, const Y& y);
 
-    typedef Collapse< dimensions< d1, d2, d3, d4, d5, d6, d7 >, T > type;
-};
+      template <typename D, typename X, typename Y>
+      friend constexpr quantity<D, detail::PromoteMul<X, Y>> operator*(
+          const X& x, quantity<D, Y> const& y);
 
-template< typename DX, typename DY, typename X, typename Y>
-using Quotient = typename quotient<DX, DY, PromoteMul<X,Y>>::type;
+      template <typename DX, typename DY, typename X, typename Y>
+      friend constexpr detail::Product<DX, DY, X, Y> operator*(
+          quantity<DX, X> const& lhs, quantity<DY, Y> const& rhs);
 
-/**
- * reciprocal type generator.
- */
-template< typename D, typename T >
-struct reciprocal
-{
-    enum
-    {
-        d1 = - D::dim1,
-        d2 = - D::dim2,
-        d3 = - D::dim3,
-        d4 = - D::dim4,
-        d5 = - D::dim5,
-        d6 = - D::dim6,
-        d7 = - D::dim7,
-    };
+      template <typename D, typename X, typename Y>
+      friend constexpr quantity<D, X>& operator/=(quantity<D, X>& x, const Y& y);
 
-    typedef Collapse< dimensions< d1, d2, d3, d4, d5, d6, d7 >, T > type;
-};
+      template <typename D, typename X, typename Y>
+      friend constexpr quantity<D, detail::PromoteMul<X, Y>> operator/(
+          quantity<D, X> const& x, const Y& y);
 
-template< typename D, typename X, typename Y>
-using Reciprocal = typename reciprocal<D, PromoteMul<X,Y>>::type;
+      template <typename D, typename X, typename Y>
+      friend constexpr detail::Reciprocal<D, X, Y> operator/(const X& x,
+                                                             quantity<D, Y> const& y);
 
-/**
- * power type generator.
- */
-template< typename D, int N, typename T >
-struct power
-{
-    enum
-    {
-        d1 = N * D::dim1,
-        d2 = N * D::dim2,
-        d3 = N * D::dim3,
-        d4 = N * D::dim4,
-        d5 = N * D::dim5,
-        d6 = N * D::dim6,
-        d7 = N * D::dim7,
-    };
+      template <typename DX, typename DY, typename X, typename Y>
+      friend constexpr detail::Quotient<DX, DY, X, Y> operator/(quantity<DX, X> const& x,
+                                                                quantity<DY, Y> const& y);
 
-    typedef Collapse< dimensions< d1, d2, d3, d4, d5, d6, d7 >, T > type;
-};
+      // absolute value.
 
-template< typename D, int N, typename T >
-using Power = typename detail::power< D, N, T >::type;
+      template <typename D, typename X>
+      friend constexpr quantity<D, X> abs(quantity<D, X> const& x);
 
-/**
- * root type generator.
- */
-template< typename D, int N, typename T >
-struct root
-{
-    enum
-    {
-        all_even_multiples =
-            D::dim1 % N == 0 &&
-            D::dim2 % N == 0 &&
-            D::dim3 % N == 0 &&
-            D::dim4 % N == 0 &&
-            D::dim5 % N == 0 &&
-            D::dim6 % N == 0 &&
-            D::dim7 % N == 0
-    };
+      // powers and roots
 
-    enum
-    {
-        d1 = D::dim1 / N,
-        d2 = D::dim2 / N,
-        d3 = D::dim3 / N,
-        d4 = D::dim4 / N,
-        d5 = D::dim5 / N,
-        d6 = D::dim6 / N,
-        d7 = D::dim7 / N
-    };
+      template <int N, typename D, typename X>
+      friend detail::Power<D, N, X> nth_power(quantity<D, X> const& x);
 
-    typedef Collapse< dimensions< d1, d2, d3, d4, d5, d6, d7 >, T > type;
-};
+      template <typename D, typename X>
+      friend constexpr detail::Power<D, 2, X> square(quantity<D, X> const& x);
 
-template< typename D, int N, typename T >
-using Root = typename detail::root< D, N, T >::type;
+      template <typename D, typename X>
+      friend constexpr detail::Power<D, 3, X> cube(quantity<D, X> const& x);
 
-/**
- * tag to construct a quantity from a magnitude.
- */
-constexpr struct magnitude_tag_t{} magnitude_tag{};
+      template <int N, typename D, typename X>
+      friend detail::Root<D, N, X> nth_root(quantity<D, X> const& x);
 
-} // namespace detail
+      template <typename D, typename X>
+      friend detail::Root<D, 2, X> sqrt(quantity<D, X> const& x);
 
-/**
- * \brief class "quantity" is the heart of the library. It associates
- * dimensions  with a single "Rep" data member and protects it from
- * dimensionally inconsistent use.
- */
-template< typename Dims, typename T /*= Rep */ >
-class quantity
-{
-public:
-    typedef Dims dimension_type;
+      // comparison
 
-    typedef T value_type;
+      template <typename D, typename X, typename Y>
+      friend constexpr bool operator==(quantity<D, X> const& x, quantity<D, Y> const& y);
 
-    typedef quantity<Dims, T> this_type;
+      template <typename D, typename X, typename Y>
+      friend constexpr bool operator!=(quantity<D, X> const& x, quantity<D, Y> const& y);
 
-    constexpr quantity() : m_value{} { }
+      template <typename D, typename X, typename Y>
+      friend constexpr bool operator<(quantity<D, X> const& x, quantity<D, Y> const& y);
 
-    /**
-     * public converting initializing constructor;
-     * requires magnitude_tag to prevent constructing a quantity from a raw magnitude.
-     */
-    template <typename X>
-    constexpr explicit quantity( detail::magnitude_tag_t, X x )
-    : m_value( x ) { }
+      template <typename D, typename X, typename Y>
+      friend constexpr bool operator<=(quantity<D, X> const& x, quantity<D, Y> const& y);
 
-    /**
-     * converting copy-assignment constructor.
-     */
-    template <typename X >
-    constexpr quantity( quantity<Dims, X> const & x )
-    : m_value( x.magnitude() ) { }
+      template <typename D, typename X, typename Y>
+      friend constexpr bool operator>(quantity<D, X> const& x, quantity<D, Y> const& y);
 
-//    /**
-//     * convert to compatible unit, for example: (3._dm).to(meter) gives 0.3;
-//     */
-//    constexpr value_type to( quantity const & x ) const {  return *this / x; }
+      template <typename D, typename X, typename Y>
+      friend constexpr bool operator>=(quantity<D, X> const& x, quantity<D, Y> const& y);
+    };
 
-    /**
-     * convert to given unit, for example: (3._dm).to(meter) gives 0.3;
-     */
-    template <typename DX, typename X>
-    constexpr auto to( quantity<DX,X> const & x ) const -> detail::Quotient<Dims,DX,T,X>
-    {
-        return *this / x;
-    }
+    // Give names to the seven fundamental dimensions of physical reality.
 
-    /**
-     * the quantity's magnitude.
-     */
-    constexpr value_type magnitude() const { return m_value; }
+    typedef dimensions<1, 0, 0, 0, 0, 0, 0, 0> length_d;
+    typedef dimensions<0, 1, 0, 0, 0, 0, 0, 0> mass_d;
+    typedef dimensions<0, 0, 1, 0, 0, 0, 0, 0> time_interval_d;
+    typedef dimensions<0, 0, 0, 1, 0, 0, 0, 0> electric_current_d;
+    typedef dimensions<0, 0, 0, 0, 1, 0, 0, 0> thermodynamic_temperature_d;
+    typedef dimensions<0, 0, 0, 0, 0, 1, 0, 0> amount_of_substance_d;
+    typedef dimensions<0, 0, 0, 0, 0, 0, 1, 0> luminous_intensity_d;
+    typedef dimensions<0, 0, 0, 0, 0, 0, 0, 1> hepenergy_d;
 
-    /**
-     * the quantity's dimensions.
-     */
-    constexpr dimension_type dimension() const { return dimension_type{}; }
+    // Addition operators
 
-    /**
-     * We need a "zero" of each type -- for comparisons, to initialize running
-     * totals, etc.  Note:  0 m != 0 kg, since they are of different dimensionality.
-     * zero is really just defined for convenience, since
-     * quantity< length_d >::zero == 0 * meter, etc.
-     */
-    static constexpr quantity zero() { return quantity{ value_type( 0.0 ) }; }
-//    static constexpr quantity zero = quantity{ value_type( 0.0 ) };
+    /// quan += quan
 
-private:
-    /**
-     * private initializing constructor.
-     */
-    constexpr explicit quantity( value_type x ) : m_value{ x } { }
+    template <typename D, typename X, typename Y>
+    constexpr quantity<D, X>& operator+=(quantity<D, X>& x, quantity<D, Y> const& y) {
+      return x.m_value += y.m_value, x;
+    }
 
-private:
-    value_type m_value;
+    /// + quan
+
+    template <typename D, typename X>
+    constexpr quantity<D, X> operator+(quantity<D, X> const& x) {
+      return quantity<D, X>(+x.m_value);
+    }
 
-    enum { has_dimension = ! Dims::is_all_zero };
+    /// quan + quan
 
-    // static_assert( has_dimension, "quantity dimensions must not all be zero" ); // MR: removed
+    template <typename D, typename X, typename Y>
+    constexpr quantity<D, detail::PromoteAdd<X, Y>> operator+(quantity<D, X> const& x,
+                                                              quantity<D, Y> const& y) {
+      return quantity<D, detail::PromoteAdd<X, Y>>(x.m_value + y.m_value);
+    }
 
-private:
-    // friends:
+    // Subtraction operators
 
-    // arithmetic
+    /// quan -= quan
 
     template <typename D, typename X, typename Y>
-    friend constexpr quantity<D, X> &
-    operator+=( quantity<D, X> & x, quantity<D, Y> const & y );
+    constexpr quantity<D, X>& operator-=(quantity<D, X>& x, quantity<D, Y> const& y) {
+      return x.m_value -= y.m_value, x;
+    }
+
+    /// - quan
 
     template <typename D, typename X>
-    friend constexpr quantity<D, X>
-    operator+( quantity<D, X> const & x );
+    constexpr quantity<D, X> operator-(quantity<D, X> const& x) {
+      return quantity<D, X>(-x.m_value);
+    }
 
-    template< typename D, typename X, typename Y >
-    friend constexpr quantity <D, detail::PromoteAdd<X,Y>>
-    operator+( quantity<D, X> const & x, quantity<D, Y> const & y );
+    /// quan - quan
 
     template <typename D, typename X, typename Y>
-    friend constexpr quantity<D, X> &
-    operator-=( quantity<D, X> & x, quantity<D, Y> const & y );
+    constexpr quantity<D, detail::PromoteAdd<X, Y>> operator-(quantity<D, X> const& x,
+                                                              quantity<D, Y> const& y) {
+      return quantity<D, detail::PromoteAdd<X, Y>>(x.m_value - y.m_value);
+    }
 
-    template <typename D, typename X>
-    friend constexpr quantity<D, X>
-    operator-( quantity<D, X> const & x );
+    // Multiplication operators
+
+    /// quan *= num
 
-    template< typename D, typename X, typename Y >
-    friend constexpr quantity <D, detail::PromoteAdd<X,Y>>
-    operator-( quantity<D, X> const & x, quantity<D, Y> const & y );
+    template <typename D, typename X, typename Y>
+    constexpr quantity<D, X>& operator*=(quantity<D, X>& x, const Y& y) {
+      return x.m_value *= y, x;
+    }
 
-    template< typename D, typename X, typename Y>
-    friend constexpr quantity<D, X> &
-    operator*=( quantity<D, X> & x, const Y & y );
+    /// quan * num
 
     template <typename D, typename X, typename Y>
-    friend constexpr quantity<D, detail::PromoteMul<X,Y>>
-    operator*( quantity<D, X> const & x, const Y & y );
+    constexpr quantity<D, detail::PromoteMul<X, Y>> operator*(quantity<D, X> const& x,
+                                                              const Y& y) {
+      return quantity<D, detail::PromoteMul<X, Y>>(x.m_value * y);
+    }
+
+    /// num * quan
 
     template <typename D, typename X, typename Y>
-    friend constexpr quantity< D, detail::PromoteMul<X,Y> >
-    operator*( const X & x, quantity<D, Y> const & y );
+    constexpr quantity<D, detail::PromoteMul<X, Y>> operator*(const X& x,
+                                                              quantity<D, Y> const& y) {
+      return quantity<D, detail::PromoteMul<X, Y>>(x * y.m_value);
+    }
+
+    /// quan * quan:
 
     template <typename DX, typename DY, typename X, typename Y>
-    friend constexpr detail::Product<DX, DY, X, Y>
-    operator*( quantity<DX, X> const & lhs, quantity< DY, Y > const & rhs );
+    constexpr detail::Product<DX, DY, X, Y> operator*(quantity<DX, X> const& lhs,
+                                                      quantity<DY, Y> const& rhs) {
+      return detail::Product<DX, DY, X, Y>(lhs.m_value * rhs.m_value);
+    }
+
+    // Division operators
 
-    template< typename D, typename X, typename Y>
-    friend constexpr quantity<D, X> &
-    operator/=( quantity<D, X> & x, const Y & y );
+    /// quan /= num
 
     template <typename D, typename X, typename Y>
-    friend constexpr quantity<D, detail::PromoteMul<X,Y>>
-    operator/( quantity<D, X> const & x, const Y & y );
+    constexpr quantity<D, X>& operator/=(quantity<D, X>& x, const Y& y) {
+      return x.m_value /= y, x;
+    }
+
+    /// quan / num
 
     template <typename D, typename X, typename Y>
-    friend constexpr detail::Reciprocal<D, X, Y>
-    operator/( const X & x, quantity<D, Y> const & y );
+    constexpr quantity<D, detail::PromoteMul<X, Y>> operator/(quantity<D, X> const& x,
+                                                              const Y& y) {
+      return quantity<D, detail::PromoteMul<X, Y>>(x.m_value / y);
+    }
 
-    template <typename DX, typename DY, typename X, typename Y>
-    friend constexpr detail::Quotient<DX, DY, X, Y>
-    operator/( quantity<DX, X> const & x, quantity< DY, Y > const & y );
+    /// num / quan
 
-    // absolute value.
+    template <typename D, typename X, typename Y>
+    constexpr detail::Reciprocal<D, X, Y> operator/(const X& x, quantity<D, Y> const& y) {
+      return detail::Reciprocal<D, X, Y>(x / y.m_value);
+    }
 
-    template <typename D, typename X>
-    friend constexpr quantity<D,X>
-    abs( quantity<D,X> const & x );
+    /// quan / quan:
 
-    // powers and roots
+    template <typename DX, typename DY, typename X, typename Y>
+    constexpr detail::Quotient<DX, DY, X, Y> operator/(quantity<DX, X> const& x,
+                                                       quantity<DY, Y> const& y) {
+      return detail::Quotient<DX, DY, X, Y>(x.m_value / y.m_value);
+    }
 
-    template <int N, typename D, typename X>
-    friend detail::Power<D, N, X>
-    nth_power( quantity<D, X> const & x );
+    /// absolute value.
 
     template <typename D, typename X>
-    friend constexpr detail::Power<D, 2, X>
-    square( quantity<D, X> const & x );
+    constexpr quantity<D, X> abs(quantity<D, X> const& x) {
+      return quantity<D, X>(std::abs(x.m_value));
+    }
 
-    template <typename D, typename X>
-    friend constexpr detail::Power<D, 3, X>
-    cube( quantity<D, X> const & x );
+    // General powers
 
-    template <int N, typename D, typename X>
-    friend detail::Root<D, N, X>
-    nth_root( quantity<D, X> const & x );
+    /// N-th power.
 
-    template <typename D, typename X>
-    friend detail::Root< D, 2, X >
-    sqrt( quantity<D, X> const & x );
+    template <int N, typename D, typename X>
+    detail::Power<D, N, X> nth_power(quantity<D, X> const& x) {
+      return detail::Power<D, N, X>(std::pow(x.m_value, X(N)));
+    }
 
-    // comparison
+    // Low powers defined separately for efficiency.
 
-    template <typename D, typename X, typename Y>
-    friend constexpr bool operator==( quantity<D, X> const & x, quantity<D, Y> const & y );
+    /// square.
 
-    template <typename D, typename X, typename Y>
-    friend constexpr bool operator!=( quantity<D, X> const & x, quantity<D, Y> const & y );
+    template <typename D, typename X>
+    constexpr detail::Power<D, 2, X> square(quantity<D, X> const& x) {
+      return x * x;
+    }
 
-    template <typename D, typename X, typename Y>
-    friend constexpr bool operator<( quantity<D, X> const & x, quantity<D, Y> const & y );
+    /// cube.
 
-    template <typename D, typename X, typename Y>
-    friend constexpr bool operator<=( quantity<D, X> const & x, quantity<D, Y> const & y );
+    template <typename D, typename X>
+    constexpr detail::Power<D, 3, X> cube(quantity<D, X> const& x) {
+      return x * x * x;
+    }
 
-    template <typename D, typename X, typename Y>
-    friend constexpr bool operator>( quantity<D, X> const & x, quantity<D, Y> const & y );
+    // General root
 
-    template <typename D, typename X, typename Y>
-    friend constexpr bool operator>=( quantity<D, X> const & x, quantity<D, Y> const & y );
-};
+    /// n-th root.
 
-// Give names to the seven fundamental dimensions of physical reality.
-
-typedef dimensions< 1, 0, 0, 0, 0, 0, 0 > length_d;
-typedef dimensions< 0, 1, 0, 0, 0, 0, 0 > mass_d;
-typedef dimensions< 0, 0, 1, 0, 0, 0, 0 > time_interval_d;
-typedef dimensions< 0, 0, 0, 1, 0, 0, 0 > electric_current_d;
-typedef dimensions< 0, 0, 0, 0, 1, 0, 0 > thermodynamic_temperature_d;
-typedef dimensions< 0, 0, 0, 0, 0, 1, 0 > amount_of_substance_d;
-typedef dimensions< 0, 0, 0, 0, 0, 0, 1 > luminous_intensity_d;
+    template <int N, typename D, typename X>
+    detail::Root<D, N, X> nth_root(quantity<D, X> const& x) {
+      static_assert(detail::root<D, N, X>::all_even_multiples,
+                    "root result dimensions must be integral");
 
-// Addition operators
+      return detail::Root<D, N, X>(std::pow(x.m_value, X(1.0) / N));
+    }
 
-/// quan += quan
-
-template <typename D, typename X, typename Y>
-constexpr quantity<D, X> &
-operator+=( quantity<D, X> & x, quantity<D, Y> const & y )
-{
-    return x.m_value += y.m_value, x;
-}
-
-/// + quan
-
-template <typename D, typename X>
-constexpr quantity<D, X>
-operator+( quantity<D, X> const & x )
-{
-   return quantity<D, X >( +x.m_value );
-}
-
-/// quan + quan
-
-template< typename D, typename X, typename Y >
-constexpr quantity <D, detail::PromoteAdd<X,Y>>
-operator+( quantity<D, X> const & x, quantity<D, Y> const & y )
-{
-   return quantity<D, detail::PromoteAdd<X,Y>>( x.m_value + y.m_value );
-}
-
-// Subtraction operators
-
-/// quan -= quan
-
-template <typename D, typename X, typename Y>
-constexpr quantity<D, X> &
-operator-=( quantity<D, X> & x, quantity<D, Y> const & y )
-{
-    return x.m_value -= y.m_value, x;
-}
-
-/// - quan
-
-template <typename D, typename X>
-constexpr quantity<D, X>
-operator-( quantity<D, X> const & x )
-{
-   return quantity<D, X >( -x.m_value );
-}
-
-/// quan - quan
-
-template< typename D, typename X, typename Y >
-constexpr quantity <D, detail::PromoteAdd<X,Y>>
-operator-( quantity<D, X> const & x, quantity<D, Y> const & y )
-{
-   return quantity<D, detail::PromoteAdd<X,Y>>( x.m_value - y.m_value );
-}
+    // Low roots defined separately for convenience.
 
-// Multiplication operators
-
-/// quan *= num
-
-template< typename D, typename X, typename Y>
-constexpr quantity<D, X> &
-operator*=( quantity<D, X> & x, const Y & y )
-{
-   return x.m_value *= y, x;
-}
-
-/// quan * num
-
-template <typename D, typename X, typename Y>
-constexpr quantity<D, detail::PromoteMul<X,Y>>
-operator*( quantity<D, X> const & x, const Y & y )
-{
-   return quantity<D, detail::PromoteMul<X,Y>>( x.m_value * y );
-}
+    /// square root.
 
-/// num * quan
-
-template <typename D, typename X, typename Y>
-constexpr quantity< D, detail::PromoteMul<X,Y> >
-operator*( const X & x, quantity<D, Y> const & y )
-{
-   return quantity<D, detail::PromoteMul<X,Y>>( x * y.m_value );
-}
-
-/// quan * quan:
+    template <typename D, typename X>
+    detail::Root<D, 2, X> sqrt(quantity<D, X> const& x) {
+      static_assert(detail::root<D, 2, X>::all_even_multiples,
+                    "root result dimensions must be integral");
 
-template <typename DX, typename DY, typename X, typename Y>
-constexpr detail::Product<DX, DY, X, Y>
-operator*( quantity<DX, X> const & lhs, quantity< DY, Y > const & rhs )
-{
-    return detail::Product<DX, DY, X, Y>( lhs.m_value * rhs.m_value );
-}
-
-// Division operators
+      return detail::Root<D, 2, X>(std::pow(x.m_value, X(1.0) / 2));
+    }
 
-/// quan /= num
+    // Comparison operators
 
-template< typename D, typename X, typename Y>
-constexpr quantity<D, X> &
-operator/=( quantity<D, X> & x, const Y & y )
-{
-   return x.m_value /= y, x;
-}
+    /// equality.
 
-/// quan / num
+    template <typename D, typename X, typename Y>
+    constexpr bool operator==(quantity<D, X> const& x, quantity<D, Y> const& y) {
+      return x.m_value == y.m_value;
+    }
 
-template <typename D, typename X, typename Y>
-constexpr quantity<D, detail::PromoteMul<X,Y>>
-operator/( quantity<D, X> const & x, const Y & y )
-{
-   return quantity<D, detail::PromoteMul<X,Y>>( x.m_value / y );
-}
+    /// inequality.
 
-/// num / quan
+    template <typename D, typename X, typename Y>
+    constexpr bool operator!=(quantity<D, X> const& x, quantity<D, Y> const& y) {
+      return x.m_value != y.m_value;
+    }
 
-template <typename D, typename X, typename Y>
-constexpr detail::Reciprocal<D, X, Y>
-operator/( const X & x, quantity<D, Y> const & y )
-{
-   return detail::Reciprocal<D, X, Y>( x / y.m_value );
-}
+    /// less-than.
 
-/// quan / quan:
+    template <typename D, typename X, typename Y>
+    constexpr bool operator<(quantity<D, X> const& x, quantity<D, Y> const& y) {
+      return x.m_value < y.m_value;
+    }
 
-template <typename DX, typename DY, typename X, typename Y>
-constexpr detail::Quotient<DX, DY, X, Y>
-operator/( quantity<DX, X> const & x, quantity< DY, Y > const & y )
-{
-    return detail::Quotient<DX, DY, X, Y>( x.m_value / y.m_value );
-}
-
-/// absolute value.
-
-template <typename D, typename X>
-constexpr quantity<D,X> abs( quantity<D,X> const & x )
-{
-   return quantity<D,X>( std::abs( x.m_value ) );
-}
+    /// less-equal.
 
-// General powers
-
-/// N-th power.
-
-template <int N, typename D, typename X>
-detail::Power<D, N, X>
-nth_power( quantity<D, X> const & x )
-{
-   return detail::Power<D, N, X>( std::pow( x.m_value, X( N ) ) );
-}
-
-// Low powers defined separately for efficiency.
-
-/// square.
+    template <typename D, typename X, typename Y>
+    constexpr bool operator<=(quantity<D, X> const& x, quantity<D, Y> const& y) {
+      return x.m_value <= y.m_value;
+    }
 
-template <typename D, typename X>
-constexpr detail::Power<D, 2, X>
-square( quantity<D, X> const & x )
-{
-   return x * x;
-}
+    /// greater-than.
 
-/// cube.
+    template <typename D, typename X, typename Y>
+    constexpr bool operator>(quantity<D, X> const& x, quantity<D, Y> const& y) {
+      return x.m_value > y.m_value;
+    }
 
-template <typename D, typename X>
-constexpr detail::Power<D, 3, X>
-cube( quantity<D, X> const & x )
-{
-   return x * x * x;
-}
+    /// greater-equal.
 
-// General root
+    template <typename D, typename X, typename Y>
+    constexpr bool operator>=(quantity<D, X> const& x, quantity<D, Y> const& y) {
+      return x.m_value >= y.m_value;
+    }
 
-/// n-th root.
+    /// quantity's dimension.
 
-template <int N, typename D, typename X>
-detail::Root<D, N, X>
-nth_root( quantity<D, X> const & x )
-{
-   static_assert( detail::root<D, N, X>::all_even_multiples, "root result dimensions must be integral" );
+    template <typename DX, typename X>
+    inline constexpr DX dimension(quantity<DX, X> const& q) {
+      return q.dimension();
+    }
 
-   return detail::Root<D, N, X>( std::pow( x.m_value, X( 1.0 ) / N ) );
-}
+    /// quantity's magnitude.
 
-// Low roots defined separately for convenience.
-
-/// square root.
-
-template <typename D, typename X>
-detail::Root< D, 2, X >
-sqrt( quantity<D, X> const & x )
-{
-   static_assert(
-      detail::root<D, 2, X >::all_even_multiples, "root result dimensions must be integral" );
-
-   return detail::Root<D, 2, X>( std::pow( x.m_value, X( 1.0 ) / 2 ) );
-}
-
-// Comparison operators
-
-/// equality.
-
-template <typename D, typename X, typename Y>
-constexpr bool
-operator==( quantity<D, X> const & x, quantity<D, Y> const & y )
-{
-   return x.m_value == y.m_value;
-}
-
-/// inequality.
-
-template <typename D, typename X, typename Y>
-constexpr bool
-operator!=( quantity<D, X> const & x, quantity<D, Y> const & y )
-{
-   return x.m_value != y.m_value;
-}
-
-/// less-than.
-
-template <typename D, typename X, typename Y>
-constexpr bool
-operator<( quantity<D, X> const & x, quantity<D, Y> const & y )
-{
-   return x.m_value < y.m_value;
-}
-
-/// less-equal.
-
-template <typename D, typename X, typename Y>
-constexpr bool
-operator<=( quantity<D, X> const & x, quantity<D, Y> const & y )
-{
-   return x.m_value <= y.m_value;
-}
-
-/// greater-than.
-
-template <typename D, typename X, typename Y>
-constexpr bool
-operator>( quantity<D, X> const & x, quantity<D, Y> const & y )
-{
-   return x.m_value > y.m_value;
-}
-
-/// greater-equal.
-
-template <typename D, typename X, typename Y>
-constexpr bool
-operator>=( quantity<D, X> const & x, quantity<D, Y> const & y )
-{
-   return x.m_value >= y.m_value;
-}
-
-/// quantity's dimension.
-
-template <typename DX, typename X>
-inline constexpr DX dimension( quantity<DX,X> const & q ) { return q.dimension(); }
-
-/// quantity's magnitude.
-
-template <typename DX, typename X>
-inline constexpr X magnitude( quantity<DX,X> const & q ) { return q.magnitude(); }
-
-// The seven SI base units.  These tie our numbers to the real world.
-
-constexpr quantity<length_d                   > meter   { detail::magnitude_tag, 1.0 };
-constexpr quantity<mass_d                     > kilogram{ detail::magnitude_tag, 1.0 };
-constexpr quantity<time_interval_d            > second  { detail::magnitude_tag, 1.0 };
-constexpr quantity<electric_current_d         > ampere  { detail::magnitude_tag, 1.0 };
-constexpr quantity<thermodynamic_temperature_d> kelvin  { detail::magnitude_tag, 1.0 };
-constexpr quantity<amount_of_substance_d      > mole    { detail::magnitude_tag, 1.0 };
-constexpr quantity<luminous_intensity_d       > candela { detail::magnitude_tag, 1.0 };
-
-// The standard SI prefixes.
-
-constexpr long double yotta = 1e+24L;
-constexpr long double zetta = 1e+21L;
-constexpr long double   exa = 1e+18L;
-constexpr long double  peta = 1e+15L;
-constexpr long double  tera = 1e+12L;
-constexpr long double  giga = 1e+9L;
-constexpr long double  mega = 1e+6L;
-constexpr long double  kilo = 1e+3L;
-constexpr long double hecto = 1e+2L;
-constexpr long double  deka = 1e+1L;
-constexpr long double  deci = 1e-1L;
-constexpr long double centi = 1e-2L;
-constexpr long double milli = 1e-3L;
-constexpr long double micro = 1e-6L;
-constexpr long double  nano = 1e-9L;
-constexpr long double  pico = 1e-12L;
-constexpr long double femto = 1e-15L;
-constexpr long double  atto = 1e-18L;
-constexpr long double zepto = 1e-21L;
-constexpr long double yocto = 1e-24L;
-
-// Binary prefixes, pending adoption.
-
-constexpr long double kibi = 1024;
-constexpr long double mebi = 1024 * kibi;
-constexpr long double gibi = 1024 * mebi;
-constexpr long double tebi = 1024 * gibi;
-constexpr long double pebi = 1024 * tebi;
-constexpr long double exbi = 1024 * pebi;
-constexpr long double zebi = 1024 * exbi;
-constexpr long double yobi = 1024 * zebi;
-
-// The rest of the standard dimensional types, as specified in SP811.
-
-using absorbed_dose_d             = dimensions< 2, 0, -2 >;
-using absorbed_dose_rate_d        = dimensions< 2, 0, -3 >;
-using acceleration_d              = dimensions< 1, 0, -2 >;
-using activity_of_a_nuclide_d     = dimensions< 0, 0, -1 >;
-using angular_velocity_d          = dimensions< 0, 0, -1 >;
-using angular_acceleration_d      = dimensions< 0, 0, -2 >;
-using area_d                      = dimensions< 2, 0, 0 >;
-using capacitance_d               = dimensions< -2, -1, 4, 2 >;
-using concentration_d             = dimensions< -3, 0, 0, 0, 0, 1 >;
-using current_density_d           = dimensions< -2, 0, 0, 1 >;
-using dose_equivalent_d           = dimensions< 2, 0, -2 >;
-using dynamic_viscosity_d         = dimensions< -1, 1, -1 >;
-using electric_charge_d           = dimensions< 0, 0, 1, 1 >;
-using electric_charge_density_d   = dimensions< -3, 0, 1, 1 >;
-using electric_conductance_d      = dimensions< -2, -1, 3, 2 >;
-using electric_field_strenth_d    = dimensions< 1, 1, -3, -1 >;
-using electric_flux_density_d     = dimensions< -2, 0, 1, 1 >;
-using electric_potential_d        = dimensions< 2, 1, -3, -1 >;
-using electric_resistance_d       = dimensions< 2, 1, -3, -2 >;
-using energy_d                    = dimensions< 2, 1, -2 >;
-using energy_density_d            = dimensions< -1, 1, -2 >;
-using exposure_d                  = dimensions< 0, -1, 1, 1 >;
-using force_d                     = dimensions< 1, 1, -2 >;
-using frequency_d                 = dimensions< 0, 0, -1 >;
-using heat_capacity_d             = dimensions< 2, 1, -2, 0, -1 >;
-using heat_density_d              = dimensions< 0, 1, -2 >;
-using heat_density_flow_rate_d    = dimensions< 0, 1, -3 >;
-using heat_flow_rate_d            = dimensions< 2, 1, -3 >;
-using heat_flux_density_d         = dimensions< 0, 1, -3 >;
-using heat_transfer_coefficient_d = dimensions< 0, 1, -3, 0, -1 >;
-using illuminance_d               = dimensions< -2, 0, 0, 0, 0, 0, 1 >;
-using inductance_d                = dimensions< 2, 1, -2, -2 >;
-using irradiance_d                = dimensions< 0, 1, -3 >;
-using kinematic_viscosity_d       = dimensions< 2, 0, -1 >;
-using luminance_d                 = dimensions< -2, 0, 0, 0, 0, 0, 1 >;
-using luminous_flux_d             = dimensions< 0, 0, 0, 0, 0, 0, 1 >;
-using magnetic_field_strength_d   = dimensions< -1, 0, 0, 1 >;
-using magnetic_flux_d             = dimensions< 2, 1, -2, -1 >;
-using magnetic_flux_density_d     = dimensions< 0, 1, -2, -1 >;
-using magnetic_permeability_d     = dimensions< 1, 1, -2, -2 >;
-using mass_density_d              = dimensions< -3, 1, 0 >;
-using mass_flow_rate_d            = dimensions< 0, 1, -1 >;
-using molar_energy_d              = dimensions< 2, 1, -2, 0, 0, -1 >;
-using molar_entropy_d             = dimensions< 2, 1, -2, -1, 0, -1 >;
-using moment_of_force_d           = dimensions< 2, 1, -2 >;
-using permittivity_d              = dimensions< -3, -1, 4, 2 >;
-using power_d                     = dimensions< 2, 1, -3 >;
-using pressure_d                  = dimensions< -1, 1, -2 >;
-using radiance_d                  = dimensions< 0, 1, -3 >;
-using radiant_intensity_d         = dimensions< 2, 1, -3 >;
-using speed_d                     = dimensions< 1, 0, -1 >;
-using specific_energy_d           = dimensions< 2, 0, -2 >;
-using specific_heat_capacity_d    = dimensions< 2, 0, -2, 0, -1 >;
-using specific_volume_d           = dimensions< 3, -1, 0 >;
-using substance_permeability_d    = dimensions< -1, 0, 1 >;
-using surface_tension_d           = dimensions< 0, 1, -2 >;
-using thermal_conductivity_d      = dimensions< 1, 1, -3, 0, -1 >;
-using thermal_diffusivity_d       = dimensions< 2, 0, -1 >;
-using thermal_insulance_d         = dimensions< 0, -1, 3, 0, 1 >;
-using thermal_resistance_d        = dimensions< -2, -1, 3, 0, 1 >;
-using thermal_resistivity_d       = dimensions< -1, -1, 3, 0, 1 >;
-using torque_d                    = dimensions< 2, 1, -2 >;
-using volume_d                    = dimensions< 3, 0, 0 >;
-using volume_flow_rate_d          = dimensions< 3, 0, -1 >;
-using wave_number_d               = dimensions< -1, 0, 0 >;
-
-// Handy values.
-
-constexpr Rep pi      { Rep( 3.141592653589793238462L ) };
-constexpr Rep percent { Rep( 1 ) / 100 };
-
-//// Not approved for use alone, but needed for use with prefixes.
-constexpr quantity< mass_d                  > gram         { kilogram / 1000 };
-
-// The derived SI units, as specified in SP811.
-
-constexpr Rep                                 radian       { Rep( 1 ) };
-constexpr Rep                                 steradian    { Rep( 1 ) };
-constexpr quantity< force_d                 > newton       { meter * kilogram / square( second ) };
-constexpr quantity< pressure_d              > pascal       { newton / square( meter ) };
-constexpr quantity< energy_d                > joule        { newton * meter };
-constexpr quantity< power_d                 > watt         { joule / second };
-constexpr quantity< electric_charge_d       > coulomb      { second * ampere };
-constexpr quantity< electric_potential_d    > volt         { watt / ampere };
-constexpr quantity< capacitance_d           > farad        { coulomb / volt };
-constexpr quantity< electric_resistance_d   > ohm          { volt / ampere };
-constexpr quantity< electric_conductance_d  > siemens      { ampere / volt };
-constexpr quantity< magnetic_flux_d         > weber        { volt * second };
-constexpr quantity< magnetic_flux_density_d > tesla        { weber / square( meter ) };
-constexpr quantity< inductance_d            > henry        { weber / ampere };
-constexpr quantity< thermodynamic_temperature_d > degree_celsius   { kelvin };
-constexpr quantity< luminous_flux_d         > lumen        { candela * steradian };
-constexpr quantity< illuminance_d           > lux          { lumen / meter / meter };
-constexpr quantity< activity_of_a_nuclide_d > becquerel    { 1 / second };
-constexpr quantity< absorbed_dose_d         > gray         { joule / kilogram };
-constexpr quantity< dose_equivalent_d       > sievert      { joule / kilogram };
-constexpr quantity< frequency_d             > hertz        { 1 / second };
-
-// The rest of the units approved for use with SI, as specified in SP811.
-// (However, use of these units is generally discouraged.)
-
-constexpr quantity< length_d                > angstrom     { Rep( 1e-10L ) * meter };
-constexpr quantity< area_d                  > are          { Rep( 1e+2L ) * square( meter ) };
-constexpr quantity< pressure_d              > bar          { Rep( 1e+5L ) * pascal };
-constexpr quantity< area_d                  > barn         { Rep( 1e-28L ) * square( meter ) };
-constexpr quantity< activity_of_a_nuclide_d > curie        { Rep( 3.7e+10L ) * becquerel };
-constexpr quantity< time_interval_d         > day          { Rep( 86400L ) * second };
-constexpr Rep                                 degree_angle { pi / 180 };
-constexpr quantity< acceleration_d          > gal          { Rep( 1e-2L ) * meter / square( second ) };
-constexpr quantity< area_d                  > hectare      { Rep( 1e+4L ) * square( meter ) };
-constexpr quantity< time_interval_d         > hour         { Rep( 3600 ) * second };
-constexpr quantity< speed_d                 > knot         { Rep( 1852 ) / 3600 * meter / second };
-constexpr quantity< volume_d                > liter        { Rep( 1e-3L ) * cube( meter ) };
-constexpr quantity< time_interval_d         > minute       { Rep( 60 ) * second };
-constexpr Rep                                 minute_angle { pi / 10800 };
-constexpr quantity< length_d                > mile_nautical{ Rep( 1852 ) * meter };
-constexpr quantity< absorbed_dose_d         > rad          { Rep( 1e-2L ) * gray };
-constexpr quantity< dose_equivalent_d       > rem          { Rep( 1e-2L ) * sievert };
-constexpr quantity< exposure_d              > roentgen     { Rep( 2.58e-4L ) * coulomb / kilogram };
-constexpr Rep                                 second_angle { pi / 648000L };
-constexpr quantity< mass_d                  > ton_metric   { Rep( 1e+3L ) * kilogram };
-
-// Alternate (non-US) spellings:
-
-constexpr quantity< length_d                > metre        { meter };
-constexpr quantity< volume_d                > litre        { liter };
-constexpr Rep                                 deca         { deka };
-constexpr quantity< mass_d                  > tonne        { ton_metric };
-
-// cooked literals for base units;
-// these could also have been created with a script.
-
-#define QUANTITY_DEFINE_SCALING_LITERAL( sfx, dim, factor ) \
-    constexpr quantity<dim, double> operator "" _ ## sfx(unsigned long long x) \
-    { \
-        return quantity<dim, double>( detail::magnitude_tag, factor * x ); \
-    } \
-    constexpr quantity<dim, double> operator "" _ ## sfx(long double x) \
-    { \
-        return quantity<dim, double>( detail::magnitude_tag, factor * x ); \
+    template <typename DX, typename X>
+    inline constexpr X magnitude(quantity<DX, X> const& q) {
+      return q.magnitude();
     }
 
-#define QUANTITY_DEFINE_SCALING_LITERALS( pfx, dim, fact ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( Y ## pfx, dim, fact * yotta ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( Z ## pfx, dim, fact * zetta ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( E ## pfx, dim, fact * exa   ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( P ## pfx, dim, fact * peta  ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( T ## pfx, dim, fact * tera  ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( G ## pfx, dim, fact * giga  ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( M ## pfx, dim, fact * mega  ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( k ## pfx, dim, fact * kilo  ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( h ## pfx, dim, fact * hecto ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( da## pfx, dim, fact * deka  ) \
-    QUANTITY_DEFINE_SCALING_LITERAL(      pfx, dim, fact * 1     ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( d ## pfx, dim, fact * deci  ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( c ## pfx, dim, fact * centi ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( m ## pfx, dim, fact * milli ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( u ## pfx, dim, fact * micro ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( n ## pfx, dim, fact * nano  ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( p ## pfx, dim, fact * pico  ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( f ## pfx, dim, fact * femto ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( a ## pfx, dim, fact * atto  ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( z ## pfx, dim, fact * zepto ) \
-    QUANTITY_DEFINE_SCALING_LITERAL( y ## pfx, dim, fact * yocto )
-
-
-#define QUANTITY_DEFINE_LITERALS( pfx, dim ) \
-    QUANTITY_DEFINE_SCALING_LITERALS( pfx, dim, 1 )
-
-/// literals
-
-namespace literals {
-
-QUANTITY_DEFINE_SCALING_LITERALS( g, mass_d, 1e-3 )
-
-QUANTITY_DEFINE_LITERALS( m  , length_d )
-QUANTITY_DEFINE_LITERALS( s  , time_interval_d )
-QUANTITY_DEFINE_LITERALS( A  , electric_current_d )
-QUANTITY_DEFINE_LITERALS( K  , thermodynamic_temperature_d )
-QUANTITY_DEFINE_LITERALS( mol, amount_of_substance_d )
-QUANTITY_DEFINE_LITERALS( cd , luminous_intensity_d )
-
-} // namespace literals
-
-}} // namespace phys::units
+    // The seven SI base units.  These tie our numbers to the real world.
+
+    constexpr quantity<length_d> meter{detail::magnitude_tag, 1.0};
+    constexpr quantity<mass_d> kilogram{detail::magnitude_tag, 1.0};
+    constexpr quantity<time_interval_d> second{detail::magnitude_tag, 1.0};
+    constexpr quantity<electric_current_d> ampere{detail::magnitude_tag, 1.0};
+    constexpr quantity<thermodynamic_temperature_d> kelvin{detail::magnitude_tag, 1.0};
+    constexpr quantity<amount_of_substance_d> mole{detail::magnitude_tag, 1.0};
+    constexpr quantity<luminous_intensity_d> candela{detail::magnitude_tag, 1.0};
+    constexpr quantity<hepenergy_d> electronvolt{detail::magnitude_tag, 1.0};
+
+    // The standard SI prefixes.
+
+    constexpr long double yotta = 1e+24L;
+    constexpr long double zetta = 1e+21L;
+    constexpr long double exa = 1e+18L;
+    constexpr long double peta = 1e+15L;
+    constexpr long double tera = 1e+12L;
+    constexpr long double giga = 1e+9L;
+    constexpr long double mega = 1e+6L;
+    constexpr long double kilo = 1e+3L;
+    constexpr long double hecto = 1e+2L;
+    constexpr long double deka = 1e+1L;
+    constexpr long double deci = 1e-1L;
+    constexpr long double centi = 1e-2L;
+    constexpr long double milli = 1e-3L;
+    constexpr long double micro = 1e-6L;
+    constexpr long double nano = 1e-9L;
+    constexpr long double pico = 1e-12L;
+    constexpr long double femto = 1e-15L;
+    constexpr long double atto = 1e-18L;
+    constexpr long double zepto = 1e-21L;
+    constexpr long double yocto = 1e-24L;
+
+    // Binary prefixes, pending adoption.
+
+    constexpr long double kibi = 1024;
+    constexpr long double mebi = 1024 * kibi;
+    constexpr long double gibi = 1024 * mebi;
+    constexpr long double tebi = 1024 * gibi;
+    constexpr long double pebi = 1024 * tebi;
+    constexpr long double exbi = 1024 * pebi;
+    constexpr long double zebi = 1024 * exbi;
+    constexpr long double yobi = 1024 * zebi;
+
+    // The rest of the standard dimensional types, as specified in SP811.
+
+    using absorbed_dose_d = dimensions<2, 0, -2>;
+    using absorbed_dose_rate_d = dimensions<2, 0, -3>;
+    using acceleration_d = dimensions<1, 0, -2>;
+    using activity_of_a_nuclide_d = dimensions<0, 0, -1>;
+    using angular_velocity_d = dimensions<0, 0, -1>;
+    using angular_acceleration_d = dimensions<0, 0, -2>;
+    using area_d = dimensions<2, 0, 0>;
+    using capacitance_d = dimensions<-2, -1, 4, 2>;
+    using concentration_d = dimensions<-3, 0, 0, 0, 0, 1>;
+    using current_density_d = dimensions<-2, 0, 0, 1>;
+    using dose_equivalent_d = dimensions<2, 0, -2>;
+    using dynamic_viscosity_d = dimensions<-1, 1, -1>;
+    using electric_charge_d = dimensions<0, 0, 1, 1>;
+    using electric_charge_density_d = dimensions<-3, 0, 1, 1>;
+    using electric_conductance_d = dimensions<-2, -1, 3, 2>;
+    using electric_field_strenth_d = dimensions<1, 1, -3, -1>;
+    using electric_flux_density_d = dimensions<-2, 0, 1, 1>;
+    using electric_potential_d = dimensions<2, 1, -3, -1>;
+    using electric_resistance_d = dimensions<2, 1, -3, -2>;
+    using energy_d = dimensions<2, 1, -2>;
+    using energy_density_d = dimensions<-1, 1, -2>;
+    using exposure_d = dimensions<0, -1, 1, 1>;
+    using force_d = dimensions<1, 1, -2>;
+    using frequency_d = dimensions<0, 0, -1>;
+    using heat_capacity_d = dimensions<2, 1, -2, 0, -1>;
+    using heat_density_d = dimensions<0, 1, -2>;
+    using heat_density_flow_rate_d = dimensions<0, 1, -3>;
+    using heat_flow_rate_d = dimensions<2, 1, -3>;
+    using heat_flux_density_d = dimensions<0, 1, -3>;
+    using heat_transfer_coefficient_d = dimensions<0, 1, -3, 0, -1>;
+    using illuminance_d = dimensions<-2, 0, 0, 0, 0, 0, 1>;
+    using inductance_d = dimensions<2, 1, -2, -2>;
+    using irradiance_d = dimensions<0, 1, -3>;
+    using kinematic_viscosity_d = dimensions<2, 0, -1>;
+    using luminance_d = dimensions<-2, 0, 0, 0, 0, 0, 1>;
+    using luminous_flux_d = dimensions<0, 0, 0, 0, 0, 0, 1>;
+    using magnetic_field_strength_d = dimensions<-1, 0, 0, 1>;
+    using magnetic_flux_d = dimensions<2, 1, -2, -1>;
+    using magnetic_flux_density_d = dimensions<0, 1, -2, -1>;
+    using magnetic_permeability_d = dimensions<1, 1, -2, -2>;
+    using mass_density_d = dimensions<-3, 1, 0>;
+    using mass_flow_rate_d = dimensions<0, 1, -1>;
+    using molar_energy_d = dimensions<2, 1, -2, 0, 0, -1>;
+    using molar_entropy_d = dimensions<2, 1, -2, -1, 0, -1>;
+    using moment_of_force_d = dimensions<2, 1, -2>;
+    using permittivity_d = dimensions<-3, -1, 4, 2>;
+    using power_d = dimensions<2, 1, -3>;
+    using pressure_d = dimensions<-1, 1, -2>;
+    using radiance_d = dimensions<0, 1, -3>;
+    using radiant_intensity_d = dimensions<2, 1, -3>;
+    using speed_d = dimensions<1, 0, -1>;
+    using specific_energy_d = dimensions<2, 0, -2>;
+    using specific_heat_capacity_d = dimensions<2, 0, -2, 0, -1>;
+    using specific_volume_d = dimensions<3, -1, 0>;
+    using substance_permeability_d = dimensions<-1, 0, 1>;
+    using surface_tension_d = dimensions<0, 1, -2>;
+    using thermal_conductivity_d = dimensions<1, 1, -3, 0, -1>;
+    using thermal_diffusivity_d = dimensions<2, 0, -1>;
+    using thermal_insulance_d = dimensions<0, -1, 3, 0, 1>;
+    using thermal_resistance_d = dimensions<-2, -1, 3, 0, 1>;
+    using thermal_resistivity_d = dimensions<-1, -1, 3, 0, 1>;
+    using torque_d = dimensions<2, 1, -2>;
+    using volume_d = dimensions<3, 0, 0>;
+    using volume_flow_rate_d = dimensions<3, 0, -1>;
+    using wave_number_d = dimensions<-1, 0, 0>;
+
+    // Handy values.
+
+    constexpr Rep pi{Rep(3.141592653589793238462L)};
+    constexpr Rep percent{Rep(1) / 100};
+
+    //// Not approved for use alone, but needed for use with prefixes.
+    constexpr quantity<mass_d> gram{kilogram / 1000};
+
+    // The derived SI units, as specified in SP811.
+
+    constexpr Rep radian{Rep(1)};
+    constexpr Rep steradian{Rep(1)};
+    constexpr quantity<force_d> newton{meter * kilogram / square(second)};
+    constexpr quantity<pressure_d> pascal{newton / square(meter)};
+    constexpr quantity<energy_d> joule{newton * meter};
+    constexpr quantity<power_d> watt{joule / second};
+    constexpr quantity<electric_charge_d> coulomb{second * ampere};
+    constexpr quantity<electric_potential_d> volt{watt / ampere};
+    constexpr quantity<capacitance_d> farad{coulomb / volt};
+    constexpr quantity<electric_resistance_d> ohm{volt / ampere};
+    constexpr quantity<electric_conductance_d> siemens{ampere / volt};
+    constexpr quantity<magnetic_flux_d> weber{volt * second};
+    constexpr quantity<magnetic_flux_density_d> tesla{weber / square(meter)};
+    constexpr quantity<inductance_d> henry{weber / ampere};
+    constexpr quantity<thermodynamic_temperature_d> degree_celsius{kelvin};
+    constexpr quantity<luminous_flux_d> lumen{candela * steradian};
+    constexpr quantity<illuminance_d> lux{lumen / meter / meter};
+    constexpr quantity<activity_of_a_nuclide_d> becquerel{1 / second};
+    constexpr quantity<absorbed_dose_d> gray{joule / kilogram};
+    constexpr quantity<dose_equivalent_d> sievert{joule / kilogram};
+    constexpr quantity<frequency_d> hertz{1 / second};
+
+    // The rest of the units approved for use with SI, as specified in SP811.
+    // (However, use of these units is generally discouraged.)
+
+    constexpr quantity<length_d> angstrom{Rep(1e-10L) * meter};
+    constexpr quantity<area_d> are{Rep(1e+2L) * square(meter)};
+    constexpr quantity<pressure_d> bar{Rep(1e+5L) * pascal};
+    constexpr quantity<area_d> barn{Rep(1e-28L) * square(meter)};
+    constexpr quantity<activity_of_a_nuclide_d> curie{Rep(3.7e+10L) * becquerel};
+    constexpr quantity<time_interval_d> day{Rep(86400L) * second};
+    constexpr Rep degree_angle{pi / 180};
+    constexpr quantity<acceleration_d> gal{Rep(1e-2L) * meter / square(second)};
+    constexpr quantity<area_d> hectare{Rep(1e+4L) * square(meter)};
+    constexpr quantity<time_interval_d> hour{Rep(3600) * second};
+    constexpr quantity<speed_d> knot{Rep(1852) / 3600 * meter / second};
+    constexpr quantity<volume_d> liter{Rep(1e-3L) * cube(meter)};
+    constexpr quantity<time_interval_d> minute{Rep(60) * second};
+    constexpr Rep minute_angle{pi / 10800};
+    constexpr quantity<length_d> mile_nautical{Rep(1852) * meter};
+    constexpr quantity<absorbed_dose_d> rad{Rep(1e-2L) * gray};
+    constexpr quantity<dose_equivalent_d> rem{Rep(1e-2L) * sievert};
+    constexpr quantity<exposure_d> roentgen{Rep(2.58e-4L) * coulomb / kilogram};
+    constexpr Rep second_angle{pi / 648000L};
+    constexpr quantity<mass_d> ton_metric{Rep(1e+3L) * kilogram};
+
+    // Alternate (non-US) spellings:
+
+    constexpr quantity<length_d> metre{meter};
+    constexpr quantity<volume_d> litre{liter};
+    constexpr Rep deca{deka};
+    constexpr quantity<mass_d> tonne{ton_metric};
+
+    // cooked literals for base units;
+    // these could also have been created with a script.
+
+#define QUANTITY_DEFINE_SCALING_LITERAL(sfx, dim, factor)                   \
+  constexpr quantity<dim, double> operator"" _##sfx(unsigned long long x) { \
+    return quantity<dim, double>(detail::magnitude_tag, factor * x);        \
+  }                                                                         \
+  constexpr quantity<dim, double> operator"" _##sfx(long double x) {        \
+    return quantity<dim, double>(detail::magnitude_tag, factor * x);        \
+  }
+
+#define QUANTITY_DEFINE_SCALING_LITERALS(pfx, dim, fact)    \
+  QUANTITY_DEFINE_SCALING_LITERAL(Y##pfx, dim, fact* yotta) \
+  QUANTITY_DEFINE_SCALING_LITERAL(Z##pfx, dim, fact* zetta) \
+  QUANTITY_DEFINE_SCALING_LITERAL(E##pfx, dim, fact* exa)   \
+  QUANTITY_DEFINE_SCALING_LITERAL(P##pfx, dim, fact* peta)  \
+  QUANTITY_DEFINE_SCALING_LITERAL(T##pfx, dim, fact* tera)  \
+  QUANTITY_DEFINE_SCALING_LITERAL(G##pfx, dim, fact* giga)  \
+  QUANTITY_DEFINE_SCALING_LITERAL(M##pfx, dim, fact* mega)  \
+  QUANTITY_DEFINE_SCALING_LITERAL(k##pfx, dim, fact* kilo)  \
+  QUANTITY_DEFINE_SCALING_LITERAL(h##pfx, dim, fact* hecto) \
+  QUANTITY_DEFINE_SCALING_LITERAL(da##pfx, dim, fact* deka) \
+  QUANTITY_DEFINE_SCALING_LITERAL(pfx, dim, fact * 1)       \
+  QUANTITY_DEFINE_SCALING_LITERAL(d##pfx, dim, fact* deci)  \
+  QUANTITY_DEFINE_SCALING_LITERAL(c##pfx, dim, fact* centi) \
+  QUANTITY_DEFINE_SCALING_LITERAL(m##pfx, dim, fact* milli) \
+  QUANTITY_DEFINE_SCALING_LITERAL(u##pfx, dim, fact* micro) \
+  QUANTITY_DEFINE_SCALING_LITERAL(n##pfx, dim, fact* nano)  \
+  QUANTITY_DEFINE_SCALING_LITERAL(p##pfx, dim, fact* pico)  \
+  QUANTITY_DEFINE_SCALING_LITERAL(f##pfx, dim, fact* femto) \
+  QUANTITY_DEFINE_SCALING_LITERAL(a##pfx, dim, fact* atto)  \
+  QUANTITY_DEFINE_SCALING_LITERAL(z##pfx, dim, fact* zepto) \
+  QUANTITY_DEFINE_SCALING_LITERAL(y##pfx, dim, fact* yocto)
+
+#define QUANTITY_DEFINE_LITERALS(pfx, dim) QUANTITY_DEFINE_SCALING_LITERALS(pfx, dim, 1)
+
+    /// literals
+
+    namespace literals {
+
+      QUANTITY_DEFINE_SCALING_LITERALS(g, mass_d, 1e-3)
+
+      QUANTITY_DEFINE_LITERALS(m, length_d)
+      QUANTITY_DEFINE_LITERALS(s, time_interval_d)
+      QUANTITY_DEFINE_LITERALS(A, electric_current_d)
+      QUANTITY_DEFINE_LITERALS(K, thermodynamic_temperature_d)
+      QUANTITY_DEFINE_LITERALS(mol, amount_of_substance_d)
+      QUANTITY_DEFINE_LITERALS(cd, luminous_intensity_d)
+
+    } // namespace literals
+
+  } // namespace units
+} // namespace phys
 
 #endif // PHYS_UNITS_QUANTITY_HPP_INCLUDED
 
diff --git a/ThirdParty/phys/units/quantity_io.hpp b/ThirdParty/phys/units/quantity_io.hpp
index 75df1ba64674bfdd407621c86227457419c9cddc..e94ffab36c1d0c84556cd326353aa1c6eb5d6881 100644
--- a/ThirdParty/phys/units/quantity_io.hpp
+++ b/ThirdParty/phys/units/quantity_io.hpp
@@ -131,6 +131,7 @@ struct unit_info
         emit_dim( os, "K",   Dims::dim5, first );
         emit_dim( os, "mol", Dims::dim6, first );
         emit_dim( os, "cd",  Dims::dim7, first );
+        emit_dim( os, "eV",  Dims::dim8, first );
 
         return os.str();
     }