/[escript]/branches/schroedinger/escript/src/Data.h
ViewVC logotype

Annotation of /branches/schroedinger/escript/src/Data.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1868 - (hide annotations)
Thu Oct 9 06:30:49 2008 UTC (13 years, 1 month ago) by jfenwick
File MIME type: text/plain
File size: 88676 byte(s)
Branch commit.
Bulk resolve for + - * /

1 jgs 94
2 ksteube 1312 /*******************************************************
3 ksteube 1811 *
4     * Copyright (c) 2003-2008 by University of Queensland
5     * Earth Systems Science Computational Center (ESSCC)
6     * http://www.uq.edu.au/esscc
7     *
8     * Primary Business: Queensland, Australia
9     * Licensed under the Open Software License version 3.0
10     * http://www.opensource.org/licenses/osl-3.0.php
11     *
12     *******************************************************/
13 ksteube 1312
14 ksteube 1811
15 jgs 121 /** \file Data.h */
16 jgs 94
17     #ifndef DATA_H
18     #define DATA_H
19 woo409 757 #include "system_dep.h"
20 jgs 94
21 jgs 474 #include "DataAbstract.h"
22     #include "DataAlgorithm.h"
23     #include "FunctionSpace.h"
24     #include "BinaryOp.h"
25     #include "UnaryOp.h"
26     #include "DataException.h"
27 jfenwick 1796 #include "DataTypes.h"
28 jgs 94
29     extern "C" {
30 jgs 474 #include "DataC.h"
31 ksteube 1312 /* #include "paso/Paso.h" doesn't belong in this file...causes trouble for BruceFactory.cpp */
32 jgs 94 }
33    
34 ksteube 1312 #include "esysmpi.h"
35 jgs 94 #include <string>
36     #include <algorithm>
37 jfenwick 1693 #include <sstream>
38 jgs 94
39 jfenwick 1693
40 jgs 94 #include <boost/shared_ptr.hpp>
41     #include <boost/python/object.hpp>
42     #include <boost/python/tuple.hpp>
43     #include <boost/python/numeric.hpp>
44    
45 jgs 121 namespace escript {
46    
47     //
48 jgs 149 // Forward declaration for various implementations of Data.
49 jgs 121 class DataConstant;
50     class DataTagged;
51     class DataExpanded;
52    
53 jgs 94 /**
54     \brief
55 jfenwick 1802 Data represents a collection of datapoints.
56 jgs 94
57     Description:
58 jfenwick 1802 Internally, the datapoints are actually stored by a DataAbstract object.
59     The specific instance of DataAbstract used may vary over the lifetime
60     of the Data object.
61     Some methods on this class return references (eg getShape()).
62     These references should not be used after an operation which changes the underlying DataAbstract object.
63     Doing so will lead to invalid memory access.
64     This should not affect any methods exposed via boost::python.
65 jgs 94 */
66     class Data {
67    
68     public:
69    
70 jgs 110 // These typedefs allow function names to be cast to pointers
71     // to functions of the appropriate type when calling unaryOp etc.
72 jgs 94 typedef double (*UnaryDFunPtr)(double);
73     typedef double (*BinaryDFunPtr)(double,double);
74    
75 gross 854
76 jgs 94 /**
77 jgs 102 Constructors.
78     */
79    
80     /**
81 jgs 94 \brief
82     Default constructor.
83     Creates a DataEmpty object.
84     */
85 woo409 757 ESCRIPT_DLL_API
86 jgs 94 Data();
87    
88     /**
89     \brief
90     Copy constructor.
91     WARNING: Only performs a shallow copy.
92     */
93 woo409 757 ESCRIPT_DLL_API
94 jgs 94 Data(const Data& inData);
95    
96     /**
97     \brief
98     Constructor from another Data object. If "what" is different from the
99 jgs 102 function space of inData the inData are tried to be interpolated to what,
100 jgs 94 otherwise a shallow copy of inData is returned.
101     */
102 woo409 757 ESCRIPT_DLL_API
103 jgs 94 Data(const Data& inData,
104     const FunctionSpace& what);
105    
106     /**
107 jfenwick 1796 \brief Copy Data from an existing vector
108     */
109 jgs 94
110 woo409 757 ESCRIPT_DLL_API
111 jfenwick 1796 Data(const DataTypes::ValueType& value,
112     const DataTypes::ShapeType& shape,
113     const FunctionSpace& what=FunctionSpace(),
114     bool expanded=false);
115 jgs 94
116     /**
117     \brief
118     Constructor which creates a Data from a DataArrayView shape.
119    
120     \param value - Input - Single value applied to all Data.
121     \param dataPointShape - Input - The shape of each data point.
122     \param what - Input - A description of what this data represents.
123     \param expanded - Input - Flag, if true fill the entire container with
124     the given value. Otherwise a more efficient storage
125     mechanism will be used.
126     */
127 woo409 757 ESCRIPT_DLL_API
128 jgs 94 Data(double value,
129 jfenwick 1796 const DataTypes::ShapeType& dataPointShape=DataTypes::ShapeType(),
130 jgs 94 const FunctionSpace& what=FunctionSpace(),
131     bool expanded=false);
132    
133     /**
134     \brief
135     Constructor which performs a deep copy of a region from another Data object.
136    
137     \param inData - Input - Input Data object.
138     \param region - Input - Region to copy.
139     */
140 woo409 757 ESCRIPT_DLL_API
141 jgs 94 Data(const Data& inData,
142 jfenwick 1796 const DataTypes::RegionType& region);
143 jgs 94
144     /**
145     \brief
146     Constructor which copies data from a python numarray.
147    
148     \param value - Input - Data value for a single point.
149     \param what - Input - A description of what this data represents.
150     \param expanded - Input - Flag, if true fill the entire container with
151     the value. Otherwise a more efficient storage
152     mechanism will be used.
153     */
154 woo409 757 ESCRIPT_DLL_API
155 jgs 94 Data(const boost::python::numeric::array& value,
156     const FunctionSpace& what=FunctionSpace(),
157     bool expanded=false);
158    
159     /**
160     \brief
161     Constructor which copies data from any object that can be converted into
162     a python numarray.
163    
164     \param value - Input - Input data.
165     \param what - Input - A description of what this data represents.
166     \param expanded - Input - Flag, if true fill the entire container with
167     the value. Otherwise a more efficient storage
168     mechanism will be used.
169     */
170 woo409 757 ESCRIPT_DLL_API
171 jgs 94 Data(const boost::python::object& value,
172     const FunctionSpace& what=FunctionSpace(),
173     bool expanded=false);
174    
175     /**
176     \brief
177     Constructor which creates a DataConstant.
178     Copies data from any object that can be converted
179     into a numarray. All other parameters are copied from other.
180    
181     \param value - Input - Input data.
182     \param other - Input - contains all other parameters.
183     */
184 woo409 757 ESCRIPT_DLL_API
185 jgs 94 Data(const boost::python::object& value,
186     const Data& other);
187    
188     /**
189     \brief
190     Constructor which creates a DataConstant of "shape" with constant value.
191     */
192 woo409 757 ESCRIPT_DLL_API
193 matt 1327 Data(double value,
194     const boost::python::tuple& shape=boost::python::make_tuple(),
195 jgs 94 const FunctionSpace& what=FunctionSpace(),
196     bool expanded=false);
197 jfenwick 1796
198    
199    
200 jgs 151 /**
201 jfenwick 1796 \brief Create a Data using an existing DataAbstract. Warning: The new object assumes ownership of the pointer!
202     Once you have passed the pointer, do not delete it.
203     */
204     ESCRIPT_DLL_API
205     Data(DataAbstract* underlyingdata);
206    
207    
208     /**
209 jfenwick 1868 \brief Create a Data based on the supplied DataAbstract
210     */
211     ESCRIPT_DLL_API
212     Data(DataAbstract_ptr underlyingdata);
213    
214     /**
215 jgs 151 \brief
216     Destructor
217     */
218 woo409 757 ESCRIPT_DLL_API
219 jgs 151 ~Data();
220 jgs 94
221     /**
222 jfenwick 1799 \brief Make this object a deep copy of "other".
223 jgs 94 */
224 woo409 757 ESCRIPT_DLL_API
225 jgs 94 void
226 jgs 102 copy(const Data& other);
227 jgs 94
228     /**
229 jfenwick 1799 \brief Return a pointer to a deep copy of this object.
230     */
231     ESCRIPT_DLL_API
232     Data*
233     copySelf();
234    
235    
236 jfenwick 1864 /**
237     \brief produce a delayed evaluation version of this Data.
238     */
239     ESCRIPT_DLL_API
240     Data
241     delay();
242 jfenwick 1799
243     /**
244 jgs 102 Member access methods.
245 jgs 94 */
246    
247     /**
248     \brief
249 matt 1327 switches on update protection
250 gross 783
251     */
252     ESCRIPT_DLL_API
253     void
254     setProtection();
255    
256     /**
257     \brief
258     Returns trueif the data object is protected against update
259    
260     */
261     ESCRIPT_DLL_API
262     bool
263     isProtected() const;
264 gross 1034
265 gross 783 /**
266     \brief
267 matt 1327 Return the values of a data point on this process
268 jgs 117 */
269 woo409 757 ESCRIPT_DLL_API
270 jgs 121 const boost::python::numeric::array
271 gross 1034 getValueOfDataPoint(int dataPointNo);
272 jgs 117
273     /**
274     \brief
275 gross 1034 sets the values of a data-point from a python object on this process
276 jgs 121 */
277 woo409 757 ESCRIPT_DLL_API
278 gross 921 void
279 gross 1034 setValueOfDataPointToPyObject(int dataPointNo, const boost::python::object& py_object);
280 jgs 121
281     /**
282     \brief
283 gross 1034 sets the values of a data-point from a numarray object on this process
284 jgs 121 */
285 woo409 757 ESCRIPT_DLL_API
286 jgs 149 void
287 gross 1034 setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array&);
288 jgs 149
289     /**
290     \brief
291 gross 922 sets the values of a data-point on this process
292     */
293     ESCRIPT_DLL_API
294     void
295     setValueOfDataPoint(int dataPointNo, const double);
296    
297     /**
298     \brief
299 gross 921 Return the value of the specified data-point across all processors
300     */
301     ESCRIPT_DLL_API
302     const boost::python::numeric::array
303     getValueOfGlobalDataPoint(int procNo, int dataPointNo);
304    
305     /**
306     \brief
307 jgs 149 Return the tag number associated with the given data-point.
308    
309     */
310 woo409 757 ESCRIPT_DLL_API
311 jgs 149 int
312     getTagNumber(int dpno);
313    
314     /**
315     \brief
316 jgs 94 Return the C wrapper for the Data object.
317     */
318 woo409 757 ESCRIPT_DLL_API
319 jgs 102 escriptDataC
320     getDataC();
321 jgs 94
322 jfenwick 1796
323    
324    
325    
326    
327     // REMOVE ME
328     // ESCRIPT_DLL_API
329     // void
330     // CompareDebug(const Data& rd);
331    
332    
333 jgs 94 /**
334     \brief
335     Return the C wrapper for the Data object - const version.
336     */
337 woo409 757 ESCRIPT_DLL_API
338 jgs 102 escriptDataC
339     getDataC() const;
340 jgs 94
341     /**
342     \brief
343 jfenwick 1693 Write the data as a string. For large amounts of data, a summary is printed.
344 jgs 94 */
345 woo409 757 ESCRIPT_DLL_API
346 jgs 102 std::string
347 jfenwick 1693 toString() const;
348 jgs 94
349     /**
350     \brief
351 jgs 102 Whatever the current Data type make this into a DataExpanded.
352 jgs 94 */
353 woo409 757 ESCRIPT_DLL_API
354 jgs 94 void
355     expand();
356    
357     /**
358     \brief
359 jgs 102 If possible convert this Data to DataTagged. This will only allow
360 jgs 94 Constant data to be converted to tagged. An attempt to convert
361     Expanded data to tagged will throw an exception.
362 jgs 544 ==>*
363 jgs 94 */
364 woo409 757 ESCRIPT_DLL_API
365 jgs 94 void
366     tag();
367    
368     /**
369     \brief
370     Return true if this Data is expanded.
371     */
372 woo409 757 ESCRIPT_DLL_API
373 jgs 94 bool
374     isExpanded() const;
375    
376     /**
377     \brief
378     Return true if this Data is tagged.
379     */
380 woo409 757 ESCRIPT_DLL_API
381 jgs 94 bool
382     isTagged() const;
383    
384     /**
385     \brief
386 jgs 102 Return true if this Data is constant.
387 jgs 94 */
388 woo409 757 ESCRIPT_DLL_API
389 jgs 94 bool
390 jgs 102 isConstant() const;
391 jgs 94
392     /**
393 jfenwick 1864 \brief Return true if this Data is lazy.
394     */
395     ESCRIPT_DLL_API
396     bool
397     isLazy() const;
398    
399     /**
400 jfenwick 1865 \brief Return true if this data is ready.
401     */
402     ESCRIPT_DLL_API
403     bool
404     isReady() const;
405    
406     /**
407 jgs 94 \brief
408 jfenwick 1803 Return true if this Data holds an instance of DataEmpty. This is _not_ the same as asking if the object
409     contains datapoints.
410 jgs 94 */
411 woo409 757 ESCRIPT_DLL_API
412 jgs 94 bool
413 jgs 102 isEmpty() const;
414 jgs 94
415     /**
416     \brief
417     Return the function space.
418     */
419 woo409 757 ESCRIPT_DLL_API
420 jgs 94 inline
421     const FunctionSpace&
422     getFunctionSpace() const
423     {
424     return m_data->getFunctionSpace();
425     }
426    
427     /**
428     \brief
429     Return a copy of the function space.
430     */
431 woo409 757 ESCRIPT_DLL_API
432 jgs 94 const FunctionSpace
433     getCopyOfFunctionSpace() const;
434    
435     /**
436     \brief
437     Return the domain.
438     */
439 woo409 757 ESCRIPT_DLL_API
440 jgs 94 inline
441 jfenwick 1820 // const AbstractDomain&
442     const_Domain_ptr
443 jgs 94 getDomain() const
444     {
445     return getFunctionSpace().getDomain();
446     }
447    
448 jfenwick 1822
449 jgs 94 /**
450     \brief
451 jfenwick 1822 Return the domain.
452     TODO: For internal use only. This should be removed.
453     */
454     ESCRIPT_DLL_API
455     inline
456     // const AbstractDomain&
457     Domain_ptr
458     getDomainPython() const
459     {
460     return getFunctionSpace().getDomainPython();
461     }
462    
463     /**
464     \brief
465 jgs 94 Return a copy of the domain.
466     */
467 woo409 757 ESCRIPT_DLL_API
468 jgs 94 const AbstractDomain
469     getCopyOfDomain() const;
470    
471     /**
472     \brief
473     Return the rank of the point data.
474     */
475 woo409 757 ESCRIPT_DLL_API
476 jgs 94 inline
477     int
478     getDataPointRank() const
479     {
480 jfenwick 1796 // return m_data->getPointDataView().getRank();
481     return m_data->getRank();
482 jgs 94 }
483    
484     /**
485     \brief
486 gross 921 Return the number of data points
487     */
488     ESCRIPT_DLL_API
489     inline
490     int
491     getNumDataPoints() const
492     {
493     return getNumSamples() * getNumDataPointsPerSample();
494     }
495     /**
496     \brief
497 jgs 102 Return the number of samples.
498 jgs 94 */
499 woo409 757 ESCRIPT_DLL_API
500 jgs 94 inline
501     int
502 jgs 102 getNumSamples() const
503 jgs 94 {
504 jgs 102 return m_data->getNumSamples();
505 jgs 94 }
506    
507     /**
508     \brief
509 jgs 102 Return the number of data points per sample.
510 jgs 94 */
511 woo409 757 ESCRIPT_DLL_API
512 jgs 102 inline
513 jgs 94 int
514 jgs 102 getNumDataPointsPerSample() const
515     {
516     return m_data->getNumDPPSample();
517     }
518 jfenwick 1796
519    
520 gross 950 /**
521 jfenwick 1796 \brief
522     Return the number of values in the shape for this object.
523     */
524     ESCRIPT_DLL_API
525     int
526     getNoValues() const
527     {
528     return m_data->getNoValues();
529     }
530    
531    
532     /**
533 gross 950 \brief
534 matt 1327 dumps the object into a netCDF file
535 gross 950 */
536     ESCRIPT_DLL_API
537     void
538 gross 1141 dump(const std::string fileName) const;
539 jfenwick 1864
540 jgs 94 /**
541     \brief
542     Return the sample data for the given sample no. This is not the
543     preferred interface but is provided for use by C code.
544     \param sampleNo - Input - the given sample no.
545     */
546 woo409 757 ESCRIPT_DLL_API
547 jgs 102 inline
548 jgs 94 DataAbstract::ValueType::value_type*
549 jfenwick 1864 getSampleData(DataAbstract::ValueType::size_type sampleNo);
550 jgs 94
551     /**
552     \brief
553     Return the sample data for the given tag. If an attempt is made to
554     access data that isn't tagged an exception will be thrown.
555     \param tag - Input - the tag key.
556     */
557 woo409 757 ESCRIPT_DLL_API
558 jgs 102 inline
559 jgs 94 DataAbstract::ValueType::value_type*
560 jgs 102 getSampleDataByTag(int tag)
561     {
562     return m_data->getSampleDataByTag(tag);
563     }
564 jgs 94
565     /**
566     \brief
567     Return a view into the data for the data point specified.
568     NOTE: Construction of the DataArrayView is a relatively expensive
569     operation.
570     \param sampleNo - Input -
571     \param dataPointNo - Input -
572     */
573 woo409 757 ESCRIPT_DLL_API
574 jfenwick 1796 DataTypes::ValueType::const_reference
575     getDataPoint(int sampleNo, int dataPointNo) const;
576    
577    
578     ESCRIPT_DLL_API
579     DataTypes::ValueType::reference
580     getDataPoint(int sampleNo, int dataPointNo);
581    
582    
583    
584     /**
585     \brief
586     Return the offset for the given sample and point within the sample
587     */
588     ESCRIPT_DLL_API
589 jgs 94 inline
590 jfenwick 1796 DataTypes::ValueType::size_type
591     getDataOffset(int sampleNo,
592 jgs 94 int dataPointNo)
593     {
594 jfenwick 1864 return m_data->getPointOffset(sampleNo,dataPointNo);
595 jgs 94 }
596    
597     /**
598     \brief
599     Return a reference to the data point shape.
600     */
601 woo409 757 ESCRIPT_DLL_API
602 jfenwick 1796 inline
603     const DataTypes::ShapeType&
604     getDataPointShape() const
605     {
606     return m_data->getShape();
607     }
608 jgs 94
609     /**
610     \brief
611 jgs 102 Return the data point shape as a tuple of integers.
612 jgs 94 */
613 woo409 757 ESCRIPT_DLL_API
614 jgs 121 const boost::python::tuple
615 jgs 94 getShapeTuple() const;
616    
617     /**
618     \brief
619     Return the size of the data point. It is the product of the
620     data point shape dimensions.
621     */
622 woo409 757 ESCRIPT_DLL_API
623 jgs 94 int
624     getDataPointSize() const;
625    
626     /**
627     \brief
628 jgs 102 Return the number of doubles stored for this Data.
629 jgs 94 */
630 woo409 757 ESCRIPT_DLL_API
631 jfenwick 1796 DataTypes::ValueType::size_type
632 jgs 94 getLength() const;
633    
634 gross 1044
635    
636 jgs 94 /**
637     \brief
638 gross 1044 Assign the given value to the tag assocciated with name. Implicitly converts this
639     object to type DataTagged. Throws an exception if this object
640     cannot be converted to a DataTagged object or name cannot be mapped onto a tag key.
641     \param tagKey - Input - Integer key.
642     \param value - Input - Value to associate with given key.
643     ==>*
644     */
645     ESCRIPT_DLL_API
646     void
647     setTaggedValueByName(std::string name,
648     const boost::python::object& value);
649    
650     /**
651     \brief
652 jgs 102 Assign the given value to the tag. Implicitly converts this
653 gross 1358 object to type DataTagged if it is constant.
654    
655 jgs 102 \param tagKey - Input - Integer key.
656     \param value - Input - Value to associate with given key.
657 jgs 544 ==>*
658 jgs 94 */
659 woo409 757 ESCRIPT_DLL_API
660 jgs 102 void
661     setTaggedValue(int tagKey,
662     const boost::python::object& value);
663    
664     /**
665     \brief
666     Assign the given value to the tag. Implicitly converts this
667 gross 1358 object to type DataTagged if it is constant.
668    
669 jgs 102 \param tagKey - Input - Integer key.
670 jfenwick 1796 \param pointshape - Input - The shape of the value parameter
671 jgs 102 \param value - Input - Value to associate with given key.
672 jfenwick 1796 \param dataOffset - Input - Offset of the begining of the point within the value parameter
673 jgs 102 */
674 woo409 757 ESCRIPT_DLL_API
675 jgs 102 void
676 jgs 121 setTaggedValueFromCPP(int tagKey,
677 jfenwick 1796 const DataTypes::ShapeType& pointshape,
678     const DataTypes::ValueType& value,
679     int dataOffset=0);
680 jgs 102
681 jfenwick 1796
682    
683 jgs 102 /**
684     \brief
685     Copy other Data object into this Data object where mask is positive.
686     */
687 woo409 757 ESCRIPT_DLL_API
688 jgs 102 void
689     copyWithMask(const Data& other,
690     const Data& mask);
691    
692     /**
693     Data object operation methods and operators.
694     */
695    
696     /**
697     \brief
698 gross 1118 set all values to zero
699     *
700     */
701     ESCRIPT_DLL_API
702     void
703     setToZero();
704    
705     /**
706     \brief
707 jgs 102 Interpolates this onto the given functionspace and returns
708     the result as a Data object.
709 jgs 123 *
710 jgs 102 */
711 woo409 757 ESCRIPT_DLL_API
712 jgs 94 Data
713     interpolate(const FunctionSpace& functionspace) const;
714     /**
715     \brief
716     Calculates the gradient of the data at the data points of functionspace.
717     If functionspace is not present the function space of Function(getDomain()) is used.
718 jgs 123 *
719 jgs 94 */
720 woo409 757 ESCRIPT_DLL_API
721 jgs 94 Data
722     gradOn(const FunctionSpace& functionspace) const;
723    
724 woo409 757 ESCRIPT_DLL_API
725 jgs 94 Data
726     grad() const;
727    
728     /**
729     \brief
730     Calculate the integral over the function space domain.
731 jgs 123 *
732 jgs 94 */
733 woo409 757 ESCRIPT_DLL_API
734 jgs 94 boost::python::numeric::array
735     integrate() const;
736    
737     /**
738     \brief
739 gross 854 Returns 1./ Data object
740     *
741     */
742     ESCRIPT_DLL_API
743     Data
744     oneOver() const;
745     /**
746     \brief
747 jgs 94 Return a Data with a 1 for +ive values and a 0 for 0 or -ive values.
748 jgs 123 *
749 jgs 94 */
750 woo409 757 ESCRIPT_DLL_API
751 jgs 94 Data
752 gross 698 wherePositive() const;
753 jgs 94
754     /**
755     \brief
756 jgs 102 Return a Data with a 1 for -ive values and a 0 for +ive or 0 values.
757 jgs 123 *
758 jgs 94 */
759 woo409 757 ESCRIPT_DLL_API
760 jgs 94 Data
761 gross 698 whereNegative() const;
762 jgs 102
763     /**
764     \brief
765     Return a Data with a 1 for +ive or 0 values and a 0 for -ive values.
766 jgs 123 *
767 jgs 102 */
768 woo409 757 ESCRIPT_DLL_API
769 jgs 102 Data
770 gross 698 whereNonNegative() const;
771 jgs 94
772     /**
773     \brief
774 jgs 102 Return a Data with a 1 for -ive or 0 values and a 0 for +ive values.
775 jgs 123 *
776 jgs 94 */
777 woo409 757 ESCRIPT_DLL_API
778 jgs 94 Data
779 gross 698 whereNonPositive() const;
780 jgs 94
781     /**
782     \brief
783 jgs 102 Return a Data with a 1 for 0 values and a 0 for +ive or -ive values.
784 jgs 123 *
785 jgs 94 */
786 woo409 757 ESCRIPT_DLL_API
787 jgs 94 Data
788 jgs 571 whereZero(double tol=0.0) const;
789 jgs 94
790     /**
791     \brief
792 jgs 102 Return a Data with a 0 for 0 values and a 1 for +ive or -ive values.
793 jgs 123 *
794 jgs 94 */
795 woo409 757 ESCRIPT_DLL_API
796 jgs 94 Data
797 jgs 571 whereNonZero(double tol=0.0) const;
798 jgs 102
799     /**
800     \brief
801     Return the maximum absolute value of this Data object.
802 jgs 123 *
803 jgs 94 */
804 woo409 757 ESCRIPT_DLL_API
805 jgs 102 double
806     Lsup() const;
807 jgs 94
808     /**
809     \brief
810 jgs 102 Return the maximum value of this Data object.
811 jgs 123 *
812 jgs 94 */
813 woo409 757 ESCRIPT_DLL_API
814 jgs 102 double
815     sup() const;
816 jgs 94
817     /**
818     \brief
819 jgs 102 Return the minimum value of this Data object.
820 jgs 123 *
821 jgs 94 */
822 woo409 757 ESCRIPT_DLL_API
823 jgs 94 double
824 jgs 102 inf() const;
825 jgs 94
826     /**
827     \brief
828 jgs 102 Return the absolute value of each data point of this Data object.
829 jgs 123 *
830 jgs 94 */
831 woo409 757 ESCRIPT_DLL_API
832 jgs 102 Data
833     abs() const;
834 jgs 94
835     /**
836     \brief
837 jgs 102 Return the maximum value of each data point of this Data object.
838 jgs 123 *
839 jgs 94 */
840 woo409 757 ESCRIPT_DLL_API
841 jgs 102 Data
842     maxval() const;
843 jgs 94
844     /**
845     \brief
846 jgs 102 Return the minimum value of each data point of this Data object.
847 jgs 123 *
848 jgs 94 */
849 woo409 757 ESCRIPT_DLL_API
850 jgs 94 Data
851 jgs 102 minval() const;
852 jgs 94
853     /**
854     \brief
855 jgs 121 Return the (sample number, data-point number) of the data point with
856     the minimum value in this Data object.
857     */
858 woo409 757 ESCRIPT_DLL_API
859 jgs 121 const boost::python::tuple
860 gross 921 minGlobalDataPoint() const;
861 jgs 121
862 woo409 757 ESCRIPT_DLL_API
863 jgs 148 void
864 gross 921 calc_minGlobalDataPoint(int& ProcNo, int& DataPointNo) const;
865 jgs 121 /**
866     \brief
867 jgs 102 Return the sign of each data point of this Data object.
868     -1 for negative values, zero for zero values, 1 for positive values.
869 jgs 123 *
870 jgs 94 */
871 woo409 757 ESCRIPT_DLL_API
872 jgs 102 Data
873     sign() const;
874 jgs 94
875     /**
876 jgs 123 \brief
877 ksteube 775 Return the symmetric part of a matrix which is half the matrix plus its transpose.
878     *
879     */
880     ESCRIPT_DLL_API
881     Data
882     symmetric() const;
883    
884     /**
885     \brief
886     Return the nonsymmetric part of a matrix which is half the matrix minus its transpose.
887     *
888     */
889     ESCRIPT_DLL_API
890     Data
891     nonsymmetric() const;
892    
893     /**
894     \brief
895     Return the trace of a matrix
896     *
897     */
898     ESCRIPT_DLL_API
899     Data
900 gross 800 trace(int axis_offset) const;
901 ksteube 775
902     /**
903     \brief
904     Transpose each data point of this Data object around the given axis.
905     *
906     */
907     ESCRIPT_DLL_API
908     Data
909     transpose(int axis_offset) const;
910    
911     /**
912     \brief
913 gross 576 Return the eigenvalues of the symmetric part at each data point of this Data object in increasing values.
914     Currently this function is restricted to rank 2, square shape, and dimension 3.
915     *
916     */
917 woo409 757 ESCRIPT_DLL_API
918 gross 576 Data
919     eigenvalues() const;
920    
921     /**
922     \brief
923     Return the eigenvalues and corresponding eigenvcetors of the symmetric part at each data point of this Data object.
924 matt 1327 the eigenvalues are ordered in increasing size where eigenvalues with relative difference less than
925     tol are treated as equal. The eigenvectors are orthogonal, normalized and the sclaed such that the
926 gross 576 first non-zero entry is positive.
927     Currently this function is restricted to rank 2, square shape, and dimension 3
928     *
929     */
930 woo409 757 ESCRIPT_DLL_API
931 gross 576 const boost::python::tuple
932     eigenvalues_and_eigenvectors(const double tol=1.e-12) const;
933    
934     /**
935     \brief
936 gross 804 swaps the components axis0 and axis1
937 jgs 123 *
938 jgs 102 */
939 woo409 757 ESCRIPT_DLL_API
940 jgs 102 Data
941 gross 804 swapaxes(const int axis0, const int axis1) const;
942 jgs 102
943     /**
944 jgs 123 \brief
945 ksteube 876 Return the error function erf of each data point of this Data object.
946     *
947     */
948     ESCRIPT_DLL_API
949     Data
950     erf() const;
951    
952     /**
953     \brief
954 jgs 123 Return the sin of each data point of this Data object.
955     *
956 jgs 102 */
957 woo409 757 ESCRIPT_DLL_API
958 jgs 102 Data
959 jgs 123 sin() const;
960    
961     /**
962     \brief
963     Return the cos of each data point of this Data object.
964     *
965     */
966 woo409 757 ESCRIPT_DLL_API
967 jgs 123 Data
968     cos() const;
969    
970     /**
971     \brief
972     Return the tan of each data point of this Data object.
973     *
974     */
975 woo409 757 ESCRIPT_DLL_API
976 jgs 123 Data
977     tan() const;
978    
979     /**
980     \brief
981 jgs 150 Return the asin of each data point of this Data object.
982     *
983     */
984 woo409 757 ESCRIPT_DLL_API
985 jgs 150 Data
986     asin() const;
987    
988     /**
989     \brief
990     Return the acos of each data point of this Data object.
991     *
992     */
993 woo409 757 ESCRIPT_DLL_API
994 jgs 150 Data
995     acos() const;
996    
997     /**
998     \brief
999     Return the atan of each data point of this Data object.
1000     *
1001     */
1002 woo409 757 ESCRIPT_DLL_API
1003 jgs 150 Data
1004     atan() const;
1005    
1006     /**
1007     \brief
1008     Return the sinh of each data point of this Data object.
1009     *
1010     */
1011 woo409 757 ESCRIPT_DLL_API
1012 jgs 150 Data
1013     sinh() const;
1014    
1015     /**
1016     \brief
1017     Return the cosh of each data point of this Data object.
1018     *
1019     */
1020 woo409 757 ESCRIPT_DLL_API
1021 jgs 150 Data
1022     cosh() const;
1023    
1024     /**
1025     \brief
1026     Return the tanh of each data point of this Data object.
1027     *
1028     */
1029 woo409 757 ESCRIPT_DLL_API
1030 jgs 150 Data
1031     tanh() const;
1032    
1033     /**
1034     \brief
1035     Return the asinh of each data point of this Data object.
1036     *
1037     */
1038 woo409 757 ESCRIPT_DLL_API
1039 jgs 150 Data
1040     asinh() const;
1041    
1042     /**
1043     \brief
1044     Return the acosh of each data point of this Data object.
1045     *
1046     */
1047 woo409 757 ESCRIPT_DLL_API
1048 jgs 150 Data
1049     acosh() const;
1050    
1051     /**
1052     \brief
1053     Return the atanh of each data point of this Data object.
1054     *
1055     */
1056 woo409 757 ESCRIPT_DLL_API
1057 jgs 150 Data
1058     atanh() const;
1059    
1060     /**
1061     \brief
1062 jgs 123 Return the log to base 10 of each data point of this Data object.
1063     *
1064     */
1065 woo409 757 ESCRIPT_DLL_API
1066 jgs 123 Data
1067 gross 286 log10() const;
1068 jgs 123
1069     /**
1070     \brief
1071     Return the natural log of each data point of this Data object.
1072     *
1073     */
1074 woo409 757 ESCRIPT_DLL_API
1075 jgs 123 Data
1076 gross 286 log() const;
1077 jgs 123
1078     /**
1079     \brief
1080     Return the exponential function of each data point of this Data object.
1081     *
1082     */
1083 woo409 757 ESCRIPT_DLL_API
1084 jgs 123 Data
1085 jgs 102 exp() const;
1086    
1087     /**
1088 jgs 123 \brief
1089     Return the square root of each data point of this Data object.
1090     *
1091 jgs 102 */
1092 woo409 757 ESCRIPT_DLL_API
1093 jgs 102 Data
1094     sqrt() const;
1095    
1096     /**
1097 jgs 123 \brief
1098     Return the negation of each data point of this Data object.
1099     *
1100 jgs 121 */
1101 woo409 757 ESCRIPT_DLL_API
1102 jgs 121 Data
1103     neg() const;
1104    
1105     /**
1106 jgs 123 \brief
1107     Return the identity of each data point of this Data object.
1108     Simply returns this object unmodified.
1109     *
1110 jgs 121 */
1111 woo409 757 ESCRIPT_DLL_API
1112 jgs 121 Data
1113     pos() const;
1114    
1115     /**
1116 jgs 94 \brief
1117 jgs 102 Return the given power of each data point of this Data object.
1118 jgs 121
1119     \param right Input - the power to raise the object to.
1120 jgs 123 *
1121 jgs 102 */
1122 woo409 757 ESCRIPT_DLL_API
1123 jgs 102 Data
1124     powD(const Data& right) const;
1125    
1126 jgs 121 /**
1127 jgs 123 \brief
1128     Return the given power of each data point of this boost python object.
1129 matt 1327
1130 jgs 123 \param right Input - the power to raise the object to.
1131     *
1132 jgs 121 */
1133 woo409 757 ESCRIPT_DLL_API
1134 jgs 102 Data
1135     powO(const boost::python::object& right) const;
1136    
1137     /**
1138 jgs 123 \brief
1139 gross 699 Return the given power of each data point of this boost python object.
1140 matt 1327
1141 gross 699 \param left Input - the bases
1142     *
1143     */
1144    
1145 woo409 757 ESCRIPT_DLL_API
1146 gross 699 Data
1147     rpowO(const boost::python::object& left) const;
1148    
1149     /**
1150     \brief
1151 jgs 123 writes the object to a file in the DX file format
1152 jgs 104 */
1153 woo409 757 ESCRIPT_DLL_API
1154 jgs 104 void
1155     saveDX(std::string fileName) const;
1156    
1157     /**
1158 jgs 123 \brief
1159     writes the object to a file in the VTK file format
1160 jgs 110 */
1161 woo409 757 ESCRIPT_DLL_API
1162 jgs 110 void
1163     saveVTK(std::string fileName) const;
1164    
1165     /**
1166 jgs 102 \brief
1167     Overloaded operator +=
1168     \param right - Input - The right hand side.
1169 jgs 123 *
1170 jgs 102 */
1171 woo409 757 ESCRIPT_DLL_API
1172 jgs 102 Data& operator+=(const Data& right);
1173 woo409 757 ESCRIPT_DLL_API
1174 jgs 102 Data& operator+=(const boost::python::object& right);
1175    
1176 ksteube 1312 ESCRIPT_DLL_API
1177     Data& operator=(const Data& other);
1178    
1179 jgs 102 /**
1180     \brief
1181     Overloaded operator -=
1182     \param right - Input - The right hand side.
1183 jgs 123 *
1184 jgs 102 */
1185 woo409 757 ESCRIPT_DLL_API
1186 jgs 102 Data& operator-=(const Data& right);
1187 woo409 757 ESCRIPT_DLL_API
1188 jgs 102 Data& operator-=(const boost::python::object& right);
1189    
1190     /**
1191     \brief
1192     Overloaded operator *=
1193     \param right - Input - The right hand side.
1194 jgs 123 *
1195 jgs 102 */
1196 woo409 757 ESCRIPT_DLL_API
1197 jgs 102 Data& operator*=(const Data& right);
1198 woo409 757 ESCRIPT_DLL_API
1199 jgs 102 Data& operator*=(const boost::python::object& right);
1200    
1201     /**
1202     \brief
1203     Overloaded operator /=
1204     \param right - Input - The right hand side.
1205 jgs 123 *
1206 jgs 102 */
1207 woo409 757 ESCRIPT_DLL_API
1208 jgs 102 Data& operator/=(const Data& right);
1209 woo409 757 ESCRIPT_DLL_API
1210 jgs 102 Data& operator/=(const boost::python::object& right);
1211    
1212     /**
1213     \brief
1214 jgs 94 Returns true if this can be interpolated to functionspace.
1215     */
1216 woo409 757 ESCRIPT_DLL_API
1217 jgs 94 bool
1218     probeInterpolation(const FunctionSpace& functionspace) const;
1219    
1220     /**
1221 jgs 102 Data object slicing methods.
1222     */
1223    
1224     /**
1225 jgs 94 \brief
1226 jgs 102 Returns a slice from this Data object.
1227    
1228     /description
1229     Implements the [] get operator in python.
1230     Calls getSlice.
1231    
1232     \param key - Input - python slice tuple specifying
1233     slice to return.
1234 jgs 94 */
1235 woo409 757 ESCRIPT_DLL_API
1236 jgs 102 Data
1237     getItem(const boost::python::object& key) const;
1238    
1239     /**
1240     \brief
1241     Copies slice from value into this Data object.
1242    
1243     Implements the [] set operator in python.
1244     Calls setSlice.
1245    
1246     \param key - Input - python slice tuple specifying
1247     slice to copy from value.
1248     \param value - Input - Data object to copy from.
1249     */
1250 woo409 757 ESCRIPT_DLL_API
1251 jgs 94 void
1252 jgs 102 setItemD(const boost::python::object& key,
1253     const Data& value);
1254 jgs 94
1255 woo409 757 ESCRIPT_DLL_API
1256 jgs 102 void
1257     setItemO(const boost::python::object& key,
1258     const boost::python::object& value);
1259    
1260     // These following public methods should be treated as private.
1261    
1262 jgs 94 /**
1263     \brief
1264 jgs 102 Perform the given unary operation on every element of every data point in
1265     this Data object.
1266 jgs 94 */
1267 jgs 102 template <class UnaryFunction>
1268 woo409 757 ESCRIPT_DLL_API
1269 jgs 102 inline
1270 jgs 94 void
1271 matt 1334 unaryOp2(UnaryFunction operation);
1272 jgs 102
1273     /**
1274     \brief
1275     Return a Data object containing the specified slice of
1276     this Data object.
1277     \param region - Input - Region to copy.
1278 jgs 123 *
1279 jgs 94 */
1280 woo409 757 ESCRIPT_DLL_API
1281 jgs 102 Data
1282 jfenwick 1796 getSlice(const DataTypes::RegionType& region) const;
1283 jgs 94
1284 jgs 102 /**
1285     \brief
1286     Copy the specified slice from the given value into this
1287     Data object.
1288     \param value - Input - Data to copy from.
1289     \param region - Input - Region to copy.
1290 jgs 123 *
1291 jgs 102 */
1292 woo409 757 ESCRIPT_DLL_API
1293 jgs 102 void
1294     setSlice(const Data& value,
1295 jfenwick 1796 const DataTypes::RegionType& region);
1296 jgs 102
1297 jgs 119 /**
1298     \brief
1299 matt 1327 print the data values to stdout. Used for debugging
1300 bcumming 751 */
1301 bcumming 782 ESCRIPT_DLL_API
1302 matt 1327 void
1303 matt 1332 print(void);
1304 bcumming 751
1305 bcumming 782 /**
1306     \brief
1307     return the MPI rank number of the local data
1308 matt 1332 MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1309     is returned
1310 bcumming 782 */
1311     ESCRIPT_DLL_API
1312 matt 1332 int
1313     get_MPIRank(void) const;
1314 bcumming 782
1315     /**
1316     \brief
1317     return the MPI rank number of the local data
1318 matt 1332 MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1319     is returned
1320 bcumming 782 */
1321     ESCRIPT_DLL_API
1322 matt 1332 int
1323     get_MPISize(void) const;
1324 bcumming 782
1325     /**
1326     \brief
1327     return the MPI rank number of the local data
1328 matt 1332 MPI_COMM_WORLD is assumed and returned.
1329 bcumming 782 */
1330     ESCRIPT_DLL_API
1331 matt 1332 MPI_Comm
1332     get_MPIComm(void) const;
1333 ksteube 813
1334     /**
1335     \brief
1336     return the object produced by the factory, which is a DataConstant or DataExpanded
1337 jfenwick 1796 TODO Ownership of this object should be explained in doco.
1338 ksteube 813 */
1339     ESCRIPT_DLL_API
1340 matt 1332 DataAbstract*
1341     borrowData(void) const;
1342 ksteube 813
1343 jfenwick 1868 ESCRIPT_DLL_API
1344     DataAbstract_ptr
1345     borrowDataPtr(void) const;
1346 jfenwick 1796
1347 jfenwick 1868 ESCRIPT_DLL_API
1348     DataReady_ptr
1349     borrowReadyPtr(void) const;
1350    
1351    
1352    
1353 jfenwick 1796 /**
1354     \brief
1355     Return a pointer to the beginning of the datapoint at the specified offset.
1356     TODO Eventually these should be inlined.
1357     \param i - position(offset) in the underlying datastructure
1358     */
1359     ESCRIPT_DLL_API
1360     DataTypes::ValueType::const_reference
1361     getDataAtOffset(DataTypes::ValueType::size_type i) const;
1362    
1363    
1364     ESCRIPT_DLL_API
1365     DataTypes::ValueType::reference
1366     getDataAtOffset(DataTypes::ValueType::size_type i);
1367    
1368 jgs 102 protected:
1369    
1370 jgs 94 private:
1371    
1372     /**
1373     \brief
1374 jgs 102 Check *this and the right operand are compatible. Throws
1375     an exception if they aren't.
1376     \param right - Input - The right hand side.
1377     */
1378     inline
1379     void
1380     operandCheck(const Data& right) const
1381     {
1382     return m_data->operandCheck(*(right.m_data.get()));
1383     }
1384    
1385     /**
1386     \brief
1387     Perform the specified reduction algorithm on every element of every data point in
1388 jgs 113 this Data object according to the given function and return the single value result.
1389 jgs 102 */
1390 jgs 147 template <class BinaryFunction>
1391 jgs 102 inline
1392     double
1393 jgs 147 algorithm(BinaryFunction operation,
1394     double initial_value) const;
1395 jgs 102
1396 jgs 113 /**
1397     \brief
1398     Reduce each data-point in this Data object using the given operation. Return a Data
1399     object with the same number of data-points, but with each data-point containing only
1400     one value - the result of the reduction operation on the corresponding data-point in
1401     this Data object
1402     */
1403 jgs 147 template <class BinaryFunction>
1404 jgs 106 inline
1405     Data
1406 jgs 147 dp_algorithm(BinaryFunction operation,
1407     double initial_value) const;
1408 jgs 106
1409 jgs 102 /**
1410     \brief
1411     Perform the given binary operation on all of the data's elements.
1412     The underlying type of the right hand side (right) determines the final
1413     type of *this after the operation. For example if the right hand side
1414     is expanded *this will be expanded if necessary.
1415     RHS is a Data object.
1416     */
1417     template <class BinaryFunction>
1418     inline
1419     void
1420     binaryOp(const Data& right,
1421     BinaryFunction operation);
1422    
1423     /**
1424     \brief
1425     Convert the data type of the RHS to match this.
1426     \param right - Input - data type to match.
1427     */
1428     void
1429     typeMatchLeft(Data& right) const;
1430    
1431     /**
1432     \brief
1433     Convert the data type of this to match the RHS.
1434     \param right - Input - data type to match.
1435     */
1436     void
1437     typeMatchRight(const Data& right);
1438    
1439     /**
1440     \brief
1441 jgs 94 Construct a Data object of the appropriate type.
1442     */
1443 jfenwick 1796
1444 jgs 94 void
1445 jfenwick 1796 initialise(const DataTypes::ValueType& value,
1446     const DataTypes::ShapeType& shape,
1447 jgs 94 const FunctionSpace& what,
1448     bool expanded);
1449    
1450 jfenwick 1796 void
1451     initialise(const boost::python::numeric::array& value,
1452     const FunctionSpace& what,
1453     bool expanded);
1454    
1455 jgs 94 //
1456 gross 783 // flag to protect the data object against any update
1457     bool m_protected;
1458    
1459     //
1460 jgs 102 // pointer to the actual data object
1461 jfenwick 1828 // boost::shared_ptr<DataAbstract> m_data;
1462     DataAbstract_ptr m_data;
1463 jgs 94
1464 jfenwick 1864 const DataReady*
1465     getReady() const;
1466    
1467     DataReady*
1468     getReady();
1469    
1470 jgs 94 };
1471    
1472 jfenwick 1864 } // end namespace escript
1473 jgs 94
1474 jfenwick 1796
1475 jfenwick 1864 // No, this is not supposed to be at the top of the file
1476     #include "DataReady.h"
1477    
1478     namespace escript
1479     {
1480    
1481     inline
1482     const DataReady*
1483     Data::getReady() const
1484     {
1485     const DataReady* dr=dynamic_cast<const DataReady*>(m_data.get());
1486     EsysAssert((dr!=0), "Error - casting to DataReady.");
1487     return dr;
1488     }
1489    
1490     inline
1491     DataReady*
1492     Data::getReady()
1493     {
1494     DataReady* dr=dynamic_cast<DataReady*>(m_data.get());
1495     EsysAssert((dr!=0), "Error - casting to DataReady.");
1496     return dr;
1497     }
1498    
1499     inline
1500     DataAbstract::ValueType::value_type*
1501     Data::getSampleData(DataAbstract::ValueType::size_type sampleNo)
1502     {
1503     return getReady()->getSampleData(sampleNo);
1504     }
1505    
1506    
1507 jgs 102 /**
1508 ksteube 1748 Modify a filename for MPI parallel output to multiple files
1509     */
1510     char *Escript_MPI_appendRankToFileName(const char *, int, int);
1511    
1512     /**
1513 jgs 102 Binary Data object operators.
1514     */
1515 matt 1327 inline double rpow(double x,double y)
1516 gross 854 {
1517     return pow(y,x);
1518 gross 1028 }
1519 jgs 94
1520     /**
1521     \brief
1522     Operator+
1523     Takes two Data objects.
1524     */
1525 woo409 757 ESCRIPT_DLL_API Data operator+(const Data& left, const Data& right);
1526 jgs 94
1527     /**
1528     \brief
1529     Operator-
1530     Takes two Data objects.
1531     */
1532 woo409 757 ESCRIPT_DLL_API Data operator-(const Data& left, const Data& right);
1533 jgs 94
1534     /**
1535     \brief
1536     Operator*
1537     Takes two Data objects.
1538     */
1539 woo409 757 ESCRIPT_DLL_API Data operator*(const Data& left, const Data& right);
1540 jgs 94
1541     /**
1542     \brief
1543     Operator/
1544     Takes two Data objects.
1545     */
1546 woo409 757 ESCRIPT_DLL_API Data operator/(const Data& left, const Data& right);
1547 jgs 94
1548     /**
1549     \brief
1550     Operator+
1551     Takes LHS Data object and RHS python::object.
1552     python::object must be convertable to Data type.
1553     */
1554 woo409 757 ESCRIPT_DLL_API Data operator+(const Data& left, const boost::python::object& right);
1555 jgs 94
1556     /**
1557     \brief
1558     Operator-
1559     Takes LHS Data object and RHS python::object.
1560     python::object must be convertable to Data type.
1561     */
1562 woo409 757 ESCRIPT_DLL_API Data operator-(const Data& left, const boost::python::object& right);
1563 jgs 94
1564     /**
1565     \brief
1566     Operator*
1567     Takes LHS Data object and RHS python::object.
1568     python::object must be convertable to Data type.
1569     */
1570 woo409 757 ESCRIPT_DLL_API Data operator*(const Data& left, const boost::python::object& right);
1571 jgs 94
1572     /**
1573     \brief
1574     Operator/
1575     Takes LHS Data object and RHS python::object.
1576     python::object must be convertable to Data type.
1577     */
1578 woo409 757 ESCRIPT_DLL_API Data operator/(const Data& left, const boost::python::object& right);
1579 jgs 94
1580     /**
1581     \brief
1582     Operator+
1583     Takes LHS python::object and RHS Data object.
1584     python::object must be convertable to Data type.
1585     */
1586 woo409 757 ESCRIPT_DLL_API Data operator+(const boost::python::object& left, const Data& right);
1587 jgs 94
1588     /**
1589     \brief
1590     Operator-
1591     Takes LHS python::object and RHS Data object.
1592     python::object must be convertable to Data type.
1593     */
1594 woo409 757 ESCRIPT_DLL_API Data operator-(const boost::python::object& left, const Data& right);
1595 jgs 94
1596     /**
1597     \brief
1598     Operator*
1599     Takes LHS python::object and RHS Data object.
1600     python::object must be convertable to Data type.
1601     */
1602 woo409 757 ESCRIPT_DLL_API Data operator*(const boost::python::object& left, const Data& right);
1603 jgs 94
1604     /**
1605     \brief
1606     Operator/
1607     Takes LHS python::object and RHS Data object.
1608     python::object must be convertable to Data type.
1609     */
1610 woo409 757 ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);
1611 jgs 94
1612 ksteube 1312
1613    
1614 jgs 94 /**
1615     \brief
1616     Output operator
1617     */
1618 woo409 757 ESCRIPT_DLL_API std::ostream& operator<<(std::ostream& o, const Data& data);
1619 jgs 94
1620     /**
1621     \brief
1622 ksteube 813 Compute a tensor product of two Data objects
1623     \param arg0 - Input - Data object
1624     \param arg1 - Input - Data object
1625     \param axis_offset - Input - axis offset
1626     \param transpose - Input - 0: transpose neither, 1: transpose arg0, 2: transpose arg1
1627     */
1628     ESCRIPT_DLL_API
1629     Data
1630     C_GeneralTensorProduct(Data& arg0,
1631     Data& arg1,
1632     int axis_offset=0,
1633     int transpose=0);
1634    
1635 jgs 102 /**
1636     \brief
1637     Perform the given binary operation with this and right as operands.
1638     Right is a Data object.
1639     */
1640 jgs 94 template <class BinaryFunction>
1641     inline
1642     void
1643     Data::binaryOp(const Data& right,
1644     BinaryFunction operation)
1645     {
1646     //
1647     // if this has a rank of zero promote it to the rank of the RHS
1648 jfenwick 1796 if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1649 gross 854 throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1650 jgs 94 }
1651 jfenwick 1864
1652     if (isLazy() || right.isLazy())
1653     {
1654     throw DataException("Programmer error - attempt to call binaryOp with Lazy Data.");
1655     }
1656 jgs 94 //
1657     // initially make the temporary a shallow copy
1658     Data tempRight(right);
1659 jfenwick 1864
1660 jgs 94 if (getFunctionSpace()!=right.getFunctionSpace()) {
1661     if (right.probeInterpolation(getFunctionSpace())) {
1662     //
1663 matt 1327 // an interpolation is required so create a new Data
1664 jgs 94 tempRight=Data(right,this->getFunctionSpace());
1665     } else if (probeInterpolation(right.getFunctionSpace())) {
1666     //
1667     // interpolate onto the RHS function space
1668     Data tempLeft(*this,right.getFunctionSpace());
1669     m_data=tempLeft.m_data;
1670     }
1671     }
1672     operandCheck(tempRight);
1673     //
1674     // ensure this has the right type for the RHS
1675 jgs 102 typeMatchRight(tempRight);
1676 jgs 94 //
1677     // Need to cast to the concrete types so that the correct binaryOp
1678     // is called.
1679     if (isExpanded()) {
1680     //
1681     // Expanded data will be done in parallel, the right hand side can be
1682     // of any data type
1683     DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1684     EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1685 jfenwick 1864 escript::binaryOp(*leftC,*(tempRight.getReady()),operation);
1686 jgs 94 } else if (isTagged()) {
1687     //
1688     // Tagged data is operated on serially, the right hand side can be
1689     // either DataConstant or DataTagged
1690     DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1691     EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1692     if (right.isTagged()) {
1693     DataTagged* rightC=dynamic_cast<DataTagged*>(tempRight.m_data.get());
1694     EsysAssert((rightC!=0), "Programming error - casting to DataTagged.");
1695     escript::binaryOp(*leftC,*rightC,operation);
1696     } else {
1697     DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1698     EsysAssert((rightC!=0), "Programming error - casting to DataConstant.");
1699     escript::binaryOp(*leftC,*rightC,operation);
1700     }
1701 jgs 102 } else if (isConstant()) {
1702 jgs 94 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1703     DataConstant* rightC=dynamic_cast<DataConstant*>(tempRight.m_data.get());
1704     EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
1705     escript::binaryOp(*leftC,*rightC,operation);
1706     }
1707     }
1708    
1709 jgs 102 /**
1710     \brief
1711     Perform the given Data object reduction algorithm on this and return the result.
1712     Given operation combines each element of each data point, thus argument
1713     object (*this) is a rank n Data object, and returned object is a scalar.
1714     Calls escript::algorithm.
1715     */
1716 jgs 147 template <class BinaryFunction>
1717 jgs 94 inline
1718     double
1719 jgs 147 Data::algorithm(BinaryFunction operation, double initial_value) const
1720 jgs 94 {
1721     if (isExpanded()) {
1722     DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());
1723     EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");
1724 jgs 147 return escript::algorithm(*leftC,operation,initial_value);
1725 jgs 102 } else if (isTagged()) {
1726 jgs 94 DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());
1727     EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");
1728 jgs 147 return escript::algorithm(*leftC,operation,initial_value);
1729 jgs 102 } else if (isConstant()) {
1730 jgs 94 DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1731     EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1732 jgs 147 return escript::algorithm(*leftC,operation,initial_value);
1733 jfenwick 1803 } else if (isEmpty()) {
1734     throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1735 jfenwick 1865 } else if (isLazy()) {
1736     throw DataException("Error - Operations not permitted on instances of DataLazy.");
1737     } else {
1738     throw DataException("Error - Data encapsulates an unknown type.");
1739 jgs 94 }
1740     }
1741    
1742 jgs 102 /**
1743     \brief
1744     Perform the given data point reduction algorithm on data and return the result.
1745     Given operation combines each element within each data point into a scalar,
1746 matt 1327 thus argument object is a rank n Data object, and returned object is a
1747 jgs 102 rank 0 Data object.
1748     Calls escript::dp_algorithm.
1749     */
1750 jgs 147 template <class BinaryFunction>
1751 jgs 94 inline
1752     Data
1753 jgs 147 Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1754 jgs 94 {
1755 jfenwick 1803 if (isEmpty()) {
1756     throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1757     }
1758     else if (isExpanded()) {
1759 jfenwick 1796 Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1760 jgs 106 DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1761 jgs 102 DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1762     EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1763     EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1764 jgs 147 escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1765 jgs 559 return result;
1766 jfenwick 1803 }
1767     else if (isTagged()) {
1768 jgs 106 DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
1769 jgs 102 EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1770 jfenwick 1796 DataTypes::ValueType defval(1);
1771     defval[0]=0;
1772     DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1773 jgs 147 escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1774 jfenwick 1796 return Data(resultT); // note: the Data object now owns the resultT pointer
1775 jfenwick 1803 }
1776     else if (isConstant()) {
1777 jfenwick 1796 Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1778 jgs 106 DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1779 jgs 102 DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1780     EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
1781     EsysAssert((resultC!=0), "Programming error - casting result to DataConstant.");
1782 jgs 147 escript::dp_algorithm(*dataC,*resultC,operation,initial_value);
1783 jgs 559 return result;
1784 jfenwick 1865 } else if (isLazy()) {
1785     throw DataException("Error - Operations not permitted on instances of DataLazy.");
1786     } else {
1787     throw DataException("Error - Data encapsulates an unknown type.");
1788 jgs 102 }
1789 jgs 94 }
1790    
1791 trankine 1430 /**
1792     \brief
1793     Compute a tensor operation with two Data objects
1794     \param arg0 - Input - Data object
1795     \param arg1 - Input - Data object
1796     \param operation - Input - Binary op functor
1797     */
1798 matt 1327 template <typename BinaryFunction>
1799 trankine 1430 inline
1800 matt 1327 Data
1801     C_TensorBinaryOperation(Data const &arg_0,
1802 matt 1332 Data const &arg_1,
1803     BinaryFunction operation)
1804 matt 1327 {
1805 jfenwick 1803 if (arg_0.isEmpty() || arg_1.isEmpty())
1806     {
1807     throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1808     }
1809 jfenwick 1865 if (arg_0.isLazy() || arg_1.isLazy())
1810     {
1811     throw DataException("Error - Operations not permitted on lazy data.");
1812     }
1813 matt 1327 // Interpolate if necessary and find an appropriate function space
1814     Data arg_0_Z, arg_1_Z;
1815     if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1816     if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1817     arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1818     arg_1_Z = Data(arg_1);
1819     }
1820     else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1821     arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1822     arg_0_Z =Data(arg_0);
1823     }
1824     else {
1825     throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1826     }
1827     } else {
1828     arg_0_Z = Data(arg_0);
1829     arg_1_Z = Data(arg_1);
1830     }
1831     // Get rank and shape of inputs
1832     int rank0 = arg_0_Z.getDataPointRank();
1833     int rank1 = arg_1_Z.getDataPointRank();
1834 jfenwick 1796 DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1835     DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1836 matt 1327 int size0 = arg_0_Z.getDataPointSize();
1837     int size1 = arg_1_Z.getDataPointSize();
1838    
1839     // Declare output Data object
1840     Data res;
1841    
1842     if (shape0 == shape1) {
1843    
1844     if (arg_0_Z.isConstant() && arg_1_Z.isConstant()) {
1845 matt 1332 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace()); // DataConstant output
1846 jfenwick 1796 /* double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1847 matt 1327 double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1848 jfenwick 1796 double *ptr_2 = &((res.getPointDataView().getData())[0]);*/
1849     double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
1850     double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
1851     double *ptr_2 = &(res.getDataAtOffset(0));
1852    
1853 matt 1327 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1854     }
1855     else if (arg_0_Z.isConstant() && arg_1_Z.isTagged()) {
1856    
1857     // Prepare the DataConstant input
1858     DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1859    
1860     // Borrow DataTagged input from Data object
1861     DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1862    
1863     // Prepare a DataTagged output 2
1864 matt 1332 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace()); // DataTagged output
1865 matt 1327 res.tag();
1866     DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1867    
1868     // Prepare offset into DataConstant
1869     int offset_0 = tmp_0->getPointOffset(0,0);
1870 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1871 matt 1327 // Get the views
1872 jfenwick 1796 // DataArrayView view_1 = tmp_1->getDefaultValue();
1873     // DataArrayView view_2 = tmp_2->getDefaultValue();
1874     // // Get the pointers to the actual data
1875     // double *ptr_1 = &((view_1.getData())[0]);
1876     // double *ptr_2 = &((view_2.getData())[0]);
1877    
1878 matt 1327 // Get the pointers to the actual data
1879 jfenwick 1796 double *ptr_1 = &(tmp_1->getDefaultValue(0));
1880     double *ptr_2 = &(tmp_2->getDefaultValue(0));
1881    
1882 matt 1327 // Compute a result for the default
1883     tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1884     // Compute a result for each tag
1885     const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1886     DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1887     for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1888 jfenwick 1796 tmp_2->addTag(i->first);
1889     /* DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1890 matt 1332 DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1891     double *ptr_1 = &view_1.getData(0);
1892 jfenwick 1796 double *ptr_2 = &view_2.getData(0);*/
1893     double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
1894     double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1895    
1896 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1897 matt 1327 }
1898    
1899     }
1900     else if (arg_0_Z.isConstant() && arg_1_Z.isExpanded()) {
1901    
1902     res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1903     DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1904     DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1905     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1906    
1907     int sampleNo_1,dataPointNo_1;
1908     int numSamples_1 = arg_1_Z.getNumSamples();
1909     int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1910     int offset_0 = tmp_0->getPointOffset(0,0);
1911     #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1912     for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1913 matt 1332 for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1914     int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1915     int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1916 jfenwick 1796 // double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1917     // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1918     // double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1919    
1920     double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1921     double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1922     double *ptr_2 = &(res.getDataAtOffset(offset_2));
1923 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1924     }
1925 matt 1327 }
1926    
1927     }
1928     else if (arg_0_Z.isTagged() && arg_1_Z.isConstant()) {
1929    
1930     // Borrow DataTagged input from Data object
1931     DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1932    
1933     // Prepare the DataConstant input
1934     DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1935    
1936     // Prepare a DataTagged output 2
1937 matt 1332 res = Data(0.0, shape0, arg_0_Z.getFunctionSpace()); // DataTagged output
1938 matt 1327 res.tag();
1939     DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1940    
1941     // Prepare offset into DataConstant
1942     int offset_1 = tmp_1->getPointOffset(0,0);
1943 jfenwick 1796 // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1944     double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1945 matt 1327 // Get the views
1946 jfenwick 1796 // DataArrayView view_0 = tmp_0->getDefaultValue();
1947     // DataArrayView view_2 = tmp_2->getDefaultValue();
1948     // // Get the pointers to the actual data
1949     // double *ptr_0 = &((view_0.getData())[0]);
1950     // double *ptr_2 = &((view_2.getData())[0]);
1951 matt 1327 // Get the pointers to the actual data
1952 jfenwick 1796 double *ptr_0 = &(tmp_0->getDefaultValue(0));
1953     double *ptr_2 = &(tmp_2->getDefaultValue(0));
1954 matt 1327 // Compute a result for the default
1955     tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1956     // Compute a result for each tag
1957     const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1958     DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1959     for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1960 jfenwick 1796 tmp_2->addTag(i->first);
1961     // DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1962     // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1963     // double *ptr_0 = &view_0.getData(0);
1964     // double *ptr_2 = &view_2.getData(0);
1965     double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
1966     double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
1967 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1968 matt 1327 }
1969    
1970     }
1971     else if (arg_0_Z.isTagged() && arg_1_Z.isTagged()) {
1972    
1973     // Borrow DataTagged input from Data object
1974     DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1975    
1976     // Borrow DataTagged input from Data object
1977     DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1978    
1979     // Prepare a DataTagged output 2
1980     res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1981 matt 1332 res.tag(); // DataTagged output
1982 matt 1327 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1983    
1984 jfenwick 1796 // // Get the views
1985     // DataArrayView view_0 = tmp_0->getDefaultValue();
1986     // DataArrayView view_1 = tmp_1->getDefaultValue();
1987     // DataArrayView view_2 = tmp_2->getDefaultValue();
1988     // // Get the pointers to the actual data
1989     // double *ptr_0 = &((view_0.getData())[0]);
1990     // double *ptr_1 = &((view_1.getData())[0]);
1991     // double *ptr_2 = &((view_2.getData())[0]);
1992    
1993 matt 1327 // Get the pointers to the actual data
1994 jfenwick 1796 double *ptr_0 = &(tmp_0->getDefaultValue(0));
1995     double *ptr_1 = &(tmp_1->getDefaultValue(0));
1996     double *ptr_2 = &(tmp_2->getDefaultValue(0));
1997    
1998 matt 1327 // Compute a result for the default
1999     tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2000     // Merge the tags
2001     DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2002     const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2003     const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2004     for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2005 jfenwick 1796 tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2006 matt 1327 }
2007     for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2008 jfenwick 1796 tmp_2->addTag(i->first);
2009 matt 1327 }
2010     // Compute a result for each tag
2011     const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2012     for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2013 jfenwick 1796
2014     // DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2015     // DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2016     // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2017     // double *ptr_0 = &view_0.getData(0);
2018     // double *ptr_1 = &view_1.getData(0);
2019     // double *ptr_2 = &view_2.getData(0);
2020    
2021     double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2022     double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2023     double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2024    
2025 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2026 matt 1327 }
2027    
2028     }
2029     else if (arg_0_Z.isTagged() && arg_1_Z.isExpanded()) {
2030    
2031     // After finding a common function space above the two inputs have the same numSamples and num DPPS
2032     res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2033     DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2034     DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2035     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2036    
2037     int sampleNo_0,dataPointNo_0;
2038     int numSamples_0 = arg_0_Z.getNumSamples();
2039     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2040     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2041     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2042 matt 1332 int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2043 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2044 matt 1332 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2045     int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2046     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2047 jfenwick 1796
2048     // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2049     // double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2050     double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2051     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2052    
2053    
2054 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2055     }
2056 matt 1327 }
2057    
2058     }
2059     else if (arg_0_Z.isExpanded() && arg_1_Z.isConstant()) {
2060    
2061     res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2062     DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2063     DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2064     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2065    
2066     int sampleNo_0,dataPointNo_0;
2067     int numSamples_0 = arg_0_Z.getNumSamples();
2068     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2069     int offset_1 = tmp_1->getPointOffset(0,0);
2070     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2071     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2072 matt 1332 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2073     int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2074     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2075 jfenwick 1796
2076     // double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2077     // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2078     // double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2079    
2080     double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2081     double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2082     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2083    
2084    
2085 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2086     }
2087 matt 1327 }
2088    
2089     }
2090     else if (arg_0_Z.isExpanded() && arg_1_Z.isTagged()) {
2091    
2092     // After finding a common function space above the two inputs have the same numSamples and num DPPS
2093     res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2094     DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2095     DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2096     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2097    
2098     int sampleNo_0,dataPointNo_0;
2099     int numSamples_0 = arg_0_Z.getNumSamples();
2100     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2101     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2102     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2103 matt 1332 int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2104 jfenwick 1796 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2105 matt 1332 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2106     int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2107     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2108 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2109     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2110 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2111     }
2112 matt 1327 }
2113    
2114     }
2115     else if (arg_0_Z.isExpanded() && arg_1_Z.isExpanded()) {
2116    
2117     // After finding a common function space above the two inputs have the same numSamples and num DPPS
2118     res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2119     DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2120     DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2121     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2122    
2123     int sampleNo_0,dataPointNo_0;
2124     int numSamples_0 = arg_0_Z.getNumSamples();
2125     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2126     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2127     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2128 matt 1332 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2129     int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2130     int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2131     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2132 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2133     double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2134     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2135 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2136     }
2137 matt 1327 }
2138    
2139     }
2140     else {
2141     throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2142     }
2143    
2144     } else if (0 == rank0) {
2145    
2146     if (arg_0_Z.isConstant() && arg_1_Z.isConstant()) {
2147 matt 1332 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace()); // DataConstant output
2148 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2149     double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2150     double *ptr_2 = &(res.getDataAtOffset(0));
2151 matt 1327 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2152     }
2153     else if (arg_0_Z.isConstant() && arg_1_Z.isTagged()) {
2154    
2155     // Prepare the DataConstant input
2156     DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2157    
2158     // Borrow DataTagged input from Data object
2159     DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2160    
2161     // Prepare a DataTagged output 2
2162 matt 1332 res = Data(0.0, shape1, arg_1_Z.getFunctionSpace()); // DataTagged output
2163 matt 1327 res.tag();
2164     DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2165    
2166     // Prepare offset into DataConstant
2167     int offset_0 = tmp_0->getPointOffset(0,0);
2168 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2169 matt 1327 // Get the views
2170 jfenwick 1796 // DataArrayView view_1 = tmp_1->getDefaultValue();
2171     // DataArrayView view_2 = tmp_2->getDefaultValue();
2172     // // Get the pointers to the actual data
2173     // double *ptr_1 = &((view_1.getData())[0]);
2174     // double *ptr_2 = &((view_2.getData())[0]);
2175     double *ptr_1 = &(tmp_1->getDefaultValue(0));
2176     double *ptr_2 = &(tmp_2->getDefaultValue(0));
2177    
2178 matt 1327 // Compute a result for the default
2179     tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2180     // Compute a result for each tag
2181     const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2182     DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2183     for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2184 jfenwick 1796 tmp_2->addTag(i->first);
2185     // DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2186     // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2187     // double *ptr_1 = &view_1.getData(0);
2188     // double *ptr_2 = &view_2.getData(0);
2189     double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2190     double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2191 matt 1332 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2192 matt 1327 }
2193    
2194     }
2195     else if (arg_0_Z.isConstant() && arg_1_Z.isExpanded()) {
2196    
2197     res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2198     DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2199     DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2200     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2201    
2202     int sampleNo_1,dataPointNo_1;
2203     int numSamples_1 = arg_1_Z.getNumSamples();
2204     int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2205     int offset_0 = tmp_0->getPointOffset(0,0);
2206     #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2207     for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2208 matt 1332 for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2209     int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2210     int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2211 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2212     double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2213     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2214 matt 1332 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2215 matt 1327
2216 matt 1332 }
2217 matt 1327 }
2218    
2219     }
2220     else if (arg_0_Z.isTagged() && arg_1_Z.isConstant()) {
2221    
2222     // Borrow DataTagged input from Data object
2223     DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2224    
2225     // Prepare the DataConstant input
2226     DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2227    
2228     // Prepare a DataTagged output 2
2229 matt 1332 res = Data(0.0, shape1, arg_0_Z.getFunctionSpace()); // DataTagged output
2230 matt 1327 res.tag();
2231     DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2232    
2233     // Prepare offset into DataConstant
2234     int offset_1 = tmp_1->getPointOffset(0,0);
2235 jfenwick 1796 // double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2236     double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2237 matt 1327 // Get the views
2238 jfenwick 1796 /* DataArrayView view_0 = tmp_0->getDefaultValue();
2239 matt 1327 DataArrayView view_2 = tmp_2->getDefaultValue();
2240     // Get the pointers to the actual data
2241     double *ptr_0 = &((view_0.getData())[0]);
2242 jfenwick 1796 double *ptr_2 = &((view_2.getData())[0]);*/
2243    
2244     // Get the pointers to the actual data
2245     double *ptr_0 = &(tmp_0->getDefaultValue(0));
2246     double *ptr_2 = &(tmp_2->getDefaultValue(0));
2247    
2248    
2249 matt 1327 // Compute a result for the default
2250     tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2251     // Compute a result for each tag
2252     const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2253     DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2254     for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2255 jfenwick 1796 tmp_2->addTag(i->first);
2256     /* DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2257 matt 1332 DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2258     double *ptr_0 = &view_0.getData(0);
2259 jfenwick 1796 double *ptr_2 = &view_2.getData(0);*/
2260     double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2261     double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2262    
2263 matt 1332 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2264 matt 1327 }
2265    
2266     }
2267     else if (arg_0_Z.isTagged() && arg_1_Z.isTagged()) {
2268    
2269     // Borrow DataTagged input from Data object
2270     DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2271    
2272     // Borrow DataTagged input from Data object
2273     DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2274    
2275     // Prepare a DataTagged output 2
2276     res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2277 matt 1332 res.tag(); // DataTagged output
2278 matt 1327 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2279    
2280     // Get the views
2281 jfenwick 1796 /* DataArrayView view_0 = tmp_0->getDefaultValue();
2282 matt 1327 DataArrayView view_1 = tmp_1->getDefaultValue();
2283     DataArrayView view_2 = tmp_2->getDefaultValue();
2284     // Get the pointers to the actual data
2285     double *ptr_0 = &((view_0.getData())[0]);
2286     double *ptr_1 = &((view_1.getData())[0]);
2287 jfenwick 1796 double *ptr_2 = &((view_2.getData())[0]);*/
2288    
2289     // Get the pointers to the actual data
2290     double *ptr_0 = &(tmp_0->getDefaultValue(0));
2291     double *ptr_1 = &(tmp_1->getDefaultValue(0));
2292     double *ptr_2 = &(tmp_2->getDefaultValue(0));
2293    
2294    
2295 matt 1327 // Compute a result for the default
2296     tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2297     // Merge the tags
2298     DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2299     const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2300     const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2301     for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2302 jfenwick 1796 tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2303 matt 1327 }
2304     for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2305 jfenwick 1796 tmp_2->addTag(i->first);
2306 matt 1327 }
2307     // Compute a result for each tag
2308     const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2309     for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2310 jfenwick 1796
2311     /* DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2312 matt 1332 DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2313     DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2314     double *ptr_0 = &view_0.getData(0);
2315     double *ptr_1 = &view_1.getData(0);
2316 jfenwick 1796 double *ptr_2 = &view_2.getData(0);*/
2317    
2318     double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2319     double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2320     double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2321    
2322 matt 1332 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2323 matt 1327 }
2324    
2325     }
2326     else if (arg_0_Z.isTagged() && arg_1_Z.isExpanded()) {
2327    
2328     // After finding a common function space above the two inputs have the same numSamples and num DPPS
2329     res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2330     DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2331     DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2332     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2333    
2334     int sampleNo_0,dataPointNo_0;
2335     int numSamples_0 = arg_0_Z.getNumSamples();
2336     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2337     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2338     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2339 matt 1332 int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2340 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2341 matt 1332 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2342     int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2343     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2344 jfenwick 1796 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2345     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2346 matt 1332 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2347     }
2348 matt 1327 }
2349    
2350     }
2351     else if (arg_0_Z.isExpanded() && arg_1_Z.isConstant()) {
2352    
2353     res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2354     DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2355     DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2356     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2357    
2358     int sampleNo_0,dataPointNo_0;
2359     int numSamples_0 = arg_0_Z.getNumSamples();
2360     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2361     int offset_1 = tmp_1->getPointOffset(0,0);
2362     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2363     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2364 matt 1332 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2365     int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2366     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2367 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2368     double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2369     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2370 matt 1332 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2371     }
2372 matt 1327 }
2373    
2374    
2375     }
2376     else if (arg_0_Z.isExpanded() && arg_1_Z.isTagged()) {
2377    
2378     // After finding a common function space above the two inputs have the same numSamples and num DPPS
2379     res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2380     DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2381     DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2382     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2383    
2384     int sampleNo_0,dataPointNo_0;
2385     int numSamples_0 = arg_0_Z.getNumSamples();
2386     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2387     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2388     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2389 matt 1332 int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2390 jfenwick 1796 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2391 matt 1332 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2392     int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2393     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2394 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2395     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2396 matt 1332 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2397     }
2398 matt 1327 }
2399    
2400     }
2401     else if (arg_0_Z.isExpanded() && arg_1_Z.isExpanded()) {
2402    
2403     // After finding a common function space above the two inputs have the same numSamples and num DPPS
2404     res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2405     DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2406     DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2407     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2408    
2409     int sampleNo_0,dataPointNo_0;
2410     int numSamples_0 = arg_0_Z.getNumSamples();
2411     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2412     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2413     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2414 matt 1332 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2415     int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2416     int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2417     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2418 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2419     double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2420     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2421 matt 1332 tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2422     }
2423 matt 1327 }
2424    
2425     }
2426     else {
2427     throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2428     }
2429    
2430     } else if (0 == rank1) {
2431    
2432     if (arg_0_Z.isConstant() && arg_1_Z.isConstant()) {
2433 matt 1332 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace()); // DataConstant output
2434 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2435     double *ptr_1 = &(arg_1_Z.getDataAtOffset(0));
2436     double *ptr_2 = &(res.getDataAtOffset(0));
2437 matt 1327 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2438     }
2439     else if (arg_0_Z.isConstant() && arg_1_Z.isTagged()) {
2440    
2441     // Prepare the DataConstant input
2442     DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2443    
2444     // Borrow DataTagged input from Data object
2445     DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2446    
2447     // Prepare a DataTagged output 2
2448 matt 1332 res = Data(0.0, shape0, arg_1_Z.getFunctionSpace()); // DataTagged output
2449 matt 1327 res.tag();
2450     DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2451    
2452     // Prepare offset into DataConstant
2453     int offset_0 = tmp_0->getPointOffset(0,0);
2454 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2455 matt 1327 // Get the views
2456 jfenwick 1796 /* DataArrayView view_1 = tmp_1->getDefaultValue();
2457 matt 1327 DataArrayView view_2 = tmp_2->getDefaultValue();
2458     // Get the pointers to the actual data
2459     double *ptr_1 = &((view_1.getData())[0]);
2460 jfenwick 1796 double *ptr_2 = &((view_2.getData())[0]);*/
2461     //Get the pointers to the actual data
2462     double *ptr_1 = &(tmp_1->getDefaultValue(0));
2463     double *ptr_2 = &(tmp_2->getDefaultValue(0));
2464    
2465 matt 1327 // Compute a result for the default
2466     tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2467     // Compute a result for each tag
2468     const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2469     DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2470     for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2471 jfenwick 1796 tmp_2->addTag(i->first);
2472     // DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2473     // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2474     // double *ptr_1 = &view_1.getData(0);
2475     // double *ptr_2 = &view_2.getData(0);
2476     double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2477     double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2478    
2479    
2480 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2481 matt 1327 }
2482    
2483     }
2484     else if (arg_0_Z.isConstant() && arg_1_Z.isExpanded()) {
2485    
2486     res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2487     DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2488     DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2489     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2490    
2491     int sampleNo_1,dataPointNo_1;
2492     int numSamples_1 = arg_1_Z.getNumSamples();
2493     int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2494     int offset_0 = tmp_0->getPointOffset(0,0);
2495     #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2496     for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2497 matt 1332 for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2498     int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2499     int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2500 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2501     double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2502     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2503 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2504     }
2505 matt 1327 }
2506    
2507     }
2508     else if (arg_0_Z.isTagged() && arg_1_Z.isConstant()) {
2509    
2510     // Borrow DataTagged input from Data object
2511     DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2512    
2513     // Prepare the DataConstant input
2514     DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2515    
2516     // Prepare a DataTagged output 2
2517 matt 1332 res = Data(0.0, shape0, arg_0_Z.getFunctionSpace()); // DataTagged output
2518 matt 1327 res.tag();
2519     DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2520    
2521     // Prepare offset into DataConstant
2522     int offset_1 = tmp_1->getPointOffset(0,0);
2523 jfenwick 1796 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2524 matt 1327 // Get the views
2525 jfenwick 1796 // DataArrayView view_0 = tmp_0->getDefaultValue();
2526     // DataArrayView view_2 = tmp_2->getDefaultValue();
2527     // // Get the pointers to the actual data
2528     // double *ptr_0 = &((view_0.getData())[0]);
2529     // double *ptr_2 = &((view_2.getData())[0]);
2530 matt 1327 // Get the pointers to the actual data
2531 jfenwick 1796 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2532     double *ptr_2 = &(tmp_2->getDefaultValue(0));
2533 matt 1327 // Compute a result for the default
2534     tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2535     // Compute a result for each tag
2536     const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2537     DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2538     for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2539 jfenwick 1796 tmp_2->addTag(i->first);
2540     /* DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2541 matt 1332 DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2542     double *ptr_0 = &view_0.getData(0);
2543 jfenwick 1796 double *ptr_2 = &view_2.getData(0);*/
2544     double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2545     double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2546 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2547 matt 1327 }
2548    
2549     }
2550     else if (arg_0_Z.isTagged() && arg_1_Z.isTagged()) {
2551    
2552     // Borrow DataTagged input from Data object
2553     DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2554    
2555     // Borrow DataTagged input from Data object
2556     DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2557    
2558     // Prepare a DataTagged output 2
2559     res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2560 matt 1332 res.tag(); // DataTagged output
2561 matt 1327 DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2562    
2563     // Get the views
2564 jfenwick 1796 // DataArrayView view_0 = tmp_0->getDefaultValue();
2565     // DataArrayView view_1 = tmp_1->getDefaultValue();
2566     // DataArrayView view_2 = tmp_2->getDefaultValue();
2567     // // Get the pointers to the actual data
2568     // double *ptr_0 = &((view_0.getData())[0]);
2569     // double *ptr_1 = &((view_1.getData())[0]);
2570     // double *ptr_2 = &((view_2.getData())[0]);
2571    
2572 matt 1327 // Get the pointers to the actual data
2573 jfenwick 1796 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2574     double *ptr_1 = &(tmp_1->getDefaultValue(0));
2575     double *ptr_2 = &(tmp_2->getDefaultValue(0));
2576    
2577 matt 1327 // Compute a result for the default
2578     tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2579     // Merge the tags
2580     DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2581     const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2582     const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2583     for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2584 jfenwick 1796 tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2585 matt 1327 }
2586     for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2587 jfenwick 1796 tmp_2->addTag(i->first);
2588 matt 1327 }
2589     // Compute a result for each tag
2590     const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2591     for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2592 jfenwick 1796 // DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2593     // DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2594     // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2595     // double *ptr_0 = &view_0.getData(0);
2596     // double *ptr_1 = &view_1.getData(0);
2597     // double *ptr_2 = &view_2.getData(0);
2598    
2599     double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2600     double *ptr_1 = &(tmp_1->getDataByTag(i->first,0));
2601     double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2602 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2603 matt 1327 }
2604    
2605     }
2606     else if (arg_0_Z.isTagged() && arg_1_Z.isExpanded()) {
2607    
2608     // After finding a common function space above the two inputs have the same numSamples and num DPPS
2609     res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2610     DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2611     DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2612     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2613    
2614     int sampleNo_0,dataPointNo_0;
2615     int numSamples_0 = arg_0_Z.getNumSamples();
2616     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2617     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2618     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2619 matt 1332 int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2620 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2621 matt 1332 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2622     int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2623     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2624 jfenwick 1796 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2625     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2626 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2627     }
2628 matt 1327 }
2629    
2630     }
2631     else if (arg_0_Z.isExpanded() && arg_1_Z.isConstant()) {
2632    
2633     res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2634     DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2635     DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2636     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2637    
2638     int sampleNo_0,dataPointNo_0;
2639     int numSamples_0 = arg_0_Z.getNumSamples();
2640     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2641     int offset_1 = tmp_1->getPointOffset(0,0);
2642     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2643     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2644 matt 1332 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2645     int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2646     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2647 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2648     double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2649     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2650 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2651     }
2652 matt 1327 }
2653    
2654    
2655     }
2656     else if (arg_0_Z.isExpanded() && arg_1_Z.isTagged()) {
2657    
2658     // After finding a common function space above the two inputs have the same numSamples and num DPPS
2659     res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2660     DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2661     DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2662     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2663    
2664     int sampleNo_0,dataPointNo_0;
2665     int numSamples_0 = arg_0_Z.getNumSamples();
2666     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2667     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2668     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2669 matt 1332 int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2670 jfenwick 1796 double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2671 matt 1332 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2672     int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2673     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2674 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2675     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2676 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2677     }
2678 matt 1327 }
2679    
2680     }
2681     else if (arg_0_Z.isExpanded() && arg_1_Z.isExpanded()) {
2682    
2683     // After finding a common function space above the two inputs have the same numSamples and num DPPS
2684     res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2685     DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2686     DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2687     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2688    
2689     int sampleNo_0,dataPointNo_0;
2690     int numSamples_0 = arg_0_Z.getNumSamples();
2691     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2692     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2693     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2694 matt 1332 for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2695     int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2696     int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2697     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2698 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2699     double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2700     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2701 matt 1332 tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2702     }
2703 matt 1327 }
2704    
2705     }
2706     else {
2707     throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2708     }
2709    
2710     } else {
2711     throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2712     }
2713    
2714     return res;
2715 jgs 94 }
2716 matt 1327
2717 matt 1334 template <typename UnaryFunction>
2718     Data
2719     C_TensorUnaryOperation(Data const &arg_0,
2720     UnaryFunction operation)
2721     {
2722 jfenwick 1803 if (arg_0.isEmpty()) // do this before we attempt to interpolate
2723     {
2724     throw DataException("Error - Operations not permitted on instances of DataEmpty.");
2725     }
2726 jfenwick 1865 if (arg_0.isLazy())
2727     {
2728     throw DataException("Error - Operations not permitted on lazy data.");
2729     }
2730 matt 1334 // Interpolate if necessary and find an appropriate function space
2731     Data arg_0_Z = Data(arg_0);
2732    
2733     // Get rank and shape of inputs
2734     int rank0 = arg_0_Z.getDataPointRank();
2735 jfenwick 1796 const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2736 matt 1334 int size0 = arg_0_Z.getDataPointSize();
2737    
2738     // Declare output Data object
2739     Data res;
2740    
2741     if (arg_0_Z.isConstant()) {
2742     res = Data(0.0, shape0, arg_0_Z.getFunctionSpace()); // DataConstant output
2743 jfenwick 1796 // double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2744     // double *ptr_2 = &((res.getPointDataView().getData())[0]);
2745     double *ptr_0 = &(arg_0_Z.getDataAtOffset(0));
2746     double *ptr_2 = &(res.getDataAtOffset(0));
2747 matt 1334 tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2748     }
2749     else if (arg_0_Z.isTagged()) {
2750    
2751     // Borrow DataTagged input from Data object
2752     DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2753    
2754     // Prepare a DataTagged output 2
2755     res = Data(0.0, shape0, arg_0_Z.getFunctionSpace()); // DataTagged output
2756     res.tag();
2757     DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2758    
2759 jfenwick 1796 // // Get the views
2760     // DataArrayView view_0 = tmp_0->getDefaultValue();
2761     // DataArrayView view_2 = tmp_2->getDefaultValue();
2762     // // Get the pointers to the actual data
2763     // double *ptr_0 = &((view_0.getData())[0]);
2764     // double *ptr_2 = &((view_2.getData())[0]);
2765 matt 1334 // Get the pointers to the actual data
2766 jfenwick 1796 double *ptr_0 = &(tmp_0->getDefaultValue(0));
2767     double *ptr_2 = &(tmp_2->getDefaultValue(0));
2768 matt 1334 // Compute a result for the default
2769     tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2770     // Compute a result for each tag
2771     const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2772     DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2773     for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2774 jfenwick 1796 tmp_2->addTag(i->first);
2775     // DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2776     // DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2777     // double *ptr_0 = &view_0.getData(0);
2778     // double *ptr_2 = &view_2.getData(0);
2779     double *ptr_0 = &(tmp_0->getDataByTag(i->first,0));
2780     double *ptr_2 = &(tmp_2->getDataByTag(i->first,0));
2781 matt 1334 tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2782     }
2783    
2784     }
2785     else if (arg_0_Z.isExpanded()) {
2786    
2787     res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2788     DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2789     DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2790    
2791     int sampleNo_0,dataPointNo_0;
2792     int numSamples_0 = arg_0_Z.getNumSamples();
2793     int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2794     #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2795     for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2796     for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2797 jfenwick 1796 // int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2798     // int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2799     // double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2800     // double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2801 matt 1334 int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2802     int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2803 jfenwick 1796 double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2804     double *ptr_2 = &(res.getDataAtOffset(offset_2));
2805 matt 1334 tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2806     }
2807     }
2808     }
2809     else {
2810     throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2811     }
2812    
2813     return res;
2814 matt 1327 }
2815 matt 1334
2816     }
2817 jgs 94 #endif

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26