jplus-0.4.5
src/jarray.h
Go to the documentation of this file.
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