text:
// This file is part of the dune-xt-common project:
//   https://github.com/dune-community/dune-xt-common
// Copyright 2009-2018 dune-xt-common developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Andreas Buhr    (2014)
//   Felix Schindler (2009, 2012 - 2018)
//   René Fritze     (2009 - 2016, 2018)
//   Sven Kaulmann   (2011 - 2012)
//   Tobias Leibner  (2014 - 2015, 2017 - 2019)

#ifndef DUNE_XT_COMMON_STRING_INTERNAL_HH
#define DUNE_XT_COMMON_STRING_INTERNAL_HH

#include <cstring>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <string>

#include <dune/xt/common/disable_warnings.hh>
#include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <dune/xt/common/reenable_warnings.hh>

#include <dune/xt/common/debug.hh>
#include <dune/xt/common/exceptions.hh>
#include <dune/xt/common/ranges.hh>
#include <dune/xt/common/type_traits.hh>
#include <dune/xt/common/vector.hh>
#include <dune/xt/common/matrix.hh>
#include <dune/xt/common/math.hh>

namespace Dune {
namespace XT {
namespace Common {

#ifndef DUNE_XT_COMMON_STRING_HH
// only necessary for headercheck
template <class T = std::string>
inline std::vector<T>
tokenize(const std::string& msg,
         const std::string& separators,
         const boost::algorithm::token_compress_mode_type mode = boost::algorithm::token_compress_off);
#endif // DUNE_XT_COMMON_STRING_HH

namespace internal {

static inline std::string trim_copy_safely(std::string str_in)
{
  const std::string str_out = boost::algorithm::trim_copy(str_in);
  if (str_out.find(";") != std::string::npos)
    DUNE_THROW(Exceptions::conversion_error,
               "There was an error while parsing the string below. "
                   << "The value contained a ';': '" << str_out << "'!\n"
                   << "This usually happens if you try to get a matrix expression with a vector type "
                   << "or if you are missing the white space after the ';' in a matrix expression!\n");
  return str_out;
} // ... trim_copy_safely(...)

template <class T>
static inline T convert_safely(std::string ss)
{
  try {
    return boost::lexical_cast<T, std::string>(ss);
  } catch (boost::bad_lexical_cast& e) {
    DUNE_THROW(Exceptions::conversion_error,
               "Error in boost while converting the string '" << ss << "' to type '" << Typename<T>::value() << "':\n"
                                                              << e.what());
  } catch (std::exception& e) {
    DUNE_THROW(Exceptions::conversion_error,
               "Error in the stl while converting the string '" << ss << "' to type '" << Typename<T>::value() << "':\n"
                                                                << e.what());
  }
  return T();
} // ... convert_safely(...)

// unspecialized variant
template <class T, bool anything = true>
struct Helper
{
  static inline T convert_from_string(std::string ss)
  {
    return convert_safely<T>(ss);
  }
}; // struct Helper

// variant for bool, to correctly parse true and false
template <bool anything>
struct Helper<bool, anything>
{
  static inline bool convert_from_string(std::string ss)
  {
    std::string ss_lower_case = ss;
    std::transform(ss_lower_case.begin(), ss_lower_case.end(), ss_lower_case.begin(), ::tolower);
    if (ss_lower_case == "true")
      return true;
    else if (ss_lower_case == "false")
      return false;
    else
      return convert_safely<bool>(ss);
  }
}; // struct Helper< bool, ... >

// variant for all basic types supported by std::sto*
#define DUNE_XT_COMMON_STRING_GENERATE_HELPER(tn, tns)                                                                 \
  template <bool anything>                                                                                \
  struct Helper<tn, anything>                                                                                \
  {                                                                                \
    static inline tn convert_from_string(std::string ss)                                                               \
    {                                                                                \
      try {                                                                                \
        return std::sto##tns(ss);                                                                                \
      } catch (const std::exception& ee) {                                                                             \
        DUNE_THROW(Exceptions::conversion_error,                                                                       \
                   "in stl when converting '" << ss << "' to '" << Typename<tn>::value() << "': " << ee.what());       \
      }                                                                                \
    }                                                                                \
  };

DUNE_XT_COMMON_STRING_GENERATE_HELPER(int, i)
DUNE_XT_COMMON_STRING_GENERATE_HELPER(long, l)
DUNE_XT_COMMON_STRING_GENERATE_HELPER(long long, ll)
DUNE_XT_COMMON_STRING_GENERATE_HELPER(unsigned long, ul)
DUNE_XT_COMMON_STRING_GENERATE_HELPER(unsigned long long, ull)
DUNE_XT_COMMON_STRING_GENERATE_HELPER(float, f)
DUNE_XT_COMMON_STRING_GENERATE_HELPER(double, d)
DUNE_XT_COMMON_STRING_GENERATE_HELPER(long double, ld)

#undef DUNE_XT_COMMON_STRING_GENERATE_HELPER

// variant for unsigned int as there is no stoui
template <bool anything>
struct Helper<unsigned int, anything>
{
  static inline unsigned int convert_from_string(std::string ss)
  {
    try {
      return XT::Common::numeric_cast<unsigned int>(std::stoul(ss));
    } catch (const XT::Common::Exceptions::external_error& ee) {
      DUNE_THROW(Exceptions::conversion_error,
                 "in XT::Common::numeric_cast when converting '" << ss << "' to '" << Typename<unsigned int>::value()
                                                                 << "': " << ee.what());
    } catch (const std::exception& ee) {
      DUNE_THROW(Exceptions::conversion_error,
                 "in stl when converting '" << ss << "' to '" << Typename<unsigned long>::value()
                                            << "': " << ee.what());
    }
  }
};

// variant for everything that is not a matrix or a vector or complex value
template <class T>
static inline typename std::enable_if<!is_vector<T>::value && !is_matrix<T>::value && !is_complex<T>::value, T>::type
convert_from_string(std::string ss, const size_t DXTC_DEBUG_ONLY(rows) = 0, const size_t DXTC_DEBUG_ONLY(cols) = 0)
{
  DXT_ASSERT(rows == 0);
  DXT_ASSERT(cols == 0);
  return Helper<T>::convert_from_string(ss);
}

template <class V>
static inline typename std::enable_if<is_complex<V>::value, V>::type
convert_from_string(std::string ss, const size_t /*size*/ = 0, const size_t /*cols*/ = 0)
{
  boost::algorithm::trim(ss);
  if (ss.size() < 1)
    DUNE_THROW(Exceptions::conversion_error, "Error converting " << ss << " (too short)");
  using namespace std;
  typedef typename V::value_type T;
  T re(0), im(0);
  const auto sign_pos = ss.find("+", 1) != string::npos ? ss.find("+", 1) : ss.find("-", 1);
  re = convert_from_string<T>(ss.substr(0, sign_pos));
  if (sign_pos != string::npos) {
    ss = ss.substr(sign_pos);
    const auto im_pos = ss.find("i");
    if (im_pos == string::npos)
      DUNE_THROW(Exceptions::conversion_error, "Error converting " << ss << " no imaginary unit");
    im = convert_from_string<T>(ss.substr(0, im_pos));
  }
  return V(re, im);
}

template <class VectorType>
static inline typename std::enable_if<is_vector<VectorType>::value, VectorType>::type
convert_from_string(std::string ss, const size_t size, const size_t DXTC_DEBUG_ONLY(cols) = 0)
{
  auto vector_str = ss;
  typedef typename VectorAbstraction<VectorType>::S S;
  DXT_ASSERT(cols == 0);
  // check if this is a vector
  if (vector_str.substr(0, 1) == "[" && vector_str.substr(vector_str.size() - 1, 1) == "]") {
    vector_str = vector_str.substr(1, vector_str.size() - 2);
    // we treat this as a vector and split along ' '
    const auto tokens = tokenize<std::string>(vector_str, " ", boost::algorithm::token_compress_on);
    if (size > 0 && tokens.size() < size)
      DUNE_THROW(Exceptions::conversion_error,
                 "Vector expression (see below) has only " << tokens.size() << " elements but " << size
                                                           << " elements were requested!"
                                                           << "\n"
                                                           << "'[" << vector_str << "]'");
    const size_t automatic_size = (size > 0) ? std::min(tokens.size(), size) : tokens.size();
    const size_t actual_size =
        VectorAbstraction<VectorType>::has_static_size ? VectorAbstraction<VectorType>::static_size : automatic_size;
    if (actual_size > automatic_size)
      DUNE_THROW(Exceptions::conversion_error,
                 "Vector expression (see below) has only " << automatic_size << " elements but " << actual_size
                                                           << " elements are required for this VectorType ("
                                                           << Typename<VectorType>::value() << ")!"
                                                           << "\n"
                                                           << "'[" << vector_str << "]'");
    VectorType ret = VectorAbstraction<VectorType>::create(actual_size);
    for (size_t ii = 0; ii < actual_size; ++ii)
      ret[ii] = convert_from_string<S>(trim_copy_safely(tokens[ii]));
    return ret;
  } else {
    // we treat this as a scalar
    const auto val = convert_from_string<S>(trim_copy_safely(vector_str));
    const size_t automatic_size = (size == 0 ? 1 : size);
    const size_t actual_size =
        VectorAbstraction<VectorType>::has_static_size ? VectorAbstraction<VectorType>::static_size : automatic_size;
    if (actual_size > automatic_size && automatic_size != 1)
      DUNE_THROW(Exceptions::conversion_error,
                 "Vector expression (see below) has only " << automatic_size << " elements but " << actual_size
                                                           << " elements are required for this VectorType ("
                                                           << Typename<VectorType>::value() << ")!"
                                                           << "\n"
                                                           << "'[" << vector_str << "]'");
    VectorType ret = VectorAbstraction<VectorType>::create(actual_size);
    for (size_t ii = 0; ii < std::min(actual_size, ret.size()); ++ii)
      ret[ii] = val;
    return ret;
  }
} // ... convert_from_string(...)

template <class MatrixType>
static inline typename std::enable_if<is_matrix<MatrixType>::value, MatrixType>::type
convert_from_string(std::string matrix_str, const size_t rows, const size_t cols)
{
  typedef typename MatrixAbstraction<MatrixType>::S S;
  // check if this is a matrix
  if (matrix_str.substr(0, 1) == "[" && matrix_str.substr(matrix_str.size() - 1, 1) == "]") {
    matrix_str = matrix_str.substr(1, matrix_str.size() - 2);
    // we treat this as a matrix and split along ';' to obtain the rows
    const auto row_tokens = tokenize<std::string>(matrix_str, ";", boost::algorithm::token_compress_on);
    if (rows > 0 && row_tokens.size() < rows)
      DUNE_THROW(Exceptions::conversion_error,
                 "Matrix expression (see below) has only " << row_tokens.size() << " rows but " << rows
                                                           << " rows were requested!"
                                                           << "\n"
                                                           << "'[" << matrix_str << "]'");
    const size_t automatic_rows = (rows > 0) ? std::min(row_tokens.size(), rows) : row_tokens.size();
    const size_t actual_rows =
        MatrixAbstraction<MatrixType>::has_static_size ? MatrixAbstraction<MatrixType>::static_rows : automatic_rows;
    if (actual_rows > automatic_rows)
      DUNE_THROW(Exceptions::conversion_error,
                 "Matrix expression (see below) has only " << automatic_rows << " rows but " << actual_rows
                                                           << " rows are required for this MatrixType ("
                                                           << Typename<MatrixType>::value() << ")!"
                                                           << "\n"
                                                           << "'[" << matrix_str << "]'");
    // compute the number of columns the matrix will have
    size_t min_cols = std::numeric_limits<size_t>::max();
    for (size_t rr = 0; rr < actual_rows; ++rr) {
      const auto row_token = boost::algorithm::trim_copy(row_tokens[rr]);
      // we treat this as a vector, so we split along ' '
      const auto column_tokens = tokenize<std::string>(row_token, " ", boost::algorithm::token_compress_on);
      min_cols = std::min(min_cols, column_tokens.size());
    }
    if (cols > 0 && min_cols < cols)
      DUNE_THROW(Exceptions::conversion_error,
                 "Matrix expression (see below) has only " << min_cols << " columns but " << cols
                                                           << " columns were requested!"
                                                           << "\n"
                                                           << "'[" << matrix_str << "]'");
    const auto automatic_cols = (cols > 0) ? std::min(min_cols, cols) : min_cols;
    const size_t actual_cols =
        MatrixAbstraction<MatrixType>::has_static_size ? MatrixAbstraction<MatrixType>::static_cols : automatic_cols;
    if (actual_cols > automatic_cols)
      DUNE_THROW(Exceptions::conversion_error,
                 "Matrix expression (see below) has only " << automatic_cols << " cols but " << actual_cols
                                                           << " cols are required for this MatrixType ("
                                                           << Typename<MatrixType>::value() << ")!"
                                                           << "\n"
                                                           << "'[" << matrix_str << "]'");
    MatrixType ret = MatrixAbstraction<MatrixType>::create(actual_rows, actual_cols);
    // now we do the same again and build the actual matrix
    for (size_t rr = 0; rr < actual_rows; ++rr) {
      const std::string row_token = boost::algorithm::trim_copy(row_tokens[rr]);
      const auto column_tokens = tokenize<std::string>(row_token, " ", boost::algorithm::token_compress_on);
      for (size_t cc = 0; cc < actual_cols; ++cc)
        MatrixAbstraction<MatrixType>::set_entry(
            ret, rr, cc, convert_from_string<S>(trim_copy_safely(column_tokens[cc])));
    }
    return ret;
  } else {
    // we treat this as a scalar
    const S val = convert_from_string<S>(trim_copy_safely(matrix_str));
    const size_t automatic_rows = (rows == 0 ? 1 : rows);
    const size_t actual_rows =
        MatrixAbstraction<MatrixType>::has_static_size ? MatrixAbstraction<MatrixType>::static_rows : automatic_rows;
    if (actual_rows > automatic_rows)
      DUNE_THROW(Exceptions::conversion_error,
                 "Matrix expression (see below) has only " << automatic_rows << " rows but " << actual_rows
                                                           << " rows are required for this MatrixType ("
                                                           << Typename<MatrixType>::value() << ")!"
                                                           << "\n"
                                                           << "'[" << matrix_str << "]'");
    const size_t automatic_cols = (cols == 0 ? 1 : cols);
    const size_t actual_cols =
        MatrixAbstraction<MatrixType>::has_static_size ? MatrixAbstraction<MatrixType>::static_cols : automatic_cols;
    if (actual_cols > automatic_cols)
      DUNE_THROW(Exceptions::conversion_error,
                 "Matrix expression (see below) has only " << automatic_cols << " cols but " << actual_cols
                                                           << " cols are required for this MatrixType ("
                                                           << Typename<MatrixType>::value() << ")!"
                                                           << "\n"
                                                           << "'[" << matrix_str << "]'");
    MatrixType ret = MatrixAbstraction<MatrixType>::create(actual_rows, actual_cols);
    for (size_t rr = 0; rr < std::min(actual_rows, MatrixAbstraction<MatrixType>::rows(ret)); ++rr)
      for (size_t cc = 0; cc < std::min(actual_cols, MatrixAbstraction<MatrixType>::cols(ret)); ++cc)
        MatrixAbstraction<MatrixType>::set_entry(ret, rr, cc, val);
    return ret;
  }
} // ... convert_from_string(...)

// variant for everything that is not a matrix, a vector or any of the types specified below
template <class T>
static inline typename std::enable_if<!is_vector<T>::value && !is_matrix<T>::value, std::string>::type
convert_to_string(const T& ss, const std::size_t precision)
{
  std::ostringstream out;
  out << std::setprecision(boost::numeric_cast<int>(precision)) << ss;
  return out.str();
}

template <typename T>
static inline std::string convert_to_string(const std::complex<T>& val, const std::size_t precision)
{
  using namespace std;
  stringstream os;
  const auto im = imag(val);
  const string sign = signum(im) < 0 ? "" : "+";
  const auto real_str = convert_to_string(real(val), precision);
  const auto imag_str = convert_to_string(im, precision);
  os << real_str << sign << imag_str << "i";
  return os.str();
}

template <int size>
static inline std::string convert_to_string(const Dune::bigunsignedint<size>& ss, const std::size_t /*precision*/)
{
  std::stringstream os;
  os << ss;
  return os.str();
}

inline std::string convert_to_string(const char* ss, const std::size_t /*precision*/)
{
  return std::string(ss);
}

inline std::string convert_to_string(char ss, const std::size_t /*precision*/)
{
  return std::string(1, ss);
}

inline std::string convert_to_string(const std::string ss, const std::size_t /*precision*/)
{
  return std::string(ss);
}

// forward such that vectors of matrices can be converted
template <class M>
static inline typename std::enable_if<is_matrix<M>::value, std::string>::type
convert_to_string(const M& /*mat*/, const std::size_t /*precision*/);

template <class V>
static inline typename std::enable_if<is_vector<V>::value, std::string>::type
convert_to_string(const V& vec, const std::size_t precision)
{
  std::string ret = "[";
  for (auto ii : value_range(vec.size())) {
    if (ii > 0)
      ret += " ";
    ret += convert_to_string(vec[ii], precision);
  }
  ret += "]";
  return ret;
} // ... convert_to_string(...)

template <class M>
static inline typename std::enable_if<is_matrix<M>::value, std::string>::type
convert_to_string(const M& mat, const std::size_t precision)
{
  std::string ret = "[";
  for (auto rr : value_range(MatrixAbstraction<M>::rows(mat))) {
    if (rr > 0)
      ret += "; ";
    for (auto cc : value_range(MatrixAbstraction<M>::cols(mat))) {
      if (cc > 0)
        ret += " ";
      ret += convert_to_string(MatrixAbstraction<M>::get_entry(mat, rr, cc), precision);
    }
  }
  ret += "]";
  return ret;
} // ... convert_to_string(...)

} // namespace internal
} // namespace Common
} // namespace XT
} // namespace Dune

#endif // DUNE_XT_COMMON_STRING_INTERNAL_HH

ext: hh

max_stars_repo_name: ftschindler-work/dune-xt-common

max_issues_repo_name: ftschindler-work/dune-xt-common

max_forks_repo_name: ftschindler-work/dune-xt-common


text:
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PARSER_DETAIL_TEXT_DANGLING_HPP
#define BOOST_PARSER_DETAIL_TEXT_DANGLING_HPP

#include <boost/parser/detail/text/config.hpp>

#if defined(BOOST_TEXT_DOXYGEN) || BOOST_PARSER_USE_CONCEPTS

namespace boost::parser::detail::text {
    template<std::ranges::range R, std::ranges::view V>
    using borrowed_view_t = std::
        conditional_t<std::ranges::borrowed_range<R>, V, std::ranges::dangling>;
}

#endif

#endif

ext: hpp

max_stars_repo_name: tzlaine/parser

max_issues_repo_name: tzlaine/parser

max_forks_repo_name: tzlaine/parser


text:
#ifndef BOOST_GEOMETRY_PROJECTIONS_AEQD_HPP
#define BOOST_GEOMETRY_PROJECTIONS_AEQD_HPP

// Boost.Geometry - extensions-gis-projections (based on PROJ4)
// This file is automatically generated. DO NOT EDIT.

// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.

// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// This file is converted from PROJ4, http://trac.osgeo.org/proj
// PROJ4 is originally written by Gerald Evenden (then of the USGS)
// PROJ4 is maintained by Frank Warmerdam
// PROJ4 is converted to Boost.Geometry by Barend Gehrels

// Original copyright notice:

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include <boost/math/special_functions/hypot.hpp>

#include <boost/geometry/extensions/gis/projections/impl/base_static.hpp>
#include <boost/geometry/extensions/gis/projections/impl/base_dynamic.hpp>
#include <boost/geometry/extensions/gis/projections/impl/projects.hpp>
#include <boost/geometry/extensions/gis/projections/impl/factory_entry.hpp>
#include <boost/geometry/extensions/gis/projections/impl/aasincos.hpp>
#include <boost/geometry/extensions/gis/projections/impl/pj_mlfn.hpp>
#include <boost/geometry/extensions/gis/projections/impl/proj_mdist.hpp>

namespace boost { namespace geometry { namespace projections
{
    #ifndef DOXYGEN_NO_DETAIL
    namespace detail { namespace aeqd{
            static const double EPS10 = 1.e-10;
            static const double TOL = 1.e-14;
            static const int N_POLE = 0;
            static const int S_POLE = 1;
            static const int EQUIT = 2;
            static const int OBLIQ = 3;

            struct par_aeqd
            {
                double    sinph0;
                double    cosph0;
                double    en[EN_SIZE];
                double    M1;
                double    N1;
                double    Mp;
                double    He;
                double    G;
                int        mode;
            };

            // template class, using CRTP to implement forward/inverse
            template <typename Geographic, typename Cartesian, typename Parameters>
            struct base_aeqd_ellipsoid : public base_t_fi<base_aeqd_ellipsoid<Geographic, Cartesian, Parameters>,
                     Geographic, Cartesian, Parameters>
            {

                 typedef double geographic_type;
                 typedef double cartesian_type;

                par_aeqd m_proj_parm;

                inline base_aeqd_ellipsoid(const Parameters& par)
                    : base_t_fi<base_aeqd_ellipsoid<Geographic, Cartesian, Parameters>,
                     Geographic, Cartesian, Parameters>(*this, par) {}

                inline void fwd(geographic_type& lp_lon, geographic_type& lp_lat, cartesian_type& xy_x, cartesian_type& xy_y) const
                {
                    double  coslam, cosphi, sinphi, rho, s, H, H2, c, Az, t, ct, st, cA, sA;

                    coslam = cos(lp_lon);
                    cosphi = cos(lp_lat);
                    sinphi = sin(lp_lat);
                    switch (this->m_proj_parm.mode) {
                    case N_POLE:
                        coslam = - coslam;
                    case S_POLE:
                        xy_x = (rho = fabs(this->m_proj_parm.Mp - pj_mlfn(lp_lat, sinphi, cosphi, this->m_proj_parm.en))) *
                            sin(lp_lon);
                        xy_y = rho * coslam;
                        break;
                    case EQUIT:
                    case OBLIQ:
                        if (fabs(lp_lon) < EPS10 && fabs(lp_lat - this->m_par.phi0) < EPS10) {
                            xy_x = xy_y = 0.;
                            break;
                        }
                        t = atan2(this->m_par.one_es * sinphi + this->m_par.es * this->m_proj_parm.N1 * this->m_proj_parm.sinph0 *
                            sqrt(1. - this->m_par.es * sinphi * sinphi), cosphi);
                        ct = cos(t); st = sin(t);
                        Az = atan2(sin(lp_lon) * ct, this->m_proj_parm.cosph0 * st - this->m_proj_parm.sinph0 * coslam * ct);
                        cA = cos(Az); sA = sin(Az);
                        s = aasin( fabs(sA) < TOL ?
                            (this->m_proj_parm.cosph0 * st - this->m_proj_parm.sinph0 * coslam * ct) / cA :
                            sin(lp_lon) * ct / sA );
                        H = this->m_proj_parm.He * cA;
                        H2 = H * H;
                        c = this->m_proj_parm.N1 * s * (1. + s * s * (- H2 * (1. - H2)/6. +
                            s * ( this->m_proj_parm.G * H * (1. - 2. * H2 * H2) / 8. +
                            s * ((H2 * (4. - 7. * H2) - 3. * this->m_proj_parm.G * this->m_proj_parm.G * (1. - 7. * H2)) /
                            120. - s * this->m_proj_parm.G * H / 48.))));
                        xy_x = c * sA;
                        xy_y = c * cA;
                        break;
                    }
                }

                inline void inv(cartesian_type& xy_x, cartesian_type& xy_y, geographic_type& lp_lon, geographic_type& lp_lat) const
                {
                    double c, Az, cosAz, A, B, D, E, F, psi, t;

                    if ((c = boost::math::hypot(xy_x, xy_y)) < EPS10) {
                        lp_lat = this->m_par.phi0;
                        lp_lon = 0.;
                            return;
                    }
                    if (this->m_proj_parm.mode == OBLIQ || this->m_proj_parm.mode == EQUIT) {
                        cosAz = cos(Az = atan2(xy_x, xy_y));
                        t = this->m_proj_parm.cosph0 * cosAz;
                        B = this->m_par.es * t / this->m_par.one_es;
                        A = - B * t;
                        B *= 3. * (1. - A) * this->m_proj_parm.sinph0;
                        D = c / this->m_proj_parm.N1;
                        E = D * (1. - D * D * (A * (1. + A) / 6. + B * (1. + 3.*A) * D / 24.));
                        F = 1. - E * E * (A / 2. + B * E / 6.);
                        psi = aasin(this->m_proj_parm.sinph0 * cos(E) + t * sin(E));
                        lp_lon = aasin(sin(Az) * sin(E) / cos(psi));
                        if ((t = fabs(psi)) < EPS10)
                            lp_lat = 0.;
                        else if (fabs(t - HALFPI) < 0.)
                            lp_lat = HALFPI;
                        else
                            lp_lat = atan((1. - this->m_par.es * F * this->m_proj_parm.sinph0 / sin(psi)) * tan(psi) /
                                this->m_par.one_es);
                    } else { /* Polar */
                        lp_lat = pj_inv_mlfn(this->m_proj_parm.mode == N_POLE ? this->m_proj_parm.Mp - c : this->m_proj_parm.Mp + c,
                            this->m_par.es, this->m_proj_parm.en);
                        lp_lon = atan2(xy_x, this->m_proj_parm.mode == N_POLE ? -xy_y : xy_y);
                    }
                }
            };

            // template class, using CRTP to implement forward/inverse
            template <typename Geographic, typename Cartesian, typename Parameters>
            struct base_aeqd_guam : public base_t_fi<base_aeqd_guam<Geographic, Cartesian, Parameters>,
                     Geographic, Cartesian, Parameters>
            {

                 typedef double geographic_type;
                 typedef double cartesian_type;

                par_aeqd m_proj_parm;

                inline base_aeqd_guam(const Parameters& par)
                    : base_t_fi<base_aeqd_guam<Geographic, Cartesian, Parameters>,
                     Geographic, Cartesian, Parameters>(*this, par) {}

                inline void fwd(geographic_type& lp_lon, geographic_type& lp_lat, cartesian_type& xy_x, cartesian_type& xy_y) const
                {
                    double  cosphi, sinphi, t;

                    cosphi = cos(lp_lat);
                    sinphi = sin(lp_lat);
                    t = 1. / sqrt(1. - this->m_par.es * sinphi * sinphi);
                    xy_x = lp_lon * cosphi * t;
                    xy_y = pj_mlfn(lp_lat, sinphi, cosphi, this->m_proj_parm.en) - this->m_proj_parm.M1 +
                        .5 * lp_lon * lp_lon * cosphi * sinphi * t;
                }

                inline void inv(cartesian_type& xy_x, cartesian_type& xy_y, geographic_type& lp_lon, geographic_type& lp_lat) const
                {
                    double x2, t;
                    int i;

                    x2 = 0.5 * xy_x * xy_x;
                    lp_lat = this->m_par.phi0;
                    for (i = 0; i < 3; ++i) {
                        t = this->m_par.e * sin(lp_lat);
                        lp_lat = pj_inv_mlfn(this->m_proj_parm.M1 + xy_y -
                            x2 * tan(lp_lat) * (t = sqrt(1. - t * t)), this->m_par.es, this->m_proj_parm.en);
                    }
                    lp_lon = xy_x * t / cos(lp_lat);
                }
            };

            // template class, using CRTP to implement forward/inverse
            template <typename Geographic, typename Cartesian, typename Parameters>
            struct base_aeqd_spheroid : public base_t_fi<base_aeqd_spheroid<Geographic, Cartesian, Parameters>,
                     Geographic, Cartesian, Parameters>
            {

                 typedef double geographic_type;
                 typedef double cartesian_type;

                par_aeqd m_proj_parm;

                inline base_aeqd_spheroid(const Parameters& par)
                    : base_t_fi<base_aeqd_spheroid<Geographic, Cartesian, Parameters>,
                     Geographic, Cartesian, Parameters>(*this, par) {}

                inline void fwd(geographic_type& lp_lon, geographic_type& lp_lat, cartesian_type& xy_x, cartesian_type& xy_y) const
                {
                    double  coslam, cosphi, sinphi;

                    sinphi = sin(lp_lat);
                    cosphi = cos(lp_lat);
                    coslam = cos(lp_lon);
                    switch (this->m_proj_parm.mode) {
                    case EQUIT:
                        xy_y = cosphi * coslam;
                        goto oblcon;
                    case OBLIQ:
                        xy_y = this->m_proj_parm.sinph0 * sinphi + this->m_proj_parm.cosph0 * cosphi * coslam;
                oblcon:
                        if (fabs(fabs(xy_y) - 1.) < TOL)
                            if (xy_y < 0.)
                                throw proj_exception();
                            else
                                xy_x = xy_y = 0.;
                        else {
                            xy_y = acos(xy_y);
                            xy_y /= sin(xy_y);
                            xy_x = xy_y * cosphi * sin(lp_lon);
                            xy_y *= (this->m_proj_parm.mode == EQUIT) ? sinphi :
                                   this->m_proj_parm.cosph0 * sinphi - this->m_proj_parm.sinph0 * cosphi * coslam;
                        }
                        break;
                    case N_POLE:
                        lp_lat = -lp_lat;
                        coslam = -coslam;
                    case S_POLE:
                        if (fabs(lp_lat - HALFPI) < EPS10) throw proj_exception();;
                        xy_x = (xy_y = (HALFPI + lp_lat)) * sin(lp_lon);
                        xy_y *= coslam;
                        break;
                    }
                }

                inline void inv(cartesian_type& xy_x, cartesian_type& xy_y, geographic_type& lp_lon, geographic_type& lp_lat) const
                {
                    double cosc, c_rh, sinc;

                    if ((c_rh = boost::math::hypot(xy_x, xy_y)) > PI) {
                        if (c_rh - EPS10 > PI) throw proj_exception();;
                        c_rh = PI;
                    } else if (c_rh < EPS10) {
                        lp_lat = this->m_par.phi0;
                        lp_lon = 0.;
                            return;
                    }
                    if (this->m_proj_parm.mode == OBLIQ || this->m_proj_parm.mode == EQUIT) {
                        sinc = sin(c_rh);
                        cosc = cos(c_rh);
                        if (this->m_proj_parm.mode == EQUIT) {
                                        lp_lat = aasin(xy_y * sinc / c_rh);
                            xy_x *= sinc;
                            xy_y = cosc * c_rh;
                        } else {
                            lp_lat = aasin(cosc * this->m_proj_parm.sinph0 + xy_y * sinc * this->m_proj_parm.cosph0 /
                                c_rh);
                            xy_y = (cosc - this->m_proj_parm.sinph0 * sin(lp_lat)) * c_rh;
                            xy_x *= sinc * this->m_proj_parm.cosph0;
                        }
                        lp_lon = xy_y == 0. ? 0. : atan2(xy_x, xy_y);
                    } else if (this->m_proj_parm.mode == N_POLE) {
                        lp_lat = HALFPI - c_rh;
                        lp_lon = atan2(xy_x, -xy_y);
                    } else {
                        lp_lat = c_rh - HALFPI;
                        lp_lon = atan2(xy_x, xy_y);
                    }
                }
            };

            // Azimuthal Equidistant
            template <typename Parameters>
            void setup_aeqd(Parameters& par, par_aeqd& proj_parm)
            {
                par.phi0 = pj_param(par.params, "rlat_0").f;
                if (fabs(fabs(par.phi0) - HALFPI) < EPS10) {
                    proj_parm.mode = par.phi0 < 0. ? S_POLE : N_POLE;
                    proj_parm.sinph0 = par.phi0 < 0. ? -1. : 1.;
                    proj_parm.cosph0 = 0.;
                } else if (fabs(par.phi0) < EPS10) {
                    proj_parm.mode = EQUIT;
                    proj_parm.sinph0 = 0.;
                    proj_parm.cosph0 = 1.;
                } else {
                    proj_parm.mode = OBLIQ;
                    proj_parm.sinph0 = sin(par.phi0);
                    proj_parm.cosph0 = cos(par.phi0);
                }
                if (! par.es) {
                // par.inv = s_inverse;
                // par.fwd = s_forward;
                } else {
                    pj_enfn(par.es, proj_parm.en);
                    if (pj_param(par.params, "bguam").i) {
                        proj_parm.M1 = pj_mlfn(par.phi0, proj_parm.sinph0, proj_parm.cosph0, proj_parm.en);
                // par.inv = e_guam_inv;
                // par.fwd = e_guam_fwd;
                    } else {
                        switch (proj_parm.mode) {
                        case N_POLE:
                            proj_parm.Mp = pj_mlfn(HALFPI, 1., 0., proj_parm.en);
                            break;
                        case S_POLE:
                            proj_parm.Mp = pj_mlfn(-HALFPI, -1., 0., proj_parm.en);
                            break;
                        case EQUIT:
                        case OBLIQ:
                // par.inv = e_inverse;
                // par.fwd = e_forward;
                            proj_parm.N1 = 1. / sqrt(1. - par.es * proj_parm.sinph0 * proj_parm.sinph0);
                            proj_parm.G = proj_parm.sinph0 * (proj_parm.He = par.e / sqrt(par.one_es));
                            proj_parm.He *= proj_parm.cosph0;
                            break;
                        }
                // par.inv = e_inverse;
                // par.fwd = e_forward;
                    }
                }
            }

        }} // namespace detail::aeqd
    #endif // doxygen

    /*!
        \brief Azimuthal Equidistant projection
        \ingroup projections
        \tparam Geographic latlong point type
        \tparam Cartesian xy point type
        \tparam Parameters parameter type
        \par Projection characteristics
         - Azimuthal
         - Spheroid
         - Ellipsoid
         - lat_0 guam
        \par Example
        \image html ex_aeqd.gif
    */
    template <typename Geographic, typename Cartesian, typename Parameters = parameters>
    struct aeqd_ellipsoid : public detail::aeqd::base_aeqd_ellipsoid<Geographic, Cartesian, Parameters>
    {
        inline aeqd_ellipsoid(const Parameters& par) : detail::aeqd::base_aeqd_ellipsoid<Geographic, Cartesian, Parameters>(par)
        {
            detail::aeqd::setup_aeqd(this->m_par, this->m_proj_parm);
        }
    };

    /*!
        \brief Azimuthal Equidistant projection
        \ingroup projections
        \tparam Geographic latlong point type
        \tparam Cartesian xy point type
        \tparam Parameters parameter type
        \par Projection characteristics
         - Azimuthal
         - Spheroid
         - Ellipsoid
         - lat_0 guam
        \par Example
        \image html ex_aeqd.gif
    */
    template <typename Geographic, typename Cartesian, typename Parameters = parameters>
    struct aeqd_guam : public detail::aeqd::base_aeqd_guam<Geographic, Cartesian, Parameters>
    {
        inline aeqd_guam(const Parameters& par) : detail::aeqd::base_aeqd_guam<Geographic, Cartesian, Parameters>(par)
        {
            detail::aeqd::setup_aeqd(this->m_par, this->m_proj_parm);
        }
    };

    /*!
        \brief Azimuthal Equidistant projection
        \ingroup projections
        \tparam Geographic latlong point type
        \tparam Cartesian xy point type
        \tparam Parameters parameter type
        \par Projection characteristics
         - Azimuthal
         - Spheroid
         - Ellipsoid
         - lat_0 guam
        \par Example
        \image html ex_aeqd.gif
    */
    template <typename Geographic, typename Cartesian, typename Parameters = parameters>
    struct aeqd_spheroid : public detail::aeqd::base_aeqd_spheroid<Geographic, Cartesian, Parameters>
    {
        inline aeqd_spheroid(const Parameters& par) : detail::aeqd::base_aeqd_spheroid<Geographic, Cartesian, Parameters>(par)
        {
            detail::aeqd::setup_aeqd(this->m_par, this->m_proj_parm);
        }
    };

    #ifndef DOXYGEN_NO_DETAIL
    namespace detail
    {

        // Factory entry(s)
        template <typename Geographic, typename Cartesian, typename Parameters>
        class aeqd_entry : public detail::factory_entry<Geographic, Cartesian, Parameters>
        {
            public :
                virtual projection<Geographic, Cartesian>* create_new(const Parameters& par) const
                {
                    if (! par.es)
                        return new base_v_fi<aeqd_spheroid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
                    else if (pj_param(par.params, "bguam").i)
                        return new base_v_fi<aeqd_guam<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
                    else
                        return new base_v_fi<aeqd_ellipsoid<Geographic, Cartesian, Parameters>, Geographic, Cartesian, Parameters>(par);
                }
        };

        template <typename Geographic, typename Cartesian, typename Parameters>
        inline void aeqd_init(detail::base_factory<Geographic, Cartesian, Parameters>& factory)
        {
            factory.add_to_factory("aeqd", new aeqd_entry<Geographic, Cartesian, Parameters>);
        }

    } // namespace detail
    #endif // doxygen

}}} // namespace boost::geometry::projections

#endif // BOOST_GEOMETRY_PROJECTIONS_AEQD_HPP

max_stars_repo_name: ballisticwhisper/boost

max_issues_repo_name: ballisticwhisper/boost

max_forks_repo_name: ballisticwhisper/boost


text:
//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/CPPAlliance/url
//

#ifndef BOOST_URL_IMPL_SEGMENTS_VIEW_IPP
#define BOOST_URL_IMPL_SEGMENTS_VIEW_IPP

#include <boost/url/segments_view.hpp>
#include <boost/url/detail/pct_encoding.hpp>
#include <boost/url/grammar/parse.hpp>
#include <boost/url/rfc/paths_rule.hpp>
#include <boost/assert.hpp>
#include <ostream>

namespace boost {
namespace urls {

//------------------------------------------------
//
// Iterators
//
//------------------------------------------------

auto
segments_view::
begin() const noexcept ->
    iterator
{
    return iterator(s_, n_, a_);
}

auto
segments_view::
end() const noexcept ->
    iterator
{
    return iterator(s_, n_, a_, 0);
}

//------------------------------------------------
//
// Friends
//
//------------------------------------------------

std::ostream&
operator<<(
    std::ostream& os,
    segments_view const& vw)
{
    auto it = vw.begin();
    auto const end = vw.end();
    if( it != end )
    {
        if( vw.is_absolute() )
            os << "/";
        os << *it;
        while( ++it != end )
            os << '/' << *it;
    }
    return os;
}

} // urls
} // boost

#endif

ext: ipp

max_stars_repo_name: abitmore/url

max_issues_repo_name: abitmore/url

max_forks_repo_name: alandefreitas/url


text:
#include <iostream>
#include <fstream>
#include <boost/utility.hpp>
#include <cassert>
#include <set>
#include <string>

#include "CLHEP/Vector/LorentzVector.h"
#include "CLHEP/Vector/ThreeVector.h"
#include "CLHEP/Units/SystemOfUnits.h"

#include "fhiclcpp/types/Name.h"
#include "art/Framework/IO/Sources/Source.h"
#include "art/Framework/Core/InputSourceMacros.h"
#include "art/Framework/IO/Sources/SourceHelper.h"
#include "art/Framework/Principal/RunPrincipal.h"
#include "art/Framework/Principal/SubRunPrincipal.h"
#include "art/Framework/Principal/EventPrincipal.h"
#include "art/Framework/IO/Sources/put_product_in_principal.h"
#include "canvas/Persistency/Provenance/Timestamp.h"
#include "canvas/Persistency/Provenance/RunID.h"
#include "canvas/Persistency/Provenance/SubRunID.h"
#include "canvas/Persistency/Provenance/EventID.h"
#include "canvas/Persistency/Provenance/BranchType.h"
#include "canvas/Persistency/Provenance/ProductID.h"
#include "canvas/Persistency/Provenance/canonicalProductName.h"
#include "art/Framework/Principal/Event.h"
#include "art/Framework/Services/Registry/ServiceHandle.h"

#include "Offline/RecoDataProducts/inc/StrawDigi.hh"
#include "Offline/DataProducts/inc/TrkTypes.hh"
#include "Offline/DataProducts/inc/StrawId.hh"

#include "TTree.h"
#include "TFile.h"
#include "TBranch.h"

#include "Offline/SeedService/inc/SeedService.hh"

using CLHEP::Hep3Vector;
using CLHEP::HepLorentzVector;

using namespace std;

namespace mu2e {
  struct Config
  {
    using Name = fhicl::Name;
    using Comment = fhicl::Comment;
    fhicl::Sequence<std::string> inputFiles{Name("fileNames"),Comment("Input flat TTree Root file")};
    fhicl::Atom<unsigned int> runNumber{Name("runNumber"), Comment("Run number")};
    fhicl::Atom<unsigned int> maxEvents{Name("maxEvents"), Comment("Max number of events"), 0};

    // These are used by art and are required.
    fhicl::Atom<std::string> module_label{Name("module_label"), Comment("Art module label"), ""};
    fhicl::Atom<std::string> module_type{Name("module_type"), Comment("Art module type"), ""};
  };
  typedef fhicl::WrappedTable<Config> Parameters;

  //================================================================
  class TrackerPrototypeDataDetail : private boost::noncopyable {
    std::string myModuleLabel_;
    art::SourceHelper const& pm_;
    unsigned runNumber_; // from ParSet
    art::SubRunID lastSubRunID_;
    std::set<art::SubRunID> seenSRIDs_;

    std::string currentFileName_;

    TFile *currentFile_ = nullptr;
    TTree *tree_ = nullptr;

    TBranch *bsamples;
    int _panel, _channel;
    int _run;
    uint32_t _ewm;
    uint32_t _tdcCal, _tdcHV;
    uint16_t _totCal, _totHV;
    uint16_t _pmp;
    std::vector<uint16_t> *_samples = 0;
    int entryIndex_;

    mu2e::StrawDigiCollection digis_;
    mu2e::StrawDigiADCWaveformCollection digiadcs_;

    unsigned currentSubRunNumber_; // from file
    unsigned currentEventNumber_;
    unsigned maxEvents_;

    bool first_call;
    int printAtEvent;
    int currentEvent;

    // A helper function used to manage the principals.
    // This is boilerplate that does not change if you change the data products.
    void managePrincipals ( int runNumber,
        int subRunNumber,
        int eventNumber,
        art::RunPrincipal*&    outR,
        art::SubRunPrincipal*& outSR,
        art::EventPrincipal*&  outE);

    public:
    TrackerPrototypeDataDetail(const Parameters &conf,
        art::ProductRegistryHelper &,
        const art::SourceHelper &);

    void readFile(std::string const& filename, art::FileBlock*& fb);

    bool readNext(art::RunPrincipal* const& inR,
        art::SubRunPrincipal* const& inSR,
        art::RunPrincipal*& outR,
        art::SubRunPrincipal*& outSR,
        art::EventPrincipal*& outE);

    void closeCurrentFile();
  };

  //----------------------------------------------------------------
  TrackerPrototypeDataDetail::TrackerPrototypeDataDetail(const Parameters& conf,
      art::ProductRegistryHelper& rh,
      const art::SourceHelper& pm)
    : myModuleLabel_("FromTrackerPrototypeData")
      , pm_(pm)
      , runNumber_(conf().runNumber())
      , currentSubRunNumber_(-1U)
      , currentEventNumber_(0)
      , maxEvents_(conf().maxEvents())
  {
    if(!art::RunID(runNumber_).isValid()) {
      throw cet::exception("BADCONFIG", " FromTrackerPrototypeData: ")
        << " fhicl::ParameterSet specifies an invalid runNumber = "<<runNumber_<<"\n";
    }

    rh.reconstitutes<mu2e::StrawDigiCollection,art::InEvent>(myModuleLabel_);
    rh.reconstitutes<mu2e::StrawDigiADCWaveformCollection,art::InEvent>(myModuleLabel_);

    currentFileName_ = conf().inputFiles()[0];

    currentFile_ = new TFile(currentFileName_.c_str());
    tree_ = dynamic_cast<TTree*>(currentFile_->Get("T"));

    tree_->SetBranchAddress("run",&_run);
    tree_->SetBranchAddress("panel",&_panel);
    tree_->SetBranchAddress("channel",&_channel);
    tree_->SetBranchAddress("ewm",&_ewm);
    tree_->SetBranchAddress("tdcCal",&_tdcCal);
    tree_->SetBranchAddress("tdcHV",&_tdcHV);
    tree_->SetBranchAddress("totCal",&_totCal);
    tree_->SetBranchAddress("totHV",&_totHV);
    tree_->SetBranchAddress("pmp",&_pmp);

    bsamples = 0;
    tree_->SetBranchAddress("samples",&_samples,&bsamples);

    entryIndex_ = 0;

    tree_->GetEntry(0);
    currentSubRunNumber_ = _run;
    currentEventNumber_ = _ewm;

    first_call = true;
    printAtEvent = 0;
    currentEvent = 0;

  }

  //----------------------------------------------------------------
  void TrackerPrototypeDataDetail::readFile(const std::string& filename, art::FileBlock*& fb) {

    currentFileName_ = filename;

    currentFile_ = new TFile(currentFileName_.c_str());
    tree_ = dynamic_cast<TTree*>(currentFile_->Get("T"));

    tree_->SetBranchAddress("run",&_run);
    tree_->SetBranchAddress("panel",&_panel);
    tree_->SetBranchAddress("channel",&_channel);
    tree_->SetBranchAddress("ewm",&_ewm);
    tree_->SetBranchAddress("tdcCal",&_tdcCal);
    tree_->SetBranchAddress("tdcHV",&_tdcHV);
    tree_->SetBranchAddress("totCal",&_totCal);
    tree_->SetBranchAddress("totHV",&_totHV);
    tree_->SetBranchAddress("pmp",&_pmp);

    bsamples = 0;
    tree_->SetBranchAddress("samples",&_samples,&bsamples);

    entryIndex_ = 0;

    tree_->GetEntry(0);
    currentSubRunNumber_ = _run;
    currentEventNumber_ = _ewm;

    fb = new art::FileBlock(art::FileFormatVersion(1, "TrackerPrototypeDataInput"), currentFileName_);
  }

  //----------------------------------------------------------------
  void TrackerPrototypeDataDetail::closeCurrentFile() {
    currentFileName_ = "";
    currentFile_->Close();
  }

  //----------------------------------------------------------------
  bool TrackerPrototypeDataDetail::readNext(art::RunPrincipal* const& inR,
      art::SubRunPrincipal* const& inSR,
      art::RunPrincipal*& outR,
      art::SubRunPrincipal*& outSR,
      art::EventPrincipal*& outE)
  {
    if (maxEvents_ > 0 && static_cast<unsigned int>(currentEvent) >= maxEvents_)
      return false;
    while (true) {
      if (entryIndex_ >= tree_->GetEntries()){
        return false;
      }

      tree_->GetEntry(entryIndex_);
      if (static_cast<unsigned>(_run) != currentSubRunNumber_ || _ewm != currentEventNumber_){
        managePrincipals(runNumber_, currentSubRunNumber_, currentEventNumber_, outR, outSR, outE);
        std::unique_ptr<mu2e::StrawDigiCollection> updigis(new mu2e::StrawDigiCollection);
        for (size_t i=0;i<digis_.size();i++){
          updigis->push_back(digis_[i]);
        }
        std::unique_ptr<mu2e::StrawDigiADCWaveformCollection> updigiadcs(new mu2e::StrawDigiADCWaveformCollection);
        for (size_t i=0;i<digiadcs_.size();i++){
          updigiadcs->push_back(digiadcs_[i]);
        }
        art::put_product_in_principal(std::move(updigis), *outE, myModuleLabel_);
        art::put_product_in_principal(std::move(updigiadcs), *outE, myModuleLabel_);
        digis_.clear();
        digiadcs_.clear();
        currentSubRunNumber_ = _run;
        currentEventNumber_ = _ewm;
        return true;
      }

      mu2e::TrkTypes::TDCValues tdcs = {_tdcCal, _tdcHV};
      mu2e::TrkTypes::TOTValues tots = {_totCal, _totHV};
      mu2e::TrkTypes::ADCValue firmwarepmp = _pmp;
      mu2e::TrkTypes::ADCWaveform adc;

      Long64_t tentry = tree_->LoadTree(entryIndex_);
      bsamples->GetEntry(tentry);
      for (size_t j=0;j<_samples->size();j++){
        adc.push_back(_samples->at(j));
      }
      mu2e::StrawId sid(0,_panel,_channel);
      auto sd = mu2e::StrawDigi(sid,tdcs,tots,firmwarepmp);
      auto sda = mu2e::StrawDigiADCWaveform(adc);
      digis_.push_back(sd);
      digiadcs_.push_back(sda);
      entryIndex_++;

      if (entryIndex_ == tree_->GetEntries()){
        managePrincipals(runNumber_, currentSubRunNumber_, currentEventNumber_, outR, outSR, outE);
        std::unique_ptr<mu2e::StrawDigiCollection> updigis(new mu2e::StrawDigiCollection);
        for (size_t i=0;i<digis_.size();i++){
          updigis->push_back(digis_[i]);
        }
        std::unique_ptr<mu2e::StrawDigiADCWaveformCollection> updigiadcs(new mu2e::StrawDigiADCWaveformCollection);
        for (size_t i=0;i<digiadcs_.size();i++){
          updigiadcs->push_back(digiadcs_[i]);
        }
        art::put_product_in_principal(std::move(updigis), *outE, myModuleLabel_);
        art::put_product_in_principal(std::move(updigiadcs), *outE, myModuleLabel_);
        digis_.clear();
        digiadcs_.clear();
        std::cout << "DONE!" << std::endl;
        return true;
      }
    }
    return true;
  } // readNext()

  // Each time that we encounter a new run, a new subRun or a new event, we need to make a new principal
  // of the appropriate type.  This code does not need to change as the number and type of data products changes.
  void TrackerPrototypeDataDetail::managePrincipals ( int runNumber,
      int subRunNumber,
      int eventNumber,
      art::RunPrincipal*&    outR,
      art::SubRunPrincipal*& outSR,
      art::EventPrincipal*&  outE){

    art::Timestamp ts;

    if (currentEvent == printAtEvent){
      std::cout << "Event " << currentEvent << std::endl;
      printAtEvent = (printAtEvent+1)*2-1;
    }
    currentEvent++;

    if (first_call){
      outR = pm_.makeRunPrincipal(runNumber, ts);
      first_call = false;
    }
    art::SubRunID newID(runNumber, subRunNumber);

    if(newID != lastSubRunID_) {
      std::cout << "Subrun " << subRunNumber << std::endl;
      // art takes ownership of the object pointed to by outSR and will delete it at the appropriate time.
      outSR = pm_.makeSubRunPrincipal(runNumber,
          subRunNumber,
          ts);

    }
    lastSubRunID_ = newID;

    // art takes ownership of the object pointed to by outE and will delete it at the appropriate time.
    outE = pm_.makeEventPrincipal(runNumber, subRunNumber, eventNumber, ts, false);

  } // managePrincipals()
  //----------------------------------------------------------------

} // namespace mu2e

typedef art::Source<mu2e::TrackerPrototypeDataDetail> FromTrackerPrototypeData;
DEFINE_ART_INPUT_SOURCE(FromTrackerPrototypeData);

ext: cc


text:
#include <boost/property_tree/json_parser.hpp>

#include <fstream>
#include <gtest/gtest.h>
#include <ed25519-donna/ed25519.h>
#include <vector>

#include <logos/lib/utility.hpp>
#include <logos/node/common.hpp>
#include <logos/consensus/messages/messages.hpp>
#include <logos/consensus/messages/rejection.hpp>
#include <logos/consensus/persistence/nondel_persistence.hpp>
#include <logos/consensus/persistence/epoch/nondel_epoch_persistence.hpp>
#include <logos/consensus/persistence/request/nondel_request_persistence.hpp>
#include <logos/consensus/persistence/microblock/nondel_microblock_persistence.hpp>

#include <logos/unit_test/msg_validator_setup.hpp>

using namespace std;

#define Unit_Test_Crypto_BLS
#define Unit_Test_Read_Write
#define Unit_Test_Msg
#define Unit_Test_Single_Block
#define Unit_Test_Consensus_Block
#define Unit_Test_Msg_Validator
#define Unit_Test_DB

void init_ecies(ECIESPublicKey &ecies)
{
    ecies.FromHexString("8e1ad798008baac3663c0c1a6ce04c7cb632eb504562de923845fccf39d1c46dee"
                        "52df70f6cf46f1351ce7ac8e92055e5f168f5aff24bcaab7513d447fd677d3");
}

Delegate init_delegate(AccountAddress account, Amount vote, Amount stake, bool starting_term)
{
    ECIESPublicKey ecies;
    init_ecies(ecies);
    std::string bls_pub_str("BA64DB0880DBB3E3F7D31AD9E1BE820EF2048AAE2CEC506C9C0F7D64C63FD716E4BAC2D76BBEC6788DAE2C9526161DC72DE9CCA762C40758794342A477240117");
    DelegatePubKey pub;
    pub.from_hex_string(bls_pub_str);
    return {account, pub, ecies, vote, stake, starting_term};
}

std::string byte_vector_to_string (const std::vector<uint8_t> & buf)
{
    std::stringstream stream;
    for(size_t i = 0; i < buf.size(); ++i)
    {
        stream << std::hex << std::noshowbase << std::setw (2) << std::setfill ('0') << (unsigned int)(buf[i]);
    }
    return stream.str ();
}

PrePrepareMessage<ConsensusType::Request>
create_bsb_preprepare(uint16_t num_sb)
{
    PrePrepareMessage<ConsensusType::Request> block;
    block.requests.reserve(num_sb);
    block.hashes.reserve(num_sb);
    for(uint32_t i = 0; i < num_sb; ++i)
    {
        block.AddRequest(std::make_shared<Send>(Send(1, 2, i, 5, 6, 7, 8)));
    }

    return block;
}

template<ConsensusType CT>
PostCommittedBlock<CT> create_approved_block(PrePrepareMessage<CT> & preperpare)
{
    AggSignature    post_prepare_sig;
    AggSignature    post_commit_sig;

    post_prepare_sig.map = 12;
    post_prepare_sig.sig = 34;
    post_commit_sig.map = 56;
    post_commit_sig.sig = 78;

    return PostCommittedBlock<CT>(preperpare, post_prepare_sig, post_commit_sig);
}

PrePrepareMessage<ConsensusType::MicroBlock> create_mb_preprepare()
{
    PrePrepareMessage<ConsensusType::MicroBlock> block;
    block.last_micro_block = 1;
    block.number_batch_blocks = 2;
    for(uint8_t i = 0; i < NUM_DELEGATES; ++i)
    {
        block.tips[i].digest = i;
    }
    return block;
}

PrePrepareMessage<ConsensusType::Epoch> create_eb_preprepare(bool starting_term = true)
{
    PrePrepareMessage<ConsensusType::Epoch> block;
    block.micro_block_tip.digest = 1234;
    block.transaction_fee_pool = 0;
    for(uint8_t i = 0; i < NUM_DELEGATES; ++i)
    {
        block.delegates[i] = init_delegate(i, i, i, i && starting_term);
    }
    return block;
}

///////////////////////////////// utils tests
TEST (crypto, ed25519)
{
    AccountPrivKey prv (0);
    AccountPubKey pub;
    ed25519_publickey (prv.data (), pub.data ());
    BlockHash message (1234567890);
    AccountSig signature;
    ed25519_sign (message.data (), HASH_SIZE, prv.data (), pub.data (), signature.data ());
    auto valid1 (ed25519_sign_open (message.data (), HASH_SIZE, pub.data (), signature.data ()));
    ASSERT_EQ (0, valid1);
    signature.data()[32] ^= 0x1;
    auto valid2 (ed25519_sign_open (message.data (), HASH_SIZE, pub.data (), signature.data ()));
    ASSERT_NE (0, valid2);
}

TEST (crypto, blake2b)
{
    struct HashData
    {
        uint8_t x;
        HashData(uint8_t x):x(x){}
        void Hash(blake2b_state & hash) const
        {
            blake2b_update(&hash, this, sizeof(HashData));
        }
    };

    auto a = Blake2bHash<HashData>(HashData(1));
    auto b = Blake2bHash<HashData>(HashData(1));
    auto c = Blake2bHash<HashData>(HashData(3));

    ASSERT_EQ(a, b);
    ASSERT_NE(b, c);
}

#ifdef Unit_Test_Crypto_BLS
TEST (crypto, bls)
{
    auto nodes = setup_nodes();
    SigVec sigs;
    BlockHash msg(123);

    //sign
    for(uint8_t i = 0; i < NUM_DELEGATES; ++i)
    {
        auto & validator = nodes[i]->validator;
        MessageValidator::DelegateSignature sig;
        sig.delegate_id = i;
        validator.Sign(msg, sig.signature);
        sigs.push_back(sig);
    }
    //single verify
    for(uint8_t i = 0; i < NUM_DELEGATES; ++i)
    {
        auto & validator = nodes[i]->validator;
        for(uint8_t j = 0; j < NUM_DELEGATES; ++j)
        {
            ASSERT_TRUE(validator.Validate(msg, sigs[j].signature, sigs[j].delegate_id));
        }
    }
    //aggregate
    uint8_t primary = 7;
    AggSignature agg_sig;
    std::unordered_map<uint8_t,MessageValidator::DelegateSignature> map;
    for(auto& x: sigs)
    {
        map[x.delegate_id] = x;
    }
    nodes[primary]->validator.AggregateSignature(map, agg_sig);
    //verify
    for(uint8_t i = 0; i < NUM_DELEGATES; ++i)
    {
        auto & validator = nodes[i]->validator;
        ASSERT_TRUE(validator.Validate(msg, agg_sig));
    }

    //error cases
    BlockHash wrong_msg(45); //wrong_msg
    for(uint8_t i = 0; i < NUM_DELEGATES; ++i)
    {
        auto & validator = nodes[i]->validator;
        for(uint8_t j = 0; j < NUM_DELEGATES; ++j)
        {
            ASSERT_FALSE(validator.Validate(wrong_msg, sigs[j].signature, sigs[j].delegate_id));
        }
    }

    DelegateSig wrong_sig = 12; //wrong_sig
    for(uint8_t i = 0; i < NUM_DELEGATES; ++i)
    {
        auto & validator = nodes[i]->validator;
        for(uint8_t j = 0; j < NUM_DELEGATES; ++j)
        {
            ASSERT_FALSE(validator.Validate(msg, wrong_sig, sigs[j].delegate_id));
        }
    }

    for(uint8_t i = 0; i < NUM_DELEGATES; ++i)
    {
        auto & validator = nodes[i]->validator;
        for(uint8_t j = 0; j < NUM_DELEGATES; ++j)
        {
            uint8_t wrong_id = sigs[j].delegate_id+1; //wrong_id
            ASSERT_FALSE(validator.Validate(msg, sigs[j].signature, wrong_id));
        }
    }

    for(uint8_t i = 0; i < NUM_DELEGATES; ++i)
    {
        auto & validator = nodes[i]->validator;
        ASSERT_FALSE(validator.Validate(wrong_msg, agg_sig)); //wrong_msg, agg_verify
    }

    AggSignature wrong_agg_sig = agg_sig;//wrong_agg_sig, agg_verify
    wrong_agg_sig.map.flip(3);
    for(uint8_t i = 0; i < NUM_DELEGATES; ++i)
    {
        auto & validator = nodes[i]->validator;
        ASSERT_FALSE(validator.Validate(msg, wrong_agg_sig));
    }
}
#endif

#ifdef Unit_Test_Read_Write
TEST (write_read, all)
{
    BlockHash hash = 1;
    DelegateSig dsig = 2;
    DelegatePubKey dpub = 3;
    DelegatePrivKey dpriv = 4;
    AccountAddress aa = 5;
    AccountPubKey apub = 6;
    AccountPrivKey apriv = 7;
    AccountSig asig = 8;
    Amount amount = 9;
    uint64_t ui64 = 10;

    BlockHash hash2;
    DelegateSig dsig2;
    DelegatePubKey dpub2;
    DelegatePrivKey dpriv2;
    AccountAddress aa2;
    AccountPubKey apub2;
    AccountPrivKey apriv2;
    AccountSig asig2;
    Amount amount2;
    uint64_t ui642;

    std::vector<uint8_t> buf;
    {
        logos::vectorstream write_stream(buf);
        logos::write(write_stream, hash);
        logos::write(write_stream, dsig);
        logos::write(write_stream, dpub);
        logos::write(write_stream, dpriv);
        logos::write(write_stream, aa);
        logos::write(write_stream, apub);
        logos::write(write_stream, apriv);
        logos::write(write_stream, asig);
        logos::write(write_stream, amount);
        logos::write(write_stream, ui64);
    }
    //std::cout << "buf.size=" << buf.size() << std::endl;

    logos::bufferstream read_stream(buf.data(), buf.size());
    logos::read(read_stream, hash2);
    logos::read(read_stream, dsig2);
    logos::read(read_stream, dpub2);
    logos::read(read_stream, dpriv2);
    logos::read(read_stream, aa2);
    logos::read(read_stream, apub2);
    logos::read(read_stream, apriv2);
    logos::read(read_stream, asig2);
    logos::read(read_stream, amount2);
    logos::read(read_stream, ui642);

    ASSERT_EQ(hash, hash2);
    ASSERT_EQ(dsig, dsig2);
    ASSERT_EQ(dpub, dpub2);
    ASSERT_EQ(dpriv, dpriv2);
    ASSERT_EQ(aa, aa2);
    ASSERT_EQ(apub, apub2);
    ASSERT_EQ(apriv, apriv2);
    ASSERT_EQ(asig, asig2);
    ASSERT_EQ(amount, amount2);
    ASSERT_EQ(ui64, ui642);
}

TEST (write_read, bool_vec)
{
    vector<string> ss;
    ss.push_back(string(""));

    ss.push_back(string("1"));
    ss.push_back(string("0"));

    ss.push_back(string("00"));
    ss.push_back(string("10"));
    ss.push_back(string("01"));
    ss.push_back(string("11"));

    ss.push_back(string("10010110"));
    ss.push_back(string("100000001"));
    ss.push_back(string("10000000100000001"));
    ss.push_back(string("100000001000000010000000"));
    ss.push_back(string("1000000010000000100000001010"));

    for(auto &s : ss)
    {
        std::cout << s << std::endl;
        vector<bool> block;
        for(auto c : s)
        {
            block.push_back(c=='1'? true:false);
        }

        std::vector<uint8_t> buf;
        uint written = 0;
        {
            logos::vectorstream write_stream(buf);
            written = logos::write(write_stream, block);
        }
        std::cout << "buf.size=" << buf.size() << std::endl;

        vector<bool> block2;
        logos::bufferstream read_stream(buf.data(), buf.size());
        logos::read(read_stream, block2);

        string output;
        ASSERT_EQ(block.size(), block2.size());
        for(int i = 0; i < block.size(); ++i)
        {
            ASSERT_EQ(block[i], block2[i]);
            output.push_back(block[i]? '1':'0');
        }

        std::cout << output << std::endl << std::endl;
    }
}

TEST (write_read, short_msg)
{
    BlockHash hash = 1;
    BlockHash hash2;
    std::vector<uint8_t> buf;
    {
        logos::vectorstream write_stream(buf);
        logos::write(write_stream, hash);
    }
    std::cout << "buf.size=" << buf.size() << std::endl;
    {
        logos::bufferstream read_stream(buf.data(), buf.size());
        ASSERT_FALSE(logos::read(read_stream, hash2));
    }
    {
        logos::bufferstream read_stream(buf.data(), buf.size()-1);
        ASSERT_TRUE(logos::read(read_stream, hash2));
    }
}

#endif

///////////////////////////// message serialization tests
#ifdef Unit_Test_Msg

TEST (messages, HeartBeat)
{
    for(int i = 0; i < 10000; ++i)
    {
        HeartBeat block;
        vector<uint8_t> buf;
        block.Serialize(buf);
        //cout << "block.payload_size=" << block.payload_size << endl;

        bool error = false;
        logos::bufferstream stream(buf.data(), buf.size());
        Prequel prequel(error, stream);
        HeartBeat block2(error, stream, prequel.version);
        //cout << "prequel.payload_size=" << prequel.payload_size << endl;
        ASSERT_EQ(block.payload_size, prequel.payload_size);

        ASSERT_EQ(prequel.payload_size, sizeof(block.is_request));
        ASSERT_EQ(prequel.type, MessageType::Heart_Beat);
        ASSERT_EQ(prequel.consensus_type, ConsensusType::Any);
        ASSERT_EQ(prequel.version, logos_version);

        ASSERT_FALSE(error);
        ASSERT_EQ(block.is_request, block2.is_request);
        ASSERT_EQ(block.version, block2.version);
        ASSERT_EQ(block.type, block2.type);
        ASSERT_EQ(block.consensus_type, block2.consensus_type);
    }
}

TEST (messages, StandardPhaseMessage)
{
    PrepareMessage<ConsensusType::Epoch> block(23);
    block.signature = 45;

    vector<uint8_t> buf;
    block.Serialize(buf);

    bool error = false;
    logos::bufferstream stream(buf.data(), buf.size());
    Prequel prequel(error, stream);
    PrepareMessage<ConsensusType::Epoch> block2(error, stream, prequel.version);

    ASSERT_FALSE(error);
    ASSERT_EQ(block.preprepare_hash, block2.preprepare_hash);
    ASSERT_EQ(block.signature, block2.signature);
    ASSERT_EQ(block.version, block2.version);
    ASSERT_EQ(block.type, block2.type);
    ASSERT_EQ(block.consensus_type, block2.consensus_type);
}
#endif

TEST (messages, PostPhaseMessage)
{
    BlockHash pp_hash = 11;
    AggSignature as;
    as.map = 12;
    as.sig = 34;
    PostPrepareMessage<ConsensusType::Epoch> block(pp_hash, as);

    vector<uint8_t> buf;
    block.Serialize(buf);

    bool error = false;
    logos::bufferstream stream(buf.data(), buf.size());
    Prequel prequel(error, stream);
    ASSERT_EQ(prequel.version, block.version);
    ASSERT_EQ(prequel.type, block.type);
    ASSERT_EQ(prequel.consensus_type, block.consensus_type);

    PostPrepareMessage<ConsensusType::Epoch> block2(error, stream, prequel.version);
    ASSERT_EQ(block.preprepare_hash, block2.preprepare_hash);
    ASSERT_EQ(block.signature.map, block2.signature.map);
    ASSERT_EQ(block.signature.sig, block2.signature.sig);
}

#ifdef Unit_Test_Msg
TEST (messages, RejectionMessage)
{
    BlockHash pp_hash = 11;
    RejectionMessage<ConsensusType::Request> block(pp_hash);
    block.reason = RejectionReason::Bad_Signature;
    for(uint16_t i = 0; i < CONSENSUS_BATCH_SIZE; i+=2)
    {
        block.rejection_map.push_back(true);
    }
    block.signature = 123;
    vector<uint8_t> buf;
    block.Serialize(buf);

    bool error = false;
    logos::bufferstream stream(buf.data(), buf.size());
    Prequel prequel(error, stream);
    ASSERT_EQ(prequel.version, block.version);
    ASSERT_EQ(prequel.type, block.type);
    ASSERT_EQ(prequel.consensus_type, block.consensus_type);

    RejectionMessage<ConsensusType::Request> block2(error, stream, prequel.version);
    ASSERT_EQ(block.Hash(), block2.Hash());
}

#endif

#ifdef Unit_Test_Single_Block

TEST (blocks, receive_block)
{
    ReceiveBlock block(1,2,3);
    auto r_hash = block.Hash();

    std::vector<uint8_t> buf;
    auto db_val = block.to_mdb_val(buf);
    bool error = false;
    ReceiveBlock block2(error, db_val);
    auto r2_hash = block2.Hash();

    ASSERT_FALSE(error);
    ASSERT_EQ(r_hash, r2_hash);
}

TEST (blocks, state_block)
{
    Send send_a(1,2,3,5,6,7,8);

    std::vector<uint8_t> buf;
    auto db_val = send_a.ToDatabase(buf);

    bool error = false;
    Send send_b(error, db_val);

    ASSERT_FALSE(error);
    ASSERT_EQ(send_a.GetHash(), send_b.GetHash());
    ASSERT_EQ(send_a.Hash(), send_b.Hash());
    ASSERT_EQ(send_a.Hash(), send_a.GetHash());
    ASSERT_EQ(send_b.Hash(), send_b.GetHash());
}

void create_real_StateBlock(Send & request)
{
    logos::keypair pair(std::string("34F0A37AAD20F4A260F0A5B3CB3D7FB50673212263E58A380BC10474BB039CE4"));
    Amount amount(std::numeric_limits<logos::uint128_t>::max());
    Amount fee(0);

    AccountAddress account = pair.pub;
    AccountPubKey pub_key = pair.pub;
    AccountPrivKey priv_key = pair.prv.data;

    new (&request) Send(account,     // account
                        BlockHash(), // previous
                        0,           // sqn
                        account,     // destination
                        amount,
                        fee,
                        priv_key,
                        pub_key);
}

TEST (blocks, state_block_json)
{
    Send send_a;
    create_real_StateBlock(send_a);
    auto s(send_a.ToJson());

    std::cout << "StateBlock1 json: " << s << std::endl;

    bool error = false;
    boost::property_tree::ptree tree;
    std::stringstream istream(s);
    boost::property_tree::read_json(istream, tree);
    Send send_b(error, tree);
    auto s2(send_b.ToJson());

    std::cout << "StateBlock2 json: " << s2 << std::endl;

    ASSERT_FALSE(error);
    ASSERT_EQ(send_a.GetHash(), send_b.GetHash());
    ASSERT_EQ(send_a.Hash(), send_b.Hash());
    ASSERT_EQ(send_a.Hash(), send_a.GetHash());
    ASSERT_EQ(send_b.Hash(), send_b.GetHash());
}

#endif

#ifdef Unit_Test_Consensus_Block
TEST (blocks, batch_state_block_PrePrepare_empty)
{
    auto block = create_bsb_preprepare(0);
    vector<uint8_t> buf;
    block.Serialize(buf);

    bool error = false;
    logos::bufferstream stream(buf.data()+MessagePrequelSize, buf.size()-MessagePrequelSize);
    PrePrepareMessage<ConsensusType::Request> block2(error, stream, logos_version);

    ASSERT_FALSE(error);
    ASSERT_EQ(block.Hash(), block2.Hash());
}

TEST (blocks, batch_state_block_PrePrepare_full)
{
    auto block = create_bsb_preprepare(CONSENSUS_BATCH_SIZE);
    ASSERT_FALSE(block.AddRequest(std::make_shared<Send>(Send(1, 2, CONSENSUS_BATCH_SIZE + 1, 5, 6, 7, 8))));
    ASSERT_EQ(block.requests.size(), CONSENSUS_BATCH_SIZE);
    vector<uint8_t> buf;
    block.Serialize(buf);

    bool error = false;
    logos::bufferstream stream(buf.data()+MessagePrequelSize, buf.size()-MessagePrequelSize);
    PrePrepareMessage<ConsensusType::Request> block2(error, stream, logos_version);

    ASSERT_FALSE(error);
    ASSERT_EQ(block.Hash(), block2.Hash());
}

TEST (blocks, batch_state_block_PostCommit_net)
{
    auto block_pp = create_bsb_preprepare(CONSENSUS_BATCH_SIZE/3);/* /3 so not a full block*/
    auto block = create_approved_block<ConsensusType::Request>(block_pp);

    vector<uint8_t> buf;
    block.Serialize(buf, true, false);

    bool error = false;
    logos::bufferstream stream(buf.data()+MessagePrequelSize, buf.size()-MessagePrequelSize);
    PostCommittedBlock<ConsensusType::Request> block2(error, stream, logos_version, true, false);

    ASSERT_FALSE(error);
    ASSERT_EQ(block.Hash(), block2.Hash());
}

TEST (blocks, batch_state_block_PostCommit_DB)
{
    uint16_t num_state_block =  CONSENSUS_BATCH_SIZE/2; /* /2 so not a full block*/
    auto block_pp = create_bsb_preprepare(num_state_block);
    auto block = create_approved_block<ConsensusType::Request>(block_pp);
    block.next = 90;

    vector<uint8_t> buf;
    auto block_db_val = block.to_mdb_val(buf);
    vector<vector<uint8_t> > buffers(num_state_block);
    vector<logos::mdb_val> sb_db_vals;
    for(uint16_t i = 0; i < block.requests.size(); ++i)
    {
        sb_db_vals.push_back(block.requests[i]->ToDatabase(buffers[i]));
    }

    bool error = false;
    PostCommittedBlock<ConsensusType::Request> block2(error, block_db_val);
    ASSERT_FALSE(error);
    if(! error)
    {
        block.requests.reserve(block2.hashes.size());
        for(uint16_t i = 0; i < block2.hashes.size(); ++i)
        {
            block2.requests.push_back(
                std::shared_ptr<Request>(
                    new Send(error, sb_db_vals[i])
                )
            );

            ASSERT_FALSE(error);
        }
    }

    ASSERT_EQ(block.Hash(), block2.Hash());
}

#endif

TEST (blocks, micro_block_PrePrepare)
{
    auto block = create_mb_preprepare();
    vector<uint8_t> buf;
    block.Serialize(buf);

    bool error = false;
    logos::bufferstream stream(buf.data()+MessagePrequelSize, buf.size()-MessagePrequelSize);
    PrePrepareMessage<ConsensusType::MicroBlock> block2(error, stream, logos_version);

    ASSERT_FALSE(error);
    ASSERT_EQ(block.Hash(), block2.Hash());
}

#ifdef Unit_Test_Consensus_Block

TEST (blocks, micro_block_PostCommit_net)
{
    auto block_pp = create_mb_preprepare();
    auto block = create_approved_block<ConsensusType::MicroBlock>(block_pp);

    vector<uint8_t> buf;
    block.Serialize(buf, true, false);

    bool error = false;
    logos::bufferstream stream(buf.data()+MessagePrequelSize, buf.size()-MessagePrequelSize);
    PostCommittedBlock<ConsensusType::MicroBlock> block2(error, stream, logos_version, true, false);

    ASSERT_FALSE(error);
    ASSERT_EQ(block.Hash(), block2.Hash());
}

TEST (blocks, micro_block_PostCommit_DB)
{
    auto block_pp = create_mb_preprepare();
    auto block = create_approved_block<ConsensusType::MicroBlock>(block_pp);
    block.next = 90;

    vector<uint8_t> buf;
    auto block_db_val = block.to_mdb_val(buf);
    bool error = false;
    PostCommittedBlock<ConsensusType::MicroBlock> block2(error, block_db_val);

    ASSERT_FALSE(error);
    ASSERT_EQ(block.Hash(), block2.Hash());
}

#endif

TEST (blocks, epoch_block_PrePrepare)
{
    auto block = create_eb_preprepare();

    vector<uint8_t> buf;
    block.Serialize(buf);

    bool error = false;
    logos::bufferstream stream(buf.data()+MessagePrequelSize, buf.size()-MessagePrequelSize);
    PrePrepareMessage<ConsensusType::Epoch> block2(error, stream, logos_version);

    ASSERT_FALSE(error);
    ASSERT_EQ(block.Hash(), block2.Hash());
}

#ifdef Unit_Test_Consensus_Block

TEST (blocks, epoch_block_PostCommit_net)
{
    auto block_pp = create_eb_preprepare();
    auto block = create_approved_block<ConsensusType::Epoch>(block_pp);

    vector<uint8_t> buf;
    block.Serialize(buf, true, false);

    bool error = false;
    logos::bufferstream stream(buf.data()+MessagePrequelSize, buf.size()-MessagePrequelSize);
    PostCommittedBlock<ConsensusType::Epoch> block2(error, stream, logos_version, true, false);

    ASSERT_FALSE(error);
    ASSERT_EQ(block.Hash(), block2.Hash());
}

TEST (blocks, epoch_block_PostCommit_DB)
{
    auto block_pp = create_eb_preprepare();
    auto block = create_approved_block<ConsensusType::Epoch>(block_pp);
    block.next = 90;

    vector<uint8_t> buf;
    auto block_db_val = block.to_mdb_val(buf);
    bool error = false;
    PostCommittedBlock<ConsensusType::Epoch> block2(error, block_db_val);

    ASSERT_FALSE(error);
    ASSERT_EQ(block.Hash(), block2.Hash());
}

#endif

///////////////////////////////////////message_validator tests

#ifdef Unit_Test_Msg_Validator

TEST (message_validator, consensus_session)
{
    auto nodes = setup_nodes();

    //step 1, pre-prepare
    //primary, node[0], signs the preprepare
    PrePrepareMessage<ConsensusType::Epoch> preprepare;
    preprepare.micro_block_tip.digest = 1234;
    preprepare.transaction_fee_pool = 2345;
    for(uint8_t i = 0; i < NUM_DELEGATES; ++i)
    {
        preprepare.delegates[i] = init_delegate(i, i, i, i);
    }

    auto & primary = nodes[0]->validator;
    auto preprepare_hash = preprepare.Hash();
    primary.Sign(preprepare_hash, preprepare.preprepare_sig);
    ASSERT_TRUE(primary.Validate(preprepare_hash, preprepare.preprepare_sig, 0));
    std::vector<uint8_t> preprepare_buf;
    preprepare.Serialize(preprepare_buf);

    //step 2, prepare
    //backups (and primary)
    //verify the signature of preprepare and create signed prepares
    std::vector<std::vector<uint8_t>> prepare_bufs;
    std::vector<PrePrepareMessage<ConsensusType::Epoch>> preprepare_copies;
    for(int i = 0; i < NUM_DELEGATES; ++i)
    {
        bool error = false;
        logos::bufferstream stream(preprepare_buf.data()+MessagePrequelSize, preprepare_buf.size()-MessagePrequelSize);
        PrePrepareMessage<ConsensusType::Epoch> block2(error, stream, logos_version);
        ASSERT_FALSE(error);

        auto & validator = nodes[i]->validator;
        auto pre_prepare_hash = block2.Hash();
        ASSERT_EQ(pre_prepare_hash, preprepare_hash);
        ASSERT_TRUE(validator.Validate(pre_prepare_hash, block2.preprepare_sig, 0));
        preprepare_copies.push_back(block2);

        PrepareMessage<ConsensusType::Epoch> prepare(pre_prepare_hash);
        validator.Sign(pre_prepare_hash, prepare.signature);
        ASSERT_TRUE(validator.Validate(pre_prepare_hash, prepare.signature, i));
        prepare_bufs.push_back(std::vector<uint8_t>());
        auto & buf = prepare_bufs.back();
        prepare.Serialize(buf);
    }

    //step 3, post-prepare
    //primary verify the prepares and aggregate the signatures
    AggSignature postprepare_agg_sig;
    {
        SigVec signatures(NUM_DELEGATES);
        for(int i = 0; i < NUM_DELEGATES; ++i)
        {
            //            auto & msg = prepares[i];
            //            ASSERT_TRUE(primary.Validate(preprepare_hash, msg.signature, i));
            //            signatures[i].delegate_id = i;
            //            signatures[i].signature = msg.signature;
            bool error = false;
            logos::bufferstream stream(prepare_bufs[i].data()+MessagePrequelSize, prepare_bufs[i].size()-MessagePrequelSize);
            PrepareMessage<ConsensusType::Epoch> prepare(error, stream, logos_version);
            ASSERT_FALSE(error);

            ASSERT_TRUE(primary.Validate(preprepare_hash, prepare.signature, i));
            signatures[i].delegate_id = i;
            signatures[i].signature = prepare.signature;
        }
        std::unordered_map<uint8_t,MessageValidator::DelegateSignature> map;
        for(auto& x: signatures)
        {
            map[x.delegate_id] = x;
        }
        ASSERT_TRUE(primary.AggregateSignature(map, postprepare_agg_sig));
        ASSERT_TRUE(primary.Validate(preprepare_hash, postprepare_agg_sig));
    }
    PostPrepareMessage<ConsensusType::Epoch> postprepare(preprepare_hash, postprepare_agg_sig);
    auto postprepare_hash = postprepare.ComputeHash();
    std::vector<uint8_t> postprepare_buf;
    postprepare.Serialize(postprepare_buf);

    //step 4, commit
    //delegates verify the signature of postprepare and create signed commits
    //std::vector<CommitMessage<ConsensusType::Epoch>> commits;
    std::vector<std::vector<uint8_t>> commit_bufs;
    std::vector<AggSignature> postprepare_sig_copies;
    for(int i = 0; i < NUM_DELEGATES; ++i)
    {
        bool error = false;
        logos::bufferstream stream(postprepare_buf.data()+MessagePrequelSize, postprepare_buf.size()-MessagePrequelSize);
        PostPrepareMessage<ConsensusType::Epoch> block2(error, stream, logos_version);
        ASSERT_FALSE(error);

        auto & validator = nodes[i]->validator;
        ASSERT_TRUE(validator.Validate(preprepare_hash, block2.signature));
        auto post_prepare_hash = block2.ComputeHash();
        ASSERT_EQ(post_prepare_hash, postprepare_hash);
        postprepare_sig_copies.push_back(block2.signature);

        CommitMessage<ConsensusType::Epoch> commit(preprepare_hash);
        validator.Sign(post_prepare_hash, commit.signature);
        ASSERT_TRUE(validator.Validate(post_prepare_hash, commit.signature, i));

        commit_bufs.push_back(std::vector<uint8_t>());
        auto & buf = commit_bufs.back();
        commit.Serialize(buf);
    }

    //step 5, primary post-commit
    //primary verify the commits and aggregate the signatures
    AggSignature postcommit_agg_sig;
    {
        SigVec signatures(NUM_DELEGATES);
        for(int i = 0; i < NUM_DELEGATES; ++i)
        {
            bool error = false;
            logos::bufferstream stream(commit_bufs[i].data()+MessagePrequelSize, commit_bufs[i].size()-MessagePrequelSize);
            CommitMessage<ConsensusType::Epoch> commit(error, stream, logos_version);
            ASSERT_FALSE(error);

            ASSERT_TRUE(primary.Validate(postprepare_hash, commit.signature, i));
            signatures[i].delegate_id = i;
            signatures[i].signature = commit.signature;
        }
        std::unordered_map<uint8_t,MessageValidator::DelegateSignature> map;
        for(auto& x: signatures)
        {
            map[x.delegate_id] = x;
        }
        ASSERT_TRUE(primary.AggregateSignature(map, postcommit_agg_sig));
        ASSERT_TRUE(primary.Validate(postprepare_hash, postcommit_agg_sig));
    }
    PostCommitMessage<ConsensusType::Epoch> postcommit(preprepare_hash, postcommit_agg_sig);
    std::vector<uint8_t> postcommit_buf;
    postcommit.Serialize(postcommit_buf);
    PostCommittedBlock<ConsensusType::Epoch> primary_block(preprepare, postprepare_agg_sig, postcommit_agg_sig);

    //make sure hash matches
    ASSERT_EQ(preprepare_hash, primary_block.Hash());

    //step 6, backup post-commit
    //delegates verify the signature of postcommit
    for(int i = 0; i < NUM_DELEGATES; ++i)
    {
        bool error = false;
        logos::bufferstream stream(postcommit_buf.data()+MessagePrequelSize, postcommit_buf.size()-MessagePrequelSize);
        PostCommitMessage<ConsensusType::Epoch> block2(error, stream, logos_version);
        ASSERT_FALSE(error);

        auto & validator = nodes[i]->validator;
        ASSERT_TRUE(validator.Validate(postprepare_hash, block2.signature));
        PostCommittedBlock<ConsensusType::Epoch> backup_block(preprepare_copies[i], postprepare_sig_copies[i], block2.signature);

        ASSERT_EQ(primary_block.Hash(), backup_block.Hash());
        ASSERT_EQ(primary_block.post_prepare_sig.map, backup_block.post_prepare_sig.map);
        ASSERT_EQ(primary_block.post_prepare_sig.sig, backup_block.post_prepare_sig.sig);
        ASSERT_EQ(primary_block.post_commit_sig.map, backup_block.post_commit_sig.map);
        ASSERT_EQ(primary_block.post_commit_sig.sig, backup_block.post_commit_sig.sig);
    }
}

#define LOOPS   10
TEST (message_validator, signature_order_twoThirds)
{
    auto nodes = setup_nodes();

    PrePrepareMessage<ConsensusType::Epoch> preperpare = create_eb_preprepare();

    auto & primary = nodes[0]->validator;
    auto preprepare_hash = preperpare.Hash();
    primary.Sign(preprepare_hash, preperpare.preprepare_sig);
    ASSERT_TRUE(primary.Validate(preprepare_hash, preperpare.preprepare_sig, 0));

    std::vector<PrepareMessage<ConsensusType::Epoch>> prepares;
    for(int i = 0; i < NUM_DELEGATES; ++i)
    {
        auto & validator = nodes[i]->validator;
        ASSERT_TRUE(validator.Validate(preprepare_hash, preperpare.preprepare_sig, 0));

        prepares.push_back(PrepareMessage<ConsensusType::Epoch>(preprepare_hash));
        auto & msg = prepares.back();
        validator.Sign(preprepare_hash, msg.signature);
        ASSERT_TRUE(validator.Validate(preprepare_hash, msg.signature, i));
    }

    for(int r = 0; r < LOOPS; ++r)
    {
        //Now the primary have prepares. It aggregates 2/3*32 signatures with random order.

        AggSignature postprepare_agg_sig;
        {
            SigVec signatures(NUM_DELEGATES);
            for(int i = 0; i < NUM_DELEGATES; ++i)
            {
                auto & msg = prepares[i];
                ASSERT_TRUE(primary.Validate(preprepare_hash, msg.signature, i));
                signatures[i].delegate_id = i;
                signatures[i].signature = msg.signature;
            }

            std::random_shuffle ( signatures.begin(), signatures.end() );
            signatures.resize(NUM_DELEGATES*2/3);

            SigVec signatures_copy;
            for(auto &xx : signatures)
            {
                signatures_copy.push_back(xx);
                signatures_copy.push_back(xx);
            }

            std::unordered_map<uint8_t,MessageValidator::DelegateSignature> map;
            for(auto& x: signatures_copy)
            {
                map[x.delegate_id] = x;
            }
            ASSERT_TRUE(primary.AggregateSignature(map, postprepare_agg_sig));
            ASSERT_TRUE(primary.Validate(preprepare_hash, postprepare_agg_sig));
        }
        PostPrepareMessage<ConsensusType::Epoch> postprepare(preprepare_hash, postprepare_agg_sig);

        //All delegate verify the aggregated signature
        for(int i = 0; i < NUM_DELEGATES; ++i)
        {
            auto & validator = nodes[i]->validator;
            ASSERT_TRUE(validator.Validate(preprepare_hash, postprepare.signature));
        }
    }
}

#endif

///////////////// DB tests

#ifdef Unit_Test_DB
TEST (DB, receive_block)
{
    auto store = get_db();
    ASSERT_TRUE(store != NULL);
    if(store == NULL)
        return;
    logos::transaction txn(store->environment, nullptr, true);

    ReceiveBlock block(1,2,3);
    auto hash = block.Hash();
    std::vector<uint8_t> buf;
    ASSERT_FALSE(store->receive_put(hash, block, txn));

    ReceiveBlock block2;
    ASSERT_FALSE(store->receive_get(hash, block2, txn));

    auto hash2 = block2.Hash();
    ASSERT_EQ(hash, hash2);
}

TEST (DB, state_block)
{
    auto store = get_db();
    ASSERT_TRUE(store != NULL);
    if(store == NULL)
        return;
    logos::transaction txn(store->environment, nullptr, true);

    Send send_a(1,2,3,5,6,7,8);
    std::vector<uint8_t> buf;
    ASSERT_FALSE(store->request_put(static_cast<Request&>(send_a), txn));

    Send send_b;
    ASSERT_FALSE(store->request_get(send_a.GetHash(), send_b, txn));

    ASSERT_EQ(send_a.GetHash(), send_b.GetHash());
    ASSERT_EQ(send_a.Hash(), send_b.Hash());
    ASSERT_EQ(send_a.Hash(), send_a.GetHash());
    ASSERT_EQ(send_b.Hash(), send_b.GetHash());
}

TEST (DB, account)
{
    auto store = get_db();
    ASSERT_TRUE(store != NULL);
    if(store == NULL)
        return;
    logos::transaction txn(store->environment, nullptr, true);

    logos::account_info block(1, 2, 3, 4, 5, 6, 7, 8, 9);
    AccountAddress address(11);

    vector<uint8_t> buf;
    {
        logos::vectorstream stream(buf);
        block.Serialize(stream);
    }
    std::cout << byte_vector_to_string(buf) << std::endl;

    ASSERT_FALSE(store->account_put(address, block, txn));

    logos::account_info block2;
    ASSERT_FALSE(store->account_get(address, block2, txn));
    ASSERT_EQ(block, block2);
}

TEST (DB, bsb)
{
    auto store = get_db();
    ASSERT_TRUE(store != NULL);
    if(store == NULL)
        return;
    logos::transaction txn(store->environment, nullptr, true);

    auto block_pp = create_bsb_preprepare(CONSENSUS_BATCH_SIZE/2);
    auto block = create_approved_block<ConsensusType::Request>(block_pp);
    block.next = 90;

    auto block_hash(block.Hash());
    ASSERT_FALSE(store->request_block_put(block, block_hash, txn));

    ApprovedRB block2;
    ASSERT_FALSE(store->request_block_get(block_hash, block2, txn));
    ASSERT_EQ(block_hash, block2.Hash());
}

TEST (DB, mb)
{
    auto store = get_db();
    ASSERT_TRUE(store != NULL);
    if(store == NULL)
        return;
    logos::transaction txn(store->environment, nullptr, true);

    auto block_pp = create_mb_preprepare();
    auto block = create_approved_block<ConsensusType::MicroBlock>(block_pp);
    block.next = 90;

    ASSERT_FALSE(store->micro_block_put(block, txn));
    auto block_hash(block.Hash());

    ApprovedMB block2;
    ASSERT_FALSE(store->micro_block_get(block_hash, block2, txn));
    ASSERT_EQ(block_hash, block2.Hash());
}

TEST (DB, eb)
{
    auto store = get_db();
    ASSERT_TRUE(store != NULL);
    if(store == NULL)
        return;
    logos::transaction txn(store->environment, nullptr, true);

    auto block_pp = create_eb_preprepare();
    auto block = create_approved_block<ConsensusType::Epoch>(block_pp);
    block.next = 90;

    ASSERT_FALSE(store->epoch_put(block, txn));
    auto block_hash(block.Hash());

    ApprovedEB block2;
    ASSERT_FALSE(store->epoch_get(block_hash, block2, txn));
    ASSERT_EQ(block_hash, block2.Hash());
}

TEST (DB, bsb_next)
{
    auto store = get_db();
    ASSERT_TRUE(store != NULL);
    if(store == NULL)
        return;
//    logos::transaction txn(store->environment, nullptr, true);

    auto block_pp = create_bsb_preprepare(CONSENSUS_BATCH_SIZE/4);
    auto block = create_approved_block<ConsensusType::Request>(block_pp);
    auto block_hash(block.Hash());
    {
        logos::transaction txn(store->environment, nullptr, true);
        ASSERT_FALSE(store->request_block_put(block, block_hash, txn));
    }

    BlockHash next(90);
    {
        logos::transaction txn(store->environment, nullptr, true);
        store->consensus_block_update_next(block_hash, next, ConsensusType::Request, txn);
    }

    logos::transaction txn(store->environment, nullptr, false);
    ApprovedRB block2;
    ASSERT_FALSE(store->request_block_get(block_hash, block2, txn));
    ASSERT_EQ(block_hash, block2.Hash());
    ASSERT_EQ(block2.next, next);
}
#endif

ext: cpp

max_stars_repo_name: LogosNetwork/logos-core

max_issues_repo_name: LogosNetwork/logos-core

max_forks_repo_name: LogosNetwork/logos-core


text:
/*=============================================================================
    Spirit v1.6.0
    Copyright (c) 2001-2003 Joel de Guzman
    http://spirit.sourceforge.net/

    Permission to copy, use, modify, sell and distribute this software is
    granted provided this copyright notice appears in all copies. This
    software is provided "as is" without express or implied warranty, and
    with no claim as to its suitability for any purpose.
=============================================================================*/
#if !defined(BOOST_SPIRIT_BASICS_HPP)
#define BOOST_SPIRIT_BASICS_HPP

#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x561)
#include "boost/spirit/core/impl/borland.hpp"
#endif

#include <boost/config.hpp>
#include <boost/mpl/apply_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/bool.hpp>

#if defined(BOOST_MSVC) || defined(BOOST_INTEL_CXX_VERSION)
#include "boost/spirit/core/impl/msvc.hpp"
#endif

#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
#define BOOST_SPIRIT_TYPENAME
#else
#define BOOST_SPIRIT_TYPENAME typename
#endif

///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit {

    struct nil_t {};

}} // namespace boost::spirit

#endif


text:
#ifndef PYTHONIC_INCLUDE_NUMPY_ARCSIN_HPP
#define PYTHONIC_INCLUDE_NUMPY_ARCSIN_HPP

#include "pythonic/include/utils/functor.hpp"
#include "pythonic/include/types/ndarray.hpp"
#include "pythonic/include/utils/numpy_traits.hpp"

#include <boost/simd/function/asin.hpp>

PYTHONIC_NS_BEGIN

namespace numpy
{

  namespace wrapper
  {
    double arcsin(long const &v);
    template <class T>
    auto arcsin(T const &v) -> decltype(boost::simd::asin(v));
  }
#define NUMPY_NARY_FUNC_NAME arcsin
#define NUMPY_NARY_FUNC_SYM wrapper::arcsin
#include "pythonic/include/types/numpy_nary_expr.hpp"
}
PYTHONIC_NS_END

#endif