Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

LAStreams.h

Go to the documentation of this file.
00001 // This may look like C code, but it is really -*- C++ -*-
00002 /*
00003  ************************************************************************
00004  *
00005  *                        Linear Algebra Package
00006  *                        
00007  * The following functions support a _sequential_ traversal of a matrix
00008  * or its parts (a row, a column, a diagonal, or an arbitrary rectangular
00009  * block). As the README file explains, a random access to matrix elements
00010  * is often an unnecessary luxury. Many Numerical Math algorithms access
00011  * matrices by walking them in regular sequential ways. This _serial_
00012  * access can be implemented far more efficiently than the arbitrary
00013  * access.
00014  * 
00015  * The classes below act as input/ouput "matrix" streams. As with regular
00016  * streams, be sure to check for eof() before attempting to get() an
00017  * element.
00018  * Note, since all the methods of the matrix streams are implemented inline,
00019  * the whole iteration would be inline, too.
00020  * Note, that if the stream is applied to the entire Matrix or its
00021  * rectangular block, it would be traversed in the natural, that is,
00022  * COLUMN major order.
00023  *
00024  * $Id: LAStreams.h,v 1.1 2004/05/21 21:02:52 maxx Exp $
00025  *
00026  ************************************************************************
00027  */
00028 
00029 #ifndef __GNUC__
00030 #pragma once
00031 #endif
00032 
00033 #ifndef _LAStreams_h
00034 #define _LAStreams_h 1
00035 
00036 #if !defined(_LinAlg_h)
00037 #include "LinAlg.h"
00038 #endif
00039 
00040 namespace linalg 
00041 {
00042     using namespace linalg;
00043     
00044 class LAS {                     // A "namespace" to define some common constants
00045 public:
00046  enum seek_dir { beg, cur, end};
00047  
00048  static inline const REAL * min(const REAL * const p1, const REAL * const p2)
00049         { return p1 > p2 ? p2 : p1; }
00050         
00051  static inline const REAL * max(const REAL * const p1, const REAL * const p2)
00052         { return p1 > p2 ? p1 : p2; }
00053         
00054 };
00055                                 // A bookmark in the stream
00056 class AREALMark
00057 {
00058   friend class AREALStreamIn;
00059   friend class AREALStreamOut;
00060   friend class AREALStrideStreamIn;
00061   friend class AREALStrideStreamOut;
00062   friend class AREALBlockStreamIn;
00063   friend class AREALBlockStreamOut;
00064   size_t offset;
00065   enum { invalid_offset = (size_t)(-1) };
00066   AREALMark(const size_t _offset) : offset(_offset) {}
00067 public:
00068   AREALMark(void) : offset(invalid_offset) {}
00069   operator bool (void) const    { return offset != invalid_offset; }
00070   bool operator ! (void) const  { return offset == invalid_offset; }
00071   rowcol get_2dpos(const DimSpec dims) const
00072         { assert( (bool)(*this) && dims.q_nrows() > 0 );
00073           div_t res = div(offset,dims.q_nrows());
00074           return rowcol(res.rem+dims.q_row_lwb(),res.quot+dims.q_col_lwb()); }
00075   friend ostream& operator << (ostream& os, const AREALMark& mark);
00076 };
00077   
00078  
00079                         // The following are the pair of "streams" over
00080                         // the field of REALs
00081                         // These classes are mixins - they provide an
00082                         // "abstract" stream functionality. The classes
00083                         // don't have public constructors, as none of
00084                         // mixin classes do. The classes are supposed to be
00085                         // "blended" with other classes to imbue them with
00086                         // stream properties: the derived class
00087                         // must then properly set the current element
00088                         // pointer and the last element pointer.
00089                         // Since the classes do not declare any virtual
00090                         // functions, they are lightweight (and can be
00091                         // inlined)
00092 
00093 class AREALStreamIn
00094 {
00095   const REAL * curr_el_p;            // curr_el_p <= last_el_p always
00096   const REAL * const first_el_p;     // The first element pointer
00097   const REAL * const last_el_p;      // The == condition means EOF
00098   
00099   AREALStreamIn(const AREALStreamIn&);   // Not implemented and forbidden:
00100   void operator = (const AREALStreamIn&);// no cloning/assignment allowed
00101 
00102                                 // Apply range:dir to yield a new first_el_p
00103                                 // invariant: new_first_el_p >= first_el_p
00104   const REAL * subrange_first(const IRange range, LAS::seek_dir dir) const
00105   {
00106     if( dir == LAS::beg )
00107       return range.lwb <= 0 ? first_el_p : first_el_p + range.lwb;
00108     else if( dir == LAS::end )
00109       return range.lwb == - IRange::INF ? first_el_p : 
00110                 LAS::max(first_el_p,last_el_p - range.lwb);
00111     else
00112       return range.lwb == - IRange::INF ? curr_el_p : 
00113                 LAS::max(first_el_p,curr_el_p + range.lwb);
00114   }
00115 
00116                                 // Apply range:dir to yield a new last_el_p
00117                                 // invariant: new_last_el_p <= last_el_p
00118   const REAL * subrange_last(const IRange range, LAS::seek_dir dir) const
00119   {
00120     if( dir == LAS::beg )
00121       return range.upb == IRange::INF ? last_el_p : 
00122                 LAS::min(last_el_p,first_el_p + range.upb + 1);
00123     else if( dir == LAS::end )
00124       return last_el_p;
00125     else
00126       return range.upb == IRange::INF ? last_el_p : 
00127                 LAS::min(last_el_p,curr_el_p + range.upb + 1);
00128   }
00129 
00130 protected:
00131                                 // A protected constructor
00132   AREALStreamIn(const REAL * _beg_ptr, const REAL * _end_ptr)
00133         : curr_el_p(_beg_ptr),
00134           first_el_p(_beg_ptr),
00135           last_el_p(_end_ptr)
00136           {}
00137 
00138                                 // Subrange the current stream by applying
00139                                 // the range. seek_dir determines if the
00140                                 // range applies to the current state
00141                                 // of the stream or its init position
00142   AREALStreamIn(const AREALStreamIn& proto, const IRange range,
00143                 LAS::seek_dir dir)
00144         : first_el_p(proto.subrange_first(range,dir)),
00145           last_el_p(proto.subrange_last(range,dir))
00146           { curr_el_p = first_el_p;
00147             assert(first_el_p <= last_el_p); }
00148 
00149                                 // Get the current elem _ref_ and advance
00150                                 // in the stream
00151   const REAL& get_ref(void)
00152         { if( curr_el_p >= last_el_p)
00153            _error("Can't get() the AREALStream boundary!");
00154           return *curr_el_p++; }
00155   const REAL& peek_ref(void) const      // Does *not* advance the "stream ptr"
00156         { if( curr_el_p >= last_el_p)
00157            _error("Can't peek() past the AREALStream boundary!");
00158           return *curr_el_p; }
00159 
00160 public:
00161                         // No public constructors!
00162 
00163   bool eof(void) const          { return curr_el_p == last_el_p; }
00164   bool bof(void) const          { return curr_el_p == first_el_p; }
00165 
00166                                 // Get the current elem and advance in the
00167                                 // stream
00168   REAL get(void)                { return get_ref(); }
00169   REAL peek(void) const         // Does *not* advance the "stream ptr"
00170                                 { return peek_ref(); }
00171           
00172                                 // Reset the stream at the beginning
00173   void rewind(void)             { curr_el_p = first_el_p; }
00174  
00175                         // Note the current position in the stream
00176   AREALMark tell(void) const
00177         { return AREALMark(curr_el_p - first_el_p); }
00178   
00179                         // Note the previous (that is, just gotten)
00180                         // position in the stream
00181   AREALMark tell_prev(void) const
00182         { if( curr_el_p == first_el_p )
00183             _error("The stream is at its beginng, no previous pos exists");
00184           return AREALMark(curr_el_p - first_el_p - 1); }
00185  
00186                         // Set the current position at the mark
00187   AREALStreamIn& seek(const AREALMark mark)
00188         { assert( (bool) mark );
00189           curr_el_p = first_el_p + mark.offset;
00190           assert( curr_el_p >= first_el_p && curr_el_p < last_el_p );
00191           return *this; }
00192           
00193 
00194                         // Set the current position according to the
00195                         // given offset and seek_dir.
00196                         // Note: the offset can be arbitrarily large:
00197                         // if it points beyond this stream, no run-time
00198                         // error is generated but the EOF condition is set
00199                         // (which can later be checked with eof())
00200   AREALStreamIn& seek(const int offset, LAS::seek_dir dir = LAS::cur)
00201         { switch(dir)
00202           { case LAS::beg: curr_el_p = first_el_p + offset; break;
00203             case LAS::cur: curr_el_p = curr_el_p + offset; break;
00204             case LAS::end: curr_el_p = last_el_p - offset; break;
00205             default: assert(0 /*wrong seek_dir*/); };
00206           if( curr_el_p > last_el_p ) curr_el_p = last_el_p;
00207           else assert( curr_el_p >= first_el_p );
00208           return *this; }
00209           
00210   AREALStreamIn& ignore(const int how_many)
00211         { return seek(how_many,LAS::cur); }
00212  
00213                         // Dump the current status of the stream
00214   ostream& dump(ostream& os) const;
00215 };
00216 
00217                         // This is a readable _and_ writable stream
00218 class AREALStreamOut : public AREALStreamIn
00219 {
00220   AREALStreamOut(const AREALStreamOut&);  // Not implemented and forbidden:
00221   void operator = (const AREALStreamOut&);// no cloning/assignment allowed
00222 
00223 protected:
00224                                 // A protected constructor
00225   AREALStreamOut(REAL * _beg_ptr, REAL * _end_ptr)
00226         : AREALStreamIn(_beg_ptr,_end_ptr)
00227           {}
00228 
00229   AREALStreamOut(const AREALStreamIn& proto, const IRange range,
00230                 LAS::seek_dir dir)
00231         : AREALStreamIn(proto,range,dir) {}
00232 
00233 public:
00234                         // No public constructors!
00235 
00236                                 // Get the current elem and advance in the
00237                                 // stream
00238   REAL& get(void)               { return const_cast<REAL&>(get_ref()); }
00239   REAL& peek(void) const         // Does *not* advance the "stream ptr"
00240                                 { return const_cast<REAL&>(peek_ref()); }
00241           
00242                         // Dump the current status of the stream
00243 //  ostream& dump(ostream& os) const;
00244 };
00245  
00246 
00247                                 // The following class is an STL-like iterator
00248                                 // to access _values_ of Matrix elements
00249                                 // one-by-one.
00250                                 // Note this is a _read-only_ stream
00251 class LAStreamIn : protected Matrix::ConstReference,
00252                    public AREALStreamIn
00253 {
00254   LAStreamIn(const LAStreamIn&);        // Not implemented and forbidden:
00255   void operator = (const LAStreamIn&);  // no cloning/assignment allowed
00256 
00257 public:
00258   LAStreamIn(const Matrix& m)
00259         : Matrix::ConstReference(m),
00260           AREALStreamIn(m.elements,m.elements+m.nelems)
00261           {}
00262   inline LAStreamIn(const ConstMatrixColumn& mc);
00263   LAStreamIn(const LAStreamIn& ls, const IRange range,
00264             LAS::seek_dir dir = LAS::cur)
00265         : Matrix::ConstReference(ls.ref()),
00266           AREALStreamIn(ls,range,dir) {}
00267   inline LAStreamIn(const LAStreamOut& ls, const IRange range,
00268                     LAS::seek_dir dir = LAS::cur);
00269   rowcol get_pos(const AREALMark mark) const
00270           { return mark.get_2dpos(operator const Matrix& ()); }
00271 };
00272 
00273 inline LAStreamIn::LAStreamIn(const ConstMatrixColumn& mc)
00274         : Matrix::ConstReference(mc.ref()),
00275           AREALStreamIn(mc.col_ptr,mc.col_ptr+mc.nrows)
00276           {}
00277 
00278                                 // This class provides read *and* write
00279                                 // access to matrix elements, one-by-one
00280 class LAStreamOut : protected Matrix::Reference,
00281                     public AREALStreamOut
00282 {
00283   friend class LAStreamIn;
00284   LAStreamOut(const LAStreamOut&);      // Not implemented and forbidden:
00285   void operator = (const LAStreamOut&); // no cloning/assignment allowed
00286 public:
00287   LAStreamOut(Matrix& m)
00288         : Matrix::Reference(m),
00289           AREALStreamOut(m.elements,m.elements+m.nelems)
00290           {}
00291   inline LAStreamOut(const MatrixColumn& mc);
00292   LAStreamOut(const LAStreamOut& ls, const IRange range,
00293             LAS::seek_dir dir = LAS::cur)
00294         : Matrix::Reference(ls.ref()),
00295           AREALStreamOut(ls,range,dir) {}
00296   rowcol get_pos(const AREALMark mark)
00297           { return mark.get_2dpos(operator Matrix& ()); }
00298 };
00299 
00300 inline LAStreamOut::LAStreamOut(const MatrixColumn& mc)
00301         : Matrix::Reference(const_cast<Matrix&>(mc.ref())),
00302           AREALStreamOut(const_cast<REAL*>(mc.col_ptr),
00303                          const_cast<REAL*>(mc.col_ptr)+mc.q_nrows())
00304           {}
00305 
00306 inline LAStreamIn::LAStreamIn(const LAStreamOut& ls, const IRange range,
00307                     LAS::seek_dir dir)
00308         : Matrix::ConstReference(ls.ref()),
00309           AREALStreamIn(ls,range,dir) {}
00310 
00311  
00312                         // The following pair of streams are similar
00313                         // to the ones above, with an exception they
00314                         // walk a sequence of REALs with a non-unit
00315                         // stride
00316 class AREALStrideStreamIn
00317 {
00318   const REAL * curr_el_p;
00319   const REAL * const first_el_p;     // The first element pointer
00320   const REAL * const last_el_p;      // The curr_el_p >= condition means EOF
00321   const int stride;
00322 
00323   AREALStrideStreamIn(const AREALStrideStreamIn&); // Not implemented and forbidden:
00324   void operator = (const AREALStrideStreamIn&);// no cloning/assignment allowed
00325 
00326                                 // Apply range:dir to yield a new first_el_p
00327                                 // invariant: new_first_el_p >= first_el_p
00328   const REAL * subrange_first(const IRange range, LAS::seek_dir dir) const
00329   {
00330     if( dir == LAS::beg )
00331       return range.lwb <= 0 ? first_el_p : first_el_p + stride*range.lwb;
00332     else if( dir == LAS::end )
00333      if( range.lwb == - IRange::INF )
00334        return first_el_p;
00335      else
00336      { const int r = (last_el_p - first_el_p) % stride;
00337        return LAS::max(first_el_p,
00338                        (r == 0 ? last_el_p : last_el_p - r + stride)
00339                                         - range.lwb*stride); }
00340     else
00341       return range.lwb == - IRange::INF ? curr_el_p : 
00342                 LAS::max(first_el_p,curr_el_p + stride*range.lwb);
00343   }
00344 
00345                                 // Apply range:dir to yield a new last_el_p
00346                                 // invariant: new_last_el_p <= last_el_p
00347   const REAL * subrange_last(const IRange range, LAS::seek_dir dir) const
00348   {
00349     if( dir == LAS::beg )
00350       return range.upb == IRange::INF ? last_el_p : 
00351                 LAS::min(last_el_p,first_el_p + stride*(range.upb+1));
00352     else if( dir == LAS::end )
00353       return last_el_p;
00354     else
00355       return range.upb == IRange::INF ? last_el_p : 
00356                 LAS::min(last_el_p,curr_el_p + stride*(range.upb+1));
00357   }
00358  
00359 protected:
00360                                 // A protected constructor
00361   AREALStrideStreamIn(const REAL * _beg_ptr, const REAL * _end_ptr,
00362                       const int _stride)
00363         : curr_el_p(_beg_ptr),
00364           first_el_p(_beg_ptr),
00365           last_el_p(_end_ptr),
00366           stride(_stride)
00367           {}
00368 
00369                                 // Subrange the current stream by applying
00370                                 // the range. seek_dir determines if the
00371                                 // range applies to the current state
00372                                 // of the stream or its init position
00373   AREALStrideStreamIn(const AREALStrideStreamIn& proto, const IRange range,
00374                 LAS::seek_dir dir)
00375         : first_el_p(proto.subrange_first(range,dir)),
00376           last_el_p(proto.subrange_last(range,dir)),
00377           stride(proto.stride)
00378           { curr_el_p = first_el_p;
00379             assert(first_el_p <= last_el_p); }
00380 
00381                                 // Get the current elem _ref_ and advance
00382                                 // in the stream
00383   const REAL& get_ref(void)
00384         { if( curr_el_p >= last_el_p)
00385            _error("Can't get() past the AREALStrideStream boundary!");
00386           const REAL& curr = *curr_el_p;
00387           return curr_el_p += stride, curr; }
00388   const REAL& peek_ref(void) const      // Does *not* advance the "stream ptr"
00389         { if( curr_el_p >= last_el_p)
00390            _error("Can't peek() past the AREALStrideStream boundary!");
00391           return *curr_el_p; }
00392 
00393 public:
00394                         // No public constructors!
00395 
00396   bool eof(void) const          { return curr_el_p >= last_el_p; }
00397   bool bof(void) const          { return curr_el_p == first_el_p; }
00398 
00399                                 // Get the current elem and advance in the
00400                                 // stream
00401   REAL get(void)                { return get_ref(); }
00402   REAL peek(void) const         // Does *not* advance the "stream ptr"
00403                                 { return peek_ref(); }
00404           
00405                                 // Reset the stream at the beginning
00406   void rewind(void)             { curr_el_p = first_el_p; }
00407  
00408                         // Note the current position in the stream
00409   AREALMark tell(void) const
00410         { return AREALMark(curr_el_p - first_el_p); }
00411   
00412                         // Note the previous (that is, just gotten)
00413                         // position in the stream
00414   AREALMark tell_prev(void) const
00415         { if( curr_el_p == first_el_p )
00416             _error("The stream is at its beginng, no previous pos exists");
00417           return AREALMark(curr_el_p - first_el_p - stride); }
00418  
00419                         // Set the current position at the mark
00420   AREALStrideStreamIn& seek(const AREALMark mark)
00421         { assert( (bool) mark );
00422           curr_el_p = first_el_p + mark.offset;
00423           assert( curr_el_p >= first_el_p && curr_el_p < last_el_p );
00424           return *this; }
00425   
00426                         // Set the current position according to the
00427                         // given offset and seek_dir.
00428                         // Note: the offset can be arbitrarily large:
00429                         // if it points beyond this stream, no run-time
00430                         // error is generated but the EOF condition is set
00431                         // (which can later be checked with eof())
00432   AREALStrideStreamIn& seek(const int offset, LAS::seek_dir dir = LAS::cur)
00433         { switch(dir)
00434           { case LAS::beg: curr_el_p = first_el_p + offset*stride; break;
00435             case LAS::cur: curr_el_p = curr_el_p + offset*stride; break;
00436             case LAS::end: { const int r = (last_el_p - first_el_p) % stride;
00437                         curr_el_p = (r == 0 ? last_el_p : last_el_p - r + stride)
00438                                         - offset*stride; } break;
00439             default: assert(0 /*wrong seek_dir*/); };
00440           assert( curr_el_p >= first_el_p );
00441           return *this; }
00442           
00443   AREALStrideStreamIn& ignore(const int how_many)
00444         { return seek(how_many,LAS::cur); }
00445         
00446                         // Dump the current status of the stream
00447   ostream& dump(ostream& os) const;
00448 };
00449 
00450                         // This is a readable _and_ writable stream
00451 class AREALStrideStreamOut : public AREALStrideStreamIn
00452 {
00453   AREALStrideStreamOut(const AREALStrideStreamOut&);  // Not implemented and forbidden:
00454   void operator = (const AREALStrideStreamOut&);// no cloning/assignment allowed
00455 
00456 protected:
00457                                 // A protected constructor
00458   AREALStrideStreamOut(REAL * _beg_ptr, REAL * _end_ptr,
00459                        const int _stride)
00460         : AREALStrideStreamIn(_beg_ptr,_end_ptr,_stride)
00461           {}
00462 
00463 
00464   AREALStrideStreamOut(const AREALStrideStreamIn& proto, const IRange range,
00465                 LAS::seek_dir dir)
00466         : AREALStrideStreamIn(proto,range,dir) {}
00467 
00468 public:
00469                         // No public constructors!
00470 
00471                                 // Get the current elem and advance in the
00472                                 // stream
00473   REAL& get(void)               { return const_cast<REAL&>(get_ref()); }
00474   REAL& peek(void) const         // Does *not* advance the "stream ptr"
00475                                 { return const_cast<REAL&>(peek_ref()); }
00476           
00477                         // Dump the current status of the stream
00478 //  ostream& dump(ostream& os) const;
00479 };
00480  
00481 
00482 
00483                                 // LAStreams with a stride
00484 class LAStrideStreamIn : protected Matrix::ConstReference,
00485                    public AREALStrideStreamIn
00486 {
00487   LAStrideStreamIn(const LAStrideStreamIn&);    // Not implemented and forbidden:
00488   void operator = (const LAStrideStreamIn&);    // no cloning/assignment allowed
00489 
00490 public:
00491   LAStrideStreamIn(const Matrix& m, const int stride)
00492         : Matrix::ConstReference(m),
00493           AREALStrideStreamIn(m.elements,m.elements+m.nelems,stride)
00494           {}
00495   LAStrideStreamIn(const LAStrideStreamIn& ls, const IRange range,
00496             LAS::seek_dir dir = LAS::cur)
00497         : Matrix::ConstReference(ls.ref()),
00498           AREALStrideStreamIn(ls,range,dir) {}
00499  inline LAStrideStreamIn(const LAStrideStreamOut& ls, const IRange range,
00500                     LAS::seek_dir dir = LAS::cur);
00501  inline LAStrideStreamIn(const ConstMatrixRow& mr);
00502  inline LAStrideStreamIn(const ConstMatrixDiag& md);
00503  rowcol get_pos(const AREALMark mark) const
00504           { return mark.get_2dpos(operator const Matrix& ()); }
00505 };
00506 
00507 inline
00508 LAStrideStreamIn::LAStrideStreamIn(const ConstMatrixRow& mr)
00509         : Matrix::ConstReference(mr.ref()),
00510           AREALStrideStreamIn(const_cast<REAL*>(mr.row_ptr),
00511                               const_cast<REAL*>(mr.end_ptr),mr.stride) 
00512         { }
00513 inline
00514 LAStrideStreamIn::LAStrideStreamIn(const ConstMatrixDiag& md)
00515         : Matrix::ConstReference(md.ref()),
00516           AREALStrideStreamIn(const_cast<REAL*>(md.start_ptr),
00517                               const_cast<REAL*>(md.end_ptr),md.stride) 
00518         { }
00519 
00520 
00521 
00522 class LAStrideStreamOut : protected Matrix::Reference,
00523                     public AREALStrideStreamOut
00524 {
00525   friend class LAStrideStreamIn;
00526   LAStrideStreamOut(const LAStrideStreamOut&);  // Not implemented and forbidden:
00527   void operator = (const LAStrideStreamOut&);   // no cloning/assignment allowed
00528 public:
00529   LAStrideStreamOut(Matrix& m, const int stride)
00530         : Matrix::Reference(m),
00531           AREALStrideStreamOut(m.elements,m.elements+m.nelems,stride)
00532           {}
00533   LAStrideStreamOut(const LAStrideStreamOut& ls, const IRange range,
00534             LAS::seek_dir dir = LAS::cur)
00535         : Matrix::Reference(ls.ref()),
00536           AREALStrideStreamOut(ls,range,dir) {}
00537   inline LAStrideStreamOut(const MatrixRow& mr);
00538   inline LAStrideStreamOut(const MatrixDiag& md);
00539   rowcol get_pos(const AREALMark mark)
00540           { return mark.get_2dpos(operator Matrix& ()); }
00541 };
00542 
00543 inline LAStrideStreamOut::LAStrideStreamOut(const MatrixRow& mr)
00544         : Matrix::Reference(const_cast<Matrix&>(mr.ref())),
00545           AREALStrideStreamOut(const_cast<REAL*>(mr.row_ptr),
00546                               const_cast<REAL*>(mr.end_ptr),mr.stride)
00547           {}
00548 inline LAStrideStreamOut::LAStrideStreamOut(const MatrixDiag& md)
00549         : Matrix::Reference(const_cast<Matrix&>(md.ref())),
00550           AREALStrideStreamOut(const_cast<REAL*>(md.start_ptr),
00551                                const_cast<REAL*>(md.end_ptr),md.stride)
00552           {}
00553 
00554 inline LAStrideStreamIn::LAStrideStreamIn(const LAStrideStreamOut& ls, 
00555                                           const IRange range,
00556                                          LAS::seek_dir dir)
00557         : Matrix::ConstReference(ls.ref()),
00558           AREALStrideStreamIn(ls,range,dir) {}
00559 
00560 
00561 
00562 
00563 
00564                         // The following pair of streams are similar
00565                         // to the ones above, with an exception they
00566                         // sequentially walk a *block* of REALs, in
00567                         // a column major order
00568 class AREALBlockStreamIn
00569 {
00570   const REAL * curr_el_p;
00571   const REAL * const first_el_p;        // The first element pointer
00572   const REAL * const last_el_p;         // The curr_el_p >= condition means EOF
00573   const REAL * last_col_el_p;           // The end-boundary of the curr column
00574   const int col_size;                   // The size of the column in a block
00575   const int eoc_jump;                   // The amount to forward-feed the
00576                                 // curr_el_p to point at the beginning of the
00577                                 // next col once we have moved past the curr col
00578   
00579   AREALBlockStreamIn(const AREALBlockStreamIn&); // Not implemented and forbidden:
00580   void operator = (const AREALBlockStreamIn&);// no cloning/assignment allowed
00581 
00582                                 // Set curr_el_p to p and compute the
00583                                 // corresponding column boundary
00584   void set_curr_col(const REAL * const p)
00585   {
00586     curr_el_p = p;
00587     last_col_el_p = curr_el_p
00588         - ((curr_el_p - first_el_p) % (col_size + eoc_jump))
00589         + col_size;
00590   }
00591 protected:
00592                                 // A protected constructor
00593   AREALBlockStreamIn(const REAL * _beg_ptr, const REAL * _end_ptr,
00594                       const int _col_size, const int _eoc_jump)
00595         : curr_el_p(_beg_ptr),
00596           first_el_p(_beg_ptr),
00597           last_el_p(_end_ptr),
00598           last_col_el_p(_beg_ptr+_col_size),
00599           col_size(_col_size),
00600           eoc_jump(_eoc_jump)
00601           {}
00602 
00603           
00604                                 // Another protected constructor
00605   AREALBlockStreamIn(const REAL * orig_ptr, const DimSpecSubranged& clip)
00606         : first_el_p(orig_ptr + clip.q_min_offset()),
00607           last_el_p(orig_ptr + clip.q_max_offset()+1),
00608           col_size(clip.q_nrows()),
00609           eoc_jump(clip.q_row_diff())
00610           { last_col_el_p = (curr_el_p = first_el_p)  + col_size;
00611             assert(eoc_jump>=0); }
00612 
00613 
00614                                 // Get the current elem _ref_ and advance
00615                                 // in the stream
00616   const REAL& get_ref(void)
00617         { if( curr_el_p >= last_el_p)
00618            _error("Can't get() past the AREALBlockStreamIn boundary!");
00619           const REAL& curr = *curr_el_p++;
00620           if( curr_el_p >= last_col_el_p )
00621             last_col_el_p = (curr_el_p += eoc_jump) + col_size;
00622           return curr; }
00623   const REAL& peek_ref(void) const      // Does *not* advance the "stream ptr"
00624         { if( curr_el_p >= last_el_p)
00625            _error("Can't peek() past the AREALBlockStreamIn boundary!");
00626           return *curr_el_p; }
00627 public:
00628                         // No public constructors!
00629 
00630   bool eof(void) const          { return curr_el_p >= last_el_p; }
00631   bool bof(void) const          { return curr_el_p == first_el_p; }
00632 
00633                                 // Get the current elem and advance in the
00634                                 // stream
00635   REAL get(void)                { return get_ref(); }
00636   REAL peek(void) const         // Does *not* advance the "stream ptr"
00637                                 { return peek_ref(); }
00638           
00639                                 // Reset the stream at the beginning
00640   void rewind(void)
00641         { last_col_el_p = (curr_el_p = first_el_p) + col_size; }
00642  
00643                         // Note the current position in the stream
00644   AREALMark tell(void) const
00645         { return AREALMark(curr_el_p - first_el_p); }
00646   
00647                         // Note the previous (that is, just gotten)
00648                         // position in the stream
00649   AREALMark tell_prev(void) const
00650         { if( curr_el_p == first_el_p )
00651             _error("The stream is at its beginng, no previous pos exists");
00652           return AREALMark( curr_el_p - first_el_p -
00653                 ( curr_el_p + col_size > last_col_el_p ? 1
00654                          : 1 + eoc_jump)); }
00655  
00656                         // Set the current position at the mark
00657   AREALBlockStreamIn& seek(const AREALMark mark)
00658         { assert( (bool) mark );
00659           set_curr_col(first_el_p + mark.offset);
00660           assert( curr_el_p >= first_el_p && curr_el_p < last_el_p );
00661           return *this; }
00662   
00663                         // Set the current position according to the
00664                         // given offset and seek_dir.
00665                         // Note: the offset can be arbitrarily large:
00666                         // if it points beyond this stream, no run-time
00667                         // error is generated but the EOF condition is set
00668                         // (which can later be checked with eof())
00669   AREALBlockStreamIn& seek(const int offset, LAS::seek_dir dir = LAS::cur)
00670         { div_t res = div(offset,col_size);
00671           switch(dir)
00672           { case LAS::beg: curr_el_p = first_el_p + res.quot*(col_size+eoc_jump);
00673                            last_col_el_p = curr_el_p + col_size;
00674                            curr_el_p += res.rem; break;
00675             case LAS::cur: curr_el_p += res.rem;
00676                            if( curr_el_p >= last_col_el_p )
00677                                 curr_el_p += eoc_jump, last_col_el_p += col_size+eoc_jump;
00678                            curr_el_p += res.quot*(col_size+eoc_jump);
00679                            last_col_el_p += res.quot*(col_size+eoc_jump);
00680                            break;
00681             case LAS::end: last_col_el_p = last_el_p - res.quot*(col_size+eoc_jump);
00682                            curr_el_p = last_col_el_p - res.rem; break;
00683             default: assert(0 /*wrong seek_dir*/); };
00684           assert( curr_el_p >= first_el_p );
00685           return *this; }
00686           
00687   AREALBlockStreamIn& ignore(const int how_many)
00688         { return seek(how_many,LAS::cur); }
00689         
00690                         // Dump the current status of the stream
00691   ostream& dump(ostream& os) const;
00692 };
00693 
00694                         // This is a readable _and_ writable stream
00695 class AREALBlockStreamOut : public AREALBlockStreamIn
00696 {
00697   AREALBlockStreamOut(const AREALBlockStreamOut&);  // Not implemented and forbidden:
00698   void operator = (const AREALBlockStreamOut&);// no cloning/assignment allowed
00699 
00700 protected:
00701                                 // A protected constructor
00702   AREALBlockStreamOut(REAL * _beg_ptr, REAL * _end_ptr,
00703                        const int _col_size, const int _eoc_jump)
00704         : AREALBlockStreamIn(_beg_ptr,_end_ptr,_col_size,_eoc_jump)
00705           {}
00706   AREALBlockStreamOut(REAL * orig_ptr, const DimSpecSubranged& clip)
00707         : AREALBlockStreamIn(orig_ptr,clip)
00708           {}
00709 
00710 public:
00711                         // No public constructors!
00712 
00713                                 // Get the current elem and advance in the
00714                                 // stream
00715   REAL& get(void)               { return const_cast<REAL&>(get_ref()); }
00716   REAL& peek(void) const         // Does *not* advance the "stream ptr"
00717                                 { return const_cast<REAL&>(peek_ref()); }
00718           
00719 };
00720  
00721 
00722 
00723                                 // LAStreams over a sub-block of a matrix
00724 class LABlockStreamIn : protected Matrix::ConstReference,
00725                    public AREALBlockStreamIn
00726 {
00727   LABlockStreamIn(const LABlockStreamIn&);      // Not implemented and forbidden:
00728   void operator = (const LABlockStreamIn&);     // no cloning/assignment allowed
00729 
00730 public:
00731   LABlockStreamIn(const Matrix& m, const IRange row_range,
00732                   const IRange col_range)
00733         : Matrix::ConstReference(m),
00734           AREALBlockStreamIn(m.elements,DimSpecSubranged(m,row_range,col_range))
00735           {}
00736   rowcol get_pos(const AREALMark mark) const
00737           { return mark.get_2dpos(operator const Matrix& ()); }
00738 };
00739 
00740 class LABlockStreamOut : protected Matrix::Reference,
00741                     public AREALBlockStreamOut
00742 {
00743   LABlockStreamOut(const LABlockStreamOut&);    // Not implemented and forbidden:
00744   void operator = (const LABlockStreamOut&);    // no cloning/assignment allowed
00745 public:
00746   LABlockStreamOut(Matrix& m, const IRange row_range,
00747                   const IRange col_range)
00748         : Matrix::Reference(m),
00749           AREALBlockStreamOut(m.elements,DimSpecSubranged(m,row_range,col_range))
00750           {}
00751   rowcol get_pos(const AREALMark mark)
00752           { return mark.get_2dpos(operator Matrix& ()); }
00753 };
00754 
00755 #endif
00756  
00757 }

Generated on Wed Dec 15 21:20:29 2004 for vuVolume by  doxygen 1.3.9.1