/*
 *
 * Copyright (c) Kresimir Fresl 2003
 *
 * 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)
 *
 * Author acknowledges the support of the Faculty of Civil Engineering,
 * University of Zagreb, Croatia.
 *
 */

#ifndef BOOST_NUMERIC_BINDINGS_TRAITS_DETAIL_UTILS_HPP
#define BOOST_NUMERIC_BINDINGS_TRAITS_DETAIL_UTILS_HPP

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

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

  namespace detail {

    // complex array => real & imaginary arrays
    template <typename CIt, typename RIt>
    void disentangle (CIt c, CIt c_end, RIt rr, RIt ri) {
      for (; c != c_end; ++c, ++rr, ++ri) {
        *rr = traits::real (*c); 
        *ri = traits::imag (*c); 
      }
    }
    // real & imaginary arrays => complex array
    template <typename RIt, typename CIt>
    void interlace (RIt r, RIt r_end, RIt ri, CIt c) {
      typedef typename std::iterator_traits<CIt>::value_type cmplx_t;
#ifdef BOOST_NUMERIC_BINDINGS_BY_THE_BOOK
      for (; r != r_end; ++r, ++ri, ++c)
        *c = cmplx_t (*r, *ri);
#else
      typedef typename type_traits<cmplx_t>::real_type real_t;
      real_t *cp = reinterpret_cast<real_t*> (&*c);
      for (; r != r_end; ++r, ++ri) {
        *cp = *r; ++cp;
        *cp = *ri; ++cp;
      }
#endif
    }

    // converts real/complex to std::ptrdiff_t
    inline std::ptrdiff_t to_int (float f) { return static_cast<std::ptrdiff_t> (f); }
    inline std::ptrdiff_t to_int (double d) { return static_cast<std::ptrdiff_t> (d); }
    inline std::ptrdiff_t to_int (traits::complex_f const& cf) {
      return static_cast<std::ptrdiff_t> (traits::real (cf));
    }
    inline std::ptrdiff_t to_int (traits::complex_d const& cd) {
      return static_cast<std::ptrdiff_t> (traits::real (cd));
    }

  }

}}}}

#endif
