3
0
mirror of https://github.com/triqs/dft_tools synced 2024-11-01 03:33:50 +01:00
dft_tools/triqs/mc_tools/generator.hpp
Olivier Parcollet edca014785 rng : preview
2014-04-02 20:36:54 +02:00

97 lines
4.2 KiB
C++

// (C) Copyright 2008-10 Lukas Gamper <gamperl -at- gmail.com>
// Brigitte Surer <surerb -at- phys.ethz.ch>
// Bela Bauer <bauerb -at- phys.ethz.ch>
//
// downgraded by O. Parcollet for compilation with icc11 & boost 1.45
//
// Use, modification, and distribution are subject to the Boost Software
// License, Version 1.0. (See at <http://www.boost.org/LICENSE_1_0.txt>.)
#include <vector>
#include <algorithm>
#include <boost/function.hpp>
#include <boost/ref.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/construct.hpp>
#include <boost/lambda/exceptions.hpp>
namespace boost{
template<typename R> class generator {
public:
static std::size_t const buffer_size = 1000;
template<typename Generator> generator(Generator const & gen, std::size_t size = buffer_size)
:
buf(make_shared<buffer>(gen, size))
, cur(buf->cur)
, end(buf->end())
{}
inline R const operator()() {
if (cur == end)
buf->fill();
return *cur++;
}
inline R const preview() {
if (cur == end)
buf->fill();
return *cur;
}
generator(generator<R> const & rhs)
:
buf(new buffer (*rhs.buf))
, cur(buf->cur)
, end(buf->end())
{}
generator<R> & operator=(generator<R> rhs) {
swap(*this, rhs);
return *this;
}
private:
class buffer: public std::vector<R> {
public:
friend class generator<R>;
template<typename Generator> buffer(Generator const & gen, std::size_t size)
: std::vector<R>(size)
, engine(make_shared<Generator>(gen))
, cur(this->end())
, fill_helper(lambda::bind(std::generate<typename buffer::iterator, Generator &>, lambda::_1, lambda::_2, ref(*reinterpret_cast<Generator *>(engine.get()))))
, clone(lambda::bind(buffer::template type_keeper<Generator>, lambda::_1, lambda::_2))
{}
template<typename Generator> buffer(reference_wrapper<Generator> gen, std::size_t size)
: std::vector<R>(size)
, cur(this->end())
, fill_helper(lambda::bind(std::generate<typename buffer::iterator, Generator &>, lambda::_1, lambda::_2, gen))
{}
buffer(buffer const & rhs)
: std::vector<R>(rhs)
, cur(this->begin() + (rhs.cur - rhs.begin()))
, fill_helper(rhs.fill_helper)
, clone(rhs.clone)
{
if (rhs.engine)
clone(*this, rhs);
}
inline void fill() {
fill_helper(this->begin(), this->end());
cur = this->begin();
}
private:
template<typename Generator> static void type_keeper(buffer & lhs, buffer const & rhs) {
lhs.engine = make_shared<Generator>(*reinterpret_cast<Generator *>(rhs.engine.get()));
lhs.fill_helper = lambda::bind(std::generate<typename buffer::iterator, Generator &>, lambda::_1, lambda::_2, ref(*reinterpret_cast<Generator *>(lhs.engine.get())));
}
shared_ptr<void> engine;
typename std::vector<R>::const_iterator cur;
function<void(typename std::vector<R>::iterator, typename std::vector<R>::iterator)> fill_helper;
function<void(buffer &, buffer const &)> clone;
};
shared_ptr<buffer> buf;
typename buffer::const_iterator & cur;
typename buffer::const_iterator end;
};
}