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