/[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 1803 - (hide annotations)
Wed Sep 24 06:20:29 2008 UTC (11 years ago) by jfenwick
Original Path: trunk/escript/src/Data.h
File MIME type: text/plain
File size: 87960 byte(s)
All about making DataEmpty instances throw.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Exposed getDim from AbstractDomain to python to fix bug.

Added isEmpty member to DataAbstract to allow it to throw is queries are 
made about a DataEmpty instance.


Added exceptions to DataAbstract, DataEmpty and Data to prevent calls 
being made against DataEmpty objects.
The following still work as expected on DataEmpty instances

copy, getDomain, getFunctionSpace, isEmpty, isExpanded, isProtected, 
isTagged, setprotection.

You can also call interpolate, however it should throw if you try to 
change FunctionSpaces.


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26