diff --git a/include/RHEJ/MatrixElement.hh b/include/RHEJ/MatrixElement.hh
index d70102b..6f4a46b 100644
--- a/include/RHEJ/MatrixElement.hh
+++ b/include/RHEJ/MatrixElement.hh
@@ -1,225 +1,219 @@
 /** \file
  *  \brief Contains the MatrixElement Class
  */
 #pragma once
 
 #include <functional>
 
 #include "RHEJ/config.hh"
 #include "RHEJ/utility.hh"
 #include "RHEJ/HiggsCouplingSettings.hh"
 
 #include "CLHEP/Vector/LorentzVector.h"
+typedef CLHEP::HepLorentzVector HLV;
 
 
 namespace RHEJ{
 
   //! Class to calculate the squares of matrix elements
   class MatrixElement{
   public:
     /** \brief MatrixElement Constructor
      * @param alpha_s        Function taking the renormalisation scale
      *                       and returning the strong coupling constant
      * @param conf           General matrix element settings
      */
     MatrixElement(
         std::function<double (double)> alpha_s,
         MatrixElementConfig conf
     );
 
   /**
    * \brief regulated HEJ matrix element
    * @param mur            Value of the renormalisation scale
    * @param incoming       Incoming particles
    * @param outgoing       Outgoing particles
    * @param check_momenta  Special treatment for partons inside extremal jets
    * @returns              The HEJ matrix element including virtual corrections
    *
    * cf. eq. (22) in \cite Andersen:2011hs
    * Incoming particles should be ordered by ascending z momentum.
    * Outgoing particles should be ordered by ascending rapidity.
    *
    * \internal Relation to standard HEJ Met2: MatrixElement = Met2*shat^2/(pdfta*pdftb)
    */
     double operator()(
         double mur,
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> const & outgoing,
         std::unordered_map<int, std::vector<Particle>> const & decays,
         bool check_momenta
     ) const;
 
   //! HEJ tree-level matrix element
   /**
    * @param mur            Value of the renormalisation scale
    * @param incoming       Incoming particles
    * @param outgoing       Outgoing particles
    * @param check_momenta  Special treatment for partons inside extremal jets
    * @returns              The HEJ matrix element without virtual corrections
    *
    * cf. eq. (22) in \cite Andersen:2011hs
    * Incoming particles should be ordered by ascending z momentum.
    * Outgoing particles should be ordered by ascending rapidity.
    */
     double tree(
         double mur,
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> const & outgoing,
         std::unordered_map<int, std::vector<Particle>> const & decays,
         bool check_momenta
     ) const;
 
   //! HEJ tree-level matrix element - parametric part
   /**
    * @param mur            Value of the renormalisation scale
    * @param incoming       Incoming particles
    * @param outgoing       Outgoing particles
    * @returns              The parametric part of the tree matrix element
    *
    * cf. eq. (22) in \cite Andersen:2011hs
    *
    * The tree level matrix element factorises into a parametric part
    * which depends on the theory parameters (alpha_s and scale)
    * and a kinematic part comprising the dependence on the particle momenta
    * and colour factors. This function returns the former.
    */
     double tree_param(
         double mur,
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> const & outgoing
     ) const;
 
   //! HEJ tree-level matrix element - kinematic part
   /**
    * @param incoming       Incoming particles
    * @param outgoing       Outgoing particles
    * @param check_momenta  Special treatment for partons inside extremal jets
    * @returns              The kinematic part of the tree matrix element
    *
    * cf. eq. (22) in \cite Andersen:2011hs
    * Incoming particles should be ordered by ascending z momentum.
    * Outgoing particles should be ordered by ascending rapidity.
    *
    * The tree level matrix element factorises into a parametric part
    * which depends on the theory parameters (alpha_s and scale)
    * and a kinematic part comprising the dependence on the particle momenta
    * and colour factors. This function returns the latter.
    */
     double tree_kin(
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> const & outgoing,
         std::unordered_map<int, std::vector<Particle>> const & decays,
         bool check_momenta
     ) const;
 
    /**
     * \brief Calculates the Virtual Corrections
     * @param mur            Value of the renormalisation scale
     * @param in             Incoming particles
     * @param out            Outgoing particles
     * @returns              The Virtual Corrections of the Matrix Element
     *
     * Incoming particles should be ordered by ascending z momentum.
     * Outgoing particles should be ordered by ascending rapidity.
     *
     * The all order virtual corrections to LL in the MRK limit is
     * given by replacing 1/t in the scattering amplitude according to the
     * lipatov ansatz.
     *
     * cf. second-to-last line of eq. (22) in \cite Andersen:2011hs
     * note that indices are off by one, i.e. out[0].p corresponds to p_1
     */
     double virtual_corrections(
         double mur,
         std::array<Particle, 2> const & in,
         std::vector<Particle> const & out
     ) const;
 
   private:
     //! \internal cf. last line of eq. (22) in \cite Andersen:2011hs
     double omega0(
         double alpha_s, double mur,
         fastjet::PseudoJet const & q_j, double lambda
     ) const;
 
     double tree_kin_jets(
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> partons,
         bool check_momenta
     ) const;
     double tree_kin_W(
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> const & outgoing,
         std::unordered_map<int, std::vector<Particle>> const & decays,
         bool WPlus,
         bool check_momenta
     ) const;
-    double tree_kin_W_FKL(
-        std::array<Particle, 2> const & incoming,
-        std::vector<Particle> const & outgoing,
-        std::unordered_map<int, std::vector<Particle>> const & decays,
-        bool WPlus,
-        bool check_momenta
-    ) const;
     double tree_kin_Higgs(
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> const & outgoing,
         bool check_momenta
     ) const;
     double tree_kin_Higgs_first(
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> const & outgoing,
         bool check_momenta
     ) const;
     double tree_kin_Higgs_last(
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> const & outgoing,
         bool check_momenta
     ) const;
 
     /**
      * \internal
      * \brief Higgs inbetween extremal partons.
      *
      * Note that in the case of unordered emission, the Higgs is *always*
      * treated as if in between the extremal (FKL) partons, even if its
      * rapidity is outside the extremal parton rapidities
      */
     double tree_kin_Higgs_between(
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> const & outgoing,
         bool check_momenta
     ) const;
 
 
     double tree_param_partons(
         double alpha_s, double mur,
         std::vector<Particle> const & partons
     ) const;
 
 
     std::vector<int> in_extremal_jet_indices(
         std::vector<fastjet::PseudoJet> const & partons
     ) const;
 
 
     std::vector<Particle> tag_extremal_jet_partons(
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> out_partons, bool check_momenta
     ) const;
 
     double MH2_forwardH(
         CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
         pid::ParticleID type2,
         CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
         CLHEP::HepLorentzVector pH,
         double t1, double t2
     ) const;
 
     std::function<double (double)> alpha_s_;
 
     MatrixElementConfig param_;
   };
 
 
 }
diff --git a/include/RHEJ/currents.hh b/include/RHEJ/currents.hh
index 4c86079..5c3f795 100644
--- a/include/RHEJ/currents.hh
+++ b/include/RHEJ/currents.hh
@@ -1,1325 +1,1350 @@
 //////////////////////////////////////////////////
 //////////////////////////////////////////////////
 // This source code is Copyright (2012) of      //
 //  Jeppe R. Andersen and Jennifer M. Smillie   //
 // and is distributed under the                 //
 // Gnu Public License version 2                 //
 // http://www.gnu.org/licenses/gpl-2.0.html     //
 // You are allowed to distribute and alter the  //
 // source under the conditions of the GPLv2     //
 // as long as this copyright notice             //
 // is unaltered and distributed with the source //
 // Any use should comply with the               //
 //             MCNET GUIDELINES                 //
 //    for Event Generator Authors and Users     //
 // as distributed with this source code         //
 //////////////////////////////////////////////////
 //////////////////////////////////////////////////
 
 /** \file
  *  \brief Functions computing the square of current contractions.
  *
  *  This file contains all the necessary functions to compute the current
  *  contractions for all valid HEJ processes. PJETS, H+JETS and W+JETS along with
  *  some unordered counterparts.
  *
  *  @TODO add a namespace
  */
 
 
 #pragma once
 
 #include <CLHEP/Vector/LorentzVector.h>
 #include <complex>
 #include <vector>
 #include <valarray>
 #include <limits>
 
 
 typedef std::complex<double> COM;
 typedef COM current[4];
 typedef CLHEP::HepLorentzVector HLV;
 
 //! The Higgs field vacuum expectation value in GeV
 static constexpr double v = 246.;
 
 constexpr double infinity = std::numeric_limits<double>::infinity();
 constexpr double mb_default = 4.7;
 
 void Setup_Currents(void);
 
 
 //! Square of qQ->qenuQ W+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state quark
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state quark
  *  @param p2out                Momentum of final state quark
  *  @param p2in                 Momentum of intial state quark
  *  @returns                    Square of the current contractions for qQ->qenuQ Scattering
  *
  *  This returns the square of the current contractions in qQ->qenuQ scattering
  *  with an emission of a W Boson.
  */
 double jMWqQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe,
               CLHEP::HepLorentzVector pnu,   CLHEP::HepLorentzVector p1in,
               CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 
 //! Square of qbarQ->qbarenuQ W+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state anti-quark
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param p2out                Momentum of final state quark
  *  @param p2in                 Momentum of intial state quark
  *  @returns                    Square of the current contractions for qbarQ->qbarenuQ Scattering
  *
  *  This returns the square of the current contractions in qbarQ->qbarenuQ scattering
  *  with an emission of a W Boson.
  */
 double jMWqbarQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe,
                  CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in,
                  CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 
 //! Square of qQbar->qenuQbar W+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state quark
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state quark
  *  @param p2out                Momentum of final state anti-quark
  *  @param p2in                 Momentum of intial state anti-quark
  *  @returns                    Square of the current contractions for qQbar->qenuQbar Scattering
  *
  *  This returns the square of the current contractions in qQbar->qenuQbar scattering
  *  with an emission of a W Boson.
  */
 double jMWqQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe,
                  CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in,
                  CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 
 //! Square of qbarQbar->qbarenuQbar W+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state anti-quark
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param p2out                Momentum of final state anti-quark
  *  @param p2in                 Momentum of intial state anti-quark
  *  @returns                    Square of the current contractions for qbarQbar->qbarenuQbar Scattering
  *
  *  This returns the square of the current contractions in qbarQbar->qbarenuQbar scattering
  *  with an emission of a W Boson.
  */
 double jMWqbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe,
                     CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in,
                     CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 //! Square of qg->qenug W+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state quark
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state quark
  *  @param p2out                Momentum of final state gluon
  *  @param p2in                 Momentum of intial state gluon
  *  @returns                    Square of the current contractions for qg->qenug Scattering
  *
  *  This returns the square of the current contractions in qg->qenug scattering
  *  with an emission of a W Boson.
  */
 double jMWqg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe,
               CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in,
               CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 //! Square of qbarg->qbarenug W+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state anti-quark
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param p2out                Momentum of final state gluon
  *  @param p2in                 Momentum of intial state gluon
  *  @returns                    Square of the current contractions for qbarg->qbarenug Scattering
  *
  *  This returns the square of the current contractions in qbarg->qbarenug scattering
  *  with an emission of a W Boson.
  */
 double jMWqbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe,
                  CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in,
                  CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 
 // W+Jets Unordered Functions
 
 //! qQg Wjets Unordered backwards opposite leg to W
 /**
  *  @param p1out                Momentum of final state quark a
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state quark a
  *  @param p2out                Momentum of final state quark b
  *  @param p2in                 Momentum of intial state quark b
  *  @param pg                   Momentum of final state unordered gluon
  *  @returns                    Square of the current contractions for qQ->qQg Scattering
  *
  *  This returns the square of the current contractions in qQg->qQg scattering
  *  with an emission of a W Boson.
  */
 double junobMWqQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg);
 
 //! qbarQg Wjets Unordered backwards opposite leg to W
 /**
  *  @param p1out                Momentum of final state anti-quark a
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state anti-quark a
  *  @param p2out                Momentum of final state quark b
  *  @param p2in                 Momentum of intial state quark b
  *  @param pg                   Momentum of final state unordered gluon
  *  @returns                    Square of the current contractions for qbarQ->qbarQg Scattering
  *
  *  This returns the square of the current contractions in qbarQg->qbarQg scattering
  *  with an emission of a W Boson.
  */
 double junobMWqbarQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg);
 
 
 
 //! qQbarg Wjets Unordered backwards opposite leg to W
 /**
  *  @param p1out                Momentum of final state quark a
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state quark a
  *  @param p2out                Momentum of final state anti-quark b
  *  @param p2in                 Momentum of intial state anti-quark b
  *  @param pg                   Momentum of final state unordered gluon
  *  @returns                    Square of the current contractions for qQbar->qQbarg Scattering
  *
  *  This returns the square of the current contractions in qQbarg->qQbarg scattering
  *  with an emission of a W Boson.
  */
 double junobMWqQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg);
 
 //! qbarQbarg Wjets Unordered backwards opposite leg to W
 /**
  *  @param p1out                Momentum of final state anti-quark a
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state anti-quark a
  *  @param p2out                Momentum of final state anti-quark b
  *  @param p2in                 Momentum of intial state anti-quark b
  *  @param pg                   Momentum of final state unordered gluon
  *  @returns                    Square of the current contractions for qbarQbar->qbarQbarg Scattering
  *
  *  This returns the square of the current contractions in qbarQbarg->qbarQbarg scattering
  *  with an emission of a W Boson.
  */
 double junobMWqbarQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg);
 
 
 //!Wjets Unordered forwards opposite leg to W
 /**
  *  @param pg                   Momentum of final state unordered gluon
  *  @param p1out                Momentum of final state quark a
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state quark a
  *  @param p2out                Momentum of final state quark b
  *  @param p2in                 Momentum of intial state quark b
  *  @returns                    Square of the current contractions for qQ->gqQ Scattering
  *
  *  This returns the square of the current contractions in qQg->gqQ scattering
  *  with an emission of a W Boson.
  */
 double junofMWgqQ (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in);
 
 //!Wjets Unordered forwards opposite leg to W
 /**
  *  @param pg                   Momentum of final state unordered gluon
  *  @param p1out                Momentum of final state anti-quark a
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state anti-quark a
  *  @param p2out                Momentum of final state quark b
  *  @param p2in                 Momentum of intial state quark b
  *  @returns                    Square of the current contractions for qbarQ->gqbarQ Scattering
  *
  *  This returns the square of the current contractions in qbarQg->gqbarQ scattering
  *  with an emission of a W Boson.
  */
 double junofMWgqbarQ (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in);
 
 //!Wjets Unordered forwards opposite leg to W
 /**
  *  @param pg                   Momentum of final state unordered gluon
  *  @param p1out                Momentum of final state quark a
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state quark a
  *  @param p2out                Momentum of final state anti-quark b
  *  @param p2in                 Momentum of intial state anti-quark b
  *  @returns                    Square of the current contractions for qQbar->gqQbar Scattering
  *
  *  This returns the square of the current contractions in qQbarg->gqQbar scattering
  *  with an emission of a W Boson.
  */
 double junofMWgqQbar (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in);
 
 //!Wjets Unordered forwards opposite leg to W
 /**
  *  @param pg                   Momentum of final state unordered gluon
  *  @param p1out                Momentum of final state anti-quark a
  *  @param pe                   Momentum of final state electron
  *  @param pnu                  Momentum of final state Neutrino
  *  @param p1in                 Momentum of initial state anti-quark a
  *  @param p2out                Momentum of final state anti-quark b
  *  @param p2in                 Momentum of intial state anti-quark b
  *  @returns                    Square of the current contractions for qbarQbar->gqbarQbar Scattering
  *
  *  This returns the square of the current contractions in qbarQbarg->gqbarQbar scattering
  *  with an emission of a W Boson.
  */
 double junofMWgqbarQbar (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in);
 
 //!W+uno same leg
 /**
  *  @param pg                   Momentum of final state unordered gluon
  *  @param p1out                Momentum of final state quark a
  *  @param plbar                Momentum of final state anti-lepton
  *  @param pl                   Momentum of final state lepton
  *  @param p1in                 Momentum of initial state quark a
  *  @param p2out                Momentum of final state quark b
  *  @param p2in                 Momentum of intial state quark b
  *  @returns                    Square of the current contractions for qQ->qQg Scattering
  *
  *  This returns the square of the current contractions in gqQ->gqQ scattering
  *  with an emission of a W Boson.
  */
 double jM2WunogqQ(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 //! @TODO What does this function do? Crossed contribution is Exqqx..?
 /**
  *  @param pg                   Momentum of final state unordered gluon
  *  @param p1out                Momentum of final state quark a
  *  @param plbar                Momentum of final state anti-lepton
  *  @param pl                   Momentum of final state lepton
  *  @param p1in                 Momentum of initial state quark a
  *  @param p2out                Momentum of final state quark b
  *  @param p2in                 Momentum of intial state quark b
  *  @returns                    Square of the current contractions for qQ->gqQ Scattering
  *
  *  This returns the square of the current contractions in gqQ->gqQ scattering
  *  with an emission of a W Boson.
  */
 double jM2WunogqQ_crossqQ(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 //! W+uno same leg. quark anti-quark
 /**
  *  @param pg                   Momentum of final state unordered gluon
  *  @param p1out                Momentum of final state quark a
  *  @param plbar                Momentum of final state anti-lepton
  *  @param pl                   Momentum of final state lepton
  *  @param p1in                 Momentum of initial state quark a
  *  @param p2out                Momentum of final state anti-quark b
  *  @param p2in                 Momentum of intial state anti-quark b
  *  @returns                    Square of the current contractions for qQbar->gqQbar Scattering
  *
  *  This returns the square of the current contractions in gqQbar->gqQbar scattering
  *  with an emission of a W Boson. (Unordered Same Leg)
  */
 double jM2WunogqQbar(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 //! W+uno same leg. quark gluon
 /**
  *  @param pg                   Momentum of final state unordered gluon
  *  @param p1out                Momentum of final state quark a
  *  @param plbar                Momentum of final state anti-lepton
  *  @param pl                   Momentum of final state lepton
  *  @param p1in                 Momentum of initial state quark a
  *  @param p2out                Momentum of final state gluon b
  *  @param p2in                 Momentum of intial state gluon b
  *  @returns                    Square of the current contractions for qg->gqg Scattering
  *
  *  This returns the square of the current contractions in qg->gqg scattering
  *  with an emission of a W Boson.
  */
 double jM2Wunogqg(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 //! W+uno same leg. anti-quark quark
 /**
  *  @param pg                   Momentum of final state unordered gluon
  *  @param p1out                Momentum of final state anti-quark a
  *  @param plbar                Momentum of final state anti-lepton
  *  @param pl                   Momentum of final state lepton
  *  @param p1in                 Momentum of initial state anti-quark a
  *  @param p2out                Momentum of final state quark b
  *  @param p2in                 Momentum of intial state quark b
  *  @returns                    Square of the current contractions for qbarQ->gqbarQ Scattering
  *
  *  This returns the square of the current contractions in qbarQ->gqbarQ scattering
  *  with an emission of a W Boson.
  */
 double jM2WunogqbarQ(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 //! W+uno same leg. anti-quark anti-quark
 /**
  *  @param pg                   Momentum of final state unordered gluon
  *  @param p1out                Momentum of final state anti-quark a
  *  @param plbar                Momentum of final state anti-lepton
  *  @param pl                   Momentum of final state lepton
  *  @param p1in                 Momentum of initial state anti-quark a
  *  @param p2out                Momentum of final state anti-quark b
  *  @param p2in                 Momentum of intial state anti-quark b
  *  @returns                    Square of the current contractions for qbarQbar->gqbarQbar Scattering
  *
  *  This returns the square of the current contractions in gqbarQbar->qbarQbar scattering
  *  with an emission of a W Boson.
  */
 double jM2WunogqbarQbar(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 //! W+uno same leg. anti-quark gluon
 /**
  *  @param pg                   Momentum of final state unordered gluon
  *  @param p1out                Momentum of final state anti-quark a
  *  @param plbar                Momentum of final state anti-lepton
  *  @param pl                   Momentum of final state lepton
  *  @param p1in                 Momentum of initial state anti-quark a
  *  @param p2out                Momentum of final state gluon b
  *  @param p2in                 Momentum of intial state gluon b
  *  @returns                    Square of the current contractions for ->gqbarg Scattering
  *
  *  This returns the square of the current contractions in qbarg->gqbarg scattering
  *  with an emission of a W Boson.
  */
 double jM2Wunogqbarg(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 //W+Jets qqxExtremal
 //! W+Extremal qqx. qxqQ
 /**
  *  @param pgin                 Momentum of initial state gluon
  *  @param pqout                Momentum of final state quark a
  *  @param plbar                Momentum of final state anti-lepton
  *  @param pl                   Momentum of final state lepton
  *  @param pqbarout             Momentum of final state anti-quark a
  *  @param p2out                Momentum of initial state anti-quark b
  *  @param p2in                 Momentum of final state gluon b
  *  @returns                    Square of the current contractions for ->qbarqQ Scattering
  *
  *  Calculates the square of the current contractions with extremal qqbar pair
  *  production. This is calculated through the use of crossing symmetry.
  */
 double jM2WgQtoqbarqQ(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqbarout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 //W+Jets qqxExtremal
 //! W+Extremal qqx. qqxQ
 /**
  *  @param pgin                 Momentum of initial state gluon
  *  @param pqout                Momentum of final state quark a
  *  @param plbar                Momentum of final state anti-lepton
  *  @param pl                   Momentum of final state lepton
  *  @param pqbarout             Momentum of final state anti-quark a
  *  @param p2out                Momentum of initial state anti-quark b
  *  @param p2in                 Momentum of final state gluon b
  *  @returns                    Square of the current contractions for ->qqbarQ Scattering
  *
  *  Calculates the square of the current contractions with extremal qqbar pair
  *  production. This is calculated through the use of crossing symmetry.
  */
 double jM2WgQtoqqbarQ(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqbarout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 //W+Jets qqxExtremal
 //! W+Extremal qqx. gg->qxqg
 /**
  *  @param pgin                 Momentum of initial state gluon
  *  @param pqout                Momentum of final state quark a
  *  @param plbar                Momentum of final state anti-lepton
  *  @param pl                   Momentum of final state lepton
  *  @param pqbarout             Momentum of final state anti-quark a
  *  @param p2out                Momentum of initial state gluon b
  *  @param p2in                 Momentum of final state gluon b
  *  @returns                    Square of the current contractions for gg->qbarqg Scattering
  *
  *  Calculates the square of the current contractions with extremal qqbar pair
  *  production. This is calculated through the use of crossing symmetry.
  */
 double jM2Wggtoqbarqg(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqbarout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 //W+Jets qqxExtremal
 //! W+Extremal qqx. gg->qqxg
 /**
  *  @param pgin                 Momentum of initial state gluon
  *  @param pqout                Momentum of final state quark a
  *  @param plbar                Momentum of final state anti-lepton
  *  @param pl                   Momentum of final state lepton
  *  @param pqbarout             Momentum of final state anti-quark a
  *  @param p2out                Momentum of initial state gluon a
  *  @param p2in                 Momentum of final state gluon b
  *  @returns                    Square of the current contractions for gg->qqbarg Scattering
  *
  *  Calculates the square of the current contractions with extremal qqbar pair
  *  production. This is calculated through the use of crossing symmetry.
  */
 double jM2Wggtoqqbarg(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqbarout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
+//W+Jets qqxExtremal, W emission from opposite leg
+//! W+Extremal qqx. gg->qqxg. qqx on forwards leg, W emission backwards leg.
+/**
+ *  @param pa                   Momentum of initial state (anti-)quark
+ *  @param pb                   Momentum of initial state gluon
+ *  @param p1                   Momentum of final state (anti-)quark (after W emission)
+ *  @param p2                   Momentum of final state anti-quark
+ *  @param p3                   Momentum of final state quark
+ *  @param plbar                Momentum of final state anti-lepton
+ *  @param pl                   Momentum of final state lepton
+ *  @returns                    Square of the current contractions for gq->qqbarqW Scattering
+ *
+ *  Calculates the square of the current contractions with extremal qqbar pair
+ *  production. This is calculated via current contraction of existing currents.
+ *  Assumes qqx split from forwards leg, W emission from backwards leg.
+ *  Switch input (pa<->pb, p1<->pn) if calculating forwards qqx.
+ */
+double jM2WgqtoQQqW(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb, CLHEP::HepLorentzVector p1,  CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p3,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl);
+
 //! W+Jets qqxCentral. qqx W emission.
 /**
  *  @param pa                Momentum of initial state particle a
  *  @param pb                Momentum of initial state particle b
  *  @param pl                Momentum of final state lepton
  *  @param plbar             Momentum of final state anti-lepton
  *  @param partons           Vector of outgoing parton momenta
  *  @param aqlinepa          Bool: True= pa is anti-quark
  *  @param aqlinepb          Bool: True= pb is anti-quark
  *  @param qqxmarker         Bool: Ordering of the qqbar pair produced (qqx vs qxq)
  *  @param nabove            Number of lipatov vertices "above" qqbar pair
  *  @param nbelow            Number of lipatov vertices "below" qqbar pair
  *  @returns                 Square of the current contractions for qq>qQQbarWq Scattering
  *
  *  Calculates the square of the current contractions with extremal qqbar pair
  *  production. This is calculated through the use of crossing symmetry.
  */
-double jM2WqqtoqQQq(HLV pa, HLV pb,HLV pl,HLV plbar, std::vector<HLV> partons, bool aqlinepa, bool aqlinepb, bool qqxmarker, int nabove, int nbelow); //Doing
+double jM2WqqtoqQQq(HLV pa, HLV pb,HLV pl,HLV plbar, std::vector<HLV> partons, bool aqlinepa, bool aqlinepb, bool qqxmarker, int nabove);
 //emission from backwards leg
 
 //! W+Jets qqxCentral. W emission from backwards leg.
 /**
  *  @param ka                HLV: Momentum of initial state particle a
  *  @param kb                HLV: Momentum of initial state particle b
  *  @param pl                HLV: Momentum of final state lepton
  *  @param plbar             HLV: Momentum of final state anti-lepton
  *  @param partons           Vector(HLV): outgoing parton momenta
  *  @param aqlinepa          Bool: True= pa is anti-quark
  *  @param aqlinepb          Bool: True= pb is anti-quark
  *  @param qqxmarker         Bool: Ordering of the qqbar pair produced (qqx vs qxq)
  *  @param nabove            Int: Number of lipatov vertices "above" qqbar pair
  *  @param nbelow            Int: Number of lipatov vertices "below" qqbar pair
  *  @param forwards          Bool: Swap to emission off front leg TODO:remove so args can be const
  *  @returns                 Square of the current contractions for qq>qQQbarWq Scattering
  *
  *  Calculates the square of the current contractions with extremal qqbar pair
  *  production. This is calculated through the use of crossing symmetry.
  */
 double jM2WqqtoqQQqW(HLV ka, HLV kb,HLV pl,HLV plbar, std::vector<HLV> partons, bool aqlinepa, bool aqlinepb, bool qqxmarker, int nabove, int nbelow, bool forwards); //Doing
 
 
 
 //! Square of qQ->qQ Pure Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state quark
  *  @param p1in                 Momentum of initial state quark
  *  @param p2out                Momentum of final state quark
  *  @param p2in                 Momentum of intial state quark
  *  @returns                    Square of the current contractions for qQ->qQ Scattering
  *
  *  This returns the square of the current contractions in qQ->qQ Pure Jet Scattering.
  */
 double jM2qQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
               CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 
 //! Square of qQbar->qQbar Pure Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state quark
  *  @param p1in                 Momentum of initial state quark
  *  @param p2out                Momentum of final state anti-quark
  *  @param p2in                 Momentum of intial state anti-quark
  *  @returns                    Square of the current contractions for qQbar->qQbar Scattering
  *
  *  This returns the square of the current contractions in qQbar->qQbar Pure Jet Scattering.
  *  Note this can be used for qbarQ->qbarQ Scattering by inputting arguments appropriately.
  */
 double jM2qQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                  CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 
 //! Square of qbarQbar->qbarQbar Pure Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state anti-quark
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param p2out                Momentum of final state anti-quark
  *  @param p2in                 Momentum of intial state anti-quark
  *  @returns                    Square of the current contractions for qbarQbar->qbarQbar Scattering
  *
  *  This returns the square of the current contractions in qbarQbar->qbarQbar Pure Jet Scattering.
  */
 double jM2qbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                     CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 
 //! Square of qg->qg Pure Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state quark
  *  @param p1in                 Momentum of initial state quark
  *  @param p2out                Momentum of final state gluon
  *  @param p2in                 Momentum of intial state gluon
  *  @returns                    Square of the current contractions for qg->qg Scattering
  *
  *  This returns the square of the current contractions in qg->qg Pure Jet Scattering.
  *  Note this can be used for gq->gq Scattering by inputting arguments appropriately.
  */
 double jM2qg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
               CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 
 //! Square of qbarg->qbarg Pure Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state anti-quark
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param p2out                Momentum of final state gluon
  *  @param p2in                 Momentum of intial state gluon
  *  @returns                    Square of the current contractions for qbarg->qbarg Scattering
  *
  *  This returns the square of the current contractions in qbarg->qbarg Pure Jet Scattering.
  *  Note this can be used for gqbar->gqbar Scattering by inputting arguments appropriately.
  */
 double jM2qbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                  CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 
 //! Square of gg->gg Pure Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state gluon
  *  @param p1in                 Momentum of initial state gluon
  *  @param p2out                Momentum of final state gluon
  *  @param p2in                 Momentum of intial state gluon
  *  @returns                    Square of the current contractions for gg->gg Scattering
  *
  *  This returns the square of the current contractions in gg->gg Pure Jet Scattering.
  */
 double jM2gg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
               CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
 
 
 //! Square of gg->gg Higgs+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state gluon
  *  @param p1in                 Momentum of initial state gluon
  *  @param p2out                Momentum of final state gluon
  *  @param p2in                 Momentum of intial state gluon
  *  @param q1                   Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for gg->gg Scattering
  *
  *  This returns the square of the current contractions in gg->gg Higgs+Jet Scattering.
  *
  *  g~p1 g~p2
  *  should be called with q1 meant to be contracted with p2 in first part of vertex
  *  (i.e. if g is backward, q1 is forward)
  */
 double MH2gg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
               CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
               CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
               double mt = infinity,
               bool include_bottom = false, double mb = mb_default);
 
 //! Square of gq->gq Higgs+Jets Scattering Current with Higgs before Gluon
 /**
  *  @param p1out                Momentum of final state gluon
  *  @param p1in                 Momentum of initial state gluon
  *  @param p2out                Momentum of final state gluon
  *  @param p2in                 Momentum of intial state gluon
  *  @param pH                   Momentum of Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contraction
  *
  */
 double MH2gq_outsideH(CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                       CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
                       CLHEP::HepLorentzVector pH,
                       double mt = infinity,
                       bool include_bottom = false, double mb = mb_default);
 
 
 //! Square of qg->qg Higgs+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state quark
  *  @param p1in                 Momentum of initial state quark
  *  @param p2out                Momentum of final state gluon
  *  @param p2in                 Momentum of intial state gluon
  *  @param q1                   Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qg->qg Scattering
  *
  *  This returns the square of the current contractions in qg->qg Higgs+Jet Scattering.
  *
  *  q~p1 g~p2 (i.e. ALWAYS p1 for quark, p2 for gluon)
  *  should be called with q1 meant to be contracted with p2 in first part of vertex
  *  (i.e. if g is backward, q1 is forward)
  */
 double MH2qg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
               CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
               CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
               double mt = infinity,
               bool include_bottom = false, double mb = mb_default);
 
 
 //! Square of qbarg->qbarg Higgs+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state anti-quark
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param p2out                Momentum of final state gluon
  *  @param p2in                 Momentum of intial state gluon
  *  @param q1                   Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qbarg->qbarg Scattering
  *
  *  This returns the square of the current contractions in qbarg->qbarg Higgs+Jet Scattering.
  *
  *  qbar~p1 g~p2 (i.e. ALWAYS p1 for anti-quark, p2 for gluon)
  *  should be called with q1 meant to be contracted with p2 in first part of vertex
  *  (i.e. if g is backward, q1 is forward)
  */
 double MH2qbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                  CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
                  CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
                  double mt = infinity,
                  bool include_bottom = false, double mb = mb_default);
 
 
 //! Square of qQ->qQ Higgs+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state quark
  *  @param p1in                 Momentum of initial state quark
  *  @param p2out                Momentum of final state quark
  *  @param p2in                 Momentum of intial state quark
  *  @param q1                   Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qQ->qQ Scattering
  *
  *  This returns the square of the current contractions in qQ->qQ Higgs+Jet Scattering.
  *
  *  q~p1 Q~p2 (i.e. ALWAYS p1 for quark, p2 for quark)
  *  should be called with q1 meant to be contracted with p2 in first part of vertex
  *  (i.e. if Q is backward, q1 is forward)
  */
 double MH2qQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
               CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
               CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
               double mt = infinity,
               bool include_bottom = false, double mb = mb_default);
 
 //! Square of qQbar->qQbar Higgs+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state quark
  *  @param p1in                 Momentum of initial state quark
  *  @param p2out                Momentum of final state anti-quark
  *  @param p2in                 Momentum of intial state anti-quark
  *  @param q1                   Momentum of t-channel propagator before Higgs
  *  @param qH2                   Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qQ->qQ Scattering
  *
  *  This returns the square of the current contractions in qQbar->qQbar Higgs+Jet Scattering.
  *
  *  q~p1 Qbar~p2 (i.e. ALWAYS p1 for quark, p2 for anti-quark)
  *  should be called with q1 meant to be contracted with p2 in first part of vertex
  *  (i.e. if Qbar is backward, q1 is forward)
  */
 double MH2qQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                  CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
                  CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
                  double mt = infinity,
                  bool include_bottom = false, double mb = mb_default);
 
 //! Square of qbarQ->qbarQ Higgs+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state anti-quark
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param p2out                Momentum of final state quark
  *  @param p2in                 Momentum of intial state quark
  *  @param q1                   Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qbarQ->qbarQ Scattering
  *
  *  This returns the square of the current contractions in qbarQ->qbarQ Higgs+Jet Scattering.
  *
  *  qbar~p1 Q~p2 (i.e. ALWAYS p1 for anti-quark, p2 for quark)
  *  should be called with q1 meant to be contracted with p2 in first part of vertex
  *  (i.e. if Q is backward, q1 is forward)
  */
 double MH2qbarQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                  CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
                  CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
                  double mt = infinity,
                  bool include_bottom = false, double mb = mb_default);
 
 
 //! Square of qbarQbar->qbarQbar Higgs+Jets Scattering Current
 /**
  *  @param p1out                Momentum of final state anti-quark
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param p2out                Momentum of final state anti-quark
  *  @param p2in                 Momentum of intial state anti-quark
  *  @param q1                   Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qbarQbar->qbarQbar Scattering
  *
  *  This returns the square of the current contractions in qbarQbar->qbarQbar Higgs+Jet Scattering.
  *
  *  qbar~p1 Qbar~p2 (i.e. ALWAYS p1 for anti-quark, p2 for anti-quark)
  *  should be called with q1 meant to be contracted with p2 in first part of vertex
  *  (i.e. if Qbar is backward, q1 is forward)
  */
 double MH2qbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                     CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
                     CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
                     double mt = infinity,
                     bool include_bottom = false, double mb = mb_default);
 
 
 // Unordered f
 
 //! Square of qQ->gqQ Higgs+Jets Unordered f Scattering Current
 /**
  *  @param pg                   Momentum of unordered gluon
  *  @param p1out                Momentum of final state quark
  *  @param p1in                 Momentum of initial state quark
  *  @param p2out                Momentum of final state quark
  *  @param p2in                 Momentum of intial state quark
  *  @param qH1                  Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qQ->gqQ Scattering
  *
  *  This returns the square of the current contractions in qQ->gqQ Higgs+Jet Scattering.
  *
  *  This construction is taking rapidity order: pg > p1out >> p2out
  */
 double jM2unogqHQ (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,
                    CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out,
                    CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
                    CLHEP::HepLorentzVector qH2,
                    double mt = infinity,
                    bool include_bottom = false, double mb = mb_default);
 
 
 //! Square of qQbar->gqQbar Higgs+Jets Unordered f Scattering Current
 /**
  *  @param pg                   Momentum of unordered gluon
  *  @param p1out                Momentum of final state quark
  *  @param p1in                 Momentum of initial state quark
  *  @param p2out                Momentum of final state anti-quark
  *  @param p2in                 Momentum of intial state anti-quark
  *  @param qH1                  Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qQbar->gqQbar Scattering
  *
  *  This returns the square of the current contractions in qQbar->gqQbar Higgs+Jet Scattering.
  *
  *  This construction is taking rapidity order: pg > p1out >> p2out
  */
 double jM2unogqHQbar (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,
                       CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out,
                       CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
                       CLHEP::HepLorentzVector qH2,
                       double mt = infinity,
                       bool include_bottom = false, double mb = mb_default);
 
 //! Square of qbarQ->gqbarQ Higgs+Jets Unordered f Scattering Current
 /**
  *  @param pg                   Momentum of unordered gluon
  *  @param p1out                Momentum of final state anti-quark
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param p2out                Momentum of final state quark
  *  @param p2in                 Momentum of intial state quark
  *  @param qH1                  Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qbarQ->gqbarQ Scattering
  *
  *  This returns the square of the current contractions in qbarQ->gqbarQ Higgs+Jet Scattering.
  *
  *  This construction is taking rapidity order: pg > p1out >> p2out
  */
 double jM2unogqbarHQ (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,
                       CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out,
                       CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
                       CLHEP::HepLorentzVector qH2,
                       double mt = infinity,
                       bool include_bottom = false, double mb = mb_default);
 
 //! Square of qbarQbar->gqbarQbar Higgs+Jets Unordered f Scattering Current
 /**
  *  @param pg                   Momentum of unordered gluon
  *  @param p1out                Momentum of final state anti-quark
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param p2out                Momentum of final state anti-quark
  *  @param p2in                 Momentum of intial state anti-quark
  *  @param qH1                  Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qbarQbar->gqbarQbar Scattering
  *
  *  This returns the square of the current contractions in qbarQbar->gqbarQbar Higgs+Jet Scattering.
  *
  *  This construction is taking rapidity order: pg > p1out >> p2out
  */
 double jM2unogqbarHQbar (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,
                          CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out,
                          CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
                          CLHEP::HepLorentzVector qH2,
                          double mt = infinity,
                          bool include_bottom = false, double mb = mb_default);
 
 
 //! Square of qg->gqg Higgs+Jets Unordered f Scattering Current
 /**
  *  @param pg                   Momentum of unordered gluon
  *  @param p1out                Momentum of final state quark
  *  @param p1in                 Momentum of initial state quark
  *  @param p2out                Momentum of final state gluon
  *  @param p2in                 Momentum of intial state gluon
  *  @param qH1                  Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qg->gqg Scattering
  *
  *  This returns the square of the current contractions in qg->gqg Higgs+Jet Scattering.
  *
  *  This construction is taking rapidity order: pg > p1out >> p2out
  */
 double jM2unogqHg (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,
                    CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out,
                    CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
                    CLHEP::HepLorentzVector qH2,
                    double mt = infinity,
                    bool include_bottom = false, double mb = mb_default);
 
 
 //! Square of qbarg->gqbarg Higgs+Jets Unordered f Scattering Current
 /**
  *  @param pg                   Momentum of unordered gluon
  *  @param p1out                Momentum of final state anti-quark
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param p2out                Momentum of final state gluon
  *  @param p2in                 Momentum of intial state gluon
  *  @param qH1                  Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qbarg->gbarg Scattering
  *
  *  This returns the square of the current contractions in qbarg->gqbarg Higgs+Jet Scattering.
  *
  *  This construction is taking rapidity order: pg > p1out >> p2out
  */
 double jM2unogqbarHg (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,
                       CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out,
                       CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
                       CLHEP::HepLorentzVector qH2,
                       double mt = infinity,
                       bool include_bottom = false, double mb = mb_default);
 
 
 //Unordered b
 
 //! Square of qbarQ->qbarQg Higgs+Jets Unordered b Scattering Current
 /**
  *  @param p1out                Momentum of final state anti-quark
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param pg                   Momentum of unordered b gluon
  *  @param p2out                Momentum of final state quark
  *  @param p2in                 Momentum of intial state quark
  *  @param qH1                  Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qbarQ->qbarQg Scattering
  *
  *  This returns the square of the current contractions in qbarQ->qbarQg Higgs+Jet Scattering.
  *
  *  This construction is taking rapidity order: p1out >> p2out > pg
  */
 double jM2unobqbarHQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                        CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out,
                        CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
                        CLHEP::HepLorentzVector qH2,
                        double mt = infinity,
                        bool include_bottom = false, double mb = mb_default);
 
 
 //! Square of qQ->qQg Higgs+Jets Unordered b Scattering Current
 /**
  *  @param p1out                Momentum of final state quark
  *  @param p1in                 Momentum of initial state quark
  *  @param pg                   Momentum of unordered b gluon
  *  @param p2out                Momentum of final state quark
  *  @param p2in                 Momentum of intial state quark
  *  @param qH1                  Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qQ->qQg Scattering
  *
  *  This returns the square of the current contractions in qQ->qQg Higgs+Jet Scattering.
  *
  *  This construction is taking rapidity order: p1out >> p2out > pg
  */
 double jM2unobqHQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                     CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out,
                     CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
                     CLHEP::HepLorentzVector qH2,
                     double mt = infinity,
                     bool include_bottom = false, double mb = mb_default);
 
 
 //! Square of qQbar->qQbarg Higgs+Jets Unordered b Scattering Current
 /**
  *  @param p1out                Momentum of final state quark
  *  @param p1in                 Momentum of initial state quark
  *  @param pg                   Momentum of unordered b gluon
  *  @param p2out                Momentum of final state anti-quark
  *  @param p2in                 Momentum of intial state anti-quark
  *  @param qH1                  Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qQbar->qQbarg Scattering
  *
  *  This returns the square of the current contractions in qQbar->qQbarg Higgs+Jet Scattering.
  *
  *  This construction is taking rapidity order: p1out >> p2out > pg
  */
 double jM2unobqHQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                        CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out,
                        CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
                        CLHEP::HepLorentzVector qH2,
                        double mt = infinity,
                        bool include_bottom = false, double mb = mb_default);
 
 //! Square of qbarQbar->qbarQbarg Higgs+Jets Unordered b Scattering Current
 /**
  *  @param p1out                Momentum of final state anti-quark
  *  @param p1in                 Momentum of initial state anti-quark
  *  @param pg                   Momentum of unordered b gluon
  *  @param p2out                Momentum of final state anti-quark
  *  @param p2in                 Momentum of intial state anti-quark
  *  @param qH1                  Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for qbarQbar->qbarQbarg Scattering
  *
  *  This returns the square of the current contractions in qbarQbar->qbarQbarg Higgs+Jet Scattering.
  *
  *  This construction is taking rapidity order: p1out >> p2out > pg
  */
 double jM2unobqbarHQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                           CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out,
                           CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
                           CLHEP::HepLorentzVector qH2,
                           double mt = infinity,
                           bool include_bottom = false, double mb = mb_default);
 
 
 //! Square of gQbar->gQbarg Higgs+Jets Unordered b Scattering Current
 /**
  *  @param p1out                Momentum of final state gluon
  *  @param p1in                 Momentum of initial state gluon
  *  @param pg                   Momentum of unordered b gluon
  *  @param p2out                Momentum of final state anti-quark
  *  @param p2in                 Momentum of intial state anti-quark
  *  @param qH1                  Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for gQbar->gQbarg Scattering
  *
  *  This returns the square of the current contractions in gQbar->gQbarg Higgs+Jet Scattering.
  *
  *  This construction is taking rapidity order: p1out >> p2out > pg
  */
 double jM2unobgHQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                        CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out,
                        CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
                        CLHEP::HepLorentzVector qH2,
                        double mt = infinity,
                        bool include_bottom = false, double mb = mb_default);
 
 //! Square of gQ->gQg Higgs+Jets Unordered b Scattering Current
 /**
  *  @param p1out                Momentum of final state gluon
  *  @param p1in                 Momentum of initial state gluon
  *  @param pg                   Momentum of unordered b gluon
  *  @param p2out                Momentum of final state quark
  *  @param p2in                 Momentum of intial state quark
  *  @param qH1                  Momentum of t-channel propagator before Higgs
  *  @param qH2                  Momentum of t-channel propagator after Higgs
  *  @param mt                   Top quark mass
  *  @param include_bottom       Specifies whether bottom corrections are included
  *  @param mb                   Bottom quark mass
  *  @returns                    Square of the current contractions for gQ->gQg Scattering
  *
  *  This returns the square of the current contractions in gQ->gQg Higgs+Jet Scattering.
  *
  *  This construction is taking rapidity order: p1out >> p2out > pg
  */
 double jM2unobgHQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
                     CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out,
                     CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
                     CLHEP::HepLorentzVector qH2,
                     double mt = infinity,
                     bool include_bottom = false, double mb = mb_default);
 
 // impact factors for Higgs + jet
 
 
 //! Implements Eq. (4.22) in hep-ph/0301013 with modifications to incoming plus momenta
 /**
  * @param p2               Momentum of Particle 2
  * @param p1               Momentum of Particle 1
  * @param pH               Momentum of Higgs
  * @returns                Value of Eq. (4.22) in Hep-ph/0301013 with modifications
  *
  *  This gives the impact factor. First it determines first whether this is the case
  *  p1p\sim php>>p3p or the opposite
  */
 double C2gHgm(CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p1,
               CLHEP::HepLorentzVector pH);
 
 
 //! Implements Eq. (4.23) in hep-ph/0301013 with modifications to incoming plus momenta
 /**
  * @param p2               Momentum of Particle 2
  * @param p1               Momentum of Particle 1
  * @param pH               Momentum of Higgs
  * @returns                Value of Eq. (4.23) in Hep-ph/0301013
  *
  *  This gives the impact factor. First it determines first whether this is the case
  *  p1p\sim php>>p3p or the opposite
  */
 double C2gHgp(CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p1,
               CLHEP::HepLorentzVector pH);
 
 
 //! Implements Eq. (4.22) in hep-ph/0301013
 /**
  * @param p2               Momentum of Particle 2
  * @param p1               Momentum of Particle 1
  * @param pH               Momentum of Higgs
  * @returns                Value of Eq. (4.22) in Hep-ph/0301013
  *
  *  This gives the impact factor. First it determines first whether this is the case
  *  p1p\sim php>>p3p or the opposite
  */
 double C2qHqm(CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p1,
               CLHEP::HepLorentzVector pH);
 
 /** \class CCurrent currents.hh "include/RHEJ/currents.hh"
  *  \brief This is the a new class structure for currents.
  */
 class CCurrent
 {
 public:
     CCurrent(COM sc0, COM sc1, COM sc2, COM sc3)
     :c0(sc0),c1(sc1),c2(sc2),c3(sc3)
     {};
     CCurrent(const CLHEP::HepLorentzVector p)
     {
         c0=p.e();
         c1=p.px();
         c2=p.py();
         c3=p.pz();
     };
     CCurrent()
     {};
     CCurrent operator+(const CCurrent& other);
     CCurrent operator-(const CCurrent& other);
     CCurrent operator*(const double x);
     CCurrent operator*(const COM x);
     CCurrent operator/(const double x);
     CCurrent operator/(const COM x);
 
     friend std::ostream& operator<<(std::ostream& os, const CCurrent& cur);
     COM dot(CLHEP::HepLorentzVector p1);
     COM dot(CCurrent p1);
     COM c0,c1,c2,c3;
 private:
 };
 
 /* std::ostream& operator <<(std::ostream& os, const CCurrent& cur); */
 CCurrent operator * ( double x, CCurrent& m);
 CCurrent operator * ( COM x, CCurrent& m);
 CCurrent operator / ( double x, CCurrent& m);
 CCurrent operator / ( COM x, CCurrent& m);
 
 
 //! Current ???
 /**
  * These functions are a mess. There are many more defined in the source file than declared in the
  * header - and the arguments are mislabelled in some cases. Need to investigate.
  */
 void j (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin, bool helin,current &cur);
 
 //! Current ???
 /**
  * These functions are a mess. There are many more defined in the source file than declared in the
  * header - and the arguments are mislabelled in some cases. Need to investigate.
  */
 void jio(HLV pin, bool helin, HLV pout, bool helout, current &cur);
 
 //! Current ???
 /**
  * These functions are a mess. There are many more defined in the source file than declared in the
  * header - and the arguments are mislabelled in some cases. Need to investigate.
  */
 void joo(HLV pi, bool heli, HLV pj, bool helj, current &cur);
 
+//! Current ???
+/**
+ * These functions are a mess. There are many more defined in the source file than declared in the
+ * header - and the arguments are mislabelled in some cases. Need to investigate.
+ */
+void joi(HLV pout, bool helout, HLV pin, bool helin, current &cur);
 
 //! Current ???
 /**
  * These functions are a mess. There are many more defined in the source file than declared in the
  * header - and the arguments are mislabelled in some cases. Need to investigate.
  */
 CCurrent j (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin, bool helin);
 
 //! Current <incoming state | mu | outgoing state>
 /**
  * These functions are a mess. There are many more defined in the source file than declared in the
  * header - and the arguments are mislabelled in some cases. Need to investigate.
  */
 CCurrent jio (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin, bool helin);
 
 //! Current <outgoing state | mu | outgoing state>
 /**
  * These functions are a mess. There are many more defined in the source file than declared in the
  * header - and the arguments are mislabelled in some cases. Need to investigate.
  */
 CCurrent joo (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin, bool helin);
 
 /* // Coupling values */
 /* const double stw2   = 0.2222; */
 /* const double ctw    = sqrt(1.0 - stw2); */
 /* const double gs     = 1.217716; */
 /* const double gw     = 0.653232911; */
 /* const double Zem    = (-1.0 / 2.0 + stw2) / ctw; */
 /* const double Zep    = stw2 / ctw; */
 /* const double Zum    = ( 1.0 / 2.0 - 2.0 * stw2 / 3.0) / ctw; */
 /* const double Zup    = - 2.0 * stw2 / 3.0 / ctw; */
 /* const double Zdm    = (-1.0 / 2.0 + 1.0 / 3.0 * stw2) / ctw; */
 /* const double Zdp    = stw2 / 3.0 / ctw; */
 /* const double RWeak  = -pow(gw, 2.0); */
 /* const double Strong =  pow(gs, 4.0); */
 /* const double ee     =  pow(gw, 2.0) * stw2; */
 
 
 /* std::vector <double>  jMZqQ (HLV, HLV, HLV, HLV, HLV, HLV, std::vector <double>, std::vector < std::vector <double> >, int, int, bool, bool); */
 /* std::vector <double>  jMZqg (HLV, HLV, HLV, HLV, HLV, HLV, std::vector <double>, std::vector < std::vector <double> >, int, int, bool, bool); */
 /* void jZ    (HLV, HLV, HLV, HLV, bool, bool, current); */
 /* void jZbar (HLV, HLV, HLV, HLV, bool, bool, current); */
 /* COM PZ(double); */
 /* double Zq (int, bool); */
 /* double Gq (int); */
 
 inline COM cdot(const current & j1, const current & j2)
 {
   return j1[0]*j2[0]-j1[1]*j2[1]-j1[2]*j2[2]-j1[3]*j2[3];
 }
 
 inline COM cdot(const HLV & p, const current & j1) {
   return j1[0]*p.e()-j1[1]*p.x()-j1[2]*p.y()-j1[3]*p.z();
 }
 
 inline void cmult(const COM & factor, const current & j1, current &cur)
 {
   cur[0]=factor*j1[0];
   cur[1]=factor*j1[1];
   cur[2]=factor*j1[2];
   cur[3]=factor*j1[3];
 }
 
 // WHY!?!
 inline void cadd(const current & j1, const current & j2, const current & j3,
           const current & j4, const current & j5, current &sum)
 {
   sum[0]=j1[0]+j2[0]+j3[0]+j4[0]+j5[0];
   sum[1]=j1[1]+j2[1]+j3[1]+j4[1]+j5[1];
   sum[2]=j1[2]+j2[2]+j3[2]+j4[2]+j5[2];
   sum[3]=j1[3]+j2[3]+j3[3]+j4[3]+j5[3];
 }
 
 inline void cadd(const current & j1, const current & j2, const current & j3,
           const current & j4, current &sum) {
   sum[0] = j1[0] + j2[0] + j3[0] + j4[0];
   sum[1] = j1[1] + j2[1] + j3[1] + j4[1];
   sum[2] = j1[2] + j2[2] + j3[2] + j4[2];
   sum[3] = j1[3] + j2[3] + j3[3] + j4[3];
 }
 
 inline void cadd(const current & j1, const current & j2, const current & j3,
          current &sum)
 {
   sum[0]=j1[0]+j2[0]+j3[0];
   sum[1]=j1[1]+j2[1]+j3[1];
   sum[2]=j1[2]+j2[2]+j3[2];
   sum[3]=j1[3]+j2[3]+j3[3];
 }
 
 inline void cadd(const current & j1, const current & j2, current &sum)
 {
   sum[0]=j1[0]+j2[0];
   sum[1]=j1[1]+j2[1];
   sum[2]=j1[2]+j2[2];
   sum[3]=j1[3]+j2[3];
 }
 
 inline double abs2(const COM & a)
 {
     return (a*conj(a)).real();
 }
 
 inline double vabs2(const CCurrent & cur)
 {
     return abs2(cur.c0)-abs2(cur.c1)-abs2(cur.c2)-abs2(cur.c3);
 }
 
 inline double vre(const CCurrent & a, const CCurrent & b)
 {
   return real(a.c0*conj(b.c0)-a.c1*conj(b.c1)-a.c2*conj(b.c2)-a.c3*conj(b.c3));
 }
diff --git a/include/RHEJ/qqx.hh b/include/RHEJ/qqx.hh
index a353ee2..682e843 100644
--- a/include/RHEJ/qqx.hh
+++ b/include/RHEJ/qqx.hh
@@ -1,125 +1,125 @@
 /** \file qqx.hh
  *  \brief Functions for determining if event is a qqx event.
  */
 
 #pragma once
 
 #include "RHEJ/utility.hh"
 #include "RHEJ/PDG_codes.hh"
 
 namespace RHEJ{
   //! Check if an event has a backwards extremal qqx
   /**
    * @param incoming        Incoming particles in ascending pz
    * @param outgoing        Outgoing particles in ascending rapidity
    * @returns               true iff the the most backwards incoming particle is a                      *                        gluon and the corresponding outgoing particle is a quark.
    *
    * If the incoming and outgoing particles are ordered such that HEJ resummation
    * is possible, this function can help to distinguish between FKL and backwards qqx
    * events. Allows emission of A/W/Z boson unordered past qqx pair.
    */
   inline
   bool has_Ex_qqxb(
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> const & outgoing
   ){
     if (incoming.front().type!=pid::gluon) return false;
     if (is_AWZ_boson(outgoing.front().type)){
       return (is_quark(outgoing[1]) && is_antiquark(outgoing[2]))
         || (is_quark(outgoing[2]) && is_antiquark(outgoing[1]));
     }
-    if (abs(outgoing[1].type) == pid::Wp){
+    if (is_AWZ_boson(outgoing[1].type)){
       return (is_quark(outgoing.front()) && is_antiquark(outgoing[2]))
         || (is_quark(outgoing[2]) && is_antiquark(outgoing.front()));
     }
     return (is_quark(outgoing.front()) && is_antiquark(outgoing[1]))
       || (is_quark(outgoing[1]) && is_antiquark(outgoing.front()));
   }
 
   //! Check if an event has an extremal forward qqx
   /**
    * @param incoming        Incoming particles in ascending pz
    * @param outgoing        Outgoing particles in ascending rapidity
    * @returns               true iff the the most forwards incoming particle is a                       *                        gluon and the corresponding outgoing particle is a quark.
    *
    * If the incoming and outgoing particles are ordered such that HEJ resummation
    * is possible, this function can help to distinguish between FKL and forwards qqx
    * events. Allows emission of A/W/Z boson unordered beyond qqx pair.
    */
   inline
   bool has_Ex_qqxf(
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> const & outgoing
   ){
     if (incoming.back().type!=pid::gluon) return false;
     if (is_AWZ_boson(outgoing.back().type)){
       return (is_quark(outgoing.rbegin()[1]) && is_antiquark(outgoing.rbegin()[2]))
         || (is_quark(outgoing.rbegin()[2]) && is_antiquark(outgoing.rbegin()[1]));
     }
-    if (abs(outgoing.rbegin()[1].type) == pid::Wp){
+    if (is_AWZ_boson(outgoing.rbegin()[1].type)){
       return (is_quark(outgoing.back()) && is_antiquark(outgoing.rbegin()[2]))
         || (is_quark(outgoing.rbegin()[2]) && is_antiquark(outgoing.back()));
     }
     return (is_quark(outgoing.back()) && is_antiquark(outgoing.rbegin()[1]))
       || (is_quark(outgoing.rbegin()[1]) && is_antiquark(outgoing.back()));
   }
 
   //! Check if an event has an Extremal qqx
   /**
    * @see has_Ex_qqxb, has_Ex_qqxf
    */
   inline
   bool has_Ex_qqx(
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> const & outgoing
   ){
     return
       has_Ex_qqxb(incoming, outgoing) || has_Ex_qqxf(incoming, outgoing);
   }
 
   // Note that this changes the outgoing range!
     template<class Iterator>
     bool has_mid_qqx(
         Iterator begin_outgoing, Iterator end_outgoing
     ){
     assert(std::distance(begin_outgoing, end_outgoing) >= 2);
 
     // One photon, W, H, Z in the final state is allowed.
     // Remove it for remaining tests,
     end_outgoing = std::remove_if(
         begin_outgoing, end_outgoing, [](Particle const & p){return is_AWZH_boson(p);}
     );
     if(std::distance(begin_outgoing, end_outgoing) < 4){
       return false;
     }
 
     const auto quark = std::find_if(  //Find a quark
         begin_outgoing+1, end_outgoing-1,
         [](Particle const & s){ return (is_quark(s));}
     );
 
     if (quark == begin_outgoing+1)   return (is_antiquark((begin_outgoing+2)->type));
     else if(quark == end_outgoing-1) return (is_antiquark((end_outgoing-2)->type));
     else return (is_antiquark((quark-1)->type)) || (is_antiquark((quark+1)->type));
     }
 
 
   //! Check if an event has a central qqx pair
   /**
    * @param outgoing        Outgoing particles in ascending rapidity
    * @returns               true iff the the most forwards incoming particle is a                       *                        gluon and the corresponding outgoing particle is a quark.
    *
    * If the incoming and outgoing particles are ordered such that HEJ resummation
    * is possible, this function can help to distinguish between FKL and central qqx
    * events. Allows emission of one A/W/Z/H boson anywhere in the final state.
    */
     inline
     bool has_mid_qqx(
         std::vector<Particle> outgoing
     ){
 
       return has_mid_qqx(
           begin(outgoing), end(outgoing)
       );
     }
 }
diff --git a/src/Event.cc b/src/Event.cc
index 977c303..ece9702 100644
--- a/src/Event.cc
+++ b/src/Event.cc
@@ -1,602 +1,601 @@
 
 #include "RHEJ/Event.hh"
 
 #include "RHEJ/utility.hh"
 
 #include "RHEJ/qqx.hh"
 
 namespace RHEJ{
 
   namespace{
     constexpr int status_in = -1;
     constexpr int status_decayed = 2;
     constexpr int status_out = 1;
 
     // helper functions to determine event type
 
     // check if there is at most one photon, W, H, Z in the final state
     // and all the rest are quarks or gluons
     bool final_state_ok(std::vector<Particle> const & outgoing){
       bool has_AWZH_boson = false;
       for(auto const & out: outgoing){
         if(is_AWZH_boson(out.type)){
           if(has_AWZH_boson) return false;
           has_AWZH_boson = true;
         }
         else if(! is_parton(out.type)) return false;
       }
       return true;
     }
 
     template<class Iterator>
     Iterator remove_AWZH(Iterator begin, Iterator end){
       return std::remove_if(
           begin, end, [](Particle const & p){return is_AWZH_boson(p);}
       );
     }
 
     template<class Iterator>
     bool valid_outgoing(Iterator begin, Iterator end){
       return std::distance(begin, end) >= 2
         && std::is_sorted(begin, end, rapidity_less{})
         && std::count_if(
             begin, end, [](Particle const & s){return is_AWZH_boson(s);}
         ) < 2;
     }
 
     /**
      * \brief function which determines if type change is consistent with W emission.
      * @param in                      incoming Particle
      * @param out                     outgoing Particle
      *
      * Ensures that change type of quark line is possible by a flavour changing
      * W emission.
      */
     bool is_W_Current(ParticleID in, ParticleID out){
       if((in==1 && out==2)||(in==2 && out==1)){
         return true;
       }
       else if((in==-1 && out==-2)||(in==-2 && out==-1)){
         return true;
       }
       else if((in==3 && out==4)||(in==4 && out==3)){
         return true;
       }
       else if((in==-3 && out==-4)||(in==-4 && out==-3)){
         return true;
       }
       else{
         return false;
       }
     }
 
     /**
      * \brief checks if particle type remains same from incoming to outgoing
      * @param in                      incoming Particle
      * @param out                     outgoing Particle
      */
     bool is_Pure_Current(ParticleID in, ParticleID out){
       if(abs(in)<=6 || in==21) return (in==out);
       else return false;
     }
 
 
     // Note that this changes the outgoing range!
     template<class ConstIterator, class Iterator>
     bool is_FKL(
         ConstIterator begin_incoming, ConstIterator end_incoming,
         Iterator begin_outgoing, Iterator end_outgoing
     ){
       assert(std::distance(begin_incoming, end_incoming) == 2);
       assert(std::distance(begin_outgoing, end_outgoing) >= 2);
 
       // One photon, W, H, Z in the final state is allowed.
       // Remove it for remaining tests,
       end_outgoing = remove_AWZH(begin_outgoing, end_outgoing);
 
       if(std::all_of(
             begin_outgoing + 1, end_outgoing - 1,
             [](Particle const & p){ return p.type == pid::gluon; })
       ){
         // Test if this is a standard FKL configuration.
         if (is_Pure_Current(begin_incoming->type, begin_outgoing->type)
             && is_Pure_Current((end_incoming-1)->type, (end_outgoing-1)->type)){
           return true;
         }
         else if(is_W_Current(begin_incoming->type, begin_outgoing->type)
             && is_Pure_Current((end_incoming-1)->type, (end_outgoing-1)->type)){
           return true;
         }
         else if(is_Pure_Current(begin_incoming->type, begin_outgoing->type)
             && is_W_Current((end_incoming-1)->type, (end_outgoing-1)->type)){
           return true;
         }
       }
       return false;
     }
 
     bool is_FKL(
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> outgoing
     ){
       assert(std::is_sorted(begin(incoming), end(incoming), pz_less{}));
       assert(valid_outgoing(begin(outgoing), end(outgoing)));
 
       return is_FKL(
           begin(incoming), end(incoming),
           begin(outgoing), end(outgoing)
       );
     }
 
     bool has_2_jets(Event const & event){
       return event.jets().size() >= 2;
     }
 
     /**
      * \brief Checks whether event is unordered backwards
      * @param ev        Event
      * @returns         Is Event Unordered Backwards
      *
      * Checks there is more than 3 constuents in the final state
      * Checks there is more than 3 jets
      * Checks the most backwards parton is a gluon
      * Checks the most forwards jet is not a gluon
      * Checks the rest of the event is FKL
      * Checks the second most backwards is not a different boson
      * Checks the unordered gluon actually forms a jet
      */
     bool is_unordered_backward(Event const & ev){
       auto const & in = ev.incoming();
       auto const & out = ev.outgoing();
       assert(std::is_sorted(begin(in), end(in), pz_less{}));
       assert(valid_outgoing(begin(out), end(out)));
 
       if(out.size() < 3) return false;
       if(ev.jets().size() < 3) return false;
       if(in.front().type == pid::gluon) return false;
       if(out.front().type != pid::gluon) return false;
       // When skipping the unordered emission
       // the remainder should be a regular FKL event,
       // except that the (new) first outgoing particle must not be a A,W,Z,H.
       const auto FKL_begin = next(begin(out));
       if(is_AWZH_boson(*FKL_begin)) return false;
       if(!is_FKL(in, {FKL_begin, end(out)})) return false;
       // check that the unordered gluon forms an extra jet
       const auto jets = sorted_by_rapidity(ev.jets());
       const auto indices = ev.particle_jet_indices({jets.front()});
       return indices[0] >= 0 && indices[1] == -1;
     }
 
     /**
      * \brief Checks for a forward unordered gluon emission
      * @param ev          Event
      * @returns           Is the event a forward unordered emission
      *
      * \see is_unordered_backward
      */
     bool is_unordered_forward(Event const & ev){
       auto const & in = ev.incoming();
       auto const & out = ev.outgoing();
       assert(std::is_sorted(begin(in), end(in), pz_less{}));
       assert(valid_outgoing(begin(out), end(out)));
 
       if(out.size() < 3) return false;
       if(ev.jets().size() < 3) return false;
       if(in.back().type == pid::gluon) return false;
       if(out.back().type != pid::gluon) return false;
       // When skipping the unordered emission
       // the remainder should be a regular FKL event,
       // except that the (new) last outgoing particle must not be a A,W,Z,H.
       const auto FKL_end = prev(end(out));
       if(is_AWZH_boson(*prev(FKL_end))) return false;
       if(!is_FKL(in, {begin(out), FKL_end})) return false;
       // check that the unordered gluon forms an extra jet
       const auto jets = sorted_by_rapidity(ev.jets());
       const auto indices = ev.particle_jet_indices({jets.back()});
       return indices.back() >= 0 && indices[indices.size()-2] == -1;
     }
 
 
     /**
      * \brief Checks for a forward extremal qqx
      * @param ev          Event
      * @returns           Is the event a forward extremal qqx event
      *
      * Checks there is 3 or more than 3 constituents in the final state
      * Checks there is 3 or more than 3 jets
      * Checks most forwards incoming is gluon
      * Checks most extremal particle is not a Higgs (either direction)
      * Checks the second most forwards particle is not Higgs boson
      * Checks the most forwards parton is a either quark or anti-quark.
      * Checks the second most forwards parton is anti-quark or quark.
      */
     bool is_Ex_qqxf(Event const & ev){
       auto const & in = ev.incoming();
       auto const & out = ev.outgoing();
       assert(std::is_sorted(begin(in), end(in), pz_less{}));
       assert(valid_outgoing(begin(out), end(out)));
 
       int fkl_end=2;
 
       if(out.size() < 3) return false;
       if(ev.jets().size() < 3) return false;
       if(in.back().type != pid::gluon) return false;
       if(out.back().type == pid::Higgs || out.front().type == pid::Higgs
                              || out.rbegin()[1].type == pid::Higgs) return false;
 
       // if extremal AWZ
       if(is_AWZ_boson(out.back())){ // if extremal AWZ
         fkl_end++;
         if (is_quark(out.rbegin()[1])){ //if second quark
           if (!(is_antiquark(out.rbegin()[2]))) return false;// third must be anti-quark
         }
         else if (is_antiquark(out.rbegin()[1])){ //if second anti-quark
           if (!(is_quark(out.rbegin()[2]))) return false;// third must be quark
         }
         else return false;
       }
       else if (is_quark(out.rbegin()[0])){ //if extremal quark
         if(is_AWZ_boson(out.rbegin()[1])){ // if second AWZ
           fkl_end++;
           if (!(is_antiquark(out.rbegin()[2]))) return false;// third must be anti-quark
         }
         else if (!(is_antiquark(out.rbegin()[1]))) return false;// second must be anti-quark
       }
       else if (is_antiquark(out.rbegin()[0])){ //if extremal anti-quark
         if(is_AWZ_boson(out.rbegin()[1])){ // if second AWZ
           fkl_end++;
           if (!(is_quark(out.rbegin()[2]))) return false;// third must be quark
-        } //end second AWZ
+        }
         else if (!(is_quark(out.rbegin()[1]))) return false;// second must be quark
-      } // end extremal antiquark
+      }
 
       // When skipping the qqbar
       // New last outgoing particle must not be a Higgs
       if (out.rbegin()[fkl_end].type == pid::Higgs) return false;
 
       // Opposite current should be logical to process
       if (is_AWZ_boson(out.front().type)){
         return (is_Pure_Current(in.front().type, out[1].type)
                 || is_W_Current(in.front().type,out[1].type));
       }
       else
         return (is_Pure_Current(in.front().type, out[0].type)
                 || is_W_Current(in.front().type,out[0].type));
     }
 
     /**
      * \brief Checks for a backward extremal qqx
      * @param ev          Event
      * @returns           Is the event a backward extremal qqx event
      *
      * Checks there is 3 or more than 3 constituents in the final state
      * Checks there is 3 or more than 3 jets
      * Checks most backwards incoming is gluon
      * Checks most extremal particle is not a Higgs (either direction) y
      * Checks the second most backwards particle is not Higgs boson y
      * Checks the most backwards parton is a either quark or anti-quark. y
      * Checks the second most backwards parton is anti-quark or quark. y
      */
     bool is_Ex_qqxb(Event const & ev){
       auto const & in = ev.incoming();
       auto const & out = ev.outgoing();
       assert(std::is_sorted(begin(in), end(in), pz_less{}));
       assert(valid_outgoing(begin(out), end(out)));
 
       int fkl_start=2;
 
       if(out.size() < 3) return false;
       if(ev.jets().size() < 3) return false;
       if(in.front().type != pid::gluon) return false;
       if(out.back().type == pid::Higgs || out.front().type == pid::Higgs
                             || out[1].type == pid::Higgs) return false;
 
-      // if extremal AWZ
       if(is_AWZ_boson(out.front())){ // if extremal AWZ
         fkl_start++;
         if (is_quark(out[1])){ //if second quark
           if (!(is_antiquark(out[2]))) return false;// third must be anti-quark
         }
         else if (is_antiquark(out[1])){ //if second anti-quark
           if (!(is_quark(out[2]))) return false;// third must be quark
         }
         else return false;
       }
       else if (is_quark(out[0])){ // if extremal quark
         if(is_AWZ_boson(out[1])){ // if second AWZ
           fkl_start++;
           if (!(is_antiquark(out[2]))) return false;// third must be anti-quark
         }
         else if (!(is_antiquark(out[1]))) return false;// second must be anti-quark
       }
       else if (is_antiquark(out[0])){ //if extremal anti-quark
-          if(is_AWZ_boson(out[1])){ // if second AWZ
-            fkl_start++;
-            if (!(is_quark(out[2]))) return false;// third must be quark
-          }
-          else if (!(is_quark(out[1]))) return false;// second must be quark
-      } // end extremal antiquark
+        if(is_AWZ_boson(out[1])){ // if second AWZ
+          fkl_start++;
+          if (!(is_quark(out[2]))) return false;// third must be quark
+        }
+        else if (!(is_quark(out[1]))) return false;// second must be quark
+      }
 
       // When skipping the qqbar
       // New last outgoing particle must not be a Higgs.
       if (out[fkl_start].type == pid::Higgs) return false;
 
       // Other current should be logical to process
       if (is_AWZ_boson(out.back())){
         return (is_Pure_Current(in.back().type, out.rbegin()[1].type)
                 || is_W_Current(in.back().type,out.rbegin()[1].type));
       }
       else
         return (is_Pure_Current(in.back().type, out.rbegin()[0].type)
                 || is_W_Current(in.back().type, out.rbegin()[0].type));
     }
 
 
     /**
      * \brief Checks for a central qqx
      * @param ev          Event
      * @returns           Is the event a central extremal qqx event
      *
      * Checks there is 4 or more than 4 constuents in the final state
      * Checks there is 4 or more than 4 jets
      * Checks most extremal particle is not a Higgs (either direction) y
      * Checks for a central quark in the outgoing states
      * Checks for adjacent anti-quark parton. (allowing for AWZ boson emission between)
      * Checks external currents are logically sound.
      */
     bool is_Mid_qqx(Event const & ev){
       auto const & in = ev.incoming();
       auto const & out = ev.outgoing();
       assert(std::is_sorted(begin(in), end(in), pz_less{}));
       assert(valid_outgoing(begin(out), end(out)));
 
       if(out.size() < 4) return false;
       if(ev.jets().size() < 4) return false;
 
       if(out.back().type == pid::Higgs || out.front().type == pid::Higgs)
         return false;
 
-      int start_FKL=0;
-      int end_FKL=0;
+      size_t start_FKL=0;
+      size_t end_FKL=0;
 
       if (is_AWZ_boson(out.back())){
         end_FKL++;
       }
       if (is_AWZ_boson(out.front())){
         start_FKL++;
       }
 
       if ((is_Pure_Current(in.back().type,out.rbegin()[end_FKL].type)
            && is_Pure_Current(in.front().type,out[start_FKL].type))){
         //nothing to do
       }
       else if (is_W_Current(in.back().type,out.rbegin()[end_FKL].type)
                && is_Pure_Current(in.front().type,out[start_FKL].type)){
         //nothing to do
       }
       else if (!(is_Pure_Current(in.back().type,out.rbegin()[end_FKL].type)
                  && is_W_Current(in.front().type,out[start_FKL].type))){
         return false;
       }
 
-      for(auto i=1+start_FKL; i<out.size()-1-end_FKL;i++){
-          if (is_quark(out[i])){
-            if ((is_antiquark(out[i-1]) && i!=1)
-                || (is_antiquark(out[i+1]) && i!=out.size()-1-end_FKL))
-              return true;
-            else if (is_AWZ_boson(out[i-1]) && (is_antiquark(out[i-2]) && i!=2) )
-              return true;
-            else if (is_AWZ_boson(out[i+1]) && (is_antiquark(out[i+2]) && i!=out.size()-2) )
-              return true;
-          }
+      for(size_t i=1+start_FKL; i<out.size()-1-end_FKL;i++){
+        if (is_quark(out[i])){
+          if ((is_antiquark(out[i-1]) && i!=1)
+              || (is_antiquark(out[i+1]) && i!=out.size()-1-end_FKL))
+            return true;
+          else if (is_AWZ_boson(out[i-1]) && (is_antiquark(out[i-2]) && i!=2) )
+            return true;
+          else if (is_AWZ_boson(out[i+1]) && (is_antiquark(out[i+2]) && i!=out.size()-2) )
+            return true;
+        }
       }
       return false;
     }
 
     using event_type::EventType;
 
     EventType classify(Event const & ev){
       if(! final_state_ok(ev.outgoing())) return EventType::bad_final_state;
       if(! has_2_jets(ev)) return EventType::no_2_jets;
       if(is_FKL(ev.incoming(), ev.outgoing())) {
         return EventType::FKL;
       }
       if(is_unordered_backward(ev)){
         return EventType::unordered_backward;
       }
       if(is_unordered_forward(ev)){
         return EventType::unordered_forward;
       }
       if(is_Ex_qqxb(ev)){
         return EventType::extremal_qqxb;
       }
       if(is_Ex_qqxf(ev)){
         return EventType::extremal_qqxf;
       }
       if(is_Mid_qqx(ev)){
         return EventType::central_qqx;
       }
       return EventType::nonHEJ;
     }
 
     Particle extract_particle(LHEF::HEPEUP const & hepeup, int i){
       return Particle{
         static_cast<ParticleID>(hepeup.IDUP[i]),
         fastjet::PseudoJet{
           hepeup.PUP[i][0], hepeup.PUP[i][1],
           hepeup.PUP[i][2], hepeup.PUP[i][3]
         }
       };
     }
 
     bool is_decay_product(std::pair<int, int> const & mothers){
       if(mothers.first == 0) return false;
       return mothers.second == 0 || mothers.first == mothers.second;
     }
 
-  }
+  } // namespace anonymous
 
   UnclusteredEvent::UnclusteredEvent(LHEF::HEPEUP const & hepeup):
     central(EventParameters{
       hepeup.scales.mur, hepeup.scales.muf, hepeup.weight()
     })
   {
     size_t in_idx = 0;
     for (int i = 0; i < hepeup.NUP; ++i) {
       // skip decay products
       // we will add them later on, but we have to ensure that
       // the decayed particle is added before
       if(is_decay_product(hepeup.MOTHUP[i])) continue;
 
       auto particle = extract_particle(hepeup, i);
       // needed to identify mother particles for decay products
       particle.p.set_user_index(i+1);
 
       if(hepeup.ISTUP[i] == status_in){
-         if(in_idx > incoming.size()) {
-           throw std::invalid_argument{
-             "Event has too many incoming particles"
-           };
-         }
-         incoming[in_idx++] = std::move(particle);
+        if(in_idx > incoming.size()) {
+          throw std::invalid_argument{
+           "Event has too many incoming particles"
+          };
+        }
+        incoming[in_idx++] = std::move(particle);
       }
       else outgoing.emplace_back(std::move(particle));
     }
     std::sort(
         begin(incoming), end(incoming),
         [](Particle o1, Particle o2){return o1.p.pz()<o2.p.pz();}
     );
     std::sort(begin(outgoing), end(outgoing), rapidity_less{});
 
     // add decay products
     for (int i = 0; i < hepeup.NUP; ++i) {
       if(!is_decay_product(hepeup.MOTHUP[i])) continue;
       const int mother_id = hepeup.MOTHUP[i].first;
       const auto mother = std::find_if(
           begin(outgoing), end(outgoing),
           [mother_id](Particle const & particle){
             return particle.p.user_index() == mother_id;
           }
       );
       if(mother == end(outgoing)){
         throw std::invalid_argument{"invalid decay product parent"};
       }
       const int mother_idx = std::distance(begin(outgoing), mother);
       assert(mother_idx >= 0);
       decays[mother_idx].emplace_back(extract_particle(hepeup, i));
     }
   }
 
   Event::Event(
       UnclusteredEvent ev,
       fastjet::JetDefinition const & jet_def, double min_jet_pt
   ):
     ev_{std::move(ev)},
     cs_{to_PseudoJet(filter_partons(ev_.outgoing)), jet_def},
     min_jet_pt_{min_jet_pt}
   {
     type_ = classify(*this);
   }
 
   std::vector<fastjet::PseudoJet> Event::jets() const{
     return cs_.inclusive_jets(min_jet_pt_);
   }
 
   /**
    * \brief Returns the invarient mass of the event
    * @param ev         Event
    * @returns          s hat
    *
    * Makes use of the FastJet PseudoJet function m2().
    * Applies this function to the sum of the incoming partons.
    */
   double shat(Event const & ev){
     return (ev.incoming()[0].p + ev.incoming()[1].p).m2();
   }
 
   namespace{
     // colour flow according to Les Houches standard
     // TODO: stub
     std::vector<std::pair<int, int>> colour_flow(
         std::array<Particle, 2> const & incoming,
         std::vector<Particle> const & outgoing
     ){
       std::vector<std::pair<int, int>> result(
           incoming.size() + outgoing.size()
       );
       for(auto & col: result){
         col = std::make_pair(-1, -1);
       }
       return result;
     }
   }
 
   LHEF::HEPEUP to_HEPEUP(Event const & event, LHEF::HEPRUP * heprup){
     LHEF::HEPEUP result;
     result.heprup = heprup;
     result.weights = {{event.central().weight, nullptr}};
     for(auto const & var: event.variations()){
       result.weights.emplace_back(var.weight, nullptr);
     }
     size_t num_particles = event.incoming().size() + event.outgoing().size();
     for(auto const & decay: event.decays()) num_particles += decay.second.size();
     result.NUP = num_particles;
     // the following entries are pretty much meaningless
     result.IDPRUP = event.type()+1;  // event ID
     result.AQEDUP = 1./128.;  // alpha_EW
     //result.AQCDUP = 0.118 // alpha_QCD
     // end meaningless part
     result.XWGTUP = event.central().weight;
     result.SCALUP = event.central().muf;
     result.scales.muf = event.central().muf;
     result.scales.mur = event.central().mur;
     result.scales.SCALUP = event.central().muf;
     result.pdfinfo.p1 = event.incoming().front().type;
     result.pdfinfo.p2 = event.incoming().back().type;
     result.pdfinfo.scale = event.central().muf;
     for(Particle const & in: event.incoming()){
       result.IDUP.emplace_back(in.type);
       result.ISTUP.emplace_back(status_in);
       result.PUP.push_back({in.p[0], in.p[1], in.p[2], in.p[3], in.p.m()});
       result.MOTHUP.emplace_back(0, 0);
     }
     for(size_t i = 0; i < event.outgoing().size(); ++i){
       Particle const & out = event.outgoing()[i];
       result.IDUP.emplace_back(out.type);
       const int status = event.decays().count(i)?status_decayed:status_out;
       result.ISTUP.emplace_back(status);
       result.PUP.push_back({out.p[0], out.p[1], out.p[2], out.p[3], out.p.m()});
       result.MOTHUP.emplace_back(1, 2);
     }
     result.ICOLUP = colour_flow(
         event.incoming(), filter_partons(event.outgoing())
     );
     if(result.ICOLUP.size() < num_particles){
       const size_t AWZH_boson_idx = std::find_if(
           begin(event.outgoing()), end(event.outgoing()),
           [](Particle const & s){ return is_AWZH_boson(s); }
       ) - begin(event.outgoing()) + event.incoming().size();
       assert(AWZH_boson_idx <= result.ICOLUP.size());
       result.ICOLUP.insert(
           begin(result.ICOLUP) + AWZH_boson_idx,
           std::make_pair(0,0)
       );
     }
     for(auto const & decay: event.decays()){
       for(auto const out: decay.second){
         result.IDUP.emplace_back(out.type);
         result.ISTUP.emplace_back(status_out);
         result.PUP.push_back({out.p[0], out.p[1], out.p[2], out.p[3], out.p.m()});
         const int mother_idx = 1 + event.incoming().size() + decay.first;
         result.MOTHUP.emplace_back(mother_idx, mother_idx);
         result.ICOLUP.emplace_back(0,0);
       }
     }
     assert(result.ICOLUP.size() == num_particles);
     static constexpr double unknown_spin = 9.;     //per Les Houches accord
     result.VTIMUP = std::vector<double>(num_particles, unknown_spin);
     result.SPINUP = result.VTIMUP;
     return result;
   }
 
 }
diff --git a/src/MatrixElement.cc b/src/MatrixElement.cc
index a1d09d7..e129609 100644
--- a/src/MatrixElement.cc
+++ b/src/MatrixElement.cc
@@ -1,994 +1,1601 @@
 #include "RHEJ/MatrixElement.hh"
 
 #include <CLHEP/Random/Randomize.h>
 #include <CLHEP/Random/RanluxEngine.h>
 
 #include "RHEJ/Constants.hh"
 #include "RHEJ/currents.hh"
 #include "RHEJ/PDG_codes.hh"
 #include "RHEJ/uno.hh"
 #include "RHEJ/qqx.hh"
 #include "RHEJ/utility.hh"
 
 namespace RHEJ{
   //cf. last line of eq. (22) in \ref Andersen:2011hs
   double MatrixElement::omega0(
       double alpha_s, double mur,
       fastjet::PseudoJet const & q_j, double lambda
   ) const {
     const double result = - alpha_s*N_C/M_PI*log(q_j.perp2()/(lambda*lambda));
     if(! param_.log_correction) return result;
     // use alpha_s(sqrt(q_j*lambda)), evolved to mur
     return (
         1. + alpha_s/(4.*M_PI)*beta0*log(mur*mur/(q_j.perp()*lambda))
     )*result;
   }
 
   double MatrixElement::virtual_corrections(
       double mur,
       std::array<Particle, 2> const & in,
       std::vector<Particle> const & out
   ) const{
     fastjet::PseudoJet const & pa = in.front().p;
 #ifndef NDEBUG
     fastjet::PseudoJet const & pb = in.back().p;
     double const norm = (in.front().p + in.back().p).E();
 #endif
 
     assert(std::is_sorted(out.begin(), out.end(), rapidity_less{}));
     assert(out.size() >= 2);
     assert(pa.pz() < pb.pz());
 
     fastjet::PseudoJet q = pa - out[0].p;
     size_t first_idx = 0;
     size_t last_idx = out.size() - 1;
     // if there is a Higgs or unordered gluon outside the extremal partons
     // then it is not part of the FKL ladder and does not contribute
     // to the virtual corrections
     if(out.front().type == pid::Higgs || has_unob_gluon(in, out)){
       q -= out[1].p;
       ++first_idx;
     }
     if(out.back().type == pid::Higgs || has_unof_gluon(in, out)){
       --last_idx;
     }
 
     double exponent = 0;
     const double alpha_s = alpha_s_(mur);
     for(size_t j = first_idx; j < last_idx; ++j){
       exponent += omega0(alpha_s, mur, q, CLAMBDA)*(
           out[j+1].rapidity() - out[j].rapidity()
       );
       q -= out[j+1].p;
     }
     assert(
         nearby(q, -1*pb, norm)
         || out.back().type == pid::Higgs
         || has_unof_gluon(in, out)
     );
     return exp(exponent);
   }
 } // namespace RHEJ
 
 namespace {
   //! Lipatov vertex for partons emitted into extremal jets
   double C2Lipatov(CLHEP::HepLorentzVector qav, CLHEP::HepLorentzVector qbv,
     CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector p2)
   {
     CLHEP::HepLorentzVector temptrans=-(qav+qbv);
     CLHEP::HepLorentzVector p5=qav-qbv;
     CLHEP::HepLorentzVector CL=temptrans
       + p1*(qav.m2()/p5.dot(p1) + 2.*p5.dot(p2)/p1.dot(p2))
       - p2*(qbv.m2()/p5.dot(p2) + 2.*p5.dot(p1)/p1.dot(p2));
 
     // cout << "#Fadin qa : "<<qav<<endl;
     // cout << "#Fadin qb : "<<qbv<<endl;
     // cout << "#Fadin p1 : "<<p1<<endl;
     // cout << "#Fadin p2 : "<<p2<<endl;
     // cout << "#Fadin p5 : "<<p5<<endl;
     // cout << "#Fadin Gauge Check : "<< CL.dot(p5)<<endl;
     // cout << "#Fadin C2L : "<< -CL.dot(CL)<<" "<<-CL.dot(CL)/(qav.m2()*qbv.m2())/(4./p5.perp2())<<endl;
 
     // TODO can this dead test go?
     // if (-CL.dot(CL)<0.)
       //   if (fabs(CL.dot(p5))>fabs(CL.dot(CL))) // not sufficient!
     //   return 0.;
     // else
     return -CL.dot(CL);
   }
 
   //! Lipatov vertex with soft subtraction for partons emitted into extremal jets
   double C2Lipatovots(CLHEP::HepLorentzVector qav, CLHEP::HepLorentzVector qbv,
     CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector p2)
   {
     double kperp=(qav-qbv).perp();
     if (kperp>RHEJ::CLAMBDA)
       return C2Lipatov(qav, qbv, p1, p2)/(qav.m2()*qbv.m2());
     else {
       double Cls=(C2Lipatov(qav, qbv, p1, p2)/(qav.m2()*qbv.m2()));
       return Cls-4./(kperp*kperp);
     }
   }
 
   //! Lipatov vertex
   double C2Lipatov(CLHEP::HepLorentzVector qav, CLHEP::HepLorentzVector qbv,
     CLHEP::HepLorentzVector pim, CLHEP::HepLorentzVector pip,
     CLHEP::HepLorentzVector pom, CLHEP::HepLorentzVector pop) // B
   {
     CLHEP::HepLorentzVector temptrans=-(qav+qbv);
     CLHEP::HepLorentzVector p5=qav-qbv;
     CLHEP::HepLorentzVector CL=temptrans
       + qav.m2()*(1./p5.dot(pip)*pip + 1./p5.dot(pop)*pop)/2.
       - qbv.m2()*(1./p5.dot(pim)*pim + 1./p5.dot(pom)*pom)/2.
       + ( pip*(p5.dot(pim)/pip.dot(pim) + p5.dot(pom)/pip.dot(pom))
         + pop*(p5.dot(pim)/pop.dot(pim) + p5.dot(pom)/pop.dot(pom))
         - pim*(p5.dot(pip)/pip.dot(pim) + p5.dot(pop)/pop.dot(pim))
         - pom*(p5.dot(pip)/pip.dot(pom) + p5.dot(pop)/pop.dot(pom)) )/2.;
 
     return -CL.dot(CL);
   }
 
   //! Lipatov vertex with soft subtraction
   double C2Lipatovots(CLHEP::HepLorentzVector qav, CLHEP::HepLorentzVector qbv,
     CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb,
     CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector p2)
   {
     double kperp=(qav-qbv).perp();
     if (kperp>RHEJ::CLAMBDA)
       return C2Lipatov(qav, qbv, pa, pb, p1, p2)/(qav.m2()*qbv.m2());
     else {
       double Cls=(C2Lipatov(qav, qbv, pa, pb, p1, p2)/(qav.m2()*qbv.m2()));
       double temp=Cls-4./(kperp*kperp);
       return temp;
     }
   }
 
   /** Matrix element squared for tree-level current-current scattering
    *  @param aptype          Particle a PDG ID
    *  @param bptype          Particle b PDG ID
    *  @param pn              Particle n Momentum
    *  @param pb              Particle b Momentum
    *  @param p1              Particle 1 Momentum
    *  @param pa              Particle a Momentum
    *  @returns               ME Squared for Tree-Level Current-Current Scattering
    */
   double ME_current(
       int aptype, int bptype,
       CLHEP::HepLorentzVector const & pn,
       CLHEP::HepLorentzVector const & pb,
       CLHEP::HepLorentzVector const & p1,
       CLHEP::HepLorentzVector const & pa
   ){
     if (aptype==21&&bptype==21) {
       return jM2gg(pn,pb,p1,pa);
     } else if (aptype==21&&bptype!=21) {
       if (bptype > 0)
         return jM2qg(pn,pb,p1,pa);
       else
         return jM2qbarg(pn,pb,p1,pa);
     }
     else if (bptype==21&&aptype!=21) { // ----- || -----
       if (aptype > 0)
         return jM2qg(p1,pa,pn,pb);
       else
         return jM2qbarg(p1,pa,pn,pb);
     }
     else { // they are both quark
       if (bptype>0) {
         if (aptype>0)
           return jM2qQ(pn,pb,p1,pa);
         else
           return jM2qQbar(pn,pb,p1,pa);
       }
       else {
         if (aptype>0)
           return jM2qQbar(p1,pa,pn,pb);
         else
           return jM2qbarQbar(pn,pb,p1,pa);
       }
     }
     throw std::logic_error("unknown particle types");
   }
 
   /** Matrix element squared for tree-level current-current scattering With W+Jets
    *  @param aptype          Particle a PDG ID
    *  @param bptype          Particle b PDG ID
    *  @param pn              Particle n Momentum
    *  @param pb              Particle b Momentum
    *  @param p1              Particle 1 Momentum
    *  @param pa              Particle a Momentum
    *  @returns               ME Squared for Tree-Level Current-Current Scattering
    */
   double ME_W_current(
       int aptype, int bptype,
       CLHEP::HepLorentzVector const & pn,
       CLHEP::HepLorentzVector const & pb,
       CLHEP::HepLorentzVector const & p1,
       CLHEP::HepLorentzVector const & pa,
       CLHEP::HepLorentzVector const & plbar,
-      CLHEP::HepLorentzVector const & pl
+      CLHEP::HepLorentzVector const & pl,
+      bool const wc
   ){
-    if (aptype==21&&bptype==21) {
-      throw std::logic_error("gg incoming in W+jets, qqx not yet implemented");
-    } else if (aptype==21&&bptype!=21) {
+    // We know it cannot be gg incoming.
+    if (aptype==21&&bptype!=21) {
       if (bptype > 0)
         return jMWqg(pn,pl,plbar,pb,p1,pa);
       else
         return jMWqbarg(pn,pl,plbar,pb,p1,pa);
     }
     else if (bptype==21&&aptype!=21) { // ----- || -----
       if (aptype > 0)
         return jMWqg(p1,pl,plbar,pa,pn,pb);
       else
         return jMWqbarg(p1,pl,plbar,pa,pn,pb);
     }
     else { // they are both quark
-      if (bptype>0) {
-        if (aptype>0)
-          return jMWqQ(pn,pl,plbar,pb,p1,pa);
-        else
-          return jMWqQbar(pn,pl,plbar,pb,p1,pa);
+      if (wc==true){ // emission off b, (first argument pbout)
+        if (bptype>0) {
+          if (aptype>0)
+            return jMWqQ(pn,pl,plbar,pb,p1,pa);
+          else
+            return jMWqQbar(pn,pl,plbar,pb,p1,pa);
+        }
+        else {
+          if (aptype>0)
+            return jMWqbarQ(pn,pl,plbar,pb,p1,pa);
+          else
+            return jMWqbarQbar(pn,pl,plbar,pb,p1,pa);
+        }
       }
-      else {
-        if (aptype>0)
-          return jMWqQbar(p1,pl,plbar,pa,pn,pb);
-        else
-          return jMWqbarQbar(pn,pl,plbar,pb,p1,pa);
+      else{ // emission off a, (first argument paout)
+        if (aptype > 0) {
+          if (bptype > 0)
+            return jMWqQ(p1,plbar,pl,pa,pn,pb);
+          else
+            return jMWqQbar(p1,plbar,pl,pa,pn,pb);
+        }
+        else {  // a is anti-quark
+          if (bptype > 0)
+            return jMWqbarQ(p1,plbar,pl,pa,pn,pb);
+          else
+            return jMWqbarQbar(p1,plbar,pl,pa,pn,pb);
+        }
+
       }
     }
     throw std::logic_error("unknown particle types");
   }
 
+  /** Matrix element squared for backwards uno tree-level current-current scattering With W+Jets
+   *  @param aptype          Particle a PDG ID
+   *  @param bptype          Particle b PDG ID
+   *  @param pn              Particle n Momentum
+   *  @param pb              Particle b Momentum
+   *  @param p1              Particle 1 Momentum
+   *  @param pa              Particle a Momentum
+   *  @param pg              Unordered gluon momentum
+   *  @returns               ME Squared for unob Tree-Level Current-Current Scattering
+   */
+  double ME_W_unob_current(
+      int aptype, int bptype,
+      CLHEP::HepLorentzVector const & pn,
+      CLHEP::HepLorentzVector const & pb,
+      CLHEP::HepLorentzVector const & p1,
+      CLHEP::HepLorentzVector const & pa,
+      CLHEP::HepLorentzVector const & pg,
+      CLHEP::HepLorentzVector const & plbar,
+      CLHEP::HepLorentzVector const & pl,
+      bool const wc
+  ){
+    // we know they are not both gluons
+    if (bptype == 21 && aptype != 21) { // b gluon => W emission off a
+      if (aptype > 0)
+        return jM2Wunogqg(pg,p1,plbar,pl,pa,pn,pb);
+      else
+        return jM2Wunogqbarg(pg,p1,plbar,pl,pa,pn,pb);
+    }
+
+    else { // they are both quark
+      if (wc==true) {// emission off b, i.e. b is first current
+        if (bptype>0){
+          if (aptype>0)
+            return junobMWqQg(pn,plbar,pl,pb,p1,pa,pg);
+          else
+            return junobMWqQbarg(pn,plbar,pl,pb,p1,pa,pg);
+        }
+        else{
+          if (aptype>0)
+            return junobMWqbarQg(pn,plbar,pl,pb,p1,pa,pg);
+          else
+            return junobMWqbarQbarg(pn,plbar,pl,pb,p1,pa,pg);
+        }
+      }
+      else {// wc == false, emission off a, i.e. a is first current
+        if (aptype > 0) {
+          if (bptype > 0) //qq
+            return jM2WunogqQ(pg,p1,plbar,pl,pa,pn,pb);
+          else //qqbar
+            return jM2WunogqQbar(pg,p1,plbar,pl,pa,pn,pb);
+        }
+        else {  // a is anti-quark
+          if (bptype > 0) //qbarq
+            return jM2WunogqbarQ(pg,p1,plbar,pl,pa,pn,pb);
+          else //qbarqbar
+            return jM2WunogqbarQbar(pg,p1,plbar,pl,pa,pn,pb);
+        }
+      }
+    }
+  }
+
+  /** Matrix element squared for uno forward tree-level current-current scattering With W+Jets
+   *  @param aptype          Particle a PDG ID
+   *  @param bptype          Particle b PDG ID
+   *  @param pn              Particle n Momentum
+   *  @param pb              Particle b Momentum
+   *  @param p1              Particle 1 Momentum
+   *  @param pa              Particle a Momentum
+   *  @param pg              Unordered gluon momentum
+   *  @returns               ME Squared for unof Tree-Level Current-Current Scattering
+   */
+  double ME_W_unof_current(
+                           int aptype, int bptype,
+                           CLHEP::HepLorentzVector const & pn,
+                           CLHEP::HepLorentzVector const & pb,
+                           CLHEP::HepLorentzVector const & p1,
+                           CLHEP::HepLorentzVector const & pa,
+                           CLHEP::HepLorentzVector const & pg,
+                           CLHEP::HepLorentzVector const & plbar,
+                           CLHEP::HepLorentzVector const & pl,
+                           bool const wc
+                           ){
+
+    // we know they are not both gluons
+    if (aptype==21 && bptype!=21) {//a gluon => W emission off b
+      if (bptype > 0)
+        return jM2Wunogqg(pg, pn,plbar, pl, pb, p1, pa);
+      else
+        return jM2Wunogqbarg(pg, pn,plbar, pl, pb, p1, pa);
+    }
+    else { // they are both quark
+      if (wc==true) {// emission off b, i.e. b is first current
+        if (bptype>0){
+          if (aptype>0)
+            return jM2WunogqQ(pg,pn,plbar,pl,pb,p1,pa);
+          else
+            return jM2WunogqQbar(pg,pn,plbar,pl,pb,p1,pa);
+        }
+        else{
+          if (aptype>0)
+            return jM2WunogqbarQ(pg,pn,plbar,pl,pb,p1,pa);
+          else
+            return jM2WunogqbarQbar(pg,pn,plbar,pl,pb,p1,pa);
+        }
+      }
+      else {// wc == false, emission off a, i.e. a is first current
+        if (aptype > 0) {
+          if (bptype > 0) //qq
+            return junofMWgqQ(pg,pn,pb,p1,plbar,pl,pa);
+          else //qqbar
+            return junofMWgqQbar(pg,pn,pb,p1,plbar,pl,pa);
+        }
+        else {  // a is anti-quark
+          if (bptype > 0) //qbarq
+            return junofMWgqbarQ(pg,pn,pb,p1,plbar,pl,pa);
+          else //qbarqbar
+            return junofMWgqbarQbar(pg,pn,pb,p1,plbar,pl,pa);
+        }
+      }
+    }
+  }
+
+  /** \brief Matrix element squared for backward qqx tree-level current-current scattering With W+Jets
+   *  @param aptype          Particle a PDG ID
+   *  @param bptype          Particle b PDG ID
+   *  @param pa              Initial state a Momentum
+   *  @param pb              Initial state b Momentum
+   *  @param pq              Final state q Momentum
+   *  @param pqbar           Final state qbar Momentum
+   *  @param pn              Final state n Momentum
+   *  @param plbar           Final state anti-lepton momentum
+   *  @param pl              Final state lepton momentum
+   *  @returns               ME Squared for qqxb Tree-Level Current-Current Scattering
+   */
+  double ME_W_qqxb_current(
+                           int aptype, int bptype,
+                           CLHEP::HepLorentzVector const & pa,
+                           CLHEP::HepLorentzVector const & pb,
+                           CLHEP::HepLorentzVector const & pq,
+                           CLHEP::HepLorentzVector const & pqbar,
+                           CLHEP::HepLorentzVector const & pn,
+                           CLHEP::HepLorentzVector const & plbar,
+                           CLHEP::HepLorentzVector const & pl,
+                           bool const wc
+                           ){
+    // CAM factors for the qqx amps, and qqbar ordering (default, qbar extremal)
+    bool swapQuarkAntiquark=false;
+    double CFbackward;
+    if (pqbar.rapidity() > pq.rapidity()){
+      swapQuarkAntiquark=true;
+      CFbackward = (0.5*(3.-1./3.)*(pa.minus()/(pq.minus())+(pq.minus())/pa.minus())+1./3.)*3./4.;
+    }
+    else{
+      CFbackward = (0.5*(3.-1./3.)*(pa.minus()/(pqbar.minus())+(pqbar.minus())/pa.minus())+1./3.)*3./4.;
+    }
+    // With qqbar we could have 2 incoming gluons and W Emission
+    if (aptype==21&&bptype==21) {//a gluon, b gluon gg->qqbarWg
+      // This will be a wqqx emission as there is no other possible W Emission Site.
+      if (swapQuarkAntiquark){
+        return jM2Wggtoqqbarg(pa, pqbar, plbar, pl, pq, pn,pb)*CFbackward;}
+      else {
+        return jM2Wggtoqbarqg(pa, pq, plbar, pl, pqbar, pn,pb)*CFbackward;}
+    }
+    else if (aptype==21&&bptype!=21 ) {//a gluon => W emission off b leg or qqx
+      if (wc!=1){ // W Emitted from backwards qqx
+        if (swapQuarkAntiquark){
+          return jM2WgQtoqqbarQ(pa, pq, plbar, pl, pqbar, pn, pb)*CFbackward;}
+        else{
+          return jM2WgQtoqbarqQ(pa, pq, plbar, pl, pqbar, pn, pb)*CFbackward;}
+      }
+      else {   // W Must be emitted from forwards leg.
+        if (swapQuarkAntiquark){
+          return jM2WgqtoQQqW(pb, pa, pn, pqbar, pq, plbar, pl)*CFbackward;}
+        else{
+          return jM2WgqtoQQqW(pb, pa, pn, pq, pqbar, plbar, pl)*CFbackward;}
+      }
+    }
+    else{
+      throw std::logic_error("Incompatible incoming particle types with qqxb");
+    }
+  }
+
+  /*  \brief Matrix element squared for forward qqx tree-level current-current scattering With W+Jets
+   *  @param aptype          Particle a PDG ID
+   *  @param bptype          Particle b PDG ID
+   *  @param pa              Initial state a Momentum
+   *  @param pb              Initial state b Momentum
+   *  @param pq              Final state q Momentum
+   *  @param pqbar           Final state qbar Momentum
+   *  @param p1              Final state 1 Momentum
+   *  @param plbar           Final state anti-lepton momentum
+   *  @param pl              Final state lepton momentum
+   *  @returns               ME Squared for qqxf Tree-Level Current-Current Scattering
+   */
+  double ME_W_qqxf_current(
+                           int aptype, int bptype,
+                           CLHEP::HepLorentzVector const & pa,
+                           CLHEP::HepLorentzVector const & pb,
+                           CLHEP::HepLorentzVector const & pq,
+                           CLHEP::HepLorentzVector const & pqbar,
+                           CLHEP::HepLorentzVector const & p1,
+                           CLHEP::HepLorentzVector const & plbar,
+                           CLHEP::HepLorentzVector const & pl,
+                           bool const wc
+                           ){
+    // CAM factors for the qqx amps, and qqbar ordering (default, qbar extremal)
+    bool swapQuarkAntiquark=false;
+    double CFforward;
+    if (pqbar.rapidity() < pq.rapidity()){
+      swapQuarkAntiquark=true;
+      CFforward = (0.5*(3.-1./3.)*(pb.plus()/(pq.plus())+(pq.plus())/pb.plus())+1./3.)*3./4.;
+    }
+    else{
+      CFforward = (0.5*(3.-1./3.)*(pb.plus()/(pqbar.plus())+(pqbar.plus())/pb.plus())+1./3.)*3./4.;
+    }
+
+    // With qqbar we could have 2 incoming gluons and W Emission
+    if (aptype==21&&bptype==21) {//a gluon, b gluon gg->qqbarWg
+      // This will be a wqqx emission as there is no other possible W Emission Site.
+      if (swapQuarkAntiquark){
+        return jM2Wggtoqqbarg(pb, pqbar, plbar, pl, pq, p1,pa)*CFforward;}
+      else {
+        return jM2Wggtoqbarqg(pb, pq, plbar, pl, pqbar, p1,pa)*CFforward;}
+    }
+
+    else if (bptype==21&&aptype!=21) {// b gluon => W emission off a or qqx
+      if (wc==1){ // W Emitted from forwards qqx
+        if (swapQuarkAntiquark){
+          return jM2WgQtoqbarqQ(pb, pq, plbar,pl, pqbar, p1, pa)*CFforward;}
+        else {
+          return jM2WgQtoqqbarQ(pb, pq, plbar,pl, pqbar, p1, pa)*CFforward;}
+      }
+      // W Must be emitted from backwards leg.
+      if (swapQuarkAntiquark){
+        return jM2WgqtoQQqW(pa,pb, p1, pqbar, pq, plbar, pl)*CFforward;}
+      else{
+        return jM2WgqtoQQqW(pa,pb, p1, pq, pqbar, plbar, pl)*CFforward;}
+    }
+    else{
+      throw std::logic_error("Incompatible incoming particle types with qqxf");
+    }
+  }
+
+  /*  \brief Matrix element squared for central qqx tree-level current-current scattering With W+Jets
+   *  @param aptype          Particle a PDG ID
+   *  @param bptype          Particle b PDG ID
+   *  @param nabove          Number of gluons emitted before central qqxpair
+   *  @param nbelow          Number of gluons emitted after central qqxpair
+   *  @param pa              Initial state a Momentum
+   *  @param pb              Initial state b Momentum\
+   *  @param pq              Final state qbar Momentum
+   *  @param pqbar           Final state q Momentum
+   *  @param partons         Vector of all outgoing partons
+   *  @param plbar           Final state anti-lepton momentum
+   *  @param pl              Final state lepton momentum
+   *  @param wqq             Boolean. True siginfies W boson is emitted from Central qqx
+   *  @param wc              Boolean. wc=true signifies w boson emitted from leg b; if wqq=false.
+   *  @returns               ME Squared for qqxmid Tree-Level Current-Current Scattering
+   */
+  double ME_W_qqxmid_current(
+                           int aptype, int bptype,
+                           int nabove, int nbelow,
+                           CLHEP::HepLorentzVector const & pa,
+                           CLHEP::HepLorentzVector const & pb,
+                           CLHEP::HepLorentzVector const & pq,
+                           CLHEP::HepLorentzVector const & pqbar,
+                           std::vector<HLV> partons,
+                           CLHEP::HepLorentzVector const & plbar,
+                           CLHEP::HepLorentzVector const & pl,
+                           bool const wqq, bool const wc
+                           ){
+    // CAM factors for the qqx amps, and qqbar ordering (default, pq backwards)
+    bool swapQuarkAntiquark=false;
+    if (pqbar.rapidity() < pq.rapidity()){
+      swapQuarkAntiquark=true;
+    }
+    double CFforward = (0.5*(3.-1./3.)*(pb.plus()/(partons[partons.size()-1].plus())+(partons[partons.size()-1].plus())/pb.plus())+1./3.)*3./4.;
+    double CFbackward = (0.5*(3.-1./3.)*(pa.minus()/(partons[0].minus())+(partons[0].minus())/pa.minus())+1./3.)*3./4.;
+    double wt=1.;
+
+    if (aptype==21)  wt*=CFbackward;
+    if (bptype==21)  wt*=CFforward;
+
+    if (aptype <=0 && bptype <=0){ // Both External AntiQuark
+      if (wqq==1){//emission from central qqbar
+	return wt*jM2WqqtoqQQq(pa, pb, pl,plbar, partons,true,true, swapQuarkAntiquark, nabove);
+      }
+      else if (wc==1){//emission from b leg
+	return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons, true,true, swapQuarkAntiquark, nabove, nbelow, true);
+      }
+      else { // emission from a leg
+	return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons, true,true, swapQuarkAntiquark, nabove, nbelow, false);
+      }
+    } // end both antiquark
+    else if (aptype<=0){ // a is antiquark
+      if (wqq==1){//emission from central qqbar
+	return wt*jM2WqqtoqQQq(pa, pb, pl,plbar, partons, false, true, swapQuarkAntiquark, nabove);
+      }
+      else if (wc==1){//emission from b leg
+	return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons,false,true, swapQuarkAntiquark, nabove, nbelow, true);
+      }
+      else { // emission from a leg
+	return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons, false, true, swapQuarkAntiquark, nabove, nbelow, false);
+      }
+
+    } // end a is antiquark
+
+    else if (bptype<=0){ // b is antiquark
+      if (wqq==1){//emission from central qqbar
+	return wt*jM2WqqtoqQQq(pa, pb, pl,plbar, partons, true, false, swapQuarkAntiquark, nabove);
+      }
+      else if (wc==1){//emission from b leg
+	return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons, true, false, swapQuarkAntiquark, nabove, nbelow, true);
+      }
+      else { // emission from a leg
+	return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons, true, false, swapQuarkAntiquark, nabove, nbelow, false);
+      }
+
+    } //end b is antiquark
+    else{ //Both Quark or gluon
+      if (wqq==1){//emission from central qqbar
+        return wt*jM2WqqtoqQQq(pa, pb, pl, plbar, partons, false, false, swapQuarkAntiquark, nabove);}
+      else if (wc==1){//emission from b leg
+	return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons, false, false, swapQuarkAntiquark, nabove, nbelow, true);
+      }
+      else { // emission from a leg
+	return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons, false, false, swapQuarkAntiquark, nabove, nbelow, false);
+      }
+
+    }
+  }
 
   /** \brief Matrix element squared for tree-level current-current scattering with Higgs
    *  @param aptype          Particle a PDG ID
    *  @param bptype          Particle b PDG ID
    *  @param pn              Particle n Momentum
    *  @param pb              Particle b Momentum
    *  @param p1              Particle 1 Momentum
    *  @param pa              Particle a Momentum
    *  @param qH              t-channel momentum before Higgs
    *  @param qHp1            t-channel momentum after Higgs
    *  @returns               ME Squared for Tree-Level Current-Current Scattering with Higgs
    */
   double ME_Higgs_current(
       int aptype, int bptype,
       CLHEP::HepLorentzVector const & pn,
       CLHEP::HepLorentzVector const & pb,
       CLHEP::HepLorentzVector const & p1,
       CLHEP::HepLorentzVector const & pa,
       CLHEP::HepLorentzVector const & qH,  // t-channel momentum before Higgs
       CLHEP::HepLorentzVector const & qHp1, // t-channel momentum after Higgs
       double mt, bool include_bottom, double mb
   ){
     if (aptype==21&&bptype==21) // gg initial state
       return MH2gg(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
     else if (aptype==21&&bptype!=21) {
       if (bptype > 0)
         return MH2qg(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4./9.;
       else
         return MH2qbarg(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4./9.;
     }
     else if (bptype==21&&aptype!=21) {
       if (aptype > 0)
         return MH2qg(p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb)*4./9.;
       else
         return MH2qbarg(p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb)*4./9.;
     }
     else { // they are both quark
       if (bptype>0) {
         if (aptype>0)
           return MH2qQ(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4.*4./(9.*9.);
         else
           return MH2qQbar(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4.*4./(9.*9.);
       }
       else {
         if (aptype>0)
           return MH2qQbar(p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb)*4.*4./(9.*9.);
         else
           return MH2qbarQbar(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4.*4./(9.*9.);
       }
     }
     throw std::logic_error("unknown particle types");
   }
 
   /** \brief  Current matrix element squared with Higgs and unordered forward emission
    *  @param aptype          Particle A PDG ID
    *  @param bptype          Particle B PDG ID
    *  @param punof           Unordered Particle Momentum
    *  @param pn              Particle n Momentum
    *  @param pb              Particle b Momentum
    *  @param p1              Particle 1 Momentum
    *  @param pa              Particle a Momentum
    *  @param qH              t-channel momentum before Higgs
    *  @param qHp1            t-channel momentum after Higgs
    *  @returns               ME Squared with Higgs and unordered forward emission
    */
   double ME_Higgs_current_unof(
       int aptype, int bptype,
       CLHEP::HepLorentzVector const & punof,
       CLHEP::HepLorentzVector const & pn,
       CLHEP::HepLorentzVector const & pb,
       CLHEP::HepLorentzVector const & p1,
       CLHEP::HepLorentzVector const & pa,
       CLHEP::HepLorentzVector const & qH,  // t-channel momentum before Higgs
       CLHEP::HepLorentzVector const & qHp1, // t-channel momentum after Higgs
       double mt, bool include_bottom, double mb
   ){
     if (aptype==21&&bptype!=21) {
       if (bptype > 0)
         return jM2unogqHg(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
       else
         return jM2unogqbarHg(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
     }
     else { // they are both quark
       if (bptype>0) {
         if (aptype>0)
           return jM2unogqHQ(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
         else
           return jM2unogqHQbar(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
       }
       else {
         if (aptype>0)
           return jM2unogqbarHQ(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
         else
           return jM2unogqbarHQbar(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
       }
     }
     throw std::logic_error("unknown particle types");
   }
 
   /** \brief Current matrix element squared with Higgs and unordered backward emission
    *  @param aptype          Particle A PDG ID
    *  @param bptype          Particle B PDG ID
    *  @param pn              Particle n Momentum
    *  @param pb              Particle b Momentum
    *  @param punob           Unordered back Particle Momentum
    *  @param p1              Particle 1 Momentum
    *  @param pa              Particle a Momentum
    *  @param qH              t-channel momentum before Higgs
    *  @param qHp1            t-channel momentum after Higgs
    *  @returns               ME Squared with Higgs and unordered backward emission
    */
   double ME_Higgs_current_unob(
       int aptype, int bptype,
       CLHEP::HepLorentzVector const & pn,
       CLHEP::HepLorentzVector const & pb,
       CLHEP::HepLorentzVector const & punob,
       CLHEP::HepLorentzVector const & p1,
       CLHEP::HepLorentzVector const & pa,
       CLHEP::HepLorentzVector const & qH,  // t-channel momentum before Higgs
       CLHEP::HepLorentzVector const & qHp1, // t-channel momentum after Higgs
       double mt, bool include_bottom, double mb
   ){
     if (bptype==21&&aptype!=21) {
       if (aptype > 0)
         return jM2unobgHQg(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
       else
         return jM2unobgHQbarg(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
     }
     else { // they are both quark
       if (aptype>0) {
         if (bptype>0)
           return jM2unobqHQg(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
         else
           return jM2unobqbarHQg(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
       }
       else {
         if (bptype>0)
           return jM2unobqHQbarg(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
         else
           return jM2unobqbarHQbarg(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
       }
     }
     throw std::logic_error("unknown particle types");
   }
 
   CLHEP::HepLorentzVector to_HepLorentzVector(RHEJ::Particle const & particle){
     return {particle.p.px(), particle.p.py(), particle.p.pz(), particle.p.E()};
   }
 
   void validate(RHEJ::MatrixElementConfig const & config) {
 #ifndef RHEJ_BUILD_WITH_QCDLOOP
     if(!config.Higgs_coupling.use_impact_factors) {
       throw std::invalid_argument{
         "Invalid Higgs coupling settings.\n"
         "HEJ without QCDloop support can only use impact factors.\n"
         "Set use_impact_factors to true or recompile HEJ.\n"
        };
     }
 #endif
     if(config.Higgs_coupling.use_impact_factors
       && config.Higgs_coupling.mt != std::numeric_limits<double>::infinity()) {
       throw std::invalid_argument{
         "Conflicting settings: "
           "impact factors may only be used in the infinite top mass limit"
       };
     }
   }
 } // namespace anonymous
 
 namespace RHEJ{
   MatrixElement::MatrixElement(
       std::function<double (double)> alpha_s,
       MatrixElementConfig conf
   ):
     alpha_s_{std::move(alpha_s)},
     param_{std::move(conf)}
   {
     validate(param_);
   }
 
   double MatrixElement::operator()(
       double mur,
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> const & outgoing,
       std::unordered_map<int, std::vector<Particle>> const & decays,
       bool check_momenta
   ) const {
     return tree(
         mur,
         incoming, outgoing, decays,
         check_momenta
     )*virtual_corrections(
         mur,
         incoming, outgoing
     );
   }
 
   double MatrixElement::tree_kin(
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> const & outgoing,
       std::unordered_map<int, std::vector<Particle>> const & decays,
       bool check_momenta
   ) const {
     assert(
         std::is_sorted(
             incoming.begin(), incoming.end(),
             [](Particle o1, Particle o2){return o1.p.pz()<o2.p.pz();}
         )
     );
     assert(std::is_sorted(outgoing.begin(), outgoing.end(), rapidity_less{}));
 
     auto AWZH_boson = std::find_if(
         begin(outgoing), end(outgoing),
         [](Particle const & p){return is_AWZH_boson(p);}
     );
 
     if(AWZH_boson == end(outgoing)){
       return tree_kin_jets(incoming, outgoing, check_momenta);
     }
 
     switch(AWZH_boson->type){
     case pid::Higgs: {
       return tree_kin_Higgs(incoming, outgoing, check_momenta);
     }
     // TODO
     case pid::Wp: {
       return tree_kin_W(incoming, outgoing, decays, true, check_momenta);
     }
     case pid::Wm: {
       return tree_kin_W(incoming, outgoing, decays, false, check_momenta);
     }
     case pid::photon:
     case pid::Z:
     default:
       throw std::logic_error("Emission of boson of unsupported type.");
     }
   }
 
   namespace{
     constexpr int extremal_jet_idx = 1;
     constexpr int no_extremal_jet_idx = 0;
 
     bool treat_as_extremal(Particle const & parton){
       return parton.p.user_index() == extremal_jet_idx;
     }
 
     template<class InputIterator>
       double FKL_ladder_weight(
           InputIterator begin_gluon, InputIterator end_gluon,
           CLHEP::HepLorentzVector const & q0,
           CLHEP::HepLorentzVector const & pa, CLHEP::HepLorentzVector const & pb,
           CLHEP::HepLorentzVector const & p1, CLHEP::HepLorentzVector const & pn
       ){
       double wt = 1;
       auto qi = q0;
       for(auto gluon_it = begin_gluon; gluon_it != end_gluon; ++gluon_it){
         assert(gluon_it->type == pid::gluon);
         const auto g = to_HepLorentzVector(*gluon_it);
         const auto qip1 = qi - g;
 
         if(treat_as_extremal(*gluon_it)){
           wt *= C2Lipatovots(qip1, qi, pa, pb)*C_A;
         } else{
           wt *= C2Lipatovots(qip1, qi, pa, pb, p1, pn)*C_A;
         }
 
         qi = qip1;
       }
       return wt;
     }
 
   }  // namespace anonymous
 
   std::vector<Particle> MatrixElement::tag_extremal_jet_partons(
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> out_partons, bool check_momenta
   ) const{
     if(!check_momenta){
       for(auto & parton: out_partons){
         parton.p.set_user_index(no_extremal_jet_idx);
       }
       return out_partons;
     }
     fastjet::ClusterSequence cs(to_PseudoJet(out_partons), param_.jet_param.def);
     const auto jets = sorted_by_rapidity(cs.inclusive_jets(param_.jet_param.min_pt));
     assert(jets.size() >= 2);
     auto most_backward = begin(jets);
     auto most_forward = end(jets) - 1;
     // skip jets caused by unordered emission
     if(has_unob_gluon(incoming, out_partons)){
       assert(jets.size() >= 3);
       ++most_backward;
     }
     else if(has_unof_gluon(incoming, out_partons)){
       assert(jets.size() >= 3);
       --most_forward;
     }
     const auto extremal_jet_indices = cs.particle_jet_indices(
         {*most_backward, *most_forward}
     );
     assert(extremal_jet_indices.size() == out_partons.size());
     for(size_t i = 0; i < out_partons.size(); ++i){
       assert(RHEJ::is_parton(out_partons[i]));
       const int idx = (extremal_jet_indices[i]>=0)?
         extremal_jet_idx:
         no_extremal_jet_idx;
       out_partons[i].p.set_user_index(idx);
     }
     return out_partons;
   }
 
   double MatrixElement::tree_kin_jets(
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> partons,
       bool check_momenta
   ) const {
     partons = tag_extremal_jet_partons(incoming, partons, check_momenta);
     if(has_unob_gluon(incoming, partons) || has_unof_gluon(incoming, partons)){
       throw std::logic_error("unordered emission not implemented for pure jets");
     }
 
     const auto pa = to_HepLorentzVector(incoming[0]);
     const auto pb = to_HepLorentzVector(incoming[1]);
 
     const auto p1 = to_HepLorentzVector(partons.front());
     const auto pn = to_HepLorentzVector(partons.back());
 
     return ME_current(
         incoming[0].type, incoming[1].type,
         pn, pb, p1, pa
     )/(4*(N_C*N_C - 1))*FKL_ladder_weight(
         begin(partons) + 1, end(partons) - 1,
         pa - p1, pa, pb, p1, pn
     );
   }
 
-  double MatrixElement::tree_kin_W(
-      std::array<Particle, 2> const & incoming,
-      std::vector<Particle> const & outgoing,
-      std::unordered_map<int, std::vector<Particle>> const & decays,
-      bool WPlus,
-      bool check_momenta
-  ) const {
-    if(has_unob_gluon(incoming, outgoing)){
-      throw std::logic_error("unordered emission not yet implemented for W+jets");
-      //return tree_kin_W_unob(incoming, outgoing, check_momenta);
+  namespace{
+  double tree_kin_W_FKL(
+        int aptype, int bptype, HLV pa, HLV pb,
+        std::vector<Particle> const & partons,
+        HLV plbar, HLV pl, bool WPlus
+  ) {
+    auto p1 = to_HepLorentzVector(partons[0]);
+    auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
+
+    auto q0 = pa - p1;
+    auto begin_ladder = begin(partons) + 1;
+    auto end_ladder = end(partons) - 1;
+
+    bool wc;
+    if (aptype==partons[0].type) { //leg b emits w
+      wc = true;}
+    else{
+      wc = false;
+      q0 -=pl + plbar;
     }
-    else if(has_unof_gluon(incoming, outgoing)){
-      throw std::logic_error("unordered emission not yet implemented for W+jets");
-      // return tree_kin_W_unof(incoming, outgoing, check_momenta);
+
+    double current_factor;
+    if (WPlus){
+      current_factor = ME_W_current(
+          aptype, bptype, pn, pb,
+          p1, pa, pl, plbar, wc
+      );
     }
-    else if(has_Ex_qqx(incoming, outgoing)){
-      throw std::logic_error("Extremal qqx not yet implemented for W+jets");
-      // return tree_kin_W_Exqqx(incoming, outgoing, check_momenta);
+    else{
+      current_factor = ME_W_current(
+          aptype, bptype, pn, pb,
+          p1, pa, plbar, pl, wc
+      );
     }
-    else if(has_mid_qqx(outgoing)){
-      throw std::logic_error("Central qqx not yet implemented for W+jets");
-      // return tree_kin_W_qqxCentral(incoming, outgoing, check_momenta);
+
+    const double ladder_factor = FKL_ladder_weight(
+        begin_ladder, end_ladder,
+        q0, pa, pb, p1, pn
+    );
+    return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
+  }
+
+  double tree_kin_W_unob(
+      int aptype, int bptype, HLV pa, HLV pb,
+      std::vector<Particle> const & partons,
+      HLV plbar, HLV pl, bool WPlus
+  ) {
+    auto pg = to_HepLorentzVector(partons[0]);
+    auto p1 = to_HepLorentzVector(partons[1]);
+    auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
+
+    auto q0 = pa - p1- pg;
+    auto begin_ladder = begin(partons) + 2;
+    auto end_ladder = end(partons) - 1;
+
+    bool wc;
+    if (aptype==partons[1].type) { //leg b emits w
+      wc = true;}
+    else{
+      wc = false;
+      q0 -=pl + plbar;
+    }
+
+    double current_factor;
+    if (WPlus){
+      current_factor = ME_W_unob_current(
+          aptype, bptype, pn, pb,
+          p1, pa, pg, pl, plbar, wc
+      );
     }
     else{
-      return tree_kin_W_FKL(incoming, outgoing, decays, WPlus, check_momenta);
+      current_factor = ME_W_unob_current(
+          aptype, bptype, pn, pb,
+          p1, pa, pg, plbar, pl, wc
+      );
     }
+
+    const double ladder_factor = FKL_ladder_weight(
+        begin_ladder, end_ladder,
+        q0, pa, pb, p1, pn
+    );
+    return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
   }
 
-  double MatrixElement::tree_kin_W_FKL(
-        std::array<Particle, 2> const & incoming,
-        std::vector<Particle> const & outgoing,
-        std::unordered_map<int, std::vector<Particle>> const & decays,
-        bool WPlus,
-        bool check_momenta
-  ) const {
+  double tree_kin_W_unof(
+      int aptype, int bptype, HLV pa, HLV pb,
+      std::vector<Particle> const & partons,
+      HLV plbar, HLV pl, bool WPlus
+  ) {
+    auto p1 = to_HepLorentzVector(partons[0]);
+    auto pn = to_HepLorentzVector(partons[partons.size() - 2]);
+    auto pg = to_HepLorentzVector(partons[partons.size() - 1]);
 
-    const auto the_W = std::find_if(
-        begin(outgoing), end(outgoing),
-        [](Particle const & s){ return abs(s.type) == pid::Wp; }
+    auto q0 = pa - p1;
+    auto begin_ladder = begin(partons) + 1;
+    auto end_ladder = end(partons) - 2;
+
+    bool wc;
+    if (aptype==partons[0].type) { //leg b emits w
+      wc = true;}
+    else{
+      wc = false;
+      q0 -=pl + plbar;
+    }
+
+    double current_factor;
+    if (WPlus){
+      current_factor = ME_W_unof_current(
+          aptype, bptype, pn, pb,
+          p1, pa, pg, pl, plbar, wc
+      );
+    }
+    else{
+      current_factor = ME_W_unof_current(
+          aptype, bptype, pn, pb,
+          p1, pa, pg, plbar, pl, wc
+      );
+    }
+
+    const double ladder_factor = FKL_ladder_weight(
+        begin_ladder, end_ladder,
+        q0, pa, pb, p1, pn
     );
+    return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
+  }
 
-    HLV plbar, pl;
+  double tree_kin_W_qqxb(
+      int aptype, int bptype, HLV pa, HLV pb,
+      std::vector<Particle> const & partons,
+      HLV plbar, HLV pl, bool WPlus
+  ) {
+    HLV pq,pqbar;
+    if(is_quark(partons[0])){
+      pq = to_HepLorentzVector(partons[0]);
+      pqbar = to_HepLorentzVector(partons[1]);
+    }
+    else{
+      pq = to_HepLorentzVector(partons[1]);
+      pqbar = to_HepLorentzVector(partons[0]);
+    }
+    auto p1 = to_HepLorentzVector(partons[0]);
+    auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
 
-    for (auto& x: decays) {
-      if (x.second.at(0).type < 0){
-        plbar = to_HepLorentzVector(x.second.at(0));
-        pl = to_HepLorentzVector(x.second.at(1));
-      }
-      else{
-        pl = to_HepLorentzVector(x.second.at(0));
-        plbar = to_HepLorentzVector(x.second.at(1));
-      }
+    auto q0 = pa - pq - pqbar;
+    auto begin_ladder = begin(partons) + 2;
+    auto end_ladder = end(partons) - 1;
+
+    bool wc;
+    if (partons[0].type==-partons[1].type) { //leg b emits w
+      wc = true;}
+    else{
+      wc = false;
+      q0 -=pl + plbar;
     }
 
-    const auto pW = to_HepLorentzVector(*the_W);
-    std::vector<Particle> partons(begin(outgoing), the_W);
-    partons.insert(end(partons), the_W + 1, end(outgoing));
-    partons = tag_extremal_jet_partons(incoming, partons, check_momenta);
+    double current_factor;
+    if (WPlus){
+      current_factor = ME_W_qqxb_current(
+          aptype, bptype, pa, pb,
+          pq, pqbar, pn, pl, plbar, wc
+      );
+    }
+    else{
+      current_factor = ME_W_qqxb_current(
+          aptype, bptype, pa, pb,
+          pq, pqbar, pn, plbar, pl, wc
+      );
+    }
 
-    const auto pa = to_HepLorentzVector(incoming[0]);
-    const auto pb = to_HepLorentzVector(incoming[1]);
+    const double ladder_factor = FKL_ladder_weight(
+        begin_ladder, end_ladder,
+        q0, pa, pb, p1, pn
+    );
+    return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
+  }
 
+  double tree_kin_W_qqxf(
+      int aptype, int bptype, HLV pa, HLV pb,
+      std::vector<Particle> const & partons,
+      HLV plbar, HLV pl, bool WPlus
+  ) {
+    HLV pq,pqbar;
+    if(is_quark(partons[partons.size() - 1])){
+      pq = to_HepLorentzVector(partons[partons.size() - 1]);
+      pqbar = to_HepLorentzVector(partons[partons.size() - 2]);
+    }
+    else{
+      pq = to_HepLorentzVector(partons[partons.size() - 2]);
+      pqbar = to_HepLorentzVector(partons[partons.size() - 1]);
+    }
     auto p1 = to_HepLorentzVector(partons[0]);
     auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
 
-    auto first_after_W = begin(partons) + (the_W-begin(outgoing));
+    auto q0 = pa - p1;
+    auto begin_ladder = begin(partons) + 1;
+    auto end_ladder = end(partons) - 2;
+
+    bool wc;
+    if (aptype==partons[0].type) { //leg b emits w
+      wc = true;}
+    else{
+      wc = false;
+      q0 -=pl + plbar;
+    }
+
+    double current_factor;
+    if (WPlus){
+      current_factor = ME_W_qqxf_current(
+          aptype, bptype, pa, pb,
+          pq, pqbar, p1, pl, plbar, wc
+      );
+    }
+    else{
+      current_factor = ME_W_qqxf_current(
+          aptype, bptype, pa, pb,
+          pq, pqbar, p1, plbar, pl, wc
+      );
+    }
+
+    const double ladder_factor = FKL_ladder_weight(
+        begin_ladder, end_ladder,
+        q0, pa, pb, p1, pn
+    );
+    return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
+  }
 
-    if(first_after_W == begin(partons)) ++first_after_W;
-    else if(first_after_W == end(partons)) --first_after_W;
+  double tree_kin_W_qqxmid(
+      int aptype, int bptype, HLV pa, HLV pb,
+      std::vector<Particle> const & partons,
+      HLV plbar, HLV pl, bool WPlus
+  ) {
+   HLV pq,pqbar;
+    const auto backmidquark = std::find_if(
+        begin(partons)+1, end(partons)-1,
+        [](Particle const & s){ return s.type != pid::gluon; }
+    );
 
-    // t-channel momentum before W
-    auto qW = pa;
-    for(auto parton_it = begin(partons); parton_it != first_after_W; ++parton_it){
-      qW -= to_HepLorentzVector(*parton_it);
+    if (is_quark(backmidquark->type)){
+      pq = to_HepLorentzVector(*backmidquark);
+      pqbar = to_HepLorentzVector(*(backmidquark+1));
     }
+    else {
+      pqbar = to_HepLorentzVector(*backmidquark);
+      pq = to_HepLorentzVector(*(backmidquark+1));
+    }
+
+    auto p1 = to_HepLorentzVector(partons[0]);
+    auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
 
     auto q0 = pa - p1;
+    // t-channel momentum after qqx
+    auto qqxt = q0;
+
+    bool wc, wqq;
+    if (backmidquark->type == -(backmidquark+1)->type){ // Central qqx does not emit
+      wqq=false;
+      if (aptype==partons[0].type) {
+        wc = true;
+      }
+      else{
+        wc = false;
+        q0-=pl+plbar;
+      }
+    }
+    else{
+      wqq = true;
+      wc  = false;
+      qqxt-=pl+plbar;
+    }
+
     auto begin_ladder = begin(partons) + 1;
     auto end_ladder = end(partons) - 1;
+    auto first_after_qqx = (backmidquark+2);
+    for(auto parton_it = begin_ladder; parton_it != first_after_qqx; ++parton_it){
+      qqxt -= to_HepLorentzVector(*parton_it);
+    }
+
+    int nabove = std::distance(begin_ladder, backmidquark-1);
+    int nbelow = std::distance(first_after_qqx, end_ladder);
+
+    std::vector<HLV> partonsHLV;
+    partonsHLV.reserve(partons.size());
+    for (size_t i = 0; i != partons.size(); ++i) {
+      partonsHLV.push_back(to_HepLorentzVector(partons[i]));
+    }
 
     double current_factor;
     if (WPlus){
-      current_factor = ME_W_current(
-          incoming[0].type, incoming[1].type,
-          pn, pb, p1, pa, pl, plbar
+      current_factor = ME_W_qqxmid_current(
+          aptype, bptype, nabove, nbelow, pa, pb,
+          pq, pqbar, partonsHLV, pl, plbar, wqq, wc
       );
     }
     else{
-      current_factor = ME_W_current(
-          incoming[0].type, incoming[1].type,
-          pn, pb, p1, pa, plbar, pl
+      current_factor = ME_W_qqxmid_current(
+          aptype, bptype, nabove, nbelow, pa, pb,
+          pq, pqbar, partonsHLV, plbar, pl, wqq, wc
       );
-}
+    }
 
     const double ladder_factor = FKL_ladder_weight(
-        begin_ladder, first_after_W,
+        begin_ladder, backmidquark-1,
         q0, pa, pb, p1, pn
     )*FKL_ladder_weight(
-        begin_ladder, end_ladder,
-        pa - p1, pa, pb, p1, pn
-    );
-    return current_factor*9./8.*ladder_factor;
+        first_after_qqx, end_ladder,
+        qqxt, pa, pb, p1, pn
+                        );
+    return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
+    }
   }
 
+  double MatrixElement::tree_kin_W(
+      std::array<Particle, 2> const & incoming,
+      std::vector<Particle> const & outgoing,
+      std::unordered_map<int, std::vector<Particle>> const & decays,
+      bool WPlus,
+      bool check_momenta
+  ) const {
+    HLV plbar, pl;
+    for (auto& x: decays) {
+      if (x.second.at(0).type < 0){
+        plbar = to_HepLorentzVector(x.second.at(0));
+        pl = to_HepLorentzVector(x.second.at(1));
+      }
+      else{
+        pl = to_HepLorentzVector(x.second.at(0));
+        plbar = to_HepLorentzVector(x.second.at(1));
+      }
+    }
+    const auto pa = to_HepLorentzVector(incoming[0]);
+    const auto pb = to_HepLorentzVector(incoming[1]);
+    const auto the_W = std::find_if(
+        begin(outgoing), end(outgoing),
+        [](Particle const & s){ return abs(s.type) == pid::Wp; }
+    );
+
+    std::vector<Particle> partons(begin(outgoing), the_W);
+    partons.insert(end(partons), the_W + 1, end(outgoing));
+    partons = tag_extremal_jet_partons(incoming, partons, check_momenta);
+
+    if(has_unob_gluon(incoming, outgoing)){
+      return tree_kin_W_unob(incoming[0].type, incoming[1].type,
+                             pa, pb, partons, plbar, pl, WPlus);
+    }
+    else if(has_unof_gluon(incoming, outgoing)){
+      return tree_kin_W_unof(incoming[0].type, incoming[1].type,
+                             pa, pb, partons, plbar, pl, WPlus);
+    }
+    else if(has_Ex_qqxb(incoming, outgoing)){
+      return tree_kin_W_qqxb(incoming[0].type, incoming[1].type,
+                             pa, pb, partons, plbar, pl, WPlus);
+    }
+    else if(has_Ex_qqxf(incoming, outgoing)){
+      return tree_kin_W_qqxf(incoming[0].type, incoming[1].type,
+                             pa, pb, partons, plbar, pl, WPlus);
+    }
+    else if(has_mid_qqx(outgoing)){
+      return tree_kin_W_qqxmid(incoming[0].type, incoming[1].type,
+                             pa, pb, partons, plbar, pl, WPlus);
+    }
+    return tree_kin_W_FKL(incoming[0].type, incoming[1].type,
+                           pa, pb, partons, plbar, pl, WPlus);
+  }
 
   double MatrixElement::tree_kin_Higgs(
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> const & outgoing,
       bool check_momenta
   ) const {
     if(has_uno_gluon(incoming, outgoing)){
       return tree_kin_Higgs_between(incoming, outgoing, check_momenta);
     }
     if(outgoing.front().type == pid::Higgs){
       return tree_kin_Higgs_first(incoming, outgoing, check_momenta);
     }
     if(outgoing.back().type == pid::Higgs){
       return tree_kin_Higgs_last(incoming, outgoing, check_momenta);
     }
     return tree_kin_Higgs_between(incoming, outgoing, check_momenta);
   }
 
   namespace {
     // Colour acceleration multipliers, for gluons see eq. (7) in arXiv:0910.5113
     // TODO: code duplication with currents.cc
     double K_g(double p1minus, double paminus) {
       return 1./2.*(p1minus/paminus + paminus/p1minus)*(C_A - 1./C_A) + 1./C_A;
     }
     double K_g(
         CLHEP::HepLorentzVector const & pout,
         CLHEP::HepLorentzVector const & pin
     ) {
       if(pin.z() > 0) return K_g(pout.plus(), pin.plus());
       return K_g(pout.minus(), pin.minus());
     }
     double K(
         ParticleID type,
         CLHEP::HepLorentzVector const & pout,
         CLHEP::HepLorentzVector const & pin
     ) {
       if(type == ParticleID::gluon) return K_g(pout, pin);
       return C_F;
     }
     // Colour factor in strict MRK limit
     double K_MRK(ParticleID type) {
       return (type == ParticleID::gluon)?C_A:C_F;
     }
   }
 
   double MatrixElement::MH2_forwardH(
       CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
       ParticleID type2,
       CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
       CLHEP::HepLorentzVector pH,
       double t1, double t2
   ) const{
     ignore(p2out, p2in);
     const double shat = p1in.invariantMass2(p2in);
     // gluon case
 #ifdef RHEJ_BUILD_WITH_QCDLOOP
     if(!param_.Higgs_coupling.use_impact_factors){
       return K(type2, p2out, p2in)*C_A*1./(16*M_PI*M_PI)*t1/t2*MH2gq_outsideH(
           p1out, p1in, p2out, p2in, pH,
           param_.Higgs_coupling.mt, param_.Higgs_coupling.include_bottom,
           param_.Higgs_coupling.mb
       )/(4*(N_C*N_C - 1));
     }
 #endif
     return K_MRK(type2)/C_A*9./2.*shat*shat*(
         C2gHgp(p1in,p1out,pH) + C2gHgm(p1in,p1out,pH)
     )/(t1*t2);
   }
 
   double MatrixElement::tree_kin_Higgs_first(
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> const & outgoing,
       bool check_momenta
   ) const {
     assert(outgoing.front().type == pid::Higgs);
     if(outgoing[1].type != pid::gluon) {
       assert(incoming.front().type == outgoing[1].type);
       return tree_kin_Higgs_between(incoming, outgoing, check_momenta);
     }
     const auto pH = to_HepLorentzVector(outgoing.front());
     const auto partons = tag_extremal_jet_partons(
         incoming,
         std::vector<Particle>(begin(outgoing) + 1, end(outgoing)),
         check_momenta
     );
 
     const auto pa = to_HepLorentzVector(incoming[0]);
     const auto pb = to_HepLorentzVector(incoming[1]);
 
     const auto p1 = to_HepLorentzVector(partons.front());
     const auto pn = to_HepLorentzVector(partons.back());
 
     const auto q0 = pa - p1 - pH;
 
     const double t1 = q0.m2();
     const double t2 = (pn - pb).m2();
 
     return MH2_forwardH(
         p1, pa, incoming[1].type, pn, pb, pH,
         t1, t2
     )*FKL_ladder_weight(
         begin(partons) + 1, end(partons) - 1,
         q0, pa, pb, p1, pn
     );
   }
 
   double MatrixElement::tree_kin_Higgs_last(
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> const & outgoing,
       bool check_momenta
   ) const {
     assert(outgoing.back().type == pid::Higgs);
     if(outgoing[outgoing.size()-2].type != pid::gluon) {
       assert(incoming.back().type == outgoing[outgoing.size()-2].type);
       return tree_kin_Higgs_between(incoming, outgoing, check_momenta);
     }
     const auto pH = to_HepLorentzVector(outgoing.back());
     const auto partons = tag_extremal_jet_partons(
         incoming,
         std::vector<Particle>(begin(outgoing), end(outgoing) - 1),
         check_momenta
     );
 
     const auto pa = to_HepLorentzVector(incoming[0]);
     const auto pb = to_HepLorentzVector(incoming[1]);
 
     auto p1 = to_HepLorentzVector(partons.front());
     const auto pn = to_HepLorentzVector(partons.back());
 
     auto q0 = pa - p1;
 
     const double t1 = q0.m2();
     const double t2 = (pn + pH - pb).m2();
 
     return MH2_forwardH(
         pn, pb, incoming[0].type, p1, pa, pH,
         t2, t1
     )*FKL_ladder_weight(
         begin(partons) + 1, end(partons) - 1,
         q0, pa, pb, p1, pn
     );
   }
 
 
   double MatrixElement::tree_kin_Higgs_between(
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> const & outgoing,
       bool check_momenta
   ) const {
     const auto the_Higgs = std::find_if(
         begin(outgoing), end(outgoing),
         [](Particle const & s){ return s.type == pid::Higgs; }
     );
     assert(the_Higgs != end(outgoing));
     const auto pH = to_HepLorentzVector(*the_Higgs);
     std::vector<Particle> partons(begin(outgoing), the_Higgs);
     partons.insert(end(partons), the_Higgs + 1, end(outgoing));
     partons = tag_extremal_jet_partons(incoming, partons, check_momenta);
 
     const auto pa = to_HepLorentzVector(incoming[0]);
     const auto pb = to_HepLorentzVector(incoming[1]);
 
     auto p1 = to_HepLorentzVector(
         partons[has_unob_gluon(incoming, outgoing)?1:0]
     );
     auto pn = to_HepLorentzVector(
         partons[partons.size() - (has_unof_gluon(incoming, outgoing)?2:1)]
     );
 
     auto first_after_Higgs = begin(partons) + (the_Higgs-begin(outgoing));
     assert(
         (first_after_Higgs == end(partons) && (
             has_unob_gluon(incoming, outgoing)
             || partons.back().type != pid::gluon
         ))
         || first_after_Higgs->rapidity() >= the_Higgs->rapidity()
     );
     assert(
         (first_after_Higgs == begin(partons) && (
             has_unof_gluon(incoming, outgoing)
             || partons.front().type != pid::gluon
         ))
         || (first_after_Higgs-1)->rapidity() <= the_Higgs->rapidity()
     );
     // always treat the Higgs as if it were in between the extremal FKL partons
     if(first_after_Higgs == begin(partons)) ++first_after_Higgs;
     else if(first_after_Higgs == end(partons)) --first_after_Higgs;
 
     // t-channel momentum before Higgs
     auto qH = pa;
     for(auto parton_it = begin(partons); parton_it != first_after_Higgs; ++parton_it){
       qH -= to_HepLorentzVector(*parton_it);
     }
 
     auto q0 = pa - p1;
     auto begin_ladder = begin(partons) + 1;
     auto end_ladder = end(partons) - 1;
 
     double current_factor;
     if(has_unob_gluon(incoming, outgoing)){
       current_factor = C_A*C_A/2.*ME_Higgs_current_unob( // 1/2 = "K_uno"
           incoming[0].type, incoming[1].type,
           pn, pb, to_HepLorentzVector(partons.front()), p1, pa, qH, qH - pH,
           param_.Higgs_coupling.mt,
           param_.Higgs_coupling.include_bottom, param_.Higgs_coupling.mb
       );
       const auto p_unob = to_HepLorentzVector(partons.front());
       q0 -= p_unob;
       p1 += p_unob;
       ++begin_ladder;
     }
     else if(has_unof_gluon(incoming, outgoing)){
       current_factor = C_A*C_A/2.*ME_Higgs_current_unof( // 1/2 = "K_uno"
           incoming[0].type, incoming[1].type,
            to_HepLorentzVector(partons.back()), pn, pb, p1, pa, qH, qH - pH,
           param_.Higgs_coupling.mt,
           param_.Higgs_coupling.include_bottom, param_.Higgs_coupling.mb
       );
       pn += to_HepLorentzVector(partons.back());
       --end_ladder;
     }
     else{
       current_factor = ME_Higgs_current(
           incoming[0].type, incoming[1].type,
           pn, pb, p1, pa, qH, qH - pH,
           param_.Higgs_coupling.mt,
           param_.Higgs_coupling.include_bottom, param_.Higgs_coupling.mb
       );
     }
 
     const double ladder_factor = FKL_ladder_weight(
         begin_ladder, first_after_Higgs,
         q0, pa, pb, p1, pn
     )*FKL_ladder_weight(
         first_after_Higgs, end_ladder,
         qH - pH, pa, pb, p1, pn
     );
     return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
   }
 
   double MatrixElement::tree_param_partons(
       double alpha_s, double mur,
       std::vector<Particle> const & partons
   ) const{
     const double gs2 = 4.*M_PI*alpha_s;
     double wt = std::pow(gs2, partons.size());
     if(param_.log_correction){
       // use alpha_s(q_perp), evolved to mur
       assert(partons.size() >= 2);
       for(size_t i = 1; i < partons.size()-1; ++i){
         wt *= 1 + alpha_s/(2*M_PI)*beta0*log(mur/partons[i].p.perp());
       }
     }
     return wt;
   }
 
   double MatrixElement::tree_param(
       double mur,
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> const & outgoing
   ) const{
     const double alpha_s = alpha_s_(mur);
     auto AWZH_boson = std::find_if(
         begin(outgoing), end(outgoing),
         [](auto const & p){return is_AWZH_boson(p);}
     );
     double AWZH_coupling = 1.;
     if(AWZH_boson != end(outgoing)){
       switch(AWZH_boson->type){
       case pid::Higgs: {
         AWZH_coupling = alpha_s*alpha_s;
         break;
       }
       // TODO
       case pid::Wp:{
         AWZH_coupling = alpha_w*alpha_w/2;
         break;
       }
       case pid::Wm:{
         AWZH_coupling = alpha_w*alpha_w/2;
         break;
       }
       case pid::photon:
       case pid::Z:
       default:
         throw std::logic_error("Emission of boson of unsupported type");
       }
     }
     if(has_unob_gluon(incoming, outgoing)){
       return AWZH_coupling*4*M_PI*alpha_s*tree_param_partons(
           alpha_s, mur, filter_partons({begin(outgoing) + 1, end(outgoing)})
       );
     }
     if(has_unof_gluon(incoming, outgoing)){
       return AWZH_coupling*4*M_PI*alpha_s*tree_param_partons(
           alpha_s, mur, filter_partons({begin(outgoing), end(outgoing) - 1})
       );
     }
     return AWZH_coupling*tree_param_partons(alpha_s, mur, filter_partons(outgoing));
   }
 
   double MatrixElement::tree(
       double mur,
       std::array<Particle, 2> const & incoming,
       std::vector<Particle> const & outgoing,
       std::unordered_map<int, std::vector<Particle>> const & decays,
       bool check_momenta
   ) const {
     return tree_param(mur, incoming, outgoing)*tree_kin(
                 incoming, outgoing, decays, check_momenta
     );
   }
 } // namespace RHEJ
diff --git a/src/Wjets.cc b/src/Wjets.cc
index 7e02575..9f3effe 100644
--- a/src/Wjets.cc
+++ b/src/Wjets.cc
@@ -1,1769 +1,1868 @@
 #include "RHEJ/currents.hh"
 #include "RHEJ/utility.hh"
 #include "RHEJ/Tensor.hh"
 #include "RHEJ/Constants.hh"
 
 #include <array>
 
 #include <iostream>
 
 
 
 namespace { // Helper Functions
   // FKL W Helper Functions
-  void jW (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pe,
-    bool hele, CLHEP::HepLorentzVector pnu, bool helnu, CLHEP::HepLorentzVector pin,
-    bool helin, current cur)
-  {
-    // NOTA BENE: Conventions for W+ --> e+ nu, so that nu is lepton(6), e is anti-lepton(5)
-    // Need to swap e and nu for events with W- --> e- nubar!
-    if (helin==helout && hele==helnu) {
-      CLHEP::HepLorentzVector qa=pout+pe+pnu;
-      CLHEP::HepLorentzVector qb=pin-pe-pnu;
-      double ta(qa.m2()),tb(qb.m2());
-
-      current t65,vout,vin,temp2,temp3,temp5;
-      joo(pnu,helnu,pe,hele,t65);
-      vout[0]=pout.e();
-      vout[1]=pout.x();
-      vout[2]=pout.y();
-      vout[3]=pout.z();
-      vin[0]=pin.e();
-      vin[1]=pin.x();
-      vin[2]=pin.y();
-      vin[3]=pin.z();
-
-      COM brac615=cdot(t65,vout);
-      COM brac645=cdot(t65,vin);
-
-      // prod1565 and prod6465 are zero for Ws (not Zs)!!
-      joo(pout,helout,pnu,helout,temp2);
-      COM prod1665=cdot(temp2,t65);
-      j(pe,helin,pin,helin,temp3);
-      COM prod5465=cdot(temp3,t65);
-
-      joo(pout,helout,pe,helout,temp2);
-      j(pnu,helnu,pin,helin,temp3);
-      j(pout,helout,pin,helin,temp5);
-
-      current term1,term2,term3,sum;
-      cmult(2.*brac615/ta+2.*brac645/tb,temp5,term1);
-      cmult(prod1665/ta,temp3,term2);
-      cmult(-prod5465/tb,temp2,term3);
-
-      cadd(term1,term2,term3,sum);
-
-      cur[0]=sum[0];
-      cur[1]=sum[1];
-      cur[2]=sum[2];
-      cur[3]=sum[3];
-    }
-  }
-
-  void jWbar (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pe, bool hele, CLHEP::HepLorentzVector pnu, bool helnu, CLHEP::HepLorentzVector pin, bool helin, current cur)
-  {
-    // NOTA BENE: Conventions for W+ --> e+ nu, so that nu is lepton(6), e is anti-lepton(5)
-    // Need to swap e and nu for events with W- --> e- nubar!
-    if (helin==helout && hele==helnu) {
-      CLHEP::HepLorentzVector qa=pout+pe+pnu;
-      CLHEP::HepLorentzVector qb=pin-pe-pnu;
-      double ta(qa.m2()),tb(qb.m2());
-
-      current t65,vout,vin,temp2,temp3,temp5;
-      joo(pnu,helnu,pe,hele,t65);
-      vout[0]=pout.e();
-      vout[1]=pout.x();
-      vout[2]=pout.y();
-      vout[3]=pout.z();
-      vin[0]=pin.e();
-      vin[1]=pin.x();
-      vin[2]=pin.y();
-      vin[3]=pin.z();
-
-      COM brac615=cdot(t65,vout);
-      COM brac645=cdot(t65,vin);
-
-      // prod1565 and prod6465 are zero for Ws (not Zs)!!
-      joo(pe,helout,pout,helout,temp2);  //  temp2 is <5|alpha|1>
-      COM prod5165=cdot(temp2,t65);
-      jio(pin,helin,pnu,helin,temp3);      // temp3 is <4|alpha|6>
-      COM prod4665=cdot(temp3,t65);
-
-      joo(pnu,helout,pout,helout,temp2);  // temp2 is now <6|mu|1>
-      jio(pin,helin,pe,helin,temp3);        // temp3 is now <4|mu|5>
-      jio(pin,helin,pout,helout,temp5);     //  temp5 is <4|mu|1>
-
-      current term1,term2,term3,sum;
-      cmult(-2.*brac615/ta-2.*brac645/tb,temp5,term1);
-      cmult(-prod5165/ta,temp3,term2);
-      cmult(prod4665/tb,temp2,term3);
-
-      cadd(term1,term2,term3,sum);
-
-      cur[0]=sum[0];
-      cur[1]=sum[1];
-      cur[2]=sum[2];
-      cur[3]=sum[3];
-    }
-  }
-
 CCurrent jW (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pe, bool hele, CLHEP::HepLorentzVector pnu, bool helnu, CLHEP::HepLorentzVector pin, bool helin)
 {
 
   COM cur[4];
 
   cur[0]=0.;
   cur[1]=0.;
   cur[2]=0.;
   cur[3]=0.;
   CCurrent sum(0.,0.,0.,0.);
 
   // NOTA BENE: Conventions for W+ --> e+ nu, so that nu is lepton(6), e is anti-lepton(5)
   // Need to swap e and nu for events with W- --> e- nubar!
   if (helin==helout && hele==helnu) {
     CLHEP::HepLorentzVector qa=pout+pe+pnu;
     CLHEP::HepLorentzVector qb=pin-pe-pnu;
     double ta(qa.m2()),tb(qb.m2());
 
     CCurrent temp2,temp3,temp5;
     CCurrent t65 = joo(pnu,helnu,pe,hele);
     CCurrent vout(pout.e(),pout.x(),pout.y(),pout.z());
     CCurrent vin(pin.e(),pin.x(),pin.y(),pin.z());
 
     COM brac615=t65.dot(vout);
     COM brac645=t65.dot(vin);
 
 
     // prod1565 and prod6465 are zero for Ws (not Zs)!!
     temp2 = joo(pout,helout,pnu,helout);
     COM prod1665=temp2.dot(t65);
     temp3 = j(pe,helin,pin,helin);
     COM prod5465=temp3.dot(t65);
 
     temp2=joo(pout,helout,pe,helout);
     temp3=j(pnu,helnu,pin,helin);
     temp5=j(pout,helout,pin,helin);
 
     CCurrent term1,term2,term3;
     term1=(2.*brac615/ta+2.*brac645/tb)*temp5;
     term2=(prod1665/ta)*temp3;
     term3=(-prod5465/tb)*temp2;
 
     sum=term1+term2+term3;
   }
 
   return sum;
 }
 
 CCurrent jWbar (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pe, bool hele, CLHEP::HepLorentzVector pnu, bool helnu, CLHEP::HepLorentzVector pin, bool helin)
 {
 
     COM cur[4];
 
     cur[0]=0.;
     cur[1]=0.;
     cur[2]=0.;
     cur[3]=0.;
     CCurrent sum(0.,0.,0.,0.);
 
   // NOTA BENE: Conventions for W+ --> e+ nu, so that nu is lepton(6), e is anti-lepton(5)
   // Need to swap e and nu for events with W- --> e- nubar!
   if (helin==helout && hele==helnu) {
     CLHEP::HepLorentzVector qa=pout+pe+pnu;
     CLHEP::HepLorentzVector qb=pin-pe-pnu;
     double ta(qa.m2()),tb(qb.m2());
 
     CCurrent temp2,temp3,temp5;
     CCurrent t65 = joo(pnu,helnu,pe,hele);
     CCurrent vout(pout.e(),pout.x(),pout.y(),pout.z());
     CCurrent vin(pin.e(),pin.x(),pin.y(),pin.z());
 
     COM brac615=t65.dot(vout);
     COM brac645=t65.dot(vin);
 
     // prod1565 and prod6465 are zero for Ws (not Zs)!!
     temp2 = joo(pe,helout,pout,helout);  //  temp2 is <5|alpha|1>
     COM prod5165=temp2.dot(t65);
     temp3 = jio(pin,helin,pnu,helin);      // temp3 is <4|alpha|6>
     COM prod4665=temp3.dot(t65);
 
     temp2=joo(pnu,helout,pout,helout);  // temp2 is now <6|mu|1>
     temp3=jio(pin,helin,pe,helin);        // temp3 is now <4|mu|5>
     temp5=jio(pin,helin,pout,helout);     //  temp5 is <4|mu|1>
 
     CCurrent term1,term2,term3;
     term1 =(-2.*brac615/ta-2.*brac645/tb)*temp5;
     term2 =(-prod5165/ta)*temp3;
     term3 =(prod4665/tb)*temp2;
 
     sum = term1 + term2 + term3;
   }
 
   return sum;
 }
 
   // Relevant W+Jets Unordered Contribution Helper Functions
   // W+Jets Uno
   double jM2Wuno(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1,CLHEP::HepLorentzVector plbar, CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pa, bool h1, CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector pb, bool h2, bool pol)
   {
     static bool is_sigma_index_set(false);
 
     if(!is_sigma_index_set){
       //std::cout<<"Setting sigma_index...." << std::endl;
       if(init_sigma_index())
   is_sigma_index_set = true;
       else
   return 0.;
     }
 
     CLHEP::HepLorentzVector pW = pl+plbar;
     CLHEP::HepLorentzVector q1g=pa-pW-p1-pg;
     CLHEP::HepLorentzVector q1 = pa-p1-pW;
     CLHEP::HepLorentzVector q2 = p2-pb;
 
     const double taW  = (pa-pW).m2();
     const double taW1 = (pa-pW-p1).m2();
     const double tb2  = (pb-p2).m2();
     const double tb2g = (pb-p2-pg).m2();
     const double s1W  = (p1+pW).m2();
     const double s1gW = (p1+pW+pg).m2();
     const double s1g  = (p1+pg).m2();
     const double tag  = (pa-pg).m2();
     const double taWg = (pa-pW-pg).m2();
-    const double ca = RHEJ::C_A;
-    const double cf = RHEJ::C_F; ///<TODO directly use RHEJ constants
 
     //use p1 as ref vec in pol tensor
     Tensor<1,4> epsg = eps(pg,p2,pol);
     Tensor<1,4> epsW = TCurrent(pl,false,plbar,false);
     Tensor<1,4> j2b = TCurrent(p2,h2,pb,h2);
 
     Tensor<1,4> Tq1q2 = Construct1Tensor((q1+q2)/taW1 + (pb/pb.dot(pg)
       + p2/p2.dot(pg)) * tb2/(2*tb2g));
     Tensor<1,4> Tq1g = Construct1Tensor((-pg-q1))/taW1;
     Tensor<1,4> Tq2g = Construct1Tensor((pg-q2));
     Tensor<1,4> TqaW = Construct1Tensor((pa-pW));//pa-pw
     Tensor<1,4> Tqag = Construct1Tensor((pa-pg));
     Tensor<1,4> TqaWg = Construct1Tensor((pa-pg-pW));
     Tensor<1,4> Tp1g = Construct1Tensor((p1+pg));
     Tensor<1,4> Tp1W = Construct1Tensor((p1+pW));//p1+pw
     Tensor<1,4> Tp1gW = Construct1Tensor((p1+pg+pW));//p1+pw+pg
 
     Tensor<2,4> g=Metric();
 
     Tensor<3,4> J31a = T3Current(p1, h1, pa, h1);
     Tensor<2,4> J2_qaW =J31a.contract(TqaW/taW, 2);
     Tensor<2,4> J2_p1W =J31a.contract(Tp1W/s1W, 2);
     Tensor<3,4> L1a =J2_qaW.leftprod(Tq1q2);
     Tensor<3,4> L1b =J2_p1W.leftprod(Tq1q2);
     Tensor<3,4> L2a = J2_qaW.leftprod(Tq1g);
     Tensor<3,4> L2b = J2_p1W.leftprod(Tq1g);
     Tensor<3,4> L3 = (g.rightprod(J2_qaW.contract(Tq2g,1)+J2_p1W.contract(Tq2g,2)))/taW1;
     Tensor<3,4> L(0.);
 
     Tensor<5,4> J51a = T5Current(p1, h1, pa, h1);
 
     Tensor<4,4> J_qaW = J51a.contract(TqaW,4);
     Tensor<4,4> J_qag = J51a.contract(Tqag,4);
     Tensor<4,4> J_p1gW = J51a.contract(Tp1gW,4);
 
     Tensor<3,4> U1a = J_qaW.contract(Tp1g,2);
     Tensor<3,4> U1b = J_p1gW.contract(Tp1g,2);
     Tensor<3,4> U1c = J_p1gW.contract(Tp1W,2);
     Tensor<3,4> U1(0.);
 
     Tensor<3,4> U2a = J_qaW.contract(TqaWg,2);
     Tensor<3,4> U2b = J_qag.contract(TqaWg,2);
     Tensor<3,4> U2c = J_qag.contract(Tp1W,2);
     Tensor<3,4> U2(0.);
 
     for(int nu=0; nu<4;nu++){
       for(int mu=0;mu<4;mu++){
         for(int rho=0;rho<4;rho++){
           L.Set(nu, mu, rho, L1a.at(nu,mu,rho) + L1b.at(nu,rho,mu)
             + L2a.at(mu,nu,rho) + L2b.at(mu,rho,nu) + L3.at(mu,nu,rho));
           U1.Set(nu, mu, rho, U1a.at(nu, mu, rho) / (s1g*taW)
             + U1b.at(nu,rho,mu) / (s1g*s1gW) + U1c.at(rho,nu,mu) / (s1W*s1gW));
           U2.Set(nu,mu,rho,U2a.at(mu,nu,rho) / (taWg*taW)
             + U2b.at(mu,rho,nu) / (taWg*tag) + U2c.at(rho,mu,nu) / (s1W*tag));
         }
       }
     }
 
     COM X = ((((U1-L).contract(epsW,3)).contract(j2b,2)).contract(epsg,1)).at(0);
     COM Y = ((((U2+L).contract(epsW,3)).contract(j2b,2)).contract(epsg,1)).at(0);
 
-    double amp = ca*cf*cf/2.*(norm(X)+norm(Y)) - cf/2.*(X*conj(Y)).real();
+    double amp = RHEJ::C_A*RHEJ::C_F*RHEJ::C_F/2.*(norm(X)+norm(Y)) - RHEJ::C_F/2.*(X*conj(Y)).real();
 
     double t1 = q1g.m2();
     double t2 = q2.m2();
 
     //Divide by t-channels
     amp/=(t1*t2);
 
     //Average over initial states
-    amp/=(4.*ca*ca);
+    amp/=(4.*RHEJ::C_A*RHEJ::C_A);
 
     return amp;
   }
 
 
 
   // Relevant Wqqx Helper Functions.
   //g->qxqlxl (Calculates gluon to qqx Current. See JV_\mu in WSubleading Notes)
   Tensor <1,4> gtqqxW(CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar,CLHEP::HepLorentzVector pl,CLHEP::HepLorentzVector plbar){
 
     double s2AB=(pl+plbar+pq).m2();
     double s3AB=(pl+plbar+pqbar).m2();
 
     Tensor<1,4> Tpq = Construct1Tensor(pq);
     Tensor<1,4> Tpqbar = Construct1Tensor(pqbar);
     Tensor<1,4> TAB = Construct1Tensor(pl+plbar);
 
     // Define llx current.
     Tensor<1,4> ABCur = TCurrent(pl, false, plbar, false);
 
     //blank 3 Gamma Current
     Tensor<3,4> JV23 = T3Current(pq,false,pqbar,false);
 
     // Components of g->qqW before W Contraction
     Tensor<2,4> JV1 = JV23.contract((Tpq + TAB),2)/(s2AB);
     Tensor<2,4> JV2 = JV23.contract((Tpqbar + TAB),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,4> JVCur = (JV1.contract(ABCur,1) - JV2.contract(ABCur,2))*COM(0.,-1.);
 
     return JVCur;
   }
 
   // Helper Functions Calculate the Crossed Contribution
   Tensor <2,4> MCrossW(CLHEP::HepLorentzVector pa,CLHEP::HepLorentzVector p1,CLHEP::HepLorentzVector pb,CLHEP::HepLorentzVector p4, CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar,CLHEP::HepLorentzVector pl,CLHEP::HepLorentzVector plbar, std::vector<HLV> partons, int nabove){
 
     // Useful propagator factors
     double s2AB=(pl+plbar+pq).m2();
     double s3AB=(pl+plbar+pqbar).m2();
 
     CLHEP::HepLorentzVector q1, q3;
     q1=pa;
     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();
 
     Tensor<1,4> Tp1 = Construct1Tensor(p1);
     Tensor<1,4> Tp4 = Construct1Tensor(p4);
     Tensor<1,4> Tpa = Construct1Tensor(pa);
     Tensor<1,4> Tpb = Construct1Tensor(pb);
     Tensor<1,4> Tpq = Construct1Tensor(pq);
     Tensor<1,4> Tpqbar = Construct1Tensor(pqbar);
     Tensor<1,4> TAB = Construct1Tensor(pl+plbar);
     Tensor<1,4> Tq1 = Construct1Tensor(q1);
     Tensor<1,4> Tq3 = Construct1Tensor(q3);
     Tensor<2,4> g=Metric();
 
     // Define llx current.
     Tensor<1,4> ABCur = TCurrent(pl, false, plbar,false);
 
     //Blank 5 gamma Current
     Tensor<5,4> J523 = T5Current(pq,false,pqbar,false);
 
     // 4 gamma currents (with 1 contraction already).
     Tensor<4,4> J_q3q = J523.contract((Tq3+Tpq),2);
     Tensor<4,4> J_2AB = J523.contract((Tpq+TAB),2);
 
     // Components of Crossed Vertex Contribution
     Tensor<3,4> Xcro1 = J_q3q.contract((Tpqbar + TAB),3);
     Tensor<3,4> Xcro2 = J_q3q.contract((Tq1-Tpqbar),3);
     Tensor<3,4> Xcro3 = J_2AB.contract((Tq1-Tpqbar),3);
 
     // Term Denominators Taken Care of at this stage
     Tensor<2,4> Xcro1Cont = Xcro1.contract(ABCur,3)/(tcro1*s3AB);
     Tensor<2,4> Xcro2Cont = Xcro2.contract(ABCur,2)/(tcro1*tcro2);
     Tensor<2,4> Xcro3Cont = Xcro3.contract(ABCur,1)/(s2AB*tcro2);
 
     //Initialise the Crossed Vertex Object
     Tensor<2,4> Xcro(0.);
 
     for(int mu=0; mu<4;mu++){
       for(int nu=0;nu<4;nu++){
         Xcro.Set(mu,nu, -(-Xcro1Cont.at(nu,mu)+Xcro2Cont.at(nu,mu)+Xcro3Cont.at(nu,mu)));
       }
     }
 
 
     return Xcro;
   }
 
   // Helper Functions Calculate the Uncrossed Contribution
   Tensor <2,4> MUncrossW(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector pb, CLHEP::HepLorentzVector p4, CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar,CLHEP::HepLorentzVector pl,CLHEP::HepLorentzVector plbar, std::vector<HLV> partons, int nabove){
 
     double s2AB=(pl+plbar+pq).m2();
     double s3AB=(pl+plbar+pqbar).m2();
 
     CLHEP::HepLorentzVector q1, q3;
     q1=pa;
     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();
 
     Tensor<1,4> Tp1 = Construct1Tensor(p1);
     Tensor<1,4> Tp4 = Construct1Tensor(p4);
     Tensor<1,4> Tpa = Construct1Tensor(pa);
     Tensor<1,4> Tpb = Construct1Tensor(pb);
     Tensor<1,4> Tpq = Construct1Tensor(pq);
     Tensor<1,4> Tpqbar = Construct1Tensor(pqbar);
     Tensor<1,4> TAB = Construct1Tensor(pl+plbar);
     Tensor<1,4> Tq1 = Construct1Tensor(q1);
     Tensor<1,4> Tq3 = Construct1Tensor(q3);
     Tensor<2,4> g=Metric();
 
 
     // Define llx current.
     Tensor<1,4> ABCur = TCurrent(pl, false, plbar, false);
 
     //Blank 5 gamma Current
     Tensor<5,4> J523 = T5Current(pq,false,pqbar,false);
 
     // 4 gamma currents (with 1 contraction already).
     Tensor<4,4> J_2AB = J523.contract((Tpq+TAB),2);
     Tensor<4,4> J_q1q = J523.contract((Tq1-Tpq),2);
 
     // 2 Contractions taken care of.
     Tensor<3,4> Xunc1 = J_2AB.contract((Tq3+Tpqbar),3);
     Tensor<3,4> Xunc2 = J_q1q.contract((Tq3+Tpqbar),3);
     Tensor<3,4> Xunc3 = J_q1q.contract((Tpqbar+TAB),3);
 
     // Term Denominators Taken Care of at this stage
     Tensor<2,4> Xunc1Cont = Xunc1.contract(ABCur,1)/(s2AB*tunc2);
     Tensor<2,4> Xunc2Cont = Xunc2.contract(ABCur,2)/(tunc1*tunc2);
     Tensor<2,4> Xunc3Cont = Xunc3.contract(ABCur,3)/(tunc1*s3AB);
 
     //Initialise the Uncrossed Vertex Object
     Tensor<2,4> Xunc(0.);
 
     for(int mu=0; mu<4;mu++){
       for(int nu=0;nu<4;nu++){
         Xunc.Set(mu,nu,-(- Xunc1Cont.at(mu,nu)+Xunc2Cont.at(mu,nu) +Xunc3Cont.at(mu,nu)));
       }
     }
 
     return Xunc;
   }
 
 
   // Helper Functions Calculate the g->qqxW (Eikonal) Contributions
   Tensor <2,4> MSymW(CLHEP::HepLorentzVector pa,CLHEP::HepLorentzVector p1,CLHEP::HepLorentzVector pb,CLHEP::HepLorentzVector p4, CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar,CLHEP::HepLorentzVector pl,CLHEP::HepLorentzVector plbar, std::vector<HLV> partons, int nabove){
 
     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();
 
     CLHEP::HepLorentzVector q1,q3;
     q1=pa;
     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();
 
     //Define Tensors to be used
     Tensor<1,4> Tp1 = Construct1Tensor(p1);
     Tensor<1,4> Tp4 = Construct1Tensor(p4);
     Tensor<1,4> Tpa = Construct1Tensor(pa);
     Tensor<1,4> Tpb = Construct1Tensor(pb);
     Tensor<1,4> Tpq = Construct1Tensor(pq);
     Tensor<1,4> Tpqbar = Construct1Tensor(pqbar);
     Tensor<1,4> TAB = Construct1Tensor(pl+plbar);
     Tensor<1,4> Tq1 = Construct1Tensor(q1);
     Tensor<1,4> Tq3 = Construct1Tensor(q3);
     Tensor<2,4> g=Metric();
 
     // g->qqW Current (Factors of sqrt2 dealt with in this function.)
     Tensor<1,4> JV = gtqqxW(pq,pqbar,pl,plbar);
 
     // 1a gluon emisson Contribution
     Tensor<3,4> X1a = g.rightprod(Tp1*(t1/(s12+s13+s1A+s1B)) + Tpa*(t1/(sa2+sa3+saA+saB)));
     Tensor<2,4> X1aCont = X1a.contract(JV,3);
 
     //4b gluon emission Contribution
     Tensor<3,4> X4b = g.rightprod(Tp4*(t3/(s42+s43+s4A+s4B)) + Tpb*(t3/(sb2+sb3+sbA+sbB)));
     Tensor<2,4> X4bCont = X4b.contract(JV,3);
 
     //Set up each term of 3G diagram.
     Tensor<3,4> X3g1 = g.leftprod(Tq1+Tpq+Tpqbar+TAB);
     Tensor<3,4> X3g2 = g.leftprod(Tq3-Tpq-Tpqbar-TAB);
     Tensor<3,4> X3g3 = g.leftprod((Tq1+Tq3));
 
     // Note the contraction of indices changes term by term
     Tensor<2,4> X3g1Cont = X3g1.contract(JV,3);
     Tensor<2,4> X3g2Cont = X3g2.contract(JV,2);
     Tensor<2,4> 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,4>Xsym(0.);
 
     for(int mu=0; mu<4;mu++){
       for(int nu=0;nu<4;nu++){
   Xsym.Set(mu,nu, (X3g1Cont.at(nu,mu) + X3g2Cont.at(mu,nu) - X3g3Cont.at(nu,mu))
      + (X1aCont.at(mu,nu) - X4bCont.at(mu,nu)) );
       }
     }
     return Xsym/s23AB;
   }
 
   Tensor <2,4> MCross(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar, std::vector<HLV> partons, bool hq, int nabove){
 
     CLHEP::HepLorentzVector q1;
     q1=pa;
     for(int i=0;i<nabove+1;i++){
       q1-=partons.at(i);
     }
 
     double t2=(q1-pqbar).m2();
 
     Tensor<1,4> Tq1 = Construct1Tensor(q1-pqbar);
 
     //Blank 3 gamma Current
     Tensor<3,4> J323 = T3Current(pq,hq,pqbar,hq);
 
     // 2 gamma current (with 1 contraction already).
     Tensor<2,4> XCroCont = J323.contract((Tq1),2)/(t2);
 
     //Initialise the Crossed Vertex
     Tensor<2,4> Xcro(0.);
 
     for(int mu=0; mu<4;mu++){
       for(int nu=0;nu<4;nu++){
         Xcro.Set(mu,nu, (XCroCont.at(nu,mu)));
       }
     }
 
     return Xcro;
   }
 
 
   // Helper Functions Calculate the Uncrossed Contribution
   Tensor <2,4> MUncross(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar, std::vector<HLV> partons, bool hq, int nabove){
 
     CLHEP::HepLorentzVector q1;
     q1=pa;
     for(int i=0;i<nabove+1;i++){
       q1-=partons.at(i);
     }
     double t2 = (q1-pq).m2();
 
     Tensor<1,4> Tq1 = Construct1Tensor(q1-pq);
 
     //Blank 3 gamma Current
     Tensor<3,4> J323 = T3Current(pq,hq,pqbar,hq);
 
     // 2 gamma currents (with 1 contraction already).
     Tensor<2,4> XUncCont = J323.contract((Tq1),2)/t2;
 
     //Initialise the Uncrossed Vertex
     Tensor<2,4> Xunc(0.);
 
     for(int mu=0; mu<4;mu++){
       for(int nu=0;nu<4;nu++){
   Xunc.Set(mu,nu,-(XUncCont.at(mu,nu)));
       }
     }
 
     return Xunc;
   }
 
 
   // Helper Functions Calculate the Eikonal Contributions
   Tensor <2,4> MSym(CLHEP::HepLorentzVector pa,CLHEP::HepLorentzVector p1,CLHEP::HepLorentzVector pb,CLHEP::HepLorentzVector p4, CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar, std::vector<HLV> partons, bool hq, int nabove){
 
     CLHEP::HepLorentzVector q1, q3;
     q1=pa;
     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();
 
     //Define Tensors to be used
     Tensor<1,4> Tp1 = Construct1Tensor(p1);
     Tensor<1,4> Tp4 = Construct1Tensor(p4);
     Tensor<1,4> Tpa = Construct1Tensor(pa);
     Tensor<1,4> Tpb = Construct1Tensor(pb);
     Tensor<1,4> Tpq = Construct1Tensor(pq);
     Tensor<1,4> Tpqbar = Construct1Tensor(pqbar);
     Tensor<1,4> Tq1 = Construct1Tensor(q1);
     Tensor<1,4> Tq3 = Construct1Tensor(q3);
     Tensor<2,4> g=Metric();
 
     Tensor<1,4> qqxCur = TCurrent(pq, hq, pqbar, hq);
 
     // // 1a gluon emisson Contribution
     Tensor<3,4> X1a = g.rightprod(Tp1*(t1/(s12+s13))+Tpa*(t1/(sa2+sa3)));
     Tensor<2,4> X1aCont = X1a.contract(qqxCur,3);
 
     // //4b gluon emission Contribution
     Tensor<3,4> X4b = g.rightprod(Tp4*(t3/(s42+s43)) + Tpb*(t3/(sb2+sb3)));
     Tensor<2,4> X4bCont = X4b.contract(qqxCur,3);
 
     // New Formulation Corresponding to New Analytics
     Tensor<3,4> X3g1 = g.leftprod(Tq1+Tpq+Tpqbar);
     Tensor<3,4> X3g2 = g.leftprod(Tq3-Tpq-Tpqbar);
     Tensor<3,4> X3g3 = g.leftprod((Tq1+Tq3));
 
     // Note the contraction of indices changes term by term
     Tensor<2,4> X3g1Cont = X3g1.contract(qqxCur,3);
     Tensor<2,4> X3g2Cont = X3g2.contract(qqxCur,2);
     Tensor<2,4> X3g3Cont = X3g3.contract(qqxCur,1);
 
     Tensor<2,4>Xsym(0.);
 
     for(int mu=0; mu<4;mu++){
       for(int nu=0;nu<4;nu++){
         Xsym.Set(mu, nu, COM(0,1) * ( (X3g1Cont.at(nu,mu) + X3g2Cont.at(mu,nu)
           - X3g3Cont.at(nu,mu)) + (X1aCont.at(mu,nu) - X4bCont.at(mu,nu)) ) );
       }
     }
     return Xsym/s23;
   }
 
   Tensor <1,4> jW4bEmit(HLV pb, HLV p4, HLV pl, HLV plbar, bool aqlinepb){
     // Build the external quark line W Emmision
     Tensor<1,4> ABCurr = TCurrent(pl, false, plbar, false)/2;
     Tensor<1,4> Tp4W = Construct1Tensor((p4+pl+plbar));//p4+pw
     Tensor<1,4> TpbW = Construct1Tensor((pb-pl-plbar));//pb-pw
 
     Tensor<3,4> J4bBlank;
     if (aqlinepb){
       J4bBlank = T3Current(pb,false,p4,false);
     }
     else{
       J4bBlank = T3Current(p4,false,pb,false);
     }
     double t4AB = (p4+pl+plbar).m2();
     double tbAB = (pb-pl-plbar).m2();
 
     Tensor<2,4> J4b1 = (J4bBlank.contract(Tp4W,2))/t4AB;
     Tensor<2,4> J4b2 = (J4bBlank.contract(TpbW,2))/tbAB;
 
     Tensor<2,4> T4bmMom(0.);
 
     if (aqlinepb){
       for(int mu=0; mu<4;mu++){
         for(int nu=0;nu<4;nu++){
           T4bmMom.Set(mu,nu, (J4b1.at(nu,mu) + J4b2.at(mu,nu))*(COM(-1,0)));
         }
       }
     }
     else{
       for(int mu=0; mu<4;mu++){
         for(int nu=0;nu<4;nu++){
           T4bmMom.Set(nu,mu, (J4b1.at(nu,mu) + J4b2.at(mu,nu)));
         }
       }
     }
     Tensor<1,4> T4bm = T4bmMom.contract(ABCurr,1);
 
     return T4bm;
   }
 
 } // Anonymous Namespace helper functions
 
-
-
 //Functions which can be called elsewhere (declarations in currents.hh).
 
 // W+Jets Unordered Contributions
-
 //qQ->qQWg_unob
 double junobMWqQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg)
 // Calculates the square of the current contractions for qQ->qenuQ scattering
 // p1: quark (with W emittance)
 // p2: Quark
 {
   CCurrent mj1m,mj2p,mj2m;
   CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
   CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);
   CLHEP::HepLorentzVector q3=-(p2in-p2out);
 
   mj1m=jW(p1out,false,pe,false,pnu,false,p1in,false);
   mj2p=j(p2out,true,p2in,true);
   mj2m=j(p2out,false,p2in,false);
 
 
   // Dot products of these which occur again and again
   COM MWmp=mj1m.dot(mj2p);  // And now for the Higgs ones
   COM MWmm=mj1m.dot(mj2m);
 
   CCurrent jgbm,jgbp,j2gm,j2gp;
   j2gp=joo(p2out,true,pg,true);
   j2gm=joo(p2out,false,pg,false);
   jgbp=j(pg,true,p2in,true);
   jgbm=j(pg,false,p2in,false);
 
   CCurrent qsum(q2+q3);
 
   CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
   CCurrent p2o(p2out);
   CCurrent p2i(p2in);
 
 
   Lmm=((-1.)*qsum*(MWmm) + (-2.*mj1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmm/2.))/q3.m2();
   Lmp=((-1.)*qsum*(MWmp) + (-2.*mj1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmp/2.))/q3.m2();
 
   U1mm=(jgbm.dot(mj1m)*j2gm+2.*p2o*MWmm)/(p2out+pg).m2();
   U1mp=(jgbp.dot(mj1m)*j2gp+2.*p2o*MWmp)/(p2out+pg).m2();
 
   U2mm=((-1.)*j2gm.dot(mj1m)*jgbm+2.*p2i*MWmm)/(p2in-pg).m2();
   U2mp=((-1.)*j2gp.dot(mj1m)*jgbp+2.*p2i*MWmp)/(p2in-pg).m2();
 
 
-  const double cf=RHEJ::C_F;
   double amm,amp;
 
-  amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
-  amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
+  amm=RHEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1mm+U2mm);
+  amp=RHEJ::C_F*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1mp+U2mp);
 
   double ampsq=-(amm+amp);
 
   // Now add the t-channels
   double th=q2.m2()*q1.m2();
   ampsq/=th;
   ampsq/=16.;
 
   return ampsq;
 
 
 }
 
 //qQbar->qQbarWg_unob
 double junobMWqQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg)
 // Calculates the square of the current contractions for qQ->qenuQ scattering
 // p1: quark (with W emittance)
 // p2: Quark
 {
   CCurrent mj1m,mj2p,mj2m;
   CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
   CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);
   CLHEP::HepLorentzVector q3=-(p2in-p2out);
 
   mj1m=jW(p1out,false,pe,false,pnu,false,p1in,false);
   mj2p=jio(p2in,true,p2out,true);
   mj2m=jio(p2in,false,p2out,false);
 
 
   // Dot products of these which occur again and again
   COM MWmp=mj1m.dot(mj2p);  // And now for the Higgs ones
   COM MWmm=mj1m.dot(mj2m);
 
   CCurrent jgbm,jgbp,j2gm,j2gp;
   j2gp=joo(pg,true,p2out,true);
   j2gm=joo(pg,false,p2out,false);
   jgbp=jio(p2in,true,pg,true);
   jgbm=jio(p2in,false,pg,false);
 
   CCurrent qsum(q2+q3);
 
   CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
   CCurrent p2o(p2out);
   CCurrent p2i(p2in);
 
 
   Lmm=((-1.)*qsum*(MWmm) + (-2.*mj1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmm/2.))/q3.m2();
   Lmp=((-1.)*qsum*(MWmp) + (-2.*mj1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmp/2.))/q3.m2();
 
   U1mm=(jgbm.dot(mj1m)*j2gm+2.*p2o*MWmm)/(p2out+pg).m2();
   U1mp=(jgbp.dot(mj1m)*j2gp+2.*p2o*MWmp)/(p2out+pg).m2();
 
   U2mm=((-1.)*j2gm.dot(mj1m)*jgbm+2.*p2i*MWmm)/(p2in-pg).m2();
   U2mp=((-1.)*j2gp.dot(mj1m)*jgbp+2.*p2i*MWmp)/(p2in-pg).m2();
 
-
-  const double cf=RHEJ::C_F;
   double amm,amp;
 
-  amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
-  amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
+  amm=RHEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1mm+U2mm);
+  amp=RHEJ::C_F*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1mp+U2mp);
 
   double ampsq=-(amm+amp);
 
   // Now add the t-channels
   double th=q2.m2()*q1.m2();
   ampsq/=th;
   ampsq/=16.;
 
   return ampsq;
 
 
 }
 
 //qbarQ->qbarQWg_unob
 double junobMWqbarQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg)
 // Calculates the square of the current contractions for qQ->qenuQ scattering
 // p1: quark (with W emittance)
 // p2: Quark
 {
   CCurrent mj1m,mj2p,mj2m;
   CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
   CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);
   CLHEP::HepLorentzVector q3=-(p2in-p2out);
 
   mj1m=jWbar(p1out,false,pe,false,pnu,false,p1in,false);
   mj2p=j(p2out,true,p2in,true);
   mj2m=j(p2out,false,p2in,false);
 
 
   // Dot products of these which occur again and again
   COM MWmp=mj1m.dot(mj2p);  // And now for the Higgs ones
   COM MWmm=mj1m.dot(mj2m);
 
   CCurrent jgbm,jgbp,j2gm,j2gp;
   j2gp=joo(p2out,true,pg,true);
   j2gm=joo(p2out,false,pg,false);
   jgbp=j(pg,true,p2in,true);
   jgbm=j(pg,false,p2in,false);
 
   CCurrent qsum(q2+q3);
 
   CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
   CCurrent p2o(p2out);
   CCurrent p2i(p2in);
 
 
   Lmm=((-1.)*qsum*(MWmm) + (-2.*mj1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmm/2.))/q3.m2();
   Lmp=((-1.)*qsum*(MWmp) + (-2.*mj1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmp/2.))/q3.m2();
 
   U1mm=(jgbm.dot(mj1m)*j2gm+2.*p2o*MWmm)/(p2out+pg).m2();
   U1mp=(jgbp.dot(mj1m)*j2gp+2.*p2o*MWmp)/(p2out+pg).m2();
 
   U2mm=((-1.)*j2gm.dot(mj1m)*jgbm+2.*p2i*MWmm)/(p2in-pg).m2();
   U2mp=((-1.)*j2gp.dot(mj1m)*jgbp+2.*p2i*MWmp)/(p2in-pg).m2();
 
 
-  const double cf=RHEJ::C_F;
   double amm,amp;
 
-  amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
-  amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
+  amm=RHEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1mm+U2mm);
+  amp=RHEJ::C_F*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1mp+U2mp);
 
   double ampsq=-(amm+amp);
 
   // Now add the t-channels
   double th=q2.m2()*q1.m2();
   ampsq/=th;
   ampsq/=16.;
 
   return ampsq;
 
 
 }
 
 //qbarQbar->qbarQbarWg_unob
 double junobMWqbarQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg)
 // Calculates the square of the current contractions for qQ->qenuQ scattering
 // p1: quark (with W emittance)
 // p2: Quark
 {
   CCurrent mj1m,mj2p,mj2m;
   CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
   CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);
   CLHEP::HepLorentzVector q3=-(p2in-p2out);
 
   mj1m=jWbar(p1out,false,pe,false,pnu,false,p1in,false);
   mj2p=jio(p2in,true,p2out,true);
   mj2m=jio(p2in,false,p2out,false);
 
 
   // Dot products of these which occur again and again
   COM MWmp=mj1m.dot(mj2p);  // And now for the Higgs ones
   COM MWmm=mj1m.dot(mj2m);
 
   CCurrent jgbm,jgbp,j2gm,j2gp;
   j2gp=joo(pg,true,p2out,true);
   j2gm=joo(pg,false,p2out,false);
   jgbp=jio(p2in,true,pg,true);
   jgbm=jio(p2in,false,pg,false);
 
   CCurrent qsum(q2+q3);
 
   CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
   CCurrent p2o(p2out);
   CCurrent p2i(p2in);
 
 
   Lmm=((-1.)*qsum*(MWmm) + (-2.*mj1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmm/2.))/q3.m2();
   Lmp=((-1.)*qsum*(MWmp) + (-2.*mj1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmp/2.))/q3.m2();
 
   U1mm=(jgbm.dot(mj1m)*j2gm+2.*p2o*MWmm)/(p2out+pg).m2();
   U1mp=(jgbp.dot(mj1m)*j2gp+2.*p2o*MWmp)/(p2out+pg).m2();
 
   U2mm=((-1.)*j2gm.dot(mj1m)*jgbm+2.*p2i*MWmm)/(p2in-pg).m2();
   U2mp=((-1.)*j2gp.dot(mj1m)*jgbp+2.*p2i*MWmp)/(p2in-pg).m2();
 
 
-  const double cf=RHEJ::C_F;
   double amm,amp;
 
-  amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
-  amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
+  amm=RHEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1mm+U2mm);
+  amp=RHEJ::C_F*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1mp+U2mp);
 
   double ampsq=-(amm+amp);
 
   // Now add the t-channels
   double th=q2.m2()*q1.m2();
   ampsq/=th;
   ampsq/=16.;
 
   return ampsq;
 
 
 }
 
 ////////////////////////////////////////////////////////////////////
 //qQ->qQWg_unof
 double junofMWgqQ (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for qQ->qenuQ scattering
 // p1: quark (with W emittance)
 // p2: Quark
 {
   CCurrent mj2m,mj1p,mj1m;
   CLHEP::HepLorentzVector q1=p1in-p1out;
   CLHEP::HepLorentzVector qg=p1in-p1out-pg;
   CLHEP::HepLorentzVector q2=-(p2in-p2out-pe-pnu);
 
   mj2m=jW(p2out,false,pe,false,pnu,false,p2in,false);
   mj1p=j(p1out,true,p1in,true);
   mj1m=j(p1out,false,p1in,false);
 
 
   // Dot products of these which occur again and again
   COM MWpm=mj1p.dot(mj2m);  // And now for the Higgs ones
   COM MWmm=mj1m.dot(mj2m);
 
   CCurrent jgam,jgap,j2gm,j2gp;
   j2gp=joo(p1out,true,pg,true);
   j2gm=joo(p1out,false,pg,false);
   jgap=j(pg,true,p1in,true);
   jgam=j(pg,false,p1in,false);
 
   CCurrent qsum(q1+qg);
 
   CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
   CCurrent p1o(p1out);
   CCurrent p1i(p1in);
 
   Lmm=(qsum*(MWmm) + (-2.*mj2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWmm/2.))/q1.m2();
-
   Lpm=(qsum*(MWpm) + (-2.*mj2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWpm/2.))/q1.m2();
 
 
   U1mm=(jgam.dot(mj2m)*j2gm+2.*p1o*MWmm)/(p1out+pg).m2();
-
   U1pm=(jgap.dot(mj2m)*j2gp+2.*p1o*MWpm)/(p1out+pg).m2();
 
   U2mm=((-1.)*j2gm.dot(mj2m)*jgam+2.*p1i*MWmm)/(p1in-pg).m2();
-
   U2pm=((-1.)*j2gp.dot(mj2m)*jgap+2.*p1i*MWpm)/(p1in-pg).m2();
 
-
-  const double cf=RHEJ::C_F;
   double amm,apm;
-
-  amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
-
-  apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
-
-
+  amm=RHEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1mm+U2mm);
+  apm=RHEJ::C_F*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1pm+U2pm);
 
   double ampsq=-(apm+amm);
 
   // Now add the t-channels
   double th=q2.m2()*qg.m2();
   ampsq/=th;
   ampsq/=16.;
 
   return ampsq;
 
 
 }
 
 //qQbar->qQbarWg_unof
 double junofMWgqQbar (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for qQ->qenuQ scattering
 // p1: quark (with W emittance)
 // p2: Quark
 {
   CCurrent mj2m,mj1p,mj1m;
   CLHEP::HepLorentzVector q1=p1in-p1out;
   CLHEP::HepLorentzVector qg=p1in-p1out-pg;
   CLHEP::HepLorentzVector q2=-(p2in-p2out-pe-pnu);
 
   mj2m=jWbar(p2out,false,pe,false,pnu,false,p2in,false);
   mj1p=j(p1out,true,p1in,true);
   mj1m=j(p1out,false,p1in,false);
 
 
   // Dot products of these which occur again and again
   COM MWpm=mj1p.dot(mj2m);  // And now for the Higgs ones
   COM MWmm=mj1m.dot(mj2m);
 
   CCurrent jgam,jgap,j2gm,j2gp;
   j2gp=joo(p1out,true,pg,true);
   j2gm=joo(p1out,false,pg,false);
   jgap=j(pg,true,p1in,true);
   jgam=j(pg,false,p1in,false);
 
   CCurrent qsum(q1+qg);
 
   CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
   CCurrent p1o(p1out);
   CCurrent p1i(p1in);
 
   Lmm=(qsum*(MWmm) + (-2.*mj2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWmm/2.))/q1.m2();
-
   Lpm=(qsum*(MWpm) + (-2.*mj2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWpm/2.))/q1.m2();
 
 
   U1mm=(jgam.dot(mj2m)*j2gm+2.*p1o*MWmm)/(p1out+pg).m2();
-
   U1pm=(jgap.dot(mj2m)*j2gp+2.*p1o*MWpm)/(p1out+pg).m2();
 
   U2mm=((-1.)*j2gm.dot(mj2m)*jgam+2.*p1i*MWmm)/(p1in-pg).m2();
-
   U2pm=((-1.)*j2gp.dot(mj2m)*jgap+2.*p1i*MWpm)/(p1in-pg).m2();
 
-
-  const double cf=RHEJ::C_F;
   double amm,apm;
 
-  amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
-
-  apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
-
-
+  amm=RHEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1mm+U2mm);
+  apm=RHEJ::C_F*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1pm+U2pm);
 
   double ampsq=-(apm+amm);
 
   // Now add the t-channels
   double th=q2.m2()*qg.m2();
   ampsq/=th;
   ampsq/=16.;
 
   return ampsq;
 }
 
 //qbarQ->qbarQWg_unof
 double junofMWgqbarQ (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for qQ->qenuQ scattering
 // p1: quark (with W emittance)
 // p2: Quark
 {
   CCurrent mj2m,mj1p,mj1m;
   CLHEP::HepLorentzVector q1=p1in-p1out;
   CLHEP::HepLorentzVector qg=p1in-p1out-pg;
   CLHEP::HepLorentzVector q2=-(p2in-p2out-pe-pnu);
 
   mj2m=jW(p2out,false,pe,false,pnu,false,p2in,false);
   mj1p=jio(p1in,true,p1out,true);
   mj1m=jio(p1in,false,p1out,false);
 
 
   // Dot products of these which occur again and again
   COM MWpm=mj1p.dot(mj2m);  // And now for the Higgs ones
   COM MWmm=mj1m.dot(mj2m);
 
   CCurrent jgam,jgap,j2gm,j2gp;
   j2gp=joo(pg,true,p1out,true);
   j2gm=joo(pg,false,p1out,false);
   jgap=jio(p1in,true,pg,true);
   jgam=jio(p1in,false,pg,false);
 
   CCurrent qsum(q1+qg);
 
   CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
   CCurrent p1o(p1out);
   CCurrent p1i(p1in);
 
   Lmm=(qsum*(MWmm) + (-2.*mj2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWmm/2.))/q1.m2();
-
   Lpm=(qsum*(MWpm) + (-2.*mj2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWpm/2.))/q1.m2();
 
 
   U1mm=(jgam.dot(mj2m)*j2gm+2.*p1o*MWmm)/(p1out+pg).m2();
-
   U1pm=(jgap.dot(mj2m)*j2gp+2.*p1o*MWpm)/(p1out+pg).m2();
 
   U2mm=((-1.)*j2gm.dot(mj2m)*jgam+2.*p1i*MWmm)/(p1in-pg).m2();
-
   U2pm=((-1.)*j2gp.dot(mj2m)*jgap+2.*p1i*MWpm)/(p1in-pg).m2();
 
-
-  const double cf=RHEJ::C_F;
   double amm,apm;
-
-  amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
-
-  apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
-
-
+  amm=RHEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1mm+U2mm);
+  apm=RHEJ::C_F*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1pm+U2pm);
 
   double ampsq=-(apm+amm);
 
   // Now add the t-channels
   double th=q2.m2()*qg.m2();
   ampsq/=th;
   ampsq/=16.;
 
   return ampsq;
 
 
 }
 
 //qbarQbar->qbarQbarWg_unof
 double junofMWgqbarQbar (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for qQ->qenuQ scattering
 // p1: quark (with W emittance)
 // p2: Quark
 {
   CCurrent mj2m,mj1p,mj1m;
   CLHEP::HepLorentzVector q1=p1in-p1out;
   CLHEP::HepLorentzVector qg=p1in-p1out-pg;
   CLHEP::HepLorentzVector q2=-(p2in-p2out-pe-pnu);
 
   mj2m=jWbar(p2out,false,pe,false,pnu,false,p2in,false);
   mj1p=jio(p1in,true,p1out,true);
   mj1m=jio(p1in,false,p1out,false);
 
 
   // Dot products of these which occur again and again
   COM MWpm=mj1p.dot(mj2m);  // And now for the Higgs ones
   COM MWmm=mj1m.dot(mj2m);
 
   CCurrent jgam,jgap,j2gm,j2gp;
   j2gp=joo(pg,true,p1out,true);
   j2gm=joo(pg,false,p1out,false);
   jgap=jio(p1in,true,pg,true);
   jgam=jio(p1in,false,pg,false);
 
   CCurrent qsum(q1+qg);
 
   CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
   CCurrent p1o(p1out);
   CCurrent p1i(p1in);
 
   Lmm=(qsum*(MWmm) + (-2.*mj2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWmm/2.))/q1.m2();
-
   Lpm=(qsum*(MWpm) + (-2.*mj2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWpm/2.))/q1.m2();
 
-
   U1mm=(jgam.dot(mj2m)*j2gm+2.*p1o*MWmm)/(p1out+pg).m2();
-
   U1pm=(jgap.dot(mj2m)*j2gp+2.*p1o*MWpm)/(p1out+pg).m2();
 
   U2mm=((-1.)*j2gm.dot(mj2m)*jgam+2.*p1i*MWmm)/(p1in-pg).m2();
-
   U2pm=((-1.)*j2gp.dot(mj2m)*jgap+2.*p1i*MWpm)/(p1in-pg).m2();
 
-
-  const double cf=RHEJ::C_F;
   double amm,apm;
 
-  amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
-
-  apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
+  amm=RHEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1mm+U2mm);
+  apm=RHEJ::C_F*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*RHEJ::C_F*RHEJ::C_F/3.*vabs2(U1pm+U2pm);
 
 
 
   double ampsq=-(apm+amm);
 
 
   // Now add the t-channels
   double th=q2.m2()*qg.m2();
   ampsq/=th;
   ampsq/=16.;
   return ampsq;
 
 
 }
 
 
 
 ///TODO make this comment more visible
 /// Naming scheme jM2-Wuno-g-({q/qbar}{Q/Qbar/g})
 ///TODO Spit naming for more complicated functions?
 /// e.g. jM2WqqtoqQQq -> jM2_Wqq_to_qQQq
 double jM2WunogqQ(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 {
   //COM temp;
   double ME2mpp=0.;
   double ME2mpm=0.;
   double ME2mmp=0.;
   double ME2mmm=0.;
   double ME2;
 
   ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,true);
   ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,false);
   ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,true);
   ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,false);
 
   //Helicity sum
   ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
 
   return ME2;
 
 }
 
 //same as function above but actually obtaining the antiquark line by crossing symmetry, where p1out and p1in are expected to be negative.
 //should give same result as jM2WunogqbarQ below (verified)
 double jM2WunogqQ_crossqQ(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 {
   //COM temp;
   double ME2mpp=0.;
   double ME2mpm=0.;
   double ME2mmp=0.;
   double ME2mmm=0.;
   double ME2;
 
   ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,true);
   ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,false);
   ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,true);
   ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,false);
 
   //Helicity sum
   ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
 
   return ME2;
 
 }
 
 double jM2WunogqQbar(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 {
   //COM temp;
   double ME2mpp=0.;
   double ME2mpm=0.;
   double ME2mmp=0.;
   double ME2mmm=0.;
   double ME2;
 
   ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,true);
   ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,false);
   ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,true);
   ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,false);
 
   //Helicity sum
   ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
 
   return ME2;
 
 }
 
 double jM2Wunogqg(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 {
   //COM temp;
   double ME2mpp=0.;
   double ME2mpm=0.;
   double ME2mmp=0.;
   double ME2mmm=0.;
   double ME2;
 
   ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,true);
   ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,false);
   ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,true);
   ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,false);
 
   //Helicity sum
   ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
 
-  const double ca = RHEJ::C_A;
-  const double cf = RHEJ::C_F; ///<TODO directly use RHEJ constants
-
   double ratio; // p2-/pb- in the notes
   if (p2in.pz()>0.) // if the gluon is the positive
     ratio=p2out.plus()/p2in.plus();
   else // the gluon is the negative
     ratio=p2out.minus()/p2in.minus();
 
-  double cam = ( (ca - 1/ca)*(ratio + 1./ratio)/2. + 1/ca)/cf;
+  double cam = ( (RHEJ::C_A - 1/RHEJ::C_A)*(ratio + 1./ratio)/2. + 1/RHEJ::C_A)/RHEJ::C_F;
   ME2*=cam;
 
   return ME2;
 
 }
 
 double jM2WunogqbarQ(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 {
   //COM temp;
   double ME2mpp=0.;
   double ME2mpm=0.;
   double ME2mmp=0.;
   double ME2mmm=0.;
   double ME2;
 
   ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,true,true);
   ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,true,false);
   ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,false,true);
   ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,false,false);
 
   //Helicity sum
   ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
 
   return ME2;
 
 }
 
 double jM2WunogqbarQbar(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 {
   //COM temp;
   double ME2mpp=0.;
   double ME2mpm=0.;
   double ME2mmp=0.;
   double ME2mmm=0.;
   double ME2;
 
   ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,true,true);
   ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,true,false);
   ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,false,true);
   ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,false,false);
 
   //Helicity sum
   ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
 
   return ME2;
 
 }
 
 double jM2Wunogqbarg(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 {
   //COM temp;
   double ME2mpp=0.;
   double ME2mpm=0.;
   double ME2mmp=0.;
   double ME2mmm=0.;
   double ME2;
 
   ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,true,true);
   ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,true,false);
   ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,false,true);
   ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,false,false);
 
   //Helicity sum
   ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
 
-  const double ca = RHEJ::C_A;
-  const double cf = RHEJ::C_F; ///<TODO directly use RHEJ constants
-
   double ratio; // p2-/pb- in the notes
   if (p2in.pz()>0.) // if the gluon is the positive
     ratio=p2out.plus()/p2in.plus();
   else // the gluon is the negative
     ratio=p2out.minus()/p2in.minus();
 
-  double cam = ( (ca - 1/ca)*(ratio + 1./ratio)/2. + 1/ca)/cf;
+  double cam = ( (RHEJ::C_A - 1/RHEJ::C_A)*(ratio + 1./ratio)/2. + 1/RHEJ::C_A)/RHEJ::C_F;
   ME2*=cam;
 
   return ME2;
 
 }
 
 
 // W+Jets qqxExtremal
 // W+Jets qqxExtremal Currents - wqq emission
 double jM2WgQtoqbarqQ(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqbarout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 {
   //COM temp;
   double ME2mpp=0.;
   double ME2mpm=0.;
   double ME2mmp=0.;
   double ME2mmm=0.;
   double ME2;
 
   ME2mpp = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,true,true);
   ME2mpm = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,true,false);
   ME2mmp = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,false,true);
   ME2mmm = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,false,false);
 
   //Helicity sum
   ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
 
   //Correct colour averaging
   ME2*=(3.0/8.0);
 
   return ME2;
 
 }
 
 double jM2WgQtoqqbarQ(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqbarout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in){
 
   //COM temp;
   double ME2mpp=0.;
   double ME2mpm=0.;
   double ME2mmp=0.;
   double ME2mmm=0.;
   double ME2;
 
   ME2mpp = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,true,true);
   ME2mpm = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,true,false);
   ME2mmp = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,false,true);
   ME2mmm = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,false,false);
 
   //Helicity sum
   ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
 
   //Correct colour averaging
   ME2*=(3.0/8.0);
 
   return ME2;
 
 }
 
 
 double jM2Wggtoqbarqg(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqbarout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 {
   //COM temp;
   double ME2mpp=0.;
   double ME2mpm=0.;
   double ME2mmp=0.;
   double ME2mmm=0.;
   double ME2;
 
   ME2mpp = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,true,true);
   ME2mpm = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,true,false);
   ME2mmp = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,false,true);
   ME2mmm = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,false,false);
 
   //Helicity sum
   ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
 
-  const double ca = RHEJ::C_A;
-  const double cf = RHEJ::C_F; ///<TODO directly use RHEJ constants
-
   double ratio; // p2-/pb- in the notes
   if (p2in.pz()>0.) // if the gluon is the positive
     ratio=p2out.plus()/p2in.plus();
   else // the gluon is the negative
     ratio=p2out.minus()/p2in.minus();
 
-  double cam = ( (ca - 1/ca)*(ratio + 1./ratio)/2. + 1/ca)/cf;
+  double cam = ( (RHEJ::C_A - 1/RHEJ::C_A)*(ratio + 1./ratio)/2. + 1/RHEJ::C_A)/RHEJ::C_F;
   ME2*=cam;
 
   //Correct colour averaging
   ME2*=(3.0/8.0);
 
   return ME2;
 }
 
 double jM2Wggtoqqbarg(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqbarout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in){
 
   //COM temp;
   double ME2mpp=0.;
   double ME2mpm=0.;
   double ME2mmp=0.;
   double ME2mmm=0.;
   double ME2;
 
   ME2mpp = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,true,true);
   ME2mpm = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,true,false);
   ME2mmp = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,false,true);
   ME2mmm = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,false,false);
 
   //Helicity sum
   ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
 
-  const double ca = RHEJ::C_A;
-  const double cf = RHEJ::C_F; ///<TODO directly use RHEJ constants
-
   double ratio; // p2-/pb- in the notes
   if (p2in.pz()>0.) // if the gluon is the positive
     ratio=p2out.plus()/p2in.plus();
   else // the gluon is the negative
     ratio=p2out.minus()/p2in.minus();
 
-  double cam = ( (ca - 1/ca)*(ratio + 1./ratio)/2. + 1/ca)/cf;
+  double cam = ( (RHEJ::C_A - 1/RHEJ::C_A)*(ratio + 1./ratio)/2. + 1/RHEJ::C_A)/RHEJ::C_F;
   ME2*=cam;
 
   //Correct colour averaging
   ME2*=(3.0/8.0);
 
   return ME2;
 
 }
 
 
+namespace {
+//First, a function for generating polarisation tensors. Output as 'current'.
+void eps(CLHEP::HepLorentzVector refmom, CLHEP::HepLorentzVector kb, bool hel, current &ep){
+    current curm,curp;
+    //Recall - positive helicity eps has negative helicity choices for spinors and vice versa
+    j(refmom,true,kb,true,curm);
+    j(refmom,false,kb,false,curp);
+    double norm=1.;
+    if(kb.z()<0.)
+    norm *= sqrt(2.*refmom.plus()*kb.minus());
+    if(kb.z()>0.)
+    norm = sqrt(2.*refmom.minus()*kb.plus());
+    if(hel==false){
+        ep[0] = curm[0]/norm;
+        ep[1] = curm[1]/norm;
+        ep[2] = curm[2]/norm;
+        ep[3] = curm[3]/norm;
+    }
+    if(hel==true){
+        ep[0] = curp[0]/norm;
+        ep[1] = curp[1]/norm;
+        ep[2] = curp[2]/norm;
+        ep[3] = curp[3]/norm;
+    }
+}
+
+
+//Now build up each part of the squared amplitude
+
+COM qWggm1(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p3, CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector plbar, bool helchain, bool helb,CLHEP::HepLorentzVector refmom){
+    current cur33, cur23, curb3, cur2b, ep;
+    joo(p3, helchain, p3, helchain,cur33);
+    joo(p2,helchain,p3,helchain,cur23);
+    jio(pb,helchain,p3,helchain,curb3);
+    joi(p2,helchain,pb,helchain,cur2b);
+
+    // Build the external quark line W Emmision
+    Tensor<1,4> ABCurr = TCurrent(pl, false, plbar, false);
+    Tensor<1,4> Tp1W = Construct1Tensor((p1+pl+plbar));//p1+pw
+    Tensor<1,4> TqaW = Construct1Tensor((pa-pl-plbar));//pa-pw
+    Tensor<3,4> J1aBlank = T3Current(p1,false,pa,false);
+    double t1AB = (p1+pl+plbar).m2();
+    double taAB = (pa-pl-plbar).m2();
+    Tensor<2,4> J1a1 = (J1aBlank.contract(Tp1W,2))/t1AB;
+    Tensor<2,4> J1a2 = (J1aBlank.contract(TqaW,2))/taAB;
+    Tensor<1,4> cur1a = J1a1.contract(ABCurr,1) + J1a2.contract(ABCurr,2);
+
+    double t2 = (p3-pb)*(p3-pb);
+
+    //Create vertex
+    COM v1[4][4];
+    for(int u=0; u<4;u++)
+    {
+        for(int v=0; v<4; v++)
+        {
+            v1[u][v]=(cur23[u]*cur33[v]-cur2b[u]*curb3[v])/t2*(-1.);
+        }
+    }
+    //Dot in current and eps
+    //Metric tensor
+    double eta[4][4]={};
+    eta[0][0]=1.;
+    eta[1][1]=-1.;
+    eta[2][2]=-1.;
+    eta[3][3]=-1.;
+    //eps
+    eps(refmom,pb,helb, ep);
+    COM M1=0.;
+    for(int i=0;i<4;i++){
+        for(int j=0;j<4;j++){
+            for(int k=0; k<4; k++){
+                for(int l=0; l<4;l++){
+                    M1+= eta[i][k]*cur1a.at(k)*(v1[i][j])*ep[l]*eta[l][j];
+                }
+            }
+        }
+    }
+    return M1;
+}
+
+COM qWggm2(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p3, CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector plbar, bool helchain, bool helb,CLHEP::HepLorentzVector refmom){
+    current cur22, cur23, curb3, cur2b, ep;
+    joo(p2, helchain, p2, helchain,cur22);
+    joo(p2,helchain,p3,helchain,cur23);
+    jio(pb,helchain,p3,helchain,curb3);
+    joi(p2,helchain,pb,helchain,cur2b);
+
+    // Build the external quark line W Emmision
+    Tensor<1,4> ABCurr = TCurrent(pl, false, plbar, false);
+    Tensor<1,4> Tp1W = Construct1Tensor((p1+pl+plbar));//p1+pw
+    Tensor<1,4> TqaW = Construct1Tensor((pa-pl-plbar));//pa-pw
+
+    Tensor<3,4> J1aBlank = T3Current(p1,false,pa,false);
+
+    double t1AB = (p1+pl+plbar).m2();
+    double taAB = (pa-pl-plbar).m2();
+
+    Tensor<2,4> J1a1 = (J1aBlank.contract(Tp1W,2))/t1AB;
+    Tensor<2,4> J1a2 = (J1aBlank.contract(TqaW,2))/taAB;
+
+    Tensor<1,4> cur1a = J1a1.contract(ABCurr,1) + J1a2.contract(ABCurr,2);
+
+    double t2t = (p2-pb)*(p2-pb);
+    //Create vertex
+    COM v2[4][4]={};
+    for(int u=0; u<4;u++)
+    {
+        for(int v=0; v<4; v++)
+        {
+            v2[u][v]=(cur22[v]*cur23[u]-cur2b[v]*curb3[u])/t2t;
+        }
+    }
+    //Dot in current and eps
+    //Metric tensor
+    double eta[4][4]={};
+    eta[0][0]=1.;
+    eta[1][1]=-1.;
+    eta[2][2]=-1.;
+    eta[3][3]=-1.;
+    //eps
+    eps(refmom,pb,helb, ep);
+    COM M2=0.;
+    for(int i=0;i<4;i++){
+        for(int j=0;j<4;j++){
+            for(int k=0; k<4; k++){
+                for(int l=0; l<4;l++){
+		  M2+= eta[i][k]*cur1a.at(k)*(v2[i][j])*ep[l]*eta[l][j];
+                }
+            }
+        }
+    }
+    return M2;
+}
+
+COM qWggm3(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p3, CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector plbar, bool helchain, bool helb,CLHEP::HepLorentzVector refmom){
+    //3 gluon vertex bit
+    double eta[4][4]={};
+    eta[0][0]=1.;
+    eta[1][1]=-1.;
+    eta[2][2]=-1.;
+    eta[3][3]=-1.;
+    current spincur,ep;
+    double s23 = (p2+p3)*(p2+p3);
+    joo(p2,helchain,p3,helchain,spincur);
+
+    // Build the external quark line W Emmision
+    Tensor<1,4> ABCurr = TCurrent(pl, false, plbar, false);
+    Tensor<1,4> Tp1W = Construct1Tensor((p1+pl+plbar));//p1+pw
+    Tensor<1,4> TqaW = Construct1Tensor((pa-pl-plbar));//pa-pw
+
+    Tensor<3,4> J1aBlank = T3Current(p1,false,pa,false);
+
+    double t1AB = (p1+pl+plbar).m2();
+    double taAB = (pa-pl-plbar).m2();
+
+    Tensor<2,4> J1a1 = (J1aBlank.contract(Tp1W,2))/t1AB;
+    Tensor<2,4> J1a2 = (J1aBlank.contract(TqaW,2))/taAB;
+
+    Tensor<1,4> cur1a = J1a1.contract(ABCurr,1) + J1a2.contract(ABCurr,2);
+
+    //Redefine relevant momenta as currents - for ease of calling correct part of vector
+    current ka,k2,k3,kb;
+    kb[0]=pb.e();
+    kb[1]=pb.x();
+    kb[2]=pb.y();
+    kb[3]=pb.z();
+    k2[0]=p2.e();
+    k2[1]=p2.x();
+    k2[2]=p2.y();
+    k2[3]=p2.z();
+    k3[0]=p3.e();
+    k3[1]=p3.x();
+    k3[2]=p3.y();
+    k3[3]=p3.z();
+    ka[0]=pa.e();
+    ka[1]=pa.x();
+    ka[2]=pa.y();
+    ka[3]=pa.z();
+    COM V3g[4][4]={};
+    for(int u=0;u<4;u++){
+        for(int v=0;v<4;v++){
+            for(int p=0;p<4;p++){
+                for(int r=0; r<4;r++){
+            V3g[u][v] += COM(0.,1.)*(((2.*k2[v]+2.*k3[v])*eta[u][p] - (2.*kb[u])*eta[p][v]+2.*kb[p]*eta[u][v])*spincur[r]*eta[r][p])/s23;
+                }
+            }
+        }
+    }
+    COM diffextrabit[4][4]={};
+    for(int u=0;u<4;u++) {
+      for(int v=0;v<4;v++) {
+        diffextrabit[u][v] = 0.;
+      }
+    }
+
+    //Dot in current and eps
+    //eps
+    eps(refmom,pb,helb, ep);
+    COM M3=0.;
+    for(int i=0;i<4;i++){
+        for(int j=0;j<4;j++){
+            for(int k=0; k<4; k++){
+                for(int l=0; l<4;l++){
+		  M3+= eta[i][k]*cur1a.at(k)*(V3g[i][j]+diffextrabit[i][j])*ep[l]*eta[l][j];
+                }
+            }
+        }
+    }
+    return M3;
+}
+}
+
+// no wqq emission
+double jM2WgqtoQQqW(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb, CLHEP::HepLorentzVector p1,  CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p3,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl){
+
+  // 4 indepedent helicity choices (complex conjugation related).
+
+  //Need to evalute each independent hel configuration and store that result somewhere
+  COM Mmmm1 = qWggm1(pa,pb,p1,p2,p3,pl,plbar,false,false, pa);
+  COM Mmmm2 = qWggm2(pa,pb,p1,p2,p3,pl,plbar,false,false, pa);
+  COM Mmmm3 = qWggm3(pa,pb,p1,p2,p3,pl,plbar,false,false, pa);
+  COM Mmmp1 = qWggm1(pa,pb,p1,p2,p3,pl,plbar,true,false, pa);
+  COM Mmmp2 = qWggm2(pa,pb,p1,p2,p3,pl,plbar,true,false, pa);
+  COM Mmmp3 = qWggm3(pa,pb,p1,p2,p3,pl,plbar,true,false, pa);
+  COM Mpmm1 = qWggm1(pa,pb,p1,p2,p3,pl,plbar,false,true, pa);
+  COM Mpmm2 = qWggm2(pa,pb,p1,p2,p3,pl,plbar,false,true, pa);
+  COM Mpmm3 = qWggm3(pa,pb,p1,p2,p3,pl,plbar,false,true, pa);
+  COM Mpmp1 = qWggm1(pa,pb,p1,p2,p3,pl,plbar,true,true, pa);
+  COM Mpmp2 = qWggm2(pa,pb,p1,p2,p3,pl,plbar,true,true, pa);
+  COM Mpmp3 = qWggm3(pa,pb,p1,p2,p3,pl,plbar,true,true, pa);
+
+  //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,Mmmp,Mpmm,Mpmp;
+  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)));
+  Mmmp = real(cm1m1*pow(abs(Mmmp1),2)+cm2m2*pow(abs(Mmmp2),2)+cm3m3*pow(abs(Mmmp3),2)+2.*real(cm1m2*Mmmp1*conj(Mmmp2))+2.*real(cm1m3*Mmmp1*conj(Mmmp3))+2.*real(cm2m3*Mmmp2*conj(Mmmp3)));
+  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)));
+  Mpmp = real(cm1m1*pow(abs(Mpmp1),2)+cm2m2*pow(abs(Mpmp2),2)+cm3m3*pow(abs(Mpmp3),2)+2.*real(cm1m2*Mpmp1*conj(Mpmp2))+2.*real(cm1m3*Mpmp1*conj(Mpmp3))+2.*real(cm2m3*Mpmp2*conj(Mpmp3)));
+
+  return ((Mmmm+Mmmp+Mpmm+Mpmp)/24./4.)/(pa-p1).m2()/(p2+p3-pb).m2();
+}
+
 
 // W+Jets qqxCentral
 double jM2WqqtoqQQq(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector plbar, std::vector<HLV> partons, bool aqlinepa, bool aqlinepb, bool qqxmarker, int nabove)
 {
 
   static bool is_sigma_index_set(false);
   if(!is_sigma_index_set){
     if(init_sigma_index())
       is_sigma_index_set = true;
     else
       return 0.;}
 
   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,4> T1am, T4bm, T1ap, T4bp;
   if(!(aqlinepa)){
     T1ap = TCurrent(p1, true, pa, true);
     T1am = TCurrent(p1, false, pa, false);}
   else if(aqlinepa){
     T1ap = TCurrent(pa, true, p1, true);
     T1am = TCurrent(pa, false, p1, false);}
   if(!(aqlinepb)){
     T4bp = TCurrent(p4, true, pb, true);
     T4bm = TCurrent(p4, false, pb, false);}
   else if(aqlinepb){
     T4bp = TCurrent(pb, true, p4, true);
     T4bm = TCurrent(pb, false, p4, false);}
 
   // Calculate the 3 separate contributions to the effective vertex
   Tensor<2,4> Xunc = MUncrossW(pa, p1, pb, p4, pq, pqbar, pl, plbar, partons, nabove);
   Tensor<2,4> Xcro = MCrossW(  pa, p1, pb, p4, pq, pqbar, pl, plbar, partons, nabove);
   Tensor<2,4> 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)).at(0);
   COM M_mmCro = (((Xcro).contract(T1am,1)).contract(T4bm,1)).at(0);
   COM M_mmSym = (((Xsym).contract(T1am,1)).contract(T4bm,1)).at(0);
   // (- + hel choice)
   COM M_mpUnc = (((Xunc).contract(T1am,1)).contract(T4bp,1)).at(0);
   COM M_mpCro = (((Xcro).contract(T1am,1)).contract(T4bp,1)).at(0);
   COM M_mpSym = (((Xsym).contract(T1am,1)).contract(T4bp,1)).at(0);
   // (+ - hel choice)
   COM M_pmUnc = (((Xunc).contract(T1ap,1)).contract(T4bm,1)).at(0);
   COM M_pmCro = (((Xcro).contract(T1ap,1)).contract(T4bm,1)).at(0);
   COM M_pmSym = (((Xsym).contract(T1ap,1)).contract(T4bm,1)).at(0);
   // (+ + hel choice)
   COM M_ppUnc = (((Xunc).contract(T1ap,1)).contract(T4bp,1)).at(0);
   COM M_ppCro = (((Xcro).contract(T1ap,1)).contract(T4bp,1)).at(0);
   COM M_ppSym = (((Xsym).contract(T1ap,1)).contract(T4bp,1)).at(0);
 
   //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.));
 
 
 
   CLHEP::HepLorentzVector q1,q3;
   q1=pa;
   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);
 
   return amp;
 }
 
 // no wqq emission
 double jM2WqqtoqQQqW(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb,CLHEP::HepLorentzVector pl,CLHEP::HepLorentzVector plbar, std::vector<CLHEP::HepLorentzVector> partons, bool aqlinepa, bool aqlinepb, bool qqxmarker, int nabove, int nbelow, bool forwards){
 
   static bool is_sigma_index_set(false);
   if(!is_sigma_index_set){
     if(init_sigma_index())
       is_sigma_index_set = true;
     else
       return 0.;
   }
 
   if (!forwards){ //If Emission from Leg a instead, flip process.
     HLV dummymom = pa;
     bool dummybool= aqlinepa;
     int dummyint = nabove;
     pa = pb;
     pb = dummymom;
     std::reverse(partons.begin(),partons.end());
     qqxmarker = !(qqxmarker);
     aqlinepa = aqlinepb;
     aqlinepb = dummybool;
     nabove = nbelow;
     nbelow = dummyint;
   }
 
   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,4> T1am(0.), T1ap(0.);
   if(!(aqlinepa)){
     T1ap = TCurrent(p1, true, pa, true);
     T1am = TCurrent(p1, false, pa, false);}
   else if(aqlinepa){
     T1ap = TCurrent(pa, true, p1, true);
     T1am = TCurrent(pa, false, p1, false);}
 
   Tensor <1,4> T4bm = jW4bEmit(pb, p4, pl, plbar, aqlinepb);
 
   // Calculate the 3 separate contributions to the effective vertex
   Tensor<2,4> Xunc_m = MUncross(pa, pq, pqbar,partons, false, nabove);
   Tensor<2,4> Xcro_m = MCross(  pa, pq, pqbar,partons, false, nabove);
   Tensor<2,4> Xsym_m = MSym(    pa, p1, pb, p4, pq, pqbar, partons, false, nabove);
 
   Tensor<2,4> Xunc_p = MUncross(pa, pq, pqbar,partons, true, nabove);
   Tensor<2,4> Xcro_p = MCross(  pa, pq, pqbar,partons, true, nabove);
   Tensor<2,4> Xsym_p = MSym(    pa, p1, pb, p4, pq, pqbar, partons, true, nabove);
 
 
   // (- - hel choice)
   COM M_mmUnc = (((Xunc_m).contract(T1am,1)).contract(T4bm,1)).at(0);
   COM M_mmCro = (((Xcro_m).contract(T1am,1)).contract(T4bm,1)).at(0);
   COM M_mmSym = (((Xsym_m).contract(T1am,1)).contract(T4bm,1)).at(0);
   // (- + hel choice)
   COM M_mpUnc = (((Xunc_p).contract(T1am,1)).contract(T4bm,1)).at(0);
   COM M_mpCro = (((Xcro_p).contract(T1am,1)).contract(T4bm,1)).at(0);
   COM M_mpSym = (((Xsym_p).contract(T1am,1)).contract(T4bm,1)).at(0);
   // (+ - hel choice)
   COM M_pmUnc = (((Xunc_m).contract(T1ap,1)).contract(T4bm,1)).at(0);
   COM M_pmCro = (((Xcro_m).contract(T1ap,1)).contract(T4bm,1)).at(0);
   COM M_pmSym = (((Xsym_m).contract(T1ap,1)).contract(T4bm,1)).at(0);
   // (+ + hel choice)
   COM M_ppUnc = (((Xunc_p).contract(T1ap,1)).contract(T4bm,1)).at(0);
   COM M_ppCro = (((Xcro_p).contract(T1ap,1)).contract(T4bm,1)).at(0);
   COM M_ppSym = (((Xsym_p).contract(T1ap,1)).contract(T4bm,1)).at(0);
 
   //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.));
 
   CLHEP::HepLorentzVector q1,q3;
   q1=pa;
   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);
 
   return amp;
 }
diff --git a/src/currents.cc b/src/currents.cc
index 9abcce8..d592be2 100644
--- a/src/currents.cc
+++ b/src/currents.cc
@@ -1,3694 +1,3641 @@
 //////////////////////////////////////////////////
 //////////////////////////////////////////////////
 // This source code is Copyright (2012) of      //
 //  Jeppe R. Andersen and Jennifer M. Smillie   //
 // and is distributed under the                 //
 // Gnu Public License version 2                 //
 // http://www.gnu.org/licenses/gpl-2.0.html     //
 // You are allowed to distribute and alter the  //
 // source under the conditions of the GPLv2     //
 // as long as this copyright notice             //
 // is unaltered and distributed with the source //
 // Any use should comply with the               //
 //             MCNET GUIDELINES                 //
 //    for Event Generator Authors and Users     //
 // as distributed with this source code         //
 //////////////////////////////////////////////////
 //////////////////////////////////////////////////
 #include "RHEJ/currents.hh"
 //#include "ZJets/Flags.h"
 #include "RHEJ/Constants.hh"
 #include "RHEJ/utility.hh"
 #include "RHEJ/PDG_codes.hh"
 
 const COM looprwfactor = (COM(0.,1.)*M_PI*M_PI)/pow((2.*M_PI),4);
 //const double HVE = 246.21845810181637;
 
 #ifdef RHEJ_BUILD_WITH_QCDLOOP
 #include "qcdloop/qcdloop.h"
 #endif
 
 #include <iostream>
 
 namespace {
   // Loop integrals
   #ifdef RHEJ_BUILD_WITH_QCDLOOP
 
   COM B0DD(CLHEP::HepLorentzVector 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(CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector 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(CLHEP::HepLorentzVector q1,CLHEP::HepLorentzVector q2, CLHEP::HepLorentzVector 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(CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt)
   // As given in Eq. (B.2) of VDD
   {
     double q12,q22,Q2;
     CLHEP::HepLorentzVector 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();
     // std::cout<<"Higgs mass? : "<<sqrt(Q2)<<std::endl;
 
     Delta3=q12*q12+q22*q22+Q2*Q2-2*q12*q22-2*q12*Q2-2*q22*Q2;
     if (mt < 0.)
       std::cerr<<"Problem in A1! mt = "<<mt<<std::endl;
     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));
     ans=ans-looprwfactor*COM(0,-1)*(B0DD(q2,mt)-B0DD(Q,mt))*(2.*q22/Delta3+12.*q12*q22/Delta3/Delta3*(q22-q12+Q2));
     ans=ans-looprwfactor*COM(0,-1)*(B0DD(q1,mt)-B0DD(Q,mt))*(2.*q12/Delta3+12.*q12*q22/Delta3/Delta3*(q12-q22+Q2));
     ans=ans-2./Delta3/16/M_PI/M_PI*(q12+q22-Q2);
 
     //cout << "q12, q22= "<<q12<<" "<<q22<<" "<<endl;
 
     return ans;
 
   }
 
 
   COM A2(CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt)
   // As given in Eq. (B.2) of VDD, but with high energy limit
   // of invariants taken.
   {
     double q12,q22,Q2;
     CLHEP::HepLorentzVector Q;
     double Delta3,mt2;
     COM ans(COM(0.,0.));
 
     if (mt < 0.)
       std::cerr<<"Problem in A2! mt = "<<mt<<std::endl;
     mt2=mt*mt;
 
     q12=q1.m2();
     q22=q2.m2();
     Q=-q1-q2; // Define all momenta ingoing as in appendix of VDD
     Q2=Q.m2();
     // std::cout<<"Higgs mass Square? : "<<Q2<<std::endl;
 
     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);
     ans=ans+looprwfactor*COM(0,-1)*(B0DD(q2,mt)-B0DD(Q,mt))*q22*(q22-q12-Q2)/Delta3;
     ans=ans+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(CLHEP::HepLorentzVector, CLHEP::HepLorentzVector, double) {
     throw std::logic_error{"A1 called without QCDloop support"};
   }
 
   COM A2(CLHEP::HepLorentzVector, CLHEP::HepLorentzVector, double) {
     throw std::logic_error{"A2 called without QCDloop support"};
   }
 
 #endif
 
   void to_current(const CLHEP::HepLorentzVector & q, current & ret){
     ret[0]=q.e();
     ret[1]=q.x();
     ret[2]=q.y();
     ret[3]=q.z();
   }
 
   constexpr double C_A = 3.;
   constexpr double C_F = 4./3.;
   using ParticleID = RHEJ::pid::ParticleID;
 
   // Colour acceleration multiplier for gluons see eq. (7) in arXiv:0910.5113
   // TODO: this is not a current and should be moved somewhere else
   double K_g(double p1minus, double paminus) {
     return 1./2.*(p1minus/paminus + paminus/p1minus)*(C_A - 1./C_A) + 1./C_A;
   }
   double K_g(
       CLHEP::HepLorentzVector const & pout,
       CLHEP::HepLorentzVector const & pin
   ) {
     if(pin.z() > 0) return K_g(pout.plus(), pin.plus());
     return K_g(pout.minus(), pin.minus());
   }
 
 } // namespace anonymous
 
 
 CCurrent CCurrent::operator+(const CCurrent& other)
 {
     COM result_c0=c0 + other.c0;
     COM result_c1=c1 + other.c1;
     COM result_c2=c2 + other.c2;
     COM result_c3=c3 + other.c3;
 
     return CCurrent(result_c0,result_c1,result_c2,result_c3);
 }
 
 CCurrent CCurrent::operator-(const CCurrent& other)
 {
     COM result_c0=c0 - other.c0;
     COM result_c1=c1 - other.c1;
     COM result_c2=c2 - other.c2;
     COM result_c3=c3 - other.c3;
 
     return CCurrent(result_c0,result_c1,result_c2,result_c3);
 }
 
 CCurrent CCurrent::operator*(const double x)
 {
     COM result_c0=x*CCurrent::c0;
     COM result_c1=x*CCurrent::c1;
     COM result_c2=x*CCurrent::c2;
     COM result_c3=x*CCurrent::c3;
 
     return CCurrent(result_c0,result_c1,result_c2,result_c3);
 }
 
 CCurrent CCurrent::operator/(const double x)
 {
     COM result_c0=CCurrent::c0/x;
     COM result_c1=CCurrent::c1/x;
     COM result_c2=CCurrent::c2/x;
     COM result_c3=CCurrent::c3/x;
 
     return CCurrent(result_c0,result_c1,result_c2,result_c3);
 }
 
 CCurrent CCurrent::operator*(const COM x)
 {
     COM result_c0=x*CCurrent::c0;
     COM result_c1=x*CCurrent::c1;
     COM result_c2=x*CCurrent::c2;
     COM result_c3=x*CCurrent::c3;
 
     return CCurrent(result_c0,result_c1,result_c2,result_c3);
 }
 
 CCurrent CCurrent::operator/(const COM x)
 {
     COM result_c0=(CCurrent::c0)/x;
     COM result_c1=(CCurrent::c1)/x;
     COM result_c2=(CCurrent::c2)/x;
     COM result_c3=(CCurrent::c3)/x;
 
     return CCurrent(result_c0,result_c1,result_c2,result_c3);
 }
 
 std::ostream& operator <<(std::ostream& os, const CCurrent& cur)
 {
     os << "("<<cur.c0<< " ; "<<cur.c1<<" , "<<cur.c2<<" , "<<cur.c3<<")";
     return os;
 }
 
 CCurrent operator * ( double x, CCurrent& m)
 {
     return m*x;
 }
 
 CCurrent operator * ( COM x, CCurrent& m)
 {
     return m*x;
 }
 
 CCurrent operator / ( double x, CCurrent& m)
 {
     return m/x;
 }
 
 CCurrent operator / ( COM x, CCurrent& m)
 {
     return m/x;
 }
 
 COM CCurrent::dot(CLHEP::HepLorentzVector p1)
 {
     //  Current goes (E,px,py,pz)
     //  std::cout<<"current = ("<<c0<<","<<c1<<","<<c2<<","<<c3<<")\n";
     //  Vector goes (px,py,pz,E)
     //  std::cout<<"vector = ("<<p1[0]<<","<<p1[1]<<","<<p1[2]<<","<<p1[3]<<")\n";
     return p1[3]*c0-p1[0]*c1-p1[1]*c2-p1[2]*c3;
 }
 
 COM CCurrent::dot(CCurrent p1)
 {
     return p1.c0*c0-p1.c1*c1-p1.c2*c2-p1.c3*c3;
 }
 
 
 
 void j (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin, bool helin,current &cur) {
 
   cur[0]=0.;
   cur[1]=0.;
   cur[2]=0.;
   cur[3]=0.;
 
   double sqpop=sqrt(pout.plus());
   double sqpom=sqrt(pout.minus());
   COM poperp=pout.x()+COM(0,1)*pout.y();
 
   if (helout!=helin) {
     std::cerr<< "void j : Non-matching helicities at line " << __LINE__ << std::endl;
   } else if (helout==false) { // negative helicity
     if (pin.plus()>pin.minus()) { // if forward
       double sqpip=sqrt(pin.plus());
       cur[0]=sqpop*sqpip;
       cur[1]=sqpom*sqpip*poperp/abs(poperp);
       cur[2]=-COM(0,1)*cur[1];
       cur[3]=cur[0];
     } else { // if backward
       double sqpim=sqrt(pin.minus());
       cur[0]=-sqpom*sqpim*poperp/abs(poperp);
       cur[1]=-sqpim*sqpop;
       cur[2]=COM(0,1)*cur[1];
       cur[3]=-cur[0];
     }
   } else { // positive helicity
     if (pin.plus()>pin.minus()) { // if forward
       double sqpip=sqrt(pin.plus());
       cur[0]=sqpop*sqpip;
       cur[1]=sqpom*sqpip*conj(poperp)/abs(poperp);
       cur[2]=COM(0,1)*cur[1];
       cur[3]=cur[0];
     } else { // if backward
       double sqpim=sqrt(pin.minus());
       cur[0]=-sqpom*sqpim*conj(poperp)/abs(poperp);
       cur[1]=-sqpim*sqpop;
       cur[2]=-COM(0,1)*cur[1];
       cur[3]=-cur[0];
     }
   }
 }
 
 CCurrent j (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin, bool helin)
 {
     COM cur[4];
 
     cur[0]=0.;
     cur[1]=0.;
     cur[2]=0.;
     cur[3]=0.;
 
     double sqpop=sqrt(pout.plus());
     double sqpom=sqrt(pout.minus());
     COM poperp=pout.x()+COM(0,1)*pout.y();
 
     if (helout!=helin) {
         std::cerr<< "void j : Non-matching helicities\n";
     } else if (helout==false) { // negative helicity
         if (pin.plus()>pin.minus()) { // if forward
             double sqpip=sqrt(pin.plus());
             cur[0]=sqpop*sqpip;
             cur[1]=sqpom*sqpip*poperp/abs(poperp);
             cur[2]=-COM(0,1)*cur[1];
             cur[3]=cur[0];
         } else { // if backward
             double sqpim=sqrt(pin.minus());
             cur[0]=-sqpom*sqpim*poperp/abs(poperp);
             cur[1]=-sqpim*sqpop;
             cur[2]=COM(0,1)*cur[1];
             cur[3]=-cur[0];
         }
     } else { // positive helicity
         if (pin.plus()>pin.minus()) { // if forward
             double sqpip=sqrt(pin.plus());
             cur[0]=sqpop*sqpip;
             cur[1]=sqpom*sqpip*conj(poperp)/abs(poperp);
             cur[2]=COM(0,1)*cur[1];
             cur[3]=cur[0];
         } else { // if backward
             double sqpim=sqrt(pin.minus());
             cur[0]=-sqpom*sqpim*conj(poperp)/abs(poperp);
             cur[1]=-sqpim*sqpop;
             cur[2]=-COM(0,1)*cur[1];
             cur[3]=-cur[0];
         }
     }
     CCurrent temp(cur[0],cur[1],cur[2],cur[3]);
     return temp;
 }
 
 CCurrent jio (CLHEP::HepLorentzVector pin, bool helin, CLHEP::HepLorentzVector pout, bool helout)
 {
     COM cur[4];
 
     cur[0]=0.;
     cur[1]=0.;
     cur[2]=0.;
     cur[3]=0.;
 
     double sqpop=sqrt(pout.plus());
     double sqpom=sqrt(pout.minus());
     COM poperp=pout.x()+COM(0,1)*pout.y();
 
     if (helout!=helin) {
         std::cerr<< "void j : Non-matching helicities\n";
     } else if (helout==false) { // negative helicity
         if (pin.plus()>pin.minus()) { // if forward
             double sqpip=sqrt(pin.plus());
             cur[0]=sqpop*sqpip;
             cur[1]=sqpom*sqpip*conj(poperp)/abs(poperp);
             cur[2]=COM(0,1)*cur[1];
             cur[3]=cur[0];
         } else { // if backward
             double sqpim=sqrt(pin.minus());
             cur[0]=-sqpom*sqpim*conj(poperp)/abs(poperp);
             cur[1]=-sqpim*sqpop;
             cur[2]=-COM(0,1)*cur[1];
             cur[3]=-cur[0];
         }
     } else { // positive helicity
         if (pin.plus()>pin.minus()) { // if forward
             double sqpip=sqrt(pin.plus());
             cur[0]=sqpop*sqpip;
             cur[1]=sqpom*sqpip*poperp/abs(poperp);
             cur[2]=-COM(0,1)*cur[1];
             cur[3]=cur[0];
         } else { // if backward
             double sqpim=sqrt(pin.minus());
             cur[0]=-sqpom*sqpim*poperp/abs(poperp);
             cur[1]=-sqpim*sqpop;
             cur[2]=COM(0,1)*cur[1];
             cur[3]=-cur[0];
         }
     }
     CCurrent temp(cur[0],cur[1],cur[2],cur[3]);
     return temp;
 }
 
 
 // Current for <incoming state | mu | outgoing state>
 void jio(HLV pin, bool helin, HLV pout, bool helout, current &cur) {
 
   cur[0] = 0.0;
   cur[1] = 0.0;
   cur[2] = 0.0;
   cur[3] = 0.0;
   if(helin!=helout){
     std::cout<<__LINE__<<" "<<__FILE__<<std::endl;
   }
   double sqpop  = sqrt(pout.plus());
   double sqpom  = sqrt(pout.minus());
   COM    poperp = pout.x() + COM(0, 1) * pout.y();
 
   if (helout == false) {
 
     if (pin.plus() > pin.minus()) { // if forward
       double sqpip=sqrt(pin.plus());
       cur[0] = sqpop * sqpip;
       cur[1] = sqpom * sqpip * conj(poperp) / abs(poperp);
       cur[2] = COM(0,1) * cur[1];
       cur[3] = cur[0];
     }
     else {
       double sqpim = sqrt(pin.minus());
       cur[0] = -sqpom * sqpim * conj(poperp) / abs(poperp);
       cur[1] = -sqpim * sqpop;
       cur[2] = -COM(0,1) * cur[1];
       cur[3] = -cur[0];
     }
   }
 
   else {
     if (pin.plus() > pin.minus()) { // if forward
       double sqpip = sqrt(pin.plus());
       cur[0] = sqpop * sqpip;
       cur[1] = sqpom * sqpip*poperp/abs(poperp);
       cur[2] = -COM(0,1)*cur[1];
       cur[3] = cur[0];
     }
     else {
       double sqpim = sqrt(pin.minus());
       cur[0] = -sqpom * sqpim * poperp/abs(poperp);
       cur[1] = -sqpim * sqpop;
       cur[2] = COM(0,1)*cur[1];
       cur[3] = -cur[0];
     }
   }
 }
 
 
 // Current for <outgoing state | mu | outgoing state>
 void joo(HLV pi, bool heli, HLV pj, bool helj, current &cur) {
 
   // Zero our current
   cur[0] = 0.0;
   cur[1] = 0.0;
   cur[2] = 0.0;
   cur[3] = 0.0;
   if(helj){
     std::cout<<__LINE__<<" "<<__FILE__<<std::endl;
   }
   // If positive helicity swap momenta
   if (heli == true) {
     HLV dummy;
     dummy = pi;
     pi = pj;
     pj = dummy;
   }
 
   double sqpjp = sqrt(pj.plus());
   double sqpjm = sqrt(pj.minus());
   double sqpip = sqrt(pi.plus());
   double sqpim = sqrt(pi.minus());
 
   COM piperp = pi.x() + COM(0,1) * pi.y();
   COM pjperp = pj.x() + COM(0,1) * pj.y();
   COM phasei = piperp / abs(piperp);
   COM phasej = pjperp / abs(pjperp);
 
   cur[0] = sqpim * sqpjm * phasei * conj(phasej) + sqpip * sqpjp;
   cur[1] = sqpim * sqpjp * phasei + sqpip * sqpjm * conj(phasej);
   cur[2] = -COM(0, 1) * (sqpim * sqpjp * phasei - sqpip * sqpjm * conj(phasej));
   cur[3] = -sqpim * sqpjm * phasei * conj(phasej) + sqpip * sqpjp;
 }
 
 CCurrent joo (CLHEP::HepLorentzVector pi, bool heli, CLHEP::HepLorentzVector pj, bool helj)
 {
     COM cur[4];
 
     if (heli!=helj) {
         std::cerr<< "void j : Non-matching helicities\n";
     } else if (heli==true) { // negative helicity
         CLHEP::HepLorentzVector dummy;
         dummy=pi;
         pi=pj;
         pj=dummy;
     }
     double sqpjp=sqrt(pj.plus());
     double sqpjm=sqrt(pj.minus());
     double sqpip=sqrt(pi.plus());
     double sqpim=sqrt(pi.minus());
     COM piperp=pi.x()+COM(0,1)*pi.y();
     COM pjperp=pj.x()+COM(0,1)*pj.y();
     COM phasei=piperp/abs(piperp);
     COM phasej=pjperp/abs(pjperp);
 
     cur[0]=sqpim*sqpjm*phasei*conj(phasej)+sqpip*sqpjp;
     cur[1]=sqpim*sqpjp*phasei+sqpip*sqpjm*conj(phasej);
     cur[2]=-COM(0,1)*(sqpim*sqpjp*phasei-sqpip*sqpjm*conj(phasej));
     cur[3]=-sqpim*sqpjm*phasei*conj(phasej)+sqpip*sqpjp;
 
     CCurrent temp(cur[0],cur[1],cur[2],cur[3]);
     return temp;
 }
 
 
 // Current Functions
 // Current for <outgoing state | mu | incoming state>
 void joi(HLV pout, bool helout, HLV pin, bool helin, current &cur) {
 
   cur[0] = 0.0;
   cur[1] = 0.0;
   cur[2] = 0.0;
   cur[3] = 0.0;
   if(helin){
     std::cout<<__LINE__<<" "<<__FILE__<<std::endl;
   }
   double sqpop  = sqrt(pout.plus());
   double sqpom  = sqrt(pout.minus());
   COM    poperp = pout.x() + COM(0, 1) * pout.y();
 
   if (helout == false) {
 
     if (pin.plus() > pin.minus()) { // if forward
       double sqpip=sqrt(pin.plus());
       cur[0] = sqpop * sqpip;
       cur[1] = sqpom * sqpip * poperp/abs(poperp);
       cur[2] = -COM(0,1)*cur[1];
       cur[3] = cur[0];
     }
     else {
       double sqpim = sqrt(pin.minus());
       cur[0] = -sqpom*sqpim*poperp/abs(poperp);
       cur[1] = -sqpim*sqpop;
       cur[2] = COM(0,1)*cur[1];
       cur[3] = -cur[0];
     }
   }
   else {
     if (pin.plus() > pin.minus()) { // if forward
       double sqpip = sqrt(pin.plus());
       cur[0] = sqpop * sqpip;
       cur[1] = sqpom * sqpip*conj(poperp)/abs(poperp);
       cur[2] = COM(0,1)*cur[1];
       cur[3] = cur[0];
     }
     else {
       double sqpim = sqrt(pin.minus());
       cur[0] = -sqpom * sqpim * conj(poperp)/abs(poperp);
       cur[1] = -sqpim * sqpop;
       cur[2] = -COM(0,1)*cur[1];
       cur[3] = -cur[0];
     }
   }
 }
 
 namespace {
   /// @TODO unused function
   // double jM2 (CLHEP::HepLorentzVector p1out, bool hel1out, CLHEP::HepLorentzVector p1in, bool hel1in, CLHEP::HepLorentzVector p2out, bool hel2out, CLHEP::HepLorentzVector p2in, bool hel2in)
   // {
   //   CLHEP::HepLorentzVector q1=p1in-p1out;
   //   CLHEP::HepLorentzVector q2=-(p2in-p2out);
   //   current C1,C2;
   //   j (p1out,hel1out,p1in,hel1in, C1);
   //   j (p2out,hel2out,p2in,hel2in, C2);
 
   //   std::cout << "# From Currents, C1 : ("<<C1[0]<<","<<C1[1]<<","<<C1[2]<<","<<C1[3]<<"\n";
   //   std::cout << "# From Currents, C2 : ("<<C2[0]<<","<<C2[1]<<","<<C2[2]<<","<<C2[3]<<"\n";
 
   //   COM M=cdot(C1,C2);
 
   //   return (M*conj(M)).real()/(q1.m2()*q2.m2());
   // }
 
   void jW (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pe, bool hele, CLHEP::HepLorentzVector pnu, bool helnu, CLHEP::HepLorentzVector pin, bool helin, current cur)
   {
     // NOTA BENE: Conventions for W+ --> e+ nu, so that nu is lepton(6), e is anti-lepton(5)
     // Need to swap e and nu for events with W- --> e- nubar!
     if (helin==helout && hele==helnu) {
       CLHEP::HepLorentzVector qa=pout+pe+pnu;
       CLHEP::HepLorentzVector qb=pin-pe-pnu;
       double ta(qa.m2()),tb(qb.m2());
 
       current t65,vout,vin,temp2,temp3,temp5;
       joo(pnu,helnu,pe,hele,t65);
       vout[0]=pout.e();
       vout[1]=pout.x();
       vout[2]=pout.y();
       vout[3]=pout.z();
       vin[0]=pin.e();
       vin[1]=pin.x();
       vin[2]=pin.y();
       vin[3]=pin.z();
 
       COM brac615=cdot(t65,vout);
       COM brac645=cdot(t65,vin);
 
       // prod1565 and prod6465 are zero for Ws (not Zs)!!
       // noalias(temp)=prod(trans(CurrentOutOut(pout,helout,pnu,helout)),metric);
       joo(pout,helout,pnu,helout,temp2);
       // noalias(temp2)=prod(temp,ctemp);
       COM prod1665=cdot(temp2,t65);
       // noalias(temp)=prod(trans(Current(pe,helin,pin,helin)),metric);
       // noalias(temp2)=prod(temp,ctemp);
       j(pe,helin,pin,helin,temp3);
       COM prod5465=cdot(temp3,t65);
       // noalias(temp)=prod(trans(Current(pnu,helin,pin,helin)),metric);
       // noalias(temp2)=prod(temp,ctemp);
 
       joo(pout,helout,pe,helout,temp2);
       j(pnu,helnu,pin,helin,temp3);
       j(pout,helout,pin,helin,temp5);
 
       current term1,term2,term3,sum;
       cmult(2.*brac615/ta+2.*brac645/tb,temp5,term1);
       cmult(prod1665/ta,temp3,term2);
       cmult(-prod5465/tb,temp2,term3);
 
      //    cur=((2.*brac615*Current(pout,helout,pin,helin)+prod1565*Current(pe,helin,pin,helin)+prod1665*Current(pnu,helin,pin,helin))/ta + (2.*brac645*Current(pout,helout,pin,helin)-prod5465*CurrentOutOut(pout,helout,pe,helout)-prod6465*CurrentOutOut(pout,helout,pnu,helout))/tb);
       //    cur=((2.*brac615*temp5+prod1565*temp3+prod1665*temp4)/ta + (2.*brac645*temp5-prod5465*temp1-prod6465*temp2)/tb);
       cadd(term1,term2,term3,sum);
       //    std::cout<<"sum: ("<<sum[0]<<","<<sum[1]<<","<<sum[2]<<","<<sum[3]<<")\n";
       cur[0]=sum[0];
       cur[1]=sum[1];
       cur[2]=sum[2];
       cur[3]=sum[3];
     }
   }
 
   void jWbar (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pe, bool hele, CLHEP::HepLorentzVector pnu, bool helnu, CLHEP::HepLorentzVector pin, bool helin, current cur)
   {
     // NOTA BENE: Conventions for W+ --> e+ nu, so that nu is lepton(6), e is anti-lepton(5)
     // Need to swap e and nu for events with W- --> e- nubar!
     if (helin==helout && hele==helnu) {
       CLHEP::HepLorentzVector qa=pout+pe+pnu;
       CLHEP::HepLorentzVector qb=pin-pe-pnu;
       double ta(qa.m2()),tb(qb.m2());
 
       current t65,vout,vin,temp2,temp3,temp5;
       joo(pnu,helnu,pe,hele,t65);
       vout[0]=pout.e();
       vout[1]=pout.x();
       vout[2]=pout.y();
       vout[3]=pout.z();
       vin[0]=pin.e();
       vin[1]=pin.x();
       vin[2]=pin.y();
       vin[3]=pin.z();
 
       COM brac615=cdot(t65,vout);
       COM brac645=cdot(t65,vin);
 
       // prod1565 and prod6465 are zero for Ws (not Zs)!!
       joo(pe,helout,pout,helout,temp2);  //  temp2 is <5|alpha|1>
       COM prod5165=cdot(temp2,t65);
       jio(pin,helin,pnu,helin,temp3);      // temp3 is <4|alpha|6>
       COM prod4665=cdot(temp3,t65);
 
       joo(pnu,helout,pout,helout,temp2);  // temp2 is now <6|mu|1>
       jio(pin,helin,pe,helin,temp3);        // temp3 is now <4|mu|5>
       jio(pin,helin,pout,helout,temp5);     //  temp5 is <4|mu|1>
 
       current term1,term2,term3,sum;
       cmult(-2.*brac615/ta-2.*brac645/tb,temp5,term1);
       cmult(-prod5165/ta,temp3,term2);
       cmult(prod4665/tb,temp2,term3);
 
      //    cur=((2.*brac615*Current(pout,helout,pin,helin)+prod1565*Current(pe,helin,pin,helin)+prod1665*Current(pnu,helin,pin,helin))/ta + (2.*brac645*Current(pout,helout,pin,helin)-prod5465*CurrentOutOut(pout,helout,pe,helout)-prod6465*CurrentOutOut(pout,helout,pnu,helout))/tb);
       //    cur=((2.*brac615*temp5+prod1565*temp3+prod1665*temp4)/ta + (2.*brac645*temp5-prod5465*temp1-prod6465*temp2)/tb);
       cadd(term1,term2,term3,sum);
       //    std::cout<<"term1: ("<<temp5[0]<<"  "<<temp5[1]<<"  "<<temp5[2]<<"  "<<temp5[3]<<")"<<std::endl;
       //    std::cout<<"sum: ("<<sum[0]<<","<<sum[1]<<","<<sum[2]<<","<<sum[3]<<")\n";
       cur[0]=sum[0];
       cur[1]=sum[1];
       cur[2]=sum[2];
       cur[3]=sum[3];
     }
   }
 } // namespace anonymous
 
 double jMWqQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for qQ->qenuQ scattering
 // p1: quark (with W emittance)
 // p2: Quark
 {
   current mj1m,mj2p,mj2m;
   CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
   CLHEP::HepLorentzVector q2=-(p2in-p2out);
 
   jW(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
   j(p2out,true,p2in,true,mj2p);
   j(p2out,false,p2in,false,mj2m);
 
-  // std::cout<<"jMW1: ("<<mj1m[0]<<","<<mj1m[1]<<","<<mj1m[2]<<","<<mj1m[3]<<")\n";
-  // std::cout<<"jMW2: ("<<mj2p[0]<<","<<mj2p[1]<<","<<mj2p[2]<<","<<mj2p[3]<<")\n";
-  // std::cout<<"jMW3: ("<<mj2m[0]<<","<<mj2m[1]<<","<<mj2m[2]<<","<<mj2m[3]<<")\n";
-
-  // mj1m.mj2p
-
   COM Mmp=cdot(mj1m,mj2p);
 
   // mj1m.mj2m
   COM Mmm=cdot(mj1m,mj2m);
 
   // sum of spinor strings ||^2
   double a2Mmp=abs2(Mmp);
   double a2Mmm=abs2(Mmm);
 
-//   // Leave division by colour and Helicity avg until Tree files
+  // Leave division by colour and Helicity avg until Tree files
   // Leave multi. of couplings to later
   // Multiply by Cf^2
-  return (4./3.)*(4./3.)*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2());
+  return C_F*C_F*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2());
 
 }
 
 double jMWqQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for qQ->qenuQ scattering
 // p1: quark (with W emittance)
 // p2: Quark
 {
   current mj1m,mj2p,mj2m;
   CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
   CLHEP::HepLorentzVector q2=-(p2in-p2out);
 
   jW(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
   jio(p2in,true,p2out,true,mj2p);
   jio(p2in,false,p2out,false,mj2m);
 
-  // std::cout<<"jMW1: ("<<mj1m[0]<<","<<mj1m[1]<<","<<mj1m[2]<<","<<mj1m[3]<<")\n";
-  // std::cout<<"jMW2: ("<<mj2p[0]<<","<<mj2p[1]<<","<<mj2p[2]<<","<<mj2p[3]<<")\n";
-  // std::cout<<"jMW3: ("<<mj2m[0]<<","<<mj2m[1]<<","<<mj2m[2]<<","<<mj2m[3]<<")\n";
-
-  // mj1m.mj2p
-
   COM Mmp=cdot(mj1m,mj2p);
 
   // mj1m.mj2m
   COM Mmm=cdot(mj1m,mj2m);
 
   // sum of spinor strings ||^2
   double a2Mmp=abs2(Mmp);
   double a2Mmm=abs2(Mmm);
 
-//   // Leave division by colour and Helicity avg until Tree files
+  // Leave division by colour and Helicity avg until Tree files
   // Leave multi. of couplings to later
   // Multiply by Cf^2
-  return (4./3.)*(4./3.)*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2());
+  return C_F*C_F*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2());
 
 }
 
 double jMWqbarQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for qQ->qenuQ scattering
 // p1: quark (with W emittance)
 // p2: Quark
 {
   current mj1m,mj2p,mj2m;
   CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
   CLHEP::HepLorentzVector q2=-(p2in-p2out);
 
   jWbar(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
   j(p2out,true,p2in,true,mj2p);
   j(p2out,false,p2in,false,mj2m);
 
-  // std::cout<<"jMW1: ("<<mj1m[0]<<","<<mj1m[1]<<","<<mj1m[2]<<","<<mj1m[3]<<")\n";
-  // std::cout<<"jMW2: ("<<mj2p[0]<<","<<mj2p[1]<<","<<mj2p[2]<<","<<mj2p[3]<<")\n";
-  // std::cout<<"jMW3: ("<<mj2m[0]<<","<<mj2m[1]<<","<<mj2m[2]<<","<<mj2m[3]<<")\n";
-
-  // mj1m.mj2p
-
   COM Mmp=cdot(mj1m,mj2p);
 
   // mj1m.mj2m
   COM Mmm=cdot(mj1m,mj2m);
 
   // sum of spinor strings ||^2
   double a2Mmp=abs2(Mmp);
   double a2Mmm=abs2(Mmm);
 
-//   // Leave division by colour and Helicity avg until Tree files
+  // Leave division by colour and Helicity avg until Tree files
   // Leave multi. of couplings to later
   // Multiply by Cf^2
-  return (4./3.)*(4./3.)*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2());
+  return C_F*C_F*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2());
 
 }
 
 double jMWqbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for qQ->qenuQ scattering
 // p1: quark (with W emittance)
 // p2: Quark
 {
   current mj1m,mj2p,mj2m;
   CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
   CLHEP::HepLorentzVector q2=-(p2in-p2out);
 
   jWbar(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
   jio(p2in,true,p2out,true,mj2p);
   jio(p2in,false,p2out,false,mj2m);
 
-  // std::cout<<"jMW1: ("<<mj1m[0]<<","<<mj1m[1]<<","<<mj1m[2]<<","<<mj1m[3]<<")\n";
-  // std::cout<<"jMW2: ("<<mj2p[0]<<","<<mj2p[1]<<","<<mj2p[2]<<","<<mj2p[3]<<")\n";
-  // std::cout<<"jMW3: ("<<mj2m[0]<<","<<mj2m[1]<<","<<mj2m[2]<<","<<mj2m[3]<<")\n";
-
-  // mj1m.mj2p
-
   COM Mmp=cdot(mj1m,mj2p);
 
   // mj1m.mj2m
   COM Mmm=cdot(mj1m,mj2m);
 
   // sum of spinor strings ||^2
   double a2Mmp=abs2(Mmp);
   double a2Mmm=abs2(Mmm);
 
-//   // Leave division by colour and Helicity avg until Tree files
+  // Leave division by colour and Helicity avg until Tree files
   // Leave multi. of couplings to later
   // Multiply by Cf^2
-  return (4./3.)*(4./3.)*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2());
+  return C_F*C_F*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2());
 
 }
 
 double jMWqg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for qg->qenug scattering
 // p1: quark
 // p2: gluon
 {
   CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
   CLHEP::HepLorentzVector q2=-(p2in-p2out);
   current mj1m,mj2p,mj2m;
 
   jW(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
 
   j(p2out,true,p2in,true,mj2p);
   j(p2out,false,p2in,false,mj2m);
 
   // mj1m.mj2p
-
   COM Mmp=cdot(mj1m,mj2p);
 
   // mj1m.mj2m
   COM Mmm=cdot(mj1m,mj2m);
 
   const double K = K_g(p2out, p2in);
 
   // sum of spinor strings ||^2
   double a2Mmp=abs2(Mmp);
   double a2Mmm=abs2(Mmm);
   double sst = K/C_A*(a2Mmp+a2Mmm);
-  // double sstsave=sst;
 
-//   // Leave division by colour and Helicity avg until Tree files
+  // Leave division by colour and Helicity avg until Tree files
   // Leave multi. of couplings to later
   // Multiply by Cf*Ca=4
-  return 4.*sst/(q1.m2()*q2.m2());
+  return C_F*C_A*sst/(q1.m2()*q2.m2());
 
 }
 
 double jMWqbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for qg->qenug scattering
 // p1: quark
 // p2: gluon
 {
   CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
   CLHEP::HepLorentzVector q2=-(p2in-p2out);
   current mj1m,mj2p,mj2m;
 
   jWbar(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
 
   j(p2out,true,p2in,true,mj2p);
   j(p2out,false,p2in,false,mj2m);
 
   // mj1m.mj2p
-
   COM Mmp=cdot(mj1m,mj2p);
 
   // mj1m.mj2m
   COM Mmm=cdot(mj1m,mj2m);
 
   const double K = K_g(p2out, p2in);
 
   // sum of spinor strings ||^2
   double a2Mmp=abs2(Mmp);
   double a2Mmm=abs2(Mmm);
   double sst = K/C_A*(a2Mmp+a2Mmm);
-  // double sstsave=sst;
 
 //   // Leave division by colour and Helicity avg until Tree files
   // Leave multi. of couplings to later
   // Multiply by Cf*Ca=4
-  return 4.*sst/(q1.m2()*q2.m2());
+  return C_F*C_A*sst/(q1.m2()*q2.m2());
 
 }
 
 double jM2qQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 {
   //  std::cerr<<"Current: "<<p1out<<"  "<<p1in<<"  "<<p2out<<"  "<<p2in<<std::endl;
 
   CLHEP::HepLorentzVector q1=p1in-p1out;
   CLHEP::HepLorentzVector q2=-(p2in-p2out);
   //  std::cerr<<"Current:  "<<q1.m2()<<"  "<<q2.m2()<<std::endl;
   current mj1m,mj1p,mj2m,mj2p;
   j(p1out,true,p1in,true,mj1p);
   j(p1out,false,p1in,false,mj1m);
   j(p2out,true,p2in,true,mj2p);
   j(p2out,false,p2in,false,mj2m);
 
   COM Mmp=cdot(mj1m,mj2p);
   COM Mmm=cdot(mj1m,mj2m);
   COM Mpp=cdot(mj1p,mj2p);
   COM Mpm=cdot(mj1p,mj2m);
 
   double sst=abs2(Mmm)+abs2(Mmp)+abs2(Mpp)+abs2(Mpm);
 
   // Multiply by Cf^2
   return RHEJ::C_F*RHEJ::C_F*(sst)/(q1.m2()*q2.m2());
 }
 
 double jM2qQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 {
   CLHEP::HepLorentzVector q1=p1in-p1out;
   CLHEP::HepLorentzVector q2=-(p2in-p2out);
   current mj1m,mj1p,mj2m,mj2p;
   j(p1out,true,p1in,true,mj1p);
   j(p1out,false,p1in,false,mj1m);
   jio(p2in,true,p2out,true,mj2p);
   jio(p2in,false,p2out,false,mj2m);
 
   COM Mmp=cdot(mj1m,mj2p);
   COM Mmm=cdot(mj1m,mj2m);
   COM Mpp=cdot(mj1p,mj2p);
   COM Mpm=cdot(mj1p,mj2m);
 
   double sumsq=abs2(Mmm)+abs2(Mmp)+abs2(Mpp)+abs2(Mpm);
 
   // Multiply by Cf^2
-  return (4./3.)*(4./3.)*(sumsq)/(q1.m2()*q2.m2());
+  return C_F*C_F*(sumsq)/(q1.m2()*q2.m2());
 }
 
 double jM2qbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 {
   CLHEP::HepLorentzVector q1=p1in-p1out;
   CLHEP::HepLorentzVector q2=-(p2in-p2out);
   current mj1m,mj1p,mj2m,mj2p;
   jio(p1in,true,p1out,true,mj1p);
   jio(p1in,false,p1out,false,mj1m);
   jio(p2in,true,p2out,true,mj2p);
   jio(p2in,false,p2out,false,mj2m);
 
   COM Mmp=cdot(mj1m,mj2p);
   COM Mmm=cdot(mj1m,mj2m);
   COM Mpp=cdot(mj1p,mj2p);
   COM Mpm=cdot(mj1p,mj2m);
 
   double sumsq=abs2(Mmm)+abs2(Mmp)+abs2(Mpp)+abs2(Mpm);
 
   // Multiply by Cf^2
-  return (4./3.)*(4./3.)*(sumsq)/(q1.m2()*q2.m2());
+  return C_F*C_F*(sumsq)/(q1.m2()*q2.m2());
 }
 
 double jM2qg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for qg scattering
 // p1: quark
 // p2: gluon
 {
   CLHEP::HepLorentzVector q1=p1in-p1out;
   CLHEP::HepLorentzVector q2=-(p2in-p2out);
 
   current mj1m,mj1p,mj2m,mj2p;
   j(p1out,true,p1in,true,mj1p);
   j(p1out,false,p1in,false,mj1m);
   j(p2out,true,p2in,true,mj2p);
   j(p2out,false,p2in,false,mj2m);
 
   COM Mmp=cdot(mj1m,mj2p);
   COM Mmm=cdot(mj1m,mj2m);
   COM Mpp=cdot(mj1p,mj2p);
   COM Mpm=cdot(mj1p,mj2m);
 
   const double K = K_g(p2out, p2in);
 
   // sum of spinor strings ||^2
   double a2Mmp=abs2(Mmp);
   double a2Mmm=abs2(Mmm);
   double a2Mpp=abs2(Mpp);
   double a2Mpm=abs2(Mpm);
   double sst = K/C_A*(a2Mpp+a2Mpm+a2Mmp+a2Mmm);
-  // double sstsave=sst;
 
-   // std::cout <<"ratio: "<<sst/sstsave<<std::endl;
   // Cf*Ca=4
-  return 4.*sst/(q1.m2()*q2.m2());
+  return C_F*C_A*sst/(q1.m2()*q2.m2());
 
 }
 
 double jM2qbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for qg scattering
 // p1: quark
 // p2: gluon
 {
   CLHEP::HepLorentzVector q1=p1in-p1out;
   CLHEP::HepLorentzVector q2=-(p2in-p2out);
 
   current mj1m,mj1p,mj2m,mj2p;
   jio(p1in,true,p1out,true,mj1p);
   jio(p1in,false,p1out,false,mj1m);
   j(p2out,true,p2in,true,mj2p);
   j(p2out,false,p2in,false,mj2m);
 
   COM Mmp=cdot(mj1m,mj2p);
   COM Mmm=cdot(mj1m,mj2m);
   COM Mpp=cdot(mj1p,mj2p);
   COM Mpm=cdot(mj1p,mj2m);
 
   const double K = K_g(p2out, p2in);
 
   // sum of spinor strings ||^2
   double a2Mmp=abs2(Mmp);
   double a2Mmm=abs2(Mmm);
   double a2Mpp=abs2(Mpp);
   double a2Mpm=abs2(Mpm);
   double sst = K/C_A*(a2Mpp+a2Mpm+a2Mmp+a2Mmm);
-  // double sstsave=sst;
 
-   // std::cout <<"ratio: "<<sst/sstsave<<std::endl;
   // Cf*Ca=4
-  return 4.*sst/(q1.m2()*q2.m2());
+  return C_F*C_A*sst/(q1.m2()*q2.m2());
 
 }
 
 double jM2gg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
 // Calculates the square of the current contractions for gg scattering
 // p1: gluon
 // p2: gluon
 {
   CLHEP::HepLorentzVector q1=p1in-p1out;
   CLHEP::HepLorentzVector q2=-(p2in-p2out);
 
   current mj1m,mj1p,mj2m,mj2p;
   j(p1out,true,p1in,true,mj1p);
   j(p1out,false,p1in,false,mj1m);
   j(p2out,true,p2in,true,mj2p);
   j(p2out,false,p2in,false,mj2m);
 
   COM Mmp=cdot(mj1m,mj2p);
   COM Mmm=cdot(mj1m,mj2m);
   COM Mpp=cdot(mj1p,mj2p);
   COM Mpm=cdot(mj1p,mj2m);
 
   const double K_g1 = K_g(p1out, p1in);
   const double K_g2 = K_g(p2out, p2in);
 
   // sum of spinor strings ||^2
   double a2Mmp=abs2(Mmp);
   double a2Mmm=abs2(Mmm);
   double a2Mpp=abs2(Mpp);
   double a2Mpm=abs2(Mpm);
   double sst = K_g1/C_A*K_g2/C_A*(a2Mpp+a2Mpm+a2Mmp+a2Mmm);
-  // double sstsave=sst;
-   // std::cout <<"ratio: "<<sst/sstsave<<std::endl;
   // Ca*Ca=9
-  return 9.*sst/(q1.m2()*q2.m2());
-
+  return C_A*C_A*sst/(q1.m2()*q2.m2());
 }
 
 namespace {
-  /// @TODO what was this intended to do?
-  // double MH2helper(current C1, current C2, current q1, current q2)
-  // {
-  //   COM M;
-  //   COM temp1,temp2;
-  //   // First the C1.q2 * C2.q1 - part
-  //   temp1=cdot(C1,q2);
-  //   temp2=cdot(C2,q1);
-  //   M=temp1*temp2;
-
-  //   // Then the C1.C2 * q1.q2
-  //   temp1=cdot(C1,C2);
-  //   temp2=cdot(q1,q2);
-  //   M-=temp1*temp2;
-
-  //   return (M*conj(M)).real();
-  // }
-
   /**
    * @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)
   {
     if (mt == infinity) {
       return (cdot(C1,C2)*cdot(q1,q2)-cdot(C1,q2)*cdot(C2,q1))/(6*M_PI*v);
     }
     else {
       CLHEP::HepLorentzVector 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
       // std::cout<<"A1 : " << A1(-vq1,vq2)<<std::endl;
       // std::cout<<"A2 : " << A2(-vq1,vq2)<<std::endl;
       if(!(incBot))
         // Factor is because 4 mt^2 g^2/v A1 -> 16 pi mt^2/v alphas,
         // and we divide by a factor 4 at the amp sqaured level later
         // which I absorb here (i.e. I divide by 2)
         /// @TODO move factor 1/2 from S to |ME|^2 => consistent with general notation
         return 8.*M_PI*mt*mt/v*(-cdot(C1,q2)*cdot(C2,q1)*A1(-vq1,vq2,mt)-cdot(C1,C2)*A2(-vq1,vq2,mt));
       else
         return 8.*M_PI*mt*mt/v*(-cdot(C1,q2)*cdot(C2,q1)*A1(-vq1,vq2,mt)-cdot(C1,C2)*A2(-vq1,vq2,mt))
              + 8.*M_PI*mb*mb/v*(-cdot(C1,q2)*cdot(C2,q1)*A1(-vq1,vq2,mb)-cdot(C1,C2)*A2(-vq1,vq2,mb));
     }
   }
 } // namespace anonymous
 
 double MH2qQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
               CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
               CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2,
               double mt, bool incBot, double mb)
 {
 //   CLHEP::HepLorentzVector q1=p1in-p1out;
 //   CLHEP::HepLorentzVector q2=-(p2in-p2out);
   current j1p,j1m,j2p,j2m, q1v, q2v;
 
   j (p1out,true,p1in,true,j1p);
   j (p1out,false,p1in,false,j1m);
 
   j (p2out,true,p2in,true,j2p);
   j (p2out,false,p2in,false,j2m);
 
   to_current(q1, q1v);
   to_current(q2, q2v);
 
   COM Mmp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
   COM Mmm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
   COM Mpp=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
   COM Mpm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
 
   double sst=abs2(Mmp)+abs2(Mmm)+abs2(Mpp)+abs2(Mpm);
   // return (4./3.)*(4./3.)*sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
   return sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
 }
 
 double MH2qQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt, bool incBot, double mb)
 {
 //   CLHEP::HepLorentzVector q1=p1in-p1out;
 //   CLHEP::HepLorentzVector q2=-(p2in-p2out);
   current j1p,j1m,j2p,j2m,q1v,q2v;
 
   j (p1out,true,p1in,true,j1p);
   j (p1out,false,p1in,false,j1m);
 
   jio (p2in,true,p2out,true,j2p);
   jio (p2in,false,p2out,false,j2m);
 
   to_current(q1, q1v);
   to_current(q2, q2v);
 
   COM Mmp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
   COM Mmm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
   COM Mpp=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
   COM Mpm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
 
   double sst=abs2(Mmp)+abs2(Mmm)+abs2(Mpp)+abs2(Mpm);
   // return (4./3.)*(4./3.)*sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
   return sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
 }
 
 double MH2qbarQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt, bool incBot, double mb)
 {
 //   CLHEP::HepLorentzVector q1=p1in-p1out;
 //   CLHEP::HepLorentzVector q2=-(p2in-p2out);
   current j1p,j1m,j2p,j2m,q1v,q2v;
 
   jio (p1in,true,p1out,true,j1p);
   jio (p1in,false,p1out,false,j1m);
 
   j (p2out,true,p2in,true,j2p);
   j (p2out,false,p2in,false,j2m);
 
   to_current(q1, q1v);
   to_current(q2, q2v);
 
   COM Mmp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
   COM Mmm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
   COM Mpp=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
   COM Mpm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
 
   double sst=abs2(Mmp)+abs2(Mmm)+abs2(Mpp)+abs2(Mpm);
   // return (4./3.)*(4./3.)*sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
   return sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
 }
 
 double MH2qbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt, bool incBot, double mb)
 {
 //   CLHEP::HepLorentzVector q1=p1in-p1out;
 //   CLHEP::HepLorentzVector q2=-(p2in-p2out);
   current j1p,j1m,j2p,j2m,q1v,q2v;
 
   jio (p1in,true,p1out,true,j1p);
   jio (p1in,false,p1out,false,j1m);
 
   jio (p2in,true,p2out,true,j2p);
   jio (p2in,false,p2out,false,j2m);
 
   to_current(q1, q1v);
   to_current(q2, q2v);
 
   COM Mmp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
   COM Mmm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
   COM Mpp=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
   COM Mpm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
 
   double sst=abs2(Mmp)+abs2(Mmm)+abs2(Mpp)+abs2(Mpm);
   // return (4./3.)*(4./3.)*sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
   return sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
 }
 
 double MH2qg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt, bool incBot, double mb)
 // q~p1 g~p2 (i.e. ALWAYS p1 for quark, p2 for gluon)
 // should be called with q1 meant to be contracted with p2 in first part of vertex
 // (i.e. if g is backward, q1 is forward)
 {
   current j1p,j1m,j2p,j2m,q1v,q2v;
 
   j (p1out,true,p1in,true,j1p);
   j (p1out,false,p1in,false,j1m);
 
   j (p2out,true,p2in,true,j2p);
   j (p2out,false,p2in,false,j2m);
 
   to_current(q1, q1v);
   to_current(q2, q2v);
 
   // First, calculate the non-flipping amplitudes:
 
   COM Mpp=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
   COM Mpm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
   COM Mmp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
   COM Mmm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
 
   //cout << "Bits in MH2qg: " << Mpp << " " << Mpm << " " << Mmp << " " << Mmm << endl;
 
   const double K = K_g(p2out, p2in);
 
   double sst=K/C_A*(abs2(Mmp)+abs2(Mmm)+abs2(Mpp)+abs2(Mpm));
 
   // Cf*Ca=4
   // return 4.*sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
   return sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
 }
 
 double MH2qbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt, bool incBot, double mb)
 // qbar~p1 g~p2 (i.e. ALWAYS p1 for anti-quark, p2 for gluon)
 // should be called with q1 meant to be contracted with p2 in first part of vertex
 // (i.e. if g is backward, q1 is forward)
 {
   current j1p,j1m,j2p,j2m,q1v,q2v;
 
   jio (p1in,true,p1out,true,j1p);
   jio (p1in,false,p1out,false,j1m);
 
   j (p2out,true,p2in,true,j2p);
   j (p2out,false,p2in,false,j2m);
 
   to_current(q1, q1v);
   to_current(q2, q2v);
 
   // First, calculate the non-flipping amplitudes:
 
   COM amp,amm,apm,app;
   app=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
   apm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
   amp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
   amm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
 
   double MH2sum = abs2(app)+abs2(amm)+abs2(apm)+abs2(amp);
 
   const double K = K_g(p2out, p2in);
   MH2sum*=K/C_A;
 
   // Cf*Ca=4
   // return 4.*MH2sum/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
   return MH2sum/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
 }
 
 double MH2gg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt, bool incBot, double mb)
 // g~p1 g~p2
 // should be called with q1 meant to be contracted with p2 in first part of vertex
 // (i.e. if g is backward, q1 is forward)
 {
   current j1p,j1m,j2p,j2m,q1v,q2v;
 
   j (p1out,true,p1in,true,j1p);
   j (p1out,false,p1in,false,j1m);
 
   j (p2out,true,p2in,true,j2p);
   j (p2out,false,p2in,false,j2m);
 
   to_current(q1, q1v);
   to_current(q2, q2v);
 
   // First, calculate the non-flipping amplitudes:
 
   COM amp,amm,apm,app;
   app=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
   apm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
   amp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
   amm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
 
   double MH2sum = abs2(app)+abs2(amm)+abs2(apm)+abs2(amp);
 
   const double K_g1 = K_g(p1out, p1in);
   const double K_g2 = K_g(p2out, p2in);
 
   MH2sum*=K_g1/C_A*K_g2/C_A;
 
   // Ca*Ca=9
   // return 9.*MH2sum/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
   return MH2sum/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
 }
 
 // // Z's stuff
 // void jZ(HLV pin, HLV pout, HLV pem, HLV pep, bool HelPartons, bool HelLeptons, current cur) {
 
 //  // Init current to zero
 //  cur[0] = 0.0;
 //  cur[1] = 0.0;
 //  cur[2] = 0.0;
 //  cur[3] = 0.0;
 
 //  // Temporary variables
 //  COM temp;
 //  current Term_1, Term_2, Term_3, Term_4, J_temp, TempCur1, TempCur2;
 
 //  // Momentum of virtual gluons aroun weak boson emission site
 //  HLV qa = pout + pep + pem;
 //  HLV qb = pin  - pep - pem;
 
 //  double ta = qa.m2();
 //  double tb = qb.m2();
 
 //  // Out-Out currents:
 //  current Em_Ep, Out_Em, Out_Ep;
 
 //  // Other currents:
 //  current Out_In, Em_In, Ep_In;
 
 //  joi(pout, HelPartons, pin, HelPartons, Out_In);
 //  joi(pem,  HelLeptons, pin, HelPartons, Em_In);
 //  joi(pep,  HelLeptons, pin, HelPartons, Ep_In);
 
 //  joo(pem,  HelLeptons, pep, HelLeptons, Em_Ep);
 //  joo(pout, HelPartons, pem, HelLeptons, Out_Em);
 //  joo(pout, HelPartons, pep, HelLeptons, Out_Ep);
 
 //  if (HelLeptons == HelPartons) {
 
 //    temp = 2.0 * cdot(pout, Em_Ep);
 //    cmult(temp / ta, Out_In, Term_1);
 
 //    temp = cdot(Out_Em, Em_Ep);
 //    cmult(temp / ta , Em_In, Term_2);
 
 //    temp = 2.0 * cdot(pin, Em_Ep);
 //    cmult(temp / tb, Out_In, Term_3);
 
 //    temp = -cdot(Ep_In, Em_Ep);
 //    cmult(temp / tb, Out_Ep, Term_4);
 
 //    cadd(Term_1, Term_2, Term_3, Term_4, J_temp);
 
 //    cur[0] = J_temp[0];
 //    cur[1] = J_temp[1];
 //    cur[2] = J_temp[2];
 //    cur[3] = J_temp[3];
 //  }
 
 //  else {
 //    if (HelPartons == true) {
 //      temp = 2.0 * cdot(pout, Em_Ep);
 //      cmult(temp / ta, Out_In, Term_1);
 
 //      joo(pout, true, pep, true, TempCur1);
 //      joi(pep,  true, pin, true, TempCur2);
 
 //      temp = cdot(TempCur1, Em_Ep);
 //      cmult(temp / ta , TempCur2, Term_2);
 
 //      temp = 2.0 * cdot(pin, Em_Ep);
 //      cmult(temp / tb, Out_In, Term_3);
 
 //      joo(pout, true, pem, true, TempCur1);
 //      joi(pem,  true, pin, true, TempCur2);
 
 //      temp = -cdot(TempCur2, Em_Ep);
 //      cmult(temp / tb, TempCur1, Term_4);
 
 //      cadd(Term_1, Term_2, Term_3, Term_4, J_temp);
 
 //      cur[0] = J_temp[0];
 //      cur[1] = J_temp[1];
 //      cur[2] = J_temp[2];
 //      cur[3] = J_temp[3];
 //    }
 
 //    else {
 //      temp = 2.0 * cdot(pout, Em_Ep);
 //      cmult(temp / ta, Out_In, Term_1);
 
 //      joo(pout, false, pep, false, TempCur1);
 //      joi(pep,  false, pin, false, TempCur2);
 
 //      temp = cdot(TempCur1, Em_Ep);
 //      cmult(temp / ta, TempCur2, Term_2);
 
 //      temp = 2.0 * cdot(pin, Em_Ep);
 //      cmult(temp / tb, Out_In, Term_3);
 
 //      joo(pout, false, pem, false, TempCur1);
 //      joi(pem,  false, pin, false, TempCur2);
 
 //      temp = -cdot(TempCur2, Em_Ep);
 //      cmult(temp / tb, TempCur1, Term_4);
 
 //      cadd(Term_1, Term_2, Term_3, Term_4, J_temp);
 
 //      cur[0] = J_temp[0];
 //      cur[1] = J_temp[1];
 //      cur[2] = J_temp[2];
 //      cur[3] = J_temp[3];
 //    }
 
 //  }
 // }
 
 // void jZbar(HLV pin, HLV pout, HLV pem, HLV pep, bool HelPartons, bool HelLeptons, current cur) {
 
 //  // Init current to zero
 //  cur[0] = 0.0;
 //  cur[1] = 0.0;
 //  cur[2] = 0.0;
 //  cur[3] = 0.0;
 
 //  // Temporary variables
 //  COM temp;
 //  current Term_1, Term_2, Term_3, Term_4, J_temp, TempCur1, TempCur2;
 
 //  // Transfered 4-momenta
 //  HLV qa = pout + pep + pem;
 //  HLV qb = pin  - pep - pem;
 
 //  // The square of the transfered 4-momenta
 //  double ta = qa.m2();
 //  double tb = qb.m2();
 
 //  // Out-Out currents:
 //  current Em_Ep, Em_Out, Ep_Out;
 
 //  // In-Out currents:
 //  current In_Out, In_Em, In_Ep;
 
 //  // Safe to use the currents since helicity structure is ok
 //  if (HelPartons == HelLeptons) {
 //    jio(pin, HelPartons, pout, HelPartons, In_Out);
 //    joo(pem, HelLeptons, pep,  HelLeptons, Em_Ep);
 //    jio(pin, HelPartons, pem,  HelLeptons, In_Em);
 //    jio(pin, HelPartons, pep,  HelLeptons, In_Ep);
 //    joo(pem, HelLeptons, pout, HelPartons, Em_Out);
 //    joo(pep, HelLeptons, pout, HelPartons, Ep_Out);
 //  }
 
 //  else {
 //    jio(pin, HelPartons, pout, HelPartons, In_Out);
 //    joo(pem, HelLeptons, pep,  HelLeptons, Em_Ep);
 
 //    In_Em[0] = 0.0;
 //    In_Em[1] = 0.0;
 //    In_Em[2] = 0.0;
 //    In_Em[3] = 0.0;
 
 //    In_Ep[0] = 0.0;
 //    In_Ep[1] = 0.0;
 //    In_Ep[2] = 0.0;
 //    In_Ep[3] = 0.0;
 
 //    Em_Out[0] = 0.0;
 //    Em_Out[1] = 0.0;
 //    Em_Out[2] = 0.0;
 //    Em_Out[3] = 0.0;
 
 //    Ep_Out[0] = 0.0;
 //    Ep_Out[1] = 0.0;
 //    Ep_Out[2] = 0.0;
 //    Ep_Out[3] = 0.0;
 //  }
 
 //  if (HelLeptons == HelPartons) {
 
 //    temp = 2.0 * cdot(pout, Em_Ep);
 //    cmult(temp / ta, In_Out, Term_1);
 
 //    temp = cdot(Ep_Out, Em_Ep);
 //    cmult(temp / ta, In_Ep, Term_2);
 
 //    temp = 2.0 * cdot(pin, Em_Ep);
 //    cmult(temp / tb, In_Out, Term_3);
 
 //    temp = - cdot(In_Em, Em_Ep);
 //    cmult(temp / tb, Em_Out, Term_4);
 
 //    cadd(Term_1, Term_2, Term_3, Term_4, J_temp);
 
 //    cur[0] = J_temp[0];
 //    cur[1] = J_temp[1];
 //    cur[2] = J_temp[2];
 //    cur[3] = J_temp[3];
 //  }
 
 //  else {
 //    if (HelPartons == true) {
 
 //      temp = 2.0 * cdot(pout, Em_Ep);
 //      cmult(temp / ta, In_Out, Term_1);
 
 //      joo(pem, true, pout, true, TempCur1);
 //      jio(pin, true, pem,  true, TempCur2);
 
 //      temp = cdot(TempCur1, Em_Ep);
 //      cmult(temp / ta , TempCur2, Term_2);
 
 //      temp = 2.0 * cdot(pin, Em_Ep);
 //      cmult(temp / tb, In_Out, Term_3);
 
 //      joo(pep, true, pout, true, TempCur1);
 //      jio(pin, true, pep,  true, TempCur2);
 
 //      temp = - cdot(TempCur2, Em_Ep);
 //      cmult(temp / tb, TempCur1, Term_4);
 
 //      cadd(Term_1, Term_2, Term_3, Term_4, J_temp);
 
 //      cur[0] = J_temp[0];
 //      cur[1] = J_temp[1];
 //      cur[2] = J_temp[2];
 //      cur[3] = J_temp[3];
 //    }
 
 //    else {
 
 //      temp = 2.0 * cdot(pout, Em_Ep);
 //      cmult(temp / ta, In_Out, Term_1);
 
 //      joo(pem, false, pout, false, TempCur1);
 //      jio(pin, false, pem,  false, TempCur2);
 
 //      temp = cdot(TempCur1, Em_Ep);
 //      cmult(temp / ta , TempCur2, Term_2);
 
 //      temp = 2.0 * cdot(pin, Em_Ep);
 //      cmult(temp / tb, In_Out, Term_3);
 
 //      joo(pep, false, pout, false, TempCur1);
 //      jio(pin, false, pep,  false, TempCur2);
 
 //      temp = - cdot(TempCur2, Em_Ep);
 //      cmult(temp / tb, TempCur1, Term_4);
 
 //      cadd(Term_1, Term_2, Term_3, Term_4, J_temp);
 
 //      cur[0] = J_temp[0];
 //      cur[1] = J_temp[1];
 //      cur[2] = J_temp[2];
 //      cur[3] = J_temp[3];
 //    }
 //  }
 // }
 
 // // Progagators
 // COM PZ(double s) {
 
 //  double MZ, GammaZ;
 
 //  MZ       = 9.118800e+01;  // Mass of the mediating gauge boson
 //  GammaZ   = 2.441404e+00;  // Z peak width
 
 //  // Return Z Prop value
 //  return 1.0 / (s - MZ * MZ + COM(0.0, 1.0) * GammaZ * MZ);
 // }
 
 // COM PG(double s) {
 //  return 1.0 / s;
 // }
 
 // // Non-gluonic with pa emitting
 // std::vector <double> jMZqQ (HLV pa, HLV pb, HLV p1, HLV p2, HLV pep, HLV pem, std::vector <double> VProducts, std::vector < std::vector <double> > Virtuals, int aptype, int bptype, bool UseVirtuals, bool BottomLineEmit) {
 
 //  std::vector <double> ScaledWeights;
 
 //  double Sum;
 
 //  // Propagator factors
 //  COM PZs = PZ((pep + pem).m2());
 //  COM PGs = PG((pep + pem).m2());
 
 
 //  // Emitting current initialisation
 //  current j1pptop, j1pmtop; // Emission from top line
 //  current j1ppbot, j1pmbot; // Emission from bottom line
 
 //  // Non-emitting current initialisation
 //  current j2ptop, j2mtop;   // Emission from top line
 //  current j2pbot, j2mbot;   // Emission from bottom line
 
 //  // Currents for top emission
 //  // Upper current calculations
 //  // if a is a quark
 //  if (aptype > 0) {
 //    jZ(pa, p1, pem, pep, true,  true,  j1pptop);
 //    jZ(pa, p1, pem, pep, true,  false, j1pmtop);
 //  }
 //  // if a is an antiquark
 //  else {
 //    jZbar(pa, p1, pem, pep, true,  true,  j1pptop);
 //    jZbar(pa, p1, pem, pep, true,  false, j1pmtop);
 //  }
 
 //  // Lower current calculations
 //  // if b is a quark
 //  if (bptype > 0) {
 //    joi(p2, true,  pb, true,  j2ptop);
 //    joi(p2, false, pb, false, j2mtop);
 //  }
 //  // if b is an antiquark
 //  else {
 //    jio(pb, true,  p2, true,  j2ptop);
 //    jio(pb, false, p2, false, j2mtop);
 //  }
 
 //  // Currents for bottom emission
 //  // Lower current calculations
 //  if (bptype > 0) {
 //    jZ(pb, p2, pem, pep, true,  true,  j1ppbot);
 //    jZ(pb, p2, pem, pep, true,  false, j1pmbot);
 //  }
 //  else {
 //    jZbar(pb, p2, pem, pep, true,  true,  j1ppbot);
 //    jZbar(pb, p2, pem, pep, true,  false, j1pmbot);
 //  }
 
 //  // Upper current calculations
 //  if (aptype > 0) {
 //    joi(p1, true,  pa, true,  j2pbot);
 //    joi(p1, false, pa, false, j2mbot);
 //  }
 //  else {
 //    jio(pa, true,  p1, true,  j2pbot);
 //    jio(pa, false, p1, false, j2mbot);
 //  }
 
 //  COM Coeff[2][8];
 
 //  if (!Interference) {
 
 //    double ZCharge_a_P = Zq(aptype, true);
 //    double ZCharge_a_M = Zq(aptype, false);
 //    double ZCharge_b_P = Zq(bptype, true);
 //    double ZCharge_b_M = Zq(bptype, false);
 
 //    if (BottomLineEmit) {
 //      // Emission from top-line quark (pa/p1 line)
 //      Coeff[0][0] = (ZCharge_a_P * Zep * PZs * RWeak + Gq(aptype) * PGs) *      cdot(j1pptop, j2ptop);
 //      Coeff[0][1] = (ZCharge_a_P * Zep * PZs * RWeak + Gq(aptype) * PGs) *      cdot(j1pptop, j2mtop);
 //      Coeff[0][2] = (ZCharge_a_P * Zem * PZs * RWeak + Gq(aptype) * PGs) *      cdot(j1pmtop, j2ptop);
 //      Coeff[0][3] = (ZCharge_a_P * Zem * PZs * RWeak + Gq(aptype) * PGs) *      cdot(j1pmtop, j2mtop);
 //      Coeff[0][4] = (ZCharge_a_M * Zem * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pptop, j2ptop));
 //      Coeff[0][5] = (ZCharge_a_M * Zem * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pptop, j2mtop));
 //      Coeff[0][6] = (ZCharge_a_M * Zep * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pmtop, j2ptop));
 //      Coeff[0][7] = (ZCharge_a_M * Zep * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pmtop, j2mtop));
 //    }
 
 //    else {
 //      // Emission from bottom-line quark (pb/p2 line)
 //      Coeff[1][0] = (ZCharge_b_P * Zep * PZs * RWeak + Gq(bptype) * PGs) *      cdot(j1ppbot, j2pbot);
 //      Coeff[1][7] = (ZCharge_b_P * Zep * PZs * RWeak + Gq(bptype) * PGs) *      cdot(j1ppbot, j2mbot);
 //      Coeff[1][2] = (ZCharge_b_P * Zem * PZs * RWeak + Gq(bptype) * PGs) *      cdot(j1pmbot, j2pbot);
 //      Coeff[1][5] = (ZCharge_b_P * Zem * PZs * RWeak + Gq(bptype) * PGs) *      cdot(j1pmbot, j2mbot);
 //      Coeff[1][4] = (ZCharge_b_M * Zem * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1ppbot, j2pbot));
 //      Coeff[1][3] = (ZCharge_b_M * Zem * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1ppbot, j2mbot));
 //      Coeff[1][6] = (ZCharge_b_M * Zep * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1pmbot, j2pbot));
 //      Coeff[1][1] = (ZCharge_b_M * Zep * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1pmbot, j2mbot));
 //    }
 //  }
 
 //  // Else calculate all the possiblities
 //  else {
 
 //    double ZCharge_a_P = Zq(aptype, true);
 //    double ZCharge_a_M = Zq(aptype, false);
 //    double ZCharge_b_P = Zq(bptype, true);
 //    double ZCharge_b_M = Zq(bptype, false);
 
 //    // Emission from top-line quark (pa/p1 line)
 //    Coeff[0][0] = (ZCharge_a_P * Zep * PZs * RWeak + Gq(aptype) * PGs) *      cdot(j1pptop, j2ptop);
 //    Coeff[0][1] = (ZCharge_a_P * Zep * PZs * RWeak + Gq(aptype) * PGs) *      cdot(j1pptop, j2mtop);
 //    Coeff[0][2] = (ZCharge_a_P * Zem * PZs * RWeak + Gq(aptype) * PGs) *      cdot(j1pmtop, j2ptop);
 //    Coeff[0][3] = (ZCharge_a_P * Zem * PZs * RWeak + Gq(aptype) * PGs) *      cdot(j1pmtop, j2mtop);
 //    Coeff[0][4] = (ZCharge_a_M * Zem * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pptop, j2ptop));
 //    Coeff[0][5] = (ZCharge_a_M * Zem * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pptop, j2mtop));
 //    Coeff[0][6] = (ZCharge_a_M * Zep * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pmtop, j2ptop));
 //    Coeff[0][7] = (ZCharge_a_M * Zep * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pmtop, j2mtop));
 
 //    // Emission from bottom-line quark (pb/p2 line)
 //    Coeff[1][0] = (ZCharge_b_P * Zep * PZs * RWeak + Gq(bptype) * PGs) *      cdot(j1ppbot, j2pbot);
 //    Coeff[1][7] = (ZCharge_b_P * Zep * PZs * RWeak + Gq(bptype) * PGs) *      cdot(j1ppbot, j2mbot);
 //    Coeff[1][2] = (ZCharge_b_P * Zem * PZs * RWeak + Gq(bptype) * PGs) *      cdot(j1pmbot, j2pbot);
 //    Coeff[1][5] = (ZCharge_b_P * Zem * PZs * RWeak + Gq(bptype) * PGs) *      cdot(j1pmbot, j2mbot);
 //    Coeff[1][4] = (ZCharge_b_M * Zem * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1ppbot, j2pbot));
 //    Coeff[1][3] = (ZCharge_b_M * Zem * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1ppbot, j2mbot));
 //    Coeff[1][6] = (ZCharge_b_M * Zep * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1pmbot, j2pbot));
 //    Coeff[1][1] = (ZCharge_b_M * Zep * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1pmbot, j2mbot));
 //  }
 
 //  // Find the numbers of scales
 //  int ScaleCount;
 //  #if calcscaleunc
 //    ScaleCount = 20;
 //  #else
 //    ScaleCount = 1;
 //  #endif
 
 //  // For each scale...
 //  for (int j = 0; j < ScaleCount; j++) {
 
 //    Sum = 0.0;
 
 //    // If we want to compare back to the W's code only emit from one quark and only couple to left handed particles
 //    // virtuals arent here since they are calculated and included in weight() call.
 //    if (!Interference) {
 
 //      if (BottomLineEmit) for (int i = 0; i < 8; i++) Sum += abs2(Coeff[1][i]) * VProducts.at(1);
 //      else                for (int i = 0; i < 8; i++) Sum += abs2(Coeff[0][i]) * VProducts.at(0);
 //    }
 
 //    // Else work out the full interference
 //    else {
 
 //      // For the full calculation...
 //      if (UseVirtuals) {
 //        for (int i = 0; i < 8; i++) {
 //          Sum += abs2(Coeff[0][i])  * VProducts.at(0) * Virtuals.at(j).at(0)
 //               + abs2(Coeff[1][i])  * VProducts.at(1) * Virtuals.at(j).at(1)
 //                     + 2.0 * real(Coeff[0][i] * conj(Coeff[1][i])) * VProducts.at(2) * Virtuals.at(j).at(2);
 //        }
 //      }
 
 //      // For the tree level calculation...
 //      else {
 //        for (int i = 0; i < 8; i++) {
 //          Sum += abs2(Coeff[0][i])  * VProducts.at(0)
 //               + abs2(Coeff[1][i])  * VProducts.at(1)
 //        + 2.0 * real(Coeff[0][i] * conj(Coeff[1][i])) * VProducts.at(2);
 //        }
 //      }
 //    }
 
 //    // Add this to the vector to be returned with the other factors of C_A and the helicity sum/average factors.
 //    ScaledWeights.push_back(Sum / 18.0);
 //  }
 
 //  // Return all the scale values
 //  return ScaledWeights;
 // }
 
 // // Semi-gluonic with pa emitting
 // std::vector <double> jMZqg (HLV pa, HLV pb, HLV p1, HLV p2, HLV pep, HLV pem, std::vector <double> VProducts, std::vector < std::vector <double> > Virtuals, int aptype, int bptype, bool UseVirtuals, bool BottomLineEmit) {
 
 //  COM Coeff[8];
 
 //  double Sum;
 
 //  std::vector <double> ScaledWeights;
 
 //  COM PZs = PZ((pep + pem).m2());
 //  COM PGs = PG((pep + pem).m2());
 
 //  // Emitting current initialisation - Emission from top line
 //  current j1pptop, j1pmtop;
 
 //  // Non-emitting current initialisation - Emission from top line
 //  current j2ptop, j2mtop;
 
 //  // Currents for top emission
 //  // Upper current calculations
 //  if (aptype > 0) {
 //    jZ   (pa, p1, pem, pep, true,  true,  j1pptop);
 //    jZ   (pa, p1, pem, pep, true,  false, j1pmtop);
 //  }
 //  else {
 //    jZbar(pa, p1, pem, pep, true,  true,  j1pptop);
 //    jZbar(pa, p1, pem, pep, true,  false, j1pmtop);
 //  }
 
 //  // Lower current calculations
 //  joi(p2, true,  pb, true,  j2ptop);
 //  joi(p2, false, pb, false, j2mtop);
 
 //  // Calculate all the possiblities
 //  double ZCharge_a_P = Zq(aptype, true);
 //  double ZCharge_a_M = Zq(aptype, false);
 
 //  // Emission from top-line quark (pa/p1 line)
 //  Coeff[0] = (ZCharge_a_P * Zep * PZs * RWeak + Gq(aptype) * PGs) *      cdot(j1pptop, j2ptop);
 //  Coeff[1] = (ZCharge_a_P * Zep * PZs * RWeak + Gq(aptype) * PGs) *      cdot(j1pptop, j2mtop);
 //  Coeff[2] = (ZCharge_a_P * Zem * PZs * RWeak + Gq(aptype) * PGs) *      cdot(j1pmtop, j2ptop);
 //  Coeff[3] = (ZCharge_a_P * Zem * PZs * RWeak + Gq(aptype) * PGs) *      cdot(j1pmtop, j2mtop);
 //  Coeff[4] = (ZCharge_a_M * Zem * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pptop, j2ptop));
 //  Coeff[5] = (ZCharge_a_M * Zem * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pptop, j2mtop));
 //  Coeff[6] = (ZCharge_a_M * Zep * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pmtop, j2ptop));
 //  Coeff[7] = (ZCharge_a_M * Zep * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pmtop, j2mtop));
 
 //  // Calculate gluon colour accelerated factor
 //  double CAMFactor, z;
 
 //  // If b is a forward moving gluon define z (C.F. multiple jets papers)
 //  if (pb.pz() > 0) z = p2.plus()  / pb.plus();
 //  else             z = p2.minus() / pb.minus();
 
 //  CAMFactor = (1.0 - 1.0 / 9.0) / 2.0 * (z + 1.0 / z) + 1.0 / 9.0;
 
 //  // Find the numbers of scales
 //  int ScaleCount;
 //  #if calcscaleunc
 //    ScaleCount = 20;
 //  #else
 //    ScaleCount = 1;
 //  #endif
 
 //  // For each scale...
 //  for (int j = 0; j < ScaleCount; j++) {
 
 //    Sum = 0.0;
 
 //    // If we dont want the interference
 //    if (!Interference) for (int i = 0; i < 8; i++) Sum += abs2(Coeff[i]) * VProducts.at(0);
 
 //    // Else work out the full interference
 //    else {
 //      if (UseVirtuals) {
 //        for (int i = 0; i < 8; i++) Sum += abs2(Coeff[i]) * VProducts.at(0) * Virtuals.at(j).at(0);
 //      }
 //      else {
 //        for (int i = 0; i < 8; i++) Sum += abs2(Coeff[i]) * VProducts.at(0);
 //      }
 //    }
 
 //    // Add this to the vector to be returned with the other factors of C_A, the colour accelerated factor and the helicity sum/average factors.: (4/3)*3/32
 //    ScaledWeights.push_back(CAMFactor * Sum / 8.0);
 //  }
 
 //  return ScaledWeights;
 // }
 
 // // Electroweak Charge Functions
 // double Zq (int PID, bool Helcitiy) {
 
 //  double temp;
 
 //  // Positive Spin
 //  if (Helcitiy == true) {
 //    if (PID ==   1 || PID ==  3 || PID ==  5) temp = (+ 1.0 * stw2 / 3.0) / ctw;
 //    if (PID ==   2 || PID ==  4)              temp = (- 2.0 * stw2 / 3.0) / ctw;
 //    if (PID ==  -1 || PID == -3 || PID == -5) temp = (- 1.0 * stw2 / 3.0) / ctw;
 //    if (PID ==  -2 || PID == -4)              temp = (+ 2.0 * stw2 / 3.0) / ctw;
 
 //    // If electron or positron
 //    if (PID ==  7 || PID == -7) temp = Zep;
 //  }
 
 //  // Negative Spin
 //  else {
 //    if (PID ==  1 || PID ==  3 || PID ==  5) temp = (-0.5 + 1.0 * stw2 / 3.0) / ctw;
 //    if (PID ==  2 || PID ==  4)              temp = ( 0.5 - 2.0 * stw2 / 3.0) / ctw;
 //    if (PID == -1 || PID == -3 || PID == -5) temp = ( 0.5 - 1.0 * stw2 / 3.0) / ctw;
 //    if (PID == -2 || PID == -4)              temp = (-0.5 + 2.0 * stw2 / 3.0) / ctw;
 
 //    // If electron or positron
 //    if (PID ==  7 || PID == -7) temp = Zem;
 
 //  }
 
 //  return temp;
 // }
 
 // double Gq (int PID) {
 
 //  if (!VirtualPhoton) return 0.0;
 
 //  if (PID == -1) return  1.0 * ee / 3.0;
 //  if (PID == -2) return -2.0 * ee / 3.0;
 //  if (PID == -3) return  1.0 * ee / 3.0;
 //  if (PID == -4) return -2.0 * ee / 3.0;
 //  if (PID == -5) return  1.0 * ee / 3.0;
 //  if (PID ==  1) return -1.0 * ee / 3.0;
 //  if (PID ==  2) return  2.0 * ee / 3.0;
 //  if (PID ==  3) return -1.0 * ee / 3.0;
 //  if (PID ==  4) return  2.0 * ee / 3.0;
 //  if (PID ==  5) return -1.0 * ee / 3.0;
 
 //  std::cout << "ERROR! No Electroweak Charge Found at line " << __LINE__ << "..." << std::endl;
 //  return 0.0;
 // }
 
 
 namespace {
 
   //@{
   /// @brief Higgs vertex contracted with one current
 
   CCurrent jH (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin,
               bool helin, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2,
               double mt, bool incBot, double mb)
   {
 
       CCurrent j2 = j(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*v);
       else
       {
         if(incBot)
           return (-16.*M_PI*mb*mb/v*j2.dot(q1)*jq2*A1(-q1,q2,mb)-16.*M_PI*mb*mb/v*j2*A2(-q1,q2,mb))
                + (-16.*M_PI*mt*mt/v*j2.dot(q1)*jq2*A1(-q1,q2,mt)-16.*M_PI*mt*mt/v*j2*A2(-q1,q2,mt));
         else
           return (-16.*M_PI*mt*mt/v*j2.dot(q1)*jq2*A1(-q1,q2,mt)-16.*M_PI*mt*mt/v*j2*A2(-q1,q2,mt));
       }
   }
 
   CCurrent jioH (CLHEP::HepLorentzVector pin, bool helin, CLHEP::HepLorentzVector pout,
                 bool helout, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2,
                 double mt, bool incBot, double mb)
   {
 
       CCurrent j2 = jio(pin,helin,pout,helout);
       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*v);
       else
       {
         if(incBot)
           return (-16.*M_PI*mb*mb/v*j2.dot(q1)*jq2*A1(-q1,q2,mb)-16.*M_PI*mb*mb/v*j2*A2(-q1,q2,mb))
                + (-16.*M_PI*mt*mt/v*j2.dot(q1)*jq2*A1(-q1,q2,mt)-16.*M_PI*mt*mt/v*j2*A2(-q1,q2,mt));
         else
           return (-16.*M_PI*mt*mt/v*j2.dot(q1)*jq2*A1(-q1,q2,mt)-16.*M_PI*mt*mt/v*j2*A2(-q1,q2,mt));
       }
   }
 
   CCurrent jHtop (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin,
                   bool helin, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2,
                   double mt, bool incBot, double mb)
   {
 
       CCurrent j1 = j(pout,helout,pin,helin);
       CCurrent jq1(q1.e(),q1.px(),q1.py(),q1.pz());
 
       if(mt == infinity)
         return ((q1.dot(q2))*j1 - j1.dot(q2)*jq1)/(3*M_PI*v);
       else
       {
         if(incBot)
           return (-16.*M_PI*mb*mb/v*j1.dot(q2)*jq1*A1(-q1,q2,mb)-16.*M_PI*mb*mb/v*j1*A2(-q1,q2,mb))
                + (-16.*M_PI*mt*mt/v*j1.dot(q2)*jq1*A1(-q1,q2,mt)-16.*M_PI*mt*mt/v*j1*A2(-q1,q2,mt));
         else
           return (-16.*M_PI*mt*mt/v*j1.dot(q2)*jq1*A1(-q1,q2,mt)-16.*M_PI*mt*mt/v*j1*A2(-q1,q2,mt));
       }
   }
 
 
   CCurrent jioHtop (CLHEP::HepLorentzVector pin, bool helin, CLHEP::HepLorentzVector pout,
                     bool helout, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2,
                     double mt, bool incBot, double mb)
   {
 
       CCurrent j1 = jio(pin,helin,pout,helout);
       CCurrent jq1(q1.e(),q1.px(),q1.py(),q1.pz());
 
       if(mt == infinity)
         return ((q1.dot(q2))*j1 - j1.dot(q2)*jq1)/(3*M_PI*v);
       else
       {
         if(incBot)
           return (-16.*M_PI*mb*mb/v*j1.dot(q2)*jq1*A1(-q1,q2,mb)-16.*M_PI*mb*mb/v*j1*A2(-q1,q2,mb))
                + (-16.*M_PI*mt*mt/v*j1.dot(q2)*jq1*A1(-q1,q2,mt)-16.*M_PI*mt*mt/v*j1*A2(-q1,q2,mt));
         else
           return (-16.*M_PI*mt*mt/v*j1.dot(q2)*jq1*A1(-q1,q2,mt)-16.*M_PI*mt*mt/v*j1*A2(-q1,q2,mt));
       }
   }
   //@}
 } // namespace anonymous
 
 double jM2unogqHQ (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
 {
     //  This construction is taking rapidity order: pg > p1out >> p2out
     //  std::cerr<<"This Uno Current: "<<p1out<<"  "<<p1in<<"  "<<p2out<<"  "<<p2in<<"  "<<pg<<std::endl;
 
     CLHEP::HepLorentzVector q1=p1in-p1out;  // Top End
     CLHEP::HepLorentzVector q2=-(p2in-p2out);   // Bottom End
     CLHEP::HepLorentzVector qg=p1in-p1out-pg;  // Extra bit post-gluon
 
     //  std::cerr<<"Current:  "<<q1.m2()<<"  "<<q2.m2()<<std::endl;
     CCurrent mj1m,mj1p,mj2m,mj2p,mjH2m,mjH2p;
     mj1p=j(p1out,true,p1in,true);
     mj1m=j(p1out,false,p1in,false);
     mjH2p=jH(p2out,true,p2in,true,qH1,qH2, mt, incBot, mb);
     mjH2m=jH(p2out,false,p2in,false,qH1,qH2, mt, incBot, mb);
 
     // Dot products of these which occur again and again
     COM MHmp=mj1m.dot(mjH2p);  // And now for the Higgs ones
     COM MHmm=mj1m.dot(mjH2m);
     COM MHpp=mj1p.dot(mjH2p);
     COM MHpm=mj1p.dot(mjH2m);
 
     //  std::cout<< p1out.rapidity() << "  " << p2out.rapidity()<< "  " << qH1 << "  " << qH2 << "\n" <<MHmm << "  " << MHmp << "  "  << MHpm << "  " << MHpp << std::endl;
 
     // Currents with pg
     CCurrent jgam,jgap,j2gm,j2gp;
     j2gp=joo(p1out,true,pg,true);
     j2gm=joo(p1out,false,pg,false);
     jgap=j(pg,true,p1in,true);
     jgam=j(pg,false,p1in,false);
 
     CCurrent qsum(q1+qg);
 
     CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
     CCurrent p1o(p1out);
     CCurrent p1i(p1in);
 
     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();
     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();
     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();
     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();
 
     U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
     U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
     U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
     U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
     U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
     U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
     U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
     U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
 
     const double cf=RHEJ::C_F;
     double amm,amp,apm,app;
 
     amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     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());
 
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
 
     // Now add the t-channels for the Higgs
     double th=qH1.m2()*qg.m2();
     ampsq/=th;
     ampsq/=16.;
     ampsq*=RHEJ::C_F*RHEJ::C_F/RHEJ::C_A/RHEJ::C_A;  // Factor of (Cf/Ca) for each quark to match MH2qQ.
     //Higgs coupling is included in Hjets.C
 
     return ampsq;
 }
 
 double jM2unogqbarHQ (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
 {
     //  This construction is taking rapidity order: pg > p1out >> p2out
     //  std::cerr<<"This Uno Current: "<<p1out<<"  "<<p1in<<"  "<<p2out<<"  "<<p2in<<"  "<<pg<<std::endl;
 
     CLHEP::HepLorentzVector q1=p1in-p1out;  // Top End
     CLHEP::HepLorentzVector q2=-(p2in-p2out);   // Bottom End
     CLHEP::HepLorentzVector qg=p1in-p1out-pg;  // Extra bit post-gluon
 
     //  std::cerr<<"Current:  "<<q1.m2()<<"  "<<q2.m2()<<std::endl;
     CCurrent mj1m,mj1p,mj2m,mj2p,mjH2m,mjH2p;
     mj1p=jio(p1in,true,p1out,true);
     mj1m=jio(p1in,false,p1out,false);
     mjH2p=jH(p2out,true,p2in,true,qH1,qH2, mt, incBot, mb);
     mjH2m=jH(p2out,false,p2in,false,qH1,qH2, mt, incBot, mb);
 
     // Dot products of these which occur again and again
     COM MHmp=mj1m.dot(mjH2p);  // And now for the Higgs ones
     COM MHmm=mj1m.dot(mjH2m);
     COM MHpp=mj1p.dot(mjH2p);
     COM MHpm=mj1p.dot(mjH2m);
 
     // Currents with pg
     CCurrent jgam,jgap,j2gm,j2gp;
     j2gp=joo(pg,true,p1out,true);
     j2gm=joo(pg,false,p1out,false);
     jgap=jio(p1in,true,pg,true);
     jgam=jio(p1in,false,pg,false);
 
     CCurrent qsum(q1+qg);
 
     CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
     CCurrent p1o(p1out);
     CCurrent p1i(p1in);
 
     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();
     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();
     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();
     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();
 
     U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
     U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
     U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
     U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
     U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
     U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
     U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
     U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
 
     const double cf=RHEJ::C_F;
     double amm,amp,apm,app;
 
     amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     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());
 
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
 
     // Now add the t-channels for the Higgs
     double th=qH1.m2()*qg.m2();
     ampsq/=th;
     ampsq/=16.;
     ampsq*=4.*4./(9.*9.);  // Factor of (Cf/Ca) for each quark to match MH2qQ.
     //Higgs coupling is included in Hjets.C
 
     return ampsq;
 }
 
 double jM2unogqHQbar (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
 {
     //  This construction is taking rapidity order: pg > p1out >> p2out
     //  std::cerr<<"This Uno Current: "<<p1out<<"  "<<p1in<<"  "<<p2out<<"  "<<p2in<<"  "<<pg<<std::endl;
 
     CLHEP::HepLorentzVector q1=p1in-p1out;  // Top End
     CLHEP::HepLorentzVector q2=-(p2in-p2out);   // Bottom End
     CLHEP::HepLorentzVector qg=p1in-p1out-pg;  // Extra bit post-gluon
 
     //  std::cerr<<"Current:  "<<q1.m2()<<"  "<<q2.m2()<<std::endl;
     CCurrent mj1m,mj1p,mj2m,mj2p,mjH2m,mjH2p;
     mj1p=j(p1out,true,p1in,true);
     mj1m=j(p1out,false,p1in,false);
     mjH2p=jioH(p2in,true,p2out,true,qH1,qH2, mt, incBot, mb);
     mjH2m=jioH(p2in,false,p2out,false,qH1,qH2, mt, incBot, mb);
 
     // Dot products of these which occur again and again
     COM MHmp=mj1m.dot(mjH2p);  // And now for the Higgs ones
     COM MHmm=mj1m.dot(mjH2m);
     COM MHpp=mj1p.dot(mjH2p);
     COM MHpm=mj1p.dot(mjH2m);
 
     // Currents with pg
     CCurrent jgam,jgap,j2gm,j2gp;
     j2gp=joo(p1out,true,pg,true);
     j2gm=joo(p1out,false,pg,false);
     jgap=j(pg,true,p1in,true);
     jgam=j(pg,false,p1in,false);
 
     CCurrent qsum(q1+qg);
 
     CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
     CCurrent p1o(p1out);
     CCurrent p1i(p1in);
 
     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();
     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();
     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();
     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();
 
     U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
     U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
     U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
     U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
     U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
     U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
     U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
     U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
 
     const double cf=RHEJ::C_F;
     double amm,amp,apm,app;
 
     amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     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());
 
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
 
     // Now add the t-channels for the Higgs
     double th=qH1.m2()*qg.m2();
     ampsq/=th;
     ampsq/=16.;
     ampsq*=4.*4./(9.*9.);  // Factor of (Cf/Ca) for each quark to match MH2qQ.
     //Higgs coupling is included in Hjets.C
 
     return ampsq;
 }
 
 double jM2unogqbarHQbar (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
 {
     //  This construction is taking rapidity order: pg > p1out >> p2out
     //  std::cerr<<"This Uno Current: "<<p1out<<"  "<<p1in<<"  "<<p2out<<"  "<<p2in<<"  "<<pg<<std::endl;
 
     CLHEP::HepLorentzVector q1=p1in-p1out;  // Top End
     CLHEP::HepLorentzVector q2=-(p2in-p2out);   // Bottom End
     CLHEP::HepLorentzVector qg=p1in-p1out-pg;  // Extra bit post-gluon
 
     //  std::cerr<<"Current:  "<<q1.m2()<<"  "<<q2.m2()<<std::endl;
     CCurrent mj1m,mj1p,mj2m,mj2p,mjH2m,mjH2p;
     mj1p=jio(p1in,true,p1out,true);
     mj1m=jio(p1in,false,p1out,false);
     mjH2p=jioH(p2in,true,p2out,true,qH1,qH2, mt, incBot, mb);
     mjH2m=jioH(p2in,false,p2out,false,qH1,qH2, mt, incBot, mb);
 
     // Dot products of these which occur again and again
     COM MHmp=mj1m.dot(mjH2p);  // And now for the Higgs ones
     COM MHmm=mj1m.dot(mjH2m);
     COM MHpp=mj1p.dot(mjH2p);
     COM MHpm=mj1p.dot(mjH2m);
 
     // Currents with pg
     CCurrent jgam,jgap,j2gm,j2gp;
     j2gp=joo(pg,true,p1out,true);
     j2gm=joo(pg,false,p1out,false);
     jgap=jio(p1in,true,pg,true);
     jgam=jio(p1in,false,pg,false);
 
     CCurrent qsum(q1+qg);
 
     CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
     CCurrent p1o(p1out);
     CCurrent p1i(p1in);
 
     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();
     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();
     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();
     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();
 
     U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
     U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
     U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
     U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
     U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
     U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
     U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
     U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
 
     const double cf=RHEJ::C_F;
     double amm,amp,apm,app;
 
     amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     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());
 
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
 
     // Now add the t-channels for the Higgs
     double th=qH1.m2()*qg.m2();
     ampsq/=th;
     ampsq/=16.;
     //Higgs coupling is included in Hjets.C
     ampsq*=4.*4./(9.*9.);  // Factor of (Cf/Ca) for each quark to match MH2qQ.
 
     return ampsq;
 }
 
 double jM2unogqHg (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
 {
     //  This construction is taking rapidity order: pg > p1out >> p2out
     //  std::cerr<<"This Uno Current: "<<p1out<<"  "<<p1in<<"  "<<p2out<<"  "<<p2in<<"  "<<pg<<std::endl;
 
     CLHEP::HepLorentzVector q1=p1in-p1out;  // Top End
     CLHEP::HepLorentzVector q2=-(p2in-p2out);   // Bottom End
     CLHEP::HepLorentzVector qg=p1in-p1out-pg;  // Extra bit post-gluon
 
     CCurrent mj1m,mj1p,mj2m,mj2p,mjH2m,mjH2p;
     mj1p=j(p1out,true,p1in,true);
     mj1m=j(p1out,false,p1in,false);
     mjH2p=jH(p2out,true,p2in,true,qH1,qH2, mt, incBot, mb);
     mjH2m=jH(p2out,false,p2in,false,qH1,qH2, mt, incBot, mb);
 
     // Dot products of these which occur again and again
     COM MHmp=mj1m.dot(mjH2p);  // And now for the Higgs ones
     COM MHmm=mj1m.dot(mjH2m);
     COM MHpp=mj1p.dot(mjH2p);
     COM MHpm=mj1p.dot(mjH2m);
 
     // Currents with pg
     CCurrent jgam,jgap,j2gm,j2gp;
     j2gp=joo(p1out,true,pg,true);
     j2gm=joo(p1out,false,pg,false);
     jgap=j(pg,true,p1in,true);
     jgam=j(pg,false,p1in,false);
 
     CCurrent qsum(q1+qg);
 
     CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
     CCurrent p1o(p1out);
     CCurrent p1i(p1in);
 
     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();
     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();
     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();
     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();
 
     U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
     U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
     U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
     U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
     U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
     U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
     U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
     U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
 
     const double cf=RHEJ::C_F;
     double amm,amp,apm,app;
 
     amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     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());
 
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
 
     // Now add the t-channels for the Higgs
     double th=qH1.m2()*qg.m2();
     ampsq/=th;
     ampsq/=16.;
     ampsq*=4./9.*4./9.;  // Factor of (Cf/Ca) for each quark to match MH2qQ.
     // here we need 2 to match with the normalization
     // gq is 9./4. times the qQ
     //Higgs coupling is included in Hjets.C
 
     const double K = K_g(p2out, p2in);
 
     return ampsq*K/C_A*9./4.; //ca/cf = 9/4
 }
 
 double jM2unogqbarHg (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
 {
     //  This construction is taking rapidity order: pg > p1out >> p2out
     //  std::cerr<<"This Uno Current: "<<p1out<<"  "<<p1in<<"  "<<p2out<<"  "<<p2in<<"  "<<pg<<std::endl;
 
     CLHEP::HepLorentzVector q1=p1in-p1out;  // Top End
     CLHEP::HepLorentzVector q2=-(p2in-p2out);   // Bottom End
     CLHEP::HepLorentzVector qg=p1in-p1out-pg;  // Extra bit post-gluon
 
     CCurrent mj1m,mj1p,mj2m,mj2p,mjH2m,mjH2p;
     mj1p=jio(p1in,true,p1out,true);
     mj1m=jio(p1in,false,p1out,false);
     mjH2p=jH(p2out,true,p2in,true,qH1,qH2, mt, incBot, mb);
     mjH2m=jH(p2out,false,p2in,false,qH1,qH2, mt, incBot, mb);
 
     // Dot products of these which occur again and again
     COM MHmp=mj1m.dot(mjH2p);  // And now for the Higgs ones
     COM MHmm=mj1m.dot(mjH2m);
     COM MHpp=mj1p.dot(mjH2p);
     COM MHpm=mj1p.dot(mjH2m);
 
     // Currents with pg
     CCurrent jgam,jgap,j2gm,j2gp;
     j2gp=joo(pg,true,p1out,true);
     j2gm=joo(pg,false,p1out,false);
     jgap=jio(p1in,true,pg,true);
     jgam=jio(p1in,false,pg,false);
 
     CCurrent qsum(q1+qg);
 
     CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
     CCurrent p1o(p1out);
     CCurrent p1i(p1in);
 
     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();
     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();
     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();
     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();
 
     U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
     U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
     U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
     U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
     U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
     U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
     U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
     U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
 
     const double cf=RHEJ::C_F;
     double amm,amp,apm,app;
 
     amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     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());
 
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
 
     // Now add the t-channels for the Higgs
     double th=qH1.m2()*qg.m2();
     ampsq/=th;
     ampsq/=16.;
     ampsq*=4./9.*4./9.;  // Factor of (Cf/Ca) for each quark to match MH2qQ.
     // here we need 2 to match with the normalization
     // gq is 9./4. times the qQ
     //Higgs coupling is included in Hjets.C
 
     const double K = K_g(p2out, p2in);
 
     return ampsq*K/C_F;
 }
 
 double jM2unobqHQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
 {
     // std::cout << "####################\n";
     // std::cout << "# p1in : "<<p1in<< " "<<p1in.plus()<<" "<<p1in.minus()<<std::endl;
     // std::cout << "# p2in : "<<p2in<< " "<<p2in.plus()<<" "<<p2in.minus()<<std::endl;
     // std::cout << "# p1out : "<<p1out<< " "<<p1out.rapidity()<<std::endl;
     // std::cout << "# (qH1-qH2) : "<<(qH1-qH2)<< " "<<(qH1-qH2).rapidity()<<std::endl;
     // std::cout << "# pg : "<<pg<< " "<<pg.rapidity()<<std::endl;
     // std::cout << "# p2out : "<<p2out<< " "<<p2out.rapidity()<<std::endl;
     // std::cout << "####################\n";
 
     CLHEP::HepLorentzVector q1=p1in-p1out;  // Top End
     CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);  // Extra bit pre-gluon
     CLHEP::HepLorentzVector q3=-(p2in-p2out);   // Bottom End
 
     //  std::cerr<<"Current:  "<<q1.m2()<<"  "<<q2.m2()<<std::endl;
     CCurrent mjH1m,mjH1p,mj2m,mj2p;
     mjH1p=jHtop(p1out,true,p1in,true,qH1,qH2, mt, incBot, mb);
     mjH1m=jHtop(p1out,false,p1in,false,qH1,qH2, mt, incBot, mb);
     mj2p=j(p2out,true,p2in,true);
     mj2m=j(p2out,false,p2in,false);
 
     // Dot products of these which occur again and again
     COM MHmp=mjH1m.dot(mj2p);  // And now for the Higgs ones
     COM MHmm=mjH1m.dot(mj2m);
     COM MHpp=mjH1p.dot(mj2p);
     COM MHpm=mjH1p.dot(mj2m);
 
     // Currents with pg
     CCurrent jgbm,jgbp,j2gm,j2gp;
     j2gp=joo(p2out,true,pg,true);
     j2gm=joo(p2out,false,pg,false);
     jgbp=j(pg,true,p2in,true);
     jgbm=j(pg,false,p2in,false);
 
     CCurrent qsum(q2+q3);
 
     CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
     CCurrent p2o(p2out);
     CCurrent p2i(p2in);
 
     CCurrent pplus((p1in+p1out)/2.);
     CCurrent pminus((p2in+p2out)/2.);
 
     // COM test=pminus.dot(p1in);
 
     Lmm=((-1.)*qsum*(MHmm) + (-2.*mjH1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1m
         + (p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmm/2.))/q3.m2();
     Lmp=((-1.)*qsum*(MHmp) + (-2.*mjH1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1m
         +(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmp/2.))/q3.m2();
     Lpm=((-1.)*qsum*(MHpm) + (-2.*mjH1p.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1p
         +(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpm/2.))/q3.m2();
     Lpp=((-1.)*qsum*(MHpp) + (-2.*mjH1p.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1p
         +(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpp/2.))/q3.m2();
     U1mm=(jgbm.dot(mjH1m)*j2gm+2.*p2o*MHmm)/(p2out+pg).m2();
     U1mp=(jgbp.dot(mjH1m)*j2gp+2.*p2o*MHmp)/(p2out+pg).m2();
     U1pm=(jgbm.dot(mjH1p)*j2gm+2.*p2o*MHpm)/(p2out+pg).m2();
     U1pp=(jgbp.dot(mjH1p)*j2gp+2.*p2o*MHpp)/(p2out+pg).m2();
     U2mm=((-1.)*j2gm.dot(mjH1m)*jgbm+2.*p2i*MHmm)/(p2in-pg).m2();
     U2mp=((-1.)*j2gp.dot(mjH1m)*jgbp+2.*p2i*MHmp)/(p2in-pg).m2();
     U2pm=((-1.)*j2gm.dot(mjH1p)*jgbm+2.*p2i*MHpm)/(p2in-pg).m2();
     U2pp=((-1.)*j2gp.dot(mjH1p)*jgbp+2.*p2i*MHpp)/(p2in-pg).m2();
 
     const double cf=RHEJ::C_F;
     double amm,amp,apm,app;
 
     amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
     // 1/3. = 1/C_A ?
     double ampsq=-(amm+amp+apm+app)/(q1.m2()*qH1.m2());
 
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
 
     // Now add the t-channels for the Higgs
     const double th=qH2.m2()*q2.m2();
     ampsq/=th;
     ampsq/=16.;
     ampsq*=RHEJ::C_F*RHEJ::C_F/(RHEJ::C_A*RHEJ::C_A);  // Factor of (Cf/Ca) for each quark to match MH2qQ.
 
     return ampsq;
 }
 
 
 
 double jM2unobqbarHQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
 {
 
     CLHEP::HepLorentzVector q1=p1in-p1out;  // Top End
     CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);  // Extra bit pre-gluon
     CLHEP::HepLorentzVector q3=-(p2in-p2out);   // Bottom End
 
     //  std::cerr<<"Current:  "<<q1.m2()<<"  "<<q2.m2()<<std::endl;
     CCurrent mjH1m,mjH1p,mj2m,mj2p;
     mjH1p=jioHtop(p1in,true,p1out,true,qH1,qH2, mt, incBot, mb);
     mjH1m=jioHtop(p1in,false,p1out,false,qH1,qH2, mt, incBot, mb);
     mj2p=j(p2out,true,p2in,true);
     mj2m=j(p2out,false,p2in,false);
 
     // Dot products of these which occur again and again
     COM MHmp=mjH1m.dot(mj2p);  // And now for the Higgs ones
     COM MHmm=mjH1m.dot(mj2m);
     COM MHpp=mjH1p.dot(mj2p);
     COM MHpm=mjH1p.dot(mj2m);
 
 
     // Currents with pg
     CCurrent jgbm,jgbp,j2gm,j2gp;
     j2gp=joo(p2out,true,pg,true);
     j2gm=joo(p2out,false,pg,false);
     jgbp=j(pg,true,p2in,true);
     jgbm=j(pg,false,p2in,false);
 
     CCurrent qsum(q2+q3);
 
     CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
     CCurrent p2o(p2out);
     CCurrent p2i(p2in);
 
     CCurrent pplus((p1in+p1out)/2.);
     CCurrent pminus((p2in+p2out)/2.);
 
     // COM test=pminus.dot(p1in);
 
 
     Lmm=((-1.)*qsum*(MHmm) + (-2.*mjH1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmm/2.))/q3.m2();
     Lmp=((-1.)*qsum*(MHmp) + (-2.*mjH1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmp/2.))/q3.m2();
     Lpm=((-1.)*qsum*(MHpm) + (-2.*mjH1p.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpm/2.))/q3.m2();
     Lpp=((-1.)*qsum*(MHpp) + (-2.*mjH1p.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpp/2.))/q3.m2();
     U1mm=(jgbm.dot(mjH1m)*j2gm+2.*p2o*MHmm)/(p2out+pg).m2();
     U1mp=(jgbp.dot(mjH1m)*j2gp+2.*p2o*MHmp)/(p2out+pg).m2();
     U1pm=(jgbm.dot(mjH1p)*j2gm+2.*p2o*MHpm)/(p2out+pg).m2();
     U1pp=(jgbp.dot(mjH1p)*j2gp+2.*p2o*MHpp)/(p2out+pg).m2();
     U2mm=((-1.)*j2gm.dot(mjH1m)*jgbm+2.*p2i*MHmm)/(p2in-pg).m2();
     U2mp=((-1.)*j2gp.dot(mjH1m)*jgbp+2.*p2i*MHmp)/(p2in-pg).m2();
     U2pm=((-1.)*j2gm.dot(mjH1p)*jgbm+2.*p2i*MHpm)/(p2in-pg).m2();
     U2pp=((-1.)*j2gp.dot(mjH1p)*jgbp+2.*p2i*MHpp)/(p2in-pg).m2();
 
     const double cf=RHEJ::C_F;
     double amm,amp,apm,app;
 
     amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
     double ampsq=-(amm+amp+apm+app)/(q1.m2()*qH1.m2());
 
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
 
     // Now add the t-channels for the Higgs
     double th=qH2.m2()*q2.m2();
     ampsq/=th;
     ampsq/=16.;
     ampsq*=4.*4./(9.*9.);  // Factor of (Cf/Ca) for each quark to match MH2qQ.
     //Higgs coupling is included in Hjets.C
 
     return ampsq;
 }
 
 
 
 double jM2unobqHQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
 {
 
     CLHEP::HepLorentzVector q1=p1in-p1out;  // Top End
     CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);  // Extra bit pre-gluon
     CLHEP::HepLorentzVector q3=-(p2in-p2out);   // Bottom End
 
     //  std::cerr<<"Current:  "<<q1.m2()<<"  "<<q2.m2()<<std::endl;
     CCurrent mjH1m,mjH1p,mj2m,mj2p;
     mjH1p=jHtop(p1out,true,p1in,true,qH1,qH2,mt, incBot, mb);
     mjH1m=jHtop(p1out,false,p1in,false,qH1,qH2,mt, incBot, mb);
     mj2p=jio(p2in,true,p2out,true);
     mj2m=jio(p2in,false,p2out,false);
 
     // Dot products of these which occur again and again
     COM MHmp=mjH1m.dot(mj2p);  // And now for the Higgs ones
     COM MHmm=mjH1m.dot(mj2m);
     COM MHpp=mjH1p.dot(mj2p);
     COM MHpm=mjH1p.dot(mj2m);
 
 
     // Currents with pg
     CCurrent jgbm,jgbp,j2gm,j2gp;
     j2gp=joo(pg,true,p2out,true);
     j2gm=joo(pg,false,p2out,false);
     jgbp=jio(p2in,true,pg,true);
     jgbm=jio(p2in,false,pg,false);
 
     CCurrent qsum(q2+q3);
 
     CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
     CCurrent p2o(p2out);
     CCurrent p2i(p2in);
 
     CCurrent pplus((p1in+p1out)/2.);
     CCurrent pminus((p2in+p2out)/2.);
 
     // COM test=pminus.dot(p1in);
 
 
     Lmm=((-1.)*qsum*(MHmm) + (-2.*mjH1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmm/2.))/q3.m2();
     Lmp=((-1.)*qsum*(MHmp) + (-2.*mjH1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmp/2.))/q3.m2();
     Lpm=((-1.)*qsum*(MHpm) + (-2.*mjH1p.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpm/2.))/q3.m2();
     Lpp=((-1.)*qsum*(MHpp) + (-2.*mjH1p.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpp/2.))/q3.m2();
     U1mm=(jgbm.dot(mjH1m)*j2gm+2.*p2o*MHmm)/(p2out+pg).m2();
     U1mp=(jgbp.dot(mjH1m)*j2gp+2.*p2o*MHmp)/(p2out+pg).m2();
     U1pm=(jgbm.dot(mjH1p)*j2gm+2.*p2o*MHpm)/(p2out+pg).m2();
     U1pp=(jgbp.dot(mjH1p)*j2gp+2.*p2o*MHpp)/(p2out+pg).m2();
     U2mm=((-1.)*j2gm.dot(mjH1m)*jgbm+2.*p2i*MHmm)/(p2in-pg).m2();
     U2mp=((-1.)*j2gp.dot(mjH1m)*jgbp+2.*p2i*MHmp)/(p2in-pg).m2();
     U2pm=((-1.)*j2gm.dot(mjH1p)*jgbm+2.*p2i*MHpm)/(p2in-pg).m2();
     U2pp=((-1.)*j2gp.dot(mjH1p)*jgbp+2.*p2i*MHpp)/(p2in-pg).m2();
 
     const double cf=RHEJ::C_F;
     double amm,amp,apm,app;
 
     amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
     double ampsq=-(amm+amp+apm+app)/(q1.m2()*qH1.m2());
 
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
 
     // Now add the t-channels for the Higgs
     double th=qH2.m2()*q2.m2();
     ampsq/=th;
     ampsq/=16.;
     ampsq*=4.*4./(9.*9.);  // Factor of (Cf/Ca) for each quark to match MH2qQ.
     //Higgs coupling is included in Hjets.C
 
     return ampsq;
 }
 
 
 
 double jM2unobqbarHQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
 {
 
     CLHEP::HepLorentzVector q1=p1in-p1out;  // Top End
     CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);  // Extra bit pre-gluon
     CLHEP::HepLorentzVector q3=-(p2in-p2out);   // Bottom End
 
     //  std::cerr<<"Current:  "<<q1.m2()<<"  "<<q2.m2()<<std::endl;
     CCurrent mjH1m,mjH1p,mj2m,mj2p;
     mjH1p=jioHtop(p1in,true,p1out,true,qH1,qH2,mt, incBot, mb);
     mjH1m=jioHtop(p1in,false,p1out,false,qH1,qH2,mt, incBot, mb);
     mj2p=jio(p2in,true,p2out,true);
     mj2m=jio(p2in,false,p2out,false);
 
     // Dot products of these which occur again and again
     COM MHmp=mjH1m.dot(mj2p);  // And now for the Higgs ones
     COM MHmm=mjH1m.dot(mj2m);
     COM MHpp=mjH1p.dot(mj2p);
     COM MHpm=mjH1p.dot(mj2m);
 
 
     // Currents with pg
     CCurrent jgbm,jgbp,j2gm,j2gp;
     j2gp=joo(pg,true,p2out,true);
     j2gm=joo(pg,false,p2out,false);
     jgbp=jio(p2in,true,pg,true);
     jgbm=jio(p2in,false,pg,false);
 
     CCurrent qsum(q2+q3);
 
     CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
     CCurrent p2o(p2out);
     CCurrent p2i(p2in);
 
     CCurrent pplus((p1in+p1out)/2.);
     CCurrent pminus((p2in+p2out)/2.);
 
     // COM test=pminus.dot(p1in);
 
 
     Lmm=((-1.)*qsum*(MHmm) + (-2.*mjH1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmm/2.))/q3.m2();
     Lmp=((-1.)*qsum*(MHmp) + (-2.*mjH1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmp/2.))/q3.m2();
     Lpm=((-1.)*qsum*(MHpm) + (-2.*mjH1p.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpm/2.))/q3.m2();
     Lpp=((-1.)*qsum*(MHpp) + (-2.*mjH1p.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpp/2.))/q3.m2();
     U1mm=(jgbm.dot(mjH1m)*j2gm+2.*p2o*MHmm)/(p2out+pg).m2();
     U1mp=(jgbp.dot(mjH1m)*j2gp+2.*p2o*MHmp)/(p2out+pg).m2();
     U1pm=(jgbm.dot(mjH1p)*j2gm+2.*p2o*MHpm)/(p2out+pg).m2();
     U1pp=(jgbp.dot(mjH1p)*j2gp+2.*p2o*MHpp)/(p2out+pg).m2();
     U2mm=((-1.)*j2gm.dot(mjH1m)*jgbm+2.*p2i*MHmm)/(p2in-pg).m2();
     U2mp=((-1.)*j2gp.dot(mjH1m)*jgbp+2.*p2i*MHmp)/(p2in-pg).m2();
     U2pm=((-1.)*j2gm.dot(mjH1p)*jgbm+2.*p2i*MHpm)/(p2in-pg).m2();
     U2pp=((-1.)*j2gp.dot(mjH1p)*jgbp+2.*p2i*MHpp)/(p2in-pg).m2();
 
     const double cf=RHEJ::C_F;
     double amm,amp,apm,app;
 
     amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
     double ampsq=-(amm+amp+apm+app)/(q1.m2()*qH1.m2());
 
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
 
     // Now add the t-channels for the Higgs
     double th=qH2.m2()*q2.m2();
     ampsq/=th;
     ampsq/=16.;
     ampsq*=4.*4./(9.*9.);  // Factor of (Cf/Ca) for each quark to match MH2qQ.
     //Higgs coupling is included in Hjets.C
 
 
 
     return ampsq;
 }
 
 double jM2unobgHQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
 {
     // std::cout << "####################\n";
     // std::cout << "# p1in : "<<p1in<< " "<<p1in.plus()<<" "<<p1in.minus()<<std::endl;
     // std::cout << "# p2in : "<<p2in<< " "<<p2in.plus()<<" "<<p2in.minus()<<std::endl;
     // std::cout << "# p1out : "<<p1out<< " "<<p1out.rapidity()<<std::endl;
     // std::cout << "# (qH1-qH2) : "<<(qH1-qH2)<< " "<<(qH1-qH2).rapidity()<<std::endl;
     // std::cout << "# pg : "<<pg<< " "<<pg.rapidity()<<std::endl;
     // std::cout << "# p2out : "<<p2out<< " "<<p2out.rapidity()<<std::endl;
     // std::cout << "####################\n";
 
     CLHEP::HepLorentzVector q1=p1in-p1out;  // Top End
     CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);  // Extra bit pre-gluon
     CLHEP::HepLorentzVector q3=-(p2in-p2out);   // Bottom End
 
     //  std::cerr<<"Current:  "<<q1.m2()<<"  "<<q2.m2()<<std::endl;
     CCurrent mjH1m,mjH1p,mj2m,mj2p;
     mjH1p=jHtop(p1out,true,p1in,true,qH1,qH2,mt, incBot, mb);
     mjH1m=jHtop(p1out,false,p1in,false,qH1,qH2,mt, incBot, mb);
     mj2p=j(p2out,true,p2in,true);
     mj2m=j(p2out,false,p2in,false);
 
     // Dot products of these which occur again and again
     COM MHmp=mjH1m.dot(mj2p);  // And now for the Higgs ones
     COM MHmm=mjH1m.dot(mj2m);
     COM MHpp=mjH1p.dot(mj2p);
     COM MHpm=mjH1p.dot(mj2m);
 
     // Currents with pg
     CCurrent jgbm,jgbp,j2gm,j2gp;
     j2gp=joo(p2out,true,pg,true);
     j2gm=joo(p2out,false,pg,false);
     jgbp=j(pg,true,p2in,true);
     jgbm=j(pg,false,p2in,false);
 
     CCurrent qsum(q2+q3);
 
     CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
     CCurrent p2o(p2out);
     CCurrent p2i(p2in);
 
     CCurrent pplus((p1in+p1out)/2.);
     CCurrent pminus((p2in+p2out)/2.);
 
     // COM test=pminus.dot(p1in);
 
     Lmm=((-1.)*qsum*(MHmm) + (-2.*mjH1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmm/2.))/q3.m2();
     Lmp=((-1.)*qsum*(MHmp) + (-2.*mjH1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmp/2.))/q3.m2();
     Lpm=((-1.)*qsum*(MHpm) + (-2.*mjH1p.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpm/2.))/q3.m2();
     Lpp=((-1.)*qsum*(MHpp) + (-2.*mjH1p.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpp/2.))/q3.m2();
     U1mm=(jgbm.dot(mjH1m)*j2gm+2.*p2o*MHmm)/(p2out+pg).m2();
     U1mp=(jgbp.dot(mjH1m)*j2gp+2.*p2o*MHmp)/(p2out+pg).m2();
     U1pm=(jgbm.dot(mjH1p)*j2gm+2.*p2o*MHpm)/(p2out+pg).m2();
     U1pp=(jgbp.dot(mjH1p)*j2gp+2.*p2o*MHpp)/(p2out+pg).m2();
     U2mm=((-1.)*j2gm.dot(mjH1m)*jgbm+2.*p2i*MHmm)/(p2in-pg).m2();
     U2mp=((-1.)*j2gp.dot(mjH1m)*jgbp+2.*p2i*MHmp)/(p2in-pg).m2();
     U2pm=((-1.)*j2gm.dot(mjH1p)*jgbm+2.*p2i*MHpm)/(p2in-pg).m2();
     U2pp=((-1.)*j2gp.dot(mjH1p)*jgbp+2.*p2i*MHpp)/(p2in-pg).m2();
 
     const double cf=RHEJ::C_F;
     double amm,amp,apm,app;
 
     amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
     double ampsq=-(amm+amp+apm+app)/(q1.m2()*qH1.m2());
 
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
 
     // Now add the t-channels for the Higgs
     double th=qH2.m2()*q2.m2();
     ampsq/=th;
     ampsq/=16.;
     ampsq*=4./9.*4./9.;  // Factor of (Cf/Ca) for each quark to match MH2qQ.
     // need twice to match the normalization
     //Higgs coupling is included in Hjets.C
 
     const double K = K_g(p1out, p1in);
 
     return ampsq*K/C_F;
 }
 
 
 
 double jM2unobgHQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
 {
 
     CLHEP::HepLorentzVector q1=p1in-p1out;  // Top End
     CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);  // Extra bit pre-gluon
     CLHEP::HepLorentzVector q3=-(p2in-p2out);   // Bottom End
 
     //  std::cerr<<"Current:  "<<q1.m2()<<"  "<<q2.m2()<<std::endl;
     CCurrent mjH1m,mjH1p,mj2m,mj2p;
     mjH1p=jHtop(p1out,true,p1in,true,qH1,qH2,mt, incBot, mb);
     mjH1m=jHtop(p1out,false,p1in,false,qH1,qH2,mt, incBot, mb);
     mj2p=jio(p2in,true,p2out,true);
     mj2m=jio(p2in,false,p2out,false);
 
     // Dot products of these which occur again and again
     COM MHmp=mjH1m.dot(mj2p);  // And now for the Higgs ones
     COM MHmm=mjH1m.dot(mj2m);
     COM MHpp=mjH1p.dot(mj2p);
     COM MHpm=mjH1p.dot(mj2m);
 
 
     // Currents with pg
     CCurrent jgbm,jgbp,j2gm,j2gp;
     j2gp=joo(pg,true,p2out,true);
     j2gm=joo(pg,false,p2out,false);
     jgbp=jio(p2in,true,pg,true);
     jgbm=jio(p2in,false,pg,false);
 
     CCurrent qsum(q2+q3);
 
     CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
     CCurrent p2o(p2out);
     CCurrent p2i(p2in);
 
     CCurrent pplus((p1in+p1out)/2.);
     CCurrent pminus((p2in+p2out)/2.);
 
     // COM test=pminus.dot(p1in);
 
 
     Lmm=((-1.)*qsum*(MHmm) + (-2.*mjH1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmm/2.))/q3.m2();
     Lmp=((-1.)*qsum*(MHmp) + (-2.*mjH1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmp/2.))/q3.m2();
     Lpm=((-1.)*qsum*(MHpm) + (-2.*mjH1p.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpm/2.))/q3.m2();
     Lpp=((-1.)*qsum*(MHpp) + (-2.*mjH1p.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpp/2.))/q3.m2();
     U1mm=(jgbm.dot(mjH1m)*j2gm+2.*p2o*MHmm)/(p2out+pg).m2();
     U1mp=(jgbp.dot(mjH1m)*j2gp+2.*p2o*MHmp)/(p2out+pg).m2();
     U1pm=(jgbm.dot(mjH1p)*j2gm+2.*p2o*MHpm)/(p2out+pg).m2();
     U1pp=(jgbp.dot(mjH1p)*j2gp+2.*p2o*MHpp)/(p2out+pg).m2();
     U2mm=((-1.)*j2gm.dot(mjH1m)*jgbm+2.*p2i*MHmm)/(p2in-pg).m2();
     U2mp=((-1.)*j2gp.dot(mjH1m)*jgbp+2.*p2i*MHmp)/(p2in-pg).m2();
     U2pm=((-1.)*j2gm.dot(mjH1p)*jgbm+2.*p2i*MHpm)/(p2in-pg).m2();
     U2pp=((-1.)*j2gp.dot(mjH1p)*jgbp+2.*p2i*MHpp)/(p2in-pg).m2();
 
     const double cf=RHEJ::C_F;
     double amm,amp,apm,app;
 
     amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
     amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
     apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
     app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
     double ampsq=-(amm+amp+apm+app)/(q1.m2()*qH1.m2());
 
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
   // if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
   //   std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << "  " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
 
     // Now add the t-channels for the Higgs
     double th=qH2.m2()*q2.m2();
     ampsq/=th;
     ampsq/=16.;
     ampsq*=4./9.*4./9.;  // Factor of (Cf/Ca) for each quark to match MH2qQ.
     //Higgs coupling is included in Hjets.C
 
     const double K = K_g(p1out, p1in);
 
     return ampsq*K/C_F; //ca/cf = 9/4
 
 }
 
 // Begin finite mass stuff
 #ifdef RHEJ_BUILD_WITH_QCDLOOP
 namespace {
 
 
   // All the stuff needed for the box functions in qg->qgH now...
 
   //COM E1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM E1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //CLHEP::HepLorentzVector q2=k3+k4;
     CLHEP::HepLorentzVector 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 = 2.*k3.dot(k4);
     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(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM F1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //CLHEP::HepLorentzVector q2=k3+k4;
     CLHEP::HepLorentzVector 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 = 2.*k3.dot(k4);
     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(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM G1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //CLHEP::HepLorentzVector q2=k3+k4;
     CLHEP::HepLorentzVector 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 = 2.*k3.dot(k4);
     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(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM E4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //CLHEP::HepLorentzVector q2=k3+k4;
     CLHEP::HepLorentzVector 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 = 2.*k3.dot(k4);
     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(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM F4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //CLHEP::HepLorentzVector q2=k3+k4;
     CLHEP::HepLorentzVector 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 = 2.*k3.dot(k4);
     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(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM G4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //CLHEP::HepLorentzVector q2=k3+k4;
     CLHEP::HepLorentzVector 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 = 2.*k3.dot(k4);
     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(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM E10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //CLHEP::HepLorentzVector q2=k3+k4;
     CLHEP::HepLorentzVector 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 = 2.*k3.dot(k4);
     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(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM F10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //CLHEP::HepLorentzVector q2=k3+k4;
     CLHEP::HepLorentzVector 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 = 2.*k3.dot(k4);
     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(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM G10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //CLHEP::HepLorentzVector q2=k3+k4;
     CLHEP::HepLorentzVector 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 = 2.*k3.dot(k4);
     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(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM H1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //return E1(k1,k2,k3,k4,mq)+F1(k1,k2,k3,k4,mq)+G1(k1,k2,k3,k4,mq);
     return E1(k1,k2,kh,mq)+F1(k1,k2,kh,mq)+G1(k1,k2,kh,mq);
   }
   //COM H4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM H4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //return E4(k1,k2,k3,k4,mq)+F4(k1,k2,k3,k4,mq)+G4(k1,k2,k3,k4,mq);
     return E4(k1,k2,kh,mq)+F4(k1,k2,kh,mq)+G4(k1,k2,kh,mq);
   }
   //COM H10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM H10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //return E10(k1,k2,k3,k4,mq)+F10(k1,k2,k3,k4,mq)+G10(k1,k2,k3,k4,mq);
     return E10(k1,k2,kh,mq)+F10(k1,k2,kh,mq)+G10(k1,k2,kh,mq);
   }
   //COM H2(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM H2(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //return -1.*H1(k2,k1,k3,k4,mq);
     return -1.*H1(k2,k1,kh,mq);
   }
   //COM H5(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM H5(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //return -1.*H4(k2,k1,k3,k4,mq);
     return -1.*H4(k2,k1,kh,mq);
   }
   //COM H12(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
   COM H12(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
   {
     //return -1.*H10(k2,k1,k3,k4,mq);
     return -1.*H10(k2,k1,kh,mq);
   }
 
   // FL and FT functions
   COM FL(CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mq)
   {
     CLHEP::HepLorentzVector 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(CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mq)
   {
     CLHEP::HepLorentzVector 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);
   }
 
   CLHEP::HepLorentzVector ParityFlip(CLHEP::HepLorentzVector p)
   {
     CLHEP::HepLorentzVector 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(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector p1,
     CLHEP::HepLorentzVector pH, double mq, current &retAns)
   {
     current cura1,pacur,p1cur,pHcur,conjeps1,conjepsH1,epsa,epsHa,epsHapart1,
       epsHapart2,conjepsH1part1,conjepsH1part2;
     COM ang1a,sqa1;
 
     const double F = 4.*mq*mq/v;
     // 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++)
     {
         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(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector pH, double mq, current &retAns)
   {
     const double F = 4.*mq*mq/v;
     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);
     j(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++)
     {
       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 MH2gq_outsideH(CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pH, double mq, bool includeBottom, double mq2)
 {
 
   current cur2bplus,cur2bminus, cur2bplusFlip, cur2bminusFlip;
   current retAns,retAnsb;
   j(p2out,true,p2in,true,cur2bplus);
   j(p2out,false,p2in,false,cur2bminus);
   j(ParityFlip(p2out),true,ParityFlip(p2in),true,cur2bplusFlip);
   j(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,retAns);
     app1=cdot(retAns,cur2bplus);
     app2=cdot(retAns,cur2bminus);
 
     g_gH_HC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq,retAns);
     app3=cdot(retAns,cur2bplusFlip);
     app4=cdot(retAns,cur2bminusFlip);
 
     // And non-conserving bits
     g_gH_HNC(p1in,p1out,pH,mq,retAns);
     apm1=cdot(retAns,cur2bplus);
     apm2=cdot(retAns,cur2bminus);
 
     g_gH_HNC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq,retAns);
     apm3=cdot(retAns,cur2bplusFlip);
     apm4=cdot(retAns,cur2bminusFlip);
   } else {
     g_gH_HC(p1in,p1out,pH,mq,retAns);
     g_gH_HC(p1in,p1out,pH,mq2,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,retAns);
     g_gH_HC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq2,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,retAns);
     g_gH_HNC(p1in,p1out,pH,mq2,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,retAns);
     g_gH_HNC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq2,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 // RHEJ_BUILD_WITH_QCDLOOP
 
 double C2gHgm(CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector pH)
 {
   static double A=1./(3.*M_PI*v);
   // 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 og 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(CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector pH)
 {
   static double A=1./(3.*M_PI*v);
   // 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 og 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(CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector pH)
 {
   static double A=1./(3.*M_PI*v);
   // 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 og 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();
 }