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 <string_view>
22#include <cstring>
23#include <gmp.h>
24
25// Inc Pure
26#include "conversion.h"
27#include "dbc.h"
28#include "helper.h"
29#include "algo.h"
30
31// Inc Medium
32#include "error.h"
33
34// Inc Rich
35#include "so.h"
36
37
43class SOQ : public SO {
44
47 mpq_t q_{};
48
49
52 size_t str_length() const {
53 const size_t num_size = mpz_sizeinbase( mpq_numref(q_), BASE10 );
54 const size_t den_size = mpz_sizeinbase( mpq_denref(q_), BASE10 );
55 // +3 for an optional '-', a ':' and a '\0'
56 return num_size + den_size + 3;
57 }
58
59
69 bool parse_work( std::string & p_str );
70
71protected:
72
73#ifndef DBC_IS_VOID
77 bool invariant() const noexcept override { /* LCOV_EXCL_START */
78 if( mpz_sgn( mpq_denref( q_ ) ) != 1 )
79 return false;
80 mpz_t g;
81 mpz_init( g );
82 mpz_gcd( g, mpq_numref(q_), mpq_denref(q_) );
83 const int rv = mpz_cmp_si( g, 1 );
84 mpz_clear( g );
85 return rv == 0;
86 } /* LCOV_EXCL_STOP */
87#endif
88
89public:
90
92 SOQ() {
93 mpq_init( q_ );
94
96 }
97
98
103 explicit SOQ( std::string & p_s ) {
105
106 (void) parse_work( p_s );
107
109 }
110
111
112
115 explicit SOQ( const mpq_t p_q ) {
116 mpq_init( q_ );
117 mpq_set( q_, p_q );
118
120 }
121
122
128 SOQ( const __int128 p_num, const __int128 p_den ) {
129 DBC_PRE( p_den != 0 );
130
131 mpq_init( q_ );
132
133 conversion::__int128_to_mpz_t( mpq_numref( q_ ), p_num );
134 conversion::__int128_to_mpz_t( mpq_denref( q_ ), p_den );
135 mpq_canonicalize( q_ );
136
138 }
139
140
142 ~SOQ() override {
144
145 mpq_clear( q_ );
146 }
147
148
149 SOQ( const SOQ & ) = delete;
150 SOQ( SOQ && ) = delete;
151 SOQ & operator=( const SOQ & ) = delete;
152 SOQ & operator=( SOQ && ) = delete;
153
154public: /* virtual */
155
156 [[nodiscard]] SOQ * dup() const override { return new SOQ( q_ ); }
157
158
159 std::string opequal() const override;
160
161
162 OTCode ot() const override { return OTCode::Q; }
163
164
165 std::string_view type() const override { return "rationaltype"; }
166
167
170 bool equal( const SO * p_other ) const override {
171 DBC_PRE( p_other != nullptr );
172
173 if( p_other->ot() != ot() )
174 return false;
175 const auto o = static_cast<const SOQ *>( p_other );
176 return mpq_equal( q_, o->q_);
177 }
178
179
183 bool gt( OpError & p_ec, const SO * p_other ) const override {
184 DBC_PRE( p_other != nullptr );
185
186 if( p_other->ot() != OTCode::Q ) {
187 p_ec = typecheck;
188 return false;
189 }
190 const auto o = static_cast<const SOQ *>( p_other );
191 p_ec = success;
192 return mpq_cmp( q_, o->q_) > 0;
193 }
194
195
199 bool ge( OpError & p_ec, const SO * p_other ) const override {
200 DBC_PRE( p_other != nullptr );
201
202 if( p_other->ot() != OTCode::Q ) {
203 p_ec = typecheck;
204 return false;
205 }
206 const auto o = static_cast<const SOQ *>( p_other );
207 p_ec = success;
208 return mpq_cmp( q_, o->q_) >= 0;
209 }
210
211public: /* accessor */
212
215 void getRational( mpq_t p_q ) const {
216 mpq_set( p_q, q_ );
217 }
218
219
221 void setRational( const mpq_t p_q ) {
222 mpq_set( q_, p_q );
223
224 DBC_INV;
225 }
226
227
230 void getNumerator( mpz_t p_z ) const {
231 mpz_set( p_z, mpq_numref(q_) );
232 }
233
234
236 void setNumerator( mpz_t p_z ) {
237 mpz_set( mpq_numref(q_), p_z );
238 mpq_canonicalize( q_ );
239
240 DBC_INV;
241 }
242
243
249 bool getComponents( __int128 & p_num, __int128 & p_den ) const {
250 auto [conv1, num] = conversion::mpz_t_to___int128( mpq_numref( q_ ) );
251 if( !conv1 )
252 return false;
253 p_num = num;
254 auto [conv2, den] = conversion::mpz_t_to___int128( mpq_denref( q_ ) );
255 if( !conv2 )
256 return false;
257 p_den = den;
258 return true;
259 }
260
261public: /* other */
262
265 bool isunitfraction() const {
266 return mpz_cmp_ui( mpq_numref(q_), 1u ) == 0;
267 }
268
269
272 bool isinteger() const {
273 return mpz_cmp_ui( mpq_denref(q_), 1u ) == 0;
274 }
275
276
281 void divqr( mpq_t p_q, mpq_t p_r ) const {
282 mpz_set_ui( mpq_denref( p_q ), 1u ); // set the denominator of p_q = 1
283 mpz_set( mpq_denref( p_r ), mpq_denref( q_ ) ); // set the denominator of p_r = denominator of q_
284 mpz_fdiv_qr( mpq_numref(p_q), mpq_numref(p_r), mpq_numref(q_), mpq_denref(q_) );
285 }
286
287
295 bool parse( std::string & p_str ) {
296 const bool rv = parse_work( p_str );
297 if( !rv )
298 mpq_set_si( q_, 0, 1 );
299
300 DBC_INV;
301 return rv;
302 }
303
304
306 void abs__1() {
307 mpq_abs( q_, q_ );
308
309 DBC_INV;
310 }
311
312
314 void neg__1() {
315 mpq_neg( q_, q_ );
316
317 DBC_INV;
318 }
319
320
322 void sqr__1() {
323 mpz_mul( mpq_numref(q_), mpq_numref(q_), mpq_numref(q_) );
324 mpz_mul( mpq_denref(q_), mpq_denref(q_), mpq_denref(q_) );
325
326 DBC_INV;
327 }
328
329
331 void half__1() {
332 mpq_div_2exp( q_, q_, 1 );
333
334 DBC_INV;
335 }
336
337
340 void reciprocal__1( OpError & p_ec ) {
341 p_ec = success;
342 if( mpz_sgn( mpq_numref( q_ ) ) == 0 )
343 p_ec = undefinedresult;
344 else
345 mpq_inv( q_, q_ );
346
347 DBC_INV;
348 }
349
350
356 __float128 float128( OpError & p_ec ) const;
357
358};
Algorithms.
Semantic Object Rational Number.
Definition soq.h:43
std::string opequal() const override
String representation of object for operators '=', 'cvs' and 'stack'.
Definition soq.cpp:36
SOQ(const mpq_t p_q)
Ctor from a mpq_t.
Definition soq.h:115
void getNumerator(mpz_t p_z) const
Getter for the numerator of q_.
Definition soq.h:230
SOQ(const __int128 p_num, const __int128 p_den)
Ctor from a numerator and a denominator.
Definition soq.h:128
void neg__1()
In place neg.
Definition soq.h:314
void reciprocal__1(OpError &p_ec)
In place reciprocal.
Definition soq.h:340
bool gt(OpError &p_ec, const SO *p_other) const override
Greater than.
Definition soq.h:183
~SOQ() override
Dtor.
Definition soq.h:142
void abs__1()
In place abs.
Definition soq.h:306
OTCode ot() const override
Returns an OTCode.
Definition soq.h:162
void setNumerator(mpz_t p_z)
Setter for the numerator of q_.
Definition soq.h:236
bool isinteger() const
Checks denominator == 1.
Definition soq.h:272
SOQ(std::string &p_s)
Ctor from a string representation.
Definition soq.h:103
bool getComponents(__int128 &p_num, __int128 &p_den) const
Getter for numerator and denominator.
Definition soq.h:249
SOQ * dup() const override
Creates a new instance as copy following the red book definition.
Definition soq.h:156
bool ge(OpError &p_ec, const SO *p_other) const override
Greater or equal.
Definition soq.h:199
void divqr(mpq_t p_q, mpq_t p_r) const
Calculates quotient and remainder.
Definition soq.h:281
size_t str_length() const
Calculates an upper limit of the maximum length of the string representation of q_.
Definition soq.h:52
bool invariant() const noexcept override
Checks class invariants.
Definition soq.h:77
void half__1()
In place half value.
Definition soq.h:331
bool parse(std::string &p_str)
Parses a string representation of a rational number.
Definition soq.h:295
bool parse_work(std::string &p_str)
Parses a string representation of a rational number.
Definition soq.cpp:65
void getRational(mpq_t p_q) const
Getter for q_.
Definition soq.h:215
void setRational(const mpq_t p_q)
Setter for the rational number.
Definition soq.h:221
__float128 float128(OpError &p_ec) const
Converts the rational number to a real number.
Definition soq.cpp:48
void sqr__1()
In place sqr.
Definition soq.h:322
bool equal(const SO *p_other) const override
Checks if this SO is equal to another SO.
Definition soq.h:170
SOQ()
Ctor.
Definition soq.h:92
bool isunitfraction() const
Checks numerator == 1.
Definition soq.h:265
std::string_view type() const override
Returns a type name.
Definition soq.h:165
mpq_t q_
The rational number by GMP.
Definition soq.h:47
Semantic Object.
Definition so.h:67
virtual OTCode ot() const =0
Returns an OTCode.
Conversion functions.
Helpers for design by contract idioms.
#define DBC_INV_CTOR(T)
Assert for invariant checks in ctors and dtors.
Definition dbc.h:122
#define DBC_INV
Assert for invariant checks in member functions.
Definition dbc.h:114
#define DBC_PRE(XXX)
Assert for preconditions.
Definition dbc.h:104
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:67
bool hasRationalSyntax(const std::string &p_str)
Checks, if the string has the syntax of a rational number.
Definition algo.cpp:125
std::pair< bool, __int128 > mpz_t_to___int128(const mpz_t p_src)
Converts a mpz_t into an __int128.
Definition conversion.cpp:99
void __int128_to_mpz_t(mpz_t p_dst, __int128 p_src)
Converts an __int128 into a mpz_t.
Definition conversion.cpp:135
The class SO - semantic object.
OTCode
OTCode - the Object Type Code.
Definition so.h:38
@ o
SOo.
@ Q
SOQ.