1/// @ref gtc_random
2/// @file glm/gtc/random.inl
3
4#include "../geometric.hpp"
5#include "../exponential.hpp"
6#include <cstdlib>
7#include <ctime>
8#include <cassert>
9
10namespace glm{
11namespace detail
12{
13	template <typename T, precision P, template <class, precision> class vecType>
14	struct compute_rand
15	{
16		GLM_FUNC_QUALIFIER static vecType<T, P> call();
17	};
18
19	template <precision P>
20	struct compute_rand<uint8, P, tvec1>
21	{
22		GLM_FUNC_QUALIFIER static tvec1<uint8, P> call()
23		{
24			return tvec1<uint8, P>(
25				std::rand() % std::numeric_limits<uint8>::max());
26		}
27	};
28
29	template <precision P>
30	struct compute_rand<uint8, P, tvec2>
31	{
32		GLM_FUNC_QUALIFIER static tvec2<uint8, P> call()
33		{
34			return tvec2<uint8, P>(
35				std::rand() % std::numeric_limits<uint8>::max(),
36				std::rand() % std::numeric_limits<uint8>::max());
37		}
38	};
39
40	template <precision P>
41	struct compute_rand<uint8, P, tvec3>
42	{
43		GLM_FUNC_QUALIFIER static tvec3<uint8, P> call()
44		{
45			return tvec3<uint8, P>(
46				std::rand() % std::numeric_limits<uint8>::max(),
47				std::rand() % std::numeric_limits<uint8>::max(),
48				std::rand() % std::numeric_limits<uint8>::max());
49		}
50	};
51
52	template <precision P>
53	struct compute_rand<uint8, P, tvec4>
54	{
55		GLM_FUNC_QUALIFIER static tvec4<uint8, P> call()
56		{
57			return tvec4<uint8, P>(
58				std::rand() % std::numeric_limits<uint8>::max(),
59				std::rand() % std::numeric_limits<uint8>::max(),
60				std::rand() % std::numeric_limits<uint8>::max(),
61				std::rand() % std::numeric_limits<uint8>::max());
62		}
63	};
64
65	template <precision P, template <class, precision> class vecType>
66	struct compute_rand<uint16, P, vecType>
67	{
68		GLM_FUNC_QUALIFIER static vecType<uint16, P> call()
69		{
70			return
71				(vecType<uint16, P>(compute_rand<uint8, P, vecType>::call()) << static_cast<uint16>(8)) |
72				(vecType<uint16, P>(compute_rand<uint8, P, vecType>::call()) << static_cast<uint16>(0));
73		}
74	};
75
76	template <precision P, template <class, precision> class vecType>
77	struct compute_rand<uint32, P, vecType>
78	{
79		GLM_FUNC_QUALIFIER static vecType<uint32, P> call()
80		{
81			return
82				(vecType<uint32, P>(compute_rand<uint16, P, vecType>::call()) << static_cast<uint32>(16)) |
83				(vecType<uint32, P>(compute_rand<uint16, P, vecType>::call()) << static_cast<uint32>(0));
84		}
85	};
86
87	template <precision P, template <class, precision> class vecType>
88	struct compute_rand<uint64, P, vecType>
89	{
90		GLM_FUNC_QUALIFIER static vecType<uint64, P> call()
91		{
92			return
93				(vecType<uint64, P>(compute_rand<uint32, P, vecType>::call()) << static_cast<uint64>(32)) |
94				(vecType<uint64, P>(compute_rand<uint32, P, vecType>::call()) << static_cast<uint64>(0));
95		}
96	};
97
98	template <typename T, precision P, template <class, precision> class vecType>
99	struct compute_linearRand
100	{
101		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & Min, vecType<T, P> const & Max);
102	};
103
104	template <precision P, template <class, precision> class vecType>
105	struct compute_linearRand<int8, P, vecType>
106	{
107		GLM_FUNC_QUALIFIER static vecType<int8, P> call(vecType<int8, P> const & Min, vecType<int8, P> const & Max)
108		{
109			return (vecType<int8, P>(compute_rand<uint8, P, vecType>::call() % vecType<uint8, P>(Max + static_cast<int8>(1) - Min))) + Min;
110		}
111	};
112
113	template <precision P, template <class, precision> class vecType>
114	struct compute_linearRand<uint8, P, vecType>
115	{
116		GLM_FUNC_QUALIFIER static vecType<uint8, P> call(vecType<uint8, P> const & Min, vecType<uint8, P> const & Max)
117		{
118			return (compute_rand<uint8, P, vecType>::call() % (Max + static_cast<uint8>(1) - Min)) + Min;
119		}
120	};
121
122	template <precision P, template <class, precision> class vecType>
123	struct compute_linearRand<int16, P, vecType>
124	{
125		GLM_FUNC_QUALIFIER static vecType<int16, P> call(vecType<int16, P> const & Min, vecType<int16, P> const & Max)
126		{
127			return (vecType<int16, P>(compute_rand<uint16, P, vecType>::call() % vecType<uint16, P>(Max + static_cast<int16>(1) - Min))) + Min;
128		}
129	};
130
131	template <precision P, template <class, precision> class vecType>
132	struct compute_linearRand<uint16, P, vecType>
133	{
134		GLM_FUNC_QUALIFIER static vecType<uint16, P> call(vecType<uint16, P> const & Min, vecType<uint16, P> const & Max)
135		{
136			return (compute_rand<uint16, P, vecType>::call() % (Max + static_cast<uint16>(1) - Min)) + Min;
137		}
138	};
139
140	template <precision P, template <class, precision> class vecType>
141	struct compute_linearRand<int32, P, vecType>
142	{
143		GLM_FUNC_QUALIFIER static vecType<int32, P> call(vecType<int32, P> const & Min, vecType<int32, P> const & Max)
144		{
145			return (vecType<int32, P>(compute_rand<uint32, P, vecType>::call() % vecType<uint32, P>(Max + static_cast<int32>(1) - Min))) + Min;
146		}
147	};
148
149	template <precision P, template <class, precision> class vecType>
150	struct compute_linearRand<uint32, P, vecType>
151	{
152		GLM_FUNC_QUALIFIER static vecType<uint32, P> call(vecType<uint32, P> const & Min, vecType<uint32, P> const & Max)
153		{
154			return (compute_rand<uint32, P, vecType>::call() % (Max + static_cast<uint32>(1) - Min)) + Min;
155		}
156	};
157
158	template <precision P, template <class, precision> class vecType>
159	struct compute_linearRand<int64, P, vecType>
160	{
161		GLM_FUNC_QUALIFIER static vecType<int64, P> call(vecType<int64, P> const & Min, vecType<int64, P> const & Max)
162		{
163			return (vecType<int64, P>(compute_rand<uint64, P, vecType>::call() % vecType<uint64, P>(Max + static_cast<int64>(1) - Min))) + Min;
164		}
165	};
166
167	template <precision P, template <class, precision> class vecType>
168	struct compute_linearRand<uint64, P, vecType>
169	{
170		GLM_FUNC_QUALIFIER static vecType<uint64, P> call(vecType<uint64, P> const & Min, vecType<uint64, P> const & Max)
171		{
172			return (compute_rand<uint64, P, vecType>::call() % (Max + static_cast<uint64>(1) - Min)) + Min;
173		}
174	};
175
176	template <template <class, precision> class vecType>
177	struct compute_linearRand<float, lowp, vecType>
178	{
179		GLM_FUNC_QUALIFIER static vecType<float, lowp> call(vecType<float, lowp> const & Min, vecType<float, lowp> const & Max)
180		{
181			return vecType<float, lowp>(compute_rand<uint8, lowp, vecType>::call()) / static_cast<float>(std::numeric_limits<uint8>::max()) * (Max - Min) + Min;
182		}
183	};
184
185	template <template <class, precision> class vecType>
186	struct compute_linearRand<float, mediump, vecType>
187	{
188		GLM_FUNC_QUALIFIER static vecType<float, mediump> call(vecType<float, mediump> const & Min, vecType<float, mediump> const & Max)
189		{
190			return vecType<float, mediump>(compute_rand<uint16, mediump, vecType>::call()) / static_cast<float>(std::numeric_limits<uint16>::max()) * (Max - Min) + Min;
191		}
192	};
193
194	template <template <class, precision> class vecType>
195	struct compute_linearRand<float, highp, vecType>
196	{
197		GLM_FUNC_QUALIFIER static vecType<float, highp> call(vecType<float, highp> const & Min, vecType<float, highp> const & Max)
198		{
199			return vecType<float, highp>(compute_rand<uint32, highp, vecType>::call()) / static_cast<float>(std::numeric_limits<uint32>::max()) * (Max - Min) + Min;
200		}
201	};
202
203	template <template <class, precision> class vecType>
204	struct compute_linearRand<double, lowp, vecType>
205	{
206		GLM_FUNC_QUALIFIER static vecType<double, lowp> call(vecType<double, lowp> const & Min, vecType<double, lowp> const & Max)
207		{
208			return vecType<double, lowp>(compute_rand<uint16, lowp, vecType>::call()) / static_cast<double>(std::numeric_limits<uint16>::max()) * (Max - Min) + Min;
209		}
210	};
211
212	template <template <class, precision> class vecType>
213	struct compute_linearRand<double, mediump, vecType>
214	{
215		GLM_FUNC_QUALIFIER static vecType<double, mediump> call(vecType<double, mediump> const & Min, vecType<double, mediump> const & Max)
216		{
217			return vecType<double, mediump>(compute_rand<uint32, mediump, vecType>::call()) / static_cast<double>(std::numeric_limits<uint32>::max()) * (Max - Min) + Min;
218		}
219	};
220
221	template <template <class, precision> class vecType>
222	struct compute_linearRand<double, highp, vecType>
223	{
224		GLM_FUNC_QUALIFIER static vecType<double, highp> call(vecType<double, highp> const & Min, vecType<double, highp> const & Max)
225		{
226			return vecType<double, highp>(compute_rand<uint64, highp, vecType>::call()) / static_cast<double>(std::numeric_limits<uint64>::max()) * (Max - Min) + Min;
227		}
228	};
229
230	template <template <class, precision> class vecType>
231	struct compute_linearRand<long double, lowp, vecType>
232	{
233		GLM_FUNC_QUALIFIER static vecType<long double, lowp> call(vecType<long double, lowp> const & Min, vecType<long double, lowp> const & Max)
234		{
235			return vecType<long double, lowp>(compute_rand<uint32, lowp, vecType>::call()) / static_cast<long double>(std::numeric_limits<uint32>::max()) * (Max - Min) + Min;
236		}
237	};
238
239	template <template <class, precision> class vecType>
240	struct compute_linearRand<long double, mediump, vecType>
241	{
242		GLM_FUNC_QUALIFIER static vecType<long double, mediump> call(vecType<long double, mediump> const & Min, vecType<long double, mediump> const & Max)
243		{
244			return vecType<long double, mediump>(compute_rand<uint64, mediump, vecType>::call()) / static_cast<long double>(std::numeric_limits<uint64>::max()) * (Max - Min) + Min;
245		}
246	};
247
248	template <template <class, precision> class vecType>
249	struct compute_linearRand<long double, highp, vecType>
250	{
251		GLM_FUNC_QUALIFIER static vecType<long double, highp> call(vecType<long double, highp> const & Min, vecType<long double, highp> const & Max)
252		{
253			return vecType<long double, highp>(compute_rand<uint64, highp, vecType>::call()) / static_cast<long double>(std::numeric_limits<uint64>::max()) * (Max - Min) + Min;
254		}
255	};
256}//namespace detail
257
258	template <typename genType>
259	GLM_FUNC_QUALIFIER genType linearRand(genType Min, genType Max)
260	{
261		return detail::compute_linearRand<genType, highp, tvec1>::call(
262			tvec1<genType, highp>(Min),
263			tvec1<genType, highp>(Max)).x;
264	}
265
266	template <typename T, precision P, template <typename, precision> class vecType>
267	GLM_FUNC_QUALIFIER vecType<T, P> linearRand(vecType<T, P> const & Min, vecType<T, P> const & Max)
268	{
269		return detail::compute_linearRand<T, P, vecType>::call(Min, Max);
270	}
271
272	template <typename genType>
273	GLM_FUNC_QUALIFIER genType gaussRand(genType Mean, genType Deviation)
274	{
275		genType w, x1, x2;
276
277		do
278		{
279			x1 = linearRand(genType(-1), genType(1));
280			x2 = linearRand(genType(-1), genType(1));
281
282			w = x1 * x1 + x2 * x2;
283		} while(w > genType(1));
284
285		return x2 * Deviation * Deviation * sqrt((genType(-2) * log(w)) / w) + Mean;
286	}
287
288	template <typename T, precision P, template <typename, precision> class vecType>
289	GLM_FUNC_QUALIFIER vecType<T, P> gaussRand(vecType<T, P> const & Mean, vecType<T, P> const & Deviation)
290	{
291		return detail::functor2<T, P, vecType>::call(gaussRand, Mean, Deviation);
292	}
293
294	template <typename T>
295	GLM_FUNC_QUALIFIER tvec2<T, defaultp> diskRand(T Radius)
296	{
297		tvec2<T, defaultp> Result(T(0));
298		T LenRadius(T(0));
299
300		do
301		{
302			Result = linearRand(
303				tvec2<T, defaultp>(-Radius),
304				tvec2<T, defaultp>(Radius));
305			LenRadius = length(Result);
306		}
307		while(LenRadius > Radius);
308
309		return Result;
310	}
311
312	template <typename T>
313	GLM_FUNC_QUALIFIER tvec3<T, defaultp> ballRand(T Radius)
314	{
315		tvec3<T, defaultp> Result(T(0));
316		T LenRadius(T(0));
317
318		do
319		{
320			Result = linearRand(
321				tvec3<T, defaultp>(-Radius),
322				tvec3<T, defaultp>(Radius));
323			LenRadius = length(Result);
324		}
325		while(LenRadius > Radius);
326
327		return Result;
328	}
329
330	template <typename T>
331	GLM_FUNC_QUALIFIER tvec2<T, defaultp> circularRand(T Radius)
332	{
333		T a = linearRand(T(0), T(6.283185307179586476925286766559f));
334		return tvec2<T, defaultp>(cos(a), sin(a)) * Radius;
335	}
336
337	template <typename T>
338	GLM_FUNC_QUALIFIER tvec3<T, defaultp> sphericalRand(T Radius)
339	{
340		T z = linearRand(T(-1), T(1));
341		T a = linearRand(T(0), T(6.283185307179586476925286766559f));
342
343		T r = sqrt(T(1) - z * z);
344
345		T x = r * cos(a);
346		T y = r * sin(a);
347
348		return tvec3<T, defaultp>(x, y, z) * Radius;
349	}
350}//namespace glm
351