xref: /aosp_15_r20/external/oboe/samples/RhythmGame/third_party/glm/gtc/round.inl (revision 05767d913155b055644481607e6fa1e35e2fe72c)
1/// @ref gtc_round
2/// @file glm/gtc/round.inl
3
4#include "../detail/func_integer.hpp"
5
6namespace glm{
7namespace detail
8{
9	template <typename T, precision P, template <typename, precision> class vecType, bool compute = false>
10	struct compute_ceilShift
11	{
12		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T)
13		{
14			return v;
15		}
16	};
17
18	template <typename T, precision P, template <typename, precision> class vecType>
19	struct compute_ceilShift<T, P, vecType, true>
20	{
21		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T Shift)
22		{
23			return v | (v >> Shift);
24		}
25	};
26
27	template <typename T, precision P, template <typename, precision> class vecType, bool isSigned = true>
28	struct compute_ceilPowerOfTwo
29	{
30		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
31		{
32			GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");
33
34			vecType<T, P> const Sign(sign(x));
35
36			vecType<T, P> v(abs(x));
37
38			v = v - static_cast<T>(1);
39			v = v | (v >> static_cast<T>(1));
40			v = v | (v >> static_cast<T>(2));
41			v = v | (v >> static_cast<T>(4));
42			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 2>::call(v, 8);
43			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 4>::call(v, 16);
44			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 8>::call(v, 32);
45			return (v + static_cast<T>(1)) * Sign;
46		}
47	};
48
49	template <typename T, precision P, template <typename, precision> class vecType>
50	struct compute_ceilPowerOfTwo<T, P, vecType, false>
51	{
52		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
53		{
54			GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");
55
56			vecType<T, P> v(x);
57
58			v = v - static_cast<T>(1);
59			v = v | (v >> static_cast<T>(1));
60			v = v | (v >> static_cast<T>(2));
61			v = v | (v >> static_cast<T>(4));
62			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 2>::call(v, 8);
63			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 4>::call(v, 16);
64			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 8>::call(v, 32);
65			return v + static_cast<T>(1);
66		}
67	};
68
69	template <bool is_float, bool is_signed>
70	struct compute_ceilMultiple{};
71
72	template <>
73	struct compute_ceilMultiple<true, true>
74	{
75		template <typename genType>
76		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
77		{
78			if(Source > genType(0))
79				return Source + (Multiple - std::fmod(Source, Multiple));
80			else
81				return Source + std::fmod(-Source, Multiple);
82		}
83	};
84
85	template <>
86	struct compute_ceilMultiple<false, false>
87	{
88		template <typename genType>
89		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
90		{
91			genType Tmp = Source - genType(1);
92			return Tmp + (Multiple - (Tmp % Multiple));
93		}
94	};
95
96	template <>
97	struct compute_ceilMultiple<false, true>
98	{
99		template <typename genType>
100		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
101		{
102			if(Source > genType(0))
103			{
104				genType Tmp = Source - genType(1);
105				return Tmp + (Multiple - (Tmp % Multiple));
106			}
107			else
108				return Source + (-Source % Multiple);
109		}
110	};
111
112	template <bool is_float, bool is_signed>
113	struct compute_floorMultiple{};
114
115	template <>
116	struct compute_floorMultiple<true, true>
117	{
118		template <typename genType>
119		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
120		{
121			if(Source >= genType(0))
122				return Source - std::fmod(Source, Multiple);
123			else
124				return Source - std::fmod(Source, Multiple) - Multiple;
125		}
126	};
127
128	template <>
129	struct compute_floorMultiple<false, false>
130	{
131		template <typename genType>
132		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
133		{
134			if(Source >= genType(0))
135				return Source - Source % Multiple;
136			else
137			{
138				genType Tmp = Source + genType(1);
139				return Tmp - Tmp % Multiple - Multiple;
140			}
141		}
142	};
143
144	template <>
145	struct compute_floorMultiple<false, true>
146	{
147		template <typename genType>
148		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
149		{
150			if(Source >= genType(0))
151				return Source - Source % Multiple;
152			else
153			{
154				genType Tmp = Source + genType(1);
155				return Tmp - Tmp % Multiple - Multiple;
156			}
157		}
158	};
159
160	template <bool is_float, bool is_signed>
161	struct compute_roundMultiple{};
162
163	template <>
164	struct compute_roundMultiple<true, true>
165	{
166		template <typename genType>
167		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
168		{
169			if(Source >= genType(0))
170				return Source - std::fmod(Source, Multiple);
171			else
172			{
173				genType Tmp = Source + genType(1);
174				return Tmp - std::fmod(Tmp, Multiple) - Multiple;
175			}
176		}
177	};
178
179	template <>
180	struct compute_roundMultiple<false, false>
181	{
182		template <typename genType>
183		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
184		{
185			if(Source >= genType(0))
186				return Source - Source % Multiple;
187			else
188			{
189				genType Tmp = Source + genType(1);
190				return Tmp - Tmp % Multiple - Multiple;
191			}
192		}
193	};
194
195	template <>
196	struct compute_roundMultiple<false, true>
197	{
198		template <typename genType>
199		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
200		{
201			if(Source >= genType(0))
202				return Source - Source % Multiple;
203			else
204			{
205				genType Tmp = Source + genType(1);
206				return Tmp - Tmp % Multiple - Multiple;
207			}
208		}
209	};
210}//namespace detail
211
212	////////////////
213	// isPowerOfTwo
214
215	template <typename genType>
216	GLM_FUNC_QUALIFIER bool isPowerOfTwo(genType Value)
217	{
218		genType const Result = glm::abs(Value);
219		return !(Result & (Result - 1));
220	}
221
222	template <typename T, precision P, template <typename, precision> class vecType>
223	GLM_FUNC_QUALIFIER vecType<bool, P> isPowerOfTwo(vecType<T, P> const & Value)
224	{
225		vecType<T, P> const Result(abs(Value));
226		return equal(Result & (Result - 1), vecType<T, P>(0));
227	}
228
229	//////////////////
230	// ceilPowerOfTwo
231
232	template <typename genType>
233	GLM_FUNC_QUALIFIER genType ceilPowerOfTwo(genType value)
234	{
235		return detail::compute_ceilPowerOfTwo<genType, defaultp, tvec1, std::numeric_limits<genType>::is_signed>::call(tvec1<genType, defaultp>(value)).x;
236	}
237
238	template <typename T, precision P, template <typename, precision> class vecType>
239	GLM_FUNC_QUALIFIER vecType<T, P> ceilPowerOfTwo(vecType<T, P> const & v)
240	{
241		return detail::compute_ceilPowerOfTwo<T, P, vecType, std::numeric_limits<T>::is_signed>::call(v);
242	}
243
244	///////////////////
245	// floorPowerOfTwo
246
247	template <typename genType>
248	GLM_FUNC_QUALIFIER genType floorPowerOfTwo(genType value)
249	{
250		return isPowerOfTwo(value) ? value : static_cast<genType>(1) << findMSB(value);
251	}
252
253	template <typename T, precision P, template <typename, precision> class vecType>
254	GLM_FUNC_QUALIFIER vecType<T, P> floorPowerOfTwo(vecType<T, P> const & v)
255	{
256		return detail::functor1<T, T, P, vecType>::call(floorPowerOfTwo, v);
257	}
258
259	///////////////////
260	// roundPowerOfTwo
261
262	template <typename genIUType>
263	GLM_FUNC_QUALIFIER genIUType roundPowerOfTwo(genIUType value)
264	{
265		if(isPowerOfTwo(value))
266			return value;
267
268		genIUType const prev = static_cast<genIUType>(1) << findMSB(value);
269		genIUType const next = prev << static_cast<genIUType>(1);
270		return (next - value) < (value - prev) ? next : prev;
271	}
272
273	template <typename T, precision P, template <typename, precision> class vecType>
274	GLM_FUNC_QUALIFIER vecType<T, P> roundPowerOfTwo(vecType<T, P> const & v)
275	{
276		return detail::functor1<T, T, P, vecType>::call(roundPowerOfTwo, v);
277	}
278
279	////////////////
280	// isMultiple
281
282	template <typename genType>
283	GLM_FUNC_QUALIFIER bool isMultiple(genType Value, genType Multiple)
284	{
285		return isMultiple(tvec1<genType>(Value), tvec1<genType>(Multiple)).x;
286	}
287
288	template <typename T, precision P, template <typename, precision> class vecType>
289	GLM_FUNC_QUALIFIER vecType<bool, P> isMultiple(vecType<T, P> const & Value, T Multiple)
290	{
291		return (Value % Multiple) == vecType<T, P>(0);
292	}
293
294	template <typename T, precision P, template <typename, precision> class vecType>
295	GLM_FUNC_QUALIFIER vecType<bool, P> isMultiple(vecType<T, P> const & Value, vecType<T, P> const & Multiple)
296	{
297		return (Value % Multiple) == vecType<T, P>(0);
298	}
299
300	//////////////////////
301	// ceilMultiple
302
303	template <typename genType>
304	GLM_FUNC_QUALIFIER genType ceilMultiple(genType Source, genType Multiple)
305	{
306		return detail::compute_ceilMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
307	}
308
309	template <typename T, precision P, template <typename, precision> class vecType>
310	GLM_FUNC_QUALIFIER vecType<T, P> ceilMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple)
311	{
312		return detail::functor2<T, P, vecType>::call(ceilMultiple, Source, Multiple);
313	}
314
315	//////////////////////
316	// floorMultiple
317
318	template <typename genType>
319	GLM_FUNC_QUALIFIER genType floorMultiple(genType Source, genType Multiple)
320	{
321		return detail::compute_floorMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
322	}
323
324	template <typename T, precision P, template <typename, precision> class vecType>
325	GLM_FUNC_QUALIFIER vecType<T, P> floorMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple)
326	{
327		return detail::functor2<T, P, vecType>::call(floorMultiple, Source, Multiple);
328	}
329
330	//////////////////////
331	// roundMultiple
332
333	template <typename genType>
334	GLM_FUNC_QUALIFIER genType roundMultiple(genType Source, genType Multiple)
335	{
336		return detail::compute_roundMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
337	}
338
339	template <typename T, precision P, template <typename, precision> class vecType>
340	GLM_FUNC_QUALIFIER vecType<T, P> roundMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple)
341	{
342		return detail::functor2<T, P, vecType>::call(roundMultiple, Source, Multiple);
343	}
344}//namespace glm
345