// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2014 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef EIGEN_SPARSE_CWISE_BINARY_OP_H
#define EIGEN_SPARSE_CWISE_BINARY_OP_H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

// Here we have to handle 3 cases:
//  1 - sparse op dense
//  2 - dense op sparse
//  3 - sparse op sparse
// We also need to implement a 4th iterator for:
//  4 - dense op dense
// Finally, we also need to distinguish between the product and other operations :
//                configuration      returned mode
//  1 - sparse op dense    product      sparse
//                         generic      dense
//  2 - dense op sparse    product      sparse
//                         generic      dense
//  3 - sparse op sparse   product      sparse
//                         generic      sparse
//  4 - dense op dense     product      dense
//                         generic      dense
//
// TODO: to ease compiler job, we could specialize product/quotient with a scalar
//      and fallback to cwise-unary evaluator using bind1st_op and bind2nd_op.

template <typename BinaryOp, typename Lhs, typename Rhs>
class CwiseBinaryOpImpl<BinaryOp, Lhs, Rhs, Sparse> : public SparseMatrixBase<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > {
 public:
  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> Derived;
  typedef SparseMatrixBase<Derived> Base;
  EIGEN_SPARSE_PUBLIC_INTERFACE(Derived)
  EIGEN_STATIC_ASSERT(((!internal::is_same<typename internal::traits<Lhs>::StorageKind,
                                           typename internal::traits<Rhs>::StorageKind>::value) ||
                       ((internal::evaluator<Lhs>::Flags & RowMajorBit) ==
                        (internal::evaluator<Rhs>::Flags & RowMajorBit))),
                      THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH)
};

namespace internal {

// The default evaluator performs an "arithmetic" operation on two input arrays.
// Given input arrays 'lhs' and 'rhs' and binary functor 'func',
// the sparse destination array 'dst' is evaluated as follows:
//   if lhs(i,j) and rhs(i,j) are present, dst(i,j) = func(lhs(i,j), rhs(i,j))
//   if lhs(i,j) is present and rhs(i,j) is null, dst(i,j) = func(lhs(i,j), 0)
//   if lhs(i,j) is null and rhs(i,j) is present, dst(i,j) = func(0, rhs(i,j))

// Generic "sparse OP sparse"
template <typename XprType>
struct binary_sparse_evaluator;

template <typename BinaryOp, typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IteratorBased, IteratorBased>
    : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > {
 protected:
  typedef typename evaluator<Lhs>::InnerIterator LhsIterator;
  typedef typename evaluator<Rhs>::InnerIterator RhsIterator;
  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
  typedef typename traits<XprType>::Scalar Scalar;
  typedef typename XprType::StorageIndex StorageIndex;

 public:
  class InnerIterator {
   public:
    EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
        : m_lhsIter(aEval.m_lhsImpl, outer),
          m_rhsIter(aEval.m_rhsImpl, outer),
          m_functor(aEval.m_functor),
          m_value(Scalar(0)) {
      this->operator++();
    }

    EIGEN_STRONG_INLINE InnerIterator& operator++() {
      if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index())) {
        m_id = m_lhsIter.index();
        m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
        ++m_lhsIter;
        ++m_rhsIter;
      } else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index()))) {
        m_id = m_lhsIter.index();
        m_value = m_functor(m_lhsIter.value(), Scalar(0));
        ++m_lhsIter;
      } else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index()))) {
        m_id = m_rhsIter.index();
        m_value = m_functor(Scalar(0), m_rhsIter.value());
        ++m_rhsIter;
      } else {
        m_id = -1;
      }
      return *this;
    }

    EIGEN_STRONG_INLINE Scalar value() const { return m_value; }

    EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
    EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
    EIGEN_STRONG_INLINE Index row() const { return Lhs::IsRowMajor ? m_lhsIter.row() : index(); }
    EIGEN_STRONG_INLINE Index col() const { return Lhs::IsRowMajor ? index() : m_lhsIter.col(); }

    EIGEN_STRONG_INLINE operator bool() const { return m_id >= 0; }

   protected:
    LhsIterator m_lhsIter;
    RhsIterator m_rhsIter;
    const BinaryOp& m_functor;
    Scalar m_value;
    StorageIndex m_id;
  };

  enum {
    CoeffReadCost =
        int(evaluator<Lhs>::CoeffReadCost) + int(evaluator<Rhs>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
    Flags = XprType::Flags
  };

  explicit binary_evaluator(const XprType& xpr) : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {
    EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
    EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  }

  inline Index nonZerosEstimate() const { return m_lhsImpl.nonZerosEstimate() + m_rhsImpl.nonZerosEstimate(); }

 protected:
  const BinaryOp m_functor;
  evaluator<Lhs> m_lhsImpl;
  evaluator<Rhs> m_rhsImpl;
};

// dense op sparse
template <typename BinaryOp, typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IndexBased, IteratorBased>
    : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > {
 protected:
  typedef typename evaluator<Rhs>::InnerIterator RhsIterator;
  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
  typedef typename traits<XprType>::Scalar Scalar;
  typedef typename XprType::StorageIndex StorageIndex;

 public:
  class InnerIterator {
    enum { IsRowMajor = (int(Rhs::Flags) & RowMajorBit) == RowMajorBit };

   public:
    EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
        : m_lhsEval(aEval.m_lhsImpl),
          m_rhsIter(aEval.m_rhsImpl, outer),
          m_functor(aEval.m_functor),
          m_value(0),
          m_id(-1),
          m_innerSize(aEval.m_expr.rhs().innerSize()) {
      this->operator++();
    }

    EIGEN_STRONG_INLINE InnerIterator& operator++() {
      ++m_id;
      if (m_id < m_innerSize) {
        Scalar lhsVal = m_lhsEval.coeff(IsRowMajor ? m_rhsIter.outer() : m_id, IsRowMajor ? m_id : m_rhsIter.outer());
        if (m_rhsIter && m_rhsIter.index() == m_id) {
          m_value = m_functor(lhsVal, m_rhsIter.value());
          ++m_rhsIter;
        } else
          m_value = m_functor(lhsVal, Scalar(0));
      }

      return *this;
    }

    EIGEN_STRONG_INLINE Scalar value() const {
      eigen_internal_assert(m_id < m_innerSize);
      return m_value;
    }

    EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
    EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); }
    EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_rhsIter.outer() : m_id; }
    EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_rhsIter.outer(); }

    EIGEN_STRONG_INLINE operator bool() const { return m_id < m_innerSize; }

   protected:
    const evaluator<Lhs>& m_lhsEval;
    RhsIterator m_rhsIter;
    const BinaryOp& m_functor;
    Scalar m_value;
    StorageIndex m_id;
    StorageIndex m_innerSize;
  };

  enum {
    CoeffReadCost =
        int(evaluator<Lhs>::CoeffReadCost) + int(evaluator<Rhs>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
    Flags = XprType::Flags
  };

  explicit binary_evaluator(const XprType& xpr)
      : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()), m_expr(xpr) {
    EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
    EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  }

  inline Index nonZerosEstimate() const { return m_expr.size(); }

 protected:
  const BinaryOp m_functor;
  evaluator<Lhs> m_lhsImpl;
  evaluator<Rhs> m_rhsImpl;
  const XprType& m_expr;
};

// sparse op dense
template <typename BinaryOp, typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<BinaryOp, Lhs, Rhs>, IteratorBased, IndexBased>
    : evaluator_base<CwiseBinaryOp<BinaryOp, Lhs, Rhs> > {
 protected:
  typedef typename evaluator<Lhs>::InnerIterator LhsIterator;
  typedef CwiseBinaryOp<BinaryOp, Lhs, Rhs> XprType;
  typedef typename traits<XprType>::Scalar Scalar;
  typedef typename XprType::StorageIndex StorageIndex;

 public:
  class InnerIterator {
    enum { IsRowMajor = (int(Lhs::Flags) & RowMajorBit) == RowMajorBit };

   public:
    EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer)
        : m_lhsIter(aEval.m_lhsImpl, outer),
          m_rhsEval(aEval.m_rhsImpl),
          m_functor(aEval.m_functor),
          m_value(0),
          m_id(-1),
          m_innerSize(aEval.m_expr.lhs().innerSize()) {
      this->operator++();
    }

    EIGEN_STRONG_INLINE InnerIterator& operator++() {
      ++m_id;
      if (m_id < m_innerSize) {
        Scalar rhsVal = m_rhsEval.coeff(IsRowMajor ? m_lhsIter.outer() : m_id, IsRowMajor ? m_id : m_lhsIter.outer());
        if (m_lhsIter && m_lhsIter.index() == m_id) {
          m_value = m_functor(m_lhsIter.value(), rhsVal);
          ++m_lhsIter;
        } else
          m_value = m_functor(Scalar(0), rhsVal);
      }

      return *this;
    }

    EIGEN_STRONG_INLINE Scalar value() const {
      eigen_internal_assert(m_id < m_innerSize);
      return m_value;
    }

    EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
    EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
    EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_lhsIter.outer() : m_id; }
    EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_lhsIter.outer(); }

    EIGEN_STRONG_INLINE operator bool() const { return m_id < m_innerSize; }

   protected:
    LhsIterator m_lhsIter;
    const evaluator<Rhs>& m_rhsEval;
    const BinaryOp& m_functor;
    Scalar m_value;
    StorageIndex m_id;
    StorageIndex m_innerSize;
  };

  enum {
    CoeffReadCost =
        int(evaluator<Lhs>::CoeffReadCost) + int(evaluator<Rhs>::CoeffReadCost) + int(functor_traits<BinaryOp>::Cost),
    Flags = XprType::Flags
  };

  explicit binary_evaluator(const XprType& xpr)
      : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()), m_expr(xpr) {
    EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
    EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  }

  inline Index nonZerosEstimate() const { return m_expr.size(); }

 protected:
  const BinaryOp m_functor;
  evaluator<Lhs> m_lhsImpl;
  evaluator<Rhs> m_rhsImpl;
  const XprType& m_expr;
};

template <typename T, typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,
          typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind,
          typename LhsScalar = typename traits<typename T::Lhs>::Scalar,
          typename RhsScalar = typename traits<typename T::Rhs>::Scalar>
struct sparse_conjunction_evaluator;

// "sparse .* sparse"
template <typename T1, typename T2, typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T1, T2>, Lhs, Rhs>, IteratorBased, IteratorBased>
    : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1, T2>, Lhs, Rhs> > {
  typedef CwiseBinaryOp<scalar_product_op<T1, T2>, Lhs, Rhs> XprType;
  typedef sparse_conjunction_evaluator<XprType> Base;
  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
};
// "dense .* sparse"
template <typename T1, typename T2, typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T1, T2>, Lhs, Rhs>, IndexBased, IteratorBased>
    : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1, T2>, Lhs, Rhs> > {
  typedef CwiseBinaryOp<scalar_product_op<T1, T2>, Lhs, Rhs> XprType;
  typedef sparse_conjunction_evaluator<XprType> Base;
  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
};
// "sparse .* dense"
template <typename T1, typename T2, typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<scalar_product_op<T1, T2>, Lhs, Rhs>, IteratorBased, IndexBased>
    : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_product_op<T1, T2>, Lhs, Rhs> > {
  typedef CwiseBinaryOp<scalar_product_op<T1, T2>, Lhs, Rhs> XprType;
  typedef sparse_conjunction_evaluator<XprType> Base;
  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
};

// "sparse ./ dense"
template <typename T1, typename T2, typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<scalar_quotient_op<T1, T2>, Lhs, Rhs>, IteratorBased, IndexBased>
    : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_quotient_op<T1, T2>, Lhs, Rhs> > {
  typedef CwiseBinaryOp<scalar_quotient_op<T1, T2>, Lhs, Rhs> XprType;
  typedef sparse_conjunction_evaluator<XprType> Base;
  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
};

// "sparse && sparse"
template <typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs>, IteratorBased, IteratorBased>
    : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> > {
  typedef CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> XprType;
  typedef sparse_conjunction_evaluator<XprType> Base;
  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
};
// "dense && sparse"
template <typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs>, IndexBased, IteratorBased>
    : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> > {
  typedef CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> XprType;
  typedef sparse_conjunction_evaluator<XprType> Base;
  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
};
// "sparse && dense"
template <typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs>, IteratorBased, IndexBased>
    : sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> > {
  typedef CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> XprType;
  typedef sparse_conjunction_evaluator<XprType> Base;
  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
};

// The conjunction "^" evaluator performs a logical "and" or set "intersection" operation on two input arrays.
// Given input arrays 'lhs' and 'rhs' and binary functor 'func',
// the sparse destination array 'dst' is evaluated as follows:
//   if lhs(i,j) and rhs(i,j) are present, dst(i,j) = func(lhs(i,j), rhs(i,j))
//   if lhs(i,j) is present and rhs(i,j) is null, dst(i,j) is null
//   if lhs(i,j) is null and rhs(i,j) is present, dst(i,j) is null

// "sparse ^ sparse"
template <typename XprType>
struct sparse_conjunction_evaluator<XprType, IteratorBased, IteratorBased> : evaluator_base<XprType> {
 protected:
  typedef typename XprType::Functor BinaryOp;
  typedef typename XprType::Lhs LhsArg;
  typedef typename XprType::Rhs RhsArg;
  typedef typename evaluator<LhsArg>::InnerIterator LhsIterator;
  typedef typename evaluator<RhsArg>::InnerIterator RhsIterator;
  typedef typename XprType::StorageIndex StorageIndex;
  typedef typename traits<XprType>::Scalar Scalar;

 public:
  class InnerIterator {
   public:
    EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer)
        : m_lhsIter(aEval.m_lhsImpl, outer), m_rhsIter(aEval.m_rhsImpl, outer), m_functor(aEval.m_functor) {
      while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index())) {
        if (m_lhsIter.index() < m_rhsIter.index())
          ++m_lhsIter;
        else
          ++m_rhsIter;
      }
    }

    EIGEN_STRONG_INLINE InnerIterator& operator++() {
      ++m_lhsIter;
      ++m_rhsIter;
      while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index())) {
        if (m_lhsIter.index() < m_rhsIter.index())
          ++m_lhsIter;
        else
          ++m_rhsIter;
      }
      return *this;
    }

    EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_lhsIter.value(), m_rhsIter.value()); }

    EIGEN_STRONG_INLINE StorageIndex index() const { return m_lhsIter.index(); }
    EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
    EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
    EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }

    EIGEN_STRONG_INLINE operator bool() const { return (m_lhsIter && m_rhsIter); }

   protected:
    LhsIterator m_lhsIter;
    RhsIterator m_rhsIter;
    const BinaryOp& m_functor;
  };

  enum {
    CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) +
                    int(functor_traits<BinaryOp>::Cost),
    Flags = XprType::Flags
  };

  explicit sparse_conjunction_evaluator(const XprType& xpr)
      : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {
    EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
    EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  }

  inline Index nonZerosEstimate() const {
    return (std::min)(m_lhsImpl.nonZerosEstimate(), m_rhsImpl.nonZerosEstimate());
  }

 protected:
  const BinaryOp m_functor;
  evaluator<LhsArg> m_lhsImpl;
  evaluator<RhsArg> m_rhsImpl;
};

// "dense ^ sparse"
template <typename XprType>
struct sparse_conjunction_evaluator<XprType, IndexBased, IteratorBased> : evaluator_base<XprType> {
 protected:
  typedef typename XprType::Functor BinaryOp;
  typedef typename XprType::Lhs LhsArg;
  typedef typename XprType::Rhs RhsArg;
  typedef evaluator<LhsArg> LhsEvaluator;
  typedef typename evaluator<RhsArg>::InnerIterator RhsIterator;
  typedef typename XprType::StorageIndex StorageIndex;
  typedef typename traits<XprType>::Scalar Scalar;

 public:
  class InnerIterator {
    enum { IsRowMajor = (int(RhsArg::Flags) & RowMajorBit) == RowMajorBit };

   public:
    EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer)
        : m_lhsEval(aEval.m_lhsImpl), m_rhsIter(aEval.m_rhsImpl, outer), m_functor(aEval.m_functor), m_outer(outer) {}

    EIGEN_STRONG_INLINE InnerIterator& operator++() {
      ++m_rhsIter;
      return *this;
    }

    EIGEN_STRONG_INLINE Scalar value() const {
      return m_functor(
          m_lhsEval.coeff(IsRowMajor ? m_outer : m_rhsIter.index(), IsRowMajor ? m_rhsIter.index() : m_outer),
          m_rhsIter.value());
    }

    EIGEN_STRONG_INLINE StorageIndex index() const { return m_rhsIter.index(); }
    EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); }
    EIGEN_STRONG_INLINE Index row() const { return m_rhsIter.row(); }
    EIGEN_STRONG_INLINE Index col() const { return m_rhsIter.col(); }

    EIGEN_STRONG_INLINE operator bool() const { return m_rhsIter; }

   protected:
    const LhsEvaluator& m_lhsEval;
    RhsIterator m_rhsIter;
    const BinaryOp& m_functor;
    const Index m_outer;
  };

  enum {
    CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) +
                    int(functor_traits<BinaryOp>::Cost),
    Flags = XprType::Flags
  };

  explicit sparse_conjunction_evaluator(const XprType& xpr)
      : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {
    EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
    EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  }

  inline Index nonZerosEstimate() const { return m_rhsImpl.nonZerosEstimate(); }

 protected:
  const BinaryOp m_functor;
  evaluator<LhsArg> m_lhsImpl;
  evaluator<RhsArg> m_rhsImpl;
};

// "sparse ^ dense"
template <typename XprType>
struct sparse_conjunction_evaluator<XprType, IteratorBased, IndexBased> : evaluator_base<XprType> {
 protected:
  typedef typename XprType::Functor BinaryOp;
  typedef typename XprType::Lhs LhsArg;
  typedef typename XprType::Rhs RhsArg;
  typedef typename evaluator<LhsArg>::InnerIterator LhsIterator;
  typedef evaluator<RhsArg> RhsEvaluator;
  typedef typename XprType::StorageIndex StorageIndex;
  typedef typename traits<XprType>::Scalar Scalar;

 public:
  class InnerIterator {
    enum { IsRowMajor = (int(LhsArg::Flags) & RowMajorBit) == RowMajorBit };

   public:
    EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer)
        : m_lhsIter(aEval.m_lhsImpl, outer), m_rhsEval(aEval.m_rhsImpl), m_functor(aEval.m_functor), m_outer(outer) {}

    EIGEN_STRONG_INLINE InnerIterator& operator++() {
      ++m_lhsIter;
      return *this;
    }

    EIGEN_STRONG_INLINE Scalar value() const {
      return m_functor(m_lhsIter.value(), m_rhsEval.coeff(IsRowMajor ? m_outer : m_lhsIter.index(),
                                                          IsRowMajor ? m_lhsIter.index() : m_outer));
    }

    EIGEN_STRONG_INLINE StorageIndex index() const { return m_lhsIter.index(); }
    EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
    EIGEN_STRONG_INLINE Index row() const { return m_lhsIter.row(); }
    EIGEN_STRONG_INLINE Index col() const { return m_lhsIter.col(); }

    EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; }

   protected:
    LhsIterator m_lhsIter;
    const evaluator<RhsArg>& m_rhsEval;
    const BinaryOp& m_functor;
    const Index m_outer;
  };

  enum {
    CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) +
                    int(functor_traits<BinaryOp>::Cost),
    Flags = XprType::Flags
  };

  explicit sparse_conjunction_evaluator(const XprType& xpr)
      : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {
    EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
    EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  }

  inline Index nonZerosEstimate() const { return m_lhsImpl.nonZerosEstimate(); }

 protected:
  const BinaryOp m_functor;
  evaluator<LhsArg> m_lhsImpl;
  evaluator<RhsArg> m_rhsImpl;
};

template <typename T, typename LhsKind = typename evaluator_traits<typename T::Lhs>::Kind,
          typename RhsKind = typename evaluator_traits<typename T::Rhs>::Kind,
          typename LhsScalar = typename traits<typename T::Lhs>::Scalar,
          typename RhsScalar = typename traits<typename T::Rhs>::Scalar>
struct sparse_disjunction_evaluator;

// The disjunction "v" evaluator performs a logical "or" or set "union" operation on two input arrays.
// Given input arrays 'lhs' and 'rhs' and binary functor 'func',
// the sparse destination array 'dst' is evaluated as follows:
//   if lhs(i,j) and rhs(i,j) are present, dst(i,j) = func(lhs(i,j), rhs(i,j))
//   if lhs(i,j) is present and rhs(i,j) is null, dst(i,j) = lhs(i,j)
//   if lhs(i,j) is null and rhs(i,j) is present, dst(i,j) = rhs(i,j)

// "sparse v sparse"
template <typename XprType>
struct sparse_disjunction_evaluator<XprType, IteratorBased, IteratorBased> : evaluator_base<XprType> {
 protected:
  typedef typename XprType::Functor BinaryOp;
  typedef typename XprType::Lhs LhsArg;
  typedef typename XprType::Rhs RhsArg;
  typedef typename evaluator<LhsArg>::InnerIterator LhsIterator;
  typedef typename evaluator<RhsArg>::InnerIterator RhsIterator;
  typedef typename XprType::StorageIndex StorageIndex;
  typedef typename traits<XprType>::Scalar Scalar;

 public:
  class InnerIterator {
   public:
    EIGEN_STRONG_INLINE InnerIterator(const sparse_disjunction_evaluator& aEval, Index outer)
        : m_lhsIter(aEval.m_lhsImpl, outer),
          m_rhsIter(aEval.m_rhsImpl, outer),
          m_functor(aEval.m_functor),
          m_value(Scalar(0)) {
      this->operator++();
    }

    EIGEN_STRONG_INLINE InnerIterator& operator++() {
      if (m_lhsIter && m_rhsIter && (m_lhsIter.index() == m_rhsIter.index())) {
        m_id = m_lhsIter.index();
        m_value = m_functor(m_lhsIter.value(), m_rhsIter.value());
        ++m_lhsIter;
        ++m_rhsIter;
      } else if (m_lhsIter && (!m_rhsIter || (m_lhsIter.index() < m_rhsIter.index()))) {
        m_id = m_lhsIter.index();
        m_value = m_lhsIter.value();
        ++m_lhsIter;
      } else if (m_rhsIter && (!m_lhsIter || (m_lhsIter.index() > m_rhsIter.index()))) {
        m_id = m_rhsIter.index();
        m_value = m_rhsIter.value();
        ++m_rhsIter;
      } else {
        m_id = -1;
      }
      return *this;
    }

    EIGEN_STRONG_INLINE Scalar value() const { return m_value; }

    EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
    EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
    EIGEN_STRONG_INLINE Index row() const { return LhsArg::IsRowMajor ? m_lhsIter.row() : index(); }
    EIGEN_STRONG_INLINE Index col() const { return LhsArg::IsRowMajor ? index() : m_lhsIter.col(); }

    EIGEN_STRONG_INLINE operator bool() const { return m_id >= 0; }

   protected:
    LhsIterator m_lhsIter;
    RhsIterator m_rhsIter;
    const BinaryOp& m_functor;
    Scalar m_value;
    StorageIndex m_id;
  };

  enum {
    CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) +
                    int(functor_traits<BinaryOp>::Cost),
    Flags = XprType::Flags
  };

  explicit sparse_disjunction_evaluator(const XprType& xpr)
      : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) {
    EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
    EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  }

  inline Index nonZerosEstimate() const { return m_lhsImpl.nonZerosEstimate() + m_rhsImpl.nonZerosEstimate(); }

 protected:
  const BinaryOp m_functor;
  evaluator<LhsArg> m_lhsImpl;
  evaluator<RhsArg> m_rhsImpl;
};

// "dense v sparse"
template <typename XprType>
struct sparse_disjunction_evaluator<XprType, IndexBased, IteratorBased> : evaluator_base<XprType> {
 protected:
  typedef typename XprType::Functor BinaryOp;
  typedef typename XprType::Lhs LhsArg;
  typedef typename XprType::Rhs RhsArg;
  typedef evaluator<LhsArg> LhsEvaluator;
  typedef typename evaluator<RhsArg>::InnerIterator RhsIterator;
  typedef typename XprType::StorageIndex StorageIndex;
  typedef typename traits<XprType>::Scalar Scalar;

 public:
  class InnerIterator {
    enum { IsRowMajor = (int(RhsArg::Flags) & RowMajorBit) == RowMajorBit };

   public:
    EIGEN_STRONG_INLINE InnerIterator(const sparse_disjunction_evaluator& aEval, Index outer)
        : m_lhsEval(aEval.m_lhsImpl),
          m_rhsIter(aEval.m_rhsImpl, outer),
          m_functor(aEval.m_functor),
          m_value(0),
          m_id(-1),
          m_innerSize(aEval.m_expr.rhs().innerSize()) {
      this->operator++();
    }

    EIGEN_STRONG_INLINE InnerIterator& operator++() {
      ++m_id;
      if (m_id < m_innerSize) {
        Scalar lhsVal = m_lhsEval.coeff(IsRowMajor ? m_rhsIter.outer() : m_id, IsRowMajor ? m_id : m_rhsIter.outer());
        if (m_rhsIter && m_rhsIter.index() == m_id) {
          m_value = m_functor(lhsVal, m_rhsIter.value());
          ++m_rhsIter;
        } else
          m_value = lhsVal;
      }

      return *this;
    }

    EIGEN_STRONG_INLINE Scalar value() const {
      eigen_internal_assert(m_id < m_innerSize);
      return m_value;
    }

    EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
    EIGEN_STRONG_INLINE Index outer() const { return m_rhsIter.outer(); }
    EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_rhsIter.outer() : m_id; }
    EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_rhsIter.outer(); }

    EIGEN_STRONG_INLINE operator bool() const { return m_id < m_innerSize; }

   protected:
    const evaluator<LhsArg>& m_lhsEval;
    RhsIterator m_rhsIter;
    const BinaryOp& m_functor;
    Scalar m_value;
    StorageIndex m_id;
    StorageIndex m_innerSize;
  };

  enum {
    CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) +
                    int(functor_traits<BinaryOp>::Cost),
    Flags = XprType::Flags
  };

  explicit sparse_disjunction_evaluator(const XprType& xpr)
      : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()), m_expr(xpr) {
    EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
    EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  }

  inline Index nonZerosEstimate() const { return m_expr.size(); }

 protected:
  const BinaryOp m_functor;
  evaluator<LhsArg> m_lhsImpl;
  evaluator<RhsArg> m_rhsImpl;
  const XprType& m_expr;
};

// "sparse v dense"
template <typename XprType>
struct sparse_disjunction_evaluator<XprType, IteratorBased, IndexBased> : evaluator_base<XprType> {
 protected:
  typedef typename XprType::Functor BinaryOp;
  typedef typename XprType::Lhs LhsArg;
  typedef typename XprType::Rhs RhsArg;
  typedef typename evaluator<LhsArg>::InnerIterator LhsIterator;
  typedef evaluator<RhsArg> RhsEvaluator;
  typedef typename XprType::StorageIndex StorageIndex;
  typedef typename traits<XprType>::Scalar Scalar;

 public:
  class InnerIterator {
    enum { IsRowMajor = (int(LhsArg::Flags) & RowMajorBit) == RowMajorBit };

   public:
    EIGEN_STRONG_INLINE InnerIterator(const sparse_disjunction_evaluator& aEval, Index outer)
        : m_lhsIter(aEval.m_lhsImpl, outer),
          m_rhsEval(aEval.m_rhsImpl),
          m_functor(aEval.m_functor),
          m_value(0),
          m_id(-1),
          m_innerSize(aEval.m_expr.lhs().innerSize()) {
      this->operator++();
    }

    EIGEN_STRONG_INLINE InnerIterator& operator++() {
      ++m_id;
      if (m_id < m_innerSize) {
        Scalar rhsVal = m_rhsEval.coeff(IsRowMajor ? m_lhsIter.outer() : m_id, IsRowMajor ? m_id : m_lhsIter.outer());
        if (m_lhsIter && m_lhsIter.index() == m_id) {
          m_value = m_functor(m_lhsIter.value(), rhsVal);
          ++m_lhsIter;
        } else
          m_value = rhsVal;
      }

      return *this;
    }

    EIGEN_STRONG_INLINE Scalar value() const {
      eigen_internal_assert(m_id < m_innerSize);
      return m_value;
    }

    EIGEN_STRONG_INLINE StorageIndex index() const { return m_id; }
    EIGEN_STRONG_INLINE Index outer() const { return m_lhsIter.outer(); }
    EIGEN_STRONG_INLINE Index row() const { return IsRowMajor ? m_lhsIter.outer() : m_id; }
    EIGEN_STRONG_INLINE Index col() const { return IsRowMajor ? m_id : m_lhsIter.outer(); }

    EIGEN_STRONG_INLINE operator bool() const { return m_id < m_innerSize; }

   protected:
    LhsIterator m_lhsIter;
    const evaluator<RhsArg>& m_rhsEval;
    const BinaryOp& m_functor;
    Scalar m_value;
    StorageIndex m_id;
    StorageIndex m_innerSize;
  };

  enum {
    CoeffReadCost = int(evaluator<LhsArg>::CoeffReadCost) + int(evaluator<RhsArg>::CoeffReadCost) +
                    int(functor_traits<BinaryOp>::Cost),
    Flags = XprType::Flags
  };

  explicit sparse_disjunction_evaluator(const XprType& xpr)
      : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()), m_expr(xpr) {
    EIGEN_INTERNAL_CHECK_COST_VALUE(functor_traits<BinaryOp>::Cost);
    EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost);
  }

  inline Index nonZerosEstimate() const { return m_expr.size(); }

 protected:
  const BinaryOp m_functor;
  evaluator<LhsArg> m_lhsImpl;
  evaluator<RhsArg> m_rhsImpl;
  const XprType& m_expr;
};

// when DupFunc is wrapped with scalar_dup_op, use disjunction evaluator
template <typename T1, typename T2, typename DupFunc, typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<scalar_disjunction_op<DupFunc, T1, T2>, Lhs, Rhs>, IteratorBased, IteratorBased>
    : sparse_disjunction_evaluator<CwiseBinaryOp<scalar_disjunction_op<DupFunc, T1, T2>, Lhs, Rhs> > {
  typedef CwiseBinaryOp<scalar_disjunction_op<DupFunc, T1, T2>, Lhs, Rhs> XprType;
  typedef sparse_disjunction_evaluator<XprType> Base;
  explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
};
}  // namespace internal

/***************************************************************************
 * Implementation of SparseMatrixBase and SparseCwise functions/operators
 ***************************************************************************/

template <typename Derived>
template <typename OtherDerived>
Derived& SparseMatrixBase<Derived>::operator+=(const EigenBase<OtherDerived>& other) {
  call_assignment(derived(), other.derived(), internal::add_assign_op<Scalar, typename OtherDerived::Scalar>());
  return derived();
}

template <typename Derived>
template <typename OtherDerived>
Derived& SparseMatrixBase<Derived>::operator-=(const EigenBase<OtherDerived>& other) {
  call_assignment(derived(), other.derived(), internal::sub_assign_op<Scalar, typename OtherDerived::Scalar>());
  return derived();
}

template <typename Derived>
template <typename OtherDerived>
EIGEN_STRONG_INLINE Derived& SparseMatrixBase<Derived>::operator-=(const SparseMatrixBase<OtherDerived>& other) {
  return derived() = derived() - other.derived();
}

template <typename Derived>
template <typename OtherDerived>
EIGEN_STRONG_INLINE Derived& SparseMatrixBase<Derived>::operator+=(const SparseMatrixBase<OtherDerived>& other) {
  return derived() = derived() + other.derived();
}

template <typename Derived>
template <typename OtherDerived>
Derived& SparseMatrixBase<Derived>::operator+=(const DiagonalBase<OtherDerived>& other) {
  call_assignment_no_alias(derived(), other.derived(),
                           internal::add_assign_op<Scalar, typename OtherDerived::Scalar>());
  return derived();
}

template <typename Derived>
template <typename OtherDerived>
Derived& SparseMatrixBase<Derived>::operator-=(const DiagonalBase<OtherDerived>& other) {
  call_assignment_no_alias(derived(), other.derived(),
                           internal::sub_assign_op<Scalar, typename OtherDerived::Scalar>());
  return derived();
}

template <typename Derived>
template <typename OtherDerived>
EIGEN_STRONG_INLINE const typename SparseMatrixBase<Derived>::template CwiseProductDenseReturnType<OtherDerived>::Type
SparseMatrixBase<Derived>::cwiseProduct(const MatrixBase<OtherDerived>& other) const {
  return typename CwiseProductDenseReturnType<OtherDerived>::Type(derived(), other.derived());
}

template <typename DenseDerived, typename SparseDerived>
EIGEN_STRONG_INLINE const
    CwiseBinaryOp<internal::scalar_sum_op<typename DenseDerived::Scalar, typename SparseDerived::Scalar>,
                  const DenseDerived, const SparseDerived>
    operator+(const MatrixBase<DenseDerived>& a, const SparseMatrixBase<SparseDerived>& b) {
  return CwiseBinaryOp<internal::scalar_sum_op<typename DenseDerived::Scalar, typename SparseDerived::Scalar>,
                       const DenseDerived, const SparseDerived>(a.derived(), b.derived());
}

template <typename SparseDerived, typename DenseDerived>
EIGEN_STRONG_INLINE const
    CwiseBinaryOp<internal::scalar_sum_op<typename SparseDerived::Scalar, typename DenseDerived::Scalar>,
                  const SparseDerived, const DenseDerived>
    operator+(const SparseMatrixBase<SparseDerived>& a, const MatrixBase<DenseDerived>& b) {
  return CwiseBinaryOp<internal::scalar_sum_op<typename SparseDerived::Scalar, typename DenseDerived::Scalar>,
                       const SparseDerived, const DenseDerived>(a.derived(), b.derived());
}

template <typename DenseDerived, typename SparseDerived>
EIGEN_STRONG_INLINE const
    CwiseBinaryOp<internal::scalar_difference_op<typename DenseDerived::Scalar, typename SparseDerived::Scalar>,
                  const DenseDerived, const SparseDerived>
    operator-(const MatrixBase<DenseDerived>& a, const SparseMatrixBase<SparseDerived>& b) {
  return CwiseBinaryOp<internal::scalar_difference_op<typename DenseDerived::Scalar, typename SparseDerived::Scalar>,
                       const DenseDerived, const SparseDerived>(a.derived(), b.derived());
}

template <typename SparseDerived, typename DenseDerived>
EIGEN_STRONG_INLINE const
    CwiseBinaryOp<internal::scalar_difference_op<typename SparseDerived::Scalar, typename DenseDerived::Scalar>,
                  const SparseDerived, const DenseDerived>
    operator-(const SparseMatrixBase<SparseDerived>& a, const MatrixBase<DenseDerived>& b) {
  return CwiseBinaryOp<internal::scalar_difference_op<typename SparseDerived::Scalar, typename DenseDerived::Scalar>,
                       const SparseDerived, const DenseDerived>(a.derived(), b.derived());
}

}  // end namespace Eigen

#endif  // EIGEN_SPARSE_CWISE_BINARY_OP_H
