aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Benoit Jacob <jacob.benoit.1@gmail.com>2008-12-22 19:17:44 +0000
committerGravatar Benoit Jacob <jacob.benoit.1@gmail.com>2008-12-22 19:17:44 +0000
commit4336cf3833d87bc1c8b4c9ef6f884547c80e31f0 (patch)
tree67fac7b672e66246d2d8d52642615d1c004b2636
parentf5a05e7ed159d771545767c430d12263e205ec87 (diff)
* add unit-tests to check allowed and forbiddent mixing of different scalar types
* fix issues in Product revealed by this test * in Dot.h forbid mixing of different types (at least for now, might allow real.dot(complex) in the future).
-rw-r--r--Eigen/src/Core/Assign.h2
-rw-r--r--Eigen/src/Core/Dot.h3
-rw-r--r--Eigen/src/Core/Product.h45
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/mixingtypes.cpp81
5 files changed, 110 insertions, 22 deletions
diff --git a/Eigen/src/Core/Assign.h b/Eigen/src/Core/Assign.h
index 7e8102997..42b411e6f 100644
--- a/Eigen/src/Core/Assign.h
+++ b/Eigen/src/Core/Assign.h
@@ -437,6 +437,8 @@ template<typename OtherDerived>
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
::operator=(const MatrixBase<OtherDerived>& other)
{
+ EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
+ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
return ei_assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
}
diff --git a/Eigen/src/Core/Dot.h b/Eigen/src/Core/Dot.h
index 86bebe246..18e81ac1c 100644
--- a/Eigen/src/Core/Dot.h
+++ b/Eigen/src/Core/Dot.h
@@ -266,6 +266,9 @@ MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
EIGEN_STATIC_ASSERT_VECTOR_ONLY(_Nested)
EIGEN_STATIC_ASSERT_VECTOR_ONLY(_OtherNested)
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(_Nested,_OtherNested)
+ EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
+ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
+
ei_assert(size() == other.size());
return ei_dot_impl<_Nested, _OtherNested>::run(derived(), other.derived());
diff --git a/Eigen/src/Core/Product.h b/Eigen/src/Core/Product.h
index 7df7ac67b..6587ad3e0 100644
--- a/Eigen/src/Core/Product.h
+++ b/Eigen/src/Core/Product.h
@@ -30,7 +30,7 @@
*** Forward declarations ***
***************************/
-template<int VectorizationMode, int Index, typename Lhs, typename Rhs>
+template<int VectorizationMode, int Index, typename Lhs, typename Rhs, typename RetScalar>
struct ei_product_coeff_impl;
template<int StorageOrder, int Index, typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
@@ -94,6 +94,7 @@ template<typename Lhs, typename Rhs> struct ei_product_mode
|| Rhs::MaxColsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD )
&& (!(Rhs::IsVectorAtCompileTime && (Lhs::Flags&RowMajorBit) && (!(Lhs::Flags&DirectAccessBit))))
&& (!(Lhs::IsVectorAtCompileTime && (!(Rhs::Flags&RowMajorBit)) && (!(Rhs::Flags&DirectAccessBit))))
+ && (ei_is_same_type<typename Lhs::Scalar, typename Rhs::Scalar>::ret)
? CacheFriendlyProduct
: NormalProduct };
};
@@ -120,7 +121,7 @@ struct ei_traits<Product<LhsNested, RhsNested, ProductMode> >
// clean the nested types:
typedef typename ei_cleantype<LhsNested>::type _LhsNested;
typedef typename ei_cleantype<RhsNested>::type _RhsNested;
- typedef typename _LhsNested::Scalar Scalar;
+ typedef typename ei_scalar_product_traits<typename _LhsNested::Scalar, typename _RhsNested::Scalar>::ReturnType Scalar;
enum {
LhsCoeffReadCost = _LhsNested::CoeffReadCost,
@@ -189,7 +190,7 @@ template<typename LhsNested, typename RhsNested, int ProductMode> class Product
typedef ei_product_coeff_impl<CanVectorizeInner ? InnerVectorization : NoVectorization,
Unroll ? InnerSize-1 : Dynamic,
- _LhsNested, _RhsNested> ScalarCoeffImpl;
+ _LhsNested, _RhsNested, Scalar> ScalarCoeffImpl;
public:
@@ -312,29 +313,29 @@ MatrixBase<Derived>::operator*=(const MatrixBase<OtherDerived> &other)
*** Scalar path - no vectorization ***
**************************************/
-template<int Index, typename Lhs, typename Rhs>
-struct ei_product_coeff_impl<NoVectorization, Index, Lhs, Rhs>
+template<int Index, typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl<NoVectorization, Index, Lhs, Rhs, RetScalar>
{
- EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
{
- ei_product_coeff_impl<NoVectorization, Index-1, Lhs, Rhs>::run(row, col, lhs, rhs, res);
+ ei_product_coeff_impl<NoVectorization, Index-1, Lhs, Rhs, RetScalar>::run(row, col, lhs, rhs, res);
res += lhs.coeff(row, Index) * rhs.coeff(Index, col);
}
};
-template<typename Lhs, typename Rhs>
-struct ei_product_coeff_impl<NoVectorization, 0, Lhs, Rhs>
+template<typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl<NoVectorization, 0, Lhs, Rhs, RetScalar>
{
- EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
{
res = lhs.coeff(row, 0) * rhs.coeff(0, col);
}
};
-template<typename Lhs, typename Rhs>
-struct ei_product_coeff_impl<NoVectorization, Dynamic, Lhs, Rhs>
+template<typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl<NoVectorization, Dynamic, Lhs, Rhs, RetScalar>
{
- EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar& res)
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, RetScalar& res)
{
ei_assert(lhs.cols()>0 && "you are using a non initialized matrix");
res = lhs.coeff(row, 0) * rhs.coeff(0, col);
@@ -344,10 +345,10 @@ struct ei_product_coeff_impl<NoVectorization, Dynamic, Lhs, Rhs>
};
// prevent buggy user code from causing an infinite recursion
-template<typename Lhs, typename Rhs>
-struct ei_product_coeff_impl<NoVectorization, -1, Lhs, Rhs>
+template<typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl<NoVectorization, -1, Lhs, Rhs, RetScalar>
{
- EIGEN_STRONG_INLINE static void run(int, int, const Lhs&, const Rhs&, typename Lhs::Scalar&) {}
+ EIGEN_STRONG_INLINE static void run(int, int, const Lhs&, const Rhs&, RetScalar&) {}
};
/*******************************************
@@ -374,16 +375,16 @@ struct ei_product_coeff_vectorized_unroller<0, Lhs, Rhs, PacketScalar>
}
};
-template<int Index, typename Lhs, typename Rhs>
-struct ei_product_coeff_impl<InnerVectorization, Index, Lhs, Rhs>
+template<int Index, typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl<InnerVectorization, Index, Lhs, Rhs, RetScalar>
{
typedef typename Lhs::PacketScalar PacketScalar;
enum { PacketSize = ei_packet_traits<typename Lhs::Scalar>::size };
- EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
+ EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, RetScalar &res)
{
PacketScalar pres;
ei_product_coeff_vectorized_unroller<Index+1-PacketSize, Lhs, Rhs, PacketScalar>::run(row, col, lhs, rhs, pres);
- ei_product_coeff_impl<NoVectorization,Index,Lhs,Rhs>::run(row, col, lhs, rhs, res);
+ ei_product_coeff_impl<NoVectorization,Index,Lhs,Rhs,RetScalar>::run(row, col, lhs, rhs, res);
res = ei_predux(pres);
}
};
@@ -438,8 +439,8 @@ struct ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,1>
}
};
-template<typename Lhs, typename Rhs>
-struct ei_product_coeff_impl<InnerVectorization, Dynamic, Lhs, Rhs>
+template<typename Lhs, typename Rhs, typename RetScalar>
+struct ei_product_coeff_impl<InnerVectorization, Dynamic, Lhs, Rhs, RetScalar>
{
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
{
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 4255128ad..051a73e15 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -157,6 +157,7 @@ ei_add_test(meta)
ei_add_test(sizeof)
ei_add_test(dynalloc)
ei_add_test(nomalloc)
+ei_add_test(mixingtypes)
ei_add_test(packetmath)
ei_add_test(basicstuff)
ei_add_test(linearstructure)
diff --git a/test/mixingtypes.cpp b/test/mixingtypes.cpp
new file mode 100644
index 000000000..ddf1c2b4d
--- /dev/null
+++ b/test/mixingtypes.cpp
@@ -0,0 +1,81 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// Eigen is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// Alternatively, you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#define EIGEN_NO_STATIC_ASSERT // turn static asserts into runtime asserts in order to check them
+#include "main.h"
+
+
+template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
+{
+ typedef Matrix<float, SizeAtCompileType, SizeAtCompileType> Mat_f;
+ typedef Matrix<double, SizeAtCompileType, SizeAtCompileType> Mat_d;
+ typedef Matrix<std::complex<float>, SizeAtCompileType, SizeAtCompileType> Mat_cf;
+ typedef Matrix<std::complex<double>, SizeAtCompileType, SizeAtCompileType> Mat_cd;
+ typedef Matrix<float, SizeAtCompileType, 1> Vec_f;
+ typedef Matrix<double, SizeAtCompileType, 1> Vec_d;
+ typedef Matrix<std::complex<float>, SizeAtCompileType, 1> Vec_cf;
+ typedef Matrix<std::complex<double>, SizeAtCompileType, 1> Vec_cd;
+
+ Mat_f mf(size,size);
+ Mat_d md(size,size);
+ Mat_cf mcf(size,size);
+ Mat_cd mcd(size,size);
+ Vec_f vf(size,1);
+ Vec_d vd(size,1);
+ Vec_cf vcf(size,1);
+ Vec_cd vcd(size,1);
+
+ mf+mf;
+ VERIFY_RAISES_ASSERT(mf+md);
+ VERIFY_RAISES_ASSERT(mf+mcf);
+ VERIFY_RAISES_ASSERT(vf=vd);
+ VERIFY_RAISES_ASSERT(vf+=vd);
+ VERIFY_RAISES_ASSERT(mcd=md);
+
+ mf*mf;
+ md*mcd;
+ mcd*md;
+ mf*vcf;
+ mcf*vf;
+ mcf *= mf;
+ vcd = md*vcd;
+ vcf = mcf*vf;
+ VERIFY_RAISES_ASSERT(mf*md);
+ VERIFY_RAISES_ASSERT(mcf*mcd);
+ VERIFY_RAISES_ASSERT(mcf*vcd);
+ VERIFY_RAISES_ASSERT(vcf = mf*vf);
+
+ vf.dot(vf);
+ VERIFY_RAISES_ASSERT(vd.dot(vf));
+ VERIFY_RAISES_ASSERT(vcf.dot(vf)); // yeah eventually we should allow this but i'm too lazy to make that change now in Dot.h
+} // especially as that might be rewritten as cwise product .sum() which would make that automatic.
+
+void test_mixingtypes()
+{
+ // check that our operator new is indeed called:
+ CALL_SUBTEST(mixingtypes<3>());
+ CALL_SUBTEST(mixingtypes<4>());
+ CALL_SUBTEST(mixingtypes<Dynamic>(20));
+}