1///////////////////////////////////////////////////////////////////////////////////
2/// OpenGL Mathematics (glm.g-truc.net)
3///
4/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net)
5/// Permission is hereby granted, free of charge, to any person obtaining a copy
6/// of this software and associated documentation files (the "Software"), to deal
7/// in the Software without restriction, including without limitation the rights
8/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9/// copies of the Software, and to permit persons to whom the Software is
10/// furnished to do so, subject to the following conditions:
11///
12/// The above copyright notice and this permission notice shall be included in
13/// all copies or substantial portions of the Software.
14///
15/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21/// THE SOFTWARE.
22///
23/// @ref core
24/// @file glm/core/func_exponential.inl
25/// @date 2008-08-03 / 2011-06-15
26/// @author Christophe Riccio
27///////////////////////////////////////////////////////////////////////////////////
28
29#include "func_vector_relational.hpp"
30#include "_vectorize.hpp"
31#include <limits>
32#include <cassert>
33
34namespace glm{
35namespace detail
36{
37	template <bool isFloat>
38	struct compute_log2
39	{
40		template <typename T>
41		T operator() (T const & Value) const;
42	};
43
44	template <>
45	struct compute_log2<true>
46	{
47		template <typename T>
48		GLM_FUNC_QUALIFIER T operator() (T const & Value) const
49		{
50			return static_cast<T>(::std::log(Value)) * static_cast<T>(1.4426950408889634073599246810019);
51		}
52	};
53
54	template <template <class, precision> class vecType, typename T, precision P>
55	struct compute_inversesqrt
56	{
57		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
58		{
59			return static_cast<T>(1) / sqrt(x);
60		}
61	};
62
63	template <template <class, precision> class vecType>
64	struct compute_inversesqrt<vecType, float, lowp>
65	{
66		GLM_FUNC_QUALIFIER static vecType<float, lowp> call(vecType<float, lowp> const & x)
67		{
68			vecType<float, lowp> tmp(x);
69			vecType<float, lowp> xhalf(tmp * 0.5f);
70			vecType<uint, lowp>* p = reinterpret_cast<vecType<uint, lowp>*>(const_cast<vecType<float, lowp>*>(&x));
71			vecType<uint, lowp> i = vecType<uint, lowp>(0x5f375a86) - (*p >> vecType<uint, lowp>(1));
72			vecType<float, lowp>* ptmp = reinterpret_cast<vecType<float, lowp>*>(&i);
73			tmp = *ptmp;
74			tmp = tmp * (1.5f - xhalf * tmp * tmp);
75			return tmp;
76		}
77	};
78}//namespace detail
79
80	// pow
81	template <typename genType>
82	GLM_FUNC_QUALIFIER genType pow
83	(
84		genType const & x,
85		genType const & y
86	)
87	{
88		GLM_STATIC_ASSERT(
89			std::numeric_limits<genType>::is_iec559,
90			"'pow' only accept floating-point inputs");
91
92		return std::pow(x, y);
93	}
94
95	VECTORIZE_VEC_VEC(pow)
96
97	// exp
98	template <typename genType>
99	GLM_FUNC_QUALIFIER genType exp
100	(
101		genType const & x
102	)
103	{
104		GLM_STATIC_ASSERT(
105			std::numeric_limits<genType>::is_iec559,
106			"'exp' only accept floating-point inputs");
107
108		return std::exp(x);
109	}
110
111	VECTORIZE_VEC(exp)
112
113	// log
114	template <typename genType>
115	GLM_FUNC_QUALIFIER genType log
116	(
117		genType const & x
118	)
119	{
120		GLM_STATIC_ASSERT(
121			std::numeric_limits<genType>::is_iec559,
122			"'log' only accept floating-point inputs");
123
124		return std::log(x);
125	}
126
127	VECTORIZE_VEC(log)
128
129	//exp2, ln2 = 0.69314718055994530941723212145818f
130	template <typename genType>
131	GLM_FUNC_QUALIFIER genType exp2(genType const & x)
132	{
133		GLM_STATIC_ASSERT(
134			std::numeric_limits<genType>::is_iec559,
135			"'exp2' only accept floating-point inputs");
136
137		return std::exp(static_cast<genType>(0.69314718055994530941723212145818) * x);
138	}
139
140	VECTORIZE_VEC(exp2)
141
142	// log2, ln2 = 0.69314718055994530941723212145818f
143	template <typename genType>
144	GLM_FUNC_QUALIFIER genType log2(genType x)
145	{
146		GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer,
147			"GLM core 'log2' only accept floating-point inputs. Include <glm/gtx/integer.hpp> for additional integer support.");
148
149		assert(x > genType(0)); // log2 is only defined on the range (0, inf]
150		return detail::compute_log2<std::numeric_limits<genType>::is_iec559>()(x);
151	}
152
153	VECTORIZE_VEC(log2)
154
155	namespace detail
156	{
157		template <template <class, precision> class vecType, typename T, precision P>
158		struct compute_sqrt{};
159
160		template <typename T, precision P>
161		struct compute_sqrt<detail::tvec1, T, P>
162		{
163			GLM_FUNC_QUALIFIER static detail::tvec1<T, P> call(detail::tvec1<T, P> const & x)
164			{
165				return detail::tvec1<T, P>(std::sqrt(x.x));
166			}
167		};
168
169		template <typename T, precision P>
170		struct compute_sqrt<detail::tvec2, T, P>
171		{
172			GLM_FUNC_QUALIFIER static detail::tvec2<T, P> call(detail::tvec2<T, P> const & x)
173			{
174				return detail::tvec2<T, P>(std::sqrt(x.x), std::sqrt(x.y));
175			}
176		};
177
178		template <typename T, precision P>
179		struct compute_sqrt<detail::tvec3, T, P>
180		{
181			GLM_FUNC_QUALIFIER static detail::tvec3<T, P> call(detail::tvec3<T, P> const & x)
182			{
183				return detail::tvec3<T, P>(std::sqrt(x.x), std::sqrt(x.y), std::sqrt(x.z));
184			}
185		};
186
187		template <typename T, precision P>
188		struct compute_sqrt<detail::tvec4, T, P>
189		{
190			GLM_FUNC_QUALIFIER static detail::tvec4<T, P> call(detail::tvec4<T, P> const & x)
191			{
192				return detail::tvec4<T, P>(std::sqrt(x.x), std::sqrt(x.y), std::sqrt(x.z), std::sqrt(x.w));
193			}
194		};
195	}//namespace detail
196
197	// sqrt
198	GLM_FUNC_QUALIFIER float sqrt(float x)
199	{
200#		ifdef __CUDACC__ // Wordaround for a CUDA compiler bug up to CUDA6
201			detail::tvec1<float, highp> tmp(detail::compute_sqrt<detail::tvec1, float, highp>::call(x));
202			return tmp.x;
203#		else
204			return detail::compute_sqrt<detail::tvec1, float, highp>::call(x).x;
205#		endif
206	}
207
208	GLM_FUNC_QUALIFIER double sqrt(double x)
209	{
210#		ifdef __CUDACC__ // Wordaround for a CUDA compiler bug up to CUDA6
211			detail::tvec1<double, highp> tmp(detail::compute_sqrt<detail::tvec1, double, highp>::call(x));
212			return tmp.x;
213#		else
214			return detail::compute_sqrt<detail::tvec1, double, highp>::call(x).x;
215#		endif
216	}
217
218	template <typename T, precision P, template <typename, precision> class vecType>
219	GLM_FUNC_QUALIFIER vecType<T, P> sqrt(vecType<T, P> const & x)
220	{
221		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'sqrt' only accept floating-point inputs");
222		return detail::compute_sqrt<vecType, T, P>::call(x);
223	}
224
225	// inversesqrt
226	GLM_FUNC_QUALIFIER float inversesqrt(float const & x)
227	{
228		return 1.0f / sqrt(x);
229	}
230
231	GLM_FUNC_QUALIFIER double inversesqrt(double const & x)
232	{
233		return 1.0 / sqrt(x);
234	}
235
236	template <template <class, precision> class vecType, typename T, precision P>
237	GLM_FUNC_QUALIFIER vecType<T, P> inversesqrt
238	(
239		vecType<T, P> const & x
240	)
241	{
242		GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'inversesqrt' only accept floating-point inputs");
243		return detail::compute_inversesqrt<vecType, T, P>::call(x);
244	}
245
246	VECTORIZE_VEC(inversesqrt)
247}//namespace glm
248