00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX_POLYNOMIAL_QUOTIENT_HPP
00014 #define __MMX_POLYNOMIAL_QUOTIENT_HPP
00015 #include <algebramix/quotient.hpp>
00016 #include <algebramix/polynomial_dicho.hpp>
00017 namespace mmx {
00018 #define TMPL template<typename C>
00019 #define NC Numerator_type(C)
00020 #define DC Denominator_type(C)
00021
00022
00023
00024
00025
00026 template<typename V>
00027 struct polynomial_quotient: public V {
00028 typedef typename V::Vec Vec;
00029 typedef typename V::Naive Naive;
00030 typedef polynomial_quotient<typename V::Positive> Positive;
00031 typedef polynomial_quotient<typename V::No_simd> No_simd;
00032 typedef polynomial_quotient<typename V::No_thread> No_thread;
00033 typedef polynomial_quotient<typename V::No_scaled> No_scaled;
00034 };
00035
00036 template<typename F, typename V, typename W>
00037 struct implementation<F,V,polynomial_quotient<W> >:
00038 public implementation<F,V,W> {};
00039
00040
00041
00042
00043
00044 template<typename C, typename V>
00045 struct polynomial_variant_helper<quotient<polynomial<C,V>,
00046 polynomial<C,V> > > {
00047 typedef polynomial_quotient<polynomial_naive> PV;
00048 };
00049
00050
00051
00052
00053
00054 template<typename V,typename W>
00055 struct implementation<polynomial_defaults,V,polynomial_quotient<W> > {
00056
00057 template<typename P>
00058 class global_variables {
00059 static inline generic& dyn_name () {
00060 static generic name = "x";
00061 return name; }
00062 public:
00063 static inline void set_variable_name (const generic& x) { dyn_name () = x; }
00064 static inline generic get_variable_name () { return dyn_name (); }
00065 };
00066
00067 template<typename C, typename V1, typename V2>
00068 class global_variables<polynomial<
00069 quotient<polynomial<C,V1>,
00070 polynomial<C,V1> >, V2> > {
00071 static inline generic& dyn_name () {
00072 static generic name = "y";
00073 return name; }
00074 public:
00075 static inline void set_variable_name (const generic& x) {
00076 dyn_name () = x; }
00077 static inline generic get_variable_name () {
00078 return dyn_name (); }
00079 };
00080 };
00081
00082
00083
00084
00085
00086 TMPL DC
00087 least_common_denominator (const C* src, nat n) {
00088 switch (n) {
00089 case 0: return 1;
00090 case 1: return denominator (src[0]);
00091 case 2: return lcm (denominator (src[0]), denominator (src[1]));
00092 case 3: return lcm (denominator (src[0]), lcm (denominator (src[1]),
00093 denominator (src[2])));
00094 default: return lcm (least_common_denominator (src, n>>1),
00095 least_common_denominator (src + (n>>1), n - (n>>1)));
00096 }
00097 }
00098
00099 TMPL void
00100 denominator_mul (NC* dest, const C* src, nat n, const DC& d) {
00101 for (nat i=0; i<n; i++)
00102 dest[i]= numerator (src[i]) * (d / denominator (src[i]));
00103 }
00104
00105 TMPL void
00106 denominator_div (C* dest, const NC* src, nat n, const DC& d) {
00107 for (nat i=0; i<n; i++)
00108 dest[i]= C (src[i]) / d;
00109 }
00110
00111
00112
00113
00114
00115 template<typename V, typename W>
00116 struct implementation<polynomial_multiply,V,polynomial_quotient<W> >:
00117 public implementation<polynomial_linear,V>
00118 {
00119 typedef polynomial_multiply_threshold<polynomial_quotient<W> > Th;
00120 typedef implementation<polynomial_multiply,W> Fallback;
00121
00122 TMPL static void
00123 mul (C* dest, const C* s1, const C* s2, nat n1, nat n2) {
00124 typedef typename Polynomial_variant(NC) NV;
00125 typedef implementation<polynomial_multiply,NV> Pol_N;
00126 if (min (n1, n2) < Threshold(C,Th))
00127 Fallback::mul (dest, s1, s2, n1, n2);
00128 else {
00129 DC d1 = least_common_denominator (s1, n1);
00130 DC d2 = least_common_denominator (s2, n2);
00131
00132
00133
00134
00135
00136
00137
00138 NC* Src1= mmx_new<NC> (n1);
00139 NC* Src2= mmx_new<NC> (n2);
00140 NC* Dest= mmx_new<NC> (n1+n2-1);
00141 denominator_mul (Src1, s1, n1, d1);
00142 denominator_mul (Src2, s2, n2, d2);
00143 Pol_N::mul (Dest, Src1, Src2, n1, n2);
00144 denominator_div (dest, Dest, n1+n2-1, d1*d2);
00145 mmx_delete<NC> (Src1, n1);
00146 mmx_delete<NC> (Src2, n2);
00147 mmx_delete<NC> (Dest, n1+n2-1);
00148 }
00149 }
00150
00151 TMPL static void
00152 square (C* dest, const C* s1, nat n1) {
00153 typedef typename Polynomial_variant(NC) NV;
00154 typedef implementation<polynomial_multiply,NV> Pol_N;
00155 if (n1 < Threshold(C,Th))
00156 Fallback::square (dest, s1, n1);
00157 else {
00158 DC d1 = least_common_denominator (s1, n1);
00159 NC* Src1= mmx_new<NC> (n1);
00160 NC* Dest= mmx_new<NC> (n1+n1-1);
00161 denominator_mul (Src1, s1, n1, d1);
00162 Pol_N::square (Dest, Src1, n1);
00163 denominator_div (dest, Dest, n1+n1-1, square_op::op (d1));
00164 mmx_delete<NC> (Src1, n1);
00165 mmx_delete<NC> (Dest, n1+n1-1);
00166 }
00167 }
00168
00169 TMPL static inline void
00170 tmul (C* dest, const C* s1, const C* s2, nat n1, nat n2) {
00171 (void) dest; (void) s1; (void) s2; (void) n1; (void) n2;
00172 ERROR ("transposed quotient multiplication not implemented");
00173 }
00174
00175 };
00176
00177 #undef TMPL
00178 #undef NC
00179 #undef DC
00180 }
00181 #endif // __MMX_POLYNOMIAL_QUOTIENT_HPP