00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef __MMX__POLYNOMIAL_TANGENT__HPP
00014 #define __MMX__POLYNOMIAL_TANGENT__HPP
00015 #include <algebramix/polynomial.hpp>
00016 #include <algebramix/polynomial_dicho.hpp>
00017 #include <numerix/tangent.hpp>
00018
00019 namespace mmx {
00020 #define TMPL template<typename C>
00021
00022
00023
00024
00025
00026 template<typename V>
00027 struct polynomial_tangent {
00028 typedef typename V::Vec Vec;
00029 typedef typename V::Naive Naive;
00030 typedef polynomial_tangent<typename V::Positive> Positive;
00031 typedef polynomial_tangent<typename V::No_simd> No_simd;
00032 typedef polynomial_tangent<typename V::No_thread> No_thread;
00033 typedef polynomial_tangent<typename V::No_scaled> No_scaled;
00034 };
00035
00036 template<typename F, typename V, typename W>
00037 struct implementation<F,V,polynomial_tangent<W> >:
00038 public implementation<F,V,W> {};
00039
00040 template<typename C>
00041 struct polynomial_variant_helper<tangent<C> > {
00042 typedef typename Polynomial_variant(C) CPV;
00043 typedef polynomial_tangent<CPV> PV;
00044 };
00045
00046
00047
00048
00049
00050 template<typename V, typename CV>
00051 struct implementation<polynomial_multiply,V,polynomial_tangent<CV> >:
00052 public implementation<polynomial_linear,V>
00053 {
00054 typedef implementation<vector_linear,CV> Vec_C;
00055 typedef implementation<polynomial_multiply,CV> Pol_C;
00056
00057 TMPL static inline void
00058 mul (tangent<C>* dest, const tangent<C>* s1, const tangent<C>* s2,
00059 nat n1, nat n2)
00060 {
00061 nat nd = n1 + n2 - 1;
00062 nat spc1 = aligned_size<C,CV> (n1);
00063 nat spc2 = aligned_size<C,CV> (n2);
00064 nat spcd = aligned_size<C,CV> (nd);
00065 nat spc = 5 * (spc1 + spc2);
00066 C* base_x1 = mmx_new<C> (spc);
00067 C* slope_x1= base_x1 + spc1;
00068 C* base_x2 = slope_x1 + spc1;
00069 C* slope_x2= base_x2 + spc2;
00070 C* base_d = slope_x2 + spc2;
00071 C* slope_d = base_d + spcd;
00072 C* extra_d = slope_d + spcd;
00073
00074 Vec_C::half_copy (base_x1, (C*) ((void*) s1), n1);
00075 Vec_C::half_copy (slope_x1, ((C*) ((void*) s1)) + 1, n1);
00076 Vec_C::half_copy (base_x2, (C*) ((void*) s2), n2);
00077 Vec_C::half_copy (slope_x2, ((C*) ((void*) s2)) + 1, n2);
00078 Pol_C::mul (base_d, base_x1, base_x2, n1, n2);
00079 Pol_C::mul (slope_d, base_x1, slope_x2, n1, n2);
00080 Pol_C::mul (extra_d, slope_x1, base_x2, n1, n2);
00081 Pol_C::add (slope_d, extra_d, nd);
00082 Vec_C::double_copy ((C*) ((void*) dest), base_d, nd);
00083 Vec_C::double_copy (((C*) ((void*) dest)) + 1, slope_d, nd);
00084
00085 mmx_delete<C> (base_x1, spc);
00086 }
00087
00088 TMPL static inline void
00089 square (tangent<C>* dest, const tangent<C>* s1, nat n1) {
00090 nat nd = n1 + n1 - 1;
00091 nat spc1 = aligned_size<C,CV> (n1);
00092 nat spcd = aligned_size<C,CV> (nd);
00093 nat spc = 6 * spc1;
00094 C* base_x1 = mmx_new<C> (spc);
00095 C* slope_x1= base_x1 + spc1;
00096 C* base_d = slope_x1 + spc1;
00097 C* slope_d = base_d + spcd;
00098
00099 Vec_C::half_copy (base_x1, (C*) ((void*) s1), n1);
00100 Vec_C::half_copy (slope_x1, ((C*) ((void*) s1)) + 1, n1);
00101 Pol_C::square (base_d, base_x1, n1);
00102 Pol_C::mul (slope_d, base_x1, slope_x1, n1, n1);
00103 Pol_C::add (slope_d, slope_d, nd);
00104 Vec_C::double_copy ((C*) ((void*) dest), base_d, nd);
00105 Vec_C::double_copy (((C*) ((void*) dest)) + 1, slope_d, nd);
00106
00107 mmx_delete<C> (base_x1, spc);
00108 }
00109
00110 TMPL static inline void
00111 tmul (C* dest, const C* s1, const C* s2, nat n1, nat n2) {
00112 (void) dest; (void) s1; (void) s2; (void) n1; (void) n2;
00113 ERROR ("transposed tangent multiplication not implemented");
00114 }
00115
00116 };
00117
00118 #undef TMPL
00119 }
00120 #endif //__MMX__POLYNOMIAL_TANGENT__HPP