Zp_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
4 *
5 * Copyright (C) 2022 Inria
6 *
7 * Modification(s):
8 * - YYYY/MM Author: Description of the modification
9 */
10
17#ifndef MATRIX_FIELD_ZP_VAR_H_
18#define MATRIX_FIELD_ZP_VAR_H_
19
20#include <utility>
21#include <vector>
22#include <limits.h>
23#include <stdexcept>
24
25namespace Gudhi {
26namespace persistence_fields {
27
40template <typename Unsigned_integer_type = unsigned int,
41 class = std::enable_if_t<std::is_unsigned_v<Unsigned_integer_type> > >
43 public:
44 using Element = Unsigned_integer_type;
46 template <class T>
47 using isInteger = std::enable_if_t<std::is_integral_v<T> >;
48
52 Shared_Zp_field_element() : element_(0) {}
59 template <typename Integer_type, class = isInteger<Integer_type> >
60 Shared_Zp_field_element(Integer_type element) : element_(_get_value(element)) {}
66 Shared_Zp_field_element(const Shared_Zp_field_element& toCopy) : element_(toCopy.element_) {}
72 Shared_Zp_field_element(Shared_Zp_field_element&& toMove) noexcept : element_(std::exchange(toMove.element_, 0)) {}
73
80 static void initialize(Characteristic characteristic) {
81 if (characteristic <= 1)
82 throw std::invalid_argument("Characteristic must be strictly positive and a prime number.");
83
84 inverse_.resize(characteristic);
85 inverse_[0] = 0;
86 for (Element i = 1; i < characteristic; ++i) {
87 Element inv = 1;
88 Element mult = inv * i;
89 while ((mult % characteristic) != 1) {
90 ++inv;
91 if (mult == characteristic) throw std::invalid_argument("Characteristic must be a prime number.");
92 mult = inv * i;
93 }
94 inverse_[i] = inv;
95 }
96
97 characteristic_ = characteristic;
98 }
99
105 Element get_value() const { return element_; }
106
111 f1.element_ = Shared_Zp_field_element::_add(f1.element_, f2.element_);
112 }
117 f1 += f2;
118 return f1;
119 }
125 template <typename Integer_type, class = isInteger<Integer_type> >
126 friend void operator+=(Shared_Zp_field_element& f, const Integer_type& v) {
127 f.element_ = Shared_Zp_field_element::_add(f.element_, _get_value(v));
128 }
134 template <typename Integer_type, class = isInteger<Integer_type> >
136 f += v;
137 return f;
138 }
144 template <typename Integer_type, class = isInteger<Integer_type> >
145 friend Integer_type operator+(const Integer_type& v, Shared_Zp_field_element f) {
146 f += v;
147 return f.element_;
148 }
149
154 f1.element_ = Shared_Zp_field_element::_subtract(f1.element_, f2.element_);
155 }
160 f1 -= f2;
161 return f1;
162 }
168 template <typename Integer_type, class = isInteger<Integer_type> >
169 friend void operator-=(Shared_Zp_field_element& f, const Integer_type& v) {
170 f.element_ = Shared_Zp_field_element::_subtract(f.element_, _get_value(v));
171 }
177 template <typename Integer_type, class = isInteger<Integer_type> >
179 f -= v;
180 return f;
181 }
187 template <typename Integer_type, class = isInteger<Integer_type> >
188 friend Integer_type operator-(const Integer_type& v, const Shared_Zp_field_element& f) {
189 return Shared_Zp_field_element::_subtract(_get_value(v), f.element_);
190 }
191
196 f1.element_ = Shared_Zp_field_element::_multiply(f1.element_, f2.element_);
197 }
202 f1 *= f2;
203 return f1;
204 }
210 template <typename Integer_type, class = isInteger<Integer_type> >
211 friend void operator*=(Shared_Zp_field_element& f, const Integer_type& v) {
212 f.element_ = Shared_Zp_field_element::_multiply(f.element_, _get_value(v));
213 }
219 template <typename Integer_type, class = isInteger<Integer_type> >
221 f *= v;
222 return f;
223 }
229 template <typename Integer_type, class = isInteger<Integer_type> >
230 friend Integer_type operator*(const Integer_type& v, Shared_Zp_field_element f) {
231 f *= v;
232 return f.element_;
233 }
234
239 return f1.element_ == f2.element_;
240 }
246 template <typename Integer_type, class = isInteger<Integer_type> >
247 friend bool operator==(const Integer_type& v, const Shared_Zp_field_element& f) {
248 return Shared_Zp_field_element::_get_value(v) == f.element_;
249 }
255 template <typename Integer_type, class = isInteger<Integer_type> >
256 friend bool operator==(const Shared_Zp_field_element& f, const Integer_type& v) {
257 return Shared_Zp_field_element::_get_value(v) == f.element_;
258 }
262 friend bool operator!=(const Shared_Zp_field_element& f1, const Shared_Zp_field_element& f2) { return !(f1 == f2); }
268 template <typename Integer_type, class = isInteger<Integer_type> >
269 friend bool operator!=(const Integer_type& v, const Shared_Zp_field_element& f) {
270 return !(v == f);
271 }
277 template <typename Integer_type, class = isInteger<Integer_type> >
278 friend bool operator!=(const Shared_Zp_field_element& f, const Integer_type& v) {
279 return !(v == f);
280 }
281
286 std::swap(element_, other.element_);
287 return *this;
288 }
294 template <typename Integer_type, class = isInteger<Integer_type> >
295 Shared_Zp_field_element& operator=(const Integer_type& value) {
296 element_ = Shared_Zp_field_element::_get_value(value);
297 return *this;
298 }
302 friend void swap(Shared_Zp_field_element& f1, Shared_Zp_field_element& f2) { std::swap(f1.element_, f2.element_); }
303
307 operator unsigned int() const { return element_; }
308
314 Shared_Zp_field_element get_inverse() const { return Shared_Zp_field_element(inverse_[element_]); }
321 std::pair<Shared_Zp_field_element, Characteristic> get_partial_inverse(
322 Characteristic productOfCharacteristics) const {
323 return {get_inverse(), productOfCharacteristics};
324 }
325
345 [[maybe_unused]] Characteristic productOfCharacteristics) {
346 return Shared_Zp_field_element(1);
347 }
353 static Characteristic get_characteristic() { return characteristic_; }
354
355 // static constexpr bool handles_only_z2() { return false; }
356
357 private:
358 Element element_;
359 static inline Characteristic characteristic_;
360 static inline std::vector<Element> inverse_;
362 static Element _add(Element element, Element v) {
363 if (UINT_MAX - element < v) {
364 // automatic unsigned integer overflow behaviour will make it work
365 element += v;
366 element -= characteristic_;
367 return element;
368 }
369
370 element += v;
371 if (element >= characteristic_) element -= characteristic_;
372
373 return element;
374 }
375 static Element _subtract(Element element, Element v) {
376 if (element < v) {
377 element += characteristic_;
378 }
379 element -= v;
380
381 return element;
382 }
383 static Element _multiply(Element element, Element v) {
384 Element a = element;
385 element = 0;
386 Element temp_b;
387
388 while (a != 0) {
389 if (a & 1) {
390 if (v >= characteristic_ - element) element -= characteristic_;
391 element += v;
392 }
393 a >>= 1;
394
395 temp_b = v;
396 if (v >= characteristic_ - v) temp_b -= characteristic_;
397 v += temp_b;
398 }
399
400 return element;
401 }
402
403 template <typename Integer_type, class = isInteger<Integer_type> >
404 static constexpr Element _get_value(Integer_type e) {
405 if constexpr (std::is_signed_v<Integer_type>){
406 if (e < -static_cast<Integer_type>(characteristic_)) e = e % characteristic_;
407 if (e < 0) return e += characteristic_;
408 return e < static_cast<Integer_type>(characteristic_) ? e : e % characteristic_;
409 } else {
410 return e < characteristic_ ? e : e % characteristic_;
411 }
412 }
413};
414
415} // namespace persistence_fields
416} // namespace Gudhi
417
418#endif // MATRIX_FIELD_ZP_VAR_H_
Class representing an element of the field for any prime number . If each instantiation of the class...
Definition: Zp_field_shared.h:42
static void initialize(Characteristic characteristic)
Initialize the field to the given characteristic. Should be called first before constructing the fiel...
Definition: Zp_field_shared.h:80
friend bool operator==(const Shared_Zp_field_element &f, const Integer_type &v)
operator==
Definition: Zp_field_shared.h:256
Shared_Zp_field_element get_inverse() const
Returns the inverse of the element in the field.
Definition: Zp_field_shared.h:314
friend bool operator==(const Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator==
Definition: Zp_field_shared.h:238
Shared_Zp_field_element()
Default constructor. Sets the element to 0.
Definition: Zp_field_shared.h:52
Shared_Zp_field_element & operator=(const Integer_type &value)
Assign operator.
Definition: Zp_field_shared.h:295
friend bool operator==(const Integer_type &v, const Shared_Zp_field_element &f)
operator==
Definition: Zp_field_shared.h:247
Shared_Zp_field_element & operator=(Shared_Zp_field_element other)
Assign operator.
Definition: Zp_field_shared.h:285
friend Integer_type operator+(const Integer_type &v, Shared_Zp_field_element f)
operator+
Definition: Zp_field_shared.h:145
Element Characteristic
Definition: Zp_field_shared.h:45
friend void operator-=(Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator-=
Definition: Zp_field_shared.h:153
friend Integer_type operator*(const Integer_type &v, Shared_Zp_field_element f)
operator*
Definition: Zp_field_shared.h:230
friend Shared_Zp_field_element operator+(Shared_Zp_field_element f, const Integer_type &v)
operator+
Definition: Zp_field_shared.h:135
friend bool operator!=(const Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator!=
Definition: Zp_field_shared.h:262
friend void operator*=(Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator*=
Definition: Zp_field_shared.h:195
Shared_Zp_field_element(const Shared_Zp_field_element &toCopy)
Copy constructor.
Definition: Zp_field_shared.h:66
static Shared_Zp_field_element get_partial_multiplicative_identity(Characteristic productOfCharacteristics)
For interface purposes with multi-fields. Returns the multiplicative identity of the field.
Definition: Zp_field_shared.h:344
friend Shared_Zp_field_element operator*(Shared_Zp_field_element f, const Integer_type &v)
operator*
Definition: Zp_field_shared.h:220
static Shared_Zp_field_element get_additive_identity()
Returns the additive identity of the field.
Definition: Zp_field_shared.h:331
friend void operator-=(Shared_Zp_field_element &f, const Integer_type &v)
operator-=
Definition: Zp_field_shared.h:169
Unsigned_integer_type Element
Definition: Zp_field_shared.h:44
friend Shared_Zp_field_element operator-(Shared_Zp_field_element f1, const Shared_Zp_field_element &f2)
operator-
Definition: Zp_field_shared.h:159
friend Shared_Zp_field_element operator+(Shared_Zp_field_element f1, const Shared_Zp_field_element &f2)
operator+
Definition: Zp_field_shared.h:116
static Shared_Zp_field_element get_multiplicative_identity()
Returns the multiplicative identity of the field.
Definition: Zp_field_shared.h:337
friend void operator*=(Shared_Zp_field_element &f, const Integer_type &v)
operator*=
Definition: Zp_field_shared.h:211
friend void swap(Shared_Zp_field_element &f1, Shared_Zp_field_element &f2)
Swap operator.
Definition: Zp_field_shared.h:302
static Characteristic get_characteristic()
Returns the current characteristic.
Definition: Zp_field_shared.h:353
friend Shared_Zp_field_element operator-(Shared_Zp_field_element f, const Integer_type &v)
operator-
Definition: Zp_field_shared.h:178
friend Shared_Zp_field_element operator*(Shared_Zp_field_element f1, const Shared_Zp_field_element &f2)
operator*
Definition: Zp_field_shared.h:201
Element get_value() const
Returns the value of the element.
Definition: Zp_field_shared.h:105
Shared_Zp_field_element(Integer_type element)
Constructor setting the element to the given value.
Definition: Zp_field_shared.h:60
friend bool operator!=(const Integer_type &v, const Shared_Zp_field_element &f)
operator!=
Definition: Zp_field_shared.h:269
std::pair< Shared_Zp_field_element, Characteristic > get_partial_inverse(Characteristic productOfCharacteristics) const
For interface purposes with multi-fields. Returns the inverse together with the argument.
Definition: Zp_field_shared.h:321
friend Integer_type operator-(const Integer_type &v, const Shared_Zp_field_element &f)
operator-
Definition: Zp_field_shared.h:188
Shared_Zp_field_element(Shared_Zp_field_element &&toMove) noexcept
Move constructor.
Definition: Zp_field_shared.h:72
friend void operator+=(Shared_Zp_field_element &f, const Integer_type &v)
operator+=
Definition: Zp_field_shared.h:126
friend bool operator!=(const Shared_Zp_field_element &f, const Integer_type &v)
operator!=
Definition: Zp_field_shared.h:278
friend void operator+=(Shared_Zp_field_element &f1, const Shared_Zp_field_element &f2)
operator+=
Definition: Zp_field_shared.h:110
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14