LAL: Linear Arrangement Library 21.07.01
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
utils.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 - 2021
7 *
8 * This file is part of Linear Arrangement Library. To see the full code
9 * visit the webpage:
10 * https://github.com/lluisalemanypuig/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// C++ includes
45#include <cstdint>
46
47// gmp includes
48#include <gmp.h>
49
50namespace lal {
51namespace internal {
52
53/* Other arithmetic operations */
54
55/*
56 * @brief Computes the exponentiation of a big integer to another big integer.
57 *
58 * Fast exponentiation algorithm.
59 *
60 * This function has, as an exception, its output parameter as its first
61 * parameter.
62 * @param[out] r Result. \f$r = b^e\f$.
63 * @param[in] b Base.
64 * @param[in] e Exponent.
65 */
66void mpz_pow_mpz(mpz_t& r, const mpz_t& b, const mpz_t& e);
67
68/*
69 * @brief Rational-Integer division.
70 *
71 * Divide a rational \f$r\f$ by an integer \f$k\f$.
72 * @param[out] r The rational to be divided by \f$k\f$. Result is \f$r := r/k\f$.
73 * @param[in] k The integer that divides the rational.
74 */
75void mpz_divide_mpq(mpq_t& r, const mpz_t& k);
76
77/*
78 * @brief Rational-Rational division.
79 *
80 * Divide a rational \f$r_1\f$ by another rational \f$r_2\f$.
81 * @param[out] r1 The rational to be divided by \f$k\f$. Result is \f$r_1 := r_1/r_2\f$.
82 * @param[in] r2 The integer that divides the rational.
83 */
84void mpq_divide_mpq(mpq_t& r1, const mpq_t& r2);
85
86/*
87 * @brief Power operation.
88 *
89 * Raise a rational value \f$r\f$ to a certain power \f$p\f$.
90 * @param[out] r Rational value. Result is \f$ r = r^p\f$.
91 * @param[in] p Exponent.
92 */
93void operate_power(mpq_t& r, uint64_t p);
94
95/*
96 * @brief Power operation.
97 *
98 * Raise a rational value \f$r\f$ to a certain power \f$p\f$.
99 * @param[out] r Rational value. Result is \f$ r = r^p\f$.
100 * @param[in] p Exponent.
101 */
102void operate_power(mpq_t& r, const mpz_t& p);
103
104/* Getters of mpz_t objects */
105
106// Return the amount of bytes of a gmp's integer value.
107inline
108size_t mpz_bytes(const mpz_t& v) noexcept {
109 const size_t alloc = static_cast<size_t>(v[0]._mp_alloc);
110 return sizeof(mp_limb_t)*alloc;
111}
112
113/* Moving gmp types */
114
115namespace __lal {
116
117// Move contents of 'source' and give them to 'target'
118inline void move_from_source_to_target
119(__mpz_struct& source, __mpz_struct& target)
120noexcept
121{
122 target._mp_alloc = source._mp_alloc;
123 target._mp_size = source._mp_size;
124 target._mp_d = source._mp_d;
125
126 // We need to make sure 'source' is not going to be
127 // cleared, otherwise we'll loose the contents in *this.
128 source._mp_alloc = 0;
129 source._mp_size = 0;
130 source._mp_d = nullptr;
131}
132
133} // -- namespace __lal
134
135/*
136 * @brief Move the contents from 'source' to 'target'.
137 *
138 * The contents are moved in a way that 'source' no longer has them.
139 * @param[in] source The mpz_t whose contents we want.
140 * @param[out] target The mpz_t with the contents of 'source'.
141 * @pre @e source must be initialised.
142 * @pre Optionally, target can be initialised, but should not have been
143 * assigned any value (otherwise its contents are never going to be freed,
144 * thus causing memory leaks).
145 * @post @e source does not hold any value.
146 */
147inline
148void move_mpz_to_mpz(mpz_t& source, mpz_t& target) noexcept {
149 __lal::move_from_source_to_target(source[0], target[0]);
150}
151
152/*
153 * @brief Move the contents from 'source' to 'target'.
154 *
155 * The contents are moved in a way that 'source' no longer has them.
156 * @param[in] source The mpq_t whose contents we want.
157 * @param[out] target The mpq_t with the contents of 'source'.
158 * @pre @e source must be initialised.
159 * @pre @e target should not be initialised (otherwise its contents
160 * are never going to be freed, thus causing memory leaks).
161 * @post @e source does not hold any value.
162 */
163inline
164void move_mpq_to_mpq(mpq_t& source, mpq_t& target) noexcept {
165 __lal::move_from_source_to_target(source[0]._mp_num, target[0]._mp_num);
166 __lal::move_from_source_to_target(source[0]._mp_den, target[0]._mp_den);
167}
168
169/*
170 * @brief Move the contents from 'source' to 'target'.
171 *
172 * The contents are moved in a way that 'source' no longer has them.
173 * @param[in] source The mpz_t whose contents we want (numerator).
174 * @param[out] target The mpq_t with the contents of 'source'.
175 * @pre @e source must be initialised.
176 * @pre @e target should not be initialised (otherwise its contents
177 * are never going to be freed, thus causing memory leaks).
178 * @post @e source does not hold any value.
179 * @post The denominator of @e target is initialised to 1
180 */
181inline
182void move_mpz_to_mpq(mpz_t& source, mpq_t& target) noexcept {
183 // move numerator
184 __lal::move_from_source_to_target(source[0], target[0]._mp_num);
185 // set the denominator to 1
186 mpz_init_set_ui(&target[0]._mp_den, 1);
187 mpq_canonicalize(target);
188}
189
190/*
191 * @brief Move the contents from 'source' to 'target'.
192 *
193 * The contents are moved in a way that 'source' no longer has them.
194 * @param[in] source_n The mpz_t whose contents we want (numerator).
195 * @param[in] source_d The mpz_t whose contents we want (denominator).
196 * @param[out] target The mpq_t with the contents of 'source'.
197 * @pre @e source must be initialised.
198 * @pre @e target should not be initialised (otherwise its contents
199 * are never going to be freed, thus causing memory leaks).
200 * @post @e source does not hold any value.
201 */
202inline
203void move_mpz_to_mpq(mpz_t& source_n, mpz_t& source_d, mpq_t& target) noexcept {
204 __lal::move_from_source_to_target(source_n[0], target[0]._mp_num);
205 __lal::move_from_source_to_target(source_d[0], target[0]._mp_den);
206}
207
208} // -- namespace internal
209} // -- namespace lal
Main namespace of the library.
Definition definitions.hpp:48