Loading...
Searching...
No Matches
Multi_field.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_H_
18#define MATRIX_FIELD_MULTI_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
40template <unsigned int minimum, unsigned int maximum>
42{
43 public:
44 using Element = mpz_class;
46
50 Multi_field_element() : element_(0)
51 {
52 static_assert(maximum >= 2, "Characteristics have to be positive.");
53 static_assert(minimum <= maximum, "The given interval is not valid.");
54 static_assert(minimum != maximum || _is_prime(minimum), "The given interval does not contain a prime number.");
55
56 if (productOfAllCharacteristics_ == 1)
57 throw std::runtime_error("The given interval does not contain a prime number.");
58 }
59
65 Multi_field_element(Element element) : element_(std::move(element))
66 {
67 static_assert(maximum >= 2, "Characteristics has to be positive.");
68 static_assert(minimum <= maximum, "The given interval is not valid.");
69 static_assert(minimum != maximum || _is_prime(minimum), "The given interval does not contain a prime number.");
70
71 if (productOfAllCharacteristics_ == 1)
72 throw std::runtime_error("The given interval does not contain a prime number.");
73
74 mpz_mod(element_.get_mpz_t(), element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
75 }
76
81 {
82 f1.element_ += f2.element_;
83 mpz_mod(f1.element_.get_mpz_t(), f1.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
84 }
85
90 {
91 f1 += f2;
92 return f1;
93 }
94
98 friend void operator+=(Multi_field_element& f, const Element& v)
99 {
100 f.element_ += v;
101 mpz_mod(f.element_.get_mpz_t(), f.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
102 }
103
108 {
109 f += v;
110 return f;
111 }
112
117 {
118 v += f.element_;
119 mpz_mod(v.get_mpz_t(), v.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
120 return v;
121 }
122
127 {
128 f1.element_ -= f2.element_;
129 mpz_mod(f1.element_.get_mpz_t(), f1.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
130 }
131
136 {
137 f1 -= f2;
138 return f1;
139 }
140
144 friend void operator-=(Multi_field_element& f, const Element& v)
145 {
146 f.element_ -= v;
147 mpz_mod(f.element_.get_mpz_t(), f.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
148 }
149
154 {
155 f -= v;
156 return f;
157 }
158
163 {
164 // Element e(v);
165 if (v >= productOfAllCharacteristics_)
166 mpz_mod(v.get_mpz_t(), v.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
167 if (f.element_ > v) v += productOfAllCharacteristics_;
168 v -= f.element_;
169 return v;
170 }
171
176 {
177 f1.element_ *= f2.element_;
178 mpz_mod(f1.element_.get_mpz_t(), f1.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
179 }
180
185 {
186 f1 *= f2;
187 return f1;
188 }
189
193 friend void operator*=(Multi_field_element& f, const Element& v)
194 {
195 f.element_ *= v;
196 mpz_mod(f.element_.get_mpz_t(), f.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
197 }
198
203 {
204 f *= v;
205 return f;
206 }
207
212 {
213 v *= f.element_;
214 mpz_mod(v.get_mpz_t(), v.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
215 return v;
216 }
217
221 friend bool operator==(const Multi_field_element& f1, const Multi_field_element& f2)
222 {
223 return f1.element_ == f2.element_;
224 }
225
229 friend bool operator==(const Element& v, const Multi_field_element& f)
230 {
231 if (v < productOfAllCharacteristics_) return v == f.element_;
232 Element e(v);
233 mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
234 return e == f.element_;
235 }
236
240 friend bool operator==(const Multi_field_element& f, const Element& v)
241 {
242 if (v < productOfAllCharacteristics_) return v == f.element_;
243 Element e(v);
244 mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
245 return e == f.element_;
246 }
247
251 friend bool operator!=(const Multi_field_element& f1, const Multi_field_element& f2) { return !(f1 == f2); }
252
256 friend bool operator!=(const Element& v, const Multi_field_element& f) { return !(v == f); }
257
261 friend bool operator!=(const Multi_field_element& f, const Element& v) { return !(v == f); }
262
263 // /**
264 // * @brief Assign operator.
265 // */
266 // Multi_field_element& operator=(const Element& value)
267 // {
268 // mpz_mod(element_.get_mpz_t(), value.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
269 // return *this;
270 // }
271
275 friend void swap(Multi_field_element& f1, Multi_field_element& f2) noexcept { std::swap(f1.element_, f2.element_); }
276
280 operator unsigned int() const { return element_.get_ui(); }
281
285 explicit operator mpz_class() const { return element_; }
286
292 [[nodiscard]] Multi_field_element get_inverse() const
293 {
294 return get_partial_inverse(productOfAllCharacteristics_).first;
295 }
296
304 [[nodiscard]] std::pair<Multi_field_element, Characteristic> get_partial_inverse(
305 const Characteristic& productOfCharacteristics) const
306 {
307 GUDHI_CHECK(productOfCharacteristics >= 0 && productOfCharacteristics <= productOfAllCharacteristics_,
308 std::invalid_argument(
309 "The given product is not the product of a subset of the current Multi-field characteristics."));
310
312 mpz_gcd(QR.get_mpz_t(), element_.get_mpz_t(), productOfCharacteristics.get_mpz_t()); // QR <- gcd(x,QS)
313
314 if (QR == productOfCharacteristics) return {Multi_field_element(), multiplicativeID_}; // partial inverse is 0
315
316 Characteristic QT = productOfCharacteristics / QR;
317
318 Characteristic inv_qt;
319 mpz_invert(inv_qt.get_mpz_t(), element_.get_mpz_t(), QT.get_mpz_t());
320
322 res *= inv_qt;
323
324 return {res, QT};
325 }
326
333
343
352 {
353 GUDHI_CHECK(productOfCharacteristics >= 0 && productOfCharacteristics <= productOfAllCharacteristics_,
354 std::invalid_argument(
355 "The given product is not the product of a subset of the current Multi-field characteristics."));
356
357 if (productOfCharacteristics == 0 || productOfCharacteristics == productOfAllCharacteristics_) {
359 }
361 for (unsigned int idx = 0; idx < primes_.size(); ++idx) {
362 if ((productOfCharacteristics % primes_[idx]) == 0) {
363 mult += partials_[idx];
364 }
365 }
366 return mult;
367 }
368
374 static Characteristic get_characteristic() { return productOfAllCharacteristics_; }
375
381 [[nodiscard]] Element get_value() const { return element_; }
382
383 private:
384 Element element_;
385 static inline const std::vector<unsigned int> primes_ = []() {
386 std::vector<unsigned int> res;
387
388 unsigned int curr_prime = minimum;
389 mpz_t tmp_prime;
390 mpz_init_set_ui(tmp_prime, minimum);
391 // test if min_prime is prime
392 int is_prime = mpz_probab_prime_p(tmp_prime, 25); // probabilistic primality test
393
394 if (is_prime == 0) { // min_prime is composite
395 mpz_nextprime(tmp_prime, tmp_prime);
396 curr_prime = mpz_get_ui(tmp_prime);
397 }
398
399 while (curr_prime <= maximum) {
400 res.push_back(curr_prime);
401 mpz_nextprime(tmp_prime, tmp_prime);
402 curr_prime = mpz_get_ui(tmp_prime);
403 }
404 mpz_clear(tmp_prime);
405
406 return res;
407 }();
408 static inline const Characteristic productOfAllCharacteristics_ = []() {
409 Characteristic res = 1;
410 for (const auto p : primes_) {
411 res *= p;
412 }
413
414 return res;
415 }();
416 static inline const std::vector<Characteristic> partials_ = []() {
417 std::vector<Characteristic> res;
418
419 if (productOfAllCharacteristics_ == 1) return res;
420
421 for (unsigned int p : primes_) {
422 res.emplace_back(productOfAllCharacteristics_ / p);
423 mpz_powm_ui(res.back().get_mpz_t(), res.back().get_mpz_t(), p - 1, productOfAllCharacteristics_.get_mpz_t());
424 }
425
426 return res;
427 }();
428 // If I understood the paper well, multiplicativeID_ always equals to 1. But in Clement's code,
429 // multiplicativeID_ is computed (see commented lambda function below). TODO: verify with Clement.
430 static inline const Element multiplicativeID_ = 1; /*[](){
431 mpz_class res = 0;
432 for (unsigned int i = 0; i < partials_.size(); ++i){
433 res = (res + partials_[i]) % productOfAllCharacteristics_;
434 }
435
436 return res;
437 }();*/
438
439 static constexpr bool _is_prime(const int p)
440 {
441 if (p <= 1) return false;
442 if (p <= 3) return true;
443 if (p % 2 == 0 || p % 3 == 0) return false;
444
445 for (long i = 5; i * i <= p; i = i + 6)
446 if (p % i == 0 || p % (i + 2) == 0) return false;
447
448 return true;
449 }
450};
451
452} // namespace persistence_fields
453} // namespace Gudhi
454
455#endif // MATRIX_FIELD_MULTI_H_
Multi_field_element(Element element)
Constructor setting the element to the given value.
Definition Multi_field.h:65
friend bool operator!=(const Multi_field_element &f, const Element &v)
operator!=
Definition Multi_field.h:261
Element get_value() const
Returns the value of the element.
Definition Multi_field.h:381
mpz_class Element
Definition Multi_field.h:44
Element Characteristic
Definition Multi_field.h:45
friend Multi_field_element operator-(Multi_field_element f1, Multi_field_element const &f2)
operator-
Definition Multi_field.h:135
friend bool operator==(const Multi_field_element &f, const Element &v)
operator==
Definition Multi_field.h:240
friend Multi_field_element operator+(Multi_field_element f1, Multi_field_element const &f2)
operator+
Definition Multi_field.h:89
friend bool operator!=(const Element &v, const Multi_field_element &f)
operator!=
Definition Multi_field.h:256
friend void operator+=(Multi_field_element &f1, Multi_field_element const &f2)
operator+=
Definition Multi_field.h:80
friend void operator*=(Multi_field_element &f, const Element &v)
operator*=
Definition Multi_field.h:193
friend Multi_field_element operator*(Multi_field_element f, const Element &v)
operator*
Definition Multi_field.h:202
Multi_field_element get_inverse() const
Returns the inverse of the element in the multi-field, see boissonnat:hal-00922572.
Definition Multi_field.h:292
friend bool operator!=(const Multi_field_element &f1, const Multi_field_element &f2)
operator!=
Definition Multi_field.h:251
friend Element operator+(Element v, Multi_field_element const &f)
operator+
Definition Multi_field.h:116
friend Multi_field_element operator*(Multi_field_element f1, Multi_field_element const &f2)
operator*
Definition Multi_field.h:184
std::pair< 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.h:304
friend bool operator==(const Element &v, const Multi_field_element &f)
operator==
Definition Multi_field.h:229
static Multi_field_element get_additive_identity()
Returns the additive identity of a field.
Definition Multi_field.h:332
friend Multi_field_element operator+(Multi_field_element f, const Element &v)
operator+
Definition Multi_field.h:107
friend Element operator*(Element v, Multi_field_element const &f)
operator*
Definition Multi_field.h:211
Multi_field_element()
Default constructor. Sets the element to 0.
Definition Multi_field.h:50
friend Element operator-(Element v, Multi_field_element const &f)
operator-
Definition Multi_field.h:162
friend void swap(Multi_field_element &f1, Multi_field_element &f2) noexcept
Assign operator.
Definition Multi_field.h:275
static Multi_field_element get_multiplicative_identity()
Returns the multiplicative identity of a field.
Definition Multi_field.h:339
friend void operator+=(Multi_field_element &f, const Element &v)
operator+=
Definition Multi_field.h:98
static 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.h:351
friend void operator-=(Multi_field_element &f, const Element &v)
operator-=
Definition Multi_field.h:144
friend bool operator==(const Multi_field_element &f1, const Multi_field_element &f2)
operator==
Definition Multi_field.h:221
friend void operator*=(Multi_field_element &f1, Multi_field_element const &f2)
operator*=
Definition Multi_field.h:175
static Characteristic get_characteristic()
Returns the product of all characteristics.
Definition Multi_field.h:374
friend void operator-=(Multi_field_element &f1, Multi_field_element const &f2)
operator-=
Definition Multi_field.h:126
friend Multi_field_element operator-(Multi_field_element f, const Element &v)
operator-
Definition Multi_field.h:153
Field namespace.
Definition Intro_field_elements_and_operators.h:16
Gudhi namespace.
Definition SimplicialComplexForAlpha.h:14
STL namespace.