1 |
// $Id$ |
2 |
/* |
3 |
****************************************************************************** |
4 |
* * |
5 |
* COPYRIGHT ACcESS 2004 - All Rights Reserved * |
6 |
* * |
7 |
* This software is the property of ACcESS. No part of this code * |
8 |
* may be copied in any form or by any means without the expressed written * |
9 |
* consent of ACcESS. Copying, use or modification of this software * |
10 |
* by any unauthorised person is illegal unless that person has a software * |
11 |
* license agreement with ACcESS. * |
12 |
* * |
13 |
****************************************************************************** |
14 |
*/ |
15 |
|
16 |
#if !defined escript_DataArrayView_20040323_H |
17 |
#define escript_DataArrayView_20040323_H |
18 |
|
19 |
#include "esysUtils/EsysAssert.h" |
20 |
|
21 |
#include <vector> |
22 |
#include <boost/python/numeric.hpp> |
23 |
#include <boost/python/object.hpp> |
24 |
#include <boost/shared_ptr.hpp> |
25 |
|
26 |
#include <iostream> |
27 |
|
28 |
namespace escript { |
29 |
|
30 |
/** |
31 |
\brief |
32 |
DataArrayView provides a view of data allocated externally. |
33 |
|
34 |
Description: |
35 |
DataArrayView provides a view of data allocated externally. The |
36 |
external data should provide sufficient values so that the dimensions |
37 |
specified for the view will be satisfied. The viewer can update |
38 |
values within the external data but cannot resize the external data. |
39 |
*/ |
40 |
|
41 |
class DataArrayView { |
42 |
|
43 |
friend bool operator==(const DataArrayView& left, const DataArrayView& right); |
44 |
friend bool operator!=(const DataArrayView& left, const DataArrayView& right); |
45 |
|
46 |
public: |
47 |
|
48 |
typedef std::vector<double> ValueType; |
49 |
typedef std::vector<int> ShapeType; |
50 |
typedef std::vector<std::pair<int, int> > RegionType; |
51 |
|
52 |
/** |
53 |
\brief |
54 |
Default constructor for DataArrayView. |
55 |
|
56 |
Description: |
57 |
Default constructor for DataArrayView. Creates an |
58 |
empty view with no associated data. |
59 |
*/ |
60 |
DataArrayView(); |
61 |
|
62 |
/** |
63 |
\brief |
64 |
Constructor for DataArrayView. |
65 |
|
66 |
Description: |
67 |
Constructor for DataArrayView. |
68 |
|
69 |
\param data - Input - Container holding data to be viewed. This must |
70 |
be large enough for the specified shape. |
71 |
\param viewShape - Input - The shape of the view. |
72 |
\param offset - Input - Offset into the data at which view should start. |
73 |
*/ |
74 |
DataArrayView(ValueType& data, |
75 |
const ShapeType& viewShape, |
76 |
int offset=0); |
77 |
|
78 |
/** |
79 |
\brief |
80 |
Copy constructor for DataArrayView. |
81 |
|
82 |
Description: |
83 |
Copy constructor for DataArrayView. |
84 |
|
85 |
\param other - Input - DataArrayView to copy. |
86 |
|
87 |
NOTE: The copy references the same data container. |
88 |
*/ |
89 |
DataArrayView(const DataArrayView& other); |
90 |
|
91 |
/** |
92 |
\brief |
93 |
Check if view is empty. |
94 |
*/ |
95 |
bool |
96 |
isEmpty() const; |
97 |
|
98 |
/** |
99 |
\brief |
100 |
Copy from a numarray into the data managed by DataArrayView. |
101 |
*/ |
102 |
void |
103 |
copy(const boost::python::numeric::array& value); |
104 |
|
105 |
/** |
106 |
\brief |
107 |
Copy from another DataArrayViewinto the data managed by this |
108 |
DataArrayView at the default offset. |
109 |
*/ |
110 |
void |
111 |
copy(const DataArrayView& other); |
112 |
|
113 |
/** |
114 |
\brief |
115 |
Copy from another DataArrayView into this view at the |
116 |
given offset. |
117 |
*/ |
118 |
void |
119 |
copy(ValueType::size_type offset, |
120 |
const DataArrayView& other); |
121 |
|
122 |
/** |
123 |
\brief |
124 |
Copy from another DataArrayView into this view at the |
125 |
given offsets. |
126 |
|
127 |
\param thisOffset - Input - Offset into this view's data array to copy to. |
128 |
\param other - Input - View for the data to copy. |
129 |
\param otherOffset - Input - Offset into the other view to copy data from. |
130 |
*/ |
131 |
void |
132 |
copy(ValueType::size_type thisOffset, |
133 |
const DataArrayView& other, |
134 |
ValueType::size_type otherOffset); |
135 |
|
136 |
/** |
137 |
\brief |
138 |
Copy the given single value over the entire view. |
139 |
|
140 |
\param offset - Input - Offset into this view's data array to copy to. |
141 |
\param value - Input - Value to copy. |
142 |
*/ |
143 |
void |
144 |
copy(ValueType::size_type offset, |
145 |
ValueType::value_type value); |
146 |
|
147 |
/** |
148 |
\brief |
149 |
Return this view's offset to the start of data. |
150 |
*/ |
151 |
ValueType::size_type |
152 |
getOffset() const; |
153 |
|
154 |
/** |
155 |
\brief |
156 |
Return the rank of the data. |
157 |
*/ |
158 |
int |
159 |
getRank() const; |
160 |
|
161 |
/** |
162 |
\brief |
163 |
Return the shape of the data. |
164 |
*/ |
165 |
const ShapeType& |
166 |
getShape() const; |
167 |
|
168 |
/** |
169 |
\brief |
170 |
Calculate the number of values for the given shape. |
171 |
*/ |
172 |
static int |
173 |
noValues(const ShapeType& shape); |
174 |
|
175 |
/** |
176 |
\brief |
177 |
Return the number of values for the current view. |
178 |
*/ |
179 |
int |
180 |
noValues() const; |
181 |
|
182 |
/** |
183 |
\brief |
184 |
Return true if the given shape is the same as this object's shape. |
185 |
*/ |
186 |
bool |
187 |
checkShape(const DataArrayView::ShapeType& other) const; |
188 |
|
189 |
/** |
190 |
\brief |
191 |
Return a reference to the underlying data. |
192 |
*/ |
193 |
ValueType& |
194 |
getData() const; |
195 |
|
196 |
/** |
197 |
\brief |
198 |
Return the value with the given index for the view. This takes into account |
199 |
the offset. Effectively this returns each value of the view in sequential order. |
200 |
*/ |
201 |
ValueType::reference |
202 |
getData(ValueType::size_type i) const; |
203 |
|
204 |
/** |
205 |
\brief |
206 |
Create a shape error message. Normally used when there is a shape |
207 |
mismatch. |
208 |
|
209 |
\param messagePrefix - Input - First part of the error message. |
210 |
\param other - Input - The other shape. |
211 |
*/ |
212 |
std::string |
213 |
createShapeErrorMessage(const std::string& messagePrefix, |
214 |
const DataArrayView::ShapeType& other) const; |
215 |
|
216 |
/** |
217 |
\brief |
218 |
Set the offset into the array. |
219 |
*/ |
220 |
void |
221 |
setOffset(ValueType::size_type offset); |
222 |
|
223 |
/** |
224 |
\brief |
225 |
Return the shape of a data view following the slice specified. |
226 |
|
227 |
\param region - Input - Slice region. |
228 |
*/ |
229 |
static DataArrayView::ShapeType |
230 |
getResultSliceShape(const RegionType& region); |
231 |
|
232 |
/** |
233 |
\brief |
234 |
Copy a slice specified by the given region from the given view |
235 |
into this view. |
236 |
The given region must be the same shape as this view. |
237 |
|
238 |
\param other - Input - view to copy from. |
239 |
\param region - Input - region in other to copy. |
240 |
*/ |
241 |
void |
242 |
copySlice(const DataArrayView& other, |
243 |
const RegionType& region); |
244 |
|
245 |
/** |
246 |
\brief |
247 |
Copy a slice specified by the given region from the given view into this view. |
248 |
The given region must be the same shape as this view. |
249 |
|
250 |
\param thisOffset - Input - use this offset into this object instead of the default. |
251 |
\param other - Input - view to copy from. |
252 |
\param otherOffset - Input - use this offset into the given object instead of the default. |
253 |
\param region - Input - region in other to copy. |
254 |
*/ |
255 |
void |
256 |
copySlice(ValueType::size_type thisOffset, |
257 |
const DataArrayView& other, |
258 |
ValueType::size_type otherOffset, |
259 |
const RegionType& region); |
260 |
|
261 |
/** |
262 |
\brief |
263 |
Copy into a slice from the given view. |
264 |
This view must have the same rank as the slice region. |
265 |
|
266 |
\param other - Input - Data to copy from. |
267 |
\param region - Input - Slice region. |
268 |
*/ |
269 |
void |
270 |
copySliceFrom(const DataArrayView& other, |
271 |
const RegionType& region); |
272 |
|
273 |
/** |
274 |
\brief |
275 |
Copy into a slice from the given value. |
276 |
This view must have the same rank as the slice region. |
277 |
|
278 |
\param thisOffset - Input - use this view offset instead of the default. |
279 |
\param other - Input - Data to copy from. |
280 |
\param otherOffset - Input - use this slice offset instead of the default. |
281 |
\param region - Input - Slice region. |
282 |
*/ |
283 |
void |
284 |
copySliceFrom(ValueType::size_type thisOffset, |
285 |
const DataArrayView& other, |
286 |
ValueType::size_type otherOffset, |
287 |
const RegionType& region); |
288 |
|
289 |
/** |
290 |
\brief |
291 |
Determine the shape of the result array for a matrix multiplication. |
292 |
*/ |
293 |
static ShapeType |
294 |
determineResultShape(const DataArrayView& left, |
295 |
const DataArrayView& right); |
296 |
|
297 |
/** |
298 |
\brief |
299 |
Determine the region specified by the given python slice object. |
300 |
|
301 |
\param key - Input - python slice object specifying region to be returned. |
302 |
|
303 |
\description |
304 |
|
305 |
The slice object is a tuple of n python slice specifiers, where |
306 |
n <= the rank of this Data object. Each slice specifier specifies the |
307 |
range of indexes to be sliced from the corresponding dimension. The |
308 |
first specifier corresponds to the first dimension, the second to the |
309 |
second and so on. Where n < the rank, the remaining dimensions are |
310 |
sliced across the full range of their indicies. |
311 |
|
312 |
Each slice specifier is of the form "a:b", which specifies a slice |
313 |
from index a, up to but not including index b. Where index a is ommitted |
314 |
a is assumed to be 0. Where index b is ommitted, b is assumed to be the |
315 |
length of this dimension. |
316 |
|
317 |
The return value is a vector of pairs with length equal to the rank of |
318 |
this object. Each pair corresponds to the range of indexes from the |
319 |
corresponding dimension to be sliced from, as specified in the input |
320 |
slice object. |
321 |
|
322 |
Examples: |
323 |
|
324 |
For a rank 1 object of shape(5): |
325 |
|
326 |
getSliceRegion(:) => < <0,5> > |
327 |
getSliceRegion(2:3) => < <2,3> > |
328 |
getSliceRegion(:3) => < <0,3> > |
329 |
getSliceRegion(2:) => < <2,5> > |
330 |
|
331 |
For a rank 3 object of shape (2,4,6): |
332 |
|
333 |
getSliceRegion(0:2,0:4,0:6) => < <0,2> <0,4> <0,6> > |
334 |
getSliceRegion(:,:,:) => < <0,2> <0,4> <0,6> > |
335 |
getSliceRegion(0:1) => < <0,1> <0,4> <0,6> > |
336 |
getSliceRegion(:1,0:2) => < <0,1> <0,2> <0,6> > |
337 |
*/ |
338 |
DataArrayView::RegionType |
339 |
getSliceRegion(const boost::python::object& key) const; |
340 |
|
341 |
// ******************************************************************* |
342 |
// NOTE: The following relIndex functions are a hack. The indexing |
343 |
// mechanism should be split out from DataArrayView to get the flexability |
344 |
// needed. |
345 |
|
346 |
/** |
347 |
\brief |
348 |
Return the 1 dimensional index of the element at position i,j,k,m |
349 |
ignoring the offset. |
350 |
*/ |
351 |
ValueType::size_type |
352 |
relIndex(ValueType::size_type i, |
353 |
ValueType::size_type j, |
354 |
ValueType::size_type k, |
355 |
ValueType::size_type m) const; |
356 |
|
357 |
/** |
358 |
\brief |
359 |
Return the 1 dimensional index of the element at position i,j,k |
360 |
ignoring the offset. |
361 |
*/ |
362 |
ValueType::size_type |
363 |
relIndex(ValueType::size_type i, |
364 |
ValueType::size_type j, |
365 |
ValueType::size_type k) const; |
366 |
|
367 |
/** |
368 |
\brief |
369 |
Return the 1 dimensional index of the element at position i,j |
370 |
ignoring the offset. |
371 |
*/ |
372 |
ValueType::size_type |
373 |
relIndex(ValueType::size_type i, |
374 |
ValueType::size_type j) const; |
375 |
|
376 |
// ******************************************************************** |
377 |
|
378 |
/** |
379 |
\brief |
380 |
Return the 1 dimensional index of the element at position i,j,k,m. |
381 |
*/ |
382 |
ValueType::size_type |
383 |
index(ValueType::size_type i, |
384 |
ValueType::size_type j, |
385 |
ValueType::size_type k, |
386 |
ValueType::size_type m) const; |
387 |
|
388 |
/** |
389 |
\brief |
390 |
Return the 1 dimensional index of the element at position i,j,k. |
391 |
*/ |
392 |
ValueType::size_type |
393 |
index(ValueType::size_type i, |
394 |
ValueType::size_type j, |
395 |
ValueType::size_type k) const; |
396 |
|
397 |
/** |
398 |
\brief |
399 |
Return the 1 dimensional index of the element at position i,j. |
400 |
*/ |
401 |
ValueType::size_type |
402 |
index(ValueType::size_type i, |
403 |
ValueType::size_type j) const; |
404 |
|
405 |
/** |
406 |
\brief |
407 |
Return the 1 dimensional index of the element at position i. |
408 |
*/ |
409 |
ValueType::size_type |
410 |
index(ValueType::size_type i) const; |
411 |
|
412 |
/** |
413 |
\brief |
414 |
Return a reference to the element at position i. |
415 |
*/ |
416 |
ValueType::reference |
417 |
operator()(ValueType::size_type i); |
418 |
|
419 |
ValueType::const_reference |
420 |
operator()(ValueType::size_type i) const; |
421 |
|
422 |
/** |
423 |
\brief |
424 |
Return a reference to the element at position i,j. |
425 |
*/ |
426 |
ValueType::reference |
427 |
operator()(ValueType::size_type i, |
428 |
ValueType::size_type j); |
429 |
|
430 |
ValueType::const_reference |
431 |
operator()(ValueType::size_type i, |
432 |
ValueType::size_type j) const; |
433 |
|
434 |
/** |
435 |
\brief |
436 |
Return a reference to the element at position i,j,k. |
437 |
*/ |
438 |
ValueType::reference |
439 |
operator()(ValueType::size_type i, |
440 |
ValueType::size_type j, |
441 |
ValueType::size_type k); |
442 |
|
443 |
ValueType::const_reference |
444 |
operator()(ValueType::size_type i, |
445 |
ValueType::size_type j, |
446 |
ValueType::size_type k) const; |
447 |
|
448 |
/** |
449 |
\brief |
450 |
Return a reference to the element at position i,j,k,m. |
451 |
*/ |
452 |
ValueType::reference |
453 |
operator()(ValueType::size_type i, |
454 |
ValueType::size_type j, |
455 |
ValueType::size_type k, |
456 |
ValueType::size_type m); |
457 |
|
458 |
ValueType::const_reference |
459 |
operator()(ValueType::size_type i, |
460 |
ValueType::size_type j, |
461 |
ValueType::size_type k, |
462 |
ValueType::size_type m) const; |
463 |
|
464 |
/** |
465 |
\brief |
466 |
Return a reference for the only element, assuming rank 0. |
467 |
*/ |
468 |
ValueType::reference |
469 |
operator()(); |
470 |
|
471 |
ValueType::const_reference |
472 |
operator()() const; |
473 |
|
474 |
/** |
475 |
\brief |
476 |
Perform the unary operation using the given offset |
477 |
instead of the offset defined within the view. |
478 |
*/ |
479 |
template <class UnaryFunction> |
480 |
void |
481 |
unaryOp(ValueType::size_type leftOffset, |
482 |
UnaryFunction operation); |
483 |
|
484 |
/** |
485 |
\brief |
486 |
Perform the unary operation using the view's offset. |
487 |
*/ |
488 |
template <class UnaryFunction> |
489 |
void |
490 |
unaryOp(UnaryFunction operation); |
491 |
|
492 |
/** |
493 |
\brief |
494 |
Perform the given data point reduction operation on the data point |
495 |
specified by the given offset into the view. Reduces all elements of |
496 |
the data point using the given operation, returning the result as a |
497 |
scalar. |
498 |
|
499 |
Called by escript::dp_algorithm. |
500 |
*/ |
501 |
template <class UnaryFunction> |
502 |
double |
503 |
dp_algorithm(ValueType::size_type leftOffset, |
504 |
UnaryFunction operation); |
505 |
|
506 |
/** |
507 |
\brief |
508 |
Perform the given data point reduction operation on the data point |
509 |
specified by the default offset into the view. Reduces all elements of |
510 |
the data point using the given operation, returning the result as a |
511 |
scalar. |
512 |
|
513 |
Called by escript::dp_algorithm. |
514 |
*/ |
515 |
template <class UnaryFunction> |
516 |
double |
517 |
dp_algorithm(UnaryFunction operation); |
518 |
|
519 |
/** |
520 |
\brief |
521 |
Perform the given operation and return a result. |
522 |
*/ |
523 |
template <class UnaryFunction> |
524 |
double |
525 |
algorithm(ValueType::size_type leftOffset, |
526 |
UnaryFunction operation) const; |
527 |
|
528 |
/** |
529 |
\brief |
530 |
Perform the given operation and return a result. Use the default offset. |
531 |
*/ |
532 |
template <class UnaryFunction> |
533 |
double |
534 |
algorithm(UnaryFunction operation) const; |
535 |
|
536 |
/** |
537 |
\brief |
538 |
Perform the binary operation. Version which applies a double value |
539 |
to all values within the view. The given offset is used instead of |
540 |
the default offset specified within the view. |
541 |
*/ |
542 |
template <class BinaryFunction> |
543 |
void |
544 |
binaryOp(ValueType::size_type leftOffset, |
545 |
double right, |
546 |
BinaryFunction operation); |
547 |
|
548 |
/** |
549 |
\brief |
550 |
Perform the binary operation. Version which applies a double value |
551 |
to all values within the view. |
552 |
*/ |
553 |
template <class BinaryFunction> |
554 |
void |
555 |
binaryOp(double right, |
556 |
BinaryFunction operation); |
557 |
|
558 |
/** |
559 |
\brief |
560 |
Perform the binary operation. The given offsets override the default |
561 |
offsets specified within the views. |
562 |
*/ |
563 |
template <class BinaryFunction> |
564 |
void |
565 |
binaryOp(ValueType::size_type leftOffset, |
566 |
const DataArrayView& right, |
567 |
ValueType::size_type rightOffset, |
568 |
BinaryFunction operation); |
569 |
|
570 |
/** |
571 |
\brief |
572 |
Perform the binary operation. |
573 |
*/ |
574 |
template <class BinaryFunction> |
575 |
void |
576 |
binaryOp(const DataArrayView& right, |
577 |
BinaryFunction operation); |
578 |
|
579 |
/** |
580 |
\brief |
581 |
Return the data as a string. Not recommended for very large objects. |
582 |
\param suffix - Input - Suffix appended to index display. |
583 |
*/ |
584 |
std::string |
585 |
toString(const std::string& suffix=std::string("")) const; |
586 |
|
587 |
/** |
588 |
\brief |
589 |
Return the given shape as a string. |
590 |
|
591 |
\param shape - Input. |
592 |
*/ |
593 |
static std::string |
594 |
shapeToString(const DataArrayView::ShapeType& shape); |
595 |
|
596 |
/** |
597 |
\brief |
598 |
Perform matrix multiply. |
599 |
|
600 |
Description: |
601 |
Perform matrix multiply. |
602 |
|
603 |
\param left - Input - The left hand side. |
604 |
\param right - Input - The right hand side. |
605 |
\param result - Output - The result of the operation. |
606 |
*/ |
607 |
static void |
608 |
matMult(const DataArrayView& left, |
609 |
const DataArrayView& right, |
610 |
DataArrayView& result); |
611 |
|
612 |
protected: |
613 |
|
614 |
private: |
615 |
|
616 |
// |
617 |
static const int m_maxRank=4; |
618 |
|
619 |
// |
620 |
// The data values for the view. NOTE: This points to data external to the view. |
621 |
ValueType* m_data; |
622 |
|
623 |
// |
624 |
// The offset into the data array used by different views. |
625 |
ValueType::size_type m_offset; |
626 |
|
627 |
// |
628 |
// The shape of the data. |
629 |
ShapeType m_shape; |
630 |
|
631 |
// |
632 |
// The number of values needed for the array. |
633 |
int m_noValues; |
634 |
|
635 |
}; |
636 |
|
637 |
/** |
638 |
\brief |
639 |
Calculate the slice range from the given python key object |
640 |
Used by DataArrayView::getSliceRegion. |
641 |
Returns the python slice object key as a pair of ints where the first |
642 |
member is the start and the second member is the end. the presence of a possible |
643 |
step attribute with value different from one will throw an exception |
644 |
|
645 |
/param key - Input - key object specifying slice range. |
646 |
*/ |
647 |
std::pair<int,int> |
648 |
getSliceRange(const boost::python::object& key, |
649 |
const int shape); |
650 |
|
651 |
inline |
652 |
DataArrayView::ValueType::size_type |
653 |
DataArrayView::getOffset() const |
654 |
{ |
655 |
return m_offset; |
656 |
} |
657 |
|
658 |
inline |
659 |
DataArrayView::ValueType& |
660 |
DataArrayView::getData() const |
661 |
{ |
662 |
EsysAssert(!isEmpty(),"Error - View is empty"); |
663 |
return *m_data; |
664 |
} |
665 |
|
666 |
inline |
667 |
DataArrayView::ValueType::reference |
668 |
DataArrayView::getData(ValueType::size_type i) const |
669 |
{ |
670 |
// |
671 |
// don't do any checking to allow one past the end of the vector providing |
672 |
// the equivalent of end() |
673 |
return (*m_data)[i+m_offset]; |
674 |
} |
675 |
|
676 |
template <class UnaryFunction> |
677 |
inline |
678 |
void |
679 |
DataArrayView::unaryOp(ValueType::size_type leftOffset, |
680 |
UnaryFunction operation) |
681 |
{ |
682 |
for (ValueType::size_type i=0;i<(noValues(m_shape));i++) { |
683 |
(*m_data)[i+leftOffset]=operation((*m_data)[i+leftOffset]); |
684 |
} |
685 |
} |
686 |
|
687 |
template <class UnaryFunction> |
688 |
inline |
689 |
void |
690 |
DataArrayView::unaryOp(UnaryFunction operation) |
691 |
{ |
692 |
unaryOp(m_offset,operation); |
693 |
} |
694 |
|
695 |
template <class UnaryFunction> |
696 |
inline |
697 |
double |
698 |
DataArrayView::dp_algorithm(ValueType::size_type leftOffset, |
699 |
UnaryFunction operation) |
700 |
{ |
701 |
for (ValueType::size_type i=0;i<(noValues(m_shape));i++) { |
702 |
operation((*m_data)[i+leftOffset]); |
703 |
} |
704 |
return operation.getResult(); |
705 |
} |
706 |
|
707 |
template <class UnaryFunction> |
708 |
inline |
709 |
double |
710 |
DataArrayView::dp_algorithm(UnaryFunction operation) |
711 |
{ |
712 |
return dp_algorithm(m_offset,operation); |
713 |
} |
714 |
|
715 |
template <class UnaryFunction> |
716 |
inline |
717 |
double |
718 |
DataArrayView::algorithm(ValueType::size_type leftOffset, |
719 |
UnaryFunction operation) const |
720 |
{ |
721 |
for (ValueType::size_type i=0;i<(noValues(m_shape));++i) { |
722 |
operation((*m_data)[i+leftOffset]); |
723 |
} |
724 |
return operation.getResult(); |
725 |
} |
726 |
|
727 |
template <class UnaryFunction> |
728 |
inline |
729 |
double |
730 |
DataArrayView::algorithm(UnaryFunction operation) const |
731 |
{ |
732 |
return algorithm(m_offset,operation); |
733 |
} |
734 |
|
735 |
template <class BinaryFunction> |
736 |
inline |
737 |
void |
738 |
DataArrayView::binaryOp(ValueType::size_type leftOffset, |
739 |
const DataArrayView& right, |
740 |
ValueType::size_type rightOffset, |
741 |
BinaryFunction operation) |
742 |
{ |
743 |
EsysAssert(getShape()==right.getShape(), |
744 |
"Error - Right hand shape: " << shapeToString(right.getShape()) << " doesn't match the left: " << shapeToString(getShape())); |
745 |
for (ValueType::size_type i=0;i<noValues();++i) { |
746 |
(*m_data)[i+leftOffset]=operation((*m_data)[i+leftOffset],(*right.m_data)[i+rightOffset]); |
747 |
} |
748 |
} |
749 |
|
750 |
template <class BinaryFunction> |
751 |
inline |
752 |
void |
753 |
DataArrayView::binaryOp(const DataArrayView& right, |
754 |
BinaryFunction operation) |
755 |
{ |
756 |
// |
757 |
// version using the offsets specified within the view |
758 |
binaryOp(m_offset,right,right.getOffset(),operation); |
759 |
} |
760 |
|
761 |
template <class BinaryFunction> |
762 |
inline |
763 |
void |
764 |
DataArrayView::binaryOp(ValueType::size_type leftOffset, |
765 |
double right, |
766 |
BinaryFunction operation) |
767 |
{ |
768 |
// |
769 |
// If a scalar is to be applied to the entire array force the caller to |
770 |
// explicitly specify a single value |
771 |
for (ValueType::size_type i=0;i<(noValues(m_shape));++i) { |
772 |
(*m_data)[i+leftOffset]=operation((*m_data)[i+leftOffset],right); |
773 |
} |
774 |
} |
775 |
|
776 |
template <class BinaryFunction> |
777 |
inline |
778 |
void |
779 |
DataArrayView::binaryOp(double right, |
780 |
BinaryFunction operation) |
781 |
{ |
782 |
// |
783 |
// use the default offset |
784 |
binaryOp(m_offset,right,operation); |
785 |
} |
786 |
|
787 |
inline |
788 |
DataArrayView::ValueType::size_type |
789 |
DataArrayView::index(ValueType::size_type i) const |
790 |
{ |
791 |
//EsysAssert((i >= 0) && (i < noValues(m_shape)), "Invalid index."); |
792 |
EsysAssert((i < noValues(m_shape)), "Invalid index."); |
793 |
return (i+m_offset); |
794 |
} |
795 |
|
796 |
inline |
797 |
DataArrayView::ValueType::size_type |
798 |
DataArrayView::relIndex(ValueType::size_type i, |
799 |
ValueType::size_type j) const |
800 |
{ |
801 |
ValueType::size_type temp=i+j*m_shape[0]; |
802 |
//EsysAssert((temp >= 0 || temp < noValues(m_shape)), "Invalid index."); |
803 |
EsysAssert((temp < noValues(m_shape)), "Invalid index."); |
804 |
// |
805 |
// no offset |
806 |
return temp; |
807 |
} |
808 |
|
809 |
inline |
810 |
DataArrayView::ValueType::size_type |
811 |
DataArrayView::index(ValueType::size_type i, |
812 |
ValueType::size_type j) const |
813 |
{ |
814 |
ValueType::size_type temp=i+j*m_shape[0]; |
815 |
//EsysAssert((temp >= 0 || temp < noValues(m_shape)), "Invalid index."); |
816 |
EsysAssert((temp < noValues(m_shape)), "Invalid index."); |
817 |
return (temp+m_offset); |
818 |
} |
819 |
|
820 |
inline |
821 |
DataArrayView::ValueType::size_type |
822 |
DataArrayView::relIndex(ValueType::size_type i, |
823 |
ValueType::size_type j, |
824 |
ValueType::size_type k) const |
825 |
{ |
826 |
ValueType::size_type temp=i+j*m_shape[0]+k*m_shape[1]*m_shape[0]; |
827 |
//EsysAssert((temp >= 0 || temp < noValues(m_shape)), "Invalid index."); |
828 |
EsysAssert((temp < noValues(m_shape)), "Invalid index."); |
829 |
// |
830 |
// no offset |
831 |
return temp; |
832 |
} |
833 |
|
834 |
inline |
835 |
DataArrayView::ValueType::size_type |
836 |
DataArrayView::index(ValueType::size_type i, |
837 |
ValueType::size_type j, |
838 |
ValueType::size_type k) const |
839 |
{ |
840 |
ValueType::size_type temp=i+j*m_shape[0]+k*m_shape[1]*m_shape[0]; |
841 |
//EsysAssert((temp >= 0 || temp < noValues(m_shape)), "Invalid index."); |
842 |
EsysAssert((temp < noValues(m_shape)), "Invalid index."); |
843 |
return (temp+m_offset); |
844 |
} |
845 |
|
846 |
inline |
847 |
DataArrayView::ValueType::size_type |
848 |
DataArrayView::relIndex(ValueType::size_type i, |
849 |
ValueType::size_type j, |
850 |
ValueType::size_type k, |
851 |
ValueType::size_type m) const |
852 |
{ |
853 |
ValueType::size_type temp=i+j*m_shape[0]+k*m_shape[1]*m_shape[0]+m*m_shape[2]*m_shape[1]*m_shape[0]; |
854 |
//EsysAssert((temp >= 0 || temp < noValues(m_shape)), "Invalid index."); |
855 |
EsysAssert((temp < noValues(m_shape)), "Invalid index."); |
856 |
// |
857 |
// no offset |
858 |
return temp; |
859 |
} |
860 |
|
861 |
inline |
862 |
DataArrayView::ValueType::size_type |
863 |
DataArrayView::index(ValueType::size_type i, |
864 |
ValueType::size_type j, |
865 |
ValueType::size_type k, |
866 |
ValueType::size_type m) const |
867 |
{ |
868 |
ValueType::size_type temp=i+j*m_shape[0]+k*m_shape[1]*m_shape[0]+m*m_shape[2]*m_shape[1]*m_shape[0]; |
869 |
//EsysAssert((temp >= 0 || temp < noValues(m_shape)), "Invalid index."); |
870 |
EsysAssert((temp < noValues(m_shape)), "Invalid index."); |
871 |
return (temp+m_offset); |
872 |
} |
873 |
|
874 |
inline |
875 |
DataArrayView::ValueType::reference |
876 |
DataArrayView::operator()(ValueType::size_type i, |
877 |
ValueType::size_type j, |
878 |
ValueType::size_type k, |
879 |
ValueType::size_type m) |
880 |
{ |
881 |
EsysAssert((getRank()==4), |
882 |
"Incorrect number of indices for the rank of this object."); |
883 |
return (*m_data)[index(i,j,k,m)]; |
884 |
} |
885 |
|
886 |
inline |
887 |
DataArrayView::ValueType::const_reference |
888 |
DataArrayView::operator()(ValueType::size_type i, |
889 |
ValueType::size_type j, |
890 |
ValueType::size_type k, |
891 |
ValueType::size_type m) const |
892 |
{ |
893 |
EsysAssert((getRank()==4), |
894 |
"Incorrect number of indices for the rank of this object."); |
895 |
return (*m_data)[index(i,j,k,m)]; |
896 |
} |
897 |
|
898 |
inline |
899 |
DataArrayView::ValueType::reference |
900 |
DataArrayView::operator()(ValueType::size_type i, |
901 |
ValueType::size_type j, |
902 |
ValueType::size_type k) |
903 |
{ |
904 |
EsysAssert((getRank()==3), |
905 |
"Incorrect number of indices for the rank of this object."); |
906 |
return (*m_data)[index(i,j,k)]; |
907 |
} |
908 |
|
909 |
inline |
910 |
DataArrayView::ValueType::const_reference |
911 |
DataArrayView::operator()(ValueType::size_type i, |
912 |
ValueType::size_type j, |
913 |
ValueType::size_type k) const |
914 |
{ |
915 |
EsysAssert((getRank()==3), |
916 |
"Incorrect number of indices for the rank of this object."); |
917 |
return (*m_data)[index(i,j,k)]; |
918 |
} |
919 |
|
920 |
inline |
921 |
DataArrayView::ValueType::reference |
922 |
DataArrayView::operator()(ValueType::size_type i, |
923 |
ValueType::size_type j) |
924 |
{ |
925 |
EsysAssert((getRank()==2), |
926 |
"Incorrect number of indices for the rank of this object."); |
927 |
return (*m_data)[index(i,j)]; |
928 |
} |
929 |
|
930 |
inline |
931 |
DataArrayView::ValueType::const_reference |
932 |
DataArrayView::operator()(ValueType::size_type i, |
933 |
ValueType::size_type j) const |
934 |
{ |
935 |
EsysAssert((getRank()==2), |
936 |
"Incorrect number of indices for the rank of this object."); |
937 |
return (*m_data)[index(i,j)]; |
938 |
} |
939 |
|
940 |
inline |
941 |
DataArrayView::ValueType::reference |
942 |
DataArrayView::operator()(ValueType::size_type i) |
943 |
{ |
944 |
EsysAssert((getRank()==1), |
945 |
"Incorrect number of indices for the rank of this object."); |
946 |
return (*m_data)[index(i)]; |
947 |
} |
948 |
|
949 |
inline |
950 |
DataArrayView::ValueType::const_reference |
951 |
DataArrayView::operator()(ValueType::size_type i) const |
952 |
{ |
953 |
EsysAssert((getRank()==1), |
954 |
"Incorrect number of indices for the rank of this object."); |
955 |
return (*m_data)[index(i)]; |
956 |
} |
957 |
|
958 |
inline |
959 |
DataArrayView::ValueType::reference |
960 |
DataArrayView::operator()() |
961 |
{ |
962 |
EsysAssert((getRank()==0), |
963 |
"Incorrect number of indices for the rank of this object."); |
964 |
return (*m_data)[m_offset]; |
965 |
} |
966 |
|
967 |
inline |
968 |
DataArrayView::ValueType::const_reference |
969 |
DataArrayView::operator()() const |
970 |
{ |
971 |
EsysAssert((getRank()==0), |
972 |
"Incorrect number of indices for the rank of this object."); |
973 |
return (*m_data)[m_offset]; |
974 |
} |
975 |
|
976 |
bool operator==(const DataArrayView& left, const DataArrayView& right); |
977 |
bool operator!=(const DataArrayView& left, const DataArrayView& right); |
978 |
|
979 |
} // end of namespace |
980 |
|
981 |
#endif |