Leonardus
Loading...
Searching...
No Matches
soq.h
Go to the documentation of this file.
1
17#pragma once
18
19// Inc Library
20#include <string>
21#include <gmp.h>
22
23// Inc HAA
24#include "adapter128.h"
25#include "dbc.h"
26#include "helper.h"
27#include "error.h"
28
29// Inc Rich
30#include "so.h"
31
32
38class SOQ : public SO {
39
42 mpq_t q_{};
43
46 size_t str_length() const {
47 const size_t num_size = mpz_sizeinbase(mpq_numref(q_), 10);
48 const size_t den_size = mpz_sizeinbase(mpq_denref(q_), 10);
49 // +3 for opional '-' and '/' and '\0'
50 return num_size + den_size + 3;
51 }
52
53
54protected:
55#ifndef DBC_IS_VOID
59 bool invariant() const noexcept override { /* LCOV_EXCL_START */
60 if( mpz_sgn( mpq_denref( q_ ) ) != 1 )
61 return false;
62 mpz_t g;
63 mpz_init( g );
64 mpz_gcd( g, mpq_numref(q_), mpq_denref(q_) );
65 const int rv = mpz_cmp_si( g, 1 );
66 mpz_clear( g );
67 return rv == 0;
68 } /* LCOV_EXCL_STOP */
69#endif
70
71
72public:
74 SOQ() {
75 mpq_init( q_ );
76
78 }
79
80
83 explicit SOQ( const mpq_t p_q ) {
84 mpq_init( q_ );
85 mpq_set( q_, p_q );
86
88 }
89
90
96 SOQ( const __int128 p_num, const __int128 p_den ) {
97 DBC_PRE( p_den != 0 );
98
99 mpq_init( q_ );
100
101 __int128_to_mpz_t( mpq_numref( q_ ), p_num );
102 __int128_to_mpz_t( mpq_denref( q_ ), p_den );
103 mpq_canonicalize( q_ );
104
106 }
107
108
110 ~SOQ() override {
112
113 mpq_clear( q_ );
114 }
115
116
117 SOQ( const SOQ & ) = delete;
118 SOQ( SOQ && ) = delete;
119 SOQ & operator=( const SOQ & ) = delete;
120 SOQ & operator=( SOQ && ) = delete;
121
122
123public: /* virtual */
124 [[nodiscard]] SOQ * dup() const override { return new SOQ( q_ ); }
125
126
127 std::string opequal() const override {
128 char * buffer = new char[ str_length() ];
129 mpq_get_str( buffer, BASE10, q_ );
130 std::string str( buffer );
131 delete[] buffer;
132 return str;
133 }
134
135
136 OTCode ot() const override { return OTCode::Q; }
137
138
139 std::string type() const override { return "rationaltype"; }
140
141
144 bool equal( const SO * p_other ) const override {
145 auto o = dynamic_cast<const SOQ*>( p_other );
146 return o ? mpq_equal( q_, o->q_) : false;
147 }
148
149
152 bool gt( OpError & p_ec, const SO * p_other ) const override {
153 auto o = dynamic_cast<const SOQ*>( p_other );
154 if( o == nullptr ) {
155 p_ec = typecheck;
156 return false;
157 }
158 p_ec = success;
159 return mpq_cmp( q_, o->q_) > 0;
160 }
161
162
165 bool ge( OpError & p_ec, const SO * p_other ) const override {
166 auto o = dynamic_cast<const SOQ*>( p_other );
167 if( o == nullptr ) {
168 p_ec = typecheck;
169 return false;
170 }
171 p_ec = success;
172 return mpq_cmp( q_, o->q_) >= 0;
173 }
174
175
176public: /* accessor */
179 void getRational( mpq_t p_q ) const {
180 mpq_set( p_q, q_ );
181 }
182
183
185 void setRational( const mpq_t p_q ) {
186 mpq_set( q_, p_q );
187
188 DBC_INV;
189 }
190
191
194 void getNumerator( mpz_t p_z ) const {
195 mpz_set( p_z, mpq_numref(q_) );
196 }
197
198
200 void setNumerator( mpz_t p_z ) {
201 mpz_set( mpq_numref(q_), p_z );
202 mpq_canonicalize( q_ );
203
204 DBC_INV;
205 }
206
207
213 bool getComponents( __int128 & p_num, __int128 & p_den ) const {
214 if( ! mpz_t_to___int128( p_num, mpq_numref( q_ ) ) )
215 return false;
216 if( ! mpz_t_to___int128( p_den, mpq_denref( q_ ) ) )
217 return false;
218 return true;
219 }
220
221
222public: /* other */
225 bool isunitfraction() const {
226 return mpz_cmp_ui( mpq_numref(q_), 1u ) == 0;
227 }
228
229
232 bool iszero() const {
233 return mpz_cmp_ui( mpq_numref(q_), 0u ) == 0;
234 }
235
236
239 bool isinteger() const {
240 return mpz_cmp_ui( mpq_denref(q_), 1u ) == 0;
241 }
242
243
248 void divqr( mpq_t p_q, mpq_t p_r ) const {
249 mpz_set_ui( mpq_denref( p_q ), 1u ); // set the denominator of p_q = 1
250 mpz_set( mpq_denref( p_r ), mpq_denref( q_ ) ); // set the denominator of p_r = denominator of q_
251 mpz_fdiv_qr( mpq_numref(p_q), mpq_numref(p_r), mpq_numref(q_), mpq_denref(q_) );
252 }
253
254
262 bool parse( const std::string & p_str ) {
263 if( mpq_set_str( q_, p_str.c_str(), BASE10 ) != 0 )
264 return false;
265 if( mpz_sgn( mpq_denref( q_ ) ) == 0 )
266 return false;
267 mpq_canonicalize( q_ );
268
269 DBC_INV;
270 return true;
271 }
272
273
275 void abs() {
276 mpq_abs( q_, q_ );
277
278 DBC_INV;
279 }
280
281
283 void neg() {
284 mpq_neg( q_, q_ );
285
286 DBC_INV;
287 }
288
289
292 void reciprocal( OpError & p_ec ) {
293 p_ec = success;
294 if( mpz_sgn( mpq_numref( q_ ) ) == 0 )
295 p_ec = undefinedresult;
296 else
297 mpq_inv( q_, q_ );
298
299 DBC_INV;
300 }
301
302
305 __float128 float128() const;
306
307};
void __int128_to_mpz_t(mpz_t p_dst, __int128 p_src)
Converts an __int128 into a mpz_t.
Definition adapter128.cpp:128
bool mpz_t_to___int128(__int128 &p_dst, const mpz_t p_src)
Converts a mpz_t into an __int128.
Definition adapter128.cpp:90
Adapters for 128 bit versions of standard functions.
Semantic Object Rational Number.
Definition soq.h:38
std::string opequal() const override
String representation of object for operators '=', 'cvs' and 'stack'.
Definition soq.h:127
SOQ(const mpq_t p_q)
Ctor from a mpq_t.
Definition soq.h:83
void getNumerator(mpz_t p_z) const
Getter for the numerator of q_.
Definition soq.h:194
SOQ(const __int128 p_num, const __int128 p_den)
Ctor from a numerator and a denominator.
Definition soq.h:96
void abs()
In place abs.
Definition soq.h:275
std::string type() const override
Returns a type name.
Definition soq.h:139
bool gt(OpError &p_ec, const SO *p_other) const override
Greater than.
Definition soq.h:152
~SOQ() override
Dtor.
Definition soq.h:110
OTCode ot() const override
Returns an OTCode.
Definition soq.h:136
void setNumerator(mpz_t p_z)
Setter for the numerator of q_.
Definition soq.h:200
bool isinteger() const
Checks denominator == 1.
Definition soq.h:239
bool getComponents(__int128 &p_num, __int128 &p_den) const
Getter for numerator and denominator.
Definition soq.h:213
SOQ * dup() const override
Creates a new instance as copy following the red book definition.
Definition soq.h:124
bool ge(OpError &p_ec, const SO *p_other) const override
Greater or equal.
Definition soq.h:165
void reciprocal(OpError &p_ec)
In place reciprocal.
Definition soq.h:292
void divqr(mpq_t p_q, mpq_t p_r) const
Calculates quotient and remainder.
Definition soq.h:248
size_t str_length() const
Calculates an upper limit of the maximum length of the string representation of q_.
Definition soq.h:46
bool invariant() const noexcept override
Checks class invariants.
Definition soq.h:59
void neg()
In place neg.
Definition soq.h:283
void getRational(mpq_t p_q) const
Getter for q_.
Definition soq.h:179
bool iszero() const
Checks numerator == 0.
Definition soq.h:232
void setRational(const mpq_t p_q)
Setter for the rational number.
Definition soq.h:185
__float128 float128() const
Converts the rational number to a real number.
Definition soq.cpp:30
bool parse(const std::string &p_str)
Parses a string representation of a rational number.
Definition soq.h:262
bool equal(const SO *p_other) const override
Checks if this SO is equal to another SO.
Definition soq.h:144
SOQ()
Ctor.
Definition soq.h:74
bool isunitfraction() const
Checks numerator == 1.
Definition soq.h:225
mpq_t q_
The rational number by GMP.
Definition soq.h:42
Semantic Object.
Definition so.h:60
Helpers for design by contract idioms.
#define DBC_INV_CTOR(T)
Assert for invariant checks in ctors and dtors.
Definition dbc.h:121
#define DBC_INV
Assert for invariant checks in member functions.
Definition dbc.h:113
#define DBC_PRE(XXX)
Assert for preconditions.
Definition dbc.h:103
Error handling.
OpError
Operator error code enum.
Definition error.h:30
@ undefinedresult
operator error undefinedresult
Definition error.h:39
@ success
No operator error.
Definition error.h:32
@ typecheck
operator error typecheck
Definition error.h:36
Miscellaneous definitions and functions.
constexpr int BASE10
We use base 10.
Definition helper.h:97
The class SO - semantic object.
OTCode
OTCode - the Object Type Code.
Definition so.h:35
@ o
SOo.
@ Q
SOQ.