1 |
|
2 |
/******************************************************* |
3 |
* |
4 |
* Copyright (c) 2003-2009 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_DataLazy_20081008_H |
16 |
#define escript_DataLazy_20081008_H |
17 |
#include "system_dep.h" |
18 |
|
19 |
#include "DataAbstract.h" |
20 |
|
21 |
#include <string> |
22 |
#include <functional> |
23 |
|
24 |
#include "LocalOps.h" // for tensor_binary_op |
25 |
#include "BufferGroup.h" |
26 |
#include "DataVector.h" // for ElementType |
27 |
|
28 |
|
29 |
#define LAZY_NODE_STORAGE |
30 |
|
31 |
namespace escript { |
32 |
|
33 |
// For the purposes of unit testing and maintaining sanity, it is important that this enum be contiguous |
34 |
enum ES_optype |
35 |
{ |
36 |
UNKNOWNOP=0, |
37 |
IDENTITY=1, |
38 |
ADD=2, |
39 |
SUB=3, |
40 |
MUL=4, |
41 |
DIV=5, |
42 |
POW=6, |
43 |
SIN=POW+1, |
44 |
COS=SIN+1, |
45 |
TAN=SIN+2, |
46 |
ASIN=SIN+3, |
47 |
ACOS=SIN+4, |
48 |
ATAN=SIN+5, |
49 |
SINH=SIN+6, |
50 |
COSH=SIN+7, |
51 |
TANH=SIN+8, |
52 |
ERF=SIN+9, |
53 |
ASINH=SIN+10, |
54 |
ACOSH=SIN+11, |
55 |
ATANH=SIN+12, |
56 |
LOG10=ATANH+1, |
57 |
LOG=LOG10+1, |
58 |
SIGN=LOG10+2, |
59 |
ABS=LOG10+3, |
60 |
NEG=LOG10+4, |
61 |
POS=LOG10+5, |
62 |
EXP=LOG10+6, |
63 |
SQRT=LOG10+7, |
64 |
RECIP=LOG10+8, |
65 |
GZ=RECIP+1, |
66 |
LZ=GZ+1, |
67 |
GEZ=GZ+2, |
68 |
LEZ=GZ+3, |
69 |
NEZ=GZ+4, |
70 |
EZ=GZ+5, |
71 |
SYM=EZ+1, |
72 |
NSYM=SYM+1, |
73 |
PROD=NSYM+1, |
74 |
TRANS=PROD+1, |
75 |
TRACE=TRANS+1, |
76 |
SWAP=TRACE+1 |
77 |
}; |
78 |
|
79 |
ESCRIPT_DLL_API |
80 |
const std::string& |
81 |
opToString(ES_optype op); |
82 |
|
83 |
/** |
84 |
\class escript::DataLazy |
85 |
\brief Wraps an expression tree of other DataObjects. |
86 |
The data will be evaluated when required. |
87 |
|
88 |
|
89 |
NOTE: This class assumes that the Data being pointed at are immutable. |
90 |
*/ |
91 |
|
92 |
class DataLazy; |
93 |
|
94 |
typedef POINTER_WRAPPER_CLASS(DataLazy) DataLazy_ptr; |
95 |
typedef POINTER_WRAPPER_CLASS(const DataLazy) const_DataLazy_ptr; |
96 |
|
97 |
class DataLazy : public DataAbstract |
98 |
{ |
99 |
|
100 |
typedef DataAbstract parent; |
101 |
typedef DataTypes::ValueType ValueType; |
102 |
typedef DataTypes::ShapeType ShapeType; |
103 |
|
104 |
public: |
105 |
/** |
106 |
\brief Create an IDENTITY DataLazy for the given DataAbstract. |
107 |
\param p DataAbstract to be wrapped. |
108 |
\throws DataException if p is lazy data or it is not constant, tagged or expanded. |
109 |
*/ |
110 |
ESCRIPT_DLL_API |
111 |
DataLazy(DataAbstract_ptr p); |
112 |
|
113 |
|
114 |
/** |
115 |
\brief Produce a DataLazy for a unary operation. |
116 |
\param left DataAbstract to be operated on. |
117 |
\param op unary operation to perform. |
118 |
\throws DataException if op is not a unary operation or if p cannot be converted to a DataLazy. |
119 |
Note that IDENTITY is not considered a unary operation. |
120 |
*/ |
121 |
ESCRIPT_DLL_API |
122 |
DataLazy(DataAbstract_ptr left, ES_optype op); |
123 |
|
124 |
/** |
125 |
\brief Produce a DataLazy for a unary operation. |
126 |
\param left DataAbstract to be operated on. |
127 |
\param op unary operation to perform. |
128 |
\param tol tolerance for operation |
129 |
\throws DataException if op is not a unary operation or if p cannot be converted to a DataLazy. |
130 |
Note that IDENTITY is not considered a unary operation. |
131 |
*/ |
132 |
ESCRIPT_DLL_API |
133 |
DataLazy(DataAbstract_ptr left, ES_optype op, double tol); |
134 |
|
135 |
/** |
136 |
\brief Produce a DataLazy for a unary operation which requires a parameter. |
137 |
\param left DataAbstract to be operated on. |
138 |
\param op unary operation to perform. |
139 |
\param axis_offset the parameter for the operation |
140 |
\throws DataException if op is not a unary operation or if p cannot be converted to a DataLazy. |
141 |
Note that IDENTITY is not considered a unary operation. |
142 |
*/ |
143 |
ESCRIPT_DLL_API |
144 |
DataLazy(DataAbstract_ptr left, ES_optype op, int axis_offset); |
145 |
|
146 |
|
147 |
/** |
148 |
\brief Produce a DataLazy for a binary operation. |
149 |
\param left left operand |
150 |
\param right right operand |
151 |
\param op unary operation to perform. |
152 |
\throws DataException if op is not a binary operation or if left or right cannot be converted to a DataLazy. |
153 |
*/ |
154 |
ESCRIPT_DLL_API |
155 |
DataLazy(DataAbstract_ptr left, DataAbstract_ptr right, ES_optype op); |
156 |
|
157 |
/** |
158 |
\brief Produce a DataLazy for a binary operation with additional paramters. |
159 |
\param left left operand |
160 |
\param right right operand |
161 |
\param op unary operation to perform. |
162 |
\param axis_offset |
163 |
\param transpose |
164 |
\throws DataException if op is not a binary operation requiring parameters or if left or right cannot be converted to a DataLazy. |
165 |
*/ |
166 |
ESCRIPT_DLL_API |
167 |
DataLazy(DataAbstract_ptr left, DataAbstract_ptr right, ES_optype op, int axis_offset, int transpose); |
168 |
|
169 |
/** |
170 |
\brief Produce a DataLazy for a unary operation which requires two integer parameters. |
171 |
\param left DataAbstract to be operated on. |
172 |
\param op unary operation to perform. |
173 |
\param axis0 the first parameter for the operation |
174 |
\param axis1 the second parameter for the operation |
175 |
\throws DataException if op is not a unary operation or if p cannot be converted to a DataLazy. |
176 |
Note that IDENTITY is not considered a unary operation. |
177 |
*/ |
178 |
ESCRIPT_DLL_API |
179 |
DataLazy(DataAbstract_ptr left, ES_optype op, const int axis0, const int axis1); |
180 |
|
181 |
ESCRIPT_DLL_API |
182 |
~DataLazy(); |
183 |
|
184 |
/** |
185 |
\brief Evaluate the lazy expression. |
186 |
\return A DataReady with the value of the lazy expresion. |
187 |
*/ |
188 |
ESCRIPT_DLL_API |
189 |
DataReady_ptr |
190 |
resolve(); |
191 |
|
192 |
ESCRIPT_DLL_API |
193 |
std::string |
194 |
toString() const; |
195 |
|
196 |
ESCRIPT_DLL_API |
197 |
DataAbstract* |
198 |
deepCopy(); |
199 |
|
200 |
|
201 |
/** |
202 |
\brief |
203 |
This method throws an exception. It does not really make sense to ask this question of lazy data. |
204 |
*/ |
205 |
ESCRIPT_DLL_API |
206 |
ValueType::size_type |
207 |
getLength() const; |
208 |
|
209 |
|
210 |
ESCRIPT_DLL_API |
211 |
DataAbstract* |
212 |
getSlice(const DataTypes::RegionType& region) const; |
213 |
|
214 |
|
215 |
DataTypes::ValueType::size_type |
216 |
getPointOffset(int sampleNo, |
217 |
int dataPointNo) const; |
218 |
|
219 |
DataTypes::ValueType::size_type |
220 |
getPointOffset(int sampleNo, |
221 |
int dataPointNo); |
222 |
|
223 |
|
224 |
/** |
225 |
\return the number of samples which need to be stored to evaluate the expression. |
226 |
*/ |
227 |
ESCRIPT_DLL_API |
228 |
int |
229 |
getBuffsRequired() const; |
230 |
|
231 |
/** |
232 |
\return the largest samplesize required to evaluate the expression. |
233 |
*/ |
234 |
ESCRIPT_DLL_API |
235 |
size_t |
236 |
getMaxSampleSize() const; |
237 |
|
238 |
/** |
239 |
\return the size of the buffer required to evaulate a sample for this object |
240 |
*/ |
241 |
ESCRIPT_DLL_API |
242 |
size_t |
243 |
getSampleBufferSize() const; |
244 |
|
245 |
/** |
246 |
\brief Compute the value of the expression for the given sample. |
247 |
\return Vector which stores the value of the subexpression for the given sample. |
248 |
\param bg A BufferGroup to store intermediate results. |
249 |
\param sampleNo Sample number to evaluate. |
250 |
\param roffset (output parameter) the offset in the return vector where the result begins. |
251 |
|
252 |
The return value will be an existing vector so do not deallocate it. |
253 |
*/ |
254 |
ESCRIPT_DLL_API |
255 |
const ValueType* |
256 |
resolveSample(BufferGroup& bg, int sampleNo, size_t& roffset); |
257 |
|
258 |
/** |
259 |
\brief if resolve() was called would it produce expanded data. |
260 |
*/ |
261 |
ESCRIPT_DLL_API |
262 |
bool |
263 |
actsExpanded() const; |
264 |
|
265 |
/** |
266 |
\brief Produces an IDENTITY DataLazy containing zero. |
267 |
The result will have the same shape and functionspace as before. |
268 |
*/ |
269 |
ESCRIPT_DLL_API |
270 |
virtual void |
271 |
setToZero(); |
272 |
|
273 |
private: |
274 |
DataReady_ptr m_id; // For IDENTITY nodes, stores a wrapped value. |
275 |
DataLazy_ptr m_left, m_right; // operands for operation. |
276 |
ES_optype m_op; // operation to perform. |
277 |
|
278 |
int m_buffsRequired; // how many samples are required to evaluate this expression |
279 |
size_t m_samplesize; // number of values required to store a sample |
280 |
|
281 |
char m_readytype; // E for expanded, T for tagged, C for constant |
282 |
|
283 |
int m_axis_offset; // required extra info for general tensor product |
284 |
int m_transpose; // offset and transpose are used for swapaxes as well |
285 |
int m_SL, m_SM, m_SR; // computed properties used in general tensor product |
286 |
|
287 |
|
288 |
double m_tol; // required extra info for <>0 and ==0 |
289 |
|
290 |
size_t m_maxsamplesize; // largest samplesize required by any node in the expression |
291 |
size_t m_children; |
292 |
size_t m_height; |
293 |
|
294 |
#ifdef LAZY_NODE_STORAGE |
295 |
|
296 |
int* m_sampleids; // may be NULL |
297 |
DataVector m_samples; |
298 |
|
299 |
#endif // LAZY_NODE_STORAGE |
300 |
|
301 |
|
302 |
#ifdef LAZY_NODE_STORAGE |
303 |
/** |
304 |
Allocates sample storage at each node |
305 |
*/ |
306 |
void LazyNodeSetup(); |
307 |
|
308 |
|
309 |
const DataTypes::ValueType* |
310 |
resolveNodeUnary(int tid, int sampleNo, size_t& roffset); |
311 |
|
312 |
const DataTypes::ValueType* |
313 |
resolveNodeSample(int tid, int sampleNo, size_t& roffset); |
314 |
|
315 |
const DataTypes::ValueType* |
316 |
resolveNodeBinary(int tid, int sampleNo, size_t& roffset); |
317 |
|
318 |
const DataTypes::ValueType* |
319 |
resolveNodeNP1OUT(int tid, int sampleNo, size_t& roffset); |
320 |
|
321 |
const DataTypes::ValueType* |
322 |
resolveNodeNP1OUT_P(int tid, int sampleNo, size_t& roffset); |
323 |
|
324 |
const DataTypes::ValueType* |
325 |
resolveNodeTProd(int tid, int sampleNo, size_t& roffset); |
326 |
|
327 |
const DataTypes::ValueType* |
328 |
resolveNodeNP1OUT_2P(int tid, int sampleNo, size_t& roffset); |
329 |
|
330 |
#endif |
331 |
|
332 |
/** |
333 |
Does the work for toString. |
334 |
*/ |
335 |
void |
336 |
intoString(std::ostringstream& oss) const; |
337 |
|
338 |
/** |
339 |
\brief Converts the DataLazy into an IDENTITY storing the value of the expression. |
340 |
This method uses the original methods on the Data class to evaluate the expressions. |
341 |
For this reason, it should not be used on DataExpanded instances. (To do so would defeat |
342 |
the purpose of using DataLazy in the first place). |
343 |
*/ |
344 |
void |
345 |
collapse(); // converts the node into an IDENTITY node |
346 |
|
347 |
|
348 |
/** |
349 |
\brief Evaluates the expression using methods on Data. |
350 |
This does the work for the collapse method. |
351 |
For reasons of efficiency do not call this method on DataExpanded nodes. |
352 |
*/ |
353 |
DataReady_ptr |
354 |
collapseToReady(); |
355 |
|
356 |
/** |
357 |
\brief resolve the expression can store it in the current node |
358 |
The current node will be converted to an identity node. |
359 |
*/ |
360 |
void |
361 |
resolveToIdentity(); |
362 |
|
363 |
/** |
364 |
\brief helper method for resolveToIdentity and the identity constructor |
365 |
*/ |
366 |
void |
367 |
makeIdentity(const DataReady_ptr& p); |
368 |
|
369 |
/** |
370 |
\brief resolve to a ReadyData object using a vector buffer. |
371 |
*/ |
372 |
DataReady_ptr |
373 |
resolveVectorWorker(); |
374 |
|
375 |
#ifdef LAZY_NODE_STORAGE |
376 |
/** |
377 |
\brief resolve to a ReadyData object using storage at nodes |
378 |
*/ |
379 |
DataReady_ptr |
380 |
resolveNodeWorker(); |
381 |
#endif |
382 |
|
383 |
/** |
384 |
\brief Compute the value of the expression for the given sample - using the vector buffer approach. |
385 |
\return Vector which stores the value of the subexpression for the given sample. |
386 |
\param v A vector to store intermediate results. |
387 |
\param offset Index in v to begin storing results. |
388 |
\param sampleNo Sample number to evaluate. |
389 |
\param roffset (output parameter) the offset in the return vector where the result begins. |
390 |
|
391 |
The return value will be an existing vector so do not deallocate it. |
392 |
*/ |
393 |
ESCRIPT_DLL_API |
394 |
const ValueType* |
395 |
resolveVectorSample(ValueType& v, size_t offset, int sampleNo, size_t& roffset); |
396 |
|
397 |
|
398 |
/** |
399 |
\brief Compute the value of the expression (unary operation) for the given sample. |
400 |
\return Vector which stores the value of the subexpression for the given sample. |
401 |
\param v A vector to store intermediate results. |
402 |
\param offset Index in v to begin storing results. |
403 |
\param sampleNo Sample number to evaluate. |
404 |
\param roffset (output parameter) the offset in the return vector where the result begins. |
405 |
|
406 |
The return value will be an existing vector so do not deallocate it. |
407 |
If the result is stored in v it should be stored at the offset given. |
408 |
Everything from offset to the end of v should be considered available for this method to use. |
409 |
*/ |
410 |
ValueType* |
411 |
resolveUnary(ValueType& v, size_t offset,int sampleNo, size_t& roffset) const; |
412 |
|
413 |
/** |
414 |
\brief Compute the value of the expression (unary non-pointwise operation) for the given sample. |
415 |
\return Vector which stores the value of the subexpression for the given sample. |
416 |
\param v A vector to store intermediate results. |
417 |
\param offset Index in v to begin storing results. |
418 |
\param sampleNo Sample number to evaluate. |
419 |
\param roffset (output parameter) the offset in the return vector where the result begins. |
420 |
|
421 |
The return value will be an existing vector so do not deallocate it. |
422 |
If the result is stored in v it should be stored at the offset given. |
423 |
Everything from offset to the end of v should be considered available for this method to use. |
424 |
|
425 |
This method differs from the one above in that deals with operations that are not |
426 |
point-wise. That is, the answer cannot just be written on top of the input. |
427 |
Extra buffers are required for these operations. |
428 |
*/ |
429 |
|
430 |
ValueType* |
431 |
resolveNP1OUT(ValueType& v, size_t offset, int sampleNo, size_t& roffset) const; |
432 |
|
433 |
/** |
434 |
\brief Compute the value of the expression (unary operation) for the given sample. |
435 |
\return Vector which stores the value of the subexpression for the given sample. |
436 |
\param v A vector to store intermediate results. |
437 |
\param offset Index in v to begin storing results. |
438 |
\param sampleNo Sample number to evaluate. |
439 |
\param roffset (output parameter) the offset in the return vector where the result begins. |
440 |
|
441 |
The return value will be an existing vector so do not deallocate it. |
442 |
If the result is stored in v it should be stored at the offset given. |
443 |
Everything from offset to the end of v should be considered available for this method to use. |
444 |
*/ |
445 |
DataTypes::ValueType* |
446 |
resolveNP1OUT_P(ValueType& v, size_t offset, int sampleNo, size_t& roffset) const; |
447 |
|
448 |
/** |
449 |
\brief Compute the value of the expression (unary operation with int params) for the given sample. |
450 |
\return Vector which stores the value of the subexpression for the given sample. |
451 |
\param v A vector to store intermediate results. |
452 |
\param offset Index in v to begin storing results. |
453 |
\param sampleNo Sample number to evaluate. |
454 |
\param roffset (output parameter) the offset in the return vector where the result begins. |
455 |
|
456 |
The return value will be an existing vector so do not deallocate it. |
457 |
If the result is stored in v it should be stored at the offset given. |
458 |
Everything from offset to the end of v should be considered available for this method to use. |
459 |
*/ |
460 |
DataTypes::ValueType* |
461 |
resolveNP1OUT_2P(ValueType& v, size_t offset, int sampleNo, size_t& roffset) const; |
462 |
|
463 |
|
464 |
/** |
465 |
\brief Compute the value of the expression (binary operation) for the given sample. |
466 |
\return Vector which stores the value of the subexpression for the given sample. |
467 |
\param v A vector to store intermediate results. |
468 |
\param offset Index in v to begin storing results. |
469 |
\param sampleNo Sample number to evaluate. |
470 |
\param roffset (output parameter) the offset in the return vector where the result begins. |
471 |
|
472 |
The return value will be an existing vector so do not deallocate it. |
473 |
If the result is stored in v it should be stored at the offset given. |
474 |
Everything from offset to the end of v should be considered available for this method to use. |
475 |
*/ |
476 |
ValueType* |
477 |
resolveBinary(ValueType& v, size_t offset,int sampleNo, size_t& roffset) const; |
478 |
|
479 |
/** |
480 |
\brief Compute the value of the expression (tensor product) for the given sample. |
481 |
\return Vector which stores the value of the subexpression for the given sample. |
482 |
\param v A vector to store intermediate results. |
483 |
\param offset Index in v to begin storing results. |
484 |
\param sampleNo Sample number to evaluate. |
485 |
\param roffset (output parameter) the offset in the return vector where the result begins. |
486 |
|
487 |
The return value will be an existing vector so do not deallocate it. |
488 |
If the result is stored in v it should be stored at the offset given. |
489 |
Everything from offset to the end of v should be considered available for this method to use. |
490 |
*/ |
491 |
DataTypes::ValueType* |
492 |
resolveTProd(ValueType& v, size_t offset, int sampleNo, size_t& roffset) const; |
493 |
|
494 |
}; |
495 |
|
496 |
} |
497 |
#endif |