/[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 100 - (show annotations)
Wed Dec 15 03:48:48 2004 UTC (14 years, 5 months ago) by jgs
File MIME type: text/plain
File size: 26799 byte(s)
*** empty log message ***

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 Note: removed for now - this version not needed, and breaks escript.cpp
685 */
686 /*
687 void
688 setTaggedValue(int tagKey,
689 const DataArrayView& value);
690 */
691
692 private:
693
694 /**
695 \brief
696 Construct a Data object of the appropriate type.
697 */
698 template <class IValueType>
699 void
700 initialise(const IValueType& value,
701 const FunctionSpace& what,
702 bool expanded);
703
704 /**
705 \brief
706 Reshape the data point if the data point is currently rank 0.
707 Will throw an exception if the data points are not rank 0.
708 The original data point value is used for all values of the new
709 data point.
710 */
711 void
712 reshapeDataPoint(const DataArrayView::ShapeType& shape);
713
714 //
715 // pointer to the actual data
716 boost::shared_ptr<DataAbstract> m_data;
717
718 };
719
720 template <class IValueType>
721 void
722 Data::initialise(const IValueType& value,
723 const FunctionSpace& what,
724 bool expanded)
725 {
726 //
727 // Construct a Data object of the appropriate type.
728 // Construct the object first as there seems to be a bug which causes
729 // undefined behaviour if an exception is thrown during construction
730 // within the shared_ptr constructor.
731 if (expanded) {
732 DataAbstract* temp=new DataExpanded(value,what);
733 m_data=boost::shared_ptr<DataAbstract>(temp);
734 } else {
735 DataAbstract* temp=new DataConstant(value,what);
736 m_data=boost::shared_ptr<DataAbstract>(temp);
737 }
738 }
739
740 inline
741 DataAbstract::ValueType::value_type*
742 Data::getSampleData(DataAbstract::ValueType::size_type sampleNo)
743 {
744 return m_data->getSampleData(sampleNo);
745 }
746
747 inline
748 DataAbstract::ValueType::value_type*
749 Data::getSampleDataByTag(int tag)
750 {
751 return m_data->getSampleDataByTag(tag);
752 }
753
754 inline
755 void
756 Data::operandCheck(const Data& right) const
757 {
758 return m_data->operandCheck(*(right.m_data.get()));
759 }
760
761 inline
762 int
763 Data::getNumSamples() const
764 {
765 return m_data->getNumSamples();
766 }
767
768 inline
769 std::string
770 Data::toString() const
771 {
772 return m_data->toString();
773 }
774
775 /**
776 \brief
777 Operator+
778 Takes two Data objects.
779 */
780 Data operator+(const Data& left, const Data& right);
781
782 /**
783 \brief
784 Operator-
785 Takes two Data objects.
786 */
787 Data operator-(const Data& left, const Data& right);
788
789 /**
790 \brief
791 Operator*
792 Takes two Data objects.
793 */
794 Data operator*(const Data& left, const Data& right);
795
796 /**
797 \brief
798 Operator/
799 Takes two Data objects.
800 */
801 Data operator/(const Data& left, const Data& right);
802
803 /**
804 \brief
805 Operator+
806 Takes LHS Data object and RHS python::object.
807 python::object must be convertable to Data type.
808 */
809 Data operator+(const Data& left, const boost::python::object& right);
810
811 /**
812 \brief
813 Operator-
814 Takes LHS Data object and RHS python::object.
815 python::object must be convertable to Data type.
816 */
817 Data operator-(const Data& left, const boost::python::object& right);
818
819 /**
820 \brief
821 Operator*
822 Takes LHS Data object and RHS python::object.
823 python::object must be convertable to Data type.
824 */
825 Data operator*(const Data& left, const boost::python::object& right);
826
827 /**
828 \brief
829 Operator/
830 Takes LHS Data object and RHS python::object.
831 python::object must be convertable to Data type.
832 */
833 Data operator/(const Data& left, const boost::python::object& right);
834
835 /**
836 \brief
837 Operator+
838 Takes LHS python::object and RHS Data object.
839 python::object must be convertable to Data type.
840 */
841 Data operator+(const boost::python::object& left, const Data& right);
842
843 /**
844 \brief
845 Operator-
846 Takes LHS python::object and RHS Data object.
847 python::object must be convertable to Data type.
848 */
849 Data operator-(const boost::python::object& left, const Data& right);
850
851 /**
852 \brief
853 Operator*
854 Takes LHS python::object and RHS Data object.
855 python::object must be convertable to Data type.
856 */
857 Data operator*(const boost::python::object& left, const Data& right);
858
859 /**
860 \brief
861 Operator/
862 Takes LHS python::object and RHS Data object.
863 python::object must be convertable to Data type.
864 */
865 Data operator/(const boost::python::object& left, const Data& right);
866
867 /**
868 \brief
869 Output operator
870 */
871 std::ostream& operator<<(std::ostream& o, const Data& data);
872
873 /**
874 \brief
875 Return true if operands are equivalent, else return false.
876 NB: this operator does very little at this point, and isn't to
877 be relied on. Requires further implementation.
878 */
879 bool operator==(const Data& left, const Data& right);
880
881 template <class BinaryFunction>
882 inline
883 void
884 Data::binaryOp(const Data& right,
885 BinaryFunction operation)
886 {
887 //
888 // if this has a rank of zero promote it to the rank of the RHS
889 if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {
890 reshapeDataPoint(right.getPointDataView().getShape());
891 }
892 //
893 // initially make the temporary a shallow copy
894 Data tempRight(right);
895 if (getFunctionSpace()!=right.getFunctionSpace()) {
896 if (right.probeInterpolation(getFunctionSpace())) {
897 //
898 // an interpolation is required so create a new Data
899 tempRight=Data(right,this->getFunctionSpace());
900 } else if (probeInterpolation(right.getFunctionSpace())) {
901 //
902 // interpolate onto the RHS function space
903 Data tempLeft(*this,right.getFunctionSpace());
904 m_data=tempLeft.m_data;
905 }
906 }
907 operandCheck(tempRight);
908 //
909 // ensure this has the right type for the RHS
910 typeMatch(tempRight);
911 //
912 // Need to cast to the concrete types so that the correct binaryOp
913 // is called.
914 if (isExpanded()) {
915 //
916 // Expanded data will be done in parallel, the right hand side can be
917 // of any data type
918 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
919 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
920 escript::binaryOp(*leftC,*(tempRight.m_data.get()),operation);
921 } else if (isTagged()) {
922 //
923 // Tagged data is operated on serially, the right hand side can be
924 // either DataConstant or DataTagged
925 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
926 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
927 if (right.isTagged()) {
928 DataTagged* rightC=dynamic_cast<DataTagged*>(tempRight.m_data.get());
929 EsysAssert((rightC!=0), "Programming error - casting to DataTagged.");
930 escript::binaryOp(*leftC,*rightC,operation);
931 } else {
932 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
933 EsysAssert((rightC!=0), "Programming error - casting to DataConstant.");
934 escript::binaryOp(*leftC,*rightC,operation);
935 }
936 } else {
937 //
938 // can only be DataConstant
939 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
940 DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
941 EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
942 escript::binaryOp(*leftC,*rightC,operation);
943 }
944 }
945
946 template <class BinaryFunction>
947 inline
948 void
949 Data::binaryOp(const boost::python::object& right,
950 BinaryFunction operation)
951 {
952 DataArray temp(right);
953 //
954 // if this has a rank of zero promote it to the rank of the RHS.
955 if (getPointDataView().getRank()==0 && temp.getView().getRank()!=0) {
956 reshapeDataPoint(temp.getView().getShape());
957 }
958 //
959 // Always allow scalar values for the RHS but check other shapes
960 if (temp.getView().getRank()!=0) {
961 if (!getPointDataView().checkShape(temp.getView().getShape())) {
962 throw DataException(getPointDataView().createShapeErrorMessage(
963 "Error - RHS shape doesn't match LHS shape.",temp.getView().getShape()));
964 }
965 }
966
967 if (isExpanded()) {
968 //
969 // Expanded data will be done in parallel
970 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
971 EsysAssert((leftC!=0),"Programming error - casting to DataExpanded.");
972 escript::binaryOp(*leftC,temp.getView(),operation);
973 } else if (isTagged()) {
974 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
975 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
976 escript::binaryOp(*leftC,temp.getView(),operation);
977 } else {
978 //
979 // can only be DataConstant
980 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
981 EsysAssert((leftC!=0),"Programming error - casting to DataConstant.");
982 escript::binaryOp(*leftC,temp.getView(),operation);
983 }
984 }
985
986 template <class UnaryFunction>
987 inline
988 void
989 Data::unaryOp(UnaryFunction operation)
990 {
991 if (isExpanded()) {
992 //
993 // Expanded data will be done in parallel
994 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
995 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
996 escript::unaryOp(*leftC,operation);
997 } else if (isTagged()) {
998 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
999 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1000 escript::unaryOp(*leftC,operation);
1001 } else {
1002 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1003 EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1004 escript::unaryOp(*leftC,operation);
1005 }
1006 }
1007
1008 template <class UnaryFunction>
1009 inline
1010 double
1011 Data::algorithm(UnaryFunction operation) const
1012 {
1013 if (isExpanded()) {
1014 //
1015 // Expanded data will be done in parallel
1016 DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1017 EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1018 return escript::algorithm(*leftC,operation);
1019 }
1020 else if (isTagged()) {
1021 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1022 EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1023 return escript::algorithm(*leftC,operation);
1024 } else {
1025 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1026 EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1027 return escript::algorithm(*leftC,operation);
1028 }
1029 }
1030
1031 template <class UnaryFunction>
1032 inline
1033 Data
1034 unaryOp(const Data& other,
1035 UnaryFunction operation)
1036 {
1037 //
1038 // Perform the given operation on a copy of the input data and return the result
1039 Data result;
1040 //
1041 // perform a deep copy
1042 result.copy(other);
1043 result.unaryOp(operation);
1044 return result;
1045 }
1046
1047 }
1048
1049 #endif

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26