/*
 *
 * Copyright (c) 2003 Kresimir Fresl, Toon Knapen and Karl Meerbergen
 *
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 *
 * KF author acknowledges the support of the Faculty of Civil Engineering,
 * University of Zagreb, Croatia.
 *
 */

#ifndef BOOST_NUMERIC_BINDINGS_TRAITS_SPARSE_TRAITS_H
#define BOOST_NUMERIC_BINDINGS_TRAITS_SPARSE_TRAITS_H

#include <boost/numeric/bindings/traits/config.hpp>

#ifndef BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS

#include <boost/numeric/bindings/traits/traits.hpp>

namespace boost { namespace numeric { namespace bindings { namespace traits {

  /// There is no default implementation since there is no reasonable default.
  /// Most matrix libraries provide totally different functions.

  /// Auxiliary traits class to reduce the number of specializations.
  template <typename MIdentifier, typename MType>
  struct sparse_matrix_detail_traits {
    typedef MIdentifier identifier_type;
    typedef MType       matrix_type;
  };

  /// sparse_matrix_traits<> generic version:
  template <typename M>
  struct sparse_matrix_traits
    : sparse_matrix_detail_traits <typename boost::remove_const<M>::type, M>
  {
    // typedefs:
    //   matrix_structure
    //   storage_format
    //   ordering_type
    //   value_type
    //   value_pointer
    //   index_pointer
    // enum (or static size_t const):
    //   index_base
    // static functions:
    //   index_pointer index1_storage()
    //     - compressed column: array of column start locations
    //     - compressed row: array of row start locations
    //     - coordinate, column major: column indices of nonzeros
    //     - coordinate, row major: row indices of nonzeros
    //   index_pointer index2_storage()
    //     - compressed column: array of row indices of nonzeros
    //     - compressed row: array of column indices of nonzeros
    //     - coordinate, column major: row indices of nonzeros
    //     - coordinate, row major: column indices of nonzeros
    //   value_pointer value_storage()
    //     - array of nonzeros
    //   std::ptrdiff_t num_rows()
    //   std::ptrdiff_t num_columns()
    //   std::ptrdiff_t num_nonzeros()
  };


  // storage format tags
  struct compressed_t {};
  struct coordinate_t {};


  ///////////////////////////
  //
  // free accessor functions
  //
  ///////////////////////////

  template <typename M>
  inline
  typename sparse_matrix_traits<M>::index_pointer
  spmatrix_index1_storage (M& m) {
    return sparse_matrix_traits<M>::index1_storage (m);
  }
  template <typename M>
  inline
  typename sparse_matrix_traits<M>::index_pointer
  spmatrix_index2_storage (M& m) {
    return sparse_matrix_traits<M>::index2_storage (m);
  }

  template <typename M>
  inline
  typename sparse_matrix_traits<M>::value_pointer
  spmatrix_value_storage (M& m) {
    return sparse_matrix_traits<M>::value_storage (m);
  }

  template <typename M>
  inline
  std::ptrdiff_t spmatrix_num_rows (M& m) { return sparse_matrix_traits<M>::num_rows (m); }
  template <typename M>
  inline
  std::ptrdiff_t spmatrix_num_columns (M& m) { return sparse_matrix_traits<M>::num_columns (m); }

  template <typename M>
  inline
  std::ptrdiff_t spmatrix_num_nonzeros (M& m) {
    return sparse_matrix_traits<M>::num_nonzeros (m);
  }

  // Retain for older codes

  template <typename M>
  inline
  std::ptrdiff_t spmatrix_size1 (M& m) { return sparse_matrix_traits<M>::num_rows (m); }
  template <typename M>
  inline
  std::ptrdiff_t spmatrix_size2 (M& m) { return sparse_matrix_traits<M>::num_columns (m); }

}}}}

#else // BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS

#error with your compiler sparse matrices cannot be used in bindings

#endif // BOOST_NUMERIC_BINDINGS_POOR_MANS_TRAITS

#endif // BOOST_NUMERIC_BINDINGS_TRAITS_SPARSE_TRAITS_H
