/[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 1858 - (hide annotations)
Wed Oct 8 00:28:28 2008 UTC (11 years ago) by jfenwick
File MIME type: text/plain
File size: 88237 byte(s)
Branch of branch moreshared_from_1812 at revision 1857.

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26