/* vector.cc */

#include "vector.h"

void dc_vector::touch( void ) {
  valid = ( val.Nrows() != 0 );
}

dc_vector::dc_vector() {
  valid = false;
}

dc_vector::dc_vector( const int n, const string &label, 
		      dc_node *parent = nil) {
  resize( n );
  set_both( label, parent );
  touch();
}

dc_vector::dc_vector( const ColumnVector &V, const string &label, 
		      dc_node *parent = nil ) {
  set( V );
  set_both( label, parent );
}

dc_vector::dc_vector( const string &label, dc_node *parent = nil ) {
  valid = false;
  set_both( label, parent );
}

dc_vector::~dc_vector() {
  val.CleanUp();
}

dc_vector &dc_vector::operator=( const ColumnVector &V ) {
  val = V;
  touch();
  return *this;
}

dc_vector &dc_vector::operator=( const RowVector &V ) {
  set_row( V );
  return *this;
}

dc_vector &dc_vector::operator=( dc_data &D ) {
  if( D.sub_type() != Vector_t ) {
    cerr << "dc_vector::operator= -- Cannot assign " << D.full_type()
	 << " to " << full_type() << "\n";
    exit( 1 );
  }
  val = ( ( dc_vector * )&D )->get();
  touch();
  if( D.is_temporary() ) delete( &D );
  return *this;
}

ostream &dc_vector::display_c( ostream &stream = cout ) const {
  if( !( is_valid() ) ) {
    return stream << full_type(); /* add trailing newline since normal
				     vector out does */
  } else {
    Real *d = get_store();
    int n = val.Storage();
    stream << "{ ";
    for( int i = 0 ; i < n - 1 ; stream << d[i++] << ", " );
    stream << d[n-1];
    return stream << " }" << units;
  }
}

istream &operator>>( istream &stream, dc_vector &V ) {
  if( !V.is_valid() ) {
    cerr << "dc_vector::operator>> -- invalid operation on " 
	 << V.full_type() << "\n";
    exit(1);
  }
  int area = ( ( ColumnVector )V.get() ).Storage();
  double *n = ( ( ColumnVector )V.get() ).Store();
  for( int i = 0 ; i < area ; i++ ){
     stream >> n[i];
  }
  
  V.set( n );
  return stream;
}

ReturnMatrix dc_vector::get( void ) {
  if( !valid ) {
    cerr << "dc_vector::get -- invalid operation on " << full_type() 
	 << "\n";
    exit(1);
  }

  return val;
}

ReturnMatrix dc_vector::get_as_row( void ) {
  if( !valid ) {
    cerr << "dc_vector::get_T -- invalid operation on " << full_type() 
	 << "\n";
    exit(1);
  }

  RowVector R = val.AsRow();
  return R.ForReturn();
}

void dc_vector::set( const ColumnVector &V ) {
  val = V;
  touch();
}

void dc_vector::set_row( const RowVector &V ) {
  val = V.AsColumn();
  touch();
}

void dc_vector::set( dc_vector &D ) {
  val = D.get();
  touch();
}

void dc_vector::set( const double n[] ) {
  val << n;
  touch();
}

void dc_vector::resize( const int d ) {
  val.ReDimension( d );
  touch();
}

dc_label *dc_vector::duplicate( dc_node *parent ) const {
  dc_vector *dupe = new dc_vector( val );
  dupe->set_units( get_units_c() );
  if( !is_temporary() ) {
    if( dupe->set_both( local_label(), parent ) ) {
      delete( dupe );
      return nil;
    }
  }
  dupe->set_visible( is_visible() );
  return ( dc_label * )dupe;
}
