Collection of DPF-based plugins for packaging
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

827 lines
25KB

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