text: // -*- C++ -*-
  /*
   *
   * Template Numerical Toolkit (TNT)
   *
   * Mathematical and Computational Sciences Division
   * National Institute of Technology,
   * Gaithersburg, MD USA
   *
   *
   * This software was developed at the National Institute of Standards and
   * Technology (NIST) by employees of the Federal Government in the course
   * of their official duties. Pursuant to title 17 Section 105 of the
   * United States Code, this software is not subject to copyright protection
   * and is in the public domain. NIST assumes no responsibility whatsoever for
   * its use by other parties, and makes no guarantees, expressed or implied,
   * about its quality, reliability, or any other characteristic.
   *
   */
  
  #ifndef TNT_I_REFVEC_H
  #define TNT_I_REFVEC_H
  
  #include <cstdlib>
  #include <iostream>
  
  #ifdef TNT_BOUNDS_CHECK
  #include <cassert>
  #endif
  
  #ifndef NULL
  #define NULL 0
  #endif
  
  namespace TNT {
  /*
    Internal representation of ref-counted array.  The TNT
    arrays all use this building block.
  
    <p>
    If an array block is created by TNT, then every time
    an assignment is made, the left-hand-side reference
    is decreased by one, and the right-hand-side refernce
    count is increased by one.  If the array block was
    external to TNT, the refernce count is a NULL pointer
    regardless of how many references are made, since the
    memory is not freed by TNT.
  
  
  
  */
  template <class T> class i_refvec {
  
  private:
    T *data_;
    int *ref_count_;
  
  public:
    i_refvec();
    explicit i_refvec(int n);
     inline i_refvec(const T *data);
    inline i_refvec(T *data);
    inline i_refvec(const i_refvec &v);
    inline T *begin();
    inline const T *begin() const;
    inline T &operator[](int i);
    inline const T &operator[](int i) const;
    inline i_refvec<T> &operator=(const i_refvec<T> &V);
    void copy_(T *p, const T *q, const T *e);
    void set_(T *p, const T *b, const T *e);
    inline int ref_count() const;
    inline int is_null() const;
    inline void destroy();
    ~i_refvec();
  };
  
  template <class T> void i_refvec<T>::copy_(T *p, const T *q, const T *e) {
    for (T *t = p; q < e; t++, q++)
      *t = *q;
  }
  
  template <class T> i_refvec<T>::i_refvec() : data_(NULL), ref_count_(NULL) {}
  
  /**
     In case n is 0 or negative, it does NOT call new.
  */
  template <class T>
  i_refvec<T>::i_refvec(int n)
      : data_(NULL), ref_count_(NULL) {
    if (n >= 1) {
  #ifdef TNT_DEBUG
      std::cout << "new data storage.\n";
  #endif
      data_ = new T[n];
      ref_count_ = new int;
      *ref_count_ = 1;
    }
  }
  
  template <class T>
  inline i_refvec<T>::i_refvec(const i_refvec<T> &V)
      : data_(V.data_), ref_count_(V.ref_count_) {
    if (V.ref_count_ != NULL)
      (*(V.ref_count_))++;
  }
  
  template <class T>
  i_refvec<T>::i_refvec(const T *data)
      : data_(const_cast<T*>(data)), ref_count_(NULL) {}
  
  template <class T>
  i_refvec<T>::i_refvec(T *data)
      : data_(data), ref_count_(NULL) {}
  
  template <class T> inline T *i_refvec<T>::begin() { return data_; }
  
  template <class T> inline const T &i_refvec<T>::operator[](int i) const {
    return data_[i];
  }
  
  template <class T> inline T &i_refvec<T>::operator[](int i) { return data_[i]; }
  
  template <class T> inline const T *i_refvec<T>::begin() const { return data_; }
  
  template <class T> i_refvec<T> &i_refvec<T>::operator=(const i_refvec<T> &V) {
    if (this == &V)
      return *this;
  
    if (ref_count_ != NULL) {
      (*ref_count_)--;
      if ((*ref_count_) == 0)
        destroy();
    }
  
    data_ = V.data_;
    ref_count_ = V.ref_count_;
  
    if (V.ref_count_ != NULL)
      (*(V.ref_count_))++;
  
    return *this;
  }
  
  template <class T> void i_refvec<T>::destroy() {
    if (ref_count_ != NULL) {
  #ifdef TNT_DEBUG
      std::cout << "destorying data... \n";
  #endif
      delete ref_count_;
  
  #ifdef TNT_DEBUG
      std::cout << "deleted ref_count_ ...\n";
  #endif
      if (data_ != NULL)
        delete[] data_;
  #ifdef TNT_DEBUG
      std::cout << "deleted data_[] ...\n";
  #endif
      data_ = NULL;
    }
  }
  
  /*
   * return 1 is vector is empty, 0 otherwise
   *
   * if is_null() is false and ref_count() is 0, then
   *
   */
  template <class T> int i_refvec<T>::is_null() const {
    return (data_ == NULL ? 1 : 0);
  }
  
  /*
   *  returns -1 if data is external,
   *  returns 0 if a is NULL array,
   *  otherwise returns the positive number of vectors sharing
   *  		this data space.
   */
  template <class T> int i_refvec<T>::ref_count() const {
    if (data_ == NULL)
      return 0;
    return (ref_count_ != NULL ? *ref_count_ : -1);
  }
  
  template <class T> i_refvec<T>::~i_refvec() {
    if (ref_count_ != NULL) {
      (*ref_count_)--;
  
      if (*ref_count_ == 0)
        destroy();
    }
  }
  
  } /* namespace TNT */
  
  #endif
  /* TNT_I_REFVEC_H */
  