//#####################################################################
// Copyright 2013.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class ZERO_VECTOR
//##################################################################### 
#ifndef __ZERO_VECTOR__
#define __ZERO_VECTOR__

#include <Core/Math_Tools/FIXED_NUMBER.h>
#include <Core/Utilities/TYPE_UTILITIES.h>
#include <Core/Vectors/VECTOR.h>
#include <cmath>
namespace PhysBAM{

template<class T,int d>
class ZERO_VECTOR
{
public:
    static constexpr int m=d;
    static constexpr int fixed_m=d;
    static constexpr bool is_zero=true;
    static constexpr int type=vec_zero;
    typedef T SCALAR;

    int Size() const
    {return d;}

    FIXED_NUMBER<T,0> operator[](const int i) const
    {return {};}

    FIXED_NUMBER<T,0> operator()(const int i) const
    {return {};}

    ZERO_VECTOR operator+() const
    {return *this;}

    ZERO_VECTOR operator-() const
    {return *this;}

    ZERO_VECTOR operator+(const ZERO_VECTOR&) const
    {return *this;}

    ZERO_VECTOR operator-(const ZERO_VECTOR&) const
    {return *this;}

    ZERO_VECTOR operator*(const T&) const
    {return *this;}

    ZERO_VECTOR operator/(const T&) const
    {return *this;}

    template<class A,class R=enable_if_t<IS_VECTOR<A>::value>>
    FIXED_NUMBER<T,0> Dot(const A&) const
    {return FIXED_NUMBER<T,0>();}

    template<class A,int p=decltype(VECTOR<T,m>().Cross(VECTOR<T,A::m>()))::m>
    ZERO_VECTOR<T,p> Cross(const A&) const
    {return {};}
};

template<class T,int d> VECTOR<T,d> operator+=(const VECTOR<T,d>& v,const ZERO_VECTOR<T,d>& z){return v;}

template<class T,int d> VECTOR<T,d> operator+ (const ZERO_VECTOR<T,d>& z,const VECTOR<T,d>& v) {return v;}
template<class T,int d> VECTOR<T,d> operator+ (const VECTOR<T,d>& v,const ZERO_VECTOR<T,d>& z) {return v;}
template<class T,int d> VECTOR<T,d> operator- (const ZERO_VECTOR<T,d>& z,const VECTOR<T,d>& v) {return -v;}
template<class T,int d> VECTOR<T,d> operator- (const VECTOR<T,d>& v,const ZERO_VECTOR<T,d>& z) {return v;}
template<class T,int d> ZERO_VECTOR<T,d> operator* (const VECTOR<T,d>& v,const ZERO_VECTOR<T,d>& z) {return z;}
template<class T,int d> ZERO_VECTOR<T,d> operator* (const ZERO_VECTOR<T,d>& z,const VECTOR<T,d>& v) {return z;}
template<class T,int d> ZERO_VECTOR<T,d> operator* (const ZERO_VECTOR<T,d>& y,const ZERO_VECTOR<T,d>& z) {return z;}

template<class T,int d> VECTOR<T,d> operator+ (const ZERO_VECTOR<T,d>& z,const ARRAY<T>& v) {return VECTOR<T,d>(v);}
template<class T,int d> VECTOR<T,d> operator+ (const ARRAY<T>& v,const ZERO_VECTOR<T,d>& z) {return VECTOR<T,d>(v);}
template<class T,int d> VECTOR<T,d> operator- (const ZERO_VECTOR<T,d>& z,const ARRAY<T>& v) {return -VECTOR<T,d>(v);}
template<class T,int d> VECTOR<T,d> operator- (const ARRAY<T>& v,const ZERO_VECTOR<T,d>& z) {return VECTOR<T,d>(v);}
template<class T,int d> ZERO_VECTOR<T,d> operator* (const ARRAY<T>& v,const ZERO_VECTOR<T,d>& z) {return z;}
template<class T,int d> ZERO_VECTOR<T,d> operator* (const ZERO_VECTOR<T,d>& z,const ARRAY<T>& v) {return z;}

template<class T,int d> void Fill_From(VECTOR<T,d>& m,const ZERO_VECTOR<T,d>& z){m=VECTOR<T,d>();}

template<class T,int d> void Fill_From(ZERO_VECTOR<T,d>& m,const ZERO_VECTOR<T,d>& z){}

template<class T_VEC> enable_if_t<IS_VECTOR<T_VEC>::value,T_VEC> Choose(const T_VEC& a,const T_VEC& b);
template<class T,int d,class T_VEC> T_VEC Choose(const T_VEC& a,const ZERO_VECTOR<T,d>& b);
template<class T,int d,class T_VEC> T_VEC Choose(const ZERO_VECTOR<T,d>& a,const T_VEC& b);
template<class T,int d> ZERO_VECTOR<T,d> Choose(const ZERO_VECTOR<T,d>& a,const ZERO_VECTOR<T,d>& b);

template<class T,int d> inline ZERO_VECTOR<T,d> operator*(const FIXED_NUMBER<T,0>,const VECTOR<T,d>&) {return ZERO_VECTOR<T,d>();}
template<class T,int d> inline ZERO_VECTOR<T,d> operator/(const FIXED_NUMBER<T,0>,const VECTOR<T,d>&) {return ZERO_VECTOR<T,d>();}
template<class T,int d> inline ZERO_VECTOR<T,d> operator*(const VECTOR<T,d>&,const FIXED_NUMBER<T,0>) {return ZERO_VECTOR<T,d>();}

template<class T,int d> inline enable_if_t<is_same<SCALAR_TYPE<T>,T>::value,ZERO_VECTOR<T,d> > operator*(ND<T>,const ZERO_VECTOR<T,d>&) {return ZERO_VECTOR<T,d>();}

template<class T> ZERO_VECTOR<T,3> Cross_Product(const ZERO_VECTOR<T,3>&,const ZERO_VECTOR<T,3>&){return ZERO_VECTOR<T,3>();}
template<class T> ZERO_VECTOR<T,3> Cross_Product(const ZERO_VECTOR<T,3>&,const VECTOR<T,3>&){return ZERO_VECTOR<T,3>();}
template<class T> ZERO_VECTOR<T,3> Cross_Product(const VECTOR<T,3>&,const ZERO_VECTOR<T,3>&){return ZERO_VECTOR<T,3>();}
template<class T> VECTOR<T,3> Cross_Product(const VECTOR<T,3>& a,const VECTOR<T,3>& b){return a.Cross(b);}

template<class T,int n> bool operator==(const ZERO_VECTOR<T,n>&,const ZERO_VECTOR<T,n>&){return true;}

template<class T,int n> bool operator==(const ZERO_VECTOR<T,n>& a,const ARRAY<T>& b)
{return b.m==n && b.Contains_Only(0);}

template<class T,int n> bool operator==(const ARRAY<T>& b,const ZERO_VECTOR<T,n>& a)
{return b.m==n && b.Contains_Only(0);}

template<class T,int n> bool operator==(const ZERO_VECTOR<T,n>& a,const VECTOR<T,n>& b)
{return b.Contains_Only(0);}

template<class T,int n> bool operator==(const VECTOR<T,n>& b,const ZERO_VECTOR<T,n>& a)
{return b.Contains_Only(0);}

}
#endif
