Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7877717
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
71 KB
Subscribers
None
View Options
diff --git a/Changes-API.md b/Changes-API.md
index 50d28ee..9f1ad56 100644
--- a/Changes-API.md
+++ b/Changes-API.md
@@ -1,132 +1,133 @@
# Changelog for HEJ API
This log lists only changes on the HEJ API. These are primarily code changes
relevant for calling HEJ as an API. This file should only be read as an addition
to [`Changes.md`](Changes.md), where the main features are documented.
## Version 2.2
### 2.2.0
#### New and updated functions
* New functions to decide whether particles are massive, charged,
charged leptons, antiparticles.
* Added `to_string` function for `Event`.
* Updated function `Event::EventData.reconstruct_intermediate()`
- Now requires an `EWConstants` argument
- Added support for WpWp and WmWm events.
- In the case of WW same-flavour the reconstruction will minimise the total
off-shell momentum.
-* Renamed `no_2_jets` error flag to `not_enough_jets`.
+* Replaced `no_2_jets` and `bad_final_state` enumerators in `EventType` with
+ `invalid` and `unknown`.
* Added helper functions `is_backward_g_to_h`, `is_forward_g_to_h` to
detect incoming gluon to outgoing Higgs transitions.
* Updated function `implemented_types()` to now be in HEJ namespace.
## Version 2.1
### 2.1.0
#### Changes to Event class
* Restructured `Event` class
- `Event` can now only be build from a (new) `Event::EventData` class
- Removed default constructor for `Event`
- `Event::EventData` replaces the old `UnclusteredEvent` struct.
- `UnclusteredEvent` is now **deprecated**, and will be removed in version
2.2.0
- Removed `Event.unclustered()` function
- Added new member function `Events.parameters()`, to directly access
(underlying) `Parameters<EventParameters>`
- New member functions `begin_partons`, `end_partons` (`rbegin_partons`,
`rend_partons`) with aliases `cbegin_partons`, `cend_partons`
(`crbegin_partons`, `crend_partons`) for constant (reversed) iterators over
outgoing partons.
* New function `Event::EventData.reconstruct_intermediate()` to reconstruct
bosons from decays, e.g. `positron + nu_e => Wp`
* Added optional Colour charges to particles (`Particle.colour`)
- Colour connection in the HEJ limit can be generated via
`Event.generate_colours` (automatically done in the resummation)
- Colour configuration of input events can be checked with
`Event.is_leading_colour`
* Added function `Event.valid_hej_state` to check if event _could have_ been
produced by `HEJ` according to the `soft pt regulator` cut on the jets
#### New and updated functions
* Renamed `EventType::nonHEJ` to `EventType::non_resummable` and `is_HEJ()`
to `is_resummable()` such that run card is consistent with internal workings
* Made `MatrixElement.tree_kin(...)` and `MatrixElement.tree_param(...)` public
* New `EventReweighter` member function `treatment` to query the
treatment with respect to resummation for the various event types.
* Added auxiliary functions to obtain a `std::string` from `EventDescription`
(`to_string` for human readable, and `to_simple_string` for easy parsable
string)
* New `get_analyses` function to read in multiple `HEJ::Analysis` at once,
similar to `get_analysis`
* New `get_ew_parameters` function to extract electroweak parameters from
YAML configuration.
#### New classes
* New class `Unweighter` to do unweighting
* New class `CrossSectionAccumulator` to keep track of Cross Section of the
different subprocess
* New template struct `Parameters` similar to old `Weights`
- `Weights` are now an alias for `Parameters<double>`. Calling `Weights` did
not change
- `Weights.hh` was replaced by `Parameters.hh`. The old `Weights.hh` header
will be removed in version 2.2.0
* Function to multiplication and division of `EventParameters.weight` by double
- This can be combined with `Parameters`, e.g.
`Parameters<EventParameters>*Weights`, see also `Events.parameters()`
- Moved `EventParameters` to `Parameters.hh` header
* new class `EWConstants` replaces previously hard coded `vev`
- `EWConstants` have to be set in the general `Config` and the
`MatrixElementConfig`
#### Input/Output
* New abstract `EventReader` class, as base for reading events from files
- Moved LHE file reader to `HEJ::LesHouchesReader`
* New (optional) function `finish()` in abstract class `EventWriter`. `finish()`
is called _after_ all events are written.
* Support reading (`HDF5Reader`) and writing (`HDF5Writer`) `hdf5` files
* New `BufferedEventReader` class that allows to put events back into
the reader.
* New `SherpaLHEReader` to read Sherpa LHE files with correct weights
* `get_analysis` now requires `YAML::Node` and `LHEF::HEPRUP` as arguments
* Replaced `HepMCInterface` and `HepMCWriter` by `HepMCInterfaceX` and
`HepMCWriterX` respectively, with `X` being the major version of HepMC (2 or
3)
- Renamed `HepMCInterfaceX::init_kinematics` to `HepMCInterfaceX::init_event`
and protected it, use `HepMCInterfaceX::operator()` instead
- Removed redundant `HepMCInterfaceX::add_variation` function
#### Linking
* Export cmake target `HEJ::HEJ` to link directly against `libHEJ`
* Preprocessor flags (`HEJ_BUILD_WITH_XYZ`) for enabled/disabled dependencies
are now written to `ConfigFlags.hh`
* Provide links to version specific object files, e.g. `libHEJ.so ->
libHEJ.so.2.1 (soname) -> libHEJ.so.2.1.0`
* Removed `LHAPDF` from public interface
#### Miscellaneous
* Capitalisation of `Config.hh` now matches class `Config` (was `config.hh`)
* Renamed `Config::max_ext_soft_pt_fraction` to `Config::soft_pt_regulator`.
The new `Config::soft_pt_regulator` parameter is optional and the old
`Config::max_ext_soft_pt_fraction` is **deprecated**.
* Replaced redundant member `EventReweighterConfig::jet_param` with getter
function `EventReweighter.jet_param()` (`JetParameters` are already in
`PhaseSpacePointConfig`)
* Avoid storing reference to the Random Number Generator inside classes
- Constructors of `EventReweighter` now expect `std::shared_ptr<HEJ::RNG>`
(was reference)
- Moved reference to `HEJ::RNG` from constructor of `JetSplitter` to
`JetSplitter.split`
## Version 2.0
### 2.0.4
* Fixed wrong path of `HEJ_INCLUDE_DIR` in `hej-config.cmake`
### 2.0.0
* First release
diff --git a/include/HEJ/event_types.hh b/include/HEJ/event_types.hh
index 165a552..c62633a 100644
--- a/include/HEJ/event_types.hh
+++ b/include/HEJ/event_types.hh
@@ -1,119 +1,113 @@
/** \file
* \brief Define different types of events.
*
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#pragma once
#include <string>
#include "HEJ/exceptions.hh"
namespace HEJ {
//! Namespace for event types
namespace event_type {
//! Possible event types
enum EventType: std::size_t {
non_resummable = 0, //!< event configuration not covered by All Order resummation
- bad_final_state = 1, //!< event with an unsupported final state
- not_enough_jets = 2, //!< event with less than two jets
+ invalid = 1, //!< unphysical event, e.g. violating conservation laws
+ unknown = 2, //!< configuration not considered by HEJ, e.g di-Higgs
FKL = 4, //!< FKL-type event
unordered_backward = 8, //!< event with unordered backward emission
unordered_forward = 16, //!< event with unordered forward emission
extremal_qqbar_backward = 32, //!< event with a backward extremal qqbar
extremal_qqbar_forward = 64, //!< event with a forward extremal qqbar
central_qqbar = 128, //!< event with a central qqbar
unob = unordered_backward, //!< alias for unordered_backward
unof = unordered_forward, //!< alias for unordered_forward
qqbar_exb = extremal_qqbar_backward, //!< alias for extremal_qqbar_backward
qqbar_exf = extremal_qqbar_forward, //!< alias for extremal_qqbar_forward
qqbar_mid = central_qqbar, //!< alias for central_qqbar
- invalid = 256, //!< unphysical event, e.g. violating conservation laws
- unknown = 512, //!< configuration not considered by HEJ, e.g di-Higgs
first_type = non_resummable, //!< alias for numerically smallest enumerator
- last_type = unknown //!< alias for numerically largest enumerator
+ last_type = central_qqbar //!< alias for numerically largest enumerator
};
constexpr std::size_t UNO = unordered_backward | unordered_forward;
constexpr std::size_t EXTREMAL_QQBAR =
extremal_qqbar_backward | extremal_qqbar_forward;
constexpr std::size_t QQBAR =
EXTREMAL_QQBAR | central_qqbar;
constexpr auto NLL = UNO | QQBAR;
constexpr auto RESUMMABLE = FKL | NLL;
constexpr auto VALID = RESUMMABLE | non_resummable;
//! Event type names
/**
* For example, name(FKL) is the string "FKL"
*/
inline
std::string name(EventType type) {
switch(type) {
case FKL:
return "FKL";
case unordered_backward:
return "unordered backward";
case unordered_forward:
return "unordered forward";
case extremal_qqbar_backward:
return "extremal qqbar backward";
case extremal_qqbar_forward:
return "extremal qqbar forward";
case central_qqbar:
return "central qqbar";
case non_resummable:
return "non-resummable";
- case not_enough_jets:
- return "not enough jets";
- case bad_final_state:
- return "bad final state";
case invalid:
return "invalid";
case unknown:
return "unknown";
default:
throw std::logic_error{"Unreachable"};
}
}
//! Returns True for a HEJ \ref event_type::EventType "EventType"
inline
constexpr bool is_resummable(EventType type) {
return type & RESUMMABLE;
}
//! Returns True for an unordered \ref event_type::EventType "EventType"
inline
constexpr bool is_uno(EventType type) {
return type & UNO;
}
//! Returns True for an extremal_qqbar \ref event_type::EventType "EventType"
inline
constexpr bool is_ex_qqbar(EventType type) {
return type & EXTREMAL_QQBAR;
}
//! Returns True for an central_qqbar \ref event_type::EventType "EventType"
inline
constexpr bool is_mid_qqbar(EventType type) {
return type == central_qqbar;
}
//! Returns True for any qqbar event \ref event_type::EventType "EventType"
inline
constexpr bool is_qqbar(EventType type) {
return type & QQBAR;
}
} // namespace event_type
} // namespace HEJ
diff --git a/src/YAMLreader.cc b/src/YAMLreader.cc
index 5d301af..99f99b3 100644
--- a/src/YAMLreader.cc
+++ b/src/YAMLreader.cc
@@ -1,608 +1,606 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include "HEJ/YAMLreader.hh"
#include <algorithm>
#include <iostream>
#include <limits>
#include <map>
#include <string>
#include <unordered_map>
#include <vector>
#include <dlfcn.h>
#include "HEJ/ConfigFlags.hh"
#include "HEJ/Constants.hh"
#include "HEJ/ScaleFunction.hh"
#include "HEJ/event_types.hh"
#include "HEJ/output_formats.hh"
namespace HEJ {
class Event;
namespace {
//! Get YAML tree of supported options
/**
* The configuration file is checked against this tree of options
* in assert_all_options_known.
*/
YAML::Node const & get_supported_options(){
const static YAML::Node supported = [](){
YAML::Node supported;
static const auto opts = {
"trials", "min extparton pt", "max ext soft pt fraction",
"soft pt regulator",
"scales", "scale factors", "max scale ratio", "import scales",
"log correction", "event output", "analysis", "analyses", "vev",
"regulator parameter", "max events", "off-shell tolerance",
"require low pt jet"
};
// add subnodes to "supported" - the assigned value is irrelevant
for(auto && opt: opts) supported[opt] = "";
for(auto && jet_opt: {"min pt", "algorithm", "R"}){
supported["resummation jets"][jet_opt] = "";
supported["fixed order jets"][jet_opt] = "";
}
for(auto && opt: {"mt", "use impact factors", "include bottom", "mb"}){
supported["Higgs coupling"][opt] = "";
}
for(auto && opt: {"name", "seed"}){
supported["random generator"][opt] = "";
}
for(auto && opt: {"enabled", "nlo order"}){
supported["NLO truncation"][opt] = "";
}
for(
auto && opt: {
"FKL", "unordered", "extremal qqbar", "central qqbar", "non-resummable",
"unknown", "invalid"
}){
supported["event treatment"][opt] = "";
}
for(auto && particle_type: {"Higgs", "W", "Z"}){
for(auto && particle_opt: {"mass", "width"}){
supported["particle properties"][particle_type][particle_opt] = "";
}
}
for(auto && opt: {"type", "trials", "max deviation"}){
supported["unweight"][opt] = "";
}
return supported;
}();
return supported;
}
fastjet::JetAlgorithm to_JetAlgorithm(std::string const & algo){
using namespace fastjet;
static const std::map<std::string, fastjet::JetAlgorithm> known = {
{"kt", kt_algorithm},
{"cambridge", cambridge_algorithm},
{"antikt", antikt_algorithm},
{"cambridge for passive", cambridge_for_passive_algorithm},
{"plugin", plugin_algorithm}
};
const auto res = known.find(algo);
if(res == known.end()){
throw std::invalid_argument("Unknown jet algorithm \"" + algo + "\"");
}
return res->second;
}
EventTreatment to_EventTreatment(std::string const & name){
static const std::map<std::string, EventTreatment> known = {
{"reweight", EventTreatment::reweight},
{"keep", EventTreatment::keep},
{"discard", EventTreatment::discard},
{"abort", EventTreatment::abort}
};
const auto res = known.find(name);
if(res == known.end()){
throw std::invalid_argument("Unknown event treatment \"" + name + "\"");
}
return res->second;
}
WeightType to_weight_type(std::string const & setting){
if(setting == "weighted")
return WeightType::weighted;
if(setting =="resummation")
return WeightType::unweighted_resum;
if(setting =="partial")
return WeightType::partially_unweighted;
throw std::invalid_argument{"Unknown weight type \"" + setting + "\""};
}
} // namespace
namespace detail{
void set_from_yaml(fastjet::JetAlgorithm & setting, YAML::Node const & yaml){
setting = to_JetAlgorithm(yaml.as<std::string>());
}
void set_from_yaml(EventTreatment & setting, YAML::Node const & yaml){
setting = to_EventTreatment(yaml.as<std::string>());
}
void set_from_yaml(ParticleID & setting, YAML::Node const & yaml){
setting = to_ParticleID(yaml.as<std::string>());
}
void set_from_yaml(WeightType & setting, YAML::Node const & yaml){
setting = to_weight_type(yaml.as<std::string>());
}
} // namespace detail
JetParameters get_jet_parameters(
YAML::Node const & node,
std::string const & entry
){
assert(node);
JetParameters result;
fastjet::JetAlgorithm jet_algo = fastjet::antikt_algorithm;
double R = NAN;
set_from_yaml_if_defined(jet_algo, node, entry, "algorithm");
set_from_yaml(R, node, entry, "R");
result.def = fastjet::JetDefinition{jet_algo, R};
set_from_yaml(result.min_pt, node, entry, "min pt");
return result;
}
RNGConfig to_RNGConfig(
YAML::Node const & node,
std::string const & entry
){
assert(node);
RNGConfig result;
set_from_yaml(result.name, node, entry, "name");
set_from_yaml_if_defined(result.seed, node, entry, "seed");
return result;
}
NLOConfig to_NLOConfig(
YAML::Node const & node,
std::string const & entry
){
assert(node);
NLOConfig result;
set_from_yaml_if_defined(result.enabled, node, entry, "enabled");
set_from_yaml_if_defined(result.nj, node, entry, "nlo order");
return result;
}
ParticleProperties get_particle_properties(
YAML::Node const & node, std::string const & entry,
std::string const & boson
){
ParticleProperties result{};
set_from_yaml(result.mass, node, entry, boson, "mass");
set_from_yaml(result.width, node, entry, boson, "width");
return result;
}
EWConstants get_ew_parameters(YAML::Node const & node){
EWConstants result;
double vev = NAN;
set_from_yaml(vev, node, "vev");
result.set_vevWZH(vev,
get_particle_properties(node, "particle properties", "W"),
get_particle_properties(node, "particle properties", "Z"),
get_particle_properties(node, "particle properties", "Higgs")
);
return result;
}
HiggsCouplingSettings get_Higgs_coupling(
YAML::Node const & node,
std::string const & entry
){
assert(node);
static constexpr double mt_max = 2e4;
#ifndef HEJ_BUILD_WITH_QCDLOOP
if(node[entry].IsDefined()){
throw std::invalid_argument{
"Higgs coupling settings require building HEJ 2 "
"with QCDloop support"
};
}
#endif
HiggsCouplingSettings settings;
set_from_yaml_if_defined(settings.mt, node, entry, "mt");
set_from_yaml_if_defined(settings.mb, node, entry, "mb");
set_from_yaml_if_defined(settings.include_bottom, node, entry, "include bottom");
set_from_yaml_if_defined(settings.use_impact_factors, node, entry, "use impact factors");
if(settings.use_impact_factors){
if(settings.mt != std::numeric_limits<double>::infinity()){
throw std::invalid_argument{
"Conflicting settings: "
"impact factors may only be used in the infinite top mass limit"
};
}
}
else{
// huge values of the top mass are numerically unstable
settings.mt = std::min(settings.mt, mt_max);
}
return settings;
}
FileFormat to_FileFormat(std::string const & name){
static const std::map<std::string, FileFormat> known = {
{"Les Houches", FileFormat::Les_Houches},
{"HepMC", FileFormat::HepMC},
{"HepMC2", FileFormat::HepMC2},
{"HepMC3", FileFormat::HepMC3},
{"HDF5", FileFormat::HDF5}
};
const auto res = known.find(name);
if(res == known.end()){
throw std::invalid_argument("Unknown file format \"" + name + "\"");
}
return res->second;
}
std::string extract_suffix(std::string const & filename){
size_t separator = filename.rfind('.');
if(separator == std::string::npos) return {};
return filename.substr(separator + 1);
}
FileFormat format_from_suffix(std::string const & filename){
const std::string suffix = extract_suffix(filename);
if(suffix == "lhe") return FileFormat::Les_Houches;
if(suffix == "hepmc") return FileFormat::HepMC;
if(suffix == "hepmc3") return FileFormat::HepMC3;
if(suffix == "hepmc2") return FileFormat::HepMC2;
if(suffix == "hdf5") return FileFormat::HDF5;
throw std::invalid_argument{
"Can't determine format for output file \"" + filename + "\""
};
}
void assert_all_options_known(
YAML::Node const & conf, YAML::Node const & supported
){
if(!conf.IsMap()) return;
if(!supported.IsMap()) throw invalid_type{"must not have sub-entries"};
for(auto const & entry: conf){
const auto name = entry.first.as<std::string>();
if(! supported[name]) throw unknown_option{name};
/* check sub-options, e.g. 'resummation jets: min pt'
* we don't check analyses sub-options
* those depend on the analysis being used and should be checked there
* similar for "import scales"
*/
if(name != "analyses" && name != "analysis" && name != "import scales"){
try{
assert_all_options_known(conf[name], supported[name]);
}
catch(unknown_option const & ex){
throw unknown_option{name + ": " + ex.what()};
}
catch(invalid_type const & ex){
throw invalid_type{name + ": " + ex.what()};
}
}
}
}
} // namespace HEJ
namespace YAML {
Node convert<HEJ::OutputFile>::encode(HEJ::OutputFile const & outfile) {
Node node;
node[to_string(outfile.format)] = outfile.name;
return node;
}
bool convert<HEJ::OutputFile>::decode(Node const & node, HEJ::OutputFile & out) {
switch(node.Type()){
case NodeType::Map: {
YAML::const_iterator it = node.begin();
out.format = HEJ::to_FileFormat(it->first.as<std::string>());
out.name = it->second.as<std::string>();
return true;
}
case NodeType::Scalar:
out.name = node.as<std::string>();
out.format = HEJ::format_from_suffix(out.name);
return true;
default:
return false;
}
}
} // namespace YAML
namespace HEJ {
namespace detail{
void set_from_yaml(OutputFile & setting, YAML::Node const & yaml){
setting = yaml.as<OutputFile>();
}
}
namespace {
void update_fixed_order_jet_parameters(
JetParameters & fixed_order_jets, YAML::Node const & yaml
){
if(!yaml["fixed order jets"]) return;
set_from_yaml_if_defined(
fixed_order_jets.min_pt, yaml, "fixed order jets", "min pt"
);
fastjet::JetAlgorithm algo = fixed_order_jets.def.jet_algorithm();
set_from_yaml_if_defined(algo, yaml, "fixed order jets", "algorithm");
double R = fixed_order_jets.def.R();
set_from_yaml_if_defined(R, yaml, "fixed order jets", "R");
fixed_order_jets.def = fastjet::JetDefinition{algo, R};
}
// like std::stod, but throw if not the whole string can be converted
double to_double(std::string const & str){
std::size_t pos = 0;
const double result = std::stod(str, &pos);
if(pos < str.size()){
throw std::invalid_argument(str + " is not a valid double value");
}
return result;
}
using EventScale = double (*)(Event const &);
void import_scale_functions(
std::string const & file,
std::vector<std::string> const & scale_names,
std::unordered_map<std::string, EventScale> & known
) {
void * handle = dlopen(file.c_str(), RTLD_NOW);
char * error = dlerror();
if(error != nullptr) throw std::runtime_error{error};
for(auto const & scale: scale_names) {
void * sym = dlsym(handle, scale.c_str());
error = dlerror();
if(error != nullptr) throw std::runtime_error{error};
known.emplace(scale, reinterpret_cast<EventScale>(sym)); // NOLINT
}
}
auto get_scale_map(
YAML::Node const & yaml
) {
std::unordered_map<std::string, EventScale> scale_map;
scale_map.emplace("H_T", H_T);
scale_map.emplace("max jet pperp", max_jet_pt);
scale_map.emplace("jet invariant mass", jet_invariant_mass);
scale_map.emplace("m_j1j2", m_j1j2);
if(yaml["import scales"].IsDefined()) {
if(! yaml["import scales"].IsMap()) {
throw invalid_type{"Entry 'import scales' is not a map"};
}
for(auto const & import: yaml["import scales"]) {
const auto file = import.first.as<std::string>();
const auto scale_names =
import.second.IsSequence()
?import.second.as<std::vector<std::string>>()
:std::vector<std::string>{import.second.as<std::string>()};
import_scale_functions(file, scale_names, scale_map);
}
}
return scale_map;
}
// simple (as in non-composite) scale functions
/**
* An example for a simple scale function would be H_T,
* H_T/2 is then composite (take H_T and then divide by 2)
*/
ScaleFunction parse_simple_ScaleFunction(
std::string const & scale_fun,
std::unordered_map<std::string, EventScale> const & known
) {
assert(
scale_fun.empty() ||
(!std::isspace(scale_fun.front()) && !std::isspace(scale_fun.back()))
);
const auto it = known.find(scale_fun);
if(it != end(known)) return {it->first, it->second};
try{
const double scale = to_double(scale_fun);
return {scale_fun, FixedScale{scale}};
} catch(std::invalid_argument const &){}
throw std::invalid_argument{"Unknown scale choice: \"" + scale_fun + "\""};
}
std::string trim_front(std::string const & str){
const auto new_begin = std::find_if(
begin(str), end(str), [](char c){ return std::isspace(c) == 0; }
);
return std::string(new_begin, end(str));
}
std::string trim_back(std::string str){
size_t pos = str.size() - 1;
// use guaranteed wrap-around behaviour to check whether we have
// traversed the whole string
for(; pos < str.size() && std::isspace(str[pos]); --pos) {}
str.resize(pos + 1); // note that pos + 1 can be 0
return str;
}
ScaleFunction parse_ScaleFunction(
std::string const & scale_fun,
std::unordered_map<std::string, EventScale> const & known
){
assert(
scale_fun.empty() ||
(!std::isspace(scale_fun.front()) && !std::isspace(scale_fun.back()))
);
// parse from right to left => a/b/c gives (a/b)/c
const size_t delim = scale_fun.find_last_of("*/");
if(delim == std::string::npos){
return parse_simple_ScaleFunction(scale_fun, known);
}
const std::string first = trim_back(std::string{scale_fun, 0, delim});
const std::string second = trim_front(std::string{scale_fun, delim+1});
if(scale_fun[delim] == '/'){
return parse_ScaleFunction(first, known)
/ parse_ScaleFunction(second, known);
}
assert(scale_fun[delim] == '*');
return parse_ScaleFunction(first, known)
* parse_ScaleFunction(second, known);
}
EventTreatMap get_event_treatment(
YAML::Node const & node, std::string const & entry
){
using namespace event_type;
EventTreatMap treat {
- {not_enough_jets, EventTreatment::discard},
- {bad_final_state, EventTreatment::discard},
{FKL, EventTreatment::discard},
{unob, EventTreatment::discard},
{unof, EventTreatment::discard},
{qqbar_exb, EventTreatment::discard},
{qqbar_exf, EventTreatment::discard},
{qqbar_mid, EventTreatment::discard},
{non_resummable, EventTreatment::discard},
{unknown, EventTreatment::abort},
{invalid, EventTreatment::abort}
};
set_from_yaml(treat.at(FKL), node, entry, "FKL");
set_from_yaml(treat.at(unob), node, entry, "unordered");
treat.at(unof) = treat.at(unob);
set_from_yaml(treat.at(qqbar_exb), node, entry, "extremal qqbar");
treat.at(qqbar_exf) = treat.at(qqbar_exb);
set_from_yaml(treat.at(qqbar_mid), node, entry, "central qqbar");
set_from_yaml(treat.at(non_resummable), node, entry, "non-resummable");
set_from_yaml(treat.at(unknown), node, entry, "unknown");
set_from_yaml(treat.at(invalid), node, entry, "invalid");
if(treat[non_resummable] == EventTreatment::reweight){
throw std::invalid_argument{"Cannot reweight non-resummable events"};
}
return treat;
}
Config to_Config(YAML::Node const & yaml){
try{
assert_all_options_known(yaml, get_supported_options());
}
catch(unknown_option const & ex){
throw unknown_option{std::string{"Unknown option '"} + ex.what() + "'"};
}
Config config;
config.resummation_jets = get_jet_parameters(yaml, "resummation jets");
config.fixed_order_jets = config.resummation_jets;
update_fixed_order_jet_parameters(config.fixed_order_jets, yaml);
set_from_yaml_if_defined(config.min_extparton_pt, yaml, "min extparton pt");
if(config.min_extparton_pt!=0)
std::cerr << "WARNING: \"min extparton pt\" is deprecated."
<< " Please remove this entry or set \"soft pt regulator\" instead.\n";
set_from_yaml_if_defined(
config.max_ext_soft_pt_fraction, yaml, "max ext soft pt fraction"
);
if(config.max_ext_soft_pt_fraction){
std::cerr << "WARNING: \"max ext soft pt fraction\" is deprecated."
<< " Please remove this entry or set \"soft pt regulator\" instead.\n";
config.soft_pt_regulator = *config.max_ext_soft_pt_fraction;
} else {
set_from_yaml_if_defined(
config.soft_pt_regulator, yaml, "soft pt regulator"
);
}
// Sets the standard value, then changes this if defined
config.regulator_lambda=CLAMBDA;
set_from_yaml_if_defined(config.regulator_lambda, yaml, "regulator parameter");
set_from_yaml_if_defined(config.max_events, yaml, "max events");
set_from_yaml(config.trials, yaml, "trials");
config.weight_type = WeightType::weighted;
set_from_yaml_if_defined(config.weight_type, yaml, "unweight", "type");
if(config.weight_type == WeightType::partially_unweighted) {
config.unweight_config = PartialUnweightConfig{};
set_from_yaml(
config.unweight_config->trials, yaml,
"unweight", "trials"
);
set_from_yaml(
config.unweight_config->max_dev, yaml,
"unweight", "max deviation"
);
}
else if(yaml["unweight"].IsDefined()) {
for(auto && opt: {"trials", "max deviation"}) {
if(yaml["unweight"][opt].IsDefined()) {
throw std::invalid_argument{
"'unweight: " + std::string{opt} + "' "
"is only supported if 'unweight: type' is set to 'partial'"
};
}
}
}
set_from_yaml(config.log_correction, yaml, "log correction");
config.treat = get_event_treatment(yaml, "event treatment");
set_from_yaml_if_defined(config.output, yaml, "event output");
config.rng = to_RNGConfig(yaml, "random generator");
set_from_yaml_if_defined(config.lowpt, yaml, "require low pt jet");
set_from_yaml_if_defined(config.analyses_parameters, yaml, "analyses");
if(yaml["analysis"].IsDefined()){
std::cerr <<
"WARNING: Configuration entry 'analysis' is deprecated. "
" Use 'analyses' instead.\n";
set_from_yaml(config.analysis_parameters, yaml, "analysis");
if(!config.analysis_parameters.IsNull()){
config.analyses_parameters.push_back(config.analysis_parameters);
}
}
config.scales = to_ScaleConfig(yaml);
config.ew_parameters = get_ew_parameters(yaml);
config.Higgs_coupling = get_Higgs_coupling(yaml, "Higgs coupling");
//HEJ@NLO Truncation
config.nlo = to_NLOConfig(yaml, "NLO truncation");
set_from_yaml_if_defined(
config.off_shell_tolerance,
yaml,
"off-shell tolerance"
);
return config;
}
} // namespace
ScaleConfig to_ScaleConfig(YAML::Node const & yaml){
ScaleConfig config;
auto scale_funs = get_scale_map(yaml);
std::vector<std::string> scales;
set_from_yaml(scales, yaml, "scales");
config.base.reserve(scales.size());
std::transform(
begin(scales), end(scales), std::back_inserter(config.base),
[scale_funs](auto const & entry){
return parse_ScaleFunction(entry, scale_funs);
}
);
set_from_yaml_if_defined(config.factors, yaml, "scale factors");
config.max_ratio = std::numeric_limits<double>::infinity();
set_from_yaml_if_defined(config.max_ratio, yaml, "max scale ratio");
return config;
}
Config load_config(std::string const & config_file){
try{
return to_Config(YAML::LoadFile(config_file));
}
catch(...){
std::cerr << "Error reading " << config_file << ":\n ";
throw;
}
}
} // namespace HEJ
diff --git a/t/check_res.cc b/t/check_res.cc
index b01e9db..6445d36 100644
--- a/t/check_res.cc
+++ b/t/check_res.cc
@@ -1,153 +1,151 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include "hej_test.hh"
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <memory>
#include <string>
#include <utility>
#include "HEJ/Config.hh"
#include "HEJ/CrossSectionAccumulator.hh"
#include "HEJ/Event.hh"
#include "HEJ/event_types.hh"
#include "HEJ/EventReweighter.hh"
#include "HEJ/EWConstants.hh"
#include "HEJ/Fraction.hh"
#include "HEJ/HiggsCouplingSettings.hh"
#include "HEJ/make_RNG.hh"
#include "HEJ/Mixmax.hh"
#include "HEJ/Parameters.hh"
#include "HEJ/ScaleFunction.hh"
#include "HEJ/EventReader.hh"
#include "HEJ/YAMLreader.hh"
#include "fastjet/JetDefinition.hh"
#include "LHEF/LHEF.h"
namespace HEJ { struct RNG; }
namespace {
using EventTreatment = HEJ::EventTreatment;
using namespace HEJ::event_type;
HEJ::EventTreatMap TREAT{
- {not_enough_jets, EventTreatment::discard},
- {bad_final_state, EventTreatment::discard},
{non_resummable, EventTreatment::discard},
{unof, EventTreatment::discard},
{unob, EventTreatment::discard},
{qqbar_exb, EventTreatment::discard},
{qqbar_exf, EventTreatment::discard},
{qqbar_mid, EventTreatment::discard},
{FKL, EventTreatment::reweight}
};
bool correct_colour(HEJ::Event const & ev){
if(!HEJ::event_type::is_resummable(ev.type()))
return true;
return ev.is_leading_colour();
}
} // namespace
int main(int argn, char** argv) {
if(argn == 6 && std::string(argv[5]) == "unof"){
--argn;
TREAT[unof] = EventTreatment::reweight;
TREAT[unob] = EventTreatment::discard;
TREAT[FKL] = EventTreatment::discard;
}
else if(argn == 6 && std::string(argv[5]) == "unob"){
--argn;
TREAT[unof] = EventTreatment::discard;
TREAT[unob] = EventTreatment::reweight;
TREAT[FKL] = EventTreatment::discard;
}
else if(argn == 6 && std::string(argv[5]) == "splitf"){
--argn;
TREAT[qqbar_exb] = EventTreatment::discard;
TREAT[qqbar_exf] = EventTreatment::reweight;
TREAT[FKL] = EventTreatment::discard;
}
else if(argn == 6 && std::string(argv[5]) == "splitb"){
--argn;
TREAT[qqbar_exb] = EventTreatment::reweight;
TREAT[qqbar_exf] = EventTreatment::discard;
TREAT[FKL] = EventTreatment::discard;
}
else if(argn == 6 && std::string(argv[5]) == "qqbar_mid"){
--argn;
TREAT[qqbar_mid] = EventTreatment::reweight;
TREAT[FKL] = EventTreatment::discard;
}
if(argn != 5){
std::cerr << "Usage: check_res yaml eventfile xsection tolerance [uno] \n";
return EXIT_FAILURE;
}
HEJ::Config config = HEJ::load_config(argv[1]);
auto reader = HEJ::make_reader(argv[2]);
const double xsec_ref = std::stod(argv[3]);
const double tolerance = std::stod(argv[4]);
reader->read_event();
HEJ::EventReweighterConfig conf = HEJ::to_EventReweighterConfig(config);
conf.treat = TREAT;
HEJ::MatrixElementConfig ME_conf = HEJ::to_MatrixElementConfig(config);
HEJ::PhaseSpacePointConfig psp_conf = HEJ::to_PhaseSpacePointConfig(config);
const fastjet::JetDefinition BORN_JET_DEF = config.fixed_order_jets.def;
const double BORN_JETPTMIN = config.fixed_order_jets.min_pt;
const int NUM_TRIES = config.trials;
HEJ::ScaleGenerator scale_gen{
config.scales.base,
config.scales.factors,
config.scales.max_ratio
};
std::shared_ptr<HEJ::RNG> ran{
HEJ::make_RNG(config.rng.name,config.rng.seed)
};
HEJ::EventReweighter hej{reader->heprup(), std::move(scale_gen), conf, ran};
HEJ::CrossSectionAccumulator xs;
do{
auto ev_data = HEJ::Event::EventData{reader->hepeup()};
shuffle_particles(ev_data);
ev_data.reconstruct_intermediate(ME_conf.ew_parameters);
HEJ::Event ev{
ev_data.cluster(
BORN_JET_DEF, BORN_JETPTMIN
)
};
auto resummed_events = hej.reweight(ev, NUM_TRIES);
for(auto const & res_ev: resummed_events) {
ASSERT(correct_colour(res_ev));
ASSERT(std::isfinite(res_ev.central().weight));
// we fill the xs uncorrelated since we only want to test the uncertainty
// of the resummation
xs.fill(res_ev);
}
} while(reader->read_event());
const double xsec = xs.total().value;
const double xsec_err = std::sqrt(xs.total().error);
const double significance =
std::abs(xsec - xsec_ref) / std::sqrt( xsec_err*xsec_err + tolerance*tolerance );
std::cout << xsec_ref << " +/- " << tolerance << " ~ "
<< xsec << " +- " << xsec_err << " => " << significance << " sigma\n";
if(significance > 3.){
std::cerr << "Cross section is off by over 3 sigma!\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/t/classify_ref_4j b/t/classify_ref_4j
index 98687cd..7f5a5f2 100644
--- a/t/classify_ref_4j
+++ b/t/classify_ref_4j
@@ -1,3255 +1,3255 @@
4
4
0
4
4
8
4
4
4
16
4
32
0
4
4
0
4
4
128
4
4
4
4
4
4
4
0
4
64
4
4
8
4
64
4
4
-512
+2
8
4
-512
+2
4
4
4
4
4
4
4
8
4
4
4
4
4
-512
+2
4
4
4
16
128
4
4
4
4
4
4
64
4
4
64
4
4
4
4
4
4
0
8
32
0
4
4
64
-512
+2
4
4
4
64
4
0
4
4
4
128
4
4
0
16
8
4
4
4
4
4
4
4
4
4
-512
+2
4
32
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
64
4
4
4
32
4
4
4
-512
+2
4
4
4
4
0
4
8
4
16
4
4
32
8
4
4
-512
+2
4
-512
+2
4
4
64
4
64
4
4
4
4
4
8
4
128
4
128
4
4
-512
+2
4
64
-512
-512
+2
+2
8
4
4
128
4
4
8
4
4
16
8
0
4
128
4
4
4
4
0
4
4
4
4
0
4
4
4
-512
+2
0
4
4
4
4
4
4
4
4
4
4
4
4
-512
+2
8
4
4
4
4
4
4
4
128
4
64
4
8
4
4
64
0
128
4
16
4
4
4
4
32
4
4
4
4
4
4
4
4
4
4
32
4
4
128
4
64
4
8
4
4
4
4
0
4
8
4
8
4
4
4
4
4
4
4
4
128
0
4
4
32
4
4
4
4
4
16
4
4
4
-512
+2
0
64
4
4
4
4
0
64
8
4
4
4
4
4
32
4
4
4
16
64
4
4
16
4
4
32
4
4
16
4
-512
+2
4
4
64
4
4
4
0
0
4
4
4
4
4
4
-512
+2
4
4
0
0
4
4
4
64
4
4
32
4
4
4
4
4
0
4
16
0
4
4
4
4
0
4
64
4
4
4
-512
+2
16
-512
+2
4
128
32
4
0
4
4
4
4
0
4
4
4
4
4
-512
+2
0
4
4
16
4
4
64
4
4
4
4
4
4
4
4
4
4
4
4
0
4
4
16
0
4
4
128
4
4
64
-512
+2
4
64
4
4
32
4
4
4
4
-512
+2
0
4
16
8
8
4
4
0
4
4
-512
+2
4
4
4
4
4
4
4
4
4
32
4
4
4
-512
+2
128
4
4
4
4
4
4
8
4
4
4
4
128
4
4
32
8
4
4
4
4
4
-512
+2
16
0
4
4
-512
+2
4
4
4
4
4
-512
+2
0
4
4
8
4
64
4
4
-512
+2
4
4
4
4
4
4
4
0
4
4
0
4
8
4
4
4
0
64
16
4
4
4
0
4
4
4
4
4
4
4
4
4
4
4
4
16
4
4
4
4
4
4
4
4
4
-512
+2
4
4
4
16
64
4
128
16
-512
+2
4
4
4
64
4
0
4
4
64
0
4
4
4
4
4
4
4
4
4
4
4
4
4
4
32
4
0
64
4
0
4
4
4
4
4
4
-512
+2
4
4
4
4
4
4
4
4
32
8
4
0
4
32
128
4
-512
+2
4
4
64
4
4
4
4
128
16
4
4
4
4
128
-512
+2
8
4
4
4
64
4
4
4
0
4
4
4
4
0
4
4
4
4
4
8
64
4
32
4
128
-512
+2
4
4
0
4
4
-512
+2
0
0
4
4
4
64
4
4
4
128
-512
+2
4
4
128
4
8
0
4
4
4
-512
+2
4
32
0
4
4
4
4
4
-512
+2
4
4
0
4
0
64
32
0
4
4
4
4
-512
-512
+2
+2
4
4
4
4
32
4
0
4
4
0
4
4
4
4
4
8
4
-512
+2
4
4
4
8
4
-512
+2
4
4
4
0
0
4
4
4
4
4
4
4
4
4
4
4
64
4
4
4
4
4
4
-512
-512
-512
+2
+2
+2
4
4
4
4
4
4
4
4
0
0
4
4
4
4
8
4
8
4
0
8
64
4
4
4
-512
-512
+2
+2
4
-512
+2
4
32
4
4
4
4
0
4
-512
+2
0
4
0
4
0
4
4
4
4
0
4
4
4
0
4
4
4
64
128
4
4
4
4
4
4
4
4
64
4
8
4
0
4
-512
+2
4
4
16
4
-512
+2
4
128
-512
+2
8
4
4
0
4
4
4
4
4
4
4
4
4
4
32
4
4
4
4
4
0
4
4
0
32
4
-512
+2
4
4
4
4
-512
+2
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
8
4
4
4
4
4
4
4
128
4
64
4
128
-512
+2
128
16
4
128
0
4
4
4
4
4
4
16
4
0
-512
+2
4
4
4
4
4
4
4
4
4
64
4
16
4
4
4
32
-512
-512
+2
+2
4
32
8
4
4
4
4
4
4
4
4
4
64
4
64
32
4
4
4
32
4
0
4
4
8
4
4
4
4
4
-512
+2
4
0
-512
+2
4
4
-512
+2
4
4
0
4
128
4
4
4
4
4
16
64
4
0
4
4
4
4
-512
+2
4
4
4
4
4
0
4
4
128
4
-512
+2
0
4
4
4
0
4
4
4
4
4
4
4
4
32
4
4
4
4
4
128
128
0
4
4
4
4
128
32
4
4
4
4
64
4
4
4
4
128
0
4
4
4
8
4
4
128
4
4
64
4
4
4
0
4
-512
+2
4
4
4
4
4
4
4
4
4
32
4
-512
+2
32
4
4
16
4
4
4
128
128
4
4
4
4
4
4
4
128
4
32
4
64
4
4
4
0
4
16
4
4
-512
+2
4
4
4
4
4
4
128
4
4
4
4
4
4
4
64
32
4
4
-512
+2
4
-512
+2
16
4
-512
+2
4
4
8
16
4
4
4
4
4
128
4
4
16
0
4
4
0
4
128
4
4
4
4
4
4
4
0
4
4
4
4
64
4
4
4
4
4
4
4
4
4
4
4
8
4
-512
+2
4
4
4
4
4
4
4
4
4
-512
+2
4
16
8
4
-512
+2
4
0
4
4
8
4
4
4
4
0
4
16
32
4
16
4
0
4
4
4
4
4
4
128
4
4
4
4
0
4
0
4
4
128
-512
+2
0
4
4
4
4
4
64
4
4
4
0
4
4
4
4
4
4
4
8
4
4
4
-512
+2
8
4
4
4
4
4
4
4
4
128
4
4
4
4
-512
+2
16
32
-512
+2
4
4
-512
+2
32
32
4
4
4
-512
+2
4
64
4
128
64
0
4
4
4
-512
+2
4
4
4
32
4
4
0
4
4
4
4
32
4
4
4
4
4
4
0
64
4
4
4
4
64
0
4
4
0
4
4
4
4
4
-512
+2
4
4
0
128
4
4
0
4
16
0
4
16
4
4
0
4
4
128
-512
+2
4
4
4
4
4
4
128
4
4
8
4
4
0
4
4
4
4
4
8
8
64
16
4
4
4
4
4
16
16
-512
+2
128
4
4
4
4
4
16
16
4
64
4
4
4
64
128
-512
+2
8
4
4
-512
+2
4
4
0
4
4
4
4
4
4
4
-512
+2
32
0
4
4
4
-512
+2
128
4
4
4
4
4
4
4
4
4
4
4
4
64
128
4
4
4
-512
+2
4
4
4
4
8
4
4
4
4
0
4
8
4
4
4
4
4
32
4
0
4
4
4
4
4
64
4
4
4
-512
+2
0
4
0
4
128
4
4
4
4
4
4
16
4
4
4
8
4
-512
+2
4
4
4
4
-512
+2
4
4
0
4
4
4
32
0
4
4
4
4
4
4
4
4
8
4
64
4
4
4
4
4
0
4
32
32
4
4
4
8
4
4
4
4
4
4
64
4
4
0
4
-512
+2
32
-512
+2
8
4
4
4
4
32
-512
+2
4
4
4
-512
+2
4
4
-512
-512
+2
+2
4
4
4
4
4
128
4
4
4
0
32
4
4
4
4
-512
+2
4
-512
+2
4
-512
+2
4
4
4
-512
+2
4
4
-512
+2
4
4
8
4
4
8
4
-512
+2
4
4
16
128
4
4
4
4
-512
+2
4
-512
+2
4
4
4
4
4
4
16
4
4
4
4
-512
+2
64
4
4
4
-512
+2
0
4
16
4
4
4
4
4
4
4
4
4
4
4
4
4
64
4
4
4
4
4
4
0
-512
+2
4
0
4
4
4
4
4
4
4
0
4
-512
+2
64
4
4
8
-512
+2
32
4
4
4
16
4
4
4
4
4
4
0
64
64
4
4
4
16
4
4
0
4
4
4
-512
+2
8
4
4
4
4
4
4
4
0
4
4
4
4
4
4
4
0
4
16
32
4
4
4
4
128
4
4
4
4
128
4
128
32
4
64
0
4
16
16
4
4
0
4
4
4
4
-512
+2
4
128
0
4
4
4
4
8
4
128
4
4
4
4
4
4
4
-512
+2
4
128
4
64
4
4
16
8
4
64
4
128
4
4
128
4
32
4
8
4
4
4
4
4
4
4
4
0
4
-512
+2
4
4
4
4
128
4
4
4
4
4
4
0
4
4
-512
+2
4
64
4
4
64
64
4
4
4
64
4
4
4
4
4
16
4
8
4
4
4
8
4
4
-512
+2
4
4
4
128
4
4
32
4
0
4
4
4
4
0
4
16
4
4
4
4
4
64
4
-512
+2
4
32
4
-512
+2
32
8
4
128
4
4
4
4
4
-512
+2
64
4
4
4
4
4
4
4
-512
+2
4
4
4
32
4
4
64
4
4
4
4
0
4
4
4
4
4
4
4
4
64
4
4
4
4
4
4
4
0
-512
+2
4
4
4
4
4
4
0
4
0
4
32
4
0
4
4
4
128
8
64
128
4
4
64
8
4
4
4
4
4
4
4
4
0
4
4
4
4
4
4
4
4
4
4
32
4
4
4
4
4
8
4
4
4
4
4
4
8
4
4
64
0
-512
+2
32
0
4
4
4
4
0
4
4
4
4
4
4
4
4
4
4
4
4
4
0
0
0
4
4
0
4
4
32
4
4
4
4
4
4
16
4
0
128
4
4
4
4
4
-512
+2
16
32
4
4
4
4
0
-512
+2
4
64
4
4
4
4
4
4
4
4
4
-512
+2
4
16
4
4
4
4
-512
+2
0
4
4
4
4
4
4
4
4
4
4
4
4
4
4
16
4
8
4
8
32
4
4
4
4
4
128
64
4
4
4
4
4
4
-512
+2
4
4
4
4
4
4
4
4
4
4
0
4
4
4
4
4
4
0
-512
+2
4
4
8
0
4
4
4
4
0
4
4
4
4
0
4
64
4
128
-512
+2
4
4
4
4
16
4
4
4
4
4
4
4
4
4
4
4
4
64
4
4
4
-512
+2
4
4
4
4
4
4
-512
+2
4
4
4
4
4
4
-512
+2
0
4
4
4
4
4
4
4
4
4
4
4
-512
+2
4
32
4
128
4
4
4
64
4
-512
+2
4
4
4
0
4
128
32
4
128
4
4
8
0
4
-512
+2
4
4
0
4
4
4
4
4
4
4
4
4
4
-512
+2
4
4
128
4
4
4
4
0
4
-512
+2
32
4
4
4
4
-512
+2
4
8
4
4
4
8
4
4
128
4
4
4
4
0
0
4
4
-512
+2
4
4
4
4
32
4
-512
+2
4
4
128
8
16
128
4
4
4
32
128
4
32
0
4
4
-512
+2
4
32
4
4
32
8
4
4
4
4
4
4
8
4
4
4
4
4
4
4
64
4
4
4
4
4
4
8
4
4
-512
-512
+2
+2
4
4
4
4
4
32
4
4
4
4
32
4
4
4
4
4
64
4
4
4
4
8
4
-512
+2
4
4
64
-512
+2
4
4
4
4
4
4
0
4
128
4
4
4
4
-512
+2
4
4
4
64
4
4
4
4
-512
+2
128
4
4
4
4
4
8
4
4
128
4
4
4
4
128
4
4
4
0
4
4
16
64
4
4
32
4
32
64
16
4
4
64
4
4
4
0
4
4
4
4
0
4
64
4
64
16
4
4
4
4
64
4
0
128
4
4
8
4
-512
+2
4
0
4
-512
+2
0
4
128
4
4
4
4
4
4
4
4
4
4
-512
+2
4
16
64
64
4
4
4
4
4
4
4
4
4
-512
+2
8
4
4
4
-512
+2
32
16
4
4
128
32
4
4
-512
+2
32
4
4
4
4
64
4
4
-512
+2
4
32
4
4
0
4
128
64
4
4
4
16
4
4
4
-512
+2
4
4
4
4
4
4
128
4
4
4
0
4
-512
+2
4
4
4
4
0
0
32
4
32
4
4
4
4
4
4
128
4
4
4
4
4
4
4
4
16
4
32
4
4
4
4
4
-512
+2
0
4
4
4
64
16
4
4
4
4
4
4
4
4
4
4
-512
+2
8
-512
+2
4
4
4
0
4
4
128
4
4
4
0
4
4
4
4
4
64
4
4
4
4
4
0
4
4
4
4
4
4
4
4
4
4
4
4
4
-512
+2
4
4
32
4
64
64
128
0
8
4
0
4
0
16
4
4
4
-512
+2
16
4
4
4
4
4
0
8
0
4
4
4
4
4
4
4
-512
+2
16
4
4
4
0
4
128
4
4
32
16
4
4
4
4
4
4
4
4
4
4
0
4
4
16
128
4
4
4
4
4
4
4
4
16
4
4
4
-512
+2
4
-512
+2
4
-512
+2
4
4
4
4
4
4
4
32
32
4
4
16
4
-512
+2
0
4
4
-512
+2
4
4
4
4
16
4
128
4
4
4
4
64
0
4
128
4
4
4
4
4
8
4
4
4
4
4
4
4
4
4
16
4
4
4
4
4
4
16
32
64
0
4
0
8
4
4
4
4
4
4
4
4
32
4
4
4
4
0
4
4
128
-512
+2
16
-512
+2
4
32
4
16
0
4
4
4
4
4
4
4
64
8
4
0
4
4
64
4
4
4
4
4
64
-512
+2
4
32
4
0
4
128
4
4
16
4
0
4
4
4
64
4
4
4
4
128
4
-512
+2
4
4
4
128
-512
+2
4
4
4
16
32
4
4
4
4
64
4
4
-512
+2
4
128
-512
+2
4
0
4
-512
+2
4
4
0
4
64
4
4
4
0
128
8
16
4
-512
+2
4
4
4
4
4
8
4
4
4
4
4
4
4
4
4
16
4
4
4
4
32
4
128
4
4
4
4
16
4
4
4
64
4
4
4
4
4
4
4
4
4
4
0
4
4
4
4
4
64
4
4
64
4
8
4
4
4
4
4
4
4
4
4
16
4
4
4
8
16
-512
+2
4
4
32
4
128
4
4
4
4
4
4
4
4
0
8
-512
+2
4
4
128
4
4
4
4
4
4
64
8
4
4
4
4
0
16
4
4
4
-512
+2
4
4
4
4
4
4
4
32
0
4
4
4
4
4
4
4
0
32
4
64
4
4
4
4
4
4
4
4
0
4
4
4
4
4
-512
+2
4
128
4
4
4
64
4
128
0
4
4
8
16
4
8
4
32
4
4
16
-512
+2
4
4
4
4
4
4
4
16
4
4
0
4
4
4
4
4
4
8
4
0
4
4
4
-512
+2
4
-512
+2
4
4
128
4
4
0
4
4
4
4
4
-512
+2
16
4
16
4
4
4
4
8
4
4
4
4
4
4
4
4
4
4
4
4
4
0
4
4
4
4
4
-512
+2
4
4
4
0
16
4
4
4
4
4
4
-512
+2
4
4
16
4
4
64
64
-512
+2
4
4
16
4
128
4
4
4
4
4
128
-512
+2
4
4
4
4
4
128
4
4
8
4
32
128
4
16
-512
+2
4
4
4
-512
+2
4
4
32
4
-512
+2
4
4
4
4
16
4
4
4
4
8
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
128
16
32
4
8
4
4
4
4
4
4
4
32
128
4
0
32
4
4
4
4
0
4
128
4
4
4
128
4
4
4
-512
+2
4
4
4
4
4
128
4
0
4
4
4
64
0
-512
+2
0
4
32
16
4
4
4
4
-512
+2
4
64
4
64
4
4
32
128
4
0
4
4
32
4
4
4
4
128
0
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
16
8
4
4
16
4
4
4
4
4
4
4
4
-512
+2
4
4
128
16
4
4
16
4
4
4
4
4
4
4
4
4
0
4
4
8
4
4
-512
+2
4
4
4
4
128
4
0
-512
+2
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
64
8
4
0
4
-512
+2
4
4
4
4
8
4
diff --git a/t/classify_ref_W4j b/t/classify_ref_W4j
index 3c3640a..982ef2b 100644
--- a/t/classify_ref_W4j
+++ b/t/classify_ref_W4j
@@ -1,3000 +1,3000 @@
0
0
0
4
4
64
32
0
4
0
32
4
128
4
0
4
4
16
0
0
4
4
0
4
128
4
4
4
4
16
4
4
0
0
8
-512
+2
32
64
4
-512
+2
0
4
4
16
32
0
0
8
4
4
128
4
8
-512
+2
4
0
4
4
4
4
0
0
128
4
4
128
0
8
16
0
16
4
0
32
128
128
4
4
16
32
16
4
4
64
0
0
128
0
0
0
16
16
8
0
16
4
4
0
4
4
16
8
16
0
8
4
4
16
0
-512
+2
0
-512
+2
128
16
4
128
32
8
16
0
0
8
4
4
4
4
-512
+2
4
0
4
64
4
4
4
8
4
0
4
64
16
4
4
4
128
0
16
4
0
0
0
4
0
4
128
0
16
32
8
-512
+2
0
4
4
4
16
32
8
0
4
128
4
4
4
4
0
4
4
4
16
4
128
16
4
16
0
0
0
4
4
16
4
4
0
4
4
16
0
-512
+2
0
128
0
4
4
0
16
32
0
8
128
128
16
16
4
4
0
4
0
8
0
0
4
64
4
0
4
0
8
16
8
4
4
32
8
0
16
16
0
4
128
0
4
128
16
4
4
128
0
0
8
4
8
0
0
4
0
0
0
0
4
0
0
0
4
16
0
4
0
8
4
0
0
4
4
0
4
16
0
4
4
8
4
0
8
128
4
16
16
4
4
4
4
4
4
4
0
4
8
4
8
4
64
0
8
16
0
64
0
8
8
4
0
4
8
4
0
4
4
8
4
4
4
16
8
4
0
-512
+2
0
4
-512
+2
16
16
4
64
0
4
8
16
4
4
32
4
32
4
64
4
4
0
16
4
16
16
0
0
4
16
4
0
4
-512
+2
0
16
0
0
4
0
0
16
128
32
8
4
4
8
128
8
8
64
4
4
8
8
16
0
4
4
128
32
4
0
4
0
0
4
16
16
4
0
32
16
0
8
4
8
16
4
32
4
4
4
128
0
128
4
8
4
128
4
8
128
0
0
4
4
4
16
8
32
4
4
4
0
4
4
128
16
16
16
4
0
4
16
16
0
4
0
64
8
8
4
4
16
16
4
0
8
0
8
64
4
4
8
0
128
4
-512
+2
4
4
0
4
4
4
0
4
4
0
8
0
16
64
0
0
16
0
4
16
16
0
4
4
4
16
4
0
4
4
0
8
4
8
4
128
4
0
16
0
0
4
4
0
16
32
4
0
0
8
4
0
16
4
4
0
16
128
8
0
4
4
64
4
128
0
0
4
4
0
4
16
0
8
0
0
16
4
4
4
4
0
4
16
16
0
8
4
4
4
4
4
4
0
16
8
16
128
4
4
0
4
64
4
4
128
0
16
4
0
8
0
128
4
0
4
4
8
64
0
4
8
128
128
4
8
4
32
128
128
4
4
16
0
0
128
4
4
0
8
8
8
16
8
16
128
0
8
8
4
4
0
16
4
0
4
0
4
4
0
0
4
4
4
16
4
-512
+2
4
4
8
0
4
0
4
32
4
0
4
16
0
4
0
8
4
4
0
4
4
4
4
4
0
128
4
16
4
16
0
4
0
8
4
8
4
4
4
8
0
16
0
8
128
64
0
8
4
128
4
4
0
4
4
16
8
4
8
16
0
16
0
4
4
32
0
4
4
0
0
32
4
4
4
16
4
-512
+2
128
4
0
4
32
4
16
0
8
0
4
16
4
4
16
4
8
4
8
8
64
128
0
8
0
4
0
0
-512
+2
0
32
4
128
4
0
-512
+2
8
4
0
16
4
4
0
8
8
8
8
4
8
16
4
4
0
0
0
0
4
0
4
8
16
4
0
0
0
4
16
8
128
32
16
0
4
4
0
0
32
32
128
4
8
4
16
16
4
0
0
16
4
8
0
0
16
4
4
16
4
64
-512
-512
+2
+2
0
0
0
0
128
4
4
8
8
0
4
16
8
8
4
32
16
4
8
8
0
64
0
16
4
64
0
8
4
16
4
0
4
32
4
64
0
32
0
4
0
0
0
4
8
8
128
8
0
4
4
4
0
4
4
8
4
-512
+2
4
4
4
8
32
4
4
16
-512
+2
0
4
4
4
0
4
4
4
4
4
4
4
0
32
4
4
4
64
8
4
16
-512
+2
4
64
4
4
0
128
0
4
-512
-512
+2
+2
16
8
32
8
4
16
4
4
128
4
4
0
0
4
0
0
0
64
0
16
8
0
16
8
4
4
4
4
16
4
4
16
0
16
0
4
16
-512
+2
4
4
0
4
8
8
4
4
8
0
4
4
4
0
4
16
16
0
4
4
128
4
4
4
4
8
0
64
4
128
16
64
0
8
4
4
4
32
4
4
0
4
8
0
0
0
4
0
128
4
4
4
-512
+2
64
4
4
4
64
4
4
8
64
4
32
4
0
4
32
0
4
4
4
4
4
4
0
0
64
8
0
-512
+2
4
4
4
4
0
0
4
64
16
16
4
16
0
8
4
0
4
8
16
8
32
8
4
0
4
16
4
16
4
0
4
16
64
0
16
4
16
0
4
4
32
8
0
4
128
16
4
0
4
4
4
4
16
4
32
128
16
32
0
4
0
4
0
4
8
-512
+2
4
16
16
-512
+2
64
4
8
4
4
4
4
0
0
8
4
0
0
-512
+2
16
4
0
8
4
0
8
16
0
0
16
4
0
0
32
0
8
0
0
4
64
4
8
64
4
0
4
64
4
8
-512
+2
0
8
4
4
16
0
4
64
4
4
4
-512
+2
16
16
0
0
4
-512
+2
0
4
8
4
4
4
0
4
4
0
0
4
32
4
4
4
16
64
0
4
32
4
4
4
8
8
4
128
4
8
4
64
4
4
16
4
4
4
128
-512
+2
8
0
0
-512
+2
0
0
0
-512
+2
4
0
4
64
0
-512
+2
4
4
0
16
4
0
16
8
0
0
4
16
0
4
4
0
4
8
0
32
0
0
0
16
0
4
8
0
0
4
8
4
0
-512
+2
8
8
0
0
16
8
0
16
0
32
4
16
0
4
128
4
4
0
0
4
128
128
4
4
16
128
16
4
8
4
0
0
-512
+2
4
64
4
0
32
4
4
0
4
8
4
32
4
16
128
4
4
0
4
0
4
16
0
4
4
4
4
16
16
8
16
8
4
16
0
4
0
0
0
8
4
16
4
4
0
0
4
4
4
0
4
4
8
64
4
8
4
0
4
4
64
4
4
0
4
16
4
4
16
4
16
4
4
0
4
0
4
4
0
32
4
128
0
16
0
0
4
0
8
64
4
0
4
4
4
4
4
4
4
64
8
4
4
4
4
16
4
4
16
16
4
128
0
4
8
32
4
4
8
0
0
8
8
128
0
16
4
8
4
4
4
16
4
0
4
128
0
4
32
4
4
4
4
4
4
0
8
8
-512
+2
4
4
16
0
4
4
4
16
4
8
16
0
8
128
4
4
4
4
16
8
4
4
4
0
4
0
0
0
16
8
16
8
0
4
64
128
16
4
32
0
4
0
32
0
4
128
4
4
4
4
32
4
64
4
8
64
4
8
0
4
-512
+2
0
4
4
4
0
4
8
0
16
4
-512
+2
16
0
4
0
4
0
4
128
0
0
4
64
16
4
4
4
64
8
8
8
64
0
4
4
4
0
32
4
4
4
4
0
4
16
-512
+2
4
4
8
0
16
8
4
8
8
4
4
-512
+2
64
16
4
4
4
16
4
4
8
0
16
32
4
4
4
4
4
4
4
0
4
16
8
8
4
0
-512
+2
4
4
8
16
16
4
4
16
0
128
0
4
128
32
4
0
0
128
16
0
4
4
8
8
0
0
0
4
4
4
4
0
-512
+2
32
4
8
-512
+2
4
4
0
4
4
4
0
0
16
4
-512
+2
64
4
16
0
0
4
4
0
16
64
16
16
128
8
-512
+2
0
64
4
128
4
4
16
8
4
4
0
4
16
4
128
4
128
64
0
4
128
8
16
32
16
16
4
4
32
4
4
0
4
128
0
64
16
128
0
4
0
0
4
0
128
128
8
0
8
4
8
8
4
4
128
0
16
4
0
8
0
8
4
4
4
0
4
8
4
8
4
16
32
8
32
8
32
4
128
0
16
0
4
4
32
16
64
0
128
0
8
16
8
4
-512
+2
4
16
16
-512
+2
128
4
4
-512
+2
16
0
128
0
4
4
128
4
0
64
4
4
0
8
0
32
4
4
0
4
8
4
4
0
4
-512
+2
4
8
-512
+2
0
0
16
-512
+2
4
0
0
8
128
4
16
4
0
4
8
0
4
0
32
0
4
8
64
16
32
32
8
0
4
4
4
4
16
0
4
0
64
4
32
4
0
4
-512
+2
4
-512
+2
16
16
4
0
16
32
32
0
4
0
128
4
4
8
4
0
0
0
0
4
4
16
4
0
16
0
0
16
8
4
128
8
0
0
-512
+2
4
4
0
4
4
4
8
8
8
4
4
4
0
32
0
4
4
32
0
32
0
0
0
128
4
8
0
8
4
128
4
4
0
8
0
0
16
128
8
64
4
4
8
0
4
16
8
4
128
32
128
4
4
32
0
4
4
4
16
8
4
4
16
16
16
-512
+2
4
0
4
32
4
4
4
4
4
128
0
4
0
8
16
32
16
4
8
64
8
0
4
16
4
4
4
0
-512
+2
0
0
16
0
4
-512
+2
4
4
4
4
4
64
8
0
128
4
4
4
4
4
32
4
0
4
16
4
4
0
4
0
4
4
4
4
0
4
4
8
16
4
0
128
16
0
128
16
4
0
128
0
4
128
4
32
4
8
4
4
0
4
0
8
16
0
16
4
4
4
8
4
0
64
16
0
0
4
4
0
4
4
0
16
8
16
4
4
4
4
0
0
16
-512
+2
0
0
128
0
0
8
0
0
8
0
32
0
0
16
4
8
-512
+2
0
0
4
0
-512
+2
0
32
0
16
128
0
4
4
-512
+2
4
16
0
16
4
0
0
128
-512
+2
128
16
4
8
128
4
4
0
0
4
8
0
0
4
16
64
4
16
0
0
8
8
4
128
4
32
4
0
4
32
128
8
16
4
64
4
4
0
0
4
4
16
0
4
4
16
4
16
128
4
0
4
4
32
4
0
4
4
4
32
-512
+2
4
8
4
64
8
8
16
16
0
64
-512
+2
4
8
8
4
16
0
4
4
0
0
32
0
4
4
-512
+2
16
16
16
128
-512
+2
0
0
0
8
4
128
4
16
4
4
4
-512
+2
8
4
4
4
128
4
4
0
0
128
0
16
128
8
0
8
0
4
4
-512
+2
16
8
4
4
0
128
4
0
32
-512
+2
16
4
4
4
8
8
0
4
4
0
8
0
16
128
0
8
4
4
4
64
-512
+2
4
4
4
4
8
0
128
0
4
4
128
4
32
0
128
4
0
0
0
4
4
4
4
4
0
8
4
0
0
0
0
16
4
4
4
0
4
16
4
4
16
4
4
0
0
4
16
4
4
0
16
4
4
16
4
4
4
4
0
4
0
16
32
4
32
8
8
0
32
0
4
4
16
64
0
0
4
8
128
4
16
4
4
0
16
32
0
0
0
16
0
4
0
16
8
4
128
4
4
4
8
0
4
8
0
4
0
8
128
4
128
0
0
4
-512
+2
4
16
0
0
0
64
4
8
8
0
0
0
4
16
4
4
4
16
4
4
0
0
0
-512
+2
128
4
4
4
8
4
0
0
0
0
0
0
128
8
4
16
4
4
16
4
8
16
0
64
4
8
4
16
4
4
0
-512
+2
0
8
4
0
4
64
0
128
-512
+2
0
0
-512
+2
0
16
4
0
0
4
4
0
0
16
8
16
4
0
4
4
0
8
32
0
4
4
16
4
4
4
4
4
16
0
4
16
8
4
32
16
4
4
16
0
8
8
4
8
4
0
4
8
-512
+2
0
32
4
0
4
0
0
4
128
8
-512
+2
0
0
0
-512
+2
4
0
4
8
32
128
64
16
4
8
4
128
4
4
16
16
8
0
4
4
16
16
16
8
0
-512
+2
64
0
16
4
8
128
0
4
0
-512
+2
8
64
8
4
-512
+2
0
8
16
16
4
8
0
128
8
8
0
16
-512
+2
4
4
64
64
64
16
4
0
4
4
16
16
4
0
0
4
8
16
8
16
8
4
16
4
0
0
0
4
0
4
4
4
0
4
8
0
0
0
4
32
4
4
4
0
4
16
16
4
4
8
128
4
16
4
4
4
0
8
0
0
0
4
0
-512
+2
64
4
4
0
0
0
128
0
0
4
4
4
4
16
-512
+2
32
64
0
8
4
128
0
8
16
128
0
4
0
128
0
64
4
4
0
0
8
0
4
0
0
8
16
0
64
8
0
4
4
4
4
4
128
4
0
16
128
4
8
4
0
16
4
4
8
16
4
16
4
16
4
32
8
4
0
32
8
0
4
0
4
4
4
4
4
16
128
4
0
128
16
128
16
4
32
32
4
16
4
4
4
4
8
4
8
4
0
0
4
4
32
16
64
32
4
16
4
0
4
4
16
0
0
4
0
0
32
16
8
4
4
0
16
16
4
0
-512
+2
16
16
0
4
128
4
4
0
0
0
8
4
-512
+2
8
16
4
0
8
8
64
16
8
4
4
4
4
0
0
8
8
0
16
4
16
0
4
4
0
8
4
4
128
4
8
0
64
32
64
0
4
4
4
0
8
8
0
16
4
16
0
64
4
4
4
4
0
4
4
-512
+2
64
64
4
64
0
4
0
0
4
0
4
4
16
4
0
4
0
8
16
8
16
16
0
4
32
16
16
4
4
4
16
0
0
4
16
4
16
8
8
4
4
4
4
4
0
16
8
8
8
4
16
4
4
8
16
-512
+2
4
0
16
4
0
4
32
4
0
16
4
4
0
4
16
0
4
16
0
8
16
4
4
4
4
0
16
16
4
8
4
8
4
4
4
0
4
4
0
8
4
4
-512
+2
4
128
4
0
4
16
8
32
0
64
4
0
4
64
4
4
8
0
4
0
0
8
0
4
0
4
8
0
0
4
32
16
0
4
64
16
16
0
4
4
16
128
32
4
16
4
16
64
16
4
4
32
8
4
0
0
4
0
0
8
4
0
4
8
4
4
4
4
4
0
0
0
16
-512
+2
16
0
4
4
0
0
8
64
0
16
4
0
0
0
128
0
0
4
16
8
16
4
128
4
diff --git a/t/classify_ref_Z4j b/t/classify_ref_Z4j
index ec65988..5653d40 100644
--- a/t/classify_ref_Z4j
+++ b/t/classify_ref_Z4j
@@ -1,4000 +1,4000 @@
4
0
0
4
0
4
0
16
0
16
0
16
0
0
0
0
0
16
0
4
8
8
8
0
4
0
0
0
16
0
8
0
4
0
4
0
0
0
0
0
0
4
0
0
0
4
4
0
0
0
4
8
0
0
4
0
0
16
0
0
0
4
16
0
0
4
0
0
16
0
4
0
0
0
4
8
0
16
0
8
0
0
8
4
0
0
0
0
0
4
0
0
0
4
0
0
0
0
0
0
0
0
16
4
0
0
0
0
0
-512
+2
0
0
0
0
16
8
4
0
0
0
16
0
0
8
0
0
4
0
0
0
0
0
8
0
0
0
0
8
0
0
16
0
4
4
16
4
0
0
0
0
0
8
0
0
0
0
0
16
4
4
0
0
0
4
0
0
0
0
0
4
0
4
16
0
0
16
0
0
0
0
4
0
0
4
0
16
0
8
16
16
0
0
0
0
8
0
0
0
16
0
8
0
8
0
0
4
0
0
0
0
0
4
0
0
16
4
16
4
4
0
0
0
0
8
0
0
16
0
0
0
8
0
0
16
0
16
0
8
0
0
0
0
0
4
8
0
0
0
0
-512
+2
0
0
0
4
0
8
16
16
0
-512
+2
8
0
0
0
0
0
16
0
0
0
0
4
4
0
0
0
0
0
0
0
8
8
4
8
0
0
16
0
4
0
0
0
0
0
0
4
0
0
0
0
0
0
0
4
0
0
0
0
0
0
0
0
4
0
0
0
0
4
16
4
0
0
0
0
8
0
0
0
16
0
8
0
8
0
4
-512
+2
16
0
0
4
4
0
8
4
4
0
0
0
0
4
0
0
0
0
0
0
0
16
0
0
16
0
8
4
4
8
16
16
0
0
0
8
16
0
0
8
4
0
16
0
8
0
0
16
0
0
16
0
0
0
4
4
0
4
4
0
0
4
0
0
4
0
0
4
4
0
0
16
0
0
0
4
16
0
16
0
0
0
4
16
8
8
0
0
0
0
0
0
4
0
4
8
16
0
4
0
8
0
0
16
4
0
0
0
0
0
8
0
0
8
0
16
4
0
0
16
0
8
0
0
0
0
0
0
0
0
0
0
8
0
16
0
0
0
0
0
0
0
0
4
8
16
0
0
8
8
16
16
0
0
4
4
0
0
0
0
0
0
4
0
0
0
0
0
16
4
0
8
16
0
0
0
0
0
0
8
0
0
4
4
0
0
4
4
0
0
0
0
4
0
4
0
0
16
0
0
8
0
0
0
16
0
4
8
0
0
0
16
16
0
8
0
0
0
8
0
4
4
0
0
0
0
0
0
0
0
4
0
0
0
0
0
16
4
16
0
0
8
8
0
4
0
4
0
4
0
8
0
0
8
4
0
0
8
0
0
0
0
16
4
0
0
8
0
16
0
0
16
8
0
8
0
0
0
0
4
0
0
0
4
0
0
0
0
0
0
8
4
0
4
0
0
0
0
0
0
4
0
0
0
16
4
16
0
0
0
0
0
0
0
8
0
8
0
16
0
8
4
0
0
0
8
16
8
0
4
0
4
0
0
8
0
0
4
4
0
0
4
8
0
0
0
0
0
0
0
16
0
8
0
16
16
8
0
4
0
0
4
0
8
0
0
4
0
0
8
0
0
4
0
4
4
8
16
4
0
0
0
0
0
0
0
4
0
0
0
0
0
4
4
0
0
0
0
16
0
0
8
4
4
4
0
0
0
0
4
0
0
0
0
8
0
8
4
4
0
0
0
0
16
0
4
0
16
0
0
4
0
4
0
0
0
0
0
0
0
0
0
0
0
0
8
0
0
0
4
0
0
8
0
0
0
0
0
0
4
0
0
0
16
0
0
0
0
4
4
8
0
0
0
0
0
0
16
4
0
16
0
0
0
4
0
8
0
0
16
4
4
0
16
0
8
0
16
0
0
8
0
4
0
8
16
0
0
-512
+2
0
4
4
0
0
0
16
0
0
0
0
8
0
0
0
0
0
0
-512
+2
4
8
4
0
0
16
0
0
0
8
0
0
0
4
0
0
0
0
0
16
0
0
0
0
0
4
4
16
0
4
16
0
0
0
8
0
0
0
4
0
0
0
16
16
4
4
-512
+2
0
4
0
0
0
0
4
8
0
4
8
16
4
4
8
0
0
0
0
16
16
8
0
0
0
0
16
4
0
0
4
4
16
4
0
0
0
0
0
0
0
8
8
0
4
16
0
8
16
4
8
0
0
0
4
0
4
0
0
4
0
0
0
4
8
0
8
0
16
0
8
0
0
0
0
0
0
0
0
0
0
0
8
0
4
0
0
0
0
0
16
16
0
0
0
0
0
0
16
4
4
0
0
16
4
0
16
0
4
16
0
-512
+2
0
0
4
8
0
0
4
8
4
8
4
0
0
0
8
8
0
0
0
16
4
0
0
0
0
0
8
0
0
16
0
0
0
0
4
0
8
16
4
0
4
0
8
0
8
16
0
0
0
0
16
8
4
0
0
8
0
16
4
0
4
0
0
0
0
0
0
0
0
0
0
16
8
0
16
0
0
4
0
8
0
0
16
0
4
0
8
0
0
0
0
16
4
0
0
-512
+2
8
8
0
0
0
0
4
0
0
4
0
0
0
4
16
0
0
4
0
8
16
0
0
0
4
0
0
0
16
0
16
0
0
0
0
0
0
0
0
0
8
0
0
0
0
8
0
4
0
0
16
16
0
0
0
4
4
4
0
0
0
0
0
16
0
0
8
0
16
0
0
4
0
0
4
0
0
0
0
0
16
0
0
0
4
16
8
16
16
0
0
0
16
16
16
0
0
0
0
0
0
0
0
8
4
0
0
0
4
4
0
16
0
0
0
0
0
4
0
0
0
0
0
0
4
4
0
0
16
16
0
0
4
0
0
4
4
0
0
0
0
16
8
4
16
0
0
4
0
0
4
0
0
8
8
0
16
0
0
0
4
4
16
0
0
4
0
0
0
8
0
0
0
0
0
0
8
0
0
0
0
4
0
8
0
0
4
0
8
0
0
0
16
4
4
8
0
8
0
0
8
0
0
16
0
0
0
16
0
0
0
0
8
0
8
16
4
0
0
8
4
0
8
0
4
0
16
0
4
0
8
8
0
8
4
0
8
0
4
0
0
0
0
0
4
0
0
0
4
0
16
0
4
0
0
4
0
0
0
0
0
0
16
0
0
0
0
4
-512
+2
0
0
8
0
8
0
0
0
0
0
8
0
4
0
4
16
0
0
8
0
0
0
4
0
0
0
16
0
0
8
0
4
0
0
16
0
4
0
0
0
0
0
4
0
8
0
0
0
8
-512
+2
0
0
0
0
4
0
0
0
8
0
0
0
0
0
4
16
4
0
0
16
0
4
0
16
0
0
0
16
0
0
0
0
0
0
8
0
0
0
0
0
4
0
0
0
0
16
0
0
8
0
0
0
16
16
0
0
0
0
0
4
0
4
0
0
8
0
0
4
0
16
0
0
0
0
0
0
8
0
0
4
0
0
16
0
0
0
0
0
16
0
0
0
4
0
0
0
16
0
0
0
0
0
0
0
0
0
0
0
4
0
4
0
0
0
0
0
4
0
16
16
0
8
0
0
4
0
0
8
4
0
0
0
0
0
0
0
0
-512
+2
16
8
0
0
4
0
0
4
0
0
8
8
0
0
0
4
16
16
8
0
8
4
4
0
16
0
16
0
16
0
0
8
0
16
0
8
0
0
0
0
8
4
0
16
0
0
0
8
0
0
4
0
0
4
4
0
16
16
0
8
16
0
0
0
0
16
8
8
0
4
4
4
0
0
0
0
0
-512
+2
0
0
0
0
4
0
16
0
8
0
0
0
4
0
0
4
0
0
4
4
0
16
0
16
0
0
0
0
8
0
0
16
8
0
0
0
0
4
0
8
4
0
0
0
0
4
0
0
0
0
0
8
0
8
16
4
4
4
0
0
4
0
0
0
8
0
0
0
4
-512
+2
4
0
4
0
0
0
0
0
8
0
0
0
0
4
0
0
0
4
0
0
8
0
0
0
4
8
0
0
0
0
4
0
0
16
0
0
-512
+2
0
4
0
4
0
16
0
8
0
4
0
0
0
0
0
0
0
0
4
8
0
0
0
0
4
0
0
4
16
0
8
0
0
16
8
0
0
0
0
0
4
16
0
8
16
0
8
4
-512
+2
4
0
0
16
8
16
8
4
4
0
0
0
0
0
0
0
0
8
0
0
0
0
8
4
0
0
0
0
0
4
0
0
0
0
0
0
0
0
16
0
0
4
8
0
8
4
16
0
16
16
4
0
4
8
4
0
0
0
0
0
4
0
0
0
0
0
8
0
4
0
0
0
0
4
0
8
0
8
16
4
16
0
0
16
4
0
0
16
8
0
0
0
0
8
4
16
0
0
0
0
0
16
0
-512
+2
4
0
0
0
4
0
4
4
4
0
0
0
0
0
0
0
0
0
8
0
4
0
0
0
0
4
0
0
4
0
4
0
0
0
0
0
0
0
0
0
0
0
0
4
0
0
0
4
0
0
16
4
0
4
0
4
4
0
4
0
0
0
0
0
0
0
16
0
0
0
0
0
0
4
8
0
0
0
0
0
8
4
16
0
0
0
0
0
0
4
0
0
0
0
0
0
4
0
4
0
0
4
0
0
0
4
0
0
0
0
0
0
0
0
0
0
-512
+2
0
16
0
0
0
0
0
4
8
4
0
16
0
0
0
0
4
0
0
8
0
0
8
0
0
4
0
-512
+2
0
0
16
4
8
0
4
8
0
8
0
0
4
0
0
16
0
0
0
0
8
0
8
0
4
0
0
0
0
8
0
0
16
4
8
0
0
0
0
0
16
0
0
0
16
0
0
16
0
16
16
4
16
0
4
0
0
16
16
16
16
0
0
0
16
0
0
0
0
4
4
0
0
4
0
16
0
16
0
4
0
0
0
0
4
16
16
4
-512
+2
0
0
0
16
0
0
16
8
0
8
0
0
0
0
0
8
0
0
0
16
4
4
4
0
0
0
0
0
0
0
4
0
0
8
0
16
16
0
0
4
0
4
0
4
0
0
4
8
0
4
0
0
4
0
0
0
0
0
0
0
4
4
4
4
0
0
0
0
0
-512
+2
4
8
0
0
4
8
0
0
0
0
0
0
0
0
0
0
0
0
16
4
8
4
8
0
0
0
0
4
0
0
0
4
0
0
0
16
8
4
0
0
0
0
0
0
0
0
0
0
16
16
16
0
0
4
0
0
8
0
8
0
0
4
16
0
0
8
0
0
4
0
0
8
8
0
0
8
4
0
0
0
8
0
0
0
4
0
0
0
8
-512
+2
0
0
8
0
16
0
0
4
4
0
0
0
0
0
0
0
4
0
-512
+2
0
0
0
0
0
4
8
0
4
0
0
16
4
0
0
0
0
4
0
16
4
0
0
0
4
0
0
0
4
0
0
4
16
4
4
0
0
0
0
16
16
0
0
0
0
0
0
0
4
0
0
8
0
0
0
0
16
0
0
0
4
0
8
0
0
0
16
16
0
0
16
0
0
0
16
0
0
8
0
8
0
0
8
0
0
0
0
16
0
0
0
8
0
4
0
4
8
16
4
0
0
0
0
8
8
0
0
0
0
0
0
8
0
0
0
0
0
0
0
0
4
0
0
0
0
0
0
0
0
0
0
0
0
-512
+2
8
0
0
8
0
0
8
0
4
0
0
0
0
0
8
0
0
0
0
0
0
0
4
0
0
0
8
-512
+2
4
0
8
0
0
0
0
0
0
8
0
0
0
0
0
16
16
0
0
0
0
0
16
0
0
0
0
4
16
8
0
0
0
0
0
0
0
8
4
0
0
0
0
16
0
0
4
0
0
4
0
0
8
0
0
0
16
0
0
4
16
16
8
4
0
0
0
0
4
8
0
16
4
0
0
0
4
0
0
4
0
0
0
0
0
0
4
4
8
0
0
0
0
0
0
0
4
0
4
0
0
0
0
0
16
4
0
0
4
0
0
0
0
0
0
0
0
0
0
0
0
0
16
0
0
0
0
0
0
8
0
4
0
0
0
4
0
0
4
0
0
0
0
0
4
16
0
4
0
0
0
0
8
0
0
4
0
4
0
0
8
8
0
0
0
16
0
4
0
0
8
0
16
0
0
16
8
0
0
0
0
0
0
8
0
4
0
0
0
0
0
8
0
0
4
0
0
0
0
0
0
0
0
8
0
0
8
0
0
4
4
0
16
4
0
0
0
0
16
0
4
0
0
16
0
-512
+2
0
0
0
0
0
0
0
0
0
0
8
8
4
4
8
0
0
4
-512
+2
0
8
4
0
4
0
4
-512
+2
0
4
16
0
0
-512
+2
0
4
0
8
0
0
16
0
0
4
0
8
8
4
8
0
16
0
0
8
8
4
0
0
4
4
0
8
8
0
0
0
4
0
16
0
0
0
0
0
16
0
4
-512
+2
0
0
0
4
0
4
0
0
0
0
4
8
0
0
0
0
0
8
16
16
4
0
0
8
0
8
0
0
0
16
0
0
0
4
0
4
0
16
0
0
0
0
0
0
4
4
4
4
-512
+2
0
8
0
0
4
0
0
0
0
0
16
0
0
0
0
4
0
0
8
0
0
0
0
-512
+2
0
8
0
0
0
8
0
0
8
0
0
0
0
0
0
8
0
0
0
0
4
4
0
4
4
16
0
0
0
0
8
16
4
0
0
0
0
0
0
0
0
-512
+2
0
0
0
4
0
0
0
0
16
4
0
0
8
0
8
0
0
8
4
0
0
0
0
0
16
8
0
0
0
0
0
0
0
0
8
0
0
0
0
0
0
0
4
0
0
0
0
8
0
8
0
0
0
4
16
0
4
0
0
0
16
4
0
8
4
16
4
4
0
0
4
0
0
0
0
4
0
0
16
0
0
0
0
8
8
16
0
8
4
0
16
0
0
0
4
0
4
0
0
0
0
0
16
16
0
0
0
0
0
0
0
0
8
4
4
0
0
4
0
0
4
0
8
0
0
0
0
0
0
0
0
0
0
0
4
8
0
0
0
4
0
4
0
0
16
0
0
0
0
0
8
4
4
0
0
0
0
4
16
8
4
4
4
0
0
0
16
8
0
4
0
0
0
0
4
4
0
0
4
0
0
0
8
16
-512
+2
4
0
4
0
0
4
0
8
0
0
4
-512
+2
4
4
16
0
0
4
0
0
0
0
0
0
4
4
0
0
0
0
0
4
0
4
0
16
4
0
0
0
0
16
16
8
0
0
0
0
0
0
0
16
4
16
4
8
8
0
0
0
0
16
8
4
0
4
0
0
16
4
0
8
4
0
0
0
0
0
0
0
4
0
0
0
0
4
0
0
4
0
-512
+2
0
0
4
0
0
0
0
0
0
0
0
0
0
0
16
0
4
4
0
0
0
0
0
4
4
8
0
16
0
0
0
16
0
16
0
0
0
0
0
8
8
0
0
0
0
16
0
16
0
0
0
4
4
4
4
8
0
0
0
0
0
4
0
4
8
4
0
8
0
16
16
0
0
0
0
8
0
4
16
0
8
16
0
16
4
0
0
0
0
0
4
0
4
0
0
4
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
16
0
0
0
0
0
0
0
0
0
4
0
8
8
0
4
0
0
0
4
0
0
0
0
0
4
4
0
0
4
0
4
0
0
0
0
0
0
0
4
8
0
0
0
0
0
4
8
-512
+2
0
0
0
0
4
0
0
0
0
0
8
0
0
0
0
0
0
0
8
4
4
0
16
0
0
4
0
0
4
0
0
0
0
0
0
0
0
0
8
0
0
8
0
8
8
0
0
8
0
4
0
0
4
0
16
16
0
16
0
0
0
0
0
0
0
4
0
4
0
4
0
0
16
0
0
4
0
4
0
4
0
16
8
16
0
0
16
0
0
0
0
0
8
0
8
0
0
8
8
0
0
0
0
4
16
4
4
0
8
0
8
0
4
0
16
0
8
16
0
0
4
4
4
4
0
0
4
0
4
0
0
0
0
16
0
0
0
16
8
0
16
0
0
0
0
0
0
0
-512
+2
4
-512
+2
0
16
0
8
8
8
0
0
0
0
0
0
0
0
16
4
16
4
0
0
0
0
0
8
8
0
0
0
4
0
0
0
0
0
0
0
4
0
0
0
16
0
0
0
4
0
0
8
8
0
16
0
0
0
0
8
8
0
0
4
0
16
0
16
4
-512
+2
0
0
0
16
4
0
0
4
0
0
0
0
0
0
8
0
0
16
0
0
0
0
0
0
0
0
0
0
-512
+2
0
0
8
0
0
0
0
0
0
4
0
0
0
0
0
0
0
8
4
8
0
4
0
0
4
0
0
8
0
0
16
0
4
0
0
0
0
0
16
0
0
0
8
4
0
4
0
0
0
0
0
0
0
0
0
0
0
0
0
0
-512
+2
0
0
0
0
0
0
0
8
0
16
0
0
0
16
16
0
0
16
0
8
0
0
4
0
0
0
0
-512
+2
0
0
8
0
16
16
0
8
4
16
8
0
0
0
0
0
0
0
0
4
0
0
16
0
4
0
0
8
0
4
0
8
0
4
16
8
0
16
8
4
0
8
16
0
0
8
4
0
-512
+2
0
0
0
0
0
0
0
0
4
0
0
0
8
0
4
4
0
0
4
0
0
16
16
0
-512
+2
0
0
0
0
4
0
0
4
0
16
16
0
0
0
8
0
0
16
0
0
0
0
0
0
0
16
16
0
0
0
4
4
0
8
0
0
0
0
8
0
16
0
0
8
0
4
4
0
8
16
4
0
0
0
0
0
16
0
4
0
0
0
0
0
0
4
0
0
-512
+2
0
4
0
4
0
0
0
0
0
0
0
0
16
0
0
0
16
0
8
0
0
0
0
0
0
0
4
4
16
8
4
0
0
0
8
0
0
8
0
0
8
0
16
0
4
8
0
0
4
8
0
0
4
8
0
0
4
0
0
4
0
16
0
0
0
16
0
0
8
8
4
0
0
0
0
0
0
-512
+2
4
0
-512
+2
0
0
0
8
0
0
8
4
0
0
4
16
0
0
0
0
0
0
4
4
0
0
4
8
4
0
16
8
4
0
0
0
8
0
0
4
0
0
0
0
0
4
4
0
0
0
0
0
4
8
0
8
8
0
0
0
0
0
16
0
0
16
0
0
4
0
4
8
8
0
0
0
16
0
16
0
0
16
4
4
16
0
0
0
16
8
0
0
0
4
0
4
0
4
0
4
0
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 4:19 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3805113
Default Alt Text
(71 KB)
Attached To
rHEJ HEJ
Event Timeline
Log In to Comment