summaryrefslogtreecommitdiff
path: root/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h')
-rw-r--r--src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h
new file mode 100644
index 00000000..9dd0998c
--- /dev/null
+++ b/src/Persistent_cohomology/include/gudhi/Persistent_cohomology/Multi_field.h
@@ -0,0 +1,167 @@
+ /* This file is part of the Gudhi Library. The Gudhi library
+ * (Geometric Understanding in Higher Dimensions) is a generic C++
+ * library for computational topology.
+ *
+ * Author(s): Clément Maria
+ *
+ * Copyright (C) 2014 INRIA Sophia Antipolis-Méditerranée (France)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GUDHI_MULTI_FIELD_H
+#define GUDHI_MULTI_FIELD_H
+
+#include <iostream>
+#include <vector>
+#include <gmpxx.h>
+
+namespace Gudhi{
+
+/** \brief Structure representing coefficients in a set of finite fields simultaneously
+ * using the chinese remainder theorem.
+ *
+ * \implements CoefficientField
+ * \ingroup persistent_cohomology
+
+ * Details on the algorithms may be found in \cite boissonnat:hal-00922572
+ */
+class Multi_field {
+public:
+ typedef mpz_class Element;
+
+ Multi_field () {}
+
+/* Initialize the multi-field. The generation of prime numbers might fail with
+ * a very small probability.*/
+ void init(int min_prime, int max_prime)
+ {
+ if(max_prime<2)
+ { std::cerr << "There is no prime less than " << max_prime << std::endl; }
+ if(min_prime > max_prime)
+ { std::cerr << "No prime in ["<<min_prime<<":"<<max_prime<<"]"<<std::endl; }
+ // fill the list of prime numbers
+ unsigned int curr_prime = min_prime;
+ mpz_t tmp_prime; mpz_init_set_ui(tmp_prime,min_prime);
+ //test if min_prime is prime
+ int is_prime = mpz_probab_prime_p(tmp_prime,25); //probabilistic primality test
+
+ if(is_prime == 0) //min_prime is composite
+ {
+ mpz_nextprime(tmp_prime,tmp_prime);
+ curr_prime = mpz_get_ui(tmp_prime);
+ }
+
+ while (curr_prime <= max_prime)
+ {
+ primes_.push_back(curr_prime);
+ mpz_nextprime(tmp_prime,tmp_prime);
+ curr_prime = mpz_get_ui(tmp_prime);
+ }
+ //set m to primorial(bound_prime)
+ prod_characteristics_ = 1;
+ for(auto p : primes_)
+ { mpz_mul_ui(prod_characteristics_.get_mpz_t(),
+ prod_characteristics_.get_mpz_t(),
+ p);
+ }
+
+ num_primes_ = primes_.size();
+
+ //Uvect_
+ Element Ui; Element tmp_elem;
+ for(auto p : primes_)
+ {
+ tmp_elem = prod_characteristics_ / p;
+ //Element tmp_elem_bis = 10;
+ mpz_powm_ui ( tmp_elem.get_mpz_t()
+ , tmp_elem.get_mpz_t()
+ , p - 1
+ , prod_characteristics_.get_mpz_t() );
+ Uvect_.push_back(tmp_elem);
+ }
+ mult_id_all = 0;
+ for(int idx = 0; idx < num_primes_; ++idx)
+ { mult_id_all = (mult_id_all + Uvect_[idx]) % prod_characteristics_; }
+
+ }
+
+ void clear_coefficient(Element & x) { mpz_clear(x.get_mpz_t()); }
+
+ /** \brief Returns the additive idendity \f$0_{\Bbbk}\f$ of the field.*/
+ Element additive_identity () { return 0; }
+ /** \brief Returns the multiplicative identity \f$1_{\Bbbk}\f$ of the field.*/
+ Element multiplicative_identity () { return mult_id_all; }// 1 everywhere
+
+ Element multiplicative_identity (Element Q)
+ {
+ if(Q == prod_characteristics_) { return multiplicative_identity(); }
+
+ Element mult_id = 0;
+ for(int idx = 0; idx < num_primes_; ++idx) {
+ if( (Q % primes_[idx]) == 0 )
+ { mult_id = (mult_id + Uvect_[idx]) % prod_characteristics_; }
+ }
+ return mult_id;
+ }
+
+ /** Returns y * w */
+ Element times ( Element y, int w ) {
+ Element tmp = (y*w) % prod_characteristics_;
+ if(tmp < 0) return prod_characteristics_ + tmp;
+ return tmp;
+ }
+
+ void plus_equal(Element & x, Element y)
+ { x += y; x %= prod_characteristics_; }
+
+ /** \brief Returns the characteristic \f$p\f$ of the field.*/
+ Element characteristic() { return prod_characteristics_; }
+
+ /** Returns the inverse in the field. Modifies P.*/
+ std::pair<Element,Element> inverse ( Element x
+ , Element QS )
+ {
+ Element QR;
+ mpz_gcd( QR.get_mpz_t(), x.get_mpz_t(), QS.get_mpz_t() ); // QR <- gcd(x,QS)
+ if( QR == QS ) return std::pair<Element,Element>(additive_identity()
+ , multiplicative_identity() ); //partial inverse is 0
+ Element QT = QS / QR;
+ Element inv_qt;
+ mpz_invert(inv_qt.get_mpz_t(), x.get_mpz_t(), QT.get_mpz_t());
+
+ return std::pair<Element,Element>(
+ (inv_qt * multiplicative_identity(QT)) % prod_characteristics_
+ , QT );
+ }
+ /** Returns -x * y.*/
+ Element times_minus ( Element x, Element y )
+ { return prod_characteristics_ - ((x*y)%prod_characteristics_); }
+
+ /** Set x <- x + w * y*/
+ void plus_times_equal ( Element & x, Element y, Element w )
+ { x = (x + w * y) % prod_characteristics_; }
+
+ Element prod_characteristics_; //product of characteristics of the fields
+ //represented by the multi-field class
+ std::vector<int> primes_; //all the characteristics of the fields
+ std::vector<Element> Uvect_;
+ size_t num_primes_; //number of fields
+ Element mult_id_all;
+
+};
+
+} // namespace GUDHI
+
+#endif // GUDHI_MULTI_FIELD_H