/[escript]/trunk/escript/src/Data.h
ViewVC logotype

Diff of /trunk/escript/src/Data.h

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

revision 854 by gross, Thu Sep 21 05:29:42 2006 UTC revision 1430 by trankine, Wed Feb 27 09:07:19 2008 UTC
# Line 1  Line 1 
1  // $Id$  
2  /*  /* $Id$ */
3   ************************************************************  
4   *          Copyright 2006 by ACcESS MNRF                   *  /*******************************************************
5   *                                                          *   *
6   *              http://www.access.edu.au                    *   *           Copyright 2003-2007 by ACceSS MNRF
7   *       Primary Business: Queensland, Australia            *   *       Copyright 2007 by University of Queensland
8   *  Licensed under the Open Software License version 3.0    *   *
9   *     http://www.opensource.org/licenses/osl-3.0.php       *   *                http://esscc.uq.edu.au
10   *                                                          *   *        Primary Business: Queensland, Australia
11   ************************************************************   *  Licensed under the Open Software License version 3.0
12  */   *     http://www.opensource.org/licenses/osl-3.0.php
13     *
14     *******************************************************/
15    
16  /** \file Data.h */  /** \file Data.h */
17    
# Line 26  Line 28 
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    
# Line 51  class DataExpanded; Line 50  class DataExpanded;
50    
51  /**  /**
52     \brief     \brief
53     Data creates the appropriate Data object for the given construction     Data creates the appropriate Data object for the given construction
54     arguments.     arguments.
55    
56     Description:     Description:
57     Data is essentially a factory class which creates the appropriate Data     Data is essentially a factory class which creates the appropriate Data
# Line 214  class Data { Line 213  class Data {
213       Constructor which creates a DataConstant of "shape" with constant value.       Constructor which creates a DataConstant of "shape" with constant value.
214    */    */
215    ESCRIPT_DLL_API    ESCRIPT_DLL_API
216    Data(double value,    Data(double value,
217         const boost::python::tuple& shape=boost::python::make_tuple(),         const boost::python::tuple& shape=boost::python::make_tuple(),
218         const FunctionSpace& what=FunctionSpace(),         const FunctionSpace& what=FunctionSpace(),
219         bool expanded=false);         bool expanded=false);
220    /**    /**
# Line 239  class Data { Line 238  class Data {
238    
239    /**    /**
240       \brief       \brief
241       switches on update protection       switches on update protection
242    
243    */    */
244    ESCRIPT_DLL_API    ESCRIPT_DLL_API
# Line 254  class Data { Line 253  class Data {
253    ESCRIPT_DLL_API    ESCRIPT_DLL_API
254    bool    bool
255    isProtected() const;    isProtected() const;
256    
257    /**    /**
258       \brief       \brief
259       Return the values of all data-points as a single python numarray object.       Return the values of a data point on this process
260    */    */
261    ESCRIPT_DLL_API    ESCRIPT_DLL_API
262    const boost::python::numeric::array    const boost::python::numeric::array
263    convertToNumArray();    getValueOfDataPoint(int dataPointNo);
264    
265    /**    /**
266       \brief       \brief
267       Return the values of all data-points for the given sample as a single python numarray object.       sets the values of a data-point from a python object on this process
268    */    */
269    ESCRIPT_DLL_API    ESCRIPT_DLL_API
270    const boost::python::numeric::array    void
271    convertToNumArrayFromSampleNo(int sampleNo);    setValueOfDataPointToPyObject(int dataPointNo, const boost::python::object& py_object);
272    
273    /**    /**
274       \brief       \brief
275       Return the value of the specified data-point as a single python numarray object.       sets the values of a data-point from a numarray object on this process
276    */    */
 #ifndef PASO_MPI    
277    ESCRIPT_DLL_API    ESCRIPT_DLL_API
278    const boost::python::numeric::array    void
279    convertToNumArrayFromDPNo(int ProcNo,    setValueOfDataPointToArray(int dataPointNo, const boost::python::numeric::array&);
                                                         int sampleNo,  
                             int dataPointNo);  
 #else  
   ESCRIPT_DLL_API  
   const boost::python::numeric::array  
   convertToNumArrayFromDPNo(int procNo,  
                 int sampleNo,  
                 int dataPointNo);  
 #endif  
   
280    
281    /**    /**
282       \brief       \brief
283       Fills the expanded Data object from values of a python numarray object.       sets the values of a data-point on this process
284    */    */
285    ESCRIPT_DLL_API    ESCRIPT_DLL_API
286    void    void
287    fillFromNumArray(const boost::python::numeric::array);    setValueOfDataPoint(int dataPointNo, const double);
288    
289      /**
290         \brief
291         Return the value of the specified data-point across all processors
292      */
293      ESCRIPT_DLL_API
294      const boost::python::numeric::array
295      getValueOfGlobalDataPoint(int procNo, int dataPointNo);
296    
297    /**    /**
298       \brief       \brief
# Line 455  class Data { Line 452  class Data {
452    
453    /**    /**
454       \brief       \brief
455         Return the number of data points
456      */
457      ESCRIPT_DLL_API
458      inline
459      int
460      getNumDataPoints() const
461      {
462        return getNumSamples() * getNumDataPointsPerSample();
463      }
464      /**
465         \brief
466       Return the number of samples.       Return the number of samples.
467    */    */
468    ESCRIPT_DLL_API    ESCRIPT_DLL_API
# Line 476  class Data { Line 484  class Data {
484    {    {
485      return m_data->getNumDPPSample();      return m_data->getNumDPPSample();
486    }    }
487      /**
488         \brief
489         dumps the object into a netCDF file
490      */
491      ESCRIPT_DLL_API
492      void
493      dump(const std::string fileName) const;
494    /**    /**
495       \brief       \brief
496       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 507  class Data { Line 521  class Data {
521    
522    /**    /**
523       \brief       \brief
      Assign the given value to the data-points referenced by the given  
      reference number.  
   
      The value supplied is a python numarray object.  The data from this numarray  
      is unpacked into a DataArray, and this is used to set the corresponding  
      data-points in the underlying Data object.  
   
      If the underlying Data object cannot be accessed via reference numbers, an  
      exception will be thrown.  
   
      \param ref - Input - reference number.  
      \param value - Input - value to assign to data-points associated with  
                             the given reference number.  
   */  
   ESCRIPT_DLL_API  
   void  
   setRefValue(int ref,  
               const boost::python::numeric::array& value);  
   
   /**  
      \brief  
      Return the values associated with the data-points referenced by the given  
      reference number.  
   
      The value supplied is a python numarray object. The data from the corresponding  
      data-points in this Data object are packed into the given numarray object.  
   
      If the underlying Data object cannot be accessed via reference numbers, an  
      exception will be thrown.  
   
      \param ref - Input - reference number.  
      \param value - Output - object to receive values from data-points  
                              associated with the given reference number.  
   */  
   ESCRIPT_DLL_API  
   void  
   getRefValue(int ref,  
               boost::python::numeric::array& value);  
   
   /**  
      \brief  
524       Return a view into the data for the data point specified.       Return a view into the data for the data point specified.
525       NOTE: Construction of the DataArrayView is a relatively expensive       NOTE: Construction of the DataArrayView is a relatively expensive
526       operation.       operation.
# Line 560  class Data { Line 533  class Data {
533    getDataPoint(int sampleNo,    getDataPoint(int sampleNo,
534                 int dataPointNo)                 int dataPointNo)
535    {    {
536          return m_data->getDataPoint(sampleNo,dataPointNo);                  return m_data->getDataPoint(sampleNo,dataPointNo);
537    }    }
538    
539    /**    /**
# Line 596  class Data { Line 569  class Data {
569    DataArrayView::ValueType::size_type    DataArrayView::ValueType::size_type
570    getLength() const;    getLength() const;
571    
572    
573    
574    /**    /**
575       \brief       \brief
576       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag assocciated with name. Implicitly converts this
577       object to type DataTagged. Throws an exception if this object       object to type DataTagged. Throws an exception if this object
578       cannot be converted to a DataTagged object.       cannot be converted to a DataTagged object or name cannot be mapped onto a tag key.
579         \param tagKey - Input - Integer key.
580         \param value - Input - Value to associate with given key.
581        ==>*
582      */
583      ESCRIPT_DLL_API
584      void
585      setTaggedValueByName(std::string name,
586                           const boost::python::object& value);
587    
588      /**
589         \brief
590         Assign the given value to the tag. Implicitly converts this
591         object to type DataTagged if it is constant.
592    
593       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
594       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
595      ==>*      ==>*
# Line 613  class Data { Line 602  class Data {
602    /**    /**
603       \brief       \brief
604       Assign the given value to the tag. Implicitly converts this       Assign the given value to the tag. Implicitly converts this
605       object to type DataTagged. Throws an exception if this object       object to type DataTagged if it is constant.
606       cannot be converted to a DataTagged object.  
607       \param tagKey - Input - Integer key.       \param tagKey - Input - Integer key.
608       \param value - Input - Value to associate with given key.       \param value - Input - Value to associate with given key.
609      ==>*      ==>*
# Line 639  class Data { Line 628  class Data {
628    
629    /**    /**
630       \brief       \brief
631         set all values to zero
632         *
633      */
634      ESCRIPT_DLL_API
635      void
636      setToZero();
637    
638      /**
639         \brief
640       Interpolates this onto the given functionspace and returns       Interpolates this onto the given functionspace and returns
641       the result as a Data object.       the result as a Data object.
642       *       *
# Line 646  class Data { Line 644  class Data {
644    ESCRIPT_DLL_API    ESCRIPT_DLL_API
645    Data    Data
646    interpolate(const FunctionSpace& functionspace) const;    interpolate(const FunctionSpace& functionspace) const;
   
647    /**    /**
648       \brief       \brief
649       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 743  class Data { Line 740  class Data {
740    
741    /**    /**
742       \brief       \brief
      Return the minimum absolute value of this Data object.  
      *  
   */  
   ESCRIPT_DLL_API  
   double  
   Linf() const;  
   
   /**  
      \brief  
743       Return the maximum value of this Data object.       Return the maximum value of this Data object.
744       *       *
745    */    */
# Line 802  class Data { Line 790  class Data {
790    */    */
791    ESCRIPT_DLL_API    ESCRIPT_DLL_API
792    const boost::python::tuple    const boost::python::tuple
793    mindp() const;    minGlobalDataPoint() const;
794    
795    ESCRIPT_DLL_API    ESCRIPT_DLL_API
796    void    void
797    calc_mindp(int& ProcNo,    calc_minGlobalDataPoint(int& ProcNo,  int& DataPointNo) const;
                         int& SampleNo,    
              int& DataPointNo) const;  
798    /**    /**
799       \brief       \brief
800       Return the sign of each data point of this Data object.       Return the sign of each data point of this Data object.
# Line 868  class Data { Line 854  class Data {
854    /**    /**
855       \brief       \brief
856       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.
857       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
858       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
859       first non-zero entry is positive.       first non-zero entry is positive.
860       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
861       *       *
# Line 889  class Data { Line 875  class Data {
875    
876    /**    /**
877       \brief       \brief
878         Return the error function erf of each data point of this Data object.
879         *
880      */
881      ESCRIPT_DLL_API
882      Data
883      erf() const;
884    
885      /**
886         \brief
887       Return the sin of each data point of this Data object.       Return the sin of each data point of this Data object.
888       *       *
889    */    */
# Line 1064  class Data { Line 1059  class Data {
1059    /**    /**
1060       \brief       \brief
1061       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.
1062        
1063       \param right Input - the power to raise the object to.       \param right Input - the power to raise the object to.
1064       *       *
1065     */     */
# Line 1075  class Data { Line 1070  class Data {
1070    /**    /**
1071       \brief       \brief
1072       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.
1073        
1074       \param left Input - the bases       \param left Input - the bases
1075       *       *
1076     */     */
# Line 1111  class Data { Line 1106  class Data {
1106    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1107    Data& operator+=(const boost::python::object& right);    Data& operator+=(const boost::python::object& right);
1108    
1109      ESCRIPT_DLL_API
1110      Data& operator=(const Data& other);
1111    
1112    /**    /**
1113       \brief       \brief
1114       Overloaded operator -=       Overloaded operator -=
# Line 1203  class Data { Line 1201  class Data {
1201    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1202    inline    inline
1203    void    void
1204    unaryOp(UnaryFunction operation);    unaryOp2(UnaryFunction operation);
1205    
1206    /**    /**
1207       \brief       \brief
# Line 1254  class Data { Line 1252  class Data {
1252    
1253    /**    /**
1254       \brief       \brief
1255       print the data values to stdout. Used for debugging       print the data values to stdout. Used for debugging
1256    */    */
1257    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1258    void    void
1259      print(void);          print(void);
1260    
1261    /**    /**
1262       \brief       \brief
1263       return the MPI rank number of the local data       return the MPI rank number of the local data
1264           MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()                   MPI_COMM_WORLD is assumed and the result of MPI_Comm_size()
1265           is returned                   is returned
1266    */    */
1267    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1268      int          int
1269      get_MPIRank(void) const;          get_MPIRank(void) const;
1270    
1271    /**    /**
1272       \brief       \brief
1273       return the MPI rank number of the local data       return the MPI rank number of the local data
1274           MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()                   MPI_COMM_WORLD is assumed and the result of MPI_Comm_rank()
1275           is returned                   is returned
1276    */    */
1277    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1278      int          int
1279      get_MPISize(void) const;          get_MPISize(void) const;
1280    
1281    /**    /**
1282       \brief       \brief
1283       return the MPI rank number of the local data       return the MPI rank number of the local data
1284           MPI_COMM_WORLD is assumed and returned.                   MPI_COMM_WORLD is assumed and returned.
1285    */    */
1286    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1287      MPI_Comm          MPI_Comm
1288      get_MPIComm(void) const;          get_MPIComm(void) const;
1289    
1290    /**    /**
1291       \brief       \brief
1292       return the object produced by the factory, which is a DataConstant or DataExpanded       return the object produced by the factory, which is a DataConstant or DataExpanded
1293    */    */
1294    ESCRIPT_DLL_API    ESCRIPT_DLL_API
1295      DataAbstract*          DataAbstract*
1296      borrowData(void) const;          borrowData(void) const;
1297    
1298   protected:   protected:
1299    
# Line 1386  class Data { Line 1384  class Data {
1384    // pointer to the actual data object    // pointer to the actual data object
1385    boost::shared_ptr<DataAbstract> m_data;    boost::shared_ptr<DataAbstract> m_data;
1386    
   //  
   // pointer to the internal profiling data  
   struct profDataEntry *profData;  
   
1387  };  };
1388    
1389  template <class IValueType>  template <class IValueType>
# Line 1417  Data::initialise(const IValueType& value Line 1411  Data::initialise(const IValueType& value
1411  /**  /**
1412     Binary Data object operators.     Binary Data object operators.
1413  */  */
1414  inline double rpow(double x,double y)  inline double rpow(double x,double y)
1415  {  {
1416      return pow(y,x);      return pow(y,x);
1417  };  }
1418    
1419  /**  /**
1420    \brief    \brief
# Line 1514  ESCRIPT_DLL_API Data operator*(const boo Line 1508  ESCRIPT_DLL_API Data operator*(const boo
1508  */  */
1509  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);
1510    
1511    
1512    
1513  /**  /**
1514    \brief    \brief
1515    Output operator    Output operator
# Line 1535  C_GeneralTensorProduct(Data& arg0, Line 1531  C_GeneralTensorProduct(Data& arg0,
1531                       int axis_offset=0,                       int axis_offset=0,
1532                       int transpose=0);                       int transpose=0);
1533    
1534    
1535    
1536  /**  /**
1537    \brief    \brief
1538    Return true if operands are equivalent, else return false.    Return true if operands are equivalent, else return false.
1539    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
1540    be relied on. Requires further implementation.    be relied on. Requires further implementation.
1541  */  */
1542  //ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);  // ESCRIPT_DLL_API bool operator==(const Data& left, const Data& right);
1543    
1544  /**  /**
1545    \brief    \brief
# Line 1565  Data::binaryOp(const Data& right, Line 1563  Data::binaryOp(const Data& right,
1563     if (getFunctionSpace()!=right.getFunctionSpace()) {     if (getFunctionSpace()!=right.getFunctionSpace()) {
1564       if (right.probeInterpolation(getFunctionSpace())) {       if (right.probeInterpolation(getFunctionSpace())) {
1565         //         //
1566         // an interpolation is required so create a new Data         // an interpolation is required so create a new Data
1567         tempRight=Data(right,this->getFunctionSpace());         tempRight=Data(right,this->getFunctionSpace());
1568       } else if (probeInterpolation(right.getFunctionSpace())) {       } else if (probeInterpolation(right.getFunctionSpace())) {
1569         //         //
# Line 1609  Data::binaryOp(const Data& right, Line 1607  Data::binaryOp(const Data& right,
1607       EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");       EsysAssert((leftC!=0 && rightC!=0), "Programming error - casting to DataConstant.");
1608       escript::binaryOp(*leftC,*rightC,operation);       escript::binaryOp(*leftC,*rightC,operation);
1609     }     }
    #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);  
   }  
1610  }  }
1611    
1612  /**  /**
# Line 1692  Data::algorithm(BinaryFunction operation Line 1641  Data::algorithm(BinaryFunction operation
1641    \brief    \brief
1642    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.
1643    Given operation combines each element within each data point into a scalar,    Given operation combines each element within each data point into a scalar,
1644    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
1645    rank 0 Data object.    rank 0 Data object.
1646    Calls escript::dp_algorithm.    Calls escript::dp_algorithm.
1647  */  */
# Line 1741  Data::dp_algorithm(BinaryFunction operat Line 1690  Data::dp_algorithm(BinaryFunction operat
1690    return falseRetVal;    return falseRetVal;
1691  }  }
1692    
1693    /**
1694      \brief
1695      Compute a tensor operation with two Data objects
1696      \param arg0 - Input - Data object
1697      \param arg1 - Input - Data object
1698      \param operation - Input - Binary op functor
1699    */
1700    template <typename BinaryFunction>
1701    inline
1702    Data
1703    C_TensorBinaryOperation(Data const &arg_0,
1704                            Data const &arg_1,
1705                            BinaryFunction operation)
1706    {
1707      // Interpolate if necessary and find an appropriate function space
1708      Data arg_0_Z, arg_1_Z;
1709      if (arg_0.getFunctionSpace()!=arg_1.getFunctionSpace()) {
1710        if (arg_0.probeInterpolation(arg_1.getFunctionSpace())) {
1711          arg_0_Z = arg_0.interpolate(arg_1.getFunctionSpace());
1712          arg_1_Z = Data(arg_1);
1713        }
1714        else if (arg_1.probeInterpolation(arg_0.getFunctionSpace())) {
1715          arg_1_Z=arg_1.interpolate(arg_0.getFunctionSpace());
1716          arg_0_Z =Data(arg_0);
1717        }
1718        else {
1719          throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible function spaces.");
1720        }
1721      } else {
1722          arg_0_Z = Data(arg_0);
1723          arg_1_Z = Data(arg_1);
1724      }
1725      // Get rank and shape of inputs
1726      int rank0 = arg_0_Z.getDataPointRank();
1727      int rank1 = arg_1_Z.getDataPointRank();
1728      DataArrayView::ShapeType shape0 = arg_0_Z.getDataPointShape();
1729      DataArrayView::ShapeType shape1 = arg_1_Z.getDataPointShape();
1730      int size0 = arg_0_Z.getDataPointSize();
1731      int size1 = arg_1_Z.getDataPointSize();
1732    
1733      // Declare output Data object
1734      Data res;
1735    
1736      if (shape0 == shape1) {
1737    
1738        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1739          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
1740          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1741          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1742          double *ptr_2 = &((res.getPointDataView().getData())[0]);
1743          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1744        }
1745        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
1746    
1747          // Prepare the DataConstant input
1748          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1749    
1750          // Borrow DataTagged input from Data object
1751          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1752    
1753          // Prepare a DataTagged output 2
1754          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
1755          res.tag();
1756          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1757    
1758          // Prepare offset into DataConstant
1759          int offset_0 = tmp_0->getPointOffset(0,0);
1760          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1761          // Get the views
1762          DataArrayView view_1 = tmp_1->getDefaultValue();
1763          DataArrayView view_2 = tmp_2->getDefaultValue();
1764          // Get the pointers to the actual data
1765          double *ptr_1 = &((view_1.getData())[0]);
1766          double *ptr_2 = &((view_2.getData())[0]);
1767          // Compute a result for the default
1768          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1769          // Compute a result for each tag
1770          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1771          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1772          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1773            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
1774            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1775            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1776            double *ptr_1 = &view_1.getData(0);
1777            double *ptr_2 = &view_2.getData(0);
1778            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1779          }
1780    
1781        }
1782        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
1783    
1784          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1785          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
1786          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1787          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1788    
1789          int sampleNo_1,dataPointNo_1;
1790          int numSamples_1 = arg_1_Z.getNumSamples();
1791          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
1792          int offset_0 = tmp_0->getPointOffset(0,0);
1793          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
1794          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
1795            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
1796              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
1797              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
1798              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1799              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1800              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1801              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1802            }
1803          }
1804    
1805        }
1806        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
1807    
1808          // Borrow DataTagged input from Data object
1809          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1810    
1811          // Prepare the DataConstant input
1812          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1813    
1814          // Prepare a DataTagged output 2
1815          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
1816          res.tag();
1817          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1818    
1819          // Prepare offset into DataConstant
1820          int offset_1 = tmp_1->getPointOffset(0,0);
1821          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1822          // Get the views
1823          DataArrayView view_0 = tmp_0->getDefaultValue();
1824          DataArrayView view_2 = tmp_2->getDefaultValue();
1825          // Get the pointers to the actual data
1826          double *ptr_0 = &((view_0.getData())[0]);
1827          double *ptr_2 = &((view_2.getData())[0]);
1828          // Compute a result for the default
1829          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1830          // Compute a result for each tag
1831          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1832          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1833          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1834            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
1835            DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1836            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1837            double *ptr_0 = &view_0.getData(0);
1838            double *ptr_2 = &view_2.getData(0);
1839            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1840          }
1841    
1842        }
1843        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
1844    
1845          // Borrow DataTagged input from Data object
1846          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1847    
1848          // Borrow DataTagged input from Data object
1849          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1850    
1851          // Prepare a DataTagged output 2
1852          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
1853          res.tag();        // DataTagged output
1854          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
1855    
1856          // Get the views
1857          DataArrayView view_0 = tmp_0->getDefaultValue();
1858          DataArrayView view_1 = tmp_1->getDefaultValue();
1859          DataArrayView view_2 = tmp_2->getDefaultValue();
1860          // Get the pointers to the actual data
1861          double *ptr_0 = &((view_0.getData())[0]);
1862          double *ptr_1 = &((view_1.getData())[0]);
1863          double *ptr_2 = &((view_2.getData())[0]);
1864          // Compute a result for the default
1865          tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1866          // Merge the tags
1867          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
1868          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
1869          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
1870          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
1871            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue()); // use tmp_2 to get correct shape
1872          }
1873          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
1874            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
1875          }
1876          // Compute a result for each tag
1877          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
1878          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
1879            DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
1880            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
1881            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
1882            double *ptr_0 = &view_0.getData(0);
1883            double *ptr_1 = &view_1.getData(0);
1884            double *ptr_2 = &view_2.getData(0);
1885            tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1886          }
1887    
1888        }
1889        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
1890    
1891          // After finding a common function space above the two inputs have the same numSamples and num DPPS
1892          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1893          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
1894          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1895          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1896    
1897          int sampleNo_0,dataPointNo_0;
1898          int numSamples_0 = arg_0_Z.getNumSamples();
1899          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1900          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1901          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
1902            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
1903            double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1904            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
1905              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
1906              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
1907              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1908              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1909              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1910            }
1911          }
1912    
1913        }
1914        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
1915    
1916          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1917          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
1918          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
1919          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1920    
1921          int sampleNo_0,dataPointNo_0;
1922          int numSamples_0 = arg_0_Z.getNumSamples();
1923          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1924          int offset_1 = tmp_1->getPointOffset(0,0);
1925          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1926          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
1927            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
1928              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
1929              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
1930              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1931              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1932              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1933              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1934            }
1935          }
1936    
1937        }
1938        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
1939    
1940          // After finding a common function space above the two inputs have the same numSamples and num DPPS
1941          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1942          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
1943          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
1944          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1945    
1946          int sampleNo_0,dataPointNo_0;
1947          int numSamples_0 = arg_0_Z.getNumSamples();
1948          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1949          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1950          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
1951            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
1952            double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1953            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
1954              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
1955              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
1956              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1957              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1958              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1959            }
1960          }
1961    
1962        }
1963        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
1964    
1965          // After finding a common function space above the two inputs have the same numSamples and num DPPS
1966          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
1967          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
1968          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
1969          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
1970    
1971          int sampleNo_0,dataPointNo_0;
1972          int numSamples_0 = arg_0_Z.getNumSamples();
1973          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
1974          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
1975          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
1976            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
1977              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
1978              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
1979              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
1980              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
1981              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
1982              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
1983              tensor_binary_operation(size0, ptr_0, ptr_1, ptr_2, operation);
1984            }
1985          }
1986    
1987        }
1988        else {
1989          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
1990        }
1991    
1992      } else if (0 == rank0) {
1993    
1994        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
1995          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataConstant output
1996          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
1997          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
1998          double *ptr_2 = &((res.getPointDataView().getData())[0]);
1999          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2000        }
2001        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2002    
2003          // Prepare the DataConstant input
2004          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2005    
2006          // Borrow DataTagged input from Data object
2007          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2008    
2009          // Prepare a DataTagged output 2
2010          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());      // DataTagged output
2011          res.tag();
2012          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2013    
2014          // Prepare offset into DataConstant
2015          int offset_0 = tmp_0->getPointOffset(0,0);
2016          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2017          // Get the views
2018          DataArrayView view_1 = tmp_1->getDefaultValue();
2019          DataArrayView view_2 = tmp_2->getDefaultValue();
2020          // Get the pointers to the actual data
2021          double *ptr_1 = &((view_1.getData())[0]);
2022          double *ptr_2 = &((view_2.getData())[0]);
2023          // Compute a result for the default
2024          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2025          // Compute a result for each tag
2026          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2027          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2028          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2029            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2030            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2031            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2032            double *ptr_1 = &view_1.getData(0);
2033            double *ptr_2 = &view_2.getData(0);
2034            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2035          }
2036    
2037        }
2038        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2039    
2040          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2041          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2042          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2043          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2044    
2045          int sampleNo_1,dataPointNo_1;
2046          int numSamples_1 = arg_1_Z.getNumSamples();
2047          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2048          int offset_0 = tmp_0->getPointOffset(0,0);
2049          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2050          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2051            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2052              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2053              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2054              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2055              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2056              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2057              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2058    
2059            }
2060          }
2061    
2062        }
2063        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2064    
2065          // Borrow DataTagged input from Data object
2066          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2067    
2068          // Prepare the DataConstant input
2069          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2070    
2071          // Prepare a DataTagged output 2
2072          res = Data(0.0, shape1, arg_0_Z.getFunctionSpace());      // DataTagged output
2073          res.tag();
2074          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2075    
2076          // Prepare offset into DataConstant
2077          int offset_1 = tmp_1->getPointOffset(0,0);
2078          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2079          // Get the views
2080          DataArrayView view_0 = tmp_0->getDefaultValue();
2081          DataArrayView view_2 = tmp_2->getDefaultValue();
2082          // Get the pointers to the actual data
2083          double *ptr_0 = &((view_0.getData())[0]);
2084          double *ptr_2 = &((view_2.getData())[0]);
2085          // Compute a result for the default
2086          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2087          // Compute a result for each tag
2088          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2089          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2090          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2091            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2092            DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2093            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2094            double *ptr_0 = &view_0.getData(0);
2095            double *ptr_2 = &view_2.getData(0);
2096            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2097          }
2098    
2099        }
2100        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2101    
2102          // Borrow DataTagged input from Data object
2103          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2104    
2105          // Borrow DataTagged input from Data object
2106          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2107    
2108          // Prepare a DataTagged output 2
2109          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace());
2110          res.tag();        // DataTagged output
2111          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2112    
2113          // Get the views
2114          DataArrayView view_0 = tmp_0->getDefaultValue();
2115          DataArrayView view_1 = tmp_1->getDefaultValue();
2116          DataArrayView view_2 = tmp_2->getDefaultValue();
2117          // Get the pointers to the actual data
2118          double *ptr_0 = &((view_0.getData())[0]);
2119          double *ptr_1 = &((view_1.getData())[0]);
2120          double *ptr_2 = &((view_2.getData())[0]);
2121          // Compute a result for the default
2122          tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2123          // Merge the tags
2124          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2125          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2126          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2127          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2128            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue()); // use tmp_2 to get correct shape
2129          }
2130          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2131            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2132          }
2133          // Compute a result for each tag
2134          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2135          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2136            DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2137            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2138            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2139            double *ptr_0 = &view_0.getData(0);
2140            double *ptr_1 = &view_1.getData(0);
2141            double *ptr_2 = &view_2.getData(0);
2142            tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2143          }
2144    
2145        }
2146        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2147    
2148          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2149          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2150          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2151          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2152          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2153    
2154          int sampleNo_0,dataPointNo_0;
2155          int numSamples_0 = arg_0_Z.getNumSamples();
2156          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2157          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2158          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2159            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2160            double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2161            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2162              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2163              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2164              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2165              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2166              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2167            }
2168          }
2169    
2170        }
2171        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2172    
2173          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2174          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2175          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2176          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2177    
2178          int sampleNo_0,dataPointNo_0;
2179          int numSamples_0 = arg_0_Z.getNumSamples();
2180          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2181          int offset_1 = tmp_1->getPointOffset(0,0);
2182          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2183          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2184            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2185              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2186              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2187              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2188              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2189              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2190              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2191            }
2192          }
2193    
2194    
2195        }
2196        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2197    
2198          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2199          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2200          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2201          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2202          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2203    
2204          int sampleNo_0,dataPointNo_0;
2205          int numSamples_0 = arg_0_Z.getNumSamples();
2206          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2207          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2208          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2209            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2210            double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2211            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2212              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2213              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2214              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2215              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2216              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2217            }
2218          }
2219    
2220        }
2221        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2222    
2223          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2224          res = Data(0.0, shape1, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2225          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2226          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2227          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2228    
2229          int sampleNo_0,dataPointNo_0;
2230          int numSamples_0 = arg_0_Z.getNumSamples();
2231          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2232          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2233          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2234            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2235              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2236              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2237              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2238              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2239              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2240              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2241              tensor_binary_operation(size1, ptr_0[0], ptr_1, ptr_2, operation);
2242            }
2243          }
2244    
2245        }
2246        else {
2247          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2248        }
2249    
2250      } else if (0 == rank1) {
2251    
2252        if (arg_0_Z.isConstant()   && arg_1_Z.isConstant()) {
2253          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataConstant output
2254          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2255          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[0]);
2256          double *ptr_2 = &((res.getPointDataView().getData())[0]);
2257          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2258        }
2259        else if (arg_0_Z.isConstant()   && arg_1_Z.isTagged()) {
2260    
2261          // Prepare the DataConstant input
2262          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2263    
2264          // Borrow DataTagged input from Data object
2265          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2266    
2267          // Prepare a DataTagged output 2
2268          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());      // DataTagged output
2269          res.tag();
2270          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2271    
2272          // Prepare offset into DataConstant
2273          int offset_0 = tmp_0->getPointOffset(0,0);
2274          double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2275          // Get the views
2276          DataArrayView view_1 = tmp_1->getDefaultValue();
2277          DataArrayView view_2 = tmp_2->getDefaultValue();
2278          // Get the pointers to the actual data
2279          double *ptr_1 = &((view_1.getData())[0]);
2280          double *ptr_2 = &((view_2.getData())[0]);
2281          // Compute a result for the default
2282          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2283          // Compute a result for each tag
2284          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2285          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2286          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2287            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2288            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2289            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2290            double *ptr_1 = &view_1.getData(0);
2291            double *ptr_2 = &view_2.getData(0);
2292            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2293          }
2294    
2295        }
2296        else if (arg_0_Z.isConstant()   && arg_1_Z.isExpanded()) {
2297    
2298          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2299          DataConstant* tmp_0=dynamic_cast<DataConstant*>(arg_0_Z.borrowData());
2300          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2301          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2302    
2303          int sampleNo_1,dataPointNo_1;
2304          int numSamples_1 = arg_1_Z.getNumSamples();
2305          int numDataPointsPerSample_1 = arg_1_Z.getNumDataPointsPerSample();
2306          int offset_0 = tmp_0->getPointOffset(0,0);
2307          #pragma omp parallel for private(sampleNo_1,dataPointNo_1) schedule(static)
2308          for (sampleNo_1 = 0; sampleNo_1 < numSamples_1; sampleNo_1++) {
2309            for (dataPointNo_1 = 0; dataPointNo_1 < numDataPointsPerSample_1; dataPointNo_1++) {
2310              int offset_1 = tmp_1->getPointOffset(sampleNo_1,dataPointNo_1);
2311              int offset_2 = tmp_2->getPointOffset(sampleNo_1,dataPointNo_1);
2312              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2313              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2314              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2315              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2316            }
2317          }
2318    
2319        }
2320        else if (arg_0_Z.isTagged()     && arg_1_Z.isConstant()) {
2321    
2322          // Borrow DataTagged input from Data object
2323          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2324    
2325          // Prepare the DataConstant input
2326          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2327    
2328          // Prepare a DataTagged output 2
2329          res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataTagged output
2330          res.tag();
2331          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2332    
2333          // Prepare offset into DataConstant
2334          int offset_1 = tmp_1->getPointOffset(0,0);
2335          double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2336          // Get the views
2337          DataArrayView view_0 = tmp_0->getDefaultValue();
2338          DataArrayView view_2 = tmp_2->getDefaultValue();
2339          // Get the pointers to the actual data
2340          double *ptr_0 = &((view_0.getData())[0]);
2341          double *ptr_2 = &((view_2.getData())[0]);
2342          // Compute a result for the default
2343          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2344          // Compute a result for each tag
2345          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2346          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2347          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2348            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2349            DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2350            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2351            double *ptr_0 = &view_0.getData(0);
2352            double *ptr_2 = &view_2.getData(0);
2353            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2354          }
2355    
2356        }
2357        else if (arg_0_Z.isTagged()     && arg_1_Z.isTagged()) {
2358    
2359          // Borrow DataTagged input from Data object
2360          DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2361    
2362          // Borrow DataTagged input from Data object
2363          DataTagged* tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2364    
2365          // Prepare a DataTagged output 2
2366          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace());
2367          res.tag();        // DataTagged output
2368          DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2369    
2370          // Get the views
2371          DataArrayView view_0 = tmp_0->getDefaultValue();
2372          DataArrayView view_1 = tmp_1->getDefaultValue();
2373          DataArrayView view_2 = tmp_2->getDefaultValue();
2374          // Get the pointers to the actual data
2375          double *ptr_0 = &((view_0.getData())[0]);
2376          double *ptr_1 = &((view_1.getData())[0]);
2377          double *ptr_2 = &((view_2.getData())[0]);
2378          // Compute a result for the default
2379          tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2380          // Merge the tags
2381          DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2382          const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2383          const DataTagged::DataMapType& lookup_1=tmp_1->getTagLookup();
2384          for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2385            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue()); // use tmp_2 to get correct shape
2386          }
2387          for (i=lookup_1.begin();i!=lookup_1.end();i++) {
2388            tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2389          }
2390          // Compute a result for each tag
2391          const DataTagged::DataMapType& lookup_2=tmp_2->getTagLookup();
2392          for (i=lookup_2.begin();i!=lookup_2.end();i++) {
2393            DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2394            DataArrayView view_1 = tmp_1->getDataPointByTag(i->first);
2395            DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2396            double *ptr_0 = &view_0.getData(0);
2397            double *ptr_1 = &view_1.getData(0);
2398            double *ptr_2 = &view_2.getData(0);
2399            tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2400          }
2401    
2402        }
2403        else if (arg_0_Z.isTagged()     && arg_1_Z.isExpanded()) {
2404    
2405          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2406          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2407          DataTagged*   tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2408          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2409          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2410    
2411          int sampleNo_0,dataPointNo_0;
2412          int numSamples_0 = arg_0_Z.getNumSamples();
2413          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2414          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2415          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2416            int offset_0 = tmp_0->getPointOffset(sampleNo_0,0); // They're all the same, so just use #0
2417            double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2418            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2419              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2420              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2421              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2422              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2423              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2424            }
2425          }
2426    
2427        }
2428        else if (arg_0_Z.isExpanded()   && arg_1_Z.isConstant()) {
2429    
2430          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2431          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2432          DataConstant* tmp_1=dynamic_cast<DataConstant*>(arg_1_Z.borrowData());
2433          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2434    
2435          int sampleNo_0,dataPointNo_0;
2436          int numSamples_0 = arg_0_Z.getNumSamples();
2437          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2438          int offset_1 = tmp_1->getPointOffset(0,0);
2439          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2440          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2441            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2442              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2443              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2444              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2445              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2446              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2447              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2448            }
2449          }
2450    
2451    
2452        }
2453        else if (arg_0_Z.isExpanded()   && arg_1_Z.isTagged()) {
2454    
2455          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2456          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2457          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2458          DataTagged*   tmp_1=dynamic_cast<DataTagged*>(arg_1_Z.borrowData());
2459          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2460    
2461          int sampleNo_0,dataPointNo_0;
2462          int numSamples_0 = arg_0_Z.getNumSamples();
2463          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2464          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2465          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2466            int offset_1 = tmp_1->getPointOffset(sampleNo_0,0);
2467            double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2468            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2469              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2470              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2471              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2472              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2473              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2474            }
2475          }
2476    
2477        }
2478        else if (arg_0_Z.isExpanded()   && arg_1_Z.isExpanded()) {
2479    
2480          // After finding a common function space above the two inputs have the same numSamples and num DPPS
2481          res = Data(0.0, shape0, arg_1_Z.getFunctionSpace(),true); // DataExpanded output
2482          DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2483          DataExpanded* tmp_1=dynamic_cast<DataExpanded*>(arg_1_Z.borrowData());
2484          DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2485    
2486          int sampleNo_0,dataPointNo_0;
2487          int numSamples_0 = arg_0_Z.getNumSamples();
2488          int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2489          #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2490          for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2491            for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2492              int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2493              int offset_1 = tmp_1->getPointOffset(sampleNo_0,dataPointNo_0);
2494              int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2495              double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2496              double *ptr_1 = &((arg_1_Z.getPointDataView().getData())[offset_1]);
2497              double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2498              tensor_binary_operation(size0, ptr_0, ptr_1[0], ptr_2, operation);
2499            }
2500          }
2501    
2502        }
2503        else {
2504          throw DataException("Error - C_TensorBinaryOperation: unknown combination of inputs");
2505        }
2506    
2507      } else {
2508        throw DataException("Error - C_TensorBinaryOperation: arguments have incompatible shapes");
2509      }
2510    
2511      return res;
2512    }
2513    
2514    template <typename UnaryFunction>
2515    Data
2516    C_TensorUnaryOperation(Data const &arg_0,
2517                           UnaryFunction operation)
2518    {
2519      // Interpolate if necessary and find an appropriate function space
2520      Data arg_0_Z = Data(arg_0);
2521    
2522      // Get rank and shape of inputs
2523      int rank0 = arg_0_Z.getDataPointRank();
2524      DataArrayView::ShapeType shape0 = arg_0_Z.getDataPointShape();
2525      int size0 = arg_0_Z.getDataPointSize();
2526    
2527      // Declare output Data object
2528      Data res;
2529    
2530      if (arg_0_Z.isConstant()) {
2531        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());      // DataConstant output
2532        double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[0]);
2533        double *ptr_2 = &((res.getPointDataView().getData())[0]);
2534        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2535      }
2536      else if (arg_0_Z.isTagged()) {
2537    
2538        // Borrow DataTagged input from Data object
2539        DataTagged* tmp_0=dynamic_cast<DataTagged*>(arg_0_Z.borrowData());
2540    
2541        // Prepare a DataTagged output 2
2542        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace());   // DataTagged output
2543        res.tag();
2544        DataTagged* tmp_2=dynamic_cast<DataTagged*>(res.borrowData());
2545    
2546        // Get the views
2547        DataArrayView view_0 = tmp_0->getDefaultValue();
2548        DataArrayView view_2 = tmp_2->getDefaultValue();
2549        // Get the pointers to the actual data
2550        double *ptr_0 = &((view_0.getData())[0]);
2551        double *ptr_2 = &((view_2.getData())[0]);
2552        // Compute a result for the default
2553        tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2554        // Compute a result for each tag
2555        const DataTagged::DataMapType& lookup_0=tmp_0->getTagLookup();
2556        DataTagged::DataMapType::const_iterator i; // i->first is a tag, i->second is an offset into memory
2557        for (i=lookup_0.begin();i!=lookup_0.end();i++) {
2558          tmp_2->addTaggedValue(i->first,tmp_2->getDefaultValue());
2559          DataArrayView view_0 = tmp_0->getDataPointByTag(i->first);
2560          DataArrayView view_2 = tmp_2->getDataPointByTag(i->first);
2561          double *ptr_0 = &view_0.getData(0);
2562          double *ptr_2 = &view_2.getData(0);
2563          tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2564        }
2565    
2566      }
2567      else if (arg_0_Z.isExpanded()) {
2568    
2569        res = Data(0.0, shape0, arg_0_Z.getFunctionSpace(),true); // DataExpanded output
2570        DataExpanded* tmp_0=dynamic_cast<DataExpanded*>(arg_0_Z.borrowData());
2571        DataExpanded* tmp_2=dynamic_cast<DataExpanded*>(res.borrowData());
2572    
2573        int sampleNo_0,dataPointNo_0;
2574        int numSamples_0 = arg_0_Z.getNumSamples();
2575        int numDataPointsPerSample_0 = arg_0_Z.getNumDataPointsPerSample();
2576        #pragma omp parallel for private(sampleNo_0,dataPointNo_0) schedule(static)
2577        for (sampleNo_0 = 0; sampleNo_0 < numSamples_0; sampleNo_0++) {
2578          for (dataPointNo_0 = 0; dataPointNo_0 < numDataPointsPerSample_0; dataPointNo_0++) {
2579            int offset_0 = tmp_0->getPointOffset(sampleNo_0,dataPointNo_0);
2580            int offset_2 = tmp_2->getPointOffset(sampleNo_0,dataPointNo_0);
2581            double *ptr_0 = &((arg_0_Z.getPointDataView().getData())[offset_0]);
2582            double *ptr_2 = &((res.getPointDataView().getData())[offset_2]);
2583            tensor_unary_operation(size0, ptr_0, ptr_2, operation);
2584          }
2585        }
2586    
2587      }
2588      else {
2589        throw DataException("Error - C_TensorUnaryOperation: unknown combination of inputs");
2590      }
2591    
2592      return res;
2593    }
2594    
2595  }  }
2596  #endif  #endif

Legend:
Removed from v.854  
changed lines
  Added in v.1430

  ViewVC Help
Powered by ViewVC 1.1.26