vec4.h 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078
  1. /*
  2. * Copyright (c), Recep Aslantas.
  3. *
  4. * MIT License (MIT), http://opensource.org/licenses/MIT
  5. * Full license can be found in the LICENSE file
  6. */
  7. /*
  8. Macros:
  9. GLM_VEC4_ONE_INIT
  10. GLM_VEC4_BLACK_INIT
  11. GLM_VEC4_ZERO_INIT
  12. GLM_VEC4_ONE
  13. GLM_VEC4_BLACK
  14. GLM_VEC4_ZERO
  15. Functions:
  16. CGLM_INLINE void glm_vec4(vec3 v3, float last, vec4 dest);
  17. CGLM_INLINE void glm_vec4_copy3(vec4 a, vec3 dest);
  18. CGLM_INLINE void glm_vec4_copy(vec4 v, vec4 dest);
  19. CGLM_INLINE void glm_vec4_ucopy(vec4 v, vec4 dest);
  20. CGLM_INLINE float glm_vec4_dot(vec4 a, vec4 b);
  21. CGLM_INLINE float glm_vec4_norm2(vec4 v);
  22. CGLM_INLINE float glm_vec4_norm(vec4 v);
  23. CGLM_INLINE float glm_vec4_norm_one(vec4 v);
  24. CGLM_INLINE float glm_vec4_norm_inf(vec4 v);
  25. CGLM_INLINE void glm_vec4_add(vec4 a, vec4 b, vec4 dest);
  26. CGLM_INLINE void glm_vec4_adds(vec4 v, float s, vec4 dest);
  27. CGLM_INLINE void glm_vec4_sub(vec4 a, vec4 b, vec4 dest);
  28. CGLM_INLINE void glm_vec4_subs(vec4 v, float s, vec4 dest);
  29. CGLM_INLINE void glm_vec4_mul(vec4 a, vec4 b, vec4 dest);
  30. CGLM_INLINE void glm_vec4_scale(vec4 v, float s, vec4 dest);
  31. CGLM_INLINE void glm_vec4_scale_as(vec4 v, float s, vec4 dest);
  32. CGLM_INLINE void glm_vec4_div(vec4 a, vec4 b, vec4 dest);
  33. CGLM_INLINE void glm_vec4_divs(vec4 v, float s, vec4 dest);
  34. CGLM_INLINE void glm_vec4_addadd(vec4 a, vec4 b, vec4 dest);
  35. CGLM_INLINE void glm_vec4_subadd(vec4 a, vec4 b, vec4 dest);
  36. CGLM_INLINE void glm_vec4_muladd(vec4 a, vec4 b, vec4 dest);
  37. CGLM_INLINE void glm_vec4_muladds(vec4 a, float s, vec4 dest);
  38. CGLM_INLINE void glm_vec4_maxadd(vec4 a, vec4 b, vec4 dest);
  39. CGLM_INLINE void glm_vec4_minadd(vec4 a, vec4 b, vec4 dest);
  40. CGLM_INLINE void glm_vec4_negate(vec4 v);
  41. CGLM_INLINE void glm_vec4_inv(vec4 v);
  42. CGLM_INLINE void glm_vec4_inv_to(vec4 v, vec4 dest);
  43. CGLM_INLINE void glm_vec4_normalize(vec4 v);
  44. CGLM_INLINE void glm_vec4_normalize_to(vec4 vec, vec4 dest);
  45. CGLM_INLINE float glm_vec4_distance(vec4 a, vec4 b);
  46. CGLM_INLINE float glm_vec4_distance2(vec4 a, vec4 b);
  47. CGLM_INLINE void glm_vec4_maxv(vec4 a, vec4 b, vec4 dest);
  48. CGLM_INLINE void glm_vec4_minv(vec4 a, vec4 b, vec4 dest);
  49. CGLM_INLINE void glm_vec4_clamp(vec4 v, float minVal, float maxVal);
  50. CGLM_INLINE void glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest);
  51. CGLM_INLINE void glm_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest);
  52. CGLM_INLINE void glm_vec4_step_uni(float edge, vec4 x, vec4 dest);
  53. CGLM_INLINE void glm_vec4_step(vec4 edge, vec4 x, vec4 dest);
  54. CGLM_INLINE void glm_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest);
  55. CGLM_INLINE void glm_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest);
  56. CGLM_INLINE void glm_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest);
  57. CGLM_INLINE void glm_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest);
  58. CGLM_INLINE void glm_vec4_swizzle(vec4 v, int mask, vec4 dest);
  59. DEPRECATED:
  60. glm_vec4_dup
  61. glm_vec4_flipsign
  62. glm_vec4_flipsign_to
  63. glm_vec4_inv
  64. glm_vec4_inv_to
  65. glm_vec4_mulv
  66. */
  67. #ifndef cglm_vec4_h
  68. #define cglm_vec4_h
  69. #include "common.h"
  70. #include "vec4-ext.h"
  71. #include "util.h"
  72. /* DEPRECATED! functions */
  73. #define glm_vec4_dup3(v, dest) glm_vec4_copy3(v, dest)
  74. #define glm_vec4_dup(v, dest) glm_vec4_copy(v, dest)
  75. #define glm_vec4_flipsign(v) glm_vec4_negate(v)
  76. #define glm_vec4_flipsign_to(v, dest) glm_vec4_negate_to(v, dest)
  77. #define glm_vec4_inv(v) glm_vec4_negate(v)
  78. #define glm_vec4_inv_to(v, dest) glm_vec4_negate_to(v, dest)
  79. #define glm_vec4_mulv(a, b, d) glm_vec4_mul(a, b, d)
  80. #define GLM_VEC4_ONE_INIT {1.0f, 1.0f, 1.0f, 1.0f}
  81. #define GLM_VEC4_BLACK_INIT {0.0f, 0.0f, 0.0f, 1.0f}
  82. #define GLM_VEC4_ZERO_INIT {0.0f, 0.0f, 0.0f, 0.0f}
  83. #define GLM_VEC4_ONE ((vec4)GLM_VEC4_ONE_INIT)
  84. #define GLM_VEC4_BLACK ((vec4)GLM_VEC4_BLACK_INIT)
  85. #define GLM_VEC4_ZERO ((vec4)GLM_VEC4_ZERO_INIT)
  86. #define GLM_XXXX GLM_SHUFFLE4(0, 0, 0, 0)
  87. #define GLM_YYYY GLM_SHUFFLE4(1, 1, 1, 1)
  88. #define GLM_ZZZZ GLM_SHUFFLE4(2, 2, 2, 2)
  89. #define GLM_WWWW GLM_SHUFFLE4(3, 3, 3, 3)
  90. #define GLM_WZYX GLM_SHUFFLE4(0, 1, 2, 3)
  91. /*!
  92. * @brief init vec4 using vec3
  93. *
  94. * @param[in] v3 vector3
  95. * @param[in] last last item
  96. * @param[out] dest destination
  97. */
  98. CGLM_INLINE
  99. void
  100. glm_vec4(vec3 v3, float last, vec4 dest) {
  101. dest[0] = v3[0];
  102. dest[1] = v3[1];
  103. dest[2] = v3[2];
  104. dest[3] = last;
  105. }
  106. /*!
  107. * @brief copy first 3 members of [a] to [dest]
  108. *
  109. * @param[in] a source
  110. * @param[out] dest destination
  111. */
  112. CGLM_INLINE
  113. void
  114. glm_vec4_copy3(vec4 a, vec3 dest) {
  115. dest[0] = a[0];
  116. dest[1] = a[1];
  117. dest[2] = a[2];
  118. }
  119. /*!
  120. * @brief copy all members of [a] to [dest]
  121. *
  122. * @param[in] v source
  123. * @param[out] dest destination
  124. */
  125. CGLM_INLINE
  126. void
  127. glm_vec4_copy(vec4 v, vec4 dest) {
  128. #if defined( __SSE__ ) || defined( __SSE2__ )
  129. glmm_store(dest, glmm_load(v));
  130. #elif defined(CGLM_NEON_FP)
  131. vst1q_f32(dest, vld1q_f32(v));
  132. #else
  133. dest[0] = v[0];
  134. dest[1] = v[1];
  135. dest[2] = v[2];
  136. dest[3] = v[3];
  137. #endif
  138. }
  139. /*!
  140. * @brief copy all members of [a] to [dest]
  141. *
  142. * alignment is not required
  143. *
  144. * @param[in] v source
  145. * @param[out] dest destination
  146. */
  147. CGLM_INLINE
  148. void
  149. glm_vec4_ucopy(vec4 v, vec4 dest) {
  150. dest[0] = v[0];
  151. dest[1] = v[1];
  152. dest[2] = v[2];
  153. dest[3] = v[3];
  154. }
  155. /*!
  156. * @brief make vector zero
  157. *
  158. * @param[in, out] v vector
  159. */
  160. CGLM_INLINE
  161. void
  162. glm_vec4_zero(vec4 v) {
  163. #if defined( __SSE__ ) || defined( __SSE2__ )
  164. glmm_store(v, _mm_setzero_ps());
  165. #elif defined(CGLM_NEON_FP)
  166. vst1q_f32(v, vdupq_n_f32(0.0f));
  167. #else
  168. v[0] = 0.0f;
  169. v[1] = 0.0f;
  170. v[2] = 0.0f;
  171. v[3] = 0.0f;
  172. #endif
  173. }
  174. /*!
  175. * @brief make vector one
  176. *
  177. * @param[in, out] v vector
  178. */
  179. CGLM_INLINE
  180. void
  181. glm_vec4_one(vec4 v) {
  182. #if defined( __SSE__ ) || defined( __SSE2__ )
  183. glmm_store(v, _mm_set1_ps(1.0f));
  184. #elif defined(CGLM_NEON_FP)
  185. vst1q_f32(v, vdupq_n_f32(1.0f));
  186. #else
  187. v[0] = 1.0f;
  188. v[1] = 1.0f;
  189. v[2] = 1.0f;
  190. v[3] = 1.0f;
  191. #endif
  192. }
  193. /*!
  194. * @brief vec4 dot product
  195. *
  196. * @param[in] a vector1
  197. * @param[in] b vector2
  198. *
  199. * @return dot product
  200. */
  201. CGLM_INLINE
  202. float
  203. glm_vec4_dot(vec4 a, vec4 b) {
  204. #if defined(CGLM_SIMD)
  205. return glmm_dot(glmm_load(a), glmm_load(b));
  206. #else
  207. return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
  208. #endif
  209. }
  210. /*!
  211. * @brief norm * norm (magnitude) of vec
  212. *
  213. * we can use this func instead of calling norm * norm, because it would call
  214. * sqrtf fuction twice but with this func we can avoid func call, maybe this is
  215. * not good name for this func
  216. *
  217. * @param[in] v vec4
  218. *
  219. * @return norm * norm
  220. */
  221. CGLM_INLINE
  222. float
  223. glm_vec4_norm2(vec4 v) {
  224. return glm_vec4_dot(v, v);
  225. }
  226. /*!
  227. * @brief euclidean norm (magnitude), also called L2 norm
  228. * this will give magnitude of vector in euclidean space
  229. *
  230. * @param[in] v vector
  231. *
  232. * @return norm
  233. */
  234. CGLM_INLINE
  235. float
  236. glm_vec4_norm(vec4 v) {
  237. #if defined(CGLM_SIMD)
  238. return glmm_norm(glmm_load(v));
  239. #else
  240. return sqrtf(glm_vec4_dot(v, v));
  241. #endif
  242. }
  243. /*!
  244. * @brief L1 norm of vec4
  245. * Also known as Manhattan Distance or Taxicab norm.
  246. * L1 Norm is the sum of the magnitudes of the vectors in a space.
  247. * It is calculated as the sum of the absolute values of the vector components.
  248. * In this norm, all the components of the vector are weighted equally.
  249. *
  250. * This computes:
  251. * L1 norm = |v[0]| + |v[1]| + |v[2]| + |v[3]|
  252. *
  253. * @param[in] v vector
  254. *
  255. * @return L1 norm
  256. */
  257. CGLM_INLINE
  258. float
  259. glm_vec4_norm_one(vec4 v) {
  260. #if defined(CGLM_SIMD)
  261. return glmm_norm_one(glmm_load(v));
  262. #else
  263. vec4 t;
  264. glm_vec4_abs(v, t);
  265. return glm_vec4_hadd(t);
  266. #endif
  267. }
  268. /*!
  269. * @brief infinity norm of vec4
  270. * Also known as Maximum norm.
  271. * Infinity Norm is the largest magnitude among each element of a vector.
  272. * It is calculated as the maximum of the absolute values of the vector components.
  273. *
  274. * This computes:
  275. * inf norm = max(|v[0]|, |v[1]|, |v[2]|, |v[3]|)
  276. *
  277. * @param[in] v vector
  278. *
  279. * @return infinity norm
  280. */
  281. CGLM_INLINE
  282. float
  283. glm_vec4_norm_inf(vec4 v) {
  284. #if defined(CGLM_SIMD)
  285. return glmm_norm_inf(glmm_load(v));
  286. #else
  287. vec4 t;
  288. glm_vec4_abs(v, t);
  289. return glm_vec4_max(t);
  290. #endif
  291. }
  292. /*!
  293. * @brief add b vector to a vector store result in dest
  294. *
  295. * @param[in] a vector1
  296. * @param[in] b vector2
  297. * @param[out] dest destination vector
  298. */
  299. CGLM_INLINE
  300. void
  301. glm_vec4_add(vec4 a, vec4 b, vec4 dest) {
  302. #if defined( __SSE__ ) || defined( __SSE2__ )
  303. glmm_store(dest, _mm_add_ps(glmm_load(a), glmm_load(b)));
  304. #elif defined(CGLM_NEON_FP)
  305. vst1q_f32(dest, vaddq_f32(vld1q_f32(a), vld1q_f32(b)));
  306. #else
  307. dest[0] = a[0] + b[0];
  308. dest[1] = a[1] + b[1];
  309. dest[2] = a[2] + b[2];
  310. dest[3] = a[3] + b[3];
  311. #endif
  312. }
  313. /*!
  314. * @brief add scalar to v vector store result in dest (d = v + vec(s))
  315. *
  316. * @param[in] v vector
  317. * @param[in] s scalar
  318. * @param[out] dest destination vector
  319. */
  320. CGLM_INLINE
  321. void
  322. glm_vec4_adds(vec4 v, float s, vec4 dest) {
  323. #if defined( __SSE__ ) || defined( __SSE2__ )
  324. glmm_store(dest, _mm_add_ps(glmm_load(v), _mm_set1_ps(s)));
  325. #elif defined(CGLM_NEON_FP)
  326. vst1q_f32(dest, vaddq_f32(vld1q_f32(v), vdupq_n_f32(s)));
  327. #else
  328. dest[0] = v[0] + s;
  329. dest[1] = v[1] + s;
  330. dest[2] = v[2] + s;
  331. dest[3] = v[3] + s;
  332. #endif
  333. }
  334. /*!
  335. * @brief subtract b vector from a vector store result in dest (d = a - b)
  336. *
  337. * @param[in] a vector1
  338. * @param[in] b vector2
  339. * @param[out] dest destination vector
  340. */
  341. CGLM_INLINE
  342. void
  343. glm_vec4_sub(vec4 a, vec4 b, vec4 dest) {
  344. #if defined( __SSE__ ) || defined( __SSE2__ )
  345. glmm_store(dest, _mm_sub_ps(glmm_load(a), glmm_load(b)));
  346. #elif defined(CGLM_NEON_FP)
  347. vst1q_f32(dest, vsubq_f32(vld1q_f32(a), vld1q_f32(b)));
  348. #else
  349. dest[0] = a[0] - b[0];
  350. dest[1] = a[1] - b[1];
  351. dest[2] = a[2] - b[2];
  352. dest[3] = a[3] - b[3];
  353. #endif
  354. }
  355. /*!
  356. * @brief subtract scalar from v vector store result in dest (d = v - vec(s))
  357. *
  358. * @param[in] v vector
  359. * @param[in] s scalar
  360. * @param[out] dest destination vector
  361. */
  362. CGLM_INLINE
  363. void
  364. glm_vec4_subs(vec4 v, float s, vec4 dest) {
  365. #if defined( __SSE__ ) || defined( __SSE2__ )
  366. glmm_store(dest, _mm_sub_ps(glmm_load(v), _mm_set1_ps(s)));
  367. #elif defined(CGLM_NEON_FP)
  368. vst1q_f32(dest, vsubq_f32(vld1q_f32(v), vdupq_n_f32(s)));
  369. #else
  370. dest[0] = v[0] - s;
  371. dest[1] = v[1] - s;
  372. dest[2] = v[2] - s;
  373. dest[3] = v[3] - s;
  374. #endif
  375. }
  376. /*!
  377. * @brief multiply two vector (component-wise multiplication)
  378. *
  379. * @param a vector1
  380. * @param b vector2
  381. * @param dest dest = (a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3])
  382. */
  383. CGLM_INLINE
  384. void
  385. glm_vec4_mul(vec4 a, vec4 b, vec4 dest) {
  386. #if defined( __SSE__ ) || defined( __SSE2__ )
  387. glmm_store(dest, _mm_mul_ps(glmm_load(a), glmm_load(b)));
  388. #elif defined(CGLM_NEON_FP)
  389. vst1q_f32(dest, vmulq_f32(vld1q_f32(a), vld1q_f32(b)));
  390. #else
  391. dest[0] = a[0] * b[0];
  392. dest[1] = a[1] * b[1];
  393. dest[2] = a[2] * b[2];
  394. dest[3] = a[3] * b[3];
  395. #endif
  396. }
  397. /*!
  398. * @brief multiply/scale vec4 vector with scalar: result = v * s
  399. *
  400. * @param[in] v vector
  401. * @param[in] s scalar
  402. * @param[out] dest destination vector
  403. */
  404. CGLM_INLINE
  405. void
  406. glm_vec4_scale(vec4 v, float s, vec4 dest) {
  407. #if defined( __SSE__ ) || defined( __SSE2__ )
  408. glmm_store(dest, _mm_mul_ps(glmm_load(v), _mm_set1_ps(s)));
  409. #elif defined(CGLM_NEON_FP)
  410. vst1q_f32(dest, vmulq_f32(vld1q_f32(v), vdupq_n_f32(s)));
  411. #else
  412. dest[0] = v[0] * s;
  413. dest[1] = v[1] * s;
  414. dest[2] = v[2] * s;
  415. dest[3] = v[3] * s;
  416. #endif
  417. }
  418. /*!
  419. * @brief make vec4 vector scale as specified: result = unit(v) * s
  420. *
  421. * @param[in] v vector
  422. * @param[in] s scalar
  423. * @param[out] dest destination vector
  424. */
  425. CGLM_INLINE
  426. void
  427. glm_vec4_scale_as(vec4 v, float s, vec4 dest) {
  428. float norm;
  429. norm = glm_vec4_norm(v);
  430. if (norm == 0.0f) {
  431. glm_vec4_zero(dest);
  432. return;
  433. }
  434. glm_vec4_scale(v, s / norm, dest);
  435. }
  436. /*!
  437. * @brief div vector with another component-wise division: d = a / b
  438. *
  439. * @param[in] a vector 1
  440. * @param[in] b vector 2
  441. * @param[out] dest result = (a[0]/b[0], a[1]/b[1], a[2]/b[2], a[3]/b[3])
  442. */
  443. CGLM_INLINE
  444. void
  445. glm_vec4_div(vec4 a, vec4 b, vec4 dest) {
  446. #if defined( __SSE__ ) || defined( __SSE2__ )
  447. glmm_store(dest, _mm_div_ps(glmm_load(a), glmm_load(b)));
  448. #else
  449. dest[0] = a[0] / b[0];
  450. dest[1] = a[1] / b[1];
  451. dest[2] = a[2] / b[2];
  452. dest[3] = a[3] / b[3];
  453. #endif
  454. }
  455. /*!
  456. * @brief div vec4 vector with scalar: d = v / s
  457. *
  458. * @param[in] v vector
  459. * @param[in] s scalar
  460. * @param[out] dest destination vector
  461. */
  462. CGLM_INLINE
  463. void
  464. glm_vec4_divs(vec4 v, float s, vec4 dest) {
  465. #if defined( __SSE__ ) || defined( __SSE2__ )
  466. glmm_store(dest, _mm_div_ps(glmm_load(v), _mm_set1_ps(s)));
  467. #else
  468. glm_vec4_scale(v, 1.0f / s, dest);
  469. #endif
  470. }
  471. /*!
  472. * @brief add two vectors and add result to sum
  473. *
  474. * it applies += operator so dest must be initialized
  475. *
  476. * @param[in] a vector 1
  477. * @param[in] b vector 2
  478. * @param[out] dest dest += (a + b)
  479. */
  480. CGLM_INLINE
  481. void
  482. glm_vec4_addadd(vec4 a, vec4 b, vec4 dest) {
  483. #if defined( __SSE__ ) || defined( __SSE2__ )
  484. glmm_store(dest, _mm_add_ps(glmm_load(dest),
  485. _mm_add_ps(glmm_load(a),
  486. glmm_load(b))));
  487. #elif defined(CGLM_NEON_FP)
  488. vst1q_f32(dest, vaddq_f32(vld1q_f32(dest),
  489. vaddq_f32(vld1q_f32(a),
  490. vld1q_f32(b))));
  491. #else
  492. dest[0] += a[0] + b[0];
  493. dest[1] += a[1] + b[1];
  494. dest[2] += a[2] + b[2];
  495. dest[3] += a[3] + b[3];
  496. #endif
  497. }
  498. /*!
  499. * @brief sub two vectors and add result to dest
  500. *
  501. * it applies += operator so dest must be initialized
  502. *
  503. * @param[in] a vector 1
  504. * @param[in] b vector 2
  505. * @param[out] dest dest += (a - b)
  506. */
  507. CGLM_INLINE
  508. void
  509. glm_vec4_subadd(vec4 a, vec4 b, vec4 dest) {
  510. #if defined( __SSE__ ) || defined( __SSE2__ )
  511. glmm_store(dest, _mm_add_ps(glmm_load(dest),
  512. _mm_sub_ps(glmm_load(a),
  513. glmm_load(b))));
  514. #elif defined(CGLM_NEON_FP)
  515. vst1q_f32(dest, vaddq_f32(vld1q_f32(dest),
  516. vsubq_f32(vld1q_f32(a),
  517. vld1q_f32(b))));
  518. #else
  519. dest[0] += a[0] - b[0];
  520. dest[1] += a[1] - b[1];
  521. dest[2] += a[2] - b[2];
  522. dest[3] += a[3] - b[3];
  523. #endif
  524. }
  525. /*!
  526. * @brief mul two vectors and add result to dest
  527. *
  528. * it applies += operator so dest must be initialized
  529. *
  530. * @param[in] a vector 1
  531. * @param[in] b vector 2
  532. * @param[out] dest dest += (a * b)
  533. */
  534. CGLM_INLINE
  535. void
  536. glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) {
  537. #if defined( __SSE__ ) || defined( __SSE2__ )
  538. glmm_store(dest, _mm_add_ps(glmm_load(dest),
  539. _mm_mul_ps(glmm_load(a),
  540. glmm_load(b))));
  541. #elif defined(CGLM_NEON_FP)
  542. vst1q_f32(dest, vaddq_f32(vld1q_f32(dest),
  543. vmulq_f32(vld1q_f32(a),
  544. vld1q_f32(b))));
  545. #else
  546. dest[0] += a[0] * b[0];
  547. dest[1] += a[1] * b[1];
  548. dest[2] += a[2] * b[2];
  549. dest[3] += a[3] * b[3];
  550. #endif
  551. }
  552. /*!
  553. * @brief mul vector with scalar and add result to sum
  554. *
  555. * it applies += operator so dest must be initialized
  556. *
  557. * @param[in] a vector
  558. * @param[in] s scalar
  559. * @param[out] dest dest += (a * b)
  560. */
  561. CGLM_INLINE
  562. void
  563. glm_vec4_muladds(vec4 a, float s, vec4 dest) {
  564. #if defined( __SSE__ ) || defined( __SSE2__ )
  565. glmm_store(dest, _mm_add_ps(glmm_load(dest),
  566. _mm_mul_ps(glmm_load(a),
  567. _mm_set1_ps(s))));
  568. #elif defined(CGLM_NEON_FP)
  569. vst1q_f32(dest, vaddq_f32(vld1q_f32(dest),
  570. vmulq_f32(vld1q_f32(a),
  571. vdupq_n_f32(s))));
  572. #else
  573. dest[0] += a[0] * s;
  574. dest[1] += a[1] * s;
  575. dest[2] += a[2] * s;
  576. dest[3] += a[3] * s;
  577. #endif
  578. }
  579. /*!
  580. * @brief add max of two vector to result/dest
  581. *
  582. * it applies += operator so dest must be initialized
  583. *
  584. * @param[in] a vector 1
  585. * @param[in] b vector 2
  586. * @param[out] dest dest += max(a, b)
  587. */
  588. CGLM_INLINE
  589. void
  590. glm_vec4_maxadd(vec4 a, vec4 b, vec4 dest) {
  591. #if defined( __SSE__ ) || defined( __SSE2__ )
  592. glmm_store(dest, _mm_add_ps(glmm_load(dest),
  593. _mm_max_ps(glmm_load(a),
  594. glmm_load(b))));
  595. #elif defined(CGLM_NEON_FP)
  596. vst1q_f32(dest, vaddq_f32(vld1q_f32(dest),
  597. vmaxq_f32(vld1q_f32(a),
  598. vld1q_f32(b))));
  599. #else
  600. dest[0] += glm_max(a[0], b[0]);
  601. dest[1] += glm_max(a[1], b[1]);
  602. dest[2] += glm_max(a[2], b[2]);
  603. dest[3] += glm_max(a[3], b[3]);
  604. #endif
  605. }
  606. /*!
  607. * @brief add min of two vector to result/dest
  608. *
  609. * it applies += operator so dest must be initialized
  610. *
  611. * @param[in] a vector 1
  612. * @param[in] b vector 2
  613. * @param[out] dest dest += min(a, b)
  614. */
  615. CGLM_INLINE
  616. void
  617. glm_vec4_minadd(vec4 a, vec4 b, vec4 dest) {
  618. #if defined( __SSE__ ) || defined( __SSE2__ )
  619. glmm_store(dest, _mm_add_ps(glmm_load(dest),
  620. _mm_min_ps(glmm_load(a),
  621. glmm_load(b))));
  622. #elif defined(CGLM_NEON_FP)
  623. vst1q_f32(dest, vaddq_f32(vld1q_f32(dest),
  624. vminq_f32(vld1q_f32(a),
  625. vld1q_f32(b))));
  626. #else
  627. dest[0] += glm_min(a[0], b[0]);
  628. dest[1] += glm_min(a[1], b[1]);
  629. dest[2] += glm_min(a[2], b[2]);
  630. dest[3] += glm_min(a[3], b[3]);
  631. #endif
  632. }
  633. /*!
  634. * @brief negate vector components and store result in dest
  635. *
  636. * @param[in] v vector
  637. * @param[out] dest result vector
  638. */
  639. CGLM_INLINE
  640. void
  641. glm_vec4_negate_to(vec4 v, vec4 dest) {
  642. #if defined( __SSE__ ) || defined( __SSE2__ )
  643. glmm_store(dest, _mm_xor_ps(glmm_load(v), _mm_set1_ps(-0.0f)));
  644. #elif defined(CGLM_NEON_FP)
  645. vst1q_f32(dest, vnegq_f32(vld1q_f32(v)));
  646. #else
  647. dest[0] = -v[0];
  648. dest[1] = -v[1];
  649. dest[2] = -v[2];
  650. dest[3] = -v[3];
  651. #endif
  652. }
  653. /*!
  654. * @brief flip sign of all vec4 members
  655. *
  656. * @param[in, out] v vector
  657. */
  658. CGLM_INLINE
  659. void
  660. glm_vec4_negate(vec4 v) {
  661. glm_vec4_negate_to(v, v);
  662. }
  663. /*!
  664. * @brief normalize vec4 to dest
  665. *
  666. * @param[in] v source
  667. * @param[out] dest destination
  668. */
  669. CGLM_INLINE
  670. void
  671. glm_vec4_normalize_to(vec4 v, vec4 dest) {
  672. #if defined( __SSE__ ) || defined( __SSE2__ )
  673. __m128 xdot, x0;
  674. float dot;
  675. x0 = glmm_load(v);
  676. xdot = glmm_vdot(x0, x0);
  677. dot = _mm_cvtss_f32(xdot);
  678. if (dot == 0.0f) {
  679. glmm_store(dest, _mm_setzero_ps());
  680. return;
  681. }
  682. glmm_store(dest, _mm_div_ps(x0, _mm_sqrt_ps(xdot)));
  683. #else
  684. float norm;
  685. norm = glm_vec4_norm(v);
  686. if (norm == 0.0f) {
  687. glm_vec4_zero(dest);
  688. return;
  689. }
  690. glm_vec4_scale(v, 1.0f / norm, dest);
  691. #endif
  692. }
  693. /*!
  694. * @brief normalize vec4 and store result in same vec
  695. *
  696. * @param[in, out] v vector
  697. */
  698. CGLM_INLINE
  699. void
  700. glm_vec4_normalize(vec4 v) {
  701. glm_vec4_normalize_to(v, v);
  702. }
  703. /**
  704. * @brief distance between two vectors
  705. *
  706. * @param[in] a vector1
  707. * @param[in] b vector2
  708. * @return returns distance
  709. */
  710. CGLM_INLINE
  711. float
  712. glm_vec4_distance(vec4 a, vec4 b) {
  713. #if defined( __SSE__ ) || defined( __SSE2__ )
  714. return glmm_norm(_mm_sub_ps(glmm_load(a), glmm_load(b)));
  715. #elif defined(CGLM_NEON_FP)
  716. return glmm_norm(vsubq_f32(glmm_load(a), glmm_load(b)));
  717. #else
  718. return sqrtf(glm_pow2(a[0] - b[0])
  719. + glm_pow2(a[1] - b[1])
  720. + glm_pow2(a[2] - b[2])
  721. + glm_pow2(a[3] - b[3]));
  722. #endif
  723. }
  724. /**
  725. * @brief squared distance between two vectors
  726. *
  727. * @param[in] a vector1
  728. * @param[in] b vector2
  729. * @return returns squared distance
  730. */
  731. CGLM_INLINE
  732. float
  733. glm_vec4_distance2(vec4 a, vec4 b) {
  734. #if defined( __SSE__ ) || defined( __SSE2__ )
  735. return glmm_norm2(_mm_sub_ps(glmm_load(a), glmm_load(b)));
  736. #elif defined(CGLM_NEON_FP)
  737. return glmm_norm2(vsubq_f32(glmm_load(a), glmm_load(b)));
  738. #else
  739. return glm_pow2(a[0] - b[0])
  740. + glm_pow2(a[1] - b[1])
  741. + glm_pow2(a[2] - b[2])
  742. + glm_pow2(a[3] - b[3]);
  743. #endif
  744. }
  745. /*!
  746. * @brief max values of vectors
  747. *
  748. * @param[in] a vector1
  749. * @param[in] b vector2
  750. * @param[out] dest destination
  751. */
  752. CGLM_INLINE
  753. void
  754. glm_vec4_maxv(vec4 a, vec4 b, vec4 dest) {
  755. #if defined( __SSE__ ) || defined( __SSE2__ )
  756. glmm_store(dest, _mm_max_ps(glmm_load(a), glmm_load(b)));
  757. #elif defined(CGLM_NEON_FP)
  758. vst1q_f32(dest, vmaxq_f32(vld1q_f32(a), vld1q_f32(b)));
  759. #else
  760. dest[0] = glm_max(a[0], b[0]);
  761. dest[1] = glm_max(a[1], b[1]);
  762. dest[2] = glm_max(a[2], b[2]);
  763. dest[3] = glm_max(a[3], b[3]);
  764. #endif
  765. }
  766. /*!
  767. * @brief min values of vectors
  768. *
  769. * @param[in] a vector1
  770. * @param[in] b vector2
  771. * @param[out] dest destination
  772. */
  773. CGLM_INLINE
  774. void
  775. glm_vec4_minv(vec4 a, vec4 b, vec4 dest) {
  776. #if defined( __SSE__ ) || defined( __SSE2__ )
  777. glmm_store(dest, _mm_min_ps(glmm_load(a), glmm_load(b)));
  778. #elif defined(CGLM_NEON_FP)
  779. vst1q_f32(dest, vminq_f32(vld1q_f32(a), vld1q_f32(b)));
  780. #else
  781. dest[0] = glm_min(a[0], b[0]);
  782. dest[1] = glm_min(a[1], b[1]);
  783. dest[2] = glm_min(a[2], b[2]);
  784. dest[3] = glm_min(a[3], b[3]);
  785. #endif
  786. }
  787. /*!
  788. * @brief clamp vector's individual members between min and max values
  789. *
  790. * @param[in, out] v vector
  791. * @param[in] minVal minimum value
  792. * @param[in] maxVal maximum value
  793. */
  794. CGLM_INLINE
  795. void
  796. glm_vec4_clamp(vec4 v, float minVal, float maxVal) {
  797. #if defined( __SSE__ ) || defined( __SSE2__ )
  798. glmm_store(v, _mm_min_ps(_mm_max_ps(glmm_load(v), _mm_set1_ps(minVal)),
  799. _mm_set1_ps(maxVal)));
  800. #elif defined(CGLM_NEON_FP)
  801. vst1q_f32(v, vminq_f32(vmaxq_f32(vld1q_f32(v), vdupq_n_f32(minVal)),
  802. vdupq_n_f32(maxVal)));
  803. #else
  804. v[0] = glm_clamp(v[0], minVal, maxVal);
  805. v[1] = glm_clamp(v[1], minVal, maxVal);
  806. v[2] = glm_clamp(v[2], minVal, maxVal);
  807. v[3] = glm_clamp(v[3], minVal, maxVal);
  808. #endif
  809. }
  810. /*!
  811. * @brief linear interpolation between two vectors
  812. *
  813. * formula: from + t * (to - from)
  814. *
  815. * @param[in] from from value
  816. * @param[in] to to value
  817. * @param[in] t interpolant (amount)
  818. * @param[out] dest destination
  819. */
  820. CGLM_INLINE
  821. void
  822. glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) {
  823. vec4 s, v;
  824. /* from + s * (to - from) */
  825. glm_vec4_broadcast(t, s);
  826. glm_vec4_sub(to, from, v);
  827. glm_vec4_mul(s, v, v);
  828. glm_vec4_add(from, v, dest);
  829. }
  830. /*!
  831. * @brief linear interpolation between two vectors (clamped)
  832. *
  833. * formula: from + t * (to - from)
  834. *
  835. * @param[in] from from value
  836. * @param[in] to to value
  837. * @param[in] t interpolant (amount) clamped between 0 and 1
  838. * @param[out] dest destination
  839. */
  840. CGLM_INLINE
  841. void
  842. glm_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest) {
  843. glm_vec4_lerp(from, to, glm_clamp_zo(t), dest);
  844. }
  845. /*!
  846. * @brief linear interpolation between two vectors
  847. *
  848. * formula: from + t * (to - from)
  849. *
  850. * @param[in] from from value
  851. * @param[in] to to value
  852. * @param[in] t interpolant (amount)
  853. * @param[out] dest destination
  854. */
  855. CGLM_INLINE
  856. void
  857. glm_vec4_mix(vec4 from, vec4 to, float t, vec4 dest) {
  858. glm_vec4_lerp(from, to, t, dest);
  859. }
  860. /*!
  861. * @brief linear interpolation between two vectors (clamped)
  862. *
  863. * formula: from + t * (to - from)
  864. *
  865. * @param[in] from from value
  866. * @param[in] to to value
  867. * @param[in] t interpolant (amount) clamped between 0 and 1
  868. * @param[out] dest destination
  869. */
  870. CGLM_INLINE
  871. void
  872. glm_vec4_mixc(vec4 from, vec4 to, float t, vec4 dest) {
  873. glm_vec4_lerpc(from, to, t, dest);
  874. }
  875. /*!
  876. * @brief threshold function (unidimensional)
  877. *
  878. * @param[in] edge threshold
  879. * @param[in] x value to test against threshold
  880. * @param[out] dest destination
  881. */
  882. CGLM_INLINE
  883. void
  884. glm_vec4_step_uni(float edge, vec4 x, vec4 dest) {
  885. dest[0] = glm_step(edge, x[0]);
  886. dest[1] = glm_step(edge, x[1]);
  887. dest[2] = glm_step(edge, x[2]);
  888. dest[3] = glm_step(edge, x[3]);
  889. }
  890. /*!
  891. * @brief threshold function
  892. *
  893. * @param[in] edge threshold
  894. * @param[in] x value to test against threshold
  895. * @param[out] dest destination
  896. */
  897. CGLM_INLINE
  898. void
  899. glm_vec4_step(vec4 edge, vec4 x, vec4 dest) {
  900. dest[0] = glm_step(edge[0], x[0]);
  901. dest[1] = glm_step(edge[1], x[1]);
  902. dest[2] = glm_step(edge[2], x[2]);
  903. dest[3] = glm_step(edge[3], x[3]);
  904. }
  905. /*!
  906. * @brief threshold function with a smooth transition (unidimensional)
  907. *
  908. * @param[in] edge0 low threshold
  909. * @param[in] edge1 high threshold
  910. * @param[in] x value to test against threshold
  911. * @param[out] dest destination
  912. */
  913. CGLM_INLINE
  914. void
  915. glm_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest) {
  916. dest[0] = glm_smoothstep(edge0, edge1, x[0]);
  917. dest[1] = glm_smoothstep(edge0, edge1, x[1]);
  918. dest[2] = glm_smoothstep(edge0, edge1, x[2]);
  919. dest[3] = glm_smoothstep(edge0, edge1, x[3]);
  920. }
  921. /*!
  922. * @brief threshold function with a smooth transition
  923. *
  924. * @param[in] edge0 low threshold
  925. * @param[in] edge1 high threshold
  926. * @param[in] x value to test against threshold
  927. * @param[out] dest destination
  928. */
  929. CGLM_INLINE
  930. void
  931. glm_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest) {
  932. dest[0] = glm_smoothstep(edge0[0], edge1[0], x[0]);
  933. dest[1] = glm_smoothstep(edge0[1], edge1[1], x[1]);
  934. dest[2] = glm_smoothstep(edge0[2], edge1[2], x[2]);
  935. dest[3] = glm_smoothstep(edge0[3], edge1[3], x[3]);
  936. }
  937. /*!
  938. * @brief smooth Hermite interpolation between two vectors
  939. *
  940. * formula: t^2 * (3 - 2*t)
  941. *
  942. * @param[in] from from value
  943. * @param[in] to to value
  944. * @param[in] t interpolant (amount)
  945. * @param[out] dest destination
  946. */
  947. CGLM_INLINE
  948. void
  949. glm_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest) {
  950. vec4 s, v;
  951. /* from + smoothstep * (to - from) */
  952. glm_vec4_broadcast(glm_smooth(t), s);
  953. glm_vec4_sub(to, from, v);
  954. glm_vec4_mul(s, v, v);
  955. glm_vec4_add(from, v, dest);
  956. }
  957. /*!
  958. * @brief smooth Hermite interpolation between two vectors (clamped)
  959. *
  960. * formula: t^2 * (3 - 2*t)
  961. *
  962. * @param[in] from from value
  963. * @param[in] to to value
  964. * @param[in] t interpolant (amount) clamped between 0 and 1
  965. * @param[out] dest destination
  966. */
  967. CGLM_INLINE
  968. void
  969. glm_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest) {
  970. glm_vec4_smoothinterp(from, to, glm_clamp_zo(t), dest);
  971. }
  972. /*!
  973. * @brief helper to fill vec4 as [S^3, S^2, S, 1]
  974. *
  975. * @param[in] s parameter
  976. * @param[out] dest destination
  977. */
  978. CGLM_INLINE
  979. void
  980. glm_vec4_cubic(float s, vec4 dest) {
  981. float ss;
  982. ss = s * s;
  983. dest[0] = ss * s;
  984. dest[1] = ss;
  985. dest[2] = s;
  986. dest[3] = 1.0f;
  987. }
  988. /*!
  989. * @brief swizzle vector components
  990. *
  991. * you can use existin masks e.g. GLM_XXXX, GLM_WZYX
  992. *
  993. * @param[in] v source
  994. * @param[in] mask mask
  995. * @param[out] dest destination
  996. */
  997. CGLM_INLINE
  998. void
  999. glm_vec4_swizzle(vec4 v, int mask, vec4 dest) {
  1000. vec4 t;
  1001. t[0] = v[(mask & (3 << 0))];
  1002. t[1] = v[(mask & (3 << 2)) >> 2];
  1003. t[2] = v[(mask & (3 << 4)) >> 4];
  1004. t[3] = v[(mask & (3 << 6)) >> 6];
  1005. glm_vec4_copy(t, dest);
  1006. }
  1007. #endif /* cglm_vec4_h */