10 #ifndef EIGEN_AUTODIFF_SCALAR_H 11 #define EIGEN_AUTODIFF_SCALAR_H 14 #include "./InternalHeaderCheck.h" 20 template <
typename DerivativeType,
bool Enable>
21 struct auto_diff_special_op;
23 template <
typename DerivativeType,
typename OtherDerivativeType,
typename EnableIf =
void>
24 struct maybe_coherent_pad_helper {
25 static constexpr
int SizeAtCompileTime =
26 max_size_prefer_dynamic(DerivativeType::SizeAtCompileTime, OtherDerivativeType::SizeAtCompileTime);
27 using type = CoherentPadOp<DerivativeType, SizeAtCompileTime>;
28 static type pad(
const DerivativeType& x,
const OtherDerivativeType& y) {
31 return CoherentPadOp<DerivativeType, SizeAtCompileTime>(x, numext::maxi(x.size(), y.size()));
37 template <
typename DerivativeType,
typename OtherDerivativeType>
38 struct maybe_coherent_pad_helper<
39 DerivativeType, OtherDerivativeType,
40 std::enable_if_t<enum_ge_not_dynamic(DerivativeType::SizeAtCompileTime, OtherDerivativeType::SizeAtCompileTime)>> {
41 using type =
const DerivativeType&;
42 static const DerivativeType& pad(
const DerivativeType& x,
const OtherDerivativeType& ) {
return x; }
45 template <
typename DerivativeType,
typename OtherDerivativeType>
46 typename maybe_coherent_pad_helper<DerivativeType, OtherDerivativeType>::type MaybeCoherentPad(
47 const DerivativeType& x,
const OtherDerivativeType& y) {
48 return maybe_coherent_pad_helper<DerivativeType, OtherDerivativeType>::pad(x, y);
51 template <
typename Op,
typename LhsDerivativeType,
typename RhsDerivativeType>
52 auto MakeCoherentCwiseBinaryOp(
const LhsDerivativeType& x,
const RhsDerivativeType& y, Op op = Op()) {
53 const auto& lhs = MaybeCoherentPad(x, y);
54 const auto& rhs = MaybeCoherentPad(y, x);
55 return CwiseBinaryOp<Op, remove_all_t<decltype(lhs)>, remove_all_t<decltype(rhs)>>(lhs, rhs, op);
60 template <
typename DerivativeType>
63 template <
typename NewDerType>
94 template <
typename DerivativeType>
96 :
public internal::auto_diff_special_op<
97 DerivativeType, !internal::is_same<typename internal::traits<internal::remove_all_t<DerivativeType>>::Scalar,
98 typename NumTraits<typename internal::traits<
99 internal::remove_all_t<DerivativeType>>::Scalar>::Real>::value> {
101 typedef internal::auto_diff_special_op<
104 typename internal::traits<internal::remove_all_t<DerivativeType>>::Scalar,
107 typedef internal::remove_all_t<DerivativeType> DerType;
108 typedef typename internal::traits<DerType>::Scalar Scalar;
111 using Base::operator+;
112 using Base::operator*;
119 AutoDiffScalar(
const Scalar& value,
int nbDer,
int derNumber) : m_value(value), m_derivatives(DerType::Zero(nbDer)) {
120 m_derivatives.coeffRef(derNumber) = Scalar(1);
126 if (m_derivatives.size() > 0) m_derivatives.setZero();
130 AutoDiffScalar(
const Scalar& value,
const DerType& der) : m_value(value), m_derivatives(der) {}
132 template <
typename OtherDerType>
135 #ifndef EIGEN_PARSED_BY_DOXYGEN
138 internal::is_same<Scalar,
typename internal::traits<internal::remove_all_t<OtherDerType>>::Scalar>::value &&
139 internal::is_convertible<OtherDerType, DerType>::value,
143 : m_value(other.value()), m_derivatives(other.derivatives()) {
146 friend std::ostream& operator<<(std::ostream& s,
const AutoDiffScalar& a) {
return s << a.value(); }
150 template <
typename OtherDerType>
151 inline AutoDiffScalar& operator=(
const AutoDiffScalar<OtherDerType>& other) {
152 m_value = other.value();
153 m_derivatives = other.derivatives();
158 m_value = other.value();
159 m_derivatives = other.derivatives();
165 if (m_derivatives.size() > 0) m_derivatives.setZero();
172 inline const Scalar& value()
const {
return m_value; }
173 inline Scalar& value() {
return m_value; }
175 inline const DerType& derivatives()
const {
return m_derivatives; }
176 inline DerType& derivatives() {
return m_derivatives; }
178 inline bool operator<(
const Scalar& other)
const {
return m_value < other; }
179 inline bool operator<=(
const Scalar& other)
const {
return m_value <= other; }
180 inline bool operator>(
const Scalar& other)
const {
return m_value > other; }
181 inline bool operator>=(
const Scalar& other)
const {
return m_value >= other; }
182 inline bool operator==(
const Scalar& other)
const {
return m_value == other; }
183 inline bool operator!=(
const Scalar& other)
const {
return m_value != other; }
185 friend inline bool operator<(
const Scalar& a,
const AutoDiffScalar& b) {
return a < b.value(); }
186 friend inline bool operator<=(
const Scalar& a,
const AutoDiffScalar& b) {
return a <= b.value(); }
187 friend inline bool operator>(
const Scalar& a,
const AutoDiffScalar& b) {
return a > b.value(); }
188 friend inline bool operator>=(
const Scalar& a,
const AutoDiffScalar& b) {
return a >= b.value(); }
189 friend inline bool operator==(
const Scalar& a,
const AutoDiffScalar& b) {
return a == b.value(); }
190 friend inline bool operator!=(
const Scalar& a,
const AutoDiffScalar& b) {
return a != b.value(); }
192 template <
typename OtherDerType>
193 inline bool operator<(const AutoDiffScalar<OtherDerType>& b)
const {
194 return m_value < b.value();
196 template <
typename OtherDerType>
197 inline bool operator<=(const AutoDiffScalar<OtherDerType>& b)
const {
198 return m_value <= b.value();
200 template <
typename OtherDerType>
201 inline bool operator>(
const AutoDiffScalar<OtherDerType>& b)
const {
202 return m_value > b.value();
204 template <
typename OtherDerType>
205 inline bool operator>=(
const AutoDiffScalar<OtherDerType>& b)
const {
206 return m_value >= b.value();
208 template <
typename OtherDerType>
209 inline bool operator==(
const AutoDiffScalar<OtherDerType>& b)
const {
210 return m_value == b.value();
212 template <
typename OtherDerType>
213 inline bool operator!=(
const AutoDiffScalar<OtherDerType>& b)
const {
214 return m_value != b.value();
217 inline AutoDiffScalar<DerType&> operator+(
const Scalar& other)
const {
218 return AutoDiffScalar<DerType&>(m_value + other, m_derivatives);
221 friend inline AutoDiffScalar<DerType&> operator+(
const Scalar& a,
const AutoDiffScalar& b) {
222 return AutoDiffScalar<DerType&>(a + b.value(), b.derivatives());
240 template <
typename OtherDerType>
241 inline auto operator+(
const AutoDiffScalar<OtherDerType>& other)
const {
242 return MakeAutoDiffScalar(
243 m_value + other.value(),
244 internal::MakeCoherentCwiseBinaryOp<internal::scalar_sum_op<Scalar>>(m_derivatives, other.derivatives()));
247 template <
typename OtherDerType>
248 inline AutoDiffScalar& operator+=(
const AutoDiffScalar<OtherDerType>& other) {
249 (*this) = (*this) + other;
253 inline AutoDiffScalar<DerType&> operator-(
const Scalar& b)
const {
254 return AutoDiffScalar<DerType&>(m_value - b, m_derivatives);
257 friend inline AutoDiffScalar<CwiseUnaryOp<internal::scalar_opposite_op<Scalar>,
const DerType>> operator-(
259 return AutoDiffScalar<CwiseUnaryOp<internal::scalar_opposite_op<Scalar>,
const DerType>>(a - b.value(),
268 template <
typename OtherDerType>
269 inline auto operator-(
const AutoDiffScalar<OtherDerType>& other)
const {
270 return MakeAutoDiffScalar(m_value - other.value(),
271 internal::MakeCoherentCwiseBinaryOp<internal::scalar_difference_op<Scalar>>(
272 m_derivatives, other.derivatives()));
275 template <
typename OtherDerType>
276 inline AutoDiffScalar& operator-=(
const AutoDiffScalar<OtherDerType>& other) {
277 *
this = *
this - other;
281 inline AutoDiffScalar<CwiseUnaryOp<internal::scalar_opposite_op<Scalar>,
const DerType>> operator-()
const {
282 return AutoDiffScalar<CwiseUnaryOp<internal::scalar_opposite_op<Scalar>,
const DerType>>(-m_value, -m_derivatives);
285 inline auto operator*(
const Scalar& other)
const {
286 return MakeAutoDiffScalar(m_value * other, m_derivatives * other);
289 friend inline auto operator*(
const Scalar& other,
const AutoDiffScalar& a) {
290 return MakeAutoDiffScalar(a.value() * other, a.derivatives() * other);
309 inline auto operator/(
const Scalar& other)
const {
310 return MakeAutoDiffScalar(m_value / other, (m_derivatives * (Scalar(1) / other)));
313 friend inline auto operator/(
const Scalar& other,
const AutoDiffScalar& a) {
314 return MakeAutoDiffScalar(other / a.value(), a.derivatives() * (Scalar(-other) / (a.value() * a.value())));
333 template <
typename OtherDerType>
334 inline auto operator/(
const AutoDiffScalar<OtherDerType>& other)
const {
335 return MakeAutoDiffScalar(m_value / other.value(),
336 internal::MakeCoherentCwiseBinaryOp<internal::scalar_difference_op<Scalar>>(
337 m_derivatives * other.value(), (other.derivatives() * m_value)) *
338 (Scalar(1) / (other.value() * other.value())));
341 template <
typename OtherDerType>
342 inline auto operator*(
const AutoDiffScalar<OtherDerType>& other)
const {
343 return MakeAutoDiffScalar(m_value * other.value(),
344 internal::MakeCoherentCwiseBinaryOp<internal::scalar_sum_op<Scalar>>(
345 m_derivatives * other.value(), other.derivatives() * m_value));
349 *
this = *
this * other;
353 template <
typename OtherDerType>
354 inline AutoDiffScalar& operator*=(
const AutoDiffScalar<OtherDerType>& other) {
355 *
this = *
this * other;
360 *
this = *
this / other;
364 template <
typename OtherDerType>
365 inline AutoDiffScalar& operator/=(
const AutoDiffScalar<OtherDerType>& other) {
366 *
this = *
this / other;
372 DerType m_derivatives;
377 template <
typename DerivativeType>
378 struct auto_diff_special_op<DerivativeType, true>
382 typedef remove_all_t<DerivativeType> DerType;
383 typedef typename traits<DerType>::Scalar Scalar;
384 typedef typename NumTraits<Scalar>::Real Real;
396 const AutoDiffScalar<DerivativeType>& derived()
const {
397 return *
static_cast<const AutoDiffScalar<DerivativeType>*
>(
this);
399 AutoDiffScalar<DerivativeType>& derived() {
return *
static_cast<AutoDiffScalar<DerivativeType>*
>(
this); }
401 inline AutoDiffScalar<DerType&> operator+(
const Real& other)
const {
402 return AutoDiffScalar<DerType&>(derived().value() + other, derived().derivatives());
405 friend inline AutoDiffScalar<DerType&> operator+(
const Real& a,
const AutoDiffScalar<DerivativeType>& b) {
406 return AutoDiffScalar<DerType&>(a + b.value(), b.derivatives());
409 inline AutoDiffScalar<DerivativeType>& operator+=(
const Real& other) {
410 derived().value() += other;
414 inline AutoDiffScalar<typename CwiseUnaryOp<bind2nd_op<scalar_product_op<Scalar, Real>>, DerType>::Type>
operator*(
415 const Real& other)
const {
416 return AutoDiffScalar<typename CwiseUnaryOp<bind2nd_op<scalar_product_op<Scalar, Real>>, DerType>::Type>(
417 derived().value() * other, derived().derivatives() * other);
420 friend inline AutoDiffScalar<typename CwiseUnaryOp<bind1st_op<scalar_product_op<Real, Scalar>>, DerType>::Type>
421 operator*(
const Real& other,
const AutoDiffScalar<DerivativeType>& a) {
422 return AutoDiffScalar<typename CwiseUnaryOp<bind1st_op<scalar_product_op<Real, Scalar>>, DerType>::Type>(
423 a.value() * other, a.derivatives() * other);
426 inline AutoDiffScalar<DerivativeType>& operator*=(
const Scalar& other) {
427 *
this = *
this * other;
432 template <
typename DerivativeType>
433 struct auto_diff_special_op<DerivativeType, false> {
435 void operator-()
const;
436 void operator+()
const;
441 template <
typename DerType,
typename BinOp>
442 struct ScalarBinaryOpTraits<AutoDiffScalar<DerType>, typename DerType::Scalar, BinOp> {
443 typedef AutoDiffScalar<DerType> ReturnType;
446 template <
typename DerType,
typename BinOp>
447 struct ScalarBinaryOpTraits<typename DerType::Scalar, AutoDiffScalar<DerType>, BinOp> {
448 typedef AutoDiffScalar<DerType> ReturnType;
467 #define EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(FUNC, CODE) \ 468 template <typename DerType> \ 469 inline auto FUNC(const Eigen::AutoDiffScalar<DerType>& x) { \ 470 using namespace Eigen; \ 471 typedef typename Eigen::internal::traits<Eigen::internal::remove_all_t<DerType>>::Scalar Scalar; \ 472 EIGEN_UNUSED_VARIABLE(sizeof(Scalar)); \ 476 template <
typename DerType>
477 struct CleanedUpDerType {
478 typedef AutoDiffScalar<typename Eigen::internal::remove_all_t<DerType>::PlainObject> type;
481 template <
typename DerType>
482 inline const AutoDiffScalar<DerType>&
conj(
const AutoDiffScalar<DerType>& x) {
485 template <
typename DerType>
486 inline const AutoDiffScalar<DerType>&
real(
const AutoDiffScalar<DerType>& x) {
489 template <
typename DerType>
490 inline typename DerType::Scalar
imag(
const AutoDiffScalar<DerType>&) {
493 template <
typename DerType,
typename T>
494 inline typename CleanedUpDerType<DerType>::type(min)(
const AutoDiffScalar<DerType>& x,
const T& y) {
495 typedef typename CleanedUpDerType<DerType>::type ADS;
496 return (x <= y ? ADS(x) : ADS(y));
498 template <
typename DerType,
typename T>
499 inline typename CleanedUpDerType<DerType>::type(max)(
const AutoDiffScalar<DerType>& x,
const T& y) {
500 typedef typename CleanedUpDerType<DerType>::type ADS;
501 return (x >= y ? ADS(x) : ADS(y));
503 template <
typename DerType,
typename T>
504 inline typename CleanedUpDerType<DerType>::type(min)(
const T& x,
const AutoDiffScalar<DerType>& y) {
505 typedef typename CleanedUpDerType<DerType>::type ADS;
506 return (x < y ? ADS(x) : ADS(y));
508 template <
typename DerType,
typename T>
509 inline typename CleanedUpDerType<DerType>::type(max)(
const T& x,
const AutoDiffScalar<DerType>& y) {
510 typedef typename CleanedUpDerType<DerType>::type ADS;
511 return (x > y ? ADS(x) : ADS(y));
513 template <
typename DerType>
515 typename CleanedUpDerType<DerType>::type(min)(
const AutoDiffScalar<DerType>& x,
const AutoDiffScalar<DerType>& y) {
516 return (x.value() < y.value() ? x : y);
518 template <
typename DerType>
520 typename CleanedUpDerType<DerType>::type(max)(
const AutoDiffScalar<DerType>& x,
const AutoDiffScalar<DerType>& y) {
521 return (x.value() >= y.value() ? x : y);
524 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
abs,
using std::abs;
525 return Eigen::MakeAutoDiffScalar(
abs(x.value()),
526 x.derivatives() * (x.value() < 0 ? -1 : 1));)
528 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
abs2,
using numext::abs2;
529 return Eigen::MakeAutoDiffScalar(
abs2(x.value()),
530 x.derivatives() * (Scalar(2) * x.value()));)
532 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
sqrt,
using std::sqrt; Scalar sqrtx =
sqrt(x.value());
533 return Eigen::MakeAutoDiffScalar(sqrtx, x.derivatives() * (Scalar(0.5) / sqrtx));)
535 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
cos,
using std::cos;
using std::sin;
536 return Eigen::MakeAutoDiffScalar(
cos(x.value()),
537 x.derivatives() * (-
sin(x.value())));)
539 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
sin,
using std::sin;
using std::cos;
540 return Eigen::MakeAutoDiffScalar(
sin(x.value()), x.derivatives() *
cos(x.value()));)
542 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
exp,
using std::exp; Scalar expx =
exp(x.value());
543 return Eigen::MakeAutoDiffScalar(expx, x.derivatives() * expx);)
545 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
log,
using std::log;
546 return Eigen::MakeAutoDiffScalar(
log(x.value()),
547 x.derivatives() * (Scalar(1) / x.value()));)
549 template <typename DerType>
551 const typename internal::traits<internal::remove_all_t<DerType>>::Scalar& y) {
552 using namespace Eigen;
554 return Eigen::MakeAutoDiffScalar(pow(x.value(), y), x.derivatives() * (y * pow(x.value(), y - 1)));
557 template <
typename DerTypeA,
typename DerTypeB>
561 typedef typename internal::traits<internal::remove_all_t<DerTypeA>>::Scalar Scalar;
564 ret.value() = atan2(a.value(), b.value());
566 Scalar squared_hypot = a.value() * a.value() + b.value() * b.value();
569 ret.derivatives() = (a.derivatives() * b.value() - a.value() * b.derivatives()) / squared_hypot;
574 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
tan,
using std::tan;
using std::cos;
return Eigen::MakeAutoDiffScalar(
575 tan(x.value()), x.derivatives() * (Scalar(1) / numext::abs2(
cos(x.value()))));)
577 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
asin,
using std::sqrt;
using std::asin;
return Eigen::MakeAutoDiffScalar(
579 x.derivatives() * (Scalar(1) /
sqrt(1 - numext::abs2(x.value()))));)
581 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
acos,
using std::sqrt;
using std::acos;
return Eigen::MakeAutoDiffScalar(
583 x.derivatives() * (Scalar(-1) /
sqrt(1 - numext::abs2(x.value()))));)
585 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
586 tanh,
using std::cosh;
using std::tanh;
587 return Eigen::MakeAutoDiffScalar(
tanh(x.value()), x.derivatives() * (Scalar(1) / numext::abs2(
cosh(x.value()))));)
589 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
sinh,
using std::sinh;
using std::cosh;
590 return Eigen::MakeAutoDiffScalar(
sinh(x.value()),
591 x.derivatives() *
cosh(x.value()));)
593 EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY(
cosh,
using std::sinh;
using std::cosh;
594 return Eigen::MakeAutoDiffScalar(
cosh(x.value()),
595 x.derivatives() *
sinh(x.value()));)
597 #undef EIGEN_AUTODIFF_DECLARE_GLOBAL_UNARY
599 template <typename DerType>
601 :
NumTraits<
typename NumTraits<
typename internal::remove_all_t<DerType>::Scalar>::Real> {
602 typedef internal::remove_all_t<DerType> DerTypeCleaned;
604 DerTypeCleaned::RowsAtCompileTime, DerTypeCleaned::ColsAtCompileTime, 0,
605 DerTypeCleaned::MaxRowsAtCompileTime, DerTypeCleaned::MaxColsAtCompileTime>>
610 enum { RequireInitialization = 1 };
614 template <
typename DerivativeType>
617 const DerivativeType& derivatives = s.derivatives();
618 for (
int i = 0; i < derivatives.size(); ++i) {
619 if (!numext::is_exactly_zero(derivatives[i])) {
623 return numext::is_exactly_zero(s.value());
631 template <
typename T>
632 class numeric_limits<
Eigen::
AutoDiffScalar<T>> :
public numeric_limits<typename T::Scalar> {};
634 template <
typename T>
635 class numeric_limits<
Eigen::
AutoDiffScalar<T&>> :
public numeric_limits<typename T::Scalar> {};
639 #endif // EIGEN_AUTODIFF_SCALAR_H const Eigen::CwiseUnaryOp< Eigen::internal::scalar_tanh_op< typename Derived::Scalar >, const Derived > tanh(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sinh_op< typename Derived::Scalar >, const Derived > sinh(const Eigen::ArrayBase< Derived > &x)
A scalar type replacement with automatic differentiation capability.
Definition: AutoDiffScalar.h:61
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sqrt_op< typename Derived::Scalar >, const Derived > sqrt(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_conjugate_op< typename Derived::Scalar >, const Derived > conj(const Eigen::ArrayBase< Derived > &x)
Namespace containing all symbols from the Eigen library.
Definition: AutoDiffScalar.h:629
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_asin_op< typename Derived::Scalar >, const Derived > asin(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs2_op< typename Derived::Scalar >, const Derived > abs2(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_acos_op< typename Derived::Scalar >, const Derived > acos(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_cos_op< typename Derived::Scalar >, const Derived > cos(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_imag_op< typename Derived::Scalar >, const Derived > imag(const Eigen::ArrayBase< Derived > &x)
AutoDiffScalar(const Scalar &value, int nbDer, int derNumber)
Definition: AutoDiffScalar.h:119
AutoDiffScalar(const Real &value)
Definition: AutoDiffScalar.h:125
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_real_op< typename Derived::Scalar >, const Derived > real(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs_op< typename Derived::Scalar >, const Derived > abs(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_cosh_op< typename Derived::Scalar >, const Derived > cosh(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_log_op< typename Derived::Scalar >, const Derived > log(const Eigen::ArrayBase< Derived > &x)
AutoDiffScalar()
Definition: AutoDiffScalar.h:115
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_tan_op< typename Derived::Scalar >, const Derived > tan(const Eigen::ArrayBase< Derived > &x)
AutoDiffScalar(const Scalar &value, const DerType &der)
Definition: AutoDiffScalar.h:130
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_sin_op< typename Derived::Scalar >, const Derived > sin(const Eigen::ArrayBase< Derived > &x)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_exp_op< typename Derived::Scalar >, const Derived > exp(const Eigen::ArrayBase< Derived > &x)
const Product< SparseDerived, PermDerived, AliasFreeProduct > operator*(const SparseMatrixBase< SparseDerived > &matrix, const PermutationBase< PermDerived > &perm)