algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/root_modular.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : root_modular.hpp
00004 * DESCRIPTION: Roots for modulars over integers
00005 * COPYRIGHT  : (C) 2010  Gregoire Lecerf
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00011 ******************************************************************************/
00012 
00013 #ifndef __MMX_ROOT_MODULAR_HPP
00014 #define __MMX_ROOT_MODULAR_HPP
00015 
00016 #include <basix/list.hpp>
00017 #include <numerix/modular_int.hpp>
00018 #include <numerix/modular_integer.hpp>
00019 #include <algebramix/modular_polynomial.hpp>
00020 
00023 
00024 namespace mmx {
00025 
00026 #define C          typename scalar_type_helper<Polynomial>::val
00027 #define TMPL       template<typename Polynomial>
00028 #define Modulus_polynomial modulus<Polynomial>
00029 #define Modular_polynomial modular<Modulus_polynomial>
00030 
00031 struct root_modular_naive {
00032 
00033 TMPL static Polynomial
00034 pow_mod (const Polynomial& a, const integer& n, const Polynomial& f) {
00035   Modulus_polynomial _f= Modular_polynomial::get_modulus ();
00036   Modular_polynomial::set_modulus (f);
00037   Polynomial g= * binpow (Modular_polynomial (a), n);
00038   Modular_polynomial::set_modulus (_f);
00039   return g;
00040 }
00041 
00042 TMPL static Polynomial
00043 degree_one_factorization (const Polynomial& f, const integer& p) {
00044   // return the product of the linear factors
00045   Polynomial x (C(1), 1);
00046   Polynomial g= pow_mod (x, p, f) - x;
00047   return gcd (g, f);
00048 }
00049 
00050 TMPL static void
00051 linear_splitting (Polynomial& g, const Polynomial& f, const integer& p) {
00052   VERIFY (f != 0, "bug");
00053   nat n= deg (f); g= f;
00054   if (n == 1) return;
00055   Polynomial x (C(1), 1);
00056   nat counter= 0;
00057   while (deg (g) <= 0 || (nat) deg (g) == n) {
00058     vector<C> _a (C (0), n);
00059     for (nat i= 0; i < n; i++) _a[i]= C(rand ()); // TODO << improve
00060     Polynomial a (_a), b;
00061     g= gcd (a, f);
00062     if (deg (g) > 0) return;
00063     g= p == 2 ? gcd (a - 1, f)
00064               : gcd (pow_mod (a, (p-1) / 2, f) - 1, f);
00065     counter++;
00066   }
00067   //mmout << "Number of equal degree splitting failures: " << counter << "\n";
00068   ASSERT (deg (g) > 0 && (nat) deg (g) < n, "cannot find a linear factor"); }
00069 
00070 TMPL static vector<Polynomial>
00071 linear_factorization (const Polynomial& f, const integer& p) {
00072   VERIFY (f != 0, "bug");
00073   list<Polynomial> todo (f);
00074   vector<Polynomial> factors= vec<Polynomial> ();
00075   if (deg (f) <= 0) return factors;
00076   while (!is_nil (todo)) {
00077     Polynomial h= car(todo), g; todo= cdr(todo);
00078     linear_splitting (g, h, p); 
00079     if ((nat) deg (g) == 1) factors << g;
00080     else todo= cons (g, todo);
00081     if (deg (g) != deg (h)) todo= cons (h / g, todo);
00082   }
00083   return factors; }
00084 
00085 TMPL static vector<C>
00086 roots (const Polynomial& f, const integer& p) {
00087   if (deg (f) <= 0) {
00088     return vector<C> ();
00089   }
00090   //mmout << f << "\n";
00091   Polynomial g= degree_one_factorization (f, p);
00092   //mmout << g << "\n";
00093   vector<Polynomial> lin_facts= linear_factorization (g, p);
00094   vector<C> b (C(), N(lin_facts));
00095   for (nat i= 0; i < N(lin_facts); i++)
00096     b[i]= - lin_facts[i][0] / lin_facts[i][1];
00097   return b; }
00098 }; // struct modular_root_naive
00099 
00100 #undef C
00101 #undef TMPL
00102 #undef Modulus_polynomial
00103 #undef Modular_polynomial
00104 
00105 #define Modulus modulus<C,V>
00106 #define Modular modular<Modulus,W>
00107 
00108 template<typename C, typename V, typename W> vector<Modular>
00109 separable_roots (const Modular& a, nat r) {
00110   // return all the r th roots of a
00111   C p= * get_modulus (a);
00112   ASSERT (Modular (r) != 0, "wrong argument");
00113   polynomial<Modular> x_r (C(1),r);
00114   return root_modular_naive::roots (x_r - a, p);
00115 }
00116 
00117 template<typename C, typename V, typename W> Modular
00118 separable_root (const Modular& a, nat r) {
00119   // return one r th roots of a
00120   // FIXME << to optimize
00121   if (a == 1) return a;
00122   vector<Modular> ans= separable_roots (a, r); 
00123   ASSERT (N (ans) != 0, "no root");
00124   return ans [0];
00125 }
00126 
00127 template<typename C, typename V, typename W> inline Modular
00128 pth_root (const Modular& a) {
00129   // p-th root of a
00130   return a;
00131 }
00132 
00133 // general case
00134 
00135 template<typename C, typename V, typename W> vector<Modular>
00136 nth_roots (const Modular& a, nat r) {
00137   // return all the r th roots of a
00138   C p= * get_modulus (a);
00139   if (Modular (r) == 0) return nth_roots (a, r / as<nat> (p));
00140   return separable_roots (a, r);
00141 }
00142 
00143 template<typename C, typename V, typename W> Modular
00144 nth_root (const Modular& a, nat r) {
00145   if (a == 1) return a;
00146   vector<Modular> ans= nth_roots (a, r); 
00147   ASSERT (N (ans) != 0, "no root");
00148   return ans [0];
00149 }
00150 #undef Modulus
00151 #undef Modular
00152 } // namespace mmx    
00153 #endif // __MMX_ROOT_MODULAR_HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines