00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef EIGEN_SUM_H
00027 #define EIGEN_SUM_H
00028
00029
00030
00031
00032
00033 template<typename Derived>
00034 struct ei_sum_traits
00035 {
00036 private:
00037 enum {
00038 PacketSize = ei_packet_traits<typename Derived::Scalar>::size
00039 };
00040
00041 public:
00042 enum {
00043 Vectorization = (int(Derived::Flags)&ActualPacketAccessBit)
00044 && (int(Derived::Flags)&LinearAccessBit)
00045 ? LinearVectorization
00046 : NoVectorization
00047 };
00048
00049 private:
00050 enum {
00051 Cost = Derived::SizeAtCompileTime * Derived::CoeffReadCost
00052 + (Derived::SizeAtCompileTime-1) * NumTraits<typename Derived::Scalar>::AddCost,
00053 UnrollingLimit = EIGEN_UNROLLING_LIMIT * (int(Vectorization) == int(NoVectorization) ? 1 : int(PacketSize))
00054 };
00055
00056 public:
00057 enum {
00058 Unrolling = Cost <= UnrollingLimit
00059 ? CompleteUnrolling
00060 : NoUnrolling
00061 };
00062 };
00063
00064
00065
00066
00067
00068
00069
00070 template<typename Derived, int Start, int Length>
00071 struct ei_sum_novec_unroller
00072 {
00073 enum {
00074 HalfLength = Length/2
00075 };
00076
00077 typedef typename Derived::Scalar Scalar;
00078
00079 inline static Scalar run(const Derived &mat)
00080 {
00081 return ei_sum_novec_unroller<Derived, Start, HalfLength>::run(mat)
00082 + ei_sum_novec_unroller<Derived, Start+HalfLength, Length-HalfLength>::run(mat);
00083 }
00084 };
00085
00086 template<typename Derived, int Start>
00087 struct ei_sum_novec_unroller<Derived, Start, 1>
00088 {
00089 enum {
00090 col = Start / Derived::RowsAtCompileTime,
00091 row = Start % Derived::RowsAtCompileTime
00092 };
00093
00094 typedef typename Derived::Scalar Scalar;
00095
00096 inline static Scalar run(const Derived &mat)
00097 {
00098 return mat.coeff(row, col);
00099 }
00100 };
00101
00102
00103
00104 template<typename Derived, int Start, int Length>
00105 struct ei_sum_vec_unroller
00106 {
00107 enum {
00108 PacketSize = ei_packet_traits<typename Derived::Scalar>::size,
00109 HalfLength = Length/2
00110 };
00111
00112 typedef typename Derived::Scalar Scalar;
00113 typedef typename ei_packet_traits<Scalar>::type PacketScalar;
00114
00115 inline static PacketScalar run(const Derived &mat)
00116 {
00117 return ei_padd(
00118 ei_sum_vec_unroller<Derived, Start, HalfLength>::run(mat),
00119 ei_sum_vec_unroller<Derived, Start+HalfLength, Length-HalfLength>::run(mat) );
00120 }
00121 };
00122
00123 template<typename Derived, int Start>
00124 struct ei_sum_vec_unroller<Derived, Start, 1>
00125 {
00126 enum {
00127 index = Start * ei_packet_traits<typename Derived::Scalar>::size,
00128 row = int(Derived::Flags)&RowMajorBit
00129 ? index / int(Derived::ColsAtCompileTime)
00130 : index % Derived::RowsAtCompileTime,
00131 col = int(Derived::Flags)&RowMajorBit
00132 ? index % int(Derived::ColsAtCompileTime)
00133 : index / Derived::RowsAtCompileTime,
00134 alignment = (Derived::Flags & AlignedBit) ? Aligned : Unaligned
00135 };
00136
00137 typedef typename Derived::Scalar Scalar;
00138 typedef typename ei_packet_traits<Scalar>::type PacketScalar;
00139
00140 inline static PacketScalar run(const Derived &mat)
00141 {
00142 return mat.template packet<alignment>(row, col);
00143 }
00144 };
00145
00146
00147
00148
00149
00150 template<typename Derived,
00151 int Vectorization = ei_sum_traits<Derived>::Vectorization,
00152 int Unrolling = ei_sum_traits<Derived>::Unrolling
00153 >
00154 struct ei_sum_impl;
00155
00156 template<typename Derived>
00157 struct ei_sum_impl<Derived, NoVectorization, NoUnrolling>
00158 {
00159 typedef typename Derived::Scalar Scalar;
00160 static Scalar run(const Derived& mat)
00161 {
00162 ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using a non initialized matrix");
00163 Scalar res;
00164 res = mat.coeff(0, 0);
00165 for(int i = 1; i < mat.rows(); ++i)
00166 res += mat.coeff(i, 0);
00167 for(int j = 1; j < mat.cols(); ++j)
00168 for(int i = 0; i < mat.rows(); ++i)
00169 res += mat.coeff(i, j);
00170 return res;
00171 }
00172 };
00173
00174 template<typename Derived>
00175 struct ei_sum_impl<Derived, NoVectorization, CompleteUnrolling>
00176 : public ei_sum_novec_unroller<Derived, 0, Derived::SizeAtCompileTime>
00177 {};
00178
00179 template<typename Derived>
00180 struct ei_sum_impl<Derived, LinearVectorization, NoUnrolling>
00181 {
00182 typedef typename Derived::Scalar Scalar;
00183 typedef typename ei_packet_traits<Scalar>::type PacketScalar;
00184
00185 static Scalar run(const Derived& mat)
00186 {
00187 const int size = mat.size();
00188 const int packetSize = ei_packet_traits<Scalar>::size;
00189 const int alignedStart = (Derived::Flags & AlignedBit)
00190 || !(Derived::Flags & DirectAccessBit)
00191 ? 0
00192 : ei_alignmentOffset(&mat.const_cast_derived().coeffRef(0), size);
00193 enum {
00194 alignment = (Derived::Flags & DirectAccessBit) || (Derived::Flags & AlignedBit)
00195 ? Aligned : Unaligned
00196 };
00197 const int alignedSize = ((size-alignedStart)/packetSize)*packetSize;
00198 const int alignedEnd = alignedStart + alignedSize;
00199 Scalar res;
00200
00201 if(alignedSize)
00202 {
00203 PacketScalar packet_res = mat.template packet<alignment>(alignedStart);
00204 for(int index = alignedStart + packetSize; index < alignedEnd; index += packetSize)
00205 packet_res = ei_padd(packet_res, mat.template packet<alignment>(index));
00206 res = ei_predux(packet_res);
00207 }
00208 else
00209
00210 {
00211 res = Scalar(0);
00212 }
00213
00214 for(int index = 0; index < alignedStart; ++index)
00215 res += mat.coeff(index);
00216
00217 for(int index = alignedEnd; index < size; ++index)
00218 res += mat.coeff(index);
00219
00220 return res;
00221 }
00222 };
00223
00224 template<typename Derived>
00225 struct ei_sum_impl<Derived, LinearVectorization, CompleteUnrolling>
00226 {
00227 typedef typename Derived::Scalar Scalar;
00228 typedef typename ei_packet_traits<Scalar>::type PacketScalar;
00229 enum {
00230 PacketSize = ei_packet_traits<Scalar>::size,
00231 Size = Derived::SizeAtCompileTime,
00232 VectorizationSize = (Size / PacketSize) * PacketSize
00233 };
00234 static Scalar run(const Derived& mat)
00235 {
00236 Scalar res = ei_predux(ei_sum_vec_unroller<Derived, 0, Size / PacketSize>::run(mat));
00237 if (VectorizationSize != Size)
00238 res += ei_sum_novec_unroller<Derived, VectorizationSize, Size-VectorizationSize>::run(mat);
00239 return res;
00240 }
00241 };
00242
00243
00244
00245
00246
00251 template<typename Derived>
00252 inline typename ei_traits<Derived>::Scalar
00253 MatrixBase<Derived>::sum() const
00254 {
00255 return ei_sum_impl<Derived>::run(derived());
00256 }
00257
00264 template<typename Derived>
00265 inline typename ei_traits<Derived>::Scalar
00266 MatrixBase<Derived>::trace() const
00267 {
00268 return diagonal().sum();
00269 }
00270
00271 #endif // EIGEN_SUM_H