1 |
|
2 |
/******************************************************* |
3 |
* |
4 |
* Copyright (c) 2003-2008 by University of Queensland |
5 |
* Earth Systems Science Computational Center (ESSCC) |
6 |
* http://www.uq.edu.au/esscc |
7 |
* |
8 |
* Primary Business: Queensland, Australia |
9 |
* Licensed under the Open Software License version 3.0 |
10 |
* http://www.opensource.org/licenses/osl-3.0.php |
11 |
* |
12 |
*******************************************************/ |
13 |
|
14 |
|
15 |
#if !defined escript_BinaryOp_20040315_H |
16 |
#define escript_BinaryOp_20040315_H |
17 |
#include "system_dep.h" |
18 |
|
19 |
#include "DataTypes.h" |
20 |
#include "DataConstant.h" |
21 |
#include "DataTagged.h" |
22 |
#include "DataExpanded.h" |
23 |
#include "DataMaths.h" |
24 |
|
25 |
/** |
26 |
\file BinaryOp.h |
27 |
\brief Describes binary operations performed on instances of DataAbstract. |
28 |
|
29 |
For operations on DataVector see DataMaths.h. |
30 |
For operations on double* see LocalOps.h. |
31 |
*/ |
32 |
|
33 |
namespace escript { |
34 |
/** |
35 |
\brief |
36 |
Perform the given binary operation. |
37 |
\param left Input/Output - The left hand side. |
38 |
\param right Input - The right hand side. |
39 |
\param operation Input - The operation to perform. |
40 |
*/ |
41 |
template <class BinaryFunction> |
42 |
inline void binaryOp(DataTagged& left, const DataConstant& right, |
43 |
BinaryFunction operation) |
44 |
{ |
45 |
// binaryOp(left,right.getPointDataView(),operation); |
46 |
// |
47 |
// perform the operation on each tagged value |
48 |
const DataTagged::DataMapType& lookup=left.getTagLookup(); |
49 |
DataTagged::DataMapType::const_iterator i; |
50 |
DataTagged::DataMapType::const_iterator lookupEnd=lookup.end(); |
51 |
// DataArrayView& leftView=left.getPointDataView(); |
52 |
DataTypes::ValueType& leftVec=left.getVector(); |
53 |
const DataTypes::ShapeType& leftShape=left.getShape(); |
54 |
const DataTypes::ShapeType& rightShape=right.getShape(); |
55 |
double rvalue=right.getVector()[0]; // for rank==0 |
56 |
const DataTypes::ValueType& rightVec=right.getVector(); // for rank>0 |
57 |
if (right.getRank()==0) { |
58 |
for (i=lookup.begin();i!=lookupEnd;i++) { |
59 |
//leftView.binaryOp(i->second,right(),operation); |
60 |
DataMaths::binaryOp(leftVec,leftShape,i->second,rvalue,operation); |
61 |
} |
62 |
} else { |
63 |
for (i=lookup.begin();i!=lookupEnd;i++) { |
64 |
DataMaths::binaryOp(leftVec, leftShape, i->second,rightVec,rightShape,0,operation); |
65 |
} |
66 |
} |
67 |
// |
68 |
// finally perform the operation on the default value |
69 |
if (right.getRank()==0) { |
70 |
DataMaths::binaryOp(leftVec,leftShape,left.getDefaultOffset(),rvalue,operation); |
71 |
} else { |
72 |
DataMaths::binaryOp(leftVec,leftShape,left.getDefaultOffset(),rightVec,rightShape,0,operation); |
73 |
} |
74 |
} |
75 |
|
76 |
/** |
77 |
\brief apply the binary op to each value in left and the single value right. |
78 |
|
79 |
The value in right will be assumed to begin at offset 0 |
80 |
*/ |
81 |
template <class BinaryFunction> |
82 |
inline void binaryOp(DataTagged& left, const DataTypes::ValueType& right, |
83 |
const DataTypes::ShapeType& shape, |
84 |
BinaryFunction operation) |
85 |
{ |
86 |
// |
87 |
// perform the operation on each tagged value |
88 |
const DataTagged::DataMapType& lookup=left.getTagLookup(); |
89 |
DataTagged::DataMapType::const_iterator i; |
90 |
DataTagged::DataMapType::const_iterator lookupEnd=lookup.end(); |
91 |
// DataArrayView& leftView=left.getPointDataView(); |
92 |
DataTypes::ValueType& lvec=left.getVector(); |
93 |
const DataTypes::ShapeType& lshape=left.getShape(); |
94 |
if (DataTypes::getRank(shape)==0) { |
95 |
for (i=lookup.begin();i!=lookupEnd;i++) { |
96 |
DataMaths::binaryOp(lvec, lshape,i->second,right[0],operation); |
97 |
} |
98 |
} else { |
99 |
for (i=lookup.begin();i!=lookupEnd;i++) { |
100 |
DataMaths::binaryOp(lvec, lshape, i->second,right,shape,0,operation); |
101 |
} |
102 |
} |
103 |
// |
104 |
// finally perform the operation on the default value |
105 |
if (DataTypes::getRank(shape)==0) { |
106 |
DataMaths::binaryOp(lvec,lshape,left.getDefaultOffset(),right[0],operation); |
107 |
// left.getDefaultValue().binaryOp(0,right(),operation); |
108 |
} else { |
109 |
// left.getDefaultValue().binaryOp(right,operation); |
110 |
DataMaths::binaryOp(lvec,lshape,left.getDefaultOffset(),right, shape,0,operation); |
111 |
} |
112 |
} |
113 |
|
114 |
|
115 |
|
116 |
|
117 |
template <class BinaryFunction> |
118 |
inline void binaryOp(DataTagged& left, const DataTagged& right, |
119 |
BinaryFunction operation) |
120 |
{ |
121 |
using namespace DataMaths; |
122 |
|
123 |
int right_rank=right.getRank(); |
124 |
// |
125 |
// Add the right hand tag keys which can't currently be found on the left |
126 |
const DataTagged::DataMapType& rightLookup=right.getTagLookup(); |
127 |
DataTagged::DataMapType::const_iterator i; |
128 |
DataTagged::DataMapType::const_iterator rightLookupEnd=rightLookup.end(); |
129 |
for (i=rightLookup.begin();i!=rightLookupEnd;i++) { |
130 |
// |
131 |
// If the left does not already have a value assigned to this tag, |
132 |
// add the right hand tag to the left hand tag list and assign |
133 |
// the left's default value. |
134 |
if (!left.isCurrentTag(i->first)) { |
135 |
left.addTag(i->first); |
136 |
} |
137 |
} |
138 |
DataTypes::ValueType& leftVec=left.getVector(); |
139 |
const DataTypes::ShapeType& leftShape=left.getShape(); |
140 |
// |
141 |
// Perform the operation. |
142 |
const DataTagged::DataMapType& leftLookup=left.getTagLookup(); |
143 |
DataTagged::DataMapType::const_iterator leftLookupEnd=leftLookup.end(); |
144 |
for (i=leftLookup.begin();i!=leftLookupEnd;i++) { |
145 |
if (right_rank==0) { |
146 |
/* left.getDataPointByTag(i->first).binaryOp(i->second,right.getDataPointByTag(i->first)(),operation);*/ |
147 |
binaryOp(leftVec,leftShape,i->second, right.getDataByTag(i->first,0),operation); |
148 |
|
149 |
} else { // rank>0 |
150 |
binaryOp(leftVec,leftShape,left.getOffsetForTag(i->first),right.getVector(), right.getShape(), right.getOffsetForTag(i->first), operation); |
151 |
//left.getDataPointByTag(i->first).binaryOp(right.getDataPointByTag(i->first),operation); |
152 |
} |
153 |
} |
154 |
// |
155 |
// finally perform the operation on the default value |
156 |
if (right_rank==0) { |
157 |
//left.getDefaultValue().binaryOp(0,right.getDefaultValue()(),operation); |
158 |
binaryOp(leftVec,leftShape, left.getDefaultOffset(), right.getVector()[0],operation); |
159 |
} else { |
160 |
//left.getDefaultValue().binaryOp(right.getDefaultValue(),operation); |
161 |
binaryOp(leftVec,leftShape, left.getDefaultOffset(), right.getVector(), right.getShape(), right.getDefaultOffset(), operation); |
162 |
} |
163 |
} |
164 |
|
165 |
template <class BinaryFunction> |
166 |
inline void binaryOp(DataConstant& left, const DataConstant& right, |
167 |
BinaryFunction operation) |
168 |
{ |
169 |
|
170 |
DataMaths::binaryOp(left.getVector(), left.getShape(),0, right.getVector(),right.getShape(),0,operation); |
171 |
|
172 |
} |
173 |
|
174 |
|
175 |
|
176 |
template <class BinaryFunction> |
177 |
inline void binaryOp(DataExpanded& left, const DataReady& right, |
178 |
BinaryFunction operation) |
179 |
{ |
180 |
int i,j; |
181 |
DataTypes::ValueType::size_type numDPPSample=left.getNumDPPSample(); |
182 |
DataTypes::ValueType::size_type numSamples=left.getNumSamples(); |
183 |
if (right.getRank()==0) { |
184 |
|
185 |
const DataTypes::ShapeType& leftShape=left.getShape(); |
186 |
DataTypes::ValueType& leftVec=left.getVector(); |
187 |
// |
188 |
// This will call the double version of binaryOp |
189 |
#pragma omp parallel for private(i,j) schedule(static) |
190 |
for (i=0;i<numSamples;i++) { |
191 |
for (j=0;j<numDPPSample;j++) { |
192 |
// left.getPointDataView().binaryOp(left.getPointOffset(i,j), |
193 |
// right.getPointDataView().getData(right.getPointOffset(i,j)), |
194 |
// operation); |
195 |
DataMaths::binaryOp(leftVec,leftShape,left.getPointOffset(i,j), right.getVector()[right.getPointOffset(i,j)] ,operation); |
196 |
} |
197 |
} |
198 |
} else { |
199 |
#pragma omp parallel for private(i,j) schedule(static) |
200 |
for (i=0;i<numSamples;i++) { |
201 |
for (j=0;j<numDPPSample;j++) { |
202 |
// left.getPointDataView().binaryOp(left.getPointOffset(i,j), |
203 |
// right.getPointDataView(), |
204 |
// right.getPointOffset(i,j), |
205 |
// operation); |
206 |
DataMaths::binaryOp(left.getVector(),left.getShape(),left.getPointOffset(i,j), right.getVector(), right.getShape(),right.getPointOffset(i,j), operation); |
207 |
} |
208 |
} |
209 |
} |
210 |
} |
211 |
|
212 |
|
213 |
} // end of namespace |
214 |
|
215 |
#endif |