/[escript]/trunk/esys2/escript/src/Data/Data.h
ViewVC logotype

Contents of /trunk/esys2/escript/src/Data/Data.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 82 - (show annotations)
Tue Oct 26 06:53:54 2004 UTC (15 years, 9 months ago) by jgs
File MIME type: text/plain
File size: 26712 byte(s)
Initial revision

1 // $Id$
2 /*=============================================================================
3
4 ******************************************************************************
5 * *
6 * COPYRIGHT ACcESS 2004 - All Rights Reserved *
7 * *
8 * This software is the property of ACcESS. No part of this code *
9 * may be copied in any form or by any means without the expressed written *
10 * consent of ACcESS. Copying, use or modification of this software *
11 * by any unauthorised person is illegal unless that *
12 * person has a software license agreement with ACcESS. *
13 * *
14 ******************************************************************************
15
16 ******************************************************************************/
17
18 #ifndef DATA_H
19 #define DATA_H
20
21 #include "escript/Data/DataAbstract.h"
22 #include "escript/Data/DataTagged.h"
23 #include "escript/Data/FunctionSpace.h"
24 #include "escript/Data/BinaryOp.h"
25 #include "escript/Data/UnaryOp.h"
26
27 extern "C" {
28 #include "escript/Data/DataC.h"
29 }
30
31 #include <iostream>
32 #include <string>
33 #include <memory>
34 #include <algorithm>
35
36 #include <boost/shared_ptr.hpp>
37 #include <boost/python/object.hpp>
38 #include <boost/python/list.hpp>
39 #include <boost/python/tuple.hpp>
40 #include <boost/python/numeric.hpp>
41
42 /**
43 \brief
44 Data is essentially a factory class which creates the appropriate Data
45 object for the given construction arguments. It retains control over
46 the object created for the lifetime of the object.
47 The type of Data object referred to may change during the lifetime of
48 the Data object.
49
50 Description:
51 Data is essentially a factory class which creates the appropriate Data
52 object for the given construction arguments. It retains control over
53 the object created for the lifetime of the object.
54 The type of Data object referred to may change during the lifetime of
55 the Data object.
56 */
57
58 namespace escript {
59
60 //
61 // Forward declaration for various implimentations of Data.
62 class DataEmpty;
63 class DataConstant;
64 class DataTagged;
65 class DataExpanded;
66
67 class Data {
68
69 public:
70
71 typedef double (*UnaryDFunPtr)(double);
72 typedef double (*BinaryDFunPtr)(double,double);
73
74 /**
75 \brief
76 Default constructor.
77 Creates a DataEmpty object.
78 */
79 Data();
80
81 /**
82 \brief
83 Copy constructor.
84 WARNING: Only performs a shallow copy.
85 */
86 Data(const Data& inData);
87
88 /**
89 \brief
90 Constructor from another Data object. If "what" is different from the
91 function space of inData the inData are tried to be interpolated to what
92 otherwise a shallow copy of inData is returned.
93 */
94 Data(const Data& inData,
95 const FunctionSpace& what);
96
97 /**
98 \brief
99 Constructor which copies data from a DataArrayView.
100
101 \param value - Input - Data value for a single point.
102 \param what - Input - A description of what this data represents.
103 \param expanded - Input - Flag, if true fill the entire container with
104 the value. Otherwise a more efficient storage
105 mechanism will be used.
106 */
107 Data(const DataArrayView& value,
108 const FunctionSpace& what=FunctionSpace(),
109 bool expanded=false);
110
111 /**
112 \brief
113 Constructor which creates a Data from a DataArrayView shape.
114
115 \param value - Input - Single value applied to all Data.
116 \param dataPointShape - Input - The shape of each data point.
117 \param what - Input - A description of what this data represents.
118 \param expanded - Input - Flag, if true fill the entire container with
119 the given value. Otherwise a more efficient storage
120 mechanism will be used.
121 */
122 Data(double value,
123 const DataArrayView::ShapeType& dataPointShape=DataArrayView::ShapeType(),
124 const FunctionSpace& what=FunctionSpace(),
125 bool expanded=false);
126
127 /**
128 \brief
129 Constructor which performs a deep copy of a region from another Data object.
130
131 \param inData - Input - Input Data object.
132 \param region - Input - Region to copy.
133 */
134 Data(const Data& inData,
135 const DataArrayView::RegionType& region);
136
137 /**
138 \brief
139 Constructor which will create Tagged data if expanded is false.
140 No attempt is made to ensure the tag keys match the tag keys
141 within the function space.
142
143 \param tagKeys - Input - List of tag values.
144 \param values - Input - List of values, one for each tag.
145 \param defaultValue - Input - A default value, used if tag doesn't exist.
146 \param what - Input - A description of what this data represents.
147 \param expanded - Input - Flag, if true fill the entire container with
148 the appropriate values.
149 */
150 Data(const DataTagged::TagListType& tagKeys,
151 const DataTagged::ValueListType& values,
152 const DataArrayView& defaultValue,
153 const FunctionSpace& what=FunctionSpace(),
154 bool expanded=false);
155
156 /**
157 \brief
158 Constructor which copies data from a python numarray.
159
160 \param value - Input - Data value for a single point.
161 \param what - Input - A description of what this data represents.
162 \param expanded - Input - Flag, if true fill the entire container with
163 the value. Otherwise a more efficient storage
164 mechanism will be used.
165 */
166 Data(const boost::python::numeric::array& value,
167 const FunctionSpace& what=FunctionSpace(),
168 bool expanded=false);
169
170 /**
171 \brief
172 Constructor which copies data from any object that can be converted into
173 a python numarray.
174
175 \param value - Input - Input data.
176 \param what - Input - A description of what this data represents.
177 \param expanded - Input - Flag, if true fill the entire container with
178 the value. Otherwise a more efficient storage
179 mechanism will be used.
180 */
181 Data(const boost::python::object& value,
182 const FunctionSpace& what=FunctionSpace(),
183 bool expanded=false);
184
185 /**
186 \brief
187 Constructor which creates a DataConstant.
188 Copies data from any object that can be converted
189 into a numarray. All other parameters are copied from other.
190
191 \param value - Input - Input data.
192 \param other - Input - contains all other parameters.
193 */
194 Data(const boost::python::object& value,
195 const Data& other);
196
197 /**
198 \brief
199 Constructor which creates a DataConstant of "shape" with constant value.
200 */
201 Data(double value,
202 const boost::python::tuple& shape=boost::python::make_tuple(),
203 const FunctionSpace& what=FunctionSpace(),
204 bool expanded=false);
205
206 /**
207 \brief
208 Perform the specified algorithm on the Data and return result.
209 */
210 template <class UnaryFunction>
211 inline double
212 algorithm(UnaryFunction operation) const;
213
214 /**
215 \brief
216 Perform the given unary operation on all of the data's elements.
217 */
218 template <class UnaryFunction>
219 void
220 unaryOp(UnaryFunction operation);
221
222 /**
223 \brief
224 Perform the given binary operation on all of the data's elements.
225 The underlying type of the right hand side (right) determines the final
226 type of *this after the operation. For example if the right hand side
227 is expanded *this will be expanded if necessary.
228 */
229 template <class BinaryFunction>
230 void
231 binaryOp(const Data& right,
232 BinaryFunction operation);
233
234 /**
235 \brief
236 Perform the given binary operation on all of the data's elements.
237 */
238 template <class BinaryFunction>
239 void
240 binaryOp(const boost::python::object& right,
241 BinaryFunction operation);
242
243 /**
244 \brief
245 Overloaded operator +=
246 \param right - Input - The right hand side.
247 */
248 Data& operator+=(const Data& right);
249 Data& operator+=(const boost::python::object& right);
250
251 /**
252 \brief
253 Overloaded operator -=
254 \param right - Input - The right hand side.
255 */
256 Data& operator-=(const Data& right);
257 Data& operator-=(const boost::python::object& right);
258
259 /**
260 \brief
261 Overloaded operator *=
262 \param right - Input - The right hand side.
263 */
264 Data& operator*=(const Data& right);
265 Data& operator*=(const boost::python::object& right);
266
267 /**
268 \brief
269 Overloaded operator /=
270 \param right - Input - The right hand side.
271 */
272 Data& operator/=(const Data& right);
273 Data& operator/=(const boost::python::object& right);
274
275 /**
276 \brief
277 Return the power of Data.
278 */
279 Data powD(const Data& right) const;
280 Data powO(const boost::python::object& right) const;
281
282 /**
283 \brief
284 Return the C wrapper for the Data object.
285 */
286 escriptDataC getDataC();
287
288 /**
289 \brief
290 Return the C wrapper for the Data object - const version.
291 */
292 escriptDataC getDataC() const;
293
294 /**
295 \brief
296 Write the data as a string.
297 */
298 std::string toString() const;
299
300 /**
301 \brief
302 Return the DataArrayView of the point data. This essentially contains
303 the shape information for each data point although it also may be used
304 to manipulate the point data.
305 */
306 inline
307 const DataArrayView&
308 getPointDataView() const
309 {
310 return m_data->getPointDataView();
311 }
312
313 /**
314 \brief
315 Perform a deep copy.
316 */
317 void
318 copy(const Data& other);
319
320 /**
321 \brief
322 Copy other Data object into this Data object where mask is positive.
323 */
324 void
325 copyWithMask(const Data& other,
326 const Data& mask);
327
328 /**
329 \brief
330 Whatever the current Data type make it expanded.
331 */
332 void
333 expand();
334
335 /**
336 \brief
337 If possible convert the Data type to tagged. This will only allow
338 Constant data to be converted to tagged. An attempt to convert
339 Expanded data to tagged will throw an exception.
340 */
341 void
342 tag();
343
344 /**
345 \brief
346 Return true if this Data is expanded.
347 */
348 bool
349 isExpanded() const;
350
351 /**
352 \brief
353 Return true if this Data is tagged.
354 */
355 bool
356 isTagged() const;
357
358 /**
359 \brief
360 Return true if this Data is empty.
361 */
362 bool
363 isEmpty() const;
364
365 /**
366 \brief
367 Return true if this Data is constant.
368 */
369 bool
370 isConstant() const;
371
372 /**
373 \brief
374 Return the function space.
375 */
376 inline
377 const FunctionSpace&
378 getFunctionSpace() const
379 {
380 return m_data->getFunctionSpace();
381 }
382
383 /**
384 \brief
385 Return a copy of the function space.
386 */
387 const FunctionSpace
388 getCopyOfFunctionSpace() const;
389
390 /**
391 \brief
392 Return the domain.
393 */
394 inline
395 const AbstractDomain&
396 getDomain() const
397 {
398 return getFunctionSpace().getDomain();
399 }
400
401 /**
402 \brief
403 Return a copy of the domain.
404 */
405 const AbstractDomain
406 getCopyOfDomain() const;
407
408 /**
409 \brief
410 Return the rank of the point data.
411 */
412 inline
413 int
414 getDataPointRank() const
415 {
416 return m_data->getPointDataView().getRank();
417 }
418
419 /**
420 \brief
421 Return the number of data points per sample.
422 */
423 inline
424 int
425 getNumDataPointsPerSample() const
426 {
427 return m_data->getNumDPPSample();
428 }
429
430 /**
431 \brief
432 Return the number of samples.
433 */
434 int
435 getNumSamples() const;
436
437 /**
438 \brief
439 Check *this and the right operand are compatible. Throws
440 an exception if they aren't.
441 \param right - Input - The right hand side.
442 */
443 void
444 operandCheck(const Data& right) const;
445
446 /**
447 \brief
448 Return the sample data for the given sample no. This is not the
449 preferred interface but is provided for use by C code.
450 \param sampleNo - Input - the given sample no.
451 */
452 DataAbstract::ValueType::value_type*
453 getSampleData(DataAbstract::ShapeType::size_type sampleNo);
454
455 /**
456 \brief
457 Return the sample data for the given tag. If an attempt is made to
458 access data that isn't tagged an exception will be thrown.
459 \param tag - Input - the tag key.
460 */
461 DataAbstract::ValueType::value_type*
462 getSampleDataByTag(int tag);
463
464 /**
465 \brief
466 Return a view into the data for the data point specified.
467 NOTE: Construction of the DataArrayView is a relatively expensive
468 operation.
469 \param sampleNo - Input -
470 \param dataPointNo - Input -
471 */
472 inline
473 DataArrayView
474 getDataPoint(int sampleNo,
475 int dataPointNo)
476 {
477 return m_data->getDataPoint(sampleNo,dataPointNo);
478 }
479
480 /**
481 \brief
482 Return a reference to the data point shape.
483 */
484 const DataArrayView::ShapeType&
485 getDataPointShape() const;
486
487 /**
488 \brief
489 Return data point shape as a tuple of integers:
490 */
491 boost::python::tuple
492 getShapeTuple() const;
493
494 /**
495 \brief
496 Return the size of the data point. It is the product of the
497 data point shape dimensions.
498 */
499 int
500 getDataPointSize() const;
501
502 /**
503 \brief
504 Return the number of doubles stored for Data.
505 */
506 DataArrayView::ValueType::size_type
507 getLength() const;
508
509 /**
510 \brief
511 Interpolates this onto the given functionspace and returns the result as a Data object.
512 */
513 Data
514 interpolate(const FunctionSpace& functionspace) const;
515
516 /**
517 \brief
518 Calculates the gradient of the data at the data points of functionspace.
519 If functionspace is not present the function space of Function(getDomain()) is used.
520 */
521 Data
522 gradOn(const FunctionSpace& functionspace) const;
523
524 Data
525 grad() const;
526
527 /**
528 \brief
529 Calculate the integral over the function space domain.
530 */
531 boost::python::numeric::array
532 integrate() const;
533
534 /**
535 \brief
536 Return a Data with a 1 for +ive values and a 0 for 0 or -ive values.
537 */
538 Data
539 wherePositive() const;
540
541 /**
542 \brief
543 Return a Data with a 1 for +ive values and a 0 for -ive values.
544 */
545 Data
546 whereNonNegative() const;
547
548 /**
549 \brief
550 Return a Data with a 1 for -ive values and a 0 for +ive or 0 values.
551 */
552 Data
553 whereNegative() const;
554
555 /**
556 \brief
557 Return a Data with a 1 for 0 values a 0 for +ive or -ive.
558 */
559 Data
560 whereZero() const;
561
562 /**
563 \brief
564 Return the sin of Data.
565 */
566 Data
567 sin() const;
568
569 /**
570 \brief
571 Return the cos of Data.
572 */
573 Data
574 cos() const;
575
576 /**
577 \brief
578 Return the tan of Data.
579 */
580 Data
581 tan() const;
582
583 /**
584 \brief
585 Return the log to base 10 of Data.
586 */
587 Data
588 log() const;
589
590 /**
591 \brief
592 Return the natural log of Data.
593 */
594 Data
595 ln() const;
596
597 /**
598 \brief
599 Return a Data containing a slice of this Data.
600 */
601 Data
602 getSlice(const DataArrayView::RegionType& region) const;
603
604 /**
605 \brief
606 Copy the specified region from the given value.
607 \param value - Input - Data to copy from.
608 \param region - Input - Region to copy.
609 */
610 void
611 setSlice(const Data& value,
612 const DataArrayView::RegionType& region);
613
614 /**
615 \brief
616 Return the maximum absolute value.
617 */
618 double
619 Lsup() const;
620
621 /**
622 \brief
623 Return the maximum value.
624 */
625 double
626 sup() const;
627
628 /**
629 \brief
630 Return the minimum value.
631 */
632 double
633 inf() const;
634
635 /**
636 \brief
637 Returns a slice from this.
638 */
639 Data
640 getItem(const boost::python::object& key) const;
641
642 /**
643 \brief
644 Copies slice from value into this.
645 */
646 void
647 setItem(const boost::python::object& key,
648 const Data& value);
649
650 /**
651 \brief
652 Convert the underlying data type to match the RHS.
653 \param right - Input - data type to match.
654 */
655 void
656 typeMatch(const Data& right);
657
658 /**
659 \brief
660 Returns true if this can be interpolated to functionspace.
661 */
662 bool
663 probeInterpolation(const FunctionSpace& functionspace) const;
664
665 /**
666 \brief
667 Assign the given value to the tag. Implicitly converts this
668 object to type DataTagged. Throws an exception if this object
669 cannot be converted to a DataTagged object.
670 \param tagKey - Input - Integer key.
671 \param value - Input - Value to associate with given key.
672 */
673 void
674 setTaggedValue(int tagKey,
675 const boost::python::object& value);
676
677 /**
678 \brief
679 Assign the given value to the tag. Implicitly converts this
680 object to type DataTagged. Throws an exception if this object
681 cannot be converted to a DataTagged object.
682 \param tagKey - Input - Integer key.
683 \param value - Input - Value to associate with given key.
684 */
685 void
686 setTaggedValue(int tagKey,
687 const DataArrayView& value);
688
689 private:
690
691 /**
692 \brief
693 Construct a Data object of the appropriate type.
694 */
695 template <class IValueType>
696 void
697 initialise(const IValueType& value,
698 const FunctionSpace& what,
699 bool expanded);
700
701 /**
702 \brief
703 Reshape the data point if the data point is currently rank 0.
704 Will throw an exception if the data points are not rank 0.
705 The original data point value is used for all values of the new
706 data point.
707 */
708 void
709 reshapeDataPoint(const DataArrayView::ShapeType& shape);
710
711 //
712 // pointer to the actual data
713 boost::shared_ptr<DataAbstract> m_data;
714
715 };
716
717 template <class IValueType>
718 void
719 Data::initialise(const IValueType& value,
720 const FunctionSpace& what,
721 bool expanded)
722 {
723 //
724 // Construct a Data object of the appropriate type.
725 // Construct the object first as there seems to be a bug which causes
726 // undefined behaviour if an exception is thrown during construction
727 // within the shared_ptr constructor.
728 if (expanded) {
729 DataAbstract* temp=new DataExpanded(value,what);
730 m_data=boost::shared_ptr<DataAbstract>(temp);
731 } else {
732 DataAbstract* temp=new DataConstant(value,what);
733 m_data=boost::shared_ptr<DataAbstract>(temp);
734 }
735 }
736
737 inline
738 DataAbstract::ValueType::value_type*
739 Data::getSampleData(DataAbstract::ValueType::size_type sampleNo)
740 {
741 return m_data->getSampleData(sampleNo);
742 }
743
744 inline
745 DataAbstract::ValueType::value_type*
746 Data::getSampleDataByTag(int tag)
747 {
748 return m_data->getSampleDataByTag(tag);
749 }
750
751 inline
752 void
753 Data::operandCheck(const Data& right) const
754 {
755 return m_data->operandCheck(*(right.m_data.get()));
756 }
757
758 inline
759 int
760 Data::getNumSamples() const
761 {
762 return m_data->getNumSamples();
763 }
764
765 inline
766 std::string
767 Data::toString() const
768 {
769 return m_data->toString();
770 }
771
772 /**
773 \brief
774 Operator+
775 Takes two Data objects.
776 */
777 Data operator+(const Data& left, const Data& right);
778
779 /**
780 \brief
781 Operator-
782 Takes two Data objects.
783 */
784 Data operator-(const Data& left, const Data& right);
785
786 /**
787 \brief
788 Operator*
789 Takes two Data objects.
790 */
791 Data operator*(const Data& left, const Data& right);
792
793 /**
794 \brief
795 Operator/
796 Takes two Data objects.
797 */
798 Data operator/(const Data& left, const Data& right);
799
800 /**
801 \brief
802 Operator+
803 Takes LHS Data object and RHS python::object.
804 python::object must be convertable to Data type.
805 */
806 Data operator+(const Data& left, const boost::python::object& right);
807
808 /**
809 \brief
810 Operator-
811 Takes LHS Data object and RHS python::object.
812 python::object must be convertable to Data type.
813 */
814 Data operator-(const Data& left, const boost::python::object& right);
815
816 /**
817 \brief
818 Operator*
819 Takes LHS Data object and RHS python::object.
820 python::object must be convertable to Data type.
821 */
822 Data operator*(const Data& left, const boost::python::object& right);
823
824 /**
825 \brief
826 Operator/
827 Takes LHS Data object and RHS python::object.
828 python::object must be convertable to Data type.
829 */
830 Data operator/(const Data& left, const boost::python::object& right);
831
832 /**
833 \brief
834 Operator+
835 Takes LHS python::object and RHS Data object.
836 python::object must be convertable to Data type.
837 */
838 Data operator+(const boost::python::object& left, const Data& right);
839
840 /**
841 \brief
842 Operator-
843 Takes LHS python::object and RHS Data object.
844 python::object must be convertable to Data type.
845 */
846 Data operator-(const boost::python::object& left, const Data& right);
847
848 /**
849 \brief
850 Operator*
851 Takes LHS python::object and RHS Data object.
852 python::object must be convertable to Data type.
853 */
854 Data operator*(const boost::python::object& left, const Data& right);
855
856 /**
857 \brief
858 Operator/
859 Takes LHS python::object and RHS Data object.
860 python::object must be convertable to Data type.
861 */
862 Data operator/(const boost::python::object& left, const Data& right);
863
864 /**
865 \brief
866 Output operator
867 */
868 std::ostream& operator<<(std::ostream& o, const Data& data);
869
870 /**
871 \brief
872 Return true if operands are equivalent, else return false.
873 NB: this operator does very little at this point, and isn't to
874 be relied on. Requires further implementation.
875 */
876 bool operator==(const Data& left, const Data& right);
877
878 template <class BinaryFunction>
879 inline
880 void
881 Data::binaryOp(const Data& right,
882 BinaryFunction operation)
883 {
884 //
885 // if this has a rank of zero promote it to the rank of the RHS
886 if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {
887 reshapeDataPoint(right.getPointDataView().getShape());
888 }
889 //
890 // initially make the temporary a shallow copy
891 Data tempRight(right);
892 if (getFunctionSpace()!=right.getFunctionSpace()) {
893 if (right.probeInterpolation(getFunctionSpace())) {
894 //
895 // an interpolation is required so create a new Data
896 tempRight=Data(right,this->getFunctionSpace());
897 } else if (probeInterpolation(right.getFunctionSpace())) {
898 //
899 // interpolate onto the RHS function space
900 Data tempLeft(*this,right.getFunctionSpace());
901 m_data=tempLeft.m_data;
902 }
903 }
904 operandCheck(tempRight);
905 //
906 // ensure this has the right type for the RHS
907 typeMatch(tempRight);
908 //
909 // Need to cast to the concrete types so that the correct binaryOp
910 // is called.
911 if (isExpanded()) {
912 //
913 // Expanded data will be done in parallel, the right hand side can be
914 // of any data type
915 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
916 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
917 escript::binaryOp(*leftC,*(tempRight.m_data.get()),operation);
918 } else if (isTagged()) {
919 //
920 // Tagged data is operated on serially, the right hand side can be
921 // either DataConstant or DataTagged
922 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
923 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
924 if (right.isTagged()) {
925 DataTagged* rightC=dynamic_cast<DataTagged*>(tempRight.m_data.get());
926 EsysAssert((rightC!=0), "Programming error - casting to DataTagged.");
927 escript::binaryOp(*leftC,*rightC,operation);
928 } else {
929 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
930 EsysAssert((rightC!=0), "Programming error - casting to DataConstant.");
931 escript::binaryOp(*leftC,*rightC,operation);
932 }
933 } else {
934 //
935 // can only be DataConstant
936 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
937 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
938 EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
939 escript::binaryOp(*leftC,*rightC,operation);
940 }
941 }
942
943 template <class BinaryFunction>
944 inline
945 void
946 Data::binaryOp(const boost::python::object& right,
947 BinaryFunction operation)
948 {
949 DataArray temp(right);
950 //
951 // if this has a rank of zero promote it to the rank of the RHS.
952 if (getPointDataView().getRank()==0 && temp.getView().getRank()!=0) {
953 reshapeDataPoint(temp.getView().getShape());
954 }
955 //
956 // Always allow scalar values for the RHS but check other shapes
957 if (temp.getView().getRank()!=0) {
958 if (!getPointDataView().checkShape(temp.getView().getShape())) {
959 throw DataException(getPointDataView().createShapeErrorMessage(
960 "Error - RHS shape doesn't match LHS shape.",temp.getView().getShape()));
961 }
962 }
963
964 if (isExpanded()) {
965 //
966 // Expanded data will be done in parallel
967 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
968 EsysAssert((leftC!=0),"Programming error - casting to DataExpanded.");
969 escript::binaryOp(*leftC,temp.getView(),operation);
970 } else if (isTagged()) {
971 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
972 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
973 escript::binaryOp(*leftC,temp.getView(),operation);
974 } else {
975 //
976 // can only be DataConstant
977 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
978 EsysAssert((leftC!=0),"Programming error - casting to DataConstant.");
979 escript::binaryOp(*leftC,temp.getView(),operation);
980 }
981 }
982
983 template <class UnaryFunction>
984 inline
985 void
986 Data::unaryOp(UnaryFunction operation)
987 {
988 if (isExpanded()) {
989 //
990 // Expanded data will be done in parallel
991 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
992 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
993 escript::unaryOp(*leftC,operation);
994 } else if (isTagged()) {
995 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
996 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
997 escript::unaryOp(*leftC,operation);
998 } else {
999 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1000 EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1001 escript::unaryOp(*leftC,operation);
1002 }
1003 }
1004
1005 template <class UnaryFunction>
1006 inline
1007 double
1008 Data::algorithm(UnaryFunction operation) const
1009 {
1010 if (isExpanded()) {
1011 //
1012 // Expanded data will be done in parallel
1013 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1014 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1015 return escript::algorithm(*leftC,operation);
1016 }
1017 else if (isTagged()) {
1018 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1019 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1020 return escript::algorithm(*leftC,operation);
1021 } else {
1022 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1023 EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1024 return escript::algorithm(*leftC,operation);
1025 }
1026 }
1027
1028 template <class UnaryFunction>
1029 inline
1030 Data
1031 unaryOp(const Data& other,
1032 UnaryFunction operation)
1033 {
1034 //
1035 // Perform the given operation on a copy of the input data and return the result
1036 Data result;
1037 //
1038 // perform a deep copy
1039 result.copy(other);
1040 result.unaryOp(operation);
1041 return result;
1042 }
1043
1044 }
1045
1046 #endif

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.26