Skip to content

Commit

Permalink
doc + revisting fields
Browse files Browse the repository at this point in the history
  • Loading branch information
hschreiber committed Apr 17, 2024
1 parent 308b3a9 commit e05b106
Show file tree
Hide file tree
Showing 12 changed files with 1,791 additions and 1,886 deletions.
139 changes: 59 additions & 80 deletions src/Persistence_matrix/include/gudhi/Fields/Multi_field.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

/**
* @file Multi_field.h
* @author Hannah Schreiber
* @author Hannah Schreiber, Clément Maria
* @brief Contains the @ref Multi_field_element class.
*/

Expand All @@ -36,30 +36,30 @@ namespace persistence_fields {
* @tparam maximum Interval closed upper bound.
*/
template <unsigned int minimum, unsigned int maximum>
class Multi_field_element
{
class Multi_field_element {
public:
using element_type = mpz_class; /**< Type for the elements in the field. */
using element_type = mpz_class; /**< Type for the elements in the field. */
using characteristic_type = element_type; /**< Type for the field characteristic. */

/**
* @brief Default constructor. Sets the element to 0.
*/
Multi_field_element();
/**
* @brief Constructor setting the element to the given value.
*
*
* @param element Value of the element.
*/
Multi_field_element(mpz_class element);
Multi_field_element(element_type element);
/**
* @brief Copy constructor.
*
*
* @param toCopy Element to copy.
*/
Multi_field_element(const Multi_field_element& toCopy);
/**
* @brief Move constructor.
*
*
* @param toMove Element to move.
*/
Multi_field_element(Multi_field_element&& toMove) noexcept;
Expand All @@ -81,22 +81,22 @@ class Multi_field_element
/**
* @brief operator+=
*/
friend void operator+=(Multi_field_element& f, mpz_class const v) {
friend void operator+=(Multi_field_element& f, element_type const v) {
mpz_add(f.element_.get_mpz_t(), f.element_.get_mpz_t(), v.get_mpz_t());
mpz_mod(f.element_.get_mpz_t(), f.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
}
/**
* @brief operator+
*/
friend Multi_field_element operator+(Multi_field_element f, mpz_class const v) {
friend Multi_field_element operator+(Multi_field_element f, element_type const v) {
f += v;
return f;
}
/**
* @brief operator+
*/
friend mpz_class operator+(mpz_class v, Multi_field_element const& f) {
mpz_class e(v);
friend element_type operator+(element_type v, Multi_field_element const& f) {
element_type e(v);
mpz_add(e.get_mpz_t(), e.get_mpz_t(), f.element_.get_mpz_t());
mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
return e;
Expand All @@ -119,22 +119,22 @@ class Multi_field_element
/**
* @brief operator-=
*/
friend void operator-=(Multi_field_element& f, mpz_class const v) {
friend void operator-=(Multi_field_element& f, element_type const v) {
mpz_sub(f.element_.get_mpz_t(), f.element_.get_mpz_t(), v.get_mpz_t());
mpz_mod(f.element_.get_mpz_t(), f.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
}
/**
* @brief operator-
*/
friend Multi_field_element operator-(Multi_field_element f, mpz_class const v) {
friend Multi_field_element operator-(Multi_field_element f, element_type const v) {
f -= v;
return f;
}
/**
* @brief operator-
*/
friend mpz_class operator-(mpz_class v, Multi_field_element const& f) {
mpz_class e(v);
friend element_type operator-(element_type v, Multi_field_element const& f) {
element_type e(v);
if (e >= productOfAllCharacteristics_)
mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
if (f.element_ > e) mpz_add(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
Expand All @@ -159,22 +159,22 @@ class Multi_field_element
/**
* @brief operator*=
*/
friend void operator*=(Multi_field_element& f, mpz_class const v) {
friend void operator*=(Multi_field_element& f, element_type const v) {
mpz_mul(f.element_.get_mpz_t(), f.element_.get_mpz_t(), v.get_mpz_t());
mpz_mod(f.element_.get_mpz_t(), f.element_.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
}
/**
* @brief operator*
*/
friend Multi_field_element operator*(Multi_field_element f, mpz_class const v) {
friend Multi_field_element operator*(Multi_field_element f, element_type const v) {
f *= v;
return f;
}
/**
* @brief operator*
*/
friend mpz_class operator*(mpz_class v, Multi_field_element const& f) {
mpz_class e(v);
friend element_type operator*(element_type v, Multi_field_element const& f) {
element_type e(v);
mpz_mul(e.get_mpz_t(), e.get_mpz_t(), f.element_.get_mpz_t());
mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
return e;
Expand All @@ -189,36 +189,18 @@ class Multi_field_element
/**
* @brief operator==
*/
friend bool operator==(const mpz_class v, const Multi_field_element& f) {
friend bool operator==(const element_type v, const Multi_field_element& f) {
if (v < productOfAllCharacteristics_) return v == f.element_;
mpz_class e(v);
element_type e(v);
mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
return e == f.element_;
}
/**
* @brief operator==
*/
friend bool operator==(const Multi_field_element& f, const mpz_class v) {
friend bool operator==(const Multi_field_element& f, const element_type v) {
if (v < productOfAllCharacteristics_) return v == f.element_;
mpz_class e(v);
mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
return e == f.element_;
}
/**
* @brief operator==
*/
friend bool operator==(const unsigned int v, const Multi_field_element& f) {
mpz_class e(v);
if (e < productOfAllCharacteristics_) return e == f.element_;
mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
return e == f.element_;
}
/**
* @brief operator==
*/
friend bool operator==(const Multi_field_element& f, const unsigned int v) {
mpz_class e(v);
if (e < productOfAllCharacteristics_) return e == f.element_;
element_type e(v);
mpz_mod(e.get_mpz_t(), e.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
return e == f.element_;
}
Expand All @@ -229,19 +211,11 @@ class Multi_field_element
/**
* @brief operator!=
*/
friend bool operator!=(const mpz_class v, const Multi_field_element& f) { return !(v == f); }
/**
* @brief operator!=
*/
friend bool operator!=(const Multi_field_element& f, const mpz_class v) { return !(v == f); }
friend bool operator!=(const element_type v, const Multi_field_element& f) { return !(v == f); }
/**
* @brief operator!=
*/
friend bool operator!=(const unsigned int v, const Multi_field_element& f) { return !(v == f); }
/**
* @brief operator!=
*/
friend bool operator!=(const Multi_field_element& f, const unsigned int v) { return !(v == f); }
friend bool operator!=(const Multi_field_element& f, const element_type v) { return !(v == f); }

/**
* @brief Assign operator.
Expand All @@ -250,7 +224,7 @@ class Multi_field_element
/**
* @brief Assign operator.
*/
Multi_field_element& operator=(const mpz_class value);
Multi_field_element& operator=(const element_type value);
/**
* @brief Swap operator.
*/
Expand All @@ -267,57 +241,58 @@ class Multi_field_element

/**
* @brief Returns the inverse of the element in the multi-field, see @cite boissonnat:hal-00922572.
*
*
* @return The inverse.
*/
Multi_field_element get_inverse() const;
/**
* @brief Returns the inverse of the element with respect to a sub-product of the characteristics in the multi-field,
* see @cite boissonnat:hal-00922572.
*
*
* @param productOfCharacteristics Sub-product of the characteristics.
* @return Pair of the inverse and the characteristic the inverse corresponds to.
*/
std::pair<Multi_field_element, mpz_class> get_partial_inverse(const mpz_class& productOfCharacteristics) const;
std::pair<Multi_field_element, characteristic_type> get_partial_inverse(
const characteristic_type& productOfCharacteristics) const;

/**
* @brief Returns the additive identity of a field.
*
*
* @return The additive identity of a field.
*/
static Multi_field_element get_additive_identity();
/**
* @brief Returns the multiplicative identity of a field.
*
*
* @return The multiplicative identity of a field.
*/
static Multi_field_element get_multiplicative_identity();
/**
* @brief Returns the partial multiplicative identity of the multi-field from the given product.
* See @cite boissonnat:hal-00922572 for more details.
*
*
* @param productOfCharacteristics Product of the different characteristics to take into account in the multi-field.
* @return The partial multiplicative identity of the multi-field.
*/
static Multi_field_element get_partial_multiplicative_identity(const mpz_class& productOfCharacteristics);
static Multi_field_element get_partial_multiplicative_identity(const characteristic_type& productOfCharacteristics);
/**
* @brief Returns the product of all characteristics.
*
*
* @return The product of all characteristics.
*/
static mpz_class get_characteristic();
static characteristic_type get_characteristic();

/**
* @brief Returns the value of the element.
*
*
* @return Value of the element.
*/
mpz_class get_value() const;
element_type get_value() const;

// static constexpr bool handles_only_z2() { return false; }

private:
mpz_class element_;
element_type element_;
static inline const std::vector<unsigned int> primes_ = []() {
std::vector<unsigned int> res;

Expand All @@ -341,16 +316,16 @@ class Multi_field_element

return res;
}();
static inline const mpz_class productOfAllCharacteristics_ = []() {
mpz_class res = 1;
static inline const characteristic_type productOfAllCharacteristics_ = []() {
characteristic_type res = 1;
for (const auto p : primes_) {
res *= p;
}

return res;
}();
static inline const std::vector<mpz_class> partials_ = []() {
std::vector<mpz_class> res;
static inline const std::vector<characteristic_type> partials_ = []() {
std::vector<characteristic_type> res;

if (productOfAllCharacteristics_ == 1) return res;

Expand All @@ -364,7 +339,7 @@ class Multi_field_element
}();
// If I understood the paper well, multiplicativeID_ always equals to 1. But in Clement's code,
// multiplicativeID_ is computed (see commented lambda function below). TODO: verify with Clement.
static inline const mpz_class multiplicativeID_ = 1; /*[](){
static inline const element_type multiplicativeID_ = 1; /*[](){
mpz_class res = 0;
for (unsigned int i = 0; i < partials_.size(); ++i){
res = (res + partials_[i]) % productOfAllCharacteristics_;
Expand All @@ -387,7 +362,7 @@ inline Multi_field_element<minimum, maximum>::Multi_field_element() : element_(0
}

template <unsigned int minimum, unsigned int maximum>
inline Multi_field_element<minimum, maximum>::Multi_field_element(mpz_class element) : element_(element) {
inline Multi_field_element<minimum, maximum>::Multi_field_element(element_type element) : element_(element) {
static_assert(maximum >= 2, "Characteristics has to be positive.");
static_assert(minimum <= maximum, "The given interval is not valid.");
static_assert(minimum != maximum || _is_prime(minimum), "The given interval does not contain a prime number.");
Expand Down Expand Up @@ -415,7 +390,8 @@ inline Multi_field_element<minimum, maximum>& Multi_field_element<minimum, maxim
}

template <unsigned int minimum, unsigned int maximum>
inline Multi_field_element<minimum, maximum>& Multi_field_element<minimum, maximum>::operator=(mpz_class const value) {
inline Multi_field_element<minimum, maximum>& Multi_field_element<minimum, maximum>::operator=(
element_type const value) {
mpz_mod(element_.get_mpz_t(), value.get_mpz_t(), productOfAllCharacteristics_.get_mpz_t());
return *this;
}
Expand All @@ -436,16 +412,17 @@ inline Multi_field_element<minimum, maximum> Multi_field_element<minimum, maximu
}

template <unsigned int minimum, unsigned int maximum>
inline std::pair<Multi_field_element<minimum, maximum>, mpz_class>
Multi_field_element<minimum, maximum>::get_partial_inverse(const mpz_class& productOfCharacteristics) const {
mpz_class QR;
inline std::pair<Multi_field_element<minimum, maximum>,
typename Multi_field_element<minimum, maximum>::characteristic_type>
Multi_field_element<minimum, maximum>::get_partial_inverse(const characteristic_type& productOfCharacteristics) const {
characteristic_type QR;
mpz_gcd(QR.get_mpz_t(), element_.get_mpz_t(), productOfCharacteristics.get_mpz_t()); // QR <- gcd(x,QS)

if (QR == productOfCharacteristics) return {Multi_field_element(), multiplicativeID_}; // partial inverse is 0

mpz_class QT = productOfCharacteristics / QR;
characteristic_type QT = productOfCharacteristics / QR;

mpz_class inv_qt;
characteristic_type inv_qt;
mpz_invert(inv_qt.get_mpz_t(), element_.get_mpz_t(), QT.get_mpz_t());

auto res = get_partial_multiplicative_identity(QT);
Expand All @@ -466,7 +443,7 @@ inline Multi_field_element<minimum, maximum> Multi_field_element<minimum, maximu

template <unsigned int minimum, unsigned int maximum>
inline Multi_field_element<minimum, maximum> Multi_field_element<minimum, maximum>::get_partial_multiplicative_identity(
const mpz_class& productOfCharacteristics) {
const characteristic_type& productOfCharacteristics) {
if (productOfCharacteristics == 0) {
return Multi_field_element<minimum, maximum>(multiplicativeID_);
}
Expand All @@ -480,12 +457,14 @@ inline Multi_field_element<minimum, maximum> Multi_field_element<minimum, maximu
}

template <unsigned int minimum, unsigned int maximum>
inline mpz_class Multi_field_element<minimum, maximum>::get_characteristic() {
inline typename Multi_field_element<minimum, maximum>::characteristic_type
Multi_field_element<minimum, maximum>::get_characteristic() {
return productOfAllCharacteristics_;
}

template <unsigned int minimum, unsigned int maximum>
inline mpz_class Multi_field_element<minimum, maximum>::get_value() const {
inline typename Multi_field_element<minimum, maximum>::element_type Multi_field_element<minimum, maximum>::get_value()
const {
return element_;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

/**
* @file Multi_field_operators.h
* @author Hannah Schreiber
* @author Hannah Schreiber, Clément Maria
* @brief Contains the @ref Multi_field_operators class.
*/

Expand Down
Loading

0 comments on commit e05b106

Please sign in to comment.