func_common.inl 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  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, "'smoothstep' 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,
  253. std::numeric_limits<genFIType>::is_iec559, detail::is_aligned<highp>::value>::call(vec<1, genFIType>(x)).x;
  254. }
  255. template<length_t L, typename T, qualifier Q>
  256. GLM_FUNC_QUALIFIER vec<L, T, Q> sign(vec<L, T, Q> const& x)
  257. {
  258. GLM_STATIC_ASSERT(
  259. std::numeric_limits<T>::is_iec559 || (std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_integer),
  260. "'sign' only accept signed inputs");
  261. return detail::compute_sign<L, T, Q, std::numeric_limits<T>::is_iec559, detail::is_aligned<Q>::value>::call(x);
  262. }
  263. // floor
  264. using ::std::floor;
  265. template<length_t L, typename T, qualifier Q>
  266. GLM_FUNC_QUALIFIER vec<L, T, Q> floor(vec<L, T, Q> const& x)
  267. {
  268. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'floor' only accept floating-point inputs.");
  269. return detail::compute_floor<L, T, Q, detail::is_aligned<Q>::value>::call(x);
  270. }
  271. template<length_t L, typename T, qualifier Q>
  272. GLM_FUNC_QUALIFIER vec<L, T, Q> trunc(vec<L, T, Q> const& x)
  273. {
  274. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'trunc' only accept floating-point inputs");
  275. return detail::compute_trunc<L, T, Q, detail::is_aligned<Q>::value>::call(x);
  276. }
  277. template<length_t L, typename T, qualifier Q>
  278. GLM_FUNC_QUALIFIER vec<L, T, Q> round(vec<L, T, Q> const& x)
  279. {
  280. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'round' only accept floating-point inputs");
  281. return detail::compute_round<L, T, Q, detail::is_aligned<Q>::value>::call(x);
  282. }
  283. /*
  284. // roundEven
  285. template<typename genType>
  286. GLM_FUNC_QUALIFIER genType roundEven(genType const& x)
  287. {
  288. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs");
  289. return genType(int(x + genType(int(x) % 2)));
  290. }
  291. */
  292. // roundEven
  293. template<typename genType>
  294. GLM_FUNC_QUALIFIER genType roundEven(genType x)
  295. {
  296. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs");
  297. int Integer = static_cast<int>(x);
  298. genType IntegerPart = static_cast<genType>(Integer);
  299. genType FractionalPart = fract(x);
  300. if(FractionalPart > static_cast<genType>(0.5) || FractionalPart < static_cast<genType>(0.5))
  301. {
  302. return round(x);
  303. }
  304. else if((Integer % 2) == 0)
  305. {
  306. return IntegerPart;
  307. }
  308. else if(x <= static_cast<genType>(0)) // Work around...
  309. {
  310. return IntegerPart - static_cast<genType>(1);
  311. }
  312. else
  313. {
  314. return IntegerPart + static_cast<genType>(1);
  315. }
  316. //else // Bug on MinGW 4.5.2
  317. //{
  318. // return mix(IntegerPart + genType(-1), IntegerPart + genType(1), x <= genType(0));
  319. //}
  320. }
  321. template<length_t L, typename T, qualifier Q>
  322. GLM_FUNC_QUALIFIER vec<L, T, Q> roundEven(vec<L, T, Q> const& x)
  323. {
  324. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'roundEven' only accept floating-point inputs");
  325. return detail::functor1<vec, L, T, T, Q>::call(roundEven, x);
  326. }
  327. // ceil
  328. using ::std::ceil;
  329. template<length_t L, typename T, qualifier Q>
  330. GLM_FUNC_QUALIFIER vec<L, T, Q> ceil(vec<L, T, Q> const& x)
  331. {
  332. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'ceil' only accept floating-point inputs");
  333. return detail::compute_ceil<L, T, Q, detail::is_aligned<Q>::value>::call(x);
  334. }
  335. // fract
  336. template<typename genType>
  337. GLM_FUNC_QUALIFIER genType fract(genType x)
  338. {
  339. return fract(vec<1, genType>(x)).x;
  340. }
  341. template<length_t L, typename T, qualifier Q>
  342. GLM_FUNC_QUALIFIER vec<L, T, Q> fract(vec<L, T, Q> const& x)
  343. {
  344. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fract' only accept floating-point inputs");
  345. return detail::compute_fract<L, T, Q, detail::is_aligned<Q>::value>::call(x);
  346. }
  347. // mod
  348. template<typename genType>
  349. GLM_FUNC_QUALIFIER genType mod(genType x, genType y)
  350. {
  351. # if GLM_COMPILER & GLM_COMPILER_CUDA
  352. // Another Cuda compiler bug https://github.com/g-truc/glm/issues/530
  353. vec<1, genType, defaultp> Result(mod(vec<1, genType, defaultp>(x), y));
  354. return Result.x;
  355. # else
  356. return mod(vec<1, genType, defaultp>(x), y).x;
  357. # endif
  358. }
  359. template<length_t L, typename T, qualifier Q>
  360. GLM_FUNC_QUALIFIER vec<L, T, Q> mod(vec<L, T, Q> const& x, T y)
  361. {
  362. return detail::compute_mod<L, T, Q, detail::is_aligned<Q>::value>::call(x, vec<L, T, Q>(y));
  363. }
  364. template<length_t L, typename T, qualifier Q>
  365. GLM_FUNC_QUALIFIER vec<L, T, Q> mod(vec<L, T, Q> const& x, vec<L, T, Q> const& y)
  366. {
  367. return detail::compute_mod<L, T, Q, detail::is_aligned<Q>::value>::call(x, y);
  368. }
  369. // modf
  370. template<typename genType>
  371. GLM_FUNC_QUALIFIER genType modf(genType x, genType & i)
  372. {
  373. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'modf' only accept floating-point inputs");
  374. return std::modf(x, &i);
  375. }
  376. template<typename T, qualifier Q>
  377. GLM_FUNC_QUALIFIER vec<1, T, Q> modf(vec<1, T, Q> const& x, vec<1, T, Q> & i)
  378. {
  379. return vec<1, T, Q>(
  380. modf(x.x, i.x));
  381. }
  382. template<typename T, qualifier Q>
  383. GLM_FUNC_QUALIFIER vec<2, T, Q> modf(vec<2, T, Q> const& x, vec<2, T, Q> & i)
  384. {
  385. return vec<2, T, Q>(
  386. modf(x.x, i.x),
  387. modf(x.y, i.y));
  388. }
  389. template<typename T, qualifier Q>
  390. GLM_FUNC_QUALIFIER vec<3, T, Q> modf(vec<3, T, Q> const& x, vec<3, T, Q> & i)
  391. {
  392. return vec<3, T, Q>(
  393. modf(x.x, i.x),
  394. modf(x.y, i.y),
  395. modf(x.z, i.z));
  396. }
  397. template<typename T, qualifier Q>
  398. GLM_FUNC_QUALIFIER vec<4, T, Q> modf(vec<4, T, Q> const& x, vec<4, T, Q> & i)
  399. {
  400. return vec<4, T, Q>(
  401. modf(x.x, i.x),
  402. modf(x.y, i.y),
  403. modf(x.z, i.z),
  404. modf(x.w, i.w));
  405. }
  406. //// Only valid if (INT_MIN <= x-y <= INT_MAX)
  407. //// min(x,y)
  408. //r = y + ((x - y) & ((x - y) >> (sizeof(int) *
  409. //CHAR_BIT - 1)));
  410. //// max(x,y)
  411. //r = x - ((x - y) & ((x - y) >> (sizeof(int) *
  412. //CHAR_BIT - 1)));
  413. // min
  414. template<length_t L, typename T, qualifier Q>
  415. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& a, T b)
  416. {
  417. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'min' only accept floating-point or integer inputs");
  418. return detail::compute_min_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, vec<L, T, Q>(b));
  419. }
  420. template<length_t L, typename T, qualifier Q>
  421. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
  422. {
  423. return detail::compute_min_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, b);
  424. }
  425. // max
  426. template<length_t L, typename T, qualifier Q>
  427. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> const& a, T b)
  428. {
  429. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'max' only accept floating-point or integer inputs");
  430. return detail::compute_max_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, vec<L, T, Q>(b));
  431. }
  432. template<length_t L, typename T, qualifier Q>
  433. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
  434. {
  435. return detail::compute_max_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, b);
  436. }
  437. // clamp
  438. template<typename genType>
  439. GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType clamp(genType x, genType minVal, genType maxVal)
  440. {
  441. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, "'clamp' only accept floating-point or integer inputs");
  442. return min(max(x, minVal), maxVal);
  443. }
  444. template<length_t L, typename T, qualifier Q>
  445. GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> clamp(vec<L, T, Q> const& x, T minVal, T maxVal)
  446. {
  447. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'clamp' only accept floating-point or integer inputs");
  448. 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));
  449. }
  450. template<length_t L, typename T, qualifier Q>
  451. 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)
  452. {
  453. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'clamp' only accept floating-point or integer inputs");
  454. return detail::compute_clamp_vector<L, T, Q, detail::is_aligned<Q>::value>::call(x, minVal, maxVal);
  455. }
  456. template<typename genTypeT, typename genTypeU>
  457. GLM_FUNC_QUALIFIER genTypeT mix(genTypeT x, genTypeT y, genTypeU a)
  458. {
  459. return detail::compute_mix<genTypeT, genTypeU>::call(x, y, a);
  460. }
  461. template<length_t L, typename T, typename U, qualifier Q>
  462. GLM_FUNC_QUALIFIER vec<L, T, Q> mix(vec<L, T, Q> const& x, vec<L, T, Q> const& y, U a)
  463. {
  464. return detail::compute_mix_scalar<L, T, U, Q, detail::is_aligned<Q>::value>::call(x, y, a);
  465. }
  466. template<length_t L, typename T, typename U, qualifier Q>
  467. 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)
  468. {
  469. return detail::compute_mix_vector<L, T, U, Q, detail::is_aligned<Q>::value>::call(x, y, a);
  470. }
  471. // step
  472. template<typename genType>
  473. GLM_FUNC_QUALIFIER genType step(genType edge, genType x)
  474. {
  475. return mix(static_cast<genType>(1), static_cast<genType>(0), x < edge);
  476. }
  477. template<length_t L, typename T, qualifier Q>
  478. GLM_FUNC_QUALIFIER vec<L, T, Q> step(T edge, vec<L, T, Q> const& x)
  479. {
  480. return detail::compute_step_vector<L, T, Q, detail::is_aligned<Q>::value>::call(vec<L, T, Q>(edge), x);
  481. }
  482. template<length_t L, typename T, qualifier Q>
  483. GLM_FUNC_QUALIFIER vec<L, T, Q> step(vec<L, T, Q> const& edge, vec<L, T, Q> const& x)
  484. {
  485. return detail::compute_step_vector<L, T, Q, detail::is_aligned<Q>::value>::call(edge, x);
  486. }
  487. // smoothstep
  488. template<typename genType>
  489. GLM_FUNC_QUALIFIER genType smoothstep(genType edge0, genType edge1, genType x)
  490. {
  491. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'smoothstep' only accept floating-point inputs");
  492. genType const tmp(clamp((x - edge0) / (edge1 - edge0), genType(0), genType(1)));
  493. return tmp * tmp * (genType(3) - genType(2) * tmp);
  494. }
  495. template<length_t L, typename T, qualifier Q>
  496. GLM_FUNC_QUALIFIER vec<L, T, Q> smoothstep(T edge0, T edge1, vec<L, T, Q> const& x)
  497. {
  498. 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);
  499. }
  500. template<length_t L, typename T, qualifier Q>
  501. 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)
  502. {
  503. return detail::compute_smoothstep_vector<L, T, Q, detail::is_aligned<Q>::value>::call(edge0, edge1, x);
  504. }
  505. # if GLM_HAS_CXX11_STL
  506. using std::isnan;
  507. # else
  508. template<typename genType>
  509. GLM_FUNC_QUALIFIER bool isnan(genType x)
  510. {
  511. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'isnan' only accept floating-point inputs");
  512. # if GLM_HAS_CXX11_STL
  513. return std::isnan(x);
  514. # elif GLM_COMPILER & GLM_COMPILER_VC
  515. return _isnan(x) != 0;
  516. # elif GLM_COMPILER & GLM_COMPILER_INTEL
  517. # if GLM_PLATFORM & GLM_PLATFORM_WINDOWS
  518. return _isnan(x) != 0;
  519. # else
  520. return ::isnan(x) != 0;
  521. # endif
  522. # elif (GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)) && (GLM_PLATFORM & GLM_PLATFORM_ANDROID) && __cplusplus < 201103L
  523. return _isnan(x) != 0;
  524. # elif GLM_COMPILER & GLM_COMPILER_CUDA
  525. return ::isnan(x) != 0;
  526. # else
  527. return std::isnan(x);
  528. # endif
  529. }
  530. # endif
  531. template<length_t L, typename T, qualifier Q>
  532. GLM_FUNC_QUALIFIER vec<L, bool, Q> isnan(vec<L, T, Q> const& v)
  533. {
  534. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs");
  535. vec<L, bool, Q> Result;
  536. for (length_t l = 0; l < v.length(); ++l)
  537. Result[l] = glm::isnan(v[l]);
  538. return Result;
  539. }
  540. # if GLM_HAS_CXX11_STL
  541. using std::isinf;
  542. # else
  543. template<typename genType>
  544. GLM_FUNC_QUALIFIER bool isinf(genType x)
  545. {
  546. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'isinf' only accept floating-point inputs");
  547. # if GLM_HAS_CXX11_STL
  548. return std::isinf(x);
  549. # elif GLM_COMPILER & (GLM_COMPILER_INTEL | GLM_COMPILER_VC)
  550. # if(GLM_PLATFORM & GLM_PLATFORM_WINDOWS)
  551. return _fpclass(x) == _FPCLASS_NINF || _fpclass(x) == _FPCLASS_PINF;
  552. # else
  553. return ::isinf(x);
  554. # endif
  555. # elif GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)
  556. # if(GLM_PLATFORM & GLM_PLATFORM_ANDROID && __cplusplus < 201103L)
  557. return _isinf(x) != 0;
  558. # else
  559. return std::isinf(x);
  560. # endif
  561. # elif GLM_COMPILER & GLM_COMPILER_CUDA
  562. // http://developer.download.nvidia.com/compute/cuda/4_2/rel/toolkit/docs/online/group__CUDA__MATH__DOUBLE_g13431dd2b40b51f9139cbb7f50c18fab.html#g13431dd2b40b51f9139cbb7f50c18fab
  563. return ::isinf(double(x)) != 0;
  564. # else
  565. return std::isinf(x);
  566. # endif
  567. }
  568. # endif
  569. template<length_t L, typename T, qualifier Q>
  570. GLM_FUNC_QUALIFIER vec<L, bool, Q> isinf(vec<L, T, Q> const& v)
  571. {
  572. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isinf' only accept floating-point inputs");
  573. vec<L, bool, Q> Result;
  574. for (length_t l = 0; l < v.length(); ++l)
  575. Result[l] = glm::isinf(v[l]);
  576. return Result;
  577. }
  578. GLM_FUNC_QUALIFIER int floatBitsToInt(float const& v)
  579. {
  580. union
  581. {
  582. float in;
  583. int out;
  584. } u;
  585. u.in = v;
  586. return u.out;
  587. }
  588. template<length_t L, qualifier Q>
  589. GLM_FUNC_QUALIFIER vec<L, int, Q> floatBitsToInt(vec<L, float, Q> const& v)
  590. {
  591. return reinterpret_cast<vec<L, int, Q>&>(const_cast<vec<L, float, Q>&>(v));
  592. }
  593. GLM_FUNC_QUALIFIER uint floatBitsToUint(float const& v)
  594. {
  595. union
  596. {
  597. float in;
  598. uint out;
  599. } u;
  600. u.in = v;
  601. return u.out;
  602. }
  603. template<length_t L, qualifier Q>
  604. GLM_FUNC_QUALIFIER vec<L, uint, Q> floatBitsToUint(vec<L, float, Q> const& v)
  605. {
  606. return reinterpret_cast<vec<L, uint, Q>&>(const_cast<vec<L, float, Q>&>(v));
  607. }
  608. GLM_FUNC_QUALIFIER float intBitsToFloat(int const& v)
  609. {
  610. union
  611. {
  612. int in;
  613. float out;
  614. } u;
  615. u.in = v;
  616. return u.out;
  617. }
  618. template<length_t L, qualifier Q>
  619. GLM_FUNC_QUALIFIER vec<L, float, Q> intBitsToFloat(vec<L, int, Q> const& v)
  620. {
  621. return reinterpret_cast<vec<L, float, Q>&>(const_cast<vec<L, int, Q>&>(v));
  622. }
  623. GLM_FUNC_QUALIFIER float uintBitsToFloat(uint const& v)
  624. {
  625. union
  626. {
  627. uint in;
  628. float out;
  629. } u;
  630. u.in = v;
  631. return u.out;
  632. }
  633. template<length_t L, qualifier Q>
  634. GLM_FUNC_QUALIFIER vec<L, float, Q> uintBitsToFloat(vec<L, uint, Q> const& v)
  635. {
  636. return reinterpret_cast<vec<L, float, Q>&>(const_cast<vec<L, uint, Q>&>(v));
  637. }
  638. # if GLM_HAS_CXX11_STL
  639. using std::fma;
  640. # else
  641. template<typename genType>
  642. GLM_FUNC_QUALIFIER genType fma(genType const& a, genType const& b, genType const& c)
  643. {
  644. return a * b + c;
  645. }
  646. # endif
  647. template<typename genType>
  648. GLM_FUNC_QUALIFIER genType frexp(genType x, int& exp)
  649. {
  650. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'frexp' only accept floating-point inputs");
  651. return std::frexp(x, &exp);
  652. }
  653. template<length_t L, typename T, qualifier Q>
  654. GLM_FUNC_QUALIFIER vec<L, T, Q> frexp(vec<L, T, Q> const& v, vec<L, int, Q>& exp)
  655. {
  656. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'frexp' only accept floating-point inputs");
  657. vec<L, T, Q> Result;
  658. for (length_t l = 0; l < v.length(); ++l)
  659. Result[l] = std::frexp(v[l], &exp[l]);
  660. return Result;
  661. }
  662. template<typename genType>
  663. GLM_FUNC_QUALIFIER genType ldexp(genType const& x, int const& exp)
  664. {
  665. GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'ldexp' only accept floating-point inputs");
  666. return std::ldexp(x, exp);
  667. }
  668. template<length_t L, typename T, qualifier Q>
  669. GLM_FUNC_QUALIFIER vec<L, T, Q> ldexp(vec<L, T, Q> const& v, vec<L, int, Q> const& exp)
  670. {
  671. GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'ldexp' only accept floating-point inputs");
  672. vec<L, T, Q> Result;
  673. for (length_t l = 0; l < v.length(); ++l)
  674. Result[l] = std::ldexp(v[l], exp[l]);
  675. return Result;
  676. }
  677. }//namespace glm
  678. #if GLM_CONFIG_SIMD == GLM_ENABLE
  679. # include "func_common_simd.inl"
  680. #endif