diff --git a/Eigen/src/Core/CwiseNullaryOp.h b/Eigen/src/Core/CwiseNullaryOp.h index 1caf37bb7..757320ace 100644 --- a/Eigen/src/Core/CwiseNullaryOp.h +++ b/Eigen/src/Core/CwiseNullaryOp.h @@ -264,6 +264,16 @@ DenseBase::LinSpaced(Sequential_t, const Scalar& low, const Scalar& hig * Example: \include DenseBase_LinSpaced.cpp * Output: \verbinclude DenseBase_LinSpaced.out * + * For integer scalar types, an even spacing is possible if and only if the length of the range, + * i.e., \c high-low is a scalar multiple of \c size-1, or if \c size is a scalar multiple of the + * number of values \c high-low+1 (meaning each value can be repeated the same number of time). + * If one of these two considions is not satisfied, then \c high is lowered to the largest value + * satisfying one of this constraint. + * Here are some examples: + * + * Example: \include DenseBase_LinSpacedInt.cpp + * Output: \verbinclude DenseBase_LinSpacedInt.out + * * \sa setLinSpaced(Index,const Scalar&,const Scalar&), LinSpaced(Sequential_t,Index,const Scalar&,const Scalar&,Index), CwiseNullaryOp */ template @@ -377,7 +387,10 @@ PlainObjectBase::setConstant(Index rows, Index cols, const Scalar& val) * Example: \include DenseBase_setLinSpaced.cpp * Output: \verbinclude DenseBase_setLinSpaced.out * - * \sa CwiseNullaryOp + * For integer scalar types, do not miss the explanations on the definition + * of \link LinSpaced(Index,const Scalar&,const Scalar&) even spacing \endlink. + * + * \sa LinSpaced(Index,const Scalar&,const Scalar&), CwiseNullaryOp */ template EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index newSize, const Scalar& low, const Scalar& high) @@ -389,12 +402,15 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index newSize, con /** * \brief Sets a linearly spaced vector. * - * The function fills *this with equally spaced values in the closed interval [low,high]. + * The function fills \c *this with equally spaced values in the closed interval [low,high]. * When size is set to 1, a vector of length 1 containing 'high' is returned. * * \only_for_vectors * - * \sa setLinSpaced(Index, const Scalar&, const Scalar&), CwiseNullaryOp + * For integer scalar types, do not miss the explanations on the definition + * of \link LinSpaced(Index,const Scalar&,const Scalar&) even spacing \endlink. + * + * \sa LinSpaced(Index,const Scalar&,const Scalar&), setLinSpaced(Index, const Scalar&, const Scalar&), CwiseNullaryOp */ template EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, const Scalar& high) diff --git a/Eigen/src/Core/functors/NullaryFunctors.h b/Eigen/src/Core/functors/NullaryFunctors.h index a2154d3b5..0c00f4661 100644 --- a/Eigen/src/Core/functors/NullaryFunctors.h +++ b/Eigen/src/Core/functors/NullaryFunctors.h @@ -99,25 +99,24 @@ template struct linspaced_op_impl { linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps) : - m_low(low), m_length(high-low), m_divisor(convert_index(num_steps==1?1:num_steps-1)), m_interPacket(plset(0)) + m_low(low), + m_multiplier((high-low)/convert_index(num_steps<=1 ? 1 : num_steps-1)), + m_divisor(convert_index(num_steps+high-low)/(high-low+1)), + m_use_divisor((high-low+1) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE - const Scalar operator() (IndexType i) const { - return m_low + (m_length*Scalar(i))/m_divisor; + const Scalar operator() (IndexType i) const + { + if(m_use_divisor) return m_low + convert_index(i)/m_divisor; + else return m_low + convert_index(i)*m_multiplier; } - template - EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE - const Packet packetOp(IndexType i) const { - return internal::padd(pset1(m_low), pdiv(pmul(pset1(m_length), padd(pset1(Scalar(i)),m_interPacket)), - pset1(m_divisor))); } - const Scalar m_low; - const Scalar m_length; - const Scalar m_divisor; - const Packet m_interPacket; + const Scalar m_multiplier; + const Scalar m_divisor; + const bool m_use_divisor; }; // ----- Linspace functor ---------------------------------------------------------------- @@ -131,7 +130,7 @@ template struct functo enum { Cost = 1, - PacketAccess = packet_traits::HasSetLinear + PacketAccess = (!NumTraits::IsInteger) && packet_traits::HasSetLinear && ((!NumTraits::IsInteger) || packet_traits::HasDiv), IsRepeatable = true }; diff --git a/doc/snippets/DenseBase_LinSpacedInt.cpp b/doc/snippets/DenseBase_LinSpacedInt.cpp new file mode 100644 index 000000000..0d7ae068e --- /dev/null +++ b/doc/snippets/DenseBase_LinSpacedInt.cpp @@ -0,0 +1,8 @@ +cout << "Even spacing inputs:" << endl; +cout << VectorXi::LinSpaced(8,1,4).transpose() << endl; +cout << VectorXi::LinSpaced(8,1,8).transpose() << endl; +cout << VectorXi::LinSpaced(8,1,15).transpose() << endl; +cout << "Uneven spacing inputs:" << endl; +cout << VectorXi::LinSpaced(8,1,7).transpose() << endl; +cout << VectorXi::LinSpaced(8,1,9).transpose() << endl; +cout << VectorXi::LinSpaced(8,1,16).transpose() << endl; diff --git a/test/nullary.cpp b/test/nullary.cpp index 35f24de47..162e84210 100644 --- a/test/nullary.cpp +++ b/test/nullary.cpp @@ -57,23 +57,31 @@ void testVectorType(const VectorType& base) VERIFY_IS_APPROX(m,n); } - VectorType n(size); - for (int i=0; i::IsInteger) || ((high-low)>=size && (Index(high-low)%(size-1))==0) || (Index(high-low+1)::IsInteger) || (high-low>=size)) + for (int i=0; i=0) ? (1+NumTraits::dummy_precision()) : (1-NumTraits::dummy_precision()); + VERIFY( m(m.size()-1) <= high*tol_factor ); VERIFY( size==1 || internal::isApprox(m(0),low) ); // check whether everything works with row and col major vectors @@ -96,7 +104,7 @@ void testVectorType(const VectorType& base) VERIFY_IS_APPROX( ScalarMatrix::LinSpaced(1,low,high), ScalarMatrix::Constant(high) ); // regression test for bug 526 (linear vectorized transversal) - if (size > 1) { + if (size > 1 && (!NumTraits::IsInteger)) { m.tail(size-1).setLinSpaced(low, high); VERIFY_IS_APPROX(m(size-1), high); }