/[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 1820 - (hide annotations)
Wed Oct 1 03:48:18 2008 UTC (11 years, 1 month ago) by jfenwick
Original Path: branches/more_shared_ptrs_from_1812/escript/src/Data.h
File MIME type: text/plain
File size: 88078 byte(s)
Branch commit.

First experiments with shared_ptr.
There is a crash on exit due to deallocating the NullDomain object twice.
(One from shared_ptr and once in global destructors)


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26