algebramix_doc 0.3
|
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