text:
// Boost.Geometry (aka GGL, Generic Geometry Library)

// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.

// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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)

#ifndef BOOST_GEOMETRY_IO_DSV_WRITE_HPP
#define BOOST_GEOMETRY_IO_DSV_WRITE_HPP

#include <cstddef>
#include <ostream>
#include <string>

#include <boost/concept_check.hpp>
#include <boost/range.hpp>

#include <boost/geometry/algorithms/detail/interior_iterator.hpp>

#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>

#include <boost/geometry/geometries/concepts/check.hpp>

namespace boost { namespace geometry
{

#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace dsv
{

struct dsv_settings
{
    std::string coordinate_separator;
    std::string point_open;
    std::string point_close;
    std::string point_separator;
    std::string list_open;
    std::string list_close;
    std::string list_separator;

    dsv_settings(std::string const& sep
            , std::string const& open
            , std::string const& close
            , std::string const& psep
            , std::string const& lopen
            , std::string const& lclose
            , std::string const& lsep
            )
        : coordinate_separator(sep)
        , point_open(open)
        , point_close(close)
        , point_separator(psep)
        , list_open(lopen)
        , list_close(lclose)
        , list_separator(lsep)
    {}
};

/*!
\brief Stream coordinate of a point as \ref DSV
*/
template <typename Point, std::size_t Dimension, std::size_t Count>
struct stream_coordinate
{
    template <typename Char, typename Traits>
    static inline void apply(std::basic_ostream<Char, Traits>& os,
            Point const& point,
            dsv_settings const& settings)
    {
        os << (Dimension > 0 ? settings.coordinate_separator : "")
            << get<Dimension>(point);

        stream_coordinate
            <
                Point, Dimension + 1, Count
            >::apply(os, point, settings);
    }
};

template <typename Point, std::size_t Count>
struct stream_coordinate<Point, Count, Count>
{
    template <typename Char, typename Traits>
    static inline void apply(std::basic_ostream<Char, Traits>&,
            Point const&,
            dsv_settings const& )
    {
    }
};

/*!
\brief Stream indexed coordinate of a box/segment as \ref DSV
*/
template
<
    typename Geometry,
    std::size_t Index,
    std::size_t Dimension,
    std::size_t Count
>
struct stream_indexed
{
    template <typename Char, typename Traits>
    static inline void apply(std::basic_ostream<Char, Traits>& os,
            Geometry const& geometry,
            dsv_settings const& settings)
    {
        os << (Dimension > 0 ? settings.coordinate_separator : "")
            << get<Index, Dimension>(geometry);
        stream_indexed
            <
                Geometry, Index, Dimension + 1, Count
            >::apply(os, geometry, settings);
    }
};

template <typename Geometry, std::size_t Index, std::size_t Count>
struct stream_indexed<Geometry, Index, Count, Count>
{
    template <typename Char, typename Traits>
    static inline void apply(std::basic_ostream<Char, Traits>&, Geometry const&,
            dsv_settings const& )
    {
    }
};

/*!
\brief Stream points as \ref DSV
*/
template <typename Point>
struct dsv_point
{
    template <typename Char, typename Traits>
    static inline void apply(std::basic_ostream<Char, Traits>& os,
            Point const& p,
            dsv_settings const& settings)
    {
        os << settings.point_open;
        stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p, settings);
        os << settings.point_close;
    }
};

/*!
\brief Stream ranges as DSV
\note policy is used to stream prefix/postfix, enabling derived classes to override this
*/
template <typename Range>
struct dsv_range
{
    template <typename Char, typename Traits>
    static inline void apply(std::basic_ostream<Char, Traits>& os,
            Range const& range,
            dsv_settings const& settings)
    {
        typedef typename boost::range_iterator<Range const>::type iterator_type;

        bool first = true;

        os << settings.list_open;

        for (iterator_type it = boost::begin(range);
            it != boost::end(range);
            ++it)
        {
            os << (first ? "" : settings.point_separator)
                << settings.point_open;

            stream_coordinate
                <
                    point_type, 0, dimension<point_type>::type::value
                >::apply(os, *it, settings);
            os << settings.point_close;

            first = false;
        }

        os << settings.list_close;
    }

private:
    typedef typename boost::range_value<Range>::type point_type;
};

/*!
\brief Stream sequence of points as DSV-part, e.g. (1 2),(3 4)
\note Used in polygon, all multi-geometries
*/

template <typename Polygon>
struct dsv_poly
{
    template <typename Char, typename Traits>
    static inline void apply(std::basic_ostream<Char, Traits>& os,
                Polygon const& poly,
                dsv_settings const& settings)
    {
        typedef typename ring_type<Polygon>::type ring;

        os << settings.list_open;

        dsv_range<ring>::apply(os, exterior_ring(poly), settings);

        typename interior_return_type<Polygon const>::type
            rings = interior_rings(poly);
        for (typename detail::interior_iterator<Polygon const>::type
                it = boost::begin(rings); it != boost::end(rings); ++it)
        {
            os << settings.list_separator;
            dsv_range<ring>::apply(os, *it, settings);
        }
        os << settings.list_close;
    }
};

template <typename Geometry, std::size_t Index>
struct dsv_per_index
{
    typedef typename point_type<Geometry>::type point_type;

    template <typename Char, typename Traits>
    static inline void apply(std::basic_ostream<Char, Traits>& os,
            Geometry const& geometry,
            dsv_settings const& settings)
    {
        os << settings.point_open;
        stream_indexed
            <
                Geometry, Index, 0, dimension<Geometry>::type::value
            >::apply(os, geometry, settings);
        os << settings.point_close;
    }
};

template <typename Geometry>
struct dsv_indexed
{
    typedef typename point_type<Geometry>::type point_type;

    template <typename Char, typename Traits>
    static inline void apply(std::basic_ostream<Char, Traits>& os,
            Geometry const& geometry,
            dsv_settings const& settings)
    {
        os << settings.list_open;
        dsv_per_index<Geometry, 0>::apply(os, geometry, settings);
        os << settings.point_separator;
        dsv_per_index<Geometry, 1>::apply(os, geometry, settings);
        os << settings.list_close;
    }
};

}} // namespace detail::dsv
#endif // DOXYGEN_NO_DETAIL

#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{

template <typename Tag, typename Geometry>
struct dsv {};

template <typename Point>
struct dsv<point_tag, Point>
    : detail::dsv::dsv_point<Point>
{};

template <typename Linestring>
struct dsv<linestring_tag, Linestring>
    : detail::dsv::dsv_range<Linestring>
{};

template <typename Box>
struct dsv<box_tag, Box>
    : detail::dsv::dsv_indexed<Box>
{};

template <typename Segment>
struct dsv<segment_tag, Segment>
    : detail::dsv::dsv_indexed<Segment>
{};

template <typename Ring>
struct dsv<ring_tag, Ring>
    : detail::dsv::dsv_range<Ring>
{};

template <typename Polygon>
struct dsv<polygon_tag, Polygon>
    : detail::dsv::dsv_poly<Polygon>
{};

} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace dsv
{

// FIXME: This class is not copyable/assignable but it is used as such --mloskot
template <typename Geometry>
class dsv_manipulator
{
public:

    inline dsv_manipulator(Geometry const& g,
            dsv_settings const& settings)
        : m_geometry(g)
        , m_settings(settings)
    {}

    template <typename Char, typename Traits>
    inline friend std::basic_ostream<Char, Traits>& operator<<(
            std::basic_ostream<Char, Traits>& os,
            dsv_manipulator const& m)
    {
        dispatch::dsv
            <
                typename tag_cast
                    <
                        typename tag<Geometry>::type,
                        multi_tag
                    >::type,
                Geometry
            >::apply(os, m.m_geometry, m.m_settings);
        os.flush();
        return os;
    }

private:
    Geometry const& m_geometry;
    dsv_settings m_settings;
};

template <typename MultiGeometry>
struct dsv_multi
{
    typedef dispatch::dsv
                <
                    typename single_tag_of
                        <
                            typename tag<MultiGeometry>::type
                        >::type,
                    typename boost::range_value<MultiGeometry>::type
                > dispatch_one;

    typedef typename boost::range_iterator
        <
            MultiGeometry const
        >::type iterator;

    template <typename Char, typename Traits>
    static inline void apply(std::basic_ostream<Char, Traits>& os,
                MultiGeometry const& multi,
                dsv_settings const& settings)
    {
        os << settings.list_open;

        bool first = true;
        for(iterator it = boost::begin(multi);
            it != boost::end(multi);
            ++it, first = false)
        {
            os << (first ? "" : settings.list_separator);
            dispatch_one::apply(os, *it, settings);
        }
        os << settings.list_close;
    }
};

}} // namespace detail::dsv
#endif // DOXYGEN_NO_DETAIL

// TODO: The alternative to this could be a forward declaration of dispatch::dsv<>
//       or braking the code into the interface and implementation part
#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{

template <typename Geometry>
struct dsv<multi_tag, Geometry>
    : detail::dsv::dsv_multi<Geometry>
{};

} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

/*!
\brief Main DSV-streaming function
\details DSV stands for Delimiter Separated Values. Geometries can be streamed
    as DSV. There are defaults for all separators.
\note Useful for examples and testing purposes
\note With this function GeoJSON objects can be created, using the right
    delimiters
\ingroup utility
*/
template <typename Geometry>
inline detail::dsv::dsv_manipulator<Geometry> dsv(Geometry const& geometry
    , std::string const& coordinate_separator = ", "
    , std::string const& point_open = "("
    , std::string const& point_close = ")"
    , std::string const& point_separator = ", "
    , std::string const& list_open = "("
    , std::string const& list_close = ")"
    , std::string const& list_separator = ", "
    )
{
    concepts::check<Geometry const>();

    return detail::dsv::dsv_manipulator<Geometry>(geometry,
        detail::dsv::dsv_settings(coordinate_separator,
            point_open, point_close, point_separator,
            list_open, list_close, list_separator));
}

}} // namespace boost::geometry

#endif // BOOST_GEOMETRY_IO_DSV_WRITE_HPP

max_stars_repo_name: rudylee/expo

max_issues_repo_name: rudylee/expo

max_forks_repo_name: rudylee/expo


text:
#include "RoleInfoWeightedEdge.hpp"
#include <graph_analysis/EdgeTypeManager.hpp>
#include <base-logging/Logging.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/set.hpp>
#include <boost/serialization/map.hpp>
#include <iomanip>

namespace templ {

const graph_analysis::EdgeRegistration<RoleInfoWeightedEdge> RoleInfoWeightedEdge::msRoleInfoWeightedEdgeRegistration;

RoleInfoWeightedEdge::RoleInfoWeightedEdge()
    : graph_analysis::WeightedEdge()
    , RoleInfo()
{
}

RoleInfoWeightedEdge::RoleInfoWeightedEdge(const graph_analysis::Vertex::Ptr& source, const graph_analysis::Vertex::Ptr& target, double weight)
    : graph_analysis::WeightedEdge(source, target, weight)
    , RoleInfo()
{
}

std::string RoleInfoWeightedEdge::toString() const
{
    std::stringstream ss;
    double weight = getWeight();
    if(weight == std::numeric_limits<double>::max())
    {
        // inf
        ss << "capacity: +inf" << std::endl; //"\u221E" << std::endl;
    } else {
        ss << "capacity: " << std::setprecision(2) << weight << std::endl;
    }
    ss << RoleInfo::toString();

    return ss.str();
}

void RoleInfoWeightedEdge::registerAttributes(graph_analysis::EdgeTypeManager* eManager) const
{
    using namespace graph_analysis;

    eManager->registerAttribute("RoleInfoWeightedEdge", "weights",
               (io::AttributeSerializationCallbacks::serialize_func_t)&RoleInfoWeightedEdge::serializeWeights,
               (io::AttributeSerializationCallbacks::deserialize_func_t)&RoleInfoWeightedEdge::deserializeWeights,
               (io::AttributeSerializationCallbacks::print_func_t)&RoleInfoWeightedEdge::serializeWeights);

    eManager->registerAttribute("RoleInfoWeightedEdge", "roles",
               (io::AttributeSerializationCallbacks::serialize_func_t)&RoleInfoWeightedEdge::serializeRoles,
               (io::AttributeSerializationCallbacks::deserialize_func_t)&RoleInfoWeightedEdge::deserializeRoles,
               (io::AttributeSerializationCallbacks::print_func_t)&RoleInfoWeightedEdge::serializeRoles);

    eManager->registerAttribute("RoleInfoWeightedEdge", "tagged_roles",
               (io::AttributeSerializationCallbacks::serialize_func_t)&RoleInfoWeightedEdge::serializeTaggedRoles,
               (io::AttributeSerializationCallbacks::deserialize_func_t)&RoleInfoWeightedEdge::deserializeTaggedRoles,
               (io::AttributeSerializationCallbacks::print_func_t)&RoleInfoWeightedEdge::serializeTaggedRoles);

}

std::string RoleInfoWeightedEdge::serializeRoles()
{
    std::stringstream ss;
    boost::archive::text_oarchive oarch(ss);
    oarch << mRoles;
    return ss.str();
}

std::string RoleInfoWeightedEdge::serializeTaggedRoles()
{
    std::stringstream ss;
    boost::archive::text_oarchive oarch(ss);
    oarch << mTaggedRoles;
    return ss.str();
}

void RoleInfoWeightedEdge::deserializeRoles(const std::string& s)
{
    std::stringstream ss;
    ss << s;
    boost::archive::text_iarchive iarch(ss);
    iarch >> mRoles;
}

void RoleInfoWeightedEdge::deserializeTaggedRoles(const std::string& s)
{
    std::stringstream ss;
    ss << s;
    boost::archive::text_iarchive iarch(ss);
    iarch >> mTaggedRoles;
}

}  // end namespace templ

ext: cpp

max_stars_repo_name: tomcreutz/planning-templ

max_issues_repo_name: tomcreutz/planning-templ

max_forks_repo_name: tomcreutz/planning-templ


text:
#pragma once

#include <algorithm>
#include <cctype>
#include <string>
#include <deal.II/lac/trilinos_sparse_matrix.h>
#include <AztecOO_ConditionNumber.h>
#include <Epetra_CrsMatrix.h>

namespace boltzmann {
class AztecOOCondest
{
 public:
  typedef dealii::TrilinosWrappers::SparseMatrix matrix_t;

 public:
  void initialize(const matrix_t& matrix, std::string solver_type);

  void initialize(const ::Epetra_Operator& matrix, std::string solver_type);
  double compute(int maxiters, double tol = 1e-2);

 private:
  ::AztecOOConditionNumber cond_;
};

// ----------------------------------------------------------------------
void
AztecOOCondest::initialize(const matrix_t& matrix, std::string solver_type)
{
  const auto& trilinos_matrix = matrix.trilinos_matrix();

  this->initialize(matrix.trilinos_matrix(), solver_type);
}

// ----------------------------------------------------------------------
void
AztecOOCondest::initialize(const ::Epetra_Operator& matrix, std::string solver_type)
{
  int krylovSubspaceSize = 100;
  bool printSolve = true;

  if (solver_type.compare("GMRES") == 0)
    cond_.initialize(
        matrix, ::AztecOOConditionNumber::SolverType::GMRES_, krylovSubspaceSize, printSolve);
  else if (solver_type.compare("CG") == 0)
    cond_.initialize(
        matrix, ::AztecOOConditionNumber::SolverType::CG_, krylovSubspaceSize, printSolve);
  else {
    throw std::runtime_error("unknown SolverType");
  }
}

// ----------------------------------------------------------------------
double
AztecOOCondest::compute(int maxiters, double tol)
{
  cond_.computeConditionNumber(maxiters, tol);
  return cond_.getConditionNumber();
}

}  // end namespace boltzmann

ext: hpp


text:
//==================================================================================================
/*
  Copyright 2017 NumScale SAS

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#include <boost/simd/algorithm/transform_reduce.hpp>
#include <boost/align/aligned_allocator.hpp>
#include <boost/simd/function/sqr.hpp>
#include <boost/simd/function/plus.hpp>
#include <numeric>
#include <vector>
#include <simd_test.hpp>

using namespace boost::simd;
using namespace boost::alignment;

STF_CASE_TPL( "Check simd::transform_reduce(f,l,i)", STF_NUMERIC_TYPES )
{
  namespace bs =  boost::simd;
  static const int N = pack<T>::static_size;

  std::vector<T,aligned_allocator<T,pack<T>::alignment>> d(2*N+1);
  std::iota(d.begin(), d.end(),T(1));

  auto s1  = bs::transform_reduce( d.data(), d.data()+2*N, bs::sqr,T(0), bs::plus);
  auto s1s = std::inner_product( d.data(), d.data()+2*N, d.data(), T(0));
  STF_EQUAL(s1, s1s);
  auto s2 =  bs::transform_reduce( d.data()+1, d.data()+2*N+1, bs::sqr, T(1), bs::plus);
  auto s2s = std::inner_product( d.data()+1, d.data()+2*N+1, d.data()+1, T(1));
  STF_EQUAL(s2, s2s);

  auto s3  = bs::transform_reduce( d.data()+1, d.data()+2*N+1, bs::sqr, T(0), bs::plus);
  auto s3s = std::inner_product( d.data()+1, d.data()+2*N+1, d.data()+1, T(0));
  STF_EQUAL(s3, s3s);

}


text:
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2017,  Regents of the University of California,
 *                           Arizona Board of Regents,
 *                           Colorado State University,
 *                           University Pierre & Marie Curie, Sorbonne University,
 *                           Washington University in St. Louis,
 *                           Beijing Institute of Technology,
 *                           The University of Memphis.
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "multicast-discovery.hpp"
#include <boost/lexical_cast.hpp>
#include <ndn-cxx/encoding/tlv-nfd.hpp>

namespace ndn {
namespace tools {
namespace autoconfig {

using nfd::ControlParameters;
using nfd::ControlResponse;

static const Name HUB_DISCOVERY_PREFIX("/localhop/ndn-autoconf/hub");
static const uint64_t HUB_DISCOVERY_ROUTE_COST(1);
static const time::milliseconds HUB_DISCOVERY_ROUTE_EXPIRATION = time::seconds(30);
static const time::milliseconds HUB_DISCOVERY_INTEREST_LIFETIME = time::seconds(4);

MulticastDiscovery::MulticastDiscovery(Face& face, nfd::Controller& controller)
  : m_face(face)
  , m_controller(controller)
{
}

void
MulticastDiscovery::doStart()
{
  nfd::FaceQueryFilter filter;
  filter.setLinkType(nfd::LINK_TYPE_MULTI_ACCESS);

  m_controller.fetch<nfd::FaceQueryDataset>(
    filter,
    bind(&MulticastDiscovery::registerHubDiscoveryPrefix, this, _1),
    [this] (uint32_t code, const std::string& reason) {
      this->fail("Error " + to_string(code) + " when querying multi-access faces: " + reason);
    });
}

void
MulticastDiscovery::registerHubDiscoveryPrefix(const std::vector<nfd::FaceStatus>& dataset)
{
  if (dataset.empty()) {
    this->fail("No multi-access faces available");
    return;
  }

  m_nRegs = dataset.size();
  m_nRegSuccess = 0;
  m_nRegFailure = 0;

  for (const auto& faceStatus : dataset) {
    ControlParameters parameters;
    parameters.setName(HUB_DISCOVERY_PREFIX)
              .setFaceId(faceStatus.getFaceId())
              .setCost(HUB_DISCOVERY_ROUTE_COST)
              .setExpirationPeriod(HUB_DISCOVERY_ROUTE_EXPIRATION);

    m_controller.start<nfd::RibRegisterCommand>(
      parameters,
      [this] (const ControlParameters&) {
        ++m_nRegSuccess;
        afterReg();
      },
      [this, faceStatus] (const ControlResponse& resp) {
        std::cerr << "Error " << resp.getCode() << " when registering hub discovery prefix "
                  << "for face " << faceStatus.getFaceId() << " (" << faceStatus.getRemoteUri()
                  << "): " << resp.getText() << std::endl;
        ++m_nRegFailure;
        afterReg();
      });
  }
}

void
MulticastDiscovery::afterReg()
{
  if (m_nRegSuccess + m_nRegFailure < m_nRegs) {
    return; // continue waiting
  }
  if (m_nRegSuccess > 0) {
    this->setStrategy();
  }
  else {
    this->fail("Cannot register hub discovery prefix for any face");
  }
}

void
MulticastDiscovery::setStrategy()
{
  ControlParameters parameters;
  parameters.setName(HUB_DISCOVERY_PREFIX)
            .setStrategy("/localhost/nfd/strategy/multicast"),

  m_controller.start<nfd::StrategyChoiceSetCommand>(
    parameters,
    bind(&MulticastDiscovery::requestHubData, this),
    [this] (const ControlResponse& resp) {
      this->fail("Error " + to_string(resp.getCode()) + " when setting multicast strategy: " +
                 resp.getText());
    });
}

void
MulticastDiscovery::requestHubData()
{
  Interest interest(HUB_DISCOVERY_PREFIX);
  interest.setInterestLifetime(HUB_DISCOVERY_INTEREST_LIFETIME);
  interest.setMustBeFresh(true);

  m_face.expressInterest(interest,
    [this] (const Interest&, const Data& data) {
      const Block& content = data.getContent();
      content.parse();

      auto i = content.find(tlv::nfd::Uri);
      if (i == content.elements_end()) {
        this->fail("Malformed hub Data: missing Uri element");
        return;
      }

      this->provideHubFaceUri(std::string(reinterpret_cast<const char*>(i->value()), i->value_size()));
    },
    [this] (const Interest&, const lp::Nack& nack) {
      this->fail("Nack-" + boost::lexical_cast<std::string>(nack.getReason()) + " when retrieving hub Data");
    },
    [this] (const Interest&) {
      this->fail("Timeout when retrieving hub Data");
    });
}

} // namespace autoconfig
} // namespace tools
} // namespace ndn

max_stars_repo_name: NDNLink/NDN-Chord

max_issues_repo_name: NDNLink/NDN-Chord

max_forks_repo_name: NDNLink/NDN-Chord


text:
//
// Created by dchansen on 9/10/19.
//
#include "../connection/SocketStreamBuf.h"
#include <boost/asio.hpp>
#include <gtest/gtest.h>
#include <random>

namespace ba = boost::asio;
using tcp    = boost::asio::ip::tcp;
using namespace Gadgetron;

class SocketTest : public ::testing::Test {

public:
    SocketTest() : ::testing::Test() {
        auto endpoint = tcp::endpoint(tcp::v6(), 0);
        acceptor = std::make_unique<tcp::acceptor>(tcp::acceptor(ios, endpoint));

        auto port    = acceptor->local_endpoint().port();
        auto socketF = std::async([&]() {
            tcp::socket socket{ ios };
            acceptor->accept(socket);
            return socket;
        });

        socketstream = Connection::remote_stream("localhost", std::to_string(port));

        server_socket = std::make_unique<tcp::socket>(socketF.get());
    }

    ba::io_service ios{};
    std::unique_ptr<tcp::acceptor> acceptor;
    std::unique_ptr<std::iostream> socketstream;
    std::unique_ptr<tcp::socket> server_socket;

};

TEST_F(SocketTest, read_test) {

    auto data = std::vector<char>(19,42);
    ba::write(*server_socket,ba::buffer(data.data(),data.size()));

    auto data2 = std::vector<char>(19);

    socketstream->read(data2.data(),data2.size());

    ASSERT_EQ(data,data2);
}

TEST_F(SocketTest, write_test) {

    auto data = std::vector<char>(1u << 22,42);

    auto thread = std::thread([&](){socketstream->write(data.data(),data.size());});

    auto data2 = std::vector<char>(data.size());
    ba::read(*server_socket,ba::buffer(data2.data(),data2.size()));

    ASSERT_EQ(data,data2);
    thread.join();
}

TEST_F(SocketTest, stringstream_test) {
    const std::string name = "Albatros";
    std::stringstream sstream;
    sstream << name;
    *socketstream << sstream.rdbuf();

    std::vector<char> ref(name.size());
    ba::read(*server_socket,ba::buffer(ref.data(),ref.size()));

    std::string name2(ref.begin(),ref.end());
    ASSERT_EQ(name,name2);
}

TEST_F(SocketTest, nulltest) {
    auto data =  std::vector<char>(1u << 22,0);
    std::mt19937_64 engine;
    std::uniform_int_distribution<char> distribution(0);
    for (auto& d : data) d = distribution(engine);

    std::cout << data.size() << std::endl;
    std::stringstream sstream;
    sstream.write(data.data(),data.size());

    auto thread = std::thread([&](){   *socketstream << sstream.rdbuf(); *socketstream << sstream.rdbuf();});

    std::vector<char> ref(data.size());
    ba::read(*server_socket,ba::buffer(ref.data(),ref.size()));

    ASSERT_EQ(ref,data);
    thread.join();
}

max_stars_repo_name: roopchansinghv/gadgetron


text:
/*
Copyright 2020 The Magma Authors.

This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree.

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <boost/exception/diagnostic_information.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/lookup_edge.hpp>
#include <boost/graph/topological_sort.hpp>
#include <devmand/devices/cli/translation/WriterRegistry.h>

namespace devmand {
namespace devices {
namespace cli {

void WriterRegistryBuilder::addWriter(
    Path path,
    shared_ptr<Writer> writer,
    vector<Path> dependencies) {
  if (schemaContext != SchemaContext::NO_MODELS) {
    if (!schemaContext.isPathValid(path)) {
      throw WriterRegistryException(
          "Unable to register writer for path: " + path.str() +
          ". Path is not valid");
    }
    for (auto& depPath : dependencies) {
      if (!schemaContext.isPathValid(depPath)) {
        throw WriterRegistryException(
            "Unable to register writer for path: " + path.str() +
            ". Dependency path is not valid" + depPath.str());
      }
    }
  }

  allWriters.emplace(path, WriterWithDependencies{writer, dependencies});
}

static vector<Path> topologicalSort(YangHierarchy pathGraph) {
  vector<YangHierarchy::vertex_descriptor> topologicalOrderIndex;
  try {
    topological_sort(pathGraph, back_inserter(topologicalOrderIndex));
  } catch (boost::not_a_dag& e) {
    throw WriterRegistryException(
        "Unable to build writer registry, dependency cycle detected");
  } catch (exception& e) {
    throw WriterRegistryException(
        "Unable to build writer registry, unknown error: " + string(e.what()));
  }
  vector<Path> topologicalOrder;
  for (auto& index : topologicalOrderIndex) {
    topologicalOrder.push_back(pathGraph.graph()[index].path);
  }
  return topologicalOrder;
}

unique_ptr<WriterRegistry> WriterRegistryBuilder::build() {
  if (allWriters.empty()) {
    return make_unique<WriterRegistry>(
        map<Path, shared_ptr<Writer>, SortedPathComparator>(
            SortedPathComparator({})));
  }

  YangHierarchy pathGraph;

  for (auto& writer : allWriters) {
    Path childPath = writer.first;
    shared_ptr<Writer> childHandler = writer.second.writer;
    vector<Path> childDependencies = writer.second.dependencies;

    YangHierarchy::vertex_descriptor childVertex =
        boost::add_vertex(childPath, pathGraph);
    pathGraph[childPath].path = childPath;

    for (auto& depPath : childDependencies) {
      YangHierarchy::vertex_descriptor depVertex =
          boost::add_vertex(depPath, pathGraph);
      pathGraph[depPath].path = depPath;

      if (!boost::lookup_edge(depVertex, childVertex, pathGraph).second) {
        boost::add_edge_by_label(depPath, childPath, pathGraph);
      }
    }
  }

  // order writers by their dependencies
  vector<Path> topologicalOrder = topologicalSort(pathGraph);

  if (VLOG_IS_ON(MDEBUG)) {
    stringstream dotGraph;
    boost::write_graphviz(dotGraph, pathGraph, PathVertexWriter(pathGraph));
    MLOG(MDEBUG) << "Writer hierarchy calculated: " << dotGraph.str();
  }

  // put writers into and ordered map to preserve dependencies among them
  auto orderedWriters = map<Path, shared_ptr<Writer>, SortedPathComparator>(
      SortedPathComparator(topologicalOrder));
  for (auto& writerWithDeps : allWriters) {
    orderedWriters.insert(
        make_pair(writerWithDeps.first, writerWithDeps.second.writer));
  }

  return make_unique<WriterRegistry>(orderedWriters);
}

ostream& operator<<(ostream& os, const WriterRegistry& registry) {
  os << "WriterRegistry:";
  os << endl;
  for (auto& writer : registry.orderedWriters) {
    os << " " << writer.first << endl;
  }
  return os;
}

static bool writerHasUpdates(
    const WriterRegistry::Diff& diff,
    const Path& registeredPath) {
  return diff.find(registeredPath) != diff.end();
}

static void writeSingle(
    const DatastoreDiff& update,
    const Writer& writer,
    const DeviceAccess& device) {
  switch (update.type) {
    case DatastoreDiffType::create: {
      writer.create(update.keyedPath, update.after, device).get();
      break;
    }
    case DatastoreDiffType::update: {
      writer.update(update.keyedPath, update.before, update.after, device)
          .get();
      break;
    }
    case DatastoreDiffType::deleted: {
      writer.remove(update.keyedPath, update.before, device).get();
      break;
    }
  }
}

void WriterRegistry::write(const Diff& diff, const DeviceAccess& device) const {
  for (auto& writer : orderedWriters) {
    auto& registeredPath = writer.first;
    if (writerHasUpdates(diff, registeredPath)) {
      auto updateRange = diff.equal_range(registeredPath);
      for (auto itr = updateRange.first; itr != updateRange.second; ++itr) {
        DatastoreDiff update = (*itr).second;
        // TODO handle exceptions and do rollback
        writeSingle(update, *writer.second, device);
      }
    }
  }
}

vector<Path> WriterRegistry::getWriterPaths() const {
  vector<Path> pathsCopy = vector<Path>();
  for (auto& writer : orderedWriters) {
    pathsCopy.push_back(writer.first);
  }
  return pathsCopy;
}

} // namespace cli
} // namespace devices
} // namespace devmand

max_stars_repo_name: gurrapualt/magma

max_issues_repo_name: gurrapualt/magma


text:
/***************************************************************************
 * Copyright 1998-2018 by authors (see AUTHORS.txt)                        *
 *                                                                         *
 *   This file is part of LuxCoreRender.                                   *
 *                                                                         *
 * Licensed under the Apache License, Version 2.0 (the "License");         *
 * you may not use this file except in compliance with the License.        *
 * You may obtain a copy of the License at                                 *
 *                                                                         *
 *     http://www.apache.org/licenses/LICENSE-2.0                          *
 *                                                                         *
 * Unless required by applicable law or agreed to in writing, software     *
 * distributed under the License is distributed on an "AS IS" BASIS,       *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*
 * See the License for the specific language governing permissions and     *
 * limitations under the License.                                          *
 ***************************************************************************/

#include <boost/lexical_cast.hpp>

#include "luxrays/core/color/color.h"
#include "slg/samplers/sampler.h"
#include "slg/samplers/sobol.h"

using namespace std;
using namespace luxrays;
using namespace slg;

//------------------------------------------------------------------------------
// SobolSamplerSharedData
//------------------------------------------------------------------------------

SobolSamplerSharedData::SobolSamplerSharedData(RandomGenerator *rndGen, Film *engineFlm) : SamplerSharedData() {
	engineFilm = engineFlm;
	seedBase = rndGen->uintValue() % (0xFFFFFFFFu - 1u) + 1u;

	const u_int *subRegion = engineFilm->GetSubRegion();
	filmRegionPixelCount = (subRegion[1] - subRegion[0] + 1) * (subRegion[3] - subRegion[2] + 1);
	pixelIndex = 0;

	pass = SOBOL_STARTOFFSET;
}

void SobolSamplerSharedData::GetNewPixelIndex(u_int &index, u_int &sobolPass, u_int &seed) {
	SpinLocker spinLocker(spinLock);

	index = pixelIndex;
	sobolPass = pass;
	seed = (seedBase + pixelIndex) % (0xFFFFFFFFu - 1u) + 1u;

	pixelIndex += SOBOL_THREAD_WORK_SIZE;
	if (pixelIndex >= filmRegionPixelCount) {
		pixelIndex = 0;
		pass++;
	}
}

SamplerSharedData *SobolSamplerSharedData::FromProperties(const Properties &cfg,
		RandomGenerator *rndGen, Film *film) {
	return new SobolSamplerSharedData(rndGen, film);
}

//------------------------------------------------------------------------------
// Sobol sampler
//
// This sampler is based on Blender Cycles Sobol implementation.
//------------------------------------------------------------------------------

SobolSampler::SobolSampler(RandomGenerator *rnd, Film *flm,
		const FilmSampleSplatter *flmSplatter,
		const float adaptiveStr,
		SobolSamplerSharedData *samplerSharedData) : Sampler(rnd, flm, flmSplatter),
		sharedData(samplerSharedData), sobolSequence(), adaptiveStrength(adaptiveStr),
		rngGenerator(131) {
}

SobolSampler::~SobolSampler() {
}

void SobolSampler::InitNewSample() {
	for (;;) {
		// Update pixelIndexOffset

		pixelIndexOffset++;
		if ((pixelIndexOffset >= SOBOL_THREAD_WORK_SIZE) ||
				(pixelIndexBase + pixelIndexOffset >= sharedData->filmRegionPixelCount)) {
			// Ask for a new base
			u_int seed;
			sharedData->GetNewPixelIndex(pixelIndexBase, pass, seed);
			pixelIndexOffset = 0;

			// Initialize the rng0, rng1 and rngPass generator
			rngGenerator.init(seed);
		}

		// Initialize sample0 and sample 1

		const u_int *subRegion = film->GetSubRegion();

		const u_int pixelIndex = (pixelIndexBase + pixelIndexOffset) % sharedData->filmRegionPixelCount;
		const u_int subRegionWidth = subRegion[1] - subRegion[0] + 1;
		const u_int pixelX = subRegion[0] + (pixelIndex % subRegionWidth);
		const u_int pixelY = subRegion[2] + (pixelIndex / subRegionWidth);

		// Check if the current pixel is over or hunter the convergence threshold
		const Film *film = sharedData->engineFilm;
		if ((adaptiveStrength > 0.f) && film->HasChannel(Film::CONVERGENCE) &&
				(*(film->channel_CONVERGENCE->GetPixel(pixelX, pixelY)) == 0.f)) {
			// This pixel is already under the convergence threshold. Check if to
			// render or not
			if (rndGen->floatValue() < adaptiveStrength) {
				// Skip this pixel and try the next one
				continue;
			}
		}

		// Initialize rng0, rng1 and rngPass

		sobolSequence.rng0 = rngGenerator.floatValue();
		sobolSequence.rng1 = rngGenerator.floatValue();
		// Limit the number of pass skipped
		sobolSequence.rngPass = rngGenerator.uintValue();

		sample0 = pixelX +  sobolSequence.GetSample(pass, 0);
		sample1 = pixelY +  sobolSequence.GetSample(pass, 1);
		break;
	}
}

void SobolSampler::RequestSamples(const u_int size) {
	sobolSequence.RequestSamples(size);

	pixelIndexOffset = SOBOL_THREAD_WORK_SIZE;
	InitNewSample();
}

float SobolSampler::GetSample(const u_int index) {
	switch (index) {
		case 0:
			return sample0;
		case 1:
			return sample1;
		default:
			return sobolSequence.GetSample(pass, index);
	}
}

void SobolSampler::NextSample(const vector<SampleResult> &sampleResults) {
	film->AddSampleCount(1.0);
	AddSamplesToFilm(sampleResults);

	InitNewSample();
}

Properties SobolSampler::ToProperties() const {
	return Sampler::ToProperties() <<
			Property("sampler.random.adaptive.strength")(adaptiveStrength);
}

//------------------------------------------------------------------------------
// Static methods used by SamplerRegistry
//------------------------------------------------------------------------------

Properties SobolSampler::ToProperties(const Properties &cfg) {
	return Properties() <<
			cfg.Get(GetDefaultProps().Get("sampler.type")) <<
			cfg.Get(GetDefaultProps().Get("sampler.sobol.adaptive.strength"));
}

Sampler *SobolSampler::FromProperties(const Properties &cfg, RandomGenerator *rndGen,
		Film *film, const FilmSampleSplatter *flmSplatter, SamplerSharedData *sharedData) {
	const float str = Clamp(cfg.Get(GetDefaultProps().Get("sampler.sobol.adaptive.strength")).Get<float>(), 0.f, .95f);

	return new SobolSampler(rndGen, film, flmSplatter, str, (SobolSamplerSharedData *)sharedData);
}

slg::ocl::Sampler *SobolSampler::FromPropertiesOCL(const Properties &cfg) {
	slg::ocl::Sampler *oclSampler = new slg::ocl::Sampler();

	oclSampler->type = slg::ocl::SOBOL;
	oclSampler->sobol.adaptiveStrength = Clamp(cfg.Get(GetDefaultProps().Get("sampler.sobol.adaptive.strength")).Get<float>(), 0.f, .95f);

	return oclSampler;
}

Film::FilmChannelType SobolSampler::GetRequiredChannels(const luxrays::Properties &cfg) {
	const float str = cfg.Get(GetDefaultProps().Get("sampler.sobol.adaptive.strength")).Get<float>();

	if (str > 0.f)
		return Film::CONVERGENCE;
	else
		return Film::NONE;
}

const Properties &SobolSampler::GetDefaultProps() {
	static Properties props = Properties() <<
			Sampler::GetDefaultProps() <<
			Property("sampler.type")(GetObjectTag()) <<
			Property("sampler.sobol.adaptive.strength")(.7f);

	return props;
}

max_stars_repo_name: tschw/LuxCore

max_issues_repo_name: tschw/LuxCore

max_forks_repo_name: tschw/LuxCore


text:
#include <eos/eoslib/field_metadata.hpp>
#include <eos/eoslib/exceptions.hpp>

#ifdef EOS_TYPES_FULL_CAPABILITY
#include <ostream>
#include <iomanip>
#include <boost/io/ios_state.hpp>
#endif

namespace eos { namespace types {

   field_metadata::field_metadata(uint64_t storage, bool skip_validation)
   {
      if( skip_validation )
      {
         _tid = type_id(static_cast<uint32_t>(storage >> 32), true);
         _extra = static_cast<uint32_t>(storage & 0xFFFFFFFF);
      }
      else
      {
         auto f = field_metadata(storage);
         _tid   = f._tid;
         _extra = f._extra;
      }
   }

   field_metadata::field_metadata(uint64_t storage)
      : _tid(static_cast<uint32_t>(storage >> 32)), _extra(static_cast<uint32_t>(storage & 0xFFFFFFFF))
   {
      if( is_offset_in_bits() )
      {
         if( offset_window::get(_extra) >= offset_limit_in_bits )
            EOS_ERROR(std::invalid_argument, "Offset (specified in bits) is too large.");
      }
      else
      {
         if( offset_window::get(_extra) >= offset_limit )
            EOS_ERROR(std::invalid_argument, "Offset is too large.");
      }
   }

   field_metadata::field_metadata()
      : _tid(), _extra(0)
   {}

   field_metadata::field_metadata(type_id tid, uint32_t offset, sort_order so)
      : _tid(tid), _extra(0)
   {
      if( offset >= offset_limit )
         EOS_ERROR(std::domain_error, "Offset is too large");

      offset_window::set(_extra, offset);

     if( so != unsorted )
      {
         sorted_window::set(_extra, true);
         ascending_window::set(_extra, (so == ascending));
      }
   }

   void field_metadata::set_offset(uint32_t offset)
   {
      if( offset >= offset_limit )
         EOS_ERROR(std::domain_error, "Offset is too large.");

      if( is_offset_in_bits() )
         offset <<= 3;

      offset_window::set(_extra, offset);
   }

   void field_metadata::set_offset_in_bits(uint32_t offset)
   {
      if( offset >= offset_limit_in_bits )
         EOS_ERROR(std::domain_error, "Offset is too large.");

      if( !is_offset_in_bits() )
         offset >>= 3;

      offset_window::set(_extra, offset);
   }

#ifdef EOS_TYPES_FULL_CAPABILITY
   std::ostream& operator<<(std::ostream& os, const field_metadata& f)
   {
      boost::io::ios_flags_saver ifs( os );

      os << std::dec;

      os <<  f.get_type_id();

      // Write sort order information (if sorted)
      auto so = f.get_sort_order();
      if( so != field_metadata::unsorted )
      {
         os << " (sorted in ";
         if( so == field_metadata::ascending )
            os << "ascending";
         else
            os << "descending";
         os << " order)";
      }

      // Write offset
      os << " located at offset 0x" << std::hex << f.get_offset() << std::dec;

      return os;
   }
#endif

} }

max_stars_repo_name: arhag/eos-dynamic-tables

max_issues_repo_name: arhag/eos-dynamic-tables

max_forks_repo_name: arhag/eos-dynamic-tables


text:
// Copyright (c) 2018-2019, The Arqma Network
// Copyright (c) 2017-2018, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
//    conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
//    of conditions and the following disclaimer in the documentation and/or other
//    materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
//    used to endorse or promote products derived from this software without specific
//    prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Adapted from Java code by Sarang Noether

#include <stdlib.h>
#include <openssl/ssl.h>
#include <boost/thread/mutex.hpp>
#include <boost/thread/lock_guard.hpp>
#include "misc_log_ex.h"
#include "common/perf_timer.h"
extern "C"
{
#include "crypto/crypto-ops.h"
}
#include "rctOps.h"
#include "bulletproofs.h"

#undef ARQMA_DEFAULT_LOG_CATEGORY
#define ARQMA_DEFAULT_LOG_CATEGORY "bulletproofs"

//#define DEBUG_BP

#define PERF_TIMER_START_BP(x) PERF_TIMER_START_UNIT(x, 1000000)

namespace rct
{

static rct::key vector_exponent(const rct::keyV &a, const rct::keyV &b);
static rct::keyV vector_powers(rct::key x, size_t n);
static rct::key inner_product(const rct::keyV &a, const rct::keyV &b);

static constexpr size_t maxN = 64;
static rct::key Hi[maxN], Gi[maxN];
static ge_dsmp Gprecomp[64], Hprecomp[64];
static const rct::key TWO = { {0x02, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00  } };
static const rct::keyV oneN = vector_powers(rct::identity(), maxN);
static const rct::keyV twoN = vector_powers(TWO, maxN);
static const rct::key ip12 = inner_product(oneN, twoN);
static boost::mutex init_mutex;

static rct::key get_exponent(const rct::key &base, size_t idx)
{
  static const std::string salt("bulletproof");
  std::string hashed = std::string((const char*)base.bytes, sizeof(base)) + salt + tools::get_varint_data(idx);
  return rct::hashToPoint(rct::hash2rct(crypto::cn_fast_hash(hashed.data(), hashed.size())));
}

static void init_exponents()
{
  boost::lock_guard<boost::mutex> lock(init_mutex);

  static bool init_done = false;
  if (init_done)
    return;
  for (size_t i = 0; i < maxN; ++i)
  {
    Hi[i] = get_exponent(rct::H, i * 2);
    rct::precomp(Hprecomp[i], Hi[i]);
    Gi[i] = get_exponent(rct::H, i * 2 + 1);
    rct::precomp(Gprecomp[i], Gi[i]);
  }
  init_done = true;
}

static bool is_reduced(const rct::key &scalar)
{
  rct::key reduced = scalar;
  sc_reduce32(reduced.bytes);
  return scalar == reduced;
}

/* Given two scalar arrays, construct a vector commitment */
static rct::key vector_exponent(const rct::keyV &a, const rct::keyV &b)
{
  CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b");
  CHECK_AND_ASSERT_THROW_MES(a.size() <= maxN, "Incompatible sizes of a and maxN");
  rct::key res = rct::identity();
  for (size_t i = 0; i < a.size(); ++i)
  {
    rct::key term;
    rct::addKeys3(term, a[i], Gprecomp[i], b[i], Hprecomp[i]);
    rct::addKeys(res, res, term);
  }
  return res;
}

/* Compute a custom vector-scalar commitment */
static rct::key vector_exponent_custom(const rct::keyV &A, const rct::keyV &B, const rct::keyV &a, const rct::keyV &b)
{
  CHECK_AND_ASSERT_THROW_MES(A.size() == B.size(), "Incompatible sizes of A and B");
  CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b");
  CHECK_AND_ASSERT_THROW_MES(a.size() == A.size(), "Incompatible sizes of a and A");
  CHECK_AND_ASSERT_THROW_MES(a.size() <= maxN, "Incompatible sizes of a and maxN");
  rct::key res = rct::identity();
  for (size_t i = 0; i < a.size(); ++i)
  {
    rct::key term;
#if 0
    // we happen to know where A and B might fall, so don't bother checking the rest
    ge_dsmp *Acache = NULL, *Bcache = NULL;
    ge_dsmp Acache_custom[1], Bcache_custom[1];
    if (Gi[i] == A[i])
      Acache = Gprecomp + i;
    else if (i<32 && Gi[i+32] == A[i])
      Acache = Gprecomp + i + 32;
    else
    {
      rct::precomp(Acache_custom[0], A[i]);
      Acache = Acache_custom;
    }
    if (i == 0 && B[i] == Hi[0])
      Bcache = Hprecomp;
    else
    {
      rct::precomp(Bcache_custom[0], B[i]);
      Bcache = Bcache_custom;
    }
    rct::addKeys3(term, a[i], *Acache, b[i], *Bcache);
#else
    ge_dsmp Acache, Bcache;
    rct::precomp(Bcache, B[i]);
    rct::addKeys3(term, a[i], A[i], b[i], Bcache);
#endif
    rct::addKeys(res, res, term);
  }
  return res;
}

/* Given a scalar, construct a vector of powers */
static rct::keyV vector_powers(rct::key x, size_t n)
{
  rct::keyV res(n);
  if (n == 0)
    return res;
  res[0] = rct::identity();
  if (n == 1)
    return res;
  res[1] = x;
  for (size_t i = 2; i < n; ++i)
  {
    sc_mul(res[i].bytes, res[i-1].bytes, x.bytes);
  }
  return res;
}

/* Given two scalar arrays, construct the inner product */
static rct::key inner_product(const rct::keyV &a, const rct::keyV &b)
{
  CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b");
  rct::key res = rct::zero();
  for (size_t i = 0; i < a.size(); ++i)
  {
    sc_muladd(res.bytes, a[i].bytes, b[i].bytes, res.bytes);
  }
  return res;
}

/* Given two scalar arrays, construct the Hadamard product */
static rct::keyV hadamard(const rct::keyV &a, const rct::keyV &b)
{
  CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b");
  rct::keyV res(a.size());
  for (size_t i = 0; i < a.size(); ++i)
  {
    sc_mul(res[i].bytes, a[i].bytes, b[i].bytes);
  }
  return res;
}

/* Given two curvepoint arrays, construct the Hadamard product */
static rct::keyV hadamard2(const rct::keyV &a, const rct::keyV &b)
{
  CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b");
  rct::keyV res(a.size());
  for (size_t i = 0; i < a.size(); ++i)
  {
    rct::addKeys(res[i], a[i], b[i]);
  }
  return res;
}

/* Add two vectors */
static rct::keyV vector_add(const rct::keyV &a, const rct::keyV &b)
{
  CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b");
  rct::keyV res(a.size());
  for (size_t i = 0; i < a.size(); ++i)
  {
    sc_add(res[i].bytes, a[i].bytes, b[i].bytes);
  }
  return res;
}

/* Subtract two vectors */
static rct::keyV vector_subtract(const rct::keyV &a, const rct::keyV &b)
{
  CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b");
  rct::keyV res(a.size());
  for (size_t i = 0; i < a.size(); ++i)
  {
    sc_sub(res[i].bytes, a[i].bytes, b[i].bytes);
  }
  return res;
}

/* Multiply a scalar and a vector */
static rct::keyV vector_scalar(const rct::keyV &a, const rct::key &x)
{
  rct::keyV res(a.size());
  for (size_t i = 0; i < a.size(); ++i)
  {
    sc_mul(res[i].bytes, a[i].bytes, x.bytes);
  }
  return res;
}

/* Exponentiate a curve vector by a scalar */
static rct::keyV vector_scalar2(const rct::keyV &a, const rct::key &x)
{
  rct::keyV res(a.size());
  for (size_t i = 0; i < a.size(); ++i)
  {
    rct::scalarmultKey(res[i], a[i], x);
  }
  return res;
}

static rct::key switch_endianness(rct::key k)
{
  std::reverse(k.bytes, k.bytes + sizeof(k));
  return k;
}

/* Compute the inverse of a scalar, the stupid way */
static rct::key invert(const rct::key &x)
{
  rct::key inv;

  BN_CTX *ctx = BN_CTX_new();
  BIGNUM *X = BN_new();
  BIGNUM *L = BN_new();
  BIGNUM *I = BN_new();

  BN_bin2bn(switch_endianness(x).bytes, sizeof(rct::key), X);
  BN_bin2bn(switch_endianness(rct::curveOrder()).bytes, sizeof(rct::key), L);

  CHECK_AND_ASSERT_THROW_MES(BN_mod_inverse(I, X, L, ctx), "Failed to invert");

  const int len = BN_num_bytes(I);
  CHECK_AND_ASSERT_THROW_MES((size_t)len <= sizeof(rct::key), "Invalid number length");
  inv = rct::zero();
  BN_bn2bin(I, inv.bytes);
  std::reverse(inv.bytes, inv.bytes + len);

  BN_free(I);
  BN_free(L);
  BN_free(X);
  BN_CTX_free(ctx);

#ifdef DEBUG_BP
  rct::key tmp;
  sc_mul(tmp.bytes, inv.bytes, x.bytes);
  CHECK_AND_ASSERT_THROW_MES(tmp == rct::identity(), "invert failed");
#endif
  return inv;
}

/* Compute the slice of a vector */
static rct::keyV slice(const rct::keyV &a, size_t start, size_t stop)
{
  CHECK_AND_ASSERT_THROW_MES(start < a.size(), "Invalid start index");
  CHECK_AND_ASSERT_THROW_MES(stop <= a.size(), "Invalid stop index");
  CHECK_AND_ASSERT_THROW_MES(start < stop, "Invalid start/stop indices");
  rct::keyV res(stop - start);
  for (size_t i = start; i < stop; ++i)
  {
    res[i - start] = a[i];
  }
  return res;
}

static rct::key hash_cache_mash(rct::key &hash_cache, const rct::key &mash0, const rct::key &mash1)
{
  rct::keyV data;
  data.reserve(3);
  data.push_back(hash_cache);
  data.push_back(mash0);
  data.push_back(mash1);
  return hash_cache = rct::hash_to_scalar(data);
}

static rct::key hash_cache_mash(rct::key &hash_cache, const rct::key &mash0, const rct::key &mash1, const rct::key &mash2)
{
  rct::keyV data;
  data.reserve(4);
  data.push_back(hash_cache);
  data.push_back(mash0);
  data.push_back(mash1);
  data.push_back(mash2);
  return hash_cache = rct::hash_to_scalar(data);
}

static rct::key hash_cache_mash(rct::key &hash_cache, const rct::key &mash0, const rct::key &mash1, const rct::key &mash2, const rct::key &mash3)
{
  rct::keyV data;
  data.reserve(5);
  data.push_back(hash_cache);
  data.push_back(mash0);
  data.push_back(mash1);
  data.push_back(mash2);
  data.push_back(mash3);
  return hash_cache = rct::hash_to_scalar(data);
}

/* Given a value v (0..2^N-1) and a mask gamma, construct a range proof */
Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma)
{
  CHECK_AND_ASSERT_THROW_MES(is_reduced(sv), "Invalid sv input");
  CHECK_AND_ASSERT_THROW_MES(is_reduced(gamma), "Invalid gamma input");

  init_exponents();

  PERF_TIMER_UNIT(PROVE, 1000000);

  constexpr size_t logN = 6; // log2(64)
  constexpr size_t N = 1<<logN;

  rct::key V;
  rct::keyV aL(N), aR(N);

  PERF_TIMER_START_BP(PROVE_v);
  rct::addKeys2(V, gamma, sv, rct::H);
  PERF_TIMER_STOP(PROVE_v);

  PERF_TIMER_START_BP(PROVE_aLaR);
  for (size_t i = N; i-- > 0; )
  {
    if (sv[i/8] & (((uint64_t)1)<<(i%8)))
    {
      aL[i] = rct::identity();
    }
    else
    {
      aL[i] = rct::zero();
    }
    sc_sub(aR[i].bytes, aL[i].bytes, rct::identity().bytes);
  }
  PERF_TIMER_STOP(PROVE_aLaR);

  rct::key hash_cache = rct::hash_to_scalar(V);

  // DEBUG: Test to ensure this recovers the value
#ifdef DEBUG_BP
  uint64_t test_aL = 0, test_aR = 0;
  for (size_t i = 0; i < N; ++i)
  {
    if (aL[i] == rct::identity())
      test_aL += ((uint64_t)1)<<i;
    if (aR[i] == rct::zero())
      test_aR += ((uint64_t)1)<<i;
  }
  uint64_t v_test = 0;
  for (int n = 0; n < 8; ++n) v_test |= (((uint64_t)sv[n]) << (8*n));
  CHECK_AND_ASSERT_THROW_MES(test_aL == v_test, "test_aL failed");
  CHECK_AND_ASSERT_THROW_MES(test_aR == v_test, "test_aR failed");
#endif

  PERF_TIMER_START_BP(PROVE_step1);
  // PAPER LINES 38-39
  rct::key alpha = rct::skGen();
  rct::key ve = vector_exponent(aL, aR);
  rct::key A;
  rct::addKeys(A, ve, rct::scalarmultBase(alpha));

  // PAPER LINES 40-42
  rct::keyV sL = rct::skvGen(N), sR = rct::skvGen(N);
  rct::key rho = rct::skGen();
  ve = vector_exponent(sL, sR);
  rct::key S;
  rct::addKeys(S, ve, rct::scalarmultBase(rho));

  // PAPER LINES 43-45
  rct::key y = hash_cache_mash(hash_cache, A, S);
  rct::key z = hash_cache = rct::hash_to_scalar(y);

  // Polynomial construction before PAPER LINE 46
  rct::key t0 = rct::zero();
  rct::key t1 = rct::zero();
  rct::key t2 = rct::zero();

  const auto yN = vector_powers(y, N);

  rct::key ip1y = inner_product(oneN, yN);
  rct::key tmp;
  sc_muladd(t0.bytes, z.bytes, ip1y.bytes, t0.bytes);

  rct::key zsq;
  sc_mul(zsq.bytes, z.bytes, z.bytes);
  sc_muladd(t0.bytes, zsq.bytes, sv.bytes, t0.bytes);

  rct::key k = rct::zero();
  sc_mulsub(k.bytes, zsq.bytes, ip1y.bytes, k.bytes);

  rct::key zcu;
  sc_mul(zcu.bytes, zsq.bytes, z.bytes);
  sc_mulsub(k.bytes, zcu.bytes, ip12.bytes, k.bytes);
  sc_add(t0.bytes, t0.bytes, k.bytes);

  // DEBUG: Test the value of t0 has the correct form
#ifdef DEBUG_BP
  rct::key test_t0 = rct::zero();
  rct::key iph = inner_product(aL, hadamard(aR, yN));
  sc_add(test_t0.bytes, test_t0.bytes, iph.bytes);
  rct::key ips = inner_product(vector_subtract(aL, aR), yN);
  sc_muladd(test_t0.bytes, z.bytes, ips.bytes, test_t0.bytes);
  rct::key ipt = inner_product(twoN, aL);
  sc_muladd(test_t0.bytes, zsq.bytes, ipt.bytes, test_t0.bytes);
  sc_add(test_t0.bytes, test_t0.bytes, k.bytes);
  CHECK_AND_ASSERT_THROW_MES(t0 == test_t0, "t0 check failed");
#endif
  PERF_TIMER_STOP(PROVE_step1);

  PERF_TIMER_START_BP(PROVE_step2);
  const auto HyNsR = hadamard(yN, sR);
  const auto vpIz = vector_scalar(oneN, z);
  const auto vp2zsq = vector_scalar(twoN, zsq);
  const auto aL_vpIz = vector_subtract(aL, vpIz);
  const auto aR_vpIz = vector_add(aR, vpIz);

  rct::key ip1 = inner_product(aL_vpIz, HyNsR);
  sc_add(t1.bytes, t1.bytes, ip1.bytes);

  rct::key ip2 = inner_product(sL, vector_add(hadamard(yN, aR_vpIz), vp2zsq));
  sc_add(t1.bytes, t1.bytes, ip2.bytes);

  rct::key ip3 = inner_product(sL, HyNsR);
  sc_add(t2.bytes, t2.bytes, ip3.bytes);

  // PAPER LINES 47-48
  rct::key tau1 = rct::skGen(), tau2 = rct::skGen();

  rct::key T1 = rct::addKeys(rct::scalarmultKey(rct::H, t1), rct::scalarmultBase(tau1));
  rct::key T2 = rct::addKeys(rct::scalarmultKey(rct::H, t2), rct::scalarmultBase(tau2));

  // PAPER LINES 49-51
  rct::key x = hash_cache_mash(hash_cache, z, T1, T2);

  // PAPER LINES 52-53
  rct::key taux = rct::zero();
  sc_mul(taux.bytes, tau1.bytes, x.bytes);
  rct::key xsq;
  sc_mul(xsq.bytes, x.bytes, x.bytes);
  sc_muladd(taux.bytes, tau2.bytes, xsq.bytes, taux.bytes);
  sc_muladd(taux.bytes, gamma.bytes, zsq.bytes, taux.bytes);
  rct::key mu;
  sc_muladd(mu.bytes, x.bytes, rho.bytes, alpha.bytes);

  // PAPER LINES 54-57
  rct::keyV l = vector_add(aL_vpIz, vector_scalar(sL, x));
  rct::keyV r = vector_add(hadamard(yN, vector_add(aR_vpIz, vector_scalar(sR, x))), vp2zsq);
  PERF_TIMER_STOP(PROVE_step2);

  PERF_TIMER_START_BP(PROVE_step3);
  rct::key t = inner_product(l, r);

  // DEBUG: Test if the l and r vectors match the polynomial forms
#ifdef DEBUG_BP
  rct::key test_t;
  sc_muladd(test_t.bytes, t1.bytes, x.bytes, t0.bytes);
  sc_muladd(test_t.bytes, t2.bytes, xsq.bytes, test_t.bytes);
  CHECK_AND_ASSERT_THROW_MES(test_t == t, "test_t check failed");
#endif

  // PAPER LINES 32-33
  rct::key x_ip = hash_cache_mash(hash_cache, x, taux, mu, t);

  // These are used in the inner product rounds
  size_t nprime = N;
  rct::keyV Gprime(N);
  rct::keyV Hprime(N);
  rct::keyV aprime(N);
  rct::keyV bprime(N);
  const rct::key yinv = invert(y);
  rct::key yinvpow = rct::identity();
  for (size_t i = 0; i < N; ++i)
  {
    Gprime[i] = Gi[i];
    Hprime[i] = scalarmultKey(Hi[i], yinvpow);
    sc_mul(yinvpow.bytes, yinvpow.bytes, yinv.bytes);
    aprime[i] = l[i];
    bprime[i] = r[i];
  }
  rct::keyV L(logN);
  rct::keyV R(logN);
  int round = 0;
  rct::keyV w(logN); // this is the challenge x in the inner product protocol
  PERF_TIMER_STOP(PROVE_step3);

  PERF_TIMER_START_BP(PROVE_step4);
  // PAPER LINE 13
  while (nprime > 1)
  {
    // PAPER LINE 15
    nprime /= 2;

    // PAPER LINES 16-17
    rct::key cL = inner_product(slice(aprime, 0, nprime), slice(bprime, nprime, bprime.size()));
    rct::key cR = inner_product(slice(aprime, nprime, aprime.size()), slice(bprime, 0, nprime));

    // PAPER LINES 18-19
    L[round] = vector_exponent_custom(slice(Gprime, nprime, Gprime.size()), slice(Hprime, 0, nprime), slice(aprime, 0, nprime), slice(bprime, nprime, bprime.size()));
    sc_mul(tmp.bytes, cL.bytes, x_ip.bytes);
    rct::addKeys(L[round], L[round], rct::scalarmultKey(rct::H, tmp));
    R[round] = vector_exponent_custom(slice(Gprime, 0, nprime), slice(Hprime, nprime, Hprime.size()), slice(aprime, nprime, aprime.size()), slice(bprime, 0, nprime));
    sc_mul(tmp.bytes, cR.bytes, x_ip.bytes);
    rct::addKeys(R[round], R[round], rct::scalarmultKey(rct::H, tmp));

    // PAPER LINES 21-22
    w[round] = hash_cache_mash(hash_cache, L[round], R[round]);

    // PAPER LINES 24-25
    const rct::key winv = invert(w[round]);
    Gprime = hadamard2(vector_scalar2(slice(Gprime, 0, nprime), winv), vector_scalar2(slice(Gprime, nprime, Gprime.size()), w[round]));
    Hprime = hadamard2(vector_scalar2(slice(Hprime, 0, nprime), w[round]), vector_scalar2(slice(Hprime, nprime, Hprime.size()), winv));

    // PAPER LINES 28-29
    aprime = vector_add(vector_scalar(slice(aprime, 0, nprime), w[round]), vector_scalar(slice(aprime, nprime, aprime.size()), winv));
    bprime = vector_add(vector_scalar(slice(bprime, 0, nprime), winv), vector_scalar(slice(bprime, nprime, bprime.size()), w[round]));

    ++round;
  }
  PERF_TIMER_STOP(PROVE_step4);

  // PAPER LINE 58 (with inclusions from PAPER LINE 8 and PAPER LINE 20)
  return Bulletproof(V, A, S, T1, T2, taux, mu, L, R, aprime[0], bprime[0], t);
}

Bulletproof bulletproof_PROVE(uint64_t v, const rct::key &gamma)
{
  // vG + gammaH
  PERF_TIMER_START_BP(PROVE_v);
  rct::key sv = rct::zero();
  sv.bytes[0] = v & 255;
  sv.bytes[1] = (v >> 8) & 255;
  sv.bytes[2] = (v >> 16) & 255;
  sv.bytes[3] = (v >> 24) & 255;
  sv.bytes[4] = (v >> 32) & 255;
  sv.bytes[5] = (v >> 40) & 255;
  sv.bytes[6] = (v >> 48) & 255;
  sv.bytes[7] = (v >> 56) & 255;
  PERF_TIMER_STOP(PROVE_v);
  return bulletproof_PROVE(sv, gamma);
}

/* Given a range proof, determine if it is valid */
bool bulletproof_VERIFY(const Bulletproof &proof)
{
  init_exponents();

  CHECK_AND_ASSERT_MES(proof.V.size() == 1, false, "V does not have exactly one element");
  CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), false, "Mismatched L and R sizes");
  CHECK_AND_ASSERT_MES(proof.L.size() > 0, false, "Empty proof");
  CHECK_AND_ASSERT_MES(proof.L.size() == 6, false, "Proof is not for 64 bits");

  for (const rct::key &k: proof.V)
    CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(k), false, "Input point not in subgroup");
  for (const rct::key &k: proof.L)
    CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(k), false, "Input point not in subgroup");
  for (const rct::key &k: proof.R)
    CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(k), false, "Input point not in subgroup");

  CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(proof.A), false, "Input point not in subgroup");
  CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(proof.S), false, "Input point not in subgroup");
  CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(proof.T1), false, "Input point not in subgroup");
  CHECK_AND_ASSERT_MES(rct::isInMainSubgroup(proof.T2), false, "Input point not in subgroup");

  // check scalar range
  CHECK_AND_ASSERT_MES(is_reduced(proof.taux), false, "Input scalar not in range");
  CHECK_AND_ASSERT_MES(is_reduced(proof.mu), false, "Input scalar not in range");
  CHECK_AND_ASSERT_MES(is_reduced(proof.a), false, "Input scalar not in range");
  CHECK_AND_ASSERT_MES(is_reduced(proof.b), false, "Input scalar not in range");
  CHECK_AND_ASSERT_MES(is_reduced(proof.t), false, "Input scalar not in range");

  const size_t logN = proof.L.size();
  const size_t N = 1 << logN;

  // Reconstruct the challenges
  PERF_TIMER_START_BP(VERIFY);
  PERF_TIMER_START_BP(VERIFY_start);
  rct::key hash_cache = rct::hash_to_scalar(proof.V[0]);
  rct::key y = hash_cache_mash(hash_cache, proof.A, proof.S);
  rct::key z = hash_cache = rct::hash_to_scalar(y);
  rct::key x = hash_cache_mash(hash_cache, z, proof.T1, proof.T2);
  PERF_TIMER_STOP(VERIFY_start);

  PERF_TIMER_START_BP(VERIFY_line_60);
  // Reconstruct the challenges
  rct::key x_ip = hash_cache_mash(hash_cache, x, proof.taux, proof.mu, proof.t);
  PERF_TIMER_STOP(VERIFY_line_60);

  PERF_TIMER_START_BP(VERIFY_line_61);
  // PAPER LINE 61
  rct::key L61Left = rct::addKeys(rct::scalarmultBase(proof.taux), rct::scalarmultKey(rct::H, proof.t));

  rct::key k = rct::zero();
  const auto yN = vector_powers(y, N);
  rct::key ip1y = inner_product(oneN, yN);
  rct::key zsq;
  sc_mul(zsq.bytes, z.bytes, z.bytes);
  rct::key tmp, tmp2;
  sc_mulsub(k.bytes, zsq.bytes, ip1y.bytes, k.bytes);
  rct::key zcu;
  sc_mul(zcu.bytes, zsq.bytes, z.bytes);
  sc_mulsub(k.bytes, zcu.bytes, ip12.bytes, k.bytes);
  PERF_TIMER_STOP(VERIFY_line_61);

  PERF_TIMER_START_BP(VERIFY_line_61rl);
  sc_muladd(tmp.bytes, z.bytes, ip1y.bytes, k.bytes);
  rct::key L61Right = rct::scalarmultKey(rct::H, tmp);

  CHECK_AND_ASSERT_MES(proof.V.size() == 1, false, "proof.V does not have exactly one element");
  tmp = rct::scalarmultKey(proof.V[0], zsq);
  rct::addKeys(L61Right, L61Right, tmp);

  tmp = rct::scalarmultKey(proof.T1, x);
  rct::addKeys(L61Right, L61Right, tmp);

  rct::key xsq;
  sc_mul(xsq.bytes, x.bytes, x.bytes);
  tmp = rct::scalarmultKey(proof.T2, xsq);
  rct::addKeys(L61Right, L61Right, tmp);
  PERF_TIMER_STOP(VERIFY_line_61rl);

  if (!(L61Right == L61Left))
  {
    MERROR("Verification failure at step 1");
    return false;
  }

  PERF_TIMER_START_BP(VERIFY_line_62);
  // PAPER LINE 62
  rct::key P = rct::addKeys(proof.A, rct::scalarmultKey(proof.S, x));
  PERF_TIMER_STOP(VERIFY_line_62);

  // Compute the number of rounds for the inner product
  const size_t rounds = proof.L.size();
  CHECK_AND_ASSERT_MES(rounds > 0, false, "Zero rounds");

  PERF_TIMER_START_BP(VERIFY_line_21_22);
  // PAPER LINES 21-22
  // The inner product challenges are computed per round
  rct::keyV w(rounds);
  for (size_t i = 0; i < rounds; ++i)
  {
    w[i] = hash_cache_mash(hash_cache, proof.L[i], proof.R[i]);
  }
  PERF_TIMER_STOP(VERIFY_line_21_22);

  PERF_TIMER_START_BP(VERIFY_line_24_25);
  // Basically PAPER LINES 24-25
  // Compute the curvepoints from G[i] and H[i]
  rct::key inner_prod = rct::identity();
  rct::key yinvpow = rct::identity();
  rct::key ypow = rct::identity();

  PERF_TIMER_START_BP(VERIFY_line_24_25_invert);
  const rct::key yinv = invert(y);
  rct::keyV winv(rounds);
  for (size_t i = 0; i < rounds; ++i)
    winv[i] = invert(w[i]);
  PERF_TIMER_STOP(VERIFY_line_24_25_invert);

  for (size_t i = 0; i < N; ++i)
  {
    // Convert the index to binary IN REVERSE and construct the scalar exponent
    rct::key g_scalar = proof.a;
    rct::key h_scalar;
    sc_mul(h_scalar.bytes, proof.b.bytes, yinvpow.bytes);

    for (size_t j = rounds; j-- > 0; )
    {
      size_t J = w.size() - j - 1;

      if ((i & (((size_t)1)<<j)) == 0)
      {
        sc_mul(g_scalar.bytes, g_scalar.bytes, winv[J].bytes);
        sc_mul(h_scalar.bytes, h_scalar.bytes, w[J].bytes);
      }
      else
      {
        sc_mul(g_scalar.bytes, g_scalar.bytes, w[J].bytes);
        sc_mul(h_scalar.bytes, h_scalar.bytes, winv[J].bytes);
      }
    }

    // Adjust the scalars using the exponents from PAPER LINE 62
    sc_add(g_scalar.bytes, g_scalar.bytes, z.bytes);
    sc_mul(tmp.bytes, zsq.bytes, twoN[i].bytes);
    sc_muladd(tmp.bytes, z.bytes, ypow.bytes, tmp.bytes);
    sc_mulsub(h_scalar.bytes, tmp.bytes, yinvpow.bytes, h_scalar.bytes);

    // Now compute the basepoint's scalar multiplication
    // Each of these could be written as a multiexp operation instead
    rct::addKeys3(tmp, g_scalar, Gprecomp[i], h_scalar, Hprecomp[i]);
    rct::addKeys(inner_prod, inner_prod, tmp);

    if (i != N-1)
    {
      sc_mul(yinvpow.bytes, yinvpow.bytes, yinv.bytes);
      sc_mul(ypow.bytes, ypow.bytes, y.bytes);
    }
  }
  PERF_TIMER_STOP(VERIFY_line_24_25);

  PERF_TIMER_START_BP(VERIFY_line_26);
  // PAPER LINE 26
  rct::key pprime;
  sc_sub(tmp.bytes, rct::zero().bytes, proof.mu.bytes);
  rct::addKeys(pprime, P, rct::scalarmultBase(tmp));

  for (size_t i = 0; i < rounds; ++i)
  {
    sc_mul(tmp.bytes, w[i].bytes, w[i].bytes);
    sc_mul(tmp2.bytes, winv[i].bytes, winv[i].bytes);
#if 1
    ge_dsmp cacheL, cacheR;
    rct::precomp(cacheL, proof.L[i]);
    rct::precomp(cacheR, proof.R[i]);
    rct::addKeys3(tmp, tmp, cacheL, tmp2, cacheR);
    rct::addKeys(pprime, pprime, tmp);
#else
    rct::addKeys(pprime, pprime, rct::scalarmultKey(proof.L[i], tmp));
    rct::addKeys(pprime, pprime, rct::scalarmultKey(proof.R[i], tmp2));
#endif
  }
  sc_mul(tmp.bytes, proof.t.bytes, x_ip.bytes);
  rct::addKeys(pprime, pprime, rct::scalarmultKey(rct::H, tmp));
  PERF_TIMER_STOP(VERIFY_line_26);

  PERF_TIMER_START_BP(VERIFY_step2_check);
  sc_mul(tmp.bytes, proof.a.bytes, proof.b.bytes);
  sc_mul(tmp.bytes, tmp.bytes, x_ip.bytes);
  tmp = rct::scalarmultKey(rct::H, tmp);
  rct::addKeys(tmp, tmp, inner_prod);
  PERF_TIMER_STOP(VERIFY_step2_check);
  if (!(pprime == tmp))
  {
    MERROR("Verification failure at step 2");
    return false;
  }

  PERF_TIMER_STOP(VERIFY);
  return true;
}

}

ext: cc

max_stars_repo_name: mechanator/arqma

max_issues_repo_name: mechanator/arqma

max_forks_repo_name: mechanator/arqma


text:
// COL216 Assignment 4
// Mallika Prabhakar 2019CS50440
// Sayam Sethi 2019CS10399

#include <bits/stdc++.h>
#include <boost/tokenizer.hpp>

using namespace std;

// struct to store the registers and the functions to be executed
struct MIPS_Architecture
{
private:
	// struct to store all information required by DRAM queue to execute the instruction
	struct QElem
	{
		bool id;
		int PCaddr, value, issueCycle, startCycle, remainingCycles;

		/**
		 * initialise the queue element
		 * @param id 0 for sw and 1 for lw
		 * @param PCaddr stores the PC address of corresponding instruction
		 * @param value content to be stored (for sw) / register id (for lw)
		 * @param issueCycle the cycle in which the request was issued
		 * @param startCycle the cycle when the instruction began
		 * @param remainingCycles number of cycles pending to finish execution of request
		*/
		QElem(bool id, int PCaddr, int value, int issueCycle, int startCycle = -1, int remainingCycles = -1)
		{
			this->id = id;
			this->PCaddr = PCaddr;
			this->value = value;
			this->issueCycle = issueCycle;
			this->startCycle = startCycle;
			this->remainingCycles = remainingCycles;
		}
	};

public:
	// constants
	static const int MAX = (1 << 20), ROWS = (1 << 10), DRAM_MAX = (1 << 5);
	// DRAM delays
	int row_access_delay, col_access_delay;
	// instruction set
	unordered_map<string, function<int(MIPS_Architecture &, string, string, string)>> instructions;
	// mapping names to a unique number
	unordered_map<string, int> registerMap, address;
	// vector to store the commands in input program
	vector<vector<string>> commands;
	// "dynamic" vars
	int registers[32], PCcurr, PCnext, delay, currRow, currCol, clockCycles, rowBufferUpdates, DRAMsize;
	pair<int, int> registersAddrDRAM[32];
	// data stored in allocated memory
	vector<vector<int>> data;
	vector<int> buffer, commandCount;
	// data structure to store info about requests sent to the DRAM, key is the row number and value is QElem
	unordered_map<int, unordered_map<int, queue<QElem>>> DRAMbuffer;
	// last location accessed by DRAM is stored
	pair<int, int> lastAddr;
	bool isDRAM;

	// constructor to initialise the instruction set
	MIPS_Architecture(ifstream &file, int row_delay, int col_delay)
	{
		row_access_delay = row_delay, col_access_delay = col_delay;

		instructions = {{"add", &MIPS_Architecture::add}, {"sub", &MIPS_Architecture::sub}, {"mul", &MIPS_Architecture::mul}, {"beq", &MIPS_Architecture::beq}, {"bne", &MIPS_Architecture::bne}, {"slt", &MIPS_Architecture::slt}, {"j", &MIPS_Architecture::j}, {"lw", &MIPS_Architecture::lw}, {"sw", &MIPS_Architecture::sw}, {"addi", &MIPS_Architecture::addi}};

		for (int i = 0; i < 32; ++i)
			registerMap["$" + to_string(i)] = i;
		registerMap["$zero"] = 0;
		registerMap["$at"] = 1;
		registerMap["$v0"] = 2;
		registerMap["$v1"] = 3;
		for (int i = 0; i < 4; ++i)
			registerMap["$a" + to_string(i)] = i + 4;
		for (int i = 0; i < 8; ++i)
			registerMap["$t" + to_string(i)] = i + 8, registerMap["$s" + to_string(i)] = i + 16;
		registerMap["$t8"] = 24;
		registerMap["$t9"] = 25;
		registerMap["$k0"] = 26;
		registerMap["$k1"] = 27;
		registerMap["$gp"] = 28;
		registerMap["$sp"] = 29;
		registerMap["$s8"] = 30;
		registerMap["$ra"] = 31;

		constructCommands(file);
	}

	// perform add immediate operation
	int addi(string r1, string r2, string num)
	{
		if (!checkRegisters({r1, r2}) || registerMap[r1] == 0)
			return 1;
		try
		{
			if (registersAddrDRAM[registerMap[r2]] != make_pair(-1, -1))
				return -registerMap[r2] - 1;
			registers[registerMap[r1]] = registers[registerMap[r2]] + stoi(num);
			registersAddrDRAM[registerMap[r1]] = {-1, -1};
			PCnext = PCcurr + 1;
			return 0;
		}
		catch (exception &e)
		{
			return 4;
		}
	}

	// perform add operation
	int add(string r1, string r2, string r3)
	{
		return op(r1, r2, r3, [&](int a, int b) { return a + b; });
	}

	// perform subtraction operation
	int sub(string r1, string r2, string r3)
	{
		return op(r1, r2, r3, [&](int a, int b) { return a - b; });
	}

	// perform multiplication operation
	int mul(string r1, string r2, string r3)
	{
		return op(r1, r2, r3, [&](int a, int b) { return a * b; });
	}

	// implements slt operation
	int slt(string r1, string r2, string r3)
	{
		return op(r1, r2, r3, [&](int a, int b) { return a < b; });
	}

	// perform the operation
	int op(string r1, string r2, string r3, function<int(int, int)> operation)
	{
		if (!checkRegisters({r1, r2, r3}) || registerMap[r1] == 0)
			return 1;
		if (registersAddrDRAM[registerMap[r2]] != make_pair(-1, -1))
			return -registerMap[r2] - 1;
		if (registersAddrDRAM[registerMap[r3]] != make_pair(-1, -1))
			return -registerMap[r3] - 1;
		registers[registerMap[r1]] = operation(registers[registerMap[r2]], registers[registerMap[r3]]);
		registersAddrDRAM[registerMap[r1]] = {-1, -1};
		PCnext = PCcurr + 1;
		return 0;
	}

	// perform the beq operation
	int beq(string r1, string r2, string label)
	{
		return bOP(r1, r2, label, [](int a, int b) { return a == b; });
	}

	// perform the bne operation
	int bne(string r1, string r2, string label)
	{
		return bOP(r1, r2, label, [](int a, int b) { return a != b; });
	}

	// implements beq and bne by taking the comparator
	int bOP(string r1, string r2, string label, function<bool(int, int)> comp)
	{
		if (!checkLabel(label))
			return 4;
		if (address.find(label) == address.end() || address[label] == -1)
			return 2;
		if (!checkRegisters({r1, r2}))
			return 1;
		if (registersAddrDRAM[registerMap[r1]] != make_pair(-1, -1))
			return -registerMap[r1] - 1;
		if (registersAddrDRAM[registerMap[r2]] != make_pair(-1, -1))
			return -registerMap[r2] - 1;
		PCnext = comp(registers[registerMap[r1]], registers[registerMap[r2]]) ? address[label] : PCcurr + 1;
		return 0;
	}

	// perform the jump operation
	int j(string label, string unused1 = "", string unused2 = "")
	{
		if (!checkLabel(label))
			return 4;
		if (address.find(label) == address.end() || address[label] == -1)
			return 2;
		PCnext = address[label];
		return 0;
	}

	// perform load word operation
	int lw(string r, string location, string unused1 = "")
	{
		if (!checkRegister(r) || registerMap[r] == 0)
			return 1;
		auto address = locateAddress(location);
		if (!address.first)
			return address.second;

		PCnext = PCcurr + 1;
		if (address.second == lastAddr.first)
		{
			registers[registerMap[r]] = lastAddr.second;
			registersAddrDRAM[registerMap[r]] = {-1, -1};
			return 0;
		}

		if (DRAMsize == DRAM_MAX)
			return -33;
		isDRAM = true;
		DRAMbuffer[address.second / ROWS][(address.second % ROWS) / 4].push({1, PCcurr, registerMap[r], clockCycles + 1});
		registersAddrDRAM[registerMap[r]] = {clockCycles + 1, address.second};
		++DRAMsize;
		return 0;
	}

	// perform store word operation
	int sw(string r, string location, string unused1 = "")
	{
		if (!checkRegister(r))
			return 1;
		auto address = locateAddress(location);
		if (!address.first)
			return address.second;
		if (registersAddrDRAM[registerMap[r]] != make_pair(-1, -1))
			return -registerMap[r] - 1;

		if (DRAMsize == DRAM_MAX)
			return -33;
		lastAddr = {address.second, registers[registerMap[r]]};
		isDRAM = true;
		DRAMbuffer[address.second / ROWS][(address.second % ROWS) / 4].push({0, PCcurr, registers[registerMap[r]], clockCycles + 1});
		++rowBufferUpdates, ++DRAMsize;
		PCnext = PCcurr + 1;
		return 0;
	}

	// parse the address and return the actual address or error
	pair<bool, int> locateAddress(string location)
	{
		if (location.back() == ')')
		{
			try
			{
				int lparen = location.find('('), offset = stoi(lparen == 0 ? "0" : location.substr(0, lparen));
				string reg = location.substr(lparen + 1);
				reg.pop_back();
				if (!checkRegister(reg))
					return {false, 3};
				if (registersAddrDRAM[registerMap[reg]] != make_pair(-1, -1))
					return {false, -registerMap[reg] - 1};
				int address = registers[registerMap[reg]] + offset;
				if (address % 4 || address < int(4 * commands.size()) || address >= MAX)
					return {false, 3};
				return {true, address};
			}
			catch (exception &e)
			{
				return {false, 4};
			}
		}
		try
		{
			int address = stoi(location);
			if (address % 4 || address < int(4 * commands.size()) || address >= MAX)
				return {false, 3};
			return {true, address};
		}
		catch (exception &e)
		{
			return {false, 4};
		}
	}

	// checks if label is valid
	inline bool checkLabel(string str)
	{
		return str.size() > 0 && isalpha(str[0]) && all_of(++str.begin(), str.end(), [](char c) { return (bool)isalnum(c); }) && instructions.find(str) == instructions.end();
	}

	// checks if the register is a valid one
	inline bool checkRegister(string r)
	{
		return registerMap.find(r) != registerMap.end();
	}

	// checks if all of the registers are valid or not
	bool checkRegisters(vector<string> regs)
	{
		return all_of(regs.begin(), regs.end(), [&](string r) { return checkRegister(r); });
	}

	// parse the command assuming correctly formatted MIPS instruction (or label)
	void parseCommand(string line)
	{
		// strip until before the comment begins
		line = line.substr(0, line.find('#'));
		vector<string> command;
		boost::tokenizer<boost::char_separator<char>> tokens(line, boost::char_separator<char>(", \t"));
		for (auto &s : tokens)
			command.push_back(s);
		// empty line or a comment only line
		if (command.empty())
			return;
		else if (command.size() == 1)
		{
			string label = command[0].back() == ':' ? command[0].substr(0, command[0].size() - 1) : "?";
			if (address.find(label) == address.end())
				address[label] = commands.size();
			else
				address[label] = -1;
			command.clear();
		}
		else if (command[0].back() == ':')
		{
			string label = command[0].substr(0, command[0].size() - 1);
			if (address.find(label) == address.end())
				address[label] = commands.size();
			else
				address[label] = -1;
			command = vector<string>(command.begin() + 1, command.end());
		}
		else if (command[0].find(':') != string::npos)
		{
			int idx = command[0].find(':');
			string label = command[0].substr(0, idx);
			if (address.find(label) == address.end())
				address[label] = commands.size();
			else
				address[label] = -1;
			command[0] = command[0].substr(idx + 1);
		}
		else if (command[1][0] == ':')
		{
			if (address.find(command[0]) == address.end())
				address[command[0]] = commands.size();
			else
				address[command[0]] = -1;
			command[1] = command[1].substr(1);
			if (command[1] == "")
				command.erase(command.begin(), command.begin() + 2);
			else
				command.erase(command.begin(), command.begin() + 1);
		}
		if (command.empty())
			return;
		if (command.size() > 4)
			for (int i = 4; i < (int)command.size(); ++i)
				command[3] += " " + command[i];
		command.resize(4);
		commands.push_back(command);
	}

	// construct the commands vector from the input file
	void constructCommands(ifstream &file)
	{
		string line;
		while (getline(file, line))
			parseCommand(line);
		file.close();
	}

	// execute the commands sequentially
	void executeCommands()
	{
		if (commands.size() >= MAX / 4)
		{
			handleExit(5);
			return;
		}

		initVars();
		cout << "Cycle info:\n";
		while (PCcurr < (int)commands.size())
		{
			delay = 0, isDRAM = false;
			vector<string> &command = commands[PCcurr];
			if (instructions.find(command[0]) == instructions.end())
			{
				handleExit(4);
				return;
			}
			int ret = instructions[command[0]](*this, command[1], command[2], command[3]);
			if (ret > 0)
			{
				handleExit(ret);
				return;
			}
			if (ret != 0)
			{
				finishCurrDRAM(-ret - 1);
				continue;
			}
			++clockCycles;
			++commandCount[PCcurr];
			PCcurr = PCnext;
			if (!DRAMbuffer.empty())
			{
				// first lw/sw operation after DRAM_buffer emptied
				if (currCol == -1)
					setNextDRAM(DRAMbuffer.begin()->first, DRAMbuffer[DRAMbuffer.begin()->first].begin()->first);
				else if (--DRAMbuffer[currRow][currCol].front().remainingCycles == 0)
					finishCurrDRAM();
			}
			printCycleExecution(command, PCcurr);
		}
		while (!DRAMbuffer.empty())
			finishCurrDRAM();
		bufferUpdate();
		handleExit(0);
	}

	// finish the currently running DRAM instruction and set the next one
	void finishCurrDRAM(int nextRegister = 32)
	{
		auto &Q = DRAMbuffer[currRow][currCol];
		int nextRow = currRow, nextCol = currCol;
		QElem top = DRAMbuffer[currRow][currCol].front();
		popAndUpdate(Q, nextRow, nextCol);

		clockCycles += top.remainingCycles;
		if (top.id && registersAddrDRAM[top.value] != make_pair(-1, -1))
		{
			registers[top.value] = buffer[currCol];
			if (registersAddrDRAM[top.value].first == top.issueCycle)
			{
				registersAddrDRAM[top.value] = {-1, -1};
				if (nextRegister == top.value)
					nextRegister = 32;
			}
			lastAddr.first = currCol * 4 + currRow * ROWS;
			lastAddr.second = buffer[currCol];
			printDRAMCompletion(top.PCaddr, top.startCycle, clockCycles);
		}
		else if (!top.id)
		{
			buffer[currCol] = top.value;
			printDRAMCompletion(top.PCaddr, top.startCycle, clockCycles);
		}
		else
			printDRAMCompletion(top.PCaddr, top.startCycle, clockCycles, "rejected");

		setNextDRAM(nextRow, nextCol, nextRegister);
	}

	// set the next DRAM command to be executed (implements reordering)
	void setNextDRAM(int nextRow, int nextCol, int nextRegister = 32)
	{
		if (DRAMbuffer.empty())
		{
			currCol = -1;
			return;
		}
		if (nextRegister != 32)
		{
			nextRow = registersAddrDRAM[nextRegister].second / ROWS;
			nextCol = (registersAddrDRAM[nextRegister].second % ROWS) / 4;
		}

		QElem top = DRAMbuffer[nextRow][nextCol].front();
		while (top.id && registersAddrDRAM[top.value].first != top.issueCycle && popAndUpdate(DRAMbuffer[nextRow][nextCol], nextRow, nextCol, true))
			top = DRAMbuffer[nextRow][nextCol].front();

		if (DRAMbuffer.empty())
		{
			currCol = -1;
			return;
		}
		bufferUpdate(nextRow, nextCol);
		DRAMbuffer[currRow][currCol].front().startCycle = clockCycles + 1;
		DRAMbuffer[currRow][currCol].front().remainingCycles = delay;
	}

	// pop the queue element and update the row and column if needed (returns false if DRAM empty after pop)
	bool popAndUpdate(queue<QElem> &Q, int &row, int &col, bool skip = false)
	{
		if (skip)
			printDRAMCompletion(Q.front().PCaddr, clockCycles, clockCycles, "skipped");
		Q.pop();
		--DRAMsize;
		if (Q.empty())
		{
			DRAMbuffer[row].erase(col);
			if (DRAMbuffer[row].empty())
			{
				DRAMbuffer.erase(row);
				if (!DRAMbuffer.empty())
					row = DRAMbuffer.begin()->first;
			}
			if (DRAMbuffer.empty())
				return false;
			col = DRAMbuffer[row].begin()->first;
			return true;
		}
		return true;
	}

	// implement buffer update
	void bufferUpdate(int row = -1, int col = -1)
	{
		if (row == -1)
		{
			delay = (currRow != -1) * row_access_delay;
			if (currRow != -1)
				++rowBufferUpdates, data[currRow] = buffer, buffer = vector<int>();
		}
		else if (currRow == -1)
			delay = row_access_delay + col_access_delay, ++rowBufferUpdates, buffer = data[row];
		else if (currRow != row)
			delay = 2 * row_access_delay + col_access_delay, ++rowBufferUpdates, data[currRow] = buffer, buffer = data[row];
		else
			delay = col_access_delay;
		currRow = row, currCol = col;
	}

	// prints the cycle info of DRAM delay
	void printDRAMCompletion(int PCaddr, int begin, int end, string action = "executed")
	{
		cout << begin << '-' << end << " (DRAM call " << action << "): (PC address " << PCaddr << ") ";
		for (auto s : commands[PCaddr])
			cout << s << ' ';
		cout << "\n\n";
	}

	// print cycle info
	void printCycleExecution(vector<string> &command, int PCaddr)
	{
		if (isDRAM)
			cout << clockCycles << ": (DRAM call queued) ";
		else
			cout << clockCycles << ": " << (command[0] == "lw" ? "(used forwarding) " : "");
		cout << "(PC address " << PCaddr << ") ";
		for (auto &s : command)
			cout << s << ' ';
		cout << '\n';
		printRegisters();
		cout << "\n";
	}

	// print the register data in hexadecimal
	void printRegisters()
	{
		cout << hex;
		for (int i = 0; i < 32; ++i)
			cout << registers[i] << ' ';
		cout << dec << "\n";
	}

	/*
		handle all exit codes:
		0: correct execution
		1: register provided is incorrect
		2: invalid label
		3: unaligned or invalid address
		4: syntax error
		5: commands exceed memory limit
	*/
	void handleExit(int code)
	{
		switch (code)
		{
		case 1:
			cerr << "Invalid register provided or syntax error in providing register\n";
			break;
		case 2:
			cerr << "Label used not defined or defined too many times\n";
			break;
		case 3:
			cerr << "Unaligned or invalid memory address specified\n";
			break;
		case 4:
			cerr << "Syntax error encountered\n";
			break;
		case 5:
			cerr << "Memory limit exceeded\n";
			break;
		default:
			break;
		}
		if (code != 0)
		{
			cerr << "Error encountered at:\n";
			for (auto &s : commands[PCcurr])
				cerr << s << ' ';
			cerr << '\n';
		}

		cout << "Exit code: " << code << '\n';

		cout << "\nThe Row Buffer was updated " << rowBufferUpdates << " times.\n";
		cout << "\nFollowing are the non-zero data values:\n";
		for (int i = 0; i < ROWS; ++i)
			for (int j = 0; j < ROWS / 4; ++j)
				if (data[i][j] != 0)
					cout << (ROWS * i + 4 * j) << '-' << (ROWS * i + 4 * j) + 3 << hex << ": " << data[i][j] << '\n'
						 << dec;
		cout << "\nTotal number of cycles: " << clockCycles << " + " << delay << " (cycles taken for code execution + final writeback delay)\n";
		cout << "\nCount of instructions executed:\n";
		for (int i = 0; i < (int)commands.size(); ++i)
		{
			cout << commandCount[i] << " times:\t";
			for (auto &s : commands[i])
				cout << s << ' ';
			cout << '\n';
		}
	}

	// initialize variables before executing commands
	void initVars()
	{
		clockCycles = 0, PCcurr = 0, rowBufferUpdates = 0, DRAMsize = 0, currRow = -1, currCol = -1;
		fill_n(registers, 32, 0);
		fill_n(registersAddrDRAM, 32, make_pair(-1, -1));
		data = vector<vector<int>>(ROWS, vector<int>(ROWS >> 2, 0));
		buffer = vector<int>(ROWS >> 2, 0);
		commandCount.clear();
		commandCount.assign(commands.size(), 0);
		DRAMbuffer.clear();
		lastAddr = {-1, -1};
	}
};

int main(int argc, char *argv[])
{
	if (argc != 4)
	{
		cerr << "Required arguments: file_name ROW_ACCESS_DELAY COL_ACCESS_DELAY\n";
		return 0;
	}
	ifstream file(argv[1]);
	MIPS_Architecture *mips;
	if (file.is_open())
		try
		{
			mips = new MIPS_Architecture(file, stoi(argv[2]), stoi(argv[3]));
		}
		catch (exception &e)
		{
			cerr << "Required arguments: file_name ROW_ACCESS_DELAY COL_ACCESS_DELAY\n";
			return 0;
		}
	else
	{
		cerr << "File could not be opened. Terminating...\n";
		return 0;
	}

	mips->executeCommands();
	return 0;
}


text:
//***************************************************************************
//* Copyright (c) 2015 Saint Petersburg State University
//* Copyright (c) 2011-2014 Saint Petersburg Academic University
//* All Rights Reserved
//* See file LICENSE for details.
//***************************************************************************

/*
 * kmer_cluster.hpp
 *
 *  Created on: 16.07.2011
 *      Author: snikolenko
 */

#ifndef KMER_CLUSTER_HPP
#define KMER_CLUSTER_HPP

#include "hamcluster.hpp"
#include "kmer_data.hpp"

#include <string>
#include <vector>

#include <boost/numeric/ublas/fwd.hpp>

class KMerClustering {
public:
  KMerClustering(KMerData &data, unsigned nthreads, const std::string &workdir, bool debug) :
      data_(data), nthreads_(nthreads), workdir_(workdir), debug_(debug) { }

  void process(const std::string &Prefix);

private:
  KMerData &data_;
  unsigned nthreads_;
  std::string workdir_;
  bool debug_;

  struct Center {
    hammer::ExpandedSeq center_;
    size_t count_;
  };

  double ClusterBIC(const std::vector<Center> &centers,
                    const std::vector<size_t> &indices, const std::vector<hammer::ExpandedKMer> &kmers) const;

  /**
    * perform l-means clustering on the set of k-mers with initial centers being the l most frequent k-mers here
    * @param indices fill array centers with cluster centers; centers[k].count shows how many different kmers are in this cluster (used later)
    * @param centers fill array indices with ints from 0 to l that denote which kmers belong where
    * @return the resulting likelihood of this clustering
    */
  double lMeansClustering(unsigned l, const std::vector<hammer::ExpandedKMer> &kmers,
                          std::vector<size_t> & indices, std::vector<Center> & centers);

  size_t SubClusterSingle(const std::vector<size_t> & block, std::vector< std::vector<size_t> > & vec);

  std::string GetGoodKMersFname() const;
  std::string GetBadKMersFname() const;

  size_t ProcessCluster(const std::vector<size_t> &cur_class,
                        boost::numeric::ublas::matrix<uint64_t> &errs,
                        std::ofstream &ofs, std::ofstream &ofs_bad,
                        size_t &gsingl, size_t &tsingl, size_t &tcsingl, size_t &gcsingl,
                        size_t &tcls, size_t &gcls, size_t &tkmers, size_t &tncls);

private:
  DECL_LOGGER("Hamming Subclustering");
};

#endif // KMER_CLUSTER_HPP

max_stars_repo_name: STRIDES-Codes/Exploring-the-Microbiome-

max_issues_repo_name: STRIDES-Codes/Exploring-the-Microbiome-

max_forks_repo_name: STRIDES-Codes/Exploring-the-Microbiome-


text:
#define BOOST_TEST_MODULE SolutionTest

#include "solution.hpp"

//#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(SolutionSuite)

BOOST_AUTO_TEST_CASE(PlainTest1)
{
    vector<vector<int>> matrix{
        { 1, 2, 3 },
        { 4, 5, 6 },
        { 7, 8, 9 }
    };
    vector<int> result = Solution().spiralOrder(matrix);

    vector<int> expected{1,2,3,6,9,8,7,4,5};

    BOOST_CHECK_EQUAL(result.size(), expected.size());
    BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
}

BOOST_AUTO_TEST_CASE(PlainTest2)
{
    vector<vector<int>> matrix{
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9,10,11,12}
    };
    vector<int> result = Solution().spiralOrder(matrix);

    vector<int> expected{1,2,3,4,8,12,11,10,9,5,6,7};

    BOOST_CHECK_EQUAL(result.size(), expected.size());
    BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: johnhany/leetcode

max_issues_repo_name: johnhany/leetcode

max_forks_repo_name: johnhany/leetcode


text:
#include "trt_zero_model.h"

#if GOOGLE_TENSORRT

#include <fstream>
#include <string>

#include <boost/filesystem.hpp>
#include <glog/logging.h>

#include "cuda_runtime_api.h"
#include "NvInfer.h"

namespace fs = boost::filesystem;

class Logger : public nvinfer1::ILogger
{
    void log(Severity severity, const char *msg) override
    {
        switch (severity) {
         case Severity::kINTERNAL_ERROR: LOG(ERROR) << msg; break;
         case Severity::kERROR: LOG(ERROR) << msg; break;
         case Severity::kWARNING: LOG(WARNING) << msg; break;
         case Severity::kINFO: LOG(INFO) << msg; break;
        }
    }
} g_logger;

TrtZeroModel::TrtZeroModel(int gpu)
    : m_engine(nullptr), m_runtime(nullptr), m_context(nullptr), m_gpu(gpu), m_global_step(0)
{
}

TrtZeroModel::~TrtZeroModel()
{
    if (m_context) {
        m_context->destroy();
    }
    if (m_engine) {
        m_engine->destroy();
    }
    if (m_runtime) {
        m_runtime->destroy();
    }
    for (auto buf: m_cuda_buf) {
        int ret = cudaFree(buf);
        if (ret != 0) {
            LOG(ERROR) << "cuda free err " << ret;
        }
    }
}

int TrtZeroModel::Init(const ModelConfig &model_config)
{
    cudaSetDevice(m_gpu);

    fs::path train_dir = model_config.train_dir();

    fs::path tensorrt_model_path = model_config.tensorrt_model_path();
    if (tensorrt_model_path.is_relative()) {
        tensorrt_model_path = train_dir / tensorrt_model_path;
    }

    std::ostringstream model_ss(std::ios::binary);
    if (!(model_ss << std::ifstream(tensorrt_model_path.string(), std::ios::binary).rdbuf())) {
        PLOG(ERROR) << "read tensorrt model '" << tensorrt_model_path << "' error";
        return ERR_READ_TRT_MODEL;
    }
    std::string model_str = model_ss.str();

    m_runtime = nvinfer1::createInferRuntime(g_logger);
    m_engine = m_runtime->deserializeCudaEngine(model_str.c_str(), model_str.size(), nullptr);
    if (m_engine == nullptr) {
        PLOG(ERROR) << "load cuda engine error";
        return ERR_LOAD_TRT_ENGINE;
    }
    m_context = m_engine->createExecutionContext();

    int batch_size = m_engine->getMaxBatchSize();
    LOG(INFO) << "tensorrt max batch size: " << batch_size;
    for (int i = 0; i < m_engine->getNbBindings(); ++i) {
        auto dim = m_engine->getBindingDimensions(i);
        std::string dim_str = "(";
        int size = 1;
        for (int i = 0; i < dim.nbDims; ++i) {
            if (i) dim_str += ", ";
            dim_str += std::to_string(dim.d[i]);
            size *= dim.d[i];
        }
        dim_str += ")";
        LOG(INFO) << "tensorrt binding: " << m_engine->getBindingName(i) << " " << dim_str;

        void *buf;
        int ret = cudaMalloc(&buf, batch_size * size * sizeof(float));
        if (ret != 0) {
            LOG(ERROR) << "cuda malloc err " << ret;
            return ERR_CUDA_MALLOC;
        }
        m_cuda_buf.push_back(buf);
    }

    if (!(std::ifstream(tensorrt_model_path.string() + ".step") >> m_global_step)) {
        LOG(WARNING) << "read global step from " << tensorrt_model_path << ".step failed";
    }

    return 0;
}

int TrtZeroModel::Forward(const std::vector<std::vector<bool>> &inputs,
                          std::vector<std::vector<float>> &policy, std::vector<float> &value)
{
    int batch_size = inputs.size();
    if (batch_size == 0) {
        LOG(ERROR) << "Error batch size can not be 0.";
        return ERR_INVALID_INPUT;
    }

    std::vector<float> inputs_flat(batch_size * INPUT_DIM);
    for (int i = 0; i < batch_size; ++i) {
        if (inputs[i].size() != INPUT_DIM) {
            LOG(ERROR) << "Error input dim not match, need " << INPUT_DIM << ", got " << inputs[i].size();
            return ERR_INVALID_INPUT;
        }
        for (int j = 0; j < INPUT_DIM; ++j) {
            inputs_flat[i * INPUT_DIM + j] = inputs[i][j];
        }
    }

    int ret = cudaMemcpy(m_cuda_buf[0], inputs_flat.data(), inputs_flat.size() * sizeof(float), cudaMemcpyHostToDevice);
    if (ret != 0) {
        LOG(ERROR) << "cuda memcpy err " << ret;
        return ERR_CUDA_MEMCPY;
    }

    m_context->execute(batch_size, m_cuda_buf.data());

    std::vector<float> policy_flat(batch_size * OUTPUT_DIM);
    ret = cudaMemcpy(policy_flat.data(), m_cuda_buf[2], policy_flat.size() * sizeof(float), cudaMemcpyDeviceToHost);
    if (ret != 0) {
        LOG(ERROR) << "cuda memcpy err " << ret;
        return ERR_CUDA_MEMCPY;
    }
    policy.resize(batch_size);
    for (int i = 0; i < batch_size; ++i) {
        policy[i].resize(OUTPUT_DIM);
        for (int j = 0; j < OUTPUT_DIM; ++j) {
            policy[i][j] = policy_flat[i * OUTPUT_DIM + j];
        }
    }

    value.resize(batch_size);
    ret = cudaMemcpy(value.data(), m_cuda_buf[1], value.size() * sizeof(float), cudaMemcpyDeviceToHost);
    if (ret != 0) {
        LOG(ERROR) << "cuda memcpy err " << ret;
        return ERR_CUDA_MEMCPY;
    }
    for (int i = 0; i < batch_size; ++i) {
        value[i] = -value[i];
    }

    return 0;
}

int TrtZeroModel::GetGlobalStep(int &global_step)
{
    global_step = m_global_step;
    return 0;
}

#else // GOOGLE_TENSORRT

#include <glog/logging.h>

TrtZeroModel::TrtZeroModel(int gpu)
{
    LOG(FATAL) << "TensorRT is not enable!";
}

TrtZeroModel::~TrtZeroModel()
{
    LOG(FATAL) << "TensorRT is not enable!";
}

int TrtZeroModel::Init(const ModelConfig &model_config)
{
    LOG(FATAL) << "TensorRT is not enable!";
    return 0;
}

int TrtZeroModel::Forward(const std::vector<std::vector<bool>> &inputs,
                          std::vector<std::vector<float>> &policy, std::vector<float> &value)
{
    LOG(FATAL) << "TensorRT is not enable!";
    return 0;
}

int TrtZeroModel::GetGlobalStep(int &global_step)
{
    LOG(FATAL) << "TensorRT is not enable!";
    return 0;
}

#endif // GOOGLE_TENSORRT

max_stars_repo_name: samecos/PhoenixGo

max_issues_repo_name: samecos/PhoenixGo

max_forks_repo_name: samecos/PhoenixGo