/[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 1865 - (hide annotations)
Thu Oct 9 03:53:57 2008 UTC (11 years ago) by jfenwick
File MIME type: text/plain
File size: 88667 byte(s)
Branch commit
Added some missing files.

In python can ask a data object if it-  isReady(), isConstant(), 
isLazy().



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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26