1 /*
2 * Copyright (c) 2007, Michael Lehn
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1) Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2) Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * 3) Neither the name of the FLENS development group nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifndef FLENS_STORAGE_ARRAY_ARRAY_TCC
34 #define FLENS_STORAGE_ARRAY_ARRAY_TCC 1
35
36 #include <cassert>
37 #include <cxxblas/level1/copy.h>
38 #include <flens/storage/array/arrayview.h>
39 #include <flens/storage/array/constarrayview.h>
40
41 namespace flens {
42
43 template <typename T, typename I, typename A>
44 Array<T, I, A>::Array()
45 : _data(0), _length(0), _firstIndex(1)
46 {
47 }
48
49 template <typename T, typename I, typename A>
50 Array<T, I, A>::Array(IndexType length, IndexType firstIndex,
51 const ElementType &value, const Allocator &allocator)
52 : _data(0), _allocator(allocator), _length(length), _firstIndex(firstIndex)
53 {
54 ASSERT(_length>=0);
55
56 _allocate(value);
57 }
58
59 template <typename T, typename I, typename A>
60 Array<T, I, A>::Array(const Array &rhs)
61 : _data(0), _allocator(rhs.allocator()),
62 _length(rhs.length()), _firstIndex(rhs.firstIndex())
63 {
64 ASSERT(_length>=0);
65
66 if (length()>0) {
67 _allocate();
68 cxxblas::copy(length(), rhs.data(), rhs.stride(), data(), stride());
69 }
70 }
71
72 template <typename T, typename I, typename A>
73 template <typename RHS>
74 Array<T, I, A>::Array(const RHS &rhs)
75 : _data(0), _allocator(rhs.allocator()),
76 _length(rhs.length()), _firstIndex(rhs.firstIndex())
77 {
78 if (length()>0) {
79 _allocate();
80 cxxblas::copy(length(), rhs.data(), rhs.stride(), data(), stride());
81 }
82 }
83
84 template <typename T, typename I, typename A>
85 Array<T, I, A>::~Array()
86 {
87 _release();
88 }
89
90 //-- operators -----------------------------------------------------------------
91
92 template <typename T, typename I, typename A>
93 const typename Array<T, I, A>::ElementType &
94 Array<T, I, A>::operator()(IndexType index) const
95 {
96 ASSERT(index>=firstIndex());
97 ASSERT(index<=lastIndex());
98 return _data[index];
99 }
100
101 template <typename T, typename I, typename A>
102 typename Array<T, I, A>::ElementType &
103 Array<T, I, A>::operator()(IndexType index)
104 {
105 ASSERT(index>=firstIndex());
106 ASSERT(index<=lastIndex());
107 return _data[index];
108 }
109
110 template <typename T, typename I, typename A>
111 typename Array<T, I, A>::IndexType
112 Array<T, I, A>::firstIndex() const
113 {
114 return _firstIndex;
115 }
116
117 template <typename T, typename I, typename A>
118 typename Array<T, I, A>::IndexType
119 Array<T, I, A>::lastIndex() const
120 {
121 return _firstIndex+_length-IndexType(1);
122 }
123
124 template <typename T, typename I, typename A>
125 typename Array<T, I, A>::IndexType
126 Array<T, I, A>::length() const
127 {
128 return _length;
129 }
130
131 template <typename T, typename I, typename A>
132 typename Array<T, I, A>::IndexType
133 Array<T, I, A>::stride() const
134 {
135 return IndexType(1);
136 }
137
138 template <typename T, typename I, typename A>
139 const typename Array<T, I, A>::ElementType *
140 Array<T, I, A>::data() const
141 {
142 return &_data[_firstIndex];
143 }
144
145 template <typename T, typename I, typename A>
146 typename Array<T, I, A>::ElementType *
147 Array<T, I, A>::data()
148 {
149 return &_data[_firstIndex];
150 }
151
152 template <typename T, typename I, typename A>
153 const typename Array<T, I, A>::Allocator &
154 Array<T, I, A>::allocator() const
155 {
156 return _allocator;
157 }
158
159 template <typename T, typename I, typename A>
160 bool
161 Array<T, I, A>::resize(IndexType length, IndexType firstIndex,
162 const ElementType &value)
163 {
164 if (length!=_length) {
165 _release();
166 _length = length;
167 _firstIndex = firstIndex;
168 _allocate(value);
169 return true;
170 }
171 changeIndexBase(firstIndex);
172 return false;
173 }
174
175 template <typename T, typename I, typename A>
176 template <typename ARRAY>
177 bool
178 Array<T, I, A>::resize(const ARRAY &rhs, const ElementType &value)
179 {
180 return resize(rhs.length(), rhs.firstIndex(), value);
181 }
182
183 template <typename T, typename I, typename A>
184 bool
185 Array<T, I, A>::fill(const ElementType &value)
186 {
187 std::fill_n(data(), length(), value);
188 return true;
189 }
190
191 template <typename T, typename I, typename A>
192 void
193 Array<T, I, A>::changeIndexBase(IndexType firstIndex)
194 {
195 _data += _firstIndex - firstIndex;
196 _firstIndex = firstIndex;
197 }
198
199 template <typename T, typename I, typename A>
200 const typename Array<T, I, A>::ConstView
201 Array<T, I, A>::view(IndexType from, IndexType to,
202 IndexType stride, IndexType firstViewIndex) const
203 {
204 const IndexType length = (to-from)/stride+1;
205
206 # ifndef NDEBUG
207 // prevent an out-of-bound assertion in case a view is empty anyway
208 const ElementType *data = (length!=0) ? &operator()(from) : 0;
209
210 if (length!=0) {
211 ASSERT(firstIndex()<=from);
212 ASSERT(lastIndex()>=to);
213 ASSERT(from<=to);
214 }
215 ASSERT(stride>=1);
216 # else
217 const ElementType *data = &operator()(from);
218 # endif
219
220 return ConstView(length, data, stride, firstViewIndex, allocator());
221 }
222
223 template <typename T, typename I, typename A>
224 typename Array<T, I, A>::View
225 Array<T, I, A>::view(IndexType from, IndexType to,
226 IndexType stride, IndexType firstViewIndex)
227 {
228 const IndexType length = (to-from)/stride+1;
229
230 # ifndef NDEBUG
231 // prevent an out-of-bound assertion in case a view is empty anyway
232 ElementType *data = (length!=0) ? &operator()(from) : 0;
233
234 if (length!=0) {
235 ASSERT(firstIndex()<=from);
236 ASSERT(lastIndex()>=to);
237 ASSERT(from<=to);
238 }
239 ASSERT(stride>=1);
240 # else
241 ElementType *data = &operator()(from);
242 # endif
243
244 return View(length, data, stride, firstViewIndex, allocator());
245 }
246
247 //-- private methods -----------------------------------------------------------
248
249 template <typename T, typename I, typename A>
250 void
251 Array<T, I, A>::_raw_allocate()
252 {
253 ASSERT(!_data);
254 ASSERT(length()>=0);
255
256 if (length()>0) {
257 _data = _allocator.allocate(_length) - _firstIndex;
258 ASSERT(_data+_firstIndex);
259 ASSERT(_data);
260 }
261 }
262
263 template <typename T, typename I, typename A>
264 void
265 Array<T, I, A>::_allocate(const ElementType &value)
266 {
267 _raw_allocate();
268 for (IndexType i=firstIndex(); i<=lastIndex(); ++i) {
269 _allocator.construct(_data+i, value);
270 }
271 }
272
273 template <typename T, typename I, typename A>
274 void
275 Array<T, I, A>::_release()
276 {
277 if (_data) {
278 for (IndexType i=firstIndex(); i<=lastIndex(); ++i) {
279 _allocator.destroy(_data+i);
280 }
281 _allocator.deallocate(data(), _length);
282 _data = 0;
283 }
284 ASSERT(_data==0);
285 }
286
287 } // namespace flens
288
289 #endif // FLENS_STORAGE_ARRAY_ARRAY_TCC
2 * Copyright (c) 2007, Michael Lehn
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1) Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2) Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * 3) Neither the name of the FLENS development group nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifndef FLENS_STORAGE_ARRAY_ARRAY_TCC
34 #define FLENS_STORAGE_ARRAY_ARRAY_TCC 1
35
36 #include <cassert>
37 #include <cxxblas/level1/copy.h>
38 #include <flens/storage/array/arrayview.h>
39 #include <flens/storage/array/constarrayview.h>
40
41 namespace flens {
42
43 template <typename T, typename I, typename A>
44 Array<T, I, A>::Array()
45 : _data(0), _length(0), _firstIndex(1)
46 {
47 }
48
49 template <typename T, typename I, typename A>
50 Array<T, I, A>::Array(IndexType length, IndexType firstIndex,
51 const ElementType &value, const Allocator &allocator)
52 : _data(0), _allocator(allocator), _length(length), _firstIndex(firstIndex)
53 {
54 ASSERT(_length>=0);
55
56 _allocate(value);
57 }
58
59 template <typename T, typename I, typename A>
60 Array<T, I, A>::Array(const Array &rhs)
61 : _data(0), _allocator(rhs.allocator()),
62 _length(rhs.length()), _firstIndex(rhs.firstIndex())
63 {
64 ASSERT(_length>=0);
65
66 if (length()>0) {
67 _allocate();
68 cxxblas::copy(length(), rhs.data(), rhs.stride(), data(), stride());
69 }
70 }
71
72 template <typename T, typename I, typename A>
73 template <typename RHS>
74 Array<T, I, A>::Array(const RHS &rhs)
75 : _data(0), _allocator(rhs.allocator()),
76 _length(rhs.length()), _firstIndex(rhs.firstIndex())
77 {
78 if (length()>0) {
79 _allocate();
80 cxxblas::copy(length(), rhs.data(), rhs.stride(), data(), stride());
81 }
82 }
83
84 template <typename T, typename I, typename A>
85 Array<T, I, A>::~Array()
86 {
87 _release();
88 }
89
90 //-- operators -----------------------------------------------------------------
91
92 template <typename T, typename I, typename A>
93 const typename Array<T, I, A>::ElementType &
94 Array<T, I, A>::operator()(IndexType index) const
95 {
96 ASSERT(index>=firstIndex());
97 ASSERT(index<=lastIndex());
98 return _data[index];
99 }
100
101 template <typename T, typename I, typename A>
102 typename Array<T, I, A>::ElementType &
103 Array<T, I, A>::operator()(IndexType index)
104 {
105 ASSERT(index>=firstIndex());
106 ASSERT(index<=lastIndex());
107 return _data[index];
108 }
109
110 template <typename T, typename I, typename A>
111 typename Array<T, I, A>::IndexType
112 Array<T, I, A>::firstIndex() const
113 {
114 return _firstIndex;
115 }
116
117 template <typename T, typename I, typename A>
118 typename Array<T, I, A>::IndexType
119 Array<T, I, A>::lastIndex() const
120 {
121 return _firstIndex+_length-IndexType(1);
122 }
123
124 template <typename T, typename I, typename A>
125 typename Array<T, I, A>::IndexType
126 Array<T, I, A>::length() const
127 {
128 return _length;
129 }
130
131 template <typename T, typename I, typename A>
132 typename Array<T, I, A>::IndexType
133 Array<T, I, A>::stride() const
134 {
135 return IndexType(1);
136 }
137
138 template <typename T, typename I, typename A>
139 const typename Array<T, I, A>::ElementType *
140 Array<T, I, A>::data() const
141 {
142 return &_data[_firstIndex];
143 }
144
145 template <typename T, typename I, typename A>
146 typename Array<T, I, A>::ElementType *
147 Array<T, I, A>::data()
148 {
149 return &_data[_firstIndex];
150 }
151
152 template <typename T, typename I, typename A>
153 const typename Array<T, I, A>::Allocator &
154 Array<T, I, A>::allocator() const
155 {
156 return _allocator;
157 }
158
159 template <typename T, typename I, typename A>
160 bool
161 Array<T, I, A>::resize(IndexType length, IndexType firstIndex,
162 const ElementType &value)
163 {
164 if (length!=_length) {
165 _release();
166 _length = length;
167 _firstIndex = firstIndex;
168 _allocate(value);
169 return true;
170 }
171 changeIndexBase(firstIndex);
172 return false;
173 }
174
175 template <typename T, typename I, typename A>
176 template <typename ARRAY>
177 bool
178 Array<T, I, A>::resize(const ARRAY &rhs, const ElementType &value)
179 {
180 return resize(rhs.length(), rhs.firstIndex(), value);
181 }
182
183 template <typename T, typename I, typename A>
184 bool
185 Array<T, I, A>::fill(const ElementType &value)
186 {
187 std::fill_n(data(), length(), value);
188 return true;
189 }
190
191 template <typename T, typename I, typename A>
192 void
193 Array<T, I, A>::changeIndexBase(IndexType firstIndex)
194 {
195 _data += _firstIndex - firstIndex;
196 _firstIndex = firstIndex;
197 }
198
199 template <typename T, typename I, typename A>
200 const typename Array<T, I, A>::ConstView
201 Array<T, I, A>::view(IndexType from, IndexType to,
202 IndexType stride, IndexType firstViewIndex) const
203 {
204 const IndexType length = (to-from)/stride+1;
205
206 # ifndef NDEBUG
207 // prevent an out-of-bound assertion in case a view is empty anyway
208 const ElementType *data = (length!=0) ? &operator()(from) : 0;
209
210 if (length!=0) {
211 ASSERT(firstIndex()<=from);
212 ASSERT(lastIndex()>=to);
213 ASSERT(from<=to);
214 }
215 ASSERT(stride>=1);
216 # else
217 const ElementType *data = &operator()(from);
218 # endif
219
220 return ConstView(length, data, stride, firstViewIndex, allocator());
221 }
222
223 template <typename T, typename I, typename A>
224 typename Array<T, I, A>::View
225 Array<T, I, A>::view(IndexType from, IndexType to,
226 IndexType stride, IndexType firstViewIndex)
227 {
228 const IndexType length = (to-from)/stride+1;
229
230 # ifndef NDEBUG
231 // prevent an out-of-bound assertion in case a view is empty anyway
232 ElementType *data = (length!=0) ? &operator()(from) : 0;
233
234 if (length!=0) {
235 ASSERT(firstIndex()<=from);
236 ASSERT(lastIndex()>=to);
237 ASSERT(from<=to);
238 }
239 ASSERT(stride>=1);
240 # else
241 ElementType *data = &operator()(from);
242 # endif
243
244 return View(length, data, stride, firstViewIndex, allocator());
245 }
246
247 //-- private methods -----------------------------------------------------------
248
249 template <typename T, typename I, typename A>
250 void
251 Array<T, I, A>::_raw_allocate()
252 {
253 ASSERT(!_data);
254 ASSERT(length()>=0);
255
256 if (length()>0) {
257 _data = _allocator.allocate(_length) - _firstIndex;
258 ASSERT(_data+_firstIndex);
259 ASSERT(_data);
260 }
261 }
262
263 template <typename T, typename I, typename A>
264 void
265 Array<T, I, A>::_allocate(const ElementType &value)
266 {
267 _raw_allocate();
268 for (IndexType i=firstIndex(); i<=lastIndex(); ++i) {
269 _allocator.construct(_data+i, value);
270 }
271 }
272
273 template <typename T, typename I, typename A>
274 void
275 Array<T, I, A>::_release()
276 {
277 if (_data) {
278 for (IndexType i=firstIndex(); i<=lastIndex(); ++i) {
279 _allocator.destroy(_data+i);
280 }
281 _allocator.deallocate(data(), _length);
282 _data = 0;
283 }
284 ASSERT(_data==0);
285 }
286
287 } // namespace flens
288
289 #endif // FLENS_STORAGE_ARRAY_ARRAY_TCC