fix sum()/prod() on empty matrix making sure this does not affect fixed sized object, extend related unit tests including partial reduction
diff --git a/Eigen/src/Core/Redux.h b/Eigen/src/Core/Redux.h
index b1dd7d7..504a512 100644
--- a/Eigen/src/Core/Redux.h
+++ b/Eigen/src/Core/Redux.h
@@ -183,7 +183,7 @@
   typedef typename Derived::Index Index;
   static EIGEN_STRONG_INLINE Scalar run(const Derived& mat, const Func& func)
   {
-    ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using a non initialized matrix");
+    ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix");
     Scalar res;
     res = mat.coeffByOuterInner(0, 0);
     for(Index i = 1; i < mat.innerSize(); ++i)
@@ -210,6 +210,7 @@
   static Scalar run(const Derived& mat, const Func& func)
   {
     const Index size = mat.size();
+    ei_assert(size && "you are using an empty matrix");
     const Index packetSize = ei_packet_traits<Scalar>::size;
     const Index alignedStart = ei_first_aligned(mat);
     enum {
@@ -253,6 +254,7 @@
 
   static Scalar run(const Derived& mat, const Func& func)
   {
+    ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix");
     const Index innerSize = mat.innerSize();
     const Index outerSize = mat.outerSize();
     enum {
@@ -294,6 +296,7 @@
   };
   EIGEN_STRONG_INLINE static Scalar run(const Derived& mat, const Func& func)
   {
+    ei_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix");
     Scalar res = func.predux(ei_redux_vec_unroller<Func, Derived, 0, Size / PacketSize>::run(mat,func));
     if (VectorizedSize != Size)
       res = func(res,ei_redux_novec_unroller<Func, Derived, VectorizedSize, Size-VectorizedSize>::run(mat,func));
@@ -345,6 +348,8 @@
 EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar
 DenseBase<Derived>::sum() const
 {
+  if(SizeAtCompileTime==0 || (SizeAtCompileTime==Dynamic && size()==0))
+    return Scalar(0);
   return this->redux(Eigen::ei_scalar_sum_op<Scalar>());
 }
 
@@ -370,6 +375,8 @@
 EIGEN_STRONG_INLINE typename ei_traits<Derived>::Scalar
 DenseBase<Derived>::prod() const
 {
+  if(SizeAtCompileTime==0 || (SizeAtCompileTime==Dynamic && size()==0))
+    return Scalar(1);
   return this->redux(Eigen::ei_scalar_product_op<Scalar>());
 }
 
diff --git a/test/array_for_matrix.cpp b/test/array_for_matrix.cpp
index 01e31d0..3699b86 100644
--- a/test/array_for_matrix.cpp
+++ b/test/array_for_matrix.cpp
@@ -72,6 +72,10 @@
   VERIFY_IS_APPROX(m3.rowwise() += rv1, m1.rowwise() + rv1);
   m3 = m1;
   VERIFY_IS_APPROX(m3.rowwise() -= rv1, m1.rowwise() - rv1);
+  
+  // empty objects
+  VERIFY_IS_APPROX(m1.block(0,0,0,cols).colwise().sum(),  RowVectorType::Zero(cols));
+  VERIFY_IS_APPROX(m1.block(0,0,rows,0).rowwise().prod(), ColVectorType::Ones(rows));
 }
 
 template<typename MatrixType> void comparisons(const MatrixType& m)
diff --git a/test/redux.cpp b/test/redux.cpp
index b282529..9a1df71 100644
--- a/test/redux.cpp
+++ b/test/redux.cpp
@@ -64,6 +64,10 @@
   VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).prod(), m1.block(r0,c0,r1,c1).eval().prod());
   VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).real().minCoeff(), m1.block(r0,c0,r1,c1).real().eval().minCoeff());
   VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).real().maxCoeff(), m1.block(r0,c0,r1,c1).real().eval().maxCoeff());
+  
+  // test empty objects
+  VERIFY_IS_APPROX(m1.block(r0,c0,0,0).sum(),   Scalar(0));
+  VERIFY_IS_APPROX(m1.block(r0,c0,0,0).prod(),  Scalar(1));
 }
 
 template<typename VectorType> void vectorRedux(const VectorType& w)
@@ -124,6 +128,13 @@
     VERIFY_IS_APPROX(minc, v.real().segment(i, size-2*i).minCoeff());
     VERIFY_IS_APPROX(maxc, v.real().segment(i, size-2*i).maxCoeff());
   }
+  
+  // test empty objects
+  VERIFY_IS_APPROX(v.head(0).sum(),   Scalar(0));
+  VERIFY_IS_APPROX(v.tail(0).prod(),  Scalar(1));
+  VERIFY_RAISES_ASSERT(v.head(0).mean());
+  VERIFY_RAISES_ASSERT(v.head(0).minCoeff());
+  VERIFY_RAISES_ASSERT(v.head(0).maxCoeff());
 }
 
 void test_redux()