mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-04-22 09:39:34 +08:00
* 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).
This commit is contained in:
parent
f5a05e7ed1
commit
4336cf3833
@ -437,6 +437,8 @@ template<typename OtherDerived>
|
|||||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
|
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
|
||||||
::operator=(const MatrixBase<OtherDerived>& other)
|
::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());
|
return ei_assign_selector<Derived,OtherDerived>::run(derived(), other.derived());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,6 +266,9 @@ MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const
|
|||||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(_Nested)
|
EIGEN_STATIC_ASSERT_VECTOR_ONLY(_Nested)
|
||||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(_OtherNested)
|
EIGEN_STATIC_ASSERT_VECTOR_ONLY(_OtherNested)
|
||||||
EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(_Nested,_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());
|
ei_assert(size() == other.size());
|
||||||
|
|
||||||
return ei_dot_impl<_Nested, _OtherNested>::run(derived(), other.derived());
|
return ei_dot_impl<_Nested, _OtherNested>::run(derived(), other.derived());
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
*** Forward declarations ***
|
*** 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;
|
struct ei_product_coeff_impl;
|
||||||
|
|
||||||
template<int StorageOrder, int Index, typename Lhs, typename Rhs, typename PacketScalar, int LoadMode>
|
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::MaxColsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD )
|
||||||
&& (!(Rhs::IsVectorAtCompileTime && (Lhs::Flags&RowMajorBit) && (!(Lhs::Flags&DirectAccessBit))))
|
&& (!(Rhs::IsVectorAtCompileTime && (Lhs::Flags&RowMajorBit) && (!(Lhs::Flags&DirectAccessBit))))
|
||||||
&& (!(Lhs::IsVectorAtCompileTime && (!(Rhs::Flags&RowMajorBit)) && (!(Rhs::Flags&DirectAccessBit))))
|
&& (!(Lhs::IsVectorAtCompileTime && (!(Rhs::Flags&RowMajorBit)) && (!(Rhs::Flags&DirectAccessBit))))
|
||||||
|
&& (ei_is_same_type<typename Lhs::Scalar, typename Rhs::Scalar>::ret)
|
||||||
? CacheFriendlyProduct
|
? CacheFriendlyProduct
|
||||||
: NormalProduct };
|
: NormalProduct };
|
||||||
};
|
};
|
||||||
@ -120,7 +121,7 @@ struct ei_traits<Product<LhsNested, RhsNested, ProductMode> >
|
|||||||
// clean the nested types:
|
// clean the nested types:
|
||||||
typedef typename ei_cleantype<LhsNested>::type _LhsNested;
|
typedef typename ei_cleantype<LhsNested>::type _LhsNested;
|
||||||
typedef typename ei_cleantype<RhsNested>::type _RhsNested;
|
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 {
|
enum {
|
||||||
LhsCoeffReadCost = _LhsNested::CoeffReadCost,
|
LhsCoeffReadCost = _LhsNested::CoeffReadCost,
|
||||||
@ -189,7 +190,7 @@ template<typename LhsNested, typename RhsNested, int ProductMode> class Product
|
|||||||
|
|
||||||
typedef ei_product_coeff_impl<CanVectorizeInner ? InnerVectorization : NoVectorization,
|
typedef ei_product_coeff_impl<CanVectorizeInner ? InnerVectorization : NoVectorization,
|
||||||
Unroll ? InnerSize-1 : Dynamic,
|
Unroll ? InnerSize-1 : Dynamic,
|
||||||
_LhsNested, _RhsNested> ScalarCoeffImpl;
|
_LhsNested, _RhsNested, Scalar> ScalarCoeffImpl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -312,29 +313,29 @@ MatrixBase<Derived>::operator*=(const MatrixBase<OtherDerived> &other)
|
|||||||
*** Scalar path - no vectorization ***
|
*** Scalar path - no vectorization ***
|
||||||
**************************************/
|
**************************************/
|
||||||
|
|
||||||
template<int Index, typename Lhs, typename Rhs>
|
template<int Index, typename Lhs, typename Rhs, typename RetScalar>
|
||||||
struct ei_product_coeff_impl<NoVectorization, Index, Lhs, Rhs>
|
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);
|
res += lhs.coeff(row, Index) * rhs.coeff(Index, col);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||||
struct ei_product_coeff_impl<NoVectorization, 0, Lhs, Rhs>
|
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);
|
res = lhs.coeff(row, 0) * rhs.coeff(0, col);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||||
struct ei_product_coeff_impl<NoVectorization, Dynamic, Lhs, Rhs>
|
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");
|
ei_assert(lhs.cols()>0 && "you are using a non initialized matrix");
|
||||||
res = lhs.coeff(row, 0) * rhs.coeff(0, col);
|
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
|
// prevent buggy user code from causing an infinite recursion
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||||
struct ei_product_coeff_impl<NoVectorization, -1, Lhs, Rhs>
|
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>
|
template<int Index, typename Lhs, typename Rhs, typename RetScalar>
|
||||||
struct ei_product_coeff_impl<InnerVectorization, Index, Lhs, Rhs>
|
struct ei_product_coeff_impl<InnerVectorization, Index, Lhs, Rhs, RetScalar>
|
||||||
{
|
{
|
||||||
typedef typename Lhs::PacketScalar PacketScalar;
|
typedef typename Lhs::PacketScalar PacketScalar;
|
||||||
enum { PacketSize = ei_packet_traits<typename Lhs::Scalar>::size };
|
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;
|
PacketScalar pres;
|
||||||
ei_product_coeff_vectorized_unroller<Index+1-PacketSize, Lhs, Rhs, PacketScalar>::run(row, col, lhs, rhs, 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);
|
res = ei_predux(pres);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -438,8 +439,8 @@ struct ei_product_coeff_vectorized_dyn_selector<Lhs,Rhs,1,1>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs, typename RetScalar>
|
||||||
struct ei_product_coeff_impl<InnerVectorization, Dynamic, Lhs, Rhs>
|
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)
|
EIGEN_STRONG_INLINE static void run(int row, int col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res)
|
||||||
{
|
{
|
||||||
|
@ -157,6 +157,7 @@ ei_add_test(meta)
|
|||||||
ei_add_test(sizeof)
|
ei_add_test(sizeof)
|
||||||
ei_add_test(dynalloc)
|
ei_add_test(dynalloc)
|
||||||
ei_add_test(nomalloc)
|
ei_add_test(nomalloc)
|
||||||
|
ei_add_test(mixingtypes)
|
||||||
ei_add_test(packetmath)
|
ei_add_test(packetmath)
|
||||||
ei_add_test(basicstuff)
|
ei_add_test(basicstuff)
|
||||||
ei_add_test(linearstructure)
|
ei_add_test(linearstructure)
|
||||||
|
81
test/mixingtypes.cpp
Normal file
81
test/mixingtypes.cpp
Normal file
@ -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));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user