Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7876900
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
63 KB
Subscribers
None
View Options
diff --git a/src/Event.cc b/src/Event.cc
index 7d8650e..c396bc9 100644
--- a/src/Event.cc
+++ b/src/Event.cc
@@ -1,971 +1,963 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019
* \copyright GPLv2 or later
*/
#include "HEJ/Event.hh"
#include <algorithm>
#include <assert.h>
#include <iterator>
#include <numeric>
#include <unordered_set>
#include <utility>
#include "LHEF/LHEF.h"
#include "fastjet/JetDefinition.hh"
#include "HEJ/Constants.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/PDG_codes.hh"
namespace HEJ{
namespace {
constexpr int status_in = -1;
constexpr int status_decayed = 2;
constexpr int status_out = 1;
//! true if leptonic W decay
bool valid_W_decay( int const w_type, // sign of W
std::vector<Particle> const & decays
){
if(decays.size() != 2) // no 1->2 decay
return false;
const int pidsum = decays[0].type + decays[1].type;
if( std::abs(pidsum) != 1 || pidsum != w_type ) // correct charge
return false;
// leptonic decay (only check first, second follows from pidsum)
if( w_type == 1 ) // W+
return is_antilepton(decays[0]) || is_neutrino(decays[0]);
// W-
return is_lepton(decays[0]) || is_antineutrino(decays[0]);
}
/// @name helper functions to determine event type
//@{
/**
* \brief check if final state valid for HEJ
*
* 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(Event const & ev){
std::vector<Particle> const & outgoing = ev.outgoing();
if(ev.decays().size() > 1) // at most one decay
return false;
bool has_AWZH_boson = false;
for( size_t i=0; i<outgoing.size(); ++i ){
auto const & out{ outgoing[i] };
if(is_AWZH_boson(out.type)){
// at most one boson
if(has_AWZH_boson) return false;
has_AWZH_boson = true;
// valid decay for W
if(std::abs(out.type) == ParticleID::Wp){
// exactly 1 decay of W
if( ev.decays().size() != 1 || ev.decays().cbegin()->first != i )
return false;
if( !valid_W_decay(out.type>0?+1:-1, ev.decays().cbegin()->second) )
return false;
}
}
else if(! is_parton(out.type)) return false;
}
return true;
}
/**
* returns all EventTypes implemented in HEJ
*/
size_t implemented_types(std::vector<Particle> const & bosons){
using namespace event_type;
if(bosons.empty()) return FKL | unob | unof; // pure jets
if(bosons.size()>1) return non_resummable; // multi boson
switch (bosons[0].type) {
case ParticleID::Wp:
case ParticleID::Wm:
return FKL | unob | unof | qqxexb | qqxexf | qqxmid;
case ParticleID::h:
return FKL | unob | unof;
default:
return non_resummable;
}
}
/**
* \brief function which determines if type change is consistent with Wp emission.
* @param in incoming Particle id
* @param out outgoing Particle id
* @param qqx Current both incoming/both outgoing?
*
* \see is_Wm_Change
*/
bool is_Wp_Change(ParticleID in, ParticleID out, bool qqx){
if(!qqx && (in==-1 || in== 2 || in==-3 || in== 4)) return out== (in-1);
if( qqx && (in== 1 || in==-2 || in== 3 || in==-4)) return out==-(in+1);
return false;
}
/**
* \brief function which determines if type change is consistent with Wm emission.
* @param in incoming Particle id
* @param out outgoing Particle id
* @param qqx Current both incoming/both outgoing?
*
* Ensures that change type of quark line is possible by a flavour changing
* Wm emission. Allows checking of qqx currents also.
*/
bool is_Wm_Change(ParticleID in, ParticleID out, bool qqx){
if(!qqx && (in== 1 || in==-2 || in== 3 || in==-4)) return out== (in+1);
if( qqx && (in==-1 || in== 2 || in==-3 || in== 4)) return out==-(in-1);
return false;
}
/**
* \brief checks if particle type remains same from incoming to outgoing
* @param in incoming Particle
* @param out outgoing Particle
* @param qqx Current both incoming/outgoing?
*/
bool no_flavour_change(ParticleID in, ParticleID out, bool qqx){
const int qqxCurrent = qqx?-1:1;
if(abs(in)<=6 || in==pid::gluon) return (in==out*qqxCurrent);
else return false;
}
bool has_2_jets(Event const & event){
return event.jets().size() >= 2;
}
/**
* \brief check if we have a valid Impact factor
* @param in incoming Particle
* @param out outgoing Particle
* @param qqx Current both incoming/outgoing?
* @param qqx returns +1 if Wp, -1 if Wm, else 0
*/
bool is_valid_impact_factor(
ParticleID in, ParticleID out, bool qqx, int & W_change
){
if( no_flavour_change(in, out, qqx) ){
return true;
}
if( is_Wp_Change(in, out, qqx) ) {
W_change+=1;
return true;
}
if( is_Wm_Change(in, out, qqx) ) {
W_change-=1;
return true;
}
return false;
}
//! Returns all possible classifications from the impact factors
// the beginning points are changed s.t. after the the classification they
// point to the beginning of the (potential) FKL chain
// sets W_change: + if Wp change
// 0 if no change
// - if Wm change
// This function can be used with forward & backwards iterators
template<class OutIterator>
size_t possible_impact_factors(
ParticleID incoming_id, // incoming
OutIterator & begin_out, OutIterator const & end_out, // outgoing
int & W_change, std::vector<Particle> const & boson,
bool const backward // backward?
){
using namespace event_type;
assert(boson.size() < 2);
// keep track of all states that we don't test
size_t not_tested = qqxmid;
if(backward)
not_tested |= unof | qqxexf;
else
not_tested |= unob | qqxexb;
// Is this LL current?
if( is_valid_impact_factor(incoming_id, begin_out->type, false, W_change) ){
++begin_out;
return not_tested | FKL;
}
// or NLL current?
// -> needs two partons in two different jets
if( std::distance(begin_out, end_out)>=2
){
// Is this unordered emisson?
if( incoming_id!=pid::gluon && begin_out->type==pid::gluon ){
if( is_valid_impact_factor(
incoming_id, (begin_out+1)->type, false, W_change )
){
// veto Higgs inside uno
assert((begin_out+1)<end_out);
if( !boson.empty() && boson.front().type == ParticleID::h
){
if( (backward && boson.front().rapidity() < (begin_out+1)->rapidity())
||(!backward && boson.front().rapidity() > (begin_out+1)->rapidity()))
return non_resummable;
}
begin_out+=2;
return not_tested | (backward?unob:unof);
}
}
// Is this QQbar?
else if( incoming_id==pid::gluon ){
if( is_valid_impact_factor(
begin_out->type, (begin_out+1)->type, true, W_change )
){
// veto Higgs inside qqx
assert((begin_out+1)<end_out);
if( !boson.empty() && boson.front().type == ParticleID::h
){
if( (backward && boson.front().rapidity() < (begin_out+1)->rapidity())
||(!backward && boson.front().rapidity() > (begin_out+1)->rapidity()))
return non_resummable;
}
begin_out+=2;
return not_tested | (backward?qqxexb:qqxexf);
}
}
}
return non_resummable;
}
//! Returns all possible classifications from central emissions
// the beginning points are changed s.t. after the the classification they
// point to the end of the emission chain
// sets W_change: + if Wp change
// 0 if no change
// - if Wm change
template<class OutIterator>
size_t possible_central(
- OutIterator & begin_out, OutIterator const & end_out,
- int & W_change, std::vector<Particle> const & boson,
- OutIterator & qqx_pos
+ OutIterator & begin_out, OutIterator const & end_out,
+ int & W_change, std::vector<Particle> const & boson
){
using namespace event_type;
assert(boson.size() < 2);
// if we already passed the central chain,
// then it is not a valid all-order state
if(std::distance(begin_out, end_out) < 0) return non_resummable;
// keep track of all states that we don't test
size_t possible = unob | unof
| qqxexb | qqxexf;
// Find the first non-gluon/non-FKL
while( (begin_out->type==pid::gluon) && (begin_out<end_out) ){
++begin_out;
}
// end of chain -> FKL
if( begin_out==end_out ){
return possible | FKL;
}
// is this a qqbar-pair?
// needs two partons in two separate jets
if( is_valid_impact_factor(
begin_out->type, (begin_out+1)->type, true, W_change )
){
// veto Higgs inside qqx
if( !boson.empty() && boson.front().type == ParticleID::h
&& boson.front().rapidity() > begin_out->rapidity()
&& boson.front().rapidity() < (begin_out+1)->rapidity()
){
return non_resummable;
}
- qqx_pos=begin_out;
begin_out+=2;
// remaining chain should be pure gluon/FKL
for(; begin_out<end_out; ++begin_out){
if(begin_out->type != pid::gluon) return non_resummable;
}
return possible | qqxmid;
}
return non_resummable;
}
- bool invalid_jet(std::unordered_set<int> & other, int const idx){
- if(idx<0) return true;
- if(other.find(idx) != other.cend()) return true;
- other.insert(idx);
- return false;
- }
-
- bool jets_ok( size_t const final_type,
- std::vector<int> const & jet_idx, size_t const qqx_pos
- ){
- using namespace event_type;
-
- std::unordered_set<int> other;
- auto idx_begin{jet_idx.cbegin()};
- auto idx_end{jet_idx.crbegin()};
-
- // always seperate extremal jets
- if(invalid_jet(other, *idx_begin)) return false;
- if(invalid_jet(other, *idx_end)) return false;
-
- // unob -> second parton in own jet
- if( (final_type & (unob | qqxexb))
- && invalid_jet(other, *(idx_begin+1)) ) return false;
-
- if( (final_type & (unof | qqxexf))
- && invalid_jet(other, *(idx_end+1)) ) return false;
-
- assert( !(final_type & qqxmid) || jet_idx.size()>qqx_pos+1 );
- if( (final_type & qqxmid)
- && ( invalid_jet(other, *(idx_begin+qqx_pos))
- || invalid_jet(other, *(idx_begin+qqx_pos+1)) ) ) return false;
-
- return true;
- }
-
/**
* \brief Checks for all event types
* @param ev Event
* @returns Event Type
*
*/
event_type::EventType classify(Event const & ev){
using namespace event_type;
if(! has_2_jets(ev))
return no_2_jets;
// currently we can't handle multiple boson states in the ME. So they are
// considered "bad_final_state" even though the "classify" could work with
// them.
if(! final_state_ok(ev))
return bad_final_state;
// initialise variables
auto const & in = ev.incoming();
auto const & out = filter_partons(ev.outgoing());
assert(std::distance(begin(in), end(in)) == 2);
assert(out.size() >= 2);
assert(std::distance(begin(out), end(out)) >= 2);
assert(std::is_sorted(begin(out), end(out), rapidity_less{}));
auto const boson{ filter_AWZH_bosons(ev.outgoing()) };
// we only allow one boson through final_state_ok
assert(boson.size()<=1);
// keep track of potential W couplings, at the end the sum should be 0
int remaining_Wp = 0;
int remaining_Wm = 0;
if(!boson.empty() && abs(boson.front().type) == ParticleID::Wp ){
if(boson.front().type>0) ++remaining_Wp;
else ++remaining_Wm;
}
int W_change = 0;
// range for current checks
auto begin_out{out.cbegin()};
auto end_out{out.crbegin()};
size_t final_type = ~(no_2_jets | bad_final_state);
// check forward impact factor
final_type &= possible_impact_factors(
in.front().type,
begin_out, end_out.base(),
W_change, boson, true );
if( final_type == non_resummable )
return non_resummable;
if(W_change>0) remaining_Wp-=W_change;
else if(W_change<0) remaining_Wm+=W_change;
W_change = 0;
// check backward impact factor
final_type &= possible_impact_factors(
in.back().type,
end_out, std::make_reverse_iterator(begin_out),
W_change, boson, false );
if( final_type == non_resummable )
return non_resummable;
if(W_change>0) remaining_Wp-=W_change;
else if(W_change<0) remaining_Wm+=W_change;
W_change = 0;
// check central emissions
- auto qqx_pos{out.cend()};
final_type &= possible_central(
- begin_out, end_out.base(), W_change, boson, qqx_pos );
+ begin_out, end_out.base(), W_change, boson );
if( final_type == non_resummable )
return non_resummable;
- assert( !(final_type&qqxmid) || qqx_pos != out.cend() );
if(W_change>0) remaining_Wp-=W_change;
else if(W_change<0) remaining_Wm+=W_change;
// Check whether the right number of Ws are present
if( remaining_Wp != 0 || remaining_Wm != 0 ) return non_resummable;
// result has to be unique
if( (final_type & (final_type-1)) != 0) return non_resummable;
- // check jet configurations
- if(!jets_ok( final_type,
- ev.particle_jet_indices(),
- std::distance( out.cbegin(), qqx_pos) ))
- return non_resummable;
-
// check that each sub processes is implemented
// (has to be done at the end)
if( (final_type & ~implemented_types(boson)) != 0 )
return non_resummable;
return static_cast<EventType>(final_type);
}
//@}
Particle extract_particle(LHEF::HEPEUP const & hepeup, int i){
const ParticleID id = static_cast<ParticleID>(hepeup.IDUP[i]);
const fastjet::PseudoJet momentum{
hepeup.PUP[i][0], hepeup.PUP[i][1],
hepeup.PUP[i][2], hepeup.PUP[i][3]
};
if(is_parton(id))
return Particle{ id, std::move(momentum), hepeup.ICOLUP[i] };
return Particle{ id, std::move(momentum), {} };
}
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
Event::EventData::EventData(LHEF::HEPEUP const & hepeup){
parameters.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);
}
else outgoing.emplace_back(std::move(particle));
}
// 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 const & ev,
fastjet::JetDefinition const & jet_def, double const min_jet_pt
):
Event( Event::EventData{
ev.incoming, ev.outgoing, ev.decays,
Parameters<EventParameters>{ev.central, ev.variations}
}.cluster(jet_def, min_jet_pt) )
{}
//! @TODO remove in HEJ 2.2.0
UnclusteredEvent::UnclusteredEvent(LHEF::HEPEUP const & hepeup){
Event::EventData const evData{hepeup};
incoming = evData.incoming;
outgoing = evData.outgoing;
decays = evData.decays;
central = evData.parameters.central;
variations = evData.parameters.variations;
}
void Event::EventData::sort(){
// sort particles
std::sort(
begin(incoming), end(incoming),
[](Particle o1, Particle o2){return o1.p.pz()<o2.p.pz();}
);
auto old_outgoing = std::move(outgoing);
std::vector<size_t> idx(old_outgoing.size());
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(), [&old_outgoing](size_t i, size_t j){
return old_outgoing[i].rapidity() < old_outgoing[j].rapidity();
});
outgoing.clear();
outgoing.reserve(old_outgoing.size());
for(size_t i: idx) {
outgoing.emplace_back(std::move(old_outgoing[i]));
}
// find decays again
if(!decays.empty()){
auto old_decays = std::move(decays);
decays.clear();
for(size_t i=0; i<idx.size(); ++i) {
auto decay = old_decays.find(idx[i]);
if(decay != old_decays.end())
decays.emplace(i, std::move(decay->second));
}
assert(old_decays.size() == decays.size());
}
}
namespace {
Particle reconstruct_boson(std::vector<Particle> const & leptons) {
Particle decayed_boson;
decayed_boson.p = leptons[0].p + leptons[1].p;
const int pidsum = leptons[0].type + leptons[1].type;
if(pidsum == +1) {
assert(is_antilepton(leptons[0]));
if(is_antineutrino(leptons[0])) {
throw not_implemented{"lepton-flavour violating final state"};
}
assert(is_neutrino(leptons[1]));
// charged antilepton + neutrino means we had a W+
decayed_boson.type = pid::Wp;
}
else if(pidsum == -1) {
assert(is_antilepton(leptons[0]));
if(is_neutrino(leptons[1])) {
throw not_implemented{"lepton-flavour violating final state"};
}
assert(is_antineutrino(leptons[0]));
// charged lepton + antineutrino means we had a W-
decayed_boson.type = pid::Wm;
}
else {
throw not_implemented{
"final state with leptons "
+ name(leptons[0].type)
+ " and "
+ name(leptons[1].type)
};
}
return decayed_boson;
}
}
void Event::EventData::reconstruct_intermediate() {
const auto begin_leptons = std::partition(
begin(outgoing), end(outgoing),
[](Particle const & p) {return !is_anylepton(p);}
);
if(begin_leptons == end(outgoing)) return;
assert(is_anylepton(*begin_leptons));
std::vector<Particle> leptons(begin_leptons, end(outgoing));
outgoing.erase(begin_leptons, end(outgoing));
if(leptons.size() != 2) {
throw not_implemented{"Final states with one or more than two leptons"};
}
std::sort(
begin(leptons), end(leptons),
[](Particle const & p0, Particle const & p1) {
return p0.type < p1.type;
}
);
outgoing.emplace_back(reconstruct_boson(leptons));
decays.emplace(outgoing.size()-1, std::move(leptons));
}
Event Event::EventData::cluster(
fastjet::JetDefinition const & jet_def, double const min_jet_pt
){
sort();
Event ev{ std::move(incoming), std::move(outgoing), std::move(decays),
std::move(parameters),
jet_def, min_jet_pt
};
assert(std::is_sorted(begin(ev.outgoing_), end(ev.outgoing_),
rapidity_less{}));
ev.type_ = classify(ev);
return ev;
}
Event::Event(
std::array<Particle, 2> && incoming,
std::vector<Particle> && outgoing,
std::unordered_map<size_t, std::vector<Particle>> && decays,
Parameters<EventParameters> && parameters,
fastjet::JetDefinition const & jet_def,
double const min_jet_pt
): incoming_{std::move(incoming)},
outgoing_{std::move(outgoing)},
decays_{std::move(decays)},
parameters_{std::move(parameters)},
cs_{ to_PseudoJet( filter_partons(outgoing_) ), jet_def },
min_jet_pt_{min_jet_pt}
{
jets_ = sorted_by_rapidity(cs_.inclusive_jets(min_jet_pt_));
}
namespace {
// check that Particles have a reasonable colour
bool correct_colour(Particle const & part){
ParticleID id{ part.type };
if(!is_parton(id))
return !part.colour;
if(!part.colour)
return false;
Colour const & col{ *part.colour };
if(is_quark(id))
return col.first != 0 && col.second == 0;
if(is_antiquark(id))
return col.first == 0 && col.second != 0;
assert(id==ParticleID::gluon);
return col.first != 0 && col.second != 0 && col.first != col.second;
}
}
bool Event::is_leading_colour() const {
if( !correct_colour(incoming()[0]) || !correct_colour(incoming()[1]) )
return false;
Colour line_colour = *incoming()[0].colour;
std::swap(line_colour.first, line_colour.second);
for(auto const & part: outgoing()){
// reasonable colour
if(!correct_colour(part))
return false;
if(!is_parton(part)) // skip colour neutral particles
continue;
// if possible connect to line
if( line_colour.first == part.colour->second )
line_colour.first = part.colour->first;
else if( line_colour.second == part.colour->first )
line_colour.second = part.colour->second;
else
return false;
// no colour singlet exchange/disconnected diagram
if(line_colour.first == line_colour.second)
return false;
}
return (incoming()[1].colour->first == line_colour.first)
&& (incoming()[1].colour->second == line_colour.second);
}
namespace {
void connect_incoming(Particle & in, int & colour, int & anti_colour){
in.colour = std::make_pair(anti_colour, colour);
// gluon
if(in.type == pid::gluon)
return;
if(in.type > 0){
// quark
assert(is_quark(in));
in.colour->second = 0;
colour*=-1;
return;
}
// anti-quark
assert(is_antiquark(in));
in.colour->first = 0;
anti_colour*=-1;
return;
}
}
bool Event::generate_colours(RNG & ran){
// generate only for HEJ events
if(!event_type::is_resummable(type()))
return false;
assert(std::is_sorted(
begin(outgoing()), end(outgoing()), rapidity_less{}));
assert(incoming()[0].pz() < incoming()[1].pz());
// positive (anti-)colour -> can connect
// negative (anti-)colour -> not available/used up by (anti-)quark
int colour = COLOUR_OFFSET;
int anti_colour = colour+1;
// initialise first
connect_incoming(incoming_[0], colour, anti_colour);
for(auto & part: outgoing_){
assert(colour>0 || anti_colour>0);
if(part.type == ParticleID::gluon){
// gluon
if(colour>0 && anti_colour>0){
// on g line => connect to colour OR anti-colour (random)
if(ran.flat() < 0.5){
part.colour = std::make_pair(colour+2,colour);
colour+=2;
} else {
part.colour = std::make_pair(anti_colour, anti_colour+2);
anti_colour+=2;
}
} else if(colour > 0){
// on q line => connect to available colour
part.colour = std::make_pair(colour+2, colour);
colour+=2;
} else {
assert(colour<0 && anti_colour>0);
// on qx line => connect to available anti-colour
part.colour = std::make_pair(anti_colour, anti_colour+2);
anti_colour+=2;
}
} else if(is_quark(part)) {
// quark
assert(anti_colour>0);
if(colour>0){
// on g line => connect and remove anti-colour
part.colour = std::make_pair(anti_colour, 0);
anti_colour+=2;
anti_colour*=-1;
} else {
// on qx line => new colour
colour*=-1;
part.colour = std::make_pair(colour, 0);
}
} else if(is_antiquark(part)) {
// anti-quark
assert(colour>0);
if(anti_colour>0){
// on g line => connect and remove colour
part.colour = std::make_pair(0, colour);
colour+=2;
colour*=-1;
} else {
// on q line => new anti-colour
anti_colour*=-1;
part.colour = std::make_pair(0, anti_colour);
}
} else { // not a parton
assert(!is_parton(part));
part.colour = {};
}
}
// Connect last
connect_incoming(incoming_[1], anti_colour, colour);
assert(is_leading_colour());
return true;
} // generate_colours
+ namespace {
+ bool invalid_jet(std::unordered_set<int> & other, int const idx){
+ if(idx<0) return true;
+ if(other.find(idx) != other.cend()) return true;
+ other.insert(idx);
+ return false;
+ }
+
+ bool jets_ok( size_t const final_type,
+ std::vector<int> const & jet_idx, size_t const qqx_pos
+ ){
+ using namespace event_type;
+
+ std::unordered_set<int> other;
+ auto idx_begin{jet_idx.cbegin()};
+ auto idx_end{jet_idx.crbegin()};
+
+ // always seperate extremal jets
+ if(invalid_jet(other, *idx_begin)) return false;
+ if(invalid_jet(other, *idx_end)) return false;
+
+ // unob -> second parton in own jet
+ if( (final_type & (unob | qqxexb))
+ && invalid_jet(other, *(idx_begin+1)) ) return false;
+
+ if( (final_type & (unof | qqxexf))
+ && invalid_jet(other, *(idx_end+1)) ) return false;
+
+ assert( !(final_type & qqxmid) || jet_idx.size()>qqx_pos+1 );
+ if( (final_type & qqxmid)
+ && ( invalid_jet(other, *(idx_begin+qqx_pos))
+ || invalid_jet(other, *(idx_begin+qqx_pos+1)) ) ) return false;
+
+ return true;
+ }
+ }
+
// this should work with multiple types
bool Event::valid_hej_state(double const /*max_ext_soft_pt_fraction*/,
double const /*min_extparton_pt*/
) const {
using namespace event_type;
if(!is_resummable(type()))
return false;
// find qqx pair if needed
auto begin_qqx {cend_partons()};
if( type() & qqxmid){
auto begin_FKL = ++cbegin_partons();
auto end_FKL = ++cend_partons();
if( type() & (qqxexb | unob) )
++begin_FKL;
if( type() & (qqxexf | unof) )
++end_FKL;
begin_qqx = std::find_if(begin_FKL, end_FKL,
[](Particle const & part) -> bool {
return part.type != ParticleID::gluon;
}
);
assert(begin_qqx != end_FKL);
}
if( !jets_ok( type(), particle_jet_indices(),
std::distance(cbegin_partons(), begin_qqx) ))
return false;
return true;
}
Event::ConstPartonIterator Event::begin_partons() const {
return cbegin_partons();
};
Event::ConstPartonIterator Event::cbegin_partons() const {
return boost::make_filter_iterator(
static_cast<bool (*)(Particle const &)>(is_parton),
cbegin(outgoing()),
cend(outgoing())
);
};
Event::ConstPartonIterator Event::end_partons() const {
return cend_partons();
};
Event::ConstPartonIterator Event::cend_partons() const {
return boost::make_filter_iterator(
static_cast<bool (*)(Particle const &)>(is_parton),
cend(outgoing()),
cend(outgoing())
);
};
namespace {
void print_momentum(std::ostream & os, fastjet::PseudoJet const & part){
const std::streamsize orig_prec = os.precision();
os <<std::scientific<<std::setprecision(6) << "["
<<std::setw(13)<<std::right<< part.px() << ", "
<<std::setw(13)<<std::right<< part.py() << ", "
<<std::setw(13)<<std::right<< part.pz() << ", "
<<std::setw(13)<<std::right<< part.E() << "]"<< std::fixed;
os.precision(orig_prec);
}
void print_colour(std::ostream & os, optional<Colour> const & col){
if(!col)
os << "(no color)"; // American spelling for better alignment
else
os << "(" <<std::setw(3)<<std::right<< col->first
<< ", " <<std::setw(3)<<std::right<< col->second << ")";
}
}
std::ostream& operator<<(std::ostream & os, Event const & ev){
const std::streamsize orig_prec = os.precision();
os <<std::setprecision(4)<<std::fixed;
os << "########## " << event_type::name(ev.type()) << " ##########" << std::endl;
os << "Incoming particles:\n";
for(auto const & in: ev.incoming()){
os <<std::setw(3)<< in.type << ": ";
print_colour(os, in.colour);
os << " ";
print_momentum(os, in.p);
os << std::endl;
}
os << "\nOutgoing particles: " << ev.outgoing().size() << "\n";
for(auto const & out: ev.outgoing()){
os <<std::setw(3)<< out.type << ": ";
print_colour(os, out.colour);
os << " ";
print_momentum(os, out.p);
os << " => rapidity="
<<std::setw(7)<<std::right<< out.rapidity() << std::endl;
}
os << "\nForming Jets: " << ev.jets().size() << "\n";
for(auto const & jet: ev.jets()){
print_momentum(os, jet);
os << " => rapidity="
<<std::setw(7)<<std::right<< jet.rapidity() << std::endl;
}
if(ev.decays().size() > 0 ){
os << "\nDecays: " << ev.decays().size() << "\n";
for(auto const & decay: ev.decays()){
os <<std::setw(3)<< ev.outgoing()[decay.first].type
<< " (" << decay.first << ") to:\n";
for(auto const & out: decay.second){
os <<" "<<std::setw(3)<< out.type << ": ";
print_momentum(os, out.p);
os << " => rapidity="
<<std::setw(7)<<std::right<< out.rapidity() << std::endl;
}
}
}
os << std::defaultfloat;
os.precision(orig_prec);
return os;
}
double shat(Event const & ev){
return (ev.incoming()[0].p + ev.incoming()[1].p).m2();
}
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(); // event type
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;
result.IDUP.reserve(num_particles); // PID
result.ISTUP.reserve(num_particles); // status (in, out, decay)
result.PUP.reserve(num_particles); // momentum
result.MOTHUP.reserve(num_particles); // index mother particle
result.ICOLUP.reserve(num_particles); // colour
// incoming
std::array<Particle, 2> incoming{ event.incoming() };
// First incoming should be positive pz according to LHE standard
// (or at least most (everyone?) do it this way, and Pythia assumes it)
if(incoming[0].pz() < incoming[1].pz())
std::swap(incoming[0], incoming[1]);
for(Particle const & in: 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);
assert(in.colour);
result.ICOLUP.emplace_back(*in.colour);
}
// outgoing
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);
if(out.colour)
result.ICOLUP.emplace_back(*out.colour);
else{
result.ICOLUP.emplace_back(std::make_pair(0,0));
}
}
// decays
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 size_t 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/t/classify_ref b/t/classify_ref
index c7d785e..cae2ad5 100644
--- a/t/classify_ref
+++ b/t/classify_ref
@@ -1,125 +1,125 @@
8
4
4
4
4
4
4
8
4
8
4
4
4
16
4
8
4
4
8
8
4
4
8
4
4
4
4
4
4
4
4
4
4
4
16
4
4
16
4
4
4
4
4
16
4
4
4
16
4
4
8
16
4
16
4
8
4
4
8
4
8
16
8
16
4
4
4
4
4
4
4
4
4
4
4
4
8
4
4
4
4
4
4
4
4
8
4
4
4
4
16
4
8
4
4
4
4
4
4
4
4
4
4
8
4
4
4
-0
+4
4
8
4
8
8
4
4
4
4
4
4
4
4
4
16
8
4
diff --git a/t/classify_ref_4j b/t/classify_ref_4j
index 056dd0f..c3cf052 100644
--- a/t/classify_ref_4j
+++ b/t/classify_ref_4j
@@ -1,3255 +1,3255 @@
4
4
0
-0
4
-0
+4
+8
4
4
4
16
4
0
0
-0
4
-0
-0
4
0
4
-0
-0
4
0
-0
4
-0
4
-0
+4
+4
+4
+4
4
0
+4
0
-0
+4
+4
+8
+4
0
4
4
2
-0
-0
+8
+4
2
4
-0
-0
4
4
4
4
-0
4
-0
-0
4
-0
+8
+4
+4
+4
+4
+4
2
4
4
-0
-0
-0
4
+16
0
4
-0
+4
+4
+4
4
4
0
4
4
0
4
4
4
-0
+4
4
4
0
-0
+8
0
0
4
4
0
2
-0
-0
4
-0
-0
-0
-0
+4
4
0
+4
0
4
4
-0
-0
-0
4
0
+4
+4
0
-0
-0
-0
-0
-0
+16
+8
+4
+4
+4
+4
+4
+4
+4
+4
4
2
4
0
-0
4
-0
-0
4
-0
4
4
-0
-0
-0
4
-0
+4
+4
+4
+4
+4
+4
+4
+4
4
4
4
4
0
-0
+4
4
4
0
4
4
4
2
-0
-0
4
4
-0
-0
-0
+4
4
0
4
+8
+4
+16
+4
4
0
-0
+8
4
4
2
4
2
4
4
0
-0
+4
0
4
4
-0
4
-0
+4
+4
8
4
0
4
0
4
4
2
-0
+4
0
2
2
8
4
4
0
4
-0
+4
8
4
4
16
8
0
4
0
-0
-0
-0
4
-0
-0
+4
4
4
0
-0
+4
+4
4
4
0
+4
+4
+4
2
0
-0
4
4
-0
4
4
-0
-0
4
4
4
-0
+4
+4
+4
+4
+4
2
-0
+8
+4
+4
4
4
4
4
-0
4
-0
-0
-0
0
4
0
4
+8
+4
4
0
0
0
4
-0
-0
+16
4
-0
4
-0
-0
-0
4
4
0
4
4
4
-0
4
-0
-0
+4
+4
+4
+4
+4
4
0
+4
+4
0
+4
0
-0
+4
8
4
4
4
4
0
4
8
4
8
4
4
4
4
-0
4
4
4
-0
-0
4
0
0
4
-0
4
0
4
+4
+4
+4
+4
16
-0
-0
-0
+4
+4
+4
2
0
0
4
-0
-0
+4
+4
4
0
0
8
4
-0
-0
-0
-0
+4
+4
+4
+4
0
4
4
4
16
0
-0
4
-16
4
+16
4
-0
-0
4
0
-0
-2
-0
-0
-0
-0
-0
-0
-0
-0
4
-0
4
-0
-0
+16
4
2
4
4
0
-0
4
4
4
0
0
4
-0
-0
4
-0
-0
4
-0
4
-0
-0
4
4
+2
4
4
0
0
-0
-4
4
4
-2
-0
-2
-0
-0
-0
4
0
4
4
0
4
-0
4
4
-0
4
-0
-2
-0
-0
4
0
-0
-0
-0
4
+16
0
4
-0
-0
-0
4
-0
4
4
0
4
0
4
4
-16
-0
4
+2
+16
+2
4
0
0
4
0
-2
4
-0
4
4
-0
4
0
4
4
-2
-0
4
-0
-8
-8
4
-0
-0
-0
4
2
0
4
-0
+4
+16
+4
4
0
4
4
4
4
+4
+4
+4
+4
+4
+4
+4
+4
+0
+4
+4
+16
0
4
+4
0
+4
+4
0
2
+4
0
4
+4
0
4
+4
+4
+4
+2
0
4
+16
+8
+8
+4
4
0
+4
+4
+2
+4
+4
+4
+4
+4
+4
+4
+4
+4
0
4
4
4
+2
0
4
4
+4
+4
+4
+4
+8
+4
+4
+4
+4
0
+4
+4
0
+8
+4
4
4
4
4
-0
2
+16
0
-0
-0
+4
4
2
4
4
4
4
4
2
0
4
4
-0
+8
4
0
-0
+4
4
2
-0
4
-0
4
4
4
4
-0
4
-0
-0
4
0
+4
+4
0
-0
-0
-0
-0
-0
+4
+8
+4
+4
4
0
0
+16
+4
+4
+4
0
4
4
4
4
-0
-0
+4
+4
4
4
4
4
4
4
16
4
4
4
-0
4
4
4
4
-0
+4
+4
2
4
4
-0
+4
16
0
+4
0
-0
-0
+16
2
4
4
4
0
4
0
-0
4
-0
-0
4
0
0
4
4
-0
4
4
4
-0
4
4
4
4
-0
4
-0
-0
+4
+4
+4
4
0
+4
0
0
+4
0
4
4
4
+4
+4
+4
2
4
-0
-0
4
-0
-0
-0
+4
+4
+4
+4
+4
4
0
-0
-0
+8
+4
0
4
0
0
4
2
4
4
0
4
-0
-0
+4
+4
4
0
16
-0
4
-0
+4
+4
4
0
2
8
4
-0
-0
-0
-0
-0
+4
4
0
4
4
4
0
-0
-0
-0
+4
+4
4
4
0
-0
-0
4
+4
+4
+4
+4
+8
0
+4
0
+4
0
2
4
4
0
-0
+4
4
2
0
0
4
4
4
0
4
4
-0
+4
0
2
4
4
0
-0
-0
+4
+8
0
4
4
4
2
+4
0
0
-0
-0
+4
4
4
4
4
2
4
4
0
-0
-0
-0
+4
0
0
0
0
4
-0
+4
+4
+4
2
2
4
4
4
4
0
-0
-0
4
0
-0
-0
4
4
0
-0
+4
+4
+4
+4
+4
8
4
2
4
-0
4
-0
+4
+8
4
2
-0
4
-0
+4
+4
0
0
4
4
-0
4
-0
4
-0
4
-0
+4
+4
+4
+4
4
4
0
4
4
4
4
4
4
2
2
2
-0
-0
-0
4
-0
4
-0
+4
+4
+4
+4
+4
4
0
0
4
4
4
4
8
-0
+4
8
+4
0
-0
-0
+8
0
4
4
-0
+4
2
2
-0
+4
2
4
0
-0
+4
4
4
4
0
4
2
0
4
0
4
0
-0
4
-0
4
-0
4
-0
4
0
4
4
4
0
+4
+4
+4
0
0
4
4
4
4
-0
-0
-0
-0
4
-0
+4
+4
4
0
+4
+8
+4
0
+4
2
4
4
-0
-0
+16
+4
2
4
0
2
8
4
4
0
-0
4
-0
-0
4
-0
+4
+4
+4
+4
4
4
4
4
0
4
4
4
4
4
0
-0
+4
4
0
0
4
2
4
-0
4
-0
+4
+4
2
-0
-0
-0
4
4
4
4
-0
4
-0
-0
4
4
-0
+4
+4
+4
+4
+4
+4
+4
4
4
8
-0
4
-0
4
-0
4
4
-0
+4
+4
4
0
+4
0
+4
0
2
0
16
-0
+4
0
0
4
4
-0
-0
4
-0
-0
+4
+4
+4
+16
4
0
2
-0
-0
4
-0
4
-0
4
-0
+4
+4
+4
+4
+4
4
0
4
16
4
4
4
0
2
2
-0
+4
0
8
4
-0
4
-0
-0
4
4
4
-0
-0
4
-0
-0
-0
+4
+4
+4
0
4
0
0
+4
+4
+4
0
4
0
+4
+4
8
-0
-0
-0
+4
+4
+4
4
4
2
4
0
2
4
-0
+4
2
-0
-0
+4
+4
0
4
0
4
4
4
4
-0
-0
-0
4
+16
0
4
0
4
4
+4
+4
2
4
4
4
4
-0
+4
0
4
4
0
-0
+4
2
0
-0
-0
4
-0
-0
-0
-0
4
4
0
4
4
-0
-0
4
4
-0
-0
-0
-0
-0
-0
-0
4
-0
-0
-0
-0
4
-0
-0
-0
+4
4
0
-0
+4
+4
+4
+4
4
0
0
0
4
+4
+4
+4
0
0
4
+4
+4
+4
0
+4
+4
+4
+4
0
0
+4
+4
+4
+8
+4
+4
0
-0
+4
4
0
4
+4
+4
0
4
2
-0
4
4
4
-0
-0
-0
+4
+4
+4
+4
4
4
0
-0
+4
2
0
4
4
16
4
4
4
0
0
-0
4
-0
-0
-0
4
-0
-0
-0
-0
+4
+4
+4
+4
4
0
+4
0
4
0
+4
+4
+4
0
4
16
-0
+4
4
2
-0
-0
-0
-0
4
-0
-0
-0
-0
+4
+4
4
4
4
0
-0
-0
+4
+4
+4
+4
+4
+4
+4
0
0
4
+4
2
-0
+4
2
-0
+16
4
2
4
4
8
16
-0
4
4
4
4
-0
4
0
+4
+4
16
0
4
4
0
-0
-0
4
0
-0
-0
4
-0
4
-0
+4
4
4
4
4
0
4
4
-0
-0
-0
+4
+4
0
4
4
4
-0
-0
+4
+4
+4
+4
+4
+4
+4
+4
8
4
2
4
4
4
4
-0
4
4
-0
-0
+4
+4
+4
2
4
16
-0
+8
4
2
-0
+4
0
4
4
-0
-0
+8
4
4
4
-0
-0
-0
-0
4
0
4
-0
-0
-0
+16
0
4
-0
-0
-0
-0
+16
4
0
+4
+4
+4
+4
+4
+4
0
-0
+4
+4
+4
4
0
+4
0
4
+4
0
2
0
-0
-0
4
-0
-0
-0
4
-0
+4
+4
4
0
4
4
4
0
-0
4
4
-0
-0
+4
+4
+4
+4
+4
+8
+4
4
4
2
-0
+8
+4
+4
4
-0
-0
4
4
-0
4
4
-0
-0
-0
4
0
+4
+4
+4
+4
2
16
0
2
4
4
2
0
0
-0
4
-0
+4
+4
2
4
0
-0
+4
0
0
0
4
4
4
2
4
-0
-0
-0
-0
4
-0
-0
-0
-0
4
0
+4
+4
0
-0
+4
+4
+4
4
0
4
4
+4
+4
+4
+4
0
0
4
4
4
-0
+4
0
0
4
4
0
4
4
-0
-0
+4
+4
4
2
4
4
0
0
4
-0
-0
4
0
-0
4
16
0
4
+16
+4
+4
0
4
4
0
2
4
4
-0
4
-0
4
-0
+4
+4
0
4
+4
8
-0
-0
-0
+4
4
0
4
4
4
+4
+4
8
8
0
-0
+16
+4
4
-0
4
4
4
16
-0
+16
2
0
4
4
-0
-0
4
-0
-0
-0
-0
-0
+4
+4
+16
+16
4
0
+4
+4
+4
0
0
2
8
4
-0
+4
2
-0
-0
+4
+4
0
4
4
4
4
-0
-0
+4
+4
4
2
0
0
4
4
-0
+4
2
0
4
4
4
-0
4
4
4
-0
-0
4
4
-0
+4
+4
+4
+4
0
0
4
4
4
2
-0
4
4
4
-0
+4
+8
4
4
4
4
0
-0
-0
4
+8
4
4
-0
4
-0
4
-0
-0
4
0
+4
0
+4
+4
+4
+4
+4
0
-0
-0
+4
4
4
2
0
-0
-0
4
0
4
0
4
4
4
-0
+4
+4
+4
16
4
-0
+4
4
8
-0
+4
2
4
4
4
4
2
4
+4
+0
+4
+4
+4
0
0
4
4
+4
+4
+4
+4
+4
+4
+8
+4
0
-0
-0
-0
-0
-0
4
4
-0
4
-0
-0
4
-0
4
0
4
0
0
-0
4
-0
-0
-0
4
4
8
4
4
-0
-0
-0
-0
-0
+4
+4
4
4
0
+4
+4
0
+4
2
0
2
-0
+8
+4
4
4
4
-0
0
2
4
4
4
2
4
4
2
2
-0
-0
4
-0
+4
+4
+4
4
0
4
4
4
0
0
4
4
4
-0
+4
2
4
2
4
2
-0
+4
4
4
2
-0
+4
4
2
-0
4
-0
-0
4
8
-0
+4
+4
+8
+4
2
4
-0
+4
16
0
4
-0
+4
4
4
2
-0
+4
2
-0
-0
4
-0
-0
-0
-0
+4
+4
+4
+4
+4
+16
4
4
4
4
2
0
4
-0
+4
4
2
0
-0
-0
+4
+16
+4
4
4
4
4
4
4
-0
-0
4
4
4
4
-0
-0
4
4
0
-0
-0
-0
+4
+4
+4
+4
+4
+4
0
2
4
0
4
4
4
-0
-0
4
-0
+4
+4
+4
0
4
2
0
4
4
8
2
0
-0
+4
4
4
16
4
-0
-0
-0
+4
+4
+4
4
4
0
0
0
4
4
4
16
4
4
0
4
-0
-0
+4
+4
2
-0
+8
4
4
-0
4
4
-0
4
-0
4
4
0
4
-0
4
4
-0
-0
-0
-0
-0
-0
-0
4
-0
-0
+4
+4
4
0
-0
+4
+16
0
4
+4
+4
+4
0
+4
+4
+4
+4
0
+4
0
0
+4
0
0
+4
16
16
4
-0
+4
0
4
4
4
4
2
4
0
0
4
-0
4
-0
-0
4
-0
+4
+8
4
0
-0
+4
+4
+4
4
4
4
4
2
4
0
+4
0
-0
-0
+4
4
16
-0
-0
-0
+8
4
0
+4
0
4
+4
0
4
0
4
8
4
-0
4
4
-0
4
-0
+4
+4
+4
4
0
-0
+4
2
4
4
4
-0
-0
4
0
4
4
-0
-0
+4
+4
+4
+4
0
4
4
2
-0
-0
4
0
+4
+4
0
0
4
4
4
0
4
-0
4
-0
+4
+4
4
16
4
8
4
-0
4
-0
+4
+8
4
4
2
-0
4
4
-0
4
0
+4
+4
0
4
0
4
4
-0
4
-0
4
0
4
+16
+4
4
4
4
4
0
4
2
4
0
-0
+4
2
0
-0
+8
4
0
4
-0
+4
4
4
4
2
0
-0
4
4
-0
4
4
-0
+4
+4
+4
2
-0
-0
4
-0
+4
4
0
-0
+4
+4
0
4
4
4
-0
-0
+4
0
4
4
-0
-0
-0
+4
+4
+4
+4
+4
4
0
-0
-0
-0
-0
-0
-0
-0
+4
+4
+4
+4
+4
+4
+4
0
2
-0
4
-0
4
-0
4
-0
4
-0
-0
-0
+4
4
0
+4
0
+4
0
4
0
+4
+4
+4
0
+8
0
0
4
-0
+4
0
8
4
-0
-0
-0
+4
+4
+4
4
4
4
4
0
4
4
4
4
4
-0
+4
+4
4
4
4
0
-0
-0
+4
4
4
4
4
8
4
4
4
4
-0
+4
4
8
4
-0
+4
0
0
2
0
0
-0
-0
4
-0
-0
+4
+4
+4
0
4
4
4
4
4
-0
4
4
-0
4
4
4
-0
-0
-0
+4
4
4
0
0
0
+4
+4
0
+4
+4
0
4
4
4
-0
-0
-0
+4
+4
+4
+16
4
0
0
4
4
4
4
4
2
16
0
4
4
-0
-0
+4
+4
0
2
-0
-0
4
0
4
-0
-0
+4
+4
+4
+4
4
4
4
4
2
4
16
4
-0
-0
+4
+4
4
2
0
4
4
-0
4
-0
4
4
-0
4
-0
4
4
4
4
-0
4
-0
4
-0
-0
4
4
+16
+4
+8
4
+8
0
4
+4
+4
+4
+4
0
0
4
4
4
-0
4
-0
+4
+4
2
4
4
-0
4
-0
4
4
4
4
-0
-0
-0
+4
+4
+4
0
4
4
4
4
+4
+4
0
2
4
-0
+4
8
0
4
-0
-0
-0
-0
-0
4
4
4
0
+4
+4
+4
+4
0
+4
0
-0
+4
0
2
-0
+4
4
4
4
16
4
4
4
4
4
-0
-0
-0
-0
4
4
4
-0
+4
+4
4
4
0
+4
+4
+4
2
-0
4
4
4
-0
+4
+4
4
2
-0
4
4
4
-0
-0
+4
+4
+4
2
0
4
-0
-0
4
-0
-0
+4
+4
+4
+4
4
4
4
4
4
2
4
0
4
0
4
4
-0
+4
0
4
2
4
4
-0
-0
4
0
+4
0
0
+4
0
4
4
8
0
-0
+4
2
4
4
0
-0
-0
4
-0
4
-0
4
-0
+4
+4
+4
+4
+4
4
4
2
4
4
0
4
-0
+4
4
4
0
4
2
0
4
4
4
4
2
-0
-0
4
-0
-0
-0
+8
4
4
-0
+4
+8
+4
4
0
4
4
+4
+4
0
0
4
4
2
4
-0
+4
4
4
0
-0
+4
2
-0
-0
+4
+4
0
8
-0
+16
0
4
4
+4
0
0
-0
-0
+4
0
0
4
-0
+4
2
4
0
-0
4
-0
-0
4
0
+8
+4
+4
4
4
4
4
8
-0
-0
-0
-0
4
4
4
-0
4
4
-0
4
4
0
+4
+4
+4
+4
+4
+4
8
4
4
2
2
-0
-0
-0
4
-0
-0
4
4
4
4
0
-0
+4
+4
+4
4
0
4
4
+4
+4
+4
0
4
4
4
4
8
-0
+4
2
4
-0
+4
0
2
4
4
4
-0
-0
-0
-0
4
-0
-0
+4
4
0
+4
0
+4
+4
+4
+4
2
4
4
4
0
-0
4
4
-0
+4
+4
2
0
4
-0
-0
-0
+4
+4
+4
4
8
4
4
0
4
-0
-0
4
-0
+4
4
0
4
+4
+4
0
4
4
16
0
-0
+4
4
0
-0
+4
0
0
16
-0
+4
4
0
-0
+4
4
4
0
4
4
4
4
0
4
0
-0
+4
0
16
4
-0
4
4
-0
4
0
-0
-0
4
0
0
+4
+4
+8
+4
2
4
0
4
2
0
4
0
4
4
4
-0
-0
+4
+4
4
4
4
4
4
2
-0
+4
16
0
0
4
4
4
4
-0
4
-0
+4
+4
4
4
2
-0
-0
+8
+4
4
4
2
0
-0
+16
+4
4
0
0
-0
-0
-0
+4
+4
2
0
4
4
-0
4
-0
4
0
+4
+4
2
4
0
4
-0
+4
0
4
0
0
4
-0
4
-0
-0
4
-0
+16
+4
+4
+4
2
4
4
4
-0
-0
+4
+4
4
0
4
4
4
0
4
2
-0
+4
+4
4
4
0
0
0
-0
-0
+4
0
4
4
4
-0
-0
4
-0
4
4
0
4
-0
-0
-0
4
-0
-0
-0
4
4
+4
+4
+4
+4
+16
+4
0
4
4
+4
+4
+4
2
0
4
4
4
0
16
-0
-0
4
4
4
-0
4
-0
-0
+4
+4
+4
+4
+4
4
2
-0
+8
2
4
-0
4
-0
4
0
-0
4
-0
-0
-0
-0
4
0
-0
4
-0
4
-0
4
0
-0
-0
-0
4
4
4
4
4
0
-0
-0
4
-0
+4
+4
+4
4
0
+4
+4
+4
+4
+4
+4
+4
+4
+4
+4
+4
+4
+4
2
-0
+4
4
0
+4
0
0
0
0
-0
-0
+8
4
0
4
0
16
4
-0
+4
4
2
-0
-0
-0
-0
+16
+4
+4
+4
4
4
0
+8
0
-0
-0
-0
+4
+4
4
4
4
4
4
2
16
4
+4
+4
0
-0
-0
-0
+4
0
4
4
0
-0
+16
+4
4
4
4
4
4
4
4
4
-0
4
0
4
4
16
0
4
-0
-0
4
4
4
4
4
-0
+4
+4
+16
4
4
4
2
4
2
4
2
4
-0
4
4
-0
+4
+4
4
4
0
0
4
4
16
-0
+4
2
0
4
4
2
4
4
4
-0
+4
16
4
0
4
4
4
-0
-0
-0
+4
0
0
4
0
4
-0
4
-0
+4
+4
+4
+8
+4
+4
+4
4
4
4
4
-0
-0
4
4
-0
16
-0
-0
-0
-0
4
-0
+4
+4
+4
+4
+4
16
0
0
0
4
0
-0
-0
+8
+4
+4
+4
4
4
4
-0
-0
-0
-0
-0
4
4
0
4
+4
+4
+4
0
4
4
0
2
-0
+16
2
-0
-0
-0
-0
-0
4
0
+4
+16
0
4
4
4
+4
+4
+4
+4
0
-0
-0
+8
4
0
4
4
0
4
4
4
-0
+4
4
0
2
-0
-0
4
0
4
0
-0
-0
-0
4
0
4
4
+16
4
0
+4
+4
+4
0
4
4
4
+4
0
4
2
-0
+4
4
4
0
2
4
4
4
16
0
4
-0
4
-0
+4
+4
0
4
4
2
4
0
2
-0
+4
0
4
2
-0
-0
+4
+4
0
4
0
4
4
+4
0
0
-0
-0
-0
-0
+8
+16
+4
2
4
-0
4
-0
4
-8
-0
-0
+4
+4
+8
+4
+4
+4
+4
+4
+4
+4
+4
+4
+16
+4
+4
+4
4
0
-0
4
0
-0
+4
+4
+4
4
16
4
4
-0
-0
-0
4
0
-0
-0
-0
4
-16
-0
4
4
-0
4
-0
-0
4
4
4
4
-0
-0
4
-0
4
0
-0
+4
+4
+4
4
4
0
4
4
0
4
8
-0
-0
-0
4
4
4
-0
4
-0
-0
4
-0
-0
+4
+4
+4
+4
+16
+4
+4
+4
8
16
2
-0
+4
4
0
4
0
4
4
-0
-0
4
4
-0
+4
+4
+4
4
0
8
2
4
-0
+4
0
4
4
4
4
+4
+4
0
-0
-0
-0
-0
-0
+8
+4
+4
4
4
0
16
4
-0
+4
4
2
-0
4
-0
4
-0
4
-0
+4
+4
+4
+4
0
0
4
4
-0
4
4
-0
4
-0
-0
4
-0
-0
+4
0
0
4
0
-0
4
4
-0
-0
+4
+4
+4
+4
4
4
0
4
+4
+4
+4
+4
2
4
0
-0
-0
+4
+4
4
0
4
0
0
4
4
8
-0
+16
4
8
-0
+4
0
4
4
16
2
4
4
-0
4
-0
-0
+4
+4
+4
4
16
4
4
0
-0
4
-0
+4
+4
4
4
4
8
4
0
4
4
4
2
4
2
4
4
0
4
4
0
4
-0
4
4
-0
+4
+4
2
-0
+16
4
16
4
4
4
-0
-0
-0
+4
+8
+4
+4
+4
4
4
-0
4
4
-0
4
4
4
4
4
4
0
4
4
4
4
4
2
-0
4
4
-0
-0
4
0
+16
+4
+4
+4
4
4
4
-0
2
-0
4
-0
+4
+16
4
4
0
0
2
-0
4
-0
+4
+16
4
0
4
4
-0
+4
4
4
0
2
-0
+4
4
4
4
4
0
-0
-0
+4
+4
8
4
0
0
4
16
2
-0
+4
4
4
2
4
4
0
4
2
4
-0
-0
4
-0
-0
-0
-0
4
-0
-0
-0
+4
+16
+4
+4
+4
+4
+8
+4
+4
+4
+4
+4
+4
+4
+4
4
4
4
4
-0
-0
4
4
-0
4
-0
4
-0
4
4
4
4
-0
0
16
0
4
8
-0
4
-0
-0
-0
-0
+4
+4
+4
+4
+4
4
0
0
4
0
0
-0
+4
4
4
4
0
-0
+4
0
4
4
4
0
-0
4
-0
+4
+4
2
4
-0
-0
4
4
-0
4
-0
+4
0
4
0
+4
+4
+4
0
0
2
0
4
0
-0
+16
4
4
4
4
2
4
0
4
0
4
4
0
0
-0
+4
0
4
4
0
4
-0
4
-0
+4
+4
0
0
4
4
4
4
4
4
4
4
4
4
4
-0
4
4
-0
+4
+4
4
16
-0
+8
4
4
16
4
4
4
4
4
4
4
4
2
4
-0
-0
-0
4
0
-0
+16
+4
+4
+16
+4
+4
+4
+4
4
-0
4
4
4
4
0
-0
-0
-0
-0
+4
4
8
-0
+4
4
2
4
4
4
4
0
4
0
2
4
4
4
4
4
-0
4
4
-0
4
4
4
-0
-0
-0
4
-0
-0
+4
+4
+4
+4
4
0
+8
+4
0
+4
2
4
4
4
4
8
4
diff --git a/t/classify_ref_W4j b/t/classify_ref_W4j
index 0e37a12..2780c23 100644
--- a/t/classify_ref_W4j
+++ b/t/classify_ref_W4j
@@ -1,4000 +1,4000 @@
4
-0
-0
+128
+32
0
4
4
8
4
4
-0
+16
0
4
-0
+128
8
4
0
8
16
0
4
-0
-0
+4
+16
4
0
4
32
4
-0
+128
4
0
-0
-0
+16
+8
4
0
4
-0
+4
0
4
128
4
4
0
4
-0
+4
16
128
-0
-0
-0
-0
-0
+8
4
0
0
-0
+128
+4
4
0
0
+4
+16
0
+16
4
32
128
4
4
0
0
4
8
0
4
0
8
2
8
-0
+8
4
-0
+16
4
64
0
4
32
0
-0
+16
4
4
-0
+8
8
4
16
-0
+128
64
-0
-0
+4
+16
+4
4
4
4
-0
16
-0
+128
+4
4
4
-0
0
0
4
0
0
4
64
-0
+64
32
4
4
4
4
-0
+64
32
-0
+128
4
-0
+64
128
-0
4
-0
+4
+16
4
0
0
4
4
4
4
0
-0
+32
4
4
32
2
4
0
0
2
8
0
0
-0
+16
2
4
0
-0
+16
4
-0
-0
+4
+8
2
4
-0
-0
4
0
4
+16
+4
8
4
8
+8
0
-0
-0
+8
4
0
0
16
-0
+64
2
8
0
0
0
8
64
4
4
4
0
-0
-0
+16
4
-0
-0
-0
+4
+4
+128
+128
0
4
4
4
4
4
16
-0
-0
-0
-0
-0
+128
4
+16
+16
0
+4
0
4
+4
0
16
-0
-0
+8
+128
1
+8
0
-0
-0
-0
+4
+16
0
32
0
4
4
-0
+32
4
16
0
0
-0
+4
128
32
4
8
-0
-0
+8
+16
4
1
8
-0
+8
+4
4
-0
0
0
32
4
4
16
0
8
0
-0
+16
4
-0
-0
+16
+8
4
128
0
0
0
-0
-0
+64
+16
4
4
1
4
16
8
0
4
4
4
-0
+16
4
-0
+8
4
0
32
0
4
4
4
16
-0
-0
+64
4
-0
4
-0
-0
+8
4
0
+8
+4
+8
0
16
-0
+4
8
0
-0
+8
0
4
0
4
-0
4
4
4
-0
+4
+4
0
2
-0
-0
-0
+128
+4
+64
4
8
-0
+4
+4
4
4
0
-0
-0
+4
4
4
32
-0
-0
-0
64
-0
+64
+32
+64
+8
0
4
+4
0
-0
-0
-0
+8
+4
+16
16
-0
-0
128
-0
-0
-0
+128
+4
+16
+4
16
0
0
8
8
-0
-0
+4
+8
4
2
0
0
4
4
0
0
-0
-0
+4
+16
0
8
+4
0
0
0
-0
-0
-0
-0
-0
-0
4
+4
+32
+32
8
-0
+4
+8
+4
8
0
4
4
4
-0
+4
8
-0
-0
-0
-0
+4
+4
+16
+128
4
0
-0
+4
8
+4
0
-0
-0
-0
+4
0
0
0
4
-0
-0
+4
+128
+128
4
4
128
0
4
0
4
4
4
16
-0
-0
-0
+4
+64
+4
16
0
0
1
0
0
0
8
32
0
4
0
4
0
4
0
0
0
2
-0
-0
-0
-0
+4
+16
+8
+8
2
4
4
-0
+8
4
8
4
1
-0
-0
-0
-0
-0
+16
+8
+16
+16
+16
4
4
0
16
8
4
32
-0
+8
2
-0
-0
4
0
+4
+4
0
16
4
4
4
4
-0
-0
-0
+8
+4
+8
8
2
4
0
4
-0
16
-0
+16
+8
4
0
-0
-0
+64
+8
4
4
128
0
0
-0
+128
16
0
4
0
0
4
4
0
4
4
-0
-0
4
0
+4
+4
+4
0
+128
0
-0
-0
-0
+4
16
0
8
0
16
4
8
-0
+128
4
+16
+16
0
0
-0
-0
-0
+64
4
4
4
4
32
4
4
1
4
8
4
0
-0
+16
4
-0
+8
16
-0
+8
64
-0
+128
1
0
0
128
4
32
4
0
4
4
4
-0
+16
4
4
4
0
8
4
32
4
4
2
4
-0
+32
8
32
4
4
-0
+128
4
-0
-0
+64
+32
4
4
0
4
0
4
4
4
128
16
0
8
16
-0
+16
8
4
4
-0
4
-0
+4
+8
+8
8
-0
4
16
0
8
4
0
4
4
-0
4
-0
4
-0
-0
+4
+4
+4
8
8
-0
+8
+16
+4
4
-0
0
4
4
4
+8
0
-0
-0
+8
0
4
8
4
4
0
4
4
4
8
-0
+4
0
4
0
8
4
-0
+4
8
4
-0
-0
+4
+4
0
4
4
1
+4
0
-0
-0
+16
8
32
-0
+4
4
4
4
0
-0
+16
0
16
4
4
-0
+16
0
4
0
0
-0
+4
8
4
-0
-0
4
-0
+16
4
+128
4
4
-0
+4
+8
8
0
4
-0
-0
4
0
4
+4
+4
2
0
-0
+4
0
0
0
1
-0
+128
8
4
0
4
4
-0
-0
+16
+4
8
-0
+16
4
4
4
0
8
-0
-0
64
-0
4
+64
0
-0
+4
+8
+128
16
+8
0
+4
0
0
0
0
-0
-0
-0
+4
0
16
4
0
-0
+128
4
-0
+128
4
4
-0
+16
0
128
4
0
16
4
128
0
32
-0
+8
4
0
-0
-0
+32
+4
4
2
64
-0
+16
16
4
4
-0
+4
0
0
0
4
8
4
-0
+128
0
4
-0
+16
4
+64
0
0
+64
0
-0
-0
-0
+32
0
4
-0
+128
4
1
4
4
4
0
4
0
4
4
4
8
16
4
0
4
4
0
-0
+4
4
4
8
0
128
+128
+4
0
-0
-0
-0
-0
+16
+4
0
0
4
2
-0
+16
4
4
0
4
8
4
4
0
4
0
-0
+64
+4
4
-0
4
0
4
4
-0
+4
16
-0
+4
16
0
4
4
16
4
4
64
-0
-0
+8
+8
4
2
1
4
0
4
4
0
4
4
-0
+8
0
0
4
4
4
4
-0
+4
16
-0
+8
4
0
4
32
0
64
-0
4
4
-0
+4
+16
4
16
0
-0
+64
4
4
8
32
-0
+4
2
0
-0
+4
4
64
0
4
0
4
4
+4
0
0
-0
-0
-0
+16
+128
0
0
4
+4
0
-0
-0
+128
2
-0
-0
-0
4
0
0
+4
+8
0
4
+4
2
0
0
4
0
-0
+8
32
-0
+16
+8
8
0
-0
-0
+8
+4
4
-0
8
0
8
0
2
0
4
4
-0
-0
-0
+4
+128
+32
0
4
8
-0
-0
+8
+128
64
0
128
4
4
4
0
-0
+8
4
4
4
0
4
-0
+4
2
-0
+128
4
8
-0
-0
+128
+4
4
4
16
4
4
0
0
-0
+8
0
0
64
8
4
-0
+8
2
0
8
0
4
-0
+4
4
2
-0
+16
8
8
4
0
-0
+64
4
0
0
4
4
-0
-0
-0
+4
0
4
+128
+4
2
-0
-0
+8
+128
4
4
+4
+8
0
0
-0
-0
-0
-0
+128
+4
4
4
64
4
4
-0
+16
2
-0
4
4
4
-0
+4
+4
4
16
4
-0
-0
+4
+4
8
2
0
4
2
4
8
4
4
4
16
0
4
0
-0
-0
-0
+16
+4
+16
4
16
4
32
0
-0
+4
16
4
-0
+4
16
0
4
-0
+4
4
4
128
4
-0
+8
8
8
4
-0
+16
4
2
4
0
4
4
16
4
4
-0
-0
+4
+4
4
16
-0
+8
0
4
4
0
128
4
-0
+16
4
-0
+8
4
0
0
16
16
8
4
0
8
0
0
-0
+4
4
0
2
4
+4
0
-0
-0
+4
16
-0
+128
4
4
-0
+8
4
-0
+16
+4
+8
4
0
-0
-0
-0
+4
0
4
4
4
8
0
16
0
1
4
16
-0
-0
+4
0
0
4
-0
+4
+8
32
4
4
-0
+32
8
4
32
0
8
0
2
-0
+16
4
+16
0
-0
-0
+4
16
0
1
4
4
-0
+4
4
64
4
2
-0
+8
+4
+4
4
-0
-0
4
4
4
0
0
0
4
0
-0
-0
+16
+8
16
0
4
4
-0
+16
0
64
4
8
0
8
8
-0
-0
+128
+8
0
4
4
64
2
0
8
-0
+128
2
16
16
8
-0
+64
4
2
32
+4
0
0
+4
0
-0
-0
-0
+32
0
8
2
-0
+8
0
8
128
-0
-0
+16
+8
4
0
0
0
-0
-0
-0
+64
+32
+8
16
4
-0
+32
4
0
0
8
0
16
-0
+32
128
0
4
-0
+64
4
-0
+128
4
2
64
-0
-0
4
0
+4
16
16
-0
+16
+4
8
8
64
-0
+4
2
32
4
-0
+8
2
0
4
8
-0
+64
8
8
-0
-0
+16
+16
4
0
4
0
4
0
4
-0
-0
+8
+4
4
4
0
-0
+8
0
0
4
4
4
0
4
4
8
-0
-0
+4
+16
0
0
0
0
4
2
-0
+4
4
2
-0
+4
16
-0
-0
+128
+8
64
32
0
-0
+4
16
4
4
-0
+4
64
-0
+8
+16
16
-0
2
0
4
0
0
8
0
0
4
0
0
4
0
-0
+4
0
32
4
0
4
0
-0
+128
4
-0
+16
4
0
-0
+4
8
-0
-0
+16
+4
4
32
8
4
0
4
4
-0
-0
-0
-0
-0
+32
8
-0
+64
+8
+16
+8
+16
4
4
-0
+16
4
0
4
0
4
-0
-0
+4
+16
16
0
4
4
-0
-0
+16
+4
4
0
4
4
16
4
-0
+4
4
32
8
-0
-0
+4
+4
32
-0
+64
+4
4
-0
0
4
4
16
-0
-0
+16
+64
0
16
4
4
4
0
4
0
8
-0
+32
8
0
128
0
8
4
1
4
0
8
4
4
4
0
-0
+16
4
8
-0
+8
0
4
4
-0
-0
+4
+32
2
+32
0
-0
-0
-0
+16
+16
0
4
0
1
16
+8
0
+16
0
-0
-0
-0
-0
+8
+16
0
4
4
32
4
2
4
0
4
4
-0
-0
16
4
-0
-0
16
4
+4
0
16
-0
4
4
+16
0
4
+4
+16
+4
0
4
0
4
4
4
16
0
4
4
64
0
4
+64
+16
+8
0
-0
-0
-0
-0
+8
4
8
4
4
4
-0
-0
+4
+16
0
4
4
8
0
-0
+4
0
4
4
8
64
-0
+4
2
16
0
2
4
4
4
16
+16
0
-0
-0
+8
4
2
-0
+8
+4
4
-0
2
8
16
0
-0
+4
16
4
1
128
4
-0
+8
0
4
8
16
0
128
2
4
128
-0
+16
+8
8
-0
0
4
64
4
4
-0
+8
4
-0
+8
4
0
0
4
4
4
4
0
-0
-0
+8
+128
4
0
64
4
-0
+16
4
4
4
-0
-0
-0
-0
+4
+4
+8
+4
+16
16
-0
4
4
0
-0
+16
+4
4
0
-0
-0
-0
+32
+128
8
0
-0
+8
4
-0
+64
64
4
8
0
4
-0
+4
8
4
4
128
0
-0
-0
4
+16
4
4
4
-0
+4
+128
16
2
-0
+4
1
-0
+4
16
4
4
16
0
16
0
4
4
16
-0
+4
2
64
0
0
0
4
4
0
4
0
-0
4
-0
-0
+4
0
0
4
+8
+4
0
4
4
32
4
4
4
8
-0
+4
0
32
4
0
4
0
4
+16
0
-0
-0
+4
0
0
2
-0
+16
0
0
4
-0
-0
+16
+64
4
-0
+16
0
4
4
0
-0
+16
128
0
64
0
4
-0
+16
16
0
4
-0
+128
64
0
-0
+4
8
0
0
16
4
4
0
-0
-0
+128
+8
16
4
0
8
4
4
0
-0
-0
+8
+16
+16
+4
+4
16
-0
4
-0
4
-0
0
0
64
-0
+128
16
4
4
4
-0
+4
1
8
4
4
4
-0
-0
-0
+16
+4
+4
0
2
16
-0
+8
0
128
4
0
4
4
-0
+64
16
4
16
128
8
8
0
16
4
4
-0
+8
+4
4
-0
4
4
0
0
-0
-0
+64
+4
8
0
0
-0
4
4
-0
+4
+16
2
8
4
-0
+8
+4
4
-0
4
2
0
4
-0
8
-0
-0
+8
+4
+8
+4
+4
+128
4
-0
-0
-0
4
16
8
0
-0
-0
-0
+128
+16
+16
4
8
-0
-0
+4
0
0
4
4
4
-0
+4
+64
0
32
-0
+4
8
16
4
-0
+8
64
4
0
4
0
4
2
0
128
0
0
0
-0
+8
0
4
4
-0
4
-0
-0
+4
+4
+64
4
1
+128
+16
0
-0
-0
-0
+4
8
4
32
-0
+16
4
4
32
4
64
+4
0
0
0
0
-0
-0
-0
+8
+16
32
4
4
4
32
-0
+8
4
0
16
0
2
2
0
4
32
0
0
0
-0
+4
16
-0
+4
4
4
0
-0
+4
4
4
0
4
4
4
4
16
0
32
4
4
4
0
-0
+4
0
1
0
0
0
-0
-0
-0
+4
+4
+4
4
0
-0
-0
+4
+4
8
-0
+16
0
16
8
4
1
8
16
-0
+8
4
128
64
-0
+8
+4
4
-0
8
4
-0
+4
4
4
4
4
2
-0
+128
16
4
4
4
4
-0
+4
0
2
-0
-0
4
0
+4
+8
8
16
1
4
0
-0
+8
8
0
0
-0
+16
4
0
0
8
4
-0
-0
-0
+8
+4
+16
0
16
0
0
8
0
-0
+16
0
64
+8
+4
0
-0
-0
-0
-0
+4
+64
1
4
4
0
0
64
0
16
2
-0
+16
32
4
0
4
4
-0
+8
0
8
4
-0
+4
8
2
0
0
4
4
4
-0
+16
0
4
0
4
4
8
0
8
0
4
0
2
0
-0
-0
-0
4
0
-0
4
-0
+4
4
0
+4
0
4
4
4
-0
-0
-0
+4
+4
+4
4
0
+16
+4
+128
4
4
1
0
-0
-0
-0
-0
+128
+8
+16
+16
4
-0
+128
16
4
0
4
16
4
4
0
-0
+4
16
0
0
0
-0
-0
+128
+128
8
+16
0
-0
-0
+16
8
-0
+128
0
4
0
4
0
-0
+32
4
8
4
0
0
16
4
4
4
-0
+32
4
-0
-0
+64
+16
0
4
4
-0
-0
+32
+8
+4
+4
4
-0
-0
8
4
0
0
+8
0
-0
-0
-0
+128
+4
0
16
0
-0
+4
4
2
0
0
-0
-0
+64
+32
4
4
4
-0
4
+4
+128
0
-0
-0
+128
16
4
+16
0
-0
-0
-0
+4
+16
0
8
-0
+128
0
4
64
8
4
1
128
2
0
4
4
4
4
0
4
128
4
4
4
4
-0
-0
+8
0
4
-0
-0
-0
+4
0
8
+32
0
+8
+4
4
4
4
4
0
64
-0
+4
4
0
4
4
8
2
-0
-0
+32
+8
0
4
+128
+8
0
-0
-0
-0
-0
+128
+8
4
4
0
4
16
4
8
-0
+16
1
8
+4
0
0
+4
+8
+128
+4
0
-0
-0
-0
-0
-0
-0
+4
+16
16
-0
0
4
16
-0
-0
-0
+4
+16
+8
128
4
-0
+8
0
16
8
16
0
-0
-0
-0
+4
+8
+8
0
0
4
4
4
0
2
16
-0
4
4
-0
-0
-0
-0
+4
+4
0
16
+4
+4
+16
32
16
4
0
8
4
-0
+4
0
4
4
0
-0
-0
-0
+128
+4
+4
+4
4
-0
4
128
128
4
4
-0
+32
32
4
2
-0
+128
8
8
4
4
-0
+4
0
4
4
-0
+32
0
0
8
0
4
-0
+128
8
4
-0
+32
4
0
-0
+128
+16
+4
16
4
-0
-0
4
4
0
0
-0
-0
+16
+8
4
4
0
4
4
4
4
128
4
-0
-0
+8
+32
0
4
2
-0
+64
4
2
1
-0
+8
+4
+16
4
-0
-0
32
2
4
8
4
4
8
4
4
4
8
4
-0
+16
32
4
-0
+128
4
8
64
4
4
0
-0
+4
32
4
-0
+16
8
2
-0
+4
32
0
-0
+4
4
4
4
4
8
-0
-0
+64
+128
4
0
-0
+16
4
-0
-0
-0
+4
+8
+8
16
-0
+4
16
0
-0
+128
4
0
1
8
4
-0
-0
+32
+16
4
0
4
-0
-0
8
0
+8
+64
128
-0
+4
8
4
0
4
4
4
-0
+128
4
4
0
-0
+4
64
4
4
4
-0
+4
+8
+16
8
-0
-0
4
-0
-0
-0
-0
-0
-0
-0
+8
+128
+8
4
+128
+8
0
-0
+4
+4
+8
16
4
-0
4
4
-0
+4
+16
8
4
0
-0
+8
4
8
8
4
-0
+128
2
0
-0
-0
-0
+4
+4
+4
4
8
1
0
-0
+64
4
0
0
64
-0
+16
4
4
4
0
+4
0
0
-0
-0
+8
128
-0
-0
+128
+64
0
4
4
128
-0
+16
4
-0
-0
-0
-0
+16
+16
+16
+8
4
0
-0
-0
4
-0
+8
+4
4
-0
+4
+16
4
128
4
-0
+8
4
-0
-0
+32
+128
8
0
4
4
4
0
0
4
4
-0
+32
8
4
4
-0
+64
0
4
+32
0
-0
-0
+4
0
4
4
-0
+128
+4
4
-0
4
4
0
-0
-0
-0
+4
+16
+4
4
4
4
0
4
64
0
-0
+4
2
4
4
0
4
4
4
4
2
0
-0
+16
32
4
-0
4
4
-0
-0
+4
+4
+4
0
32
0
0
4
4
0
4
4
4
4
0
4
8
4
8
4
-0
+8
4
8
0
0
-0
-0
-0
+8
+16
+4
8
4
4
0
0
64
4
4
8
0
-0
-0
+4
+128
128
4
4
-0
+32
4
2
8
0
0
4
0
16
64
-0
-0
+4
+4
4
2
4
-0
+8
128
4
4
16
4
16
4
4
4
+128
0
-0
-0
+64
4
0
4
-0
+16
4
32
2
0
16
0
16
0
128
4
16
-0
+4
8
16
4
-0
+16
8
-0
+128
8
-0
+128
+4
+4
4
-0
-0
2
2
2
0
-0
+16
8
0
4
0
0
-0
+8
0
32
4
-0
+4
2
0
0
32
-0
+128
4
8
0
-0
+4
0
4
4
-0
-0
+8
+64
4
4
4
4
-0
+128
4
4
8
4
-0
+128
0
4
+32
+16
+4
0
-0
-0
-0
-0
+16
4
4
0
32
4
16
128
-0
+4
4
0
-0
+4
16
4
-0
+4
4
8
0
16
4
-0
-0
+8
+16
0
4
-0
+4
0
4
0
4
64
64
1
4
-0
+8
16
64
0
4
-0
-0
+128
+4
16
-0
-0
4
0
+4
+128
16
0
4
4
0
64
+128
0
-0
-0
+16
4
0
2
0
128
4
4
1
128
8
4
-0
4
-0
-0
-0
-0
4
+16
+4
+128
0
-0
+4
+128
+16
0
16
8
-0
-0
+8
+4
64
4
-0
+4
0
64
0
4
-0
+4
4
0
4
16
4
0
4
64
4
4
2
-0
-0
-0
4
0
+8
+4
0
0
-0
-0
+4
+128
+128
64
4
-0
+16
4
4
4
0
4
4
0
4
4
-0
-0
+4
+4
0
4
4
0
32
0
-0
+4
0
4
4
0
4
-0
+16
4
-0
+16
0
0
32
-0
+4
0
4
4
-0
+4
8
4
4
0
-0
+8
4
16
4
0
4
4
4
-0
+4
0
4
4
4
4
0
4
4
4
4
4
4
4
16
0
4
8
4
0
-0
-0
+4
+4
4
8
0
8
-0
+4
128
16
-0
+4
0
0
4
4
8
0
0
32
-0
4
4
-0
+4
+16
16
4
4
4
-0
+128
0
4
4
4
4
-0
+8
4
0
8
4
0
4
0
8
4
0
8
4
-0
+32
2
4
-0
+8
64
-0
-0
-0
+128
+16
+4
0
4
4
-0
-0
4
0
+4
0
+16
4
64
4
8
4
4
4
-0
-0
+16
+8
4
0
-0
-0
+16
+4
4
4
2
4
1
16
-0
+4
4
1
2
0
64
4
64
1
0
32
4
+64
+4
0
-0
-0
-0
+4
1
4
4
0
4
0
-0
+8
0
0
4
0
8
2
-0
+8
4
4
4
4
8
4
0
4
4
8
+4
+16
+128
0
-16
-0
-0
-0
-0
+8
0
4
+4
+16
16
-0
0
4
64
32
0
4
0
4
16
8
4
2
4
0
16
4
-0
-0
4
-0
+128
+4
+4
4
4
32
32
-0
-0
4
0
4
-0
-0
4
+4
+8
0
+4
+32
0
0
4
-0
+32
2
4
64
0
-0
+32
4
0
-0
-0
+4
+32
4
4
16
2
0
64
32
0
+16
0
-0
-0
+4
2
-0
+4
8
0
4
+4
0
0
-0
-0
+4
16
4
0
4
4
0
0
8
-0
4
-0
-0
4
0
-0
+16
+4
+4
+8
4
128
4
-0
+8
4
4
8
4
4
0
1
4
4
4
8
32
4
4
-0
-0
+16
+8
+8
8
-0
0
0
0
2
4
0
-0
-0
+16
+4
4
0
4
4
-0
-0
+128
+16
32
-0
-0
+128
+64
16
0
-0
+128
4
2
4
2
1
-0
-0
+8
+4
4
4
8
0
4
128
2
16
4
4
0
4
-0
-0
+4
+16
0
128
8
+32
0
-0
-0
+16
4
4
8
4
-0
-0
+128
+64
4
8
-0
+128
4
0
0
16
4
+4
0
-0
-0
-0
+4
+8
64
8
-0
+4
0
32
-0
+4
4
0
-0
+4
0
8
4
32
0
0
4
4
16
0
16
0
-0
-0
+4
+4
1
0
16
4
0
-0
+16
0
2
-0
+8
4
4
4
4
4
0
4
0
0
2
+8
0
-0
-0
+8
4
0
4
8
0
2
4
4
8
4
+4
0
0
-0
-0
+8
16
128
-0
+64
0
4
4
-0
+128
0
4
-0
+8
4
0
-0
+8
16
0
4
4
4
4
4
4
-0
+64
8
4
-0
+4
0
0
0
8
-0
+4
0
0
16
-0
+4
4
32
0
4
4
4
4
-0
+32
8
0
-0
+16
0
0
4
4
64
4
4
4
4
-0
+128
0
0
4
0
4
4
0
8
1
4
-0
-0
-0
8
+4
0
-0
-0
+8
0
4
-0
+4
+4
+4
+4
4
4
8
16
8
8
0
0
64
8
4
8
4
0
4
0
4
4
16
0
32
4
0
8
4
+8
+128
0
-0
-0
-0
+8
16
0
4
8
64
4
8
4
4
-0
+64
4
-0
+8
32
4
4
4
-0
+4
1
8
-0
+4
4
0
-0
+4
8
4
2
-0
+4
4
64
8
4
2
0
-0
+4
2
4
0
0
-0
-0
4
-0
+8
+4
+64
4
4
4
0
0
4
8
-0
+4
128
0
-0
-0
+64
+8
2
8
-0
+32
+4
4
4
-0
4
0
4
0
4
8
-0
-0
-0
+64
+128
+16
4
0
8
4
0
4
-0
+8
0
4
-0
+128
8
-0
+64
128
8
-0
+16
64
0
4
+8
0
0
-0
-0
+64
4
4
-0
+16
8
4
4
0
0
8
-0
+4
64
2
4
8
4
16
4
2
-0
8
-0
-0
+8
+8
+4
0
4
4
4
4
0
16
8
16
-0
-0
+4
+128
8
4
0
4
128
-0
-0
+8
+16
0
4
-0
+16
4
-0
+8
2
-0
+4
0
16
0
4
-0
-0
4
+16
4
-0
+4
+128
0
4
4
64
4
4
0
-0
+128
4
-0
+32
4
0
16
8
0
4
-0
-0
+8
+128
4
4
4
-0
+16
0
4
-0
-0
+32
+4
16
0
0
-0
+8
4
-0
+8
0
4
4
4
32
-0
+16
0
0
8
4
0
4
16
0
0
4
8
4
+4
0
0
-0
-0
+4
0
8
0
4
0
-0
+8
+4
4
4
-0
16
4
8
4
0
4
4
128
64
0
0
8
-0
-0
-0
32
-0
-0
-0
4
0
+32
0
0
0
+4
+4
0
+4
0
+128
0
+16
0
4
4
4
64
-0
+8
4
16
4
0
2
0
16
-0
+4
0
0
16
16
0
0
-0
+4
16
-0
+64
0
4
4
0
+64
0
-0
-0
+64
0
4
-0
-0
+4
+4
1
32
16
16
-0
+16
4
64
1
0
16
32
-0
+128
4
0
8
0
2
4
-0
-0
-0
4
0
-0
-0
+8
+4
+16
+4
+32
+4
4
4
-0
4
0
8
0
-0
+16
4
+32
0
-0
-0
+16
+4
4
-0
0
4
64
16
0
16
16
32
32
0
1
0
4
0
0
-0
4
-0
+4
+16
4
64
4
-0
+16
0
4
4
4
-0
+4
8
-0
-0
+64
+32
4
-0
-0
+64
+8
0
0
0
4
0
-0
+128
64
0
4
8
-0
-0
+32
4
4
-0
4
0
4
+16
+4
4
4
4
0
128
4
-0
4
-0
-0
+4
+32
+64
4
0
-0
+4
128
0
0
32
128
4
-0
-0
-0
+128
+8
+128
4
0
-0
-0
+128
+4
0
16
4
16
0
-0
+4
0
4
4
4
16
4
0
4
4
1
4
-0
+8
4
0
-0
+16
4
4
4
-0
4
+4
+8
0
-0
-0
+8
4
4
0
-0
-0
+16
+4
16
4
0
4
16
0
4
8
-0
+4
0
4
0
0
4
0
4
4
4
8
-0
-0
-0
+8
+4
+32
16
8
0
-0
+128
16
16
4
0
4
0
-0
+4
4
4
16
-0
+4
16
-0
+64
4
0
4
0
4
-0
-0
+4
+8
2
16
0
-0
-0
+4
+128
64
4
0
32
0
64
-0
4
-0
+4
+4
128
-0
-0
+4
+16
0
0
16
-0
+4
8
32
-0
+8
64
128
4
8
0
0
8
4
0
-0
+16
2
0
0
-0
+8
+4
4
-0
4
4
16
-0
+128
4
32
0
4
4
0
0
16
-0
+64
4
4
0
4
+128
0
-0
-0
+8
0
4
0
-0
+16
4
8
4
0
-0
-0
+8
+128
0
0
0
0
4
2
4
4
0
-0
+64
0
4
128
4
-0
+128
+4
+8
4
-0
-0
16
8
-0
+16
4
0
4
-0
-0
-0
+64
+4
+16
4
0
4
4
4
64
-0
+64
4
16
-0
+16
32
4
0
0
0
-0
+64
0
0
0
4
-0
-0
4
-0
+16
+4
+128
0
0
16
0
-0
+4
4
32
-0
+16
0
2
+8
0
0
-0
-0
-0
+4
+16
8
4
4
-0
+8
+4
4
-0
8
-0
-0
-0
-0
+16
+4
+128
+4
4
4
4
0
-0
+4
4
4
4
0
16
4
0
0
32
0
4
-0
+8
16
4
4
2
16
4
2
8
+16
0
-0
-0
-0
+4
+4
8
0
8
4
-0
-0
-0
+8
+64
+128
+4
4
4
-0
-0
-0
+4
+32
4
64
4
4
0
64
-0
+128
4
0
4
0
4
4
-0
+16
4
0
0
-0
4
-0
+4
+4
0
128
-0
+4
16
128
-0
4
-0
+4
+4
4
8
0
4
4
16
4
0
4
4
64
4
64
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 2:32 PM (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3798971
Default Alt Text
(63 KB)
Attached To
rHEJ HEJ
Event Timeline
Log In to Comment