Leonardus
soq.h
Go to the documentation of this file.
1
17#pragma once
18
19#include <string>
20#include <gmp.h>
21
22#include "adapter128.h"
23#include "dbc.h"
24#include "helper.h"
25#include "error.h"
26#include "so.h"
27
28
34class SOQ : public SO {
35
36 mpq_t q_;
39 size_t str_length() const {
40 const size_t num_size = mpz_sizeinbase(mpq_numref(q_), 10);
41 const size_t den_size = mpz_sizeinbase(mpq_denref(q_), 10);
42 // +3 for opional '-' and '/' and '\0'
43 return num_size + den_size + 3;
44 }
45
46protected:
47#ifndef DBC_IS_VOID
51 bool invariant() const noexcept override { /* LCOV_EXCL_START */
52 if( mpz_sgn( mpq_denref( q_ ) ) != 1 )
53 return false;
54 mpz_t g;
55 mpz_init( g );
56 mpz_gcd( g, mpq_numref(q_), mpq_denref(q_) );
57 int rv = mpz_cmp_si( g, 1 );
58 mpz_clear( g );
59 return rv == 0;
60 } /* LCOV_EXCL_STOP */
61#endif
62
63public:
65 SOQ() {
66 mpq_init( q_ );
67
69 }
70
72 SOQ( const mpq_t p_q ) {
73 mpq_init( q_ );
74 mpq_set( q_, p_q );
75
77 }
78
80 SOQ( const __int128 p_num, const __int128 p_den ) {
81 mpq_init( q_ );
82
83 if( p_den == 0 )
84 opErrExit( undefined ); // IDEA: how to handle the problem without an exit() in the ctor?
85 __int128_to_mpz_t( mpq_numref( q_ ), p_num );
86 __int128_to_mpz_t( mpq_denref( q_ ), p_den );
87 mpq_canonicalize( q_ );
88
90 }
91
93 ~SOQ() {
94 DBC_INV;
95
96 mpq_clear( q_ );
97 }
98
99public: /* virtual */
100 [[nodiscard]] SOQ * dup() const override { return new SOQ( q_ ); }
101
102 std::string opequal() const override {
103 char * buffer = new char[ str_length() ];
104 mpq_get_str( buffer, 10, q_ );
105 std::string str( buffer );
106 delete[] buffer;
107 return str;
108 }
109
110 OTCode ot() const override { return OTCode::Q; }
111
112 std::string type() const override { return "rationaltype"; }
113
114 bool equal( const SO * p_other ) const override {
115 auto o = dynamic_cast<const SOQ*>( p_other );
116 return o ? mpq_equal( q_, o->q_) : false;
117 }
118
119 bool gt( const SO * p_other ) const override {
120 auto o = dynamic_cast<const SOQ*>( p_other );
121 if( o == nullptr )
123 return mpq_cmp( q_, o->q_) > 0;
124 }
125
126 bool ge( const SO * p_other ) const override {
127 auto o = dynamic_cast<const SOQ*>( p_other );
128 if( o == nullptr )
130 return mpq_cmp( q_, o->q_) >= 0;
131 }
132
133public: /* accessor */
135 void getRational( mpq_t p_q ) const {
136 mpq_set( p_q, q_ );
137 }
138
140 void setRational( const mpq_t p_q ) {
141 mpq_set( q_, p_q );
142
143 DBC_INV;
144 }
145
149 bool getComponents( __int128 & p_num, __int128 & p_den ) const {
150 if( ! mpz_t_to___int128( p_num, mpq_numref( q_ ) ) )
151 return false;
152 if( ! mpz_t_to___int128( p_den, mpq_denref( q_ ) ) )
153 return false;
154 return true;
155 }
156
157public: /* other */
160 bool isunitfraction() const {
161 return mpz_cmp_ui( mpq_numref(q_), 1u ) == 0;
162 }
163
166 void divqr( mpq_t p_q, mpq_t p_r ) const {
167 mpz_set_ui( mpq_denref( p_q ), 1u ); // set the denominator of p_q = 1
168 mpz_set( mpq_denref( p_r ), mpq_denref( q_ ) ); // set the denominator of p_r = denominator of q_
169 mpz_fdiv_qr( mpq_numref(p_q), mpq_numref(p_r), mpq_numref(q_), mpq_denref(q_) );
170 }
171
178 bool parse( std::string p_str ) {
179 if( mpq_set_str( q_, p_str.c_str(), 10 ) != 0 )
180 return false;
181 if( mpz_sgn( mpq_denref( q_ ) ) == 0 )
182 return false;
183 mpq_canonicalize( q_ );
184
185 DBC_INV;
186 return true;
187 }
188
190 void abs() {
191 mpq_abs( q_, q_ );
192
193 DBC_INV;
194 }
195
197 void neg() {
198 mpq_neg( q_, q_ );
199
200 DBC_INV;
201 }
202
204 void reciprocal() {
205 if( mpz_sgn( mpq_numref( q_ ) ) == 0 )
207 mpq_inv( q_, q_ );
208
209 DBC_INV;
210 }
211
215 __float128 flt128() const;
216};
void __int128_to_mpz_t(mpz_t p_dst, __int128 p_src)
Converts an __int128 into a mpz_t.
Definition: adapter128.cpp:183
bool mpz_t_to___int128(__int128 &p_dst, const mpz_t p_src)
Converts a mpz_t into an __int128.
Definition: adapter128.cpp:145
Adapters for 128 bit versions of standard functions.
Semantic Object Rational Number A multiple precicion rational number.
Definition: soq.h:34
std::string opequal() const override
For operators '=', 'cvs' and 'stack'.
Definition: soq.h:102
SOQ(const mpq_t p_q)
Ctor.
Definition: soq.h:72
SOQ(const __int128 p_num, const __int128 p_den)
Ctor.
Definition: soq.h:80
void reciprocal()
Inplace reciprocal.
Definition: soq.h:204
void abs()
Inplace abs.
Definition: soq.h:190
bool gt(const SO *p_other) const override
Greater than.
Definition: soq.h:119
std::string type() const override
Returns a type name.
Definition: soq.h:112
OTCode ot() const override
Returns an OTCode.
Definition: soq.h:110
bool getComponents(__int128 &p_num, __int128 &p_den) const
Set the parameters to numerator and denominator.
Definition: soq.h:149
SOQ * dup() const override
Creates a new instance as copy following the red book definition.
Definition: soq.h:100
bool parse(std::string p_str)
Parses the string for a presentation of a rational.
Definition: soq.h:178
~SOQ()
Dtor.
Definition: soq.h:93
void divqr(mpq_t p_q, mpq_t p_r) const
Calculates quotient and remainder.
Definition: soq.h:166
bool ge(const SO *p_other) const override
Greater or equal.
Definition: soq.h:126
size_t str_length() const
Size of the string representation in characters.
Definition: soq.h:39
bool invariant() const noexcept override
Checks class invariants.
Definition: soq.h:51
void neg()
Inplace neg.
Definition: soq.h:197
void getRational(mpq_t p_q) const
Set the parameter to our value.
Definition: soq.h:135
void setRational(const mpq_t p_q)
Replaces the rational by the parameter.
Definition: soq.h:140
bool equal(const SO *p_other) const override
Equality.
Definition: soq.h:114
SOQ()
Ctor.
Definition: soq.h:65
bool isunitfraction() const
Checks numerator == 1.
Definition: soq.h:160
mpq_t q_
The rational number by GMP.
Definition: soq.h:36
__float128 flt128() const
A real representation of the rational.
Definition: soq.cpp:27
Semantic Object.
Definition: so.h:54
Helpers for design by contract idioms.
#define DBC_INV_CTOR(T)
Assert for invariant checks in ctors and dtors.
Definition: dbc.h:88
#define DBC_INV
Assert for invariant checks in member functions.
Definition: dbc.h:83
void opErrExit(OpError p_err, const std::string &p_details, const std::source_location p_location)
Operator error message to interpreter cout_ and exit( EC_OPERATOR ).
Definition: error.cpp:28
Error handling.
@ undefinedresult
PS operator error undefinedresult.
Definition: error.h:36
@ typecheck
PS operator error typecheck.
Definition: error.h:33
@ undefined
PS operator error undefined.
Definition: error.h:37
Miscellaneous definitions and functions.
The class SO - semantic object.
OTCode
OTCode - the Object Type Code.
Definition: so.h:29
@ o
SOo.
@ Q
SOQ.