#ifndef __rf_integer_ih__ #define __rf_integer_ih__ #include "rf_integer.hh" #include "rf_expr.ih" #include "rf_term.ih" #include "pxx_chunk_allocator.ih" #include "pxx_string.ih" namespace rftype { using namespace rfrt; inline Integer::Integer (intptr_t _n) : Term(type_int) { MpzContainer* p = mpz_allocator.allocate(); ptr_data2 = p; mpz_init_set_si(p->value, _n); p->ref_count = 1; } inline Integer::Integer (char const* _str) : Term(type_int) { MpzContainer* p = mpz_allocator.allocate(); ptr_data2 = p; mpz_init_set_str(p->value, _str, 0); p->ref_count = 1; } inline Integer::Integer (wchar_t const* _str) : Term(type_int) { MpzContainer* p = mpz_allocator.allocate(); ptr_data2 = p; // size_t len = wcstombs(null, _str, 0); size_t len = wcslen(_str); char* s = static_cast(alloca(len + 1)); // wcstombs(s, _str, len); for (size_t i = 0; i < len; i++) wcrtomb(&s[i], _str[i], null); s[len] = 0; mpz_init_set_str(p->value, s, 0); p->ref_count = 1; } inline Integer::Integer (pxx::WString& _str) : Term(type_int) { MpzContainer* p = mpz_allocator.allocate(); ptr_data2 = p; const wchar_t* str = _str.get_data(); // size_t len = wcstombs(null, _str.get_data(), 0); size_t len = wcslen(str); char* s = static_cast(alloca(len + 1)); // wcstombs(s, _str.get_data(), len); for (size_t i = 0; i < len; i++) wcrtomb(&s[i], str[i], null ); s[len] = 0; mpz_init_set_str(p->value, s, 0); p->ref_count = 1; } inline Integer::Integer (Integer const& _n) : Term(type_int) { ptr_data2 = _n.ptr_data2; static_cast(ptr_data2)->ref_count++; } inline Integer::Integer (MpzContainer* _p) : Term(type_int) { ptr_data2 = _p; _p->ref_count = 1; } inline Integer::~Integer () { // // As Integer destructor implicitly calls Term destructor and that calls // Integer::dtor() method which really destroys an Integer object, we should // not put any actions into Integer destructor body // mpz_t* p = static_cast(ptr_data2); // mpz_clear(*p); // mpz_allocator.deallocate(p); } #if 0 inline Integer& Integer::operator = (Integer const& _n) { mpz_t* p = static_cast(ptr_data2); mpz_clear(*p); mpz_t* q = static_cast(_n.ptr_data2); mpz_init_set(*p, *q); return self; } #endif inline bool Integer::operator == (Integer const& _n) const { return mpz_cmp(get_mpz_val(), _n.get_mpz_val()) == 0; } inline bool Integer::operator == (unsigned long _n) const { return mpz_cmp_ui(get_mpz_val(), _n) == 0; } inline bool Integer::operator == (long _n) const { return mpz_cmp_si(get_mpz_val(), _n) == 0; } inline bool Integer::operator == (unsigned int _n) const { return mpz_cmp_ui(get_mpz_val(), _n) == 0; } inline bool Integer::operator == (int _n) const { return mpz_cmp_si(get_mpz_val(), _n) == 0; } inline int Integer::cmp (Integer const& _n) const { return mpz_cmp(get_mpz_val(), _n.get_mpz_val()); } inline int Integer::cmp (unsigned long _n) const { return mpz_cmp_ui(get_mpz_val(), _n); } inline int Integer::cmp (long _n) const { return mpz_cmp_si(get_mpz_val(), _n); } inline int Integer::cmp (unsigned int _n) const { return mpz_cmp_ui(get_mpz_val(), _n); } inline int Integer::cmp (int _n) const { return mpz_cmp_si(get_mpz_val(), _n); } inline Integer Integer::operator + (Integer const& _n) const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); mpz_add(p->value, get_mpz_val(), _n.get_mpz_val()); return p; } inline Integer Integer::operator + (intptr_t _n) const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); _n >= 0 ? mpz_add_ui(p->value, get_mpz_val(), _n) : mpz_sub_ui(p->value, get_mpz_val(), -_n); return p; } inline Integer operator + (intptr_t _n1, Integer const& _n2) { return _n2 + _n1; } inline Integer Integer::operator - (Integer const& _n) const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); mpz_sub(p->value, get_mpz_val(), _n.get_mpz_val()); return p; } inline Integer Integer::operator - (intptr_t _n) const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); _n >= 0 ? mpz_sub_ui(p->value, get_mpz_val(), _n) : mpz_add_ui(p->value, get_mpz_val(), -_n); return p; } inline Integer operator - (intptr_t _n1, Integer const& _n2) { Integer::MpzContainer* p = Integer::mpz_allocator.allocate(); mpz_init(p->value); mpz_neg(p->value, _n2.get_mpz_val()); _n1 >= 0 ? mpz_add_ui(p->value, p->value, _n1) : mpz_sub_ui(p->value, p->value, -_n1); return p; } inline Integer Integer::operator * (Integer const& _n) const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); mpz_mul(p->value, get_mpz_val(), _n.get_mpz_val()); return p; } inline Integer Integer::operator * (intptr_t _n) const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); mpz_mul_si(p->value, get_mpz_val(), _n); return p; } inline Integer operator * (intptr_t _n1, Integer const& _n2) { return _n2 * _n1; } inline Integer Integer::operator / (Integer const& _n) const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); mpz_tdiv_q(p->value, get_mpz_val(), _n.get_mpz_val()); return p; } inline Integer Integer::operator / (intptr_t _n) const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); if (_n >= 0 ) { mpz_tdiv_q_ui(p->value, get_mpz_val(), _n); } else { mpz_tdiv_q_ui(p->value, get_mpz_val(), -_n); mpz_neg(p->value, p->value); } return p; } inline Integer operator / (intptr_t _n1, Integer const& _n2) { return Integer(_n1) / _n2; } inline Integer Integer::operator % (Integer const& _n) const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); mpz_tdiv_r(p->value, get_mpz_val(), _n.get_mpz_val()); return p; } inline Integer Integer::operator % (intptr_t _n) const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); if (_n >= 0 ) { mpz_tdiv_r_ui(p->value, get_mpz_val(), _n); } else { mpz_tdiv_r_ui(p->value, get_mpz_val(), -_n); } return p; } inline Integer operator % (intptr_t _n1, Integer const& _n2) { return Integer(_n1) % _n2; } inline Integer Integer::div_rem (Integer const& _n, Integer* _remp) const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); if (_remp != null) { MpzContainer* rem_ptr = static_cast(_remp->ptr_data2); mpz_tdiv_qr(p->value, rem_ptr->value, get_mpz_val(), _n.get_mpz_val()); } else { mpz_tdiv_q(p->value, get_mpz_val(), _n.get_mpz_val()); } return p; } inline Integer Integer::div_rem (intptr_t _n, Integer* _remp) const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); if (_remp != null) { MpzContainer* rem_ptr = static_cast(_remp->ptr_data2); if (_n >= 0 ) { mpz_tdiv_qr_ui(p->value, rem_ptr->value, get_mpz_val(), _n); } else { mpz_tdiv_qr_ui(p->value, rem_ptr->value, get_mpz_val(), -_n); mpz_neg(p->value, p->value); } } else { if (_n >= 0 ) { mpz_tdiv_r_ui(p->value, get_mpz_val(), _n); } else { mpz_tdiv_r_ui(p->value, get_mpz_val(), -_n); mpz_neg(p->value, p->value); } } return p; } inline Integer div_rem (intptr_t _n1, Integer const& _n2, Integer* _remp) { return Integer(_n1).div_rem(_n2, _remp); } inline Integer Integer::operator - () const { MpzContainer* p = mpz_allocator.allocate(); mpz_init(p->value); mpz_neg(p->value, get_mpz_val()); return p; } inline int Integer::sign () const { return mpz_sgn(get_mpz_val()); } inline long Integer::to_int () const { return mpz_get_si(get_mpz_val()); } inline Integer::operator pxx::WString () const { MpzContainer* p = static_cast(ptr_data2); size_t len = mpz_sizeinbase(p->value, 10) + 2; char* s = static_cast(alloca(len)); mpz_get_str(s, 10, p->value); len = strlen(s) + 1; wchar_t* ws = static_cast(alloca((len + 1)* sizeof(wchar_t))); len = mbstowcs(ws, s, len); ws[len] = 0; return pxx::WString(ws, len); } inline Expr Integer::create_expr (intptr_t _n) { Expr e = Term::create_expr(1); new(e.get_first()) Integer(_n); return e; } inline Expr Integer::create_expr (uintptr_t _n) { Expr e = Term::create_expr(1); new(e.get_first()) Integer(_n); return e; } inline Expr Integer::create_expr (size_t _n) { Expr e = Term::create_expr(1); new(e.get_first()) Integer(_n); return e; } inline Expr Integer::create_expr (int _n) { Expr e = Term::create_expr(1); new(e.get_first()) Integer(_n); return e; } inline Expr Integer::create_expr (Integer const& _n) { Expr e = Term::create_expr(1); new(e.get_first()) Integer(_n); return e; } inline Expr Integer::create_expr (char const* _str) { Expr e = Term::create_expr(1); new(e.get_first()) Integer(_str); return e; } inline Expr Integer::create_expr (wchar_t const* _str) { Expr e = Term::create_expr(1); new(e.get_first()) Integer(_str); return e; } inline Expr Integer::create_expr (pxx::WString& _str) { wchar_t const* data = _str.get_data(); return Integer::create_expr(data); } inline const mpz_t& Integer::get_mpz_val () const { return static_cast(ptr_data2)->value; } inline Expr Integer::create_sum (Integer const& _n1, Integer const& _n2) { MpzContainer* mpzp = mpz_allocator.allocate(); mpz_init(mpzp->value); mpz_add(mpzp->value, _n1.get_mpz_val(), _n2.get_mpz_val()); Expr e = Term::create_expr(1); new(e.get_first()) Integer(mpzp); return e; } inline Expr Integer::create_mult (Integer const& _n1, Integer const& _n2) { MpzContainer* mpzp = mpz_allocator.allocate(); mpz_init(mpzp->value); mpz_mul(mpzp->value, _n1.get_mpz_val(), _n2.get_mpz_val()); Expr e = Term::create_expr(1); new(e.get_first()) Integer(mpzp); return e; } } #endif // __rf_integer_ih__