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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1822 - (hide annotations)
Wed Oct 1 05:42:31 2008 UTC (11 years ago) by jfenwick
Original Path: branches/more_shared_ptrs_from_1812/escript/src/Data.h
File MIME type: text/plain
File size: 88207 byte(s)
Branch commit
Passes all unit tests.
Still resorting to special python versions of getDomain to get around type conversion.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26