LAL: Linear Arrangement Library 23.01.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
integer.hpp
1/*********************************************************************
2 *
3 * Linear Arrangement Library - A library that implements a collection
4 * algorithms for linear arrangments of graphs.
5 *
6 * Copyright (C) 2019 - 2023
7 *
8 * This file is part of Linear Arrangement Library. The full code is available
9 * at:
10 * https://github.com/LAL-project/linear-arrangement-library.git
11 *
12 * Linear Arrangement Library is free software: you can redistribute it
13 * and/or modify it under the terms of the GNU Affero General Public License
14 * as published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * Linear Arrangement Library is distributed in the hope that it will be
18 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Affero General Public License for more details.
21 *
22 * You should have received a copy of the GNU Affero General Public License
23 * along with Linear Arrangement Library. If not, see <http://www.gnu.org/licenses/>.
24 *
25 * Contact:
26 *
27 * LluĂ­s Alemany Puig (lalemany@cs.upc.edu)
28 * LARCA (Laboratory for Relational Algorithmics, Complexity and Learning)
29 * CQL (Complexity and Quantitative Linguistics Lab)
30 * Jordi Girona St 1-3, Campus Nord UPC, 08034 Barcelona. CATALONIA, SPAIN
31 * Webpage: https://cqllab.upc.edu/people/lalemany/
32 *
33 * Ramon Ferrer i Cancho (rferrericancho@cs.upc.edu)
34 * LARCA (Laboratory for Relational Algorithmics, Complexity and Learning)
35 * CQL (Complexity and Quantitative Linguistics Lab)
36 * Office S124, Omega building
37 * Jordi Girona St 1-3, Campus Nord UPC, 08034 Barcelona. CATALONIA, SPAIN
38 * Webpage: https://cqllab.upc.edu/people/rferrericancho/
39 *
40 ********************************************************************/
41
42#pragma once
43
44// gmp includes
45#include <gmp.h>
46
47// C++ includes
48#include <cstdint>
49#include <string>
50
51namespace lal {
52namespace numeric {
53
60class integer {
61public:
62 friend class rational;
63public:
64 /* CONSTRUCTORS */
65
67 integer() noexcept { mpz_init(m_val); }
68#ifndef SWIG
73 integer(mpz_t&& raw) noexcept {
74 // move raw's contents
75 *m_val = *raw;
76 m_initialized = true;
77
78 // invalidate raw's contents
79 raw->_mp_alloc = 0;
80 raw->_mp_size = 0;
81 raw->_mp_d = nullptr;
82 }
83#endif
88 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
89 integer(T i) noexcept {
90 if constexpr (std::is_signed_v<T>) { mpz_init_set_si(m_val, i); }
91 else { mpz_init_set_ui(m_val, i); }
92 }
97 integer(const std::string& s) noexcept { mpz_init_set_str(m_val, s.c_str(), 10); }
98#ifndef SWIG
104 integer(integer&& i) noexcept {
105 // move i's contents
106 *m_val = *i.m_val;
107
108 // invalidate i's contents
109 i.m_val->_mp_alloc = 0;
110 i.m_val->_mp_size = 0;
111 i.m_val->_mp_d = nullptr;
112 i.m_initialized = false;
113 }
114#endif
119 integer(const integer& i) noexcept { mpz_init_set(m_val, i.m_val); }
121 ~integer() noexcept { mpz_clear(m_val); }
122
123 /* SETTERS */
124
129 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
130 void set_number(T i) noexcept {
131 if (not is_initialized()) { mpz_init(m_val); }
132 if constexpr (std::is_signed_v<T>) { mpz_set_si(m_val, i); }
133 else { mpz_set_ui(m_val, i); }
134 m_initialized = true;
135 }
136
141 void set_integer(const integer& i) noexcept {
142 if (not is_initialized()) { mpz_init(m_val); }
143 mpz_set(m_val, i.m_val);
144 m_initialized = true;
145 }
150 void set_str(const std::string& s) noexcept {
151 if (not is_initialized()) { mpz_init(m_val); }
152 mpz_set_str(m_val, s.c_str(), 10);
153 m_initialized = true;
154 }
155
156 /* OPERATORS */
157
158 // -- ASSIGNMENT
159
160#ifndef SWIG
165 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
166 integer& operator= (T i) noexcept {
167 set_number(i);
168 return *this;
169 }
174 integer& operator= (const integer& i) noexcept {
175 set_integer(i);
176 return *this;
177 }
183 integer& operator= (integer&& i) noexcept {
184 mpz_clear(m_val);
185
186 // move i's contents
187 *m_val = *i.m_val;
188 m_initialized = true;
189
190 // invalidate i's contents
191 i.m_val->_mp_alloc = 0;
192 i.m_val->_mp_size = 0;
193 i.m_val->_mp_d = nullptr;
194 i.m_initialized = false;
195
196 return *this;
197 }
198#endif
199
200 // -- EQUALITY
201
206 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
207 bool operator== (T i) const noexcept {
208 return
209 (std::is_signed_v<T> ? mpz_cmp_si(m_val,i) : mpz_cmp_ui(m_val,i)) == 0;
210 }
211#ifndef SWIG
217 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
218 friend bool operator== (T i, const integer& ii) noexcept
219 { return ii == i; }
220#endif
225 bool operator== (const integer& i) const noexcept
226 { return mpz_cmp(m_val, i.m_val) == 0; }
227
228 // -- NON-EQUALITY
229
234 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
235 bool operator!= (T i) const noexcept
236 { return not (*this == i); }
237#ifndef SWIG
243 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
244 friend bool operator!= (T i, const integer& ii) noexcept
245 { return ii != i; }
246#endif
251 bool operator!= (const integer& i) const noexcept
252 { return not (*this == i); }
253
254 // -- LESS THAN
255
260 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
261 bool operator< (T i) const noexcept {
262 return
263 (std::is_signed_v<T> ? mpz_cmp_si(m_val, i) : mpz_cmp_ui(m_val, i)) < 0;
264 }
265#ifndef SWIG
271 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
272 friend bool operator< (T i, const integer& ii) noexcept
273 { return ii > i; }
274#endif
279 bool operator< (const integer& i) const noexcept
280 { return mpz_cmp(m_val, i.m_val) < 0; }
281
282 // -- LESS THAN OR EQUAL TO
283
288 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
289 bool operator<= (T i) const noexcept {
290 return
291 (std::is_signed_v<T> ? mpz_cmp_si(m_val, i) : mpz_cmp_ui(m_val, i)) <= 0;
292 }
293#ifndef SWIG
299 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
300 friend bool operator<= (T i, const integer& ii) noexcept
301 { return ii >= i; }
302#endif
307 bool operator<= (const integer& i) const noexcept
308 { return mpz_cmp(m_val, i.m_val) <= 0; }
309
310 // -- GREATER THAN
311
316 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
317 bool operator> (T i) const noexcept {
318 return
319 (std::is_signed_v<T> ? mpz_cmp_si(m_val, i) : mpz_cmp_ui(m_val, i)) > 0;
320 }
321#ifndef SWIG
327 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
328 friend bool operator> (T i, const integer& ii) noexcept
329 { return ii < i; }
330#endif
335 bool operator> (const integer& i) const noexcept
336 { return mpz_cmp(m_val, i.m_val) > 0; }
337
338 // -- GREATER THAN OR EQUAL TO
339
344 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
345 bool operator>= (T i) const noexcept {
346 return
347 (std::is_signed_v<T> ? mpz_cmp_si(m_val, i) : mpz_cmp_ui(m_val, i)) >= 0;
348 }
349#ifndef SWIG
355 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
356 friend bool operator>= (T i, const integer& ii) noexcept
357 { return ii <= i; }
358#endif
363 bool operator>= (const integer& i) const noexcept
364 { return mpz_cmp(m_val, i.m_val) >= 0; }
365
366 /* ARITHMETIC OPERATORS */
367
368 // -- ADDITION
369
374 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
375 integer operator+ (T i) const noexcept
376 { integer a(*this); a += i; return a; }
377#ifndef SWIG
383 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
384 friend integer operator+ (T i, const integer& ii) noexcept
385 { return ii + i; }
386#endif
391 integer operator+ (const integer& i) const noexcept
392 { integer a(*this); a += i; return a; }
397 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
398 integer& operator+= (T i) noexcept {
399 if constexpr (not std::is_signed_v<T>) { mpz_add_ui(m_val, m_val, i); }
400 else {
401 if (i > 0) {mpz_add_ui(m_val, m_val, static_cast<uint64_t>(i)); }
402 else { mpz_sub_ui(m_val, m_val, static_cast<uint64_t>(-i));}
403 }
404 return *this;
405 }
410 integer& operator+= (const integer& i) noexcept
411 { mpz_add(m_val, m_val, i.m_val); return *this; }
412
413 // -- SUBSTRACTION
414
416 integer operator- () const noexcept
417 { integer a(*this); mpz_neg(a.m_val, a.m_val); return a; }
422 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
423 integer operator- (T i) const noexcept
424 { integer a(*this); a -= i; return a; }
425#ifndef SWIG
431 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
432 friend integer operator- (T i, const integer& ii) noexcept
433 { return -ii + i; }
434#endif
439 integer operator- (const integer& i) const noexcept
440 { integer a(*this); a -= i; return a; }
445 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
446 integer& operator-= (T i) noexcept {
447 if constexpr (not std::is_signed_v<T>) { mpz_sub_ui(m_val, m_val, i); }
448 else {
449 if (i > 0) {mpz_sub_ui(m_val, m_val, static_cast<uint64_t>(i)); }
450 else { mpz_add_ui(m_val, m_val, static_cast<uint64_t>(-i));}
451 }
452 return *this;
453 }
458 integer& operator-= (const integer& i) noexcept
459 { mpz_sub(m_val, m_val, i.m_val); return *this; }
460
461 // -- MULTIPLICATION
462
467 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
468 integer operator* (T i) const noexcept
469 { integer a(*this); a *= i; return a; }
470#ifndef SWIG
476 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
477 friend integer operator* (T i, const integer& ii) noexcept
478 { return ii*i; }
479#endif
480
485 integer operator* (const integer& i) const noexcept
486 { integer a(*this); a *= i; return a; }
491 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
492 integer& operator*= (T i) noexcept {
493 if constexpr (std::is_signed_v<T>) { mpz_mul_si(m_val, m_val, i); }
494 else { mpz_mul_ui(m_val, m_val, i); }
495 return *this;
496 }
501 integer& operator*= (const integer& i) noexcept
502 { mpz_mul(m_val, m_val, i.m_val); return *this; }
503
504 // -- DIVISION
505
510 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
511 integer operator/ (T i) const noexcept
512 { integer a(*this); a /= i; return a; }
513#ifndef SWIG
519 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
520 friend int64_t operator/ (T i, const integer& ii) noexcept
521 { return i/ii.to_int(); }
522#endif
527 integer operator/ (const integer& i) const noexcept
528 { integer a(*this); a /= i; return a; }
533 template <typename T,std::enable_if_t<std::is_integral_v<T>, bool> = true>
534 integer& operator/= (T i) noexcept {
535 if constexpr (not std::is_signed_v<T>) {
536 mpz_fdiv_q_ui(m_val, m_val, i);
537 }
538 else {
539 mpz_fdiv_q_ui(m_val, m_val, static_cast<uint64_t>(i<0 ? -i : i));
540 mpz_mul_si(m_val, m_val, (i<0 ? -1 : 1));
541 }
542 return *this;
543 }
548 integer& operator/= (const integer& i) noexcept
549 { mpz_div(m_val, m_val, i.m_val); return *this; }
550
551 // -- EXPONENTIATION
552
557 integer power(uint64_t i) const noexcept
558 { integer r(*this); r.powt(i); return r; }
563 integer power(const integer& i) const noexcept
564 { integer r(*this); r.powt(i); return r; }
565
572 integer& powt(uint64_t i) noexcept
573 { mpz_pow_ui(m_val, m_val, i); return *this; }
580 integer& powt(const integer& i) noexcept;
581
582 // -- MODULUS
583
588 uint64_t operator% (uint64_t i) const noexcept {
589 mpz_t r;
590 mpz_init(r);
591 const uint64_t m = mpz_mod_ui(r, m_val, i);
592 mpz_clear(r);
593 return m;
594 }
599 integer operator% (const integer& i) const noexcept {
600 integer r;
601 mpz_mod(r.m_val, m_val, i.m_val);
602 return r;
603 }
604
605 /* GETTERS */
606
608 constexpr bool is_initialized() const noexcept { return m_initialized; }
610 int64_t get_sign() const noexcept { return mpz_sgn(m_val); }
611
613 std::size_t bytes() const noexcept;
615 const mpz_t& get_raw_value() const noexcept { return m_val; }
616
617 /* CONVERTERS */
618
620 int64_t to_int() const noexcept { return mpz_get_si(m_val); }
622 uint64_t to_uint() const noexcept { return mpz_get_ui(m_val); }
624 double to_double() const noexcept { return mpz_get_d(m_val); }
625
627 std::string to_string() const noexcept {
628 std::string k;
629 as_string(k);
630 return k;
631 }
636 void as_string(std::string& s) const noexcept {
637 char *buf = nullptr;
638 buf = mpz_get_str(buf, 10, m_val);
639 s = std::string(buf);
640 free(buf);
641 }
642
643 /* OTHERS */
644
656 void swap(integer& i) noexcept { mpz_swap(m_val, i.m_val); }
657
658#ifndef SWIG
664 friend void swap(integer& i, integer& j) noexcept {
665 i.swap(j);
666 }
667#endif
668
669private:
671 mpz_t m_val;
673 bool m_initialized = true;
674};
675
676} // -- namespace numeric
677} // -- namespace lal
Arbitrary precision integer.
Definition: integer.hpp:60
int64_t to_int() const noexcept
Converts this integer to a signed 64-bit integer.
Definition: integer.hpp:620
void swap(integer &i) noexcept
Swaps the value of this integer with integer i's value.
Definition: integer.hpp:656
integer(T i) noexcept
Constructor with unsigned integer value.
Definition: integer.hpp:89
int64_t get_sign() const noexcept
Returns the sign of this integer.
Definition: integer.hpp:610
integer & operator=(T i) noexcept
Assignment operator.
Definition: integer.hpp:166
void set_number(T i) noexcept
Overwrites the value of this integer with i.
Definition: integer.hpp:130
integer & operator*=(T i) noexcept
Product operator.
Definition: integer.hpp:492
void as_string(std::string &s) const noexcept
Converts this integer to a string.
Definition: integer.hpp:636
friend bool operator!=(T i, const integer &ii) noexcept
Non-equality operator.
Definition: integer.hpp:244
integer & operator-=(T i) noexcept
Substraction operator.
Definition: integer.hpp:446
friend bool operator<=(T i, const integer &ii) noexcept
Less than or equal to operator.
Definition: integer.hpp:300
integer operator-() const noexcept
Minus unary operator. Returns a new object of type 'integer'.
Definition: integer.hpp:416
friend integer operator+(T i, const integer &ii) noexcept
Addition operator.
Definition: integer.hpp:384
integer() noexcept
Empty constructor.
Definition: integer.hpp:67
integer(const std::string &s) noexcept
Constructor with string.
Definition: integer.hpp:97
integer & powt(const integer &i) noexcept
Exponentiation operator.
integer(const integer &i) noexcept
Copy constructor.
Definition: integer.hpp:119
friend int64_t operator/(T i, const integer &ii) noexcept
Division operator.
Definition: integer.hpp:520
friend void swap(integer &i, integer &j) noexcept
Swaps two integers.
Definition: integer.hpp:664
friend bool operator>=(T i, const integer &ii) noexcept
Greater than or equal to operator.
Definition: integer.hpp:356
void set_str(const std::string &s) noexcept
Overwrites the value of this integer with s.
Definition: integer.hpp:150
uint64_t operator%(uint64_t i) const noexcept
Modulus operator.
Definition: integer.hpp:588
mpz_t m_val
Structure from GMP storing the integer's value.
Definition: integer.hpp:671
uint64_t to_uint() const noexcept
Converts this integer to an unsigned 64-bit integer.
Definition: integer.hpp:622
friend bool operator>(T i, const integer &ii) noexcept
Greater than operator.
Definition: integer.hpp:328
integer(mpz_t &&raw) noexcept
Constructor with mpz_t.
Definition: integer.hpp:73
bool m_initialized
Is this integer initialised?
Definition: integer.hpp:673
std::string to_string() const noexcept
Converts this integer to a string.
Definition: integer.hpp:627
integer power(uint64_t i) const noexcept
Exponentiation operator.
Definition: integer.hpp:557
friend bool operator<(T i, const integer &ii) noexcept
Less operator.
Definition: integer.hpp:272
integer(integer &&i) noexcept
Move constructor.
Definition: integer.hpp:104
integer & powt(uint64_t i) noexcept
Exponentiation operator.
Definition: integer.hpp:572
integer power(const integer &i) const noexcept
Exponentiation operator.
Definition: integer.hpp:563
std::size_t bytes() const noexcept
Returns the amount of bytes this integer occupies.
void set_integer(const integer &i) noexcept
Overwrites the value of this integer with i.
Definition: integer.hpp:141
integer & operator/=(T i) noexcept
Division operator.
Definition: integer.hpp:534
~integer() noexcept
Destructor.
Definition: integer.hpp:121
friend integer operator*(T i, const integer &ii) noexcept
Product operator.
Definition: integer.hpp:477
double to_double() const noexcept
Converts this integer to a double-precision floating-point value.
Definition: integer.hpp:624
const mpz_t & get_raw_value() const noexcept
Returns the underlying gmp data structure.
Definition: integer.hpp:615
friend bool operator==(T i, const integer &ii) noexcept
Equality operator.
Definition: integer.hpp:218
integer & operator+=(T i) noexcept
Addition operator.
Definition: integer.hpp:398
constexpr bool is_initialized() const noexcept
Returns whether this object is initialised or not.
Definition: integer.hpp:608
Exact rational number.
Definition: rational.hpp:63
Main namespace of the library.
Definition: basic_types.hpp:50