// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 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_RANDOMSETTER_H
#define EIGEN_RANDOMSETTER_H

#if defined(EIGEN_GOOGLEHASH_SUPPORT)
// Ensure the ::google namespace exists, required for checking existence of
// ::google::dense_hash_map and ::google::sparse_hash_map.
namespace google {}
#endif

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

namespace Eigen {

/** Represents a std::map
 *
 * \see RandomSetter
 */
template <typename Scalar>
struct StdMapTraits {
  typedef int KeyType;
  typedef std::map<KeyType, Scalar> Type;
  enum { IsSorted = 1 };

  static void setInvalidKey(Type&, const KeyType&) {}
};

/** Represents a std::unordered_map
 * \see RandomSetter
 */
template <typename Scalar>
struct StdUnorderedMapTraits {
  typedef int KeyType;
  typedef std::unordered_map<KeyType, Scalar> Type;
  enum { IsSorted = 0 };

  static void setInvalidKey(Type&, const KeyType&) {}
};

#if defined(EIGEN_GOOGLEHASH_SUPPORT)

namespace google {

// Namespace work-around, since sometimes dense_hash_map and sparse_hash_map
// are in the global namespace, and other times they are under ::google.
using namespace ::google;

template <typename KeyType, typename Scalar>
struct DenseHashMap {
  typedef dense_hash_map<KeyType, Scalar> type;
};

template <typename KeyType, typename Scalar>
struct SparseHashMap {
  typedef sparse_hash_map<KeyType, Scalar> type;
};

}  // namespace google

/** Represents a google::dense_hash_map
 *
 * \see RandomSetter
 */
template <typename Scalar>
struct GoogleDenseHashMapTraits {
  typedef int KeyType;
  typedef typename google::DenseHashMap<KeyType, Scalar>::type Type;
  enum { IsSorted = 0 };

  static void setInvalidKey(Type& map, const KeyType& k) { map.set_empty_key(k); }
};

/** Represents a google::sparse_hash_map
 *
 * \see RandomSetter
 */
template <typename Scalar>
struct GoogleSparseHashMapTraits {
  typedef int KeyType;
  typedef typename google::SparseHashMap<KeyType, Scalar>::type Type;
  enum { IsSorted = 0 };

  static void setInvalidKey(Type&, const KeyType&) {}
};
#endif

/** \class RandomSetter
 * \ingroup SparseExtra_Module
 * \brief The RandomSetter is a wrapper object allowing to set/update a sparse matrix with random access
 *
 * \tparam SparseMatrixType the type of the sparse matrix we are updating
 * \tparam MapTraits a traits class representing the map implementation used for the temporary sparse storage.
 *                  Its default value depends on the system.
 * \tparam OuterPacketBits defines the number of rows (or columns) manage by a single map object
 *                        as a power of two exponent.
 *
 * This class temporarily represents a sparse matrix object using a generic map implementation allowing for
 * efficient random access. The conversion from the compressed representation to a hash_map object is performed
 * in the RandomSetter constructor, while the sparse matrix is updated back at destruction time. This strategy
 * suggest the use of nested blocks as in this example:
 *
 * \code
 * SparseMatrix<double> m(rows,cols);
 * {
 *   RandomSetter<SparseMatrix<double> > w(m);
 *   // don't use m but w instead with read/write random access to the coefficients:
 *   for(;;)
 *     w(rand(),rand()) = rand;
 * }
 * // when w is deleted, the data are copied back to m
 * // and m is ready to use.
 * \endcode
 *
 * Since hash_map objects are not fully sorted, representing a full matrix as a single hash_map would
 * involve a big and costly sort to update the compressed matrix back. To overcome this issue, a RandomSetter
 * use multiple hash_map, each representing 2^OuterPacketBits columns or rows according to the storage order.
 * To reach optimal performance, this value should be adjusted according to the average number of nonzeros
 * per rows/columns.
 *
 * The possible values for the template parameter MapTraits are:
 *  - \b StdMapTraits: corresponds to std::map. (does not perform very well)
 *  - \b StdUnorderedMapTraits: corresponds to std::unordered_map
 *  - \b GoogleDenseHashMapTraits: corresponds to google::dense_hash_map (best efficiency, reasonable memory
 * consumption)
 *  - \b GoogleSparseHashMapTraits: corresponds to google::sparse_hash_map (best memory consumption, relatively good
 * performance)
 *
 * The default map implementation depends on the availability, and the preferred order is:
 * GoogleSparseHashMapTraits, StdUnorderedMapTraits, and finally StdMapTraits.
 *
 * For performance and memory consumption reasons it is highly recommended to use one of
 * Google's hash_map implementations. To enable the support for them, you must define
 * EIGEN_GOOGLEHASH_SUPPORT. This will include both <google/dense_hash_map> and
 * <google/sparse_hash_map> for you.
 *
 * \see https://github.com/sparsehash/sparsehash
 */
template <typename SparseMatrixType,
          template <typename T> class MapTraits =
#if defined(EIGEN_GOOGLEHASH_SUPPORT)
              GoogleDenseHashMapTraits
#else
              StdUnorderedMapTraits
#endif
          ,
          int OuterPacketBits = 6>
class RandomSetter {
  typedef typename SparseMatrixType::Scalar Scalar;
  typedef typename SparseMatrixType::StorageIndex StorageIndex;

  struct ScalarWrapper {
    ScalarWrapper() : value(0) {}
    Scalar value;
  };
  typedef typename MapTraits<ScalarWrapper>::KeyType KeyType;
  typedef typename MapTraits<ScalarWrapper>::Type HashMapType;
  static constexpr int OuterPacketMask = (1 << OuterPacketBits) - 1;
  enum {
    SwapStorage = 1 - MapTraits<ScalarWrapper>::IsSorted,
    TargetRowMajor = (SparseMatrixType::Flags & RowMajorBit) ? 1 : 0,
    SetterRowMajor = SwapStorage ? 1 - TargetRowMajor : TargetRowMajor
  };

 public:
  /** Constructs a random setter object from the sparse matrix \a target
   *
   * Note that the initial value of \a target are imported. If you want to re-set
   * a sparse matrix from scratch, then you must set it to zero first using the
   * setZero() function.
   */
  inline RandomSetter(SparseMatrixType& target) : mp_target(&target) {
    const Index outerSize = SwapStorage ? target.innerSize() : target.outerSize();
    const Index innerSize = SwapStorage ? target.outerSize() : target.innerSize();
    m_outerPackets = outerSize >> OuterPacketBits;
    if (outerSize & OuterPacketMask) m_outerPackets += 1;
    m_hashmaps = new HashMapType[m_outerPackets];
    // compute number of bits needed to store inner indices
    Index aux = innerSize - 1;
    m_keyBitsOffset = 0;
    while (aux) {
      ++m_keyBitsOffset;
      aux = aux >> 1;
    }
    KeyType ik = (1 << (OuterPacketBits + m_keyBitsOffset));
    for (Index k = 0; k < m_outerPackets; ++k) MapTraits<ScalarWrapper>::setInvalidKey(m_hashmaps[k], ik);

    // insert current coeffs
    for (Index j = 0; j < mp_target->outerSize(); ++j)
      for (typename SparseMatrixType::InnerIterator it(*mp_target, j); it; ++it)
        (*this)(TargetRowMajor ? j : it.index(), TargetRowMajor ? it.index() : j) = it.value();
  }

  /** Destructor updating back the sparse matrix target */
  ~RandomSetter() {
    KeyType keyBitsMask = (1 << m_keyBitsOffset) - 1;
    if (!SwapStorage)  // also means the map is sorted
    {
      mp_target->setZero();
      mp_target->makeCompressed();
      mp_target->reserve(nonZeros());
      Index prevOuter = -1;
      for (Index k = 0; k < m_outerPackets; ++k) {
        const Index outerOffset = (1 << OuterPacketBits) * k;
        typename HashMapType::iterator end = m_hashmaps[k].end();
        for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it != end; ++it) {
          const Index outer = (it->first >> m_keyBitsOffset) + outerOffset;
          const Index inner = it->first & keyBitsMask;
          if (prevOuter != outer) {
            for (Index j = prevOuter + 1; j <= outer; ++j) mp_target->startVec(j);
            prevOuter = outer;
          }
          mp_target->insertBackByOuterInner(outer, inner) = it->second.value;
        }
      }
      mp_target->finalize();
    } else {
      VectorXi positions(mp_target->outerSize());
      positions.setZero();
      // pass 1
      for (Index k = 0; k < m_outerPackets; ++k) {
        typename HashMapType::iterator end = m_hashmaps[k].end();
        for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it != end; ++it) {
          const Index outer = it->first & keyBitsMask;
          ++positions[outer];
        }
      }
      // prefix sum
      StorageIndex count = 0;
      for (Index j = 0; j < mp_target->outerSize(); ++j) {
        StorageIndex tmp = positions[j];
        mp_target->outerIndexPtr()[j] = count;
        positions[j] = count;
        count += tmp;
      }
      mp_target->makeCompressed();
      mp_target->outerIndexPtr()[mp_target->outerSize()] = count;
      mp_target->resizeNonZeros(count);
      // pass 2
      for (Index k = 0; k < m_outerPackets; ++k) {
        const Index outerOffset = (1 << OuterPacketBits) * k;
        typename HashMapType::iterator end = m_hashmaps[k].end();
        for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it != end; ++it) {
          const Index inner = (it->first >> m_keyBitsOffset) + outerOffset;
          const Index outer = it->first & keyBitsMask;
          // sorted insertion
          // Note that we have to deal with at most 2^OuterPacketBits unsorted coefficients,
          // moreover those 2^OuterPacketBits coeffs are likely to be sparse, an so only a
          // small fraction of them have to be sorted, whence the following simple procedure:
          Index posStart = mp_target->outerIndexPtr()[outer];
          Index i = (positions[outer]++) - 1;
          while ((i >= posStart) && (mp_target->innerIndexPtr()[i] > inner)) {
            mp_target->valuePtr()[i + 1] = mp_target->valuePtr()[i];
            mp_target->innerIndexPtr()[i + 1] = mp_target->innerIndexPtr()[i];
            --i;
          }
          mp_target->innerIndexPtr()[i + 1] = internal::convert_index<StorageIndex>(inner);
          mp_target->valuePtr()[i + 1] = it->second.value;
        }
      }
    }
    delete[] m_hashmaps;
  }

  /** \returns a reference to the coefficient at given coordinates \a row, \a col */
  Scalar& operator()(Index row, Index col) {
    const Index outer = SetterRowMajor ? row : col;
    const Index inner = SetterRowMajor ? col : row;
    const Index outerMajor = outer >> OuterPacketBits;  // index of the packet/map
    const Index outerMinor = outer & OuterPacketMask;   // index of the inner vector in the packet
    const KeyType key = internal::convert_index<KeyType>((outerMinor << m_keyBitsOffset) | inner);
    return m_hashmaps[outerMajor][key].value;
  }

  /** \returns the number of non zero coefficients
   *
   * \note According to the underlying map/hash_map implementation,
   * this function might be quite expensive.
   */
  Index nonZeros() const {
    Index nz = 0;
    for (Index k = 0; k < m_outerPackets; ++k) nz += static_cast<Index>(m_hashmaps[k].size());
    return nz;
  }

 protected:
  HashMapType* m_hashmaps;
  SparseMatrixType* mp_target;
  Index m_outerPackets;
  unsigned char m_keyBitsOffset;
};

}  // end namespace Eigen

#endif  // EIGEN_RANDOMSETTER_H
