algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : polynomial_schonhage.hpp 00004 * DESCRIPTION: Fast product for any ring with unity 00005 * COPYRIGHT : (C) 2008 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 // Ref. "Modern Computer Algebra", Chapter 8, Exercise 8.30. 00014 00015 #ifndef __MMX__POLYNOMIAL_SCHONHAGE__HPP 00016 #define __MMX__POLYNOMIAL_SCHONHAGE__HPP 00017 #include <numerix/modulus.hpp> 00018 #include <algebramix/polynomial_dicho.hpp> 00019 #include <algebramix/polynomial_schonhage_strassen.hpp> 00020 #include <algebramix/polynomial_schonhage_triadic.hpp> 00021 00022 namespace mmx { 00023 #define TMPL template<typename C> 00024 00025 /****************************************************************************** 00026 * Variant for Schonhage multiplication 00027 ******************************************************************************/ 00028 00029 struct schonhage_threshold {}; 00030 struct schonhage_internal_threshold {}; 00031 00032 template<typename V, 00033 typename Th1= schonhage_threshold, 00034 typename Th2= schonhage_internal_threshold> 00035 struct polynomial_schonhage_inc: public V { 00036 typedef typename V::Vec Vec; 00037 typedef typename V::Naive Naive; 00038 typedef typename V::Positive Positive; 00039 typedef polynomial_schonhage_inc<typename V::No_simd,Th1,Th2> No_simd; 00040 typedef polynomial_schonhage_inc<typename V::No_thread,Th1,Th2> No_thread; 00041 typedef polynomial_schonhage_inc<typename V::No_scaled,Th1,Th2> No_scaled; 00042 }; 00043 00044 template<typename F, typename V, typename W, typename Th1, typename Th2> 00045 struct implementation<F,V,polynomial_schonhage_inc<W,Th1,Th2> >: 00046 public implementation<F,V,W> {}; 00047 00048 DEFINE_VARIANT_1 (typename V, V, 00049 polynomial_schonhage, 00050 polynomial_balanced_tft< 00051 polynomial_schonhage_inc< 00052 polynomial_karatsuba<V> > >) 00053 00054 /****************************************************************************** 00055 * Multiplication 00056 ******************************************************************************/ 00057 00058 template<typename V, typename W, typename Th, typename Th_rec> 00059 struct implementation<polynomial_multiply,V, 00060 polynomial_schonhage_inc<W,Th,Th_rec> >: 00061 public implementation<polynomial_linear,V> 00062 { 00063 typedef implementation<vector_linear,V> Vec; 00064 typedef implementation<polynomial_multiply,W> Fallback; 00065 00066 TMPL static inline void 00067 mul (C* dest, const C* s1, const C* s2, nat n1, nat n2) { 00068 typedef polynomial_schonhage_strassen_inc<V,Th_rec> V2; 00069 typedef polynomial_schonhage_triadic_inc<V,Th_rec> V3; 00070 typedef implementation<polynomial_multiply,V2> Pol2; 00071 typedef implementation<polynomial_multiply,V3> Pol3; 00072 typedef modulus_int_naive<8*sizeof(nat)> MV; 00073 typedef modulus<nat, MV> Modulus; 00074 if (n1 < Threshold(C,Th) || n2 < Threshold(C,Th)) { 00075 Fallback::mul (dest, s1, s2, n1, n2); 00076 return; 00077 } 00078 nat n = n1 + n2 - 1; 00079 nat l = aligned_size<C,V> (n); 00080 C* temp = mmx_new<C> (l); 00081 nat k2= Pol2::mul (dest, s1, s2, n1, n2, false); 00082 if (k2 == 0) return; 00083 nat k3= Pol3::mul (temp, s1, s2, n1, n2, false); 00084 if (k3 == 0) { 00085 Vec::copy (dest, temp, n); 00086 return; 00087 } 00088 nat u2, u3; 00089 nat c2= ((nat) 1) << k2, c3= binpow ((nat) 3, k3); 00090 MV::inv_mod (u2, binpow ((nat) 2, k2), Modulus (c3)); 00091 MV::inv_mod (u3, binpow ((nat) 3, k3), Modulus (c2)); 00092 u3= c2 - u3; 00093 VERIFY (u2*c2 - u3*c3 == 1, "bug"); 00094 Vec::mul (dest, C(u2), n); 00095 Vec::mul (temp, C(u3), n); 00096 Vec::sub (dest, temp , n); 00097 mmx_delete<C> (temp, l); } 00098 00099 TMPL static inline void 00100 square (C* dest, const C* s1, nat n1) { 00101 mul (dest, s1, s1, n1, n1); } 00102 00103 }; // implementation<polynomial_multiply,V,polynomial_schonhage_inc<W,Th,Th_rec> > 00104 00105 /****************************************************************************** 00106 * Schonhage Strassen multiplication for generic coefficients 00107 ******************************************************************************/ 00108 00109 DEFINE_VARIANT (polynomial_generic_schonhage, 00110 polynomial_ring_dicho< 00111 polynomial_schonhage< 00112 polynomial_ring_naive< 00113 polynomial_naive> > >) 00114 00115 STMPL 00116 struct threshold_helper<generic, 00117 polynomial_multiply_threshold< 00118 polynomial_generic_schonhage> > { 00119 typedef fixed_value<nat,16> impl; 00120 }; 00121 00122 STMPL 00123 struct threshold_helper<generic, schonhage_threshold> { 00124 typedef fixed_value<nat,16384> impl; 00125 }; 00126 00127 STMPL 00128 struct threshold_helper<generic, schonhage_internal_threshold> { 00129 typedef fixed_value<nat,128> impl; 00130 }; 00131 00132 #define POLYNOMIAL_GENERIC_USES_SCHONHAGE \ 00133 STMPL \ 00134 struct polynomial_variant_helper<generic> { \ 00135 typedef polynomial_generic_schonhage PV; \ 00136 }; 00137 00138 #undef TMPL 00139 } // namespace mmx 00140 #endif //__MMX__POLYNOMIAL_SCHONHAGE__HPP