LAL: Linear Arrangement Library 24.10.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 - 2024
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 (lluis.alemany.puig@upc.edu)
28 * LQMC (Quantitative, Mathematical, and Computational Linguisitcs)
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 * LQMC (Quantitative, Mathematical, and Computational Linguisitcs)
35 * CQL (Complexity and Quantitative Linguistics Lab)
36 * Office 220, 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
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
88 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
89 integer(const 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
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
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(const 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
164 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
165 integer& operator= (const T i) noexcept
166 {
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
199 // -- EQUALITY
200
205 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
206 [[nodiscard]] bool operator== (const T i) const noexcept {
207 return
208 (std::is_signed_v<T> ? mpz_cmp_si(m_val,i) : mpz_cmp_ui(m_val,i)) == 0;
209 }
210#if !defined __LAL_SWIG_PYTHON
216 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
217 [[nodiscard]] friend bool operator== (const T i, const integer& ii) noexcept
218 { return ii == i; }
219#endif
224 [[nodiscard]] bool operator== (const integer& i) const noexcept
225 { return mpz_cmp(m_val, i.m_val) == 0; }
226
227 // -- NON-EQUALITY
228
233 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
234 [[nodiscard]] bool operator!= (const T i) const noexcept
235 { return not (*this == i); }
236#if !defined __LAL_SWIG_PYTHON
242 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
243 [[nodiscard]] friend bool operator!= (const T i, const integer& ii) noexcept
244 { return ii != i; }
245#endif
250 [[nodiscard]] bool operator!= (const integer& i) const noexcept
251 { return not (*this == i); }
252
253 // -- LESS THAN
254
259 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
260 [[nodiscard]] bool operator< (const T i) const noexcept {
261 return
262 (std::is_signed_v<T> ? mpz_cmp_si(m_val, i) : mpz_cmp_ui(m_val, i)) < 0;
263 }
264#if !defined __LAL_SWIG_PYTHON
270 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
271 [[nodiscard]] friend bool operator< (const T i, const integer& ii) noexcept
272 { return ii > i; }
273#endif
278 [[nodiscard]] bool operator< (const integer& i) const noexcept
279 { return mpz_cmp(m_val, i.m_val) < 0; }
280
281 // -- LESS THAN OR EQUAL TO
282
287 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
288 [[nodiscard]] bool operator<= (const T i) const noexcept {
289 return
290 (std::is_signed_v<T> ? mpz_cmp_si(m_val, i) : mpz_cmp_ui(m_val, i)) <= 0;
291 }
292#if !defined __LAL_SWIG_PYTHON
298 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
299 [[nodiscard]] friend bool operator<= (const T i, const integer& ii) noexcept
300 { return ii >= i; }
301#endif
306 [[nodiscard]] bool operator<= (const integer& i) const noexcept
307 { return mpz_cmp(m_val, i.m_val) <= 0; }
308
309 // -- GREATER THAN
310
315 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
316 [[nodiscard]] bool operator> (const T i) const noexcept {
317 return
318 (std::is_signed_v<T> ? mpz_cmp_si(m_val, i) : mpz_cmp_ui(m_val, i)) > 0;
319 }
320#if !defined __LAL_SWIG_PYTHON
326 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
327 [[nodiscard]] friend bool operator> (const T i, const integer& ii) noexcept
328 { return ii < i; }
329#endif
334 [[nodiscard]] bool operator> (const integer& i) const noexcept
335 { return mpz_cmp(m_val, i.m_val) > 0; }
336
337 // -- GREATER THAN OR EQUAL TO
338
343 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
344 [[nodiscard]] bool operator>= (const T i) const noexcept {
345 return
346 (std::is_signed_v<T> ? mpz_cmp_si(m_val, i) : mpz_cmp_ui(m_val, i)) >= 0;
347 }
348#if !defined __LAL_SWIG_PYTHON
354 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
355 [[nodiscard]] friend bool operator>= (const T i, const integer& ii) noexcept
356 { return ii <= i; }
357#endif
362 [[nodiscard]] bool operator>= (const integer& i) const noexcept
363 { return mpz_cmp(m_val, i.m_val) >= 0; }
364
365 /* ARITHMETIC OPERATORS */
366
367 // -- ADDITION
368
373 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
374 [[nodiscard]] integer operator+ (const T i) const noexcept
375 { integer a(*this); a += i; return a; }
376#if !defined __LAL_SWIG_PYTHON
382 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
383 [[nodiscard]] friend integer operator+ (const T i, const integer& ii) noexcept
384 { return ii + i; }
385#endif
390 [[nodiscard]] integer operator+ (const integer& i) const noexcept
391 { integer a(*this); a += i; return a; }
396 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
397 integer& operator+= (const T i) noexcept {
398 if constexpr (not std::is_signed_v<T>) { mpz_add_ui(m_val, m_val, i); }
399 else {
400 if (i > 0) {mpz_add_ui(m_val, m_val, static_cast<uint64_t>(i)); }
401 else { mpz_sub_ui(m_val, m_val, static_cast<uint64_t>(-i));}
402 }
403 return *this;
404 }
409 integer& operator+= (const integer& i) noexcept
410 { mpz_add(m_val, m_val, i.m_val); return *this; }
411
412 // -- SUBSTRACTION
413
415 [[nodiscard]] integer operator- () const noexcept
416 { integer a(*this); mpz_neg(a.m_val, a.m_val); return a; }
421 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
422 [[nodiscard]] integer operator- (const T i) const noexcept
423 { integer a(*this); a -= i; return a; }
424#if !defined __LAL_SWIG_PYTHON
430 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
431 [[nodiscard]] friend integer operator- (const T i, const integer& ii) noexcept
432 { return -ii + i; }
433#endif
438 [[nodiscard]] integer operator- (const integer& i) const noexcept
439 { integer a(*this); a -= i; return a; }
444 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
445 integer& operator-= (const T i) noexcept {
446 if constexpr (not std::is_signed_v<T>) { mpz_sub_ui(m_val, m_val, i); }
447 else {
448 if (i > 0) {mpz_sub_ui(m_val, m_val, static_cast<uint64_t>(i)); }
449 else { mpz_add_ui(m_val, m_val, static_cast<uint64_t>(-i));}
450 }
451 return *this;
452 }
457 integer& operator-= (const integer& i) noexcept
458 { mpz_sub(m_val, m_val, i.m_val); return *this; }
459
460 // -- MULTIPLICATION
461
466 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
467 [[nodiscard]] integer operator* (const T i) const noexcept
468 { integer a(*this); a *= i; return a; }
469#if !defined __LAL_SWIG_PYTHON
475 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
476 [[nodiscard]] friend integer operator* (const T i, const integer& ii) noexcept
477 { return ii*i; }
478#endif
479
484 [[nodiscard]] integer operator* (const integer& i) const noexcept
485 { integer a(*this); a *= i; return a; }
490 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
491 integer& operator*= (const T i) noexcept {
492 if constexpr (std::is_signed_v<T>) { mpz_mul_si(m_val, m_val, i); }
493 else { mpz_mul_ui(m_val, m_val, i); }
494 return *this;
495 }
500 integer& operator*= (const integer& i) noexcept
501 { mpz_mul(m_val, m_val, i.m_val); return *this; }
502
503 // -- DIVISION
504
509 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
510 [[nodiscard]] integer operator/ (const T i) const noexcept
511 { integer a(*this); a /= i; return a; }
512#if !defined __LAL_SWIG_PYTHON
518 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
519 [[nodiscard]] friend int64_t operator/ (const T i, const integer& ii) noexcept
520 { return i/ii.to_int(); }
521#endif
526 [[nodiscard]] integer operator/ (const integer& i) const noexcept
527 { integer a(*this); a /= i; return a; }
532 template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
533 integer& operator/= (const T i) noexcept {
534 if constexpr (not std::is_signed_v<T>) {
535 mpz_fdiv_q_ui(m_val, m_val, i);
536 }
537 else {
538 mpz_fdiv_q_ui(m_val, m_val, static_cast<uint64_t>(i<0 ? -i : i));
539 mpz_mul_si(m_val, m_val, (i<0 ? -1 : 1));
540 }
541 return *this;
542 }
547 integer& operator/= (const integer& i) noexcept
548 { mpz_div(m_val, m_val, i.m_val); return *this; }
549
550 // -- EXPONENTIATION
551
556 [[nodiscard]] integer power(const uint64_t i) const noexcept
557 { integer r(*this); r.powt(i); return r; }
562 [[nodiscard]] integer power(const integer& i) const noexcept
563 { integer r(*this); r.powt(i); return r; }
564
571 integer& powt(const uint64_t i) noexcept
572 { mpz_pow_ui(m_val, m_val, i); return *this; }
579 integer& powt(const integer& i) noexcept;
580
581 // -- MODULUS
582
587 [[nodiscard]] uint64_t operator% (const uint64_t i) const noexcept {
588 mpz_t r;
589 mpz_init(r);
590 const uint64_t m = mpz_mod_ui(r, m_val, i);
591 mpz_clear(r);
592 return m;
593 }
598 [[nodiscard]] integer operator% (const integer& i) const noexcept {
599 integer r;
600 mpz_mod(r.m_val, m_val, i.m_val);
601 return r;
602 }
603
604 /* GETTERS */
605
607 [[nodiscard]] constexpr bool is_initialized() const noexcept { return m_initialized; }
609 [[nodiscard]] int64_t get_sign() const noexcept { return mpz_sgn(m_val); }
610
612 [[nodiscard]] std::size_t bytes() const noexcept;
614 [[nodiscard]] const mpz_t& get_raw_value() const noexcept { return m_val; }
615
616 /* CONVERTERS */
617
619 [[nodiscard]] int64_t to_int() const noexcept { return mpz_get_si(m_val); }
621 [[nodiscard]] uint64_t to_uint() const noexcept { return mpz_get_ui(m_val); }
623 [[nodiscard]] double to_double() const noexcept { return mpz_get_d(m_val); }
624
626 [[nodiscard]] std::string to_string() const noexcept {
627 std::string k;
628 as_string(k);
629 return k;
630 }
635 void as_string(std::string& s) const noexcept {
636 char *buf = nullptr;
637 buf = mpz_get_str(buf, 10, m_val);
638 s = std::string(buf);
639 free(buf);
640 }
641
642 /* OTHERS */
643
655 void swap(integer& i) noexcept { mpz_swap(m_val, i.m_val); }
656
657#if !defined __LAL_SWIG_PYTHON
663 friend void swap(integer& i, integer& j) noexcept {
664 i.swap(j);
665 }
666#endif
667
668private:
670 mpz_t m_val;
672 bool m_initialized = true;
673};
674
675} // -- namespace numeric
676} // -- namespace lal
Arbitrary precision integer.
Definition integer.hpp:60
integer & operator+=(const T i) noexcept
Addition operator.
Definition integer.hpp:397
friend bool operator>(const T i, const integer &ii) noexcept
Greater than operator.
Definition integer.hpp:327
int64_t to_int() const noexcept
Converts this integer to a signed 64-bit integer.
Definition integer.hpp:619
void swap(integer &i) noexcept
Swaps the value of this integer with integer i's value.
Definition integer.hpp:655
int64_t get_sign() const noexcept
Returns the sign of this integer.
Definition integer.hpp:609
integer & operator*=(const T i) noexcept
Product operator.
Definition integer.hpp:491
friend bool operator>=(const T i, const integer &ii) noexcept
Greater than or equal to operator.
Definition integer.hpp:355
void as_string(std::string &s) const noexcept
Converts this integer to a string.
Definition integer.hpp:635
integer operator-() const noexcept
Minus unary operator. Returns a new object of type 'integer'.
Definition integer.hpp:415
friend bool operator==(const T i, const integer &ii) noexcept
Equality operator.
Definition integer.hpp:217
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.
friend integer operator*(const T i, const integer &ii) noexcept
Product operator.
Definition integer.hpp:476
integer(const integer &i) noexcept
Copy constructor.
Definition integer.hpp:119
friend void swap(integer &i, integer &j) noexcept
Swaps two integers.
Definition integer.hpp:663
friend bool operator<=(const T i, const integer &ii) noexcept
Less than or equal to operator.
Definition integer.hpp:299
integer & operator/=(const T i) noexcept
Division operator.
Definition integer.hpp:533
void set_str(const std::string &s) noexcept
Overwrites the value of this integer with s.
Definition integer.hpp:150
friend bool operator!=(const T i, const integer &ii) noexcept
Non-equality operator.
Definition integer.hpp:243
mpz_t m_val
Structure from GMP storing the integer's value.
Definition integer.hpp:670
integer power(const uint64_t i) const noexcept
Exponentiation operator.
Definition integer.hpp:556
uint64_t to_uint() const noexcept
Converts this integer to an unsigned 64-bit integer.
Definition integer.hpp:621
integer(mpz_t &&raw) noexcept
Constructor with mpz_t.
Definition integer.hpp:73
bool m_initialized
Is this integer initialized?
Definition integer.hpp:672
std::string to_string() const noexcept
Converts this integer to a string.
Definition integer.hpp:626
integer(const T i) noexcept
Constructor with unsigned integer value.
Definition integer.hpp:89
friend int64_t operator/(const T i, const integer &ii) noexcept
Division operator.
Definition integer.hpp:519
integer(integer &&i) noexcept
Move constructor.
Definition integer.hpp:104
integer power(const integer &i) const noexcept
Exponentiation operator.
Definition integer.hpp:562
integer & powt(const uint64_t i) noexcept
Exponentiation operator.
Definition integer.hpp:571
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() noexcept
Destructor.
Definition integer.hpp:121
friend integer operator+(const T i, const integer &ii) noexcept
Addition operator.
Definition integer.hpp:383
double to_double() const noexcept
Converts this integer to a double-precision floating-point value.
Definition integer.hpp:623
const mpz_t & get_raw_value() const noexcept
Returns the underlying gmp data structure.
Definition integer.hpp:614
integer & operator-=(const T i) noexcept
Substraction operator.
Definition integer.hpp:445
uint64_t operator%(const uint64_t i) const noexcept
Modulus operator.
Definition integer.hpp:587
constexpr bool is_initialized() const noexcept
Returns whether this object is initialized or not.
Definition integer.hpp:607
void set_number(const T i) noexcept
Overwrites the value of this integer with i.
Definition integer.hpp:130
integer & operator=(const T i) noexcept
Assignment operator.
Definition integer.hpp:165
friend bool operator<(const T i, const integer &ii) noexcept
Less operator.
Definition integer.hpp:271
Exact rational number.
Definition rational.hpp:63
Main namespace of the library.
Definition basic_types.hpp:48