1 /*++
2 Copyright (c) 2011 Microsoft Corporation
3 
4 Module Name:
5 
6     scoped_numeral.h
7 
8 Abstract:
9 
10     Wrapper for easying the pain when using primitive numeral objects such as:
11        mpz, mpq, mpbq, mpf, mpzp
12 
13 Author:
14 
15     Leonardo de Moura (leonardo) 2011-12-03
16 
17 Revision History:
18 
19 --*/
20 #pragma once
21 
22 template<typename Manager>
23 class _scoped_numeral {
24 public:
25     typedef typename Manager::numeral numeral;
26 private:
27     Manager & m_manager;
28     numeral   m_num;
29 public:
_scoped_numeral(Manager & m)30     _scoped_numeral(Manager & m):m_manager(m) {}
_scoped_numeral(_scoped_numeral const & n)31     _scoped_numeral(_scoped_numeral const & n):m_manager(n.m_manager) { m().set(m_num, n.m_num); }
32     _scoped_numeral(_scoped_numeral &&) = default;
~_scoped_numeral()33     ~_scoped_numeral() { m_manager.del(m_num); }
34 
m()35     Manager & m() const { return m_manager; }
36 
37     operator numeral const &() const { return m_num; }
38     operator numeral&() { return m_num; }
get()39     numeral const & get() const { return m_num; }
get()40     numeral & get() { return m_num; }
41 
42     _scoped_numeral & operator=(_scoped_numeral const & n) {
43         if (this == &n)
44             return *this;
45         m().set(m_num, n.m_num);
46         return *this;
47     }
48 
49     _scoped_numeral & operator=(int n) {
50         m().set(m_num, n);
51         return *this;
52     }
53 
54     _scoped_numeral & operator=(numeral const & n) {
55         m().set(m_num, n);
56         return *this;
57     }
58 
reset()59     void reset() {
60         m().reset(m_num);
61     }
62 
swap(_scoped_numeral & n)63     void swap(_scoped_numeral & n) {
64         m_num.swap(n.m_num);
65     }
66 
swap(numeral & n)67     void swap(numeral & n) {
68         m_num.swap(n);
69     }
70 
71     _scoped_numeral & operator+=(numeral const & a) {
72         m().add(m_num, a, m_num);
73         return *this;
74     }
75 
76     _scoped_numeral & operator-=(numeral const & a) {
77         m().sub(m_num, a, m_num);
78         return *this;
79     }
80 
81     _scoped_numeral & operator*=(numeral const & a) {
82         m().mul(m_num, a, m_num);
83         return *this;
84     }
85 
86     _scoped_numeral & operator/=(numeral const & a) {
87         m().div(m_num, a, m_num);
88         return *this;
89     }
90 
91     _scoped_numeral & operator%=(numeral const & a) {
92         m().rem(m_num, a, m_num);
93         return *this;
94     }
95 
96     friend bool operator==(_scoped_numeral const & a, numeral const & b) {
97         return a.m().eq(a, b);
98     }
99 
100     friend bool operator!=(_scoped_numeral const & a, numeral const & b) {
101         return !a.m().eq(a, b);
102     }
103 
104     friend bool operator<(_scoped_numeral const & a, numeral const & b) {
105         return a.m().lt(a, b);
106     }
107 
108     friend bool operator>(_scoped_numeral const & a, numeral const & b) {
109         return a.m().gt(a, b);
110     }
111 
112     friend bool operator<=(_scoped_numeral const & a, numeral const & b) {
113         return a.m().le(a, b);
114     }
115 
116     friend bool operator>=(_scoped_numeral const & a, numeral const & b) {
117         return a.m().ge(a, b);
118     }
119 
is_zero()120     bool is_zero() const {
121         return m().is_zero(*this);
122     }
123 
is_pos()124     bool is_pos() const {
125         return m().is_pos(*this);
126     }
127 
is_neg()128     bool is_neg() const {
129         return m().is_neg(*this);
130     }
131 
is_nonpos()132     bool is_nonpos() const {
133         return m().is_nonpos(*this);
134     }
135 
is_nonneg()136     bool is_nonneg() const {
137         return m().is_nonneg(*this);
138     }
139 
is_zero(_scoped_numeral const & a)140     friend bool is_zero(_scoped_numeral const & a) {
141         return a.m().is_zero(a);
142     }
143 
is_pos(_scoped_numeral const & a)144     friend bool is_pos(_scoped_numeral const & a) {
145         return a.m().is_pos(a);
146     }
147 
is_neg(_scoped_numeral const & a)148     friend bool is_neg(_scoped_numeral const & a) {
149         return a.m().is_neg(a);
150     }
151 
is_nonneg(_scoped_numeral const & a)152     friend bool is_nonneg(_scoped_numeral const & a) {
153         return a.m().is_nonneg(a);
154     }
155 
is_nonpos(_scoped_numeral const & a)156     friend bool is_nonpos(_scoped_numeral const & a) {
157         return a.m().is_nonpos(a);
158     }
159 
abs(_scoped_numeral const & a)160     friend _scoped_numeral abs(_scoped_numeral const& a) {
161         _scoped_numeral res(a);
162         a.m().abs(res);
163         return res;
164     }
165 
neg()166     void neg() {
167         m().neg(m_num);
168     }
169 
170     friend _scoped_numeral operator+(_scoped_numeral const & r1, numeral const & r2) {
171         return _scoped_numeral(r1) += r2;
172     }
173 
174     friend _scoped_numeral operator-(_scoped_numeral const & r1, numeral const & r2) {
175         return _scoped_numeral(r1) -= r2;
176     }
177 
178     friend _scoped_numeral operator*(_scoped_numeral const & r1, numeral const & r2) {
179         return _scoped_numeral(r1) *= r2;
180     }
181 
182     friend _scoped_numeral operator/(_scoped_numeral const & r1, numeral const & r2) {
183         return _scoped_numeral(r1) /= r2;
184     }
185 
186     friend std::ostream & operator<<(std::ostream & out, _scoped_numeral const & s) {
187         s.m().display(out, s);
188         return out;
189     }
190 
191 };
192