1 // 2 // Copyright (c) 2003 Kresimir Fresl 3 // Copyright (c) 2009 Rutger ter Borg 4 // 5 // Distributed under the Boost Software License, Version 1.0. 6 // (See accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 // 9 10 #ifndef BOOST_NUMERIC_BINDINGS_DETAIL_ARRAY_HPP 11 #define BOOST_NUMERIC_BINDINGS_DETAIL_ARRAY_HPP 12 13 #include <new> 14 #include <boost/noncopyable.hpp> 15 #include <boost/numeric/bindings/detail/adaptor.hpp> 16 17 18 /* 19 very simple dynamic array class which is used in `higher level' 20 bindings functions for pivot and work arrays 21 22 Namely, there are (at least) two versions of all bindings functions 23 where called LAPACK function expects work and/or pivot array, e.g. 24 25 `lower' level (user should provide work and pivot arrays): 26 int sysv (SymmA& a, IVec& i, MatrB& b, Work& w); 27 28 `higher' level (with `internal' work and pivot arrays): 29 int sysv (SymmA& a, MatrB& b); 30 31 Probably you ask why I didn't use std::vector. There are two reasons. 32 First is efficiency -- std::vector's constructor initialises vector 33 elements. Second is consistency. LAPACK functions use `info' parameter 34 as an error indicator. On the other hand, std::vector's allocator can 35 throw an exception if memory allocation fails. detail::array's 36 constructor uses `new (nothrow)' which returns 0 if allocation fails. 37 So I can check whether array::storage == 0 and return appropriate error 38 in `info'.*/ 39 40 namespace boost { 41 namespace numeric { 42 namespace bindings { 43 namespace detail { 44 45 template <typename T> 46 class array : private noncopyable { 47 public: 48 typedef std::ptrdiff_t size_type ; 49 array(size_type n)50 array (size_type n) { 51 stg = new (std::nothrow) T[n]; 52 sz = (stg != nullptr) ? n : 0; 53 } 54 ~array()55 ~array() { 56 delete[] stg; 57 } 58 size() const59 size_type size() const { 60 return sz; 61 } 62 valid() const63 bool valid() const { 64 return stg != 0; 65 } 66 resize(int n)67 void resize (int n) { 68 delete[] stg; 69 stg = new (std::nothrow) T[n]; 70 sz = (stg != 0) ? n : 0; 71 } 72 storage()73 T* storage() { 74 return stg; 75 } 76 storage() const77 T const* storage() const { 78 return stg; 79 } 80 operator [](int i)81 T& operator[] (int i) { 82 return stg[i]; 83 } 84 operator [](int i) const85 T const& operator[] (int i) const { 86 return stg[i]; 87 } 88 89 private: 90 size_type sz; 91 T* stg; 92 }; 93 94 95 template< typename T, typename Id, typename Enable > 96 struct adaptor< array< T >, Id, Enable > { 97 98 typedef typename copy_const< Id, T >::type value_type; 99 typedef mpl::map< 100 mpl::pair< tag::value_type, value_type >, 101 mpl::pair< tag::entity, tag::vector >, 102 mpl::pair< tag::size_type<1>, std::ptrdiff_t >, 103 mpl::pair< tag::data_structure, tag::linear_array >, 104 mpl::pair< tag::stride_type<1>, tag::contiguous > 105 > property_map; 106 size1boost::numeric::bindings::detail::adaptor107 static std::ptrdiff_t size1( const Id& t ) { 108 return t.size(); 109 } 110 begin_valueboost::numeric::bindings::detail::adaptor111 static value_type* begin_value( Id& t ) { 112 return t.storage(); 113 } 114 end_valueboost::numeric::bindings::detail::adaptor115 static value_type* end_value( Id& t ) { 116 return t.storage() + t.size(); 117 } 118 119 }; 120 121 122 } // namespace detail 123 } // namespace bindings 124 } // namespace numeric 125 } // namespace boost 126 127 #endif 128