00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_DOT_INCLUDE
00013 #define MTL_DOT_INCLUDE
00014
00015 #include <boost/numeric/mtl/concept/std_concept.hpp>
00016 #include <boost/numeric/mtl/concept/collection.hpp>
00017 #include <boost/numeric/mtl/operation/conj.hpp>
00018 #include <boost/numeric/meta_math/loop1.hpp>
00019 #include <boost/numeric/linear_algebra/identity.hpp>
00020
00021 namespace mtl {
00022
00023 namespace vector {
00024
00025 namespace detail {
00026
00027
00028 template <typename Vector1, typename Vector2>
00029 struct dot_result
00030 {
00031 typedef typename Multiplicable<typename Collection<Vector1>::value_type,
00032 typename Collection<Vector2>::value_type>::result_type type;
00033 };
00034
00035
00036 struct without_conj
00037 {
00038 template <typename Value>
00039 Value operator()(const Value& v) { return v; }
00040 };
00041
00042 struct with_conj
00043 {
00044 template <typename Value>
00045 typename mtl::sfunctor::conj<Value>::result_type
00046 operator() (const Value& v)
00047 {
00048 using mtl::conj;
00049 return conj(v);
00050 }
00051 };
00052 }
00053
00054 namespace sfunctor {
00055
00056 template <unsigned long Index0, unsigned long Max0>
00057 struct dot_aux
00058 : public meta_math::loop1<Index0, Max0>
00059 {
00060 typedef meta_math::loop1<Index0, Max0> base;
00061 typedef dot_aux<base::next_index0, Max0> next_t;
00062
00063 template <typename Value, typename Vector1, typename Vector2, typename Size, typename ConjOpt>
00064 static inline void
00065 apply(Value& tmp00, Value& tmp01, Value& tmp02, Value& tmp03, Value& tmp04,
00066 Value& tmp05, Value& tmp06, Value& tmp07,
00067 const Vector1& v1, const Vector2& v2, Size i, ConjOpt conj_opt)
00068 {
00069 tmp00+= conj_opt(v1[ i + base::index0 ]) * v2[ i + base::index0 ];
00070 next_t::apply(tmp01, tmp02, tmp03, tmp04, tmp05, tmp06, tmp07, tmp00,
00071 v1, v2, i, conj_opt);
00072 }
00073 };
00074
00075
00076 template <unsigned long Max0>
00077 struct dot_aux<Max0, Max0>
00078 {
00079 typedef meta_math::loop1<Max0, Max0> base;
00080
00081 template <typename Value, typename Vector1, typename Vector2, typename Size, typename ConjOpt>
00082 static inline void
00083 apply(Value& tmp00, Value&, Value&, Value&, Value&, Value&, Value&, Value&,
00084 const Vector1& v1, const Vector2& v2, Size i, ConjOpt conj_opt)
00085 {
00086 tmp00+= conj_opt(v1[ i + base::index0 ]) * v2[ i + base::index0 ];
00087 }
00088 };
00089
00090
00091 template <unsigned long Unroll>
00092 struct dot
00093 {
00094 template <typename Vector1, typename Vector2, typename ConjOpt>
00095 typename detail::dot_result<Vector1, Vector2>::type
00096 static inline apply(const Vector1& v1, const Vector2& v2, ConjOpt conj_opt)
00097 {
00098 MTL_THROW_IF(size(v1) != size(v2), incompatible_size());
00099
00100 typedef typename Collection<Vector1>::size_type size_type;
00101 typedef typename detail::dot_result<Vector1, Vector2>::type value_type;
00102
00103 value_type dummy, z= math::zero(dummy), tmp00= z, tmp01= z, tmp02= z, tmp03= z, tmp04= z,
00104 tmp05= z, tmp06= z, tmp07= z;
00105 size_type i_max= size(v1), i_block= Unroll * (i_max / Unroll);
00106
00107 for (size_type i= 0; i < i_block; i+= Unroll)
00108 dot_aux<1, Unroll>::apply(tmp00, tmp01, tmp02, tmp03, tmp04, tmp05, tmp06, tmp07, v1, v2, i, conj_opt);
00109
00110 for (size_type i= i_block; i < i_max; i++)
00111 tmp00+= conj_opt(v1[i]) * v2[i];
00112 return ((tmp00 + tmp01) + (tmp02 + tmp03)) + ((tmp04 + tmp05) + (tmp06 + tmp07));
00113 }
00114 };
00115 }
00116
00118
00119 template <typename Vector1, typename Vector2>
00120 typename detail::dot_result<Vector1, Vector2>::type
00121 inline dot(const Vector1& v1, const Vector2& v2)
00122 {
00123 return sfunctor::dot<8>::apply(v1, v2, detail::with_conj());
00124 }
00125
00127 template <unsigned long Unroll, typename Vector1, typename Vector2>
00128 typename detail::dot_result<Vector1, Vector2>::type
00129 inline dot(const Vector1& v1, const Vector2& v2)
00130 {
00131 return sfunctor::dot<Unroll>::apply(v1, v2, detail::with_conj());
00132 }
00133
00135
00136 template <typename Vector1, typename Vector2>
00137 typename detail::dot_result<Vector1, Vector2>::type
00138 inline dot_real(const Vector1& v1, const Vector2& v2)
00139 {
00140 return sfunctor::dot<8>::apply(v1, v2, detail::without_conj());
00141 }
00142
00144 template <unsigned long Unroll, typename Vector1, typename Vector2>
00145 typename detail::dot_result<Vector1, Vector2>::type
00146 inline dot_real(const Vector1& v1, const Vector2& v2)
00147 {
00148 return sfunctor::dot<Unroll>::apply(v1, v2, detail::without_conj());
00149 }
00150
00151
00152 }
00153
00154 using vector::dot;
00155 using vector::dot_real;
00156
00157 }
00158
00159 #endif // MTL_DOT_INCLUDE