jplus-0.4.6
|
00001 /* -*- mode: c++; indent-tabs-mode:nil -*- */ 00002 #ifndef JARRAY_H 00003 #define JARRAY_H 00004 00005 #include <vector> 00006 #include <string> 00007 #include <complex> 00008 #include <istream> 00009 #include <ostream> 00010 #include <cassert> 00011 #include "sha1.h" 00012 00013 class jengine; 00014 00025 class jarray { 00026 public: 00027 // C types, corresponding to J types 00028 // TODO: these are only for 32 bit linux, need ifdefs to cover 00029 // additional platforms 00030 typedef char B; 00031 typedef char C; 00032 typedef short S; 00033 #if _UNIX64 00034 typedef long long I; 00035 #else 00036 typedef long I; 00037 #endif 00038 typedef double D; 00040 typedef struct { 00041 D re, 00042 im; 00043 } Z; 00044 00045 friend class jengine; 00046 00047 public: 00049 enum errorType { 00050 ERR_CONV=10, 00051 ERR_SHAPE=11 00052 }; 00053 00055 enum elementType { 00056 T_B01 =1, 00057 T_LIT =2, 00058 T_INT =4, 00059 T_FL =8, 00060 T_CMPX =16 00061 }; 00062 // numeric constants, corresponding to J 7.01 types. 00063 // Not all of J types are supported, but the supported ones have 00064 // the full set of automatic widening conversions. 00065 //const static I T_B01 =1; /**< B boolean */ 00066 //const static I T_LIT =2; /**< C literal (character) */ 00067 //const static I T_INT =4; /**< I integer */ 00068 //const static I T_FL =8; /**< D double (IEEE floating point) */ 00069 //const static I T_CMPX =16; /**< Z complex */ 00070 //const static I T_BOX =32; /**< A boxed */ 00071 //const static I T_XNUM =64; /**< X extended precision integer */ 00072 //const static I T_RAT =128; /**< Q rational number */ 00073 //const static I T_SB01 =1024; /**< P sparse boolean */ 00074 //const static I T_SLIT =2048; /**< P sparse literal (character) */ 00075 //const static I T_SINT =4096; /**< P sparse integer */ 00076 //const static I T_SFL =8192; /**< P sparse floating point */ 00077 //const static I T_SCMPX=16384; /**< P sparse complex */ 00078 //const static I T_SBOX =32768; /**< P sparse boxed */ 00079 //const static I T_SBT =65536; /**< SB symbol */ 00080 //const static I T_C2T =131072; /**< C2 unicode (2-byte characters) */ 00081 00082 protected: 00084 typedef struct { 00085 I offset, 00086 flag, 00087 maxbytes, 00088 type, 00089 refcnt, 00090 n, 00091 rank, 00092 shape[1]; 00093 } header; 00094 header *hdr; 00095 jengine *je; 00099 typedef struct {I*a;S j;C mflag,unused;} MS; 00100 00110 bool allocate(jengine *je_, elementType type, const I rank, const I* shape); 00111 00113 // conversions: T=bool 00114 inline static int fromB01(bool& v, const B d) {v=(d!=0); return 0;}; 00115 inline static int fromLIT(bool& v, const C d) {return ERR_CONV;}; 00116 inline static int fromINT(bool& v, const I d) {return ERR_CONV;}; 00117 inline static int fromFL(bool& v, const D d) {return ERR_CONV;}; 00118 inline static int fromCMPX(bool& v, const Z d) {return ERR_CONV;}; 00119 inline static int toB01(const bool v, B& d) {d=v; return 0;}; 00120 inline static int toLIT(const bool v, C& d) {return ERR_CONV;}; 00121 inline static int toINT(const bool v, I& d) {d=v; return 0;}; 00122 inline static int toFL(const bool v, D& d) {d=v; return 0;}; 00123 inline static int toCMPX(const bool v, Z& d) {d.re=v; d.im=0; return 0;}; 00124 00125 // conversions: T=char 00126 // it may be more convenient to obtain literal array as a string 00127 // via get(string&) method. 00128 inline static int fromB01(char& v, const B d) {return ERR_CONV;}; 00129 inline static int fromLIT(char& v, const C d) {v=d; return 0;}; 00130 inline static int fromINT(char& v, const I d) {return ERR_CONV;}; 00131 inline static int fromFL(char& v, const D d) {return ERR_CONV;}; 00132 inline static int fromCMPX(char& v, const Z d) {return ERR_CONV;}; 00133 inline static int toB01(const char v, B& d) {return ERR_CONV;}; 00134 inline static int toLIT(const char v, C& d) {d=v; return 0;}; 00135 inline static int toINT(const char v, I& d) {d=v; return 0;}; 00136 inline static int toFL(const char v, D& d) {d=v; return 0;}; 00137 inline static int toCMPX(const char v, Z& d) {d.re=v; d.im=0; return 0;}; 00138 00139 // conversions: T=int 00140 inline static int fromB01(int& v, const B d) {v=d; return 0;}; 00141 inline static int fromLIT(int& v, const C d) {v=d; return 0;}; 00142 inline static int fromINT(int& v, const I d) {v=d; return 0;}; 00143 inline static int fromFL(int& v, const D d) {return ERR_CONV;}; 00144 inline static int fromCMPX(int& v, const Z d) {return ERR_CONV;}; 00145 inline static int toB01(const int v, B& d) {return ERR_CONV;}; 00146 inline static int toLIT(const int v, C& d) {return ERR_CONV;}; 00147 inline static int toINT(const int v, I& d) {d=v; return 0;}; 00148 inline static int toFL(const int v, D& d) {d=v; return 0;}; 00149 inline static int toCMPX(const int v, Z& d) {d.re=v; d.im=0; return 0;}; 00150 00151 // conversions: T=long 00152 inline static int fromB01(long& v, const B d) {v=d; return 0;}; 00153 inline static int fromLIT(long& v, const C d) {v=d; return 0;}; 00154 inline static int fromINT(long& v, const I d) {v=d; return 0;}; 00155 inline static int fromFL(long& v, const D d) {return ERR_CONV;}; 00156 inline static int fromCMPX(long& v, const Z d) {return ERR_CONV;}; 00157 inline static int toB01(const long v, B& d) {return ERR_CONV;}; 00158 inline static int toLIT(const long v, C& d) {return ERR_CONV;}; 00159 inline static int toINT(const long v, I& d) {d=v; return 0;}; 00160 inline static int toFL(const long v, D& d) {d=v; return 0;}; 00161 inline static int toCMPX(const long v, Z& d) {d.re=v; d.im=0; return 0;}; 00162 00163 // conversions: T=long long 00164 inline static int fromB01(long long& v, const B d) {v=d; return 0;}; 00165 inline static int fromLIT(long long& v, const C d) {v=d; return 0;}; 00166 inline static int fromINT(long long& v, const I d) {v=d; return 0;}; 00167 inline static int fromFL(long long& v, const D d) {return ERR_CONV;}; 00168 inline static int fromCMPX(long long& v, const Z d) {return ERR_CONV;}; 00169 inline static int toB01(const long long v, B& d) {return ERR_CONV;}; 00170 inline static int toLIT(const long long v, C& d) {return ERR_CONV;}; 00171 inline static int toINT(const long long v, I& d) {d=v; return 0;}; 00172 inline static int toFL(const long long v, D& d) {d=v; return 0;}; 00173 inline static int toCMPX(const long long v, Z& d) {d.re=v; d.im=0; return 0;}; 00174 00175 // conversions: T=double 00176 inline static int fromB01(double& v, const B d) {v=d; return 0;}; 00177 inline static int fromLIT(double& v, const C d) {v=d; return 0;}; 00178 inline static int fromINT(double& v, const I d) {v=d; return 0;}; 00179 inline static int fromFL(double& v, const D d) {v=d; return 0;}; 00180 inline static int fromCMPX(double& v, const Z d) {return ERR_CONV;}; 00181 inline static int toB01(const double v, B& d) {return ERR_CONV;}; 00182 inline static int toLIT(const double v, C& d) {return ERR_CONV;}; 00183 inline static int toINT(const double v, I& d) {d=v; return 0;}; 00184 inline static int toFL(const double v, D& d) {d=v; return 0;}; 00185 inline static int toCMPX(const double v, Z& d) {d.re=v; d.im=0; return 0;}; 00186 00187 // conversions: T=complex<double> 00188 inline static int fromB01(std::complex<double>& v, const B d) { 00189 return ERR_CONV;}; 00190 inline static int fromLIT(std::complex<double>& v, const C d) { 00191 v=d; return 0;}; 00192 inline static int fromINT(std::complex<double>& v, const I d) { 00193 v=d; return 0;}; 00194 inline static int fromFL(std::complex<double>& v, const D d) { 00195 v=d; return 0;}; 00196 inline static int fromCMPX(std::complex<double>& v, const Z d) { 00197 std::complex<double> c(d.re, d.im); v=c; return 0;}; 00198 inline static int toB01(const std::complex<double> v, B& d) { 00199 return ERR_CONV;}; 00200 inline static int toLIT(const std::complex<double> v, C& d) { 00201 return ERR_CONV;}; 00202 inline static int toINT(const std::complex<double> v, I& d) { 00203 return ERR_CONV;}; 00204 inline static int toFL(const std::complex<double> v, D& d) { 00205 return ERR_CONV;}; 00206 inline static int toCMPX(const std::complex<double> v, Z& d) { 00207 d.re=v.real(); d.im=v.imag(); return 0;}; 00211 void grab() const; 00212 00214 void release(); 00215 00216 // returns pointer to the header and (if parameter is "true", which is 00217 // default) marks the array as owned by J preventing its memory from 00218 // being freed as it goes out of scope. 00219 inline I getHeader(bool give_up_ownership=true) const { 00220 if (give_up_ownership) hdr->flag|=OWNED_BY_J; 00221 return (I)hdr; 00222 }; 00223 00224 private: 00225 // flag, marking the array as J owned, preventing its memory from 00226 // being freed when the array goes out of scope. 00227 const static int OWNED_BY_J=131072; 00228 // marks the array as being allocated on heap without J assistance 00229 const static int OWNED_BY_JPLUS=262144; 00230 00231 public: 00234 I getRefcount() const {return hdr->refcnt;}; 00235 00242 template<class T> inline int get(T& v, const int i) const { 00243 switch(hdr->type) { 00244 case T_B01: return fromB01(v,((B*)(((B*)hdr)+hdr->offset))[i]); 00245 case T_LIT: return fromLIT(v,((C*)(((B*)hdr)+hdr->offset))[i]); 00246 case T_INT: return fromINT(v,((I*)(((B*)hdr)+hdr->offset))[i]); 00247 case T_FL: return fromFL(v,((D*)(((B*)hdr)+hdr->offset))[i]); 00248 case T_CMPX: return fromCMPX(v,((Z*)(((B*)hdr)+hdr->offset))[i]); 00249 default: return ERR_CONV; 00250 }; 00251 }; 00252 00258 template<class T> inline int set(const int i, const T v) { 00259 switch(hdr->type) { 00260 case T_B01: return toB01(v,((B*)(((B*)hdr)+hdr->offset))[i]); 00261 case T_LIT: return toLIT(v,((C*)(((B*)hdr)+hdr->offset))[i]); 00262 case T_INT: return toINT(v,((I*)(((B*)hdr)+hdr->offset))[i]); 00263 case T_FL: return toFL(v,((D*)(((B*)hdr)+hdr->offset))[i]); 00264 case T_CMPX: return toCMPX(v,((Z*)(((B*)hdr)+hdr->offset))[i]); 00265 default: return ERR_CONV; 00266 }; 00267 }; 00268 00273 template<class T> int get(std::vector<T>& v) const { 00274 std::vector<T> r; 00275 r.reserve(hdr->n); 00276 int e; 00277 switch(hdr->type) { 00278 case T_B01: for(int i=0;i<hdr->n;i++) 00279 if (e=fromB01(v[i],((B*)(((B*)hdr)+hdr->offset))[i])) return e; 00280 break; 00281 case T_LIT: for(int i=0;i<hdr->n;i++) 00282 if (e=fromLIT(v[i],((C*)(((B*)hdr)+hdr->offset))[i])) return e; 00283 break; 00284 case T_INT: for(int i=0;i<hdr->n;i++) 00285 if (e=fromINT(v[i],((I*)(((B*)hdr)+hdr->offset))[i])) return e; 00286 break; 00287 case T_FL: for(int i=0;i<hdr->n;i++) 00288 if (e=fromFL(v[i],((D*)(((B*)hdr)+hdr->offset))[i])) return e; 00289 break; 00290 case T_CMPX: for(int i=0;i<hdr->n;i++) 00291 if (e=fromCMPX(v[i],((Z*)(((B*)hdr)+hdr->offset))[i])) return e; 00292 break; 00293 default: return ERR_CONV; 00294 }; 00295 r.swap(v); 00296 return 0; 00297 }; 00298 00304 template<class T> int get(T& v); 00305 00307 jarray(); 00308 00313 jarray(jengine *je_, std::istream& in); 00314 00318 static jarray::I esize(elementType type); 00319 00321 jarray::I esize() const; 00322 00325 void addhash(SHA1 &sha); 00326 00331 bool write(std::ostream& out); 00332 00335 inline bool isValid() const { 00336 return hdr!=NULL; 00337 }; 00338 00341 inline const I type() const { 00342 return hdr->type; 00343 }; 00344 00347 inline const I rank() const { 00348 return hdr->rank; 00349 }; 00350 00353 inline I* shape() const { 00354 return &hdr->shape[0]; 00355 }; 00356 00360 int extent(int dimension) const { 00361 assert((dimension>=0)&&(dimension<rank())); 00362 return shape()[dimension]; 00363 }; 00364 00367 inline void shape(std::vector<I> &shape) const { 00368 std::vector<I> r(&hdr->shape[0],&hdr->shape[rank()]); 00369 r.swap(shape); 00370 }; 00371 00374 inline const int size() const { 00375 int n=1; 00376 for (int i=0;i<rank();i++) n*=hdr->shape[i]; 00377 return n; 00378 }; 00379 00382 inline I* data() const { 00383 return (I*)(((B*)hdr)+hdr->offset); 00384 }; 00385 00391 jengine* getEngine() const { 00392 return je; 00393 }; 00394 00398 jarray(jengine *je_, void *hdr_); 00399 00405 jarray(jengine *je_, elementType type, I rank, I* shape); 00406 00411 jarray(jengine *je_, elementType type, const std::vector<I>& shape); 00412 00416 jarray(jengine *je_,const std::string &str); 00417 00420 jarray(const jarray &other); 00421 00426 jarray& assign(const jarray& other); 00427 00431 inline jarray& operator=(const jarray& other) { 00432 return assign(other); 00433 }; 00434 00440 bool operator== ( const jarray& rhs ) const; 00441 00443 ~jarray(); 00444 }; 00445 00450 std::ostream& operator<< (std::ostream& stream, const jarray& array); 00451 00454 template<class T> class jarray_of_type: public jarray { 00455 private: 00456 static elementType jtype(I dummy) {return T_INT;}; 00457 static elementType jtype(D dummy) {return T_FL;}; 00458 static elementType jtype(Z dummy) {return T_CMPX;}; 00459 static elementType jtype(std::complex<D> dummy) {return T_CMPX;}; 00460 00461 public: 00470 jarray_of_type(const jarray &ja):jarray() { 00471 T dummy; 00472 elementType type=jtype(dummy); 00473 if (type!=ja.type()) { // make an independent copy and convert type 00474 allocate(ja.getEngine(), type, ja.rank(), ja.shape()); 00475 int n=ja.size(); 00476 for (int i=0;i<n;i++) { 00477 T v; 00478 ja.get(v,i); 00479 set(i,v); 00480 }; 00481 } else assign(ja); // type is the same, direct access 00482 }; 00483 00487 T& operator[](const I i) { 00488 // assert((i>=0)&&(i<size()); 00489 return ((T*)data())[i]; 00490 }; 00491 00495 const T& operator[](const I i) const { 00496 // assert((i>=0)&&(i<size()); 00497 return ((T*)data())[i]; 00498 }; 00499 00502 jarray_of_type(jengine *je_) { 00503 T dummy; I shape[]={}; allocate(je_, jtype(dummy), 0, shape); 00504 }; 00505 00509 jarray_of_type(jengine *je_, const I l0) { 00510 T dummy; I shape[]={l0}; allocate(je_, jtype(dummy), 1, shape); 00511 }; 00515 T& operator()(const I i0) { 00516 assert(rank()==1); return ((T*)data())[i0]; 00517 }; 00521 const T& operator()(const I i0) const { 00522 assert(rank()==1); return ((T*)data())[i0]; 00523 }; 00524 00529 jarray_of_type(jengine *je_, const I l0, const I l1) { 00530 T dummy; I shape[]={l0,l1}; allocate(je_,jtype(dummy), 2, shape); 00531 }; 00532 00537 T& operator()(const I i0,const I i1) { 00538 assert(rank()==2); return ((T*)data())[i0*extent(1)+i1]; 00539 }; 00544 const T& operator()(const I i0,const I i1) const { 00545 assert(rank()==2); return ((T*)data())[i0*extent(1)+i1]; 00546 }; 00547 00553 jarray_of_type(jengine *je_, const I l0, const I l1, const I l2) { 00554 T dummy; I shape[]={l0,l1,l2}; allocate(je_, jtype(dummy), 3, shape); 00555 }; 00556 00562 T& operator()(const I i0,const I i1,const I i2) { 00563 assert(rank()==3); return ((T*)data())[(i0*extent(1)+i1)*extent(2)+i2]; 00564 }; 00565 00571 const T& operator()(const I i0,const I i1,const I i2) const { 00572 assert(rank()==3); return ((T*)data())[(i0*extent(1)+i1)*extent(2)+i2]; 00573 }; 00574 00581 jarray_of_type(jengine *je_, const I l0, const I l1, const I l2, 00582 const I l3) { 00583 T dummy; I shape[]={l0,l1,l2,l3}; allocate(je_,jtype(dummy), 4, shape); 00584 }; 00585 00592 T& operator()(const I i0,const I i1,const I i2,const I i3) { 00593 assert(rank()==4); 00594 return ((T*)data())[((i0*extent(1)+i1)*extent(2)+i2)*extent(3)+i3]; 00595 }; 00596 00603 const T& operator()(const I i0,const I i1,const I i2,const I i3) const { 00604 assert(rank()==4); 00605 return ((T*)data())[((i0*extent(1)+i1)*extent(2)+i2)*extent(3)+i3]; 00606 }; 00607 00615 jarray_of_type(jengine *je_, const I l0, const I l1, const I l2, 00616 const I l3, const I l4) { 00617 T dummy; I shape[]={l0,l1,l2,l3,l4}; allocate(je_,jtype(dummy), 5, shape); 00618 }; 00619 00627 T& operator()(const I i0,const I i1,const I i2,const I i3,const I i4) { 00628 assert(rank()==4); 00629 return ((T*)data())[(((i0*extent(1)+i1)*extent(2)+i2)*extent(3)+i3)*extent(4)+i4]; 00630 }; 00631 00639 const T& operator()(const I i0,const I i1,const I i2,const I i3,const I i4) const { 00640 assert(rank()==4); 00641 return ((T*)data())[(((i0*extent(1)+i1)*extent(2)+i2)*extent(3)+i3)*extent(4)+i4]; 00642 }; 00643 00644 00649 jarray_of_type(jengine *je_, const I rank, const I *shape) { 00650 T dummy; allocate(je_, jtype(dummy), rank, shape); 00651 }; 00652 00656 jarray_of_type(jengine *je_, const std::vector<I> &shape) { 00657 T dummy; allocate(je_, jtype(dummy), shape.size(), &shape[0]); 00658 }; 00659 00663 T& operator()(const std::vector<I> &subscripts) { 00664 assert(rank()==subscripts.size()); 00665 I pos=0; 00666 for(int i=0;i<subscripts.size();i++) pos=pos*extent(i)+subscripts[i]; 00667 return ((T*)data())[pos]; 00668 }; 00672 const T& operator()(const std::vector<I> &subscripts) const { 00673 assert(rank()==subscripts.size()); 00674 I pos=0; 00675 for(int i=0;i<subscripts.size();i++) pos=pos*extent(i)+subscripts[i]; 00676 return ((T*)data())[pos]; 00677 }; 00682 T& operator()(const I *subscripts) { 00683 I pos=0; 00684 for(int i=0;i<rank();i++) pos=pos*extent(i)+subscripts[i]; 00685 return ((T*)data())[pos]; 00686 }; 00691 const T& operator()(const I *subscripts) const { 00692 I pos=0; 00693 for(int i=0;i<rank();i++) pos=pos*extent(i)+subscripts[i]; 00694 return ((T*)data())[pos]; 00695 }; 00696 00697 }; 00698 #endif