Browse Source

Merge branch '0.9.3' into swizzle

Christophe Riccio 14 years ago
parent
commit
dc7d8f5c0c

+ 159 - 0
glm/core/_vectorize.hpp

@@ -0,0 +1,159 @@
+///////////////////////////////////////////////////////////////////////////////////
+/// OpenGL Mathematics (glm.g-truc.net)
+///
+/// Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net)
+/// Permission is hereby granted, free of charge, to any person obtaining a copy
+/// of this software and associated documentation files (the "Software"), to deal
+/// in the Software without restriction, including without limitation the rights
+/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+/// copies of the Software, and to permit persons to whom the Software is
+/// furnished to do so, subject to the following conditions:
+/// 
+/// The above copyright notice and this permission notice shall be included in
+/// all copies or substantial portions of the Software.
+/// 
+/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+/// THE SOFTWARE.
+///
+/// @ref core
+/// @file glm/core/_vectorize.hpp
+/// @date 2011-10-14 / 2011-10-14
+/// @author Christophe Riccio
+///////////////////////////////////////////////////////////////////////////////////
+
+#define VECTORIZE2_VEC(func) \
+    template <typename T> \
+    GLM_FUNC_QUALIFIER detail::tvec2<T> func( \
+		detail::tvec2<T> const & v) \
+    { \
+        return detail::tvec2<T>( \
+            func(v.x), \
+            func(v.y)); \
+    }
+
+#define VECTORIZE3_VEC(func) \
+    template <typename T> \
+    GLM_FUNC_QUALIFIER detail::tvec3<T> func( \
+		detail::tvec3<T> const & v) \
+    { \
+        return detail::tvec3<T>( \
+            func(v.x), \
+            func(v.y), \
+            func(v.z)); \
+    }
+
+#define VECTORIZE4_VEC(func) \
+    template <typename T> \
+    GLM_FUNC_QUALIFIER detail::tvec4<T> func( \
+		detail::tvec4<T> const & v) \
+    { \
+        return detail::tvec4<T>( \
+            func(v.x), \
+            func(v.y), \
+            func(v.z), \
+            func(v.w)); \
+    }
+
+#define VECTORIZE_VEC(func) \
+	VECTORIZE2_VEC(func) \
+	VECTORIZE3_VEC(func) \
+	VECTORIZE4_VEC(func)
+
+#define VECTORIZE2_VEC_SCA(func) \
+    template <typename T> \
+    GLM_FUNC_QUALIFIER detail::tvec2<T> func \
+	( \
+		detail::tvec2<T> const & x,  \
+		typename detail::tvec2<T>::value_type const & y \
+	) \
+    { \
+        return detail::tvec2<T>( \
+            func(x.x, y), \
+            func(x.y, y)); \
+    }
+
+#define VECTORIZE3_VEC_SCA(func) \
+    template <typename T> \
+    GLM_FUNC_QUALIFIER detail::tvec3<T> func \
+	( \
+		detail::tvec3<T> const & x,  \
+		typename detail::tvec3<T>::value_type const & y \
+	) \
+    { \
+        return detail::tvec3<T>( \
+            func(x.x, y), \
+            func(x.y, y), \
+            func(x.z, y)); \
+    }
+
+#define VECTORIZE4_VEC_SCA(func) \
+    template <typename T> \
+    GLM_FUNC_QUALIFIER detail::tvec4<T> func \
+	( \
+		detail::tvec4<T> const & x,  \
+		typename detail::tvec4<T>::value_type const & y \
+	) \
+    { \
+        return detail::tvec4<T>( \
+            func(x.x, y), \
+            func(x.y, y), \
+            func(x.z, y), \
+            func(x.w, y)); \
+    }
+
+#define VECTORIZE_VEC_SCA(func) \
+	VECTORIZE2_VEC_SCA(func) \
+	VECTORIZE3_VEC_SCA(func) \
+	VECTORIZE4_VEC_SCA(func)
+
+#define VECTORIZE2_VEC_VEC(func) \
+    template <typename T> \
+    GLM_FUNC_QUALIFIER detail::tvec2<T> func \
+	( \
+		detail::tvec2<T> const & x,  \
+		detail::tvec2<T> const & y \
+	) \
+    { \
+        return detail::tvec2<T>( \
+            func(x.x, y.x), \
+            func(x.y, y.y)); \
+    }
+
+#define VECTORIZE3_VEC_VEC(func) \
+    template <typename T> \
+    GLM_FUNC_QUALIFIER detail::tvec3<T> func \
+	( \
+		detail::tvec3<T> const & x,  \
+		detail::tvec3<T> const & y \
+	) \
+    { \
+        return detail::tvec3<T>( \
+            func(x.x, y.x), \
+            func(x.y, y.y), \
+            func(x.z, y.z)); \
+    }
+
+#define VECTORIZE4_VEC_VEC(func) \
+    template <typename T> \
+    GLM_FUNC_QUALIFIER detail::tvec4<T> func \
+	( \
+		detail::tvec4<T> const & x,  \
+		detail::tvec4<T> const & y \
+	) \
+    { \
+        return detail::tvec4<T>( \
+            func(x.x, y.x), \
+            func(x.y, y.y), \
+            func(x.z, y.z), \
+            func(x.w, y.w)); \
+    }
+
+#define VECTORIZE_VEC_VEC(func) \
+	VECTORIZE2_VEC_VEC(func) \
+	VECTORIZE3_VEC_VEC(func) \
+	VECTORIZE4_VEC_VEC(func)

+ 36 - 477
glm/core/func_common.inl

@@ -26,6 +26,8 @@
 /// @author Christophe Riccio
 /// @author Christophe Riccio
 ///////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////
 
 
+#include "_vectorize.hpp"
+
 namespace glm{
 namespace glm{
 namespace detail
 namespace detail
 {
 {
@@ -60,56 +62,23 @@ namespace detail
 
 
 	// abs
 	// abs
 	template <typename genFIType>
 	template <typename genFIType>
-    GLM_FUNC_QUALIFIER genFIType abs(
-		genFIType const & x)
+    GLM_FUNC_QUALIFIER genFIType abs
+	(
+		genFIType const & x
+	)
     {
     {
 		return detail::Abs_<genFIType, std::numeric_limits<genFIType>::is_signed>::get(x);
 		return detail::Abs_<genFIType, std::numeric_limits<genFIType>::is_signed>::get(x);
     }
     }
 
 
-	//template <typename T> 
-	//GLM_FUNC_QUALIFIER detail::tvec1<T> abs(
-	//	detail::tvec1<T> const & v)
-	//{
-	//	return detail::tvec1<T>(
-	//		abs(v.x));	
-	//}
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> abs(
-		detail::tvec2<T> const & v)
-    {
-        return detail::tvec2<T>(
-            abs(v.x),
-            abs(v.y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> abs(
-		detail::tvec3<T> const & v)
-    {
-        return detail::tvec3<T>(
-            abs(v.x),
-            abs(v.y),
-            abs(v.z));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> abs(
-		detail::tvec4<T> const & v)
-    {
-        return detail::tvec4<T>(
-            abs(v.x),
-            abs(v.y),
-            abs(v.z),
-            abs(v.w));
-    }
+	VECTORIZE_VEC(abs)
 
 
     // sign
     // sign
-
 	//Try something like based on x >> 31 to get the sign bit
 	//Try something like based on x >> 31 to get the sign bit
     template <typename genFIType> 
     template <typename genFIType> 
-	GLM_FUNC_QUALIFIER genFIType sign(
-		genFIType const & x)
+	GLM_FUNC_QUALIFIER genFIType sign
+	(
+		genFIType const & x
+	)
 	{
 	{
 		GLM_STATIC_ASSERT(
 		GLM_STATIC_ASSERT(
 			detail::type<genFIType>::is_float || 
 			detail::type<genFIType>::is_float || 
@@ -125,35 +94,7 @@ namespace detail
         return result;
         return result;
 	}
 	}
 	
 	
-    template <typename valFIType>
-    GLM_FUNC_QUALIFIER detail::tvec2<valFIType> sign(
-		detail::tvec2<valFIType> const & x)
-    {
-        return detail::tvec2<valFIType>(
-            sign(x.x),
-            sign(x.y));
-    }
-
-    template <typename valFIType>
-    GLM_FUNC_QUALIFIER detail::tvec3<valFIType> sign(
-		detail::tvec3<valFIType> const & x)
-    {
-        return detail::tvec3<valFIType>(
-            sign(x.x),
-            sign(x.y),
-            sign(x.z));
-    }
-
-    template <typename valFIType>
-    GLM_FUNC_QUALIFIER detail::tvec4<valFIType> sign(
-		detail::tvec4<valFIType> const & x)
-    {
-        return detail::tvec4<valFIType>(
-            sign(x.x),
-            sign(x.y),
-            sign(x.z),
-            sign(x.w));
-    }
+	VECTORIZE_VEC(sign)
 
 
     // floor
     // floor
     template <>
     template <>
@@ -170,32 +111,7 @@ namespace detail
         return ::std::floor(x);
         return ::std::floor(x);
     }
     }
 
 
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec2<valType> floor(detail::tvec2<valType> const& x)
-    {
-        return detail::tvec2<valType>(
-            floor(x.x),
-            floor(x.y));
-    }
-
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec3<valType> floor(detail::tvec3<valType> const& x)
-    {
-        return detail::tvec3<valType>(
-            floor(x.x),
-            floor(x.y),
-            floor(x.z));
-    }
-
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec4<valType> floor(detail::tvec4<valType> const& x)
-    {
-        return detail::tvec4<valType>(
-            floor(x.x),
-            floor(x.y),
-            floor(x.z),
-            floor(x.w));
-    }
+	VECTORIZE_VEC(floor)
 
 
     // trunc
     // trunc
     template <typename genType>
     template <typename genType>
@@ -205,32 +121,7 @@ namespace detail
         return x < 0 ? -floor(-x) : floor(x);
         return x < 0 ? -floor(-x) : floor(x);
     }
     }
 
 
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec2<valType> trunc(detail::tvec2<valType> const & x)
-    {
-        return detail::tvec2<valType>(
-            trunc(x.x),
-            trunc(x.y));
-    }
-
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec3<valType> trunc(detail::tvec3<valType> const & x)
-    {
-        return detail::tvec3<valType>(
-            trunc(x.x),
-            trunc(x.y),
-            trunc(x.z));
-    }
-
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec4<valType> trunc(detail::tvec4<valType> const & x)
-    {
-        return detail::tvec4<valType>(
-            trunc(x.x),
-            trunc(x.y),
-            trunc(x.z),
-            trunc(x.w));
-    }
+	VECTORIZE_VEC(trunc)
 
 
     // round
     // round
     template <typename genType>
     template <typename genType>
@@ -243,32 +134,8 @@ namespace detail
 		return genType(int(x + genType(0.5)));
 		return genType(int(x + genType(0.5)));
     }
     }
 
 
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec2<valType> round(detail::tvec2<valType> const& x)
-    {
-        return detail::tvec2<valType>(
-            round(x.x),
-            round(x.y));
-    }
-
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec3<valType> round(detail::tvec3<valType> const& x)
-    {
-        return detail::tvec3<valType>(
-            round(x.x),
-            round(x.y),
-            round(x.z));
-    }
+	VECTORIZE_VEC(round)
 
 
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec4<valType> round(detail::tvec4<valType> const& x)
-    {
-        return detail::tvec4<valType>(
-            round(x.x),
-            round(x.y),
-            round(x.z),
-            round(x.w));
-    }
 /*
 /*
     // roundEven
     // roundEven
     template <typename genType>
     template <typename genType>
@@ -294,32 +161,7 @@ namespace detail
 		return genType(int(x + RoundValue));
 		return genType(int(x + RoundValue));
     }
     }
 	
 	
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec2<valType> roundEven(detail::tvec2<valType> const& x)
-    {
-        return detail::tvec2<valType>(
-            roundEven(x.x),
-            roundEven(x.y));
-    }
-
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec3<valType> roundEven(detail::tvec3<valType> const& x)
-    {
-        return detail::tvec3<valType>(
-            roundEven(x.x),
-            roundEven(x.y),
-            roundEven(x.z));
-    }
-
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec4<valType> roundEven(detail::tvec4<valType> const& x)
-    {
-        return detail::tvec4<valType>(
-            roundEven(x.x),
-            roundEven(x.y),
-            roundEven(x.z),
-            roundEven(x.w));
-    }
+	VECTORIZE_VEC(roundEven)
 
 
     // ceil
     // ceil
     template <typename genType>
     template <typename genType>
@@ -330,32 +172,7 @@ namespace detail
         return ::std::ceil(x);
         return ::std::ceil(x);
     }
     }
 
 
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec2<valType> ceil(detail::tvec2<valType> const & x)
-    {
-        return detail::tvec2<valType>(
-            ceil(x.x),
-            ceil(x.y));
-    }
-
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec3<valType> ceil(detail::tvec3<valType> const & x)
-    {
-        return detail::tvec3<valType>(
-            ceil(x.x),
-            ceil(x.y),
-            ceil(x.z));
-    }
-
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec4<valType> ceil(detail::tvec4<valType> const & x)
-    {
-        return detail::tvec4<valType>(
-            ceil(x.x),
-            ceil(x.y),
-            ceil(x.z),
-            ceil(x.w));
-    }
+	VECTORIZE_VEC(ceil)
 
 
     // fract
     // fract
     template <typename genType>
     template <typename genType>
@@ -369,41 +186,7 @@ namespace detail
         return x - ::std::floor(x);
         return x - ::std::floor(x);
     }
     }
 
 
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec2<valType> fract
-	(
-		detail::tvec2<valType> const & x
-	)
-    {
-        return detail::tvec2<valType>(
-            fract(x.x),
-            fract(x.y));
-    }
-
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec3<valType> fract
-	(
-		detail::tvec3<valType> const & x
-	)
-    {
-        return detail::tvec3<valType>(
-            fract(x.x),
-            fract(x.y),
-            fract(x.z));
-    }
-
-    template <typename valType>
-    GLM_FUNC_QUALIFIER detail::tvec4<valType> fract
-	(
-		detail::tvec4<valType> const & x
-	)
-    {
-        return detail::tvec4<valType>(
-            fract(x.x),
-            fract(x.y),
-            fract(x.z),
-            fract(x.w));
-    }
+	VECTORIZE_VEC(fract)
 
 
     // mod
     // mod
     template <typename genType>
     template <typename genType>
@@ -418,83 +201,8 @@ namespace detail
         return x - y * floor(x / y);
         return x - y * floor(x / y);
     }
     }
 
 
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> mod
-	(
-		detail::tvec2<T> const & x, 
-		typename detail::tvec2<T>::value_type const & y
-	)
-    {
-        return detail::tvec2<T>(
-            mod(x.x, y),
-            mod(x.y, y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> mod
-	(
-		detail::tvec3<T> const & x, 
-		typename detail::tvec3<T>::value_type const & y
-	)
-    {
-        return detail::tvec3<T>(
-            mod(x.x, y),
-            mod(x.y, y),
-            mod(x.z, y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> mod
-	(
-		detail::tvec4<T> const & x, 
-		typename detail::tvec4<T>::value_type const & y
-	)
-    {
-        return detail::tvec4<T>(
-            mod(x.x, y),
-            mod(x.y, y),
-            mod(x.z, y),
-            mod(x.w, y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> mod
-	(
-		detail::tvec2<T> const & x, 
-		detail::tvec2<T> const & y
-	)
-    {
-        return detail::tvec2<T>(
-            mod(x.x, y.x),
-            mod(x.y, y.y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> mod
-	(
-		detail::tvec3<T> const & x, 
-		detail::tvec3<T> const & y
-	)
-    {
-        return detail::tvec3<T>(
-            mod(x.x, y.x),
-            mod(x.y, y.y),
-            mod(x.z, y.z));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> mod
-	(
-		detail::tvec4<T> const & x, 
-		detail::tvec4<T> const & y
-	)
-    {
-        return detail::tvec4<T>(
-            mod(x.x, y.x),
-            mod(x.y, y.y),
-            mod(x.z, y.z),
-            mod(x.w, y.w));
-    }
+	VECTORIZE_VEC_SCA(mod)
+	VECTORIZE_VEC_VEC(mod)
 
 
     // modf
     // modf
     template <typename genType>
     template <typename genType>
@@ -515,39 +223,39 @@ namespace detail
     GLM_FUNC_QUALIFIER detail::tvec2<valType> modf
     GLM_FUNC_QUALIFIER detail::tvec2<valType> modf
 	(
 	(
 		detail::tvec2<valType> const & x, 
 		detail::tvec2<valType> const & x, 
-		detail::tvec2<valType> const & y
+		detail::tvec2<valType> & i
 	)
 	)
     {
     {
         return detail::tvec2<valType>(
         return detail::tvec2<valType>(
-            modf(x.x, y.x),
-            modf(x.y, y.y));
+            modf(x.x, i.x),
+            modf(x.y, i.y));
     }
     }
 
 
     template <typename valType>
     template <typename valType>
     GLM_FUNC_QUALIFIER detail::tvec3<valType> modf
     GLM_FUNC_QUALIFIER detail::tvec3<valType> modf
 	(
 	(
 		detail::tvec3<valType> const & x, 
 		detail::tvec3<valType> const & x, 
-		detail::tvec3<valType> const & y
+		detail::tvec3<valType> & i
 	)
 	)
     {
     {
         return detail::tvec3<valType>(
         return detail::tvec3<valType>(
-            modf(x.x, y.x),
-            modf(x.y, y.y),
-            modf(x.z, y.z));
+            modf(x.x, i.x),
+            modf(x.y, i.y),
+            modf(x.z, i.z));
     }
     }
 
 
     template <typename valType>
     template <typename valType>
     GLM_FUNC_QUALIFIER detail::tvec4<valType> modf
     GLM_FUNC_QUALIFIER detail::tvec4<valType> modf
 	(
 	(
 		detail::tvec4<valType> const & x, 
 		detail::tvec4<valType> const & x, 
-		detail::tvec4<valType> const & y
+		detail::tvec4<valType> & i
 	)
 	)
     {
     {
         return detail::tvec4<valType>(
         return detail::tvec4<valType>(
-            modf(x.x, y.x),
-            modf(x.y, y.y),
-            modf(x.z, y.z),
-            modf(x.w, y.w));
+            modf(x.x, i.x),
+            modf(x.y, i.y),
+            modf(x.z, i.z),
+            modf(x.w, i.w));
     }
     }
 
 
 	//// Only valid if (INT_MIN <= x-y <= INT_MAX)
 	//// Only valid if (INT_MIN <= x-y <= INT_MAX)
@@ -574,83 +282,8 @@ namespace detail
         return x < y ? x : y;
         return x < y ? x : y;
     }
     }
 
 
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> min
-	(
-		detail::tvec2<T> const & x, 
-		typename detail::tvec2<T>::value_type const & y
-	)
-    {
-        return detail::tvec2<T>(
-            min(x.x, y),
-            min(x.y, y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> min
-	(
-		detail::tvec3<T> const & x, 
-		typename detail::tvec3<T>::value_type const & y
-	)
-    {
-        return detail::tvec3<T>(
-            min(x.x, y),
-            min(x.y, y),
-            min(x.z, y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> min
-	(
-		detail::tvec4<T> const & x, 
-		typename detail::tvec4<T>::value_type const & y
-	)
-    {
-        return detail::tvec4<T>(
-            min(x.x, y),
-            min(x.y, y),
-            min(x.z, y),
-            min(x.w, y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> min
-	(
-		detail::tvec2<T> const & x, 
-		detail::tvec2<T> const & y
-	)
-    {
-        return detail::tvec2<T>(
-            min(x.x, y.x),
-            min(x.y, y.y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> min
-	(
-		detail::tvec3<T> const & x, 
-		detail::tvec3<T> const & y
-	)
-    {
-        return detail::tvec3<T>(
-            min(x.x, y.x),
-            min(x.y, y.y),
-            min(x.z, y.z));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> min
-	(
-		detail::tvec4<T> const & x, 
-		detail::tvec4<T> const & y
-	)
-    {
-        return detail::tvec4<T>(
-            min(x.x, y.x),
-            min(x.y, y.y),
-            min(x.z, y.z),
-            min(x.w, y.w));
-    }
+	VECTORIZE_VEC_SCA(min)
+	VECTORIZE_VEC_VEC(min)
 
 
     // max
     // max
     template <typename genType>
     template <typename genType>
@@ -668,82 +301,8 @@ namespace detail
 		return x > y ? x : y;
 		return x > y ? x : y;
     }
     }
 
 
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> max
-	(
-		detail::tvec2<T> const & x, 
-		typename detail::tvec2<T>::value_type y
-	)
-    {
-        return detail::tvec2<T>(
-            max(x.x, y),
-            max(x.y, y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> max
-	(
-		detail::tvec3<T> const & x, 
-		typename detail::tvec3<T>::value_type y
-	)
-    {
-        return detail::tvec3<T>(
-            max(x.x, y),
-            max(x.y, y),
-            max(x.z, y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> max
-	(
-		detail::tvec4<T> const & x, 
-		typename detail::tvec4<T>::value_type y
-	)
-    {
-        return detail::tvec4<T>(
-            max(x.x, y),
-            max(x.y, y),
-            max(x.z, y),
-            max(x.w, y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> max
-	(
-		detail::tvec2<T> const & x, 
-		detail::tvec2<T> const & y
-	)
-    {
-        return detail::tvec2<T>(
-            max(x.x, y.x),
-            max(x.y, y.y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> max
-	(
-		detail::tvec3<T> const & x, 
-		detail::tvec3<T> const & y
-	)
-    {
-        return detail::tvec3<T>(
-            max(x.x, y.x),
-            max(x.y, y.y),
-            max(x.z, y.z));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> max
-	(
-		detail::tvec4<T> const & x, 
-		detail::tvec4<T> const & y)
-    {
-        return detail::tvec4<T>(
-            max(x.x, y.x),
-            max(x.y, y.y),
-            max(x.z, y.z),
-            max(x.w, y.w));
-    }
+	VECTORIZE_VEC_SCA(max)
+	VECTORIZE_VEC_VEC(max)
 
 
     // clamp
     // clamp
     template <typename valType>
     template <typename valType>

+ 11 - 249
glm/core/func_exponential.inl

@@ -26,6 +26,8 @@
 /// @author Christophe Riccio
 /// @author Christophe Riccio
 ///////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////
 
 
+#include "_vectorize.hpp"
+
 namespace glm
 namespace glm
 {
 {
     // pow
     // pow
@@ -41,44 +43,7 @@ namespace glm
         return ::std::pow(x, y);
         return ::std::pow(x, y);
     }
     }
 
 
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> pow
-	(
-		detail::tvec2<T> const & x, 
-		detail::tvec2<T> const & y
-	)
-    {
-        return detail::tvec2<T>(
-            pow(x.x, y.x),
-            pow(x.y, y.y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> pow
-	(
-		detail::tvec3<T> const & x, 
-		detail::tvec3<T> const & y
-	)
-    {
-        return detail::tvec3<T>(
-            pow(x.x, y.x),
-            pow(x.y, y.y),
-            pow(x.z, y.z));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> pow
-	(
-		detail::tvec4<T> const & x, 
-		detail::tvec4<T> const & y
-	)
-    {
-        return detail::tvec4<T>(
-            pow(x.x, y.x),
-            pow(x.y, y.y),
-            pow(x.z, y.z),
-            pow(x.w, y.w));
-    }
+	VECTORIZE_VEC_VEC(pow)
 
 
     // exp
     // exp
     template <typename genType>
     template <typename genType>
@@ -92,41 +57,7 @@ namespace glm
         return ::std::exp(x);
         return ::std::exp(x);
     }
     }
 
 
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> exp
-	(
-		detail::tvec2<T> const & x
-	)
-    {
-        return detail::tvec2<T>(
-            exp(x.x),
-            exp(x.y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> exp
-	(
-		detail::tvec3<T> const & x
-	)
-    {
-        return detail::tvec3<T>(
-            exp(x.x),
-            exp(x.y),
-            exp(x.z));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> exp
-	(
-		detail::tvec4<T> const & x
-	)
-    {
-        return detail::tvec4<T>(
-            exp(x.x),
-            exp(x.y),
-            exp(x.z),
-            exp(x.w));
-    }
+	VECTORIZE_VEC(exp)
 
 
     // log
     // log
     template <typename genType>
     template <typename genType>
@@ -140,41 +71,7 @@ namespace glm
         return ::std::log(x);
         return ::std::log(x);
     }
     }
 
 
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> log
-	(
-		detail::tvec2<T> const & x
-	)
-    {
-        return detail::tvec2<T>(
-            log(x.x),
-            log(x.y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> log
-	(
-		detail::tvec3<T> const & x
-	)
-    {
-        return detail::tvec3<T>(
-            log(x.x),
-            log(x.y),
-            log(x.z));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> log
-	(
-		detail::tvec4<T> const & x
-	)
-    {
-        return detail::tvec4<T>(
-            log(x.x),
-            log(x.y),
-            log(x.z),
-            log(x.w));
-    }
+	VECTORIZE_VEC(log)
 
 
     //exp2, ln2 = 0.69314718055994530941723212145818f
     //exp2, ln2 = 0.69314718055994530941723212145818f
     template <typename genType>
     template <typename genType>
@@ -188,41 +85,7 @@ namespace glm
         return ::std::exp(genType(0.69314718055994530941723212145818) * x);
         return ::std::exp(genType(0.69314718055994530941723212145818) * x);
     }
     }
 
 
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> exp2
-	(
-		detail::tvec2<T> const & x
-	)
-    {
-        return detail::tvec2<T>(
-            exp2(x.x),
-            exp2(x.y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> exp2
-	(
-		detail::tvec3<T> const & x
-	)
-    {
-        return detail::tvec3<T>(
-            exp2(x.x),
-            exp2(x.y),
-            exp2(x.z));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> exp2
-	(
-		detail::tvec4<T> const & x
-	)
-    {
-        return detail::tvec4<T>(
-            exp2(x.x),
-            exp2(x.y),
-            exp2(x.z),
-            exp2(x.w));
-    }
+	VECTORIZE_VEC(exp2)
 
 
 namespace detail
 namespace detail
 {
 {
@@ -232,7 +95,7 @@ namespace detail
 		template <typename T>
 		template <typename T>
 		T operator() (T const & Value) const
 		T operator() (T const & Value) const
 		{
 		{
-			static_assert(0, "'log2' parameter has an invalid template parameter type");
+			GLM_STATIC_ASSERT(0, "'log2' parameter has an invalid template parameter type. GLM core features only supports floating-point types, include <glm/gtx/integer.hpp> for integer types support. Others types are not supported.");
 			return Value;
 			return Value;
 		}
 		}
 	};
 	};
@@ -255,44 +118,11 @@ namespace detail
 		genType const & x
 		genType const & x
 	)
 	)
     {
     {
+		assert(x > genType(0)); // log2 is only defined on the range (0, inf]
 		return detail::compute_log2<detail::float_or_int_trait<genType>::ID>()(x);
 		return detail::compute_log2<detail::float_or_int_trait<genType>::ID>()(x);
     }
     }
 
 
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> log2
-	(
-		detail::tvec2<T> const & x
-	)
-    {
-        return detail::tvec2<T>(
-            log2(x.x),
-            log2(x.y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> log2
-	(
-		detail::tvec3<T> const & x
-	)
-    {
-        return detail::tvec3<T>(
-            log2(x.x),
-            log2(x.y),
-            log2(x.z));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> log2
-	(
-		detail::tvec4<T> const & x
-	)
-    {
-        return detail::tvec4<T>(
-            log2(x.x),
-            log2(x.y),
-            log2(x.z),
-            log2(x.w));
-    }
+	VECTORIZE_VEC(log2)
 
 
     // sqrt
     // sqrt
     template <typename genType>
     template <typename genType>
@@ -306,41 +136,7 @@ namespace detail
         return genType(::std::sqrt(x));
         return genType(::std::sqrt(x));
     }
     }
 
 
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> sqrt
-	(
-		detail::tvec2<T> const & x
-	)
-    {
-        return detail::tvec2<T>(
-            glm::sqrt(x.x),
-            glm::sqrt(x.y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> sqrt
-	(
-		detail::tvec3<T> const & x
-	)
-    {
-        return detail::tvec3<T>(
-            glm::sqrt(x.x),
-            glm::sqrt(x.y),
-            glm::sqrt(x.z));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> sqrt
-	(
-		detail::tvec4<T> const & x
-	)
-    {
-        return detail::tvec4<T>(
-            glm::sqrt(x.x),
-            glm::sqrt(x.y),
-            glm::sqrt(x.z),
-            glm::sqrt(x.w));
-    }
+	VECTORIZE_VEC(sqrt)
 
 
     template <typename genType>
     template <typename genType>
     GLM_FUNC_QUALIFIER genType inversesqrt
     GLM_FUNC_QUALIFIER genType inversesqrt
@@ -353,40 +149,6 @@ namespace detail
         return genType(1) / ::std::sqrt(x);
         return genType(1) / ::std::sqrt(x);
     }
     }
 
 
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec2<T> inversesqrt
-	(
-		detail::tvec2<T> const & x
-	)
-    {
-        return detail::tvec2<T>(
-            inversesqrt(x.x),
-            inversesqrt(x.y));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec3<T> inversesqrt
-	(
-		detail::tvec3<T> const & x
-	)
-    {
-        return detail::tvec3<T>(
-            inversesqrt(x.x),
-            inversesqrt(x.y),
-            inversesqrt(x.z));
-    }
-
-    template <typename T>
-    GLM_FUNC_QUALIFIER detail::tvec4<T> inversesqrt
-	(
-		detail::tvec4<T> const & x
-	)
-    {
-        return detail::tvec4<T>(
-            inversesqrt(x.x),
-            inversesqrt(x.y),
-            inversesqrt(x.z),
-            inversesqrt(x.w));
-    }
+	VECTORIZE_VEC(inversesqrt)
 
 
 }//namespace glm
 }//namespace glm

+ 2 - 0
glm/core/func_geometric.inl

@@ -26,6 +26,8 @@
 /// @author Christophe Riccio
 /// @author Christophe Riccio
 ///////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////
 
 
+#include "_vectorize.hpp"
+
 namespace glm
 namespace glm
 {
 {
     // length
     // length

+ 2 - 35
glm/core/func_integer.inl

@@ -26,6 +26,7 @@
 /// @author Christophe Riccio
 /// @author Christophe Riccio
 ///////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////
 
 
+#include "_vectorize.hpp"
 #if(GLM_COMPILER & GLM_COMPILER_VC)
 #if(GLM_COMPILER & GLM_COMPILER_VC)
 #include <intrin.h>
 #include <intrin.h>
 #pragma intrinsic(_BitScanReverse)
 #pragma intrinsic(_BitScanReverse)
@@ -415,41 +416,7 @@ namespace glm
 		return Out;
 		return Out;
 	}	
 	}	
 
 
-	template <typename T>
-	GLM_FUNC_QUALIFIER detail::tvec2<T> bitfieldReverse
-	(
-		detail::tvec2<T> const & value
-	)
-	{
-		return detail::tvec2<T>(
-			bitfieldReverse(value[0]),
-			bitfieldReverse(value[1]));
-	}
-
-	template <typename T>
-	GLM_FUNC_QUALIFIER detail::tvec3<T> bitfieldReverse
-	(
-		detail::tvec3<T> const & value
-	)
-	{
-		return detail::tvec3<T>(
-			bitfieldReverse(value[0]),
-			bitfieldReverse(value[1]),
-			bitfieldReverse(value[2]));
-	}
-
-	template <typename T>
-	GLM_FUNC_QUALIFIER detail::tvec4<T> bitfieldReverse
-	(
-		detail::tvec4<T> const & value
-	)
-	{
-		return detail::tvec4<T>(
-			bitfieldReverse(value[0]),
-			bitfieldReverse(value[1]),
-			bitfieldReverse(value[2]),
-			bitfieldReverse(value[3]));
-	}
+	VECTORIZE_VEC(bitfieldReverse)
 
 
 	// bitCount
 	// bitCount
 	template <typename genIUType>
 	template <typename genIUType>

+ 2 - 0
glm/core/func_matrix.inl

@@ -26,6 +26,8 @@
 /// @author Christophe Riccio
 /// @author Christophe Riccio
 ///////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////
 
 
+#include "_vectorize.hpp"
+
 namespace glm
 namespace glm
 {
 {
 	// matrixCompMult
 	// matrixCompMult

+ 108 - 109
glm/core/func_packing.inl

@@ -26,134 +26,133 @@
 /// @author Christophe Riccio
 /// @author Christophe Riccio
 ///////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////
 
 
-namespace glm{
-
-GLM_FUNC_QUALIFIER detail::uint32 packUnorm2x16(detail::tvec2<detail::float32> const & v)
+namespace glm
 {
 {
-	detail::uint16 A(detail::uint16(round(clamp(v.x, 0.0f, 1.0f) * 65535.0f)));
-	detail::uint16 B(detail::uint16(round(clamp(v.y, 0.0f, 1.0f) * 65535.0f)));
-	return detail::uint32((B << 16) | A);
-}
+	GLM_FUNC_QUALIFIER detail::uint32 packUnorm2x16(detail::tvec2<detail::float32> const & v)
+	{
+		detail::uint16 A(detail::uint16(round(clamp(v.x, 0.0f, 1.0f) * 65535.0f)));
+		detail::uint16 B(detail::uint16(round(clamp(v.y, 0.0f, 1.0f) * 65535.0f)));
+		return detail::uint32((B << 16) | A);
+	}
 
 
-GLM_FUNC_QUALIFIER detail::tvec2<detail::float32> unpackUnorm2x16(detail::uint32 const & p)
-{
-	detail::uint32 Mask16((1 << 16) - 1);
-	detail::uint32 A((p >>  0) & Mask16);
-	detail::uint32 B((p >> 16) & Mask16);
-	return detail::tvec2<detail::float32>(
-		A * 1.0f / 65535.0f, 
-		B * 1.0f / 65535.0f);
-}
+	GLM_FUNC_QUALIFIER detail::tvec2<detail::float32> unpackUnorm2x16(detail::uint32 const & p)
+	{
+		detail::uint32 Mask16((1 << 16) - 1);
+		detail::uint32 A((p >>  0) & Mask16);
+		detail::uint32 B((p >> 16) & Mask16);
+		return detail::tvec2<detail::float32>(
+			A * 1.0f / 65535.0f, 
+			B * 1.0f / 65535.0f);
+	}
 	
 	
-GLM_FUNC_QUALIFIER detail::uint32 packSnorm2x16(detail::tvec2<detail::float32> const & v)
-{
-	union iu
+	GLM_FUNC_QUALIFIER detail::uint32 packSnorm2x16(detail::tvec2<detail::float32> const & v)
 	{
 	{
-		detail::int16 i;
-		detail::uint16 u;
-	} A, B;
+		union iu
+		{
+			detail::int16 i;
+			detail::uint16 u;
+		} A, B;
 		
 		
-	detail::tvec2<detail::float32> Unpack = clamp(v ,-1.0f, 1.0f) * 32767.0f;
-	A.i = detail::int16(round(Unpack.x));
-	B.i = detail::int16(round(Unpack.y));
-	detail::uint32 Pack = (detail::uint32(B.u) << 16) | (detail::uint32(A.u) << 0);
-	return Pack;
-}
+		detail::tvec2<detail::float32> Unpack = clamp(v ,-1.0f, 1.0f) * 32767.0f;
+		A.i = detail::int16(round(Unpack.x));
+		B.i = detail::int16(round(Unpack.y));
+		detail::uint32 Pack = (detail::uint32(B.u) << 16) | (detail::uint32(A.u) << 0);
+		return Pack;
+	}
 
 
-GLM_FUNC_QUALIFIER detail::tvec2<detail::float32> unpackSnorm2x16(detail::uint32 const & p)
-{
-	union iu
+	GLM_FUNC_QUALIFIER detail::tvec2<detail::float32> unpackSnorm2x16(detail::uint32 const & p)
 	{
 	{
-		detail::int16 i;
-		detail::uint16 u;
-	} A, B;
+		union iu
+		{
+			detail::int16 i;
+			detail::uint16 u;
+		} A, B;
 		
 		
-	detail::uint32 Mask16((1 << 16) - 1);
-	A.u = detail::uint16((p >>  0) & Mask16);
-	B.u = detail::uint16((p >> 16) & Mask16);
-	detail::tvec2<detail::float32> Pack(A.i, B.i);
+		detail::uint32 Mask16((1 << 16) - 1);
+		A.u = detail::uint16((p >>  0) & Mask16);
+		B.u = detail::uint16((p >> 16) & Mask16);
+		detail::tvec2<detail::float32> Pack(A.i, B.i);
 		
 		
-	return clamp(Pack * 1.0f / 32767.0f, -1.0f, 1.0f);
-}
+		return clamp(Pack * 1.0f / 32767.0f, -1.0f, 1.0f);
+	}
 
 
-GLM_FUNC_QUALIFIER detail::uint32 packUnorm4x8(detail::tvec4<detail::float32> const & v)
-{
-	detail::uint8 A((detail::uint8)round(clamp(v.x, 0.0f, 1.0f) * 255.0f));
-	detail::uint8 B((detail::uint8)round(clamp(v.y, 0.0f, 1.0f) * 255.0f));
-	detail::uint8 C((detail::uint8)round(clamp(v.z, 0.0f, 1.0f) * 255.0f));
-	detail::uint8 D((detail::uint8)round(clamp(v.w, 0.0f, 1.0f) * 255.0f));
-	return detail::uint32((D << 24) | (C << 16) | (B << 8) | A);
-}
+	GLM_FUNC_QUALIFIER detail::uint32 packUnorm4x8(detail::tvec4<detail::float32> const & v)
+	{
+		detail::uint8 A((detail::uint8)round(clamp(v.x, 0.0f, 1.0f) * 255.0f));
+		detail::uint8 B((detail::uint8)round(clamp(v.y, 0.0f, 1.0f) * 255.0f));
+		detail::uint8 C((detail::uint8)round(clamp(v.z, 0.0f, 1.0f) * 255.0f));
+		detail::uint8 D((detail::uint8)round(clamp(v.w, 0.0f, 1.0f) * 255.0f));
+		return detail::uint32((D << 24) | (C << 16) | (B << 8) | A);
+	}
 
 
-GLM_FUNC_QUALIFIER detail::tvec4<detail::float32> unpackUnorm4x8(detail::uint32 const & p)
-{	
-	detail::uint32 Mask8((1 << 8) - 1);
-	detail::uint32 A((p >>  0) & Mask8);
-	detail::uint32 B((p >>  8) & Mask8);
-	detail::uint32 C((p >> 16) & Mask8);
-	detail::uint32 D((p >> 24) & Mask8);
-	return detail::tvec4<detail::float32>(
-		A * 1.0f / 255.0f, 
-		B * 1.0f / 255.0f, 
-		C * 1.0f / 255.0f, 
-		D * 1.0f / 255.0f);
-}
+	GLM_FUNC_QUALIFIER detail::tvec4<detail::float32> unpackUnorm4x8(detail::uint32 const & p)
+	{	
+		detail::uint32 Mask8((1 << 8) - 1);
+		detail::uint32 A((p >>  0) & Mask8);
+		detail::uint32 B((p >>  8) & Mask8);
+		detail::uint32 C((p >> 16) & Mask8);
+		detail::uint32 D((p >> 24) & Mask8);
+		return detail::tvec4<detail::float32>(
+			A * 1.0f / 255.0f, 
+			B * 1.0f / 255.0f, 
+			C * 1.0f / 255.0f, 
+			D * 1.0f / 255.0f);
+	}
 	
 	
-GLM_FUNC_QUALIFIER detail::uint32 packSnorm4x8(detail::tvec4<detail::float32> const & v)
-{
-	union iu
+	GLM_FUNC_QUALIFIER detail::uint32 packSnorm4x8(detail::tvec4<detail::float32> const & v)
 	{
 	{
-		detail::int8 i;
-		detail::uint8 u;
-	} A, B, C, D;
+		union iu
+		{
+			detail::int8 i;
+			detail::uint8 u;
+		} A, B, C, D;
 	
 	
-	detail::tvec4<detail::float32> Unpack = clamp(v ,-1.0f, 1.0f) * 127.0f;
-	A.i = detail::int8(round(Unpack.x));
-	B.i = detail::int8(round(Unpack.y));
-	C.i = detail::int8(round(Unpack.z));
-	D.i = detail::int8(round(Unpack.w));
-	detail::uint32 Pack = (detail::uint32(D.u) << 24) | (detail::uint32(C.u) << 16) | (detail::uint32(B.u) << 8) | (detail::uint32(A.u) << 0);
-	return Pack;
-}
+		detail::tvec4<detail::float32> Unpack = clamp(v ,-1.0f, 1.0f) * 127.0f;
+		A.i = detail::int8(round(Unpack.x));
+		B.i = detail::int8(round(Unpack.y));
+		C.i = detail::int8(round(Unpack.z));
+		D.i = detail::int8(round(Unpack.w));
+		detail::uint32 Pack = (detail::uint32(D.u) << 24) | (detail::uint32(C.u) << 16) | (detail::uint32(B.u) << 8) | (detail::uint32(A.u) << 0);
+		return Pack;
+	}
 	
 	
-GLM_FUNC_QUALIFIER detail::tvec4<detail::float32> unpackSnorm4x8(detail::uint32 const & p)
-{	
-	union iu
-	{
-		detail::int8 i;
-		detail::uint8 u;
-	} A, B, C, D;
+	GLM_FUNC_QUALIFIER detail::tvec4<detail::float32> unpackSnorm4x8(detail::uint32 const & p)
+	{	
+		union iu
+		{
+			detail::int8 i;
+			detail::uint8 u;
+		} A, B, C, D;
 	
 	
-	detail::uint32 Mask8((1 << 8) - 1);
-	A.u = detail::uint8((p >>  0) & Mask8);
-	B.u = detail::uint8((p >>  8) & Mask8);
-	C.u = detail::uint8((p >> 16) & Mask8);
-	D.u = detail::uint8((p >> 24) & Mask8);
-	detail::tvec4<detail::float32> Pack(A.i, B.i, C.i, D.i);
+		detail::uint32 Mask8((1 << 8) - 1);
+		A.u = detail::uint8((p >>  0) & Mask8);
+		B.u = detail::uint8((p >>  8) & Mask8);
+		C.u = detail::uint8((p >> 16) & Mask8);
+		D.u = detail::uint8((p >> 24) & Mask8);
+		detail::tvec4<detail::float32> Pack(A.i, B.i, C.i, D.i);
 	
 	
-	return clamp(Pack * 1.0f / 127.0f, -1.0f, 1.0f);
-}
+		return clamp(Pack * 1.0f / 127.0f, -1.0f, 1.0f);
+	}
 
 
-GLM_FUNC_QUALIFIER double packDouble2x32(detail::tvec2<detail::uint32> const & v)
-{
-	return *(double*)&v;
-}
-
-GLM_FUNC_QUALIFIER detail::tvec2<uint> unpackDouble2x32(double const & v)
-{
-	return *(detail::tvec2<uint>*)&v;
-}
+	GLM_FUNC_QUALIFIER double packDouble2x32(detail::tvec2<detail::uint32> const & v)
+	{
+		return *(double*)&v;
+	}
 
 
-GLM_FUNC_QUALIFIER uint packHalf2x16(detail::tvec2<float> const & v)
-{
-	detail::tvec2<detail::hdata> Pack(detail::toFloat16(v.x), detail::toFloat16(v.y));
-	return *(uint*)&Pack;
-}
+	GLM_FUNC_QUALIFIER detail::tvec2<uint> unpackDouble2x32(double const & v)
+	{
+		return *(detail::tvec2<uint>*)&v;
+	}
 
 
-GLM_FUNC_QUALIFIER vec2 unpackHalf2x16(uint const & v)
-{
-	detail::tvec2<detail::hdata> Unpack = *(detail::tvec2<detail::hdata>*)&v;
-	return vec2(detail::toFloat32(Unpack.x), detail::toFloat32(Unpack.y));
-}
+	GLM_FUNC_QUALIFIER uint packHalf2x16(detail::tvec2<float> const & v)
+	{
+		detail::tvec2<detail::hdata> Pack(detail::toFloat16(v.x), detail::toFloat16(v.y));
+		return *(uint*)&Pack;
+	}
 
 
+	GLM_FUNC_QUALIFIER vec2 unpackHalf2x16(uint const & v)
+	{
+		detail::tvec2<detail::hdata> Unpack = *(detail::tvec2<detail::hdata>*)&v;
+		return vec2(detail::toFloat32(Unpack.x), detail::toFloat32(Unpack.y));
+	}
 }//namespace glm
 }//namespace glm

+ 214 - 725
glm/core/func_trigonometric.inl

@@ -26,732 +26,221 @@
 /// @author Christophe Riccio
 /// @author Christophe Riccio
 ///////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////
 
 
-namespace glm{
-
-// radians
-template <typename genType>
-GLM_FUNC_QUALIFIER genType radians
-(
-	genType const & degrees
-)
-{
-	GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'radians' only accept floating-point input");
-
-    const genType pi = genType(3.1415926535897932384626433832795);
-    return degrees * (pi / genType(180));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec2<T> radians
-(
-	detail::tvec2<T> const & degrees
-)
-{
-    return detail::tvec2<T>(
-        radians(degrees.x),
-        radians(degrees.y));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec3<T> radians
-(
-	detail::tvec3<T> const & degrees
-)
-{
-    return detail::tvec3<T>(
-        radians(degrees.x),
-        radians(degrees.y),
-        radians(degrees.z));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec4<T> radians
-(
-	detail::tvec4<T> const & degrees
-)
-{
-    return detail::tvec4<T>(
-        radians(degrees.x),
-        radians(degrees.y),
-        radians(degrees.z),
-        radians(degrees.w));
-}
-
-// degrees
-template <typename genType>
-GLM_FUNC_QUALIFIER genType degrees
-(
-	genType const & radians
-)
-{
-	GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'degrees' only accept floating-point input");
-
-    const genType pi = genType(3.1415926535897932384626433832795);
-    return radians * (genType(180) / pi);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec2<T> degrees
-(
-	detail::tvec2<T> const & radians
-)
-{
-    return detail::tvec2<T>(
-        degrees(radians.x),
-        degrees(radians.y));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec3<T> degrees
-(	
-	detail::tvec3<T> const & radians
-)
-{
-    return detail::tvec3<T>(
-        degrees(radians.x),
-        degrees(radians.y),
-        degrees(radians.z));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec4<T> degrees
-(
-	detail::tvec4<T> const & radians
-)
-{
-    return detail::tvec4<T>(
-        degrees(radians.x),
-        degrees(radians.y),
-        degrees(radians.z),
-        degrees(radians.w));
-}
-
-// sin
-template <typename genType>
-GLM_FUNC_QUALIFIER genType sin
-(
-	genType const & angle
-)
-{
-	GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'sin' only accept floating-point input");
-
-	return ::std::sin(angle);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec2<T> sin
-(
-	detail::tvec2<T> const & angle
-)
-{
-    return detail::tvec2<T>(
-        sin(angle.x),
-        sin(angle.y));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec3<T> sin
-(
-	detail::tvec3<T> const & angle
-)
-{
-    return detail::tvec3<T>(
-        sin(angle.x),
-        sin(angle.y),
-        sin(angle.z));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec4<T> sin
-(
-	detail::tvec4<T> const & angle
-)
-{
-    return detail::tvec4<T>(
-        sin(angle.x),
-        sin(angle.y),
-        sin(angle.z),
-        sin(angle.w));
-}
-
-// cos
-template <typename genType>
-GLM_FUNC_QUALIFIER genType cos(genType const & angle)
-{
-	GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'cos' only accept floating-point input");
-
-    return ::std::cos(angle);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec2<T> cos
-(
-	detail::tvec2<T> const & angle
-)
-{
-    return detail::tvec2<T>(
-        cos(angle.x),
-        cos(angle.y));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec3<T> cos
-(
-	detail::tvec3<T> const & angle
-)
-{
-    return detail::tvec3<T>(
-        cos(angle.x),
-        cos(angle.y),
-        cos(angle.z));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec4<T> cos
-(	
-	detail::tvec4<T> const & angle
-)
-{
-    return detail::tvec4<T>(
-        cos(angle.x),
-        cos(angle.y),
-        cos(angle.z),
-        cos(angle.w));
-}
-
-// tan
-template <typename genType>
-GLM_FUNC_QUALIFIER genType tan
-(
-	genType const & angle
-)
-{
-	GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'tan' only accept floating-point input");
-
-    return ::std::tan(angle);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec2<T> tan
-(
-	detail::tvec2<T> const & angle
-)
-{
-    return detail::tvec2<T>(
-        tan(angle.x),
-        tan(angle.y));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec3<T> tan
-(
-	detail::tvec3<T> const & angle
-)
-{
-    return detail::tvec3<T>(
-        tan(angle.x),
-        tan(angle.y),
-        tan(angle.z));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec4<T> tan
-(
-	detail::tvec4<T> const & angle
-)
-{
-    return detail::tvec4<T>(
-        tan(angle.x),
-        tan(angle.y),
-        tan(angle.z),
-        tan(angle.w));
-}
-
-// asin
-template <typename genType>
-GLM_FUNC_QUALIFIER genType asin
-(
-	genType const & x
-)
-{
-	GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'asin' only accept floating-point input");
-
-    return ::std::asin(x);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec2<T> asin
-(
-	detail::tvec2<T> const & x
-)
-{
-    return detail::tvec2<T>(
-        asin(x.x),
-        asin(x.y));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec3<T> asin
-(
-	detail::tvec3<T> const & x
-)
-{
-    return detail::tvec3<T>(
-        asin(x.x),
-        asin(x.y),
-        asin(x.z));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec4<T> asin
-(
-	detail::tvec4<T> const & x
-)
-{
-    return detail::tvec4<T>(
-        asin(x.x),
-        asin(x.y),
-        asin(x.z),
-        asin(x.w));
-}
-
-// acos
-template <typename genType>
-GLM_FUNC_QUALIFIER genType acos
-(
-	genType const & x
-)
-{
-	GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'acos' only accept floating-point input");
-
-    return ::std::acos(x);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec2<T> acos
-(
-	detail::tvec2<T> const & x
-)
-{
-    return detail::tvec2<T>(
-        acos(x.x),
-        acos(x.y));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec3<T> acos
-(
-	detail::tvec3<T> const & x
-)
-{
-    return detail::tvec3<T>(
-        acos(x.x),
-        acos(x.y),
-        acos(x.z));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec4<T> acos
-(
-	detail::tvec4<T> const & x
-)
-{
-    return detail::tvec4<T>(
-        acos(x.x),
-        acos(x.y),
-        acos(x.z),
-        acos(x.w));
-}
-
-// atan
-template <typename genType>
-GLM_FUNC_QUALIFIER genType atan
-(
-	genType const & y, 
-	genType const & x
-)
-{
-	GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'atan' only accept floating-point input");
-
-    return ::std::atan2(y, x);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec2<T> atan
-(
-	detail::tvec2<T> const & y, 
-	detail::tvec2<T> const & x
-)
-{
-    return detail::tvec2<T>(
-        atan(y.x, x.x),
-        atan(y.y, x.y));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec3<T> atan
-(
-	detail::tvec3<T> const & y, 
-	detail::tvec3<T> const & x
-)
-{
-    return detail::tvec3<T>(
-        atan(y.x, x.x),
-        atan(y.y, x.y),
-        atan(y.z, x.z));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec4<T> atan
-(
-	detail::tvec4<T> const & y, 
-	detail::tvec4<T> const & x
-)
-{
-    return detail::tvec4<T>(
-        atan(y.x, x.x),
-        atan(y.y, x.y),
-        atan(y.z, x.z),
-        atan(y.w, x.w));
-}
-
-template <typename genType>
-GLM_FUNC_QUALIFIER genType atan
-(
-	genType const & x
-)
-{
-	GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'atan' only accept floating-point input");
-
-    return ::std::atan(x);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec2<T> atan
-(
-	detail::tvec2<T> const & x
-)
-{
-    return detail::tvec2<T>(
-        atan(x.x),
-        atan(x.y));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec3<T> atan
-(
-	detail::tvec3<T> const & x
-)
-{
-    return detail::tvec3<T>(
-        atan(x.x),
-        atan(x.y),
-        atan(x.z));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec4<T> atan
-(
-	detail::tvec4<T> const & x
-)
-{
-    return detail::tvec4<T>(
-        atan(x.x),
-        atan(x.y),
-        atan(x.z),
-        atan(x.w));
-}
-
-// sinh
-template <typename genType> 
-GLM_FUNC_QUALIFIER genType sinh
-(
-	genType const & angle
-)
-{
-    GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'sinh' only accept floating-point input");
-
-	return std::sinh(angle);
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec2<T> sinh
-(
-	detail::tvec2<T> const & angle
-)
-{
-    return detail::tvec2<T>(
-        sinh(angle.x),
-        sinh(angle.y));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec3<T> sinh
-(
-	detail::tvec3<T> const & angle
-)
-{
-    return detail::tvec3<T>(
-        sinh(angle.x),
-        sinh(angle.y),
-        sinh(angle.z));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec4<T> sinh
-(
-	detail::tvec4<T> const & angle
-)
-{
-    return detail::tvec4<T>(
-        sinh(angle.x),
-        sinh(angle.y),
-        sinh(angle.z),
-        sinh(angle.w));
-}
-
-// cosh
-template <typename genType> 
-GLM_FUNC_QUALIFIER genType cosh
-(
-	genType const & angle
-)
-{
-    GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'cosh' only accept floating-point input");
-
-	return std::cosh(angle);
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec2<T> cosh
-(
-	detail::tvec2<T> const & angle
-)
-{
-    return detail::tvec2<T>(
-        cosh(angle.x),
-        cosh(angle.y));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec3<T> cosh
-(
-	detail::tvec3<T> const & angle
-)
-{
-    return detail::tvec3<T>(
-        cosh(angle.x),
-        cosh(angle.y),
-        cosh(angle.z));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec4<T> cosh
-(
-	detail::tvec4<T> const & angle
-)
-{
-    return detail::tvec4<T>(
-        cosh(angle.x),
-        cosh(angle.y),
-        cosh(angle.z),
-        cosh(angle.w));
-}
-
-// tanh
-template <typename genType>
-GLM_FUNC_QUALIFIER genType tanh
-(
-	genType const & angle
-)
-{
-    GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'tanh' only accept floating-point input");
-
-	return std::tanh(angle);
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec2<T> tanh
-(
-	detail::tvec2<T> const & angle
-)
-{
-    return detail::tvec2<T>(
-        tanh(angle.x),
-        tanh(angle.y));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec3<T> tanh
-(
-	detail::tvec3<T> const & angle
-)
-{
-    return detail::tvec3<T>(
-        tanh(angle.x),
-        tanh(angle.y),
-        tanh(angle.z));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec4<T> tanh
-(
-	detail::tvec4<T> const & angle
-)
-{
-    return detail::tvec4<T>(
-        tanh(angle.x),
-        tanh(angle.y),
-        tanh(angle.z),
-        tanh(angle.w));
-}
-
-// asinh
-template <typename genType> 
-GLM_FUNC_QUALIFIER genType asinh
-(
-	genType const & x
-)
-{
-	GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'asinh' only accept floating-point input");
+#include "_vectorize.hpp"
+
+namespace glm
+{
+	// radians
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType radians
+	(
+		genType const & degrees
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'radians' only accept floating-point input");
+
+		genType const pi = genType(3.1415926535897932384626433832795);
+		return degrees * (pi / genType(180));
+	}
+
+	VECTORIZE_VEC(radians)
+	
+	// degrees
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType degrees
+	(
+		genType const & radians
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'degrees' only accept floating-point input");
+
+		const genType pi = genType(3.1415926535897932384626433832795);
+		return radians * (genType(180) / pi);
+	}
+
+	VECTORIZE_VEC(degrees)
+
+	// sin
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType sin
+	(
+		genType const & angle
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'sin' only accept floating-point input");
+
+		return ::std::sin(angle);
+	}
+
+	VECTORIZE_VEC(sin)
+
+	// cos
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType cos(genType const & angle)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'cos' only accept floating-point input");
+
+		return ::std::cos(angle);
+	}
+
+	VECTORIZE_VEC(cos)
+
+	// tan
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType tan
+	(
+		genType const & angle
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'tan' only accept floating-point input");
+
+		return ::std::tan(angle);
+	}
+
+	VECTORIZE_VEC(tan)
+
+	// asin
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType asin
+	(
+		genType const & x
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'asin' only accept floating-point input");
+
+		return ::std::asin(x);
+	}
+
+	VECTORIZE_VEC(asin)
+
+	// acos
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType acos
+	(
+		genType const & x
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'acos' only accept floating-point input");
+
+		return ::std::acos(x);
+	}
+
+	VECTORIZE_VEC(acos)
+
+	// atan
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType atan
+	(
+		genType const & y, 
+		genType const & x
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'atan' only accept floating-point input");
+
+		return ::std::atan2(y, x);
+	}
+
+	VECTORIZE_VEC_VEC(atan)
+
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType atan
+	(
+		genType const & x
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'atan' only accept floating-point input");
+
+		return ::std::atan(x);
+	}
+
+	VECTORIZE_VEC(atan)
+
+	// sinh
+	template <typename genType> 
+	GLM_FUNC_QUALIFIER genType sinh
+	(
+		genType const & angle
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'sinh' only accept floating-point input");
+
+		return std::sinh(angle);
+	}
+
+	VECTORIZE_VEC(sinh)
+
+	// cosh
+	template <typename genType> 
+	GLM_FUNC_QUALIFIER genType cosh
+	(
+		genType const & angle
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'cosh' only accept floating-point input");
+
+		return std::cosh(angle);
+	}
+
+	VECTORIZE_VEC(cosh)
+
+	// tanh
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType tanh
+	(
+		genType const & angle
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'tanh' only accept floating-point input");
+
+		return std::tanh(angle);
+	}
+
+	VECTORIZE_VEC(tanh)
+
+	// asinh
+	template <typename genType> 
+	GLM_FUNC_QUALIFIER genType asinh
+	(
+		genType const & x
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'asinh' only accept floating-point input");
 		
 		
-	return (x < genType(0) ? genType(-1) : (x > genType(0) ? genType(1) : genType(0))) * log(abs(x) + sqrt(genType(1) + x * x));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec2<T> asinh
-(
-	detail::tvec2<T> const & x
-)
-{
-    return detail::tvec2<T>(
-        asinh(x.x),
-        asinh(x.y));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec3<T> asinh
-(
-	detail::tvec3<T> const & x
-)
-{
-    return detail::tvec3<T>(
-        asinh(x.x),
-        asinh(x.y),
-        asinh(x.z));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec4<T> asinh
-(
-	detail::tvec4<T> const & x
-)
-{
-    return detail::tvec4<T>(
-        asinh(x.x),
-        asinh(x.y),
-        asinh(x.z),
-        asinh(x.w));
-}
-
-// acosh
-template <typename genType> 
-GLM_FUNC_QUALIFIER genType acosh
-(
-	genType const & x
-)
-{
-	GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'acosh' only accept floating-point input");
-
-	if(x < genType(1))
-		return genType(0);
-	return log(x + sqrt(x * x - genType(1)));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec2<T> acosh
-(
-	detail::tvec2<T> const & x
-)
-{
-	return detail::tvec2<T>(
-		acosh(x.x),
-		acosh(x.y));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec3<T> acosh
-(
-	detail::tvec3<T> const & x
-)
-{
-    return detail::tvec3<T>(
-        acosh(x.x),
-        acosh(x.y),
-        acosh(x.z));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec4<T> acosh
-(
-	detail::tvec4<T> const & x
-)
-{
-    return detail::tvec4<T>(
-        acosh(x.x),
-        acosh(x.y),
-        acosh(x.z),
-        acosh(x.w));
-}
-
-// atanh
-template <typename genType>
-GLM_FUNC_QUALIFIER genType atanh
-(
-	genType const & x
-)
-{
-	GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'atanh' only accept floating-point input");
+		return (x < genType(0) ? genType(-1) : (x > genType(0) ? genType(1) : genType(0))) * log(abs(x) + sqrt(genType(1) + x * x));
+	}
+
+	VECTORIZE_VEC(asinh)
+
+	// acosh
+	template <typename genType> 
+	GLM_FUNC_QUALIFIER genType acosh
+	(
+		genType const & x
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'acosh' only accept floating-point input");
+
+		if(x < genType(1))
+			return genType(0);
+		return log(x + sqrt(x * x - genType(1)));
+	}
+
+	VECTORIZE_VEC(acosh)
+
+	// atanh
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType atanh
+	(
+		genType const & x
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'atanh' only accept floating-point input");
 		
 		
-	if(abs(x) >= genType(1))
-		return 0;
-	return genType(0.5) * log((genType(1) + x) / (genType(1) - x));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec2<T> atanh
-(
-	detail::tvec2<T> const & x
-)
-{
-    return detail::tvec2<T>(
-        atanh(x.x),
-        atanh(x.y));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec3<T> atanh
-(
-	detail::tvec3<T> const & x
-)
-{
-    return detail::tvec3<T>(
-        atanh(x.x),
-        atanh(x.y),
-        atanh(x.z));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec4<T> atanh
-(
-	detail::tvec4<T> const & x
-)
-{
-    return detail::tvec4<T>(
-        atanh(x.x),
-        atanh(x.y),
-        atanh(x.z),
-        atanh(x.w));
-}
+		if(abs(x) >= genType(1))
+			return 0;
+		return genType(0.5) * log((genType(1) + x) / (genType(1) - x));
+	}
+
+	VECTORIZE_VEC(atanh)
 
 
 }//namespace glm
 }//namespace glm

+ 972 - 972
glm/gtc/half_float.inl

@@ -27,981 +27,981 @@
 ///////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////
 
 
 namespace glm{
 namespace glm{
-namespace detail{
-
-#ifndef _MSC_EXTENSIONS
-
-//////////////////////////////////////
-// hvec2
-
-GLM_FUNC_QUALIFIER tvec2<thalf>::size_type tvec2<thalf>::length() const
-{
-    return 2;
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf>::size_type tvec2<thalf>::value_size()
-{
-	return 2;
-}
-
-//////////////////////////////////////
-// Accesses
-
-GLM_FUNC_QUALIFIER thalf & tvec2<thalf>::operator[](tvec2<thalf>::size_type i)
-{
-	assert(/*i >= tvec2<thalf>::size_type(0) && */i < tvec2<thalf>::value_size());
-	return (&x)[i];
-}
-
-GLM_FUNC_QUALIFIER thalf const & tvec2<thalf>::operator[](tvec2<thalf>::size_type i) const
-{
-	assert(/*i >= tvec2<thalf>::size_type(0) && */i < tvec2<thalf>::value_size());
-	return (&x)[i];
-}
-
-//////////////////////////////////////
-// Implicit basic constructors
-
-GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2() :
-	x(thalf(0.f)),
-	y(thalf(0.f))
-{}
-
-GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
-(
-	tvec2<thalf> const & v
-) :
-	x(v.x),
-	y(v.y)
-{}
-
-//////////////////////////////////////
-// Explicit basic constructors
-
-GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
-(
-	thalf const & s
-) :
-	x(s),
-	y(s)
-{}
-
-GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
-(
-	thalf const & s1, 
-	thalf const & s2
-) :
-	x(s1),
-	y(s2)
-{}
-
-//////////////////////////////////////
-// Swizzle constructors
-
-GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
-(
-	tref2<thalf> const & r
-) :
-	x(r.x),
-	y(r.y)
-{}
-
-//////////////////////////////////////
-// Convertion scalar constructors
-
-template <typename U> 
-GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
-(
-	U const & x
-) :
-	x(thalf(x)),
-	y(thalf(x))
-{}
-
-template <typename U, typename V> 
-GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
-(
-	U const & x, 
-	V const & y
-) :
-	x(thalf(x)),
-	y(thalf(y))
-{}
-
-//////////////////////////////////////
-// Convertion vector constructors
-
-template <typename U> 
-GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
-(
-	tvec2<U> const & v
-) :
-	x(thalf(v.x)),
-	y(thalf(v.y))
-{}
-
-template <typename U> 
-GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
-(	
-	tvec3<U> const & v
-) :
-	x(thalf(v.x)),
-	y(thalf(v.y))
-{}
-
-template <typename U> 
-GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
-(
-	tvec4<U> const & v
-) :
-	x(thalf(v.x)),
-	y(thalf(v.y))
-{}
-
-//////////////////////////////////////
-// Unary arithmetic operators
-
-GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator= 
-(
-	tvec2<thalf> const & v
-)
-{
-	this->x = v.x;
-	this->y = v.y;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator+=
-(
-	thalf const & s
-)
-{
-	this->x += s;
-	this->y += s;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator+=
-(
-	tvec2<thalf> const & v
-)
-{
-	this->x += v.x;
-	this->y += v.y;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator-=
-(
-	thalf const & s
-)
-{
-	this->x -= s;
-	this->y -= s;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator-=
-(
-	tvec2<thalf> const & v
-)
-{
-	this->x -= v.x;
-	this->y -= v.y;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf>& tvec2<thalf>::operator*=
-(
-	thalf const & s
-)
-{
-	this->x *= s;
-	this->y *= s;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator*=
-(
-	tvec2<thalf> const & v
-)
-{
-	this->x *= v.x;
-	this->y *= v.y;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator/=
-(
-	thalf const & s
-)
-{
-	this->x /= s;
-	this->y /= s;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator/=
-(
-	tvec2<thalf> const & v
-)
-{
-	this->x /= v.x;
-	this->y /= v.y;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator++()
-{
-	++this->x;
-	++this->y;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf>& tvec2<thalf>::operator--()
-{
-	--this->x;
-	--this->y;
-	return *this;
-}
-
-//////////////////////////////////////
-// Swizzle operators
-
-GLM_FUNC_QUALIFIER thalf tvec2<thalf>::swizzle(comp x) const
-{
-	return (*this)[x];
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf> tvec2<thalf>::swizzle(comp x, comp y) const
-{
-	return tvec2<thalf>(
-		(*this)[x],
-		(*this)[y]);
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> tvec2<thalf>::swizzle(comp x, comp y, comp z) const
-{
-	return tvec3<thalf>(
-		(*this)[x],
-		(*this)[y],
-		(*this)[z]);
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf> tvec2<thalf>::swizzle(comp x, comp y, comp z, comp w) const
-{
-	return tvec4<thalf>(
-		(*this)[x],
-		(*this)[y],
-		(*this)[z],
-		(*this)[w]);
-}
-
-GLM_FUNC_QUALIFIER tref2<thalf> tvec2<thalf>::swizzle(comp x, comp y)
-{
-	return tref2<thalf>(
-		(*this)[x],
-		(*this)[y]);
-}
-
-//////////////////////////////////////
-// hvec3
-
-GLM_FUNC_QUALIFIER tvec3<thalf>::size_type tvec3<thalf>::length() const
-{
-    return 3;
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf>::size_type tvec3<thalf>::value_size()
-{
-	return 3;
-}
-
-//////////////////////////////////////
-// Accesses
-
-GLM_FUNC_QUALIFIER thalf & tvec3<thalf>::operator[]
-(
-	tvec3<thalf>::size_type i
-)
-{
-	assert(/*i >= tvec3<thalf>::size_type(0) &&*/ i < tvec3<thalf>::value_size());
-
-	return (&x)[i];
-}
-
-GLM_FUNC_QUALIFIER thalf const & tvec3<thalf>::operator[]
-(
-	tvec3<thalf>::size_type i
-) const
-{
-	assert(/*i >= tvec3<thalf>::size_type(0) &&*/ i < tvec3<thalf>::value_size());
-
-	return (&x)[i];
-}
-
-//////////////////////////////////////
-// Implicit basic constructors
-
-GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3() :
-	x(thalf(0)),
-	y(thalf(0)),
-	z(thalf(0))
-{}
-
-GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
-(
-	tvec3<thalf> const & v
-) :
-	x(v.x),
-	y(v.y),
-	z(v.z)
-{}
-
-//////////////////////////////////////
-// Explicit basic constructors
-
-GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
-(
-	thalf const & s
-) :
-	x(s),
-	y(s),
-	z(s)
-{}
-
-GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
-(
-	thalf const & s0, 
-	thalf const & s1, 
-	thalf const & s2
-) :
-	x(s0),
-	y(s1),
-	z(s2)
-{}
-
-//////////////////////////////////////
-// Swizzle constructors
-
-GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
-(
-	tref3<thalf> const & r
-) :
-	x(r.x),
-	y(r.y),
-	z(r.z)
-{}
-
-//////////////////////////////////////
-// Convertion scalar constructors
-
-template <typename U> 
-GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
-(
-	U const & x
-) :
-	x(thalf(x)),
-	y(thalf(x)),
-	z(thalf(x))
-{}
-
-template <typename A, typename B, typename C> 
-GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
-(
-	A const & x, 
-	B const & y, 
-	C const & z
-) :
-	x(thalf(x)),
-	y(thalf(y)),
-	z(thalf(z))
-{}
-
-//////////////////////////////////////
-// Convertion vector constructors
-
-template <typename A, typename B> 
-GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
-(
-	tvec2<A> const & v, 
-	B const & s
-) :
-	x(thalf(v.x)),
-	y(thalf(v.y)),
-	z(thalf(s))
-{}
-
-template <typename A, typename B> 
-GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
-(
-	A const & s, 
-	tvec2<B> const & v
-) :
-	x(thalf(s)),
-	y(thalf(v.x)),
-	z(thalf(v.y))
-{}
-
-template <typename U> 
-GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
-(
-	tvec3<U> const & v
-) :
-	x(thalf(v.x)),
-	y(thalf(v.y)),
-	z(thalf(v.z))
-{}
-
-template <typename U> 
-GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
-(
-	tvec4<U> const & v
-) :
-	x(thalf(v.x)),
-	y(thalf(v.y)),
-	z(thalf(v.z))
-{}
-
-//////////////////////////////////////
-// Unary arithmetic operators
-
-GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator= 
-(
-	tvec3<thalf> const & v
-)
-{
-	this->x = v.x;
-	this->y = v.y;
-	this->z = v.z;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator+=
-(
-	thalf const & s
-)
-{
-	this->x += s;
-	this->y += s;
-	this->z += s;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator+=
-(
-	tvec3<thalf> const & v
-)
-{
-	this->x += v.x;
-	this->y += v.y;
-	this->z += v.z;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator-=
-(
-	thalf const & s
-)
-{
-	this->x -= s;
-	this->y -= s;
-	this->z -= s;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator-=
-(
-	tvec3<thalf> const & v
-)
+namespace detail
 {
 {
-	this->x -= v.x;
-	this->y -= v.y;
-	this->z -= v.z;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator*=
-(
-	thalf const & s
-)
-{
-	this->x *= s;
-	this->y *= s;
-	this->z *= s;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator*=
-(
-	tvec3<thalf> const & v
-)
-{
-	this->x *= v.x;
-	this->y *= v.y;
-	this->z *= v.z;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator/=
-(
-	thalf const & s
-)
-{
-	this->x /= s;
-	this->y /= s;
-	this->z /= s;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator/=
-(
-	tvec3<thalf> const & v
-)
-{
-	this->x /= v.x;
-	this->y /= v.y;
-	this->z /= v.z;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator++()
-{
-	++this->x;
-	++this->y;
-	++this->z;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator--()
-{
-	--this->x;
-	--this->y;
-	--this->z;
-	return *this;
-}
-
-//////////////////////////////////////
-// Swizzle operators
-
-GLM_FUNC_QUALIFIER thalf tvec3<thalf>::swizzle(comp x) const
-{
-	return (*this)[x];
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf> tvec3<thalf>::swizzle(comp x, comp y) const
-{
-	return tvec2<thalf>(
-		(*this)[x],
-		(*this)[y]);
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> tvec3<thalf>::swizzle(comp x, comp y, comp z) const
-{
-	return tvec3<thalf>(
-		(*this)[x],
-		(*this)[y],
-		(*this)[z]);
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf> tvec3<thalf>::swizzle(comp x, comp y, comp z, comp w) const
-{
-	return tvec4<thalf>(
-		(*this)[x],
-		(*this)[y],
-		(*this)[z],
-		(*this)[w]);
-}
-
-GLM_FUNC_QUALIFIER tref3<thalf> tvec3<thalf>::swizzle(comp x, comp y, comp z)
-{
-	return tref3<thalf>(
-		(*this)[x],
-		(*this)[y],
-		(*this)[z]);
-}
-
-//////////////////////////////////////
-// hvec4
-
-GLM_FUNC_QUALIFIER tvec4<thalf>::size_type tvec4<thalf>::length() const
-{
-    return 4;
-}
+#ifndef _MSC_EXTENSIONS
 
 
-GLM_FUNC_QUALIFIER tvec4<thalf>::size_type tvec4<thalf>::value_size()
-{
-	return 4;
-}
+	//////////////////////////////////////
+	// hvec2
+
+	GLM_FUNC_QUALIFIER tvec2<thalf>::size_type tvec2<thalf>::length() const
+	{
+		return 2;
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf>::size_type tvec2<thalf>::value_size()
+	{
+		return 2;
+	}
+
+	//////////////////////////////////////
+	// Accesses
+
+	GLM_FUNC_QUALIFIER thalf & tvec2<thalf>::operator[](tvec2<thalf>::size_type i)
+	{
+		assert(/*i >= tvec2<thalf>::size_type(0) && */i < tvec2<thalf>::value_size());
+		return (&x)[i];
+	}
+
+	GLM_FUNC_QUALIFIER thalf const & tvec2<thalf>::operator[](tvec2<thalf>::size_type i) const
+	{
+		assert(/*i >= tvec2<thalf>::size_type(0) && */i < tvec2<thalf>::value_size());
+		return (&x)[i];
+	}
+
+	//////////////////////////////////////
+	// Implicit basic constructors
+
+	GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2() :
+		x(thalf(0.f)),
+		y(thalf(0.f))
+	{}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
+	(
+		tvec2<thalf> const & v
+	) :
+		x(v.x),
+		y(v.y)
+	{}
+
+	//////////////////////////////////////
+	// Explicit basic constructors
+
+	GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
+	(
+		thalf const & s
+	) :
+		x(s),
+		y(s)
+	{}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
+	(
+		thalf const & s1, 
+		thalf const & s2
+	) :
+		x(s1),
+		y(s2)
+	{}
+
+	//////////////////////////////////////
+	// Swizzle constructors
+
+	GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
+	(
+		tref2<thalf> const & r
+	) :
+		x(r.x),
+		y(r.y)
+	{}
+
+	//////////////////////////////////////
+	// Convertion scalar constructors
+
+	template <typename U> 
+	GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
+	(
+		U const & x
+	) :
+		x(thalf(x)),
+		y(thalf(x))
+	{}
+
+	template <typename U, typename V> 
+	GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
+	(
+		U const & x, 
+		V const & y
+	) :
+		x(thalf(x)),
+		y(thalf(y))
+	{}
+
+	//////////////////////////////////////
+	// Convertion vector constructors
+
+	template <typename U> 
+	GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
+	(
+		tvec2<U> const & v
+	) :
+		x(thalf(v.x)),
+		y(thalf(v.y))
+	{}
+
+	template <typename U> 
+	GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
+	(	
+		tvec3<U> const & v
+	) :
+		x(thalf(v.x)),
+		y(thalf(v.y))
+	{}
+
+	template <typename U> 
+	GLM_FUNC_QUALIFIER tvec2<thalf>::tvec2
+	(
+		tvec4<U> const & v
+	) :
+		x(thalf(v.x)),
+		y(thalf(v.y))
+	{}
+
+	//////////////////////////////////////
+	// Unary arithmetic operators
+
+	GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator= 
+	(
+		tvec2<thalf> const & v
+	)
+	{
+		this->x = v.x;
+		this->y = v.y;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator+=
+	(
+		thalf const & s
+	)
+	{
+		this->x += s;
+		this->y += s;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator+=
+	(
+		tvec2<thalf> const & v
+	)
+	{
+		this->x += v.x;
+		this->y += v.y;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator-=
+	(
+		thalf const & s
+	)
+	{
+		this->x -= s;
+		this->y -= s;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator-=
+	(
+		tvec2<thalf> const & v
+	)
+	{
+		this->x -= v.x;
+		this->y -= v.y;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf>& tvec2<thalf>::operator*=
+	(
+		thalf const & s
+	)
+	{
+		this->x *= s;
+		this->y *= s;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator*=
+	(
+		tvec2<thalf> const & v
+	)
+	{
+		this->x *= v.x;
+		this->y *= v.y;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator/=
+	(
+		thalf const & s
+	)
+	{
+		this->x /= s;
+		this->y /= s;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator/=
+	(
+		tvec2<thalf> const & v
+	)
+	{
+		this->x /= v.x;
+		this->y /= v.y;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf> & tvec2<thalf>::operator++()
+	{
+		++this->x;
+		++this->y;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf>& tvec2<thalf>::operator--()
+	{
+		--this->x;
+		--this->y;
+		return *this;
+	}
+
+	//////////////////////////////////////
+	// Swizzle operators
+
+	GLM_FUNC_QUALIFIER thalf tvec2<thalf>::swizzle(comp x) const
+	{
+		return (*this)[x];
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf> tvec2<thalf>::swizzle(comp x, comp y) const
+	{
+		return tvec2<thalf>(
+			(*this)[x],
+			(*this)[y]);
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> tvec2<thalf>::swizzle(comp x, comp y, comp z) const
+	{
+		return tvec3<thalf>(
+			(*this)[x],
+			(*this)[y],
+			(*this)[z]);
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf> tvec2<thalf>::swizzle(comp x, comp y, comp z, comp w) const
+	{
+		return tvec4<thalf>(
+			(*this)[x],
+			(*this)[y],
+			(*this)[z],
+			(*this)[w]);
+	}
+
+	GLM_FUNC_QUALIFIER tref2<thalf> tvec2<thalf>::swizzle(comp x, comp y)
+	{
+		return tref2<thalf>(
+			(*this)[x],
+			(*this)[y]);
+	}
+
+	//////////////////////////////////////
+	// hvec3
+
+	GLM_FUNC_QUALIFIER tvec3<thalf>::size_type tvec3<thalf>::length() const
+	{
+		return 3;
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf>::size_type tvec3<thalf>::value_size()
+	{
+		return 3;
+	}
+
+	//////////////////////////////////////
+	// Accesses
+
+	GLM_FUNC_QUALIFIER thalf & tvec3<thalf>::operator[]
+	(
+		tvec3<thalf>::size_type i
+	)
+	{
+		assert(/*i >= tvec3<thalf>::size_type(0) &&*/ i < tvec3<thalf>::value_size());
+
+		return (&x)[i];
+	}
+
+	GLM_FUNC_QUALIFIER thalf const & tvec3<thalf>::operator[]
+	(
+		tvec3<thalf>::size_type i
+	) const
+	{
+		assert(/*i >= tvec3<thalf>::size_type(0) &&*/ i < tvec3<thalf>::value_size());
+
+		return (&x)[i];
+	}
+
+	//////////////////////////////////////
+	// Implicit basic constructors
+
+	GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3() :
+		x(thalf(0)),
+		y(thalf(0)),
+		z(thalf(0))
+	{}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
+	(
+		tvec3<thalf> const & v
+	) :
+		x(v.x),
+		y(v.y),
+		z(v.z)
+	{}
+
+	//////////////////////////////////////
+	// Explicit basic constructors
+
+	GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
+	(
+		thalf const & s
+	) :
+		x(s),
+		y(s),
+		z(s)
+	{}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
+	(
+		thalf const & s0, 
+		thalf const & s1, 
+		thalf const & s2
+	) :
+		x(s0),
+		y(s1),
+		z(s2)
+	{}
+
+	//////////////////////////////////////
+	// Swizzle constructors
+
+	GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
+	(
+		tref3<thalf> const & r
+	) :
+		x(r.x),
+		y(r.y),
+		z(r.z)
+	{}
+
+	//////////////////////////////////////
+	// Convertion scalar constructors
+
+	template <typename U> 
+	GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
+	(
+		U const & x
+	) :
+		x(thalf(x)),
+		y(thalf(x)),
+		z(thalf(x))
+	{}
+
+	template <typename A, typename B, typename C> 
+	GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
+	(
+		A const & x, 
+		B const & y, 
+		C const & z
+	) :
+		x(thalf(x)),
+		y(thalf(y)),
+		z(thalf(z))
+	{}
+
+	//////////////////////////////////////
+	// Convertion vector constructors
+
+	template <typename A, typename B> 
+	GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
+	(
+		tvec2<A> const & v, 
+		B const & s
+	) :
+		x(thalf(v.x)),
+		y(thalf(v.y)),
+		z(thalf(s))
+	{}
+
+	template <typename A, typename B> 
+	GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
+	(
+		A const & s, 
+		tvec2<B> const & v
+	) :
+		x(thalf(s)),
+		y(thalf(v.x)),
+		z(thalf(v.y))
+	{}
+
+	template <typename U> 
+	GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
+	(
+		tvec3<U> const & v
+	) :
+		x(thalf(v.x)),
+		y(thalf(v.y)),
+		z(thalf(v.z))
+	{}
+
+	template <typename U> 
+	GLM_FUNC_QUALIFIER tvec3<thalf>::tvec3
+	(
+		tvec4<U> const & v
+	) :
+		x(thalf(v.x)),
+		y(thalf(v.y)),
+		z(thalf(v.z))
+	{}
+
+	//////////////////////////////////////
+	// Unary arithmetic operators
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator= 
+	(
+		tvec3<thalf> const & v
+	)
+	{
+		this->x = v.x;
+		this->y = v.y;
+		this->z = v.z;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator+=
+	(
+		thalf const & s
+	)
+	{
+		this->x += s;
+		this->y += s;
+		this->z += s;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator+=
+	(
+		tvec3<thalf> const & v
+	)
+	{
+		this->x += v.x;
+		this->y += v.y;
+		this->z += v.z;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator-=
+	(
+		thalf const & s
+	)
+	{
+		this->x -= s;
+		this->y -= s;
+		this->z -= s;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator-=
+	(
+		tvec3<thalf> const & v
+	)
+	{
+		this->x -= v.x;
+		this->y -= v.y;
+		this->z -= v.z;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator*=
+	(
+		thalf const & s
+	)
+	{
+		this->x *= s;
+		this->y *= s;
+		this->z *= s;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator*=
+	(
+		tvec3<thalf> const & v
+	)
+	{
+		this->x *= v.x;
+		this->y *= v.y;
+		this->z *= v.z;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator/=
+	(
+		thalf const & s
+	)
+	{
+		this->x /= s;
+		this->y /= s;
+		this->z /= s;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator/=
+	(
+		tvec3<thalf> const & v
+	)
+	{
+		this->x /= v.x;
+		this->y /= v.y;
+		this->z /= v.z;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator++()
+	{
+		++this->x;
+		++this->y;
+		++this->z;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> & tvec3<thalf>::operator--()
+	{
+		--this->x;
+		--this->y;
+		--this->z;
+		return *this;
+	}
+
+	//////////////////////////////////////
+	// Swizzle operators
+
+	GLM_FUNC_QUALIFIER thalf tvec3<thalf>::swizzle(comp x) const
+	{
+		return (*this)[x];
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf> tvec3<thalf>::swizzle(comp x, comp y) const
+	{
+		return tvec2<thalf>(
+			(*this)[x],
+			(*this)[y]);
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> tvec3<thalf>::swizzle(comp x, comp y, comp z) const
+	{
+		return tvec3<thalf>(
+			(*this)[x],
+			(*this)[y],
+			(*this)[z]);
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf> tvec3<thalf>::swizzle(comp x, comp y, comp z, comp w) const
+	{
+		return tvec4<thalf>(
+			(*this)[x],
+			(*this)[y],
+			(*this)[z],
+			(*this)[w]);
+	}
+
+	GLM_FUNC_QUALIFIER tref3<thalf> tvec3<thalf>::swizzle(comp x, comp y, comp z)
+	{
+		return tref3<thalf>(
+			(*this)[x],
+			(*this)[y],
+			(*this)[z]);
+	}
+
+	//////////////////////////////////////
+	// hvec4
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>::size_type tvec4<thalf>::length() const
+	{
+		return 4;
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>::size_type tvec4<thalf>::value_size()
+	{
+		return 4;
+	}
 	
 	
-//////////////////////////////////////
-// Accesses
-
-GLM_FUNC_QUALIFIER thalf & tvec4<thalf>::operator[]
-(
-	tvec4<thalf>::size_type i
-)
-{
-	assert(/*i >= tvec4<thalf>::size_type(0) && */i < tvec4<thalf>::value_size());
-
-	return (&x)[i];
-}
-
-GLM_FUNC_QUALIFIER thalf const & tvec4<thalf>::operator[]
-(
-	tvec4<thalf>::size_type i
-) const
-{
-	assert(/*i >= tvec4<thalf>::size_type(0) && */i < tvec4<thalf>::value_size());
-
-	return (&x)[i];
-}
-
-//////////////////////////////////////
-// Implicit basic constructors
-
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4() :
-	x(thalf(0)),
-	y(thalf(0)),
-	z(thalf(0)),
-	w(thalf(0))
-{}
-
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	tvec4<thalf> const & v
-) :
-	x(v.x),
-	y(v.y),
-	z(v.z),
-	w(v.w)
-{}
-
-//////////////////////////////////////
-// Explicit basic constructors
-
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	thalf const & s
-) :
-	x(s),
-	y(s),
-	z(s),
-	w(s)
-{}
-
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	thalf const & s1, 
-	thalf const & s2, 
-	thalf const & s3, 
-	thalf const & s4
-) :
-	x(s1),
-	y(s2),
-	z(s3),
-	w(s4)
-{}
-
-//////////////////////////////////////
-// Swizzle constructors
-
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	tref4<thalf> const & r
-) :
-	x(r.x),
-	y(r.y),
-	z(r.z),
-	w(r.w)
-{}
-
-//////////////////////////////////////
-// Convertion scalar constructors
-
-template <typename U> 
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	U const & x
-) :
-	x(thalf(x)),
-	y(thalf(x)),
-	z(thalf(x)),
-	w(thalf(x))
-{}
-
-template <typename A, typename B, typename C, typename D> 
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	A const & x, 
-	B const & y, 
-	C const & z, 
-	D const & w
-) :
-	x(thalf(x)),
-	y(thalf(y)),
-	z(thalf(z)),
-	w(thalf(w))
-{}
-
-//////////////////////////////////////
-// Convertion vector constructors
-
-template <typename A, typename B, typename C> 
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	tvec2<A> const & v, 
-	B const & s1, 
-	C const & s2
-) :
-	x(thalf(v.x)),
-	y(thalf(v.y)),
-	z(thalf(s1)),
-	w(thalf(s2))
-{}
-
-template <typename A, typename B, typename C> 
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	A const & s1, 
-	tvec2<B> const & v, 
-	C const & s2
-) :
-	x(thalf(s1)),
-	y(thalf(v.x)),
-	z(thalf(v.y)),
-	w(thalf(s2))
-{}
-
-template <typename A, typename B, typename C> 
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	A const & s1, 
-	B const & s2, 
-	tvec2<C> const & v
-) :
-	x(thalf(s1)),
-	y(thalf(s2)),
-	z(thalf(v.x)),
-	w(thalf(v.y))
-{}
-
-template <typename A, typename B> 
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	tvec3<A> const & v, 
-	B const & s
-) :
-	x(thalf(v.x)),
-	y(thalf(v.y)),
-	z(thalf(v.z)),
-	w(thalf(s))
-{}
-
-template <typename A, typename B> 
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	A const & s, 
-	tvec3<B> const & v
-) :
-	x(thalf(s)),
-	y(thalf(v.x)),
-	z(thalf(v.y)),
-	w(thalf(v.z))
-{}
-
-template <typename A, typename B> 
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	tvec2<A> const & v1, 
-	tvec2<B> const & v2
-) :
-	x(thalf(v1.x)),
-	y(thalf(v1.y)),
-	z(thalf(v2.x)),
-	w(thalf(v2.y))
-{}
-
-template <typename U> 
-GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
-(
-	tvec4<U> const & v
-) :
-	x(thalf(v.x)),
-	y(thalf(v.y)),
-	z(thalf(v.z)),
-	w(thalf(v.w))
-{}
-
-//////////////////////////////////////
-// Unary arithmetic operators
-
-GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator= 
-(
-	tvec4<thalf> const & v
-)
-{
-	this->x = v.x;
-	this->y = v.y;
-	this->z = v.z;
-	this->w = v.w;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator+=
-(
-	thalf const & s
-)
-{
-	this->x += s;
-	this->y += s;
-	this->z += s;
-	this->w += s;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator+=
-(
-	tvec4<thalf> const & v
-)
-{
-	this->x += v.x;
-	this->y += v.y;
-	this->z += v.z;
-	this->w += v.w;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator-=
-(
-	thalf const & s
-)
-{
-	this->x -= s;
-	this->y -= s;
-	this->z -= s;
-	this->w -= s;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator-=
-(
-	tvec4<thalf> const & v
-)
-{
-	this->x -= v.x;
-	this->y -= v.y;
-	this->z -= v.z;
-	this->w -= v.w;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator*=
-(
-	thalf const & s
-)
-{
-	this->x *= s;
-	this->y *= s;
-	this->z *= s;
-	this->w *= s;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator*=
-(
-	tvec4<thalf> const & v
-)
-{
-	this->x *= v.x;
-	this->y *= v.y;
-	this->z *= v.z;
-	this->w *= v.w;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator/=
-(
-	thalf const & s
-)
-{
-	this->x /= s;
-	this->y /= s;
-	this->z /= s;
-	this->w /= s;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator/=
-(
-	tvec4<thalf> const & v
-)
-{
-	this->x /= v.x;
-	this->y /= v.y;
-	this->z /= v.z;
-	this->w /= v.w;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator++()
-{
-	++this->x;
-	++this->y;
-	++this->z;
-	++this->w;
-	return *this;
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator--()
-{
-	--this->x;
-	--this->y;
-	--this->z;
-	--this->w;
-	return *this;
-}
-
-//////////////////////////////////////
-// Swizzle operators
-
-GLM_FUNC_QUALIFIER thalf tvec4<thalf>::swizzle(comp x) const
-{
-	return (*this)[x];
-}
-
-GLM_FUNC_QUALIFIER tvec2<thalf> tvec4<thalf>::swizzle(comp x, comp y) const
-{
-	return tvec2<thalf>(
-		(*this)[x],
-		(*this)[y]);
-}
-
-GLM_FUNC_QUALIFIER tvec3<thalf> tvec4<thalf>::swizzle(comp x, comp y, comp z) const
-{
-	return tvec3<thalf>(
-		(*this)[x],
-		(*this)[y],
-		(*this)[z]);
-}
-
-GLM_FUNC_QUALIFIER tvec4<thalf> tvec4<thalf>::swizzle(comp x, comp y, comp z, comp w) const
-{
-	return tvec4<thalf>(
-		(*this)[x],
-		(*this)[y],
-		(*this)[z],
-		(*this)[w]);
-}
-
-GLM_FUNC_QUALIFIER tref4<thalf> tvec4<thalf>::swizzle(comp x, comp y, comp z, comp w)
-{
-	return tref4<thalf>(
-		(*this)[x],
-		(*this)[y],
-		(*this)[z],
-		(*this)[w]);
-}
+	//////////////////////////////////////
+	// Accesses
+
+	GLM_FUNC_QUALIFIER thalf & tvec4<thalf>::operator[]
+	(
+		tvec4<thalf>::size_type i
+	)
+	{
+		assert(/*i >= tvec4<thalf>::size_type(0) && */i < tvec4<thalf>::value_size());
+
+		return (&x)[i];
+	}
+
+	GLM_FUNC_QUALIFIER thalf const & tvec4<thalf>::operator[]
+	(
+		tvec4<thalf>::size_type i
+	) const
+	{
+		assert(/*i >= tvec4<thalf>::size_type(0) && */i < tvec4<thalf>::value_size());
+
+		return (&x)[i];
+	}
+
+	//////////////////////////////////////
+	// Implicit basic constructors
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4() :
+		x(thalf(0)),
+		y(thalf(0)),
+		z(thalf(0)),
+		w(thalf(0))
+	{}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		tvec4<thalf> const & v
+	) :
+		x(v.x),
+		y(v.y),
+		z(v.z),
+		w(v.w)
+	{}
+
+	//////////////////////////////////////
+	// Explicit basic constructors
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		thalf const & s
+	) :
+		x(s),
+		y(s),
+		z(s),
+		w(s)
+	{}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		thalf const & s1, 
+		thalf const & s2, 
+		thalf const & s3, 
+		thalf const & s4
+	) :
+		x(s1),
+		y(s2),
+		z(s3),
+		w(s4)
+	{}
+
+	//////////////////////////////////////
+	// Swizzle constructors
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		tref4<thalf> const & r
+	) :
+		x(r.x),
+		y(r.y),
+		z(r.z),
+		w(r.w)
+	{}
+
+	//////////////////////////////////////
+	// Convertion scalar constructors
+
+	template <typename U> 
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		U const & x
+	) :
+		x(thalf(x)),
+		y(thalf(x)),
+		z(thalf(x)),
+		w(thalf(x))
+	{}
+
+	template <typename A, typename B, typename C, typename D> 
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		A const & x, 
+		B const & y, 
+		C const & z, 
+		D const & w
+	) :
+		x(thalf(x)),
+		y(thalf(y)),
+		z(thalf(z)),
+		w(thalf(w))
+	{}
+
+	//////////////////////////////////////
+	// Convertion vector constructors
+
+	template <typename A, typename B, typename C> 
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		tvec2<A> const & v, 
+		B const & s1, 
+		C const & s2
+	) :
+		x(thalf(v.x)),
+		y(thalf(v.y)),
+		z(thalf(s1)),
+		w(thalf(s2))
+	{}
+
+	template <typename A, typename B, typename C> 
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		A const & s1, 
+		tvec2<B> const & v, 
+		C const & s2
+	) :
+		x(thalf(s1)),
+		y(thalf(v.x)),
+		z(thalf(v.y)),
+		w(thalf(s2))
+	{}
+
+	template <typename A, typename B, typename C> 
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		A const & s1, 
+		B const & s2, 
+		tvec2<C> const & v
+	) :
+		x(thalf(s1)),
+		y(thalf(s2)),
+		z(thalf(v.x)),
+		w(thalf(v.y))
+	{}
+
+	template <typename A, typename B> 
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		tvec3<A> const & v, 
+		B const & s
+	) :
+		x(thalf(v.x)),
+		y(thalf(v.y)),
+		z(thalf(v.z)),
+		w(thalf(s))
+	{}
+
+	template <typename A, typename B> 
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		A const & s, 
+		tvec3<B> const & v
+	) :
+		x(thalf(s)),
+		y(thalf(v.x)),
+		z(thalf(v.y)),
+		w(thalf(v.z))
+	{}
+
+	template <typename A, typename B> 
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		tvec2<A> const & v1, 
+		tvec2<B> const & v2
+	) :
+		x(thalf(v1.x)),
+		y(thalf(v1.y)),
+		z(thalf(v2.x)),
+		w(thalf(v2.y))
+	{}
+
+	template <typename U> 
+	GLM_FUNC_QUALIFIER tvec4<thalf>::tvec4
+	(
+		tvec4<U> const & v
+	) :
+		x(thalf(v.x)),
+		y(thalf(v.y)),
+		z(thalf(v.z)),
+		w(thalf(v.w))
+	{}
+
+	//////////////////////////////////////
+	// Unary arithmetic operators
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator= 
+	(
+		tvec4<thalf> const & v
+	)
+	{
+		this->x = v.x;
+		this->y = v.y;
+		this->z = v.z;
+		this->w = v.w;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator+=
+	(
+		thalf const & s
+	)
+	{
+		this->x += s;
+		this->y += s;
+		this->z += s;
+		this->w += s;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator+=
+	(
+		tvec4<thalf> const & v
+	)
+	{
+		this->x += v.x;
+		this->y += v.y;
+		this->z += v.z;
+		this->w += v.w;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator-=
+	(
+		thalf const & s
+	)
+	{
+		this->x -= s;
+		this->y -= s;
+		this->z -= s;
+		this->w -= s;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator-=
+	(
+		tvec4<thalf> const & v
+	)
+	{
+		this->x -= v.x;
+		this->y -= v.y;
+		this->z -= v.z;
+		this->w -= v.w;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator*=
+	(
+		thalf const & s
+	)
+	{
+		this->x *= s;
+		this->y *= s;
+		this->z *= s;
+		this->w *= s;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator*=
+	(
+		tvec4<thalf> const & v
+	)
+	{
+		this->x *= v.x;
+		this->y *= v.y;
+		this->z *= v.z;
+		this->w *= v.w;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator/=
+	(
+		thalf const & s
+	)
+	{
+		this->x /= s;
+		this->y /= s;
+		this->z /= s;
+		this->w /= s;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator/=
+	(
+		tvec4<thalf> const & v
+	)
+	{
+		this->x /= v.x;
+		this->y /= v.y;
+		this->z /= v.z;
+		this->w /= v.w;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator++()
+	{
+		++this->x;
+		++this->y;
+		++this->z;
+		++this->w;
+		return *this;
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf>& tvec4<thalf>::operator--()
+	{
+		--this->x;
+		--this->y;
+		--this->z;
+		--this->w;
+		return *this;
+	}
+
+	//////////////////////////////////////
+	// Swizzle operators
+
+	GLM_FUNC_QUALIFIER thalf tvec4<thalf>::swizzle(comp x) const
+	{
+		return (*this)[x];
+	}
+
+	GLM_FUNC_QUALIFIER tvec2<thalf> tvec4<thalf>::swizzle(comp x, comp y) const
+	{
+		return tvec2<thalf>(
+			(*this)[x],
+			(*this)[y]);
+	}
+
+	GLM_FUNC_QUALIFIER tvec3<thalf> tvec4<thalf>::swizzle(comp x, comp y, comp z) const
+	{
+		return tvec3<thalf>(
+			(*this)[x],
+			(*this)[y],
+			(*this)[z]);
+	}
+
+	GLM_FUNC_QUALIFIER tvec4<thalf> tvec4<thalf>::swizzle(comp x, comp y, comp z, comp w) const
+	{
+		return tvec4<thalf>(
+			(*this)[x],
+			(*this)[y],
+			(*this)[z],
+			(*this)[w]);
+	}
+
+	GLM_FUNC_QUALIFIER tref4<thalf> tvec4<thalf>::swizzle(comp x, comp y, comp z, comp w)
+	{
+		return tref4<thalf>(
+			(*this)[x],
+			(*this)[y],
+			(*this)[z],
+			(*this)[w]);
+	}
 
 
 #endif//_MSC_EXTENSIONS
 #endif//_MSC_EXTENSIONS
 
 

+ 47 - 41
glm/gtc/matrix_access.inl

@@ -26,49 +26,55 @@
 /// @author Christophe Riccio
 /// @author Christophe Riccio
 ///////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////
 
 
-namespace glm{
-
-template <typename genType>
-GLM_FUNC_QUALIFIER genType row(
-	genType const & m, 
-	int index, 
-	typename genType::row_type const & x)
-{
-    genType Result = m;
-    for(typename genType::size_type i = 0; i < genType::row_size(); ++i)
-		Result[i][index] = x[i];
-    return Result;
-}
-
-template <typename genType>
-GLM_FUNC_QUALIFIER typename genType::row_type row(
-	genType const & m, 
-	int index)
+namespace glm
 {
 {
-	typename genType::row_type Result;
-	for(typename genType::size_type i = 0; i < genType::row_size(); ++i)
-		Result[i] = m[i][index];
-	return Result;
-}
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType row
+	(
+		genType const & m, 
+		int index, 
+		typename genType::row_type const & x
+	)
+	{
+		genType Result = m;
+		for(typename genType::size_type i = 0; i < genType::row_size(); ++i)
+			Result[i][index] = x[i];
+		return Result;
+	}
 
 
-template <typename genType>
-GLM_FUNC_QUALIFIER genType column(
-	genType const & m, 
-	int index, 
-	typename genType::col_type const & x)
-{
-    genType Result = m;
-    Result[index] = x;
-    return Result;
-}
+	template <typename genType>
+	GLM_FUNC_QUALIFIER typename genType::row_type row
+	(
+		genType const & m, 
+		int index
+	)
+	{
+		typename genType::row_type Result;
+		for(typename genType::size_type i = 0; i < genType::row_size(); ++i)
+			Result[i] = m[i][index];
+		return Result;
+	}
 
 
-template <typename genType>
-GLM_FUNC_QUALIFIER typename genType::col_type column(
-	genType const & m, 
-	int index)
-{
-    return m[index];
-}
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType column
+	(
+		genType const & m, 
+		int index, 
+		typename genType::col_type const & x
+	)
+	{
+		genType Result = m;
+		Result[index] = x;
+		return Result;
+	}
 
 
+	template <typename genType>
+	GLM_FUNC_QUALIFIER typename genType::col_type column
+	(
+		genType const & m, 
+		int index
+	)
+	{
+		return m[index];
+	}
 }//namespace glm
 }//namespace glm
-

+ 128 - 123
glm/gtc/matrix_inverse.inl

@@ -26,129 +26,134 @@
 /// @author Christophe Riccio
 /// @author Christophe Riccio
 ///////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////
 
 
-namespace glm{
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tmat3x3<T> affineInverse
-(
-	detail::tmat3x3<T> const & m
-)
-{
-	detail::tmat3x3<T> Result(m);
-	Result[2] = detail::tvec3<T>(0, 0, 1);
-	Result = transpose(Result);
-	detail::tvec3<T> Translation = Result * detail::tvec3<T>(-detail::tvec2<T>(m[2]), m[2][2]);
-	Result[2] = Translation;
-	return Result;
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<T> affineInverse
-(
-	detail::tmat4x4<T> const & m
-)
-{
-	detail::tmat4x4<T> Result(m);
-	Result[3] = detail::tvec4<T>(0, 0, 0, 1);
-	Result = transpose(Result);
-	detail::tvec4<T> Translation = Result * detail::tvec4<T>(-detail::tvec3<T>(m[3]), m[3][3]);
-	Result[3] = Translation;
-	return Result;
-}
-
-template <typename valType> 
-GLM_FUNC_QUALIFIER detail::tmat2x2<valType> inverseTranspose(
-	detail::tmat2x2<valType> const & m)
-{
-	valType Determinant = m[0][0] * m[1][1] - m[1][0] * m[0][1];
-
-	detail::tmat2x2<valType> Inverse(
-		+ m[1][1] / Determinant,
-		- m[0][1] / Determinant,
-		- m[1][0] / Determinant, 
-		+ m[0][0] / Determinant);
-
-	return Inverse;
-}
-
-template <typename valType> 
-GLM_FUNC_QUALIFIER detail::tmat3x3<valType> inverseTranspose(
-	detail::tmat3x3<valType> const & m)
-{
-	valType Determinant = 
-		+ m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1])
-		- m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0])
-		+ m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
-
-	detail::tmat3x3<valType> Inverse;
-	Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]);
-	Inverse[0][1] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]);
-	Inverse[0][2] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]);
-	Inverse[1][0] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]);
-	Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]);
-	Inverse[1][2] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]);
-	Inverse[2][0] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
-	Inverse[2][1] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]);
-	Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]);
-	Inverse /= Determinant;
-
-	return Inverse;
-}
-
-template <typename valType> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<valType> inverseTranspose(
-	detail::tmat4x4<valType> const & m)
+namespace glm
 {
 {
-	valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
-	valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
-	valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
-	valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
-	valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
-	valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
-	valType SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
-	valType SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
-	valType SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
-	valType SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
-	valType SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
-	valType SubFactor11 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
-	valType SubFactor12 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
-	valType SubFactor13 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
-	valType SubFactor14 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
-	valType SubFactor15 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
-	valType SubFactor16 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
-	valType SubFactor17 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
-	valType SubFactor18 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
-
-	detail::tmat4x4<valType> Inverse;
-	Inverse[0][0] = + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02);
-	Inverse[0][1] = - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04);
-	Inverse[0][2] = + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05);
-	Inverse[0][3] = - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05);
-
-	Inverse[1][0] = - (m[0][1] * SubFactor00 - m[0][2] * SubFactor01 + m[0][3] * SubFactor02);
-	Inverse[1][1] = + (m[0][0] * SubFactor00 - m[0][2] * SubFactor03 + m[0][3] * SubFactor04);
-	Inverse[1][2] = - (m[0][0] * SubFactor01 - m[0][1] * SubFactor03 + m[0][3] * SubFactor05);
-	Inverse[1][3] = + (m[0][0] * SubFactor02 - m[0][1] * SubFactor04 + m[0][2] * SubFactor05);
-
-	Inverse[2][0] = + (m[0][1] * SubFactor06 - m[0][2] * SubFactor07 + m[0][3] * SubFactor08);
-	Inverse[2][1] = - (m[0][0] * SubFactor06 - m[0][2] * SubFactor09 + m[0][3] * SubFactor10);
-	Inverse[2][2] = + (m[0][0] * SubFactor11 - m[0][1] * SubFactor09 + m[0][3] * SubFactor12);
-	Inverse[2][3] = - (m[0][0] * SubFactor08 - m[0][1] * SubFactor10 + m[0][2] * SubFactor12);
-
-	Inverse[3][0] = - (m[0][1] * SubFactor13 - m[0][2] * SubFactor14 + m[0][3] * SubFactor15);
-	Inverse[3][1] = + (m[0][0] * SubFactor13 - m[0][2] * SubFactor16 + m[0][3] * SubFactor17);
-	Inverse[3][2] = - (m[0][0] * SubFactor14 - m[0][1] * SubFactor16 + m[0][3] * SubFactor18);
-	Inverse[3][3] = + (m[0][0] * SubFactor15 - m[0][1] * SubFactor17 + m[0][2] * SubFactor18);
-
-	valType Determinant = 
-		+ m[0][0] * Inverse[0][0] 
-		+ m[0][1] * Inverse[0][1] 
-		+ m[0][2] * Inverse[0][2] 
-		+ m[0][3] * Inverse[0][3];
-
-	Inverse /= Determinant;
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tmat3x3<T> affineInverse
+	(
+		detail::tmat3x3<T> const & m
+	)
+	{
+		detail::tmat3x3<T> Result(m);
+		Result[2] = detail::tvec3<T>(0, 0, 1);
+		Result = transpose(Result);
+		detail::tvec3<T> Translation = Result * detail::tvec3<T>(-detail::tvec2<T>(m[2]), m[2][2]);
+		Result[2] = Translation;
+		return Result;
+	}
+
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<T> affineInverse
+	(
+		detail::tmat4x4<T> const & m
+	)
+	{
+		detail::tmat4x4<T> Result(m);
+		Result[3] = detail::tvec4<T>(0, 0, 0, 1);
+		Result = transpose(Result);
+		detail::tvec4<T> Translation = Result * detail::tvec4<T>(-detail::tvec3<T>(m[3]), m[3][3]);
+		Result[3] = Translation;
+		return Result;
+	}
+
+	template <typename valType> 
+	GLM_FUNC_QUALIFIER detail::tmat2x2<valType> inverseTranspose
+	(
+		detail::tmat2x2<valType> const & m
+	)
+	{
+		valType Determinant = m[0][0] * m[1][1] - m[1][0] * m[0][1];
+
+		detail::tmat2x2<valType> Inverse(
+			+ m[1][1] / Determinant,
+			- m[0][1] / Determinant,
+			- m[1][0] / Determinant, 
+			+ m[0][0] / Determinant);
+
+		return Inverse;
+	}
+
+	template <typename valType> 
+	GLM_FUNC_QUALIFIER detail::tmat3x3<valType> inverseTranspose
+	(
+		detail::tmat3x3<valType> const & m
+	)
+	{
+		valType Determinant = 
+			+ m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1])
+			- m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0])
+			+ m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
+
+		detail::tmat3x3<valType> Inverse;
+		Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]);
+		Inverse[0][1] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]);
+		Inverse[0][2] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]);
+		Inverse[1][0] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]);
+		Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]);
+		Inverse[1][2] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]);
+		Inverse[2][0] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
+		Inverse[2][1] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]);
+		Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]);
+		Inverse /= Determinant;
+
+		return Inverse;
+	}
+
+	template <typename valType> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> inverseTranspose
+	(
+		detail::tmat4x4<valType> const & m
+	)
+	{
+		valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
+		valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
+		valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
+		valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
+		valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
+		valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
+		valType SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
+		valType SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
+		valType SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
+		valType SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
+		valType SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
+		valType SubFactor11 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
+		valType SubFactor12 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
+		valType SubFactor13 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
+		valType SubFactor14 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
+		valType SubFactor15 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
+		valType SubFactor16 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
+		valType SubFactor17 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
+		valType SubFactor18 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
+
+		detail::tmat4x4<valType> Inverse;
+		Inverse[0][0] = + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02);
+		Inverse[0][1] = - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04);
+		Inverse[0][2] = + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05);
+		Inverse[0][3] = - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05);
+
+		Inverse[1][0] = - (m[0][1] * SubFactor00 - m[0][2] * SubFactor01 + m[0][3] * SubFactor02);
+		Inverse[1][1] = + (m[0][0] * SubFactor00 - m[0][2] * SubFactor03 + m[0][3] * SubFactor04);
+		Inverse[1][2] = - (m[0][0] * SubFactor01 - m[0][1] * SubFactor03 + m[0][3] * SubFactor05);
+		Inverse[1][3] = + (m[0][0] * SubFactor02 - m[0][1] * SubFactor04 + m[0][2] * SubFactor05);
+
+		Inverse[2][0] = + (m[0][1] * SubFactor06 - m[0][2] * SubFactor07 + m[0][3] * SubFactor08);
+		Inverse[2][1] = - (m[0][0] * SubFactor06 - m[0][2] * SubFactor09 + m[0][3] * SubFactor10);
+		Inverse[2][2] = + (m[0][0] * SubFactor11 - m[0][1] * SubFactor09 + m[0][3] * SubFactor12);
+		Inverse[2][3] = - (m[0][0] * SubFactor08 - m[0][1] * SubFactor10 + m[0][2] * SubFactor12);
+
+		Inverse[3][0] = - (m[0][1] * SubFactor13 - m[0][2] * SubFactor14 + m[0][3] * SubFactor15);
+		Inverse[3][1] = + (m[0][0] * SubFactor13 - m[0][2] * SubFactor16 + m[0][3] * SubFactor17);
+		Inverse[3][2] = - (m[0][0] * SubFactor14 - m[0][1] * SubFactor16 + m[0][3] * SubFactor18);
+		Inverse[3][3] = + (m[0][0] * SubFactor15 - m[0][1] * SubFactor17 + m[0][2] * SubFactor18);
+
+		valType Determinant = 
+			+ m[0][0] * Inverse[0][0] 
+			+ m[0][1] * Inverse[0][1] 
+			+ m[0][2] * Inverse[0][2] 
+			+ m[0][3] * Inverse[0][3];
+
+		Inverse /= Determinant;
     
     
-	return Inverse;
-}
-
+		return Inverse;
+	}
 }//namespace glm
 }//namespace glm

+ 380 - 381
glm/gtc/matrix_transform.inl

@@ -26,388 +26,387 @@
 /// @author Christophe Riccio
 /// @author Christophe Riccio
 ///////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////
 
 
-namespace glm{
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<T> translate
-(
-	detail::tmat4x4<T> const & m,
-	detail::tvec3<T> const & v
-)
+namespace glm
 {
 {
-	detail::tmat4x4<T> Result(m);
-	Result[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3];
-	return Result;
-}
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<T> translate
+	(
+		detail::tmat4x4<T> const & m,
+		detail::tvec3<T> const & v
+	)
+	{
+		detail::tmat4x4<T> Result(m);
+		Result[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3];
+		return Result;
+	}
 		
 		
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<T> rotate
-(
-	detail::tmat4x4<T> const & m,
-	T const & angle, 
-	detail::tvec3<T> const & v
-)
-{
-    T a = radians(angle);
-    T c = cos(a);
-    T s = sin(a);
-
-    detail::tvec3<T> axis = normalize(v);
-
-	detail::tvec3<T> temp = (T(1) - c) * axis;
-
-    detail::tmat4x4<T> Rotate(detail::tmat4x4<T>::null);
-	Rotate[0][0] = c + temp[0] * axis[0];
-	Rotate[0][1] = 0 + temp[0] * axis[1] + s * axis[2];
-	Rotate[0][2] = 0 + temp[0] * axis[2] - s * axis[1];
-
-	Rotate[1][0] = 0 + temp[1] * axis[0] - s * axis[2];
-	Rotate[1][1] = c + temp[1] * axis[1];
-	Rotate[1][2] = 0 + temp[1] * axis[2] + s * axis[0];
-
-	Rotate[2][0] = 0 + temp[2] * axis[0] + s * axis[1];
-	Rotate[2][1] = 0 + temp[2] * axis[1] - s * axis[0];
-	Rotate[2][2] = c + temp[2] * axis[2];
-
-	detail::tmat4x4<T> Result(detail::tmat4x4<T>::null);
-	Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2];
-	Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2];
-	Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2];
-	Result[3] = m[3];
-	return Result;
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<T> scale
-(
-	detail::tmat4x4<T> const & m,
-	detail::tvec3<T> const & v
-)
-{
-    detail::tmat4x4<T> Result(detail::tmat4x4<T>::null);
-	Result[0] = m[0] * v[0];
-	Result[1] = m[1] * v[1];
-	Result[2] = m[2] * v[2];
-	Result[3] = m[3];
-	return Result;
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<T> translate_slow
-(
-	detail::tmat4x4<T> const & m,
-	detail::tvec3<T> const & v
-)
-{
-    detail::tmat4x4<T> Result(T(1));
-    Result[3] = detail::tvec4<T>(v, T(1));
-    return m * Result;
-
-	//detail::tmat4x4<valType> Result(m);
-	Result[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3];
-	//Result[3][0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0];
-	//Result[3][1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1];
-	//Result[3][2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2];
-	//Result[3][3] = m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3];
-	//return Result;
-}
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<T> rotate
+	(
+		detail::tmat4x4<T> const & m,
+		T const & angle, 
+		detail::tvec3<T> const & v
+	)
+	{
+		T a = radians(angle);
+		T c = cos(a);
+		T s = sin(a);
+
+		detail::tvec3<T> axis = normalize(v);
+
+		detail::tvec3<T> temp = (T(1) - c) * axis;
+
+		detail::tmat4x4<T> Rotate(detail::tmat4x4<T>::null);
+		Rotate[0][0] = c + temp[0] * axis[0];
+		Rotate[0][1] = 0 + temp[0] * axis[1] + s * axis[2];
+		Rotate[0][2] = 0 + temp[0] * axis[2] - s * axis[1];
+
+		Rotate[1][0] = 0 + temp[1] * axis[0] - s * axis[2];
+		Rotate[1][1] = c + temp[1] * axis[1];
+		Rotate[1][2] = 0 + temp[1] * axis[2] + s * axis[0];
+
+		Rotate[2][0] = 0 + temp[2] * axis[0] + s * axis[1];
+		Rotate[2][1] = 0 + temp[2] * axis[1] - s * axis[0];
+		Rotate[2][2] = c + temp[2] * axis[2];
+
+		detail::tmat4x4<T> Result(detail::tmat4x4<T>::null);
+		Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2];
+		Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2];
+		Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2];
+		Result[3] = m[3];
+		return Result;
+	}
+
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<T> scale
+	(
+		detail::tmat4x4<T> const & m,
+		detail::tvec3<T> const & v
+	)
+	{
+		detail::tmat4x4<T> Result(detail::tmat4x4<T>::null);
+		Result[0] = m[0] * v[0];
+		Result[1] = m[1] * v[1];
+		Result[2] = m[2] * v[2];
+		Result[3] = m[3];
+		return Result;
+	}
+
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<T> translate_slow
+	(
+		detail::tmat4x4<T> const & m,
+		detail::tvec3<T> const & v
+	)
+	{
+		detail::tmat4x4<T> Result(T(1));
+		Result[3] = detail::tvec4<T>(v, T(1));
+		return m * Result;
+
+		//detail::tmat4x4<valType> Result(m);
+		Result[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3];
+		//Result[3][0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0];
+		//Result[3][1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1];
+		//Result[3][2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2];
+		//Result[3][3] = m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3];
+		//return Result;
+	}
 		
 		
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<T> rotate_slow
-(
-	detail::tmat4x4<T> const & m,
-	T const & angle, 
-	detail::tvec3<T> const & v
-)
-{
-    T a = radians(angle);
-    T c = cos(a);
-    T s = sin(a);
-    detail::tmat4x4<T> Result;
-
-    detail::tvec3<T> axis = normalize(v);
-
-    Result[0][0] = c + (1 - c)      * axis.x     * axis.x;
-	Result[0][1] = (1 - c) * axis.x * axis.y + s * axis.z;
-	Result[0][2] = (1 - c) * axis.x * axis.z - s * axis.y;
-	Result[0][3] = 0;
-
-	Result[1][0] = (1 - c) * axis.y * axis.x - s * axis.z;
-	Result[1][1] = c + (1 - c) * axis.y * axis.y;
-	Result[1][2] = (1 - c) * axis.y * axis.z + s * axis.x;
-	Result[1][3] = 0;
-
-	Result[2][0] = (1 - c) * axis.z * axis.x + s * axis.y;
-	Result[2][1] = (1 - c) * axis.z * axis.y - s * axis.x;
-	Result[2][2] = c + (1 - c) * axis.z * axis.z;
-	Result[2][3] = 0;
-
-    Result[3] = detail::tvec4<T>(0, 0, 0, 1);
-    return m * Result;
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<T> scale_slow
-(
-	detail::tmat4x4<T> const & m,
-	detail::tvec3<T> const & v
-)
-{
-    detail::tmat4x4<T> Result(T(1));
-    Result[0][0] = v.x;
-    Result[1][1] = v.y;
-    Result[2][2] = v.z;
-    return m * Result;
-}
-
-template <typename valType> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<valType> ortho
-(
-	valType const & left, 
-	valType const & right, 
-	valType const & bottom, 
-	valType const & top, 
-	valType const & zNear, 
-	valType const & zFar
-)
-{
-	detail::tmat4x4<valType> Result(1);
-	Result[0][0] = valType(2) / (right - left);
-	Result[1][1] = valType(2) / (top - bottom);
-	Result[2][2] = - valType(2) / (zFar - zNear);
-	Result[3][0] = - (right + left) / (right - left);
-	Result[3][1] = - (top + bottom) / (top - bottom);
-	Result[3][2] = - (zFar + zNear) / (zFar - zNear);
-	return Result;
-}
-
-template <typename valType> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<valType> ortho(
-	valType const & left, 
-	valType const & right, 
-	valType const & bottom, 
-	valType const & top)
-{
-	detail::tmat4x4<valType> Result(1);
-	Result[0][0] = valType(2) / (right - left);
-	Result[1][1] = valType(2) / (top - bottom);
-	Result[2][2] = - valType(1);
-	Result[3][0] = - (right + left) / (right - left);
-	Result[3][1] = - (top + bottom) / (top - bottom);
-	return Result;
-}
-
-template <typename valType> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<valType> frustum
-(
-	valType const & left, 
-	valType const & right, 
-	valType const & bottom, 
-	valType const & top, 
-	valType const & nearVal, 
-	valType const & farVal
-)
-{
-	detail::tmat4x4<valType> Result(0);
-	Result[0][0] = (valType(2) * nearVal) / (right - left);
-	Result[1][1] = (valType(2) * nearVal) / (top - bottom);
-	Result[2][0] = (right + left) / (right - left);
-	Result[2][1] = (top + bottom) / (top - bottom);
-	Result[2][2] = -(farVal + nearVal) / (farVal - nearVal);
-	Result[2][3] = valType(-1);
-	Result[3][2] = -(valType(2) * farVal * nearVal) / (farVal - nearVal);
-	return Result;
-}
-
-template <typename valType> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<valType> perspective
-(
-	valType const & fovy, 
-	valType const & aspect, 
-	valType const & zNear, 
-	valType const & zFar
-)
-{
-	valType range = tan(radians(fovy / valType(2))) * zNear;	
-	valType left = -range * aspect;
-	valType right = range * aspect;
-	valType bottom = -range;
-	valType top = range;
-
-	detail::tmat4x4<valType> Result(valType(0));
-	Result[0][0] = (valType(2) * zNear) / (right - left);
-	Result[1][1] = (valType(2) * zNear) / (top - bottom);
-	Result[2][2] = - (zFar + zNear) / (zFar - zNear);
-	Result[2][3] = - valType(1);
-	Result[3][2] = - (valType(2) * zFar * zNear) / (zFar - zNear);
-	return Result;
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER detail::tmat4x4<valType> perspectiveFov
-(
-	valType const & fov, 
-	valType const & width, 
-	valType const & height, 
-	valType const & zNear, 
-	valType const & zFar
-)
-{
-	valType rad = glm::radians(fov);
-	valType h = glm::cos(valType(0.5) * rad) / glm::sin(valType(0.5) * rad);
-	valType w = h * height / width;
-
-	detail::tmat4x4<valType> Result(valType(0));
-	Result[0][0] = w;
-	Result[1][1] = h;
-	Result[2][2] = (zFar + zNear) / (zFar - zNear);
-	Result[2][3] = valType(1);
-	Result[3][2] = -(valType(2) * zFar * zNear) / (zFar - zNear);
-	return Result;
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<T> infinitePerspective
-(
-	T fovy, 
-	T aspect, 
-	T zNear
-)
-{
-	T range = tan(radians(fovy / T(2))) * zNear;	
-	T left = -range * aspect;
-	T right = range * aspect;
-	T bottom = -range;
-	T top = range;
-
-	detail::tmat4x4<T> Result(T(0));
-	Result[0][0] = (T(2) * zNear) / (right - left);
-	Result[1][1] = (T(2) * zNear) / (top - bottom);
-	Result[2][2] = - T(1);
-	Result[2][3] = - T(1);
-	Result[3][2] = - T(2) * zNear;
-	return Result;
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<T> tweakedInfinitePerspective
-(
-	T fovy, 
-	T aspect, 
-	T zNear
-)
-{
-	T range = tan(radians(fovy / T(2))) * zNear;	
-	T left = -range * aspect;
-	T right = range * aspect;
-	T bottom = -range;
-	T top = range;
-
-	detail::tmat4x4<T> Result(T(0));
-	Result[0][0] = (T(2) * zNear) / (right - left);
-	Result[1][1] = (T(2) * zNear) / (top - bottom);
-	Result[2][2] = T(0.0001) - T(1);
-	Result[2][3] = T(-1);
-	Result[3][2] = - (T(0.0001) - T(2)) * zNear;
-	return Result;
-}
-
-template <typename T, typename U>
-GLM_FUNC_QUALIFIER detail::tvec3<T> project
-(
-	detail::tvec3<T> const & obj, 
-	detail::tmat4x4<T> const & model, 
-	detail::tmat4x4<T> const & proj, 
-	detail::tvec4<U> const & viewport
-)
-{
-	detail::tvec4<T> tmp = detail::tvec4<T>(obj, T(1));
-	tmp = model * tmp;
-	tmp = proj * tmp;
-
-	tmp /= tmp.w;
-	tmp = tmp * T(0.5) + T(0.5);
-	tmp[0] = tmp[0] * T(viewport[2]) + T(viewport[0]);
-	tmp[1] = tmp[1] * T(viewport[3]) + T(viewport[1]);
-
-	return detail::tvec3<T>(tmp);
-}
-
-template <typename T, typename U>
-GLM_FUNC_QUALIFIER detail::tvec3<T> unProject
-(
-	detail::tvec3<T> const & win, 
-	detail::tmat4x4<T> const & model, 
-	detail::tmat4x4<T> const & proj, 
-	detail::tvec4<U> const & viewport
-)
-{
-	detail::tmat4x4<T> inverse = glm::inverse(proj * model);
-
-	detail::tvec4<T> tmp = detail::tvec4<T>(win, T(1));
-	tmp.x = (tmp.x - T(viewport[0])) / T(viewport[2]);
-	tmp.y = (tmp.y - T(viewport[1])) / T(viewport[3]);
-	tmp = tmp * T(2) - T(1);
-
-	detail::tvec4<T> obj = inverse * tmp;
-	obj /= obj.w;
-
-	return detail::tvec3<T>(obj);
-}
-
-template <typename T, typename U> 
-detail::tmat4x4<T> pickMatrix
-(
-	detail::tvec2<T> const & center, 
-	detail::tvec2<T> const & delta, 
-	detail::tvec4<U> const & viewport
-)
-{
-	assert(delta.x > T(0) && delta.y > T(0));
-	detail::tmat4x4<T> Result(1.0f);
-
-	if(!(delta.x > T(0) && delta.y > T(0))) 
-		return Result; // Error
-
-	detail::tvec3<T> Temp(
-		(T(viewport[2]) - T(2) * (center.x - T(viewport[0]))) / delta.x,
-		(T(viewport[3]) - T(2) * (center.y - T(viewport[1]))) / delta.y,
-		T(0));
-
-	// Translate and scale the picked region to the entire window
-	Result = translate(Result, Temp);
-	return scale(Result, detail::tvec3<T>(T(viewport[2]) / delta.x, T(viewport[3]) / delta.y, T(1)));
-}
-
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tmat4x4<T> lookAt
-(
-	detail::tvec3<T> const & eye,
-	detail::tvec3<T> const & center,
-	detail::tvec3<T> const & up
-)
-{
-    detail::tvec3<T> f = normalize(center - eye);
-    detail::tvec3<T> u = normalize(up);
-    detail::tvec3<T> s = normalize(cross(f, u));
-    u = cross(s, f);
-
-    detail::tmat4x4<T> Result(1);
-    Result[0][0] = s.x;
-    Result[1][0] = s.y;
-    Result[2][0] = s.z;
-    Result[0][1] = u.x;
-    Result[1][1] = u.y;
-    Result[2][1] = u.z;
-    Result[0][2] =-f.x;
-    Result[1][2] =-f.y;
-    Result[2][2] =-f.z;
-/*  Test this instead of translate3D
-    Result[3][0] =-dot(s, eye);
-    Result[3][1] =-dot(y, eye);
-    Result[3][2] = dot(f, eye);
-*/  
-	return translate(Result, -eye);
-}
-
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<T> rotate_slow
+	(
+		detail::tmat4x4<T> const & m,
+		T const & angle, 
+		detail::tvec3<T> const & v
+	)
+	{
+		T a = radians(angle);
+		T c = cos(a);
+		T s = sin(a);
+		detail::tmat4x4<T> Result;
+
+		detail::tvec3<T> axis = normalize(v);
+
+		Result[0][0] = c + (1 - c)      * axis.x     * axis.x;
+		Result[0][1] = (1 - c) * axis.x * axis.y + s * axis.z;
+		Result[0][2] = (1 - c) * axis.x * axis.z - s * axis.y;
+		Result[0][3] = 0;
+
+		Result[1][0] = (1 - c) * axis.y * axis.x - s * axis.z;
+		Result[1][1] = c + (1 - c) * axis.y * axis.y;
+		Result[1][2] = (1 - c) * axis.y * axis.z + s * axis.x;
+		Result[1][3] = 0;
+
+		Result[2][0] = (1 - c) * axis.z * axis.x + s * axis.y;
+		Result[2][1] = (1 - c) * axis.z * axis.y - s * axis.x;
+		Result[2][2] = c + (1 - c) * axis.z * axis.z;
+		Result[2][3] = 0;
+
+		Result[3] = detail::tvec4<T>(0, 0, 0, 1);
+		return m * Result;
+	}
+
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<T> scale_slow
+	(
+		detail::tmat4x4<T> const & m,
+		detail::tvec3<T> const & v
+	)
+	{
+		detail::tmat4x4<T> Result(T(1));
+		Result[0][0] = v.x;
+		Result[1][1] = v.y;
+		Result[2][2] = v.z;
+		return m * Result;
+	}
+
+	template <typename valType> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> ortho
+	(
+		valType const & left, 
+		valType const & right, 
+		valType const & bottom, 
+		valType const & top, 
+		valType const & zNear, 
+		valType const & zFar
+	)
+	{
+		detail::tmat4x4<valType> Result(1);
+		Result[0][0] = valType(2) / (right - left);
+		Result[1][1] = valType(2) / (top - bottom);
+		Result[2][2] = - valType(2) / (zFar - zNear);
+		Result[3][0] = - (right + left) / (right - left);
+		Result[3][1] = - (top + bottom) / (top - bottom);
+		Result[3][2] = - (zFar + zNear) / (zFar - zNear);
+		return Result;
+	}
+
+	template <typename valType> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> ortho(
+		valType const & left, 
+		valType const & right, 
+		valType const & bottom, 
+		valType const & top)
+	{
+		detail::tmat4x4<valType> Result(1);
+		Result[0][0] = valType(2) / (right - left);
+		Result[1][1] = valType(2) / (top - bottom);
+		Result[2][2] = - valType(1);
+		Result[3][0] = - (right + left) / (right - left);
+		Result[3][1] = - (top + bottom) / (top - bottom);
+		return Result;
+	}
+
+	template <typename valType> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> frustum
+	(
+		valType const & left, 
+		valType const & right, 
+		valType const & bottom, 
+		valType const & top, 
+		valType const & nearVal, 
+		valType const & farVal
+	)
+	{
+		detail::tmat4x4<valType> Result(0);
+		Result[0][0] = (valType(2) * nearVal) / (right - left);
+		Result[1][1] = (valType(2) * nearVal) / (top - bottom);
+		Result[2][0] = (right + left) / (right - left);
+		Result[2][1] = (top + bottom) / (top - bottom);
+		Result[2][2] = -(farVal + nearVal) / (farVal - nearVal);
+		Result[2][3] = valType(-1);
+		Result[3][2] = -(valType(2) * farVal * nearVal) / (farVal - nearVal);
+		return Result;
+	}
+
+	template <typename valType> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> perspective
+	(
+		valType const & fovy, 
+		valType const & aspect, 
+		valType const & zNear, 
+		valType const & zFar
+	)
+	{
+		valType range = tan(radians(fovy / valType(2))) * zNear;	
+		valType left = -range * aspect;
+		valType right = range * aspect;
+		valType bottom = -range;
+		valType top = range;
+
+		detail::tmat4x4<valType> Result(valType(0));
+		Result[0][0] = (valType(2) * zNear) / (right - left);
+		Result[1][1] = (valType(2) * zNear) / (top - bottom);
+		Result[2][2] = - (zFar + zNear) / (zFar - zNear);
+		Result[2][3] = - valType(1);
+		Result[3][2] = - (valType(2) * zFar * zNear) / (zFar - zNear);
+		return Result;
+	}
+
+	template <typename valType>
+	GLM_FUNC_QUALIFIER detail::tmat4x4<valType> perspectiveFov
+	(
+		valType const & fov, 
+		valType const & width, 
+		valType const & height, 
+		valType const & zNear, 
+		valType const & zFar
+	)
+	{
+		valType rad = glm::radians(fov);
+		valType h = glm::cos(valType(0.5) * rad) / glm::sin(valType(0.5) * rad);
+		valType w = h * height / width;
+
+		detail::tmat4x4<valType> Result(valType(0));
+		Result[0][0] = w;
+		Result[1][1] = h;
+		Result[2][2] = (zFar + zNear) / (zFar - zNear);
+		Result[2][3] = valType(1);
+		Result[3][2] = -(valType(2) * zFar * zNear) / (zFar - zNear);
+		return Result;
+	}
+
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<T> infinitePerspective
+	(
+		T fovy, 
+		T aspect, 
+		T zNear
+	)
+	{
+		T range = tan(radians(fovy / T(2))) * zNear;	
+		T left = -range * aspect;
+		T right = range * aspect;
+		T bottom = -range;
+		T top = range;
+
+		detail::tmat4x4<T> Result(T(0));
+		Result[0][0] = (T(2) * zNear) / (right - left);
+		Result[1][1] = (T(2) * zNear) / (top - bottom);
+		Result[2][2] = - T(1);
+		Result[2][3] = - T(1);
+		Result[3][2] = - T(2) * zNear;
+		return Result;
+	}
+
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<T> tweakedInfinitePerspective
+	(
+		T fovy, 
+		T aspect, 
+		T zNear
+	)
+	{
+		T range = tan(radians(fovy / T(2))) * zNear;	
+		T left = -range * aspect;
+		T right = range * aspect;
+		T bottom = -range;
+		T top = range;
+
+		detail::tmat4x4<T> Result(T(0));
+		Result[0][0] = (T(2) * zNear) / (right - left);
+		Result[1][1] = (T(2) * zNear) / (top - bottom);
+		Result[2][2] = T(0.0001) - T(1);
+		Result[2][3] = T(-1);
+		Result[3][2] = - (T(0.0001) - T(2)) * zNear;
+		return Result;
+	}
+
+	template <typename T, typename U>
+	GLM_FUNC_QUALIFIER detail::tvec3<T> project
+	(
+		detail::tvec3<T> const & obj, 
+		detail::tmat4x4<T> const & model, 
+		detail::tmat4x4<T> const & proj, 
+		detail::tvec4<U> const & viewport
+	)
+	{
+		detail::tvec4<T> tmp = detail::tvec4<T>(obj, T(1));
+		tmp = model * tmp;
+		tmp = proj * tmp;
+
+		tmp /= tmp.w;
+		tmp = tmp * T(0.5) + T(0.5);
+		tmp[0] = tmp[0] * T(viewport[2]) + T(viewport[0]);
+		tmp[1] = tmp[1] * T(viewport[3]) + T(viewport[1]);
+
+		return detail::tvec3<T>(tmp);
+	}
+
+	template <typename T, typename U>
+	GLM_FUNC_QUALIFIER detail::tvec3<T> unProject
+	(
+		detail::tvec3<T> const & win, 
+		detail::tmat4x4<T> const & model, 
+		detail::tmat4x4<T> const & proj, 
+		detail::tvec4<U> const & viewport
+	)
+	{
+		detail::tmat4x4<T> inverse = glm::inverse(proj * model);
+
+		detail::tvec4<T> tmp = detail::tvec4<T>(win, T(1));
+		tmp.x = (tmp.x - T(viewport[0])) / T(viewport[2]);
+		tmp.y = (tmp.y - T(viewport[1])) / T(viewport[3]);
+		tmp = tmp * T(2) - T(1);
+
+		detail::tvec4<T> obj = inverse * tmp;
+		obj /= obj.w;
+
+		return detail::tvec3<T>(obj);
+	}
+
+	template <typename T, typename U> 
+	detail::tmat4x4<T> pickMatrix
+	(
+		detail::tvec2<T> const & center, 
+		detail::tvec2<T> const & delta, 
+		detail::tvec4<U> const & viewport
+	)
+	{
+		assert(delta.x > T(0) && delta.y > T(0));
+		detail::tmat4x4<T> Result(1.0f);
+
+		if(!(delta.x > T(0) && delta.y > T(0))) 
+			return Result; // Error
+
+		detail::tvec3<T> Temp(
+			(T(viewport[2]) - T(2) * (center.x - T(viewport[0]))) / delta.x,
+			(T(viewport[3]) - T(2) * (center.y - T(viewport[1]))) / delta.y,
+			T(0));
+
+		// Translate and scale the picked region to the entire window
+		Result = translate(Result, Temp);
+		return scale(Result, detail::tvec3<T>(T(viewport[2]) / delta.x, T(viewport[3]) / delta.y, T(1)));
+	}
+
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tmat4x4<T> lookAt
+	(
+		detail::tvec3<T> const & eye,
+		detail::tvec3<T> const & center,
+		detail::tvec3<T> const & up
+	)
+	{
+		detail::tvec3<T> f = normalize(center - eye);
+		detail::tvec3<T> u = normalize(up);
+		detail::tvec3<T> s = normalize(cross(f, u));
+		u = cross(s, f);
+
+		detail::tmat4x4<T> Result(1);
+		Result[0][0] = s.x;
+		Result[1][0] = s.y;
+		Result[2][0] = s.z;
+		Result[0][1] = u.x;
+		Result[1][1] = u.y;
+		Result[2][1] = u.z;
+		Result[0][2] =-f.x;
+		Result[1][2] =-f.y;
+		Result[2][2] =-f.z;
+	/*  Test this instead of translate3D
+		Result[3][0] =-dot(s, eye);
+		Result[3][1] =-dot(y, eye);
+		Result[3][2] = dot(f, eye);
+	*/  
+		return translate(Result, -eye);
+	}
 }//namespace glm
 }//namespace glm

+ 831 - 832
glm/gtc/noise.inl

@@ -15,838 +15,837 @@
 // - GLM core
 // - GLM core
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 
-namespace glm{
-
-template <typename T>
-GLM_FUNC_QUALIFIER T mod289(T const & x)
-{
-	return x - floor(x * T(1.0 / 289.0)) * T(289.0);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER T permute(T const & x)
+namespace glm
 {
 {
-	return mod289(((x * T(34)) + T(1)) * x);
-}
-
-template <typename T, template<typename> class vecType>
-GLM_FUNC_QUALIFIER vecType<T> permute(vecType<T> const & x)
-{
-	return mod289(((x * T(34)) + T(1)) * x);
-}
+	template <typename T>
+	GLM_FUNC_QUALIFIER T mod289(T const & x)
+	{
+		return x - floor(x * T(1.0 / 289.0)) * T(289.0);
+	}
+
+	template <typename T>
+	GLM_FUNC_QUALIFIER T permute(T const & x)
+	{
+		return mod289(((x * T(34)) + T(1)) * x);
+	}
+
+	template <typename T, template<typename> class vecType>
+	GLM_FUNC_QUALIFIER vecType<T> permute(vecType<T> const & x)
+	{
+		return mod289(((x * T(34)) + T(1)) * x);
+	}
   
   
-template <typename T>
-GLM_FUNC_QUALIFIER T taylorInvSqrt(T const & r)
-{
-	return T(1.79284291400159) - T(0.85373472095314) * r;
-}
-
-template <typename T, template<typename> class vecType>
-GLM_FUNC_QUALIFIER vecType<T> taylorInvSqrt(vecType<T> const & r)
-{
-	return T(1.79284291400159) - T(0.85373472095314) * r;
-}
-
-template <typename T, template <typename> class vecType> 
-GLM_FUNC_QUALIFIER vecType<T> fade(vecType<T> const & t) 
-{
-	return t * t * t * (t * (t * T(6) - T(15)) + T(10));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec4<T> grad4(T const & j, detail::tvec4<T> const & ip)
-{
-	detail::tvec3<T> pXYZ = floor(fract(detail::tvec3<T>(j) * detail::tvec3<T>(ip)) * T(7)) * ip[2] - T(1);
-	T pW = T(1.5) - dot(abs(pXYZ), detail::tvec3<T>(1));
-	detail::tvec4<T> s = detail::tvec4<T>(lessThan(detail::tvec4<T>(pXYZ, pW), detail::tvec4<T>(0.0)));
-	pXYZ = pXYZ + (detail::tvec3<T>(s) * T(2) - T(1)) * s.w; 
-	return detail::tvec4<T>(pXYZ, pW);
-}
-
-// Classic Perlin noise
-template <typename T>
-GLM_FUNC_QUALIFIER T perlin(detail::tvec2<T> const & P)
-{
-	detail::tvec4<T> Pi = glm::floor(detail::tvec4<T>(P.x, P.y, P.x, P.y)) + detail::tvec4<T>(0.0, 0.0, 1.0, 1.0);
-	detail::tvec4<T> Pf = glm::fract(detail::tvec4<T>(P.x, P.y, P.x, P.y)) - detail::tvec4<T>(0.0, 0.0, 1.0, 1.0);
-	Pi = mod(Pi, T(289)); // To avoid truncation effects in permutation
-	detail::tvec4<T> ix(Pi.x, Pi.z, Pi.x, Pi.z);
-	detail::tvec4<T> iy(Pi.y, Pi.y, Pi.w, Pi.w);
-	detail::tvec4<T> fx(Pf.x, Pf.z, Pf.x, Pf.z);
-	detail::tvec4<T> fy(Pf.y, Pf.y, Pf.w, Pf.w);
-
-	detail::tvec4<T> i = glm::permute(glm::permute(ix) + iy);
-
-	detail::tvec4<T> gx = T(2) * glm::fract(i / T(41)) - T(1);
-	detail::tvec4<T> gy = glm::abs(gx) - T(0.5);
-	detail::tvec4<T> tx = glm::floor(gx + T(0.5));
-	gx = gx - tx;
-
-	detail::tvec2<T> g00(gx.x, gy.x);
-	detail::tvec2<T> g10(gx.y, gy.y);
-	detail::tvec2<T> g01(gx.z, gy.z);
-	detail::tvec2<T> g11(gx.w, gy.w);
-
-	detail::tvec4<T> norm = taylorInvSqrt(detail::tvec4<T>(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)));
-	g00 *= norm.x;  
-	g01 *= norm.y;  
-	g10 *= norm.z;  
-	g11 *= norm.w;  
-
-	T n00 = dot(g00, detail::tvec2<T>(fx.x, fy.x));
-	T n10 = dot(g10, detail::tvec2<T>(fx.y, fy.y));
-	T n01 = dot(g01, detail::tvec2<T>(fx.z, fy.z));
-	T n11 = dot(g11, detail::tvec2<T>(fx.w, fy.w));
-
-	detail::tvec2<T> fade_xy = fade(detail::tvec2<T>(Pf.x, Pf.y));
-	detail::tvec2<T> n_x = mix(detail::tvec2<T>(n00, n01), detail::tvec2<T>(n10, n11), fade_xy.x);
-	T n_xy = mix(n_x.x, n_x.y, fade_xy.y);
-	return T(2.3) * n_xy;
-}
-
-// Classic Perlin noise
-template <typename T>
-GLM_FUNC_QUALIFIER T perlin(detail::tvec3<T> const & P)
-{
-	detail::tvec3<T> Pi0 = floor(P); // Integer part for indexing
-	detail::tvec3<T> Pi1 = Pi0 + T(1); // Integer part + 1
-	Pi0 = mod289(Pi0);
-	Pi1 = mod289(Pi1);
-	detail::tvec3<T> Pf0 = fract(P); // Fractional part for interpolation
-	detail::tvec3<T> Pf1 = Pf0 - T(1); // Fractional part - 1.0
-	detail::tvec4<T> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
-	detail::tvec4<T> iy = detail::tvec4<T>(detail::tvec2<T>(Pi0.y), detail::tvec2<T>(Pi1.y));
-	detail::tvec4<T> iz0(Pi0.z);
-	detail::tvec4<T> iz1(Pi1.z);
-
-	detail::tvec4<T> ixy = permute(permute(ix) + iy);
-	detail::tvec4<T> ixy0 = permute(ixy + iz0);
-	detail::tvec4<T> ixy1 = permute(ixy + iz1);
-
-	detail::tvec4<T> gx0 = ixy0 * T(1.0 / 7.0);
-	detail::tvec4<T> gy0 = fract(floor(gx0) * T(1.0 / 7.0)) - T(0.5);
-	gx0 = fract(gx0);
-	detail::tvec4<T> gz0 = detail::tvec4<T>(0.5) - abs(gx0) - abs(gy0);
-	detail::tvec4<T> sz0 = step(gz0, detail::tvec4<T>(0.0));
-	gx0 -= sz0 * (step(T(0), gx0) - T(0.5));
-	gy0 -= sz0 * (step(T(0), gy0) - T(0.5));
-
-	detail::tvec4<T> gx1 = ixy1 * T(1.0 / 7.0);
-	detail::tvec4<T> gy1 = fract(floor(gx1) * T(1.0 / 7.0)) - T(0.5);
-	gx1 = fract(gx1);
-	detail::tvec4<T> gz1 = detail::tvec4<T>(0.5) - abs(gx1) - abs(gy1);
-	detail::tvec4<T> sz1 = step(gz1, detail::tvec4<T>(0.0));
-	gx1 -= sz1 * (step(T(0), gx1) - T(0.5));
-	gy1 -= sz1 * (step(T(0), gy1) - T(0.5));
-
-	detail::tvec3<T> g000(gx0.x, gy0.x, gz0.x);
-	detail::tvec3<T> g100(gx0.y, gy0.y, gz0.y);
-	detail::tvec3<T> g010(gx0.z, gy0.z, gz0.z);
-	detail::tvec3<T> g110(gx0.w, gy0.w, gz0.w);
-	detail::tvec3<T> g001(gx1.x, gy1.x, gz1.x);
-	detail::tvec3<T> g101(gx1.y, gy1.y, gz1.y);
-	detail::tvec3<T> g011(gx1.z, gy1.z, gz1.z);
-	detail::tvec3<T> g111(gx1.w, gy1.w, gz1.w);
-
-	detail::tvec4<T> norm0 = taylorInvSqrt(detail::tvec4<T>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
-	g000 *= norm0.x;
-	g010 *= norm0.y;
-	g100 *= norm0.z;
-	g110 *= norm0.w;
-	detail::tvec4<T> norm1 = taylorInvSqrt(detail::tvec4<T>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
-	g001 *= norm1.x;
-	g011 *= norm1.y;
-	g101 *= norm1.z;
-	g111 *= norm1.w;
-
-	T n000 = dot(g000, Pf0);
-	T n100 = dot(g100, detail::tvec3<T>(Pf1.x, Pf0.y, Pf0.z));
-	T n010 = dot(g010, detail::tvec3<T>(Pf0.x, Pf1.y, Pf0.z));
-	T n110 = dot(g110, detail::tvec3<T>(Pf1.x, Pf1.y, Pf0.z));
-	T n001 = dot(g001, detail::tvec3<T>(Pf0.x, Pf0.y, Pf1.z));
-	T n101 = dot(g101, detail::tvec3<T>(Pf1.x, Pf0.y, Pf1.z));
-	T n011 = dot(g011, detail::tvec3<T>(Pf0.x, Pf1.y, Pf1.z));
-	T n111 = dot(g111, Pf1);
-
-	detail::tvec3<T> fade_xyz = fade(Pf0);
-	detail::tvec4<T> n_z = mix(detail::tvec4<T>(n000, n100, n010, n110), detail::tvec4<T>(n001, n101, n011, n111), fade_xyz.z);
-	detail::tvec2<T> n_yz = mix(detail::tvec2<T>(n_z.x, n_z.y), detail::tvec2<T>(n_z.z, n_z.w), fade_xyz.y);
-	T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); 
-	return T(2.2) * n_xyz;
-}
-/*
-// Classic Perlin noise
-template <typename T>
-GLM_FUNC_QUALIFIER T perlin(detail::tvec3<T> const & P)
-{
-	detail::tvec3<T> Pi0 = floor(P); // Integer part for indexing
-	detail::tvec3<T> Pi1 = Pi0 + T(1); // Integer part + 1
-	Pi0 = mod(Pi0, T(289));
-	Pi1 = mod(Pi1, T(289));
-	detail::tvec3<T> Pf0 = fract(P); // Fractional part for interpolation
-	detail::tvec3<T> Pf1 = Pf0 - T(1); // Fractional part - 1.0
-	detail::tvec4<T> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
-	detail::tvec4<T> iy(Pi0.y, Pi0.y, Pi1.y, Pi1.y);
-	detail::tvec4<T> iz0(Pi0.z);
-	detail::tvec4<T> iz1(Pi1.z);
-
-	detail::tvec4<T> ixy = permute(permute(ix) + iy);
-	detail::tvec4<T> ixy0 = permute(ixy + iz0);
-	detail::tvec4<T> ixy1 = permute(ixy + iz1);
-
-	detail::tvec4<T> gx0 = ixy0 / T(7);
-	detail::tvec4<T> gy0 = fract(floor(gx0) / T(7)) - T(0.5);
-	gx0 = fract(gx0);
-	detail::tvec4<T> gz0 = detail::tvec4<T>(0.5) - abs(gx0) - abs(gy0);
-	detail::tvec4<T> sz0 = step(gz0, detail::tvec4<T>(0.0));
-	gx0 -= sz0 * (step(0.0, gx0) - T(0.5));
-	gy0 -= sz0 * (step(0.0, gy0) - T(0.5));
-
-	detail::tvec4<T> gx1 = ixy1 / T(7);
-	detail::tvec4<T> gy1 = fract(floor(gx1) / T(7)) - T(0.5);
-	gx1 = fract(gx1);
-	detail::tvec4<T> gz1 = detail::tvec4<T>(0.5) - abs(gx1) - abs(gy1);
-	detail::tvec4<T> sz1 = step(gz1, detail::tvec4<T>(0.0));
-	gx1 -= sz1 * (step(T(0), gx1) - T(0.5));
-	gy1 -= sz1 * (step(T(0), gy1) - T(0.5));
-
-	detail::tvec3<T> g000(gx0.x, gy0.x, gz0.x);
-	detail::tvec3<T> g100(gx0.y, gy0.y, gz0.y);
-	detail::tvec3<T> g010(gx0.z, gy0.z, gz0.z);
-	detail::tvec3<T> g110(gx0.w, gy0.w, gz0.w);
-	detail::tvec3<T> g001(gx1.x, gy1.x, gz1.x);
-	detail::tvec3<T> g101(gx1.y, gy1.y, gz1.y);
-	detail::tvec3<T> g011(gx1.z, gy1.z, gz1.z);
-	detail::tvec3<T> g111(gx1.w, gy1.w, gz1.w);
-
-	detail::tvec4<T> norm0 = taylorInvSqrt(detail::tvec4<T>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
-	g000 *= norm0.x;
-	g010 *= norm0.y;
-	g100 *= norm0.z;
-	g110 *= norm0.w;
-	detail::tvec4<T> norm1 = taylorInvSqrt(detail::tvec4<T>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
-	g001 *= norm1.x;
-	g011 *= norm1.y;
-	g101 *= norm1.z;
-	g111 *= norm1.w;
-
-	T n000 = dot(g000, Pf0);
-	T n100 = dot(g100, detail::tvec3<T>(Pf1.x, Pf0.y, Pf0.z));
-	T n010 = dot(g010, detail::tvec3<T>(Pf0.x, Pf1.y, Pf0.z));
-	T n110 = dot(g110, detail::tvec3<T>(Pf1.x, Pf1.y, Pf0.z));
-	T n001 = dot(g001, detail::tvec3<T>(Pf0.x, Pf0.y, Pf1.z));
-	T n101 = dot(g101, detail::tvec3<T>(Pf1.x, Pf0.y, Pf1.z));
-	T n011 = dot(g011, detail::tvec3<T>(Pf0.x, Pf1.y, Pf1.z));
-	T n111 = dot(g111, Pf1);
-
-	detail::tvec3<T> fade_xyz = fade(Pf0);
-	detail::tvec4<T> n_z = mix(detail::tvec4<T>(n000, n100, n010, n110), detail::tvec4<T>(n001, n101, n011, n111), fade_xyz.z);
-	detail::tvec2<T> n_yz = mix(
-        detail::tvec2<T>(n_z.x, n_z.y), 
-        detail::tvec2<T>(n_z.z, n_z.w), fade_xyz.y);
-	T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); 
-	return T(2.2) * n_xyz;
-}
-*/
-// Classic Perlin noise
-template <typename T>
-GLM_FUNC_QUALIFIER T perlin(detail::tvec4<T> const & P)
-{
-	detail::tvec4<T> Pi0 = floor(P); // Integer part for indexing
-	detail::tvec4<T> Pi1 = Pi0 + T(1); // Integer part + 1
-	Pi0 = mod(Pi0, T(289));
-	Pi1 = mod(Pi1, T(289));
-	detail::tvec4<T> Pf0 = fract(P); // Fractional part for interpolation
-	detail::tvec4<T> Pf1 = Pf0 - T(1); // Fractional part - 1.0
-	detail::tvec4<T> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
-	detail::tvec4<T> iy(Pi0.y, Pi0.y, Pi1.y, Pi1.y);
-	detail::tvec4<T> iz0(Pi0.z);
-	detail::tvec4<T> iz1(Pi1.z);
-	detail::tvec4<T> iw0(Pi0.w);
-	detail::tvec4<T> iw1(Pi1.w);
-
-	detail::tvec4<T> ixy = permute(permute(ix) + iy);
-	detail::tvec4<T> ixy0 = permute(ixy + iz0);
-	detail::tvec4<T> ixy1 = permute(ixy + iz1);
-	detail::tvec4<T> ixy00 = permute(ixy0 + iw0);
-	detail::tvec4<T> ixy01 = permute(ixy0 + iw1);
-	detail::tvec4<T> ixy10 = permute(ixy1 + iw0);
-	detail::tvec4<T> ixy11 = permute(ixy1 + iw1);
-
-	detail::tvec4<T> gx00 = ixy00 / T(7);
-	detail::tvec4<T> gy00 = floor(gx00) / T(7);
-	detail::tvec4<T> gz00 = floor(gy00) / T(6);
-	gx00 = fract(gx00) - T(0.5);
-	gy00 = fract(gy00) - T(0.5);
-	gz00 = fract(gz00) - T(0.5);
-	detail::tvec4<T> gw00 = detail::tvec4<T>(0.75) - abs(gx00) - abs(gy00) - abs(gz00);
-	detail::tvec4<T> sw00 = step(gw00, detail::tvec4<T>(0.0));
-	gx00 -= sw00 * (step(T(0), gx00) - T(0.5));
-	gy00 -= sw00 * (step(T(0), gy00) - T(0.5));
-
-	detail::tvec4<T> gx01 = ixy01 / T(7);
-	detail::tvec4<T> gy01 = floor(gx01) / T(7);
-	detail::tvec4<T> gz01 = floor(gy01) / T(6);
-	gx01 = fract(gx01) - T(0.5);
-	gy01 = fract(gy01) - T(0.5);
-	gz01 = fract(gz01) - T(0.5);
-	detail::tvec4<T> gw01 = detail::tvec4<T>(0.75) - abs(gx01) - abs(gy01) - abs(gz01);
-	detail::tvec4<T> sw01 = step(gw01, detail::tvec4<T>(0.0));
-	gx01 -= sw01 * (step(T(0), gx01) - T(0.5));
-	gy01 -= sw01 * (step(T(0), gy01) - T(0.5));
-
-	detail::tvec4<T> gx10 = ixy10 / T(7);
-	detail::tvec4<T> gy10 = floor(gx10) / T(7);
-	detail::tvec4<T> gz10 = floor(gy10) / T(6);
-	gx10 = fract(gx10) - T(0.5);
-	gy10 = fract(gy10) - T(0.5);
-	gz10 = fract(gz10) - T(0.5);
-	detail::tvec4<T> gw10 = detail::tvec4<T>(0.75) - abs(gx10) - abs(gy10) - abs(gz10);
-	detail::tvec4<T> sw10 = step(gw10, detail::tvec4<T>(0));
-	gx10 -= sw10 * (step(T(0), gx10) - T(0.5));
-	gy10 -= sw10 * (step(T(0), gy10) - T(0.5));
-
-	detail::tvec4<T> gx11 = ixy11 / T(7);
-	detail::tvec4<T> gy11 = floor(gx11) / T(7);
-	detail::tvec4<T> gz11 = floor(gy11) / T(6);
-	gx11 = fract(gx11) - T(0.5);
-	gy11 = fract(gy11) - T(0.5);
-	gz11 = fract(gz11) - T(0.5);
-	detail::tvec4<T> gw11 = detail::tvec4<T>(0.75) - abs(gx11) - abs(gy11) - abs(gz11);
-	detail::tvec4<T> sw11 = step(gw11, detail::tvec4<T>(0.0));
-	gx11 -= sw11 * (step(T(0), gx11) - T(0.5));
-	gy11 -= sw11 * (step(T(0), gy11) - T(0.5));
-
-	detail::tvec4<T> g0000(gx00.x, gy00.x, gz00.x, gw00.x);
-	detail::tvec4<T> g1000(gx00.y, gy00.y, gz00.y, gw00.y);
-	detail::tvec4<T> g0100(gx00.z, gy00.z, gz00.z, gw00.z);
-	detail::tvec4<T> g1100(gx00.w, gy00.w, gz00.w, gw00.w);
-	detail::tvec4<T> g0010(gx10.x, gy10.x, gz10.x, gw10.x);
-	detail::tvec4<T> g1010(gx10.y, gy10.y, gz10.y, gw10.y);
-	detail::tvec4<T> g0110(gx10.z, gy10.z, gz10.z, gw10.z);
-	detail::tvec4<T> g1110(gx10.w, gy10.w, gz10.w, gw10.w);
-	detail::tvec4<T> g0001(gx01.x, gy01.x, gz01.x, gw01.x);
-	detail::tvec4<T> g1001(gx01.y, gy01.y, gz01.y, gw01.y);
-	detail::tvec4<T> g0101(gx01.z, gy01.z, gz01.z, gw01.z);
-	detail::tvec4<T> g1101(gx01.w, gy01.w, gz01.w, gw01.w);
-	detail::tvec4<T> g0011(gx11.x, gy11.x, gz11.x, gw11.x);
-	detail::tvec4<T> g1011(gx11.y, gy11.y, gz11.y, gw11.y);
-	detail::tvec4<T> g0111(gx11.z, gy11.z, gz11.z, gw11.z);
-	detail::tvec4<T> g1111(gx11.w, gy11.w, gz11.w, gw11.w);
-
-	detail::tvec4<T> norm00 = taylorInvSqrt(detail::tvec4<T>(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100)));
-	g0000 *= norm00.x;
-	g0100 *= norm00.y;
-	g1000 *= norm00.z;
-	g1100 *= norm00.w;
-
-	detail::tvec4<T> norm01 = taylorInvSqrt(detail::tvec4<T>(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101)));
-	g0001 *= norm01.x;
-	g0101 *= norm01.y;
-	g1001 *= norm01.z;
-	g1101 *= norm01.w;
-
-	detail::tvec4<T> norm10 = taylorInvSqrt(detail::tvec4<T>(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110)));
-	g0010 *= norm10.x;
-	g0110 *= norm10.y;
-	g1010 *= norm10.z;
-	g1110 *= norm10.w;
-
-	detail::tvec4<T> norm11 = taylorInvSqrt(detail::tvec4<T>(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111)));
-	g0011 *= norm11.x;
-	g0111 *= norm11.y;
-	g1011 *= norm11.z;
-	g1111 *= norm11.w;
-
-	T n0000 = dot(g0000, Pf0);
-	T n1000 = dot(g1000, detail::tvec4<T>(Pf1.x, Pf0.y, Pf0.z, Pf0.w));
-	T n0100 = dot(g0100, detail::tvec4<T>(Pf0.x, Pf1.y, Pf0.z, Pf0.w));
-	T n1100 = dot(g1100, detail::tvec4<T>(Pf1.x, Pf1.y, Pf0.z, Pf0.w));
-	T n0010 = dot(g0010, detail::tvec4<T>(Pf0.x, Pf0.y, Pf1.z, Pf0.w));
-	T n1010 = dot(g1010, detail::tvec4<T>(Pf1.x, Pf0.y, Pf1.z, Pf0.w));
-	T n0110 = dot(g0110, detail::tvec4<T>(Pf0.x, Pf1.y, Pf1.z, Pf0.w));
-	T n1110 = dot(g1110, detail::tvec4<T>(Pf1.x, Pf1.y, Pf1.z, Pf0.w));
-	T n0001 = dot(g0001, detail::tvec4<T>(Pf0.x, Pf0.y, Pf0.z, Pf1.w));
-	T n1001 = dot(g1001, detail::tvec4<T>(Pf1.x, Pf0.y, Pf0.z, Pf1.w));
-	T n0101 = dot(g0101, detail::tvec4<T>(Pf0.x, Pf1.y, Pf0.z, Pf1.w));
-	T n1101 = dot(g1101, detail::tvec4<T>(Pf1.x, Pf1.y, Pf0.z, Pf1.w));
-	T n0011 = dot(g0011, detail::tvec4<T>(Pf0.x, Pf0.y, Pf1.z, Pf1.w));
-	T n1011 = dot(g1011, detail::tvec4<T>(Pf1.x, Pf0.y, Pf1.z, Pf1.w));
-	T n0111 = dot(g0111, detail::tvec4<T>(Pf0.x, Pf1.y, Pf1.z, Pf1.w));
-	T n1111 = dot(g1111, Pf1);
-
-	detail::tvec4<T> fade_xyzw = fade(Pf0);
-	detail::tvec4<T> n_0w = mix(detail::tvec4<T>(n0000, n1000, n0100, n1100), detail::tvec4<T>(n0001, n1001, n0101, n1101), fade_xyzw.w);
-	detail::tvec4<T> n_1w = mix(detail::tvec4<T>(n0010, n1010, n0110, n1110), detail::tvec4<T>(n0011, n1011, n0111, n1111), fade_xyzw.w);
-	detail::tvec4<T> n_zw = mix(n_0w, n_1w, fade_xyzw.z);
-	detail::tvec2<T> n_yzw = mix(detail::tvec2<T>(n_zw.x, n_zw.y), detail::tvec2<T>(n_zw.z, n_zw.w), fade_xyzw.y);
-	T n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x);
-	return T(2.2) * n_xyzw;
-}
-
-// Classic Perlin noise, periodic variant
-template <typename T>
-GLM_FUNC_QUALIFIER T perlin(detail::tvec2<T> const & P, detail::tvec2<T> const & rep)
-{
-	detail::tvec4<T> Pi = floor(detail::tvec4<T>(P.x, P.y, P.x, P.y)) + detail::tvec4<T>(0.0, 0.0, 1.0, 1.0);
-	detail::tvec4<T> Pf = fract(detail::tvec4<T>(P.x, P.y, P.x, P.y)) - detail::tvec4<T>(0.0, 0.0, 1.0, 1.0);
-	Pi = mod(Pi, detail::tvec4<T>(rep.x, rep.y, rep.x, rep.y)); // To create noise with explicit period
-	Pi = mod(Pi, T(289)); // To avoid truncation effects in permutation
-	detail::tvec4<T> ix(Pi.x, Pi.z, Pi.x, Pi.z);
-	detail::tvec4<T> iy(Pi.y, Pi.y, Pi.w, Pi.w);
-	detail::tvec4<T> fx(Pf.x, Pf.z, Pf.x, Pf.z);
-	detail::tvec4<T> fy(Pf.y, Pf.y, Pf.w, Pf.w);
-
-	detail::tvec4<T> i = permute(permute(ix) + iy);
-
-	detail::tvec4<T> gx = T(2) * fract(i / T(41)) - T(1);
-	detail::tvec4<T> gy = abs(gx) - T(0.5);
-	detail::tvec4<T> tx = floor(gx + T(0.5));
-	gx = gx - tx;
-
-	detail::tvec2<T> g00(gx.x, gy.x);
-	detail::tvec2<T> g10(gx.y, gy.y);
-	detail::tvec2<T> g01(gx.z, gy.z);
-	detail::tvec2<T> g11(gx.w, gy.w);
-
-	detail::tvec4<T> norm = taylorInvSqrt(detail::tvec4<T>(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)));
-	g00 *= norm.x;  
-	g01 *= norm.y;  
-	g10 *= norm.z;  
-	g11 *= norm.w;  
-
-	T n00 = dot(g00, detail::tvec2<T>(fx.x, fy.x));
-	T n10 = dot(g10, detail::tvec2<T>(fx.y, fy.y));
-	T n01 = dot(g01, detail::tvec2<T>(fx.z, fy.z));
-	T n11 = dot(g11, detail::tvec2<T>(fx.w, fy.w));
-
-	detail::tvec2<T> fade_xy = fade(detail::tvec2<T>(Pf.x, Pf.y));
-	detail::tvec2<T> n_x = mix(detail::tvec2<T>(n00, n01), detail::tvec2<T>(n10, n11), fade_xy.x);
-	T n_xy = mix(n_x.x, n_x.y, fade_xy.y);
-	return T(2.3) * n_xy;
-}
-
-// Classic Perlin noise, periodic variant
-template <typename T>
-GLM_FUNC_QUALIFIER T perlin(detail::tvec3<T> const & P, detail::tvec3<T> const & rep)
-{
-	detail::tvec3<T> Pi0 = mod(floor(P), rep); // Integer part, modulo period
-	detail::tvec3<T> Pi1 = mod(Pi0 + detail::tvec3<T>(1.0), rep); // Integer part + 1, mod period
-	Pi0 = mod(Pi0, T(289));
-	Pi1 = mod(Pi1, T(289));
-	detail::tvec3<T> Pf0 = fract(P); // Fractional part for interpolation
-	detail::tvec3<T> Pf1 = Pf0 - detail::tvec3<T>(1.0); // Fractional part - 1.0
-	detail::tvec4<T> ix = detail::tvec4<T>(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
-	detail::tvec4<T> iy = detail::tvec4<T>(Pi0.y, Pi0.y, Pi1.y, Pi1.y);
-	detail::tvec4<T> iz0(Pi0.z);
-	detail::tvec4<T> iz1(Pi1.z);
-
-	detail::tvec4<T> ixy = permute(permute(ix) + iy);
-	detail::tvec4<T> ixy0 = permute(ixy + iz0);
-	detail::tvec4<T> ixy1 = permute(ixy + iz1);
-
-	detail::tvec4<T> gx0 = ixy0 / T(7);
-	detail::tvec4<T> gy0 = fract(floor(gx0) / T(7)) - T(0.5);
-	gx0 = fract(gx0);
-	detail::tvec4<T> gz0 = detail::tvec4<T>(0.5) - abs(gx0) - abs(gy0);
-	detail::tvec4<T> sz0 = step(gz0, detail::tvec4<T>(0));
-	gx0 -= sz0 * (step(0.0, gx0) - T(0.5));
-	gy0 -= sz0 * (step(0.0, gy0) - T(0.5));
-
-	detail::tvec4<T> gx1 = ixy1 / T(7);
-	detail::tvec4<T> gy1 = fract(floor(gx1) / T(7)) - T(0.5);
-	gx1 = fract(gx1);
-	detail::tvec4<T> gz1 = detail::tvec4<T>(0.5) - abs(gx1) - abs(gy1);
-	detail::tvec4<T> sz1 = step(gz1, detail::tvec4<T>(0.0));
-	gx1 -= sz1 * (step(0.0, gx1) - T(0.5));
-	gy1 -= sz1 * (step(0.0, gy1) - T(0.5));
-
-	detail::tvec3<T> g000 = detail::tvec3<T>(gx0.x, gy0.x, gz0.x);
-	detail::tvec3<T> g100 = detail::tvec3<T>(gx0.y, gy0.y, gz0.y);
-	detail::tvec3<T> g010 = detail::tvec3<T>(gx0.z, gy0.z, gz0.z);
-	detail::tvec3<T> g110 = detail::tvec3<T>(gx0.w, gy0.w, gz0.w);
-	detail::tvec3<T> g001 = detail::tvec3<T>(gx1.x, gy1.x, gz1.x);
-	detail::tvec3<T> g101 = detail::tvec3<T>(gx1.y, gy1.y, gz1.y);
-	detail::tvec3<T> g011 = detail::tvec3<T>(gx1.z, gy1.z, gz1.z);
-	detail::tvec3<T> g111 = detail::tvec3<T>(gx1.w, gy1.w, gz1.w);
-
-	detail::tvec4<T> norm0 = taylorInvSqrt(detail::tvec4<T>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
-	g000 *= norm0.x;
-	g010 *= norm0.y;
-	g100 *= norm0.z;
-	g110 *= norm0.w;
-	detail::tvec4<T> norm1 = taylorInvSqrt(detail::tvec4<T>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
-	g001 *= norm1.x;
-	g011 *= norm1.y;
-	g101 *= norm1.z;
-	g111 *= norm1.w;
-
-	T n000 = dot(g000, Pf0);
-	T n100 = dot(g100, detail::tvec3<T>(Pf1.x, Pf0.y, Pf0.z));
-	T n010 = dot(g010, detail::tvec3<T>(Pf0.x, Pf1.y, Pf0.z));
-	T n110 = dot(g110, detail::tvec3<T>(Pf1.x, Pf1.y, Pf0.z));
-	T n001 = dot(g001, detail::tvec3<T>(Pf0.x, Pf0.y, Pf1.z));
-	T n101 = dot(g101, detail::tvec3<T>(Pf1.x, Pf0.y, Pf1.z));
-	T n011 = dot(g011, detail::tvec3<T>(Pf0.x, Pf1.y, Pf1.z));
-	T n111 = dot(g111, Pf1);
-
-	detail::tvec3<T> fade_xyz = fade(Pf0);
-	detail::tvec4<T> n_z = mix(detail::tvec4<T>(n000, n100, n010, n110), detail::tvec4<T>(n001, n101, n011, n111), fade_xyz.z);
-	detail::tvec2<T> n_yz = mix(detail::tvec2<T>(n_z.x, n_z.y), detail::tvec2<T>(n_z.z, n_z.w), fade_xyz.y);
-	T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); 
-	return T(2.2) * n_xyz;
-}
-
-// Classic Perlin noise, periodic version
-template <typename T>
-GLM_FUNC_QUALIFIER T perlin(detail::tvec4<T> const & P, detail::tvec4<T> const & rep)
-{
-	detail::tvec4<T> Pi0 = mod(floor(P), rep); // Integer part modulo rep
-	detail::tvec4<T> Pi1 = mod(Pi0 + T(1), rep); // Integer part + 1 mod rep
-	detail::tvec4<T> Pf0 = fract(P); // Fractional part for interpolation
-	detail::tvec4<T> Pf1 = Pf0 - T(1); // Fractional part - 1.0
-	detail::tvec4<T> ix = detail::tvec4<T>(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
-	detail::tvec4<T> iy = detail::tvec4<T>(Pi0.y, Pi0.y, Pi1.y, Pi1.y);
-	detail::tvec4<T> iz0(Pi0.z);
-	detail::tvec4<T> iz1(Pi1.z);
-	detail::tvec4<T> iw0(Pi0.w);
-	detail::tvec4<T> iw1(Pi1.w);
-
-	detail::tvec4<T> ixy = permute(permute(ix) + iy);
-	detail::tvec4<T> ixy0 = permute(ixy + iz0);
-	detail::tvec4<T> ixy1 = permute(ixy + iz1);
-	detail::tvec4<T> ixy00 = permute(ixy0 + iw0);
-	detail::tvec4<T> ixy01 = permute(ixy0 + iw1);
-	detail::tvec4<T> ixy10 = permute(ixy1 + iw0);
-	detail::tvec4<T> ixy11 = permute(ixy1 + iw1);
-
-	detail::tvec4<T> gx00 = ixy00 / T(7);
-	detail::tvec4<T> gy00 = floor(gx00) / T(7);
-	detail::tvec4<T> gz00 = floor(gy00) / T(6);
-	gx00 = fract(gx00) - T(0.5);
-	gy00 = fract(gy00) - T(0.5);
-	gz00 = fract(gz00) - T(0.5);
-	detail::tvec4<T> gw00 = detail::tvec4<T>(0.75) - abs(gx00) - abs(gy00) - abs(gz00);
-	detail::tvec4<T> sw00 = step(gw00, detail::tvec4<T>(0));
-	gx00 -= sw00 * (step(0.0, gx00) - T(0.5));
-	gy00 -= sw00 * (step(0.0, gy00) - T(0.5));
-
-	detail::tvec4<T> gx01 = ixy01 / T(7);
-	detail::tvec4<T> gy01 = floor(gx01) / T(7);
-	detail::tvec4<T> gz01 = floor(gy01) / T(6);
-	gx01 = fract(gx01) - T(0.5);
-	gy01 = fract(gy01) - T(0.5);
-	gz01 = fract(gz01) - T(0.5);
-	detail::tvec4<T> gw01 = detail::tvec4<T>(0.75) - abs(gx01) - abs(gy01) - abs(gz01);
-	detail::tvec4<T> sw01 = step(gw01, detail::tvec4<T>(0.0));
-	gx01 -= sw01 * (step(0.0, gx01) - T(0.5));
-	gy01 -= sw01 * (step(0.0, gy01) - T(0.5));
-
-	detail::tvec4<T> gx10 = ixy10 / T(7);
-	detail::tvec4<T> gy10 = floor(gx10) / T(7);
-	detail::tvec4<T> gz10 = floor(gy10) / T(6);
-	gx10 = fract(gx10) - T(0.5);
-	gy10 = fract(gy10) - T(0.5);
-	gz10 = fract(gz10) - T(0.5);
-	detail::tvec4<T> gw10 = detail::tvec4<T>(0.75) - abs(gx10) - abs(gy10) - abs(gz10);
-	detail::tvec4<T> sw10 = step(gw10, detail::tvec4<T>(0.0));
-	gx10 -= sw10 * (step(0.0, gx10) - T(0.5));
-	gy10 -= sw10 * (step(0.0, gy10) - T(0.5));
-
-	detail::tvec4<T> gx11 = ixy11 / T(7);
-	detail::tvec4<T> gy11 = floor(gx11) / T(7);
-	detail::tvec4<T> gz11 = floor(gy11) / T(6);
-	gx11 = fract(gx11) - T(0.5);
-	gy11 = fract(gy11) - T(0.5);
-	gz11 = fract(gz11) - T(0.5);
-	detail::tvec4<T> gw11 = detail::tvec4<T>(0.75) - abs(gx11) - abs(gy11) - abs(gz11);
-	detail::tvec4<T> sw11 = step(gw11, detail::tvec4<T>(0.0));
-	gx11 -= sw11 * (step(0.0, gx11) - T(0.5));
-	gy11 -= sw11 * (step(0.0, gy11) - T(0.5));
-
-	detail::tvec4<T> g0000(gx00.x, gy00.x, gz00.x, gw00.x);
-	detail::tvec4<T> g1000(gx00.y, gy00.y, gz00.y, gw00.y);
-	detail::tvec4<T> g0100(gx00.z, gy00.z, gz00.z, gw00.z);
-	detail::tvec4<T> g1100(gx00.w, gy00.w, gz00.w, gw00.w);
-	detail::tvec4<T> g0010(gx10.x, gy10.x, gz10.x, gw10.x);
-	detail::tvec4<T> g1010(gx10.y, gy10.y, gz10.y, gw10.y);
-	detail::tvec4<T> g0110(gx10.z, gy10.z, gz10.z, gw10.z);
-	detail::tvec4<T> g1110(gx10.w, gy10.w, gz10.w, gw10.w);
-	detail::tvec4<T> g0001(gx01.x, gy01.x, gz01.x, gw01.x);
-	detail::tvec4<T> g1001(gx01.y, gy01.y, gz01.y, gw01.y);
-	detail::tvec4<T> g0101(gx01.z, gy01.z, gz01.z, gw01.z);
-	detail::tvec4<T> g1101(gx01.w, gy01.w, gz01.w, gw01.w);
-	detail::tvec4<T> g0011(gx11.x, gy11.x, gz11.x, gw11.x);
-	detail::tvec4<T> g1011(gx11.y, gy11.y, gz11.y, gw11.y);
-	detail::tvec4<T> g0111(gx11.z, gy11.z, gz11.z, gw11.z);
-	detail::tvec4<T> g1111(gx11.w, gy11.w, gz11.w, gw11.w);
-
-	detail::tvec4<T> norm00 = taylorInvSqrt(detail::tvec4<T>(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100)));
-	g0000 *= norm00.x;
-	g0100 *= norm00.y;
-	g1000 *= norm00.z;
-	g1100 *= norm00.w;
-
-	detail::tvec4<T> norm01 = taylorInvSqrt(detail::tvec4<T>(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101)));
-	g0001 *= norm01.x;
-	g0101 *= norm01.y;
-	g1001 *= norm01.z;
-	g1101 *= norm01.w;
-
-	detail::tvec4<T> norm10 = taylorInvSqrt(detail::tvec4<T>(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110)));
-	g0010 *= norm10.x;
-	g0110 *= norm10.y;
-	g1010 *= norm10.z;
-	g1110 *= norm10.w;
-
-	detail::tvec4<T> norm11 = taylorInvSqrt(detail::tvec4<T>(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111)));
-	g0011 *= norm11.x;
-	g0111 *= norm11.y;
-	g1011 *= norm11.z;
-	g1111 *= norm11.w;
-
-	T n0000 = dot(g0000, Pf0);
-	T n1000 = dot(g1000, detail::tvec4<T>(Pf1.x, Pf0.y, Pf0.z, Pf0.w));
-	T n0100 = dot(g0100, detail::tvec4<T>(Pf0.x, Pf1.y, Pf0.z, Pf0.w));
-	T n1100 = dot(g1100, detail::tvec4<T>(Pf1.x, Pf1.y, Pf0.z, Pf0.w));
-	T n0010 = dot(g0010, detail::tvec4<T>(Pf0.x, Pf0.y, Pf1.z, Pf0.w));
-	T n1010 = dot(g1010, detail::tvec4<T>(Pf1.x, Pf0.y, Pf1.z, Pf0.w));
-	T n0110 = dot(g0110, detail::tvec4<T>(Pf0.x, Pf1.y, Pf1.z, Pf0.w));
-	T n1110 = dot(g1110, detail::tvec4<T>(Pf1.x, Pf1.y, Pf1.z, Pf0.w));
-	T n0001 = dot(g0001, detail::tvec4<T>(Pf0.x, Pf0.y, Pf0.z, Pf1.w));
-	T n1001 = dot(g1001, detail::tvec4<T>(Pf1.x, Pf0.y, Pf0.z, Pf1.w));
-	T n0101 = dot(g0101, detail::tvec4<T>(Pf0.x, Pf1.y, Pf0.z, Pf1.w));
-	T n1101 = dot(g1101, detail::tvec4<T>(Pf1.x, Pf1.y, Pf0.z, Pf1.w));
-	T n0011 = dot(g0011, detail::tvec4<T>(Pf0.x, Pf0.y, Pf1.z, Pf1.w));
-	T n1011 = dot(g1011, detail::tvec4<T>(Pf1.x, Pf0.y, Pf1.z, Pf1.w));
-	T n0111 = dot(g0111, detail::tvec4<T>(Pf0.x, Pf1.y, Pf1.z, Pf1.w));
-	T n1111 = dot(g1111, Pf1);
-
-	detail::tvec4<T> fade_xyzw = fade(Pf0);
-	detail::tvec4<T> n_0w = mix(detail::tvec4<T>(n0000, n1000, n0100, n1100), detail::tvec4<T>(n0001, n1001, n0101, n1101), fade_xyzw.w);
-	detail::tvec4<T> n_1w = mix(detail::tvec4<T>(n0010, n1010, n0110, n1110), detail::tvec4<T>(n0011, n1011, n0111, n1111), fade_xyzw.w);
-	detail::tvec4<T> n_zw = mix(n_0w, n_1w, fade_xyzw.z);
-	detail::tvec2<T> n_yzw = mix(detail::tvec2<T>(n_zw.x, n_zw.y), detail::tvec2<T>(n_zw.z, n_zw.w), fade_xyzw.y);
-	T n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x);
-	return T(2.2) * n_xyzw;
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER T simplex(glm::detail::tvec2<T> const & v)
-{
-	detail::tvec4<T> const C = detail::tvec4<T>(
-		T( 0.211324865405187),  // (3.0 -  sqrt(3.0)) / 6.0
-		T( 0.366025403784439),  //  0.5 * (sqrt(3.0)  - 1.0)
-		T(-0.577350269189626),	// -1.0 + 2.0 * C.x
-		T( 0.024390243902439)); //  1.0 / 41.0
-
-	// First corner
-	detail::tvec2<T> i  = floor(v + dot(v, detail::tvec2<T>(C[1])));
-	detail::tvec2<T> x0 = v -   i + dot(i, detail::tvec2<T>(C[0]));
-
-	// Other corners
-	//i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0
-	//i1.y = 1.0 - i1.x;
-	detail::tvec2<T> i1 = (x0.x > x0.y) ? detail::tvec2<T>(1, 0) : detail::tvec2<T>(0, 1);
-	// x0 = x0 - 0.0 + 0.0 * C.xx ;
-	// x1 = x0 - i1 + 1.0 * C.xx ;
-	// x2 = x0 - 1.0 + 2.0 * C.xx ;
-	detail::tvec4<T> x12 = detail::tvec4<T>(x0.x, x0.y, x0.x, x0.y) + detail::tvec4<T>(C.x, C.x, C.z, C.z);
-	x12 = detail::tvec4<T>(detail::tvec2<T>(x12) - i1, x12.z, x12.w);
-
-	// Permutations
-	i = mod(i, T(289)); // Avoid truncation effects in permutation
-	detail::tvec3<T> p = permute(
-		permute(i.y + detail::tvec3<T>(T(0), i1.y, T(1)))
-		+ i.x + detail::tvec3<T>(T(0), i1.x, T(1)));
-
-	detail::tvec3<T> m = max(T(0.5) - detail::tvec3<T>(
-		dot(x0, x0), 
-		dot(detail::tvec2<T>(x12.x, x12.y), detail::tvec2<T>(x12.x, x12.y)), 
-		dot(detail::tvec2<T>(x12.z, x12.w), detail::tvec2<T>(x12.z, x12.w))), T(0));
-	m = m * m ;
-	m = m * m ;
-
-	// Gradients: 41 points uniformly over a line, mapped onto a diamond.
-	// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
-
-	detail::tvec3<T> x = T(2) * fract(p * C.w) - T(1);
-	detail::tvec3<T> h = abs(x) - T(0.5);
-	detail::tvec3<T> ox = floor(x + T(0.5));
-	detail::tvec3<T> a0 = x - ox;
-
-	// Normalise gradients implicitly by scaling m
-	// Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h );
-	m *= T(1.79284291400159) - T(0.85373472095314) * (a0 * a0 + h * h);
-
-	// Compute final noise value at P
-	detail::tvec3<T> g;
-	g.x  = a0.x  * x0.x  + h.x  * x0.y;
-	//g.yz = a0.yz * x12.xz + h.yz * x12.yw;
-	g.y = a0.y * x12.x + h.y * x12.y;
-	g.z = a0.z * x12.z + h.z * x12.w;
-	return T(130) * dot(m, g);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER T simplex(detail::tvec3<T> const & v)
-{ 
-	detail::tvec2<T> const C(1.0 / 6.0, 1.0 / 3.0);
-	detail::tvec4<T> const D(0.0, 0.5, 1.0, 2.0);
-
-	// First corner
-	detail::tvec3<T> i(floor(v + dot(v, detail::tvec3<T>(C.y))));
-	detail::tvec3<T> x0(v - i + dot(i, detail::tvec3<T>(C.x)));
-
-	// Other corners
-	detail::tvec3<T> g(step(detail::tvec3<T>(x0.y, x0.z, x0.x), x0));
-	detail::tvec3<T> l(T(1) - g);
-	detail::tvec3<T> i1(min(g, detail::tvec3<T>(l.z, l.x, l.y)));
-	detail::tvec3<T> i2(max(g, detail::tvec3<T>(l.z, l.x, l.y)));
-
-	//   x0 = x0 - 0.0 + 0.0 * C.xxx;
-	//   x1 = x0 - i1  + 1.0 * C.xxx;
-	//   x2 = x0 - i2  + 2.0 * C.xxx;
-	//   x3 = x0 - 1.0 + 3.0 * C.xxx;
-	detail::tvec3<T> x1(x0 - i1 + C.x);
-	detail::tvec3<T> x2(x0 - i2 + C.y); // 2.0*C.x = 1/3 = C.y
-	detail::tvec3<T> x3(x0 - D.y);      // -1.0+3.0*C.x = -0.5 = -D.y
-
-	// Permutations
-	i = mod289(i); 
-	detail::tvec4<T> p(permute(permute(permute( 
-		i.z + detail::tvec4<T>(T(0), i1.z, i2.z, T(1))) + 
-		i.y + detail::tvec4<T>(T(0), i1.y, i2.y, T(1))) + 
-		i.x + detail::tvec4<T>(T(0), i1.x, i2.x, T(1))));
-
-	// Gradients: 7x7 points over a square, mapped onto an octahedron.
-	// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
-	T n_ = T(0.142857142857); // 1.0/7.0
-	detail::tvec3<T> ns(n_ * detail::tvec3<T>(D.w, D.y, D.z) - detail::tvec3<T>(D.x, D.z, D.x));
-
-	detail::tvec4<T> j(p - T(49) * floor(p * ns.z * ns.z));  //  mod(p,7*7)
-
-	detail::tvec4<T> x_(floor(j * ns.z));
-	detail::tvec4<T> y_(floor(j - T(7) * x_));    // mod(j,N)
-
-	detail::tvec4<T> x(x_ * ns.x + ns.y);
-	detail::tvec4<T> y(y_ * ns.x + ns.y);
-	detail::tvec4<T> h(T(1) - abs(x) - abs(y));
-
-	detail::tvec4<T> b0(x.x, x.y, y.x, y.y);
-	detail::tvec4<T> b1(x.z, x.w, y.z, y.w);
-
-	// vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
-	// vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
-	detail::tvec4<T> s0(floor(b0) * T(2) + T(1));
-	detail::tvec4<T> s1(floor(b1) * T(2) + T(1));
-	detail::tvec4<T> sh(-step(h, detail::tvec4<T>(0.0)));
-
-	detail::tvec4<T> a0 = detail::tvec4<T>(b0.x, b0.z, b0.y, b0.w) + detail::tvec4<T>(s0.x, s0.z, s0.y, s0.w) * detail::tvec4<T>(sh.x, sh.x, sh.y, sh.y);
-	detail::tvec4<T> a1 = detail::tvec4<T>(b1.x, b1.z, b1.y, b1.w) + detail::tvec4<T>(s1.x, s1.z, s1.y, s1.w) * detail::tvec4<T>(sh.z, sh.z, sh.w, sh.w);
-
-	detail::tvec3<T> p0(a0.x, a0.y, h.x);
-	detail::tvec3<T> p1(a0.z, a0.w, h.y);
-	detail::tvec3<T> p2(a1.x, a1.y, h.z);
-	detail::tvec3<T> p3(a1.z, a1.w, h.w);
-
-	// Normalise gradients
-	detail::tvec4<T> norm = taylorInvSqrt(detail::tvec4<T>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
-	p0 *= norm.x;
-	p1 *= norm.y;
-	p2 *= norm.z;
-	p3 *= norm.w;
-
-	// Mix final noise value
-	detail::tvec4<T> m = max(T(0.6) - detail::tvec4<T>(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), T(0));
-	m = m * m;
-	return T(42) * dot(m * m, detail::tvec4<T>(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER T simplex(detail::tvec4<T> const & v)
-{
-	detail::tvec4<T> const C(
-		0.138196601125011,  // (5 - sqrt(5))/20  G4
-		0.276393202250021,  // 2 * G4
-		0.414589803375032,  // 3 * G4
-		-0.447213595499958); // -1 + 4 * G4
-
-	// (sqrt(5) - 1)/4 = F4, used once below
-	T const F4 = T(0.309016994374947451);
-
-	// First corner
-	detail::tvec4<T> i  = floor(v + dot(v, vec4(F4)));
-	detail::tvec4<T> x0 = v -   i + dot(i, vec4(C.x));
-
-	// Other corners
-
-	// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
-	detail::tvec4<T> i0;
-	detail::tvec3<T> isX = step(detail::tvec3<T>(x0.y, x0.z, x0.w), detail::tvec3<T>(x0.x));
-	detail::tvec3<T> isYZ = step(detail::tvec3<T>(x0.z, x0.w, x0.w), detail::tvec3<T>(x0.y, x0.y, x0.z));
-	//  i0.x = dot(isX, vec3(1.0));
-	//i0.x = isX.x + isX.y + isX.z;
-	//i0.yzw = T(1) - isX;
-    i0 = detail::tvec4<T>(isX.x + isX.y + isX.z, T(1) - isX);
-	//  i0.y += dot(isYZ.xy, vec2(1.0));
-	i0.y += isYZ.x + isYZ.y;
-	//i0.zw += 1.0 - detail::tvec2<T>(isYZ.x, isYZ.y);
-    i0.z += T(1) - isYZ.x;
-    i0.w += T(1) - isYZ.y;
-	i0.z += isYZ.z;
-	i0.w += T(1) - isYZ.z;
-
-	// i0 now contains the unique values 0,1,2,3 in each channel
-	detail::tvec4<T> i3 = clamp(i0, 0.0, 1.0);
-	detail::tvec4<T> i2 = clamp(i0 - 1.0, 0.0, 1.0);
-	detail::tvec4<T> i1 = clamp(i0 - 2.0, 0.0, 1.0);
-
-	//  x0 = x0 - 0.0 + 0.0 * C.xxxx
-	//  x1 = x0 - i1  + 0.0 * C.xxxx
-	//  x2 = x0 - i2  + 0.0 * C.xxxx
-	//  x3 = x0 - i3  + 0.0 * C.xxxx
-	//  x4 = x0 - 1.0 + 4.0 * C.xxxx
-	detail::tvec4<T> x1 = x0 - i1 + C.x;
-	detail::tvec4<T> x2 = x0 - i2 + C.y;
-	detail::tvec4<T> x3 = x0 - i3 + C.z;
-	detail::tvec4<T> x4 = x0 + C.w;
-
-	// Permutations
-	i = mod(i, T(289)); 
-	T j0 = permute(permute(permute(permute(i.w) + i.z) + i.y) + i.x);
-	detail::tvec4<T> j1 = permute(permute(permute(permute(
-				i.w + detail::tvec4<T>(i1.w, i2.w, i3.w, T(1)))
-			+ i.z + detail::tvec4<T>(i1.z, i2.z, i3.z, T(1)))
-			+ i.y + detail::tvec4<T>(i1.y, i2.y, i3.y, T(1)))
-			+ i.x + detail::tvec4<T>(i1.x, i2.x, i3.x, T(1)));
-
-	// Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope
-	// 7*7*6 = 294, which is close to the ring size 17*17 = 289.
-	detail::tvec4<T> ip = detail::tvec4<T>(T(1) / T(294), T(1) / T(49), T(1) / T(7), T(0));
-
-	detail::tvec4<T> p0 = grad4(j0,   ip);
-	detail::tvec4<T> p1 = grad4(j1.x, ip);
-	detail::tvec4<T> p2 = grad4(j1.y, ip);
-	detail::tvec4<T> p3 = grad4(j1.z, ip);
-	detail::tvec4<T> p4 = grad4(j1.w, ip);
-
-	// Normalise gradients
-	detail::tvec4<T> norm = taylorInvSqrt(detail::tvec4<T>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
-	p0 *= norm.x;
-	p1 *= norm.y;
-	p2 *= norm.z;
-	p3 *= norm.w;
-	p4 *= taylorInvSqrt(dot(p4, p4));
-
-	// Mix contributions from the five corners
-	detail::tvec3<T> m0 = max(T(0.6) - detail::tvec3<T>(dot(x0, x0), dot(x1, x1), dot(x2, x2)), T(0));
-	detail::tvec2<T> m1 = max(T(0.6) - detail::tvec2<T>(dot(x3, x3), dot(x4, x4)             ), T(0));
-	m0 = m0 * m0;
-	m1 = m1 * m1;
-	return T(49) * 
-		(dot(m0 * m0, detail::tvec3<T>(dot(p0, x0), dot(p1, x1), dot(p2, x2))) + 
-		dot(m1 * m1, detail::tvec2<T>(dot(p3, x3), dot(p4, x4))));
-}
-
+	template <typename T>
+	GLM_FUNC_QUALIFIER T taylorInvSqrt(T const & r)
+	{
+		return T(1.79284291400159) - T(0.85373472095314) * r;
+	}
+
+	template <typename T, template<typename> class vecType>
+	GLM_FUNC_QUALIFIER vecType<T> taylorInvSqrt(vecType<T> const & r)
+	{
+		return T(1.79284291400159) - T(0.85373472095314) * r;
+	}
+
+	template <typename T, template <typename> class vecType> 
+	GLM_FUNC_QUALIFIER vecType<T> fade(vecType<T> const & t) 
+	{
+		return t * t * t * (t * (t * T(6) - T(15)) + T(10));
+	}
+
+	template <typename T>
+	GLM_FUNC_QUALIFIER detail::tvec4<T> grad4(T const & j, detail::tvec4<T> const & ip)
+	{
+		detail::tvec3<T> pXYZ = floor(fract(detail::tvec3<T>(j) * detail::tvec3<T>(ip)) * T(7)) * ip[2] - T(1);
+		T pW = T(1.5) - dot(abs(pXYZ), detail::tvec3<T>(1));
+		detail::tvec4<T> s = detail::tvec4<T>(lessThan(detail::tvec4<T>(pXYZ, pW), detail::tvec4<T>(0.0)));
+		pXYZ = pXYZ + (detail::tvec3<T>(s) * T(2) - T(1)) * s.w; 
+		return detail::tvec4<T>(pXYZ, pW);
+	}
+
+	// Classic Perlin noise
+	template <typename T>
+	GLM_FUNC_QUALIFIER T perlin(detail::tvec2<T> const & P)
+	{
+		detail::tvec4<T> Pi = glm::floor(detail::tvec4<T>(P.x, P.y, P.x, P.y)) + detail::tvec4<T>(0.0, 0.0, 1.0, 1.0);
+		detail::tvec4<T> Pf = glm::fract(detail::tvec4<T>(P.x, P.y, P.x, P.y)) - detail::tvec4<T>(0.0, 0.0, 1.0, 1.0);
+		Pi = mod(Pi, T(289)); // To avoid truncation effects in permutation
+		detail::tvec4<T> ix(Pi.x, Pi.z, Pi.x, Pi.z);
+		detail::tvec4<T> iy(Pi.y, Pi.y, Pi.w, Pi.w);
+		detail::tvec4<T> fx(Pf.x, Pf.z, Pf.x, Pf.z);
+		detail::tvec4<T> fy(Pf.y, Pf.y, Pf.w, Pf.w);
+
+		detail::tvec4<T> i = glm::permute(glm::permute(ix) + iy);
+
+		detail::tvec4<T> gx = T(2) * glm::fract(i / T(41)) - T(1);
+		detail::tvec4<T> gy = glm::abs(gx) - T(0.5);
+		detail::tvec4<T> tx = glm::floor(gx + T(0.5));
+		gx = gx - tx;
+
+		detail::tvec2<T> g00(gx.x, gy.x);
+		detail::tvec2<T> g10(gx.y, gy.y);
+		detail::tvec2<T> g01(gx.z, gy.z);
+		detail::tvec2<T> g11(gx.w, gy.w);
+
+		detail::tvec4<T> norm = taylorInvSqrt(detail::tvec4<T>(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)));
+		g00 *= norm.x;  
+		g01 *= norm.y;  
+		g10 *= norm.z;  
+		g11 *= norm.w;  
+
+		T n00 = dot(g00, detail::tvec2<T>(fx.x, fy.x));
+		T n10 = dot(g10, detail::tvec2<T>(fx.y, fy.y));
+		T n01 = dot(g01, detail::tvec2<T>(fx.z, fy.z));
+		T n11 = dot(g11, detail::tvec2<T>(fx.w, fy.w));
+
+		detail::tvec2<T> fade_xy = fade(detail::tvec2<T>(Pf.x, Pf.y));
+		detail::tvec2<T> n_x = mix(detail::tvec2<T>(n00, n01), detail::tvec2<T>(n10, n11), fade_xy.x);
+		T n_xy = mix(n_x.x, n_x.y, fade_xy.y);
+		return T(2.3) * n_xy;
+	}
+
+	// Classic Perlin noise
+	template <typename T>
+	GLM_FUNC_QUALIFIER T perlin(detail::tvec3<T> const & P)
+	{
+		detail::tvec3<T> Pi0 = floor(P); // Integer part for indexing
+		detail::tvec3<T> Pi1 = Pi0 + T(1); // Integer part + 1
+		Pi0 = mod289(Pi0);
+		Pi1 = mod289(Pi1);
+		detail::tvec3<T> Pf0 = fract(P); // Fractional part for interpolation
+		detail::tvec3<T> Pf1 = Pf0 - T(1); // Fractional part - 1.0
+		detail::tvec4<T> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
+		detail::tvec4<T> iy = detail::tvec4<T>(detail::tvec2<T>(Pi0.y), detail::tvec2<T>(Pi1.y));
+		detail::tvec4<T> iz0(Pi0.z);
+		detail::tvec4<T> iz1(Pi1.z);
+
+		detail::tvec4<T> ixy = permute(permute(ix) + iy);
+		detail::tvec4<T> ixy0 = permute(ixy + iz0);
+		detail::tvec4<T> ixy1 = permute(ixy + iz1);
+
+		detail::tvec4<T> gx0 = ixy0 * T(1.0 / 7.0);
+		detail::tvec4<T> gy0 = fract(floor(gx0) * T(1.0 / 7.0)) - T(0.5);
+		gx0 = fract(gx0);
+		detail::tvec4<T> gz0 = detail::tvec4<T>(0.5) - abs(gx0) - abs(gy0);
+		detail::tvec4<T> sz0 = step(gz0, detail::tvec4<T>(0.0));
+		gx0 -= sz0 * (step(T(0), gx0) - T(0.5));
+		gy0 -= sz0 * (step(T(0), gy0) - T(0.5));
+
+		detail::tvec4<T> gx1 = ixy1 * T(1.0 / 7.0);
+		detail::tvec4<T> gy1 = fract(floor(gx1) * T(1.0 / 7.0)) - T(0.5);
+		gx1 = fract(gx1);
+		detail::tvec4<T> gz1 = detail::tvec4<T>(0.5) - abs(gx1) - abs(gy1);
+		detail::tvec4<T> sz1 = step(gz1, detail::tvec4<T>(0.0));
+		gx1 -= sz1 * (step(T(0), gx1) - T(0.5));
+		gy1 -= sz1 * (step(T(0), gy1) - T(0.5));
+
+		detail::tvec3<T> g000(gx0.x, gy0.x, gz0.x);
+		detail::tvec3<T> g100(gx0.y, gy0.y, gz0.y);
+		detail::tvec3<T> g010(gx0.z, gy0.z, gz0.z);
+		detail::tvec3<T> g110(gx0.w, gy0.w, gz0.w);
+		detail::tvec3<T> g001(gx1.x, gy1.x, gz1.x);
+		detail::tvec3<T> g101(gx1.y, gy1.y, gz1.y);
+		detail::tvec3<T> g011(gx1.z, gy1.z, gz1.z);
+		detail::tvec3<T> g111(gx1.w, gy1.w, gz1.w);
+
+		detail::tvec4<T> norm0 = taylorInvSqrt(detail::tvec4<T>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
+		g000 *= norm0.x;
+		g010 *= norm0.y;
+		g100 *= norm0.z;
+		g110 *= norm0.w;
+		detail::tvec4<T> norm1 = taylorInvSqrt(detail::tvec4<T>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
+		g001 *= norm1.x;
+		g011 *= norm1.y;
+		g101 *= norm1.z;
+		g111 *= norm1.w;
+
+		T n000 = dot(g000, Pf0);
+		T n100 = dot(g100, detail::tvec3<T>(Pf1.x, Pf0.y, Pf0.z));
+		T n010 = dot(g010, detail::tvec3<T>(Pf0.x, Pf1.y, Pf0.z));
+		T n110 = dot(g110, detail::tvec3<T>(Pf1.x, Pf1.y, Pf0.z));
+		T n001 = dot(g001, detail::tvec3<T>(Pf0.x, Pf0.y, Pf1.z));
+		T n101 = dot(g101, detail::tvec3<T>(Pf1.x, Pf0.y, Pf1.z));
+		T n011 = dot(g011, detail::tvec3<T>(Pf0.x, Pf1.y, Pf1.z));
+		T n111 = dot(g111, Pf1);
+
+		detail::tvec3<T> fade_xyz = fade(Pf0);
+		detail::tvec4<T> n_z = mix(detail::tvec4<T>(n000, n100, n010, n110), detail::tvec4<T>(n001, n101, n011, n111), fade_xyz.z);
+		detail::tvec2<T> n_yz = mix(detail::tvec2<T>(n_z.x, n_z.y), detail::tvec2<T>(n_z.z, n_z.w), fade_xyz.y);
+		T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); 
+		return T(2.2) * n_xyz;
+	}
+	/*
+	// Classic Perlin noise
+	template <typename T>
+	GLM_FUNC_QUALIFIER T perlin(detail::tvec3<T> const & P)
+	{
+		detail::tvec3<T> Pi0 = floor(P); // Integer part for indexing
+		detail::tvec3<T> Pi1 = Pi0 + T(1); // Integer part + 1
+		Pi0 = mod(Pi0, T(289));
+		Pi1 = mod(Pi1, T(289));
+		detail::tvec3<T> Pf0 = fract(P); // Fractional part for interpolation
+		detail::tvec3<T> Pf1 = Pf0 - T(1); // Fractional part - 1.0
+		detail::tvec4<T> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
+		detail::tvec4<T> iy(Pi0.y, Pi0.y, Pi1.y, Pi1.y);
+		detail::tvec4<T> iz0(Pi0.z);
+		detail::tvec4<T> iz1(Pi1.z);
+
+		detail::tvec4<T> ixy = permute(permute(ix) + iy);
+		detail::tvec4<T> ixy0 = permute(ixy + iz0);
+		detail::tvec4<T> ixy1 = permute(ixy + iz1);
+
+		detail::tvec4<T> gx0 = ixy0 / T(7);
+		detail::tvec4<T> gy0 = fract(floor(gx0) / T(7)) - T(0.5);
+		gx0 = fract(gx0);
+		detail::tvec4<T> gz0 = detail::tvec4<T>(0.5) - abs(gx0) - abs(gy0);
+		detail::tvec4<T> sz0 = step(gz0, detail::tvec4<T>(0.0));
+		gx0 -= sz0 * (step(0.0, gx0) - T(0.5));
+		gy0 -= sz0 * (step(0.0, gy0) - T(0.5));
+
+		detail::tvec4<T> gx1 = ixy1 / T(7);
+		detail::tvec4<T> gy1 = fract(floor(gx1) / T(7)) - T(0.5);
+		gx1 = fract(gx1);
+		detail::tvec4<T> gz1 = detail::tvec4<T>(0.5) - abs(gx1) - abs(gy1);
+		detail::tvec4<T> sz1 = step(gz1, detail::tvec4<T>(0.0));
+		gx1 -= sz1 * (step(T(0), gx1) - T(0.5));
+		gy1 -= sz1 * (step(T(0), gy1) - T(0.5));
+
+		detail::tvec3<T> g000(gx0.x, gy0.x, gz0.x);
+		detail::tvec3<T> g100(gx0.y, gy0.y, gz0.y);
+		detail::tvec3<T> g010(gx0.z, gy0.z, gz0.z);
+		detail::tvec3<T> g110(gx0.w, gy0.w, gz0.w);
+		detail::tvec3<T> g001(gx1.x, gy1.x, gz1.x);
+		detail::tvec3<T> g101(gx1.y, gy1.y, gz1.y);
+		detail::tvec3<T> g011(gx1.z, gy1.z, gz1.z);
+		detail::tvec3<T> g111(gx1.w, gy1.w, gz1.w);
+
+		detail::tvec4<T> norm0 = taylorInvSqrt(detail::tvec4<T>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
+		g000 *= norm0.x;
+		g010 *= norm0.y;
+		g100 *= norm0.z;
+		g110 *= norm0.w;
+		detail::tvec4<T> norm1 = taylorInvSqrt(detail::tvec4<T>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
+		g001 *= norm1.x;
+		g011 *= norm1.y;
+		g101 *= norm1.z;
+		g111 *= norm1.w;
+
+		T n000 = dot(g000, Pf0);
+		T n100 = dot(g100, detail::tvec3<T>(Pf1.x, Pf0.y, Pf0.z));
+		T n010 = dot(g010, detail::tvec3<T>(Pf0.x, Pf1.y, Pf0.z));
+		T n110 = dot(g110, detail::tvec3<T>(Pf1.x, Pf1.y, Pf0.z));
+		T n001 = dot(g001, detail::tvec3<T>(Pf0.x, Pf0.y, Pf1.z));
+		T n101 = dot(g101, detail::tvec3<T>(Pf1.x, Pf0.y, Pf1.z));
+		T n011 = dot(g011, detail::tvec3<T>(Pf0.x, Pf1.y, Pf1.z));
+		T n111 = dot(g111, Pf1);
+
+		detail::tvec3<T> fade_xyz = fade(Pf0);
+		detail::tvec4<T> n_z = mix(detail::tvec4<T>(n000, n100, n010, n110), detail::tvec4<T>(n001, n101, n011, n111), fade_xyz.z);
+		detail::tvec2<T> n_yz = mix(
+			detail::tvec2<T>(n_z.x, n_z.y), 
+			detail::tvec2<T>(n_z.z, n_z.w), fade_xyz.y);
+		T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); 
+		return T(2.2) * n_xyz;
+	}
+	*/
+	// Classic Perlin noise
+	template <typename T>
+	GLM_FUNC_QUALIFIER T perlin(detail::tvec4<T> const & P)
+	{
+		detail::tvec4<T> Pi0 = floor(P); // Integer part for indexing
+		detail::tvec4<T> Pi1 = Pi0 + T(1); // Integer part + 1
+		Pi0 = mod(Pi0, T(289));
+		Pi1 = mod(Pi1, T(289));
+		detail::tvec4<T> Pf0 = fract(P); // Fractional part for interpolation
+		detail::tvec4<T> Pf1 = Pf0 - T(1); // Fractional part - 1.0
+		detail::tvec4<T> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
+		detail::tvec4<T> iy(Pi0.y, Pi0.y, Pi1.y, Pi1.y);
+		detail::tvec4<T> iz0(Pi0.z);
+		detail::tvec4<T> iz1(Pi1.z);
+		detail::tvec4<T> iw0(Pi0.w);
+		detail::tvec4<T> iw1(Pi1.w);
+
+		detail::tvec4<T> ixy = permute(permute(ix) + iy);
+		detail::tvec4<T> ixy0 = permute(ixy + iz0);
+		detail::tvec4<T> ixy1 = permute(ixy + iz1);
+		detail::tvec4<T> ixy00 = permute(ixy0 + iw0);
+		detail::tvec4<T> ixy01 = permute(ixy0 + iw1);
+		detail::tvec4<T> ixy10 = permute(ixy1 + iw0);
+		detail::tvec4<T> ixy11 = permute(ixy1 + iw1);
+
+		detail::tvec4<T> gx00 = ixy00 / T(7);
+		detail::tvec4<T> gy00 = floor(gx00) / T(7);
+		detail::tvec4<T> gz00 = floor(gy00) / T(6);
+		gx00 = fract(gx00) - T(0.5);
+		gy00 = fract(gy00) - T(0.5);
+		gz00 = fract(gz00) - T(0.5);
+		detail::tvec4<T> gw00 = detail::tvec4<T>(0.75) - abs(gx00) - abs(gy00) - abs(gz00);
+		detail::tvec4<T> sw00 = step(gw00, detail::tvec4<T>(0.0));
+		gx00 -= sw00 * (step(T(0), gx00) - T(0.5));
+		gy00 -= sw00 * (step(T(0), gy00) - T(0.5));
+
+		detail::tvec4<T> gx01 = ixy01 / T(7);
+		detail::tvec4<T> gy01 = floor(gx01) / T(7);
+		detail::tvec4<T> gz01 = floor(gy01) / T(6);
+		gx01 = fract(gx01) - T(0.5);
+		gy01 = fract(gy01) - T(0.5);
+		gz01 = fract(gz01) - T(0.5);
+		detail::tvec4<T> gw01 = detail::tvec4<T>(0.75) - abs(gx01) - abs(gy01) - abs(gz01);
+		detail::tvec4<T> sw01 = step(gw01, detail::tvec4<T>(0.0));
+		gx01 -= sw01 * (step(T(0), gx01) - T(0.5));
+		gy01 -= sw01 * (step(T(0), gy01) - T(0.5));
+
+		detail::tvec4<T> gx10 = ixy10 / T(7);
+		detail::tvec4<T> gy10 = floor(gx10) / T(7);
+		detail::tvec4<T> gz10 = floor(gy10) / T(6);
+		gx10 = fract(gx10) - T(0.5);
+		gy10 = fract(gy10) - T(0.5);
+		gz10 = fract(gz10) - T(0.5);
+		detail::tvec4<T> gw10 = detail::tvec4<T>(0.75) - abs(gx10) - abs(gy10) - abs(gz10);
+		detail::tvec4<T> sw10 = step(gw10, detail::tvec4<T>(0));
+		gx10 -= sw10 * (step(T(0), gx10) - T(0.5));
+		gy10 -= sw10 * (step(T(0), gy10) - T(0.5));
+
+		detail::tvec4<T> gx11 = ixy11 / T(7);
+		detail::tvec4<T> gy11 = floor(gx11) / T(7);
+		detail::tvec4<T> gz11 = floor(gy11) / T(6);
+		gx11 = fract(gx11) - T(0.5);
+		gy11 = fract(gy11) - T(0.5);
+		gz11 = fract(gz11) - T(0.5);
+		detail::tvec4<T> gw11 = detail::tvec4<T>(0.75) - abs(gx11) - abs(gy11) - abs(gz11);
+		detail::tvec4<T> sw11 = step(gw11, detail::tvec4<T>(0.0));
+		gx11 -= sw11 * (step(T(0), gx11) - T(0.5));
+		gy11 -= sw11 * (step(T(0), gy11) - T(0.5));
+
+		detail::tvec4<T> g0000(gx00.x, gy00.x, gz00.x, gw00.x);
+		detail::tvec4<T> g1000(gx00.y, gy00.y, gz00.y, gw00.y);
+		detail::tvec4<T> g0100(gx00.z, gy00.z, gz00.z, gw00.z);
+		detail::tvec4<T> g1100(gx00.w, gy00.w, gz00.w, gw00.w);
+		detail::tvec4<T> g0010(gx10.x, gy10.x, gz10.x, gw10.x);
+		detail::tvec4<T> g1010(gx10.y, gy10.y, gz10.y, gw10.y);
+		detail::tvec4<T> g0110(gx10.z, gy10.z, gz10.z, gw10.z);
+		detail::tvec4<T> g1110(gx10.w, gy10.w, gz10.w, gw10.w);
+		detail::tvec4<T> g0001(gx01.x, gy01.x, gz01.x, gw01.x);
+		detail::tvec4<T> g1001(gx01.y, gy01.y, gz01.y, gw01.y);
+		detail::tvec4<T> g0101(gx01.z, gy01.z, gz01.z, gw01.z);
+		detail::tvec4<T> g1101(gx01.w, gy01.w, gz01.w, gw01.w);
+		detail::tvec4<T> g0011(gx11.x, gy11.x, gz11.x, gw11.x);
+		detail::tvec4<T> g1011(gx11.y, gy11.y, gz11.y, gw11.y);
+		detail::tvec4<T> g0111(gx11.z, gy11.z, gz11.z, gw11.z);
+		detail::tvec4<T> g1111(gx11.w, gy11.w, gz11.w, gw11.w);
+
+		detail::tvec4<T> norm00 = taylorInvSqrt(detail::tvec4<T>(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100)));
+		g0000 *= norm00.x;
+		g0100 *= norm00.y;
+		g1000 *= norm00.z;
+		g1100 *= norm00.w;
+
+		detail::tvec4<T> norm01 = taylorInvSqrt(detail::tvec4<T>(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101)));
+		g0001 *= norm01.x;
+		g0101 *= norm01.y;
+		g1001 *= norm01.z;
+		g1101 *= norm01.w;
+
+		detail::tvec4<T> norm10 = taylorInvSqrt(detail::tvec4<T>(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110)));
+		g0010 *= norm10.x;
+		g0110 *= norm10.y;
+		g1010 *= norm10.z;
+		g1110 *= norm10.w;
+
+		detail::tvec4<T> norm11 = taylorInvSqrt(detail::tvec4<T>(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111)));
+		g0011 *= norm11.x;
+		g0111 *= norm11.y;
+		g1011 *= norm11.z;
+		g1111 *= norm11.w;
+
+		T n0000 = dot(g0000, Pf0);
+		T n1000 = dot(g1000, detail::tvec4<T>(Pf1.x, Pf0.y, Pf0.z, Pf0.w));
+		T n0100 = dot(g0100, detail::tvec4<T>(Pf0.x, Pf1.y, Pf0.z, Pf0.w));
+		T n1100 = dot(g1100, detail::tvec4<T>(Pf1.x, Pf1.y, Pf0.z, Pf0.w));
+		T n0010 = dot(g0010, detail::tvec4<T>(Pf0.x, Pf0.y, Pf1.z, Pf0.w));
+		T n1010 = dot(g1010, detail::tvec4<T>(Pf1.x, Pf0.y, Pf1.z, Pf0.w));
+		T n0110 = dot(g0110, detail::tvec4<T>(Pf0.x, Pf1.y, Pf1.z, Pf0.w));
+		T n1110 = dot(g1110, detail::tvec4<T>(Pf1.x, Pf1.y, Pf1.z, Pf0.w));
+		T n0001 = dot(g0001, detail::tvec4<T>(Pf0.x, Pf0.y, Pf0.z, Pf1.w));
+		T n1001 = dot(g1001, detail::tvec4<T>(Pf1.x, Pf0.y, Pf0.z, Pf1.w));
+		T n0101 = dot(g0101, detail::tvec4<T>(Pf0.x, Pf1.y, Pf0.z, Pf1.w));
+		T n1101 = dot(g1101, detail::tvec4<T>(Pf1.x, Pf1.y, Pf0.z, Pf1.w));
+		T n0011 = dot(g0011, detail::tvec4<T>(Pf0.x, Pf0.y, Pf1.z, Pf1.w));
+		T n1011 = dot(g1011, detail::tvec4<T>(Pf1.x, Pf0.y, Pf1.z, Pf1.w));
+		T n0111 = dot(g0111, detail::tvec4<T>(Pf0.x, Pf1.y, Pf1.z, Pf1.w));
+		T n1111 = dot(g1111, Pf1);
+
+		detail::tvec4<T> fade_xyzw = fade(Pf0);
+		detail::tvec4<T> n_0w = mix(detail::tvec4<T>(n0000, n1000, n0100, n1100), detail::tvec4<T>(n0001, n1001, n0101, n1101), fade_xyzw.w);
+		detail::tvec4<T> n_1w = mix(detail::tvec4<T>(n0010, n1010, n0110, n1110), detail::tvec4<T>(n0011, n1011, n0111, n1111), fade_xyzw.w);
+		detail::tvec4<T> n_zw = mix(n_0w, n_1w, fade_xyzw.z);
+		detail::tvec2<T> n_yzw = mix(detail::tvec2<T>(n_zw.x, n_zw.y), detail::tvec2<T>(n_zw.z, n_zw.w), fade_xyzw.y);
+		T n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x);
+		return T(2.2) * n_xyzw;
+	}
+
+	// Classic Perlin noise, periodic variant
+	template <typename T>
+	GLM_FUNC_QUALIFIER T perlin(detail::tvec2<T> const & P, detail::tvec2<T> const & rep)
+	{
+		detail::tvec4<T> Pi = floor(detail::tvec4<T>(P.x, P.y, P.x, P.y)) + detail::tvec4<T>(0.0, 0.0, 1.0, 1.0);
+		detail::tvec4<T> Pf = fract(detail::tvec4<T>(P.x, P.y, P.x, P.y)) - detail::tvec4<T>(0.0, 0.0, 1.0, 1.0);
+		Pi = mod(Pi, detail::tvec4<T>(rep.x, rep.y, rep.x, rep.y)); // To create noise with explicit period
+		Pi = mod(Pi, T(289)); // To avoid truncation effects in permutation
+		detail::tvec4<T> ix(Pi.x, Pi.z, Pi.x, Pi.z);
+		detail::tvec4<T> iy(Pi.y, Pi.y, Pi.w, Pi.w);
+		detail::tvec4<T> fx(Pf.x, Pf.z, Pf.x, Pf.z);
+		detail::tvec4<T> fy(Pf.y, Pf.y, Pf.w, Pf.w);
+
+		detail::tvec4<T> i = permute(permute(ix) + iy);
+
+		detail::tvec4<T> gx = T(2) * fract(i / T(41)) - T(1);
+		detail::tvec4<T> gy = abs(gx) - T(0.5);
+		detail::tvec4<T> tx = floor(gx + T(0.5));
+		gx = gx - tx;
+
+		detail::tvec2<T> g00(gx.x, gy.x);
+		detail::tvec2<T> g10(gx.y, gy.y);
+		detail::tvec2<T> g01(gx.z, gy.z);
+		detail::tvec2<T> g11(gx.w, gy.w);
+
+		detail::tvec4<T> norm = taylorInvSqrt(detail::tvec4<T>(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)));
+		g00 *= norm.x;  
+		g01 *= norm.y;  
+		g10 *= norm.z;  
+		g11 *= norm.w;  
+
+		T n00 = dot(g00, detail::tvec2<T>(fx.x, fy.x));
+		T n10 = dot(g10, detail::tvec2<T>(fx.y, fy.y));
+		T n01 = dot(g01, detail::tvec2<T>(fx.z, fy.z));
+		T n11 = dot(g11, detail::tvec2<T>(fx.w, fy.w));
+
+		detail::tvec2<T> fade_xy = fade(detail::tvec2<T>(Pf.x, Pf.y));
+		detail::tvec2<T> n_x = mix(detail::tvec2<T>(n00, n01), detail::tvec2<T>(n10, n11), fade_xy.x);
+		T n_xy = mix(n_x.x, n_x.y, fade_xy.y);
+		return T(2.3) * n_xy;
+	}
+
+	// Classic Perlin noise, periodic variant
+	template <typename T>
+	GLM_FUNC_QUALIFIER T perlin(detail::tvec3<T> const & P, detail::tvec3<T> const & rep)
+	{
+		detail::tvec3<T> Pi0 = mod(floor(P), rep); // Integer part, modulo period
+		detail::tvec3<T> Pi1 = mod(Pi0 + detail::tvec3<T>(1.0), rep); // Integer part + 1, mod period
+		Pi0 = mod(Pi0, T(289));
+		Pi1 = mod(Pi1, T(289));
+		detail::tvec3<T> Pf0 = fract(P); // Fractional part for interpolation
+		detail::tvec3<T> Pf1 = Pf0 - detail::tvec3<T>(1.0); // Fractional part - 1.0
+		detail::tvec4<T> ix = detail::tvec4<T>(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
+		detail::tvec4<T> iy = detail::tvec4<T>(Pi0.y, Pi0.y, Pi1.y, Pi1.y);
+		detail::tvec4<T> iz0(Pi0.z);
+		detail::tvec4<T> iz1(Pi1.z);
+
+		detail::tvec4<T> ixy = permute(permute(ix) + iy);
+		detail::tvec4<T> ixy0 = permute(ixy + iz0);
+		detail::tvec4<T> ixy1 = permute(ixy + iz1);
+
+		detail::tvec4<T> gx0 = ixy0 / T(7);
+		detail::tvec4<T> gy0 = fract(floor(gx0) / T(7)) - T(0.5);
+		gx0 = fract(gx0);
+		detail::tvec4<T> gz0 = detail::tvec4<T>(0.5) - abs(gx0) - abs(gy0);
+		detail::tvec4<T> sz0 = step(gz0, detail::tvec4<T>(0));
+		gx0 -= sz0 * (step(0.0, gx0) - T(0.5));
+		gy0 -= sz0 * (step(0.0, gy0) - T(0.5));
+
+		detail::tvec4<T> gx1 = ixy1 / T(7);
+		detail::tvec4<T> gy1 = fract(floor(gx1) / T(7)) - T(0.5);
+		gx1 = fract(gx1);
+		detail::tvec4<T> gz1 = detail::tvec4<T>(0.5) - abs(gx1) - abs(gy1);
+		detail::tvec4<T> sz1 = step(gz1, detail::tvec4<T>(0.0));
+		gx1 -= sz1 * (step(0.0, gx1) - T(0.5));
+		gy1 -= sz1 * (step(0.0, gy1) - T(0.5));
+
+		detail::tvec3<T> g000 = detail::tvec3<T>(gx0.x, gy0.x, gz0.x);
+		detail::tvec3<T> g100 = detail::tvec3<T>(gx0.y, gy0.y, gz0.y);
+		detail::tvec3<T> g010 = detail::tvec3<T>(gx0.z, gy0.z, gz0.z);
+		detail::tvec3<T> g110 = detail::tvec3<T>(gx0.w, gy0.w, gz0.w);
+		detail::tvec3<T> g001 = detail::tvec3<T>(gx1.x, gy1.x, gz1.x);
+		detail::tvec3<T> g101 = detail::tvec3<T>(gx1.y, gy1.y, gz1.y);
+		detail::tvec3<T> g011 = detail::tvec3<T>(gx1.z, gy1.z, gz1.z);
+		detail::tvec3<T> g111 = detail::tvec3<T>(gx1.w, gy1.w, gz1.w);
+
+		detail::tvec4<T> norm0 = taylorInvSqrt(detail::tvec4<T>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
+		g000 *= norm0.x;
+		g010 *= norm0.y;
+		g100 *= norm0.z;
+		g110 *= norm0.w;
+		detail::tvec4<T> norm1 = taylorInvSqrt(detail::tvec4<T>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
+		g001 *= norm1.x;
+		g011 *= norm1.y;
+		g101 *= norm1.z;
+		g111 *= norm1.w;
+
+		T n000 = dot(g000, Pf0);
+		T n100 = dot(g100, detail::tvec3<T>(Pf1.x, Pf0.y, Pf0.z));
+		T n010 = dot(g010, detail::tvec3<T>(Pf0.x, Pf1.y, Pf0.z));
+		T n110 = dot(g110, detail::tvec3<T>(Pf1.x, Pf1.y, Pf0.z));
+		T n001 = dot(g001, detail::tvec3<T>(Pf0.x, Pf0.y, Pf1.z));
+		T n101 = dot(g101, detail::tvec3<T>(Pf1.x, Pf0.y, Pf1.z));
+		T n011 = dot(g011, detail::tvec3<T>(Pf0.x, Pf1.y, Pf1.z));
+		T n111 = dot(g111, Pf1);
+
+		detail::tvec3<T> fade_xyz = fade(Pf0);
+		detail::tvec4<T> n_z = mix(detail::tvec4<T>(n000, n100, n010, n110), detail::tvec4<T>(n001, n101, n011, n111), fade_xyz.z);
+		detail::tvec2<T> n_yz = mix(detail::tvec2<T>(n_z.x, n_z.y), detail::tvec2<T>(n_z.z, n_z.w), fade_xyz.y);
+		T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); 
+		return T(2.2) * n_xyz;
+	}
+
+	// Classic Perlin noise, periodic version
+	template <typename T>
+	GLM_FUNC_QUALIFIER T perlin(detail::tvec4<T> const & P, detail::tvec4<T> const & rep)
+	{
+		detail::tvec4<T> Pi0 = mod(floor(P), rep); // Integer part modulo rep
+		detail::tvec4<T> Pi1 = mod(Pi0 + T(1), rep); // Integer part + 1 mod rep
+		detail::tvec4<T> Pf0 = fract(P); // Fractional part for interpolation
+		detail::tvec4<T> Pf1 = Pf0 - T(1); // Fractional part - 1.0
+		detail::tvec4<T> ix = detail::tvec4<T>(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
+		detail::tvec4<T> iy = detail::tvec4<T>(Pi0.y, Pi0.y, Pi1.y, Pi1.y);
+		detail::tvec4<T> iz0(Pi0.z);
+		detail::tvec4<T> iz1(Pi1.z);
+		detail::tvec4<T> iw0(Pi0.w);
+		detail::tvec4<T> iw1(Pi1.w);
+
+		detail::tvec4<T> ixy = permute(permute(ix) + iy);
+		detail::tvec4<T> ixy0 = permute(ixy + iz0);
+		detail::tvec4<T> ixy1 = permute(ixy + iz1);
+		detail::tvec4<T> ixy00 = permute(ixy0 + iw0);
+		detail::tvec4<T> ixy01 = permute(ixy0 + iw1);
+		detail::tvec4<T> ixy10 = permute(ixy1 + iw0);
+		detail::tvec4<T> ixy11 = permute(ixy1 + iw1);
+
+		detail::tvec4<T> gx00 = ixy00 / T(7);
+		detail::tvec4<T> gy00 = floor(gx00) / T(7);
+		detail::tvec4<T> gz00 = floor(gy00) / T(6);
+		gx00 = fract(gx00) - T(0.5);
+		gy00 = fract(gy00) - T(0.5);
+		gz00 = fract(gz00) - T(0.5);
+		detail::tvec4<T> gw00 = detail::tvec4<T>(0.75) - abs(gx00) - abs(gy00) - abs(gz00);
+		detail::tvec4<T> sw00 = step(gw00, detail::tvec4<T>(0));
+		gx00 -= sw00 * (step(0.0, gx00) - T(0.5));
+		gy00 -= sw00 * (step(0.0, gy00) - T(0.5));
+
+		detail::tvec4<T> gx01 = ixy01 / T(7);
+		detail::tvec4<T> gy01 = floor(gx01) / T(7);
+		detail::tvec4<T> gz01 = floor(gy01) / T(6);
+		gx01 = fract(gx01) - T(0.5);
+		gy01 = fract(gy01) - T(0.5);
+		gz01 = fract(gz01) - T(0.5);
+		detail::tvec4<T> gw01 = detail::tvec4<T>(0.75) - abs(gx01) - abs(gy01) - abs(gz01);
+		detail::tvec4<T> sw01 = step(gw01, detail::tvec4<T>(0.0));
+		gx01 -= sw01 * (step(0.0, gx01) - T(0.5));
+		gy01 -= sw01 * (step(0.0, gy01) - T(0.5));
+
+		detail::tvec4<T> gx10 = ixy10 / T(7);
+		detail::tvec4<T> gy10 = floor(gx10) / T(7);
+		detail::tvec4<T> gz10 = floor(gy10) / T(6);
+		gx10 = fract(gx10) - T(0.5);
+		gy10 = fract(gy10) - T(0.5);
+		gz10 = fract(gz10) - T(0.5);
+		detail::tvec4<T> gw10 = detail::tvec4<T>(0.75) - abs(gx10) - abs(gy10) - abs(gz10);
+		detail::tvec4<T> sw10 = step(gw10, detail::tvec4<T>(0.0));
+		gx10 -= sw10 * (step(0.0, gx10) - T(0.5));
+		gy10 -= sw10 * (step(0.0, gy10) - T(0.5));
+
+		detail::tvec4<T> gx11 = ixy11 / T(7);
+		detail::tvec4<T> gy11 = floor(gx11) / T(7);
+		detail::tvec4<T> gz11 = floor(gy11) / T(6);
+		gx11 = fract(gx11) - T(0.5);
+		gy11 = fract(gy11) - T(0.5);
+		gz11 = fract(gz11) - T(0.5);
+		detail::tvec4<T> gw11 = detail::tvec4<T>(0.75) - abs(gx11) - abs(gy11) - abs(gz11);
+		detail::tvec4<T> sw11 = step(gw11, detail::tvec4<T>(0.0));
+		gx11 -= sw11 * (step(0.0, gx11) - T(0.5));
+		gy11 -= sw11 * (step(0.0, gy11) - T(0.5));
+
+		detail::tvec4<T> g0000(gx00.x, gy00.x, gz00.x, gw00.x);
+		detail::tvec4<T> g1000(gx00.y, gy00.y, gz00.y, gw00.y);
+		detail::tvec4<T> g0100(gx00.z, gy00.z, gz00.z, gw00.z);
+		detail::tvec4<T> g1100(gx00.w, gy00.w, gz00.w, gw00.w);
+		detail::tvec4<T> g0010(gx10.x, gy10.x, gz10.x, gw10.x);
+		detail::tvec4<T> g1010(gx10.y, gy10.y, gz10.y, gw10.y);
+		detail::tvec4<T> g0110(gx10.z, gy10.z, gz10.z, gw10.z);
+		detail::tvec4<T> g1110(gx10.w, gy10.w, gz10.w, gw10.w);
+		detail::tvec4<T> g0001(gx01.x, gy01.x, gz01.x, gw01.x);
+		detail::tvec4<T> g1001(gx01.y, gy01.y, gz01.y, gw01.y);
+		detail::tvec4<T> g0101(gx01.z, gy01.z, gz01.z, gw01.z);
+		detail::tvec4<T> g1101(gx01.w, gy01.w, gz01.w, gw01.w);
+		detail::tvec4<T> g0011(gx11.x, gy11.x, gz11.x, gw11.x);
+		detail::tvec4<T> g1011(gx11.y, gy11.y, gz11.y, gw11.y);
+		detail::tvec4<T> g0111(gx11.z, gy11.z, gz11.z, gw11.z);
+		detail::tvec4<T> g1111(gx11.w, gy11.w, gz11.w, gw11.w);
+
+		detail::tvec4<T> norm00 = taylorInvSqrt(detail::tvec4<T>(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100)));
+		g0000 *= norm00.x;
+		g0100 *= norm00.y;
+		g1000 *= norm00.z;
+		g1100 *= norm00.w;
+
+		detail::tvec4<T> norm01 = taylorInvSqrt(detail::tvec4<T>(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101)));
+		g0001 *= norm01.x;
+		g0101 *= norm01.y;
+		g1001 *= norm01.z;
+		g1101 *= norm01.w;
+
+		detail::tvec4<T> norm10 = taylorInvSqrt(detail::tvec4<T>(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110)));
+		g0010 *= norm10.x;
+		g0110 *= norm10.y;
+		g1010 *= norm10.z;
+		g1110 *= norm10.w;
+
+		detail::tvec4<T> norm11 = taylorInvSqrt(detail::tvec4<T>(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111)));
+		g0011 *= norm11.x;
+		g0111 *= norm11.y;
+		g1011 *= norm11.z;
+		g1111 *= norm11.w;
+
+		T n0000 = dot(g0000, Pf0);
+		T n1000 = dot(g1000, detail::tvec4<T>(Pf1.x, Pf0.y, Pf0.z, Pf0.w));
+		T n0100 = dot(g0100, detail::tvec4<T>(Pf0.x, Pf1.y, Pf0.z, Pf0.w));
+		T n1100 = dot(g1100, detail::tvec4<T>(Pf1.x, Pf1.y, Pf0.z, Pf0.w));
+		T n0010 = dot(g0010, detail::tvec4<T>(Pf0.x, Pf0.y, Pf1.z, Pf0.w));
+		T n1010 = dot(g1010, detail::tvec4<T>(Pf1.x, Pf0.y, Pf1.z, Pf0.w));
+		T n0110 = dot(g0110, detail::tvec4<T>(Pf0.x, Pf1.y, Pf1.z, Pf0.w));
+		T n1110 = dot(g1110, detail::tvec4<T>(Pf1.x, Pf1.y, Pf1.z, Pf0.w));
+		T n0001 = dot(g0001, detail::tvec4<T>(Pf0.x, Pf0.y, Pf0.z, Pf1.w));
+		T n1001 = dot(g1001, detail::tvec4<T>(Pf1.x, Pf0.y, Pf0.z, Pf1.w));
+		T n0101 = dot(g0101, detail::tvec4<T>(Pf0.x, Pf1.y, Pf0.z, Pf1.w));
+		T n1101 = dot(g1101, detail::tvec4<T>(Pf1.x, Pf1.y, Pf0.z, Pf1.w));
+		T n0011 = dot(g0011, detail::tvec4<T>(Pf0.x, Pf0.y, Pf1.z, Pf1.w));
+		T n1011 = dot(g1011, detail::tvec4<T>(Pf1.x, Pf0.y, Pf1.z, Pf1.w));
+		T n0111 = dot(g0111, detail::tvec4<T>(Pf0.x, Pf1.y, Pf1.z, Pf1.w));
+		T n1111 = dot(g1111, Pf1);
+
+		detail::tvec4<T> fade_xyzw = fade(Pf0);
+		detail::tvec4<T> n_0w = mix(detail::tvec4<T>(n0000, n1000, n0100, n1100), detail::tvec4<T>(n0001, n1001, n0101, n1101), fade_xyzw.w);
+		detail::tvec4<T> n_1w = mix(detail::tvec4<T>(n0010, n1010, n0110, n1110), detail::tvec4<T>(n0011, n1011, n0111, n1111), fade_xyzw.w);
+		detail::tvec4<T> n_zw = mix(n_0w, n_1w, fade_xyzw.z);
+		detail::tvec2<T> n_yzw = mix(detail::tvec2<T>(n_zw.x, n_zw.y), detail::tvec2<T>(n_zw.z, n_zw.w), fade_xyzw.y);
+		T n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x);
+		return T(2.2) * n_xyzw;
+	}
+
+	template <typename T>
+	GLM_FUNC_QUALIFIER T simplex(glm::detail::tvec2<T> const & v)
+	{
+		detail::tvec4<T> const C = detail::tvec4<T>(
+			T( 0.211324865405187),  // (3.0 -  sqrt(3.0)) / 6.0
+			T( 0.366025403784439),  //  0.5 * (sqrt(3.0)  - 1.0)
+			T(-0.577350269189626),	// -1.0 + 2.0 * C.x
+			T( 0.024390243902439)); //  1.0 / 41.0
+
+		// First corner
+		detail::tvec2<T> i  = floor(v + dot(v, detail::tvec2<T>(C[1])));
+		detail::tvec2<T> x0 = v -   i + dot(i, detail::tvec2<T>(C[0]));
+
+		// Other corners
+		//i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0
+		//i1.y = 1.0 - i1.x;
+		detail::tvec2<T> i1 = (x0.x > x0.y) ? detail::tvec2<T>(1, 0) : detail::tvec2<T>(0, 1);
+		// x0 = x0 - 0.0 + 0.0 * C.xx ;
+		// x1 = x0 - i1 + 1.0 * C.xx ;
+		// x2 = x0 - 1.0 + 2.0 * C.xx ;
+		detail::tvec4<T> x12 = detail::tvec4<T>(x0.x, x0.y, x0.x, x0.y) + detail::tvec4<T>(C.x, C.x, C.z, C.z);
+		x12 = detail::tvec4<T>(detail::tvec2<T>(x12) - i1, x12.z, x12.w);
+
+		// Permutations
+		i = mod(i, T(289)); // Avoid truncation effects in permutation
+		detail::tvec3<T> p = permute(
+			permute(i.y + detail::tvec3<T>(T(0), i1.y, T(1)))
+			+ i.x + detail::tvec3<T>(T(0), i1.x, T(1)));
+
+		detail::tvec3<T> m = max(T(0.5) - detail::tvec3<T>(
+			dot(x0, x0), 
+			dot(detail::tvec2<T>(x12.x, x12.y), detail::tvec2<T>(x12.x, x12.y)), 
+			dot(detail::tvec2<T>(x12.z, x12.w), detail::tvec2<T>(x12.z, x12.w))), T(0));
+		m = m * m ;
+		m = m * m ;
+
+		// Gradients: 41 points uniformly over a line, mapped onto a diamond.
+		// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
+
+		detail::tvec3<T> x = T(2) * fract(p * C.w) - T(1);
+		detail::tvec3<T> h = abs(x) - T(0.5);
+		detail::tvec3<T> ox = floor(x + T(0.5));
+		detail::tvec3<T> a0 = x - ox;
+
+		// Normalise gradients implicitly by scaling m
+		// Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h );
+		m *= T(1.79284291400159) - T(0.85373472095314) * (a0 * a0 + h * h);
+
+		// Compute final noise value at P
+		detail::tvec3<T> g;
+		g.x  = a0.x  * x0.x  + h.x  * x0.y;
+		//g.yz = a0.yz * x12.xz + h.yz * x12.yw;
+		g.y = a0.y * x12.x + h.y * x12.y;
+		g.z = a0.z * x12.z + h.z * x12.w;
+		return T(130) * dot(m, g);
+	}
+
+	template <typename T>
+	GLM_FUNC_QUALIFIER T simplex(detail::tvec3<T> const & v)
+	{ 
+		detail::tvec2<T> const C(1.0 / 6.0, 1.0 / 3.0);
+		detail::tvec4<T> const D(0.0, 0.5, 1.0, 2.0);
+
+		// First corner
+		detail::tvec3<T> i(floor(v + dot(v, detail::tvec3<T>(C.y))));
+		detail::tvec3<T> x0(v - i + dot(i, detail::tvec3<T>(C.x)));
+
+		// Other corners
+		detail::tvec3<T> g(step(detail::tvec3<T>(x0.y, x0.z, x0.x), x0));
+		detail::tvec3<T> l(T(1) - g);
+		detail::tvec3<T> i1(min(g, detail::tvec3<T>(l.z, l.x, l.y)));
+		detail::tvec3<T> i2(max(g, detail::tvec3<T>(l.z, l.x, l.y)));
+
+		//   x0 = x0 - 0.0 + 0.0 * C.xxx;
+		//   x1 = x0 - i1  + 1.0 * C.xxx;
+		//   x2 = x0 - i2  + 2.0 * C.xxx;
+		//   x3 = x0 - 1.0 + 3.0 * C.xxx;
+		detail::tvec3<T> x1(x0 - i1 + C.x);
+		detail::tvec3<T> x2(x0 - i2 + C.y); // 2.0*C.x = 1/3 = C.y
+		detail::tvec3<T> x3(x0 - D.y);      // -1.0+3.0*C.x = -0.5 = -D.y
+
+		// Permutations
+		i = mod289(i); 
+		detail::tvec4<T> p(permute(permute(permute( 
+			i.z + detail::tvec4<T>(T(0), i1.z, i2.z, T(1))) + 
+			i.y + detail::tvec4<T>(T(0), i1.y, i2.y, T(1))) + 
+			i.x + detail::tvec4<T>(T(0), i1.x, i2.x, T(1))));
+
+		// Gradients: 7x7 points over a square, mapped onto an octahedron.
+		// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
+		T n_ = T(0.142857142857); // 1.0/7.0
+		detail::tvec3<T> ns(n_ * detail::tvec3<T>(D.w, D.y, D.z) - detail::tvec3<T>(D.x, D.z, D.x));
+
+		detail::tvec4<T> j(p - T(49) * floor(p * ns.z * ns.z));  //  mod(p,7*7)
+
+		detail::tvec4<T> x_(floor(j * ns.z));
+		detail::tvec4<T> y_(floor(j - T(7) * x_));    // mod(j,N)
+
+		detail::tvec4<T> x(x_ * ns.x + ns.y);
+		detail::tvec4<T> y(y_ * ns.x + ns.y);
+		detail::tvec4<T> h(T(1) - abs(x) - abs(y));
+
+		detail::tvec4<T> b0(x.x, x.y, y.x, y.y);
+		detail::tvec4<T> b1(x.z, x.w, y.z, y.w);
+
+		// vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
+		// vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
+		detail::tvec4<T> s0(floor(b0) * T(2) + T(1));
+		detail::tvec4<T> s1(floor(b1) * T(2) + T(1));
+		detail::tvec4<T> sh(-step(h, detail::tvec4<T>(0.0)));
+
+		detail::tvec4<T> a0 = detail::tvec4<T>(b0.x, b0.z, b0.y, b0.w) + detail::tvec4<T>(s0.x, s0.z, s0.y, s0.w) * detail::tvec4<T>(sh.x, sh.x, sh.y, sh.y);
+		detail::tvec4<T> a1 = detail::tvec4<T>(b1.x, b1.z, b1.y, b1.w) + detail::tvec4<T>(s1.x, s1.z, s1.y, s1.w) * detail::tvec4<T>(sh.z, sh.z, sh.w, sh.w);
+
+		detail::tvec3<T> p0(a0.x, a0.y, h.x);
+		detail::tvec3<T> p1(a0.z, a0.w, h.y);
+		detail::tvec3<T> p2(a1.x, a1.y, h.z);
+		detail::tvec3<T> p3(a1.z, a1.w, h.w);
+
+		// Normalise gradients
+		detail::tvec4<T> norm = taylorInvSqrt(detail::tvec4<T>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
+		p0 *= norm.x;
+		p1 *= norm.y;
+		p2 *= norm.z;
+		p3 *= norm.w;
+
+		// Mix final noise value
+		detail::tvec4<T> m = max(T(0.6) - detail::tvec4<T>(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), T(0));
+		m = m * m;
+		return T(42) * dot(m * m, detail::tvec4<T>(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
+	}
+
+	template <typename T>
+	GLM_FUNC_QUALIFIER T simplex(detail::tvec4<T> const & v)
+	{
+		detail::tvec4<T> const C(
+			0.138196601125011,  // (5 - sqrt(5))/20  G4
+			0.276393202250021,  // 2 * G4
+			0.414589803375032,  // 3 * G4
+			-0.447213595499958); // -1 + 4 * G4
+
+		// (sqrt(5) - 1)/4 = F4, used once below
+		T const F4 = T(0.309016994374947451);
+
+		// First corner
+		detail::tvec4<T> i  = floor(v + dot(v, vec4(F4)));
+		detail::tvec4<T> x0 = v -   i + dot(i, vec4(C.x));
+
+		// Other corners
+
+		// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
+		detail::tvec4<T> i0;
+		detail::tvec3<T> isX = step(detail::tvec3<T>(x0.y, x0.z, x0.w), detail::tvec3<T>(x0.x));
+		detail::tvec3<T> isYZ = step(detail::tvec3<T>(x0.z, x0.w, x0.w), detail::tvec3<T>(x0.y, x0.y, x0.z));
+		//  i0.x = dot(isX, vec3(1.0));
+		//i0.x = isX.x + isX.y + isX.z;
+		//i0.yzw = T(1) - isX;
+		i0 = detail::tvec4<T>(isX.x + isX.y + isX.z, T(1) - isX);
+		//  i0.y += dot(isYZ.xy, vec2(1.0));
+		i0.y += isYZ.x + isYZ.y;
+		//i0.zw += 1.0 - detail::tvec2<T>(isYZ.x, isYZ.y);
+		i0.z += T(1) - isYZ.x;
+		i0.w += T(1) - isYZ.y;
+		i0.z += isYZ.z;
+		i0.w += T(1) - isYZ.z;
+
+		// i0 now contains the unique values 0,1,2,3 in each channel
+		detail::tvec4<T> i3 = clamp(i0, 0.0, 1.0);
+		detail::tvec4<T> i2 = clamp(i0 - 1.0, 0.0, 1.0);
+		detail::tvec4<T> i1 = clamp(i0 - 2.0, 0.0, 1.0);
+
+		//  x0 = x0 - 0.0 + 0.0 * C.xxxx
+		//  x1 = x0 - i1  + 0.0 * C.xxxx
+		//  x2 = x0 - i2  + 0.0 * C.xxxx
+		//  x3 = x0 - i3  + 0.0 * C.xxxx
+		//  x4 = x0 - 1.0 + 4.0 * C.xxxx
+		detail::tvec4<T> x1 = x0 - i1 + C.x;
+		detail::tvec4<T> x2 = x0 - i2 + C.y;
+		detail::tvec4<T> x3 = x0 - i3 + C.z;
+		detail::tvec4<T> x4 = x0 + C.w;
+
+		// Permutations
+		i = mod(i, T(289)); 
+		T j0 = permute(permute(permute(permute(i.w) + i.z) + i.y) + i.x);
+		detail::tvec4<T> j1 = permute(permute(permute(permute(
+					i.w + detail::tvec4<T>(i1.w, i2.w, i3.w, T(1)))
+				+ i.z + detail::tvec4<T>(i1.z, i2.z, i3.z, T(1)))
+				+ i.y + detail::tvec4<T>(i1.y, i2.y, i3.y, T(1)))
+				+ i.x + detail::tvec4<T>(i1.x, i2.x, i3.x, T(1)));
+
+		// Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope
+		// 7*7*6 = 294, which is close to the ring size 17*17 = 289.
+		detail::tvec4<T> ip = detail::tvec4<T>(T(1) / T(294), T(1) / T(49), T(1) / T(7), T(0));
+
+		detail::tvec4<T> p0 = grad4(j0,   ip);
+		detail::tvec4<T> p1 = grad4(j1.x, ip);
+		detail::tvec4<T> p2 = grad4(j1.y, ip);
+		detail::tvec4<T> p3 = grad4(j1.z, ip);
+		detail::tvec4<T> p4 = grad4(j1.w, ip);
+
+		// Normalise gradients
+		detail::tvec4<T> norm = taylorInvSqrt(detail::tvec4<T>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
+		p0 *= norm.x;
+		p1 *= norm.y;
+		p2 *= norm.z;
+		p3 *= norm.w;
+		p4 *= taylorInvSqrt(dot(p4, p4));
+
+		// Mix contributions from the five corners
+		detail::tvec3<T> m0 = max(T(0.6) - detail::tvec3<T>(dot(x0, x0), dot(x1, x1), dot(x2, x2)), T(0));
+		detail::tvec2<T> m1 = max(T(0.6) - detail::tvec2<T>(dot(x3, x3), dot(x4, x4)             ), T(0));
+		m0 = m0 * m0;
+		m1 = m1 * m1;
+		return T(49) * 
+			(dot(m0 * m0, detail::tvec3<T>(dot(p0, x0), dot(p1, x1), dot(p2, x2))) + 
+			dot(m1 * m1, detail::tvec2<T>(dot(p3, x3), dot(p4, x4))));
+	}
 }//namespace glm
 }//namespace glm

+ 2 - 2
glm/gtc/quaternion.inl

@@ -29,8 +29,8 @@
 #include <limits>
 #include <limits>
 
 
 namespace glm{
 namespace glm{
-namespace detail{
-
+namespace detail
+{
     template <typename T> 
     template <typename T> 
     GLM_FUNC_QUALIFIER tquat<T>::tquat() : 
     GLM_FUNC_QUALIFIER tquat<T>::tquat() : 
         x(0),
         x(0),

+ 113 - 177
glm/gtc/random.inl

@@ -9,200 +9,136 @@
 
 
 #include <ctime>
 #include <ctime>
 #include <cassert>
 #include <cassert>
+#include "../core/_vectorize.hpp"
 
 
 namespace glm{
 namespace glm{
-
-template <> 
-GLM_FUNC_QUALIFIER glm::half linearRand
-(
-	glm::half const & Min, 
-	glm::half const & Max
-)
-{
-	return glm::half(float(std::rand()) / float(RAND_MAX) * (float(Max) - float(Min)) + float(Min));
-}
-	
-template <> 
-GLM_FUNC_QUALIFIER float linearRand
-(
-	float const & Min, 
-	float const & Max
-)
-{
-	return float(std::rand()) / float(RAND_MAX) * (Max - Min) + Min;
-}
-	
-template <> 
-GLM_FUNC_QUALIFIER double linearRand
-(
-	double const & Min, 
-	double const & Max
-)
-{
-	return double(std::rand()) / double(RAND_MAX) * (Max - Min) + Min;
-}
-	
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec2<T> linearRand
-(
-	detail::tvec2<T> const & Min, 
-	detail::tvec2<T> const & Max
-)
-{
-	return detail::tvec2<T>(
-		linearRand(Min.x, Max.x),
-		linearRand(Min.y, Max.y));
-}
-	
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec3<T> linearRand
-(
-	detail::tvec3<T> const & Min, 
-	detail::tvec3<T> const & Max
-)
+namespace detail
 {
 {
-	return detail::tvec3<T>(
-		linearRand(Min.x, Max.x),
-		linearRand(Min.y, Max.y),
-		linearRand(Min.z, Max.z));
-}
+	struct compute_linearRand
+	{
+		template <typename T>
+		GLM_FUNC_QUALIFIER T operator() (T const & Min, T const & Max) const
+		{
+			GLM_STATIC_ASSERT(0, "'linearRand' invalid template parameter type. GLM_GTC_random only supports floating-point template types.");
+			return Min;
+		}
+	};
 
 
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec4<T> linearRand
-(
-	detail::tvec4<T> const & Min, 
-	detail::tvec4<T> const & Max
-)
-{
-	return detail::tvec4<T>(
-		linearRand(Min.x, Max.x),
-		linearRand(Min.y, Max.y),
-		linearRand(Min.z, Max.z),
-		linearRand(Min.w, Max.w));
-}
+	template <>
+	GLM_FUNC_QUALIFIER half compute_linearRand::operator()<half> (half const & Min, half const & Max) const
+	{
+		return half(float(std::rand()) / float(RAND_MAX) * (float(Max) - float(Min)) + float(Min));
+	}
 
 
-template <typename genType> 
-GLM_FUNC_QUALIFIER genType gaussRand
-(
-	genType const & Mean,	
-	genType const & Deviation
-)
-{
-    genType w, x1, x2;
+	template <>
+	GLM_FUNC_QUALIFIER float compute_linearRand::operator()<float> (float const & Min, float const & Max) const
+	{
+		return float(std::rand()) / float(RAND_MAX) * (Max - Min) + Min;
+	}
+
+	template <>
+	GLM_FUNC_QUALIFIER double compute_linearRand::operator()<double> (double const & Min, double const & Max) const
+	{
+		return double(std::rand()) / double(RAND_MAX) * (Max - Min) + Min;
+	}
+}//namespace detail
+
+	template <typename genType> 
+	GLM_FUNC_QUALIFIER genType linearRand
+	(
+		genType const & Min, 
+		genType const & Max
+	)
+	{
+		return detail::compute_linearRand()(Min, Max);
+	}
+
+	VECTORIZE_VEC_VEC(linearRand)
+
+	template <typename genType> 
+	GLM_FUNC_QUALIFIER genType gaussRand
+	(
+		genType const & Mean,	
+		genType const & Deviation
+	)
+	{
+		genType w, x1, x2;
 	
 	
-    do
-    {
-        x1 = linearRand(genType(-1), genType(1));
-        x2 = linearRand(genType(-1), genType(1));
+		do
+		{
+			x1 = linearRand(genType(-1), genType(1));
+			x2 = linearRand(genType(-1), genType(1));
 		
 		
-        w = x1 * x1 + x2 * x2;
-    } while(w > genType(1));
+			w = x1 * x1 + x2 * x2;
+		} while(w > genType(1));
 	
 	
-    return x2 * Deviation * Deviation * sqrt((genType(-2) * log(w)) / w) + Mean;
-}
+		return x2 * Deviation * Deviation * sqrt((genType(-2) * log(w)) / w) + Mean;
+	}
 
 
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec2<T> gaussRand
-(
-	detail::tvec2<T> const & Mean, 
-	detail::tvec2<T> const & Deviation
-)
-{
-	return detail::tvec2<T>(
-		gaussRand(Mean.x, Deviation.x),
-		gaussRand(Mean.y, Deviation.y));
-}
-	
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec3<T> gaussRand
-(
-	detail::tvec3<T> const & Mean, 
-	detail::tvec3<T> const & Deviation
-)
-{
-	return detail::tvec3<T>(
-		gaussRand(Mean.x, Deviation.x),
-		gaussRand(Mean.y, Deviation.y),
-		gaussRand(Mean.z, Deviation.z));
-}
-	
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec4<T> gaussRand
-(
-	detail::tvec4<T> const & Mean, 
-	detail::tvec4<T> const & Deviation
-)
-{
-	return detail::tvec4<T>(
-		gaussRand(Mean.x, Deviation.x),
-		gaussRand(Mean.y, Deviation.y),
-		gaussRand(Mean.z, Deviation.z),
-		gaussRand(Mean.w, Deviation.w));
-}
-	
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec2<T> diskRand
-(
-	T const & Radius
-)
-{		
-	detail::tvec2<T> Result(T(0));
-	T LenRadius(T(0));
+	VECTORIZE_VEC_VEC(gaussRand)
+
+	template <typename T>
+	GLM_FUNC_QUALIFIER detail::tvec2<T> diskRand
+	(
+		T const & Radius
+	)
+	{		
+		detail::tvec2<T> Result(T(0));
+		T LenRadius(T(0));
 		
 		
-	do
-	{
-		Result = linearRand(detail::tvec2<T>(-Radius), detail::tvec2<T>(Radius));
-		LenRadius = length(Result);
-	}
-	while(LenRadius > Radius);
+		do
+		{
+			Result = linearRand(detail::tvec2<T>(-Radius), detail::tvec2<T>(Radius));
+			LenRadius = length(Result);
+		}
+		while(LenRadius > Radius);
 		
 		
-	return Result;
-}
+		return Result;
+	}
 	
 	
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tvec3<T> ballRand
-(
-	T const & Radius
-)
-{		
-	detail::tvec3<T> Result(T(0));
-	T LenRadius(T(0));
+	template <typename T>
+	GLM_FUNC_QUALIFIER detail::tvec3<T> ballRand
+	(
+		T const & Radius
+	)
+	{		
+		detail::tvec3<T> Result(T(0));
+		T LenRadius(T(0));
 		
 		
-	do
-	{
-		Result = linearRand(detail::tvec3<T>(-Radius), detail::tvec3<T>(Radius));
-		LenRadius = length(Result);
-	}
-	while(LenRadius > Radius);
+		do
+		{
+			Result = linearRand(detail::tvec3<T>(-Radius), detail::tvec3<T>(Radius));
+			LenRadius = length(Result);
+		}
+		while(LenRadius > Radius);
 		
 		
-	return Result;
-}
+		return Result;
+	}
 	
 	
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec2<T> circularRand
-(
-	T const & Radius
-)
-{
-	T a = linearRand(T(0), T(6.283185307179586476925286766559f));
-	return detail::tvec2<T>(cos(a), sin(a)) * Radius;		
-}
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tvec2<T> circularRand
+	(
+		T const & Radius
+	)
+	{
+		T a = linearRand(T(0), T(6.283185307179586476925286766559f));
+		return detail::tvec2<T>(cos(a), sin(a)) * Radius;		
+	}
 	
 	
-template <typename T> 
-GLM_FUNC_QUALIFIER detail::tvec3<T> sphericalRand
-(
-	T const & Radius
-)
-{
-	T z = linearRand(T(-1), T(1));
-	T a = linearRand(T(0), T(6.283185307179586476925286766559f));
+	template <typename T> 
+	GLM_FUNC_QUALIFIER detail::tvec3<T> sphericalRand
+	(
+		T const & Radius
+	)
+	{
+		T z = linearRand(T(-1), T(1));
+		T a = linearRand(T(0), T(6.283185307179586476925286766559f));
 	
 	
-	T r = sqrt(T(1) - z * z);
+		T r = sqrt(T(1) - z * z);
 	
 	
-	T x = r * cos(a);
-	T y = r * sin(a);
+		T x = r * cos(a);
+		T y = r * sin(a);
 	
 	
-	return detail::tvec3<T>(x, y, z) * Radius;	
-}
-
+		return detail::tvec3<T>(x, y, z) * Radius;	
+	}
 }//namespace glm
 }//namespace glm

+ 87 - 161
glm/gtc/swizzle.inl

@@ -26,165 +26,91 @@
 /// @author Christophe Riccio
 /// @author Christophe Riccio
 ///////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////
 
 
-namespace glm{
-
-template <typename T, template <typename> class vecType>
-GLM_FUNC_QUALIFIER T swizzle
-(	
-	vecType<T> const & v,
-	comp x
-)
-{
-	assert(int(x) < int(vecType<T>::value_size));
-	return v[x];
-}
-
-template <typename T, template <typename> class vecType>
-GLM_FUNC_QUALIFIER detail::tvec2<T> swizzle
-(
-	vecType<T> const & v,
-	comp x, comp y
-)
-{
-	return detail::tvec2<T>(
-		v[x],
-		v[y]);
-}
-
-template <typename T, template <typename> class vecType>
-GLM_FUNC_QUALIFIER detail::tvec3<T> swizzle
-(
-	vecType<T> const & v,
-	comp x, comp y, comp z
-)
-{
-	return detail::tvec3<T>(
-		v[x],
-		v[y],
-		v[z]);
-}
-
-template <typename T, template <typename> class vecType>
-GLM_FUNC_QUALIFIER detail::tvec4<T> swizzle
-(
-	vecType<T> const & v,
-	comp x, comp y, comp z, comp w
-)
-{
-	return detail::tvec4<T>(v[x], v[y],	v[z], v[w]);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER T& swizzle
-(
-	detail::tvec4<T> & v,
-	comp x
-)
-{
-	return v[x];
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tref2<T> swizzle
-(
-	detail::tvec4<T> & v,
-	comp x, comp y
-)
-{
-	return detail::tref2<T>(v[x], v[y]);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tref3<T> swizzle
-(
-	detail::tvec4<T> & v,
-	comp x, comp y, comp z
-)
-{
-	return detail::tref3<T>(v[x], v[y],	v[z]);
-}
-
-template <typename T>
-GLM_FUNC_QUALIFIER detail::tref4<T> swizzle
-(
-	detail::tvec4<T> & v,
-	comp x, comp y, comp z, comp w
-)
-{
-	return detail::tref4<T>(v[x], v[y],	v[z], v[w]);
-}
-/*
-template <comp x>
-GLM_FUNC_QUALIFIER float& swizzle
-(
-	detail::tvec4<float> & v
-)
-{
-	return v[x];
-}
-
-template <comp x>
-GLM_FUNC_QUALIFIER int& swizzle
-(
-	detail::tvec4<int> & v
-)
-{
-	return v[x];
-}
-
-template <comp x, comp y>
-GLM_FUNC_QUALIFIER detail::tref2<float> swizzle
-(
-	detail::tvec4<float> & v
-)
-{
-	return detail::tref2<float>(v[x], v[y]);
-}
-
-template <comp x, comp y>
-GLM_FUNC_QUALIFIER detail::tref2<int> swizzle
-(
-	detail::tvec4<int> & v
-)
-{
-	return detail::tref2<int>(v[x], v[y]);
-}
-
-template <comp x, comp y, comp z>
-GLM_FUNC_QUALIFIER detail::tref3<float> swizzle
-(
-	detail::tvec4<float> & v
-)
-{
-	return detail::tref3<float>(v[x], v[y],	v[z]);
-}
-	
-template <comp x, comp y, comp z>
-GLM_FUNC_QUALIFIER detail::tref3<int> swizzle
-(
-	detail::tvec4<int> & v
-)
-{
-	return detail::tref3<int>(v[x], v[y], v[z]);
-}
-
-template <comp x, comp y, comp z, comp w>
-GLM_FUNC_QUALIFIER detail::tref4<float> swizzle
-(
-	detail::tvec4<float> & v
-)
-{
-	return detail::tref4<float>(v[x], v[y],	v[z], v[w]);
-}
-
-template <comp x, comp y, comp z, comp w>
-GLM_FUNC_QUALIFIER detail::tref4<int> swizzle
-(
-	detail::tvec4<int> & v
-)
-{
-	return detail::tref4<int>(v[x], v[y],	v[z], v[w]);
-}
-*/
-
+namespace glm
+{
+	template <typename T, template <typename> class vecType>
+	GLM_FUNC_QUALIFIER T swizzle
+	(	
+		vecType<T> const & v,
+		comp x
+	)
+	{
+		assert(int(x) < int(vecType<T>::value_size));
+		return v[x];
+	}
+
+	template <typename T, template <typename> class vecType>
+	GLM_FUNC_QUALIFIER detail::tvec2<T> swizzle
+	(
+		vecType<T> const & v,
+		comp x, comp y
+	)
+	{
+		return detail::tvec2<T>(
+			v[x],
+			v[y]);
+	}
+
+	template <typename T, template <typename> class vecType>
+	GLM_FUNC_QUALIFIER detail::tvec3<T> swizzle
+	(
+		vecType<T> const & v,
+		comp x, comp y, comp z
+	)
+	{
+		return detail::tvec3<T>(
+			v[x],
+			v[y],
+			v[z]);
+	}
+
+	template <typename T, template <typename> class vecType>
+	GLM_FUNC_QUALIFIER detail::tvec4<T> swizzle
+	(
+		vecType<T> const & v,
+		comp x, comp y, comp z, comp w
+	)
+	{
+		return detail::tvec4<T>(v[x], v[y],	v[z], v[w]);
+	}
+
+	template <typename T>
+	GLM_FUNC_QUALIFIER T& swizzle
+	(
+		detail::tvec4<T> & v,
+		comp x
+	)
+	{
+		return v[x];
+	}
+
+	template <typename T>
+	GLM_FUNC_QUALIFIER detail::tref2<T> swizzle
+	(
+		detail::tvec4<T> & v,
+		comp x, comp y
+	)
+	{
+		return detail::tref2<T>(v[x], v[y]);
+	}
+
+	template <typename T>
+	GLM_FUNC_QUALIFIER detail::tref3<T> swizzle
+	(
+		detail::tvec4<T> & v,
+		comp x, comp y, comp z
+	)
+	{
+		return detail::tref3<T>(v[x], v[y],	v[z]);
+	}
+
+	template <typename T>
+	GLM_FUNC_QUALIFIER detail::tref4<T> swizzle
+	(
+		detail::tvec4<T> & v,
+		comp x, comp y, comp z, comp w
+	)
+	{
+		return detail::tref4<T>(v[x], v[y],	v[z], v[w]);
+	}
 }//namespace glm
 }//namespace glm

+ 129 - 224
glm/gtx/fast_square_root.inl

@@ -2,232 +2,137 @@
 // OpenGL Mathematics Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net)
 // OpenGL Mathematics Copyright (c) 2005 - 2011 G-Truc Creation (www.g-truc.net)
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // Created : 2006-01-04
 // Created : 2006-01-04
-// Updated : 2008-10-07
+// Updated : 2011-10-14
 // Licence : This source is under MIT License
 // Licence : This source is under MIT License
 // File    : glm/gtx/fast_square_root.inl
 // File    : glm/gtx/fast_square_root.inl
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 
-namespace glm{
-
-// fastSqrt
-template <typename genType>
-GLM_FUNC_QUALIFIER genType fastSqrt
-(
-	genType const & x
-)
-{
-    return genType(1) / fastInverseSqrt(x);
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER detail::tvec2<valType> fastSqrt
-(
-	detail::tvec2<valType> const & x
-)
-{
-    return detail::tvec2<valType>(
-        fastSqrt(x.x), 
-        fastSqrt(x.y));
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER detail::tvec3<valType> fastSqrt
-(
-	detail::tvec3<valType> const & x
-)
-{
-    return detail::tvec3<valType>(
-        fastSqrt(x.x), 
-        fastSqrt(x.y), 
-        fastSqrt(x.z));
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER detail::tvec4<valType> fastSqrt
-(
-	detail::tvec4<valType> const & x
-)
-{
-    return detail::tvec4<valType>(
-        fastSqrt(x.x), 
-        fastSqrt(x.y), 
-        fastSqrt(x.z), 
-        fastSqrt(x.w));
-}
-
-// fastInversesqrt
-template <typename genType>
-GLM_FUNC_QUALIFIER genType fastInverseSqrt
-(
-	genType const & x
-)
-{
-	genType tmp = x;
-    float xhalf = 0.5f * float(tmp);
-    uint i = *(uint*)&x;
-    i = 0x5f375a86 - (i >> 1);
-    //x = *(float*)&i;
-	//x = *((float*)(char*)&i);
-	tmp = detail::uif(i).f;
-	tmp = tmp * (1.5f - xhalf * tmp * tmp);
-    return genType(tmp);
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER detail::tvec2<valType> fastInverseSqrt
-(
-	detail::tvec2<valType> const & x
-)
-{
-    return detail::tvec2<valType>(
-        fastInverseSqrt(x.x), 
-        fastInverseSqrt(x.y));
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER detail::tvec3<valType> fastInverseSqrt
-(
-	detail::tvec3<valType> const & x
-)
-{
-    return detail::tvec3<valType>(
-        fastInverseSqrt(x.x), 
-        fastInverseSqrt(x.y), 
-        fastInverseSqrt(x.z));
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER detail::tvec4<valType> fastInverseSqrt
-(
-	detail::tvec4<valType> const & x
-)
-{
-    return detail::tvec4<valType>(
-        fastInverseSqrt(x.x), 
-        fastInverseSqrt(x.y), 
-        fastInverseSqrt(x.z), 
-        fastInverseSqrt(x.w));
-}
-
-// fastLength
-template <typename genType>
-GLM_FUNC_QUALIFIER genType fastLength
-(
-	genType const & x
-)
-{
-    return abs(x);
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER valType fastLength
-(
-	detail::tvec2<valType> const & x
-)
-{
-    valType sqr = x.x * x.x + x.y * x.y;
-    return fastSqrt(sqr);
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER valType fastLength
-(
-	detail::tvec3<valType> const & x
-)
-{
-    valType sqr = x.x * x.x + x.y * x.y + x.z * x.z;
-    return fastSqrt(sqr);
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER valType fastLength
-(
-	detail::tvec4<valType> const & x
-)
-{
-    valType sqr = x.x * x.x + x.y * x.y + x.z * x.z + x.w * x.w;
-    return fastSqrt(sqr);
-}
-
-// fastDistance
-template <typename genType>
-GLM_FUNC_QUALIFIER genType fastDistance
-(
-	genType const & x, 
-	genType const & y
-)
-{
-    return fastLength(y - x);
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER valType fastDistance
-(
-	detail::tvec2<valType> const & x, 
-	detail::tvec2<valType> const & y
-)
-{
-    return fastLength(y - x);
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER valType fastDistance
-(
-	detail::tvec3<valType> const & x, 
-	detail::tvec3<valType> const & y
-)
-{
-    return fastLength(y - x);
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER valType fastDistance
-(
-	detail::tvec4<valType> const & x, 
-	detail::tvec4<valType> const & y
-)
-{
-    return fastLength(y - x);
-}
-
-// fastNormalize
-template <typename genType>
-GLM_FUNC_QUALIFIER genType fastNormalize
-(
-	genType const & x
-)
-{
-    return x > genType(0) ? genType(1) : -genType(1);
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER detail::tvec2<valType> fastNormalize
-(
-	detail::tvec2<valType> const & x
-)
-{
-    valType sqr = x.x * x.x + x.y * x.y;
-    return x * fastInverseSqrt(sqr);
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER detail::tvec3<valType> fastNormalize
-(
-	detail::tvec3<valType> const & x
-)
-{
-    valType sqr = x.x * x.x + x.y * x.y + x.z * x.z;
-    return x * fastInverseSqrt(sqr);
-}
-
-template <typename valType>
-GLM_FUNC_QUALIFIER detail::tvec4<valType> fastNormalize
-(
-	detail::tvec4<valType> const & x
-)
-{
-    valType sqr = x.x * x.x + x.y * x.y + x.z * x.z + x.w * x.w;
-    return x * fastInverseSqrt(sqr);
-}
-
+#include "../core/_vectorize.hpp"
+
+namespace glm
+{
+	// fastSqrt
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType fastSqrt
+	(
+		genType const & x
+	)
+	{
+		GLM_STATIC_ASSERT(detail::type<genType>::is_float, "'fastSqrt' only accept floating-point input");
+
+		return genType(1) / fastInverseSqrt(x);
+	}
+
+	VECTORIZE_VEC(fastSqrt)
+
+	// fastInversesqrt
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType fastInverseSqrt
+	(
+		genType const & x
+	)
+	{
+		genType tmp = x;
+		float xhalf = 0.5f * float(tmp);
+		uint i = *(uint*)&x;
+		i = 0x5f375a86 - (i >> 1);
+		//x = *(float*)&i;
+		//x = *((float*)(char*)&i);
+		tmp = detail::uif(i).f;
+		tmp = tmp * (1.5f - xhalf * tmp * tmp);
+		return genType(tmp);
+	}
+
+	VECTORIZE_VEC(fastInverseSqrt)
+
+	// fastLength
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType fastLength
+	(
+		genType const & x
+	)
+	{
+		return abs(x);
+	}
+
+	template <typename valType>
+	GLM_FUNC_QUALIFIER valType fastLength
+	(
+		detail::tvec2<valType> const & x
+	)
+	{
+		valType sqr = x.x * x.x + x.y * x.y;
+		return fastSqrt(sqr);
+	}
+
+	template <typename valType>
+	GLM_FUNC_QUALIFIER valType fastLength
+	(
+		detail::tvec3<valType> const & x
+	)
+	{
+		valType sqr = x.x * x.x + x.y * x.y + x.z * x.z;
+		return fastSqrt(sqr);
+	}
+
+	template <typename valType>
+	GLM_FUNC_QUALIFIER valType fastLength
+	(
+		detail::tvec4<valType> const & x
+	)
+	{
+		valType sqr = x.x * x.x + x.y * x.y + x.z * x.z + x.w * x.w;
+		return fastSqrt(sqr);
+	}
+
+	// fastDistance
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType fastDistance
+	(
+		genType const & x, 
+		genType const & y
+	)
+	{
+		return fastLength(y - x);
+	}
+
+	// fastNormalize
+	template <typename genType>
+	GLM_FUNC_QUALIFIER genType fastNormalize
+	(
+		genType const & x
+	)
+	{
+		return x > genType(0) ? genType(1) : -genType(1);
+	}
+
+	template <typename valType>
+	GLM_FUNC_QUALIFIER detail::tvec2<valType> fastNormalize
+	(
+		detail::tvec2<valType> const & x
+	)
+	{
+		valType sqr = x.x * x.x + x.y * x.y;
+		return x * fastInverseSqrt(sqr);
+	}
+
+	template <typename valType>
+	GLM_FUNC_QUALIFIER detail::tvec3<valType> fastNormalize
+	(
+		detail::tvec3<valType> const & x
+	)
+	{
+		valType sqr = x.x * x.x + x.y * x.y + x.z * x.z;
+		return x * fastInverseSqrt(sqr);
+	}
+
+	template <typename valType>
+	GLM_FUNC_QUALIFIER detail::tvec4<valType> fastNormalize
+	(
+		detail::tvec4<valType> const & x
+	)
+	{
+		valType sqr = x.x * x.x + x.y * x.y + x.z * x.z + x.w * x.w;
+		return x * fastInverseSqrt(sqr);
+	}
 }//namespace glm
 }//namespace glm