-
Notifications
You must be signed in to change notification settings - Fork 36
Expand file tree
/
Copy pathCore.h
More file actions
274 lines (225 loc) · 7.9 KB
/
Copy pathCore.h
File metadata and controls
274 lines (225 loc) · 7.9 KB
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
// -*- c++ -*-
/*
* Copyright (c) 2010-2012, Jim Bosch
* All rights reserved.
*
* ndarray is distributed under a simple BSD-like license;
* see the LICENSE file that should be present in the root
* of the source distribution, or alternately available at:
* https://github.com/ndarray/ndarray
*/
#ifndef NDARRAY_DETAIL_Core_h_INCLUDED
#define NDARRAY_DETAIL_Core_h_INCLUDED
/**
* @file ndarray/detail/Core.h
*
* @brief Definitions for Core.
*/
#include <boost/intrusive_ptr.hpp>
#include <boost/mpl/int.hpp>
#include "ndarray/Vector.h"
#include "ndarray/Manager.h"
namespace ndarray {
namespace detail {
/**
* @internal
* @brief Internal data class for Array.
*
* @ingroup ndarrayInternalGroup
*
* Core holds the shape, stride, and ownership data for an Array.
* A Core maintains its own reference count and can be shared
* by multiple Arrays via a const boost::intrusive pointer.
*
* Because a Core with N dimensions inherits from
* a Core with N-1 dimensions, subarrays can share a Core with
* their parants.
*
* Core objects are never const; even an Array with a const
* template parameter holds a Core with a non-const template
* parameter.
*/
template <int N>
class Core : public Core<N-1> {
public:
typedef boost::mpl::int_<N> ND; ///< number of dimensions
typedef Core<N-1> Super; ///< base class
typedef boost::intrusive_ptr<Core> Ptr; ///< intrusive_ptr to Core
typedef boost::intrusive_ptr<Core const> ConstPtr; ///< const intrusive_ptr to Core
/// @brief Create a Core::Ptr with the given shape, strides, and manager.
template <int M>
static Ptr create(
Vector<Size,M> const & shape,
Vector<Offset,M> const & strides,
Manager::Ptr const & manager = Manager::Ptr()
) {
return Ptr(new Core(shape, strides, manager), false);
}
/// @brief Create a Core::Ptr with the given shape and manager with contiguous strides.
template <int M>
static Ptr create(
Vector<Size,M> const & shape,
DataOrderEnum order,
Manager::Ptr const & manager = Manager::Ptr()
) {
if (order == ROW_MAJOR) {
return Ptr(new Core(shape, manager), false);
} else {
return Ptr(new Core(shape, 1, manager), false);
}
}
/// @brief Create a Core::Ptr with the given manager and zero shape and strides.
static Ptr create(
Manager::Ptr const & manager = Manager::Ptr()
) {
return Ptr(new Core(manager), false);
}
Ptr copy() const { return Ptr(new Core(*this)); }
/// @brief Return the size of the Nth dimension.
Size getSize() const { return _size; }
/// @brief Return the stride of the Nth dimension.
Offset getStride() const { return _stride; }
/// @brief Set the size of the Nth dimension.
void setSize(Size size) { _size = size; }
/// @brief Set the stride of the Nth dimension.
void setStride(Offset stride) { _stride = stride; }
/// @brief Recursively compute the offset to an element.
template <int M>
Offset computeOffset(Vector<Size,M> const & index) const {
return index[M-N] * this->getStride() + Super::computeOffset(index);
}
/// @brief Recursively fill a shape vector.
template <int M>
void fillShape(Vector<Size,M> & shape) const {
shape[M-N] = this->getSize();
Super::fillShape(shape);
}
/// @brief Recursively fill a strides vector.
template <int M>
void fillStrides(Vector<Offset,M> & strides) const {
strides[M-N] = this->getStride();
Super::fillStrides(strides);
}
/// @brief Recursively determine the total number of elements.
Size getNumElements() const {
return getSize() * Super::getNumElements();
}
protected:
// Explicit strides
template <int M>
Core (
Vector<Size,M> const & shape,
Vector<Offset,M> const & strides,
Manager::Ptr const & manager
) : Super(shape, strides, manager), _size(shape[M-N]), _stride(strides[M-N]) {}
// Row-major strides
template <int M>
Core (
Vector<Size,M> const & shape,
Manager::Ptr const & manager
) : Super(shape, manager), _size(shape[M-N]), _stride(Super::getStride() * Super::getSize()) {}
// Column-major strides
template <int M>
Core (
Vector<Size,M> const & shape,
Offset stride,
Manager::Ptr const & manager
) : Super(shape, stride * shape[M-N], manager), _size(shape[M-N]), _stride(stride) {}
// Zero shape and strides
Core (
Manager::Ptr const & manager
) : Super(manager), _size(0), _stride(0) {}
Core(Core const & other) : Super(other), _size(other._size), _stride(other._stride) {}
private:
Size _size;
Offset _stride;
};
/**
* @internal
* @brief Internal data class for Array, 0-D specialization.
*
* @ingroup ndarrayInternalGroup
*
* The 0-D Core has size and stride == 1 and holds the reference
* count and manager; it is the base class for all other Cores.
*/
template <>
class Core<0> {
public:
typedef boost::mpl::int_<0> ND;
typedef boost::intrusive_ptr<Core> Ptr;
typedef boost::intrusive_ptr<Core const> ConstPtr;
friend inline void intrusive_ptr_add_ref(Core const * core) {
++core->_rc;
}
friend inline void intrusive_ptr_release(Core const * core) {
if ((--core->_rc)==0) delete core;
}
Ptr copy() const { return Ptr(new Core(*this)); }
Size getSize() const { return 1; }
Offset getStride() const { return 1; }
/// @brief Recursively compute the offset to an element.
template <int M>
Offset computeOffset(Vector<Size,M> const & index) const { return 0; }
/// @brief Return the Manager that determines the lifetime of the array data.
Manager::Ptr getManager() const { return _manager; }
/// @brief Set the Manager that determines the lifetime of the array data.
void setManager(Manager::Ptr const & manager) { _manager = manager; }
/// @brief Recursively fill a shape vector.
template <int M>
void fillShape(Vector<Size,M> const & shape) const {}
/// @brief Recursively fill a strides vector.
template <int M>
void fillStrides(Vector<Offset,M> const & strides) const {}
/// @brief Recursively determine the total number of elements.
Size getNumElements() const { return 1; }
/// @brief Return the reference count (for debugging purposes).
int getRC() const { return _rc; }
/// @brief Return true if the Core and Manager reference counts are 1 and the manager is unique.
bool isUnique() const { return (_rc == 1) && (_manager->getRC() == 1) && _manager->isUnique(); }
protected:
virtual ~Core() {}
template <int M>
Core(
Vector<Size,M> const & shape,
Vector<Offset,M> const & strides,
Manager::Ptr const & manager
) : _manager(manager), _rc(1) {}
template <int M>
Core(
Vector<Size,M> const & shape,
Manager::Ptr const & manager
) : _manager(manager), _rc(1) {}
template <int M>
Core(
Vector<Size,M> const & shape,
Offset stride,
Manager::Ptr const & manager
) : _manager(manager), _rc(1) {}
Core(
Manager::Ptr const & manager
) : _manager(manager), _rc(1) {}
Core(Core const & other) : _manager(other._manager), _rc(1) {}
private:
Manager::Ptr _manager;
mutable int _rc;
};
/**
* @internal @brief Cast a Core reference to a particular dimension.
*
* @ingroup ndarrayInternalGroup
*/
template <int P, int N>
inline Core<N-P> const &
getDimension(Core<N> const & core) { return core; }
/**
* @internal @brief Cast a Core smart pointer to a particular dimension.
*
* @ingroup ndarrayInternalGroup
*/
template <int P, int N>
inline typename Core<N-P>::Ptr
getDimension(typename Core<N>::Ptr const & core) { return core; }
} // namespace detail
} // namespace ndarray
#endif // !NDARRAY_DETAIL_Core_h_INCLUDED