/[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 1802 - (hide annotations)
Tue Sep 23 01:03:29 2008 UTC (11 years, 1 month ago) by jfenwick
Original Path: trunk/escript/src/Data.h
File MIME type: text/plain
File size: 88014 byte(s)
Added canTag methods to FunctionSpace and AbstractDomain (and its 
offspring).
This checks to see if the domain supports tags for the given type of 
function space.

Constructors for DataTagged now throw exceptions if you attempt to make 
a DataTagged with a FunctionSpace which does not support tags.
To allow the default constructor to work, NullDomain has a single 
functioncode which "supports" tagging.

Fixed a bug in DataTagged::toString and DataTypes::pointToString.

Added FunctionSpace::getListOfTagsSTL.

algorithm(DataTagged, BinaryFunction) in DataAlgorithm now only 
processes tags known to be in use.
This fixes mantis issue #0000186.

Added comment to Data.h intro warning about holding references if the 
underlying DataAbstract changes.

_python_ unit tests have been updated to test TaggedData with invalid 
FunctionSpaces and to give the correct answers to Lsup etc.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26