func_common.inl 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. /// @ref core
  2. /// @file glm/detail/func_common.inl
  3. #include "../vector_relational.hpp"
  4. #include "compute_common.hpp"
  5. #include "type_vec1.hpp"
  6. #include "type_vec2.hpp"
  7. #include "type_vec3.hpp"
  8. #include "type_vec4.hpp"
  9. #include "_vectorize.hpp"
  10. #include <limits>
  11. namespace glm
  12. {
  13. // min
  14. template<typename genType>
  15. GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType min(genType x, genType y)
  16. {
  17. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, "'min' only accept floating-point or integer inputs");
  18. return (y < x) ? y : x;
  19. }
  20. // max
  21. template<typename genType>
  22. GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType max(genType x, genType y)
  23. {
  24. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, "'max' only accept floating-point or integer inputs");
  25. return (x < y) ? y : x;
  26. }
  27. // abs
  28. template<>
  29. GLM_FUNC_QUALIFIER GLM_CONSTEXPR int abs(int x)
  30. {
  31. int const y = x >> (sizeof(int) * 8 - 1);
  32. return (x ^ y) - y;
  33. }
  34. // round
  35. # if GLM_HAS_CXX11_STL
  36. using ::std::round;
  37. # else
  38. template<typename genType>
  39. GLM_FUNC_QUALIFIER genType round(genType x)
  40. {
  41. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'round' only accept floating-point inputs");
  42. return x < static_cast<genType>(0) ? static_cast<genType>(int(x - static_cast<genType>(0.5))) : static_cast<genType>(int(x + static_cast<genType>(0.5)));
  43. }
  44. # endif
  45. // trunc
  46. # if GLM_HAS_CXX11_STL
  47. using ::std::trunc;
  48. # else
  49. template<typename genType>
  50. GLM_FUNC_QUALIFIER genType trunc(genType x)
  51. {
  52. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'trunc' only accept floating-point inputs");
  53. return x < static_cast<genType>(0) ? -std::floor(-x) : std::floor(x);
  54. }
  55. # endif
  56. }//namespace glm
  57. namespace glm{
  58. namespace detail
  59. {
  60. template<length_t L, typename T, qualifier Q, bool Aligned>
  61. struct compute_abs_vector
  62. {
  63. GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x)
  64. {
  65. return detail::functor1<vec, L, T, T, Q>::call(abs, x);
  66. }
  67. };
  68. template<length_t L, typename T, typename U, qualifier Q, bool Aligned>
  69. struct compute_mix_vector
  70. {
  71. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, U, Q> const& a)
  72. {
  73. GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a");
  74. return vec<L, T, Q>(vec<L, U, Q>(x) * (static_cast<U>(1) - a) + vec<L, U, Q>(y) * a);
  75. }
  76. };
  77. template<length_t L, typename T, qualifier Q, bool Aligned>
  78. struct compute_mix_vector<L, T, bool, Q, Aligned>
  79. {
  80. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, bool, Q> const& a)
  81. {
  82. vec<L, T, Q> Result;
  83. for(length_t i = 0; i < x.length(); ++i)
  84. Result[i] = a[i] ? y[i] : x[i];
  85. return Result;
  86. }
  87. };
  88. template<length_t L, typename T, typename U, qualifier Q, bool Aligned>
  89. struct compute_mix_scalar
  90. {
  91. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, U const& a)
  92. {
  93. GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a");
  94. return vec<L, T, Q>(vec<L, U, Q>(x) * (static_cast<U>(1) - a) + vec<L, U, Q>(y) * a);
  95. }
  96. };
  97. template<length_t L, typename T, qualifier Q, bool Aligned>
  98. struct compute_mix_scalar<L, T, bool, Q, Aligned>
  99. {
  100. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, bool const& a)
  101. {
  102. return a ? y : x;
  103. }
  104. };
  105. template<typename T, typename U>
  106. struct compute_mix
  107. {
  108. GLM_FUNC_QUALIFIER static T call(T const& x, T const& y, U const& a)
  109. {
  110. GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a");
  111. return static_cast<T>(static_cast<U>(x) * (static_cast<U>(1) - a) + static_cast<U>(y) * a);
  112. }
  113. };
  114. template<typename T>
  115. struct compute_mix<T, bool>
  116. {
  117. GLM_FUNC_QUALIFIER static T call(T const& x, T const& y, bool const& a)
  118. {
  119. return a ? y : x;
  120. }
  121. };
  122. template<length_t L, typename T, qualifier Q, bool isFloat, bool Aligned>
  123. struct compute_sign
  124. {
  125. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
  126. {
  127. return vec<L, T, Q>(glm::lessThan(vec<L, T, Q>(0), x)) - vec<L, T, Q>(glm::lessThan(x, vec<L, T, Q>(0)));
  128. }
  129. };
  130. # if GLM_ARCH == GLM_ARCH_X86
  131. template<length_t L, typename T, qualifier Q, bool Aligned>
  132. struct compute_sign<L, T, Q, false, Aligned>
  133. {
  134. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
  135. {
  136. T const Shift(static_cast<T>(sizeof(T) * 8 - 1));
  137. vec<L, T, Q> const y(vec<L, typename detail::make_unsigned<T>::type, Q>(-x) >> typename detail::make_unsigned<T>::type(Shift));
  138. return (x >> Shift) | y;
  139. }
  140. };
  141. # endif
  142. template<length_t L, typename T, qualifier Q, bool Aligned>
  143. struct compute_floor
  144. {
  145. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
  146. {
  147. return detail::functor1<vec, L, T, T, Q>::call(std::floor, x);
  148. }
  149. };
  150. template<length_t L, typename T, qualifier Q, bool Aligned>
  151. struct compute_ceil
  152. {
  153. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
  154. {
  155. return detail::functor1<vec, L, T, T, Q>::call(std::ceil, x);
  156. }
  157. };
  158. template<length_t L, typename T, qualifier Q, bool Aligned>
  159. struct compute_fract
  160. {
  161. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
  162. {
  163. return x - floor(x);
  164. }
  165. };
  166. template<length_t L, typename T, qualifier Q, bool Aligned>
  167. struct compute_trunc
  168. {
  169. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
  170. {
  171. return detail::functor1<vec, L, T, T, Q>::call(trunc, x);
  172. }
  173. };
  174. template<length_t L, typename T, qualifier Q, bool Aligned>
  175. struct compute_round
  176. {
  177. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
  178. {
  179. return detail::functor1<vec, L, T, T, Q>::call(round, x);
  180. }
  181. };
  182. template<length_t L, typename T, qualifier Q, bool Aligned>
  183. struct compute_mod
  184. {
  185. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
  186. {
  187. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'mod' only accept floating-point inputs. Include <glm/gtc/integer.hpp> for integer inputs.");
  188. return a - b * floor(a / b);
  189. }
  190. };
  191. template<length_t L, typename T, qualifier Q, bool Aligned>
  192. struct compute_min_vector
  193. {
  194. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y)
  195. {
  196. return detail::functor2<vec, L, T, Q>::call(min, x, y);
  197. }
  198. };
  199. template<length_t L, typename T, qualifier Q, bool Aligned>
  200. struct compute_max_vector
  201. {
  202. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y)
  203. {
  204. return detail::functor2<vec, L, T, Q>::call(max, x, y);
  205. }
  206. };
  207. template<length_t L, typename T, qualifier Q, bool Aligned>
  208. struct compute_clamp_vector
  209. {
  210. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> const& maxVal)
  211. {
  212. return min(max(x, minVal), maxVal);
  213. }
  214. };
  215. template<length_t L, typename T, qualifier Q, bool Aligned>
  216. struct compute_step_vector
  217. {
  218. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& edge, vec<L, T, Q> const& x)
  219. {
  220. return mix(vec<L, T, Q>(1), vec<L, T, Q>(0), glm::lessThan(x, edge));
  221. }
  222. };
  223. template<length_t L, typename T, qualifier Q, bool Aligned>
  224. struct compute_smoothstep_vector
  225. {
  226. GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& edge0, vec<L, T, Q> const& edge1, vec<L, T, Q> const& x)
  227. {
  228. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'step' only accept floating-point inputs");
  229. vec<L, T, Q> const tmp(clamp((x - edge0) / (edge1 - edge0), static_cast<T>(0), static_cast<T>(1)));
  230. return tmp * tmp * (static_cast<T>(3) - static_cast<T>(2) * tmp);
  231. }
  232. };
  233. }//namespace detail
  234. template<typename genFIType>
  235. GLM_FUNC_QUALIFIER GLM_CONSTEXPR genFIType abs(genFIType x)
  236. {
  237. return detail::compute_abs<genFIType, std::numeric_limits<genFIType>::is_signed>::call(x);
  238. }
  239. template<length_t L, typename T, qualifier Q>
  240. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> abs(vec<L, T, Q> const& x)
  241. {
  242. return detail::compute_abs_vector<L, T, Q, detail::is_aligned<Q>::value>::call(x);
  243. }
  244. // sign
  245. // fast and works for any type
  246. template<typename genFIType>
  247. GLM_FUNC_QUALIFIER genFIType sign(genFIType x)
  248. {
  249. GLM_STATIC_ASSERT(
  250. std::numeric_limits<genFIType>::is_iec559 || (std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer),
  251. "'sign' only accept signed inputs");
  252. return detail::compute_sign<1, genFIType, defaultp, std::numeric_limits<genFIType>::is_iec559, highp>::call(vec<1, genFIType>(x)).x;
  253. }
  254. template<length_t L, typename T, qualifier Q>
  255. GLM_FUNC_QUALIFIER vec<L, T, Q> sign(vec<L, T, Q> const& x)
  256. {
  257. GLM_STATIC_ASSERT(
  258. std::numeric_limits<T>::is_iec559 || (std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_integer),
  259. "'sign' only accept signed inputs");
  260. return detail::compute_sign<L, T, Q, std::numeric_limits<T>::is_iec559, detail::is_aligned<Q>::value>::call(x);
  261. }
  262. // floor
  263. using ::std::floor;
  264. template<length_t L, typename T, qualifier Q>
  265. GLM_FUNC_QUALIFIER vec<L, T, Q> floor(vec<L, T, Q> const& x)
  266. {
  267. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'floor' only accept floating-point inputs.");
  268. return detail::compute_floor<L, T, Q, detail::is_aligned<Q>::value>::call(x);
  269. }
  270. template<length_t L, typename T, qualifier Q>
  271. GLM_FUNC_QUALIFIER vec<L, T, Q> trunc(vec<L, T, Q> const& x)
  272. {
  273. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'trunc' only accept floating-point inputs");
  274. return detail::compute_trunc<L, T, Q, detail::is_aligned<Q>::value>::call(x);
  275. }
  276. template<length_t L, typename T, qualifier Q>
  277. GLM_FUNC_QUALIFIER vec<L, T, Q> round(vec<L, T, Q> const& x)
  278. {
  279. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'round' only accept floating-point inputs");
  280. return detail::compute_round<L, T, Q, detail::is_aligned<Q>::value>::call(x);
  281. }
  282. /*
  283. // roundEven
  284. template<typename genType>
  285. GLM_FUNC_QUALIFIER genType roundEven(genType const& x)
  286. {
  287. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs");
  288. return genType(int(x + genType(int(x) % 2)));
  289. }
  290. */
  291. // roundEven
  292. template<typename genType>
  293. GLM_FUNC_QUALIFIER genType roundEven(genType x)
  294. {
  295. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs");
  296. int Integer = static_cast<int>(x);
  297. genType IntegerPart = static_cast<genType>(Integer);
  298. genType FractionalPart = fract(x);
  299. if(FractionalPart > static_cast<genType>(0.5) || FractionalPart < static_cast<genType>(0.5))
  300. {
  301. return round(x);
  302. }
  303. else if((Integer % 2) == 0)
  304. {
  305. return IntegerPart;
  306. }
  307. else if(x <= static_cast<genType>(0)) // Work around...
  308. {
  309. return IntegerPart - static_cast<genType>(1);
  310. }
  311. else
  312. {
  313. return IntegerPart + static_cast<genType>(1);
  314. }
  315. //else // Bug on MinGW 4.5.2
  316. //{
  317. // return mix(IntegerPart + genType(-1), IntegerPart + genType(1), x <= genType(0));
  318. //}
  319. }
  320. template<length_t L, typename T, qualifier Q>
  321. GLM_FUNC_QUALIFIER vec<L, T, Q> roundEven(vec<L, T, Q> const& x)
  322. {
  323. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'roundEven' only accept floating-point inputs");
  324. return detail::functor1<vec, L, T, T, Q>::call(roundEven, x);
  325. }
  326. // ceil
  327. using ::std::ceil;
  328. template<length_t L, typename T, qualifier Q>
  329. GLM_FUNC_QUALIFIER vec<L, T, Q> ceil(vec<L, T, Q> const& x)
  330. {
  331. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'ceil' only accept floating-point inputs");
  332. return detail::compute_ceil<L, T, Q, detail::is_aligned<Q>::value>::call(x);
  333. }
  334. // fract
  335. template<typename genType>
  336. GLM_FUNC_QUALIFIER genType fract(genType x)
  337. {
  338. return fract(vec<1, genType>(x)).x;
  339. }
  340. template<length_t L, typename T, qualifier Q>
  341. GLM_FUNC_QUALIFIER vec<L, T, Q> fract(vec<L, T, Q> const& x)
  342. {
  343. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fract' only accept floating-point inputs");
  344. return detail::compute_fract<L, T, Q, detail::is_aligned<Q>::value>::call(x);
  345. }
  346. // mod
  347. template<typename genType>
  348. GLM_FUNC_QUALIFIER genType mod(genType x, genType y)
  349. {
  350. # if GLM_COMPILER & GLM_COMPILER_CUDA
  351. // Another Cuda compiler bug https://github.com/g-truc/glm/issues/530
  352. vec<1, genType, defaultp> Result(mod(vec<1, genType, defaultp>(x), y));
  353. return Result.x;
  354. # else
  355. return mod(vec<1, genType, defaultp>(x), y).x;
  356. # endif
  357. }
  358. template<length_t L, typename T, qualifier Q>
  359. GLM_FUNC_QUALIFIER vec<L, T, Q> mod(vec<L, T, Q> const& x, T y)
  360. {
  361. return detail::compute_mod<L, T, Q, detail::is_aligned<Q>::value>::call(x, vec<L, T, Q>(y));
  362. }
  363. template<length_t L, typename T, qualifier Q>
  364. GLM_FUNC_QUALIFIER vec<L, T, Q> mod(vec<L, T, Q> const& x, vec<L, T, Q> const& y)
  365. {
  366. return detail::compute_mod<L, T, Q, detail::is_aligned<Q>::value>::call(x, y);
  367. }
  368. // modf
  369. template<typename genType>
  370. GLM_FUNC_QUALIFIER genType modf(genType x, genType & i)
  371. {
  372. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'modf' only accept floating-point inputs");
  373. return std::modf(x, &i);
  374. }
  375. template<typename T, qualifier Q>
  376. GLM_FUNC_QUALIFIER vec<1, T, Q> modf(vec<1, T, Q> const& x, vec<1, T, Q> & i)
  377. {
  378. return vec<1, T, Q>(
  379. modf(x.x, i.x));
  380. }
  381. template<typename T, qualifier Q>
  382. GLM_FUNC_QUALIFIER vec<2, T, Q> modf(vec<2, T, Q> const& x, vec<2, T, Q> & i)
  383. {
  384. return vec<2, T, Q>(
  385. modf(x.x, i.x),
  386. modf(x.y, i.y));
  387. }
  388. template<typename T, qualifier Q>
  389. GLM_FUNC_QUALIFIER vec<3, T, Q> modf(vec<3, T, Q> const& x, vec<3, T, Q> & i)
  390. {
  391. return vec<3, T, Q>(
  392. modf(x.x, i.x),
  393. modf(x.y, i.y),
  394. modf(x.z, i.z));
  395. }
  396. template<typename T, qualifier Q>
  397. GLM_FUNC_QUALIFIER vec<4, T, Q> modf(vec<4, T, Q> const& x, vec<4, T, Q> & i)
  398. {
  399. return vec<4, T, Q>(
  400. modf(x.x, i.x),
  401. modf(x.y, i.y),
  402. modf(x.z, i.z),
  403. modf(x.w, i.w));
  404. }
  405. //// Only valid if (INT_MIN <= x-y <= INT_MAX)
  406. //// min(x,y)
  407. //r = y + ((x - y) & ((x - y) >> (sizeof(int) *
  408. //CHAR_BIT - 1)));
  409. //// max(x,y)
  410. //r = x - ((x - y) & ((x - y) >> (sizeof(int) *
  411. //CHAR_BIT - 1)));
  412. // min
  413. template<length_t L, typename T, qualifier Q>
  414. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& a, T b)
  415. {
  416. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'min' only accept floating-point or integer inputs");
  417. return detail::compute_min_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, vec<L, T, Q>(b));
  418. }
  419. template<length_t L, typename T, qualifier Q>
  420. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
  421. {
  422. return detail::compute_min_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, b);
  423. }
  424. // max
  425. template<length_t L, typename T, qualifier Q>
  426. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> const& a, T b)
  427. {
  428. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'max' only accept floating-point or integer inputs");
  429. return detail::compute_max_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, vec<L, T, Q>(b));
  430. }
  431. template<length_t L, typename T, qualifier Q>
  432. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
  433. {
  434. return detail::compute_max_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, b);
  435. }
  436. // clamp
  437. template<typename genType>
  438. GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType clamp(genType x, genType minVal, genType maxVal)
  439. {
  440. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, "'clamp' only accept floating-point or integer inputs");
  441. return min(max(x, minVal), maxVal);
  442. }
  443. template<length_t L, typename T, qualifier Q>
  444. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> clamp(vec<L, T, Q> const& x, T minVal, T maxVal)
  445. {
  446. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'clamp' only accept floating-point or integer inputs");
  447. return detail::compute_clamp_vector<L, T, Q, detail::is_aligned<Q>::value>::call(x, vec<L, T, Q>(minVal), vec<L, T, Q>(maxVal));
  448. }
  449. template<length_t L, typename T, qualifier Q>
  450. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> clamp(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> const& maxVal)
  451. {
  452. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'clamp' only accept floating-point or integer inputs");
  453. return detail::compute_clamp_vector<L, T, Q, detail::is_aligned<Q>::value>::call(x, minVal, maxVal);
  454. }
  455. template<typename genTypeT, typename genTypeU>
  456. GLM_FUNC_QUALIFIER genTypeT mix(genTypeT x, genTypeT y, genTypeU a)
  457. {
  458. return detail::compute_mix<genTypeT, genTypeU>::call(x, y, a);
  459. }
  460. template<length_t L, typename T, typename U, qualifier Q>
  461. GLM_FUNC_QUALIFIER vec<L, T, Q> mix(vec<L, T, Q> const& x, vec<L, T, Q> const& y, U a)
  462. {
  463. return detail::compute_mix_scalar<L, T, U, Q, detail::is_aligned<Q>::value>::call(x, y, a);
  464. }
  465. template<length_t L, typename T, typename U, qualifier Q>
  466. GLM_FUNC_QUALIFIER vec<L, T, Q> mix(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, U, Q> const& a)
  467. {
  468. return detail::compute_mix_vector<L, T, U, Q, detail::is_aligned<Q>::value>::call(x, y, a);
  469. }
  470. // step
  471. template<typename genType>
  472. GLM_FUNC_QUALIFIER genType step(genType edge, genType x)
  473. {
  474. return mix(static_cast<genType>(1), static_cast<genType>(0), x < edge);
  475. }
  476. template<length_t L, typename T, qualifier Q>
  477. GLM_FUNC_QUALIFIER vec<L, T, Q> step(T edge, vec<L, T, Q> const& x)
  478. {
  479. return detail::compute_step_vector<L, T, Q, detail::is_aligned<Q>::value>::call(vec<L, T, Q>(edge), x);
  480. }
  481. template<length_t L, typename T, qualifier Q>
  482. GLM_FUNC_QUALIFIER vec<L, T, Q> step(vec<L, T, Q> const& edge, vec<L, T, Q> const& x)
  483. {
  484. return detail::compute_step_vector<L, T, Q, detail::is_aligned<Q>::value>::call(edge, x);
  485. }
  486. // smoothstep
  487. template<typename genType>
  488. GLM_FUNC_QUALIFIER genType smoothstep(genType edge0, genType edge1, genType x)
  489. {
  490. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'smoothstep' only accept floating-point inputs");
  491. genType const tmp(clamp((x - edge0) / (edge1 - edge0), genType(0), genType(1)));
  492. return tmp * tmp * (genType(3) - genType(2) * tmp);
  493. }
  494. template<length_t L, typename T, qualifier Q>
  495. GLM_FUNC_QUALIFIER vec<L, T, Q> smoothstep(T edge0, T edge1, vec<L, T, Q> const& x)
  496. {
  497. return detail::compute_smoothstep_vector<L, T, Q, detail::is_aligned<Q>::value>::call(vec<L, T, Q>(edge0), vec<L, T, Q>(edge1), x);
  498. }
  499. template<length_t L, typename T, qualifier Q>
  500. GLM_FUNC_QUALIFIER vec<L, T, Q> smoothstep(vec<L, T, Q> const& edge0, vec<L, T, Q> const& edge1, vec<L, T, Q> const& x)
  501. {
  502. return detail::compute_smoothstep_vector<L, T, Q, detail::is_aligned<Q>::value>::call(edge0, edge1, x);
  503. }
  504. # if GLM_HAS_CXX11_STL
  505. using std::isnan;
  506. # else
  507. template<typename genType>
  508. GLM_FUNC_QUALIFIER bool isnan(genType x)
  509. {
  510. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'isnan' only accept floating-point inputs");
  511. # if GLM_HAS_CXX11_STL
  512. return std::isnan(x);
  513. # elif GLM_COMPILER & GLM_COMPILER_VC
  514. return _isnan(x) != 0;
  515. # elif GLM_COMPILER & GLM_COMPILER_INTEL
  516. # if GLM_PLATFORM & GLM_PLATFORM_WINDOWS
  517. return _isnan(x) != 0;
  518. # else
  519. return ::isnan(x) != 0;
  520. # endif
  521. # elif (GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)) && (GLM_PLATFORM & GLM_PLATFORM_ANDROID) && __cplusplus < 201103L
  522. return _isnan(x) != 0;
  523. # elif GLM_COMPILER & GLM_COMPILER_CUDA
  524. return ::isnan(x) != 0;
  525. # else
  526. return std::isnan(x);
  527. # endif
  528. }
  529. # endif
  530. template<length_t L, typename T, qualifier Q>
  531. GLM_FUNC_QUALIFIER vec<L, bool, Q> isnan(vec<L, T, Q> const& v)
  532. {
  533. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs");
  534. vec<L, bool, Q> Result;
  535. for (length_t l = 0; l < v.length(); ++l)
  536. Result[l] = glm::isnan(v[l]);
  537. return Result;
  538. }
  539. # if GLM_HAS_CXX11_STL
  540. using std::isinf;
  541. # else
  542. template<typename genType>
  543. GLM_FUNC_QUALIFIER bool isinf(genType x)
  544. {
  545. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'isinf' only accept floating-point inputs");
  546. # if GLM_HAS_CXX11_STL
  547. return std::isinf(x);
  548. # elif GLM_COMPILER & (GLM_COMPILER_INTEL | GLM_COMPILER_VC)
  549. # if(GLM_PLATFORM & GLM_PLATFORM_WINDOWS)
  550. return _fpclass(x) == _FPCLASS_NINF || _fpclass(x) == _FPCLASS_PINF;
  551. # else
  552. return ::isinf(x);
  553. # endif
  554. # elif GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)
  555. # if(GLM_PLATFORM & GLM_PLATFORM_ANDROID && __cplusplus < 201103L)
  556. return _isinf(x) != 0;
  557. # else
  558. return std::isinf(x);
  559. # endif
  560. # elif GLM_COMPILER & GLM_COMPILER_CUDA
  561. // http://developer.download.nvidia.com/compute/cuda/4_2/rel/toolkit/docs/online/group__CUDA__MATH__DOUBLE_g13431dd2b40b51f9139cbb7f50c18fab.html#g13431dd2b40b51f9139cbb7f50c18fab
  562. return ::isinf(double(x)) != 0;
  563. # else
  564. return std::isinf(x);
  565. # endif
  566. }
  567. # endif
  568. template<length_t L, typename T, qualifier Q>
  569. GLM_FUNC_QUALIFIER vec<L, bool, Q> isinf(vec<L, T, Q> const& v)
  570. {
  571. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isinf' only accept floating-point inputs");
  572. vec<L, bool, Q> Result;
  573. for (length_t l = 0; l < v.length(); ++l)
  574. Result[l] = glm::isinf(v[l]);
  575. return Result;
  576. }
  577. GLM_FUNC_QUALIFIER int floatBitsToInt(float const& v)
  578. {
  579. union
  580. {
  581. float in;
  582. int out;
  583. } u;
  584. u.in = v;
  585. return u.out;
  586. }
  587. template<length_t L, qualifier Q>
  588. GLM_FUNC_QUALIFIER vec<L, int, Q> floatBitsToInt(vec<L, float, Q> const& v)
  589. {
  590. return reinterpret_cast<vec<L, int, Q>&>(const_cast<vec<L, float, Q>&>(v));
  591. }
  592. GLM_FUNC_QUALIFIER uint floatBitsToUint(float const& v)
  593. {
  594. union
  595. {
  596. float in;
  597. uint out;
  598. } u;
  599. u.in = v;
  600. return u.out;
  601. }
  602. template<length_t L, qualifier Q>
  603. GLM_FUNC_QUALIFIER vec<L, uint, Q> floatBitsToUint(vec<L, float, Q> const& v)
  604. {
  605. return reinterpret_cast<vec<L, uint, Q>&>(const_cast<vec<L, float, Q>&>(v));
  606. }
  607. GLM_FUNC_QUALIFIER float intBitsToFloat(int const& v)
  608. {
  609. union
  610. {
  611. int in;
  612. float out;
  613. } u;
  614. u.in = v;
  615. return u.out;
  616. }
  617. template<length_t L, qualifier Q>
  618. GLM_FUNC_QUALIFIER vec<L, float, Q> intBitsToFloat(vec<L, int, Q> const& v)
  619. {
  620. return reinterpret_cast<vec<L, float, Q>&>(const_cast<vec<L, int, Q>&>(v));
  621. }
  622. GLM_FUNC_QUALIFIER float uintBitsToFloat(uint const& v)
  623. {
  624. union
  625. {
  626. uint in;
  627. float out;
  628. } u;
  629. u.in = v;
  630. return u.out;
  631. }
  632. template<length_t L, qualifier Q>
  633. GLM_FUNC_QUALIFIER vec<L, float, Q> uintBitsToFloat(vec<L, uint, Q> const& v)
  634. {
  635. return reinterpret_cast<vec<L, float, Q>&>(const_cast<vec<L, uint, Q>&>(v));
  636. }
  637. template<typename genType>
  638. GLM_FUNC_QUALIFIER genType fma(genType const& a, genType const& b, genType const& c)
  639. {
  640. return a * b + c;
  641. }
  642. template<typename genType>
  643. GLM_FUNC_QUALIFIER genType frexp(genType x, int& exp)
  644. {
  645. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'frexp' only accept floating-point inputs");
  646. return std::frexp(x, &exp);
  647. }
  648. template<length_t L, typename T, qualifier Q>
  649. GLM_FUNC_QUALIFIER vec<L, T, Q> frexp(vec<L, T, Q> const& v, vec<L, int, Q>& exp)
  650. {
  651. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'frexp' only accept floating-point inputs");
  652. vec<L, T, Q> Result;
  653. for (length_t l = 0; l < v.length(); ++l)
  654. Result[l] = std::frexp(v[l], &exp[l]);
  655. return Result;
  656. }
  657. template<typename genType>
  658. GLM_FUNC_QUALIFIER genType ldexp(genType const& x, int const& exp)
  659. {
  660. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'ldexp' only accept floating-point inputs");
  661. return std::ldexp(x, exp);
  662. }
  663. template<length_t L, typename T, qualifier Q>
  664. GLM_FUNC_QUALIFIER vec<L, T, Q> ldexp(vec<L, T, Q> const& v, vec<L, int, Q> const& exp)
  665. {
  666. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'ldexp' only accept floating-point inputs");
  667. vec<L, T, Q> Result;
  668. for (length_t l = 0; l < v.length(); ++l)
  669. Result[l] = std::ldexp(v[l], exp[l]);
  670. return Result;
  671. }
  672. }//namespace glm
  673. #if GLM_CONFIG_SIMD == GLM_ENABLE
  674. # include "func_common_simd.inl"
  675. #endif