00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef MTL_REDUCTION_INCLUDE
00013 #define MTL_REDUCTION_INCLUDE
00014
00015 #include <boost/static_assert.hpp>
00016 #include <boost/numeric/meta_math/loop1.hpp>
00017 #include <boost/numeric/mtl/utility/tag.hpp>
00018 #include <boost/numeric/mtl/utility/category.hpp>
00019 #include <boost/numeric/mtl/utility/range_generator.hpp>
00020
00021 namespace mtl { namespace vector {
00022
00023
00024 namespace impl {
00025
00026 template <unsigned long Index0, unsigned long Max0, typename Functor>
00027 struct reduction
00028 {
00029 typedef reduction<Index0+1, Max0, Functor> next;
00030
00031 template <typename Value>
00032 static inline void init(Value& tmp00, Value& tmp01, Value& tmp02, Value& tmp03, Value& tmp04,
00033 Value& tmp05, Value& tmp06, Value& tmp07)
00034 {
00035 Functor::init(tmp00);
00036 next::init(tmp01, tmp02, tmp03, tmp04, tmp05, tmp06, tmp07, tmp00);
00037 }
00038
00039 template <typename Value, typename Vector, typename Size>
00040 static inline void update(Value& tmp00, Value& tmp01, Value& tmp02, Value& tmp03, Value& tmp04,
00041 Value& tmp05, Value& tmp06, Value& tmp07, const Vector& v, Size i)
00042 {
00043 Functor::update(tmp00, v[ i + Index0-1 ]);
00044 next::update(tmp01, tmp02, tmp03, tmp04, tmp05, tmp06, tmp07, tmp00, v, i);
00045 }
00046
00047 template <typename Value>
00048 static inline void finish(Value& tmp00, Value& tmp01, Value& tmp02, Value& tmp03, Value& tmp04,
00049 Value& tmp05, Value& tmp06, Value& tmp07)
00050 {
00051 next::finish(tmp01, tmp02, tmp03, tmp04, tmp05, tmp06, tmp07, tmp00);
00052 Functor::finish(tmp00, tmp01);
00053 }
00054 };
00055
00056
00057 template <unsigned long Max0, typename Functor>
00058 struct reduction<Max0, Max0, Functor>
00059 {
00060 template <typename Value>
00061 static inline void init(Value& tmp00, Value&, Value&, Value&, Value&, Value&, Value&, Value&)
00062 {
00063 Functor::init(tmp00);
00064 }
00065
00066 template <typename Value, typename Vector, typename Size>
00067 static inline void update(Value& tmp00, Value&, Value&, Value&, Value&, Value&, Value&, Value&,
00068 const Vector& v, Size i)
00069 {
00070 Functor::update(tmp00, v[ i + Max0-1 ]);
00071 }
00072
00073 template <typename Value>
00074 static inline void finish(Value& tmp00, Value&, Value&, Value&, Value&, Value&, Value&, Value&) {}
00075
00076 };
00077
00078 }
00079
00080
00081
00082 template <unsigned long Unroll, typename Functor, typename Result>
00083 struct reduction
00084 {
00085 template <typename Vector>
00086 Result static inline apply(const Vector& v)
00087 {
00088 return apply(v, typename mtl::traits::category<Vector>::type());
00089 }
00090
00091
00092 private:
00093 template <typename Vector>
00094 Result static inline apply(const Vector& v, tag::sparse)
00095 {
00096 Result tmp00;
00097 Functor::init(tmp00);
00098
00099 typename mtl::traits::const_value<Vector>::type value(v);
00100 typedef typename mtl::traits::range_generator<tag::nz, Vector>::type cursor_type;
00101
00102 for (cursor_type cursor = begin<tag::nz>(v), cend = end<tag::nz>(v); cursor != cend; ++cursor)
00103 Functor::update(tmp00, value(*cursor));
00104 return tmp00;
00105 }
00106
00107 template <typename Vector>
00108 Result static inline apply(const Vector& v, tag::dense)
00109 {
00110 BOOST_STATIC_ASSERT((Unroll >= 1));
00111 BOOST_STATIC_ASSERT((Unroll <= 8));
00112
00113 Result tmp00, tmp01, tmp02, tmp03, tmp04, tmp05, tmp06, tmp07;
00114 impl::reduction<1, Unroll, Functor>::init(tmp00, tmp01, tmp02, tmp03, tmp04, tmp05, tmp06, tmp07);
00115
00116 typedef typename Collection<Vector>::size_type size_type;
00117 size_type i_max= size(v), i_block= Unroll * (i_max / Unroll);
00118
00119 for (size_type i= 0; i < i_block; i+= Unroll)
00120 impl::reduction<1, Unroll, Functor>::update(tmp00, tmp01, tmp02, tmp03,
00121 tmp04, tmp05, tmp06, tmp07, v, i);
00122
00123 for (size_type i= i_block; i < i_max; i++)
00124 Functor::update(tmp00, v[i]);
00125
00126 impl::reduction<1, Unroll, Functor>::finish(tmp00, tmp01, tmp02, tmp03, tmp04, tmp05, tmp06, tmp07);
00127 return tmp00;
00128 }
00129 };
00130
00131
00132
00133
00134
00135
00136
00137
00138 }}
00139
00140 #endif // MTL_REDUCTION_INCLUDE