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

Annotation of /trunk/escript/src/Data.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1857 - (hide annotations)
Tue Oct 7 23:58:44 2008 UTC (11 years, 4 months ago) by jfenwick
File MIME type: text/plain
File size: 88305 byte(s)
Updated doco to describe the behaviour of inf, sup and Lsup for cases 
where none of the tags in use in the domain have values.

It confused me when I was testing.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26