jplus-0.4.5
|
00001 #ifndef JARRAY_H 00002 #define JARRAY_H 00003 00004 #include <vector> 00005 #include <string> 00006 #include <complex> 00007 #include <istream> 00008 #include <ostream> 00009 #include <cassert> 00010 #include "sha1.h" 00011 00012 class jengine; 00013 00024 class jarray { 00025 public: 00026 // C types, corresponding to J types 00027 // TODO: these are only for 32 bit linux, need ifdefs to cover 00028 // additional platforms 00029 typedef char B; 00030 typedef char C; 00031 typedef short S; 00032 typedef long I; 00033 typedef double D; 00035 typedef struct { 00036 D re, 00037 im; 00038 } Z; 00039 00040 friend class jengine; 00041 00042 public: 00044 enum errorType { 00045 ERR_CONV=10, 00046 ERR_SHAPE=11 00047 }; 00048 00050 enum elementType { 00051 T_B01 =1, 00052 T_LIT =2, 00053 T_INT =4, 00054 T_FL =8, 00055 T_CMPX =16 00056 }; 00057 // numeric constants, corresponding to J 7.01 types. 00058 // Not all of J types are supported, but the supported ones have 00059 // the full set of automatic widening conversions. 00060 //const static I T_B01 =1; /**< B boolean */ 00061 //const static I T_LIT =2; /**< C literal (character) */ 00062 //const static I T_INT =4; /**< I integer */ 00063 //const static I T_FL =8; /**< D double (IEEE floating point) */ 00064 //const static I T_CMPX =16; /**< Z complex */ 00065 //const static I T_BOX =32; /**< A boxed */ 00066 //const static I T_XNUM =64; /**< X extended precision integer */ 00067 //const static I T_RAT =128; /**< Q rational number */ 00068 //const static I T_SB01 =1024; /**< P sparse boolean */ 00069 //const static I T_SLIT =2048; /**< P sparse literal (character) */ 00070 //const static I T_SINT =4096; /**< P sparse integer */ 00071 //const static I T_SFL =8192; /**< P sparse floating point */ 00072 //const static I T_SCMPX=16384; /**< P sparse complex */ 00073 //const static I T_SBOX =32768; /**< P sparse boxed */ 00074 //const static I T_SBT =65536; /**< SB symbol */ 00075 //const static I T_C2T =131072; /**< C2 unicode (2-byte characters) */ 00076 00077 protected: 00079 typedef struct { 00080 I offset, 00081 flag, 00082 maxbytes, 00083 type, 00084 refcnt, 00085 n, 00086 rank, 00087 shape[1]; 00088 } header; 00089 header *hdr; 00090 jengine *je; 00094 typedef struct {I*a;S j;C mflag,unused;} MS; 00095 00105 bool allocate(jengine *je_, elementType type, const I rank, const I* shape); 00106 00108 // conversions: T=bool 00109 inline static int fromB01(bool& v, const B d) {v=(d!=0); return 0;}; 00110 inline static int fromLIT(bool& v, const C d) {return ERR_CONV;}; 00111 inline static int fromINT(bool& v, const I d) {return ERR_CONV;}; 00112 inline static int fromFL(bool& v, const D d) {return ERR_CONV;}; 00113 inline static int fromCMPX(bool& v, const Z d) {return ERR_CONV;}; 00114 inline static int toB01(const bool v, B& d) {d=v; return 0;}; 00115 inline static int toLIT(const bool v, C& d) {return ERR_CONV;}; 00116 inline static int toINT(const bool v, I& d) {d=v; return 0;}; 00117 inline static int toFL(const bool v, D& d) {d=v; return 0;}; 00118 inline static int toCMPX(const bool v, Z& d) {d.re=v; d.im=0; return 0;}; 00119 00120 // conversions: T=char 00121 // it may be more convenient to obtain literal array as a string 00122 // via get(string&) method. 00123 inline static int fromB01(char& v, const B d) {return ERR_CONV;}; 00124 inline static int fromLIT(char& v, const C d) {v=d; return 0;}; 00125 inline static int fromINT(char& v, const I d) {return ERR_CONV;}; 00126 inline static int fromFL(char& v, const D d) {return ERR_CONV;}; 00127 inline static int fromCMPX(char& v, const Z d) {return ERR_CONV;}; 00128 inline static int toB01(const char v, B& d) {return ERR_CONV;}; 00129 inline static int toLIT(const char v, C& d) {d=v; return 0;}; 00130 inline static int toINT(const char v, I& d) {d=v; return 0;}; 00131 inline static int toFL(const char v, D& d) {d=v; return 0;}; 00132 inline static int toCMPX(const char v, Z& d) {d.re=v; d.im=0; return 0;}; 00133 00134 // conversions: T=int 00135 inline static int fromB01(int& v, const B d) {v=d; return 0;}; 00136 inline static int fromLIT(int& v, const C d) {v=d; return 0;}; 00137 inline static int fromINT(int& v, const I d) {v=d; return 0;}; 00138 inline static int fromFL(int& v, const D d) {return ERR_CONV;}; 00139 inline static int fromCMPX(int& v, const Z d) {return ERR_CONV;}; 00140 inline static int toB01(const int v, B& d) {return ERR_CONV;}; 00141 inline static int toLIT(const int v, C& d) {return ERR_CONV;}; 00142 inline static int toINT(const int v, I& d) {d=v; return 0;}; 00143 inline static int toFL(const int v, D& d) {d=v; return 0;}; 00144 inline static int toCMPX(const int v, Z& d) {d.re=v; d.im=0; return 0;}; 00145 00146 // conversions: T=long 00147 inline static int fromB01(long& v, const B d) {v=d; return 0;}; 00148 inline static int fromLIT(long& v, const C d) {v=d; return 0;}; 00149 inline static int fromINT(long& v, const I d) {v=d; return 0;}; 00150 inline static int fromFL(long& v, const D d) {return ERR_CONV;}; 00151 inline static int fromCMPX(long& v, const Z d) {return ERR_CONV;}; 00152 inline static int toB01(const long v, B& d) {return ERR_CONV;}; 00153 inline static int toLIT(const long v, C& d) {return ERR_CONV;}; 00154 inline static int toINT(const long v, I& d) {d=v; return 0;}; 00155 inline static int toFL(const long v, D& d) {d=v; return 0;}; 00156 inline static int toCMPX(const long v, Z& d) {d.re=v; d.im=0; return 0;}; 00157 00158 // conversions: T=double 00159 inline static int fromB01(double& v, const B d) {v=d; return 0;}; 00160 inline static int fromLIT(double& v, const C d) {v=d; return 0;}; 00161 inline static int fromINT(double& v, const I d) {v=d; return 0;}; 00162 inline static int fromFL(double& v, const D d) {v=d; return 0;}; 00163 inline static int fromCMPX(double& v, const Z d) {return ERR_CONV;}; 00164 inline static int toB01(const double v, B& d) {return ERR_CONV;}; 00165 inline static int toLIT(const double v, C& d) {return ERR_CONV;}; 00166 inline static int toINT(const double v, I& d) {d=v; return 0;}; 00167 inline static int toFL(const double v, D& d) {d=v; return 0;}; 00168 inline static int toCMPX(const double v, Z& d) {d.re=v; d.im=0; return 0;}; 00169 00170 // conversions: T=complex<double> 00171 inline static int fromB01(std::complex<double>& v, const B d) { 00172 return ERR_CONV;}; 00173 inline static int fromLIT(std::complex<double>& v, const C d) { 00174 v=d; return 0;}; 00175 inline static int fromINT(std::complex<double>& v, const I d) { 00176 v=d; return 0;}; 00177 inline static int fromFL(std::complex<double>& v, const D d) { 00178 v=d; return 0;}; 00179 inline static int fromCMPX(std::complex<double>& v, const Z d) { 00180 std::complex<double> c(d.re, d.im); v=c; return 0;}; 00181 inline static int toB01(const std::complex<double> v, B& d) { 00182 return ERR_CONV;}; 00183 inline static int toLIT(const std::complex<double> v, C& d) { 00184 return ERR_CONV;}; 00185 inline static int toINT(const std::complex<double> v, I& d) { 00186 return ERR_CONV;}; 00187 inline static int toFL(const std::complex<double> v, D& d) { 00188 return ERR_CONV;}; 00189 inline static int toCMPX(const std::complex<double> v, Z& d) { 00190 d.re=v.real(); d.im=v.imag(); return 0;}; 00194 void grab() const; 00195 00197 void release(); 00198 00199 // returns pointer to the header and (if parameter is "true", which is 00200 // default) marks the array as owned by J preventing its memory from 00201 // being freed as it goes out of scope. 00202 inline I getHeader(bool give_up_ownership=true) const { 00203 if (give_up_ownership) hdr->flag|=OWNED_BY_J; 00204 return (I)hdr; 00205 }; 00206 00207 private: 00208 // flag, marking the array as J owned, preventing its memory from 00209 // being freed when the array goes out of scope. 00210 const static int OWNED_BY_J=131072; 00211 // marks the array as being allocated on heap without J assistance 00212 const static int OWNED_BY_JPLUS=262144; 00213 00214 public: 00217 I getRefcount() const {return hdr->refcnt;}; 00218 00225 template<class T> inline int get(T& v, const int i) const { 00226 switch(hdr->type) { 00227 case T_B01: return fromB01(v,((B*)(((B*)hdr)+hdr->offset))[i]); 00228 case T_LIT: return fromLIT(v,((C*)(((B*)hdr)+hdr->offset))[i]); 00229 case T_INT: return fromINT(v,((I*)(((B*)hdr)+hdr->offset))[i]); 00230 case T_FL: return fromFL(v,((D*)(((B*)hdr)+hdr->offset))[i]); 00231 case T_CMPX: return fromCMPX(v,((Z*)(((B*)hdr)+hdr->offset))[i]); 00232 default: return ERR_CONV; 00233 }; 00234 }; 00235 00241 template<class T> inline int set(const int i, const T v) { 00242 switch(hdr->type) { 00243 case T_B01: return toB01(v,((B*)(((B*)hdr)+hdr->offset))[i]); 00244 case T_LIT: return toLIT(v,((C*)(((B*)hdr)+hdr->offset))[i]); 00245 case T_INT: return toINT(v,((I*)(((B*)hdr)+hdr->offset))[i]); 00246 case T_FL: return toFL(v,((D*)(((B*)hdr)+hdr->offset))[i]); 00247 case T_CMPX: return toCMPX(v,((Z*)(((B*)hdr)+hdr->offset))[i]); 00248 default: return ERR_CONV; 00249 }; 00250 }; 00251 00256 template<class T> int get(std::vector<T>& v) const { 00257 std::vector<T> r; 00258 r.reserve(hdr->n); 00259 int e; 00260 switch(hdr->type) { 00261 case T_B01: for(int i=0;i<hdr->n;i++) 00262 if (e=fromB01(v[i],((B*)(((B*)hdr)+hdr->offset))[i])) return e; 00263 break; 00264 case T_LIT: for(int i=0;i<hdr->n;i++) 00265 if (e=fromLIT(v[i],((C*)(((B*)hdr)+hdr->offset))[i])) return e; 00266 break; 00267 case T_INT: for(int i=0;i<hdr->n;i++) 00268 if (e=fromINT(v[i],((I*)(((B*)hdr)+hdr->offset))[i])) return e; 00269 break; 00270 case T_FL: for(int i=0;i<hdr->n;i++) 00271 if (e=fromFL(v[i],((D*)(((B*)hdr)+hdr->offset))[i])) return e; 00272 break; 00273 case T_CMPX: for(int i=0;i<hdr->n;i++) 00274 if (e=fromCMPX(v[i],((Z*)(((B*)hdr)+hdr->offset))[i])) return e; 00275 break; 00276 default: return ERR_CONV; 00277 }; 00278 r.swap(v); 00279 return 0; 00280 }; 00281 00287 template<class T> int get(T& v); 00288 00290 jarray(); 00291 00296 jarray(jengine *je_, std::istream& in); 00297 00301 static jarray::I esize(elementType type); 00302 00304 jarray::I esize() const; 00305 00308 void addhash(SHA1 &sha); 00309 00314 bool write(std::ostream& out); 00315 00318 inline bool isValid() const { 00319 return hdr!=NULL; 00320 }; 00321 00324 inline const I type() const { 00325 return hdr->type; 00326 }; 00327 00330 inline const I rank() const { 00331 return hdr->rank; 00332 }; 00333 00336 inline I* shape() const { 00337 return &hdr->shape[0]; 00338 }; 00339 00343 int extent(int dimension) const { 00344 assert((dimension>=0)&&(dimension<rank())); 00345 return shape()[dimension]; 00346 }; 00347 00350 inline void shape(std::vector<I> &shape) const { 00351 std::vector<I> r(&hdr->shape[0],&hdr->shape[rank()]); 00352 r.swap(shape); 00353 }; 00354 00357 inline const int size() const { 00358 int n=1; 00359 for (int i=0;i<rank();i++) n*=hdr->shape[i]; 00360 return n; 00361 }; 00362 00365 inline I* data() const { 00366 return (I*)(((B*)hdr)+hdr->offset); 00367 }; 00368 00374 jengine* getEngine() const { 00375 return je; 00376 }; 00377 00381 jarray(jengine *je_, void *hdr_); 00382 00388 jarray(jengine *je_, elementType type, I rank, I* shape); 00389 00394 jarray(jengine *je_, elementType type, const std::vector<I>& shape); 00395 00399 jarray(jengine *je_,const std::string &str); 00400 00403 jarray(const jarray &other); 00404 00409 jarray& assign(const jarray& other); 00410 00414 inline jarray& operator=(const jarray& other) { 00415 return assign(other); 00416 }; 00417 00423 bool operator== ( const jarray& rhs ) const; 00424 00426 ~jarray(); 00427 }; 00428 00433 std::ostream& operator<< (std::ostream& stream, const jarray& array); 00434 00437 template<class T> class jarray_of_type: public jarray { 00438 private: 00439 static elementType jtype(I dummy) {return T_INT;}; 00440 static elementType jtype(D dummy) {return T_FL;}; 00441 static elementType jtype(Z dummy) {return T_CMPX;}; 00442 static elementType jtype(std::complex<D> dummy) {return T_CMPX;}; 00443 00444 public: 00453 jarray_of_type(const jarray &ja):jarray() { 00454 T dummy; 00455 elementType type=jtype(dummy); 00456 if (type!=ja.type()) { // make an independent copy and convert type 00457 allocate(ja.getEngine(), type, ja.rank(), ja.shape()); 00458 int n=ja.size(); 00459 for (int i=0;i<n;i++) { 00460 T v; 00461 ja.get(v,i); 00462 set(i,v); 00463 }; 00464 } else assign(ja); // type is the same, direct access 00465 }; 00466 00470 T& operator[](const I i) { 00471 // assert((i>=0)&&(i<size()); 00472 return ((T*)data())[i]; 00473 }; 00474 00478 const T& operator[](const I i) const { 00479 // assert((i>=0)&&(i<size()); 00480 return ((T*)data())[i]; 00481 }; 00482 00485 jarray_of_type(jengine *je_) { 00486 T dummy; I shape[]={}; allocate(je_, jtype(dummy), 0, shape); 00487 }; 00488 00492 jarray_of_type(jengine *je_, const I l0) { 00493 T dummy; I shape[]={l0}; allocate(je_, jtype(dummy), 1, shape); 00494 }; 00498 T& operator()(const I i0) { 00499 assert(rank()==1); return ((T*)data())[i0]; 00500 }; 00504 const T& operator()(const I i0) const { 00505 assert(rank()==1); return ((T*)data())[i0]; 00506 }; 00507 00512 jarray_of_type(jengine *je_, const I l0, const I l1) { 00513 T dummy; I shape[]={l0,l1}; allocate(je_,jtype(dummy), 2, shape); 00514 }; 00515 00520 T& operator()(const I i0,const I i1) { 00521 assert(rank()==2); return ((T*)data())[i0*extent(1)+i1]; 00522 }; 00527 const T& operator()(const I i0,const I i1) const { 00528 assert(rank()==2); return ((T*)data())[i0*extent(1)+i1]; 00529 }; 00530 00536 jarray_of_type(jengine *je_, const I l0, const I l1, const I l2) { 00537 T dummy; I shape[]={l0,l1,l2}; allocate(je_, jtype(dummy), 3, shape); 00538 }; 00539 00545 T& operator()(const I i0,const I i1,const I i2) { 00546 assert(rank()==3); return ((T*)data())[(i0*extent(1)+i1)*extent(2)+i2]; 00547 }; 00548 00554 const T& operator()(const I i0,const I i1,const I i2) const { 00555 assert(rank()==3); return ((T*)data())[(i0*extent(1)+i1)*extent(2)+i2]; 00556 }; 00557 00564 jarray_of_type(jengine *je_, const I l0, const I l1, const I l2, 00565 const I l3) { 00566 T dummy; I shape[]={l0,l1,l2,l3}; allocate(je_,jtype(dummy), 4, shape); 00567 }; 00568 00575 T& operator()(const I i0,const I i1,const I i2,const I i3) { 00576 assert(rank()==4); 00577 return ((T*)data())[((i0*extent(1)+i1)*extent(2)+i2)*extent(3)+i3]; 00578 }; 00579 00586 const T& operator()(const I i0,const I i1,const I i2,const I i3) const { 00587 assert(rank()==4); 00588 return ((T*)data())[((i0*extent(1)+i1)*extent(2)+i2)*extent(3)+i3]; 00589 }; 00590 00598 jarray_of_type(jengine *je_, const I l0, const I l1, const I l2, 00599 const I l3, const I l4) { 00600 T dummy; I shape[]={l0,l1,l2,l3,l4}; allocate(je_,jtype(dummy), 5, shape); 00601 }; 00602 00610 T& operator()(const I i0,const I i1,const I i2,const I i3,const I i4) { 00611 assert(rank()==4); 00612 return ((T*)data())[(((i0*extent(1)+i1)*extent(2)+i2)*extent(3)+i3)*extent(4)+i4]; 00613 }; 00614 00622 const T& operator()(const I i0,const I i1,const I i2,const I i3,const I i4) const { 00623 assert(rank()==4); 00624 return ((T*)data())[(((i0*extent(1)+i1)*extent(2)+i2)*extent(3)+i3)*extent(4)+i4]; 00625 }; 00626 00627 00632 jarray_of_type(jengine *je_, const I rank, const I *shape) { 00633 T dummy; allocate(je_, jtype(dummy), rank, shape); 00634 }; 00635 00639 jarray_of_type(jengine *je_, const std::vector<I> &shape) { 00640 T dummy; allocate(je_, jtype(dummy), shape.size(), &shape[0]); 00641 }; 00642 00646 T& operator()(const std::vector<I> &subscripts) { 00647 assert(rank()==subscripts.size()); 00648 I pos=0; 00649 for(int i=0;i<subscripts.size();i++) pos=pos*extent(i)+subscripts[i]; 00650 return ((T*)data())[pos]; 00651 }; 00655 const T& operator()(const std::vector<I> &subscripts) const { 00656 assert(rank()==subscripts.size()); 00657 I pos=0; 00658 for(int i=0;i<subscripts.size();i++) pos=pos*extent(i)+subscripts[i]; 00659 return ((T*)data())[pos]; 00660 }; 00665 T& operator()(const I *subscripts) { 00666 I pos=0; 00667 for(int i=0;i<rank();i++) pos=pos*extent(i)+subscripts[i]; 00668 return ((T*)data())[pos]; 00669 }; 00674 const T& operator()(const I *subscripts) const { 00675 I pos=0; 00676 for(int i=0;i<rank();i++) pos=pos*extent(i)+subscripts[i]; 00677 return ((T*)data())[pos]; 00678 }; 00679 00680 }; 00681 #endif