\chapter{Virtual Vector of Doubles}

The virtual matrix class is derived from a class of a
vector of doubles stored in the virtual memory system. The
virtual vector gives the matrix class access to the virtual
memory. Holub\cite{Ho:pr} developed a class of integer
vectors with a set of overloaded operators. He created the
class to ease access to the vmm, and demonstrate several
aspects of using classes. Here, the integer class was
rewritten for doubles, and the operators were stripped in
favor of using them on the matrices.

Again, the virtual vector should be considered another
intermediate step in creating the virtual matrix class. It is
not needed in the in-ram version, since matrices are allocated
on the heap. Instead a structure is used to store a vector
allocated by calloc, and the number of references to the
structure. This will be explaned in more detail in the chapter
on the stack.

\section{vdoub}
The virtual vector of doubles\index{vdoub } is declared in
the following class statement

\begin{verbatim}
class vdoub{

  protected:
  
    unsigned signature;// garbage flag;
    hdr *hdr;          // virtual memory handle
    double *cur_ele;   // current element
    long  cur_index;   // current index
    //static int nobj;

    friend double val( vdoub &v);
  
  public:
  
    int Garbage( void ){ return  !( signature == SIGNATURE ); }

    vdoub ( long array_size );
    vdoub ( void );
    vdoub ( vdoub &src );
    ~vdoub( void );

    double v( long index );          // get value
    vdoub& operator[]( long index ); // store value
    double operator = ( double d );
    double operator = ( vdoub &v );
};
\end{verbatim}

Note that the access to the vmm is in a protected section
of the definition. The matrix class needs access to some of
these elements. 

\subsection{Protected Part of a vdoub}
The signature is a garbage flag. It is set to zero when the
vector is deleted. It also serves as a check for the front of
the class being overwritten by rogue functions. The hdr is
a pointer to a vmm header created by vmalloc. 

The cur\_ele is a pointer to the current element being
addressed in the virtual vector. The cur\_index is the index
of the current index in the vector. Note the index is a
long, so index operations must be cast on long integers.  
These two variables help control which buffer is stored in
the vmem of the hdr. The member function val() returns the
current value.

The static integer, nobj, counts the number of active
vectors. If it is zero, then the vmm system is initialized
in the constructors. The constructors increment nobj and
the destructors decrement nobj.

The in-ram version\index{vdoub!IN-RAM vdoub} also sets up a
virtual vector structure, but its memory is allocated entirely
on the heap. The structure is
\begin{verbatim}
typedef struct vdoub{
    int nrefs;
    double HUGE_POINTER *mm;
} vdoub;
\end{verbatim}
The variable, nrefs, stores the number of references to this
vector. The vector pointer *mm is not freed until nrefs is zero.
Note this is a typedef instead of class, so the in-ram virtual
matrix is not derived from vdoub. Also note that mm is now a
vector of huge double pointers. When using Microsoft C/C++ 7.0,
HUGE\_POINTER is replaced by \_\_huge, and it is replaced by far in
Borland C++. If you port the IN\_RAM version to other compilers,
HUGE\_POINTER\index{vdoub!HUGE\_POINTER} is defined as blank. You
can redefine it if you compiler has problems releasing large
blocks of memory when the pointer type of mm is undeclared.
(This occured in an early release of MSC7.0).

\subsection{Public Parts of a vdoub}
The public functions give access to the vmm. The function
Garbage()\index{vdoub!Garbage()} simply checks if the signature is
correct. This indicates that the vdoub is likely intact and
active. 

The constructors\index{vdoub!constructors} accept void,
long or vdoub\&  arguments.  The default constructor
accepts a void. It allocates a hdr on the vmm with one
double. The second constructor does the same, but the hdr
contains array\_size elements. The constructor with a vdoub
reference argument copies one vdoub into another. Each
constructor increments nobj, and calls
vopen()\index{vmm!vopen()} if nobj is zero.

The destructor\index{vdoub!destructor} frees the header. If
the hdr is freed with error, the system stops. Otherwise,
the signature is set to zero and nobj is decremented. If
nobj is decremented to zero, then vclose()\index{vmm!vclose()}
is called. Note that this does not guarantee that vclose()
will be called when the program leaves the main() function
because some virtual matrices are constructed outside of
the scope of main(). The matrix stack dispatcher is a
pointer to the base of a stack of matrices. It is allocated
outside of the function main() so it will not be destroyed
upon leaving main().  Thus, vclose() must be called before
leaving main(). The next time the destructor is called,
vfree() will return an error so the program will exit
through the last destructor call.

The function v()\index{vdoub!v()} gets the value at index.
It calls vread() and returns the value. It also sets
cur\_index to index, and stores the current value in
*cur\_ele. Note that the call to vread() may change the
page the buffer in vmem.

The brackets operator\index{vdoub![] operator} provides
the same function as v(), but you can use the vector
notation to do it. However it is basically very different
than accessing an element on the heap, or some offset from
a pointer base. The call to vread() shifts a new page into
RAM if necessary. The normal use of the brackets operator
just accesses RAM. This has side effects in the assignment
operation on virtual vectors.

The difference between v() and the brackets operator is
they have different return types. v() returns a double and
vdoub::operator[] returns a reference to another vdoub. To
quote Holub: 
\begin{quote}
The brackets operator is a {\em selector } operator. It
sets things up so that the next operation can access the
array element selected by the previous bracket. If the {\em
next} operation modifies the array element, then that
operation sets the dirty bit.
\end{quote}  

\section{Assignment in vdoub} 

Assignment\index{vdoub!=} takes two forms for virtual vectors. The problem
is to make the code work for saying \verb+ vect[i] = 5+ or
for saying \verb+ vect1 = vect2+. The first form of
assignment is 
\begin{verbatim}
double vdoub::operator = ( double d )
  {
    if ( Garbage() ) {
      perror("VMS assignment error, source is Garbage(=)");
      exit(1);
    }
    *cur_ele = d;
    vdirty( hdr );
    return d;
  }
\end{verbatim}

The functional form of \verb+ vect[i] = 5+ is 
\verb+ (vect.operator[](i)).operator=(5)+. First the
brackets operator is called, which sets the current index
to i.  Since the bracket operator returns a reference to a
vdoub, the vdoub::operator=(5) is called.  The current
element of the returned vdoub is set to 5. Next the buffer
is declared dirty, and the 5 is returned.

The other form of assignment copies a double vector to
another. It disposes the left operand hdr if it already
exists, then allocates a new hdr. Then it copies the
contents from v to the new hdr. The code is given by

\begin{verbatim}
double vdoub::operator = ( vdoub &v)
// copy vector v to vector t
  {
     if( v.Garbage() ){
       perror("VMS copy error, source is Garbage");
       exit(1);
     }
    if( !Garbage() ) vfree( hdr ); // replace hdr if t is active

    double *p;
    long numele = vele( v.hdr );
    signature = SIGNATURE;
    *cur_ele = *v.cur_ele;
    cur_index = v.cur_index;
    
    if ( !(hdr = vmalloc( numele, sizeof( double )))) {
      perror(" VMS copy allocation error");
      exit(1);
    }
    while( --numele >= 0 ) {
      if ( !(p = (double *) vread( v.hdr, numele))){
        perror("VMS copy-access( read ) error");
        exit(1);
      }
      if (!vwrite(hdr, numele,(char *)p)){
        perror("VMS copy-access( write ) error");
        exit(1);
      }
    }
    return *cur_ele;
  }
\end{verbatim}

This code fragment really emphasizes how well the vdoub
class insulates the user from the vmm system. You don't
have to remember all of the arguments for vread, vwrite,
and vmalloc. You also have a good deal of error checking
embedded in the assignment operators.