-
Notifications
You must be signed in to change notification settings - Fork 298
/
array.hpp
127 lines (97 loc) · 3.04 KB
/
array.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//
// Copyright (c) 2003 Kresimir Fresl
// Copyright (c) 2009 Rutger ter Borg
//
// 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)
//
#ifndef BOOST_NUMERIC_BINDINGS_DETAIL_ARRAY_HPP
#define BOOST_NUMERIC_BINDINGS_DETAIL_ARRAY_HPP
#include <new>
#include <boost/noncopyable.hpp>
#include <Core/Utils/numeric/bindings/detail/adaptor.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'.*/
namespace boost {
namespace numeric {
namespace bindings {
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;
};
template< typename T, typename Id, typename Enable >
struct adaptor< array< T >, Id, Enable > {
typedef typename copy_const< Id, T >::type value_type;
typedef mpl::map<
mpl::pair< tag::value_type, value_type >,
mpl::pair< tag::entity, tag::vector >,
mpl::pair< tag::size_type<1>, std::ptrdiff_t >,
mpl::pair< tag::data_structure, tag::linear_array >,
mpl::pair< tag::stride_type<1>, tag::contiguous >
> property_map;
static std::ptrdiff_t size1( const Id& t ) {
return t.size();
}
static value_type* begin_value( Id& t ) {
return t.storage();
}
static value_type* end_value( Id& t ) {
return t.storage() + t.size();
}
};
} // namespace detail
} // namespace bindings
} // namespace numeric
} // namespace boost
#endif