/[escript]/branches/clazy/escriptcore/src/DataLazy.cpp
ViewVC logotype

Diff of /branches/clazy/escriptcore/src/DataLazy.cpp

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

branches/schroedinger/escript/src/DataLazy.cpp revision 1899 by jfenwick, Mon Oct 20 05:13:24 2008 UTC branches/schroedinger_upto1946/escript/src/DataLazy.cpp revision 1950 by jfenwick, Thu Oct 30 00:59:34 2008 UTC
# Line 26  Line 26 
26  #include "DataTypes.h"  #include "DataTypes.h"
27  #include "Data.h"  #include "Data.h"
28  #include "UnaryFuncs.h"     // for escript::fsign  #include "UnaryFuncs.h"     // for escript::fsign
29    #include "Utils.h"
30    
31  /*  /*
32  How does DataLazy work?  How does DataLazy work?
# Line 95  enum ES_opgroup Line 96  enum ES_opgroup
96    
97    
98    
99  string ES_opstrings[]={"UNKNOWN","IDENTITY","+","-","*","/","sin","cos","tan",  string ES_opstrings[]={"UNKNOWN","IDENTITY","+","-","*","/","^",
100                "sin","cos","tan",
101              "asin","acos","atan","sinh","cosh","tanh","erf",              "asin","acos","atan","sinh","cosh","tanh","erf",
102              "asinh","acosh","atanh",              "asinh","acosh","atanh",
103              "log10","log","sign","abs","neg","pos","exp","sqrt",              "log10","log","sign","abs","neg","pos","exp","sqrt",
104              "1/","where>0","where<0","where>=0","where<=0"};              "1/","where>0","where<0","where>=0","where<=0"};
105  int ES_opcount=32;  int ES_opcount=33;
106  ES_opgroup opgroups[]={G_UNKNOWN,G_IDENTITY,G_BINARY,G_BINARY,G_BINARY,G_BINARY,G_UNARY,G_UNARY,G_UNARY, //9  ES_opgroup opgroups[]={G_UNKNOWN,G_IDENTITY,G_BINARY,G_BINARY,G_BINARY,G_BINARY, G_BINARY,
107              G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,    // 16              G_UNARY,G_UNARY,G_UNARY, //10
108              G_UNARY,G_UNARY,G_UNARY,                    // 19              G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,    // 17
109              G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,        // 27              G_UNARY,G_UNARY,G_UNARY,                    // 20
110                G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY,        // 28
111              G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY};              G_UNARY,G_UNARY,G_UNARY,G_UNARY,G_UNARY};
112  inline  inline
113  ES_opgroup  ES_opgroup
# Line 122  resultFS(DataAbstract_ptr left, DataAbst Line 125  resultFS(DataAbstract_ptr left, DataAbst
125      // that way, if interpolate is required in any other op we can just throw a      // that way, if interpolate is required in any other op we can just throw a
126      // programming error exception.      // programming error exception.
127    
128      FunctionSpace l=left->getFunctionSpace();
129      if (left->getFunctionSpace()!=right->getFunctionSpace())    FunctionSpace r=right->getFunctionSpace();
130      {    if (l!=r)
131          throw DataException("FunctionSpaces not equal - interpolation not supported on lazy data.");    {
132      }      if (r.probeInterpolation(l))
133      return left->getFunctionSpace();      {
134        return l;
135        }
136        if (l.probeInterpolation(r))
137        {
138        return r;
139        }
140        throw DataException("Cannot interpolate between the FunctionSpaces given for operation "+opToString(op)+".");
141      }
142      return l;
143  }  }
144    
145  // return the shape of the result of "left op right"  // return the shape of the result of "left op right"
# Line 136  resultShape(DataAbstract_ptr left, DataA Line 148  resultShape(DataAbstract_ptr left, DataA
148  {  {
149      if (left->getShape()!=right->getShape())      if (left->getShape()!=right->getShape())
150      {      {
151          throw DataException("Shapes not the same - shapes must match for lazy data.");        if (getOpgroup(op)!=G_BINARY)
152          {
153            throw DataException("Shapes not the name - shapes must match for (point)binary operations.");
154          }
155          if (left->getRank()==0)   // we need to allow scalar * anything
156          {
157            return right->getShape();
158          }
159          if (right->getRank()==0)
160          {
161            return left->getShape();
162          }
163          throw DataException("Shapes not the same - arguments must have matching shapes (or be scalars) for (point)binary operations on lazy data.");
164      }      }
165      return left->getShape();      return left->getShape();
166  }  }
# Line 212  cout << "(1)Lazy created with " << m_sam Line 236  cout << "(1)Lazy created with " << m_sam
236    
237    
238    
239    
240  DataLazy::DataLazy(DataAbstract_ptr left, ES_optype op)  DataLazy::DataLazy(DataAbstract_ptr left, ES_optype op)
241      : parent(left->getFunctionSpace(),left->getShape()),      : parent(left->getFunctionSpace(),left->getShape()),
242      m_op(op)      m_op(op)
# Line 237  DataLazy::DataLazy(DataAbstract_ptr left Line 262  DataLazy::DataLazy(DataAbstract_ptr left
262  }  }
263    
264    
265    // In this constructor we need to consider interpolation
266  DataLazy::DataLazy(DataAbstract_ptr left, DataAbstract_ptr right, ES_optype op)  DataLazy::DataLazy(DataAbstract_ptr left, DataAbstract_ptr right, ES_optype op)
267      : parent(resultFS(left,right,op), resultShape(left,right,op)),      : parent(resultFS(left,right,op), resultShape(left,right,op)),
268      m_op(op)      m_op(op)
# Line 245  DataLazy::DataLazy(DataAbstract_ptr left Line 271  DataLazy::DataLazy(DataAbstract_ptr left
271     {     {
272      throw DataException("Programmer error - constructor DataLazy(left, right, op) will only process BINARY operations.");      throw DataException("Programmer error - constructor DataLazy(left, right, op) will only process BINARY operations.");
273     }     }
274    
275       if (getFunctionSpace()!=left->getFunctionSpace())    // left needs to be interpolated
276       {
277        FunctionSpace fs=getFunctionSpace();
278        Data ltemp(left);
279        Data tmp(ltemp,fs);
280        left=tmp.borrowDataPtr();
281       }
282       if (getFunctionSpace()!=right->getFunctionSpace())   // left needs to be interpolated
283       {
284        Data tmp(Data(right),getFunctionSpace());
285        right=tmp.borrowDataPtr();
286       }
287       left->operandCheck(*right);
288    
289     if (left->isLazy())          // the children need to be DataLazy. Wrap them in IDENTITY if required     if (left->isLazy())          // the children need to be DataLazy. Wrap them in IDENTITY if required
290     {     {
291      m_left=dynamic_pointer_cast<DataLazy>(left);      m_left=dynamic_pointer_cast<DataLazy>(left);
# Line 575  DataLazy::resolveUnary(ValueType& v, siz Line 616  DataLazy::resolveUnary(ValueType& v, siz
616    
617    
618  #define PROC_OP(X) \  #define PROC_OP(X) \
619      for (int i=0;i<steps;++i,resultp+=getNoValues()) \      for (int i=0;i<steps;++i,resultp+=resultStep) \
620      { \      { \
621         tensor_binary_operation(chunksize, &((*left)[lroffset]), &((*right)[rroffset]), resultp, X); \         tensor_binary_operation(chunksize, &((*left)[lroffset]), &((*right)[rroffset]), resultp, X); \
622         lroffset+=leftStep; \         lroffset+=leftStep; \
# Line 600  DataLazy::resolveUnary(ValueType& v, siz Line 641  DataLazy::resolveUnary(ValueType& v, siz
641  // the whole sample as one big datapoint.  // the whole sample as one big datapoint.
642  // If one of the children is not expanded, then we need to treat each point in the sample  // If one of the children is not expanded, then we need to treat each point in the sample
643  // individually.  // individually.
644    // There is an additional complication when scalar operations are considered.
645    // For example, 2+Vector.
646    // In this case each double within the point is treated individually
647  DataTypes::ValueType*  DataTypes::ValueType*
648  DataLazy::resolveBinary(ValueType& v,  size_t offset, int sampleNo, size_t& roffset) const  DataLazy::resolveBinary(ValueType& v,  size_t offset, int sampleNo, size_t& roffset) const
649  {  {
# Line 610  cout << "Resolve binary: " << toString() Line 654  cout << "Resolve binary: " << toString()
654    bool leftExp=(m_left->m_readytype=='E');    bool leftExp=(m_left->m_readytype=='E');
655    bool rightExp=(m_right->m_readytype=='E');    bool rightExp=(m_right->m_readytype=='E');
656    bool bigloops=((leftExp && rightExp) || (!leftExp && !rightExp)); // is processing in single step?    bool bigloops=((leftExp && rightExp) || (!leftExp && !rightExp)); // is processing in single step?
657    int steps=(bigloops?1:getNumDPPSample());        int steps=(bigloops?1:getNumDPPSample());
658    size_t chunksize=(bigloops? m_samplesize : getNoValues());    // if bigloops, pretend the whole sample is a datapoint    size_t chunksize=(bigloops? m_samplesize : getNoValues());    // if bigloops, pretend the whole sample is a datapoint
659    int leftStep=((leftExp && !rightExp)? getNoValues() : 0);    if (m_left->getRank()!=m_right->getRank())    // need to deal with scalar * ? ops
660    int rightStep=((rightExp && !leftExp)? getNoValues() : 0);    {
661        EsysAssert((m_left->getRank()==0) || (m_right->getRank()==0), "Error - Ranks must match unless one is 0.");
662        steps=getNumDPPSample()*max(m_left->getNoValues(),m_right->getNoValues());
663        chunksize=1;    // for scalar
664      }    
665      int leftStep=((leftExp && !rightExp)? m_right->getNoValues() : 0);
666      int rightStep=((rightExp && !leftExp)? m_left->getNoValues() : 0);
667      int resultStep=max(leftStep,rightStep);   // only one (at most) should be !=0
668      // Get the values of sub-expressions      // Get the values of sub-expressions
669    const ValueType* left=m_left->resolveSample(v,offset,sampleNo,lroffset);    const ValueType* left=m_left->resolveSample(v,offset,sampleNo,lroffset);
670    const ValueType* right=m_right->resolveSample(v,offset+m_samplesize,sampleNo,rroffset); // Note    const ValueType* right=m_right->resolveSample(v,offset+m_samplesize,sampleNo,rroffset); // Note
# Line 633  cout << "Resolve binary: " << toString() Line 684  cout << "Resolve binary: " << toString()
684      case DIV:      case DIV:
685      PROC_OP(divides<double>());      PROC_OP(divides<double>());
686      break;      break;
687        case POW:
688        PROC_OP(::pow);
689        break;
690      default:      default:
691      throw DataException("Programmer error - resolveBinary can not resolve operator "+opToString(m_op)+".");      throw DataException("Programmer error - resolveBinary can not resolve operator "+opToString(m_op)+".");
692    }    }
# Line 799  DataLazy::intoString(ostringstream& oss) Line 853  DataLazy::intoString(ostringstream& oss)
853    }    }
854  }  }
855    
 // Note that in this case, deepCopy does not make copies of the leaves.  
 // Hopefully copy on write (or whatever we end up using) will take care of this.  
856  DataAbstract*  DataAbstract*
857  DataLazy::deepCopy()  DataLazy::deepCopy()
858  {  {
859    if (m_op==IDENTITY)    switch (getOpgroup(m_op))
860    {    {
861      return new DataLazy(m_left);    // we don't need to copy the child here    case G_IDENTITY:  return new DataLazy(m_id->deepCopy()->getPtr());
862      case G_UNARY: return new DataLazy(m_left->deepCopy()->getPtr(),m_op);
863      case G_BINARY:    return new DataLazy(m_left->deepCopy()->getPtr(),m_right->deepCopy()->getPtr(),m_op);
864      default:
865        throw DataException("Programmer error - do not know how to deepcopy operator "+opToString(m_op)+".");
866    }    }
   return new DataLazy(m_left->deepCopy()->getPtr(),m_right->deepCopy()->getPtr(),m_op);  
867  }  }
868    
869    
# Line 825  DataLazy::getSlice(const DataTypes::Regi Line 880  DataLazy::getSlice(const DataTypes::Regi
880    throw DataException("getSlice - not implemented for Lazy objects.");    throw DataException("getSlice - not implemented for Lazy objects.");
881  }  }
882    
883    
884    // To do this we need to rely on our child nodes
885    DataTypes::ValueType::size_type
886    DataLazy::getPointOffset(int sampleNo,
887                     int dataPointNo)
888    {
889      if (m_op==IDENTITY)
890      {
891        return m_id->getPointOffset(sampleNo,dataPointNo);
892      }
893      if (m_readytype!='E')
894      {
895        collapse();
896        return m_id->getPointOffset(sampleNo,dataPointNo);
897      }
898      // at this point we do not have an identity node and the expression will be Expanded
899      // so we only need to know which child to ask
900      if (m_left->m_readytype=='E')
901      {
902        return m_left->getPointOffset(sampleNo,dataPointNo);
903      }
904      else
905      {
906        return m_right->getPointOffset(sampleNo,dataPointNo);
907      }
908    }
909    
910    // To do this we need to rely on our child nodes
911  DataTypes::ValueType::size_type  DataTypes::ValueType::size_type
912  DataLazy::getPointOffset(int sampleNo,  DataLazy::getPointOffset(int sampleNo,
913                   int dataPointNo) const                   int dataPointNo) const
914  {  {
915    throw DataException("getPointOffset - not implemented for Lazy objects - yet.");    if (m_op==IDENTITY)
916      {
917        return m_id->getPointOffset(sampleNo,dataPointNo);
918      }
919      if (m_readytype=='E')
920      {
921        // at this point we do not have an identity node and the expression will be Expanded
922        // so we only need to know which child to ask
923        if (m_left->m_readytype=='E')
924        {
925        return m_left->getPointOffset(sampleNo,dataPointNo);
926        }
927        else
928        {
929        return m_right->getPointOffset(sampleNo,dataPointNo);
930        }
931      }
932      if (m_readytype=='C')
933      {
934        return m_left->getPointOffset(sampleNo,dataPointNo); // which child doesn't matter
935      }
936      throw DataException("Programmer error - getPointOffset on lazy data may require collapsing (but this object is marked const).");
937    }
938    
939    // It would seem that DataTagged will need to be treated differently since even after setting all tags
940    // to zero, all the tags from all the DataTags would be in the result.
941    // However since they all have the same value (0) whether they are there or not should not matter.
942    // So I have decided that for all types this method will create a constant 0.
943    // It can be promoted up as required.
944    // A possible efficiency concern might be expanded->constant->expanded which has an extra memory management
945    // but we can deal with that if it arrises.
946    void
947    DataLazy::setToZero()
948    {
949      DataTypes::ValueType v(getNoValues(),0);
950      m_id=DataReady_ptr(new DataConstant(getFunctionSpace(),getShape(),v));
951      m_op=IDENTITY;
952      m_right.reset();  
953      m_left.reset();
954      m_readytype='C';
955      m_buffsRequired=1;
956  }  }
957    
958  }   // end namespace  }   // end namespace

Legend:
Removed from v.1899  
changed lines
  Added in v.1950

  ViewVC Help
Powered by ViewVC 1.1.26