/*
    ChemCon - molecular mechanics and molecular graphics
    Copyright (C) 1998-2002  Alexei Nikitin

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "vect.h"
#include "Mach_eps.h"

#include <math.h>

const Vector & Vector::operator = ( const Vector & r )
  {
    if( this != &r )
      {
        x_ = r.x_;  
        y_ = r.y_;  
        z_ = r.z_;
      }
    return *this;
  }

Vector Vector::operator / ( const real a ) const
  {
    return Vector( x_ / a, y_ / a, z_ / a );
  }

Vector & Vector::operator /= ( const real a )
  {
    x_ /= a; y_ /= a; z_ /= a;
    return * this;
  }

real  length2( const Vector & v)
  { 
    return v.x_ * v.x_ + v.y_ * v.y_ + v.z_ * v.z_; 
  }

real  Vector::length() const
  {  
    return sqrt( x_ * x_ + y_ * y_ + z_ * z_ ); 
  }
real  length( const Vector & v )
  {  
    return sqrt( v.x_ * v.x_ + v.y_ * v.y_ + v.z_ * v.z_ ); 
  }
Vector::operator real() const
  { 
    return sqrt( x_ * x_ + y_ * y_ + z_ * z_ ); 
  }

Vector  Vector::norm()
  {
  //fix to k=1/mod
   real  n = sqrt( x_ * x_ + y_ * y_ + z_ * z_ ) + d_mach_eps_2;
   return  Vector( x_ / n, y_ / n, z_ / n );
  }
Vector   norm( const Vector & v )
  {
   real  n = sqrt( v.x_ * v.x_ + v.y_ * v.y_ + v.z_ * v.z_ ) + d_mach_eps_2;
   return  Vector( v.x_ / n, v.y_ / n, v.z_ / n );
  }

Vector & Vector::operator ( ) ( )
  {
   real a = sqrt( x_ * x_ + y_ * y_ + z_ * z_ ) + d_mach_eps_2;
   x_ /= a; y_ /= a; z_ /= a;
   return * this;
  }

Vector  Vector::
rotate( const Vector & W )
  {
    real ang = W;
    if ( ang == 0.0 ) return *this;
    Vector W1 = W / ang;
    Vector C = W1 * operator ^ ( W1 );
    Vector B = operator - ( C );
    Vector L = W1 * B;
    return  B * (real)cos( ang ) + L * (real)sin( ang ) + C;
  }

Vector  Vector::
rotate( const Vector & v, const Vector & v0 )
  {
    Vector tmp = *this - v0;
    tmp =  tmp.rotate( v );
    tmp += v0;
    return tmp;
  }
/*
ostream& operator << ( ostream& out, const Vector& V )
  {
    return out << setw(2) << "( "<< V.x_ << " " << V.y_ << " " << V.z_ << " )" ;
  }
*/
