text:
// (C) Copyright Chuck Allison and Jeremy Siek 2001, 2002.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all
// copies. This software is provided "as is" without express or
// implied warranty, and with no claim as to its suitability for any
// purpose.

// With optimizations, bug fixes, and improvements by Gennaro Prota.

// See http://www.boost.org/libs/dynamic_bitset for documentation.

// -------------------------------------
// CHANGE LOG:
//
// - corrected workaround for Dinkum lib's allocate() [GP]
// - changed macro test for old iostreams [GP]
// - removed #include <vector> for now. [JGS]
// - Added __GNUC__ to compilers that cannot handle the constructor from basic_string. [JGS]
// - corrected to_block_range [GP]
// - corrected from_block_range [GP]
// - Removed __GNUC__ from compilers that cannot handle the constructor
//     from basic_string and added the workaround suggested by GP. [JGS]
// - Removed __BORLANDC__ from the #if around the basic_string
//     constructor. Luckily the fix by GP for g++ also fixes Borland. [JGS]

#ifndef BOOST_DYNAMIC_BITSET_HPP
#define BOOST_DYNAMIC_BITSET_HPP

#include <boost/config.hpp>
#include <cassert>
#include <string>
#include <iosfwd>
#include <cstring>             // for memset, memcpy, memcmp, etc.
#include <stdexcept>           // for std::overflow_error
#include <algorithm>           // for std::swap, std::min, std::copy, std::fill

#if defined(__GNUC__) && !defined(__SGI_STL_PORT)
#include <ctype.h>
#else
#include <cctype>               // for isspace
#endif

#include "boost/dynamic_bitset_fwd.hpp" //G.P.S.
#include "boost/detail/dynamic_bitset.hpp"

#if defined (__STL_CONFIG_H) && !defined (__STL_USE_NEW_IOSTREAMS)
#define BOOST_OLD_IOSTREAMS
#endif

#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
//  in certain situations VC++ requires a redefinition of
//  default template arguments, in contrast with 14.1/12
//
# define BOOST_WORKAROUND_REPEAT_DEFAULT_TEMPLATE_ARGUMENTS // macro 'local' to this file
#endif

namespace boost {

#ifdef BOOST_WORKAROUND_REPEAT_DEFAULT_TEMPLATE_ARGUMENTS
 template <typename Block = unsigned long, typename Allocator = std::allocator<Block> >
#else
 template <typename Block, typename Allocator>
#endif

class dynamic_bitset :
#ifdef BOOST_DYN_BITSET_USE_FRIENDS
    private
#else
    public
#endif
    detail::dynamic_bitset_base<Block, Allocator>
{
  // Portability note: member function templates are defined inside
  // this class definition to avoid problems with VC++. Similarly,
  // with the member functions of the nested class.
public:
    typedef Block block_type;
    typedef std::size_t size_type;
    enum { bits_per_block = CHAR_BIT * sizeof(Block) };

    // reference to a bit
    class reference
    {
        friend class dynamic_bitset<Block, Allocator>;
        dynamic_bitset* bs;
        size_type bit;
        reference(); // intentionally not implemented
        reference(dynamic_bitset& bs_, size_type bit_) : bs(&bs_), bit(bit_){ }
    public:
        reference& operator=(bool value)          // for b[i] = x
        {
            if (value)
                bs->set(bit);
            else
                bs->reset(bit);
            return *this;
        }
        reference& operator|=(bool value)         // for b[i] |= x
        {
            if (value)
                bs->set(bit);
            return *this;
        }
        reference& operator&=(bool value)         // for b[i] &= x
        {
            if (! (value && bs->test(bit)))
                bs->reset(bit);
            return *this;
        }
        reference& operator^=(bool value)         // for b[i] ^= x
        {
            bs->set(bit, bs->test(bit) ^ value);
            return *this;
        }
        reference& operator-=(bool value)         // for b[i] -= x
        {
            if (!value)
                bs->reset(bit);
            return *this;
        }
        reference& operator=(const reference& j)  // for b[i] = b[j]
        {
            if (j.bs->test(j.bit))
                bs->set(bit);
            else
                bs->reset(bit);
            return *this;
        }
        reference& operator|=(const reference& j) // for b[i] |= b[j]
        {
            if (j.bs->test(j.bit))
                bs->set(bit);
            return *this;
        }
        reference& operator&=(const reference& j) // for b[i] &= b[j]
        {
            if (! (j.bs->test(j.bit) && bs->test(bit)))
                bs->reset(bit);
            return *this;
        }
        reference& operator^=(const reference& j) // for b[i] ^= b[j]
        {
            bs->set(bit, bs->test(bit) ^ j.bs->test(j.bit));
            return *this;
        }
        reference& operator-=(const reference& j) // for b[i] -= b[j]
        {
            if (!j.bs->test(j.bit))
                bs->reset(bit);
            return *this;
        }
        bool operator~() const                    // flips the bit
        {
            return ! bs->test(bit);
        }
        operator bool() const                     // for x = b[i]
        {
            return bs->test(bit);
        }
        reference& flip()                         // for b[i].flip();
        {
            bs->flip(bit);
            return *this;
        }
    };
    typedef bool const_reference;

    // constructors, etc.
    explicit
    dynamic_bitset(const Allocator& alloc = Allocator());

    explicit
    dynamic_bitset(size_type num_bits, unsigned long value = 0,
               const Allocator& alloc = Allocator());

    // from string
#if defined(BOOST_OLD_IOSTREAMS)
    explicit
    dynamic_bitset(const std::string& s,
               std::string::size_type pos = 0,
               std::string::size_type n = std::string::npos,
               const Allocator& alloc = Allocator())
        : detail::dynamic_bitset_base<Block, Allocator>
            (std::min(n, s.size() - pos), alloc)
#else
    // The parenthesis around std::basic_string<CharT, Traits, Alloc>::npos
    // in the code below are to avoid a g++ 3.2 bug and a Borland bug. -JGS
    template <typename CharT, typename Traits, typename Alloc>
    explicit
    dynamic_bitset(const std::basic_string<CharT, Traits, Alloc>& s,
        typename std::basic_string<CharT, Traits, Alloc>::size_type pos = 0,
        typename std::basic_string<CharT, Traits, Alloc>::size_type n
            = (std::basic_string<CharT, Traits, Alloc>::npos),
        const Allocator& alloc = Allocator())
        : detail::dynamic_bitset_base<Block, Allocator>
            (std::min(n, s.size() - pos), alloc)
#endif
    {
        // Locate sub string
        assert(pos <= s.length());
        from_string(s, pos, std::min(n, s.size() - pos));
    }

    // The first bit in *first is the least significant bit, and the
    // last bit in the block just before *last is the most significant bit.
    template <typename BlockInputIterator>
    dynamic_bitset(BlockInputIterator first, BlockInputIterator last,
               const Allocator& alloc = Allocator())
        : detail::dynamic_bitset_base<Block, Allocator>
            (detail::initial_num_blocks(first, last)
            * bits_per_block, alloc)
    {
        if (first != last) {
            if (this->m_num_bits == 0) { // dealing with input iterators
                this->append(first, last);
            } else {
                // dealing with forward iterators, memory has been allocated
                for (std::size_t i = 0; first != last; ++first, ++i)
                    set_block_(i, *first);
            }
        }
    }

    // copy constructor
    dynamic_bitset(const dynamic_bitset& b);

    void swap(dynamic_bitset& b);

    dynamic_bitset& operator=(const dynamic_bitset& b);

    // size changing operations
    void resize(size_type num_bits, bool value = false);
    void clear();
    void push_back(bool bit);
    void append(Block block);

    // This is declared inside the class to avoid compiler bugs.
    template <typename BlockInputIterator>
    void append(BlockInputIterator first, BlockInputIterator last)
    {
        if (first != last) {
            std::size_t nblocks = detail::initial_num_blocks(first, last);
            if (nblocks == 0) { // dealing with input iterators
                for (; first != last; ++first)
                    append(*first);
            } else { // dealing with forward iterators
                if (size() % bits_per_block == 0) {
                    std::size_t old_nblocks = this->m_num_blocks;
                    resize(size() + nblocks * bits_per_block);
                    for (std::size_t i = old_nblocks; first != last; ++first)
                        set_block_(i++, *first);
                } else {
                    // probably should optimize this,
                    // but I'm sick of bit twiddling
                    for (; first != last; ++first)
                        append(*first);
                }
            }
        }
    }

    // bitset operations
    dynamic_bitset& operator&=(const dynamic_bitset& b);
    dynamic_bitset& operator|=(const dynamic_bitset& b);
    dynamic_bitset& operator^=(const dynamic_bitset& b);
    dynamic_bitset& operator-=(const dynamic_bitset& b);
    dynamic_bitset& operator<<=(size_type n);
    dynamic_bitset& operator>>=(size_type n);
    dynamic_bitset operator<<(size_type n) const;
    dynamic_bitset operator>>(size_type n) const;

    // basic bit operations
    dynamic_bitset& set(size_type n, bool val = true);
    dynamic_bitset& set();
    dynamic_bitset& reset(size_type n);
    dynamic_bitset& reset();
    dynamic_bitset& flip(size_type n);
    dynamic_bitset& flip();
    bool test(size_type n) const;
    bool any() const;
    bool none() const;
    dynamic_bitset operator~() const;
    size_type count() const;

    // subscript
    reference operator[](size_type pos) { return reference(*this, pos); }
    bool operator[](size_type pos) const { return test_(pos); } //[gps]

    unsigned long to_ulong() const;

    size_type size() const;
    size_type num_blocks() const;

    bool is_subset_of(const dynamic_bitset& a) const;
    bool is_proper_subset_of(const dynamic_bitset& a) const;

#ifdef BOOST_DYN_BITSET_USE_FRIENDS
    // lexicographical comparison
    template <typename B, typename A>
    friend bool operator==(const dynamic_bitset<B, A>& a,
                           const dynamic_bitset<B, A>& b);
    template <typename B, typename A>
    friend bool operator<(const dynamic_bitset<B, A>& a,
                          const dynamic_bitset<B, A>& b);
    template <typename B, typename A>
    friend bool operator>(const dynamic_bitset<B, A>& a,
                          const dynamic_bitset<B, A>& b);

    template <typename B, typename A, typename BlockOutputIterator>
    friend void to_block_range(const dynamic_bitset<B, A>& b,
                               BlockOutputIterator result);

    template <typename BlockIterator, typename B, typename A>
    friend void from_block_range(BlockIterator first, BlockIterator last,
                                 dynamic_bitset<B, A>& result);

    template <typename B, typename A, typename CharT, typename Alloc>
    friend void dump_to_string(const dynamic_bitset<B, A>& b,
                               std::basic_string<CharT, Alloc>& s);
#endif

private:
    void m_zero_unused_bits();
    void set_(size_type bit);
    bool set_(size_type bit, bool val);
    void reset_(size_type bit);
    bool test_(size_type bit) const;
    void set_block_(size_type blocknum, Block b);

public:

    // This is templated on the whole String instead of just CharT,
    // Traits, Alloc to avoid compiler bugs.
    template <typename String>
    void from_string(const String& s, typename String::size_type pos,
                     typename String::size_type rlen)
    {
        reset(); // bugfix [gps]
        size_type const tot = std::min (rlen, s.length()); // bugfix [gps]

        // Assumes string contains only 0's and 1's
        for (size_type i = 0; i < tot; ++i) {
        if (s[pos + tot - i - 1] == '1') {
                set_(i);
            } else {
            assert(s[pos + tot - i - 1] == '0');
            }
        }
    }

};

// Global Functions:

// comparison
template <typename Block, typename Allocator>
bool operator!=(const dynamic_bitset<Block, Allocator>& a,
                const dynamic_bitset<Block, Allocator>& b);

template <typename Block, typename Allocator>
bool operator<=(const dynamic_bitset<Block, Allocator>& a,
                const dynamic_bitset<Block, Allocator>& b);

template <typename Block, typename Allocator>
bool operator>(const dynamic_bitset<Block, Allocator>& a,
               const dynamic_bitset<Block, Allocator>& b);

template <typename Block, typename Allocator>
bool operator>=(const dynamic_bitset<Block, Allocator>& a,
                const dynamic_bitset<Block, Allocator>& b);

// stream operators
#ifdef BOOST_OLD_IOSTREAMS
template <typename Block, typename Allocator>
std::ostream& operator<<(std::ostream& os,
                         const dynamic_bitset<Block, Allocator>& b);

template <typename Block, typename Allocator>
std::istream& operator>>(std::istream& is, dynamic_bitset<Block,Allocator>& b);
#else
template <typename CharT, typename Traits, typename Block, typename Allocator>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
           const dynamic_bitset<Block, Allocator>& b);

template <typename CharT, typename Traits, typename Block, typename Allocator>
std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is,
           dynamic_bitset<Block, Allocator>& b);
#endif

// bitset operations
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator&(const dynamic_bitset<Block, Allocator>& b1,
          const dynamic_bitset<Block, Allocator>& b2);

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator|(const dynamic_bitset<Block, Allocator>& b1,
          const dynamic_bitset<Block, Allocator>& b2);

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator^(const dynamic_bitset<Block, Allocator>& b1,
          const dynamic_bitset<Block, Allocator>& b2);

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator-(const dynamic_bitset<Block, Allocator>& b1,
          const dynamic_bitset<Block, Allocator>& b2);

template <typename Block, typename Allocator, typename CharT, typename Alloc>
void
to_string(const dynamic_bitset<Block, Allocator>& b,
          std::basic_string<CharT, Alloc>& s);

template <typename Block, typename Allocator, typename BlockOutputIterator>
void
to_block_range(const dynamic_bitset<Block, Allocator>& b,
               BlockOutputIterator result);

template <typename BlockIterator, typename B, typename A>
inline void
from_block_range(BlockIterator first, BlockIterator last,
                 dynamic_bitset<B, A>& result);

//=============================================================================
// dynamic_bitset implementation

#ifdef BOOST_OLD_IOSTREAMS
template <typename Block, typename Allocator>
inline std::ostream&
operator<<(std::ostream& os,
           const typename dynamic_bitset<Block, Allocator>::reference& br)
{
    return os << (bool)br;
}
#else
template <typename CharT, typename Traits, typename Block, typename Allocator>
inline std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
           const typename dynamic_bitset<Block, Allocator>::reference& br)
{
    return os << (bool)br;
}
#endif

//-----------------------------------------------------------------------------
// constructors, etc.

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>::dynamic_bitset(const Allocator& alloc)
  : detail::dynamic_bitset_base<Block, Allocator>(0, alloc) { }

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>::
dynamic_bitset(size_type num_bits, unsigned long value, const Allocator& alloc)
  : detail::dynamic_bitset_base<Block, Allocator>(num_bits, alloc)
{
  const size_type M = std::min(sizeof(unsigned long) * CHAR_BIT, num_bits);
  for(size_type i = 0; i < M; ++i, value >>= 1) // [G.P.S.] to be optimized
    if ( value & 0x1 )
      set_(i);
}

// copy constructor
template <typename Block, typename Allocator>
inline dynamic_bitset<Block, Allocator>::
dynamic_bitset(const dynamic_bitset& b)
  : detail::dynamic_bitset_base<Block, Allocator>(b.size(), b.m_alloc)
{
    using namespace std;
    memcpy(this->m_bits, b.m_bits, this->m_num_blocks * sizeof(Block));
}

template <typename Block, typename Allocator>
inline void dynamic_bitset<Block, Allocator>::
swap(dynamic_bitset<Block, Allocator>& b)
{
    std::swap(this->m_bits, b.m_bits);
    std::swap(this->m_num_bits, b.m_num_bits);
    std::swap(this->m_num_blocks, b.m_num_blocks);
    std::swap(this->m_alloc, b.m_alloc);
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::
operator=(const dynamic_bitset<Block, Allocator>& b)
{
    dynamic_bitset<Block, Allocator> tmp(b);
    this->swap(tmp);
    return *this;
}

//-----------------------------------------------------------------------------
// size changing operations

template <typename Block, typename Allocator>
void dynamic_bitset<Block, Allocator>::
resize(size_type num_bits, bool value)
{
  if (num_bits == size())
    return;
  size_type new_nblocks = this->calc_num_blocks(num_bits);
  Block* d = this->m_alloc.allocate(new_nblocks, static_cast<void const *>(0));
  if (num_bits < size()) { // shrink
    std::copy(this->m_bits, this->m_bits + new_nblocks, d);
    std::swap(d, this->m_bits);
    this->m_alloc.deallocate(d, this->m_num_blocks);
  } else { // grow
    std::copy(this->m_bits, this->m_bits + this->m_num_blocks, d);
    Block val = value? ~static_cast<Block>(0) : static_cast<Block>(0);
    std::fill(d + this->m_num_blocks, d + new_nblocks, val);
    std::swap(d, this->m_bits);
    for (std::size_t i = this->m_num_bits;
         i < this->m_num_blocks * bits_per_block; ++i)
      set_(i, value);
    if (d != 0)
      this->m_alloc.deallocate(d, this->m_num_blocks);
  }
  this->m_num_bits = num_bits;
  this->m_num_blocks = this->calc_num_blocks(num_bits);
  m_zero_unused_bits();
}

template <typename Block, typename Allocator>
void dynamic_bitset<Block, Allocator>::
clear()
{
  if (this->m_bits != 0) {
    this->m_alloc.deallocate(this->m_bits, this->m_num_blocks);
    this->m_bits = 0;
    this->m_num_bits = 0;
    this->m_num_blocks = 0;
  }
}

template <typename Block, typename Allocator>
void dynamic_bitset<Block, Allocator>::
push_back(bool bit)
{
  this->resize(this->size() + 1);
  set_(this->size() - 1, bit);
}

template <typename Block, typename Allocator>
void dynamic_bitset<Block, Allocator>::
append(Block value)
{
  std::size_t old_size = size();
  resize(old_size + bits_per_block);
  if (size() % bits_per_block == 0)
    set_block_(this->m_num_blocks - 1, value);
  else {
      // G.P.S. to be optimized
    for (std::size_t i = old_size; i < size(); ++i, value >>= 1)
      set_(i, value & 1);
  }
}

//-----------------------------------------------------------------------------
// bitset operations
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::operator&=(const dynamic_bitset& rhs)
{
    assert(size() == rhs.size());
    for (size_type i = 0; i < this->m_num_blocks; ++i)
        this->m_bits[i] &= rhs.m_bits[i];
    return *this;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::operator|=(const dynamic_bitset& rhs)
{
    assert(size() == rhs.size());
    for (size_type i = 0; i < this->m_num_blocks; ++i)
        this->m_bits[i] |= rhs.m_bits[i];
    m_zero_unused_bits();
    return *this;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::operator^=(const dynamic_bitset& rhs)
{
    assert(size() == rhs.size());
    for (size_type i = 0; i < this->m_num_blocks; ++i)
        this->m_bits[i] ^= rhs.m_bits[i];
    m_zero_unused_bits();
    return *this;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::operator-=(const dynamic_bitset& rhs)
{
    assert(size() == rhs.size());
    for (size_type i = 0; i < this->m_num_blocks; ++i)
        this->m_bits[i] = this->m_bits[i] & ~rhs.m_bits[i];
    m_zero_unused_bits();
    return *this;
}

/* [gps] - snipped
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::operator<<=(size_type n)
{
    if (n >= this->m_num_bits)
        reset();
    else
    {
        size_type i;
        for (i = this->m_num_bits - 1; i > n; --i)
            set_(i,test_(i-n));
        if (i == n) // careful, unsigned can't go negative!
            set_(i,test_(i-n));
        for (i = 0; i < n; ++i)
            reset_(i);
    }
    return *this;
}*/

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::operator<<=(size_type n)
{
    if (n >= this->m_num_bits)
        return reset();
    //else
    if (n > 0)
    {
        size_type  const last  = this->m_num_blocks - 1; // m_num_blocks is >= 1
        size_type  const div   = n / bits_per_block; // div is <= last
        size_type  const r     = n % bits_per_block;

        // PRE: div != 0  or  r != 0

        if (r != 0) {

            block_type const rs = bits_per_block - r;

            for (size_type i = last-div; i>0; --i) {
                this->m_bits[i+div] = (this->m_bits[i] << r) | (this->m_bits[i-1] >> rs);
            }
            this->m_bits[div] = this->m_bits[0] << r;

        }
        else {
            for (size_type i = last-div; i>0; --i) {
                this->m_bits[i+div] = this->m_bits[i];
            }
            this->m_bits[div] = this->m_bits[0];
        }

        // div blocks are zero filled at the less significant end
        std::fill(this->m_bits, this->m_bits+div, static_cast<block_type>(0));

    }

    return *this;

}

/* [gps] - snipped
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::operator>>=(size_type n)
{
    if (n >= this->m_num_bits)
        reset();
    else
    {
        size_type i;
        for (i = 0; i < this->m_num_bits - n; ++i)
            set_(i,test_(i+n));

        for (i = this->m_num_bits - n; i < this->m_num_bits; ++i)
            reset_(i);
    }
    return *this;
}*/

// NOTE: this assumes that within a single block bits are
//       numbered from right to left. G.P.S.
//
//      static Block offset(size_type bit)
//        { return  bit % bits_per_block; }
//
//
// In the implementation below the 'if (r != 0)' is logically
// unnecessary. It's there as an optimization only: in fact
// for r==0 the first branch becomes the second one with the
// b[last-div] = b[last] >> r; statement that does the work of
// the last iteration.
//
template <typename B, typename A>
dynamic_bitset<B, A> & dynamic_bitset<B, A>::operator>>=(size_type n) {
    if (n >= this->m_num_bits) {
        return reset();
    }
    //else
    if (n>0){

        size_type  const last  = this->m_num_blocks - 1; // m_num_blocks is >= 1
        size_type  const div   = n / bits_per_block; // div is <= last
        size_type  const r     = n % bits_per_block;

        // PRE: div != 0  or  r != 0

        if (r != 0) {

            block_type const ls = bits_per_block - r;

            for (size_type i = div; i < last; ++i) {
                this->m_bits[i-div] = (this->m_bits[i] >> r) | (this->m_bits[i+1]  << ls);
            }
            // r bits go to zero
            this->m_bits[last-div] = this->m_bits[last] >> r;
        }

        else {
            for (size_type i = div; i <= last; ++i) {
                this->m_bits[i-div] = this->m_bits[i];
            }
            // note the '<=': the last iteration 'absorbs'
            // this->m_bits[last-div] = this->m_bits[last] >> 0;
        }

        // div blocks are zero filled at the most significant end
        std::fill(this->m_bits+(this->m_num_blocks-div), this->m_bits+this->m_num_blocks, static_cast<block_type>(0));
    }

    return *this;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
dynamic_bitset<Block, Allocator>::operator<<(size_type n) const
{
    dynamic_bitset r(*this);
    return r <<= n;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
dynamic_bitset<Block, Allocator>::operator>>(size_type n) const
{
    dynamic_bitset r(*this);
    return r >>= n;
}

//-----------------------------------------------------------------------------
// basic bit operations

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::set(size_type pos, bool val)
{
    assert(pos < this->m_num_bits);
    set_(pos, val);
    return *this;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::set()
{
  if (this->m_num_bits > 0) {
    using namespace std;
    memset(this->m_bits, ~0u, this->m_num_blocks * sizeof(this->m_bits[0]));
    m_zero_unused_bits();
  }
  return *this;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::reset(size_type pos)
{
    assert(pos < this->m_num_bits);
    reset_(pos);
    return *this;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::reset()
{
  if (this->m_num_bits > 0) {
    using namespace std;
    memset(this->m_bits, 0, this->m_num_blocks * sizeof(this->m_bits[0]));
  }
  return *this;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::flip(size_type pos)
{
    assert(pos < this->m_num_bits);
    this->m_bits[this->word(pos)] ^= this->mask1(pos);
    return *this;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>&
dynamic_bitset<Block, Allocator>::flip()
{
    for (size_type i = 0; i < this->m_num_blocks; ++i)
        this->m_bits[i] = ~this->m_bits[i];
    m_zero_unused_bits();
    return *this;
}

template <typename Block, typename Allocator>
bool dynamic_bitset<Block, Allocator>::test(size_type pos) const
{
    assert(pos < this->m_num_bits);
    return test_(pos);
}

template <typename Block, typename Allocator>
bool dynamic_bitset<Block, Allocator>::any() const
{
    for (size_type i = 0; i < this->m_num_blocks; ++i)
        if (this->m_bits[i])
            return 1;
    return 0;
}

template <typename Block, typename Allocator>
inline bool dynamic_bitset<Block, Allocator>::none() const
{
    return !any();
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
dynamic_bitset<Block, Allocator>::operator~() const
{
    dynamic_bitset b(*this);
    b.flip();
    return b;
}

/* snipped: [gps]

The following is the straightforward implementation of count(), which
we leave here in a comment for documentation purposes.

template <typename Block, typename Allocator>
typename dynamic_bitset<Block, Allocator>::size_type
dynamic_bitset<Block, Allocator>::count() const
{
    size_type sum = 0;
    for (size_type i = 0; i != this->m_num_bits; ++i)
        if (test_(i))
            ++sum;
    return sum;
}

The actual algorithm used is based on using a lookup
table.

  The basic idea of the method is to pick up X bits at a time
  from the internal array of blocks and consider those bits as
  the binary representation of a number N. Then, to use a table
  of 1<<X elements where table[N] is the number of '1' digits
  in the binary representation of N (i.e. in our X bits).

  Note that the table can be oversized (i.e. can even have more
  than 1<<X elements; in that case only the first 1<<X will be
  actually used) but it cannot be undersized.
  In this implementation X is 8 (but can be easily changed: you
  just have to change the definition of count<>::max_bits) and
  the internal array of blocks is seen as an array of bytes: if
  a byte has exactly 8 bits then it's enough to sum the value
  of table[B] for each byte B. Otherwise 8 bits at a time are
  'extracted' from each byte by using another loop. As a further
  efficiency consideration note that even if you have, let's say,
  32-bit chars the inner loop will not do 4 (i.e. 32/8) iterations,
  unless you have at least one bit set in the highest 8 bits of the
  byte.

  Note also that the outmost if/else is not necessary but is there
  to help the optimizer (and one of the two branches is always dead
  code).

*/

template <typename Block, typename Allocator>
typename dynamic_bitset<Block, Allocator>::size_type
dynamic_bitset<Block, Allocator>::count() const
{
    using detail::byte_t;

    const byte_t * p = reinterpret_cast<const byte_t*>(this->m_bits);
    const byte_t * past_end = p + this->m_num_blocks * sizeof(Block);

    size_type num = 0;
    unsigned int const max_bit = detail::count<>::max_bit;

    if (CHAR_BIT <= max_bit) { // table is large enough
        while (p < past_end) {
            num += detail::count<>::table[*p];
            ++p;
        }
    }
    else {
        while (p < past_end) {
            // this inner loop 'extracts' max_bit bits at a time
            // from the byte at address p, and thus allows to use
            // our (small) table for any (high) CHAR_BIT value
            byte_t value = *p;
            do {
                num += detail::count<>::table[value & ((1<<max_bit)-1)];
            } while (value >>= max_bit);

            ++p;
        }
    }

    return num;
}

//-----------------------------------------------------------------------------
// conversions

// take as ref param instead?
template <typename Block, typename Allocator, typename CharT, typename Alloc>
void
to_string(const dynamic_bitset<Block, Allocator>& b,
          std::basic_string<CharT, Alloc>& s)
{
    s.assign(b.size(), '0');
    for (std::size_t i = 0; i < b.size(); ++i)
        if (b.test(i)) // [G.P.S.]
            s[b.size() - 1 - i] = '1';
}

// Differently from to_string this function dumps out
// every bit of the internal representation (useful
// for debugging purposes)
//
template <typename B, typename A, typename CharT, typename Alloc>
void
dump_to_string(const dynamic_bitset<B, A>& b,
               std::basic_string<CharT, Alloc>& s)
{
    std::size_t const len = b.m_num_blocks * (dynamic_bitset<B, A>::bits_per_block);
    s.assign(len, '0');
    for (std::size_t i = 0; i != len; ++i)
      if (b[i])// could use test_ here, but we have friend issues.-JGS
            s[len - 1 - i] = '1';
}

template <typename Block, typename Allocator, typename BlockOutputIterator>
void
to_block_range(const dynamic_bitset<Block, Allocator>& b,
               BlockOutputIterator result)
{
    assert(b.size() != 0 || b.num_blocks() == 0);
    std::copy (b.m_bits, b.m_bits + b.m_num_blocks, result);
}

template <typename BlockIterator, typename B, typename A>
inline void
from_block_range(BlockIterator first, BlockIterator last,
                 dynamic_bitset<B, A>& result)
{
    // PRE: distance(first, last) == numblocks()
    std::copy (first, last, result.m_bits);
}

template <typename Block, typename Allocator>
unsigned long dynamic_bitset<Block, Allocator>::
to_ulong() const
{
  const std::overflow_error
    overflow("boost::bit_set::operator unsigned long()");

  if (this->m_num_blocks == 0)
    return 0;

  if (sizeof(Block) >= sizeof(unsigned long)) {
    for (size_type i = 1; i < this->m_num_blocks; ++i)
      if (this->m_bits[i])
        throw overflow;
    const Block mask = static_cast<Block>(static_cast<unsigned long>(-1));
    if (this->m_bits[0] & ~mask)
      throw overflow;
    size_type N = std::min(sizeof(unsigned long) * CHAR_BIT, this->size());
    unsigned long num = 0;
    for (size_type j = 0; j < N; ++j)
      if (this->test(j))
        num |= (1 << j);
    return num;
  }
  else { // sizeof(Block) < sizeof(unsigned long).
    const size_type nwords =
      (sizeof(unsigned long) + sizeof(Block) - 1) / sizeof(Block);

    size_type min_nwords = nwords;
    if (this->m_num_blocks > nwords) {
      for (size_type i = nwords; i < this->m_num_blocks; ++i)
        if (this->m_bits[i])
          throw overflow;
    }
    else
      min_nwords = this->m_num_blocks;

    unsigned long result = 0;
    size_type N = std::min(sizeof(unsigned long) * CHAR_BIT, this->size());
    for (size_type i = 0; i < N; ++i)
      if (this->test(i))
        result |= (1 << i);
    return result;
  }
}

template <typename Block, typename Allocator>
inline typename dynamic_bitset<Block, Allocator>::size_type
dynamic_bitset<Block, Allocator>::size() const
{
    return this->m_num_bits;
}

template <typename Block, typename Allocator>
inline typename dynamic_bitset<Block, Allocator>::size_type
dynamic_bitset<Block, Allocator>::num_blocks() const
{
    return this->m_num_blocks;
}

template <typename Block, typename Allocator>
bool dynamic_bitset<Block, Allocator>::
is_subset_of(const dynamic_bitset<Block, Allocator>& a) const
{
    assert(this->size() == a.size());
    for (size_type i = 0; i < this->m_num_blocks; ++i)
        if (this->m_bits[i] & ~a.m_bits[i])
            return false;
    return true;
}

template <typename Block, typename Allocator>
bool dynamic_bitset<Block, Allocator>::
is_proper_subset_of(const dynamic_bitset<Block, Allocator>& a) const
{
    assert(this->size() == a.size());
    bool proper = false;
    for (size_type i = 0; i < this->m_num_blocks; ++i) {
        Block bt = this->m_bits[i], ba = a.m_bits[i];
        if (ba & ~bt)
            proper = true;
        if (bt & ~ba)
            return false;
    }
    return proper;
}

//-----------------------------------------------------------------------------
// comparison

template <typename Block, typename Allocator>
bool operator==(const dynamic_bitset<Block, Allocator>& a,
                const dynamic_bitset<Block, Allocator>& b)
{
    using namespace std;
    return (a.m_num_bits == b.m_num_bits) &&
      ((a.m_num_bits == 0) ||
        !memcmp(a.m_bits, b.m_bits, a.m_num_blocks * sizeof(a.m_bits[0])));
}

template <typename Block, typename Allocator>
inline bool operator!=(const dynamic_bitset<Block, Allocator>& a,
                       const dynamic_bitset<Block, Allocator>& b)
{
    return !(a == b);
}

template <typename Block, typename Allocator>
bool operator<(const dynamic_bitset<Block, Allocator>& a,
               const dynamic_bitset<Block, Allocator>& b)
{
    assert(a.size() == b.size());
    typedef typename dynamic_bitset<Block, Allocator>::size_type size_type;

    if (a.size() == 0)
      return false;

    // Since we are storing the most significant bit
    // at pos == size() - 1, we need to do the memcmp in reverse.

    // Compare a block at a time
    for (size_type i = a.m_num_blocks - 1; i > 0; --i)
      if (a.m_bits[i] < b.m_bits[i])
        return true;
      else if (a.m_bits[i] > b.m_bits[i])
        return false;

    if (a.m_bits[0] < b.m_bits[0])
      return true;
    else
      return false;
}

template <typename Block, typename Allocator>
inline bool operator<=(const dynamic_bitset<Block, Allocator>& a,
                       const dynamic_bitset<Block, Allocator>& b)
{
    return !(a > b);
}

template <typename Block, typename Allocator>
inline bool operator>(const dynamic_bitset<Block, Allocator>& a,
                      const dynamic_bitset<Block, Allocator>& b)
{
    assert(a.size() == b.size());
    typedef typename dynamic_bitset<Block, Allocator>::size_type size_type;

    if (a.size() == 0)
      return false;

    // Since we are storing the most significant bit
    // at pos == size() - 1, we need to do the memcmp in reverse.

    // Compare a block at a time
    for (size_type i = a.m_num_blocks - 1; i > 0; --i)
      if (a.m_bits[i] < b.m_bits[i])
        return false;
      else if (a.m_bits[i] > b.m_bits[i])
        return true;

    if (a.m_bits[0] > b.m_bits[0])
      return true;
    else
      return false;
}

template <typename Block, typename Allocator>
inline bool operator>=(const dynamic_bitset<Block, Allocator>& a,
                       const dynamic_bitset<Block, Allocator>& b)
{
    return !(a < b);
}

//-----------------------------------------------------------------------------
// stream operations

#ifdef BOOST_OLD_IOSTREAMS
template < typename Block, typename Allocator>
std::ostream&
operator<<(std::ostream& os, const dynamic_bitset<Block, Allocator>& b)
{
    std::string s;
    to_string(b, s);
    os << s.c_str();
    return os;
}
#else
template <typename CharT, typename Traits, typename Block, typename Allocator>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
           const dynamic_bitset<Block, Allocator>& b)
{
    std::basic_string<CharT, Traits> s;
    to_string(b, s);
    os << s;
    return os;
}
#endif

#ifdef BOOST_OLD_IOSTREAMS
template <typename Block, typename Allocator>
std::istream&
operator>>(std::istream& is, dynamic_bitset<Block, Allocator>& b)
{
    typedef char CharT;
    std::string buf;
    typedef typename std::string::size_type size_type;
    const size_type N = b.size();
    buf.reserve(N);

    // skip whitespace
    if (is.flags() & std::ios::skipws) {
        char c;
        do
            is.get(c);
#if defined(__GNUC__) && !defined(__SGI_STL_PORT)
        while (is && isspace(c));
#else
        while (is && std::isspace(c));
#endif
        if (is)
            is.putback(c);
    }

    size_type i;
    for (i = 0; i < N; ++i)
    {
        CharT c;
        is.get(c);
        if (c == '0' || c == '1')
            buf += c;
        else
        {
            is.putback(c);
            break;
        }
    }

    if (i == 0)
        is.clear(is.rdstate() | std::ios::failbit);
    else
    {
        dynamic_bitset<Block, Allocator> tmp(buf);
        b.swap(tmp);
    }
    return is;
}
#else
template <typename CharT, typename Traits, typename Block, typename Allocator>
std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& in_stream,
           dynamic_bitset<Block, Allocator>& b)
{
    std::basic_string<CharT,Traits> tmp;
    typedef typename std::basic_string<CharT,Traits>::size_type size_type;
    const size_type N = b.size();
    tmp.reserve(N);

    // skip whitespace
    typename std::basic_istream<CharT, Traits>::sentry sentry(in_stream);
    if (sentry) {
      std::basic_streambuf<CharT, Traits>* read_buf = in_stream.rdbuf();

      for (size_type i = 0; i < N; ++i) {
        typename Traits::int_type c1 = read_buf->sbumpc();
        if (Traits::eq_int_type(c1, Traits::eof())) {
          in_stream.setstate(std::ios_base::eofbit);
          break;
        } else {
          char c2 = Traits::to_char_type(c1);
          char c  = in_stream.narrow(c2, '*');

          if (c == '0' || c == '1')
            tmp += c; // old dinkumware basic_string missing push_back
          else if (Traits::eq_int_type(read_buf->sputbackc(c2), Traits::eof()))
          {
            in_stream.setstate(std::ios_base::failbit);
            break;
          }
        }
      } // for

      if (tmp.empty()) // did not read in enough bits
        in_stream.setstate(std::ios_base::failbit);
      else
          b.from_string(tmp, static_cast<size_type>(0), N);
    } // if (sentry)
    return in_stream;
}
#endif

//-----------------------------------------------------------------------------
// bitset operations

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator&(const dynamic_bitset<Block, Allocator>& x,
          const dynamic_bitset<Block, Allocator>& y)
{
    dynamic_bitset<Block, Allocator> b(x);
    return b &= y;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator|(const dynamic_bitset<Block, Allocator>& x,
          const dynamic_bitset<Block, Allocator>& y)
{
    dynamic_bitset<Block, Allocator> b(x);
    return b |= y;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator^(const dynamic_bitset<Block, Allocator>& x,
          const dynamic_bitset<Block, Allocator>& y)
{
    dynamic_bitset<Block, Allocator> b(x);
    return b ^= y;
}

template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator-(const dynamic_bitset<Block, Allocator>& x,
          const dynamic_bitset<Block, Allocator>& y)
{
    dynamic_bitset<Block, Allocator> b(x);
    return b -= y;
}

//-----------------------------------------------------------------------------
// private member functions

template <typename Block, typename Allocator>
inline void dynamic_bitset<Block, Allocator>::
set_(size_type bit)
{
    this->m_bits[this->word(bit)] |= this->mask1(bit);
}

template <typename Block, typename Allocator>
inline void dynamic_bitset<Block, Allocator>::
set_block_(size_type blocknum, Block value)
{
    this->m_bits[blocknum] = value;
}

template <typename Block, typename Allocator>
inline void dynamic_bitset<Block, Allocator>::
reset_(size_type b)
{
    this->m_bits[this->word(b)] &= this->mask0(b);
}

template <typename Block, typename Allocator>
inline bool dynamic_bitset<Block, Allocator>::test_(size_type b) const
{
    return (this->m_bits[this->word(b)] & this->mask1(b)) != static_cast<Block>(0);
}

template <typename Block, typename Allocator>
bool dynamic_bitset<Block, Allocator>::set_(size_type n, bool value)
{
    if (value)
        set_(n);
    else
        reset_(n);
    return value != static_cast<Block>(0);
}

// If size() is not a multiple of bits_per_block
// then not all the bits in the last block are used.
// This function resets the unused bits (convenient
// for the implementation of many member functions)
//
template <typename Block, typename Allocator>
inline void dynamic_bitset<Block, Allocator>::m_zero_unused_bits()
{
    assert (this->m_num_blocks == this->calc_num_blocks(this->m_num_bits));

    // if != 0 this is the number of bits used in the last block
    const size_type used_bits = this->m_num_bits % bits_per_block;

    if (used_bits != 0)
        this->m_bits[this->m_num_blocks - 1] &= ~(~static_cast<Block>(0) << used_bits);

}

} // namespace boost

#undef BOOST_WORKAROUND_REPEAT_DEFAULT_TEMPLATE_ARGUMENTS

#endif // BOOST_DYNAMIC_BITSET_HPP


text:
#pragma once

#include <paper/ledger.hpp>
#include <paper/lib/work.hpp>
#include <paper/node/bootstrap.hpp>
#include <paper/node/wallet.hpp>

#include <condition_variable>
#include <memory>
#include <mutex>
#include <queue>
#include <thread>
#include <unordered_set>

#include <boost/asio.hpp>
#include <boost/circular_buffer.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/log/trivial.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index_container.hpp>

#include <miniupnpc.h>

namespace boost
{
namespace program_options
{
	class options_description;
	class variables_map;
}
}

namespace paper
{
class node;
class election : public std::enable_shared_from_this<paper::election>
{
	std::function<void(std::shared_ptr<paper::block>, bool)> confirmation_action;
	void confirm_once (MDB_txn *);

public:
	election (MDB_txn *, paper::node &, std::shared_ptr<paper::block>, std::function<void(std::shared_ptr<paper::block>, bool)> const &);
	void vote (std::shared_ptr<paper::vote>);
	// Check if we have vote quorum
	bool have_quorum (MDB_txn *);
	// Tell the network our view of the winner
	void broadcast_winner ();
	// Change our winner to agree with the network
	void compute_rep_votes (MDB_txn *);
	// Confirmation method 1, uncontested quorum
	void confirm_if_quorum (MDB_txn *);
	// Confirmation method 2, settling time
	void confirm_cutoff (MDB_txn *);
	paper::uint128_t quorum_threshold (MDB_txn *, paper::ledger &);
	paper::uint128_t minimum_threshold (MDB_txn *, paper::ledger &);
	paper::votes votes;
	paper::node & node;
	std::chrono::steady_clock::time_point last_vote;
	std::shared_ptr<paper::block> last_winner;
	std::atomic_flag confirmed;
};
class conflict_info
{
public:
	paper::block_hash root;
	std::shared_ptr<paper::election> election;
	// Number of announcements in a row for this fork
	unsigned announcements;
};
// Core class for determining consensus
// Holds all active blocks i.e. recently added blocks that need confirmation
class active_transactions
{
public:
	active_transactions (paper::node &);
	// Start an election for a block
	// Call action with confirmed block, may be different than what we started with
	bool start (MDB_txn *, std::shared_ptr<paper::block>, std::function<void(std::shared_ptr<paper::block>, bool)> const & = [](std::shared_ptr<paper::block>, bool) {});
	void vote (std::shared_ptr<paper::vote>);
	// Is the root of this block in the roots container
	bool active (paper::block const &);
	void announce_votes ();
	void stop ();
	boost::multi_index_container<
	paper::conflict_info,
	boost::multi_index::indexed_by<
	boost::multi_index::ordered_unique<boost::multi_index::member<paper::conflict_info, paper::block_hash, &paper::conflict_info::root>>>>
	roots;
	paper::node & node;
	std::mutex mutex;
	// Maximum number of conflicts to vote on per interval, lowest root hash first
	static unsigned constexpr announcements_per_interval = 32;
	// After this many successive vote announcements, block is confirmed
	static unsigned constexpr contiguous_announcements = 4;
	static unsigned constexpr announce_interval_ms = (paper::paper_network == paper::paper_networks::paper_test_network) ? 10 : 16000;
};
class operation
{
public:
	bool operator> (paper::operation const &) const;
	std::chrono::steady_clock::time_point wakeup;
	std::function<void()> function;
};
class alarm
{
public:
	alarm (boost::asio::io_service &);
	~alarm ();
	void add (std::chrono::steady_clock::time_point const &, std::function<void()> const &);
	void run ();
	boost::asio::io_service & service;
	std::mutex mutex;
	std::condition_variable condition;
	std::priority_queue<operation, std::vector<operation>, std::greater<operation>> operations;
	std::thread thread;
};
class gap_information
{
public:
	std::chrono::steady_clock::time_point arrival;
	paper::block_hash hash;
	std::unique_ptr<paper::votes> votes;
};
class gap_cache
{
public:
	gap_cache (paper::node &);
	void add (MDB_txn *, std::shared_ptr<paper::block>);
	void vote (std::shared_ptr<paper::vote>);
	paper::uint128_t bootstrap_threshold (MDB_txn *);
	void purge_old ();
	boost::multi_index_container<
	paper::gap_information,
	boost::multi_index::indexed_by<
	boost::multi_index::ordered_non_unique<boost::multi_index::member<gap_information, std::chrono::steady_clock::time_point, &gap_information::arrival>>,
	boost::multi_index::hashed_unique<boost::multi_index::member<gap_information, paper::block_hash, &gap_information::hash>>>>
	blocks;
	size_t const max = 256;
	std::mutex mutex;
	paper::node & node;
};
class work_pool;
class peer_information
{
public:
	peer_information (paper::endpoint const &, unsigned);
	peer_information (paper::endpoint const &, std::chrono::steady_clock::time_point const &, std::chrono::steady_clock::time_point const &);
	paper::endpoint endpoint;
	std::chrono::steady_clock::time_point last_contact;
	std::chrono::steady_clock::time_point last_attempt;
	std::chrono::steady_clock::time_point last_bootstrap_attempt;
	std::chrono::steady_clock::time_point last_rep_request;
	std::chrono::steady_clock::time_point last_rep_response;
	paper::amount rep_weight;
	unsigned network_version;
};
class peer_attempt
{
public:
	paper::endpoint endpoint;
	std::chrono::steady_clock::time_point last_attempt;
};
class peer_container
{
public:
	peer_container (paper::endpoint const &);
	// We were contacted by endpoint, update peers
	void contacted (paper::endpoint const &, unsigned);
	// Unassigned, reserved, self
	bool not_a_peer (paper::endpoint const &);
	// Returns true if peer was already known
	bool known_peer (paper::endpoint const &);
	// Notify of peer we received from
	bool insert (paper::endpoint const &, unsigned);
	std::unordered_set<paper::endpoint> random_set (size_t);
	void random_fill (std::array<paper::endpoint, 8> &);
	// Request a list of the top known representatives
	std::vector<peer_information> representatives (size_t);
	// List of all peers
	std::vector<paper::endpoint> list ();
	std::map<paper::endpoint, unsigned> list_version ();
	// A list of random peers with size the square root of total peer count
	std::vector<paper::endpoint> list_sqrt ();
	// Get the next peer for attempting bootstrap
	paper::endpoint bootstrap_peer ();
	// Purge any peer where last_contact < time_point and return what was left
	std::vector<paper::peer_information> purge_list (std::chrono::steady_clock::time_point const &);
	std::vector<paper::endpoint> rep_crawl ();
	bool rep_response (paper::endpoint const &, paper::amount const &);
	void rep_request (paper::endpoint const &);
	// Should we reach out to this endpoint with a keepalive message
	bool reachout (paper::endpoint const &);
	size_t size ();
	size_t size_sqrt ();
	bool empty ();
	std::mutex mutex;
	paper::endpoint self;
	boost::multi_index_container<
	peer_information,
	boost::multi_index::indexed_by<
	boost::multi_index::hashed_unique<boost::multi_index::member<peer_information, paper::endpoint, &peer_information::endpoint>>,
	boost::multi_index::ordered_non_unique<boost::multi_index::member<peer_information, std::chrono::steady_clock::time_point, &peer_information::last_contact>>,
	boost::multi_index::ordered_non_unique<boost::multi_index::member<peer_information, std::chrono::steady_clock::time_point, &peer_information::last_attempt>, std::greater<std::chrono::steady_clock::time_point>>,
	boost::multi_index::random_access<>,
	boost::multi_index::ordered_non_unique<boost::multi_index::member<peer_information, std::chrono::steady_clock::time_point, &peer_information::last_bootstrap_attempt>>,
	boost::multi_index::ordered_non_unique<boost::multi_index::member<peer_information, std::chrono::steady_clock::time_point, &peer_information::last_rep_request>>,
	boost::multi_index::ordered_non_unique<boost::multi_index::member<peer_information, paper::amount, &peer_information::rep_weight>, std::greater<paper::amount>>>>
	peers;
	boost::multi_index_container<
	peer_attempt,
	boost::multi_index::indexed_by<
	boost::multi_index::hashed_unique<boost::multi_index::member<peer_attempt, paper::endpoint, &peer_attempt::endpoint>>,
	boost::multi_index::ordered_non_unique<boost::multi_index::member<peer_attempt, std::chrono::steady_clock::time_point, &peer_attempt::last_attempt>>>>
	attempts;
	// Called when a new peer is observed
	std::function<void(paper::endpoint const &)> peer_observer;
	std::function<void()> disconnect_observer;
	// Number of peers to crawl for being a rep every period
	static size_t constexpr peers_per_crawl = 8;
};
class send_info
{
public:
	uint8_t const * data;
	size_t size;
	paper::endpoint endpoint;
	std::function<void(boost::system::error_code const &, size_t)> callback;
};
class mapping_protocol
{
public:
	char const * name;
	int remaining;
	boost::asio::ip::address_v4 external_address;
	uint16_t external_port;
};
// These APIs aren't easy to understand so comments are verbose
class port_mapping
{
public:
	port_mapping (paper::node &);
	void start ();
	void stop ();
	void refresh_devices ();
	// Refresh when the lease ends
	void refresh_mapping ();
	// Refresh occasionally in case router loses mapping
	void check_mapping_loop ();
	int check_mapping ();
	bool has_address ();
	std::mutex mutex;
	paper::node & node;
	UPNPDev * devices; // List of all UPnP devices
	UPNPUrls urls; // Something for UPnP
	IGDdatas data; // Some other UPnP thing
	// Primes so they infrequently happen at the same time
	static int constexpr mapping_timeout = paper::paper_network == paper::paper_networks::paper_test_network ? 53 : 3593;
	static int constexpr check_timeout = paper::paper_network == paper::paper_networks::paper_test_network ? 17 : 53;
	boost::asio::ip::address_v4 address;
	std::array<mapping_protocol, 2> protocols;
	uint64_t check_count;
	bool on;
};
class message_statistics
{
public:
	message_statistics ();
	std::atomic<uint64_t> keepalive;
	std::atomic<uint64_t> publish;
	std::atomic<uint64_t> confirm_req;
	std::atomic<uint64_t> confirm_ack;
};
class block_arrival_info
{
public:
	std::chrono::steady_clock::time_point arrival;
	paper::block_hash hash;
};
// This class tracks blocks that are probably live because they arrived in a UDP packet
// This gives a fairly reliable way to differentiate between blocks being inserted via bootstrap or new, live blocks.
class block_arrival
{
public:
	void add (paper::block_hash const &);
	bool recent (paper::block_hash const &);
	boost::multi_index_container<
	paper::block_arrival_info,
	boost::multi_index::indexed_by<
	boost::multi_index::ordered_non_unique<boost::multi_index::member<paper::block_arrival_info, std::chrono::steady_clock::time_point, &paper::block_arrival_info::arrival>>,
	boost::multi_index::hashed_unique<boost::multi_index::member<paper::block_arrival_info, paper::block_hash, &paper::block_arrival_info::hash>>>>
	arrival;
	std::mutex mutex;
};
class network
{
public:
	network (paper::node &, uint16_t);
	void receive ();
	void stop ();
	void receive_action (boost::system::error_code const &, size_t);
	void rpc_action (boost::system::error_code const &, size_t);
	void rebroadcast_reps (std::shared_ptr<paper::block>);
	void republish_vote (std::chrono::steady_clock::time_point const &, std::shared_ptr<paper::vote>);
	void republish_block (MDB_txn *, std::shared_ptr<paper::block>);
	void republish (paper::block_hash const &, std::shared_ptr<std::vector<uint8_t>>, paper::endpoint);
	void publish_broadcast (std::vector<paper::peer_information> &, std::unique_ptr<paper::block>);
	void confirm_send (paper::confirm_ack const &, std::shared_ptr<std::vector<uint8_t>>, paper::endpoint const &);
	void merge_peers (std::array<paper::endpoint, 8> const &);
	void send_keepalive (paper::endpoint const &);
	void broadcast_confirm_req (std::shared_ptr<paper::block>);
	void send_confirm_req (paper::endpoint const &, std::shared_ptr<paper::block>);
	void send_buffer (uint8_t const *, size_t, paper::endpoint const &, std::function<void(boost::system::error_code const &, size_t)>);
	paper::endpoint endpoint ();
	paper::endpoint remote;
	std::array<uint8_t, 512> buffer;
	boost::asio::ip::udp::socket socket;
	std::mutex socket_mutex;
	boost::asio::ip::udp::resolver resolver;
	paper::node & node;
	uint64_t bad_sender_count;
	bool on;
	uint64_t insufficient_work_count;
	uint64_t error_count;
	paper::message_statistics incoming;
	paper::message_statistics outgoing;
	static uint16_t const node_port = paper::paper_network == paper::paper_networks::paper_live_network ? 7075 : 54000;
};
class logging
{
public:
	logging ();
	void serialize_json (boost::property_tree::ptree &) const;
	bool deserialize_json (bool &, boost::property_tree::ptree &);
	bool upgrade_json (unsigned, boost::property_tree::ptree &);
	bool ledger_logging () const;
	bool ledger_duplicate_logging () const;
	bool vote_logging () const;
	bool network_logging () const;
	bool network_message_logging () const;
	bool network_publish_logging () const;
	bool network_packet_logging () const;
	bool network_keepalive_logging () const;
	bool node_lifetime_tracing () const;
	bool insufficient_work_logging () const;
	bool log_rpc () const;
	bool bulk_pull_logging () const;
	bool callback_logging () const;
	bool work_generation_time () const;
	bool log_to_cerr () const;
	void init (boost::filesystem::path const &);

	bool ledger_logging_value;
	bool ledger_duplicate_logging_value;
	bool vote_logging_value;
	bool network_logging_value;
	bool network_message_logging_value;
	bool network_publish_logging_value;
	bool network_packet_logging_value;
	bool network_keepalive_logging_value;
	bool node_lifetime_tracing_value;
	bool insufficient_work_logging_value;
	bool log_rpc_value;
	bool bulk_pull_logging_value;
	bool work_generation_time_value;
	bool log_to_cerr_value;
	bool flush;
	uintmax_t max_size;
	uintmax_t rotation_size;
	boost::log::sources::logger_mt log;
};
class node_init
{
public:
	node_init ();
	bool error ();
	bool block_store_init;
	bool wallet_init;
};
class node_config
{
public:
	node_config ();
	node_config (uint16_t, paper::logging const &);
	void serialize_json (boost::property_tree::ptree &) const;
	bool deserialize_json (bool &, boost::property_tree::ptree &);
	bool upgrade_json (unsigned, boost::property_tree::ptree &);
	paper::account random_representative ();
	uint16_t peering_port;
	paper::logging logging;
	std::vector<std::pair<boost::asio::ip::address, uint16_t>> work_peers;
	std::vector<std::string> preconfigured_peers;
	std::vector<paper::account> preconfigured_representatives;
	unsigned bootstrap_fraction_numerator;
	paper::amount receive_minimum;
	paper::amount inactive_supply;
	unsigned password_fanout;
	unsigned io_threads;
	unsigned work_threads;
	bool enable_voting;
	unsigned bootstrap_connections;
	unsigned bootstrap_connections_max;
	std::string callback_address;
	uint16_t callback_port;
	std::string callback_target;
	int lmdb_max_dbs;
	static std::chrono::seconds constexpr keepalive_period = std::chrono::seconds (60);
	static std::chrono::seconds constexpr keepalive_cutoff = keepalive_period * 5;
	static std::chrono::minutes constexpr wallet_backup_interval = std::chrono::minutes (5);
};
class node_observers
{
public:
	paper::observer_set<std::shared_ptr<paper::block>, paper::account const &, paper::amount const &> blocks;
	paper::observer_set<bool> wallet;
	paper::observer_set<std::shared_ptr<paper::vote>, paper::endpoint const &> vote;
	paper::observer_set<paper::account const &, bool> account_balance;
	paper::observer_set<paper::endpoint const &> endpoint;
	paper::observer_set<> disconnect;
	paper::observer_set<> started;
};
class vote_processor
{
public:
	vote_processor (paper::node &);
	paper::vote_result vote (std::shared_ptr<paper::vote>, paper::endpoint);
	paper::node & node;
};
// The network is crawled for representatives by occasionally sending a unicast confirm_req for a specific block and watching to see if it's acknowledged with a vote.
class rep_crawler
{
public:
	void add (paper::block_hash const &);
	void remove (paper::block_hash const &);
	bool exists (paper::block_hash const &);
	std::mutex mutex;
	std::unordered_set<paper::block_hash> active;
};
class block_processor_item
{
public:
	block_processor_item (std::shared_ptr<paper::block>);
	block_processor_item (std::shared_ptr<paper::block>, bool);
	std::shared_ptr<paper::block> block;
	bool force;
};
// Processing blocks is a potentially long IO operation
// This class isolates block insertion from other operations like servicing network operations
class block_processor
{
public:
	block_processor (paper::node &);
	~block_processor ();
	void stop ();
	void flush ();
	void add (paper::block_processor_item const &);
	void process_receive_many (paper::block_processor_item const &);
	void process_receive_many (std::deque<paper::block_processor_item> &);
	paper::process_return process_receive_one (MDB_txn *, std::shared_ptr<paper::block>);
	void process_blocks ();

private:
	bool stopped;
	bool idle;
	std::deque<paper::block_processor_item> blocks;
	std::mutex mutex;
	std::condition_variable condition;
	paper::node & node;
};
class node : public std::enable_shared_from_this<paper::node>
{
public:
	node (paper::node_init &, boost::asio::io_service &, uint16_t, boost::filesystem::path const &, paper::alarm &, paper::logging const &, paper::work_pool &);
	node (paper::node_init &, boost::asio::io_service &, boost::filesystem::path const &, paper::alarm &, paper::node_config const &, paper::work_pool &);
	~node ();
	template <typename T>
	void background (T action_a)
	{
		alarm.service.post (action_a);
	}
	void send_keepalive (paper::endpoint const &);
	bool copy_with_compaction (boost::filesystem::path const &);
	void keepalive (std::string const &, uint16_t);
	void start ();
	void stop ();
	std::shared_ptr<paper::node> shared ();
	int store_version ();
	void process_confirmed (std::shared_ptr<paper::block>);
	void process_message (paper::message &, paper::endpoint const &);
	void process_active (std::shared_ptr<paper::block>);
	paper::process_return process (paper::block const &);
	void keepalive_preconfigured (std::vector<std::string> const &);
	paper::block_hash latest (paper::account const &);
	paper::uint128_t balance (paper::account const &);
	std::unique_ptr<paper::block> block (paper::block_hash const &);
	std::pair<paper::uint128_t, paper::uint128_t> balance_pending (paper::account const &);
	paper::uint128_t weight (paper::account const &);
	paper::account representative (paper::account const &);
	void ongoing_keepalive ();
	void ongoing_rep_crawl ();
	void ongoing_bootstrap ();
	void ongoing_store_flush ();
	void backup_wallet ();
	int price (paper::uint128_t const &, int);
	void generate_work (paper::block &);
	uint64_t generate_work (paper::uint256_union const &);
	void generate_work (paper::uint256_union const &, std::function<void(uint64_t)>);
	void add_initial_peers ();
	boost::asio::io_service & service;
	paper::node_config config;
	paper::alarm & alarm;
	paper::work_pool & work;
	boost::log::sources::logger_mt log;
	paper::block_store store;
	paper::gap_cache gap_cache;
	paper::ledger ledger;
	paper::active_transactions active;
	paper::network network;
	paper::bootstrap_initiator bootstrap_initiator;
	paper::bootstrap_listener bootstrap;
	paper::peer_container peers;
	boost::filesystem::path application_path;
	paper::node_observers observers;
	paper::wallets wallets;
	paper::port_mapping port_mapping;
	paper::vote_processor vote_processor;
	paper::rep_crawler rep_crawler;
	unsigned warmed_up;
	paper::block_processor block_processor;
	std::thread block_processor_thread;
	paper::block_arrival block_arrival;
	static double constexpr price_max = 16.0;
	static double constexpr free_cutoff = 1024.0;
	static std::chrono::seconds constexpr period = std::chrono::seconds (60);
	static std::chrono::seconds constexpr cutoff = period * 5;
	static std::chrono::minutes constexpr backup_interval = std::chrono::minutes (5);
};
class thread_runner
{
public:
	thread_runner (boost::asio::io_service &, unsigned);
	~thread_runner ();
	void join ();
	std::vector<std::thread> threads;
};
void add_node_options (boost::program_options::options_description &);
bool handle_node_options (boost::program_options::variables_map &);
class inactive_node
{
public:
	inactive_node (boost::filesystem::path const & path = paper::working_path ());
	~inactive_node ();
	boost::filesystem::path path;
	boost::shared_ptr<boost::asio::io_service> service;
	paper::alarm alarm;
	paper::logging logging;
	paper::node_init init;
	paper::work_pool work;
	std::shared_ptr<paper::node> node;
};
}

ext: hpp

max_stars_repo_name: williamstarkro/paper

max_issues_repo_name: williamstarkro/paper

max_forks_repo_name: williamstarkro/paper


text:
/**
 This homework problem consists of reading a simple, gmesh generated, mesh on
 the unit square and solving a simple reaction diffusion system using LehrFEM++
 */

#include "linfereactdiff.h"

#include <lf/assemble/assemble.h>
#include <lf/base/base.h>
#include <lf/fe/fe.h>
#include <lf/geometry/geometry.h>
#include <lf/io/io.h>
#include <lf/mesh/hybrid2d/hybrid2d.h>
#include <lf/mesh/mesh.h>
#include <lf/mesh/utils/utils.h>
#include <lf/refinement/refinement.h>
#include <lf/uscalfe/uscalfe.h>

#include <Eigen/Core>
#include <Eigen/SparseCore>
#include <Eigen/SparseLU>
#include <cmath>
#include <memory>
#include <utility>

namespace LinFeReactDiff {

/**
 * @brief generate hierarchy of meshes
 * @param levels: number of refinement steps
 */

std::shared_ptr<lf::refinement::MeshHierarchy> generateMeshHierarchy(
    const lf::base::size_type levels) {
  auto mesh_factory = std::make_unique<lf::mesh::hybrid2d::MeshFactory>(2);
  lf::io::GmshReader reader(std::move(mesh_factory),
                            CURRENT_SOURCE_DIR "/../meshes/square.msh");
  auto mesh = reader.mesh();

  std::shared_ptr<lf::refinement::MeshHierarchy> multi_mesh_p =
      lf::refinement::GenerateMeshHierarchyByUniformRefinemnt(mesh, levels);

  return multi_mesh_p;
}

/**
 * @brief solve the linear variational problem
 *        int_{\Omgea} grad(u)grad(v) dx = \int_{\Omgea} cv dx for all v
 *        with 0 Dirichlet boundary condition.
 * @param mesh: mesh discretization of computational Domain \Omega
 */
Eigen::VectorXd solveFE(std::shared_ptr<const lf::mesh::Mesh> mesh) {
  // Initialize mesh functions for solving the BVP:
  // \int_{\Omega} grad(u)grad(v) + uv dx = \_int(\Omega}cv dx
  // with Dirichlet boundary conditions fixed to 0.
  // used for the boundary conditions
  auto zero = [](Eigen::Vector2d x) -> double { return 0.; };
  lf::mesh::utils::MeshFunctionGlobal mf_zero{zero};

  // used for the Galerkin Matrix
  auto identity = [](Eigen::Vector2d x) -> double { return 1.; };
  lf::mesh::utils::MeshFunctionGlobal mf_identity{identity};

  // used for the load vector
  auto c = [](Eigen::Vector2d x) -> double { return x[0] * x[1]; };
  lf::mesh::utils::MeshFunctionGlobal mf_c{c};

  auto fe_space =
      std::make_shared<lf::uscalfe::FeSpaceLagrangeO1<double>>(mesh);
  const lf::mesh::Mesh &mesh_p{*(fe_space->Mesh())};

  // Initialize dof handler
  const lf::assemble::DofHandler &dofh{fe_space->LocGlobMap()};

  const lf::base::size_type N_dofs(dofh.NumDofs());

  // Set up Galerkin Matrix
  lf::assemble::COOMatrix<double> A(N_dofs, N_dofs);

  // Populate Galerkin Matrix
  lf::uscalfe::ReactionDiffusionElementMatrixProvider<
      double, decltype(mf_identity), decltype(mf_zero)>
      elmat_builder(fe_space, mf_identity, mf_zero);

  lf::assemble::AssembleMatrixLocally(0, dofh, dofh, elmat_builder, A);

  // Set up load vector
  Eigen::Matrix<double, Eigen::Dynamic, 1> phi(N_dofs);
  phi.setZero();

  lf::uscalfe::ScalarLoadElementVectorProvider<double, decltype(mf_c)>
      elvec_builder(fe_space, mf_c);

  AssembleVectorLocally(0, dofh, elvec_builder, phi);

  const lf::fe::ScalarReferenceFiniteElement<double> *rsf_edge_p =
      fe_space->ShapeFunctionLayout(lf::base::RefEl::kSegment());
  LF_ASSERT_MSG(rsf_edge_p != nullptr, "FE specification for edges missing");

  // Fetch flags and values for degrees of freedom located on Dirichlet
  // edges.
  auto bd_flags{lf::mesh::utils::flagEntitiesOnBoundary(fe_space->Mesh(), 1)};
  auto ess_bdc_flags_values_findest{lf::fe::InitEssentialConditionFromFunction(
      *fe_space,
      [&bd_flags](const lf::mesh::Entity &edge) -> bool {
        return bd_flags(edge);
      },
      mf_zero)};

  // Eliminate Dirichlet dofs from linear system
  lf::assemble::FixFlaggedSolutionComponents<double>(
      [&ess_bdc_flags_values_findest](lf::assemble::glb_idx_t gdof_idx) {
        return ess_bdc_flags_values_findest[gdof_idx];
      },
      A, phi);

  // Solve System
  Eigen::VectorXd mu;
  Eigen::SparseMatrix<double> A_crs = A.makeSparse();
  Eigen::SparseLU<Eigen::SparseMatrix<double>> solver;
  solver.compute(A_crs);
  mu = solver.solve(phi);
  return mu;
}

double computeEnergy(std::shared_ptr<const lf::mesh::Mesh> mesh,
                     Eigen::VectorXd mu) {
  auto fe_space =
      std::make_shared<lf::uscalfe::FeSpaceLagrangeO1<double>>(mesh);

  const lf::assemble::DofHandler &dofh{fe_space->LocGlobMap()};

  const lf::base::size_type N_dofs(dofh.NumDofs());

  auto identity = [](Eigen::Vector2d x) -> double { return 1.; };
  lf::mesh::utils::MeshFunctionGlobal mf_identity{identity};

  auto zero = [](Eigen::Vector2d x) -> double { return 0.; };
  lf::mesh::utils::MeshFunctionGlobal mf_zero{zero};

  // Matrix in triplet format holding Stiffness matrix.
  lf::assemble::COOMatrix<double> Stiffness(N_dofs, N_dofs);
  // Assemble Stiffness matrix for \int_{\Omega} uv dx
  lf::uscalfe::ReactionDiffusionElementMatrixProvider<
      double, decltype(mf_identity), decltype(mf_zero)>
      stiffness_mat_builder(fe_space, mf_identity, mf_zero);
  lf::assemble::AssembleMatrixLocally(0, dofh, dofh, stiffness_mat_builder,
                                      Stiffness);

  Eigen::SparseMatrix<double> Stiffness_crs = Stiffness.makeSparse();

  // Matrix in triplet format holding Mass matrix.
  lf::assemble::COOMatrix<double> Mass(N_dofs, N_dofs);
  // Assemble Mass matrix for \int_{\Omega} uv dx
  lf::uscalfe::ReactionDiffusionElementMatrixProvider<double, decltype(mf_zero),
                                                      decltype(mf_identity)>
      mass_mat_builder(fe_space, mf_zero, mf_identity);
  lf::assemble::AssembleMatrixLocally(0, dofh, dofh, mass_mat_builder, Mass);
  Eigen::SparseMatrix<double> Mass_crs = Mass.makeSparse();
  double energy_stiffness_sq;
  double energy_mass_sq;
  // energy_stiffness_sq = 1' A 1
  // energy_mass_sq = \mu' M \mu

  energy_stiffness_sq =
      Eigen::VectorXd::Constant(N_dofs, 1.0).transpose() *
      (Stiffness_crs * Eigen::VectorXd::Constant(N_dofs, 1.0));
  energy_mass_sq = mu.transpose() * Mass_crs * mu;

  return std::sqrt(energy_stiffness_sq + energy_mass_sq);
}

}  // namespace LinFeReactDiff

ext: cc


text:
// Copyright (c) 2011 by Raytheon BBN Technologies Corp.
// All Rights Reserved.

#include "Generic/common/leak_detection.h"
#include "Generic/PropTree/expanders/PropTreeExpander.h"
#include "Generic/PropTree/DocPropForest.h"
#include "Generic/PropTree/PropNode.h"
#include <boost/foreach.hpp>

void PropTreeExpander::expandForest(DocPropForest& docForest) const {
	PropNodes allNodes;

	BOOST_FOREACH (PropNodes_ptr & sentenceRoots, docForest) {
		PropNodes sentenceNodes;
		PropNode::enumAllNodes(*sentenceRoots, sentenceNodes);
		allNodes.insert(allNodes.begin(), sentenceNodes.begin(), sentenceNodes.end());
	}

	expand(allNodes);
}

ext: cpp

max_stars_repo_name: BBN-E/serif

max_issues_repo_name: BBN-E/serif

max_forks_repo_name: BBN-E/serif


text:
//
// Variable for Scheme
//
// Author: Zhang Zhenghao (zhangzhenghao@hotmail.com)
//
#include <boost/multiprecision/cpp_int.hpp>
#include "variable.hpp"

#ifdef STATS
#include "statistic.hpp"
#endif

// Constant values
const Variable VAR_NULL		= Variable();
const Variable VAR_VOID		= Variable();
const Variable VAR_TRUE		= Variable();
const Variable VAR_FALSE	= Variable();

using namespace std;
using namespace boost::multiprecision;

// Parser
extern int yyparse(std::istream* in, std::ostream* out = 0);
extern Variable yypval;

// Constructors

// Constructor for special
Variable::Variable(): type(TYPE_SPEC), refCount(new int(1))
{
	#ifdef STATS
	Statistic::createVariable();
	#endif
}

// Constructor for rational
Variable::Variable(const cpp_rational& rational):
	type(TYPE_RATIONAL), refCount(new int(1)), rationalPtr(new cpp_rational(rational))
{
	#ifdef STATS
	Statistic::createVariable();
	#endif
}

// Constructor for double
Variable::Variable(double value):
	type(TYPE_FLOAT), refCount(new int(1)), doublePtr(new double(value))
{
	#ifdef STATS
	Statistic::createVariable();
	#endif
}

// Constructor for rational, double, string and symbol
Variable::Variable(const string &str, Type type): type(type), refCount(new int(1))
{
	switch (type) {
		// Convert string to rational
		case TYPE_RATIONAL:
			rationalPtr = new cpp_rational(str);
			break;
		// Convert string to double
		case TYPE_FLOAT:
			doublePtr = new double(stod(str));
			break;
		case TYPE_SYMBOL:
		case TYPE_STRING:
			stringPtr = new string(str);
			break;
		default:
			throw Exception("intern error: variable construction error");
	}
	#ifdef STATS
	Statistic::createVariable();
	#endif
}

// Constructor for primitive procedure
Variable::Variable(const string& name, const function& func):
	type(TYPE_PRIM), refCount(new int(1)), primPtr(new Primitive(name, func))
{
	#ifdef STATS
	Statistic::createVariable();
	#endif
}

// Constructor for compound procedure
Variable::Variable(const string& name, const Variable& args, const Variable& body, const Environment& env):
	type(TYPE_COMP), refCount(new int(1)), compPtr(new Compound(name, args, body, env))
{
	GarbageCollector::trace(*this);
	#ifdef STATS
	Statistic::createVariable();
	#endif
}

// Constructor for pairs
Variable::Variable(const Variable& lhs, const Variable& rhs):
	type(TYPE_PAIR), refCount(new int(1)), pairPtr(new pair(lhs, rhs))
{
	GarbageCollector::trace(*this);
	#ifdef STATS
	Statistic::createVariable();
	#endif
}

// Copy constructor
Variable::Variable(const Variable& var):
	type(var.type), refCount(var.refCount), voidPtr(var.voidPtr), GarbageObject(var)
{
	#ifdef STATS
	Statistic::copyVariable();
	#endif
	// Increase reference count
	(*refCount)++;
}

// Destructor
Variable::~Variable() {
	// Decrease reference count
	(*refCount)--;
	if (*refCount > 0)
		return;
	// Free memory
	delete refCount;
	switch (type) {
		case TYPE_RATIONAL:
			delete rationalPtr;
			break;
		case TYPE_FLOAT:
			delete doublePtr;
			break;
		case TYPE_STRING:
		case TYPE_SYMBOL:
			delete stringPtr;
			break;
		case TYPE_PAIR:
			delete pairPtr;
			break;
		case TYPE_PRIM:
			delete primPtr;
			break;
		case TYPE_COMP:
			delete compPtr;
			break;
		default:
			;
	}
	#ifdef STATS
	Statistic::destroyVariable();
	#endif
}

// Assignment
Variable& Variable::operator=(Variable var)
{
	swap(*this, var);
	return *this;
}

// Swap two variables
void swap(Variable& lhs, Variable& rhs)
{
	std::swap(static_cast<GarbageObject&>(lhs), static_cast<GarbageObject&>(rhs));
	std::swap(lhs.type, rhs.type);
	std::swap(lhs.voidPtr, rhs.voidPtr);
	std::swap(lhs.refCount, rhs.refCount);
}

// Standard I/0

ostream& operator<<(ostream& out, const Variable& var)
{
	// List
	if (var == VAR_NULL || var.type == Variable::TYPE_PAIR) {
		out << '(';
		Variable it = var;
		bool empty = true;
		while (it.isPair()) {
			if (empty)
				empty = false;
			else
				out << ' ';
			out << it.car();
			it = it.cdr();
		}
		if (it != VAR_NULL)
			out << " . " << it;
		out << ')';
		return out;
	}
	// Single item
	switch (var.type) {
		case Variable::TYPE_SPEC:
			if (var == VAR_TRUE)
				out << "#t";
			else if (var == VAR_FALSE)
				out << "#f";
			break;
		case Variable::TYPE_RATIONAL:
			out << *(var.rationalPtr);
			break;
		case Variable::TYPE_FLOAT:
			out << *(var.doublePtr);
			break;
		case Variable::TYPE_STRING:
			out << *(var.stringPtr);
			break;
		case Variable::TYPE_SYMBOL:
			out << *(var.stringPtr);
			break;
		case Variable::TYPE_PRIM:
		case Variable::TYPE_COMP:
			out << "#<procedure:" + var.getProcedureName() + ">";
			break;
		default:
			;
	}
	return out;
}

istream& operator>>(istream& in, Variable& var)
{
	yyparse(&in);
	var = yypval;
	return in;
}

// Require type

void Variable::requireType(const string &caller, Type type) const
{
	if (this->type & type)
		return;
	switch (type) {
		case TYPE_INTEGER:
			if (isInteger())
				return;
			break;
		default:
			;
	}
	throw Exception(caller + ": contract violation\n"
		+ "\texpected: " + getTypeName(type) + "\n"
		+ "\tgiven: " + this->toString());
}

// Get type name

string Variable::getTypeName(Type type)
{
	switch (type) {
		case TYPE_FLOAT:
			return "double";
		case TYPE_RATIONAL:
			return "rational";
		case TYPE_NUMBER:
			return "number";
		case TYPE_PAIR:
			return "pair";
		case TYPE_STRING:
			return "string";
		case TYPE_SYMBOL:
			return "symbol";
		case TYPE_PRIM:
			return "primitive";
		case TYPE_COMP:
			return "compound";
		case TYPE_PROCEDURE:
			return "procedure";
		case TYPE_INTEGER:
			return "integer";
		default:
			return "<unkown>";
	}
}

// Convert operations

string Variable::toString() const
{
	ostringstream out;
	out << (*this);
	return out.str();
}

double Variable::toDouble() const
{
	requireType("convert to double", TYPE_NUMBER);
	if (type == TYPE_RATIONAL)
		return static_cast<double>(*rationalPtr);
	return *doublePtr;
}

// Check operations

bool Variable::isNull() const
{
	return refCount == VAR_NULL.refCount;
}

bool Variable::isVoid() const
{
	return refCount == VAR_VOID.refCount;
}

bool Variable::isPair() const
{
	return type == TYPE_PAIR;
}

bool Variable::isNumber() const
{
	return type & (TYPE_NUMBER);
}

bool Variable::isInteger() const
{
	return type == TYPE_RATIONAL &&
		denominator(*rationalPtr) == 1;
}

bool Variable::isSymbol() const
{
	return type == TYPE_SYMBOL;
}

bool Variable::isString() const
{
	return type == TYPE_STRING;
}

bool Variable::isPrim() const
{
	return type == TYPE_PRIM;
}

bool Variable::isComp() const
{
	return type == TYPE_COMP;
}

bool Variable::isProcedure() const
{
	return type & (TYPE_COMP | TYPE_PRIM);
}

// Arithmetic operations

Variable operator+(const Variable& lhs, const Variable& rhs)
{
	lhs.requireType("+", Variable::TYPE_NUMBER);
	rhs.requireType("+", Variable::TYPE_NUMBER);
	switch (lhs.type | rhs.type) {
		case Variable::TYPE_FLOAT:
			return Variable(*lhs.doublePtr + *rhs.doublePtr);
		case Variable::TYPE_RATIONAL:
			return Variable(*lhs.rationalPtr + *rhs.rationalPtr);
		default:
			return Variable(lhs.toDouble() + rhs.toDouble());
	}
}

Variable operator-(const Variable& lhs, const Variable& rhs)
{
	lhs.requireType("-", Variable::TYPE_NUMBER);
	rhs.requireType("-", Variable::TYPE_NUMBER);
	switch (lhs.type | rhs.type) {
		case Variable::TYPE_FLOAT:
			return Variable(*lhs.doublePtr - *rhs.doublePtr);
		case Variable::TYPE_RATIONAL:
			return Variable(*lhs.rationalPtr - *rhs.rationalPtr);
		default:
			return Variable(lhs.toDouble() - rhs.toDouble());
	}
}

Variable operator*(const Variable& lhs, const Variable& rhs)
{
	lhs.requireType("*", Variable::TYPE_NUMBER);
	rhs.requireType("*", Variable::TYPE_NUMBER);
	switch (lhs.type | rhs.type) {
		case Variable::TYPE_FLOAT:
			return Variable(*lhs.doublePtr * *rhs.doublePtr);
		case Variable::TYPE_RATIONAL:
			return Variable(*lhs.rationalPtr * *rhs.rationalPtr);
		default:
			return Variable(lhs.toDouble() * rhs.toDouble());
	}
}

Variable operator/(const Variable& lhs, const Variable& rhs)
{
	lhs.requireType("/", Variable::TYPE_NUMBER);
	rhs.requireType("/", Variable::TYPE_NUMBER);
	switch (lhs.type | rhs.type) {
		case Variable::TYPE_FLOAT:
			if (*rhs.doublePtr == 0)
				throw Exception("/: division by zero");
			return Variable(*lhs.doublePtr / *rhs.doublePtr);
		case Variable::TYPE_RATIONAL:
			if (*rhs.rationalPtr == 0)
				throw Exception("/: division by zero");
			return Variable(*lhs.rationalPtr / *rhs.rationalPtr);
		default:
			double a = lhs.toDouble();
			double b = rhs.toDouble();
			if (b == 0)
				throw Exception("/: division by zero");
			return Variable(a / b);
	}
}

Variable operator-(const Variable& var)
{
	var.requireType("-", Variable::TYPE_NUMBER);
	if (var.type == Variable::TYPE_FLOAT)
		return Variable(- *var.doublePtr);
	return Variable(- *var.rationalPtr);
}

Variable remainder(const Variable& lhs, const Variable& rhs)
{
	lhs.requireType("remainder", Variable::TYPE_INTEGER);
	rhs.requireType("remainder", Variable::TYPE_INTEGER);
	const cpp_int& a = numerator(*lhs.rationalPtr);
	const cpp_int& b = numerator(*rhs.rationalPtr);
	return Variable(cpp_rational(a%b));
}

Variable quotient(const Variable& lhs, const Variable& rhs)
{
	lhs.requireType("quotient", Variable::TYPE_INTEGER);
	rhs.requireType("quotient", Variable::TYPE_INTEGER);
	const cpp_int& a = numerator(*lhs.rationalPtr);
	const cpp_int& b = numerator(*rhs.rationalPtr);
	return Variable(cpp_rational(a/b));
}

Variable gcd(const Variable& lhs, const Variable& rhs)
{
	lhs.requireType("gcd", Variable::TYPE_INTEGER);
	rhs.requireType("gcd", Variable::TYPE_INTEGER);
	cpp_int a = numerator(*lhs.rationalPtr);
	cpp_int b = numerator(*rhs.rationalPtr);
	while (b) {
		cpp_int temp = a;
		a = b;
		b = temp % b;
	}
	return Variable(cpp_rational(a));
}

bool Variable::isEven() const
{
	requireType("remainder", Variable::TYPE_INTEGER);
	const cpp_int& a = numerator(*rationalPtr);
	return a % 2 == 0;
}

bool Variable::isOdd() const
{
	requireType("remainder", Variable::TYPE_INTEGER);
	const cpp_int& a = numerator(*rationalPtr);
	return a % 2 == 1;
}

// Compare operations

bool operator<(const Variable& lhs, const Variable& rhs)
{
	lhs.requireType("<", Variable::TYPE_NUMBER);
	rhs.requireType("<", Variable::TYPE_NUMBER);
	switch (lhs.type | rhs.type) {
		case Variable::TYPE_FLOAT:
			return *lhs.doublePtr < *rhs.doublePtr;
		case Variable::TYPE_RATIONAL:
			return *lhs.rationalPtr < *rhs.rationalPtr;
		default:
			return lhs.toDouble() < rhs.toDouble();
	}
}

bool operator>(const Variable& lhs, const Variable& rhs)
{
	lhs.requireType(">", Variable::TYPE_NUMBER);
	rhs.requireType(">", Variable::TYPE_NUMBER);
	switch (lhs.type | rhs.type) {
		case Variable::TYPE_FLOAT:
			return *lhs.doublePtr > *rhs.doublePtr;
		case Variable::TYPE_RATIONAL:
			return *lhs.rationalPtr > *rhs.rationalPtr;
		default:
			return lhs.toDouble() > rhs.toDouble();
	}
}

bool operator<=(const Variable& lhs, const Variable& rhs)
{
	lhs.requireType("<=", Variable::TYPE_NUMBER);
	rhs.requireType("<=", Variable::TYPE_NUMBER);
	switch (lhs.type | rhs.type) {
		case Variable::TYPE_FLOAT:
			return *lhs.doublePtr <= *rhs.doublePtr;
		case Variable::TYPE_RATIONAL:
			return *lhs.rationalPtr <= *rhs.rationalPtr;
		default:
			return lhs.toDouble() <= rhs.toDouble();
	}
}

bool operator>=(const Variable& lhs, const Variable& rhs)
{
	lhs.requireType(">=", Variable::TYPE_NUMBER);
	rhs.requireType(">=", Variable::TYPE_NUMBER);
	switch (lhs.type | rhs.type) {
		case Variable::TYPE_FLOAT:
			return *lhs.doublePtr >= *rhs.doublePtr;
		case Variable::TYPE_RATIONAL:
			return *lhs.rationalPtr >= *rhs.rationalPtr;
		default:
			return lhs.toDouble() >= rhs.toDouble();
	}
}

bool operator==(const Variable &lhs, const Variable &rhs)
{
	// Self compare
	if (lhs.refCount == rhs.refCount)
		return true;
	// Different type
	if (lhs.type != rhs.type)
		return false;
	switch (lhs.type) {
		case Variable::TYPE_FLOAT:
			return *lhs.doublePtr == *rhs.doublePtr;
		case Variable::TYPE_RATIONAL:
			return *lhs.rationalPtr == *rhs.rationalPtr;
		case Variable::TYPE_STRING:
		case Variable::TYPE_SYMBOL:
			return *lhs.stringPtr == *rhs.stringPtr;
		case Variable::TYPE_PAIR:
			return lhs.car() == rhs.car()
					&& lhs.cdr() == rhs.cdr();
		default:
			return false;
	}
}

bool operator!=(const Variable& lhs, const Variable& rhs)
{
	return !(lhs == rhs);
}

// Pair operations

Variable& Variable::car() const
{
	requireType("car", Variable::TYPE_PAIR);
	return pairPtr->first;
}

Variable& Variable::cdr() const
{
	requireType("cdr", Variable::TYPE_PAIR);
	return pairPtr->second;
}

Variable Variable::setCar(const Variable& var) const
{
	requireType("set-car!", Variable::TYPE_PAIR);
	pairPtr->first = var;
	return VAR_VOID;
}

Variable Variable::setCdr(const Variable& var) const
{
	requireType("set-cdr!", Variable::TYPE_PAIR);
	pairPtr->second = var;
	return VAR_VOID;
}

// Procedure operations

Variable Variable::operator()(const Variable& arg, Environment &env) const
{
	requireType("apply primitive procedure", TYPE_PRIM);
	return primPtr->func(arg, env);
}

Variable& Variable::getProcedureArgs() const
{
	requireType("get procedure args", TYPE_COMP);
	return compPtr->args;
}

Variable& Variable::getProcedureBody() const
{
	requireType("get procedure body", TYPE_COMP);
	return compPtr->body;
}

string Variable::getProcedureName() const
{
	requireType("get procedure name", TYPE_PROCEDURE);
	if (type == Variable::TYPE_PRIM)
		return primPtr->name;
	return compPtr->name;
}

Environment Variable::getProcedureEnv() const
{
	requireType("get procedure env", TYPE_COMP);
	return compPtr->env;
}

// Optimization: constant pool

std::unordered_map<std::string, Variable> Variable::pool;

Variable Variable::createSymbol(const std::string& str)
{
	if (pool.find(str) == pool.end())
		pool[str] = Variable(str, Variable::TYPE_SYMBOL);
	return pool[str];
}

// Optimization: garbage collection

void Variable::finalize() const
{
	switch (type) {
		case TYPE_PAIR:
			pairPtr->first = VAR_NULL;
			pairPtr->second = VAR_NULL;
			break;
		case TYPE_COMP:
			compPtr->args = VAR_NULL;
			compPtr->body = VAR_NULL;
			compPtr->env = Environment();
		default:
			;
	};
}

void Variable::scan(int tag) const
{
	switch (type) {
		case TYPE_PAIR:
			*gcTag = tag;
			if (*pairPtr->first.gcTag != tag)
				pairPtr->first.scan(tag);
			if (*pairPtr->second.gcTag != tag)
				pairPtr->second.scan(tag);
			break;
		case TYPE_COMP:
			*gcTag = tag;
			if (*compPtr->args.gcTag != tag)
				compPtr->args.scan(tag);
			if (*compPtr->body.gcTag != tag)
				compPtr->body.scan(tag);
			if (*compPtr->env.gcTag != tag)
				compPtr->env.scan(tag);
			break;
		default:
			;
	}
}

max_stars_repo_name: ZhangZhenghao/SimpleScheme

max_issues_repo_name: ZhangZhenghao/SimpleScheme

max_forks_repo_name: ZhangZhenghao/SimpleScheme


text:
/*
* Created by Mark Johnson on 3/3/2018.
*/

#ifndef VEHO_SAM3X_HPP
#define VEHO_SAM3X_HPP

#include <cstddef>
#include <utility>

#include <boost/mp11/list.hpp>

#include <veho/frame.hpp>
#include <veho/listener_policies.hpp>
#include <veho/bus_template_builder.hpp>
#include <veho/bus_constructor.hpp>

#include <veho/controller/controller_traits.hpp>
#include <veho/controller/capabilities.hpp>

namespace sam3x {
    struct rev_8e {
        std::size_t callback_count;
        std::size_t transmitter_count;
    };
}

namespace veho {
    namespace controller {
        template <>
        struct controller_traits<sam3x::rev_8e> {
            constexpr const static std::size_t num_mailboxes = 8;

            using capabilities = boost::mp11::mp_list<
                    veho::controller::transmit_capability,
                    veho::controller::receive_capability
            >;

            using execution_policies = boost::mp11::mp_list<
                    veho::listener_policies::launch::enqueue,
                    veho::listener_policies::launch::realtime
            >;
        };
    }

    template <>
    struct frame_extensions<sam3x::rev_8e> {
        using timestamp_type = uint16_t;
        using family_id_type = uint32_t;

        timestamp_type timestamp;
        family_id_type family_id;
    };

    template <typename Config>
    struct builder_extensions<Config, sam3x::rev_8e> {
        using updated_config_for_timestamping_type = Config;

        constexpr inline bus_template_builder<updated_config_for_timestamping_type> record_timestamps() {
            return bus_template_builder<updated_config_for_timestamping_type>(std::move(
                    const_cast<bus_template_builder<updated_config_for_timestamping_type>*>(
                            static_cast<const bus_template_builder<updated_config_for_timestamping_type>*>(
                                    this))->config
            ));
        }
    };

    template <typename CompiletimeConfig, typename RuntimeConfig>
    struct bus_constructor<CompiletimeConfig, RuntimeConfig, sam3x::rev_8e> {
        using bus_type = sam3x::rev_8e;

        static bus_type construct(CompiletimeConfig&& compiletime_config, RuntimeConfig&& runtime_config) {
            std::size_t callback_count = 0, transmitter_count = 0;

            if (compiletime_config.template has_capability<controller::receive_capability>()) {
                auto receiver_data = compiletime_config.template capability_data_for<controller::receive_capability>();
                auto callbacks = receiver_data.callbacks;
                callback_count = boost::mp11::mp_size<decltype(callbacks)>::value;

                auto deps = runtime_config.template capability_data_for<controller::receive_capability>().dependency_set;
            }

            if (compiletime_config.template has_capability<controller::transmit_capability>()) {
                auto transmitter_data = compiletime_config.template capability_data_for<controller::transmit_capability>();
                transmitter_count = transmitter_data.num_transmitters;
            }

            return bus_type{callback_count, transmitter_count};
        }
    };
}

#endif //VEHO_SAM3X_HPP

max_issues_repo_name: notfoundry/veho

max_forks_repo_name: notfoundry/veho


text:
//==============================================================================
//         Copyright 2003 - 2011   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2011   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef NT2_TOOLBOX_TRIGONOMETRIC_CONSTANTS_INV2PI_HPP_INCLUDED
#define NT2_TOOLBOX_TRIGONOMETRIC_CONSTANTS_INV2PI_HPP_INCLUDED
/*!
 * \file
**/
#include <boost/simd/sdk/constant/constant.hpp>
#include <boost/simd/sdk/constant/register.hpp>

/*!
 * \ingroup trigo_constant
 * \defgroup trigo_constant_inv2pi Inv2pi 0.15915494309189533576888376337251
 *
 * \par Description
 * Constant Inv2pi : \f$\frac1\pi\f$.
 *
 * \par Header file
 *
 * \code
 * #include <nt2/include/functions/inv2pi.hpp>
 * \endcode
 *
 *
 * \synopsis
 *
 * \code
 * namespace boost::simd
 * {
 *   template <class T,class A0>
 *     meta::call<tag::_inv2pi_(A0)>::type
 *     Inv2pi();
 * }
 * \endcode
 *
 *
 * \param T template parameter of Inv2pi
 *
 * \return type T value
 *
 *
**/

namespace nt2
{
  namespace tag
  {
    BOOST_SIMD_CONSTANT_REGISTER( Inv2pi, double
                                  , 0, 0x3e22f983
                                  , 0x3fc45f306dc9c883ll
                                  );
  }

  BOOST_SIMD_CONSTANT_IMPLEMENTATION(tag::Inv2pi, Inv2pi);
}

#endif


text:
/*
 *  Copyright 2011-2015 Maxim Milakov
 *
 *  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 "distort_2d_data_sampler_transformer.h"

#include "neural_network_exception.h"
#include "data_transformer_util.h"

#include <opencv2/core/core.hpp>
#include <boost/format.hpp>
#include <cstring>

namespace nnforge
{
	distort_2d_data_sampler_transformer::distort_2d_data_sampler_transformer(
		const std::vector<distort_2d_data_sampler_param>& params,
		unsigned char border_value)
		: params(params)
		, border_value(border_value)
	{
	}

	distort_2d_data_sampler_transformer::distort_2d_data_sampler_transformer(
		const std::vector<float>& rotation_angle_in_degrees_list,
		const std::vector<float>& scale_list,
		const std::vector<float>& shift_right_x_list,
		const std::vector<float>& shift_down_y_list,
		const std::vector<std::pair<float, float> >& stretch_factor_and_angle_list,
		const std::vector<std::pair<float, float> >& perspective_distance_and_angle_list,
		unsigned char border_value)
		: border_value(border_value)
	{
		for(std::vector<float>::const_iterator it1 = rotation_angle_in_degrees_list.begin(); it1 != rotation_angle_in_degrees_list.end(); ++it1)
			for(std::vector<float>::const_iterator it2 = scale_list.begin(); it2 != scale_list.end(); ++it2)
				for(std::vector<float>::const_iterator it3 = shift_right_x_list.begin(); it3 != shift_right_x_list.end(); ++it3)
					for(std::vector<float>::const_iterator it4 = shift_down_y_list.begin(); it4 != shift_down_y_list.end(); ++it4)
						for(std::vector<std::pair<float, float> >::const_iterator it5 = stretch_factor_and_angle_list.begin(); it5 != stretch_factor_and_angle_list.end(); ++it5)
							for(std::vector<std::pair<float, float> >::const_iterator it6 = perspective_distance_and_angle_list.begin(); it6 != perspective_distance_and_angle_list.end(); ++it6)
							{
								distort_2d_data_sampler_param new_item;
								new_item.rotation_angle_in_degrees = *it1;
								new_item.scale = *it2;
								new_item.shift_right_x = *it3;
								new_item.shift_down_y = *it4;
								new_item.stretch_factor_and_angle = *it5;
								new_item.perspective_distance_and_angle = *it6;
								params.push_back(new_item);
							}
	}

	distort_2d_data_sampler_transformer::~distort_2d_data_sampler_transformer()
	{
	}

	void distort_2d_data_sampler_transformer::transform(
		const void * data,
		void * data_transformed,
		neuron_data_type::input_type type,
		const layer_configuration_specific& original_config,
		unsigned int sample_id)
	{
		if (type != neuron_data_type::type_byte)
			throw neural_network_exception("distort_2d_data_sampler_transformer is implemented for data stored as bytes only");

		if (original_config.dimension_sizes.size() < 2)
			throw neural_network_exception((boost::format("distort_2d_data_sampler_transformer is processing at least 2d data, data is passed with number of dimensions %1%") % original_config.dimension_sizes.size()).str());

		float rotation_angle = params[sample_id].rotation_angle_in_degrees;
		float scale = params[sample_id].scale;
		float shift_x = params[sample_id].shift_right_x;
		float shift_y = params[sample_id].shift_down_y;
		float stretch_factor = params[sample_id].stretch_factor_and_angle.first;
		float stretch_angle = params[sample_id].stretch_factor_and_angle.second;
		float perspective_distance = params[sample_id].perspective_distance_and_angle.first;
		float perspective_angle = params[sample_id].perspective_distance_and_angle.second;

		unsigned int neuron_count_per_image = original_config.dimension_sizes[0] * original_config.dimension_sizes[1];
		unsigned int image_count = original_config.get_neuron_count() / neuron_count_per_image;
		for(unsigned int image_id = 0; image_id < image_count; ++image_id)
		{
			cv::Mat1b src_image(static_cast<int>(original_config.dimension_sizes[1]), static_cast<int>(original_config.dimension_sizes[0]), const_cast<unsigned char *>(static_cast<const unsigned char *>(data)) + (image_id * neuron_count_per_image));
			cv::Mat1b image(static_cast<int>(original_config.dimension_sizes[1]), static_cast<int>(original_config.dimension_sizes[0]), static_cast<unsigned char *>(data_transformed) + (image_id * neuron_count_per_image));
			memcpy(
				((unsigned char *)data_transformed) + image_id * neuron_count_per_image,
				((unsigned char *)data) + image_id * neuron_count_per_image,
				neuron_count_per_image * neuron_data_type::get_input_size(type));

			data_transformer_util::stretch_rotate_scale_shift_perspective(
				image,
				cv::Point2f(static_cast<float>(image.cols) * 0.5F, static_cast<float>(image.rows) * 0.5F),
				rotation_angle,
				scale,
				shift_x,
				shift_y,
				stretch_factor,
				stretch_angle,
				perspective_distance,
				perspective_angle,
				border_value);
		}
	}

	bool distort_2d_data_sampler_transformer::is_in_place() const
	{
		return false;
	}

	unsigned int distort_2d_data_sampler_transformer::get_sample_count() const
	{
		return static_cast<unsigned int>(params.size());
	}

	bool distort_2d_data_sampler_transformer::is_deterministic() const
	{
		return true;
	}
}

max_stars_repo_name: anshumang/nnForgeINST

max_issues_repo_name: anshumang/nnForgeINST

max_forks_repo_name: anshumang/nnForgeINST