/*
 *
 * 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_ARRAY_IMPL_HPP
#define BOOST_NUMERIC_BINDINGS_TRAITS_DETAIL_ARRAY_IMPL_HPP

/*
 very simple dynamic array class which is used in `higher level'
 bindings functions for pivot and work arrays

 Namely, there are (at least) two versions of all bindings functions
 where called LAPACK function expects work and/or pivot array, e.g.

      `lower' level (user should provide work and pivot arrays):
           int sysv (SymmA& a, IVec& i, MatrB& b, Work& w);

      `higher' level (with `internal' work and pivot arrays):
           int sysv (SymmA& a, MatrB& b);

 Probably you ask why I didn't use std::vector. There are two reasons.
 First is efficiency -- std::vector's constructor initialises vector
 elements. Second is consistency. LAPACK functions use `info' parameter
 as an error indicator. On the other hand, std::vector's allocator can
 throw an exception if memory allocation fails. detail::array's
 constructor uses `new (nothrow)' which returns 0 if allocation fails.
 So I can check whether array::storage == 0 and return appropriate error
 in `info'.
 */

#include <new>
#include <boost/noncopyable.hpp>

namespace boost { namespace numeric { namespace bindings {

  namespace traits { namespace detail {

    template <typename T>
    class array : private noncopyable {
    public:
      typedef std::ptrdiff_t size_type ;

      array (size_type n) {
        stg = new (std::nothrow) T[n];
        sz = (stg != 0) ? n : 0;
      }
      ~array() { delete[] stg; }

      size_type size() const { return sz; }
      bool valid() const { return stg != 0; }
      void resize (int n) {
        delete[] stg;
        stg = new (std::nothrow) T[n];
        sz = (stg != 0) ? n : 0;
      }

      T* storage() { return stg; }
      T const* storage() const { return stg; }

      T& operator[] (int i) { return stg[i]; }
      T const& operator[] (int i) const { return stg[i]; }

    private:
      size_type sz;
      T* stg;
    };

  }}

}}}

#endif
