| 18 | template <typename Derived> |
| 19 | template <typename OtherDerived> |
| 20 | inline typename internal::traits<Derived>::Scalar SparseMatrixBase<Derived>::dot( |
| 21 | const MatrixBase<OtherDerived>& other) const { |
| 22 | EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) |
| 23 | EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) |
| 24 | EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(Derived, OtherDerived) |
| 25 | EIGEN_STATIC_ASSERT( |
| 26 | (internal::is_same<Scalar, typename OtherDerived::Scalar>::value), |
| 27 | YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) |
| 28 | |
| 29 | eigen_assert(size() == other.size()); |
| 30 | eigen_assert(other.size() > 0 && "you are using a non initialized vector"); |
| 31 | |
| 32 | internal::evaluator<Derived> thisEval(derived()); |
| 33 | typename internal::evaluator<Derived>::InnerIterator i(thisEval, 0); |
| 34 | // Two accumulators, which breaks the dependency chain on the accumulator |
| 35 | // and allows more instruction-level parallelism in the following loop. |
| 36 | Scalar res1(0); |
| 37 | Scalar res2(0); |
| 38 | for (; i; ++i) { |
| 39 | res1 += numext::conj(i.value()) * other.coeff(i.index()); |
| 40 | ++i; |
| 41 | if (i) { |
| 42 | res2 += numext::conj(i.value()) * other.coeff(i.index()); |
| 43 | } |
| 44 | } |
| 45 | return res1 + res2; |
| 46 | } |
| 47 | |
| 48 | template <typename Derived> |
| 49 | template <typename OtherDerived> |