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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1799 - (hide annotations)
Wed Sep 17 06:33:18 2008 UTC (11 years, 1 month ago) by jfenwick
Original Path: trunk/escript/src/Data.h
File MIME type: text/plain
File size: 87887 byte(s)
Added Data::copySelf() [Note: this is exposed as copy() in python].
This method returns a pointer to a deep copy of the target.
There are c++ tests but no python tests for this yet.

All DataAbstracts now have a deepCopy() which simplifies the 
implementation of the compy methods.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26