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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1811 - (hide annotations)
Thu Sep 25 23:11:13 2008 UTC (11 years, 2 months ago) by ksteube
File MIME type: text/plain
File size: 87925 byte(s)
Copyright updated in all files

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26