// Copyright (c) 2013-2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
// Copyright (c) 2013-2018 Centre national de la recherche scientifique (CNRS)
// Copyright (c) 2018 Simons Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You may obtain a copy of the License at
//     https://www.gnu.org/licenses/gpl-3.0.txt
//
// Authors: Olivier Parcollet, Nils Wentzell

#ifndef TRIQS_ARRAYS_INDEXMAP_COMMON_H
#define TRIQS_ARRAYS_INDEXMAP_COMMON_H
#include "../impl/common.hpp"
#include <triqs/utility/mini_vector.hpp>
//#include "../impl/tuple_tools.hpp"
#include <iostream>

namespace boost {
  namespace serialization {
    class access;
  }
} // namespace boost
namespace triqs {
  namespace arrays {
    namespace Tag {
      struct indexmap {};
    } // namespace Tag
  }   // namespace arrays
} // namespace triqs

namespace triqs {
  namespace arrays {
    using utility::mini_vector;

    template <int Rank> using shape_t = mini_vector<long, Rank>;
    //template <typename ... Args> shape_t<sizeof...(Args)> make_shape(Args&&... args) { return {args...};}

    // make_shape
    template <typename... T> mini_vector<size_t, sizeof...(T)> make_shape(T... args) { return mini_vector<size_t, sizeof...(T)>(args...); }

    namespace indexmaps {

      // to be specialized for all IndexMap types.
      template <typename IndexMap, typename... Args> struct slicer;

      /// Returns whether the 2 indexMaps are compatible with A op B (op : = , +, etc...)
      template <typename IndexMap1, typename IndexMap2> bool compatible_for_binary_ops(const IndexMap1 &, const IndexMap2 &);

      // The generator of indices for an index domain.
      template <typename Domain, typename Parameter> class indices_generator;

      /**
  * Is a raw copy possible between 2 arrays with these indexMaps ?
  * They have to have the same ordering, and be contiguous typically.
  */
      template <typename IndexMap1, typename IndexMap2> bool raw_copy_possible(const IndexMap1 &, const IndexMap2 &);

      /**
  * Metafunction.
  * Given an IndexMapIterator and an IndexMap,
  * ::type should be the iterator of IndexMap which traverses
  * the indices in the same order as IndexMapIterator.
  * Example :
  *  - IndexMapIterator is a parallelepipedon_iterator < SomeParallelepipedon, So
  meIterationOrder>
  *  - IndexMap is AnotherParallelepipedon (e.g. with a different memory storage)
  .
  *  - type is then parallelepipedon_iterator < AnotherParallelepipedon, SomeIter
  ationOrder>
  *  Application example :
  *     A = B with A, B in different order in memory.
  *     One takes the optimized iterator on A, this defines the order of indices
  traversal,
  *     and use indexmap_iterator_adapter to deduce the iterator on B that traver
  se the indices in the same way.
  */
      //template <typename IndexMapIterator, typename IndexMap>
      // struct indexmap_iterator_adapter;

    } // namespace indexmaps
  }   // namespace arrays
} // namespace triqs
#endif
