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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/escript/src/Data.h revision 971 by ksteube, Wed Feb 14 04:40:49 2007 UTC branches/more_shared_ptrs_from_1812/escript/src/Data.h revision 1821 by jfenwick, Wed Oct 1 04:46:59 2008 UTC
# Line 1  Line 1 
1  // $Id$  
2  /*  /*******************************************************
3   ************************************************************  *
4   *          Copyright 2006 by ACcESS MNRF                   *  * Copyright (c) 2003-2008 by University of Queensland
5   *                                                          *  * Earth Systems Science Computational Center (ESSCC)
6   *              http://www.access.edu.au                    *  * http://www.uq.edu.au/esscc
7   *       Primary Business: Queensland, Australia            *  *
8   *  Licensed under the Open Software License version 3.0    *  * Primary Business: Queensland, Australia
9   *     http://www.opensource.org/licenses/osl-3.0.php       *  * Licensed under the Open Software License version 3.0
10   *                                                          *  * http://www.opensource.org/licenses/osl-3.0.php
11   ************************************************************  *
12  */  *******************************************************/
13    
14    
15  /** \file Data.h */  /** \file Data.h */
16    
# Line 23  Line 24 
24  #include "BinaryOp.h"  #include "BinaryOp.h"
25  #include "UnaryOp.h"  #include "UnaryOp.h"
26  #include "DataException.h"  #include "DataException.h"
27    #include "DataTypes.h"
28    
29  extern "C" {  extern "C" {
30  #include "DataC.h"  #include "DataC.h"
31  #include "paso/Paso.h"  /* #include "paso/Paso.h" doesn't belong in this file...causes trouble for BruceFactory.cpp */
32  }  }
33    
34  #ifndef PASO_MPI  #include "esysmpi.h"
 #define MPI_Comm long  
 #endif  
   
35  #include <string>  #include <string>
36  #include <algorithm>  #include <algorithm>
37    #include <sstream>
38    
39    
40  #include <boost/shared_ptr.hpp>  #include <boost/shared_ptr.hpp>
41  #include <boost/python/object.hpp>  #include <boost/python/object.hpp>
# Line 51  class DataExpanded; Line 52  class DataExpanded;
52    
53  /**  /**
54     \brief     \brief
55     Data creates the appropriate Data object for the given construction     Data represents a collection of datapoints.
    arguments.  
56    
57     Description:     Description:
58     Data is essentially a factory class which creates the appropriate Data     Internally, the datapoints are actually stored by a DataAbstract object.
59     object for the given construction arguments. It retains control over     The specific instance of DataAbstract used may vary over the lifetime
60     the object created for the lifetime of the object.     of the Data object.
61     The type of Data object referred to may change during the lifetime of     Some methods on this class return references (eg getShape()).
62     the Data object.     These references should not be used after an operation which changes the underlying DataAbstract object.
63       Doing so will lead to invalid memory access.
64       This should not affect any methods exposed via boost::python.
65  */  */
66  class Data {  class Data {
67    
# Line 102  class Data { Line 104  class Data {
104         const FunctionSpace& what);         const FunctionSpace& what);
105    
106    /**    /**
107       \brief      \brief Copy Data from an existing vector
108       Constructor which copies data from a DataArrayView.    */
109    
      \param value - Input - Data value for a single point.  
      \param what - Input - A description of what this data represents.  
      \param expanded - Input - Flag, if true fill the entire container with  
                        the value. Otherwise a more efficient storage  
                        mechanism will be used.  
   */  
110    ESCRIPT_DLL_API    ESCRIPT_DLL_API
111    Data(const DataArrayView& value,    Data(const DataTypes::ValueType& value,
112         const FunctionSpace& what=FunctionSpace(),           const DataTypes::ShapeType& shape,
113         bool expanded=false);                   const FunctionSpace& what=FunctionSpace(),
114                     bool expanded=false);
115    
116    /**    /**
117       \brief       \brief
# Line 129  class Data { Line 126  class Data {
126    */    */
127    ESCRIPT_DLL_API    ESCRIPT_DLL_API
128    Data(double value,    Data(double value,
129         const DataArrayView::ShapeType& dataPointShape=DataArrayView::ShapeType(),         const DataTypes::ShapeType& dataPointShape=DataTypes::ShapeType(),
130         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
131         bool expanded=false);         bool expanded=false);
132    
# Line 142  class Data { Line 139  class Data {
139    */    */
140    ESCRIPT_DLL_API    ESCRIPT_DLL_API
141    Data(const Data& inData,    Data(const Data& inData,
142         const DataArrayView::RegionType& region);         const DataTypes::RegionType& region);
   
   /**  
      \brief  
      Constructor which will create Tagged data if expanded is false.  
      No attempt is made to ensure the tag keys match the tag keys  
      within the function space.  
   
      \param tagKeys - Input - List of tag values.  
      \param values - Input - List of values, one for each tag.  
      \param defaultValue - Input - A default value, used if tag doesn't exist.  
      \param what - Input - A description of what this data represents.  
      \param expanded - Input - Flag, if true fill the entire container with  
                        the appropriate values.  
     ==>*  
   */  
   ESCRIPT_DLL_API  
   Data(const DataTagged::TagListType& tagKeys,  
        const DataTagged::ValueListType& values,  
        const DataArrayView& defaultValue,  
        const FunctionSpace& what=FunctionSpace(),  
        bool expanded=false);  
143    
144    /**    /**
145       \brief       \brief
# Line 214  class Data { Line 190  class Data {
190       Constructor which creates a DataConstant of "shape" with constant value.       Constructor which creates a DataConstant of "shape" with constant value.
191    */    */
192    ESCRIPT_DLL_API    ESCRIPT_DLL_API
193    Data(double value,    Data(double value,
194         const boost::python::tuple& shape=boost::python::make_tuple(),         const boost::python::tuple& shape=boost::python::make_tuple(),
195         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
196         bool expanded=false);         bool expanded=false);
197    
198    
199    
200      /**
201        \brief Create a Data using an existing DataAbstract. Warning: The new object assumes ownership of the pointer!
202        Once you have passed the pointer, do not delete it.
203      */
204      ESCRIPT_DLL_API
205      Data(DataAbstract* underlyingdata);
206    
207    
208    /**    /**
209       \brief       \brief
210       Destructor       Destructor
# Line 226  class Data { Line 213  class Data {
213    ~Data();    ~Data();
214    
215    /**    /**
216       \brief       \brief Make this object a deep copy of "other".
      Perform a deep copy.  
217    */    */
218    ESCRIPT_DLL_API    ESCRIPT_DLL_API
219    void    void
220    copy(const Data& other);    copy(const Data& other);
221    
222    /**    /**
223         \brief Return a pointer to a deep copy of this object.
224      */
225      ESCRIPT_DLL_API
226      Data*
227      copySelf();
228    
229    
230    
231    
232      /**
233       Member access methods.       Member access methods.
234    */    */
235    
236    /**    /**
237       \brief       \brief
238       switches on update protection       switches on update protection
239    
240    */    */
241    ESCRIPT_DLL_API    ESCRIPT_DLL_API
# Line 254  class Data { Line 250  class Data {
250    ESCRIPT_DLL_API    ESCRIPT_DLL_API
251    bool    bool
252    isProtected() const;    isProtected() const;
253    
254    /**    /**
255       \brief       \brief
256       Return the values of all data-points as a single python numarray object.       Return the values of a data point on this process
257    */    */
258    ESCRIPT_DLL_API    ESCRIPT_DLL_API
259    const boost::python::numeric::array    const boost::python::numeric::array
260    convertToNumArray();    getValueOfDataPoint(int dataPointNo);
261    
262    /**    /**
263       \brief       \brief
264       Fills the expanded Data object from values of a python numarray object.       sets the values of a data-point from a python object on this process
265    */    */
266    ESCRIPT_DLL_API    ESCRIPT_DLL_API
267    void    void
268    fillFromNumArray(const boost::python::numeric::array);    setValueOfDataPointToPyObject(int dataPointNo, const boost::python::object& py_object);
269    
270    /**    /**
271       \brief       \brief
272       Return the values of a data point on this process       sets the values of a data-point from a numarray object on this process
   */  
   ESCRIPT_DLL_API  
   const boost::python::numeric::array  
   getValueOfDataPoint(int dataPointNo);  
   
   /**  
      \brief  
      sets the values of a data-point on this process  
273    */    */
274    ESCRIPT_DLL_API    ESCRIPT_DLL_API
275    void    void
276    setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array);    setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array&);
277    
278    /**    /**
279       \brief       \brief
# Line 306  class Data { Line 295  class Data {
295       \brief       \brief
296       Return the tag number associated with the given data-point.       Return the tag number associated with the given data-point.
297    
      The data-point number here corresponds to the data-point number in the  
      numarray returned by convertToNumArray.  
298    */    */
299    ESCRIPT_DLL_API    ESCRIPT_DLL_API
300    int    int
# Line 321  class Data { Line 308  class Data {
308    escriptDataC    escriptDataC
309    getDataC();    getDataC();
310    
311    
312    
313    
314    
315    
316    // REMOVE ME
317    // ESCRIPT_DLL_API
318    // void
319    // CompareDebug(const Data& rd);
320    
321    
322    /**    /**
323       \brief       \brief
324       Return the C wrapper for the Data object - const version.       Return the C wrapper for the Data object - const version.
# Line 331  class Data { Line 329  class Data {
329    
330    /**    /**
331       \brief       \brief
332       Write the data as a string.       Write the data as a string. For large amounts of data, a summary is printed.
333    */    */
334    ESCRIPT_DLL_API    ESCRIPT_DLL_API
   inline  
335    std::string    std::string
336    toString() const    toString() const;
   {  
     return m_data->toString();  
   }  
337    
338    /**  
339       \brief  //  /**
340    /*     \brief
341       Return the DataArrayView of the point data. This essentially contains       Return the DataArrayView of the point data. This essentially contains
342       the shape information for each data point although it also may be used       the shape information for each data point although it also may be used
343       to manipulate the point data.       to manipulate the point data.*/
344    */  //  */
345    ESCRIPT_DLL_API  //   ESCRIPT_DLL_API
346    inline  //   inline
347    const DataArrayView&  //   const DataArrayView&
348    getPointDataView() const  //   getPointDataView() const
349    {  //   {
350       return m_data->getPointDataView();  //      return m_data->getPointDataView();
351    }  //   }
352    
353    /**    /**
354       \brief       \brief
# Line 400  class Data { Line 395  class Data {
395    
396    /**    /**
397       \brief       \brief
398       Return true if this Data is empty.       Return true if this Data holds an instance of DataEmpty. This is _not_ the same as asking if the object
399    contains datapoints.
400    */    */
401    ESCRIPT_DLL_API    ESCRIPT_DLL_API
402    bool    bool
# Line 432  class Data { Line 428  class Data {
428    */    */
429    ESCRIPT_DLL_API    ESCRIPT_DLL_API
430    inline    inline
431    const AbstractDomain&  //   const AbstractDomain&
432      const_Domain_ptr
433    getDomain() const    getDomain() const
434    {    {
435       return getFunctionSpace().getDomain();       return getFunctionSpace().getDomain();
# Line 455  class Data { Line 452  class Data {
452    int    int
453    getDataPointRank() const    getDataPointRank() const
454    {    {
455      return m_data->getPointDataView().getRank();  //    return m_data->getPointDataView().getRank();
456        return m_data->getRank();
457    }    }
458    
459    /**    /**
# Line 492  class Data { Line 490  class Data {
490    {    {
491      return m_data->getNumDPPSample();      return m_data->getNumDPPSample();
492    }    }
493    
494    
495    /**    /**
496       \brief      \brief
497       dumps the object into a netCDF file      Return the number of values in the shape for this object.
498    */    */
499    ESCRIPT_DLL_API    ESCRIPT_DLL_API
500    inline    int
501    void    getNoValues() const
   dump(const std::string fileName) const  
502    {    {
503      return m_data->dump(fileName);      return m_data->getNoValues();
504    }    }
505    
506    
507      /**
508         \brief
509         dumps the object into a netCDF file
510      */
511      ESCRIPT_DLL_API
512      void
513      dump(const std::string fileName) const;
514    /**    /**
515       \brief       \brief
516       Return the sample data for the given sample no. This is not the       Return the sample data for the given sample no. This is not the
# Line 532  class Data { Line 539  class Data {
539      return m_data->getSampleDataByTag(tag);      return m_data->getSampleDataByTag(tag);
540    }    }
541    
542    //  /**
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    /**    /**
561       \brief       \brief
562       Return a view into the data for the data point specified.       Return a view into the data for the data point specified.
# Line 541  class Data { Line 566  class Data {
566       \param dataPointNo - Input -       \param dataPointNo - Input -
567    */    */
568    ESCRIPT_DLL_API    ESCRIPT_DLL_API
569      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    inline    inline
585    DataArrayView    DataTypes::ValueType::size_type
586    getDataPoint(int sampleNo,    getDataOffset(int sampleNo,
587                 int dataPointNo)                 int dataPointNo)
588    {    {
589          return m_data->getDataPoint(sampleNo,dataPointNo);                  return m_data->getPointOffset(sampleNo,dataPointNo);
590    }    }
591    
592    /**    /**
# Line 554  class Data { Line 594  class Data {
594       Return a reference to the data point shape.       Return a reference to the data point shape.
595    */    */
596    ESCRIPT_DLL_API    ESCRIPT_DLL_API
597    const DataArrayView::ShapeType&    inline
598    getDataPointShape() const;    const DataTypes::ShapeType&
599      getDataPointShape() const
600      {
601        return m_data->getShape();
602      }
603    
604    /**    /**
605       \brief       \brief
# Line 579  class Data { Line 623  class Data {
623       Return the number of doubles stored for this Data.       Return the number of doubles stored for this Data.
624    */    */
625    ESCRIPT_DLL_API    ESCRIPT_DLL_API
626    DataArrayView::ValueType::size_type    DataTypes::ValueType::size_type
627    getLength() const;    getLength() const;
628    
629    
630    
631    /**    /**
632       \brief       \brief
633       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag assocciated with name. Implicitly converts this
634       object to type DataTagged. Throws an exception if this object       object to type DataTagged. Throws an exception if this object
635       cannot be converted to a DataTagged object.       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         Assign the given value to the tag. Implicitly converts this
648         object to type DataTagged if it is constant.
649    
650       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
651       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
652      ==>*      ==>*
# Line 596  class Data { Line 656  class Data {
656    setTaggedValue(int tagKey,    setTaggedValue(int tagKey,
657                   const boost::python::object& value);                   const boost::python::object& value);
658    
659    
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    /**    /**
675       \brief       \brief
676       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
677       object to type DataTagged. Throws an exception if this object       object to type DataTagged if it is constant.
678       cannot be converted to a DataTagged object.  
679       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
680         \param pointshape - Input - The shape of the value parameter
681       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
682      ==>*       \param dataOffset - Input - Offset of the begining of the point within the value parameter
683    */    */
684    ESCRIPT_DLL_API    ESCRIPT_DLL_API
685    void    void
686    setTaggedValueFromCPP(int tagKey,    setTaggedValueFromCPP(int tagKey,
687                          const DataArrayView& value);              const DataTypes::ShapeType& pointshape,
688                            const DataTypes::ValueType& value,
689                int dataOffset=0);
690    
691    
692    
693    /**    /**
694      \brief      \brief
# Line 625  class Data { Line 705  class Data {
705    
706    /**    /**
707       \brief       \brief
708         set all values to zero
709         *
710      */
711      ESCRIPT_DLL_API
712      void
713      setToZero();
714    
715      /**
716         \brief
717       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
718       the result as a Data object.       the result as a Data object.
719       *       *
# Line 632  class Data { Line 721  class Data {
721    ESCRIPT_DLL_API    ESCRIPT_DLL_API
722    Data    Data
723    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
   
724    /**    /**
725       \brief       \brief
726       Calculates the gradient of the data at the data points of functionspace.       Calculates the gradient of the data at the data points of functionspace.
# Line 729  class Data { Line 817  class Data {
817    
818    /**    /**
819       \brief       \brief
      Return the minimum absolute value of this Data object.  
      *  
   */  
   ESCRIPT_DLL_API  
   double  
   Linf() const;  
   
   /**  
      \brief  
820       Return the maximum value of this Data object.       Return the maximum value of this Data object.
821       *       *
822    */    */
# Line 852  class Data { Line 931  class Data {
931    /**    /**
932       \brief       \brief
933       Return the eigenvalues and corresponding eigenvcetors of the symmetric part at each data point of this Data object.       Return the eigenvalues and corresponding eigenvcetors of the symmetric part at each data point of this Data object.
934       the eigenvalues are ordered in increasing size where eigenvalues with relative difference less than       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       tol are treated as equal. The eigenvectors are orthogonal, normalized and the sclaed such that the
936       first non-zero entry is positive.       first non-zero entry is positive.
937       Currently this function is restricted to rank 2, square shape, and dimension 3       Currently this function is restricted to rank 2, square shape, and dimension 3
938       *       *
# Line 1057  class Data { Line 1136  class Data {
1136    /**    /**
1137       \brief       \brief
1138       Return the given power of each data point of this boost python object.       Return the given power of each data point of this boost python object.
1139        
1140       \param right Input - the power to raise the object to.       \param right Input - the power to raise the object to.
1141       *       *
1142     */     */
# Line 1068  class Data { Line 1147  class Data {
1147    /**    /**
1148       \brief       \brief
1149       Return the given power of each data point of this boost python object.       Return the given power of each data point of this boost python object.
1150        
1151       \param left Input - the bases       \param left Input - the bases
1152       *       *
1153     */     */
# Line 1104  class Data { Line 1183  class Data {
1183    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1184    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
1185    
1186      ESCRIPT_DLL_API
1187      Data& operator=(const Data& other);
1188    
1189    /**    /**
1190       \brief       \brief
1191       Overloaded operator -=       Overloaded operator -=
# Line 1196  class Data { Line 1278  class Data {
1278    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1279    inline    inline
1280    void    void
1281    unaryOp(UnaryFunction operation);    unaryOp2(UnaryFunction operation);
1282    
1283    /**    /**
1284       \brief       \brief
# Line 1207  class Data { Line 1289  class Data {
1289    */    */
1290    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1291    Data    Data
1292    getSlice(const DataArrayView::RegionType& region) const;    getSlice(const DataTypes::RegionType& region) const;
1293    
1294    /**    /**
1295       \brief       \brief
# Line 1220  class Data { Line 1302  class Data {
1302    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1303    void    void
1304    setSlice(const Data& value,    setSlice(const Data& value,
1305             const DataArrayView::RegionType& region);             const DataTypes::RegionType& region);
1306    
1307    /**    /**
1308       \brief       \brief
1309       Archive the current Data object to the given file.       print the data values to stdout. Used for debugging
      \param fileName - Input - file to archive to.  
1310    */    */
1311    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1312    void    void
1313    archiveData(const std::string fileName);          print(void);
1314    
1315    /**    /**
1316       \brief       \brief
1317       Extract the Data object archived in the given file, overwriting       return the MPI rank number of the local data
1318       the current Data object.                   MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1319       Note - the current object must be of type DataEmpty.                   is returned
      \param fileName - Input - file to extract from.  
      \param fspace - Input - a suitable FunctionSpace descibing the data.  
1320    */    */
1321    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1322    void          int
1323    extractData(const std::string fileName,          get_MPIRank(void) const;
               const FunctionSpace& fspace);  
   
1324    
1325    /**    /**
1326       \brief       \brief
1327       print the data values to stdout. Used for debugging       return the MPI rank number of the local data
1328                     MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1329                     is returned
1330    */    */
1331    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1332    void          int
1333      print(void);          get_MPISize(void) const;
1334    
1335    /**    /**
1336       \brief       \brief
1337       return the MPI rank number of the local data       return the MPI rank number of the local data
1338           MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()                   MPI_COMM_WORLD is assumed and returned.
          is returned  
1339    */    */
1340    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1341      int          MPI_Comm
1342      get_MPIRank(void) const;          get_MPIComm(void) const;
1343    
1344    /**    /**
1345       \brief       \brief
1346       return the MPI rank number of the local data       return the object produced by the factory, which is a DataConstant or DataExpanded
1347           MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()      TODO Ownership of this object should be explained in doco.
          is returned  
1348    */    */
1349    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1350      int          DataAbstract*
1351      get_MPISize(void) const;          borrowData(void) const;
1352    
1353    
1354    /**    /**
1355       \brief       \brief
1356       return the MPI rank number of the local data       Return a pointer to the beginning of the datapoint at the specified offset.
1357           MPI_COMM_WORLD is assumed and returned.       TODO Eventually these should be inlined.
1358         \param i - position(offset) in the underlying datastructure
1359    */    */
1360    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1361      MPI_Comm          DataTypes::ValueType::const_reference
1362      get_MPIComm(void) const;          getDataAtOffset(DataTypes::ValueType::size_type i) const;
1363    
1364    
   /**  
      \brief  
      return the object produced by the factory, which is a DataConstant or DataExpanded  
   */  
1365    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1366      DataAbstract*          DataTypes::ValueType::reference
1367      borrowData(void) const;          getDataAtOffset(DataTypes::ValueType::size_type i);
1368    
1369   protected:   protected:
1370    
# Line 1365  class Data { Line 1441  class Data {
1441       \brief       \brief
1442       Construct a Data object of the appropriate type.       Construct a Data object of the appropriate type.
1443    */    */
1444    template <class IValueType>  
1445    void    void
1446    initialise(const IValueType& value,    initialise(const DataTypes::ValueType& value,
1447             const DataTypes::ShapeType& shape,
1448               const FunctionSpace& what,               const FunctionSpace& what,
1449               bool expanded);               bool expanded);
1450    
1451      void
1452      initialise(const boost::python::numeric::array& value,
1453                     const FunctionSpace& what,
1454                     bool expanded);
1455    
1456    //    //
1457    // flag to protect the data object against any update    // flag to protect the data object against any update
1458    bool m_protected;    bool m_protected;
# Line 1379  class Data { Line 1461  class Data {
1461    // pointer to the actual data object    // pointer to the actual data object
1462    boost::shared_ptr<DataAbstract> m_data;    boost::shared_ptr<DataAbstract> m_data;
1463    
   //  
   // pointer to the internal profiling data  
   struct profDataEntry *profData;  
   
1464  };  };
1465    
1466  template <class IValueType>  
1467  void  
1468  Data::initialise(const IValueType& value,  /**
1469                   const FunctionSpace& what,     Modify a filename for MPI parallel output to multiple files
1470                   bool expanded)  */
1471  {  char *Escript_MPI_appendRankToFileName(const char *, int, int);
   //  
   // Construct a Data object of the appropriate type.  
   // Construct the object first as there seems to be a bug which causes  
   // undefined behaviour if an exception is thrown during construction  
   // within the shared_ptr constructor.  
   if (expanded) {  
     DataAbstract* temp=new DataExpanded(value,what);  
     boost::shared_ptr<DataAbstract> temp_data(temp);  
     m_data=temp_data;  
   } else {  
     DataAbstract* temp=new DataConstant(value,what);  
     boost::shared_ptr<DataAbstract> temp_data(temp);  
     m_data=temp_data;  
   }  
 }  
1472    
1473  /**  /**
1474     Binary Data object operators.     Binary Data object operators.
1475  */  */
1476  inline double rpow(double x,double y)  inline double rpow(double x,double y)
1477  {  {
1478      return pow(y,x);      return pow(y,x);
1479  };  }
1480    
1481  /**  /**
1482    \brief    \brief
# Line 1507  ESCRIPT_DLL_API Data operator*(const boo Line 1570  ESCRIPT_DLL_API Data operator*(const boo
1570  */  */
1571  ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);  ESCRIPT_DLL_API Data operator/(const boost::python::object& left, const Data& right);
1572    
1573    
1574    
1575  /**  /**
1576    \brief    \brief
1577    Output operator    Output operator
# Line 1528  C_GeneralTensorProduct(Data& arg0, Line 1593  C_GeneralTensorProduct(Data& arg0,
1593                       int axis_offset=0,                       int axis_offset=0,
1594                       int transpose=0);                       int transpose=0);
1595    
1596  /**  
1597    \brief  
1598    // /**
1599    /*  \brief
1600    Return true if operands are equivalent, else return false.    Return true if operands are equivalent, else return false.
1601    NB: this operator does very little at this point, and isn't to    NB: this operator does very little at this point, and isn't to
1602    be relied on. Requires further implementation.    be relied on. Requires further implementation.*/
1603  */  //*/
1604  //ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);  // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1605    
1606  /**  /**
1607    \brief    \brief
# Line 1549  Data::binaryOp(const Data& right, Line 1616  Data::binaryOp(const Data& right,
1616  {  {
1617     //     //
1618     // if this has a rank of zero promote it to the rank of the RHS     // if this has a rank of zero promote it to the rank of the RHS
1619     if (getPointDataView().getRank()==0 && right.getPointDataView().getRank()!=0) {     if (getDataPointRank()==0 && right.getDataPointRank()!=0) {
1620       throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");       throw DataException("Error - attempt to update rank zero object with object with rank bigger than zero.");
1621     }     }
1622     //     //
# Line 1558  Data::binaryOp(const Data& right, Line 1625  Data::binaryOp(const Data& right,
1625     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1626       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1627         //         //
1628         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1629         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1630       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1631         //         //
# Line 1602  Data::binaryOp(const Data& right, Line 1669  Data::binaryOp(const Data& right,
1669       EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");       EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
1670       escript::binaryOp(*leftC,*rightC,operation);       escript::binaryOp(*leftC,*rightC,operation);
1671     }     }
    #if defined DOPROF  
    profData->binary++;  
    #endif  
 }  
   
 /**  
   \brief  
   Perform the given unary operation on other and return the result.  
   Given operation is performed on each element of each data point, thus  
   argument object is a rank n Data object, and returned object is a rank n  
   Data object.  
   Calls Data::unaryOp.  
 */  
 template <class UnaryFunction>  
 inline  
 Data  
 unaryOp(const Data& other,  
         UnaryFunction operation)  
 {  
   Data result;  
   result.copy(other);  
   result.unaryOp(operation);  
   return result;  
 }  
   
 /**  
   \brief  
   Perform the given unary operation on this.  
   Given operation is performed on each element of each data point.  
   Calls escript::unaryOp.  
 */  
 template <class UnaryFunction>  
 inline  
 void  
 Data::unaryOp(UnaryFunction operation)  
 {  
   if (isExpanded()) {  
     DataExpanded* leftC=dynamic_cast<DataExpanded*>(m_data.get());  
     EsysAssert((leftC!=0), "Programming error - casting to DataExpanded.");  
     escript::unaryOp(*leftC,operation);  
   } else if (isTagged()) {  
     DataTagged* leftC=dynamic_cast<DataTagged*>(m_data.get());  
     EsysAssert((leftC!=0), "Programming error - casting to DataTagged.");  
     escript::unaryOp(*leftC,operation);  
   } else if (isConstant()) {  
     DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());  
     EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");  
     escript::unaryOp(*leftC,operation);  
   }  
1672  }  }
1673    
1674  /**  /**
# Line 1677  Data::algorithm(BinaryFunction operation Line 1695  Data::algorithm(BinaryFunction operation
1695      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* leftC=dynamic_cast<DataConstant*>(m_data.get());
1696      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");      EsysAssert((leftC!=0), "Programming error - casting to DataConstant.");
1697      return escript::algorithm(*leftC,operation,initial_value);      return escript::algorithm(*leftC,operation,initial_value);
1698      } else if (isEmpty()) {
1699        throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1700    }    }
1701    return 0;    return 0;
1702  }  }
# Line 1685  Data::algorithm(BinaryFunction operation Line 1705  Data::algorithm(BinaryFunction operation
1705    \brief    \brief
1706    Perform the given data point reduction algorithm on data and return the result.    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,    Given operation combines each element within each data point into a scalar,
1708    thus argument object is a rank n Data object, and returned object is a    thus argument object is a rank n Data object, and returned object is a
1709    rank 0 Data object.    rank 0 Data object.
1710    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1711  */  */
# Line 1694  inline Line 1714  inline
1714  Data  Data
1715  Data::dp_algorithm(BinaryFunction operation, double initial_value) const  Data::dp_algorithm(BinaryFunction operation, double initial_value) const
1716  {  {
1717    if (isExpanded()) {    if (isEmpty()) {
1718      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());      throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1719      }
1720      else if (isExpanded()) {
1721        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1722      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());      DataExpanded* dataE=dynamic_cast<DataExpanded*>(m_data.get());
1723      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());      DataExpanded* resultE=dynamic_cast<DataExpanded*>(result.m_data.get());
1724      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");      EsysAssert((dataE!=0), "Programming error - casting data to DataExpanded.");
1725      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");      EsysAssert((resultE!=0), "Programming error - casting result to DataExpanded.");
1726      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);      escript::dp_algorithm(*dataE,*resultE,operation,initial_value);
1727      return result;      return result;
1728    } else if (isTagged()) {    }
1729      else if (isTagged()) {
1730      DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());      DataTagged* dataT=dynamic_cast<DataTagged*>(m_data.get());
     DataArrayView::ShapeType viewShape;  
     DataArrayView::ValueType viewData(1);  
     viewData[0]=0;  
     DataArrayView defaultValue(viewData,viewShape);  
     DataTagged::TagListType keys;  
     DataTagged::ValueListType values;  
     DataTagged::DataMapType::const_iterator i;  
     for (i=dataT->getTagLookup().begin();i!=dataT->getTagLookup().end();i++) {  
       keys.push_back(i->first);  
       values.push_back(defaultValue);  
     }  
     Data result(keys,values,defaultValue,getFunctionSpace());  
     DataTagged* resultT=dynamic_cast<DataTagged*>(result.m_data.get());  
1731      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");      EsysAssert((dataT!=0), "Programming error - casting data to DataTagged.");
1732      EsysAssert((resultT!=0), "Programming error - casting result to DataTagged.");      DataTypes::ValueType defval(1);
1733        defval[0]=0;
1734        DataTagged* resultT=new DataTagged(getFunctionSpace(), DataTypes::scalarShape, defval, dataT);
1735      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);      escript::dp_algorithm(*dataT,*resultT,operation,initial_value);
1736      return result;      return Data(resultT);   // note: the Data object now owns the resultT pointer
1737    } else if (isConstant()) {    }
1738      Data result(0,DataArrayView::ShapeType(),getFunctionSpace(),isExpanded());    else if (isConstant()) {
1739        Data result(0,DataTypes::ShapeType(),getFunctionSpace(),isExpanded());
1740      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());      DataConstant* dataC=dynamic_cast<DataConstant*>(m_data.get());
1741      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());      DataConstant* resultC=dynamic_cast<DataConstant*>(result.m_data.get());
1742      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");      EsysAssert((dataC!=0), "Programming error - casting data to DataConstant.");
# Line 1734  Data::dp_algorithm(BinaryFunction operat Line 1748  Data::dp_algorithm(BinaryFunction operat
1748    return falseRetVal;    return falseRetVal;
1749  }  }
1750    
1751    /**
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    template <typename BinaryFunction>
1759    inline
1760    Data
1761    C_TensorBinaryOperation(Data const &arg_0,
1762                            Data const &arg_1,
1763                            BinaryFunction operation)
1764    {
1765      if (arg_0.isEmpty() || arg_1.isEmpty())
1766      {
1767         throw DataException("Error - Operations not permitted on instances of DataEmpty.");
1768      }
1769      // 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      DataTypes::ShapeType shape0 = arg_0_Z.getDataPointShape();
1791      DataTypes::ShapeType shape1 = arg_1_Z.getDataPointShape();
1792      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          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
1802    /*      double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1803          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1804          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          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          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
1821          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          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
1827          // Get the views
1828    //       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          // Get the pointers to the actual data
1835          double *ptr_1 = &(tmp_1->getDefaultValue(0));
1836          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1837    
1838          // 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            tmp_2->addTag(i->first);
1845    /*        DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1846            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1847            double *ptr_1 = &view_1.getData(0);
1848            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            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1853          }
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            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    //           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              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1880            }
1881          }
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          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
1894          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    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1900          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
1901          // Get the views
1902    //       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          // Get the pointers to the actual data
1908          double *ptr_0 = &(tmp_0->getDefaultValue(0));
1909          double *ptr_2 = &(tmp_2->getDefaultValue(0));
1910          // 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            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            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1924          }
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          res.tag();        // DataTagged output
1938          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1939    
1940    //       // 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          // Get the pointers to the actual data
1950          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          // 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            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
1962          }
1963          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1964            tmp_2->addTag(i->first);
1965          }
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    
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            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1982          }
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            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
1999            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2000            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    
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              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2011            }
2012          }
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            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    
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              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2042            }
2043          }
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            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2060            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2061            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              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2065              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2066              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2067            }
2068          }
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            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              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              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
2092            }
2093          }
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          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataConstant output
2104          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          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          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataTagged output
2119          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          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2125          // Get the views
2126    //       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          // 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            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            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2148          }
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            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              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              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2171    
2172            }
2173          }
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          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());      // DataTagged output
2186          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    //       double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2192          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2193          // Get the views
2194    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2195          DataArrayView view_2 = tmp_2->getDefaultValue();
2196          // Get the pointers to the actual data
2197          double *ptr_0 = &((view_0.getData())[0]);
2198          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          // 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            tmp_2->addTag(i->first);
2212    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2213            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2214            double *ptr_0 = &view_0.getData(0);
2215            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            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2220          }
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          res.tag();        // DataTagged output
2234          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2235    
2236          // Get the views
2237    /*      DataArrayView view_0 = tmp_0->getDefaultValue();
2238          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          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          // 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            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2259          }
2260          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2261            tmp_2->addTag(i->first);
2262          }
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    
2267    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2268            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            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            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2279          }
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            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2296            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2297            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              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2301              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2302              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2303            }
2304          }
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            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              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              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2327            }
2328          }
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            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2346            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2347            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              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2351              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2352              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2353            }
2354          }
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            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              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              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2378            }
2379          }
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          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
2390          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          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          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
2405          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          double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2411          // Get the views
2412    /*      DataArrayView view_1 = tmp_1->getDefaultValue();
2413          DataArrayView view_2 = tmp_2->getDefaultValue();
2414          // Get the pointers to the actual data
2415          double *ptr_1 = &((view_1.getData())[0]);
2416          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          // 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            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            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2437          }
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            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              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              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2460            }
2461          }
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          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
2474          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          double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2480          // Get the views
2481    //       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          // Get the pointers to the actual data
2487          double *ptr_0 = &(tmp_0->getDefaultValue(0));
2488          double *ptr_2 = &(tmp_2->getDefaultValue(0));
2489          // 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            tmp_2->addTag(i->first);
2496    /*        DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2497            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2498            double *ptr_0 = &view_0.getData(0);
2499            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            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2503          }
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          res.tag();        // DataTagged output
2517          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2518    
2519          // Get the views
2520    //       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          // Get the pointers to the actual data
2529          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          // 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            tmp_2->addTag(i->first); // use tmp_2 to get correct shape
2541          }
2542          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2543            tmp_2->addTag(i->first);
2544          }
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    //         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            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2559          }
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            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2576            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2577            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              double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2581              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2582              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2583            }
2584          }
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            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              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              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2607            }
2608          }
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            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2626            double *ptr_1 = &(arg_1_Z.getDataAtOffset(offset_1));
2627            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              double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2631              double *ptr_2 = &(res.getDataAtOffset(offset_2));
2632              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2633            }
2634          }
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            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              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              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2658            }
2659          }
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    }
2672    
2673    template <typename UnaryFunction>
2674    Data
2675    C_TensorUnaryOperation(Data const &arg_0,
2676                           UnaryFunction operation)
2677    {
2678      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      // 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      const DataTypes::ShapeType& shape0 = arg_0_Z.getDataPointShape();
2689      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    //     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        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    //     // 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        // Get the pointers to the actual data
2719        double *ptr_0 = &(tmp_0->getDefaultValue(0));
2720        double *ptr_2 = &(tmp_2->getDefaultValue(0));
2721        // 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          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          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    //         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            int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2755            int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2756            double *ptr_0 = &(arg_0_Z.getDataAtOffset(offset_0));
2757            double *ptr_2 = &(res.getDataAtOffset(offset_2));
2758            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    }
2768    
2769  }  }
2770  #endif  #endif

Legend:
Removed from v.971  
changed lines
  Added in v.1821

  ViewVC Help
Powered by ViewVC 1.1.26