00001 // -*- C++ -*- 00002 /*************************************************************************** 00003 * 00004 * The IPPL Framework 00005 * 00006 * 00007 * Visit http://people.web.psi.ch/adelmann/ for more details 00008 * 00009 ***************************************************************************/ 00010 00011 #ifndef SUB_BARE_FIELD_H 00012 #define SUB_BARE_FIELD_H 00013 00014 /*************************************************************************** 00015 SubBareField - represent a view on a given BareField, referring to a 00016 subset of the original field data. This is meant as an eventual 00017 replacement for IndexedBareField. 00018 00019 SubBareField is templated on the T and Dim of the Field, and also on the 00020 type of subset object used to refer to the field subsection. This can 00021 range from NDIndex for a rectangular block, to SIndex for an arbitrary 00022 list of points, to SOffset to store a single point. The behavior of this 00023 class, and in particular the iterator for this class, is specialized to 00024 each subset object using a traits class 'SFTraits' and a couple of global 00025 functions. 00026 00027 From a BareField, you create a SubBareField by using the bracket 00028 operators [], giving a particular type of data to further index the object. 00029 Indexing with and Index or NDIndex object results in a SubBareField object 00030 templated on NDIndex, etc. A SubBareField keeps track of the number of 00031 'Brackets' its been given; an expression can only involve a SubBareField 00032 if Brackets == Dim. Using [] on a SubBareField will generally increase the 00033 number of brackets, and result in a new SubBareField incorporating the 00034 info about how to select the subset as specified by the object in brackets. 00035 For example, Field<T,Dim>[Index] results in a SubBareField<T,Dim,NDIndex<Dim>> 00036 object with Brackets==1; further application of [Index] operators increases 00037 the number of Brackets and stores each Index in the internal NDIndex at the 00038 proper location. SFTraits provides the information on what types of objects 00039 can be used to subset, and what type of subset object they produce. 00040 00041 For the future, it might be useful to make this 'SubBareField' be the actual 00042 class employed by the user, with the current 'BareField' some form of 00043 internal class used only to store the data in whatever representation is 00044 most efficient. 00045 ***************************************************************************/ 00046 00047 // include files 00048 #include "SubField/SubFieldIter.h" 00049 #include "SubField/SubFieldTraits.h" 00050 #include "PETE/IpplExpressions.h" 00051 00052 #ifdef IPPL_USE_STANDARD_HEADERS 00053 #include <iostream> 00054 using namespace std; 00055 #else 00056 #include <iostream.h> 00057 #endif 00058 00059 // forward declarations 00060 template <class T, unsigned Dim, class S> class SubBareField; 00061 template <class T, unsigned Dim, class S> class SubFieldIter; 00062 template <class T, unsigned Dim, class S> 00063 ostream& operator<<(ostream&,const SubBareField<T,Dim,S>&); 00064 00065 00066 template <class T, unsigned Dim, class S> 00067 class SubBareField : public PETE_Expr< SubBareField<T,Dim,S> > { 00068 00069 friend class BareField<T,Dim>; 00070 00071 public: 00072 //# public typedefs 00073 typedef T T_t; 00074 typedef S Index_t; 00075 typedef SubFieldIter<T,Dim,S> iterator; 00076 00077 //# public enumerations 00078 enum { Dim_u = Dim }; 00079 00080 // Return the beginning and end iterators for this class. 00081 iterator begin() const; 00082 iterator end() const; 00083 00084 // 00085 // accessor functions 00086 // 00087 00088 // return the 'domain', that is, the information which subsets the field 00089 const S& getDomain() const { return MyDomain; } 00090 00091 // fill in the second argument with the data for the 'bounding box' of 00092 // the domain. This could be the whole field domain, a single point, or 00093 // perhaps just a subset of the whole domain. 00094 void makeNDIndex(NDIndex<Dim> &i) { iterator::makeNDIndex(MyDomain, i); } 00095 00096 // return a reference to the field we are subsetting 00097 BareField<T,Dim>& getBareField() const { return A; } 00098 00099 // Return a single value. 00100 T get() { T r; get(r); return r; } 00101 void get(T& r); 00102 00103 // Return a typecode for the subset object 00104 static int getSubsetType() { return iterator::getSubsetType(); } 00105 00106 // check to make sure Dim == Brackets. 00107 bool checkBrackets() const { return Brackets == Dim; } 00108 00109 // 00110 // bracket operators 00111 // 00112 00113 // bracket operator, which select subsets of the BareField. 00114 //mwerks template<class S2> 00115 //mwerks SubBareField<T,Dim,typename SubFieldTraits<T,Dim,S,S2>::Return_t> 00116 //mwerks operator[](const S2&); 00118 // bracket operators, which select subsets of the BareField. This 00119 // further subsets from the current SubBareField based on the type of 00120 // input subset object. 00121 template<class S2> 00122 SubBareField<T,Dim,typename SubFieldTraits<T,Dim,S,S2>::Return_t> 00123 operator[](const S2& s) { 00124 // create a new instance of the resulting subset object 00125 typename SubFieldTraits<T,Dim,S,S2>::Return_t newdomain; 00126 TAU_TYPE_STRING(taustr, CT(newdomain) + " (" + CT(s) + " )" ); 00127 TAU_PROFILE("SubBareField::operator[]()", taustr, TAU_SUBFIELD); 00128 00129 // make sure we can subset by the number of dimensions requested, then 00130 // combine the current subset value with the new one 00131 int B = SubFieldTraits<T,Dim,S,S2>::Brackets_u; 00132 if (checkAddBrackets(B)) { 00133 SubFieldTraits<T,Dim,S,S2>::combine(MyDomain, s, newdomain, Brackets, A); 00134 Brackets += B; 00135 } 00136 00137 // return a new SubBareField 00138 return SubBareField<T,Dim, 00139 typename SubFieldTraits<T,Dim,S,S2>::Return_t>(A,newdomain); 00140 } 00141 00142 00143 // 00144 // assignment operators 00145 // 00146 00147 // assignment of another SubBareField 00148 SubBareField<T,Dim,S>& operator=(const SubBareField<T,Dim,S> &); 00149 00150 // assignment of a scalar 00151 SubBareField<T,Dim,S>& operator=(T); 00152 00153 // assignment of an arbitrary expression 00154 //mwerks template<class B> 00155 //mwerks SubBareField<T,Dim,S>& operator=(const PETE_Expr<B> &); 00157 // assignment of an arbitrary expression 00158 template<class B> 00159 SubBareField<T,Dim,S>& 00160 operator=(const PETE_Expr<B> &b) { 00161 TAU_TYPE_STRING(taustr, CT(*this) + " (" + CT(b) + " )" ); 00162 TAU_PROFILE("SubBareField::operator=()",taustr, TAU_SUBFIELD | TAU_ASSIGN); 00163 assign(*this, b); 00164 return *this; 00165 } 00166 00167 00168 // 00169 // I/O 00170 // 00171 00172 void write(ostream&); 00173 00174 // 00175 // PETE interface 00176 // 00177 00178 enum { IsExpr = 1 }; 00179 typedef iterator PETE_Expr_t; 00180 iterator MakeExpression() const { return begin(); } 00181 00182 // Pass operator() down to each element of type T. 00183 // Could also build versions with 2 or more arguments... 00184 // Without member templates we are restricted to passing an integer down. 00185 PETE_TUTree<OpParens<int>, iterator> operator()(int arg) { 00186 checkBrackets(); 00187 typedef PETE_TUTree<OpParens<int>, iterator> Elem_t; 00188 return Elem_t(arg, begin()); 00189 } 00190 PETE_TUTree< OpParens< pair<int,int> >, iterator> operator()(int a1,int a2){ 00191 checkBrackets(); 00192 typedef PETE_TUTree<OpParens< pair<int,int> >, iterator> Elem_t; 00193 return Elem_t(pair<int,int>(a1,a2), begin()); 00194 } 00195 00196 protected: 00197 // the field we are subsetting 00198 BareField<T,Dim>& A; 00199 00200 // the 'domain', that is, the information which subsets the field 00201 S MyDomain; 00202 00203 // the current number of dimensions we have indexed via bracket operators. 00204 // An expression can only be carried out if the number of brackets == Dim. 00205 unsigned int Brackets; 00206 00207 // check to see if it is ok to add the given number of brackets to our 00208 // current number 00209 bool checkAddBrackets(unsigned int); 00210 00211 public: 00212 // the class constructor, used by BareField or SubBareField to make a new one 00213 //mwerks template<class S2> 00214 //mwerks SubBareField(BareField<T,Dim>&, const S2&); 00216 // Make the constructor private so that only this class and it's friends 00217 // can construct them. 00218 template<class S2> 00219 SubBareField(BareField<T,Dim>& f, const S2& s) : A(f) { 00220 TAU_TYPE_STRING(taustr, "void (" + CT(f) + ", " + CT(s) + " )" ); 00221 TAU_PROFILE("SubBareField::SubBareField()", taustr, TAU_SUBFIELD); 00222 00223 // initialize the subset object, to a state where it can be combined 00224 // with the given input data. Then, put in data from given subset object. 00225 Brackets = SubFieldTraits<T,Dim,S,S2>::construct(MyDomain, s, A); 00226 } 00227 00228 }; 00229 00230 // I/O 00231 00232 // write a subfield to the given ostream 00233 template<class T, unsigned int Dim, class S> 00234 inline 00235 ostream& operator<<(ostream& o, const SubBareField<T,Dim,S>& s) { 00236 TAU_TYPE_STRING(taustr, "ostream (ostream, " + CT(s) + " )" ); 00237 TAU_PROFILE("SubBareField::operator<<()", taustr, TAU_SUBFIELD | TAU_IO ); 00238 SubBareField<T,Dim,S>& ncs = const_cast<SubBareField<T,Dim,S>&>(s); 00239 ncs.write(o); 00240 return o; 00241 } 00242 00243 00244 #include "SubField/SubBareField.cpp" 00245 00246 #endif // SUB_BARE_FIELD_H 00247 00248 /*************************************************************************** 00249 * $RCSfile: SubBareField.h,v $ $Author: adelmann $ 00250 * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:33 $ 00251 * IPPL_VERSION_ID: $Id: SubBareField.h,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 00252 ***************************************************************************/