/* triple.cc */

#include "triple.h"

dc_triple::dc_triple( const double x = 0, const double y = 0, 
		      const double z = 0 ) {
  val.ReDimension( 3 );
  val(1) = x;
  val(2) = y;
  val(3) = z;
  valid = true;
}

dc_triple::dc_triple( const double x, const double y, const double z, 
		      const string &label, dc_node *parent = nil) {
  dc_triple::dc_triple( x, y, z );
  set_both( label, parent );
}

dc_triple::dc_triple( const string &label, dc_node *parent = nil ) {
  val.ReDimension( 3 );
  val( 1 ) = val( 2 ) = val( 3 ) = 0;
  valid = true;
  set_both( label, parent );
}

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

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

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

ostream &dc_triple::display_c( ostream &stream = cout ) const {
  if( !( is_valid() ) ) {
    return stream << full_type() << "\n"; /* add trailing newline since normal
					       vector out does */
  } else {
    return stream << "( " << val(1) << ", " << val(2) << ", " << val(3) << " )"
		  << units;
  }
}

istream &operator>>( istream &stream, dc_triple &T ) {
  if( !T.is_valid() ) {
    cerr << "dc_triple::operator>> -- invalid operation on " 
	 << T.full_type() << "\n";
    exit(1);
  }
  double *n = ( ( ColumnVector )T.get() ).Store();
  stream >> n[0] >> n[1] >> n[2];
  T.set( n );
  return stream;
}

ReturnMatrix dc_triple::get( void ) {
  return val;
}

ReturnMatrix dc_triple::get_as_row( void ) {
  RowVector R = val.AsRow();
  return R.ForReturn();
}

void dc_triple::set( const ColumnVector &V ) {
  if( V.Nrows() != 3 ) {
    cerr << "dc_triple::set -- cannot set " << full_type() 
      << " to ColumnVector of length " << V.Nrows() << "\n";
    valid = false;
    return;
  }
  val = V;
  valid = true;
}

void dc_triple::set_row( const RowVector &V ) {
  if( V.Ncols() != 3 ) {
    cerr << "dc_triple::set_row -- cannot set " << full_type()
      << " to RowVector of length " << V.Ncols() << "\n";
    valid = false;
    return;
  }
  val = V.AsColumn();
  valid = true;
}

void dc_triple::set( dc_triple &D ) {
  if( D.is_valid() ) {
    val = D.get();
    valid = true;
  } else valid = false;
}

void dc_triple::set( double n[] ) {
  val << n;
  valid = true;
}

dc_label *dc_triple::duplicate( dc_node *parent ) const {
  dc_triple *dupe = new dc_triple( 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;
}
