///////////////////////////////////////////////////////////////////////////////////////////////////
// OpenGL Mathematics Copyright (c) 2005 - 2008 G-Truc Creation (www.g-truc.net)
///////////////////////////////////////////////////////////////////////////////////////////////////
// Created : 2005-12-21
// Updated : 2008-07-24
// Licence : This source is under MIT License
// File    : glm/gtx/norm.h
///////////////////////////////////////////////////////////////////////////////////////////////////
// Dependency:
// - GLM core
// - GLM_GTX_quaternion
// - GLM_GTX_double
///////////////////////////////////////////////////////////////////////////////////////////////////
// ToDo:
// - Study the validity of the notion of length2 to quaternion
///////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef glm_gtx_norm
#define glm_gtx_norm

// Dependency:
#include "../../glm.h"
#include "../gtx/double_float.h"
#include "../gtx/quaternion.h"

namespace glm
{
    template <typename T> T length2GTX(const T x);
    template <typename T> T length2GTX(const detail::tvec2<T>& x);
    template <typename T> T length2GTX(const detail::tvec3<T>& x);
    template <typename T> T length2GTX(const detail::tvec4<T>& x);
    template <typename T> T length2GTX(const detail::tquat<T>& q);

    template <typename T> T distance2GTX(const T p0, const T p1);
    template <typename T> T distance2GTX(const detail::tvec2<T>& p0, const detail::tvec2<T>& p1);
    template <typename T> T distance2GTX(const detail::tvec3<T>& p0, const detail::tvec3<T>& p1);
    template <typename T> T distance2GTX(const detail::tvec4<T>& p0, const detail::tvec4<T>& p1);

	template <typename T> T l1NormGTX(const detail::tvec3<T>& x, const detail::tvec3<T>& y);
	template <typename T> T l1NormGTX(const detail::tvec3<T>& v);
	template <typename T> T l2NormGTX(const detail::tvec3<T>& x, const detail::tvec3<T>& y);
	template <typename T> T l2NormGTX(const detail::tvec3<T>& v);
	template <typename T> T lxNormGTX(const detail::tvec3<T>& x, const detail::tvec3<T>& y, unsigned int Depth);
	template <typename T> T lxNormGTX(const detail::tvec3<T>& x, unsigned int Depth);

    namespace gtx
    {
		//! GLM_GTX_norm extension: Varius way to compute vector norms.
        namespace norm
        {
            template <typename T> inline T length2(const T x){return length2GTX(x);}												//!< \brief Returns the squared length of x (from GLM_GTX_norm extension)
            template <typename T> inline T length2(const detail::tvec2<T>& x){return length2GTX(x);}								//!< \brief Returns the squared length of x (from GLM_GTX_norm extension)
            template <typename T> inline T length2(const detail::tvec3<T>& x){return length2GTX(x);}								//!< \brief Returns the squared length of x (from GLM_GTX_norm extension)
            template <typename T> inline T length2(const detail::tvec4<T>& x){return length2GTX(x);}								//!< \brief Returns the squared length of x (from GLM_GTX_norm extension)
            template <typename T> inline T length2(const detail::tquat<T>& q){return length2GTX(q);}								//!< \brief Returns the squared length of x (from GLM_GTX_norm extension)

			template <typename T> inline T distance2(const T p0, const T p1){return distance2GTX(p0, p1);}										//!< \brief Returns the squared distance between p0 and p1, i.e., length(p0 - p1). (From GLSL 1.10.59 specification)
			template <typename T> inline T distance2(const detail::tvec2<T>& p0, const detail::tvec2<T>& p1){return distance2GTX(p0, p1);}	//!< \brief Returns the squared distance between p0 and p1, i.e., length(p0 - p1). (From GLSL 1.10.59 specification)
			template <typename T> inline T distance2(const detail::tvec3<T>& p0, const detail::tvec3<T>& p1){return distance2GTX(p0, p1);}	//!< \brief Returns the squared distance between p0 and p1, i.e., length(p0 - p1). (From GLSL 1.10.59 specification)
			template <typename T> inline T distance2(const detail::tvec4<T>& p0, const detail::tvec4<T>& p1){return distance2GTX(p0, p1);}	//!< \brief Returns the squared distance between p0 and p1, i.e., length(p0 - p1). (From GLSL 1.10.59 specification)

			template <typename T> inline T l1Norm(const detail::tvec3<T>& x, const detail::tvec3<T>& y){return l1NormGTX(x, y);}		//!< \brief Returns the L1 norm between x and y (from GLM_GTX_norm extension)
			template <typename T> inline T l1Norm(const detail::tvec3<T>& v){return l1NormGTX(v);}										//!< \brief Returns the L1 norm of v (from GLM_GTX_norm extension)
			template <typename T> inline T l2Norm(const detail::tvec3<T>& x, const detail::tvec3<T>& y){return l2NormGTX(x, y);}		//!< \brief Returns the L2 norm between x and y (from GLM_GTX_norm extension)
			template <typename T> inline T l2Norm(const detail::tvec3<T>& x){return l2NormGTX(x);}									    //!< \brief Returns the L2 norm of v (from GLM_GTX_norm extension)
			template <typename T> inline T lxNorm(const detail::tvec3<T>& x, const detail::tvec3<T>& y, unsigned int Depth){return lxNormGTX(x, y, Depth);}	//!< \brief Returns the L norm between x and y (from GLM_GTX_norm extension)
			template <typename T> inline T lxNorm(const detail::tvec3<T>& x, unsigned int Depth){return lxNormGTX(x, Depth);}								    //!< \brief Returns the L norm of v (from GLM_GTX_norm extension)
        }
    }
}

#define GLM_GTX_norm namespace gtx::norm

#include "norm.inl"

#endif//glm_gtx_norm
