```// Copyright (C) 2003  Davis E. King (davis@dlib.net)
#undef DLIB_VECTOR_ABSTRACT_
#ifdef DLIB_VECTOR_ABSTRACT_

#include "../serialize.h"
#include <functional>
#include <iostream>
#include "../matrix/matrix_abstract.h"

namespace dlib
{
template <
typename T,
long NR = 3
>
class vector : public matrix<T,NR,1>
{
/*!
REQUIREMENTS ON T
T should be some object that provides an interface that is
compatible with double, float, int, long and the like.

REQUIREMENTS ON NR
NR == 3 || NR == 2

INITIAL VALUE
x() == 0
y() == 0
z() == 0

WHAT THIS OBJECT REPRESENTS
This object represents a three dimensional vector.  If NR == 2 then
this object is limited to representing points on the XY plane where
Z is set to 0.

Also note that this object performs the appropriate integer and
floating point conversions and promotions when vectors of mixed
type are used together.  For example:
vector<int,3> vi;
vector<double,2> vd;
vd + vi == a vector<double,3> object type since that is what
is needed to contain the result of vi+vd without
any loss of information.
!*/

public:

typedef T type;

vector (
);
/*!
ensures
- #*this has been properly initialized
!*/

vector (
const T _x,
const T _y,
const T _z
);
/*!
requires
- NR == 3
ensures
- #x() == _x
- #y() == _y
- #z() == _z
!*/

vector (
const T _x,
const T _y
);
/*!
requires
- NR == 2
ensures
- #x() == _x
- #y() == _y
- #z() == 0
!*/

template <typename U, long NRv>
vector (
const vector<U,NRv>& v
);
/*!
ensures
- Initializes *this with the contents of v and does any rounding if necessary and also
takes care of converting between 2 and 3 dimensional vectors.
- if (U is a real valued type like float or double and T is an integral type like long) then
- if (NR == 3) then
- #x() == floor(v.x() + 0.5)
- #y() == floor(v.y() + 0.5)
- #z() == floor(v.z() + 0.5)
- else // NR == 2
- #x() == floor(v.x() + 0.5)
- #y() == floor(v.y() + 0.5)
- #z() == 0
- else
- if (NR == 3) then
- #x() == v.x()
- #y() == v.y()
- #z() == v.z()
- else // NR == 2
- #x() == v.x()
- #y() == v.y()
- #z() == 0
!*/

template <typename EXP>
vector (
const matrix_exp<EXP>& m
);
/*!
requires
- m.size() == NR
- m.nr() == 1 || m.nc() == 1 (i.e. m must be a row or column matrix)
ensures
- Initializes *this with the contents of m and does any rounding if necessary and also
takes care of converting between 2 and 3 dimensional vectors.
- if (m contains real valued values like float or double and T is an integral type like long) then
- #x() == floor(m(0) + 0.5)
- #y() == floor(m(1) + 0.5)
- if (NR == 3) then
- #z() == floor(m(2) + 0.5)
- else
- #z() == 0
- else
- #x() == m(0)
- #y() == m(1)
- if (NR == 3) then
- #z() == m(2)
- else
- #z() == 0
!*/

~vector (
);
/*!
ensures
- all resources associated with *this have been released
!*/

double length(
) const;
/*!
ensures
- returns the length of the vector
!*/

double length_squared(
) const;
/*!
ensures
- returns length()*length()
!*/

T& x (
);
/*!
ensures
- returns a reference to the x component of the vector
!*/

T& y (
);
/*!
ensures
- returns a reference to the y component of the vector
!*/

T& z (
);
/*!
requires
- NR == 3 (this function actually doesn't exist when NR != 3)
ensures
- returns a reference to the z component of the vector
!*/

const T& x (
) const;
/*!
ensures
- returns a const reference to the x component of the vector
!*/

const T& y (
) const;
/*!
ensures
- returns a const reference to the y component of the vector
!*/

const T& z (
) const;
/*!
ensures
- if (NR == 3) then
- returns a const reference to the z component of the vector
- else
- return 0
(there isn't really a z in this case so we just return 0)
!*/

T dot (
const vector& rhs
) const;
/*!
ensures
- returns the result of the dot product between *this and rhs
!*/

vector<T,3> cross (
const vector& rhs
) const;
/*!
ensures
- returns the result of the cross product between *this and rhs
!*/

vector<double,NR> normalize (
) const;
/*!
ensures
- returns a vector with length() == 1 and in the same direction as *this
!*/

vector operator+ (
const vector& rhs
) const;
/*!
ensures
- returns the result of adding *this to rhs
!*/

vector operator- (
const vector& rhs
) const;
/*!
ensures
- returns the result of subtracting rhs from *this
!*/

vector operator- (
) const;
/*!
ensures
- returns -1*(*this)
!*/

vector operator/ (
const T rhs
) const;
/*!
ensures
- returns the result of dividing *this by rhs
!*/

vector& operator= (
const vector& rhs
);
/*!
ensures
- #x() == rhs.x()
- #y() == rhs.y()
- #z() == rhs.z()
- returns #*this
!*/

vector& operator += (
const vector& rhs
);
/*!
ensures
- #*this == *this + rhs
- returns #*this
!*/

vector& operator -= (
const vector& rhs
);
/*!
ensures
- #*this == *this - rhs
- returns #*this
!*/

vector& operator *= (
const T rhs
);
/*!
ensures
- #*this == *this * rhs
- returns #*this
!*/

vector& operator /= (
const T rhs
);
/*!
ensures
- #*this == *this / rhs
- returns #*this
!*/

template <typename U, long NR2>
bool operator== (
const vector<U,NR2>& rhs
) const;
/*!
ensures
- if (x() == rhs.x() && y() == rhs.y() && z() == rhs.z()) then
- returns true
- else
- returns false
!*/

template <typename U, long NR2>
bool operator!= (
const vector<U,NR2>& rhs
) const;
/*!
ensures
- returns !((*this) == rhs)
!*/

void swap (
vector& item
);
/*!
ensures
- swaps *this and item
!*/

};

// ----------------------------------------------------------------------------------------

template<typename T, typename U, long NR>
vector operator* (
const vector<T,NR> & lhs,
const U rhs
);
/*!
ensures
- returns the result of multiplying the scalar rhs by lhs
!*/

template<typename T, typename U, long NR>
vector operator* (
const U lhs,
const vector<T,NR> & rhs
);
/*!
ensures
- returns the result of multiplying the scalar lhs by rhs
!*/

template<typename T, long NR>
inline void swap (
vector<T,NR> & a,
vector<T,NR> & b
) { a.swap(b); }
/*!
provides a global swap function
!*/

template<typename T, long NR>
void serialize (
const vector<T,NR>& item,
std::ostream& out
);
/*!
provides serialization support
!*/

template<typename T, long NR>
void deserialize (
vector<T,NR>& item,
std::istream& in
);
/*!
provides deserialization support
!*/

template<typename T>
std::ostream& operator<< (
std::ostream& out,
const vector<T,3>& item
);
/*!
ensures
- writes item to out in the form "(x, y, z)"
!*/

template<typename T>
std::istream& operator>>(
std::istream& in,
vector<T,3>& item
);
/*!
ensures
- reads a vector from the input stream in and stores it in #item.
The data in the input stream should be of the form (x, y, z)
!*/

template<typename T>
std::ostream& operator<< (
std::ostream& out,
const vector<T,2>& item
);
/*!
ensures
- writes item to out in the form "(x, y)"
!*/

template<typename T>
std::istream& operator>>(
std::istream& in,
vector<T,2>& item
);
/*!
ensures
- reads a vector from the input stream in and stores it in #item.
The data in the input stream should be of the form (x, y)
!*/

// ----------------------------------------------------------------------------------------

/*!A point
This is just a typedef of the vector object.
!*/

typedef vector<long,2> point;

/*!A dpoint
This is just a typedef of the vector object.
!*/

typedef vector<double,2> dpoint;

// ----------------------------------------------------------------------------------------

const std::array<dpoint,4>& pts
);
/*!
ensures
- If you walk the points in pts in order pts[0], pts[1], pts[2], pts[3], pts[0]
does it draw a convex quadrilateral?  This routine returns true if yes and
false if not.
!*/

// ----------------------------------------------------------------------------------------

template <
typename array_of_dpoints
>
double polygon_area (
const array_of_dpoints& pts
);
/*!
requires
- array_of_dpoints is something with an interface compatible with
std::vector<dpoint> or std::array<dpoint,N>.
ensures
- If you walk the points pts in order to make a closed polygon, what is its
area?  This function returns that area.  It uses the shoelace formula to
compute the result and so works for general non-self-intersecting polygons.
!*/

// ----------------------------------------------------------------------------------------

}

namespace std
{
/*!
Define std::less<vector<T,3> > so that you can use vectors in the associative containers.
!*/
template<typename T>
struct less<dlib::vector<T,3> > : public binary_function<dlib::vector<T,3> ,dlib::vector<T,3> ,bool>
{
inline bool operator() (const dlib::vector<T,3> & a, const dlib::vector<T,3> & b) const
{
if      (a.x() < b.x()) return true;
else if (a.x() > b.x()) return false;
else if (a.y() < b.y()) return true;
else if (a.y() > b.y()) return false;
else if (a.z() < b.z()) return true;
else if (a.z() > b.z()) return false;
else                    return false;
}
};

/*!
Define std::less<vector<T,2> > so that you can use vector<T,2>s in the associative containers.
!*/
template<typename T>
struct less<dlib::vector<T,2> > : public binary_function<dlib::vector<T,2> ,dlib::vector<T,2> ,bool>
{
inline bool operator() (const dlib::vector<T,2> & a, const dlib::vector<T,2> & b) const
{
if      (a.x() < b.x()) return true;
else if (a.x() > b.x()) return false;
else if (a.y() < b.y()) return true;
else if (a.y() > b.y()) return false;
else                    return false;
}
};
}

#endif // DLIB_VECTOR_ABSTRACT_

```