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-24 Inria
6 *
7 * Modification(s):
8 * - YYYY/MM Author: Description of the modification
9 */
10
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
25namespace Gudhi {
26namespace persistence_fields {
27
38{
39 public:
40 using Element = mpz_class;
65
73 static void initialize(unsigned int minimum, unsigned int maximum);
74
79 f1.element_ += f2.element_;
80 mpz_mod(f1.element_.get_mpz_t(), f1.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
81 }
86 f1 += f2;
87 return f1;
88 }
93 f.element_ += v;
94 mpz_mod(f.element_.get_mpz_t(), f.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
95 }
100 f += v;
101 return f;
102 }
107 v += f.element_;
108 mpz_mod(v.get_mpz_t(), v.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
109 return v;
110 }
111
116 f1.element_ -= f2.element_;
117 mpz_mod(f1.element_.get_mpz_t(), f1.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
118 }
123 f1 -= f2;
124 return f1;
125 }
130 f.element_ -= v;
131 mpz_mod(f.element_.get_mpz_t(), f.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
132 }
137 f -= v;
138 return f;
139 }
144 if (v >= productOfAllCharacteristics_)
145 mpz_mod(v.get_mpz_t(), v.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
146 if (f.element_ > v) v += productOfAllCharacteristics_;
147 v -= f.element_;
148 return v;
149 }
150
155 f1.element_ *= f2.element_;
156 mpz_mod(f1.element_.get_mpz_t(), f1.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
157 }
162 f1 *= f2;
163 return f1;
164 }
169 f.element_ *= v;
170 mpz_mod(f.element_.get_mpz_t(), f.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
171 }
176 f *= v;
177 return f;
178 }
183 v *= f.element_;
184 mpz_mod(v.get_mpz_t(), v.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
185 return v;
186 }
187
192 return f1.element_ == f2.element_;
193 }
197 friend bool operator==(const Element& v, const Shared_multi_field_element& f) {
198 if (v < productOfAllCharacteristics_) return v == f.element_;
199 Element e(v);
200 mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
201 return e == f.element_;
202 }
206 friend bool operator==(const Shared_multi_field_element& f, const Element& v) {
207 if (v < productOfAllCharacteristics_) return v == f.element_;
208 Element e(v);
209 mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
210 return e == f.element_;
211 }
216 return !(f1 == f2);
217 }
221 friend bool operator!=(const Element& v, const Shared_multi_field_element& f) { return !(v == f); }
225 friend bool operator!=(const Shared_multi_field_element& f, const Element& v) { return !(v == f); }
226
239 std::swap(f1.element_, f2.element_);
240 }
241
245 operator unsigned int() const;
249 operator mpz_class() const;
250
264 std::pair<Shared_multi_field_element, Characteristic> get_partial_inverse(
265 const Characteristic& productOfCharacteristics) const;
266
287 const Characteristic& productOfCharacteristics);
294
300 Element get_value() const;
301
302 // static constexpr bool handles_only_z2() { return false; }
303
304 private:
305 Element element_;
306 static inline std::vector<unsigned int> primes_;
307 static inline Characteristic productOfAllCharacteristics_ = 0;
308 static inline std::vector<Element> partials_;
309 static inline const Element multiplicativeID_ = 1;
311 static constexpr bool _is_prime(const int p);
312};
313
315
317 mpz_mod(element_.get_mpz_t(), element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
318}
319
321 : element_(toCopy.element_) {}
322
324 : element_(std::move(toMove.element_)) {}
325
326inline void Shared_multi_field_element::initialize(unsigned int minimum, unsigned int maximum) {
327 if (maximum < 2) throw std::invalid_argument("Characteristic must be strictly positive");
328 if (minimum > maximum) throw std::invalid_argument("The given interval is not valid.");
329 if (minimum == maximum && !_is_prime(minimum))
330 throw std::invalid_argument("The given interval does not contain a prime number.");
331
332 unsigned int curr_prime = minimum;
333 mpz_t tmp_prime;
334 mpz_init_set_ui(tmp_prime, minimum);
335 // test if min_prime is prime
336 int is_prime = mpz_probab_prime_p(tmp_prime, 25); // probabilistic primality test
337
338 if (is_prime == 0) { // min_prime is composite
339 mpz_nextprime(tmp_prime, tmp_prime);
340 curr_prime = mpz_get_ui(tmp_prime);
341 }
342
343 primes_.clear();
344 while (curr_prime <= maximum) {
345 primes_.push_back(curr_prime);
346 mpz_nextprime(tmp_prime, tmp_prime);
347 curr_prime = mpz_get_ui(tmp_prime);
348 }
349 mpz_clear(tmp_prime);
350
351 if (primes_.empty()) throw std::invalid_argument("The given interval does not contain a prime number.");
352
353 productOfAllCharacteristics_ = 1;
354 for (const unsigned int p : primes_) {
355 productOfAllCharacteristics_ *= p;
356 }
357
358 partials_.resize(primes_.size());
359 for (unsigned int i = 0; i < primes_.size(); ++i) {
360 unsigned int p = primes_[i];
361 partials_[i] = productOfAllCharacteristics_ / p;
362 mpz_powm_ui(partials_[i].get_mpz_t(), partials_[i].get_mpz_t(), p - 1, productOfAllCharacteristics_.get_mpz_t());
363 }
364
365 // If I understood the paper well, multiplicativeID_ always equals to 1. But in Clement's code,
366 // multiplicativeID_ is computed (see commented loop below). TODO: verify with Clement.
367 // for (unsigned int i = 0; i < partials_.size(); ++i){
368 // multiplicativeID_ = (multiplicativeID_ + partials_[i]) % productOfAllCharacteristics_;
369 // }
370}
371
373 std::swap(element_, other.element_);
374 return *this;
375}
376
378 mpz_mod(element_.get_mpz_t(), value.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
379 return *this;
380}
381
382inline Shared_multi_field_element::operator unsigned int() const { return element_.get_ui(); }
383
384inline Shared_multi_field_element::operator mpz_class() const { return element_; }
385
387 return get_partial_inverse(productOfAllCharacteristics_).first;
388}
389
390inline std::pair<Shared_multi_field_element, Shared_multi_field_element::Characteristic>
392 Element QR;
393 mpz_gcd(QR.get_mpz_t(), element_.get_mpz_t(), productOfCharacteristics.get_mpz_t()); // QR <- gcd(x,QS)
394
395 if (QR == productOfCharacteristics) return {Shared_multi_field_element(), multiplicativeID_}; // partial inverse is 0
396
397 Element QT = productOfCharacteristics / QR;
398
399 Element inv_qt;
400 mpz_invert(inv_qt.get_mpz_t(), element_.get_mpz_t(), QT.get_mpz_t());
401
403 res *= inv_qt;
404
405 return {res, QT};
406}
407
410}
411
413 return Shared_multi_field_element(multiplicativeID_);
414}
415
417 const Characteristic& productOfCharacteristics) {
418 if (productOfCharacteristics == 0) {
419 return Shared_multi_field_element(multiplicativeID_);
420 }
422 for (unsigned int idx = 0; idx < primes_.size(); ++idx) {
423 if ((productOfCharacteristics % primes_[idx]) == 0) {
424 mult += partials_[idx];
425 }
426 }
427 return mult;
428}
429
431 return productOfAllCharacteristics_;
432}
433
435
436inline constexpr bool Shared_multi_field_element::_is_prime(const int p) {
437 if (p <= 1) return false;
438 if (p <= 3) return true;
439 if (p % 2 == 0 || p % 3 == 0) return false;
440
441 for (long i = 5; i * i <= p; i = i + 6)
442 if (p % i == 0 || p % (i + 2) == 0) return false;
443
444 return true;
445}
446
447} // namespace persistence_fields
448} // namespace Gudhi
449
450#endif // MATRIX_FIELD_MULTI_SHARED_H_
Class representing an element of a multi-field. If each instantiation of the class can represent anot...
Definition: Multi_field_shared.h:38
friend void operator*=(Shared_multi_field_element &f1, Shared_multi_field_element const &f2)
operator*=
Definition: Multi_field_shared.h:154
static Shared_multi_field_element get_multiplicative_identity()
Returns the multiplicative identity of a field.
Definition: Multi_field_shared.h:412
friend Element operator-(Element v, Shared_multi_field_element const &f)
operator-
Definition: Multi_field_shared.h:143
friend void operator-=(Shared_multi_field_element &f1, Shared_multi_field_element const &f2)
operator-=
Definition: Multi_field_shared.h:115
Shared_multi_field_element & operator=(Shared_multi_field_element other)
Assign operator.
Definition: Multi_field_shared.h:372
friend bool operator==(const Shared_multi_field_element &f1, const Shared_multi_field_element &f2)
operator==
Definition: Multi_field_shared.h:191
mpz_class Element
Definition: Multi_field_shared.h:40
friend Shared_multi_field_element operator*(Shared_multi_field_element f1, Shared_multi_field_element const &f2)
operator*
Definition: Multi_field_shared.h:161
friend Shared_multi_field_element operator+(Shared_multi_field_element f1, Shared_multi_field_element const &f2)
operator+
Definition: Multi_field_shared.h:85
friend bool operator==(const Shared_multi_field_element &f, const Element &v)
operator==
Definition: Multi_field_shared.h:206
Element Characteristic
Definition: Multi_field_shared.h:41
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:326
Shared_multi_field_element get_inverse() const
Returns the inverse of the element in the multi-field, see .
Definition: Multi_field_shared.h:386
static Characteristic get_characteristic()
Returns the product of all characteristics.
Definition: Multi_field_shared.h:430
friend bool operator!=(const Shared_multi_field_element &f, const Element &v)
operator!=
Definition: Multi_field_shared.h:225
Shared_multi_field_element()
Default constructor. Sets the element to 0.
Definition: Multi_field_shared.h:314
static Shared_multi_field_element get_additive_identity()
Returns the additive identity of a field.
Definition: Multi_field_shared.h:408
friend bool operator==(const Element &v, const Shared_multi_field_element &f)
operator==
Definition: Multi_field_shared.h:197
friend Shared_multi_field_element operator+(Shared_multi_field_element f, Element const v)
operator+
Definition: Multi_field_shared.h:99
friend Element operator*(Element v, Shared_multi_field_element const &f)
operator*
Definition: Multi_field_shared.h:182
friend bool operator!=(const Shared_multi_field_element &f1, const Shared_multi_field_element &f2)
operator!=
Definition: Multi_field_shared.h:215
friend bool operator!=(const Element &v, const Shared_multi_field_element &f)
operator!=
Definition: Multi_field_shared.h:221
friend Shared_multi_field_element operator-(Shared_multi_field_element f1, Shared_multi_field_element const &f2)
operator-
Definition: Multi_field_shared.h:122
friend Shared_multi_field_element operator-(Shared_multi_field_element f, Element const v)
operator-
Definition: Multi_field_shared.h:136
friend Shared_multi_field_element operator*(Shared_multi_field_element f, Element const v)
operator*
Definition: Multi_field_shared.h:175
Element get_value() const
Returns the value of the element.
Definition: Multi_field_shared.h:434
friend void operator*=(Shared_multi_field_element &f, Element const v)
operator*=
Definition: Multi_field_shared.h:168
friend void swap(Shared_multi_field_element &f1, Shared_multi_field_element &f2)
Swap operator.
Definition: Multi_field_shared.h:238
friend Element operator+(Element v, Shared_multi_field_element const &f)
operator+
Definition: Multi_field_shared.h:106
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:416
friend void operator-=(Shared_multi_field_element &f, Element const v)
operator-=
Definition: Multi_field_shared.h:129
friend void operator+=(Shared_multi_field_element &f, Element const v)
operator+=
Definition: Multi_field_shared.h:92
friend void operator+=(Shared_multi_field_element &f1, Shared_multi_field_element const &f2)
operator+=
Definition: Multi_field_shared.h:78
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:391
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14