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 
25 namespace Gudhi {
26 namespace persistence_fields {
27 
38 {
39  public:
40  using element_type = 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_type& v, const Shared_multi_field_element& f) {
198  if (v < productOfAllCharacteristics_) return v == f.element_;
199  element_type 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_type& v) {
207  if (v < productOfAllCharacteristics_) return v == f.element_;
208  element_type 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_type& v, const Shared_multi_field_element& f) { return !(v == f); }
225  friend bool operator!=(const Shared_multi_field_element& f, const element_type& 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_type> get_partial_inverse(
265  const characteristic_type& productOfCharacteristics) const;
266 
287  const characteristic_type& productOfCharacteristics);
294 
300  element_type get_value() const;
301 
302  // static constexpr bool handles_only_z2() { return false; }
303 
304  private:
305  element_type element_;
306  static inline std::vector<unsigned int> primes_;
307  static inline characteristic_type productOfAllCharacteristics_ = 0;
308  static inline std::vector<element_type> partials_;
309  static inline const element_type 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 
326 inline 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 
382 inline Shared_multi_field_element::operator unsigned int() const { return element_.get_ui(); }
383 
384 inline Shared_multi_field_element::operator mpz_class() const { return element_; }
385 
387  return get_partial_inverse(productOfAllCharacteristics_).first;
388 }
389 
390 inline std::pair<Shared_multi_field_element, Shared_multi_field_element::characteristic_type>
392  element_type 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_type QT = productOfCharacteristics / QR;
398 
399  element_type 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_type& 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 
436 inline 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 instanciation of the class can represent anot...
Definition: Multi_field_shared.h:38
static Shared_multi_field_element get_partial_multiplicative_identity(const characteristic_type &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 &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 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 element_type &v, const Shared_multi_field_element &f)
operator!=
Definition: Multi_field_shared.h:221
friend bool operator==(const Shared_multi_field_element &f1, const Shared_multi_field_element &f2)
operator==
Definition: Multi_field_shared.h:191
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 f, element_type const v)
operator+
Definition: Multi_field_shared.h:99
std::pair< Shared_multi_field_element, characteristic_type > get_partial_inverse(const characteristic_type &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
mpz_class element_type
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:85
friend bool operator!=(const Shared_multi_field_element &f, const element_type &v)
operator!=
Definition: Multi_field_shared.h:225
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
friend Shared_multi_field_element operator-(Shared_multi_field_element f, element_type const v)
operator-
Definition: Multi_field_shared.h:136
friend void operator-=(Shared_multi_field_element &f, element_type const v)
operator-=
Definition: Multi_field_shared.h:129
friend element_type operator*(element_type v, Shared_multi_field_element const &f)
operator*
Definition: Multi_field_shared.h:182
element_type characteristic_type
Definition: Multi_field_shared.h:41
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 void operator+=(Shared_multi_field_element &f, element_type const v)
operator+=
Definition: Multi_field_shared.h:92
friend bool operator!=(const Shared_multi_field_element &f1, const Shared_multi_field_element &f2)
operator!=
Definition: Multi_field_shared.h:215
friend void operator*=(Shared_multi_field_element &f, element_type const v)
operator*=
Definition: Multi_field_shared.h:168
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_type const v)
operator*
Definition: Multi_field_shared.h:175
friend bool operator==(const Shared_multi_field_element &f, const element_type &v)
operator==
Definition: Multi_field_shared.h:206
friend void swap(Shared_multi_field_element &f1, Shared_multi_field_element &f2)
Swap operator.
Definition: Multi_field_shared.h:238
element_type get_value() const
Returns the value of the element.
Definition: Multi_field_shared.h:434
friend element_type operator+(element_type v, Shared_multi_field_element const &f)
operator+
Definition: Multi_field_shared.h:106
friend bool operator==(const element_type &v, const Shared_multi_field_element &f)
operator==
Definition: Multi_field_shared.h:197
static characteristic_type get_characteristic()
Returns the product of all characteristics.
Definition: Multi_field_shared.h:430
friend element_type operator-(element_type 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:78
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14