/*******************************************************************************
+
+  LEDA 3.5
+
+  vector.h
+
+  This file is part of the LEDA research version (LEDA-R) that can be 
+  used free of charge in academic research and teaching. Any commercial
+  use of this software requires a license which is distributed by the
+  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
+  (fax +49 681 31104).
+
+  Copyright (c) 1991-1997  by  Max-Planck-Institut fuer Informatik
+  Im Stadtwald, 66123 Saarbruecken, Germany     
+  All rights reserved.
+ 
*******************************************************************************/
#ifndef LEDA_VECTOR_H
#define LEDA_VECTOR_H

#if !defined(LEDA_ROOT_INCL_ID)
#define LEDA_ROOT_INCL_ID 350135
#include <LEDA/REDEFINE_NAMES.h>
#endif


//------------------------------------------------------------------------------
//  vectors
//------------------------------------------------------------------------------

#include <LEDA/basic.h>


/*{\Manpage {vector} {} {Real-Valued Vectors}}*/

class vector
{

/*{\Mdefinition
An instance of data type |vector| is a vector of variables of type |double|.}*/

  friend class matrix;

  double* v;
  int d;

  void check_dimensions(const vector&) const;
 
public:

/*{\Mcreation v }*/

vector(); 
/*{\Mcreate creates an instance $v$ of type $vector$; $v$ is initialized to 
            the zero-dimensional vector.}*/

vector(int d); 
/*{\Mcreate creates an instance $v$ of type $vector$; $v$ is initialized to 
            the zero vector of dimension $d$.}*/ 

vector(double a, double b);
/*{\Mcreate creates an instance $v$ of type $vector$; $v$ is initialized to 
            the two-dimensional vector $(a,b)$.}*/

vector(double a, double b, double c);
/*{\Mcreate creates an instance $v$ of type $vector$; $v$ is initialized to 
            the three-dimensional vector $(a,b,c)$.}*/

  vector(const vector&);
 ~vector(); 
  vector& operator=(const vector&);


/*{\Moperations 2 4.5}*/

int    dim()    const { return d; }
/*{\Mop       returns the dimension of $v$.}*/ 

  
double& operator[](int i);
/*{\Marrop     returns $i$-th component of $v$.\\
	       \precond $0\le i \le v$.dim()$-$1.}*/
  
double  operator[](int) const;

double  hcoord(int i) const { return (i<d) ? (*this)[i] : 1; }
/*{\Xop for compatibility with |rat_vector|. }*/

double  coord(int i)  const { return (*this)[i]; }
/*{\Xop for compatibility with |rat_vector|. }*/


double sqr_length() const;
/*{\Mop      returns the square of the Euclidean length of $v$.}*/

double length() const;
/*{\Mop      returns the Euclidean length of $v$.}*/
  
vector norm() const { return *this/length(); }
/*{\Mop      returns |\Mvar| normalized. }*/
  
double angle(const vector& w) const; 
/*{\Mop     returns the angle between $v$ and $w$.}*/

vector rotate90() const;
/*{\Mop     returns the |\Mvar| rotated by 90 degrees.
	    \precond $v.dim() = 2$}*/


vector rotate(double a) const;
/*{\Mop     returns the |\Mvar| rotated by an angle of $a$.
	    \precond $v.dim() = 2$}*/

vector& operator+=(const vector&);
vector& operator-=(const vector&);
  
vector  operator+(const vector& v1) const;
/*{\Mbinop     Addition.\\
	       \precond $v$.dim() = $v1$.dim().}*/

vector  operator-(const vector& v1) const;
/*{\Mbinop     Subtraction.\\
	       \precond $v$.dim() = $v1$.dim().}*/

double  operator*(const vector& v1) const;
/*{\Mbinop     Scalar multiplication.\\
               \precond $v$.dim() = $v1$.dim().}*/

vector  operator*(double r)        const;
/*{\Mbinop     Componentwise multiplication with double $r$.}*/

vector  operator-() const;
vector  operator/(double)        const;
  
bool     operator==(const vector& w) const;
/*{\Mbinop     Test for equality.}*/

bool     operator!=(const vector& w)  const { return !(*this == w); }
/*{\Mbinop     Test for inequality.}*/

friend vector operator*(double f, const vector& v) { return v *f; }

void print(ostream& O);
/*{\Mop  prints $v$ componentwise to ostream $O$. }*/

void print() { print(cout); }
/*{\Mop  prints $v$ to $cout$. }*/

void read(istream& I);
/*{\Mop  reads $d = |v.dim()|$ numbers from input stream $I$ and writes 
         them into $v[0] \dots v[d-1]$.}*/

void read() { read(cin); }
/*{\Mop  reads $v$ from $cin$. }*/
  
friend ostream& operator<<(ostream& O, const vector& v);
/*{\Mbinopfunc  writes $v$ componentwise to the output stream $O$.}*/

friend istream& operator>>(istream& I, vector& v);
/*{\Mbinopfunc  reads $v$ componentwise from the input stream $I$.}*/

LEDA_MEMORY(vector)

};


inline char* leda_tname(const vector*) { return "vector"; }


/*{\Mimplementation
Vectors are implemented by arrays of real numbers. All operations on a vector 
$v$ take time $O(v.dim())$, except for dim and $[\ ]$ which take constant
time. The space requirement is $O(v.dim())$.

Be aware that the operations on vectors and matrices incur rounding errors and
hence are not completely reliable. For example, if $M$ is a matrix, $b$ is a
vector, and $x$ is computed by |x = M.solve(b)| it is not necessarily true that
the test |b == M * b| evaluates to true. The types |integer_vector| and |integer_matrix| provide exact linear algebra.
}*/


#if LEDA_ROOT_INCL_ID == 350135
#undef LEDA_ROOT_INCL_ID
#include <LEDA/UNDEFINE_NAMES.h>
#endif

#endif
