diff --git a/include/HEJ/HDF5Reader.hh b/include/HEJ/HDF5Reader.hh
index 5b00fed..3b8e9e5 100644
--- a/include/HEJ/HDF5Reader.hh
+++ b/include/HEJ/HDF5Reader.hh
@@ -1,47 +1,48 @@
 /** \file
  *  \brief Header file for reading events in the HDF5 event format.
  *
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #pragma once
 
 #include "HEJ/EventReader.hh"
 
 namespace HEJ{
 
   //! Class for reading events from a file in the HDF5 file format
   /**
    * @details This format is specified in \cite Hoeche:2019rti.
    */
   class HDF5Reader : public EventReader{
   public:
+    HDF5Reader() = delete;
+
     //! Contruct object reading from the given file
     explicit HDF5Reader(std::string const & filename);
 
     //! Read an event
     bool read_event() override;
 
     //! Access header text
     std::string const & header() const override;
 
     //! Access run information
     LHEF::HEPRUP const & heprup() const override;
 
     //! Access last read event
     LHEF::HEPEUP const & hepeup() const override;
 
     //! Get number of events
     HEJ::optional<size_t> number_events() const override;
 
+    ~HDF5Reader();
+
   private:
     struct HDF5ReaderImpl;
-    struct HDF5ReaderImplDeleter {
-      void operator()(HDF5ReaderImpl* p);
-    };
 
-    std::unique_ptr<HDF5ReaderImpl, HDF5ReaderImplDeleter> impl_;
+    std::unique_ptr<HDF5ReaderImpl> impl_;
   };
 
 }
diff --git a/include/HEJ/HDF5Writer.hh b/include/HEJ/HDF5Writer.hh
index 01103bf..718ea33 100644
--- a/include/HEJ/HDF5Writer.hh
+++ b/include/HEJ/HDF5Writer.hh
@@ -1,55 +1,54 @@
 /** \file
  *  \brief Contains the EventWriter for HDF5 Output.
  *
  *  The output format is specified in arXiv:1905.05120.
  *
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #pragma once
 
 #include <memory>
 #include <string>
 
 #include "HEJ/EventWriter.hh"
 
 namespace LHEF {
   class HEPRUP;
 }
 
 namespace HEJ{
   class Event;
 
   //! This is an event writer specifically for HDF5 output.
   /**
    * \internal Implementation note: This uses the pimpl ("pointer to
    * implementation") idiom. HDF5 support is optional. Without pimpl,
    * we would have to specify whether HDF5 is available via the
    * preprocessor whenever this header is included. We don't want to
    * burden users of the HEJ library (for example the HEJ fixed-order
    * generator) with those details
    */
   class HDF5Writer: public EventWriter{
   public:
     //! Constructor
     /**
      * @param file      name of the output file
      * @param heprup    general process information
      */
     HDF5Writer(std::string const & file, LHEF::HEPRUP heprup);
-    ~HDF5Writer() override = default;
+    HDF5Writer() = delete;
 
     //! Write an event to the output file
     void write(Event const & ev) override;
 
+    ~HDF5Writer();
+
   private:
     struct HDF5WriterImpl;
-    struct HDF5WriterImplDeleter {
-      void operator()(HDF5WriterImpl* p);
-    };
 
-    std::unique_ptr<HDF5WriterImpl, HDF5WriterImplDeleter> impl_;
+    std::unique_ptr<HDF5WriterImpl> impl_;
   };
 
 }
diff --git a/include/HEJ/HepMC2Writer.hh b/include/HEJ/HepMC2Writer.hh
index 6dcc2e3..b64bc6b 100644
--- a/include/HEJ/HepMC2Writer.hh
+++ b/include/HEJ/HepMC2Writer.hh
@@ -1,54 +1,53 @@
 /** \file
  *  \brief Contains the EventWriter for HepMC Output.
  *
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #pragma once
 
 #include <memory>
 #include <string>
 
 #include "HEJ/EventWriter.hh"
 
 namespace LHEF {
   class HEPRUP;
 }
 
 namespace HEJ{
   class Event;
 
   //! This is an event writer specifically for HepMC output.
   /**
    * \internal Implementation note:
    * This uses the pimpl ("pointer to implementation") idiom.
    * HepMC support is optional and the implementation depends on the
    * HepMC version. Without pimpl, we would have to specify the HepMC version
    * via the preprocessor whenever this header is included. We don't want to
    * burden users of the HEJ library (for example the HEJ fixed-order generator)
    * with those details
    */
   class HepMC2Writer: public EventWriter{
   public:
     //! Constructor
     /**
      * @param file      name of the output file
      * @param heprup    general process information
      */
     HepMC2Writer(std::string const & file, LHEF::HEPRUP heprup);
-    ~HepMC2Writer() override = default;
+    HepMC2Writer() = delete;
 
     //! Write an event to the output file
     void write(Event const & ev) override;
 
+    ~HepMC2Writer();
+
   private:
     struct HepMC2WriterImpl;
-    struct HepMC2WriterImplDeleter {
-      void operator()(HepMC2WriterImpl* p);
-    };
 
-    std::unique_ptr<HepMC2WriterImpl, HepMC2WriterImplDeleter> impl_;
+    std::unique_ptr<HepMC2WriterImpl> impl_;
   };
 
 }
diff --git a/include/HEJ/HepMC3Writer.hh b/include/HEJ/HepMC3Writer.hh
index fdc658c..05d3ca5 100644
--- a/include/HEJ/HepMC3Writer.hh
+++ b/include/HEJ/HepMC3Writer.hh
@@ -1,54 +1,52 @@
 /** \file
  *  \brief Contains the EventWriter for HepMC3 Output.
  *
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #pragma once
 
 #include <memory>
 #include <string>
 
 #include "HEJ/EventWriter.hh"
 
 namespace LHEF {
   class HEPRUP;
 }
 
 namespace HEJ{
   class Event;
 
   //! This is an event writer specifically for HepMC3 output.
   /**
    * \internal Implementation note:
    * This uses the pimpl ("pointer to implementation") idiom.
    * HepMC3 support is optional and the implementation depends on the
    * HepMC3 version. Without pimpl, we would have to specify the HepMC3 version
    * via the preprocessor whenever this header is included. We don't want to
    * burden users of the HEJ library (for example the HEJ fixed-order generator)
    * with those details
    */
   class HepMC3Writer: public EventWriter{
   public:
     //! Constructor
     /**
      * @param file      name of the output file
      * @param heprup    general process information
      */
     HepMC3Writer(std::string const & file, LHEF::HEPRUP heprup);
-    ~HepMC3Writer() override = default;
+    HepMC3Writer() = delete;
 
     //! Write an event to the output file
     void write(Event const & ev) override;
 
+    ~HepMC3Writer();
   private:
     struct HepMC3WriterImpl;
-    struct HepMC3WriterImplDeleter {
-      void operator()(HepMC3WriterImpl* p);
-    };
 
-    std::unique_ptr<HepMC3WriterImpl, HepMC3WriterImplDeleter> impl_;
+    std::unique_ptr<HepMC3WriterImpl> impl_;
   };
 
 }
diff --git a/src/HDF5Reader.cc b/src/HDF5Reader.cc
index 4689ed2..3ed4b14 100644
--- a/src/HDF5Reader.cc
+++ b/src/HDF5Reader.cc
@@ -1,309 +1,304 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #include "HEJ/HDF5Reader.hh"
 
 #ifdef HEJ_BUILD_WITH_HDF5
 
 #include <numeric>
 #include <iterator>
 
 #include "highfive/H5File.hpp"
 
 namespace HEJ {
   namespace {
     // buffer size for reader
     // each "reading from disk" reads "chunk_size" many event at once
     constexpr std::size_t chunk_size = 10000;
 
     struct ParticleData {
       std::vector<int> id;
       std::vector<int> status;
       std::vector<int> mother1;
       std::vector<int> mother2;
       std::vector<int> color1;
       std::vector<int> color2;
       std::vector<double> px;
       std::vector<double> py;
       std::vector<double> pz;
       std::vector<double> e;
       std::vector<double> m;
       std::vector<double> lifetime;
       std::vector<double> spin;
     };
 
     struct EventRecords {
       std::vector<int> particle_start;
       std::vector<int> nparticles;
       std::vector<int> pid;
       std::vector<double> weight;
       std::vector<double> scale;
       std::vector<double> fscale;
       std::vector<double> rscale;
       std::vector<double> aqed;
       std::vector<double> aqcd;
       double trials;
       ParticleData particles;
     };
 
 class ConstEventIterator {
    public:
       // iterator traits
       using iterator_category = std::bidirectional_iterator_tag;
       using value_type = LHEF::HEPEUP;
       using difference_type = std::ptrdiff_t;
       using pointer = const LHEF::HEPEUP*;
       using reference = LHEF::HEPEUP const &;
 
       using iterator = ConstEventIterator;
       friend iterator cbegin(EventRecords const & records) noexcept;
       friend iterator cend(EventRecords const & records) noexcept;
 
       iterator& operator++() {
         particle_offset_ += records_.get().nparticles[idx_];
         ++idx_;
         return *this;
       }
       iterator& operator--() {
         --idx_;
         particle_offset_ -= records_.get().nparticles[idx_];
         return *this;
       }
       iterator operator--(int) {
         auto res = *this;
         --(*this);
         return res;
       }
       bool operator==(iterator const & other) const {
         return idx_ == other.idx_;
       }
       bool operator!=(iterator other) const {
         return !(*this == other);
       }
       value_type operator*() const {
         value_type hepeup{};
         auto const & r = records_.get();
         hepeup.NUP        = r.nparticles[idx_];
         hepeup.IDPRUP     = r.pid[idx_];
         hepeup.XWGTUP     = r.weight[idx_]/r.trials;
         hepeup.weights.emplace_back(hepeup.XWGTUP, nullptr);
         hepeup.SCALUP     = r.scale[idx_];
         hepeup.scales.muf = r.fscale[idx_];
         hepeup.scales.mur = r.rscale[idx_];
         hepeup.AQEDUP     = r.aqed[idx_];
         hepeup.AQCDUP     = r.aqcd[idx_];
         const size_t start = particle_offset_;
         const size_t end   = start + hepeup.NUP;
         auto const & p = r.particles;
         hepeup.IDUP    = std::vector<long>(   begin(p.id)+start,       begin(p.id)+end );
         hepeup.ISTUP   = std::vector<int>(    begin(p.status)+start,   begin(p.status)+end );
         hepeup.VTIMUP  = std::vector<double>( begin(p.lifetime)+start, begin(p.lifetime)+end );
         hepeup.SPINUP  = std::vector<double>( begin(p.spin)+start,     begin(p.spin)+end );
         hepeup.MOTHUP.resize(hepeup.NUP);
         hepeup.ICOLUP.resize(hepeup.NUP);
         hepeup.PUP.resize(hepeup.NUP);
         for(size_t i = 0; i < hepeup.MOTHUP.size(); ++i) {
           const size_t idx = start + i;
           assert(idx < end);
           hepeup.MOTHUP[i] = std::make_pair(p.mother1[idx], p.mother2[idx]);
           hepeup.ICOLUP[i] = std::make_pair(p.color1[idx], p.color2[idx]);
           hepeup.PUP[i]    = std::vector<double>{
             p.px[idx], p.py[idx], p.pz[idx], p.e[idx], p.m[idx]
           };
         }
         return hepeup;
       }
 
     private:
       explicit ConstEventIterator(EventRecords const & records):
         records_{records} {}
 
       std::reference_wrapper<const EventRecords> records_;
       size_t idx_ = 0;
       size_t particle_offset_ = 0;
     }; // end ConstEventIterator
 
     ConstEventIterator cbegin(EventRecords const & records) noexcept {
       return ConstEventIterator{records};
     }
 
     ConstEventIterator cend(EventRecords const & records) noexcept {
       auto it =ConstEventIterator{records};
       it.idx_ = records.aqcd.size(); // or size of any other records member
       return it;
     }
 
   } // end anonymous namespace
 
   struct HDF5Reader::HDF5ReaderImpl{
     HighFive::File file;
     std::size_t event_idx;
     std::size_t particle_idx;
     std::size_t nevents;
 
     EventRecords records;
     ConstEventIterator cur_event;
 
     LHEF::HEPRUP heprup;
     LHEF::HEPEUP hepeup;
 
     explicit HDF5ReaderImpl(std::string const & filename):
       file{filename},
       event_idx{0},
       particle_idx{0},
       nevents{
         file.getGroup("event")
         .getDataSet("nparticles") // or any other dataset
         .getSpace().getDimensions().front()
       },
       records{},
       cur_event{cbegin(records)},
       heprup{},
       hepeup{}
     {
       read_heprup();
       read_event_records(chunk_size);
     }
 
     void read_heprup() {
       const auto init = file.getGroup("init");
       init.getDataSet( "PDFgroupA"         ).read(heprup.PDFGUP.first);
       init.getDataSet( "PDFgroupB"         ).read(heprup.PDFGUP.second);
       init.getDataSet( "PDFsetA"           ).read(heprup.PDFSUP.first);
       init.getDataSet( "PDFsetB"           ).read(heprup.PDFSUP.second);
       init.getDataSet( "beamA"             ).read(heprup.IDBMUP.first);
       init.getDataSet( "beamB"             ).read(heprup.IDBMUP.second);
       init.getDataSet( "energyA"           ).read(heprup.EBMUP.first);
       init.getDataSet( "energyB"           ).read(heprup.EBMUP.second);
       init.getDataSet( "numProcesses"      ).read(heprup.NPRUP);
       init.getDataSet( "weightingStrategy" ).read(heprup.IDWTUP);
       const auto proc_info = file.getGroup("procInfo");
       proc_info.getDataSet( "procId"     ).read(heprup.LPRUP);
       proc_info.getDataSet( "xSection"   ).read(heprup.XSECUP);
       proc_info.getDataSet( "error"      ).read(heprup.XERRUP);
       // TODO: is this identification correct?
       proc_info.getDataSet( "unitWeight" ).read(heprup.XMAXUP);
       std::vector<double> trials;
       file.getGroup("event").getDataSet("trials").read(trials);
       records.trials = std::accumulate(begin(trials), end(trials), 0.);
     }
 
     std::size_t read_event_records(std::size_t count) {
       count = std::min(count, nevents-event_idx);
 
       auto events = file.getGroup("event");
       events.getDataSet("nparticles").select({event_idx}, {count}).read(records.nparticles);
       assert(records.nparticles.size() == count);
       events.getDataSet("pid").select(    {event_idx}, {count} ).read( records.pid );
       events.getDataSet("weight").select( {event_idx}, {count} ).read( records.weight );
       events.getDataSet("scale").select(  {event_idx}, {count} ).read( records.scale );
       events.getDataSet("fscale").select( {event_idx}, {count} ).read( records.fscale );
       events.getDataSet("rscale").select( {event_idx}, {count} ).read( records.rscale );
       events.getDataSet("aqed").select(   {event_idx}, {count} ).read( records.aqed );
       events.getDataSet("aqcd").select(   {event_idx}, {count} ).read( records.aqcd );
       const std::size_t particle_count = std::accumulate(
           begin(records.nparticles), end(records.nparticles), 0
       );
       auto pdata = file.getGroup("particle");
       auto & particles = records.particles;
       pdata.getDataSet("id").select(       {particle_idx}, {particle_count} ).read( particles.id );
       pdata.getDataSet("status").select(   {particle_idx}, {particle_count} ).read( particles.status );
       pdata.getDataSet("mother1").select(  {particle_idx}, {particle_count} ).read( particles.mother1 );
       pdata.getDataSet("mother2").select(  {particle_idx}, {particle_count} ).read( particles.mother2 );
       pdata.getDataSet("color1").select(   {particle_idx}, {particle_count} ).read( particles.color1 );
       pdata.getDataSet("color2").select(   {particle_idx}, {particle_count} ).read( particles.color2 );
       pdata.getDataSet("px").select(       {particle_idx}, {particle_count} ).read( particles.px );
       pdata.getDataSet("py").select(       {particle_idx}, {particle_count} ).read( particles.py );
       pdata.getDataSet("pz").select(       {particle_idx}, {particle_count} ).read( particles.pz );
       pdata.getDataSet("e").select(        {particle_idx}, {particle_count} ).read( particles.e );
       pdata.getDataSet("m").select(        {particle_idx}, {particle_count} ).read( particles.m );
       pdata.getDataSet("lifetime").select( {particle_idx}, {particle_count} ).read( particles.lifetime );
       pdata.getDataSet("spin").select(     {particle_idx}, {particle_count} ).read( particles.spin );
 
       event_idx += count;
       particle_idx += particle_count;
       return count;
     }
   };
 
   HDF5Reader::HDF5Reader(std::string const & filename):
-    impl_{
-          new HDF5Reader::HDF5ReaderImpl{filename},
-          HDF5Reader::HDF5ReaderImplDeleter{}
-    }
+    impl_{std::make_unique<HDF5ReaderImpl>(filename)}
   {}
 
   bool HDF5Reader::read_event() {
     if(impl_->cur_event == cend(impl_->records)) {
       // end of active chunk, read new events from file
       const auto events_read = impl_->read_event_records(chunk_size);
       impl_->cur_event = cbegin(impl_->records);
       if(events_read == 0) return false;
     }
     impl_->hepeup = *impl_->cur_event;
     ++impl_->cur_event;
     return true;
   }
 
   namespace {
     static const std::string nothing = "";
   }
 
   std::string const & HDF5Reader::header() const {
     return nothing;
   }
 
   LHEF::HEPRUP const & HDF5Reader::heprup() const {
     return impl_->heprup;
   }
 
   LHEF::HEPEUP const & HDF5Reader::hepeup() const {
     return impl_->hepeup;
   }
   HEJ::optional<size_t> HDF5Reader::number_events() const {
     return impl_->nevents;
   }
 }
 
 #else // no HDF5 support
 
 namespace HEJ {
   class HDF5Reader::HDF5ReaderImpl{};
 
   HDF5Reader::HDF5Reader(std::string const &){
     throw std::invalid_argument{
           "Failed to create HDF5 reader: "
           "HEJ 2 was built without HDF5 support"
     };
   }
 
   bool HDF5Reader::read_event() {
     throw std::logic_error{"unreachable"};
   }
 
   std::string const & HDF5Reader::header() const {
     throw std::logic_error{"unreachable"};
   }
 
   LHEF::HEPRUP const & HDF5Reader::heprup() const {
     throw std::logic_error{"unreachable"};
   }
 
   LHEF::HEPEUP const & HDF5Reader::hepeup() const {
     throw std::logic_error{"unreachable"};
   }
 
   HEJ::optional<size_t> HDF5Reader::number_events() const {
     throw std::logic_error{"unreachable"};
   }
 }
 
 #endif
 
 namespace HEJ {
-  void HDF5Reader::HDF5ReaderImplDeleter::operator()(HDF5ReaderImpl* p) {
-    delete p;
-  }
+  HDF5Reader::~HDF5Reader() = default;
 }
diff --git a/src/HDF5Writer.cc b/src/HDF5Writer.cc
index c61d1e0..032db8d 100644
--- a/src/HDF5Writer.cc
+++ b/src/HDF5Writer.cc
@@ -1,386 +1,381 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #include "HEJ/HDF5Writer.hh"
 
 #include <cassert>
 
 #include "LHEF/LHEF.h"
 
 #ifdef HEJ_BUILD_WITH_HDF5
 
 #include <type_traits>
 
 #include "HEJ/event_types.hh"
 #include "HEJ/Event.hh"
 
 #include "highfive/H5File.hpp"
 
 namespace HEJ{
 
   using HighFive::File;
   using HighFive::DataSpace;
 
   namespace{
     constexpr std::size_t chunk_size = 1000;
     constexpr unsigned compression_level = 3;
 
     size_t to_index(event_type::EventType const type){
       return type==0?0:floor(log2(type))+1;
     }
 
     template<typename T>
     void write_dataset(HighFive::Group & group, std::string const & name, T val) {
       using data_t = std::decay_t<T>;
       group.createDataSet<data_t>(name, DataSpace::From(val)).write(val);
     }
 
     template<typename T>
     void write_dataset(
         HighFive::Group & group, std::string const & name,
         std::vector<T> const & val
     ) {
       using data_t = std::decay_t<T>;
       group.createDataSet<data_t>(name, DataSpace::From(val)).write(val);
     }
 
     struct Cache {
       explicit Cache(size_t capacity):
         capacity{capacity}
       {
         nparticles.reserve(capacity);
         start.reserve(capacity);
         pid.reserve(capacity);
         weight.reserve(capacity);
         scale.reserve(capacity);
         fscale.reserve(capacity);
         rscale.reserve(capacity);
         aqed.reserve(capacity);
         aqcd.reserve(capacity);
         trials.reserve(capacity);
       }
 
       void fill(HEJ::Event ev) {
         const auto hepeup = to_HEPEUP(ev, nullptr);
 
         fill_event_params(hepeup);
         fill_event_particles(hepeup);
       }
 
       void fill_event_params(LHEF::HEPEUP const & ev) {
         nparticles.emplace_back(ev.NUP);
         start.emplace_back(particle_pos);
         pid.emplace_back(ev.IDPRUP);
         weight.emplace_back(ev.XWGTUP);
         scale.emplace_back(ev.SCALUP);
         fscale.emplace_back(ev.scales.muf);
         rscale.emplace_back(ev.scales.mur);
         aqed.emplace_back(ev.AQEDUP);
         aqcd.emplace_back(ev.AQCDUP);
         // set first trial=1 for first event
         // -> sum(trials) = 1 -> xs=sum(weights)/sum(trials) as in Sherpa
         if(particle_pos == 0){
           trials.emplace_back(1.);
         } else {
           trials.emplace_back(0.);
         }
         particle_pos += ev.NUP;
       }
 
       void fill_event_particles(LHEF::HEPEUP const & ev) {
         id.insert(end(id), begin(ev.IDUP), end(ev.IDUP));
         status.insert(end(status), begin(ev.ISTUP), end(ev.ISTUP));
         lifetime.insert(end(lifetime), begin(ev.VTIMUP), end(ev.VTIMUP));
         spin.insert(end(spin), begin(ev.SPINUP), end(ev.SPINUP));
         for(int i = 0; i < ev.NUP; ++i) {
           mother1.emplace_back(ev.MOTHUP[i].first);
           mother2.emplace_back(ev.MOTHUP[i].second);
           color1.emplace_back(ev.ICOLUP[i].first);
           color2.emplace_back(ev.ICOLUP[i].second);
           px.emplace_back(ev.PUP[i][0]);
           py.emplace_back(ev.PUP[i][1]);
           pz.emplace_back(ev.PUP[i][2]);
           e.emplace_back(ev.PUP[i][3]);
           m.emplace_back(ev.PUP[i][4]);
         }
       }
 
       bool is_full() const {
         return nparticles.size() >= capacity;
       }
 
       void clear() {
         nparticles.clear();
         start.clear();
         pid.clear();
         id.clear();
         status.clear();
         mother1.clear();
         mother2.clear();
         color1.clear();
         color2.clear();
         weight.clear();
         scale.clear();
         fscale.clear();
         rscale.clear();
         aqed.clear();
         aqcd.clear();
         trials.clear();
         px.clear();
         py.clear();
         pz.clear();
         e.clear();
         m.clear();
         lifetime.clear();
         spin.clear();
       }
 
       size_t capacity;
       std::vector<int> nparticles, start, pid, id, status,
         mother1, mother2, color1, color2;
       std::vector<double> weight, scale, fscale, rscale, aqed,
         aqcd, trials, px, py, pz, e, m, lifetime, spin;
 
     private:
       size_t particle_pos = 0;
     };
 
   }
 
   struct HDF5Writer::HDF5WriterImpl{
     File file;
     LHEF::HEPRUP heprup;
     Cache cache{chunk_size};
     size_t event_idx = 0;
     size_t particle_idx = 0;
 
     HDF5WriterImpl(std::string const & filename, LHEF::HEPRUP && hepr):
       file{filename, File::ReadWrite | File::Create | File::Truncate},
       heprup{std::move(hepr)}
     {
       // TODO: code duplication with Les Houches Writer
       const int max_number_types = to_index(event_type::last_type)+1;
       heprup.NPRUP = max_number_types;
       // ids of event types
       heprup.LPRUP.clear();
       heprup.LPRUP.reserve(max_number_types);
       heprup.LPRUP.emplace_back(0);
       for(size_t i=event_type::first_type+1; i<=event_type::last_type; i*=2) {
         heprup.LPRUP.emplace_back(i);
       }
 
       heprup.XSECUP = std::vector<double>(max_number_types, 0.);
       heprup.XERRUP = std::vector<double>(max_number_types, 0.);
       heprup.XMAXUP = std::vector<double>(max_number_types, 0.);
 
       write_init();
       create_event_group();
       create_particle_group();
     }
 
     void write_init() {
       auto init = file.createGroup("init");
 
       write_dataset(init, "PDFgroupA"        , heprup.PDFGUP.first);
       write_dataset(init, "PDFgroupB"        , heprup.PDFGUP.second);
       write_dataset(init, "PDFsetA"          , heprup.PDFSUP.first);
       write_dataset(init, "PDFsetB"          , heprup.PDFSUP.second);
       write_dataset(init, "beamA"            , heprup.IDBMUP.first);
       write_dataset(init, "beamB"            , heprup.IDBMUP.second);
       write_dataset(init, "energyA"          , heprup.EBMUP.first);
       write_dataset(init, "energyB"          , heprup.EBMUP.second);
       write_dataset(init, "numProcesses"     , heprup.NPRUP);
       write_dataset(init, "weightingStrategy", heprup.IDWTUP);
 
       auto proc_info = file.createGroup("procInfo");
       write_dataset(proc_info, "procId", heprup.LPRUP);
     }
 
     static HighFive::DataSetCreateProps const & hdf5_chunk() {
       static const auto props = [](){
         HighFive::DataSetCreateProps props;
         props.add(HighFive::Chunking({chunk_size}));
         props.add(HighFive::Deflate(compression_level));
         return props;
       }();
       return props;
     }
 
     void create_event_group() {
       static const auto dim = DataSpace({0}, {DataSpace::UNLIMITED});
       auto events = file.createGroup("event");
       events.createDataSet<int>("nparticles", dim, hdf5_chunk());
       events.createDataSet<int>("start", dim, hdf5_chunk());
       events.createDataSet<int>("pid", dim, hdf5_chunk());
       events.createDataSet<double>("weight", dim, hdf5_chunk());
       events.createDataSet<double>("scale", dim, hdf5_chunk());
       events.createDataSet<double>("fscale", dim, hdf5_chunk());
       events.createDataSet<double>("rscale", dim, hdf5_chunk());
       events.createDataSet<double>("aqed", dim, hdf5_chunk());
       events.createDataSet<double>("aqcd", dim, hdf5_chunk());
       events.createDataSet<double>("trials", dim, hdf5_chunk());
     }
 
     void resize_event_group(size_t new_size) {
       auto events = file.getGroup("event");
       events.getDataSet("nparticles").resize({new_size});
       events.getDataSet("start").resize({new_size});
       events.getDataSet("pid").resize({new_size});
       events.getDataSet("weight").resize({new_size});
       events.getDataSet("scale").resize({new_size});
       events.getDataSet("fscale").resize({new_size});
       events.getDataSet("rscale").resize({new_size});
       events.getDataSet("aqed").resize({new_size});
       events.getDataSet("aqcd").resize({new_size});
       events.getDataSet("trials").resize({new_size});
     }
 
     void create_particle_group() {
       static const auto dim = DataSpace({0}, {DataSpace::UNLIMITED});
       auto particles = file.createGroup("particle");
       particles.createDataSet<int>("id", dim, hdf5_chunk());
       particles.createDataSet<int>("status", dim, hdf5_chunk());
       particles.createDataSet<int>("mother1", dim, hdf5_chunk());
       particles.createDataSet<int>("mother2", dim, hdf5_chunk());
       particles.createDataSet<int>("color1", dim, hdf5_chunk());
       particles.createDataSet<int>("color2", dim, hdf5_chunk());
       particles.createDataSet<double>("px", dim, hdf5_chunk());
       particles.createDataSet<double>("py", dim, hdf5_chunk());
       particles.createDataSet<double>("pz", dim, hdf5_chunk());
       particles.createDataSet<double>("e", dim, hdf5_chunk());
       particles.createDataSet<double>("m", dim, hdf5_chunk());
       particles.createDataSet<double>("lifetime", dim, hdf5_chunk());
       particles.createDataSet<double>("spin", dim, hdf5_chunk());
     }
 
     void resize_particle_group(size_t new_size) {
       auto particles = file.getGroup("particle");
       particles.getDataSet("id").resize({new_size});
       particles.getDataSet("status").resize({new_size});
       particles.getDataSet("mother1").resize({new_size});
       particles.getDataSet("mother2").resize({new_size});
       particles.getDataSet("color1").resize({new_size});
       particles.getDataSet("color2").resize({new_size});
       particles.getDataSet("px").resize({new_size});
       particles.getDataSet("py").resize({new_size});
       particles.getDataSet("pz").resize({new_size});
       particles.getDataSet("e").resize({new_size});
       particles.getDataSet("m").resize({new_size});
       particles.getDataSet("lifetime").resize({new_size});
       particles.getDataSet("spin").resize({new_size});
     }
 
     void write(Event const & ev){
       cache.fill(ev);
       if(cache.is_full()) {
         dump_cache();
       }
       const double wt = ev.central().weight;
       const size_t idx = to_index(ev.type());
       heprup.XSECUP[idx] += wt;
       heprup.XERRUP[idx] += wt*wt;
       if(wt > heprup.XMAXUP[idx]){
         heprup.XMAXUP[idx] = wt;
       }
     }
 
     void dump_cache() {
       write_event_params();
       write_event_particles();
       cache.clear();
     }
 
     void write_event_params() {
       auto events = file.getGroup("event");
       // choose arbitrary dataset to find size
       const auto dataset = events.getDataSet("nparticles");
       const size_t size = dataset.getSpace().getDimensions().front();
       resize_event_group(size + cache.nparticles.size());
 
 #define WRITE_FROM_CACHE(GROUP, PROPERTY)                               \
       GROUP.getDataSet(#PROPERTY).select({size}, {cache.PROPERTY.size()}).write(cache.PROPERTY)
 
       WRITE_FROM_CACHE(events, nparticles);
       WRITE_FROM_CACHE(events, start);
       WRITE_FROM_CACHE(events, pid);
       WRITE_FROM_CACHE(events, weight);
       WRITE_FROM_CACHE(events, scale);
       WRITE_FROM_CACHE(events, fscale);
       WRITE_FROM_CACHE(events, rscale);
       WRITE_FROM_CACHE(events, aqed);
       WRITE_FROM_CACHE(events, aqcd);
       WRITE_FROM_CACHE(events, trials);
     }
 
     void write_event_particles() {
       auto particles = file.getGroup("particle");
       // choose arbitrary dataset to find size
       const auto dataset = particles.getDataSet("id");
       const size_t size = dataset.getSpace().getDimensions().front();
       resize_particle_group(size + cache.id.size());
       WRITE_FROM_CACHE(particles, id);
       WRITE_FROM_CACHE(particles, status);
       WRITE_FROM_CACHE(particles, lifetime);
       WRITE_FROM_CACHE(particles, spin);
       WRITE_FROM_CACHE(particles, mother1);
       WRITE_FROM_CACHE(particles, mother2);
       WRITE_FROM_CACHE(particles, color1);
       WRITE_FROM_CACHE(particles, color2);
       WRITE_FROM_CACHE(particles, px);
       WRITE_FROM_CACHE(particles, py);
       WRITE_FROM_CACHE(particles, pz);
       WRITE_FROM_CACHE(particles, e);
       WRITE_FROM_CACHE(particles, m);
     }
 #undef WRITE_FROM_CACHE
 
     ~HDF5WriterImpl(){
       dump_cache();
       auto proc_info = file.getGroup("procInfo");
       write_dataset(proc_info, "xSection", heprup.XSECUP);
       write_dataset(proc_info, "error", heprup.XERRUP);
       write_dataset(proc_info, "unitWeight", heprup.XMAXUP);
     }
 
   };
 
   HDF5Writer::HDF5Writer(std::string const & filename, LHEF::HEPRUP heprup):
-    impl_{
-    new HDF5Writer::HDF5WriterImpl{filename, std::move(heprup)},
-    HDF5Writer::HDF5WriterImplDeleter{}
-  }
+    impl_{new HDF5Writer::HDF5WriterImpl{filename, std::move(heprup)}}
   {}
 
   void HDF5Writer::write(Event const & ev){
     impl_->write(ev);
   }
 }
 
 #else // no HDF5 support
 
 namespace HEJ{
 
   class HDF5Writer::HDF5WriterImpl{};
 
   HDF5Writer::HDF5Writer(std::string const &, LHEF::HEPRUP){
     throw std::invalid_argument{
       "Failed to create HDF5 writer: "
       "HEJ 2 was built without HDF5 support"
     };
   }
 
   void HDF5Writer::write(Event const &){
     assert(false);
   }
 
 }
 
 #endif
 
 namespace HEJ {
-  void HDF5Writer::HDF5WriterImplDeleter::operator()(HDF5WriterImpl* p) {
-    delete p;
-  }
+  HDF5Writer::~HDF5Writer() = default;
 }
diff --git a/src/HepMC2Writer.cc b/src/HepMC2Writer.cc
index f603d5d..32d92f0 100644
--- a/src/HepMC2Writer.cc
+++ b/src/HepMC2Writer.cc
@@ -1,85 +1,80 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #include "HEJ/HepMC2Writer.hh"
 
 #include <cassert>
 
 #include "LHEF/LHEF.h"
 
 #ifdef HEJ_BUILD_WITH_HepMC2
 
 #include "HepMC/IO_GenEvent.h"
 
 #include <utility>
 
 #include "HepMC/GenParticle.h"
 #include "HepMC/GenVertex.h"
 
 #include "HEJ/Event.hh"
 #include "HEJ/exceptions.hh"
 #include "HEJ/HepMC2Interface.hh"
 
 namespace HEJ{
 
   struct HepMC2Writer::HepMC2WriterImpl{
     HepMC2Interface hepmc_;
 
     HepMC2WriterImpl & operator=(HepMC2WriterImpl const & other) = delete;
     HepMC2WriterImpl(HepMC2WriterImpl const & other) = delete;
     HepMC2WriterImpl & operator=(HepMC2WriterImpl && other) = delete;
     HepMC2WriterImpl(HepMC2WriterImpl && other) = delete;
     HepMC::IO_GenEvent writer_;
 
     HepMC2WriterImpl(
         std::string const & file, LHEF::HEPRUP && heprup
     ):
       hepmc_(heprup),
       writer_{file}
     {}
 
     void write(Event const & ev){
       auto out_ev = hepmc_(ev);
       writer_.write_event(&out_ev);
     }
   };
 
-  void HepMC2Writer::HepMC2WriterImplDeleter::operator()(HepMC2WriterImpl* p) {
-    delete p;
-  }
-
   HepMC2Writer::HepMC2Writer(std::string const & file, LHEF::HEPRUP heprup):
-    impl_{std::unique_ptr<HepMC2WriterImpl, HepMC2WriterImplDeleter>{
-      new HepMC2WriterImpl(file, std::move(heprup))
-    }}
+    impl_{new HepMC2WriterImpl{file, std::move(heprup)}}
   {}
 
   void HepMC2Writer::write(Event const & ev){
     impl_->write(ev);
   }
 } // namespace HEJ
 
 #else // no HepMC2
 
 namespace HEJ{
 
   class HepMC2Writer::HepMC2WriterImpl{};
 
   HepMC2Writer::HepMC2Writer(std::string const &, LHEF::HEPRUP){
       throw std::invalid_argument(
           "Failed to create HepMC writer: "
           "HEJ 2 was built without HepMC2 support"
       );
   }
 
   void HepMC2Writer::write(Event const &){
     assert(false);
   }
 
-  void HepMC2Writer::HepMC2WriterImplDeleter::operator()(HepMC2WriterImpl* p) {
-    delete p;
-  }
 }
 #endif
+
+namespace HEJ{
+  HepMC2Writer::~HepMC2Writer() = default;
+}
diff --git a/src/HepMC3Writer.cc b/src/HepMC3Writer.cc
index d646484..143bd65 100644
--- a/src/HepMC3Writer.cc
+++ b/src/HepMC3Writer.cc
@@ -1,122 +1,117 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #include "HEJ/HepMC3Writer.hh"
 
 #include <cassert>
 
 #include "LHEF/LHEF.h"
 
 #ifdef HEJ_BUILD_WITH_HepMC3
 
 #include "HepMC3/LHEFAttributes.h"
 #include "HepMC3/WriterAscii.h"
 
 #include "HEJ/Version.hh"
 
 #include <utility>
 
 #include "HepMC3/GenParticle.h"
 #include "HepMC3/GenVertex.h"
 
 #include "HEJ/Event.hh"
 #include "HEJ/exceptions.hh"
 #include "HEJ/HepMC3Interface.hh"
 
 namespace {
     void reset_weight_info(LHEF::HEPRUP & heprup){
       heprup.IDWTUP = 2;
       // use placeholders for unknown init block values
       // we can overwrite them after processing all events
       heprup.XSECUP = {0.};
       heprup.XERRUP = {0.};
       heprup.XMAXUP = {0.};
     }
     HepMC3::shared_ptr<HepMC3::GenRunInfo> init_runinfo(LHEF::HEPRUP && heprup){
       reset_weight_info(heprup);
       HepMC3::GenRunInfo runinfo;
 
       auto hepr = HepMC3::make_shared<HepMC3::HEPRUPAttribute>();
       hepr->heprup = heprup;
       runinfo.add_attribute(std::string("HEPRUP"), hepr);
 
       for (int i = 0, N = hepr->heprup.generators.size(); i < N; ++i ){
         HepMC3::GenRunInfo::ToolInfo tool;
         tool.name =  hepr->heprup.generators[i].name;
         tool.version =  hepr->heprup.generators[i].version;
         tool.description =  hepr->heprup.generators[i].contents;
         runinfo.tools().push_back(tool);
       }
       return HepMC3::make_shared<HepMC3::GenRunInfo>(runinfo);
     }
 
 } // namespace anonymous
 
 namespace HEJ{
 
   struct HepMC3Writer::HepMC3WriterImpl{
     HepMC3Interface HepMC3_;
 
     HepMC3WriterImpl & operator=(HepMC3WriterImpl const & other) = delete;
     HepMC3WriterImpl(HepMC3WriterImpl const & other) = delete;
     HepMC3WriterImpl & operator=(HepMC3WriterImpl && other) = delete;
     HepMC3WriterImpl(HepMC3WriterImpl && other) = delete;
 
     HepMC3::WriterAscii writer_;
 
     HepMC3WriterImpl(
         std::string const & file, LHEF::HEPRUP && heprup
     ):
       HepMC3_(heprup),
       writer_{file, init_runinfo(std::move(heprup))}
     {}
 
     ~HepMC3WriterImpl(){
       writer_.close();
     }
 
     void write(Event const & ev){
       auto out_ev = HepMC3_(ev);
       writer_.write_event(out_ev);
     }
   };
 
-  void HepMC3Writer::HepMC3WriterImplDeleter::operator()(HepMC3WriterImpl* p) {
-    delete p;
-  }
-
   HepMC3Writer::HepMC3Writer(std::string const & file, LHEF::HEPRUP heprup):
-    impl_{std::unique_ptr<HepMC3WriterImpl, HepMC3WriterImplDeleter>{
-      new HepMC3WriterImpl(file, std::move(heprup))
-    }}
+    impl_{new HepMC3WriterImpl(file, std::move(heprup))}
   {}
 
   void HepMC3Writer::write(Event const & ev){
     impl_->write(ev);
   }
 } // namespace HEJ
 
 #else // no HepMC3
 
 namespace HEJ{
 
   class HepMC3Writer::HepMC3WriterImpl{};
 
   HepMC3Writer::HepMC3Writer(std::string const &, LHEF::HEPRUP){
       throw std::invalid_argument(
           "Failed to create HepMC3 writer: "
           "HEJ 2 was built without HepMC3 support"
       );
   }
 
   void HepMC3Writer::write(Event const &){
     assert(false);
   }
 
-  void HepMC3Writer::HepMC3WriterImplDeleter::operator()(HepMC3WriterImpl* p) {
-    delete p;
-  }
 }
 #endif
+
+namespace HEJ{
+  HepMC3Writer::~HepMC3Writer() = default;
+}
diff --git a/src/Hjets.cc b/src/Hjets.cc
index e2fa700..61e64f9 100644
--- a/src/Hjets.cc
+++ b/src/Hjets.cc
@@ -1,1084 +1,1084 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #include "HEJ/jets.hh"
 #include "HEJ/Hjets.hh"
 
 #include <assert.h>
 #include <limits>
 
 #include "HEJ/Constants.hh"
 #ifdef HEJ_BUILD_WITH_QCDLOOP
 #include "qcdloop/qcdloop.h"
 #endif
 
 const COM looprwfactor = (COM(0.,1.)*M_PI*M_PI)/pow((2.*M_PI),4);
 constexpr double infinity = std::numeric_limits<double>::infinity();
 
 namespace {
   // Loop integrals
   #ifdef HEJ_BUILD_WITH_QCDLOOP
 
   COM B0DD(HLV q, double mq)
   {
     static std::vector<std::complex<double>> result(3);
     static auto ql_B0 = [](){
       ql::Bubble<std::complex<double>,double,double> ql_B0;
       ql_B0.setCacheSize(100);
       return ql_B0;
     }();
     static std::vector<double> masses(2);
     static std::vector<double> momenta(1);
     for(auto & m: masses) m = mq*mq;
     momenta.front() = q.m2();
     ql_B0.integral(result, 1, masses, momenta);
     return result[0];
   }
   COM C0DD(HLV q1, HLV q2, double mq)
   {
     static std::vector<std::complex<double>> result(3);
     static auto ql_C0 = [](){
       ql::Triangle<std::complex<double>,double,double> ql_C0;
       ql_C0.setCacheSize(100);
       return ql_C0;
     }();
     static std::vector<double> masses(3);
     static std::vector<double> momenta(3);
     for(auto & m: masses) m = mq*mq;
     momenta[0] = q1.m2();
     momenta[1] = q2.m2();
     momenta[2] = (q1+q2).m2();
     ql_C0.integral(result, 1, masses, momenta);
     return result[0];
   }
   COM D0DD(HLV q1,HLV q2, HLV q3, double mq)
   {
     static std::vector<std::complex<double>> result(3);
     static auto ql_D0 = [](){
       ql::Box<std::complex<double>,double,double> ql_D0;
       ql_D0.setCacheSize(100);
       return ql_D0;
     }();
     static std::vector<double> masses(4);
     static std::vector<double> momenta(6);
     for(auto & m: masses) m = mq*mq;
     momenta[0] = q1.m2();
     momenta[1] = q2.m2();
     momenta[2] = q3.m2();
     momenta[3] = (q1+q2+q3).m2();
     momenta[4] = (q1+q2).m2();
     momenta[5] = (q2+q3).m2();
     ql_D0.integral(result, 1, masses, momenta);
     return result[0];
   }
 
   COM A1(HLV q1, HLV q2, double mt)
   // As given in Eq. (B.2) of VDD
   {
     double q12,q22,Q2;
     HLV Q;
     double Delta3,mt2;
     COM ans(COM(0.,0.));
 
     q12=q1.m2();
     q22=q2.m2();
     Q=-q1-q2; // Define all momenta ingoing as in appendix of VDD
     Q2=Q.m2();
 
     Delta3=q12*q12+q22*q22+Q2*Q2-2*q12*q22-2*q12*Q2-2*q22*Q2;
 
     assert(mt > 0.);
 
     mt2=mt*mt;
 
     ans=looprwfactor*COM(0,-1)*C0DD(q1,q2,mt)*( 4.*mt2/Delta3*(Q2-q12-q22)
         -1.-4.*q12*q22/Delta3-12.*q12*q22*Q2/Delta3/Delta3*(q12+q22-Q2) )
       - looprwfactor*COM(0,-1)*( B0DD(q2,mt)-B0DD(Q,mt) )
         * ( 2.*q22/Delta3+12.*q12*q22/Delta3/Delta3*(q22-q12+Q2) )
       - looprwfactor*COM(0,-1)*( B0DD(q1,mt)-B0DD(Q,mt) )
         * ( 2.*q12/Delta3+12.*q12*q22/Delta3/Delta3*(q12-q22+Q2) )
       - 2./Delta3/16/M_PI/M_PI*(q12+q22-Q2);
 
     return ans;
 
   }
 
   COM A2(HLV q1, HLV q2, double mt)
   // As given in Eq. (B.2) of VDD, but with high energy limit
   // of invariants taken.
   {
     double q12,q22,Q2;
     HLV Q;
     double Delta3,mt2;
     COM ans(COM(0.,0.));
 
     assert(mt > 0.);
 
     mt2=mt*mt;
 
     q12=q1.m2();
     q22=q2.m2();
     Q=-q1-q2; // Define all momenta ingoing as in appendix of VDD
     Q2=Q.m2();
 
     Delta3=q12*q12+q22*q22+Q2*Q2-2*q12*q22-2*q12*Q2-2*q22*Q2;
     ans=looprwfactor*COM(0,-1)*C0DD(q1,q2,mt)*( 2.*mt2+1./2.*(q12+q22-Q2)
         +2.*q12*q22*Q2/Delta3 )
       +looprwfactor*COM(0,-1)*(B0DD(q2,mt)-B0DD(Q,mt))
         *q22*(q22-q12-Q2)/Delta3
       +looprwfactor*COM(0,-1)*(B0DD(q1,mt)-B0DD(Q,mt))
         *q12*(q12-q22-Q2)/Delta3+1./16/M_PI/M_PI;
 
     return ans;
   }
 
 #else // no QCDloop
 
   COM A1(HLV, HLV, double) {
     throw std::logic_error{"A1 called without QCDloop support"};
   }
 
   COM A2(HLV, HLV, double) {
     throw std::logic_error{"A2 called without QCDloop support"};
   }
 
 #endif
 
   void to_current(const HLV & q, current & ret){
     ret[0]=q.e();
     ret[1]=q.x();
     ret[2]=q.y();
     ret[3]=q.z();
   }
 
   /**
    * @brief Higgs vertex contracted with current @param C1 and @param C2
    */
   COM cHdot(const current & C1, const current & C2, const current & q1,
             const current & q2, double mt, bool incBot, double mb, double vev)
   {
     if (mt == infinity) {
       return (cdot(C1,C2)*cdot(q1,q2)-cdot(C1,q2)*cdot(C2,q1))/(3*M_PI*vev);
     }
     else {
       HLV vq1,vq2;
       vq1.set(q1[1].real(),q1[2].real(),q1[3].real(),q1[0].real());
       vq2.set(q2[1].real(),q2[2].real(),q2[3].real(),q2[0].real());
       // first minus sign obtained because of q1-difference to VDD
       // Factor is because 4 mt^2 g^2/vev A1 -> 16 pi mt^2/vev alphas,
       if(!(incBot))
         return 16.*M_PI*mt*mt/vev*(-cdot(C1,q2)*cdot(C2,q1)*A1(-vq1,vq2,mt)
                                         -cdot(C1,C2)*A2(-vq1,vq2,mt));
       else
         return 16.*M_PI*mt*mt/vev*(-cdot(C1,q2)*cdot(C2,q1)*A1(-vq1,vq2,mt)
                                         -cdot(C1,C2)*A2(-vq1,vq2,mt))
              + 16.*M_PI*mb*mb/vev*(-cdot(C1,q2)*cdot(C2,q1)*A1(-vq1,vq2,mb)
                                         -cdot(C1,C2)*A2(-vq1,vq2,mb));
     }
   }
 //@{
 /**
  * @brief Higgs+Jets FKL Contributions, function to handle all incoming types.
  * @param p1out             Outgoing Particle 1. (W emission)
  * @param p1in              Incoming Particle 1. (W emission)
  * @param p2out             Outgoing Particle 2 (Quark, unordered emission this side.)
  * @param p2in              Incoming Particle 2 (Quark, unordered emission this side.)
  * @param q1                t-channel momenta into higgs vertex
  * @param q2                t-channel momenta out of higgs vertex
  * @param mt                top mass (inf or value)
  * @param incBot            Bool, to include bottom mass (true) or not (false)?
  * @param mb                bottom mass (value)
  * @param pg                Unordered Gluon momenta
  *
  * Calculates j^\mu  H  j_\mu. FKL with higgs vertex somewhere in the FKL chain.
  * Handles all possible incoming states.
  */
   double j_h_j(HLV const & p1out, HLV const & p1in, HLV const & p2out,
                HLV const &  p2in, HLV const & q1, HLV const & q2,
                double mt, bool incBot, double mb, double vev
   ){
     current j1p,j1m,j2p,j2m, q1v, q2v;
 
     // Note need to flip helicities in anti-quark case.
     joi(p1out, false, p1in, false, j1p);
     joi(p1out,  true, p1in,  true, j1m);
     joi(p2out, false, p2in, false, j2p);
     joi(p2out,  true, p2in,  true, j2m);
 
     to_current(q1, q1v);
     to_current(q2, q2v);
 
     COM Mmp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb, vev);
     COM Mmm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb, vev);
     COM Mpp=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb, vev);
     COM Mpm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb, vev);
 
     // average over helicities
     const double sst=(abs2(Mmp)+abs2(Mmm)+abs2(Mpp)+abs2(Mpm))/4.;
 
     return sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
   }
 } // namespace anonymous
 
 double ME_H_qQ(HLV p1out, HLV p1in, HLV p2out, HLV p2in, HLV q1, HLV q2,
               double mt, bool incBot, double mb, double vev){
   return j_h_j(p1out, p1in, p2out, p2in, q1, q2, mt, incBot, mb, vev);
 }
 
 double ME_H_qQbar(HLV p1out, HLV p1in, HLV p2out, HLV p2in, HLV q1, HLV q2,
                  double mt, bool incBot, double mb, double vev){
   return j_h_j(p1out, p1in, p2out, p2in, q1, q2, mt, incBot, mb, vev);
 }
 
 double ME_H_qbarQ(HLV p1out, HLV p1in, HLV p2out, HLV p2in, HLV q1, HLV q2,
                  double mt, bool incBot, double mb, double vev){
   return j_h_j(p1out, p1in, p2out, p2in, q1, q2, mt, incBot, mb, vev);
 }
 
 double ME_H_qbarQbar(HLV p1out, HLV p1in, HLV p2out, HLV p2in, HLV q1, HLV q2,
                     double mt, bool incBot, double mb, double vev){
   return j_h_j(p1out, p1in, p2out, p2in, q1, q2, mt, incBot, mb, vev);
 }
 
 double ME_H_qg(HLV p1out, HLV p1in, HLV p2out, HLV p2in, HLV q1, HLV q2,
               double mt, bool incBot, double mb, double vev){
   return j_h_j(p1out, p1in, p2out, p2in, q1, q2, mt, incBot, mb, vev)
           * K_g(p2out,p2in)/HEJ::C_A;
 }
 
 double ME_H_qbarg(HLV p1out, HLV p1in, HLV p2out, HLV p2in, HLV q1, HLV q2,
                  double mt, bool incBot, double mb, double vev){
   return j_h_j(p1out, p1in, p2out, p2in, q1, q2, mt, incBot, mb, vev)
           * K_g(p2out,p2in)/HEJ::C_A;
 }
 
 double ME_H_gg(HLV p1out, HLV p1in, HLV p2out, HLV p2in, HLV q1, HLV q2,
               double mt, bool incBot, double mb, double vev){
   return j_h_j(p1out, p1in, p2out, p2in, q1, q2, mt, incBot, mb, vev)
           * K_g(p2out,p2in)/HEJ::C_A * K_g(p1out,p1in)/HEJ::C_A;
 }
 //@}
 namespace {
 
   //@{
   /// @brief Higgs vertex contracted with one current
 
   CCurrent jH(HLV const & pout, bool helout, HLV const & pin,
               bool helin, HLV const & q1, HLV const & q2,
               double mt, bool incBot, double mb, double vev)
   {
     CCurrent j2 = joi(pout,helout,pin,helin);
     CCurrent jq2(q2.e(),q2.px(),q2.py(),q2.pz());
 
     if(mt == infinity)
       return ((q1.dot(q2))*j2 - j2.dot(q1)*jq2)/(3*M_PI*vev);
     else
     {
       if(incBot)
         return (-16.*M_PI*mb*mb/vev*j2.dot(q1)*jq2*A1(-q1,q2,mb)
                 -16.*M_PI*mb*mb/vev*j2*A2(-q1,q2,mb))
           + (-16.*M_PI*mt*mt/vev*j2.dot(q1)*jq2*A1(-q1,q2,mt)
              -16.*M_PI*mt*mt/vev*j2*A2(-q1,q2,mt));
       else
         return (-16.*M_PI*mt*mt/vev*j2.dot(q1)*jq2*A1(-q1,q2,mt)
                 -16.*M_PI*mt*mt/vev*j2*A2(-q1,q2,mt));
     }
   }
   //@}
 
 //@{
 /**
  * @brief Higgs+Jets Unordered Contributions, function to handle all incoming types.
  * @param pg                Unordered Gluon momenta
  * @param p1out             Outgoing Particle 1. (W emission)
  * @param p1in              Incoming Particle 1. (W emission)
  * @param p2out             Outgoing Particle 2 (Quark, unordered emission this side.)
  * @param p2in              Incoming Particle 2 (Quark, unordered emission this side.)
  * @param q1                t-channel momenta into higgs vertex
  * @param q2                t-channel momenta out of higgs vertex
  * @param mt                top mass (inf or value)
  * @param incBot            Bool, to include bottom mass (true) or not (false)?
  * @param mb                bottom mass (value)
  *
  * Calculates j_{uno}^\mu H j_\mu. Unordered with higgs vertex
  * somewhere in the FKL chain.  Handles all possible incoming states.
  */
   double juno_h_j(HLV const & pg, HLV const & p1out, HLV const & p1in,
                   HLV const & p2out, HLV const & p2in,
                   HLV const & qH1,  HLV const & qH2,
                   double mt, bool incBot, double mb, double vev
   ){
     //  This construction is taking rapidity order: pg > p1out >> p2out
     HLV q1=p1in-p1out;  // Top End
     HLV q2=-(p2in-p2out);   // Bottom End
     HLV qg=p1in-p1out-pg;  // Extra bit post-gluon
 
     // Note <p1|eps|pa> current split into two by gauge choice.
     // See James C's Thesis (p72). <p1|eps|pa> -> <p1|pg><pg|pa>
     CCurrent mj1p=joi(p1out,false, p1in,false);
     CCurrent mj1m=joi(p1out, true, p1in, true);
     CCurrent jgap=joi(pg,   false, p1in,false);
     CCurrent jgam=joi(pg,    true, p1in, true);
 
     // Note for function joo(): <p1+|pg+> = <pg-|p1->.
     CCurrent j2gp=joo(p1out, false, pg, false);
     CCurrent j2gm=joo(p1out,  true, pg,  true);
 
     CCurrent mjH2p=jH(p2out, true,p2in, true,qH1,qH2,mt,incBot,mb, vev);
     CCurrent mjH2m=jH(p2out,false,p2in,false,qH1,qH2,mt,incBot,mb, vev);
 
     // Dot products of these which occur again and again
     COM MHmp=mj1m.dot(mjH2p);
     COM MHmm=mj1m.dot(mjH2m);
     COM MHpp=mj1p.dot(mjH2p);
     COM MHpm=mj1p.dot(mjH2m);
 
     CCurrent p2o(p2out), p2i(p2in), p1o(p1out), p1i(p1in), qsum(q1+qg);
 
     CCurrent Lmm=(qsum*(MHmm) + (-2.*mjH2m.dot(pg))*mj1m + 2.*mj1m.dot(pg)*mjH2m
          + ( p2o/pg.dot(p2out) + p2i/pg.dot(p2in) )*( qg.m2()*MHmm/2.) )/q1.m2();
     CCurrent Lmp=(qsum*(MHmp) + (-2.*mjH2p.dot(pg))*mj1m + 2.*mj1m.dot(pg)*mjH2p
          + ( p2o/pg.dot(p2out) + p2i/pg.dot(p2in) )*( qg.m2()*MHmp/2.) )/q1.m2();
     CCurrent Lpm=(qsum*(MHpm) + (-2.*mjH2m.dot(pg))*mj1p + 2.*mj1p.dot(pg)*mjH2m
          + ( p2o/pg.dot(p2out) + p2i/pg.dot(p2in) )*( qg.m2()*MHpm/2.) )/q1.m2();
     CCurrent Lpp=(qsum*(MHpp) + (-2.*mjH2p.dot(pg))*mj1p + 2.*mj1p.dot(pg)*mjH2p
          + ( p2o/pg.dot(p2out) + p2i/pg.dot(p2in) )*( qg.m2()*MHpp/2.) )/q1.m2();
 
     CCurrent U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
     CCurrent U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
     CCurrent U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
     CCurrent U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
     CCurrent U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
     CCurrent U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
     CCurrent U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
     CCurrent U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
 
     constexpr double cf=HEJ::C_F;
 
     double amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     double amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     double apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     double app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
     double ampsq=-(amm+amp+apm+app)/(q2.m2()*qH2.m2());
 
     // Now add the t-channels for the Higgs
     ampsq/=qH1.m2()*qg.m2();
     ampsq/=16.;
     // Factor of (Cf/Ca) for each quark to match ME_H_qQ.
     ampsq*=HEJ::C_F*HEJ::C_F/HEJ::C_A/HEJ::C_A;
 
     return ampsq;
   }
 } // namespace anonymous
 
 double ME_H_unob_qQ(HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in, HLV qH1,
                    HLV qH2, double mt, bool incBot, double mb, double vev){
   return juno_h_j(pg, p1out, p1in, p2out, p2in, qH1, qH2, mt, incBot, mb, vev);
 }
 
 double ME_H_unob_qbarQ(HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                       HLV qH1, HLV qH2, double mt, bool incBot, double mb, double vev){
   return juno_h_j(pg, p1out, p1in, p2out, p2in, qH1, qH2, mt, incBot, mb, vev);
 }
 
 double ME_H_unob_qQbar(HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                       HLV qH1, HLV qH2, double mt, bool incBot, double mb, double vev){
   return juno_h_j(pg, p1out, p1in, p2out, p2in, qH1, qH2, mt, incBot, mb, vev);
 }
 
 double ME_H_unob_qbarQbar(HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                          HLV qH1, HLV qH2, double mt, bool incBot, double mb, double vev){
   return juno_h_j(pg, p1out, p1in, p2out, p2in, qH1, qH2, mt, incBot, mb, vev);
 }
 
 double ME_H_unob_gQ(HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                    HLV qH1, HLV qH2, double mt, bool incBot, double mb, double vev){
   return juno_h_j(pg, p1out, p1in, p2out, p2in, qH1, qH2, mt, incBot, mb, vev)
           *K_g(p2out,p2in)/HEJ::C_F;
 }
 
 double ME_H_unob_gQbar(HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                       HLV qH1, HLV qH2, double mt, bool incBot, double mb, double vev){
   return juno_h_j(pg, p1out, p1in, p2out, p2in, qH1, qH2, mt, incBot, mb, vev)
           *K_g(p2out,p2in)/HEJ::C_F;
 }
 //@}
 
 // Begin finite mass stuff
 #ifdef HEJ_BUILD_WITH_QCDLOOP
 namespace {
 
   // All the stuff needed for the box functions in qg->qgH now...
   COM E1(HLV k1, HLV k2, HLV kh, double mq){
     HLV q2=-(k1+k2+kh);
     double Delta, Sigma, S1, S2, s12, s34;
     S1 = 2.*k1.dot(q2);
     S2 = 2.*k2.dot(q2);
     s12 = 2.*k1.dot(k2);
     s34 = q2.m2();
     Delta = s12*s34 - S1*S2;
     Sigma = 4.*s12*s34 - pow(S1+S2,2);
 
     return looprwfactor*(-s12*D0DD(k2, k1, q2, mq)*(1 - 8.*mq*mq/s12 + S2/(2.*s12) +
           S2*(s12 - 8.*mq*mq)*(s34 + S1)/(2.*s12*Delta) +
           2.*(s34 + S1)*(s34 + S1)/Delta +
           S2*pow((s34 + S1),3)/Delta/Delta) - ((s12 + S2)*C0DD(k2,
             k1 + q2, mq) -
           s12*C0DD(k1, k2, mq) + (S1 - S2)*C0DD(k1 + k2, q2, mq) -
           S1*C0DD(k1, q2,
             mq))*(S2*(s12 - 4.*mq*mq)/(2.*s12*Delta) +
           2.*(s34 + S1)/Delta +
           S2*pow((s34 + S1),2)/Delta/Delta) + (C0DD(k1, q2, mq) -
           C0DD(k1 + k2, q2, mq))*(1. - 4.*mq*mq/s12) -
        C0DD(k1 + k2, q2, mq)*2.*s34/
          S1 - (B0DD(k1 + q2, mq) -
           B0DD(k1 + k2 + q2, mq))*2.*s34*(s34 +
            S1)/(S1*Delta) + (B0DD(q2, mq) -
           B0DD(k1 + k2 + q2, mq) +
           s12*C0DD(k1 + k2, q2,
             mq))*(2.*s34*(s34 +
              S1)*(S1 - S2)/(Delta*Sigma) +
           2.*s34*(s34 + S1)/(S1*Delta)) + (B0DD(k1 + k2, mq) -
           B0DD(k1 + k2 + q2,
            mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))*2.*(s34 +
           S1)*(2.*s12*s34 -
            S2*(S1 + S2))/(Delta*Sigma));
   }
 
   COM F1(HLV k1, HLV k2, HLV kh, double mq){
     HLV q2 = -(k1+k2+kh);
     double Delta, Sigma, S1, S2, s12, s34;
     S1 = 2.*k1.dot(q2);
     S2 = 2.*k2.dot(q2);
     s12 = 2.*k1.dot(k2);
     s34 = q2.m2();
     Delta = s12*s34 - S1*S2;
     Sigma = 4.*s12*s34 - pow(S1+S2,2);
 
     return looprwfactor*(-S2*D0DD(k1, k2, q2,
          mq)*(0.5 - (s12 - 8.*mq*mq)*(s34 + S2)/(2.*Delta) -
           s12*pow((s34 + S2),3)/Delta/Delta) + ((s12 + S1)*C0DD(k1,
             k2 + q2, mq) -
           s12*C0DD(k1, k2, mq) - (S1 - S2)*C0DD(k1 + k2, q2, mq) -
           S2*C0DD(k2, q2,
             mq))*(S2*(s12 - 4.*mq*mq)/(2.*s12*Delta) +
           S2*pow((s34 + S2),2)/Delta/Delta)
           - (C0DD(k1 + k2, q2, mq) - C0DD(k1, k2 + q2, mq))*(1. - 4.*mq*mq/s12)
           - C0DD(k1, k2 + q2, mq) + (B0DD(k2 + q2, mq) -
           B0DD(k1 + k2 + q2,
            mq))*2.*pow((s34 + S2),2)/((s12 + S1)*Delta) - (B0DD(
            q2, mq) - B0DD(k1 + k2 + q2, mq) +
           s12*C0DD(k1 + k2, q2, mq))*2.*s34*(s34 +
           S2)*(S2 - S1)/(Delta*Sigma) + (B0DD(
            k1 + k2, mq) -
           B0DD(k1 + k2 + q2,
            mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))*2.*(s34 +
           S2)*(2.*s12*s34 -
            S2*(S1 + S2))/(Delta*Sigma));
   }
 
   COM G1(HLV k1, HLV k2, HLV kh, double mq){
     HLV q2 = -(k1+k2+kh);
     double Delta, S1, S2, s12, s34;
     S1 = 2.*k1.dot(q2);
     S2 = 2.*k2.dot(q2);
     s12 = 2.*k1.dot(k2);
     s34 = q2.m2();
     Delta = s12*s34 - S1*S2;
 
     return looprwfactor*(S2*D0DD(k1, q2, k2,
          mq)*(Delta/s12/s12 - 4.*mq*mq/s12) -
        S2*((s12 + S1)*C0DD(k1, k2 + q2, mq) -
           S1*C0DD(k1, q2, mq))*(1./
            s12/s12 - (s12 - 4.*mq*mq)/(2.*s12*Delta)) -
        S2*((s12 + S2)*C0DD(k1 + q2, k2, mq) -
           S2*C0DD(k2, q2, mq))*(1./
            s12/s12 + (s12 - 4.*mq*mq)/(2.*s12*Delta)) -
        C0DD(k1, q2, mq) - (C0DD(k1, k2 + q2, mq) -
           C0DD(k1, q2, mq))*4.*mq*mq/
          s12 + (B0DD(k1 + q2, mq) - B0DD(k1 + k2 + q2, mq))*2./
          s12 + (B0DD(k1 + q2, mq) -
           B0DD(q2, mq))*2.*s34/(s12*S1) + (B0DD(k2 + q2, mq) -
           B0DD(k1 + k2 + q2, mq))*2.*(s34 + S2)/(s12*(s12 + S1)));
   }
 
   COM E4(HLV k1, HLV k2, HLV kh, double mq){
     HLV q2 = -(k1+k2+kh);
     double Delta, Sigma, S1, S2, s12, s34;
     S1 = 2.*k1.dot(q2);
     S2 = 2.*k2.dot(q2);
     s12 = 2.*k1.dot(k2);
     s34 = q2.m2();
     Delta = s12*s34 - S1*S2;
     Sigma = 4.*s12*s34 - pow(S1+S2,2);
 
     return looprwfactor* (-s12*D0DD(k2, k1, q2,
          mq)*(0.5 - (S1 - 8.*mq*mq)*(s34 + S1)/(2.*Delta) -
           s12*pow((s34 + S1),3)/Delta/Delta) + ((s12 + S2)*C0DD(k2,
             k1 + q2, mq) -
           s12*C0DD(k1, k2, mq) + (S1 - S2)*C0DD(k1 + k2, q2, mq) -
           S1*C0DD(k1, q2, mq))*((S1 - 4.*mq*mq)/(2.*Delta) +
            s12*pow((s34 + S1),2)/Delta/Delta) -
        C0DD(k1 + k2, q2, mq) + (B0DD(k1 + q2, mq) -
           B0DD(k1 + k2 + q2, mq))*(2.*s34/Delta +
           2.*s12*(s34 + S1)/((s12 + S2)*Delta)) - (B0DD(
            q2, mq) - B0DD(k1 + k2 + q2, mq) +
           s12*C0DD(k1 + k2, q2,
             mq))*((2.*s34*(2.*s12*s34 - S2*(S1 + S2) +
               s12*(S1 - S2)))/(Delta*Sigma)) + (B0DD(k1 + k2, mq) -
                 B0DD(k1 + k2 + q2, mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))
               *((2.*s12*(2.*s12*s34 - S1*(S1 + S2) + s34*(S2 - S1)))/(Delta*Sigma)));
   }
 
   COM F4(HLV k1, HLV k2, HLV kh, double mq){
     HLV q2 = -(k1+k2+kh);
     double Delta, Sigma, S1, S2, s12, s34;
     S1 = 2.*k1.dot(q2);
     S2 = 2.*k2.dot(q2);
     s12 = 2.*k1.dot(k2);
     s34 = q2.m2();
     Delta = s12*s34 - S1*S2;
     Sigma = 4.*s12*s34 - pow(S1+S2,2);
 
     return looprwfactor* (-s12*D0DD(k1, k2, q2,
          mq)*(0.5 + (S1 - 8.*mq*mq)*(s34 + S2)/(2.*Delta) +
           s12*pow((s34 + S2),3)/Delta/Delta) - ((s12 + S1)*C0DD(k1,
             k2 + q2, mq) -
           s12*C0DD(k1, k2, mq) - (S1 - S2)*C0DD(k1 + k2, q2, mq) -
           S2*C0DD(k2, q2, mq))*((S1 - 4.*mq*mq)/(2.*Delta) +
            s12*pow((s34 + S2),2)/Delta/Delta) -
        C0DD(k1 + k2, q2, mq) - (B0DD(k2 + q2, mq) -
           B0DD(k1 + k2 + q2, mq))*2.*(s34 +
            S2)/Delta + (B0DD(q2, mq) -
           B0DD(k1 + k2 + q2, mq) +
           s12*C0DD(k1 + k2, q2, mq))*2.*s34*(2.*s12*s34 -
            S1*(S1 + S2) +
            s12*(S2 - S1))/(Delta*Sigma) - (B0DD(k1 + k2, mq) -
             B0DD(k1 + k2 + q2, mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))
             *(2.*s12*(2.*s12*s34 - S2*(S1 + S2) + s34*(S1 - S2))/(Delta*Sigma)));
   }
 
   COM G4(HLV k1, HLV k2, HLV kh, double mq){
     HLV q2 = -(k1+k2+kh);
     double Delta, S1, S2, s12, s34;
     S1 = 2.*k1.dot(q2);
     S2 = 2.*k2.dot(q2);
     s12 = 2.*k1.dot(k2);
     s34 = q2.m2();
     Delta = s12*s34 - S1*S2;
 
     return looprwfactor* (-D0DD(k1, q2, k2,
           mq)*(Delta/s12 + (s12 + S1)/2. -
           4.*mq*mq) + ((s12 + S1)*C0DD(k1, k2 + q2, mq) -
           S1*C0DD(k1, q2, mq))*(1./
            s12 - (S1 - 4.*mq*mq)/(2.*Delta)) + ((s12 + S2)*C0DD(
             k1 + q2, k2, mq) -
           S2*C0DD(k2, q2, mq))*(1./
            s12 + (S1 - 4.*mq*mq)/(2.*Delta)) + (B0DD(
            k1 + k2 + q2, mq) -
           B0DD(k1 + q2, mq))*2./(s12 + S2));
   }
 
   COM E10(HLV k1, HLV k2, HLV kh, double mq){
     HLV q2 = -(k1+k2+kh);
     double Delta, Sigma, S1, S2, s12, s34;
     S1 = 2.*k1.dot(q2);
     S2 = 2.*k2.dot(q2);
     s12 = 2.*k1.dot(k2);
     s34 = q2.m2();
     Delta = s12*s34 - S1*S2;
     Sigma = 4.*s12*s34 - pow(S1+S2,2);
 
     return looprwfactor*(-s12*D0DD(k2, k1, q2, mq)*((s34 + S1)/Delta +
            12.*mq*mq*S1*(s34 + S1)/Delta/Delta -
            4.*s12*S1*pow((s34 + S1),3)/Delta/Delta/Delta) - ((s12 + S2)*C0DD(k2, k1 + q2, mq) -
            s12*C0DD(k1, k2, mq) + (S1 - S2)*C0DD(k1 + k2, q2, mq) -
             S1*C0DD(k1, q2, mq))*(1./Delta +
            4.*mq*mq*S1/Delta/Delta -
            4.*s12*S1*pow((s34 + S1),2)/Delta/Delta/Delta) +
         C0DD(k1 + k2, q2, mq)*(4.*s12*s34*(S1 - S2)/(Delta*Sigma) -
            4.*(s12 -
               2.*mq*mq)*(2.*s12*s34 -
                S1*(S1 + S2))/(Delta*Sigma)) + (B0DD(k1 + q2, mq) -
            B0DD(k1 + k2 + q2, mq))*(4.*(s34 + S1)/((s12 + S2)*Delta) +
            8.*S1*(s34 + S1)/Delta/Delta) + (B0DD(q2, mq) -
            B0DD(k1 + k2 + q2, mq) +
            s12*C0DD(k1 + k2, q2, mq))*(12.*s34*(2.*s12 + S1 +
               S2)*(2.*s12*s34 -
                S1*(S1 + S2))/(Delta*Sigma*Sigma) -
            4.*s34*(4.*s12 + 3.*S1 +
                S2)/(Delta*Sigma) +
            8.*s12*s34*(s34*(s12 + S2) -
                S1*(s34 +
                   S1))/(Delta*Delta*Sigma)) + (B0DD(k1 + k2, mq) -
            B0DD(k1 + k2 + q2, mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2,
              mq))*(12.*s12*(2.*s34 + S1 +
               S2)*(2.*s12*s34 -
                S1*(S1 + S2))/(Delta*Sigma*Sigma) +
            8.*s12*S1*(s34*(s12 + S2) -
                S1*(s34 +
                   S1))/(Delta*Delta*Sigma))) + (COM(0.,1.)/(4.*M_PI*M_PI))*((2.*s12*s34 -
           S1*(S1 + S2))/(Delta*Sigma));
   }
 
   COM F10(HLV k1, HLV k2, HLV kh, double mq){
     HLV q2 = -(k1+k2+kh);
     double Delta, Sigma, S1, S2, s12, s34;
     S1 = 2.*k1.dot(q2);
     S2 = 2.*k2.dot(q2);
     s12 = 2.*k1.dot(k2);
     s34 = q2.m2();
     Delta = s12*s34 - S1*S2;
     Sigma = 4.*s12*s34 - pow(S1+S2,2);
 
     return looprwfactor* (s12*D0DD(k1, k2, q2,
           mq)*((s34 + S2)/Delta - 4.*mq*mq/Delta +
            12.*mq*mq*s34*(s12 + S1)/Delta/Delta -
            4.*s12*pow((s34 + S2),2)/Delta/Delta -
            4.*s12*S1*pow((s34 + S2),3)/Delta/Delta/Delta) + ((s12 + S1)*C0DD(k1, k2 + q2, mq) -
            s12*C0DD(k1, k2, mq) - (S1 - S2)*C0DD(k1 + k2, q2, mq) -
             S2*C0DD(k2, q2, mq))*(1./Delta +
            4.*mq*mq*S1/Delta/Delta -
            4.*s12*(s34 + S2)/Delta/Delta -
            4.*s12*S1*pow((s34 + S2),2)/Delta/Delta/Delta) -
         C0DD(k1 + k2, q2, mq)*(4.*s12*s34/(S2*Delta) +
            4.*s12*s34*(S2 - S1)/(Delta*Sigma) +
            4.*(s12 -
               2.*mq*mq)*(2.*s12*s34 -
                S1*(S1 + S2))/(Delta*Sigma)) - (B0DD(
             k2 + q2, mq) -
            B0DD(k1 + k2 + q2, mq))*(4.*s34/(S2*Delta) +
            8.*s34*(s12 + S1)/Delta/Delta) - (B0DD(q2, mq) -
            B0DD(k1 + k2 + q2, mq) +
            s12*C0DD(k1 + k2, q2,
              mq))*(-12*s34*(2*s12 + S1 +
               S2)*(2.*s12*s34 -
                S1*(S1 + S2))/(Delta*Sigma*Sigma) -
            4.*s12*s34*s34/(S2*Delta*Delta) +
            4.*s34*S1/(Delta*Sigma) -
            4.*s34*(s12*s34*(2.*s12 + S2) -
                S1*S1*(2.*s12 +
                   S1))/(Delta*Delta*Sigma)) - (B0DD(k1 + k2, mq) -
            B0DD(k1 + k2 + q2, mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))*(-12.*s12*(2.*s34 + S1 +
               S2)*(2.*s12*s34 -
                S1*(S1 + S2))/(Delta*Sigma*Sigma) +
            8.*s12*(2.*s34 + S1)/(Delta*Sigma) -
            8.*s12*s34*(2.*s12*s34 - S1*(S1 + S2) +
                s12*(S2 -
                   S1))/(Delta*Delta*Sigma))) + (COM(0.,1.)/(4.*M_PI*M_PI))*((2.*s12*s34 -
           S1*(S1 + S2))/(Delta*Sigma));
 
   }
 
   COM G10(HLV k1, HLV k2, HLV kh, double mq){
     HLV q2 = -(k1+k2+kh);
     double Delta, S1, S2, s12, s34;
     S1 = 2.*k1.dot(q2);
     S2 = 2.*k2.dot(q2);
     s12 = 2.*k1.dot(k2);
     s34 = q2.m2();
     Delta = s12*s34 - S1*S2;
 
     return looprwfactor* (-D0DD(k1, q2, k2, mq)*(1. +
           4.*S1*mq*mq/Delta) + ((s12 + S1)*C0DD(k1,
             k2 + q2, mq) -
           S1*C0DD(k1, q2, mq))*(1./Delta +
           4.*S1*mq*mq/Delta/Delta) - ((s12 + S2)*C0DD(k1 + q2,
             k2, mq) - S2*C0DD(k2, q2, mq))*(1./Delta +
           4.*S1*mq*mq/Delta/Delta) + (B0DD(k1 + k2 + q2, mq) -
           B0DD(k1 + q2, mq))*4.*(s34 +
            S1)/(Delta*(s12 + S2)) + (B0DD(q2, mq) -
           B0DD(k2 + q2, mq))*4.*s34/(Delta*S2));
   }
 
   COM H1(HLV k1, HLV k2, HLV kh, double mq){
     return E1(k1,k2,kh,mq)+F1(k1,k2,kh,mq)+G1(k1,k2,kh,mq);
   }
 
   COM H4(HLV k1, HLV k2, HLV kh, double mq){
     return E4(k1,k2,kh,mq)+F4(k1,k2,kh,mq)+G4(k1,k2,kh,mq);
   }
 
   COM H10(HLV k1, HLV k2, HLV kh, double mq){
     return E10(k1,k2,kh,mq)+F10(k1,k2,kh,mq)+G10(k1,k2,kh,mq);
   }
 
   COM H2(HLV k1, HLV k2, HLV kh, double mq){
     return -1.*H1(k2,k1,kh,mq);
   }
 
   COM H5(HLV k1, HLV k2, HLV kh, double mq){
     return -1.*H4(k2,k1,kh,mq);
   }
 
   COM H12(HLV k1, HLV k2, HLV kh, double mq){
     return -1.*H10(k2,k1,kh,mq);
   }
 
   // FL and FT functions
   COM FL(HLV q1, HLV q2, double mq){
     HLV Q = q1 + q2;
     double detQ2 = q1.m2()*q2.m2() - q1.dot(q2)*q1.dot(q2);
     return -1./(2.*detQ2)*((2.-
            3.*q1.m2()*q2.dot(Q)/detQ2)*(B0DD(q1, mq) -
            B0DD(Q, mq)) + (2. -
            3.*q2.m2()*q1.dot(Q)/detQ2)*(B0DD(q2, mq) -
            B0DD(Q, mq)) - (4.*mq*mq + q1.m2() + q2.m2() +
            Q.m2() - 3.*q1.m2()*q2.m2()*Q.m2()/detQ2)*C0DD(
           q1, q2, mq) - 2.);
   }
 
   COM FT(HLV q1, HLV q2, double mq){
     HLV Q = q1 + q2;
     double detQ2 = q1.m2()*q2.m2() - q1.dot(q2)*q1.dot(q2);
     return -1./(2.*detQ2)*(Q.m2()*(B0DD(q1, mq) + B0DD(q2, mq) - 2.*B0DD(Q, mq) -
             2.*q1.dot(q2)*C0DD(q1, q2, mq)) + (q1.m2() -
             q2.m2()) *(B0DD(q1, mq) - B0DD(q2, mq))) -
       q1.dot(q2)*FL(q1, q2, mq);
   }
 
   HLV ParityFlip(HLV p){
     HLV flippedVector;
     flippedVector.setE(p.e());
     flippedVector.setX(-p.x());
     flippedVector.setY(-p.y());
     flippedVector.setZ(-p.z());
     return flippedVector;
   }
 
   /// @brief HC amp for qg->qgH with finite top (i.e. j^{++}_H)
   void g_gH_HC(HLV pa, HLV p1,
     HLV pH, double mq, double vev, current &retAns)
   {
     current cura1,pacur,p1cur,pHcur,conjeps1,conjepsH1,epsa,epsHa,epsHapart1,
       epsHapart2,conjepsH1part1,conjepsH1part2;
     COM ang1a,sqa1;
 
     const double F = 4.*mq*mq/vev;
     // Easier to have the whole thing as current object so I can use cdot functionality.
     // Means I need to write pa,p1 as current objects
     to_current(pa, pacur);
     to_current(p1,p1cur);
     to_current(pH,pHcur);
     bool gluonforward = true;
     if(pa.z() < 0)
       gluonforward = false;
     //HEJ gauge
     jio(pa,false,p1,false,cura1);
 
     if(gluonforward){
       // sqrt(2pa_-/p1_-)*p1_perp/abs(p1_perp)
       ang1a = sqrt(pa.plus()*p1.minus())*(p1.x()+COM(0.,1.)*p1.y())/p1.perp();
       // sqrt(2pa_-/p1_-)*p1_perp*/abs(p1_perp)
       sqa1 = sqrt(pa.plus()*p1.minus())*(p1.x()-COM(0.,1.)*p1.y())/p1.perp();
     } else {
       ang1a = sqrt(pa.minus()*p1.plus());
       sqa1 = sqrt(pa.minus()*p1.plus());
     }
 
     const double prop = (pa-p1-pH).m2();
 
     cmult(-1./sqrt(2)/ang1a,cura1,conjeps1);
     cmult(1./sqrt(2)/sqa1,cura1,epsa);
 
     const COM Fta = FT(-pa,pa-pH,mq)/(pa-pH).m2();
     const COM Ft1 = FT(-p1-pH,p1,mq)/(p1+pH).m2();
 
     const COM h4 = H4(p1,-pa,pH,mq);
     const COM h5 = H5(p1,-pa,pH,mq);
     const COM h10 = H10(p1,-pa,pH,mq);
     const COM h12 = H12(p1,-pa,pH,mq);
 
     cmult(Fta*pa.dot(pH), epsa, epsHapart1);
     cmult(-1.*Fta*cdot(pHcur,epsa), pacur, epsHapart2);
     cmult(Ft1*cdot(pHcur,conjeps1), p1cur, conjepsH1part1);
     cmult(-Ft1*p1.dot(pH), conjeps1, conjepsH1part2);
     cadd(epsHapart1, epsHapart2, epsHa);
     cadd(conjepsH1part1, conjepsH1part2, conjepsH1);
     const COM aH1 = cdot(pHcur, cura1);
 
     current T1,T2,T3,T4,T5,T6,T7,T8,T9,T10;
 
     if(gluonforward){
       cmult(sqrt(2.)*sqrt(p1.plus()/pa.plus())*prop/sqa1, conjepsH1, T1);
       cmult(-sqrt(2.)*sqrt(pa.plus()/p1.plus())*prop/ang1a, epsHa, T2);
     }
     else{
       cmult(-sqrt(2.)*sqrt(p1.minus()/pa.minus())
           *((p1.x()-COM(0.,1.)*p1.y())/p1.perp())*prop/sqa1, conjepsH1, T1);
       cmult(sqrt(2.)*sqrt(pa.minus()/p1.minus())
           *((p1.x()-COM(0.,1.)*p1.y())/p1.perp())*prop/ang1a, epsHa, T2);
     }
 
     cmult(sqrt(2.)/ang1a*aH1, epsHa, T3);
     cmult(sqrt(2.)/sqa1*aH1, conjepsH1, T4);
 
     cmult(-sqrt(2.)*Fta*pa.dot(p1)*aH1/sqa1, conjeps1, T5);
     cmult(-sqrt(2.)*Ft1*pa.dot(p1)*aH1/ang1a, epsa, T6);
 
     cmult(-aH1/sqrt(2.)/sqa1*h4*8.*COM(0.,1.)*M_PI*M_PI, conjeps1, T7);
     cmult(aH1/sqrt(2.)/ang1a*h5*8.*COM(0.,1.)*M_PI*M_PI, epsa, T8);
     cmult(aH1*aH1/2./ang1a/sqa1*h10*8.*COM(0.,1.)*M_PI*M_PI, pacur, T9);
     cmult(-aH1*aH1/2./ang1a/sqa1*h12*8.*COM(0.,1.)*M_PI*M_PI, p1cur, T10);
 
     current ans;
-    for(int i=0;i<4;i++)
+    for(int i=0;i<4;++i)
     {
         ans[i] = T1[i]+T2[i]+T3[i]+T4[i]+T5[i]+T6[i]+T7[i]+T8[i]+T9[i]+T10[i];
     }
 
     retAns[0] = F/prop*ans[0];
     retAns[1] = F/prop*ans[1];
     retAns[2] = F/prop*ans[2];
     retAns[3] = F/prop*ans[3];
   }
 
   /// @brief HNC amp for qg->qgH with finite top (i.e. j^{+-}_H)
   void g_gH_HNC(HLV pa, HLV p1, HLV pH, double mq, double vev, current &retAns)
   {
     const double F = 4.*mq*mq/vev;
     COM ang1a,sqa1;
     current conjepsH1,epsHa,p1cur,pacur,pHcur,conjeps1,epsa,paplusp1cur,
       p1minuspacur,cur1a,cura1,epsHapart1,epsHapart2,conjepsH1part1,
       conjepsH1part2;
     // Find here if pa, meaning the gluon, is forward or backward
     bool gluonforward = true;
     if(pa.z() < 0)
       gluonforward = false;
 
     jio(pa,true,p1,true,cura1);
     joi(p1,true,pa,true,cur1a);
 
     to_current(pa,pacur);
     to_current(p1,p1cur);
     to_current(pH,pHcur);
     to_current(pa+p1,paplusp1cur);
     to_current(p1-pa,p1minuspacur);
     const COM aH1 = cdot(pHcur,cura1);
     const COM oneHa = std::conj(aH1); // = cdot(pHcur,cur1a)
 
     if(gluonforward){
       // sqrt(2pa_-/p1_-)*p1_perp/abs(p1_perp)
       ang1a = sqrt(pa.plus()*p1.minus())*(p1.x()+COM(0.,1.)*p1.y())/p1.perp();
       // sqrt(2pa_-/p1_-)*p1_perp*/abs(p1_perp)
       sqa1 = sqrt(pa.plus()*p1.minus())*(p1.x()-COM(0.,1.)*p1.y())/p1.perp();
       }
     else {
       ang1a = sqrt(pa.minus()*p1.plus());
       sqa1 = sqrt(pa.minus()*p1.plus());
     }
 
     const double prop = (pa-p1-pH).m2();
 
     cmult(1./sqrt(2)/sqa1, cur1a, epsa);
     cmult(-1./sqrt(2)/sqa1, cura1, conjeps1);
     const COM phase = cdot(conjeps1, epsa);
     const COM Fta = FT(-pa,pa-pH,mq)/(pa-pH).m2();
     const COM Ft1 = FT(-p1-pH,p1,mq)/(p1+pH).m2();
     const COM Falpha = FT(p1-pa,pa-p1-pH,mq);
     const COM Fbeta = FL(p1-pa,pa-p1-pH,mq);
 
     const COM h1 = H1(p1,-pa, pH, mq);
     const COM h2 = H2(p1,-pa, pH, mq);
     const COM h4 = H4(p1,-pa, pH, mq);
     const COM h5 = H5(p1,-pa, pH, mq);
     const COM h10 = H10(p1,-pa, pH, mq);
     const COM h12 = H12(p1,-pa, pH, mq);
 
     cmult(Fta*pa.dot(pH), epsa, epsHapart1);
     cmult(-1.*Fta*cdot(pHcur,epsa), pacur, epsHapart2);
     cmult(Ft1*cdot(pHcur,conjeps1), p1cur, conjepsH1part1);
     cmult(-Ft1*p1.dot(pH), conjeps1, conjepsH1part2);
     cadd(epsHapart1, epsHapart2, epsHa);
     cadd(conjepsH1part1, conjepsH1part2, conjepsH1);
 
     current T1,T2,T3,T4,T5a,T5b,T6,T7,T8a,T8b,T9,T10,T11a,
       T11b,T12a,T12b,T13;
 
     if(gluonforward){
       cmult(sqrt(2.)*sqrt(p1.plus()/pa.plus())*prop/sqa1, conjepsH1, T1);
       cmult(-sqrt(2.)*sqrt(pa.plus()/p1.plus())*prop/sqa1, epsHa, T2);
     }
     else{
       cmult(-sqrt(2.)*sqrt(p1.minus()/pa.minus())*((p1.x()-COM(0.,1.)*p1.y())/p1.perp())
           *prop/sqa1, conjepsH1, T1);
       cmult(sqrt(2.)*sqrt(pa.minus()/p1.minus())*((p1.x()+COM(0.,1.)*p1.y())/p1.perp())
           *prop/sqa1, epsHa, T2);
     }
 
     const COM boxdiagFact = 8.*COM(0.,1.)*M_PI*M_PI;
 
     cmult(aH1*sqrt(2.)/sqa1, epsHa, T3);
     cmult(oneHa*sqrt(2.)/sqa1, conjepsH1, T4);
     cmult(-2.*phase*Fta*pa.dot(pH), p1cur, T5a);
     cmult(2.*phase*Ft1*p1.dot(pH), pacur, T5b);
     cmult(-sqrt(2.)*Fta*p1.dot(pa)*oneHa/sqa1, conjeps1, T6);
     cmult(-sqrt(2.)*Ft1*pa.dot(p1)*aH1/sqa1, epsa, T7);
 
     cmult(-boxdiagFact*phase*h2, pacur, T8a);
     cmult(boxdiagFact*phase*h1, p1cur, T8b);
     cmult(boxdiagFact*aH1/sqrt(2.)/sqa1*h5, epsa, T9);
     cmult(-boxdiagFact*oneHa/sqrt(2.)/sqa1*h4, conjeps1, T10);
     cmult(boxdiagFact*aH1*oneHa/2./sqa1/sqa1*h10, pacur, T11a);
     cmult(-boxdiagFact*aH1*oneHa/2./sqa1/sqa1*h12, p1cur, T11b);
 
     cmult(-phase/(pa-p1).m2()*Falpha*(p1-pa).dot(pa-p1-pH), paplusp1cur, T12a);
     cmult(phase/(pa-p1).m2()*Falpha*(pa+p1).dot(pa-p1-pH), p1minuspacur, T12b);
     cmult(-phase*Fbeta*(pa-p1-pH).m2(), paplusp1cur, T13);
 
     current ans;
-    for(int i=0;i<4;i++)
+    for(int i=0;i<4;++i)
     {
       ans[i] = T1[i]+T2[i]+T3[i]+T4[i]+T5a[i]+T5b[i]+T6[i]+T7[i]+T8a[i]+T8b[i]
               +T9[i]+T10[i]+T11a[i]+T11b[i]+T12a[i]+T12b[i]+T13[i];
     }
 
     retAns[0] = F/prop*ans[0];
     retAns[1] = F/prop*ans[1];
     retAns[2] = F/prop*ans[2];
     retAns[3] = F/prop*ans[3];
   }
 
 } // namespace anonymous
 
 // JDC - new amplitude with Higgs emitted close to gluon with full mt effects.
 //       Keep usual HEJ-style function call
 double ME_Houtside_gq(HLV p1out, HLV p1in, HLV p2out, HLV p2in, HLV pH,
                       double mq, bool includeBottom, double mq2, double vev
 ){
 
   current cur2bplus,cur2bminus, cur2bplusFlip, cur2bminusFlip;
   current retAns,retAnsb;
   joi(p2out,true,p2in,true,cur2bplus);
   joi(p2out,false,p2in,false,cur2bminus);
   joi(ParityFlip(p2out),true,ParityFlip(p2in),true,cur2bplusFlip);
   joi(ParityFlip(p2out),false,ParityFlip(p2in),false,cur2bminusFlip);
 
   COM app1,app2,apm1,apm2;
   COM app3, app4, apm3, apm4;
 
   if(!includeBottom)
   {
     g_gH_HC(p1in,p1out,pH,mq,vev,retAns);
     app1=cdot(retAns,cur2bplus);
     app2=cdot(retAns,cur2bminus);
 
     g_gH_HC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq,vev,retAns);
     app3=cdot(retAns,cur2bplusFlip);
     app4=cdot(retAns,cur2bminusFlip);
 
     // And non-conserving bits
     g_gH_HNC(p1in,p1out,pH,mq,vev,retAns);
     apm1=cdot(retAns,cur2bplus);
     apm2=cdot(retAns,cur2bminus);
 
     g_gH_HNC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq,vev,retAns);
     apm3=cdot(retAns,cur2bplusFlip);
     apm4=cdot(retAns,cur2bminusFlip);
   } else {
     g_gH_HC(p1in,p1out,pH,mq,vev,retAns);
     g_gH_HC(p1in,p1out,pH,mq2,vev,retAnsb);
     app1=cdot(retAns,cur2bplus) + cdot(retAnsb,cur2bplus);
     app2=cdot(retAns,cur2bminus) + cdot(retAnsb,cur2bminus);
 
     g_gH_HC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq,vev,retAns);
     g_gH_HC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq2,vev,retAnsb);
     app3=cdot(retAns,cur2bplusFlip) + cdot(retAnsb,cur2bplusFlip);
     app4=cdot(retAns,cur2bminusFlip) + cdot(retAnsb,cur2bminusFlip);
 
     // And non-conserving bits
     g_gH_HNC(p1in,p1out,pH,mq,vev,retAns);
     g_gH_HNC(p1in,p1out,pH,mq2,vev,retAnsb);
     apm1=cdot(retAns,cur2bplus) + cdot(retAnsb,cur2bplus);
     apm2=cdot(retAns,cur2bminus) + cdot(retAnsb,cur2bminus);
 
     g_gH_HNC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq,vev,retAns);
     g_gH_HNC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq2,vev,retAnsb);
     apm3=cdot(retAns,cur2bplusFlip) + cdot(retAnsb,cur2bplusFlip);
     apm4=cdot(retAns,cur2bminusFlip) + cdot(retAnsb,cur2bminusFlip);
   }
 
   return abs2(app1) + abs2(app2) + abs2(app3) + abs2(app4) + abs2(apm1)
     + abs2(apm2) + abs2(apm3) + abs2(apm4);
 }
 #endif // HEJ_BUILD_WITH_QCDLOOP
 
 double C2gHgm(HLV p2, HLV p1, HLV pH, double vev)
 {
   const double A=1./(3.*M_PI*vev);
   // Implements Eq. (4.22) in hep-ph/0301013 with modifications to incoming plus momenta
   double s12,p1p,p2p;
   COM p1perp,p3perp,phperp;
   // Determine first whether this is the case p1p\sim php>>p3p or the opposite
   s12=p1.invariantMass2(-p2);
   if (p2.pz()>0.) { // case considered in hep-ph/0301013
     p1p=p1.plus();
     p2p=p2.plus();
   } else { // opposite case
     p1p=p1.minus();
     p2p=p2.minus();
   }
   p1perp=p1.px()+COM(0,1)*p1.py();
   phperp=pH.px()+COM(0,1)*pH.py();
   p3perp=-(p1perp+phperp);
 
   COM temp=COM(0,1)*A/(2.*s12)*(p2p/p1p*conj(p1perp)*p3perp+p1p/p2p*p1perp*conj(p3perp));
   temp=temp*conj(temp);
   return temp.real();
 }
 
 double C2gHgp(HLV p2, HLV p1, HLV pH, double vev)
 {
   const double A=1./(3.*M_PI*vev);
   // Implements Eq. (4.23) in hep-ph/0301013
   double s12,php,p1p,phm;
   COM p1perp,p3perp,phperp;
   // Determine first whether this is the case p1p\sim php>>p3p or the opposite
   s12=p1.invariantMass2(-p2);
   if (p2.pz()>0.) { // case considered in hep-ph/0301013
     php=pH.plus();
     phm=pH.minus();
     p1p=p1.plus();
   } else { // opposite case
     php=pH.minus();
     phm=pH.plus();
     p1p=p1.minus();
   }
   p1perp=p1.px()+COM(0,1)*p1.py();
   phperp=pH.px()+COM(0,1)*pH.py();
   p3perp=-(p1perp+phperp);
 
   COM temp=-COM(0,1)*A/(2.*s12)*( conj(p1perp*p3perp)*pow(php/p1p,2)/(1.+php/p1p)
     +s12*(pow(conj(phperp),2)/(pow(abs(phperp),2)+p1p*phm)
       -pow(conj(p3perp)
       +(1.+php/p1p)*conj(p1perp),2)/((1.+php/p1p)*(pH.m2()+2.*p1.dot(pH)))) );
   temp=temp*conj(temp);
   return temp.real();
 }
 
 double C2qHqm(HLV p2, HLV p1, HLV pH, double vev)
 {
   const double A=1./(3.*M_PI*vev);
   // Implements Eq. (4.22) in hep-ph/0301013
   double s12,p2p,p1p;
   COM p1perp,p3perp,phperp;
   // Determine first whether this is the case p1p\sim php>>p3p or the opposite
   s12=p1.invariantMass2(-p2);
   if (p2.pz()>0.) { // case considered in hep-ph/0301013
     p2p=p2.plus();
     p1p=p1.plus();
   } else { // opposite case
     p2p=p2.minus();
     p1p=p1.minus();
   }
   p1perp=p1.px()+COM(0,1)*p1.py();
   phperp=pH.px()+COM(0,1)*pH.py();
   p3perp=-(p1perp+phperp);
 
   COM temp=A/(2.*s12)*( sqrt(p2p/p1p)*p3perp*conj(p1perp)
     +sqrt(p1p/p2p)*p1perp*conj(p3perp) );
   temp=temp*conj(temp);
   return temp.real();
 }
diff --git a/src/Tensor.cc b/src/Tensor.cc
index 9cf5c0f..69d8d75 100644
--- a/src/Tensor.cc
+++ b/src/Tensor.cc
@@ -1,691 +1,691 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #include "HEJ/Tensor.hh"
 
 #include <array>
 #include <iostream>
 #include <valarray>
 #include <vector>
 
 #include <CLHEP/Vector/LorentzVector.h>
 
 namespace HEJ {
   namespace{
     // Tensor Template definitions
     short int sigma_index5[1024];
     short int sigma_index3[64];
     std::valarray<COM> permfactor5;
     std::valarray<COM> permfactor3;
     short int helfactor5[2][1024];
     short int helfactor3[2][64];
 
     // map from a list of tensor lorentz indices onto a single index
     // in d dimensional spacetime
     // TODO: basically the same as detail::accumulate_idx
     template<std::size_t N>
       std::size_t tensor_to_list_idx(std::array<int, N> const & indices) {
       std::size_t list_idx = 0;
       for(std::size_t i = 1, factor = 1; i <= N; ++i) {
         list_idx += factor*indices[N-i];
         factor *= detail::d;
       }
 #ifndef NDEBUG
       constexpr std::size_t max_possible_idx = detail::power(detail::d, N);
       assert(list_idx < max_possible_idx);
 #endif
       return list_idx;
     }
 
     // generate all unique perms of vectors {a,a,a,a,b}, return in perms
     // set_permfactor is a bool which encodes the anticommutation relations of the
     // sigma matrices namely if we have sigma0, set_permfactor= false because it
     // commutes with all others otherwise we need to assign a minus sign to odd
     // permutations, set in permfactor
     // note, inital perm is always even
     void perms41(int same4, int diff, std::vector<std::array<int,5>> & perms){
       bool set_permfactor(true);
       if(same4==0||diff==0)
         set_permfactor=false;
 
-      for(int diffpos=0;diffpos<5;diffpos++){
+      for(int diffpos=0;diffpos<5;++diffpos){
         std::array<int,5> tempvec={same4,same4,same4,same4,same4};
         tempvec[diffpos]=diff;
         perms.push_back(tempvec);
         if(set_permfactor){
           if(diffpos%2==1)
             permfactor5[tensor_to_list_idx(tempvec)]=-1.;
         }
       }
     }
 
     // generate all unique perms of vectors {a,a,a,b,b}, return in perms
     // note, inital perm is always even
     void perms32(int same3, int diff, std::vector<std::array<int,5>> & perms){
       bool set_permfactor(true);
       if(same3==0||diff==0)
         set_permfactor=false;
 
-      for(int diffpos1=0;diffpos1<5;diffpos1++){
-        for(int diffpos2=diffpos1+1;diffpos2<5;diffpos2++){
+      for(int diffpos1=0;diffpos1<5;++diffpos1){
+        for(int diffpos2=diffpos1+1;diffpos2<5;++diffpos2){
           std::array<int,5> tempvec={same3,same3,same3,same3,same3};
           tempvec[diffpos1]=diff;
           tempvec[diffpos2]=diff;
           perms.push_back(tempvec);
           if(set_permfactor){
             if((diffpos2-diffpos1)%2==0)
               permfactor5[tensor_to_list_idx(tempvec)]=-1.;
           }
         }
       }
     }
 
     // generate all unique perms of vectors {a,a,a,b,c}, return in perms
     // we have two bools since there are three distinct type of sigma matrices to
     // permute, so need to test if the 3xrepeated = sigma0 or if one of the
     // singles is sigma0
     // if diff1/diff2 are distinct, flipping them results in a change of perm,
     // otherwise it'll be symmetric under flip -> encode this in set_permfactor2
     // as long as diff2!=0 can ensure inital perm is even
     // if diff2=0 then it is not possible to ensure inital perm even -> encode in
     // bool signflip
     void perms311(int same3, int diff1, int diff2,
                   std::vector<std::array<int,5>> & perms
     ){
       bool set_permfactor2(true);
       bool same0(false);
       bool diff0(false);
       bool signflip(false); // if true, inital perm is odd
 
       if(same3==0) // is the repeated matrix sigma0?
         same0 = true;
       else if(diff2==0){ // is one of the single matrices sigma0
         diff0=true;
         if((diff1%3-same3)!=-1)
           signflip=true;
       } else if(diff1==0){
         std::cerr<<"Note, only first and last argument may be zero"<<std::endl;
         return;
       }
 
       // possible outcomes: tt, ft, tf
 
-      for(int diffpos1=0;diffpos1<5;diffpos1++){
-        for(int diffpos2=diffpos1+1;diffpos2<5;diffpos2++){
+      for(int diffpos1=0;diffpos1<5;++diffpos1){
+        for(int diffpos2=diffpos1+1;diffpos2<5;++diffpos2){
           std::array<int,5> tempvec={same3,same3,same3,same3,same3};
           tempvec[diffpos1]=diff1;
           tempvec[diffpos2]=diff2;
           perms.push_back(tempvec);
 
           if(!same0 && !diff0){
             // full antisymmetric under exchange of same3,diff1,diff2
             if((diffpos2-diffpos1)%2==0){
               permfactor5[tensor_to_list_idx(tempvec)]=-1.*COM(0,1); // odd perm
               // if this perm is odd, swapping diff1<->diff2 automatically even
               set_permfactor2=false;
             } else {
               permfactor5[tensor_to_list_idx(tempvec)]=COM(0,1); // even perm
               // if this perm is even, swapping diff1<->diff2 automatically odd
               set_permfactor2=true;
             }
           } else if(diff0){// one of the single matrices is sigma0
             if(signflip){ // initial config is odd!
               if(diffpos1%2==1){
                 permfactor5[tensor_to_list_idx(tempvec)]=COM(0,1); // even perm
                 // initally symmetric under diff1<->diff2 =>
                 // if this perm is even, automatically even for first diffpos2
                 set_permfactor2=false;
               } else {
                 permfactor5[tensor_to_list_idx(tempvec)]=-1.*COM(0,1); // odd perm
                 // initally symmetric under diff1<->diff2 =>
                 // if this perm is odd, automatically odd for first diffpos2
                 set_permfactor2=true;
               }
             } else {// diff0=true, initial config is even
               if(diffpos1%2==1){
                 permfactor5[tensor_to_list_idx(tempvec)]=-1.*COM(0,1); // odd perm
                 // initally symmetric under diff1<->diff2 =>
                 // if this perm is odd, automatically odd for first diffpos2
                 set_permfactor2=true;
               } else {
                 permfactor5[tensor_to_list_idx(tempvec)]=COM(0,1); // even perm
                 // initally symmetric under diff1<->diff2 =>
                 // if this perm is even, automatically even for first diffpos2
                 set_permfactor2=false;
               }
             }
             if((diffpos2-diffpos1-1)%2==1)
               set_permfactor2=!set_permfactor2; // change to account for diffpos2
           } else if(same0){
             // the repeated matrix is sigma0
             // => only relative positions of diff1, diff2 matter.
             // always even before flip  because diff1pos<diff2pos
             permfactor5[tensor_to_list_idx(tempvec)]=COM(0,1);
             // if this perm is odd, swapping diff1<->diff2 automatically odd
             set_permfactor2=true;
           }
 
           tempvec[diffpos1]=diff2;
           tempvec[diffpos2]=diff1;
           perms.push_back(tempvec);
 
           if(set_permfactor2)
             permfactor5[tensor_to_list_idx(tempvec)]=-1.*COM(0,1);
           else
             permfactor5[tensor_to_list_idx(tempvec)]=COM(0,1);
 
         }
       }
     } // end perms311
 
     // generate all unique perms of vectors {a,a,b,b,c}, return in perms
     void perms221(int same2a, int same2b, int diff,
                   std::vector<std::array<int,5>> & perms
     ){
       bool set_permfactor1(true);
       bool set_permfactor2(true);
       if(same2b==0){
         std::cerr<<"second entry in perms221() shouldn't be zero" <<std::endl;
         return;
       } else if(same2a==0)
         set_permfactor1=false;
       else if(diff==0)
         set_permfactor2=false;
 
-      for(int samepos=0;samepos<5;samepos++){
+      for(int samepos=0;samepos<5;++samepos){
         int permcount = 0;
-        for(int samepos2=samepos+1;samepos2<5;samepos2++){
-          for(int diffpos=0;diffpos<5;diffpos++){
+        for(int samepos2=samepos+1;samepos2<5;++samepos2){
+          for(int diffpos=0;diffpos<5;++diffpos){
             if(diffpos==samepos||diffpos==samepos2) continue;
 
             std::array<int,5> tempvec={same2a,same2a,same2a,same2a,same2a};
             tempvec[samepos]=same2b;
             tempvec[samepos2]=same2b;
             tempvec[diffpos]=diff;
             perms.push_back(tempvec);
 
             if(set_permfactor1){
               if(set_permfactor2){// full anti-symmetry
                 if(permcount%2==1)
                   permfactor5[tensor_to_list_idx(tempvec)]=-1.;
               } else { // diff is sigma0
                 if( ((samepos2-samepos-1)%3>0)
                     && (abs(abs(samepos2-diffpos)-abs(samepos-diffpos))%3>0) )
                   permfactor5[tensor_to_list_idx(tempvec)]=-1.;
               }
             } else { // same2a is sigma0
               if((diffpos>samepos) && (diffpos<samepos2))
                 permfactor5[tensor_to_list_idx(tempvec)]=-1.;
             }
-            permcount++;
+            ++permcount;
           }
         }
       }
     }
 
     // generate all unique perms of vectors {a,a,b,b,c}, return in perms
     // there must be a sigma zero if we have 4 different matrices in string
     // bool is true if sigma0 is the repeated matrix
     void perms2111(int same2, int diff1,int diff2,int diff3,
                    std::vector<std::array<int,5>> & perms
     ){
       bool twozero(false);
       if(same2==0)
         twozero=true;
       else if (diff1!=0){
         std::cerr<<"One of first or second argurments must be a zero"<<std::endl;
         return;
       } else if(diff2==0|| diff3==0){
         std::cerr<<"Only first and second arguments may be a zero."<<std::endl;
         return;
       }
 
       int permcount = 0;
 
-      for(int diffpos1=0;diffpos1<5;diffpos1++){
-        for(int diffpos2=0;diffpos2<5;diffpos2++){
+      for(int diffpos1=0;diffpos1<5;++diffpos1){
+        for(int diffpos2=0;diffpos2<5;++diffpos2){
           if(diffpos2==diffpos1) continue;
-          for(int diffpos3=0;diffpos3<5;diffpos3++){
+          for(int diffpos3=0;diffpos3<5;++diffpos3){
             if(diffpos3==diffpos2||diffpos3==diffpos1) continue;
 
             std::array<int,5> tempvec={same2,same2,same2,same2,same2};
             tempvec[diffpos1]=diff1;
             tempvec[diffpos2]=diff2;
             tempvec[diffpos3]=diff3;
             perms.push_back(tempvec);
 
             if(twozero){// don't care about exact positions of singles, just order
               if(diffpos2>diffpos3 && diffpos3>diffpos1)
                 permfactor5[tensor_to_list_idx(tempvec)]=-1.*COM(0,1);// odd
               else if(diffpos1>diffpos2 && diffpos2>diffpos3)
                 permfactor5[tensor_to_list_idx(tempvec)]=-1.*COM(0,1);// odd
               else if(diffpos3>diffpos1 && diffpos1>diffpos2)
                 permfactor5[tensor_to_list_idx(tempvec)]=-1.*COM(0,1);// odd
               else
                 permfactor5[tensor_to_list_idx(tempvec)]=COM(0,1);// evwn
             } else {
               if(permcount%2==1)
                 permfactor5[tensor_to_list_idx(tempvec)]=-1.*COM(0,1);
               else
                 permfactor5[tensor_to_list_idx(tempvec)]=COM(0,1);
             }
-            permcount++;
+            ++permcount;
           }
         }
       }
     }
 
     void perms21(int same, int diff, std::vector<std::array<int,3>> & perms){
 
       bool set_permfactor(true);
       if(same==0||diff==0)
         set_permfactor=false;
 
-      for(int diffpos=0; diffpos<3;diffpos++){
+      for(int diffpos=0; diffpos<3;++diffpos){
         std::array<int,3> tempvec={same,same,same};
         tempvec[diffpos]=diff;
         perms.push_back(tempvec);
         if(set_permfactor && diffpos==1)
           permfactor3[tensor_to_list_idx(tempvec)]=-1.;
       }
     }
 
     void perms111(int diff1, int diff2, int diff3,
                   std::vector<std::array<int,3>> & perms
     ){
       bool sig_zero(false);
       if(diff1==0)
         sig_zero=true;
       else if(diff2==0||diff3==0){
         std::cerr<<"Only first argument may be a zero."<<std::endl;
         return;
       }
       int permcount=0;
-      for(int pos1=0;pos1<3;pos1++){
-        for(int pos2=pos1+1;pos2<3;pos2++){
+      for(int pos1=0;pos1<3;++pos1){
+        for(int pos2=pos1+1;pos2<3;++pos2){
           std::array<int,3> tempvec={diff1,diff1,diff1};
           tempvec[pos1]=diff2;
           tempvec[pos2]=diff3;
           perms.push_back(tempvec);
           if(sig_zero){
             permfactor3[tensor_to_list_idx(tempvec)]=1.*COM(0,1); // even
           } else if(permcount%2==1){
             permfactor3[tensor_to_list_idx(tempvec)]=-1.*COM(0,1); // odd
           } else {
             permfactor3[tensor_to_list_idx(tempvec)]=1.*COM(0,1); // even
           }
 
           tempvec[pos1]=diff3;
           tempvec[pos2]=diff2;
           perms.push_back(tempvec);
 
           if(sig_zero){
             permfactor3[tensor_to_list_idx(tempvec)]=-1.*COM(0,1); // odd
           } else if(permcount%2==1){
             permfactor3[tensor_to_list_idx(tempvec)]=1.*COM(0,1); // even
           } else {
             permfactor3[tensor_to_list_idx(tempvec)]=-1.*COM(0,1); // odd
           }
-          permcount++;
+          ++permcount;
         }
       }
     }
 
     COM perp(CLHEP::HepLorentzVector const & p) {
       return COM{p.x(), p.y()};
     }
 
     COM perp_hat(CLHEP::HepLorentzVector const & p) {
       const COM p_perp = perp(p);
       if(p_perp == COM{0., 0.}) return -1.;
       return p_perp/std::abs(p_perp);
     }
 
   } // anonymous namespace
 
     // "angle" product angle(pi, pj) = <i j>
     // see eq. (53) (\eqref{eq:angle_product}) in developer manual
   COM angle(CLHEP::HepLorentzVector const & pi, CLHEP::HepLorentzVector const & pj) {
     return
       + std::sqrt(COM{pi.minus()*pj.plus()})*perp_hat(pi)
       - std::sqrt(COM{pi.plus()*pj.minus()})*perp_hat(pj);
   }
 
   // "square" product square(pi, pj) = [i j]
   // see eq. (54) (\eqref{eq:square_product}) in developer manual
   COM square(CLHEP::HepLorentzVector const & pi, CLHEP::HepLorentzVector const & pj) {
     return -std::conj(angle(pi, pj));
   }
 
   Tensor<2> metric(){
     static const Tensor<2> g = [](){
       Tensor<2> g(0.);
       g(0,0) = 1.;
       g(1,1) = -1.;
       g(2,2) = -1.;
       g(3,3) = -1.;
       return g;
     }();
     return g;
   }
 
   // <1|mu|2>
   // see eqs. (48), (49) in developer manual
   Tensor<1> current(
       CLHEP::HepLorentzVector const & p,
       CLHEP::HepLorentzVector const & q,
       Helicity h
   ){
     using namespace helicity;
     const COM p_perp_hat = perp_hat(p);
     const COM q_perp_hat = perp_hat(q);
     std::array<std::array<COM, 2>, 2> sqrt_pq;
     sqrt_pq[minus][minus] = std::sqrt(COM{p.minus()*q.minus()})*p_perp_hat*conj(q_perp_hat);
     sqrt_pq[minus][plus] = std::sqrt(COM{p.minus()*q.plus()})*p_perp_hat;
     sqrt_pq[plus][minus] = std::sqrt(COM{p.plus()*q.minus()})*conj(q_perp_hat);
     sqrt_pq[plus][plus] = std::sqrt(COM{p.plus()*q.plus()});
     Tensor<1> j;
     j(0) = sqrt_pq[plus][plus] + sqrt_pq[minus][minus];
     j(1) = sqrt_pq[plus][minus] + sqrt_pq[minus][plus];
     j(2) = COM{0., 1.}*(sqrt_pq[plus][minus] - sqrt_pq[minus][plus]);
     j(3) = sqrt_pq[plus][plus] - sqrt_pq[minus][minus];
 
     return (h == minus)?j:j.complex_conj();
   }
 
   // <1|mu nu sigma|2>
   // TODO: how does this work?
   Tensor<3> rank3_current(
       CLHEP::HepLorentzVector const & p1,
       CLHEP::HepLorentzVector const & p2,
       Helicity h
   ){
     const CLHEP::HepLorentzVector p1new{ p1.e()<0?-p1:p1 };
     const CLHEP::HepLorentzVector p2new{ p2.e()<0?-p2:p2 };
 
     auto j = HEJ::current(p1new, p2new, h);
     if(h == helicity::minus) {
       j *= -1;
       j(0) *= -1;
     }
 
     Tensor<3> j3;
     for(std::size_t tensor_idx=0; tensor_idx < j3.size(); ++tensor_idx){
       const double hfact = helfactor3[h][tensor_idx];
       j3.components[tensor_idx] = j(sigma_index3[tensor_idx]) * hfact
         * permfactor3[tensor_idx];
     }
 
     return j3;
   }
 
   // <1|mu nu sigma tau rho|2>
   Tensor<5> rank5_current(
       CLHEP::HepLorentzVector const & p1,
       CLHEP::HepLorentzVector const & p2,
       Helicity h
   ){
     const CLHEP::HepLorentzVector p1new{ p1.e()<0?-p1:p1 };
     const CLHEP::HepLorentzVector p2new{ p2.e()<0?-p2:p2 };
 
     auto j = HEJ::current(p1new, p2new, h);
     if(h == helicity::minus) {
       j *= -1;
       j(0) *= -1;
     }
 
     Tensor<5> j5;
     for(std::size_t tensor_idx=0; tensor_idx < j5.size(); ++tensor_idx){
       const double hfact = helfactor5[h][tensor_idx];
       j5.components[tensor_idx] = j(sigma_index5[tensor_idx]) * hfact
         * permfactor5[tensor_idx];
     }
 
     return j5;
   }
 
   Tensor<1> to_tensor(CLHEP::HepLorentzVector const & p){
     Tensor<1> newT;
     newT.components={p.e(),p.x(),p.y(),p.z()};
     return newT;
   }
 
   // polarisation vector according to eq. (55) in developer manual
   Tensor<1> eps(
       CLHEP::HepLorentzVector const & pg,
       CLHEP::HepLorentzVector const & pr,
       Helicity pol
   ){
     if(pol == helicity::plus) {
       return current(pr, pg, pol)/(std::sqrt(2)*square(pg, pr));
     }
     return current(pr, pg, pol)/(std::sqrt(2)*angle(pg, pr));
   }
 
   namespace {
     // slow function! - but only need to evaluate once.
     bool init_sigma_index_helper(){
       // initialize permfactor(3) to list of ones (change to minus one for each odd
       // permutation and multiply by i for all permutations in perms2111, perms311,
       // perms111)
       permfactor5.resize(1024,1.);
       permfactor3.resize(64,1.);
 
       // first set sigma_index (5)
       std::vector<std::array<int,5>> sigma0indices;
       std::vector<std::array<int,5>> sigma1indices;
       std::vector<std::array<int,5>> sigma2indices;
       std::vector<std::array<int,5>> sigma3indices;
 
       // need to generate all possible permuations of {i,j,k,l,m}
       // where each index can be {0,1,2,3,4}
       // 1024 possibilities
 
       // perms with 5 same
       sigma0indices.push_back({0,0,0,0,0});
       sigma1indices.push_back({1,1,1,1,1});
       sigma2indices.push_back({2,2,2,2,2});
       sigma3indices.push_back({3,3,3,3,3});
 
       // perms with 4 same
       perms41(1,0,sigma0indices);
       perms41(2,0,sigma0indices);
       perms41(3,0,sigma0indices);
       perms41(0,1,sigma1indices);
       perms41(2,1,sigma1indices);
       perms41(3,1,sigma1indices);
       perms41(0,2,sigma2indices);
       perms41(1,2,sigma2indices);
       perms41(3,2,sigma2indices);
       perms41(0,3,sigma3indices);
       perms41(1,3,sigma3indices);
       perms41(2,3,sigma3indices);
 
       // perms with 3 same, 2 same
       perms32(0,1,sigma0indices);
       perms32(0,2,sigma0indices);
       perms32(0,3,sigma0indices);
       perms32(1,0,sigma1indices);
       perms32(1,2,sigma1indices);
       perms32(1,3,sigma1indices);
       perms32(2,0,sigma2indices);
       perms32(2,1,sigma2indices);
       perms32(2,3,sigma2indices);
       perms32(3,0,sigma3indices);
       perms32(3,1,sigma3indices);
       perms32(3,2,sigma3indices);
 
       // perms with 3 same, 2 different
       perms311(1,2,3,sigma0indices);
       perms311(2,3,1,sigma0indices);
       perms311(3,1,2,sigma0indices);
       perms311(0,2,3,sigma1indices);
       perms311(2,3,0,sigma1indices);
       perms311(3,2,0,sigma1indices);
       perms311(0,3,1,sigma2indices);
       perms311(1,3,0,sigma2indices);
       perms311(3,1,0,sigma2indices);
       perms311(0,1,2,sigma3indices);
       perms311(1,2,0,sigma3indices);
       perms311(2,1,0,sigma3indices);
 
       perms221(1,2,0,sigma0indices);
       perms221(1,3,0,sigma0indices);
       perms221(2,3,0,sigma0indices);
       perms221(0,2,1,sigma1indices);
       perms221(0,3,1,sigma1indices);
       perms221(2,3,1,sigma1indices);
       perms221(0,1,2,sigma2indices);
       perms221(0,3,2,sigma2indices);
       perms221(1,3,2,sigma2indices);
       perms221(0,1,3,sigma3indices);
       perms221(0,2,3,sigma3indices);
       perms221(1,2,3,sigma3indices);
 
       perms2111(0,1,2,3,sigma0indices);
       perms2111(1,0,2,3,sigma1indices);
       perms2111(2,0,3,1,sigma2indices);
       perms2111(3,0,1,2,sigma3indices);
 
       if(sigma0indices.size()!=256){
         std::cerr<<"sigma_index not set: ";
         std::cerr<<"sigma0indices has "<< sigma0indices.size() << " components" << std::endl;
         return false;
       } else if(sigma1indices.size()!=256){
         std::cerr<<"sigma_index not set: ";
         std::cerr<<"sigma1indices has "<< sigma0indices.size() << " components" << std::endl;
         return false;
       } else if(sigma2indices.size()!=256){
         std::cerr<<"sigma_index not set: ";
         std::cerr<<"sigma2indices has "<< sigma0indices.size() << " components" << std::endl;
         return false;
       } else if(sigma3indices.size()!=256){
         std::cerr<<"sigma_index not set: ";
         std::cerr<<"sigma3indices has "<< sigma0indices.size() << " components" << std::endl;
         return false;
       }
 
-      for(int i=0;i<256;i++){
+      for(int i=0;i<256;++i){
         // map each unique set of tensor indices to its position in a list
         int index0 = tensor_to_list_idx(sigma0indices.at(i));
         int index1 = tensor_to_list_idx(sigma1indices.at(i));
         int index2 = tensor_to_list_idx(sigma2indices.at(i));
         int index3 = tensor_to_list_idx(sigma3indices.at(i));
         sigma_index5[index0]=0;
         sigma_index5[index1]=1;
         sigma_index5[index2]=2;
         sigma_index5[index3]=3;
 
         short int sign[4]={1,-1,-1,-1};
         // plus->true->1
         helfactor5[1][index0] = sign[sigma0indices.at(i)[1]]
           * sign[sigma0indices.at(i)[3]];
         helfactor5[1][index1] = sign[sigma1indices.at(i)[1]]
           * sign[sigma1indices.at(i)[3]];
         helfactor5[1][index2] = sign[sigma2indices.at(i)[1]]
           * sign[sigma2indices.at(i)[3]];
         helfactor5[1][index3] = sign[sigma3indices.at(i)[1]]
           * sign[sigma3indices.at(i)[3]];
         // minus->false->0
         helfactor5[0][index0] = sign[sigma0indices.at(i)[0]]
           * sign[sigma0indices.at(i)[2]]
           * sign[sigma0indices.at(i)[4]];
         helfactor5[0][index1] = sign[sigma1indices.at(i)[0]]
           * sign[sigma1indices.at(i)[2]]
           * sign[sigma1indices.at(i)[4]];
         helfactor5[0][index2] = sign[sigma2indices.at(i)[0]]
           * sign[sigma2indices.at(i)[2]]
           * sign[sigma2indices.at(i)[4]];
         helfactor5[0][index3] = sign[sigma3indices.at(i)[0]]
           * sign[sigma3indices.at(i)[2]]
           * sign[sigma3indices.at(i)[4]];
       }
 
       // now set sigma_index3
       std::vector<std::array<int,3>> sigma0indices3;
       std::vector<std::array<int,3>> sigma1indices3;
       std::vector<std::array<int,3>> sigma2indices3;
       std::vector<std::array<int,3>> sigma3indices3;
 
       // perms with 3 same
       sigma0indices3.push_back({0,0,0});
       sigma1indices3.push_back({1,1,1});
       sigma2indices3.push_back({2,2,2});
       sigma3indices3.push_back({3,3,3});
 
       // 2 same
       perms21(1,0,sigma0indices3);
       perms21(2,0,sigma0indices3);
       perms21(3,0,sigma0indices3);
       perms21(0,1,sigma1indices3);
       perms21(2,1,sigma1indices3);
       perms21(3,1,sigma1indices3);
       perms21(0,2,sigma2indices3);
       perms21(1,2,sigma2indices3);
       perms21(3,2,sigma2indices3);
       perms21(0,3,sigma3indices3);
       perms21(1,3,sigma3indices3);
       perms21(2,3,sigma3indices3);
 
       // none same
       perms111(1,2,3,sigma0indices3);
       perms111(0,2,3,sigma1indices3);
       perms111(0,3,1,sigma2indices3);
       perms111(0,1,2,sigma3indices3);
 
       if(sigma0indices3.size()!=16){
         std::cerr<<"sigma_index3 not set: ";
         std::cerr<<"sigma0indices3 has "<< sigma0indices3.size() << " components" << std::endl;
         return false;
       } else if(sigma1indices3.size()!=16){
         std::cerr<<"sigma_index3 not set: ";
         std::cerr<<"sigma1indices3 has "<< sigma0indices3.size() << " components" << std::endl;
         return false;
       } else if(sigma2indices3.size()!=16){
         std::cerr<<"sigma_index3 not set: ";
         std::cerr<<"sigma2indices3 has "<< sigma0indices3.size() << " components" << std::endl;
         return false;
       } else if(sigma3indices3.size()!=16){
         std::cerr<<"sigma_index3 not set: ";
         std::cerr<<"sigma3indices3 has "<< sigma0indices3.size() << " components" << std::endl;
         return false;
       }
 
-      for(int i=0;i<16;i++){
+      for(int i=0;i<16;++i){
         int index0 = tensor_to_list_idx(sigma0indices3.at(i));
         int index1 = tensor_to_list_idx(sigma1indices3.at(i));
         int index2 = tensor_to_list_idx(sigma2indices3.at(i));
         int index3 = tensor_to_list_idx(sigma3indices3.at(i));
         sigma_index3[index0]=0;
         sigma_index3[index1]=1;
         sigma_index3[index2]=2;
         sigma_index3[index3]=3;
 
         short int sign[4]={1,-1,-1,-1};
         // plus->true->1
         helfactor3[1][index0] = sign[sigma0indices3.at(i)[1]];
         helfactor3[1][index1] = sign[sigma1indices3.at(i)[1]];
         helfactor3[1][index2] = sign[sigma2indices3.at(i)[1]];
         helfactor3[1][index3] = sign[sigma3indices3.at(i)[1]];
         // minus->false->0
         helfactor3[0][index0] = sign[sigma0indices3.at(i)[0]]
           * sign[sigma0indices3.at(i)[2]];
         helfactor3[0][index1] = sign[sigma1indices3.at(i)[0]]
           * sign[sigma1indices3.at(i)[2]];
         helfactor3[0][index2] = sign[sigma2indices3.at(i)[0]]
           * sign[sigma2indices3.at(i)[2]];
         helfactor3[0][index3] = sign[sigma3indices3.at(i)[0]]
           * sign[sigma3indices3.at(i)[2]];
       }
       return true;
     } // end init_sigma_index
   }
 
   void init_sigma_index(){
     static const bool initialised = init_sigma_index_helper();
     (void) initialised; // shut up compiler warnings
   }
 
 }
diff --git a/src/Wjets.cc b/src/Wjets.cc
index ba1da6c..1e48e5e 100644
--- a/src/Wjets.cc
+++ b/src/Wjets.cc
@@ -1,1666 +1,1666 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #include "HEJ/Wjets.hh"
 
 #include <array>
 #include <iostream>
 
 #include "HEJ/Constants.hh"
 #include "HEJ/EWConstants.hh"
 #include "HEJ/jets.hh"
 #include "HEJ/Tensor.hh"
 
 using HEJ::Tensor;
 using HEJ::init_sigma_index;
 using HEJ::metric;
 using HEJ::rank3_current;
 using HEJ::rank5_current;
 using HEJ::eps;
 using HEJ::to_tensor;
 using HEJ::Helicity;
 using HEJ::angle;
 using HEJ::square;
 using HEJ::flip;
 using HEJ::ParticleProperties;
 
 namespace helicity = HEJ::helicity;
 
 namespace { // Helper Functions
   // FKL W Helper Functions
   double WProp (const HLV & plbar, const HLV & pl, ParticleProperties const & wprop){
     COM propW = COM(0.,-1.)/( (pl+plbar).m2() - wprop.mass*wprop.mass
                             + COM(0.,1.)*wprop.mass*wprop.width);
     double PropFactor=(propW*conj(propW)).real();
     return PropFactor;
   }
 
   namespace {
     // FKL current including W emission off negative helicities
     // See eq. (87) {eq:jW-} in developer manual
     // Note that the terms are rearranged
     Tensor<1> jW_minus(
         HLV const & pa, HLV const & p1,
         HLV const & plbar, HLV const & pl
     ){
       using HEJ::helicity::minus;
 
       const double tWin = (pa-pl-plbar).m2();
       const double tWout = (p1+pl+plbar).m2();
 
       // C++ arithmetic operators are evaluated left-to-right,
       // so the following first computes complex scalar coefficients,
       // which then multiply a current, reducing the number
       // of multiplications
       return 2.*(
           + angle(p1, pl)*square(p1, plbar)/tWout
           + square(pa, plbar)*angle(pa, pl)/tWin
       )*HEJ::current(p1, pa, helicity::minus)
         + 2.*angle(p1, pl)*square(pl, plbar)/tWout
             *HEJ::current(pl, pa, helicity::minus)
         + 2.*square(pa, plbar)*angle(pl, plbar)/tWin
             *HEJ::current(p1, plbar, helicity::minus);
     }
   }
 
   // FKL current including W emission
   // see eqs. (87), (88) {eq:jW-}, {eq:jW+} in developer manual
   Tensor<1> jW(
       HLV const & pa, HLV const & p1,
       HLV const & plbar, HLV const & pl,
       Helicity h
   ){
     if(h == helicity::minus) {
       return jW_minus(pa, p1, plbar, pl);
     }
     return jW_minus(pa, p1, pl, plbar).complex_conj();
   }
 
   /**
    * @brief         Contraction of the \tilde{U}_1 tensor
    *
    * This is the contraction of the tensor defined in eq:U1tensor
    * in the developer manual with the uno gluon polarisation vector,
    * the leptonic and the partonic current (see eq:wunocurrent) in the
    * developer manual)
    */
   COM U1contr(
       HLV const & pg, HLV const & p1,HLV const & plbar, HLV const & pl,
       HLV const & pa, Helicity h1,
       HLV const & p2, HLV const & pb, Helicity h2, Helicity hg
   ) {
     const HLV pW = pl+plbar;
     const HLV q1g = pa-pW-p1-pg;
     const HLV q1 = pa-p1-pW;
     const HLV q2 = p2-pb;
 
     const double taW  = (pa-pW).m2();
     const double s1W  = (p1+pW).m2();
     const double s1gW = (p1+pW+pg).m2();
     const double s1g  = (p1+pg).m2();
 
     if(h1 == helicity::plus) {
       if(h2 == helicity::plus) {
         if(hg == helicity::plus) {
           // helicity +++
           return (4.*sqrt(2.)*(-1.*taW*angle(pa,pb)*square(p1,plbar)*
         (s1W*angle(p1,pg)*angle(pg,pl)*square(p1,p2)*square(p2,pg) -
           1.*(angle(p1,pl)*square(p1,p2) + angle(pl,plbar)*square(p2,plbar))*
            ((s1g + s1W)*angle(p1,pg)*square(p1,p2) +
              s1g*(angle(pg,pl)*square(p2,pl) + angle(pg,plbar)*square(p2,plbar)))) +
        s1gW*s1W*angle(p1,pg)*angle(pa,pl)*pow(square(p1,p2),2.)*
         (angle(pa,pb)*square(pa,plbar) + angle(pb,pl)*square(pl,plbar))))/
    (s1g*s1gW*s1W*taW*square(p2,pg));
         }
         else {
           // helicity ++-
           return (sqrt(2.)*(taW*angle(pa,pb)*(4.*s1g*square(p1,plbar)*
            (angle(p1,pl)*square(p1,pg)*(angle(pb,pg)*square(p2,pg) + angle(pb,pl)*square(p2,pl) +
                 angle(pb,plbar)*square(p2,plbar)) +
              angle(pl,plbar)*(angle(p1,pb)*square(p1,p2) + angle(pb,pg)*square(p2,pg) +
                 angle(pb,pl)*square(p2,pl) + angle(pb,plbar)*square(p2,plbar))*square(pg,plbar)) +
           square(p1,pg)*(4.*angle(p1,pb)*square(p1,plbar)*
               ((s1g + s1W)*angle(p1,pl)*square(p1,p2) - 1.*s1W*angle(pg,pl)*square(p2,pg) +
                 s1W*angle(pl,plbar)*square(p2,plbar)) -
              4.*s1W*angle(pb,pg)*(angle(p1,pl)*square(p1,p2) - 1.*angle(pg,pl)*square(p2,pg) +
                 angle(pl,plbar)*square(p2,plbar))*square(pg,plbar))) +
        4.*s1gW*s1W*angle(pa,pl)*square(p1,pg)*
         (angle(p1,pb)*square(p1,p2) + angle(pb,pg)*square(p2,pg))*
         (angle(pa,pb)*square(pa,plbar) + angle(pb,pl)*square(pl,plbar))))/
    (s1g*s1gW*s1W*taW*angle(pb,pg));
         }
       }
       else {
         if(hg == helicity::plus) {
           // helicity +-+
           return (sqrt(2.)*(4.*taW*angle(p2,pa)*square(p1,plbar)*
         (s1W*angle(p1,pg)*angle(pg,pl)*square(p1,pb)*square(pb,pg) -
           1.*(angle(p1,pl)*square(p1,pb) + angle(pl,plbar)*square(pb,plbar))*
            ((s1g + s1W)*angle(p1,pg)*square(p1,pb) +
              s1g*(angle(pg,pl)*square(pb,pl) + angle(pg,plbar)*square(pb,plbar)))) -
        4.*s1gW*s1W*angle(p1,pg)*angle(pa,pl)*pow(square(p1,pb),2.)*
         (angle(p2,pa)*square(pa,plbar) - 1.*angle(p2,pl)*square(pl,plbar))))/
    (s1g*s1gW*s1W*taW*square(pb,pg));
         }
         else {
           // helicity +--
           return (-1.*sqrt(2.)*(taW*angle(p2,pa)*(4.*s1g*square(p1,plbar)*
            (angle(p1,pl)*square(p1,pg)*(angle(p2,pg)*square(pb,pg) + angle(p2,pl)*square(pb,pl) +
                 angle(p2,plbar)*square(pb,plbar)) +
              angle(pl,plbar)*(angle(p1,p2)*square(p1,pb) + angle(p2,pg)*square(pb,pg) +
                 angle(p2,pl)*square(pb,pl) + angle(p2,plbar)*square(pb,plbar))*square(pg,plbar)) +
           square(p1,pg)*(4.*angle(p1,p2)*square(p1,plbar)*
               ((s1g + s1W)*angle(p1,pl)*square(p1,pb) - 1.*s1W*angle(pg,pl)*square(pb,pg) +
                 s1W*angle(pl,plbar)*square(pb,plbar)) -
              4.*s1W*angle(p2,pg)*(angle(p1,pl)*square(p1,pb) - 1.*angle(pg,pl)*square(pb,pg) +
                 angle(pl,plbar)*square(pb,plbar))*square(pg,plbar))) +
        4.*s1gW*s1W*angle(pa,pl)*square(p1,pg)*
         (angle(p1,p2)*square(p1,pb) + angle(p2,pg)*square(pb,pg))*
         (angle(p2,pa)*square(pa,plbar) - 1.*angle(p2,pl)*square(pl,plbar))))/
    (s1g*s1gW*s1W*taW*angle(p2,pg));
         }
       }
     }
     else {
       if(h2 == helicity::plus) {
         if(hg == helicity::plus) {
           // helicity -++
           return (
               sqrt(2.)*(-4.*s1gW*s1W*angle(p1,pg)*(angle(p1,pb)*square(p1,p2) + angle(pb,pg)*square(p2,pg))*
         (angle(pa,pl)*square(p2,pa) + angle(pl,plbar)*square(p2,plbar))*square(pa,plbar) +
        taW*angle(pg,pl)*square(p2,pa)*(4.*s1g*angle(p1,pl)*
            (angle(p1,pb)*square(p1,p2) + angle(pb,pg)*square(p2,pg) + angle(pb,pl)*square(p2,pl) +
              angle(pb,plbar)*square(p2,plbar))*square(pl,plbar) +
           4.*s1W*angle(p1,pg)*square(p2,pg)*
            (angle(p1,pb)*square(p1,plbar) - 1.*angle(pb,pg)*square(pg,plbar) -
              1.*angle(pb,pl)*square(pl,plbar))) -
        4.*taW*angle(p1,pg)*angle(p1,pl)*square(p2,pa)*
         (square(p1,plbar)*((s1g + s1W)*angle(p1,pb)*square(p1,p2) +
              s1g*(angle(pb,pg)*square(p2,pg) + angle(pb,pl)*square(p2,pl) +
                 angle(pb,plbar)*square(p2,plbar))) -
           1.*s1W*square(p1,p2)*(angle(pb,pg)*square(pg,plbar) + angle(pb,pl)*square(pl,plbar))))
           )/(s1g*s1gW*s1W*taW*square(p2,pg));
         }
         else {
           // helicity -+-
           return (-1.*sqrt(2.)*(4.*s1W*angle(p1,pb)*square(p1,pg)*
         (s1gW*angle(p1,pb)*(angle(pa,pl)*square(p2,pa) + angle(pl,plbar)*square(p2,plbar))*
            square(pa,plbar) - 1.*taW*angle(p1,pl)*angle(pb,pg)*square(p2,pa)*square(pg,plbar)) +
        taW*angle(p1,pl)*square(p2,pa)*((s1g + s1W)*angle(p1,pb)*square(p1,pg) +
           s1g*(angle(pb,pl)*square(pg,pl) + angle(pb,plbar)*square(pg,plbar)))*
         (4.*angle(p1,pb)*square(p1,plbar) - 4.*angle(pb,pl)*square(pl,plbar))))/
    (s1g*s1gW*s1W*taW*angle(pb,pg));
         }
       }
       else {
         if(hg == helicity::plus) {
           // helicity --+
           return (sqrt(2.)*(4.*s1gW*s1W*angle(p1,pg)*square(pa,plbar)*
         (angle(p1,p2)*square(p1,pb) + angle(p2,pg)*square(pb,pg))*
         (angle(pa,pl)*square(pa,pb) - 1.*angle(pl,plbar)*square(pb,plbar)) +
        taW*square(pa,pb)*(-1.*angle(pg,pl)*
            (4.*s1g*angle(p1,pl)*(angle(p1,p2)*square(p1,pb) + angle(p2,pg)*square(pb,pg) +
                 angle(p2,pl)*square(pb,pl) + angle(p2,plbar)*square(pb,plbar))*square(pl,plbar) +
              4.*s1W*angle(p1,pg)*square(pb,pg)*
               (angle(p1,p2)*square(p1,plbar) - 1.*angle(p2,pg)*square(pg,plbar) -
                 1.*angle(p2,pl)*square(pl,plbar))) +
           4.*angle(p1,pg)*angle(p1,pl)*(square(p1,plbar)*
               ((s1g + s1W)*angle(p1,p2)*square(p1,pb) +
                 s1g*(angle(p2,pg)*square(pb,pg) + angle(p2,pl)*square(pb,pl) +
                    angle(p2,plbar)*square(pb,plbar))) -
              1.*s1W*square(p1,pb)*(angle(p2,pg)*square(pg,plbar) + angle(p2,pl)*square(pl,plbar)))))
      )/(s1g*s1gW*s1W*taW*square(pb,pg));
         }
         else {
           // helicity ---
           return (sqrt(2.)*(s1W*angle(p1,p2)*square(p1,pg)*
         (4.*s1gW*angle(p1,p2)*square(pa,plbar)*
            (angle(pa,pl)*square(pa,pb) - 1.*angle(pl,plbar)*square(pb,plbar)) -
           4.*taW*angle(p1,pl)*angle(p2,pg)*square(pa,pb)*square(pg,plbar)) +
        taW*angle(p1,pl)*square(pa,pb)*((s1g + s1W)*angle(p1,p2)*square(p1,pg) +
           s1g*(angle(p2,pl)*square(pg,pl) + angle(p2,plbar)*square(pg,plbar)))*
         (4.*angle(p1,p2)*square(p1,plbar) - 4.*angle(p2,pl)*square(pl,plbar))))/
    (s1g*s1gW*s1W*taW*angle(p2,pg));
         }
       }
     }
   }
 
   /**
    * @brief         Contraction of the \tilde{U}_2 tensor
    *
    * This is the contraction of the tensor defined in eq:U2tensor
    * in the developer manual with the uno gluon polarisation vector,
    * the leptonic and the partonic current (see eq:wunocurrent) in the
    * developer manual)
    */
   COM U2contr(
       HLV const & pg, HLV const & p1,HLV const & plbar, HLV const & pl,
       HLV const & pa, Helicity h1,
       HLV const & p2, HLV const & pb, Helicity h2, Helicity hg
   ) {
     const HLV pW = pl+plbar;
     const HLV q1g=pa-pW-p1-pg;
     const HLV q1 = pa-p1-pW;
     const HLV q2 = p2-pb;
 
     const double taW  = (pa-pW).m2();
     const double s1W  = (p1+pW).m2();
     const double tag  = (pa-pg).m2();
     const double taWg = (pa-pW-pg).m2();
 
     if(h1 == helicity::plus) {
       if(h2 == helicity::plus) {
         if(hg == helicity::plus) {
           // helicity +++
           return (-4.*sqrt(2.)*(taW*angle(pa,pg)*(taWg*square(p1,plbar)*
            (angle(pa,pb)*square(p2,pa) + angle(pb,pg)*square(p2,pg))*
            (angle(p1,pl)*square(p1,p2) + angle(pl,plbar)*square(p2,plbar)) -
           1.*s1W*angle(pg,pl)*square(p1,p2)*square(p2,pg)*
            (angle(pa,pb)*square(pa,plbar) + angle(pb,pg)*square(pg,plbar) +
              angle(pb,pl)*square(pl,plbar))) +
        s1W*angle(pa,pl)*square(p1,p2)*(tag*
            (angle(pa,pg)*(angle(pb,pg)*square(p2,pg) + angle(pb,pl)*square(p2,pl) +
                 angle(pb,plbar)*square(p2,plbar))*square(pa,plbar) +
              angle(pg,pl)*(angle(pa,pb)*square(p2,pa) + angle(pb,pg)*square(p2,pg) +
                 angle(pb,pl)*square(p2,pl) + angle(pb,plbar)*square(p2,plbar))*square(pl,plbar)) +
           angle(pa,pg)*square(p2,pa)*((tag + taW)*angle(pa,pb)*square(pa,plbar) +
              taW*(angle(pb,pg)*square(pg,plbar) + angle(pb,pl)*square(pl,plbar))))))/
    (s1W*tag*taW*taWg*square(p2,pg));
         }
         else {
           // helicity ++-
           return (-4.*sqrt(2.)*(s1W*tag*angle(pa,pl)*square(p1,p2)*
         (angle(pb,pl)*square(pg,pl) + angle(pb,plbar)*square(pg,plbar))*
         (angle(pa,pb)*square(pa,plbar) + angle(pb,pl)*square(pl,plbar)) -
        1.*angle(pa,pb)*square(pa,pg)*(taW*taWg*angle(pa,pb)*square(p1,plbar)*
            (angle(p1,pl)*square(p1,p2) + angle(pl,plbar)*square(p2,plbar)) +
           s1W*angle(pa,pl)*square(p1,p2)*
            (taW*angle(pb,pg)*square(pg,plbar) +
              (tag + taW)*(angle(pa,pb)*square(pa,plbar) + angle(pb,pl)*square(pl,plbar))))))/
    (s1W*tag*taW*taWg*angle(pb,pg));
         }
       }
       else {
         if(hg == helicity::plus) {
           // helicity +-+
           return (-4.*sqrt(2.)*(taW*angle(pa,pg)*(taWg*square(p1,plbar)*
            (angle(p2,pa)*square(pa,pb) + angle(p2,pg)*square(pb,pg))*
            (angle(p1,pl)*square(p1,pb) + angle(pl,plbar)*square(pb,plbar)) -
           1.*s1W*square(p1,pb)*(angle(pa,pl)*square(pa,pb) + angle(pg,pl)*square(pb,pg))*
            (angle(p2,pg)*square(pg,plbar) + angle(p2,pl)*square(pl,plbar))) +
        s1W*square(p1,pb)*(tag*angle(pa,pl)*
            (angle(p2,pg)*square(pb,pg) + angle(p2,pl)*square(pb,pl) +
              angle(p2,plbar)*square(pb,plbar))*
            (angle(pa,pg)*square(pa,plbar) + angle(pg,pl)*square(pl,plbar)) +
           angle(p2,pa)*(angle(pa,pg)*square(pa,plbar)*
               ((tag + taW)*angle(pa,pl)*square(pa,pb) + taW*angle(pg,pl)*square(pb,pg)) +
              tag*angle(pa,pl)*angle(pg,pl)*square(pa,pb)*square(pl,plbar)))))/
    (s1W*tag*taW*taWg*square(pb,pg));
         }
         else {
           // helicity +--
           return (sqrt(2.)*(4.*taW*angle(p2,pa)*square(pa,pg)*
         (taWg*angle(p2,pa)*square(p1,plbar)*
            (angle(p1,pl)*square(p1,pb) + angle(pl,plbar)*square(pb,plbar)) -
           1.*s1W*angle(p2,pg)*angle(pa,pl)*square(p1,pb)*square(pg,plbar)) +
        s1W*angle(pa,pl)*square(p1,pb)*((tag + taW)*angle(p2,pa)*square(pa,pg) +
           tag*(angle(p2,pl)*square(pg,pl) + angle(p2,plbar)*square(pg,plbar)))*
         (4.*angle(p2,pa)*square(pa,plbar) - 4.*angle(p2,pl)*square(pl,plbar))))/
    (s1W*tag*taW*taWg*angle(p2,pg));
         }
       }
     }
     else {
       if(h2 == helicity::plus) {
         if(hg == helicity::plus) {
           // helicity -++
           return (sqrt(2.)*(-4.*s1W*angle(p1,pb)*(taW*angle(pa,pg)*angle(pg,pl)*square(p2,pa)*square(p2,pg) -
           1.*(angle(pa,pl)*square(p2,pa) + angle(pl,plbar)*square(p2,plbar))*
            ((tag + taW)*angle(pa,pg)*square(p2,pa) +
              tag*(angle(pg,pl)*square(p2,pl) + angle(pg,plbar)*square(p2,plbar))))*square(pa,plbar)
         + 4.*taW*taWg*angle(p1,pl)*angle(pa,pg)*pow(square(p2,pa),2.)*
         (angle(p1,pb)*square(p1,plbar) - 1.*angle(pb,pl)*square(pl,plbar))))/
    (s1W*tag*taW*taWg*square(p2,pg));
         }
         else {
           // helicity -+-
           return (sqrt(2.)*(4.*s1W*angle(p1,pb)*(tag*angle(pl,plbar)*
            (angle(pa,pb)*square(p2,pa) + angle(pb,pg)*square(p2,pg) + angle(pb,pl)*square(p2,pl) +
              angle(pb,plbar)*square(p2,plbar))*square(pa,plbar)*square(pg,plbar) +
           taW*angle(pg,pl)*square(p2,pg)*square(pa,pg)*
            (angle(pa,pb)*square(pa,plbar) + angle(pb,pg)*square(pg,plbar)) -
           1.*square(pa,pg)*((tag*angle(pa,pl)*
                  (angle(pb,pg)*square(p2,pg) + angle(pb,pl)*square(p2,pl) +
                    angle(pb,plbar)*square(p2,plbar)) +
                 angle(pa,pb)*((tag + taW)*angle(pa,pl)*square(p2,pa) +
                    taW*angle(pl,plbar)*square(p2,plbar)))*square(pa,plbar) +
              taW*angle(pb,pg)*(angle(pa,pl)*square(p2,pa) + angle(pl,plbar)*square(p2,plbar))*
               square(pg,plbar))) - 4.*taW*taWg*angle(p1,pl)*
         (angle(pa,pb)*square(p2,pa) + angle(pb,pg)*square(p2,pg))*square(pa,pg)*
         (angle(p1,pb)*square(p1,plbar) - 1.*angle(pb,pl)*square(pl,plbar))))/
    (s1W*tag*taW*taWg*angle(pb,pg));
         }
       }
       else {
         if(hg == helicity::plus) {
           // helicity --+
           return (4.*sqrt(2.)*(angle(p1,p2)*(taW*taWg*angle(p1,pl)*angle(pa,pg)*pow(square(pa,pb),2.)*
            square(p1,plbar) + s1W*square(pa,plbar)*
            (tag*(angle(pg,pl)*square(pb,pl) + angle(pg,plbar)*square(pb,plbar))*
               (-1.*angle(pa,pl)*square(pa,pb) + angle(pl,plbar)*square(pb,plbar)) +
              angle(pa,pg)*square(pa,pb)*((tag + taW)*angle(pa,pl)*square(pa,pb) +
                 taW*angle(pg,pl)*square(pb,pg) - 1.*(tag + taW)*angle(pl,plbar)*square(pb,plbar))))
         - 1.*taW*taWg*angle(p1,pl)*angle(p2,pl)*angle(pa,pg)*pow(square(pa,pb),2.)*square(pl,plbar))
      )/(s1W*tag*taW*taWg*square(pb,pg));
         }
         else {
           // helicity ---
           return (sqrt(2.)*(s1W*angle(p1,p2)*(-4.*square(pa,pg)*square(pa,plbar)*
            (tag*angle(pa,pl)*(angle(p2,pg)*square(pb,pg) + angle(p2,pl)*square(pb,pl) +
                 angle(p2,plbar)*square(pb,plbar)) +
              angle(p2,pa)*((tag + taW)*angle(pa,pl)*square(pa,pb) +
                 taW*angle(pg,pl)*square(pb,pg) - 1.*taW*angle(pl,plbar)*square(pb,plbar))) +
           4.*tag*angle(pl,plbar)*square(pa,plbar)*
            (angle(p2,pa)*square(pa,pb) + angle(p2,pg)*square(pb,pg) + angle(p2,pl)*square(pb,pl) +
              angle(p2,plbar)*square(pb,plbar))*square(pg,plbar) +
           4.*taW*angle(p2,pg)*square(pa,pg)*
            (angle(pa,pl)*square(pa,pb) + angle(pg,pl)*square(pb,pg) -
              1.*angle(pl,plbar)*square(pb,plbar))*square(pg,plbar)) -
        4.*taW*taWg*angle(p1,pl)*square(pa,pg)*
         (angle(p2,pa)*square(pa,pb) + angle(p2,pg)*square(pb,pg))*
         (angle(p1,p2)*square(p1,plbar) - 1.*angle(p2,pl)*square(pl,plbar))))/
    (s1W*tag*taW*taWg*angle(p2,pg));
         }
       }
     }
   }
 
   /**
    * @brief         Contraction of the \tilde{L} tensor
    *
    * This is the contraction of the tensor defined in eq:Ltensor
    * in the developer manual with the uno gluon polarisation vector,
    * the leptonic and the partonic current (see eq:wunocurrent) in the
    * developer manual)
    */
   COM Lcontr(
       HLV const & pg, HLV const & p1,HLV const & plbar, HLV const & pl,
       HLV const & pa, Helicity h1,
       HLV const & p2, HLV const & pb, Helicity h2, Helicity hg
   ) {
     const HLV pW = pl+plbar;
     const HLV q1g=pa-pW-p1-pg;
     const HLV q1 = pa-p1-pW;
     const HLV q2 = p2-pb;
 
     const double taW  = (pa-pW).m2();
     const double taW1 = (pa-pW-p1).m2();
     const double s1W  = (p1+pW).m2();
     const double s2g  = (p2+pg).m2();
     const double sbg  = (pb+pg).m2();
 
     if(h1 == helicity::plus) {
       if(h2 == helicity::plus) {
         if(hg == helicity::plus) {
           // helicity +++
           return (-2.*sqrt(2.)*(angle(pb,pg)*q1g.m2()*square(p2,pb)*
         (taW*angle(pa,pb)*square(p1,plbar)*
            (angle(p1,pl)*square(p1,p2) + angle(pl,plbar)*square(p2,plbar)) +
           s1W*angle(pa,pl)*square(p1,p2)*
            (angle(pa,pb)*square(pa,plbar) + angle(pb,pl)*square(pl,plbar))) +
        2.*sbg*(taW*square(p1,plbar)*(angle(p1,pl)*square(p1,p2) + angle(pl,plbar)*square(p2,plbar))*
            (angle(pa,pg)*angle(pb,pg)*square(p2,pg) +
              angle(pa,pb)*(angle(p1,pg)*square(p1,p2) + angle(pa,pg)*square(p2,pa) +
                 angle(pg,pl)*square(p2,pl) + angle(pg,plbar)*square(p2,plbar))) +
           s1W*angle(pa,pl)*square(p1,p2)*
            ((angle(p1,pg)*square(p1,p2) + angle(pa,pg)*square(p2,pa) + angle(pg,pl)*square(p2,pl) +
                 angle(pg,plbar)*square(p2,plbar))*
               (angle(pa,pb)*square(pa,plbar) + angle(pb,pl)*square(pl,plbar)) +
              angle(pb,pg)*square(p2,pg)*(angle(pa,pg)*square(pa,plbar) +
                 angle(pg,pl)*square(pl,plbar))))))/(s1W*sbg*taW*taW1*square(p2,pg));
         }
         else {
           // helicity ++-
           return (-1.*sqrt(2.)*(s2g*taW*angle(pa,pb)*square(p1,plbar)*
         (4.*(angle(p1,pl)*square(p1,p2) + angle(pl,plbar)*square(p2,plbar))*
            (angle(p1,pb)*square(p1,pg) - 1.*angle(pa,pb)*square(pa,pg) +
              angle(pb,pl)*square(pg,pl) + angle(pb,plbar)*square(pg,plbar)) +
           4.*angle(pb,pg)*square(p2,pg)*(angle(p1,pl)*square(p1,pg) +
              angle(pl,plbar)*square(pg,plbar))) +
        s1W*s2g*angle(pa,pl)*(4.*angle(pb,pg)*square(p1,pg)*square(p2,pg) -
           4.*angle(pa,pb)*square(p1,p2)*square(pa,pg) +
           4.*square(p1,p2)*(angle(p1,pb)*square(p1,pg) + angle(pb,pl)*square(pg,pl) +
              angle(pb,plbar)*square(pg,plbar)))*
         (angle(pa,pb)*square(pa,plbar) + angle(pb,pl)*square(pl,plbar)) -
        2.*angle(p2,pb)*q1g.m2()*square(p2,pg)*
         (taW*angle(pa,pb)*square(p1,plbar)*
            (angle(p1,pl)*square(p1,p2) + angle(pl,plbar)*square(p2,plbar)) +
           s1W*angle(pa,pl)*square(p1,p2)*
            (angle(pa,pb)*square(pa,plbar) + angle(pb,pl)*square(pl,plbar)))))/
    (s1W*s2g*taW*taW1*angle(pb,pg));
         }
       }
       else {
         if(hg == helicity::plus) {
           // helicity +-+
           return (-1.*sqrt(2.)*(2.*taW*square(p1,plbar)*(angle(p1,pl)*square(p1,pb) +
           angle(pl,plbar)*square(pb,plbar))*
         (2.*s2g*angle(pa,pg)*(angle(p2,pa)*square(pa,pb) + angle(p2,pg)*square(pb,pg)) +
           angle(p2,pa)*(angle(p2,pg)*q1g.m2()*square(p2,pb) -
              2.*s2g*(angle(p1,pg)*square(p1,pb) + angle(pg,pl)*square(pb,pl) +
                 angle(pg,plbar)*square(pb,plbar)))) +
        s1W*angle(pa,pl)*square(p1,pb)*(4.*s2g*square(pa,plbar)*
            (angle(pa,pg)*(angle(p2,pa)*square(pa,pb) + angle(p2,pg)*square(pb,pg)) -
              1.*angle(p2,pa)*(angle(p1,pg)*square(p1,pb) + angle(pg,pl)*square(pb,pl) +
                 angle(pg,plbar)*square(pb,plbar))) +
           s2g*(-4.*angle(p2,pl)*angle(pa,pg)*square(pa,pb) +
              4.*angle(p2,pg)*angle(pg,pl)*square(pb,pg) +
              4.*angle(p2,pl)*(angle(p1,pg)*square(p1,pb) + angle(pg,pl)*square(pb,pl) +
                 angle(pg,plbar)*square(pb,plbar)))*square(pl,plbar) +
           2.*angle(p2,pg)*q1g.m2()*square(p2,pb)*
            (angle(p2,pa)*square(pa,plbar) - 1.*angle(p2,pl)*square(pl,plbar)))))/
    (s1W*s2g*taW*taW1*square(pb,pg));
         }
         else {
           // helicity +--
           return (sqrt(2.)*(2.*taW*angle(p2,pa)*square(p1,plbar)*
         (2.*sbg*angle(p2,pg)*square(pb,pg)*
            (angle(p1,pl)*square(p1,pg) + angle(pl,plbar)*square(pg,plbar)) +
           (angle(p1,pl)*square(p1,pb) + angle(pl,plbar)*square(pb,plbar))*
            (angle(p2,pb)*q1g.m2()*square(pb,pg) +
              2.*sbg*(angle(p1,p2)*square(p1,pg) + angle(p2,pa)*square(pa,pg) +
                 angle(p2,pl)*square(pg,pl) + angle(p2,plbar)*square(pg,plbar)))) +
        2.*s1W*angle(pa,pl)*(2.*sbg*angle(p1,p2)*square(p1,pb)*square(p1,pg) +
           2.*sbg*angle(p2,pa)*square(p1,pb)*square(pa,pg) +
           angle(p2,pb)*q1g.m2()*square(p1,pb)*square(pb,pg) +
           2.*sbg*angle(p2,pg)*square(p1,pg)*square(pb,pg) +
           2.*sbg*angle(p2,pl)*square(p1,pb)*square(pg,pl) +
           2.*sbg*angle(p2,plbar)*square(p1,pb)*square(pg,plbar))*
         (angle(p2,pa)*square(pa,plbar) - 1.*angle(p2,pl)*square(pl,plbar))))/
    (s1W*sbg*taW*taW1*angle(p2,pg));
         }
       }
     }
     else {
       if(h2 == helicity::plus) {
         if(hg == helicity::plus) {
           // helicity -++
           return (sqrt(2.)*(2.*s1W*(angle(pa,pl)*square(p2,pa) + angle(pl,plbar)*square(p2,plbar))*
         (2.*sbg*angle(p1,pg)*angle(pb,pg)*square(p2,pg) +
           angle(p1,pb)*(angle(pb,pg)*q1g.m2()*square(p2,pb) +
              2.*sbg*(angle(p1,pg)*square(p1,p2) + angle(pa,pg)*square(p2,pa) +
                 angle(pg,pl)*square(p2,pl) + angle(pg,plbar)*square(p2,plbar))))*square(pa,plbar) +
        taW*angle(p1,pl)*square(p2,pa)*(4.*sbg*square(p1,plbar)*
            (angle(p1,pg)*angle(pb,pg)*square(p2,pg) +
              angle(p1,pb)*(angle(p1,pg)*square(p1,p2) + angle(pa,pg)*square(p2,pa) +
                 angle(pg,pl)*square(p2,pl) + angle(pg,plbar)*square(p2,plbar))) -
           4.*sbg*(angle(pb,pg)*angle(pg,pl)*square(p2,pg) +
              angle(pb,pl)*(angle(p1,pg)*square(p1,p2) + angle(pa,pg)*square(p2,pa) +
                 angle(pg,pl)*square(p2,pl) + angle(pg,plbar)*square(p2,plbar)))*square(pl,plbar) +
           2.*angle(pb,pg)*q1g.m2()*square(p2,pb)*
            (angle(p1,pb)*square(p1,plbar) - 1.*angle(pb,pl)*square(pl,plbar)))))/
    (s1W*sbg*taW*taW1*square(p2,pg));
         }
         else {
           // helicity -+-
           return (sqrt(2.)*((angle(p1,pb)*square(pa,plbar)*
           (((angle(pa,pl)*square(p2,pa) + angle(pl,plbar)*square(p2,plbar))*
                (4.*angle(p1,pb)*square(p1,pg) - (2.*angle(p2,pb)*q1g.m2()*square(p2,pg))/s2g -
                  4.*angle(pa,pb)*square(pa,pg) + 4.*angle(pb,pl)*square(pg,pl) +
                  4.*angle(pb,plbar)*square(pg,plbar)))/angle(pb,pg) +
             square(p2,pg)*(-4.*angle(pa,pl)*square(pa,pg) + 4.*angle(pl,plbar)*square(pg,plbar))))/
         taW + (2.*angle(p1,pl)*(2.*s2g*angle(p1,pb)*square(p1,pg)*square(p2,pa) -
             1.*angle(p2,pb)*q1g.m2()*square(p2,pa)*square(p2,pg) +
             2.*s2g*(-1.*angle(pa,pb)*square(p2,pa)*square(pa,pg) -
                1.*angle(pb,pg)*square(p2,pg)*square(pa,pg) +
                square(p2,pa)*(angle(pb,pl)*square(pg,pl) + angle(pb,plbar)*square(pg,plbar))))*
           (angle(p1,pb)*square(p1,plbar) - 1.*angle(pb,pl)*square(pl,plbar)))/(s1W*s2g*angle(pb,pg))
        ))/taW1;
         }
       }
       else {
         if(hg == helicity::plus) {
           // helicity --+
           return (2.*sqrt(2.)*(-1.*angle(p1,p2)*(2.*s2g*angle(p1,pg)*square(p1,pb) -
           1.*angle(p2,pg)*q1g.m2()*square(p2,pb) +
           2.*s2g*(-1.*angle(pa,pg)*square(pa,pb) + angle(pg,pl)*square(pb,pl) +
              angle(pg,plbar)*square(pb,plbar)))*
         (taW*angle(p1,pl)*square(p1,plbar)*square(pa,pb) +
           s1W*square(pa,plbar)*(angle(pa,pl)*square(pa,pb) - 1.*angle(pl,plbar)*square(pb,plbar)))
         + taW*angle(p1,pl)*square(pa,pb)*
         (angle(p2,pg)*(-1.*angle(p2,pl)*q1g.m2()*square(p2,pb) +
              2.*s2g*angle(pg,pl)*square(pb,pg)) +
           2.*s2g*angle(p2,pl)*(-1.*angle(pa,pg)*square(pa,pb) + angle(pg,pl)*square(pb,pl) +
              angle(pg,plbar)*square(pb,plbar)))*square(pl,plbar) -
        2.*s2g*angle(p1,pg)*(s1W*angle(p2,pg)*square(pa,plbar)*square(pb,pg)*
            (angle(pa,pl)*square(pa,pb) - 1.*angle(pl,plbar)*square(pb,plbar)) +
           taW*angle(p1,pl)*square(pa,pb)*
            (angle(p2,pg)*square(p1,plbar)*square(pb,pg) -
              1.*angle(p2,pl)*square(p1,pb)*square(pl,plbar)))))/(s1W*s2g*taW*taW1*square(pb,pg));
         }
         else {
           // helicity ---
           return (2.*sqrt(2.)*(-1.*angle(p1,p2)*(angle(p2,pb)*q1g.m2()*square(pb,pg)*
            (taW*angle(p1,pl)*square(p1,plbar)*square(pa,pb) +
              s1W*square(pa,plbar)*(angle(pa,pl)*square(pa,pb) - 1.*angle(pl,plbar)*square(pb,plbar))
              ) + 2.*sbg*(taW*angle(p1,pl)*square(p1,plbar) + s1W*angle(pa,pl)*square(pa,plbar))*
            (angle(p2,pg)*square(pa,pg)*square(pb,pg) +
              square(pa,pb)*(angle(p1,p2)*square(p1,pg) + angle(p2,pa)*square(pa,pg) +
                 angle(p2,pl)*square(pg,pl) + angle(p2,plbar)*square(pg,plbar))) -
           2.*s1W*sbg*angle(pl,plbar)*square(pa,plbar)*
            (angle(p2,pg)*square(pb,pg)*square(pg,plbar) +
              square(pb,plbar)*(angle(p1,p2)*square(p1,pg) + angle(p2,pa)*square(pa,pg) +
                 angle(p2,pl)*square(pg,pl) + angle(p2,plbar)*square(pg,plbar)))) +
        taW*angle(p1,pl)*angle(p2,pl)*(2.*sbg*angle(p2,pg)*square(pa,pg)*square(pb,pg) +
           square(pa,pb)*(angle(p2,pb)*q1g.m2()*square(pb,pg) +
              2.*sbg*(angle(p1,p2)*square(p1,pg) + angle(p2,pa)*square(pa,pg) +
                 angle(p2,pl)*square(pg,pl) + angle(p2,plbar)*square(pg,plbar))))*square(pl,plbar)))/
    (s1W*sbg*taW*taW1*angle(p2,pg));
         }
       }
     }
   }
 
   /**
    * @brief         W+Jets Unordered Contribution Helper Functions
    * @returns       result of equation (4.1.28) in Helen's Thesis (p.100)
    */
   double jM2Wuno(HLV pg, HLV p1,HLV plbar, HLV pl, HLV pa, Helicity h1,
                  HLV p2, HLV pb, Helicity h2, Helicity pol,
                  ParticleProperties const & wprop
   ){
     //@TODO Simplify the below (less Tensor class?)
     init_sigma_index();
 
     HLV pW = pl+plbar;
     HLV q1g=pa-pW-p1-pg;
     HLV q1 = pa-p1-pW;
     HLV q2 = p2-pb;
 
     const double taW  = (pa-pW).m2();
     const double taW1 = (pa-pW-p1).m2();
     const double s1W  = (p1+pW).m2();
     const double s1gW = (p1+pW+pg).m2();
     const double s1g  = (p1+pg).m2();
     const double s2g  = (p2+pg).m2();
     const double sbg  = (pb+pg).m2();
     const double tag  = (pa-pg).m2();
     const double taWg = (pa-pW-pg).m2();
 
     //use p1 as ref vec in pol tensor
     Tensor<1> epsg = eps(pg,p2,pol);
     Tensor<1> epsW = HEJ::current(pl,plbar,helicity::minus);
     Tensor<1> j2b = HEJ::current(p2,pb,h2);
 
     Tensor<1> Tq1q2 = to_tensor(
       (pb/sbg + p2/s2g)*(q1 - pg).m2() + 2*q1 - pg
     );
 
     Tensor<3> J31a = rank3_current(p1, pa, h1);
     Tensor<2> J2_qaW =J31a.contract((pa-pW)/taW/taW1, 2);
     Tensor<2> J2_p1W =J31a.contract((p1+pW)/s1W/taW1, 2);
     Tensor<3> L1a = outer(Tq1q2, J2_qaW);
     Tensor<3> L1b = outer(Tq1q2, J2_p1W);
     Tensor<3> L2a = outer(-2*pg, J2_qaW);
     Tensor<3> L2b = outer(-2*pg, J2_p1W);
     Tensor<3> L3 = outer(metric(), J2_qaW.contract(2*pg-q1,1)+J2_p1W.contract(2*pg-q1,2));
     Tensor<3> L(0.);
 
     Tensor<5> J51a = rank5_current(p1, pa, h1);
 
     Tensor<4> J_qaW = J51a.contract((pa-pW),4);
     Tensor<4> J_qag = J51a.contract(pa-pg,4);
     Tensor<4> J_p1gW = J51a.contract(p1+pg+pW,4);
 
     Tensor<3> U1a = J_qaW.contract(p1+pg,2);
     Tensor<3> U1b = J_p1gW.contract(p1+pg,2);
     Tensor<3> U1c = J_p1gW.contract(p1+pW,2);
     Tensor<3> U1(0.);
 
     Tensor<3> U2a = J_qaW.contract(pa-pg-pW,2);
     Tensor<3> U2b = J_qag.contract(pa-pg-pW,2);
     Tensor<3> U2c = J_qag.contract(p1+pW,2);
     Tensor<3> U2(0.);
 
-    for(int nu=0; nu<4;nu++){
-      for(int mu=0;mu<4;mu++){
-        for(int rho=0;rho<4;rho++){
+    for(int nu=0; nu<4;++nu){
+      for(int mu=0;mu<4;++mu){
+        for(int rho=0;rho<4;++rho){
           L(nu, mu, rho) =  L1a(nu,mu,rho) + L1b(nu,rho,mu)
             + L2a(mu,nu,rho) + L2b(mu,rho,nu) + L3(mu,nu,rho);
           U1(nu, mu, rho) = U1a(nu, mu, rho) / (s1g*taW)
             + U1b(nu,rho,mu) / (s1g*s1gW) + U1c(rho,nu,mu) / (s1W*s1gW);
           U2(nu,mu,rho) = U2a(mu,nu,rho) / (taWg*taW)
             + U2b(mu,rho,nu) / (taWg*tag) + U2c(rho,mu,nu) / (s1W*tag);
         }
       }
     }
 
     COM X = ((((U1-L).contract(epsW,3)).contract(j2b,2)).contract(epsg,1));
     COM Y = ((((U2+L).contract(epsW,3)).contract(j2b,2)).contract(epsg,1));
 
     double amp = HEJ::C_A*HEJ::C_F*HEJ::C_F/2.*(norm(X)+norm(Y)) - HEJ::C_F/2.*(X*conj(Y)).real();
 
     double t1 = q1g.m2();
     double t2 = q2.m2();
 
     //Divide by WProp
     amp*=WProp(plbar, pl, wprop);
 
     //Divide by t-channels
     amp/=(t1*t2);
 
     return amp;
   }
 
   /**
    * @brief         New implementation of unordered W+Jets current
    *
    * See eq:wunocurrent in the developer manual for the definition
    * of this current
    *
    * The aim is to replace jM2Wuno and eventually all uses of the Tensor class.
    * Explicit tensor contractions are rather slow and the initialisation code
    * in Tensor.cc is not very transparent.
    *
    * At the moment, this function _only_ works for positive-energy spinors,
    * so jM2Wuno has to be kept for qqbar emission.
    */
   double jM2Wuno_pos_energy(
       HLV const & pg, HLV const & p1, HLV const & plbar, HLV const & pl,
       HLV const & pa, Helicity const h1,
       HLV const & p2, HLV const & pb, Helicity const h2, Helicity const pol,
       ParticleProperties const & wprop
   ){
     using HEJ::C_A;
     using HEJ::C_F;
 
     const COM U1 = U1contr(pg, p1, plbar, pl, pa, h1, p2, pb, h2, pol);
     const COM U2 = U2contr(pg, p1, plbar, pl, pa, h1, p2, pb, h2, pol);
     const COM L = Lcontr(pg, p1, plbar, pl, pa, h1, p2, pb, h2, pol);
 
     const COM X = U1 - L;
     const COM Y = U2 + L;
 
     double amp = C_A*C_F*C_F/2.*(norm(X)+norm(Y)) - HEJ::C_F/2.*(X*conj(Y)).real();
     amp *= WProp(plbar, pl, wprop);
 
     const HLV q1g = pa-pl-plbar-p1-pg;
     const HLV q2 = p2-pb;
 
     const double t1 = q1g.m2();
     const double t2 = q2.m2();
 
     amp /= (t1*t2);
     return amp;
   }
 
 
   // Relevant Wqqx Helper Functions.
   //g->qxqlxl (Calculates gluon to qqx Current. See JV_\mu in WSubleading Notes)
   Tensor <1> gtqqxW(HLV pq,HLV pqbar,HLV pl,HLV plbar){
     //@TODO Simplify the calculation below (Less Tensor class use?)
     double s2AB=(pl+plbar+pq).m2();
     double s3AB=(pl+plbar+pqbar).m2();
 
     // Define llx current.
     Tensor<1> ABCur = HEJ::current(pl, plbar, helicity::minus);
 
     //blank 3 Gamma Current
     Tensor<3> JV23 = rank3_current(pq,pqbar,helicity::minus);
 
     // Components of g->qqW before W Contraction
     Tensor<2> JV1 = JV23.contract((pq + pl + plbar),2)/(s2AB);
     Tensor<2> JV2 = JV23.contract((pqbar + pl + plbar),2)/(s3AB);
 
     // g->qqW Current. Note Minus between terms due to momentum flow.
     // Also note: (-I)^2 from W vert. (I) from Quark prop.
     Tensor<1> JVCur = (JV1.contract(ABCur,1) - JV2.contract(ABCur,2))*COM(0.,-1.);
 
     return JVCur;
   }
 
   // Helper Functions Calculate the Crossed Contribution
   Tensor <2> MCrossW(HLV pa, HLV, HLV, HLV, HLV pq, HLV pqbar, HLV pl,
                      HLV plbar, std::vector<HLV> partons, int nabove
     ){
     //@TODO Simplify the calculation below Maybe combine with MCross?
     // Useful propagator factors
     double s2AB=(pl+plbar+pq).m2();
     double s3AB=(pl+plbar+pqbar).m2();
 
     HLV q1, q3;
     q1=pa;
-    for(int i=0; i<nabove+1;i++){
+    for(int i=0; i<nabove+1;++i){
       q1=q1-partons.at(i);
     }
     q3 = q1 - pq - pqbar - pl - plbar;
 
     double tcro1=(q3+pq).m2();
     double tcro2=(q1-pqbar).m2();
 
     // Define llx current.
     Tensor<1> ABCur = HEJ::current(pl, plbar,helicity::minus);
 
     //Blank 5 gamma Current
     Tensor<5> J523 = rank5_current(pq,pqbar,helicity::minus);
 
     // 4 gamma currents (with 1 contraction already).
     Tensor<4> J_q3q = J523.contract((q3 + pq),2);
     Tensor<4> J_2AB = J523.contract((pq + pl + plbar),2);
 
     // Components of Crossed Vertex Contribution
     Tensor<3> Xcro1 = J_q3q.contract((pqbar + pl + plbar),3);
     Tensor<3> Xcro2 = J_q3q.contract((q1 - pqbar),3);
     Tensor<3> Xcro3 = J_2AB.contract((q1 - pqbar),3);
 
     // Term Denominators Taken Care of at this stage
     Tensor<2> Xcro1Cont = Xcro1.contract(ABCur,3)/(tcro1*s3AB);
     Tensor<2> Xcro2Cont = Xcro2.contract(ABCur,2)/(tcro1*tcro2);
     Tensor<2> Xcro3Cont = Xcro3.contract(ABCur,1)/(s2AB*tcro2);
 
     //Initialise the Crossed Vertex Object
     Tensor<2> Xcro(0.);
 
-    for(int mu=0; mu<4;mu++){
-      for(int nu=0;nu<4;nu++){
+    for(int mu=0; mu<4;++mu){
+      for(int nu=0;nu<4;++nu){
         Xcro(mu,nu) = -(-Xcro1Cont(nu,mu)+Xcro2Cont(nu,mu)+Xcro3Cont(nu,mu));
       }
     }
 
     return Xcro;
   }
 
   // Helper Functions Calculate the Uncrossed Contribution
   Tensor <2> MUncrossW(HLV pa, HLV, HLV, HLV, HLV pq, HLV pqbar,
                        HLV pl, HLV plbar, std::vector<HLV> partons, int nabove
     ){
     //@TODO Simplify the calculation below Maybe combine with MUncross?
     double s2AB=(pl+plbar+pq).m2();
     double s3AB=(pl+plbar+pqbar).m2();
 
     HLV q1, q3;
     q1=pa;
-    for(int i=0; i<nabove+1;i++){
+    for(int i=0; i<nabove+1;++i){
       q1=q1-partons.at(i);
     }
     q3 = q1 - pl - plbar - pq - pqbar;
     double tunc1 = (q1-pq).m2();
     double tunc2 = (q3+pqbar).m2();
 
     // Define llx current.
     Tensor<1> ABCur = HEJ::current(pl, plbar, helicity::minus);
 
     //Blank 5 gamma Current
     Tensor<5> J523 = rank5_current(pq,pqbar,helicity::minus);
 
     // 4 gamma currents (with 1 contraction already).
     Tensor<4> J_2AB = J523.contract((pq + pl + plbar),2);
     Tensor<4> J_q1q = J523.contract((q1 - pq),2);
 
     // 2 Contractions taken care of.
     Tensor<3> Xunc1 = J_2AB.contract((q3 + pqbar),3);
     Tensor<3> Xunc2 = J_q1q.contract((q3 + pqbar),3);
     Tensor<3> Xunc3 = J_q1q.contract((pqbar + pl + plbar),3);
 
     // Term Denominators Taken Care of at this stage
     Tensor<2> Xunc1Cont = Xunc1.contract(ABCur,1)/(s2AB*tunc2);
     Tensor<2> Xunc2Cont = Xunc2.contract(ABCur,2)/(tunc1*tunc2);
     Tensor<2> Xunc3Cont = Xunc3.contract(ABCur,3)/(tunc1*s3AB);
 
     //Initialise the Uncrossed Vertex Object
     Tensor<2> Xunc(0.);
 
-    for(int mu=0; mu<4;mu++){
-      for(int nu=0;nu<4;nu++){
+    for(int mu=0; mu<4;++mu){
+      for(int nu=0;nu<4;++nu){
         Xunc(mu,nu) = -(- Xunc1Cont(mu,nu)+Xunc2Cont(mu,nu) +Xunc3Cont(mu,nu));
       }
     }
 
     return Xunc;
   }
 
   // Helper Functions Calculate the g->qqxW (Eikonal) Contributions
   Tensor <2> MSymW(HLV pa, HLV p1, HLV pb, HLV p4, HLV pq, HLV pqbar,
                    HLV pl,HLV plbar, std::vector<HLV> partons, int nabove
     ){
     //@TODO Simplify the calculation below Maybe combine with MSym?
     double sa2=(pa+pq).m2();
     double s12=(p1+pq).m2();
     double sa3=(pa+pqbar).m2();
     double s13=(p1+pqbar).m2();
     double saA=(pa+pl).m2();
     double s1A=(p1+pl).m2();
     double saB=(pa+plbar).m2();
     double s1B=(p1+plbar).m2();
     double sb2=(pb+pq).m2();
     double s42=(p4+pq).m2();
     double sb3=(pb+pqbar).m2();
     double s43=(p4+pqbar).m2();
     double sbA=(pb+pl).m2();
     double s4A=(p4+pl).m2();
     double sbB=(pb+plbar).m2();
     double s4B=(p4+plbar).m2();
     double s23AB=(pl+plbar+pq+pqbar).m2();
 
     HLV q1,q3;
     q1=pa;
-    for(int i=0;i<nabove+1;i++){
+    for(int i=0;i<nabove+1;++i){
       q1-=partons.at(i);
     }
     q3=q1-pq-pqbar-plbar-pl;
     double t1 = (q1).m2();
     double t3 = (q3).m2();
 
     // g->qqW Current (Factors of sqrt2 dealt with in this function.)
     Tensor<1> JV = gtqqxW(pq,pqbar,pl,plbar);
 
     // 1a gluon emisson Contribution
     Tensor<3> X1a = outer(metric(), p1*(t1/(s12+s13+s1A+s1B))
                           + pa*(t1/(sa2+sa3+saA+saB)) );
     Tensor<2> X1aCont = X1a.contract(JV,3);
 
     //4b gluon emission Contribution
     Tensor<3> X4b = outer(metric(), p4*(t3/(s42+s43+s4A+s4B))
                           + pb*(t3/(sb2+sb3+sbA+sbB)) );
     Tensor<2> X4bCont = X4b.contract(JV,3);
 
     //Set up each term of 3G diagram.
     Tensor<3> X3g1 = outer(q1+pq+pqbar+pl+plbar, metric());
     Tensor<3> X3g2 = outer(q3-pq-pqbar-pl-plbar, metric());
     Tensor<3> X3g3 = outer(q1+q3, metric());
 
     // Note the contraction of indices changes term by term
     Tensor<2> X3g1Cont = X3g1.contract(JV,3);
     Tensor<2> X3g2Cont = X3g2.contract(JV,2);
     Tensor<2> X3g3Cont = X3g3.contract(JV,1);
 
     // XSym is an amalgamation of x1a, X4b and X3g.
     // Makes sense from a colour factor point of view.
     Tensor<2>Xsym(0.);
 
-    for(int mu=0; mu<4;mu++){
-      for(int nu=0;nu<4;nu++){
+    for(int mu=0; mu<4;++mu){
+      for(int nu=0;nu<4;++nu){
         Xsym(mu,nu) = (X3g1Cont(nu,mu) + X3g2Cont(mu,nu) - X3g3Cont(nu,mu))
           + (X1aCont(mu,nu) - X4bCont(mu,nu));
       }
     }
     return Xsym/s23AB;
   }
 
   Tensor <2> MCross(HLV pa, HLV pq, HLV pqbar, std::vector<HLV> partons,
                     Helicity hq, int nabove
     ){
     //@TODO Simplify the calculation below Maybe combine with MCrossW?
     HLV q1;
     q1=pa;
-    for(int i=0;i<nabove+1;i++){
+    for(int i=0;i<nabove+1;++i){
       q1-=partons.at(i);
     }
 
     double t2=(q1-pqbar).m2();
 
     //Blank 3 gamma Current
     Tensor<3> J323 = rank3_current(pq,pqbar,hq);
 
     // 2 gamma current (with 1 contraction already).
     Tensor<2> XCroCont = J323.contract((q1-pqbar),2)/(t2);
 
     //Initialise the Crossed Vertex
     Tensor<2> Xcro(0.);
 
-    for(int mu=0; mu<4;mu++){
-      for(int nu=0;nu<4;nu++){
+    for(int mu=0; mu<4;++mu){
+      for(int nu=0;nu<4;++nu){
         Xcro(mu,nu) = XCroCont(nu,mu);
       }
     }
 
     return Xcro;
   }
 
   // Helper Functions Calculate the Uncrossed Contribution
   Tensor <2> MUncross(HLV pa, HLV pq,HLV pqbar, std::vector<HLV> partons,
                       Helicity hq, int nabove
     ){
     //@TODO Simplify the calculation below Maybe combine with MUncrossW?
     HLV q1;
     q1=pa;
-    for(int i=0;i<nabove+1;i++){
+    for(int i=0;i<nabove+1;++i){
       q1-=partons.at(i);
     }
     double t2 = (q1-pq).m2();
 
     //Blank 3 gamma Current
     Tensor<3> J323 = rank3_current(pq,pqbar,hq);
 
     // 2 gamma currents (with 1 contraction already).
     Tensor<2> XUncCont = J323.contract((q1-pq),2)/t2;
 
     //Initialise the Uncrossed Vertex
     Tensor<2> Xunc(0.);
 
-    for(int mu=0; mu<4;mu++){
-      for(int nu=0;nu<4;nu++){
+    for(int mu=0; mu<4;++mu){
+      for(int nu=0;nu<4;++nu){
         Xunc(mu,nu) = -XUncCont(mu,nu);
       }
     }
 
     return Xunc;
   }
 
   // Helper Functions Calculate the Eikonal Contributions
   Tensor <2> MSym(HLV pa, HLV p1, HLV pb, HLV p4, HLV pq, HLV pqbar,
                   std::vector<HLV> partons, Helicity hq, int nabove
     ){
     //@TODO Simplify the calculation below Maybe combine with MsymW?
     HLV q1, q3;
     q1=pa;
-    for(int i=0;i<nabove+1;i++){
+    for(int i=0;i<nabove+1;++i){
       q1-=partons.at(i);
     }
     q3 = q1-pq-pqbar;
     double t1 = (q1).m2();
     double t3 = (q3).m2();
 
     double s23 = (pq+pqbar).m2();
     double sa2 = (pa+pq).m2();
     double sa3 = (pa+pqbar).m2();
     double s12 = (p1+pq).m2();
     double s13 = (p1+pqbar).m2();
     double sb2 = (pb+pq).m2();
     double sb3 = (pb+pqbar).m2();
     double s42 = (p4+pq).m2();
     double s43 = (p4+pqbar).m2();
 
     Tensor<1> qqxCur = HEJ::current(pq, pqbar, hq);
 
     // // 1a gluon emisson Contribution
     Tensor<3> X1a = outer(metric(), p1*(t1/(s12+s13))+ pa*(t1/(sa2+sa3)));
     Tensor<2> X1aCont = X1a.contract(qqxCur,3);
 
     // //4b gluon emission Contribution
     Tensor<3> X4b = outer(metric(), p4*(t3/(s42+s43)) + pb*(t3/(sb2+sb3)));
     Tensor<2> X4bCont = X4b.contract(qqxCur,3);
 
     // New Formulation Corresponding to New Analytics
     Tensor<3> X3g1 = outer(q1+pq+pqbar, metric());
     Tensor<3> X3g2 = outer(q3-pq-pqbar, metric());
     Tensor<3> X3g3 = outer(q1+q3, metric());
 
     // Note the contraction of indices changes term by term
     Tensor<2> X3g1Cont = X3g1.contract(qqxCur,3);
     Tensor<2> X3g2Cont = X3g2.contract(qqxCur,2);
     Tensor<2> X3g3Cont = X3g3.contract(qqxCur,1);
 
     Tensor<2>Xsym(0.);
 
-    for(int mu=0; mu<4;mu++){
-      for(int nu=0;nu<4;nu++){
+    for(int mu=0; mu<4;++mu){
+      for(int nu=0;nu<4;++nu){
         Xsym(mu, nu) = COM(0,1) * ( (X3g1Cont(nu,mu) + X3g2Cont(mu,nu)
                                      - X3g3Cont(nu,mu)) + (X1aCont(mu,nu) - X4bCont(mu,nu)) );
       }
     }
     return Xsym/s23;
   }
 
 //! W+Jets FKL Contributions
 /**
  * @brief W+Jets FKL Contributions, function to handle all incoming types.
  * @param p1out             Outgoing Particle 1. (W emission)
  * @param plbar             Outgoing election momenta
  * @param pl                Outgoing neutrino momenta
  * @param p1in              Incoming Particle 1. (W emission)
  * @param p2out             Outgoing Particle 2
  * @param p2in              Incoming Particle 2
  * @param aqlineb           Bool. Is Backwards quark line an anti-quark line?
  * @param aqlinef           Bool. Is Forwards quark line an anti-quark line?
  *
  * Calculates j_W ^\mu    j_\mu.
  * Handles all possible incoming states.
  */
   double jW_j( HLV p1out, HLV plbar, HLV pl, HLV p1in, HLV p2out, HLV p2in,
                bool aqlineb, bool /* aqlinef */,
                ParticleProperties const & wprop
     ){
     using helicity::minus;
     using helicity::plus;
     const HLV q1=p1in-p1out-plbar-pl;
     const HLV q2=-(p2in-p2out);
 
     const double WPropfact = WProp(plbar, pl, wprop);
 
     const auto j_W = COM{0,-1}*jW(p1in, p1out, plbar, pl, aqlineb?plus:minus);
     double Msqr = 0.;
     for(const auto h: {plus, minus}) {
       const auto j = HEJ::current(p2out, p2in, h);
       Msqr += abs2(j_W.contract(j, 1));
     }
     // Division by colour and Helicity average (Nc2-1)(4)
     // Multiply by Cf^2
     return HEJ::C_F*HEJ::C_F*WPropfact*Msqr/(q1.m2()*q2.m2()*(HEJ::N_C*HEJ::N_C - 1)*4);
   }
 } // Anonymous Namespace
 
 double ME_W_qQ (HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out, HLV p2in,
    ParticleProperties const & wprop
 ){
   return jW_j(p1out, plbar, pl, p1in, p2out, p2in, false, false, wprop);
 }
 
 double ME_W_qQbar (HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out, HLV p2in,
    ParticleProperties const & wprop
 ){
   return jW_j(p1out, plbar, pl, p1in, p2out, p2in, false, true, wprop);
 }
 
 double ME_W_qbarQ (HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out, HLV p2in,
    ParticleProperties const & wprop
 ){
   return jW_j(p1out, plbar, pl, p1in, p2out, p2in, true, false, wprop);
 }
 
 double ME_W_qbarQbar (HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out, HLV p2in,
    ParticleProperties const & wprop
 ){
   return jW_j(p1out, plbar, pl, p1in, p2out, p2in, true, true, wprop);
 }
 
 double ME_W_qg (HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out, HLV p2in,
    ParticleProperties const & wprop
 ){
   return jW_j(p1out, plbar, pl, p1in, p2out, p2in, false, false, wprop)
           *K_g(p2out, p2in)/HEJ::C_F;
 }
 
 double ME_W_qbarg (HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out, HLV p2in,
    ParticleProperties const & wprop
 ){
   return jW_j(p1out, plbar, pl, p1in, p2out, p2in, true, false, wprop)
           *K_g(p2out, p2in)/HEJ::C_F;
 }
 
 namespace{
   /**
    * @brief W+Jets Unordered Contributions, function to handle all incoming types.
    * @param p1out             Outgoing Particle 1. (W emission)
    * @param plbar             Outgoing election momenta
    * @param pl                Outgoing neutrino momenta
    * @param p1in              Incoming Particle 1. (W emission)
    * @param p2out             Outgoing Particle 2 (Quark, unordered emission this side.)
    * @param p2in              Incoming Particle 2 (Quark, unordered emission this side.)
    * @param pg                Unordered Gluon momenta
    * @param aqlineb           Bool. Is Backwards quark line an anti-quark line?
    * @param aqlinef           Bool. Is Forwards quark line an anti-quark line?
    *
    * Calculates j_W ^\mu    j_{uno}_\mu. Ie, unordered with W emission opposite side.
    * Handles all possible incoming states.
    */
   double jW_juno(HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out,
                  HLV p2in, HLV pg, bool aqlineb, bool aqlinef,
                  ParticleProperties const & wprop
   ){
     using helicity::minus;
     using helicity::plus;
     const HLV q1=p1in-p1out-plbar-pl;
     const HLV q2=-(p2in-p2out-pg);
     const HLV q3=-(p2in-p2out);
     const Helicity fhel = aqlinef?plus:minus;
 
     const auto j_W = jW(p1in, p1out, plbar, pl, aqlineb?plus:minus);
     const auto mj2p = HEJ::current(p2out, p2in, flip(fhel));
     const auto mj2m = HEJ::current(p2out, p2in, fhel);
 
     const auto jgbp = HEJ::current(pg, p2in, flip(fhel));
     const auto jgbm = HEJ::current(pg, p2in, fhel);
 
     const auto j2gp = HEJ::current(p2out, pg, flip(fhel));
     const auto j2gm = HEJ::current(p2out, pg, fhel);
 
     // Dot products of these which occur again and again
     COM MWmp=j_W.dot(mj2p);  // And now for the Higgs ones
     COM MWmm=j_W.dot(mj2m);
 
     const auto qsum = to_tensor(q2+q3);
 
     const auto p1o = to_tensor(p1out);
     const auto p1i = to_tensor(p1in);
     const auto p2o = to_tensor(p2out);
     const auto p2i = to_tensor(p2in);
 
     const auto Lmm=( (-1.)*qsum*(MWmm) + (-2.*COM{j_W.dot(pg)})*mj2m + 2.*COM{mj2m.dot(pg)}*j_W
                      + ( p1o/pg.dot(p1out) + p1i/pg.dot(p1in) )*( q2.m2()*MWmm/2. ) )/q3.m2();
     const auto Lmp=( (-1.)*qsum*(MWmp) + (-2.*COM{j_W.dot(pg)})*mj2p + 2.*COM{mj2p.dot(pg)}*j_W
                      + ( p1o/pg.dot(p1out) + p1i/pg.dot(p1in) )*( q2.m2()*MWmp/2. ) )/q3.m2();
 
     const auto U1mm=(COM{jgbm.dot(j_W)}*j2gm+2.*p2o*MWmm)/(p2out+pg).m2();
     const auto U1mp=(COM{jgbp.dot(j_W)}*j2gp+2.*p2o*MWmp)/(p2out+pg).m2();
 
     const auto U2mm=((-1.)*COM{j2gm.dot(j_W)}*jgbm+2.*p2i*MWmm)/(p2in-pg).m2();
     const auto U2mp=((-1.)*COM{j2gp.dot(j_W)}*jgbp+2.*p2i*MWmp)/(p2in-pg).m2();
 
     double amm,amp;
 
     amm=HEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*HEJ::C_F*HEJ::C_F/3.*abs2(U1mm+U2mm);
     amp=HEJ::C_F*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*HEJ::C_F*HEJ::C_F/3.*abs2(U1mp+U2mp);
 
     double ampsq=-(amm+amp);
     //Divide by WProp
     ampsq*=WProp(plbar, pl, wprop);
 
     return ampsq/((16)*(q2.m2()*q1.m2()));
   }
 }
 double ME_W_unob_qQ(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                     HLV pg, HLV plbar, HLV pl,
                     ParticleProperties const & wprop
 ){
   return jW_juno(p2out, plbar, pl, p2in, p1out, p1in, pg, false, false, wprop);
 }
 
 double ME_W_unob_qQbar(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                        HLV pg, HLV plbar, HLV pl,
                        ParticleProperties const & wprop
 ){
   return jW_juno(p2out, plbar, pl, p2in, p1out, p1in, pg, false, true, wprop);
 }
 
 double ME_W_unob_qbarQ(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                        HLV pg, HLV plbar, HLV pl,
                        ParticleProperties const & wprop
 ){
   return jW_juno(p2out, plbar, pl, p2in, p1out, p1in, pg, true, false, wprop);
 }
 
 double ME_W_unob_qbarQbar(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                           HLV pg, HLV plbar, HLV pl,
                           ParticleProperties const & wprop
 ){
   return jW_juno(p2out, plbar, pl, p2in, p1out, p1in, pg, true, true, wprop);
 }
 
 namespace{
 /**
  * @brief W+Jets Unordered Contributions, function to handle all incoming types.
  * @param pg                Unordered Gluon momenta
  * @param p1out             Outgoing Particle 1. (Quark - W and Uno emission)
  * @param plbar             Outgoing election momenta
  * @param pl                Outgoing neutrino momenta
  * @param p1in              Incoming Particle 1. (Quark - W and Uno emission)
  * @param p2out             Outgoing Particle 2
  * @param p2in              Incoming Particle 2
  * @param aqlineb           Bool. Is Backwards quark line an anti-quark line?
  *
  * Calculates j_W_{uno} ^\mu    j_\mu. Ie, unordered with W emission same side.
  * Handles all possible incoming states. Note this handles both forward and back-
  * -ward Wuno emission. For forward, ensure p1out is the uno and W emission parton.
  * @TODO: Include separate wrapper functions for forward and backward to clean up
  *        ME_W_unof_current in `MatrixElement.cc`.
  */
   double jWuno_j(HLV pg, HLV p1out, HLV plbar, HLV pl, HLV p1in,
                  HLV p2out, HLV p2in, bool aqlineb,
                  ParticleProperties const & wprop
     ){
     //Calculate different Helicity choices
     const Helicity h = aqlineb?helicity::plus:helicity::minus;
     double ME2mpp = jM2Wuno_pos_energy(pg, p1out,plbar,pl,p1in,h,p2out,p2in,
                             helicity::plus,helicity::plus, wprop);
     double ME2mpm = jM2Wuno_pos_energy(pg, p1out,plbar,pl,p1in,h,p2out,p2in,
                             helicity::plus,helicity::minus, wprop);
     double ME2mmp = jM2Wuno_pos_energy(pg, p1out,plbar,pl,p1in,h,p2out,p2in,
                             helicity::minus,helicity::plus, wprop);
     double ME2mmm = jM2Wuno_pos_energy(pg, p1out,plbar,pl,p1in,h,p2out,p2in,
                             helicity::minus,helicity::minus, wprop);
 
     //Helicity sum and average over initial states
     return (ME2mpp + ME2mpm + ME2mmp + ME2mmm)/(4.*HEJ::C_A*HEJ::C_A);
   }
 }
 double ME_Wuno_qQ(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                   HLV pg, HLV plbar, HLV pl, ParticleProperties const & wprop
 ){
   return jWuno_j(pg, p1out, plbar, pl, p1in, p2out, p2in, false, wprop);
 }
 
 double ME_Wuno_qQbar(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                      HLV pg, HLV plbar, HLV pl,
                      ParticleProperties const & wprop
 ){
   return jWuno_j(pg, p1out, plbar, pl, p1in, p2out, p2in, false, wprop);
 }
 
 double ME_Wuno_qbarQ(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                      HLV pg, HLV plbar, HLV pl,
                      ParticleProperties const & wprop
 ){
   return jWuno_j(pg, p1out, plbar, pl, p1in, p2out, p2in, true, wprop);
 }
 
 double ME_Wuno_qbarQbar(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                         HLV pg, HLV plbar, HLV pl,
                         ParticleProperties const & wprop
 ){
   return jWuno_j(pg, p1out, plbar, pl, p1in, p2out, p2in, true, wprop);
 }
 
 double ME_Wuno_qg(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                   HLV pg, HLV plbar, HLV pl, ParticleProperties const & wprop
 ){
   return jWuno_j(pg, p1out, plbar, pl, p1in, p2out, p2in, false, wprop)
           *K_g(p2out, p2in)/HEJ::C_F;
 }
 
 double ME_Wuno_qbarg(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                      HLV pg, HLV plbar, HLV pl,
                      ParticleProperties const & wprop
 ){
   return jWuno_j(pg, p1out, plbar, pl, p1in, p2out, p2in, true, wprop)
           *K_g(p2out, p2in)/HEJ::C_F;
 }
 
 /**
  * @brief W+Jets Extremal qqx Contributions, function to handle all incoming types.
  * @param pgin              Incoming gluon which will split into qqx.
  * @param pqout             Quark of extremal qqx outgoing (W-Emission).
  * @param plbar             Outgoing anti-lepton momenta
  * @param pl                Outgoing lepton momenta
  * @param pqbarout          Anti-quark of extremal qqx pair. (W-Emission)
  * @param pout              Outgoing Particle 2 (end of FKL chain)
  * @param p2in              Incoming Particle 2
  * @param aqlinef           Bool. Is Forwards quark line an anti-quark line?
  *
  * Calculates j_W_{qqx} ^\mu    j_\mu. Ie, Ex-QQX with W emission same side.
  * Handles all possible incoming states. Calculated via crossing symmetry from jWuno_j.
  */
 double jWqqx_j(HLV pgin, HLV pqout, HLV plbar, HLV pl,
                HLV pqbarout, HLV p2out, HLV p2in, bool aqlinef,
                ParticleProperties const & wprop
 ){
   //Calculate Different Helicity Configurations.
   const Helicity h = aqlinef?helicity::plus:helicity::minus;
   double ME2mpp = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,h,p2out,p2in,
                           helicity::plus,helicity::plus, wprop);
   double ME2mpm = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,h,p2out,p2in,
                           helicity::plus,helicity::minus, wprop);
   double ME2mmp = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,h,p2out,p2in,
                           helicity::minus,helicity::plus, wprop);
   double ME2mmm = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,h,p2out,p2in,
                           helicity::minus,helicity::minus, wprop);
   //Helicity sum and average over initial states.
   double ME2 = (ME2mpp + ME2mpm + ME2mmp + ME2mmm)/(4.*HEJ::C_A*HEJ::C_A);
 
   //Correct colour averaging after crossing:
   ME2*=(3.0/8.0);
 
   return ME2;
 }
 
 double ME_WExqqx_qbarqQ(HLV pgin, HLV pqout, HLV plbar, HLV pl,
                       HLV pqbarout, HLV p2out, HLV p2in,
                ParticleProperties const & wprop
 ){
   return jWqqx_j(pgin, pqout, plbar, pl, pqbarout, p2out, p2in, false, wprop);
 }
 
 double ME_WExqqx_qqbarQ(HLV pgin, HLV pqbarout, HLV plbar, HLV pl,
                       HLV pqout, HLV p2out, HLV p2in,
                       ParticleProperties const & wprop
 ){
   return jWqqx_j(pgin, pqbarout, plbar, pl, pqout, p2out, p2in, true, wprop);
 }
 
 double ME_WExqqx_qbarqg(HLV pgin, HLV pqout, HLV plbar, HLV pl,
                       HLV pqbarout, HLV p2out, HLV p2in,
                       ParticleProperties const & wprop
 ){
   return jWqqx_j(pgin, pqout, plbar, pl, pqbarout, p2out, p2in, false, wprop)
           *K_g(p2out,p2in)/HEJ::C_F;
 }
 
 double ME_WExqqx_qqbarg(HLV pgin, HLV pqbarout, HLV plbar, HLV pl,
                       HLV pqout, HLV p2out, HLV p2in,
                       ParticleProperties const & wprop
 ){
   return jWqqx_j(pgin, pqbarout, plbar, pl, pqout, p2out, p2in, true, wprop)
           *K_g(p2out,p2in)/HEJ::C_F;
 }
 
 namespace {
 //Function to calculate Term 1 in Equation 3.23 in James Cockburn's Thesis.
   Tensor<1> qggm1(HLV pb, HLV p2, HLV p3, Helicity hel2, Helicity helg, HLV refmom){
     //@TODO Simplify the calculation below. (Less Tensor class use?)
     double t1 = (p3-pb)*(p3-pb);
     // Gauge choice in polarisation tensor. (see JC's Thesis)
     Tensor<1> epsg = eps(pb, refmom, helg);
     Tensor<3> qqCurBlank = rank3_current(p2,p3,hel2);
     Tensor<2> qqCur = qqCurBlank.contract(p3-pb,2);
     Tensor<1> gqqCur = qqCur.contract(epsg,2)/t1;
 
     return gqqCur*(-1);
   }
 
 //Function to calculate Term 2 in Equation 3.23 in James Cockburn's Thesis.
   Tensor<1> qggm2(HLV pb, HLV p2, HLV p3, Helicity hel2, Helicity helg, HLV refmom){
     //@TODO Simplify the calculation below (Less Tensor class use?)
     double t1 = (p2-pb)*(p2-pb);
     // Gauge choice in polarisation tensor. (see JC's Thesis)
     Tensor<1> epsg = eps(pb,refmom, helg);
     Tensor<3> qqCurBlank = rank3_current(p2,p3,hel2);
     Tensor<2> qqCur = qqCurBlank.contract(p2-pb,2);
     Tensor<1> gqqCur = qqCur.contract(epsg,1)/t1;
 
     return gqqCur;
   }
 
 //Function to calculate Term 3 in Equation 3.23 in James Cockburn's Thesis.
   Tensor<1> qggm3(HLV pb, HLV p2, HLV p3, Helicity hel2, Helicity helg, HLV refmom){
     //@TODO Simplify the calculation below (Less Tensor class use?)
     double s23 = (p2+p3)*(p2+p3);
     // Gauge choice in polarisation tensor. (see JC's Thesis)
     Tensor<1> epsg = eps(pb, refmom, helg);
     Tensor<3> qqCurBlank1 = outer(p2+p3, metric())/s23;
     Tensor<3> qqCurBlank2 = outer(pb, metric())/s23;
     Tensor<1> Cur23 = HEJ::current(p2, p3,hel2);
 
     Tensor<2> qqCur1 = qqCurBlank1.contract(Cur23,3);
     Tensor<2> qqCur2 = qqCurBlank2.contract(Cur23,3);
     Tensor<2> qqCur3 = qqCurBlank2.contract(Cur23,1);
 
     Tensor<1> gqqCur = (qqCur1.contract(epsg,1)
                           - qqCur2.contract(epsg,2)
                           + qqCur3.contract(epsg,1))*2*COM(0,1);
     return gqqCur;
   }
 }
 
 // no wqq emission
 double ME_W_Exqqx_QQq(HLV pa, HLV pb, HLV p1,  HLV p2,
                       HLV p3,HLV plbar, HLV pl, bool aqlinepa,
                       ParticleProperties const & wprop
 ){
   using helicity::minus;
   using helicity::plus;
   init_sigma_index();
 
   // 2 independent helicity choices (complex conjugation related).
   Tensor<1> TMmmm1 = qggm1(pb,p2,p3,minus,minus, pa);
   Tensor<1> TMmmm2 = qggm2(pb,p2,p3,minus,minus, pa);
   Tensor<1> TMmmm3 = qggm3(pb,p2,p3,minus,minus, pa);
   Tensor<1> TMpmm1 = qggm1(pb,p2,p3,minus,plus, pa);
   Tensor<1> TMpmm2 = qggm2(pb,p2,p3,minus,plus, pa);
   Tensor<1> TMpmm3 = qggm3(pb,p2,p3,minus,plus, pa);
 
   // Build the external quark line W Emmision
   Tensor<1> cur1a = jW(pa,p1,plbar,pl, aqlinepa?plus:minus);
 
   //Contract with the qqxCurrent.
   COM Mmmm1 = TMmmm1.contract(cur1a,1);
   COM Mmmm2 = TMmmm2.contract(cur1a,1);
   COM Mmmm3 = TMmmm3.contract(cur1a,1);
   COM Mpmm1 = TMpmm1.contract(cur1a,1);
   COM Mpmm2 = TMpmm2.contract(cur1a,1);
   COM Mpmm3 = TMpmm3.contract(cur1a,1);
 
   //Colour factors:
   COM cm1m1,cm2m2,cm3m3,cm1m2,cm1m3,cm2m3;
   cm1m1=8./3.;
   cm2m2=8./3.;
   cm3m3=6.;
   cm1m2 =-1./3.;
   cm1m3 = -3.*COM(0.,1.);
   cm2m3 = 3.*COM(0.,1.);
 
   //Sqaure and sum for each helicity config:
   double Mmmm = real( cm1m1*pow(abs(Mmmm1),2) + cm2m2*pow(abs(Mmmm2),2)
                     + cm3m3*pow(abs(Mmmm3),2) + 2.*real(cm1m2*Mmmm1*conj(Mmmm2))
                     + 2.*real(cm1m3*Mmmm1*conj(Mmmm3))
                     + 2.*real(cm2m3*Mmmm2*conj(Mmmm3)) );
   double Mpmm = real( cm1m1*pow(abs(Mpmm1),2) + cm2m2*pow(abs(Mpmm2),2)
                     + cm3m3*pow(abs(Mpmm3),2) + 2.*real(cm1m2*Mpmm1*conj(Mpmm2))
                     + 2.*real(cm1m3*Mpmm1*conj(Mpmm3))
                     + 2.*real(cm2m3*Mpmm2*conj(Mpmm3)) );
 
   // Divide by WProp
   const double WPropfact = WProp(plbar, pl, wprop);
   return (2*WPropfact*(Mmmm+Mpmm)/24./4.)/(pa-p1-pl-plbar).m2()/(p2+p3-pb).m2();
 }
 
 // W+Jets qqxCentral
 double ME_WCenqqx_qq(HLV pa, HLV pb,HLV pl, HLV plbar, std::vector<HLV> partons,
                     bool aqlinepa, bool aqlinepb, bool qqxmarker, int nabove,
                     ParticleProperties const & wprop
 ){
   init_sigma_index();
 
   HLV pq, pqbar, p1, p4;
   if (qqxmarker){
     pqbar = partons[nabove+1];
     pq = partons[nabove+2];}
   else{
     pq = partons[nabove+1];
     pqbar = partons[nabove+2];}
 
   p1 = partons.front();
   p4 = partons.back();
 
   Tensor<1> T1am, T4bm, T1ap, T4bp;
   if(!(aqlinepa)){
     T1ap = HEJ::current(p1, pa, helicity::plus);
     T1am = HEJ::current(p1, pa, helicity::minus);}
   else if(aqlinepa){
     T1ap = HEJ::current(pa, p1, helicity::plus);
     T1am = HEJ::current(pa, p1, helicity::minus);}
   if(!(aqlinepb)){
     T4bp = HEJ::current(p4, pb, helicity::plus);
     T4bm = HEJ::current(p4, pb, helicity::minus);}
   else if(aqlinepb){
     T4bp = HEJ::current(pb, p4, helicity::plus);
     T4bm = HEJ::current(pb, p4, helicity::minus);}
 
   // Calculate the 3 separate contributions to the effective vertex
   Tensor<2> Xunc = MUncrossW(pa, p1, pb, p4, pq, pqbar, pl, plbar, partons, nabove);
   Tensor<2> Xcro = MCrossW(  pa, p1, pb, p4, pq, pqbar, pl, plbar, partons, nabove);
   Tensor<2> Xsym = MSymW(    pa, p1, pb, p4, pq, pqbar, pl, plbar, partons, nabove);
 
   // 4 Different Helicity Choices (Differs from Pure Jet Case, where there is
   // also the choice in qqbar helicity.
   // (- - hel choice)
   COM M_mmUnc = (((Xunc).contract(T1am,1)).contract(T4bm,1));
   COM M_mmCro = (((Xcro).contract(T1am,1)).contract(T4bm,1));
   COM M_mmSym = (((Xsym).contract(T1am,1)).contract(T4bm,1));
   // (- + hel choice)
   COM M_mpUnc = (((Xunc).contract(T1am,1)).contract(T4bp,1));
   COM M_mpCro = (((Xcro).contract(T1am,1)).contract(T4bp,1));
   COM M_mpSym = (((Xsym).contract(T1am,1)).contract(T4bp,1));
   // (+ - hel choice)
   COM M_pmUnc = (((Xunc).contract(T1ap,1)).contract(T4bm,1));
   COM M_pmCro = (((Xcro).contract(T1ap,1)).contract(T4bm,1));
   COM M_pmSym = (((Xsym).contract(T1ap,1)).contract(T4bm,1));
   // (+ + hel choice)
   COM M_ppUnc = (((Xunc).contract(T1ap,1)).contract(T4bp,1));
   COM M_ppCro = (((Xcro).contract(T1ap,1)).contract(T4bp,1));
   COM M_ppSym = (((Xsym).contract(T1ap,1)).contract(T4bp,1));
 
   //Colour factors:
   COM cmsms,cmumu,cmcmc,cmsmu,cmsmc,cmumc;
   cmsms=3.;
   cmumu=4./3.;
   cmcmc=4./3.;
   cmsmu =3./2.*COM(0.,1.);
   cmsmc = -3./2.*COM(0.,1.);
   cmumc = -1./6.;
 
   // Work Out Interference in each case of helicity:
   double amp_mm = real(cmsms*pow(abs(M_mmSym),2)
              +cmumu*pow(abs(M_mmUnc),2)
              +cmcmc*pow(abs(M_mmCro),2)
              +2.*real(cmsmu*M_mmSym*conj(M_mmUnc))
              +2.*real(cmsmc*M_mmSym*conj(M_mmCro))
              +2.*real(cmumc*M_mmUnc*conj(M_mmCro)));
 
   double amp_mp = real(cmsms*pow(abs(M_mpSym),2)
              +cmumu*pow(abs(M_mpUnc),2)
              +cmcmc*pow(abs(M_mpCro),2)
              +2.*real(cmsmu*M_mpSym*conj(M_mpUnc))
              +2.*real(cmsmc*M_mpSym*conj(M_mpCro))
              +2.*real(cmumc*M_mpUnc*conj(M_mpCro)));
 
   double amp_pm = real(cmsms*pow(abs(M_pmSym),2)
              +cmumu*pow(abs(M_pmUnc),2)
              +cmcmc*pow(abs(M_pmCro),2)
              +2.*real(cmsmu*M_pmSym*conj(M_pmUnc))
              +2.*real(cmsmc*M_pmSym*conj(M_pmCro))
              +2.*real(cmumc*M_pmUnc*conj(M_pmCro)));
 
   double amp_pp = real(cmsms*pow(abs(M_ppSym),2)
              +cmumu*pow(abs(M_ppUnc),2)
              +cmcmc*pow(abs(M_ppCro),2)
              +2.*real(cmsmu*M_ppSym*conj(M_ppUnc))
              +2.*real(cmsmc*M_ppSym*conj(M_ppCro))
              +2.*real(cmumc*M_ppUnc*conj(M_ppCro)));
 
   double amp=((amp_mm+amp_mp+amp_pm+amp_pp)/(9.*4.));
 
   HLV q1,q3;
   q1=pa;
-  for(int i=0;i<nabove+1;i++){
+  for(int i=0;i<nabove+1;++i){
     q1-=partons.at(i);
   }
   q3 = q1 - pq - pqbar - pl - plbar;
 
   double t1 = (q1).m2();
   double t3 = (q3).m2();
 
   //Divide by t-channels
   amp/=(t1*t1*t3*t3);
 
   //Divide by WProp
   amp*=WProp(plbar, pl, wprop);
 
   return amp;
 }
 
 // no wqq emission
 double ME_W_Cenqqx_qq(HLV pa, HLV pb,HLV pl,HLV plbar, std::vector<HLV> partons,
                       bool aqlinepa, bool aqlinepb, bool qqxmarker, int nabove,
                       int nbelow, bool forwards, ParticleProperties const & wprop
 ){
   using helicity::minus;
   using helicity::plus;
 
   init_sigma_index();
 
   if (!forwards){ //If Emission from Leg a instead, flip process.
     std::swap(pa, pb);
     std::reverse(partons.begin(),partons.end());
     std::swap(aqlinepa, aqlinepb);
     qqxmarker = !qqxmarker;
     std::swap(nabove,nbelow);
   }
 
   HLV pq, pqbar, p1,p4;
   if (qqxmarker){
     pqbar = partons[nabove+1];
     pq = partons[nabove+2];}
   else{
     pq = partons[nabove+1];
     pqbar = partons[nabove+2];}
 
   p1 = partons.front();
   p4 = partons.back();
 
   Tensor<1> T1am(0.), T1ap(0.);
   if(!(aqlinepa)){
     T1ap = HEJ::current(p1, pa, plus);
     T1am = HEJ::current(p1, pa, minus);}
   else if(aqlinepa){
     T1ap = HEJ::current(pa, p1, plus);
     T1am = HEJ::current(pa, p1, minus);}
 
   Tensor <1> T4bm = jW(pb, p4, plbar, pl, aqlinepb?plus:minus);
 
   // Calculate the 3 separate contributions to the effective vertex
   Tensor<2> Xunc_m = MUncross(pa, pq, pqbar,partons, minus, nabove);
   Tensor<2> Xcro_m = MCross(  pa, pq, pqbar,partons, minus, nabove);
   Tensor<2> Xsym_m = MSym(    pa, p1, pb, p4, pq, pqbar, partons, minus, nabove);
 
   Tensor<2> Xunc_p = MUncross(pa, pq, pqbar,partons, plus, nabove);
   Tensor<2> Xcro_p = MCross(  pa, pq, pqbar,partons, plus, nabove);
   Tensor<2> Xsym_p = MSym(    pa, p1, pb, p4, pq, pqbar, partons, plus, nabove);
 
   // (- - hel choice)
   COM M_mmUnc = (((Xunc_m).contract(T1am,1)).contract(T4bm,1));
   COM M_mmCro = (((Xcro_m).contract(T1am,1)).contract(T4bm,1));
   COM M_mmSym = (((Xsym_m).contract(T1am,1)).contract(T4bm,1));
   // (- + hel choice)
   COM M_mpUnc = (((Xunc_p).contract(T1am,1)).contract(T4bm,1));
   COM M_mpCro = (((Xcro_p).contract(T1am,1)).contract(T4bm,1));
   COM M_mpSym = (((Xsym_p).contract(T1am,1)).contract(T4bm,1));
   // (+ - hel choice)
   COM M_pmUnc = (((Xunc_m).contract(T1ap,1)).contract(T4bm,1));
   COM M_pmCro = (((Xcro_m).contract(T1ap,1)).contract(T4bm,1));
   COM M_pmSym = (((Xsym_m).contract(T1ap,1)).contract(T4bm,1));
   // (+ + hel choice)
   COM M_ppUnc = (((Xunc_p).contract(T1ap,1)).contract(T4bm,1));
   COM M_ppCro = (((Xcro_p).contract(T1ap,1)).contract(T4bm,1));
   COM M_ppSym = (((Xsym_p).contract(T1ap,1)).contract(T4bm,1));
 
   //Colour factors:
   COM cmsms,cmumu,cmcmc,cmsmu,cmsmc,cmumc;
   cmsms=3.;
   cmumu=4./3.;
   cmcmc=4./3.;
   cmsmu =3./2.*COM(0.,1.);
   cmsmc = -3./2.*COM(0.,1.);
   cmumc = -1./6.;
 
   // Work Out Interference in each case of helicity:
   double amp_mm = real(cmsms*pow(abs(M_mmSym),2)
              +cmumu*pow(abs(M_mmUnc),2)
              +cmcmc*pow(abs(M_mmCro),2)
              +2.*real(cmsmu*M_mmSym*conj(M_mmUnc))
              +2.*real(cmsmc*M_mmSym*conj(M_mmCro))
              +2.*real(cmumc*M_mmUnc*conj(M_mmCro)));
 
   double amp_mp = real(cmsms*pow(abs(M_mpSym),2)
              +cmumu*pow(abs(M_mpUnc),2)
              +cmcmc*pow(abs(M_mpCro),2)
              +2.*real(cmsmu*M_mpSym*conj(M_mpUnc))
              +2.*real(cmsmc*M_mpSym*conj(M_mpCro))
              +2.*real(cmumc*M_mpUnc*conj(M_mpCro)));
 
   double amp_pm = real(cmsms*pow(abs(M_pmSym),2)
              +cmumu*pow(abs(M_pmUnc),2)
              +cmcmc*pow(abs(M_pmCro),2)
              +2.*real(cmsmu*M_pmSym*conj(M_pmUnc))
              +2.*real(cmsmc*M_pmSym*conj(M_pmCro))
              +2.*real(cmumc*M_pmUnc*conj(M_pmCro)));
 
   double amp_pp = real(cmsms*pow(abs(M_ppSym),2)
              +cmumu*pow(abs(M_ppUnc),2)
              +cmcmc*pow(abs(M_ppCro),2)
              +2.*real(cmsmu*M_ppSym*conj(M_ppUnc))
              +2.*real(cmsmc*M_ppSym*conj(M_ppCro))
              +2.*real(cmumc*M_ppUnc*conj(M_ppCro)));
 
   double amp=((amp_mm+amp_mp+amp_pm+amp_pp)/(9.*4.));
 
   HLV q1,q3;
   q1=pa;
-  for(int i=0;i<nabove+1;i++){
+  for(int i=0;i<nabove+1;++i){
     q1-=partons.at(i);
   }
   q3 = q1 - pq - pqbar;
 
   double t1 = (q1).m2();
   double t3 = (q3).m2();
 
   //Divide by t-channels
   amp/=(t1*t1*t3*t3);
 
   //Divide by WProp
   amp*=WProp(plbar, pl, wprop);
 
   return amp;
 }