Loading...
Searching...
No Matches
Multi_field_shared.h
Go to the documentation of this file.
1/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT.
2 * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details.
3 * Author(s): Hannah Schreiber, Clément Maria
4 *
5 * Copyright (C) 2022 Inria
6 *
7 * Modification(s):
8 * - YYYY/MM Author: Description of the modification
9 */
10
16
17#ifndef MATRIX_FIELD_MULTI_SHARED_H_
18#define MATRIX_FIELD_MULTI_SHARED_H_
19
20#include <utility>
21#include <vector>
22#include <gmpxx.h>
23#include <stdexcept>
24
25#include <gudhi/Debug_utils.h>
26
27namespace Gudhi {
28namespace persistence_fields {
29
40{
41 public:
42 using Element = mpz_class;
44
48 Shared_multi_field_element() : element_(0) {}
49
55 Shared_multi_field_element(Element element) : element_(std::move(element))
56 {
57 mpz_mod(element_.get_mpz_t(), element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
58 }
59
67 static void initialize(unsigned int minimum, unsigned int maximum)
68 {
69 if (maximum < 2) throw std::invalid_argument("Characteristic must be strictly positive");
70 if (minimum > maximum) throw std::invalid_argument("The given interval is not valid.");
71 if (minimum == maximum && !_is_prime(minimum))
72 throw std::invalid_argument("The given interval does not contain a prime number.");
73
74 unsigned int curr_prime = minimum;
75 mpz_t tmp_prime;
76 mpz_init_set_ui(tmp_prime, minimum);
77 // test if min_prime is prime
78 int is_prime = mpz_probab_prime_p(tmp_prime, 25); // probabilistic primality test
79
80 if (is_prime == 0) { // min_prime is composite
81 mpz_nextprime(tmp_prime, tmp_prime);
82 curr_prime = mpz_get_ui(tmp_prime);
83 }
84
85 primes_.clear();
86 while (curr_prime <= maximum) {
87 primes_.push_back(curr_prime);
88 mpz_nextprime(tmp_prime, tmp_prime);
89 curr_prime = mpz_get_ui(tmp_prime);
90 }
91 mpz_clear(tmp_prime);
92
93 if (primes_.empty()) throw std::invalid_argument("The given interval does not contain a prime number.");
94
95 productOfAllCharacteristics_ = 1;
96 for (const unsigned int p : primes_) {
97 productOfAllCharacteristics_ *= p;
98 }
99
100 partials_.resize(primes_.size());
101 for (unsigned int i = 0; i < primes_.size(); ++i) {
102 unsigned int p = primes_[i];
103 partials_[i] = productOfAllCharacteristics_ / p;
104 mpz_powm_ui(partials_[i].get_mpz_t(), partials_[i].get_mpz_t(), p - 1, productOfAllCharacteristics_.get_mpz_t());
105 }
106
107 // If I understood the paper well, multiplicativeID_ always equals to 1. But in Clement's code,
108 // multiplicativeID_ is computed (see commented loop below). TODO: verify with Clement.
109 // for (unsigned int i = 0; i < partials_.size(); ++i){
110 // multiplicativeID_ = (multiplicativeID_ + partials_[i]) % productOfAllCharacteristics_;
111 // }
112 }
113
118 {
119 f1.element_ += f2.element_;
120 mpz_mod(f1.element_.get_mpz_t(), f1.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
121 }
122
127 {
128 f1 += f2;
129 return f1;
130 }
131
136 {
137 f.element_ += v;
138 mpz_mod(f.element_.get_mpz_t(), f.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
139 }
140
145 {
146 f += v;
147 return f;
148 }
149
154 {
155 v += f.element_;
156 mpz_mod(v.get_mpz_t(), v.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
157 return v;
158 }
159
164 {
165 f1.element_ -= f2.element_;
166 mpz_mod(f1.element_.get_mpz_t(), f1.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
167 }
168
173 {
174 f1 -= f2;
175 return f1;
176 }
177
182 {
183 f.element_ -= v;
184 mpz_mod(f.element_.get_mpz_t(), f.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
185 }
186
191 {
192 f -= v;
193 return f;
194 }
195
200 {
201 if (v >= productOfAllCharacteristics_)
202 mpz_mod(v.get_mpz_t(), v.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
203 if (f.element_ > v) v += productOfAllCharacteristics_;
204 v -= f.element_;
205 return v;
206 }
207
212 {
213 f1.element_ *= f2.element_;
214 mpz_mod(f1.element_.get_mpz_t(), f1.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
215 }
216
221 {
222 f1 *= f2;
223 return f1;
224 }
225
230 {
231 f.element_ *= v;
232 mpz_mod(f.element_.get_mpz_t(), f.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
233 }
234
239 {
240 f *= v;
241 return f;
242 }
243
248 {
249 v *= f.element_;
250 mpz_mod(v.get_mpz_t(), v.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
251 return v;
252 }
253
258 {
259 return f1.element_ == f2.element_;
260 }
261
265 friend bool operator==(const Element& v, const Shared_multi_field_element& f)
266 {
267 if (v < productOfAllCharacteristics_) return v == f.element_;
268 Element e(v);
269 mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
270 return e == f.element_;
271 }
272
276 friend bool operator==(const Shared_multi_field_element& f, const Element& v)
277 {
278 if (v < productOfAllCharacteristics_) return v == f.element_;
279 Element e(v);
280 mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
281 return e == f.element_;
282 }
283
288 {
289 return !(f1 == f2);
290 }
291
295 friend bool operator!=(const Element& v, const Shared_multi_field_element& f) { return !(v == f); }
296
300 friend bool operator!=(const Shared_multi_field_element& f, const Element& v) { return !(v == f); }
301
302 // /**
303 // * @brief Assign operator.
304 // */
305 // Shared_multi_field_element& operator=(const Element& value)
306 // {
307 // mpz_mod(element_.get_mpz_t(), value.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
308 // return *this;
309 // }
310
315 {
316 std::swap(f1.element_, f2.element_);
317 }
318
322 operator unsigned int() const { return element_.get_ui(); }
323
327 explicit operator mpz_class() const { return element_; }
328
335 {
336 return get_partial_inverse(productOfAllCharacteristics_).first;
337 }
338
346 [[nodiscard]] std::pair<Shared_multi_field_element, Characteristic> get_partial_inverse(
347 const Characteristic& productOfCharacteristics) const
348 {
349 GUDHI_CHECK(productOfCharacteristics >= 0 && productOfCharacteristics <= productOfAllCharacteristics_,
350 std::invalid_argument(
351 "The given product is not the product of a subset of the current Multi-field characteristics."));
352
353 Element QR;
354 mpz_gcd(QR.get_mpz_t(), element_.get_mpz_t(), productOfCharacteristics.get_mpz_t()); // QR <- gcd(x,QS)
355
356 if (QR == productOfCharacteristics)
357 return {Shared_multi_field_element(), multiplicativeID_}; // partial inverse is 0
358
359 Element QT = productOfCharacteristics / QR;
360
361 Element inv_qt;
362 mpz_invert(inv_qt.get_mpz_t(), element_.get_mpz_t(), QT.get_mpz_t());
363
365 res *= inv_qt;
366
367 return {res, QT};
368 }
369
376
382 static Shared_multi_field_element get_multiplicative_identity() { return {multiplicativeID_}; }
383
392 {
393 GUDHI_CHECK(productOfCharacteristics >= 0 && productOfCharacteristics <= productOfAllCharacteristics_,
394 std::invalid_argument(
395 "The given product is not the product of a subset of the current Multi-field characteristics."));
396
397 if (productOfCharacteristics == 0 || productOfCharacteristics == productOfAllCharacteristics_) {
399 }
401 for (unsigned int idx = 0; idx < primes_.size(); ++idx) {
402 if ((productOfCharacteristics % primes_[idx]) == 0) {
403 mult += partials_[idx];
404 }
405 }
406 return mult;
407 }
408
414 static Characteristic get_characteristic() { return productOfAllCharacteristics_; }
415
421 [[nodiscard]] Element get_value() const { return element_; }
422
423 private:
424 Element element_;
425 static inline std::vector<unsigned int> primes_;
426 static inline Characteristic productOfAllCharacteristics_ = 0;
427 static inline std::vector<Element> partials_;
428 static inline const Element multiplicativeID_ = 1;
429
430 static constexpr bool _is_prime(const unsigned int p)
431 {
432 if (p <= 1) return false;
433 if (p <= 3) return true;
434 if (p % 2 == 0 || p % 3 == 0) return false;
435
436 for (long i = 5; i * i <= p; i = i + 6)
437 if (p % i == 0 || p % (i + 2) == 0) return false;
438
439 return true;
440 }
441};
442
443} // namespace persistence_fields
444} // namespace Gudhi
445
446#endif // MATRIX_FIELD_MULTI_SHARED_H_
static Shared_multi_field_element get_partial_multiplicative_identity(const Characteristic &productOfCharacteristics)
Returns the partial multiplicative identity of the multi-field from the given product....
Definition Multi_field_shared.h:391
friend void operator*=(Shared_multi_field_element &f1, Shared_multi_field_element const &f2)
operator*=
Definition Multi_field_shared.h:211
friend Element operator-(Element v, Shared_multi_field_element const &f)
operator-
Definition Multi_field_shared.h:199
friend Shared_multi_field_element operator*(Shared_multi_field_element f, const Element &v)
operator*
Definition Multi_field_shared.h:238
friend void operator-=(Shared_multi_field_element &f1, Shared_multi_field_element const &f2)
operator-=
Definition Multi_field_shared.h:163
friend bool operator==(const Shared_multi_field_element &f1, const Shared_multi_field_element &f2)
operator==
Definition Multi_field_shared.h:257
mpz_class Element
Definition Multi_field_shared.h:42
friend Shared_multi_field_element operator*(Shared_multi_field_element f1, Shared_multi_field_element const &f2)
operator*
Definition Multi_field_shared.h:220
Element get_value() const
Returns the value of the element.
Definition Multi_field_shared.h:421
friend void operator+=(Shared_multi_field_element &f, const Element &v)
operator+=
Definition Multi_field_shared.h:135
friend Shared_multi_field_element operator+(Shared_multi_field_element f1, Shared_multi_field_element const &f2)
operator+
Definition Multi_field_shared.h:126
friend bool operator==(const Shared_multi_field_element &f, const Element &v)
operator==
Definition Multi_field_shared.h:276
Element Characteristic
Definition Multi_field_shared.h:43
static Shared_multi_field_element get_multiplicative_identity()
Returns the multiplicative identity of a field.
Definition Multi_field_shared.h:382
friend Shared_multi_field_element operator+(Shared_multi_field_element f, const Element &v)
operator+
Definition Multi_field_shared.h:144
Shared_multi_field_element get_inverse() const
Returns the inverse of the element in the multi-field, see boissonnat:hal-00922572.
Definition Multi_field_shared.h:334
friend bool operator!=(const Shared_multi_field_element &f, const Element &v)
operator!=
Definition Multi_field_shared.h:300
friend void swap(Shared_multi_field_element &f1, Shared_multi_field_element &f2) noexcept
Assign operator.
Definition Multi_field_shared.h:314
friend Shared_multi_field_element operator-(Shared_multi_field_element f, const Element &v)
operator-
Definition Multi_field_shared.h:190
Shared_multi_field_element()
Default constructor. Sets the element to 0.
Definition Multi_field_shared.h:48
std::pair< Shared_multi_field_element, Characteristic > get_partial_inverse(const Characteristic &productOfCharacteristics) const
Returns the inverse of the element with respect to a sub-product of the characteristics in the multi-...
Definition Multi_field_shared.h:346
friend void operator*=(Shared_multi_field_element &f, const Element &v)
operator*=
Definition Multi_field_shared.h:229
friend bool operator==(const Element &v, const Shared_multi_field_element &f)
operator==
Definition Multi_field_shared.h:265
friend Element operator*(Element v, Shared_multi_field_element const &f)
operator*
Definition Multi_field_shared.h:247
friend void operator-=(Shared_multi_field_element &f, const Element &v)
operator-=
Definition Multi_field_shared.h:181
static Shared_multi_field_element get_additive_identity()
Returns the additive identity of a field.
Definition Multi_field_shared.h:375
friend bool operator!=(const Shared_multi_field_element &f1, const Shared_multi_field_element &f2)
operator!=
Definition Multi_field_shared.h:287
static void initialize(unsigned int minimum, unsigned int maximum)
Initialize the multi-field to the characteristics (primes) contained in the given interval....
Definition Multi_field_shared.h:67
friend bool operator!=(const Element &v, const Shared_multi_field_element &f)
operator!=
Definition Multi_field_shared.h:295
friend Shared_multi_field_element operator-(Shared_multi_field_element f1, Shared_multi_field_element const &f2)
operator-
Definition Multi_field_shared.h:172
Shared_multi_field_element(Element element)
Constructor setting the element to the given value.
Definition Multi_field_shared.h:55
friend Element operator+(Element v, Shared_multi_field_element const &f)
operator+
Definition Multi_field_shared.h:153
friend void operator+=(Shared_multi_field_element &f1, Shared_multi_field_element const &f2)
operator+=
Definition Multi_field_shared.h:117
static Characteristic get_characteristic()
Returns the product of all characteristics.
Definition Multi_field_shared.h:414
Field namespace.
Definition Intro_field_elements_and_operators.h:16
Gudhi namespace.
Definition SimplicialComplexForAlpha.h:14
STL namespace.