chia-blockchain/lib/chiavdf/fast_vdf/generic.h

253 lines
9.1 KiB
C++

#include "generic_macros.h"
#include <fstream>
#ifndef ILYA_SHARED_HEADER_GENERIC
#define ILYA_SHARED_HEADER_GENERIC
namespace generic {
using namespace std;
template<class type_a> void print_impl(ostream& out, const type_a& a) {}
template<class type_b> void print_impl(ostream& out, const char* a, const type_b& b) {
out << " " << b;
}
template<class type_a, class type_b> void print_impl(ostream& out, const type_a& a, const type_b& b) {
out << ", " << b;
}
template<class type_a, class type_b, class... types> void print_impl(ostream& out, const type_a& a, const type_b& b, const types&... targs) {
print_impl(out, a, b);
print_impl(out, b, targs...);
}
template<class type_a, class... types> void print_to(ostream& out, const type_a& a, const types&... targs) {
out << a;
print_impl(out, a, targs...);
out << "\n";
}
template<class type_a, class... types> void print(const type_a& a, const types&... targs) {
print_to(cerr, a, targs...);
}
//if buffer is not null, will return an empty string
string getstream(istream& targ, int block_size=10, string* buffer=nullptr) {
string new_buffer;
string& res=(buffer!=nullptr)? *buffer : new_buffer;
res.clear();
while(1) {
res.resize(res.size()+block_size);
targ.read(&(res[res.size()-block_size]), block_size);
int c=targ.gcount();
if (c!=block_size) {
res.resize(res.size()-block_size+c);
assert(targ.eof());
return new_buffer;
}
}
}
string getfile(const string& name, bool binary=0, int block_size=1024) {
ifstream in(name, binary? ios::binary|ios_base::in : ios_base::in);
assert(in.good());
return getstream(in, block_size);
}
struct less_ptr {
template<class ptr_type> bool operator()(ptr_type a, ptr_type b) {
return *a<*b;
}
};
template<class type> type instance_of();
template<class type> std::string to_string(std::ostringstream& s, const type& targ) {
s.clear();
s.str("");
s << targ;
return s.str();
}
template<class type> std::string to_string(const type& targ) {
static std::ostringstream s;
return to_string(s, targ);
}
template<class type> pair<type, bool> checked_from_string(std::istringstream& s, const std::string& targ) {
s.clear();
s.str(targ);
type res;
s >> res;
return make_pair(res, s.eof() && !s.fail());
}
template<class type> type from_string(std::istringstream& s, const std::string& targ) {
return checked_from_string<type>(s, targ).first;
}
template<class type> type from_string(const std::string& targ) {
static std::istringstream s;
return from_string<type>(s, targ);
}
template<class type> pair<type, bool> checked_from_string(const std::string& targ) {
static std::istringstream s;
return checked_from_string<type>(s, targ);
}
template<class type> type assert_from_string(const std::string& targ) {
auto res=checked_from_string<type>(targ);
assert(res.second);
return res.first;
}
template<class type, class... types> unique_ptr<type> make_unique_ptr(types&&... targs) {
return unique_ptr<type>(new type(forward<types>(targs)...));
}
template<class type, int size> int array_size(type(&)[size]) {
return size;
}
template<class type> std::ostream& print_as_number(std::ostream& out, const type& targ) { out << targ; return out; }
template<> std::ostream& print_as_number<unsigned char>(std::ostream& out, const unsigned char& targ) { out << int(targ); return out; }
template<> std::ostream& print_as_number<signed char>(std::ostream& out, const signed char& targ) { out << int(targ); return out; }
template<> std::ostream& print_as_number<char>(std::ostream& out, const char& targ) { out << int(targ); return out; }
//
template<bool n, class type> struct only_if {};
template<class type> struct only_if<1, type> { typedef type good; };
template<bool n> typename only_if<n, void>::good assert_true() {}
template<class a, class b, class type> struct only_if_same_types {};
template<class a, class type> struct only_if_same_types<a, a, type> { typedef type good; };
template<class a, class b> typename only_if_same_types<a, b, void>::good assert_same_types() {}
template<class a, class b, class type> struct only_if_not_same_types { typedef type good; };
template<class a, class type> struct only_if_not_same_types<a, a, type> {};
template<class a, class b> typename only_if_not_same_types<a, b, void>::good assert_not_same_types() {}
template<int n> struct static_abs { static const int res=n<0? -n : n; };
template<int n> struct static_sgn { static const int res=n<0? -1 : (n>0? 1 : 0); };
template<int a, int b> struct static_max { static const int res=a>b? a : b; };
template<int a, int b> struct static_min { static const int res=a<b? a : b; };
template<class type> class wrap_type { typedef type res; };
//
template<class type_a, class type_b> class union_pair {
template<class, class> friend class union_pair;
static const size_t size_bytes=static_max<sizeof(type_a), sizeof(type_b)>::res;
static const size_t alignment_bytes=static_max<alignof(type_a), alignof(type_b)>::res;
typename aligned_storage<size_bytes, alignment_bytes>::type buffer;
bool t_is_first;
public:
union_pair() : t_is_first(1) { new(&buffer) type_a(); }
union_pair(int, int) : t_is_first(0) { new(&buffer) type_b(); }
union_pair(const type_a& targ) : t_is_first(1) { new(&buffer) type_a(targ); }
union_pair(const type_b& targ) : t_is_first(0) { new(&buffer) type_b(targ); }
union_pair(type_a&& targ) : t_is_first(1) { new(&buffer) type_a(move(targ)); }
union_pair(type_b&& targ) : t_is_first(0) { new(&buffer) type_b(move(targ)); }
union_pair(const union_pair& targ) : t_is_first(targ.t_is_first) {
if (t_is_first) new(&buffer) type_a(targ.first()); else new(&buffer) type_b(targ.second());
}
union_pair(const union_pair<type_b, type_a>& targ) : t_is_first(!targ.t_is_first) {
if (t_is_first) new(&buffer) type_a(targ.second()); else new(&buffer) type_b(targ.first());
}
union_pair(union_pair&& targ) : t_is_first(targ.t_is_first) {
if (t_is_first) new(&buffer) type_a(move(targ.first())); else new(&buffer) type_b(move(targ.second()));
}
union_pair(union_pair<type_b, type_a>&& targ) : t_is_first(!targ.t_is_first) {
if (t_is_first) new(&buffer) type_a(move(targ.second())); else new(&buffer) type_b(move(targ.first()));
}
union_pair& operator=(const type_a& targ) {
if (is_first()) first()=targ; else set_first(targ);
return *this;
}
union_pair& operator=(const type_b& targ) {
if (is_second()) second()=targ; else set_second(targ);
return *this;
}
union_pair& operator=(type_a&& targ) {
if (is_first()) first()=move(targ); else set_first(move(targ));
return *this;
}
union_pair& operator=(type_b&& targ) {
if (is_second()) second()=move(targ); else set_second(move(targ));
return *this;
}
union_pair& operator=(const union_pair& targ) {
if (targ.is_first()) {
return *this=targ.first();
} else {
return *this=targ.second();
}
}
union_pair& operator=(const union_pair<type_b, type_a>& targ) {
if (targ.is_first()) {
return *this=targ.first();
} else {
return *this=targ.second();
}
}
union_pair& operator=(union_pair&& targ) {
if (targ.is_first()) {
return *this=move(targ.first());
} else {
return *this=move(targ.second());
}
}
union_pair& operator=(union_pair<type_b, type_a>&& targ) {
if (targ.is_first()) {
return *this=move(targ.first());
} else {
return *this=move(targ.second());
}
}
typedef type_a first_type;
typedef type_b second_type;
bool is_first() const { return t_is_first; }
bool is_second() const { return !t_is_first; }
//
type_a& first() { return *reinterpret_cast<type_a*>(&buffer); }
const type_a& first() const { return *reinterpret_cast<const type_a*>(&buffer); }
type_b& second() { return *reinterpret_cast<type_b*>(&buffer); }
const type_b& second() const { return *reinterpret_cast<const type_b*>(&buffer); }
//
template<class... types> type_a& set_first(types&&... targs) {
if (!t_is_first) {
second().~type_b();
t_is_first=1;
} else {
first().~type_a();
}
return *(new(&buffer) type_a(forward<types>(targs)...));
}
template<class... types> type_b& set_second(types&&... targs) {
if (t_is_first) {
first().~type_a();
t_is_first=0;
} else {
second().~type_b();
}
return *(new(&buffer) type_b(forward<types>(targs)...));
}
~union_pair() {
if (t_is_first) first().~type_a(); else second().~type_b();
}
};
}
#endif