Skip to content

Instantly share code, notes, and snippets.

@marionette-of-u
Created August 29, 2012 23:34
Show Gist options
  • Select an option

  • Save marionette-of-u/3520406 to your computer and use it in GitHub Desktop.

Select an option

Save marionette-of-u/3520406 to your computer and use it in GitHub Desktop.
#include <memory>
#include <utility>
#include <iostream>
#include <gmpxx.h>
namespace cmpxx{
namespace aux{
template<class T>
struct expr_wrapper{
typedef T type;
expr_wrapper(const type &expr_) : expr(expr_){}
type expr;
};
template<class MPClass>
class mp_wrapper{
public:
typedef MPClass mp_type;
mp_wrapper() :
value_pointer_(new MPClass)
{}
mp_wrapper(const mp_wrapper &other) :
value_pointer_(new MPClass(*other.value_pointer_.get()))
{}
mp_wrapper(mp_wrapper &&other) :
value_pointer_(nullptr)
{ value_pointer_.swap(other.value_pointer_); }
mp_wrapper(MPClass &&value) :
value_pointer_(new MPClass)
{ swap_mp_class(value); }
template<class T, class U>
mp_wrapper(const __gmp_expr<T, U> &expr) :
value_pointer_(new MPClass(expr))
{}
template<class T>
mp_wrapper(const expr_wrapper<T> &wrapped_expr) :
value_pointer_(new MPClass(wrapped_expr.expr))
{}
mp_wrapper(const std::string &s, int base = 0) :
value_pointer_(new MPClass(s, base))
{}
mp_wrapper &operator =(const mp_wrapper &other){
get_raw_value() = other.get_raw_value();
return *this;
}
mp_wrapper &operator =(mp_wrapper &&other){
value_pointer_.swap(other.value_pointer_);
other.value_pointer_.reset(nullptr);
return *this;
}
mp_wrapper &operator =(MPClass &&raw_value){
swap_mp_class(raw_value);
return *this;
}
template<class T, class U>
mp_wrapper &operator =(const __gmp_expr<T, U> &expr){
*value_pointer_.get() = expr;
return *this;
}
template<class T>
mp_wrapper &operator =(const expr_wrapper<T> &wrapped_expr){
*value_pointer_.get() = wrapped_expr.expr;
return *this;
}
const MPClass &get_raw_value() const{
return *value_pointer_.get();
}
MPClass &get_raw_value(){
return *value_pointer_.get();
}
private:
void swap_mp_class(MPClass &value){
typedef typename std::aligned_storage<
sizeof(MPClass),
std::alignment_of<MPClass>::value
>::type pod_of_mp_class;
std::swap(
*static_cast<pod_of_mp_class*>(static_cast<void*>(value_pointer_.get())),
*static_cast<pod_of_mp_class*>(static_cast<void*>(&value))
);
}
std::unique_ptr<MPClass> value_pointer_;
};
}
}
#define CMPXX_EMPTY_DEFINED
#define CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL(op, decl_lhs, type, bigtype) \
template<class T, class U> \
cmpxx::aux::expr_wrapper<decltype(__gmp_expr<T, U>() op type())> \
operator op(decl_lhs cmpxx::aux::mp_wrapper<__gmp_expr<T, U>> &expr, type t){ \
return expr.get_raw_value() op t; \
} \
template<class T, class U> \
cmpxx::aux::expr_wrapper<decltype(type() op __gmp_expr<T, U>())> \
operator op(type t, const cmpxx::aux::mp_wrapper<__gmp_expr<T, U>> &expr){ \
return t op expr.get_raw_value(); \
}
#define CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_S(op, decl_lhs, t) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL(op, decl_lhs, t, signed long int)
#define CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_U(op, decl_lhs, t) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL(op, decl_lhs, t, unsigned long int)
#define CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_D(op, decl_lhs, t) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL(op, decl_lhs, t, double)
#define CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_LD(op, decl_lhs, t) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL(op, decl_lhs, t, long double)
#define CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD(op, decl_lhs) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_S(op, decl_lhs, signed char) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_U(op, decl_lhs, unsigned char) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_S(op, decl_lhs, signed int) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_U(op, decl_lhs, unsigned int) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_S(op, decl_lhs, signed short int) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_U(op, decl_lhs, unsigned short int) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_S(op, decl_lhs, signed long int) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_U(op, decl_lhs, unsigned long int) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_D(op, decl_lhs, float) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_D(op, decl_lhs, double) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD_IMPL_LD(op, decl_lhs, long double)
#define CMPXX_DEFINE_OPERATOR_EXPR_OVERLOAD(op, decl_lhs) \
template<class T, class U, class V, class W> \
cmpxx::aux::expr_wrapper<decltype(__gmp_expr<T, U>() op __gmp_expr<V, W>())> \
operator op( \
decl_lhs cmpxx::aux::mp_wrapper<__gmp_expr<T, U>> &l, \
const cmpxx::aux::mp_wrapper<__gmp_expr<V, W>> &r \
){ return l.get_raw_value() op r.get_raw_value(); } \
template<class T, class U, class V, class W> \
cmpxx::aux::expr_wrapper<decltype(__gmp_expr<T, U>() op __gmp_expr<V, W>())> \
operator op( \
decl_lhs cmpxx::aux::expr_wrapper<__gmp_expr<T, U>> &l, \
const cmpxx::aux::expr_wrapper<__gmp_expr<V, W>> &r \
){ return l.expr op r.expr; } \
template<class T, class U, class V, class W> \
cmpxx::aux::expr_wrapper<decltype(__gmp_expr<T, U>() op __gmp_expr<V, W>())> \
operator op( \
decl_lhs cmpxx::aux::mp_wrapper<__gmp_expr<T, U>> &l, \
const cmpxx::aux::expr_wrapper<__gmp_expr<V, W>> &r \
){ return l.get_raw_value() op r.expr; } \
template<class T, class U, class V, class W> \
cmpxx::aux::expr_wrapper<decltype(__gmp_expr<T, U>() op __gmp_expr<V, W>())> \
operator op( \
const cmpxx::aux::expr_wrapper<__gmp_expr<T, U>> &l, \
const cmpxx::aux::mp_wrapper<__gmp_expr<V, W>> &r \
){ return l.expr op r.get_raw_value(); }
#define CMPXX_DEFINE_OPERATOR_OVERLOAD(op, decl_lhs) \
CMPXX_DEFINE_OPERATOR_EXPR_OVERLOAD(op, decl_lhs) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD(op, decl_lhs)
#define CMPXX_DEFINE_BOOLIAN_OPERATOR_OVERLOAD(op) \
CMPXX_DEFINE_OPERATOR_EXPR_OVERLOAD(op, const) \
CMPXX_DEFINE_OPERATOR_BUILT_IN_TYPE_OVERLOAD(op, const)
CMPXX_DEFINE_OPERATOR_OVERLOAD(+, const);
CMPXX_DEFINE_OPERATOR_OVERLOAD(-, const);
CMPXX_DEFINE_OPERATOR_OVERLOAD(*, const);
CMPXX_DEFINE_OPERATOR_OVERLOAD(/, const);
CMPXX_DEFINE_OPERATOR_OVERLOAD(%, const);
//CMPXX_DEFINE_OPERATOR_OVERLOAD(+=, CMPXX_EMPTY_DEFINED);
//CMPXX_DEFINE_OPERATOR_OVERLOAD(-=, CMPXX_EMPTY_DEFINED);
//CMPXX_DEFINE_OPERATOR_OVERLOAD(*=, CMPXX_EMPTY_DEFINED);
//CMPXX_DEFINE_OPERATOR_OVERLOAD(/=, CMPXX_EMPTY_DEFINED);
//CMPXX_DEFINE_OPERATOR_OVERLOAD(%=, CMPXX_EMPTY_DEFINED);
CMPXX_DEFINE_BOOLIAN_OPERATOR_OVERLOAD(<);
CMPXX_DEFINE_BOOLIAN_OPERATOR_OVERLOAD(>);
CMPXX_DEFINE_BOOLIAN_OPERATOR_OVERLOAD(<=);
CMPXX_DEFINE_BOOLIAN_OPERATOR_OVERLOAD(>=);
CMPXX_DEFINE_BOOLIAN_OPERATOR_OVERLOAD(==);
CMPXX_DEFINE_BOOLIAN_OPERATOR_OVERLOAD(!=);
namespace cmpxx{
typedef aux::mp_wrapper<mpz_class> integer;
typedef aux::mp_wrapper<mpq_class> rational;
}
#include <typeinfo>
int main(){
cmpxx::integer a(11);
std::cout << typeid(a * a + a * a).name() << "\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment