1/* graphene-simd4f.c
2 *
3 * SPDX-License-Identifier: MIT
4 *
5 * Copyright 2014 Emmanuele Bassi
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26/**
27 * SECTION:graphene-simd4f
28 * @Title: SIMD vector
29 * @short_description: Low level floating point 4-sized vector
30 *
31 * The #graphene_simd4f_t type wraps a platform specific implementation of
32 * a vector of four floating point values.
33 *
34 * Graphene can be compiled to use different implementations of the SIMD
35 * types, and will generally prefer the faster hardware-backed implementation
36 * if one is available.
37 *
38 * The #graphene_simd4f_t should be treated as an opaque, integral type;
39 * you cannot access its components directly, and you can only operate on
40 * all components at the same time.
41 */
42
43#include "graphene-private.h"
44#include "graphene-simd4f.h"
45
46#include <string.h>
47#include <math.h>
48
49/**
50 * graphene_simd4f_t:
51 *
52 * A vector type containing four floating point values.
53 *
54 * The contents of the #graphene_simd4f_t type are private and
55 * cannot be directly accessed; use the provided API instead.
56 *
57 * Since: 1.0
58 */
59
60/* fast paths are all defined in the graphene-simd4f.h header */
61#if defined(GRAPHENE_USE_SSE) || defined(GRAPHENE_USE_GCC) || defined(GRAPHENE_USE_ARM_NEON)
62
63/**
64 * graphene_simd4f_init:
65 * @x: the first component of the vector
66 * @y: the second component of the vector
67 * @z: the third component of the vector
68 * @w: the fourth component of the vector
69 *
70 * Initializes a #graphene_simd4f_t with the given values.
71 *
72 * Returns: the initialized #graphene_simd4f_t
73 *
74 * Since: 1.0
75 */
76graphene_simd4f_t
77(graphene_simd4f_init) (float x,
78 float y,
79 float z,
80 float w)
81{
82 return graphene_simd4f_init (x, y, z, w);
83}
84
85/**
86 * graphene_simd4f_init_zero:
87 *
88 * Initializes a #graphene_simd4f_t with 0 in all components.
89 *
90 * Returns: the initialized #graphene_simd4f_t
91 *
92 * Since: 1.0
93 */
94graphene_simd4f_t
95(graphene_simd4f_init_zero) (void)
96{
97 return graphene_simd4f_init_zero ();
98}
99
100/**
101 * graphene_simd4f_init_4f:
102 * @v: (array fixed-size=4): an array of at least 4 floating
103 * point values
104 *
105 * Initializes a #graphene_simd4f_t using an array of 4 floating
106 * point values.
107 *
108 * Returns: the initialized #graphene_simd4f_t
109 *
110 * Since: 1.0
111 */
112graphene_simd4f_t
113(graphene_simd4f_init_4f) (const float *v)
114{
115 return graphene_simd4f_init_4f (v);
116}
117
118/**
119 * graphene_simd4f_init_3f:
120 * @v: (array fixed-size=3): an array of at least 3 floating
121 * point values
122 *
123 * Initializes a #graphene_simd4f_t using an array of 3 floating
124 * point values.
125 *
126 * Returns: the initialized #graphene_simd4f_t
127 *
128 * Since: 1.0
129 */
130graphene_simd4f_t
131(graphene_simd4f_init_3f) (const float *v)
132{
133 return graphene_simd4f_init_3f (v);
134}
135
136/**
137 * graphene_simd4f_init_2f:
138 * @v: (array fixed-size=2): an array of at least 2 floating
139 * point values
140 *
141 * Initializes a #graphene_simd4f_t using an array of 2 floating
142 * point values.
143 *
144 * Returns: the initialized #graphene_simd4f_t
145 *
146 * Since: 1.0
147 */
148graphene_simd4f_t
149(graphene_simd4f_init_2f) (const float *v)
150{
151 return graphene_simd4f_init_2f (v);
152}
153
154/**
155 * graphene_simd4f_dup_4f:
156 * @s: a #graphene_simd4f_t
157 * @v: (out) (array fixed-size=4): return location for an
158 * array of at least 4 floating point values
159 *
160 * Copies the contents of a #graphene_simd4f_t into an
161 * array of floating points.
162 *
163 * Since: 1.0
164 */
165void
166(graphene_simd4f_dup_4f) (const graphene_simd4f_t s,
167 float *v)
168{
169 graphene_simd4f_dup_4f (s, v);
170}
171
172/**
173 * graphene_simd4f_dup_3f:
174 * @s: a #graphene_simd4f_t
175 * @v: (out) (array fixed-size=3): return location for an
176 * array of at least 3 floating point values
177 *
178 * Copies the contents of a #graphene_simd4f_t into an
179 * array of floating points.
180 *
181 * Since: 1.0
182 */
183void
184(graphene_simd4f_dup_3f) (const graphene_simd4f_t s,
185 float *v)
186{
187 graphene_simd4f_dup_3f (s, v);
188}
189
190/**
191 * graphene_simd4f_dup_2f:
192 * @s: a #graphene_simd4f_t
193 * @v: (out) (array fixed-size=2): return location for an
194 * array of at least 2 floating point values
195 *
196 * Copies the contents of a #graphene_simd4f_t into an
197 * array of floating points.
198 *
199 * Since: 1.0
200 */
201void
202(graphene_simd4f_dup_2f) (const graphene_simd4f_t s,
203 float *v)
204{
205 graphene_simd4f_dup_2f (s, v);
206}
207
208/**
209 * graphene_simd4f_get:
210 * @s: a #graphene_simd4f_t
211 * @i: the index of the component to retrieve
212 *
213 * Retrieves the given component of a #graphene_simd4f_t.
214 *
215 * Since: 1.2
216 */
217float
218(graphene_simd4f_get) (const graphene_simd4f_t s,
219 unsigned int i)
220{
221 switch (i)
222 {
223 case 0:
224 return graphene_simd4f_get (s, 0);
225
226 case 1:
227 return graphene_simd4f_get (s, 1);
228
229 case 2:
230 return graphene_simd4f_get (s, 2);
231
232 case 3:
233 return graphene_simd4f_get (s, 3);
234
235 default:
236 return 0.f;
237 }
238}
239
240/**
241 * graphene_simd4f_get_x:
242 * @s: a #graphene_simd4f_t
243 *
244 * Retrieves the first component of @s.
245 *
246 * Returns: the first component of a #graphene_simd4f_t
247 *
248 * Since: 1.0
249 */
250float
251(graphene_simd4f_get_x) (const graphene_simd4f_t s)
252{
253 return graphene_simd4f_get_x (s);
254}
255
256/**
257 * graphene_simd4f_get_y:
258 * @s: a #graphene_simd4f_t
259 *
260 * Retrieves the second component of @s.
261 *
262 * Returns: the second component of a #graphene_simd4f_t
263 *
264 * Since: 1.0
265 */
266float
267(graphene_simd4f_get_y) (const graphene_simd4f_t s)
268{
269 return graphene_simd4f_get_y (s);
270}
271
272/**
273 * graphene_simd4f_get_z:
274 * @s: a #graphene_simd4f_t
275 *
276 * Retrieves the third component of @s.
277 *
278 * Returns: the third component of a #graphene_simd4f_t
279 *
280 * Since: 1.0
281 */
282float
283(graphene_simd4f_get_z) (const graphene_simd4f_t s)
284{
285 return graphene_simd4f_get_z (s);
286}
287
288/**
289 * graphene_simd4f_get_w:
290 * @s: a #graphene_simd4f_t
291 *
292 * Retrieves the fourth component of @s.
293 *
294 * Returns: the fourth component of a #graphene_simd4f_t
295 *
296 * Since: 1.0
297 */
298float
299(graphene_simd4f_get_w) (const graphene_simd4f_t s)
300{
301 return graphene_simd4f_get_w (s);
302}
303
304/**
305 * graphene_simd4f_splat:
306 * @v: a floating point value
307 *
308 * Sets all the components of a new #graphene_simd4f_t to the
309 * same value @v:
310 *
311 * |[<!-- language="plain" -->
312 * {
313 * .x = v,
314 * .y = v,
315 * .z = v,
316 * .w = v
317 * };
318 * ]|
319 *
320 * Returns: the initialized #graphene_simd4f_t
321 *
322 * Since: 1.0
323 */
324graphene_simd4f_t
325(graphene_simd4f_splat) (float v)
326{
327 return graphene_simd4f_splat (v);
328}
329
330/**
331 * graphene_simd4f_splat_x:
332 * @s: a #graphene_simd4f_t
333 *
334 * Sets all the components of a new #graphene_simd4f_t to the
335 * same value of the first component of the passed vector:
336 *
337 * |[<!-- language="plain" -->
338 * {
339 * .x = s.x,
340 * .y = s.x,
341 * .z = s.x,
342 * .w = s.x
343 * }
344 * ]|
345 *
346 * Returns: the initialized #graphene_simd4f_t
347 *
348 * Since: 1.0
349 */
350graphene_simd4f_t
351(graphene_simd4f_splat_x) (const graphene_simd4f_t s)
352{
353 return graphene_simd4f_splat_x (s);
354}
355
356/**
357 * graphene_simd4f_splat_y:
358 * @s: a #graphene_simd4f_t
359 *
360 * Sets all the components of a new #graphene_simd4f_t to the
361 * same value of the second component of the passed vector:
362 *
363 * |[<!-- language="plain" -->
364 * {
365 * .x = s.y,
366 * .y = s.y,
367 * .z = s.y,
368 * .w = s.y
369 * }
370 * ]|
371 *
372 * Returns: the initialized #graphene_simd4f_t
373 *
374 * Since: 1.0
375 */
376graphene_simd4f_t
377(graphene_simd4f_splat_y) (const graphene_simd4f_t s)
378{
379 return graphene_simd4f_splat_y (s);
380}
381
382/**
383 * graphene_simd4f_splat_z:
384 * @s: a #graphene_simd4f_t
385 *
386 * Sets all the components of a #graphene_simd4f_t to the
387 * same value of the third component of the passed vector:
388 *
389 * |[<!-- language="plain" -->
390 * {
391 * .x = s.z,
392 * .y = s.z,
393 * .z = s.z,
394 * .w = s.z
395 * }
396 * ]|
397 *
398 * Returns: the initialized #graphene_simd4f_t
399 *
400 * Since: 1.0
401 */
402graphene_simd4f_t
403(graphene_simd4f_splat_z) (const graphene_simd4f_t s)
404{
405 return graphene_simd4f_splat_z (s);
406}
407
408/**
409 * graphene_simd4f_splat_w:
410 * @s: a #graphene_simd4f_t
411 *
412 * Sets all the components of a #graphene_simd4f_t to the
413 * same value of the fourth component of the passed vector:
414 *
415 * |[<!-- language="plain" -->
416 * {
417 * .x = s.w,
418 * .y = s.w,
419 * .z = s.w,
420 * .w = s.w
421 * }
422 * ]|
423 *
424 * Returns: the initialized #graphene_simd4f_t
425 *
426 * Since: 1.0
427 */
428graphene_simd4f_t
429(graphene_simd4f_splat_w) (const graphene_simd4f_t s)
430{
431 return graphene_simd4f_splat_w (s);
432}
433
434/**
435 * graphene_simd4f_reciprocal:
436 * @s: a #graphene_simd4f_t
437 *
438 * Computes the reciprocal of every component of @s.
439 *
440 * |[<!-- language="plain" -->
441 * {
442 * .x = 1.0 / s.x,
443 * .y = 1.0 / s.y,
444 * .z = 1.0 / s.z,
445 * .w = 1.0 / s.w
446 * }
447 * ]|
448 *
449 * Returns: a vector containing the reciprocal of the
450 * passed vector
451 *
452 * Since: 1.0
453 */
454graphene_simd4f_t
455(graphene_simd4f_reciprocal) (const graphene_simd4f_t s)
456{
457 return graphene_simd4f_reciprocal (s);
458}
459
460/**
461 * graphene_simd4f_sqrt:
462 * @s: a #graphene_simd4f_t
463 *
464 * Computes the square root of every component of @s.
465 *
466 * |[<!-- language="plain" -->
467 * {
468 * .x = sqrt (s.x),
469 * .y = sqrt (s.y),
470 * .z = sqrt (s.z),
471 * .w = sqrt (s.w)
472 * }
473 * ]|
474 *
475 * Returns: a vector containing the square root of the
476 * passed vector
477 *
478 * Since: 1.0
479 */
480graphene_simd4f_t
481(graphene_simd4f_sqrt) (const graphene_simd4f_t s)
482{
483 return graphene_simd4f_sqrt (s);
484}
485
486/**
487 * graphene_simd4f_rsqrt:
488 * @s: a #graphene_simd4f_t
489 *
490 * Computes the reciprocal square root of every component
491 * of @s.
492 *
493 * |[<!-- language="plain" -->
494 * {
495 * .x = 1.0 / sqrt (s.x),
496 * .y = 1.0 / sqrt (s.y),
497 * .z = 1.0 / sqrt (s.z),
498 * .w = 1.0 / sqrt (s.w)
499 * }
500 * ]|
501 *
502 * Returns: a vector containing the reciprocal square root
503 * of the passed vector
504 *
505 * Since: 1.0
506 */
507graphene_simd4f_t
508(graphene_simd4f_rsqrt) (const graphene_simd4f_t s)
509{
510 return graphene_simd4f_rsqrt (s);
511}
512
513/**
514 * graphene_simd4f_add:
515 * @a: a #graphene_simd4f_t
516 * @b: a #graphene_simd4f_t
517 *
518 * Creates a new #graphene_simd4f_t vector where each
519 * component is the sum of the respective components
520 * in @a and @b.
521 *
522 * |[<!-- lanugage="plain" -->
523 * {
524 * .x = a.x + b.x,
525 * .y = a.y + b.y,
526 * .z = a.z + b.z,
527 * .w = a.w + b.w
528 * }
529 * ]|
530 *
531 * Returns: the sum vector
532 *
533 * Since: 1.0
534 */
535graphene_simd4f_t
536(graphene_simd4f_add) (const graphene_simd4f_t a,
537 const graphene_simd4f_t b)
538{
539 return graphene_simd4f_add (a, b);
540}
541
542/**
543 * graphene_simd4f_sub:
544 * @a: a #graphene_simd4f_t
545 * @b: a #graphene_simd4f_t
546 *
547 * Creates a new #graphene_simd4f_t vector where each
548 * component is the subtraction of the respective components
549 * in @a and @b.
550 *
551 * |[<!-- lanugage="plain" -->
552 * {
553 * .x = a.x - b.x,
554 * .y = a.y - b.y,
555 * .z = a.z - b.z,
556 * .w = a.w - b.w
557 * }
558 * ]|
559 *
560 * Returns: the subtraction vector
561 *
562 * Since: 1.0
563 */
564graphene_simd4f_t
565(graphene_simd4f_sub) (const graphene_simd4f_t a,
566 const graphene_simd4f_t b)
567{
568 return graphene_simd4f_sub (a, b);
569}
570
571/**
572 * graphene_simd4f_mul:
573 * @a: a #graphene_simd4f_t
574 * @b: a #graphene_simd4f_t
575 *
576 * Creates a new #graphene_simd4f_t vector where each
577 * component is the multiplication of the respective components
578 * in @a and @b.
579 *
580 * |[<!-- lanugage="plain" -->
581 * {
582 * .x = a.x * b.x,
583 * .y = a.y * b.y,
584 * .z = a.z * b.z,
585 * .w = a.w * b.w
586 * }
587 * ]|
588 *
589 * Returns: the multiplication vector
590 *
591 * Since: 1.0
592 */
593graphene_simd4f_t
594(graphene_simd4f_mul) (const graphene_simd4f_t a,
595 const graphene_simd4f_t b)
596{
597 return graphene_simd4f_mul (a, b);
598}
599
600/**
601 * graphene_simd4f_div:
602 * @a: a #graphene_simd4f_t
603 * @b: a #graphene_simd4f_t
604 *
605 * Creates a new #graphene_simd4f_t vector where each
606 * component is the division of the respective components
607 * in @a and @b.
608 *
609 * |[<!-- lanugage="plain" -->
610 * {
611 * .x = a.x / b.x,
612 * .y = a.y / b.y,
613 * .z = a.z / b.z,
614 * .w = a.w / b.w
615 * }
616 * ]|
617 *
618 * Returns: the division vector
619 *
620 * Since: 1.0
621 */
622graphene_simd4f_t
623(graphene_simd4f_div) (const graphene_simd4f_t a,
624 const graphene_simd4f_t b)
625{
626 return graphene_simd4f_div (a, b);
627}
628
629/**
630 * graphene_simd4f_cross3:
631 * @a: a #graphene_simd4f_t
632 * @b: a #graphene_simd4f_t
633 *
634 * Creates a new #graphene_simd4f_t vector where each
635 * component contains the 3-way cross product of the
636 * given @a and @b vectors.
637 *
638 * Returns: the cross3 vector
639 *
640 * Since: 1.0
641 */
642graphene_simd4f_t
643(graphene_simd4f_cross3) (const graphene_simd4f_t a,
644 const graphene_simd4f_t b)
645{
646 return graphene_simd4f_cross3 (a, b);
647}
648
649/**
650 * graphene_simd4f_dot3:
651 * @a: a #graphene_simd4f_t
652 * @b: a #graphene_simd4f_t
653 *
654 * Computes the dot product of the first three components of the
655 * two given #graphene_simd4f_t.
656 *
657 * Returns: a vector whose components are all set to the
658 * dot product of the components of the two operands
659 *
660 * Since: 1.0
661 */
662graphene_simd4f_t
663(graphene_simd4f_dot3) (const graphene_simd4f_t a,
664 const graphene_simd4f_t b)
665{
666 return graphene_simd4f_dot3 (a, b);
667}
668
669/**
670 * graphene_simd4f_dot3_scalar:
671 * @a: a #graphene_simd4f_t
672 * @b: a #graphene_simd4f_t
673 *
674 * Computes the dot product of the first three components of the
675 * two given #graphene_simd4f_t.
676 *
677 * Returns: the dot product of the two vectors, as a scalar value.
678 *
679 * Since: 1.4
680 */
681float
682(graphene_simd4f_dot3_scalar) (const graphene_simd4f_t a,
683 const graphene_simd4f_t b)
684{
685 return graphene_simd4f_dot3_scalar (a, b);
686}
687
688/**
689 * graphene_simd4f_min:
690 * @a: a #graphene_simd4f_t
691 * @b: a #graphene_simd4f_t
692 *
693 * Creates a new #graphene_simd4f_t that contains the
694 * minimum value of each component of @a and @b.
695 *
696 * Returns: the new minimum vector
697 *
698 * Since: 1.0
699 */
700graphene_simd4f_t
701(graphene_simd4f_min) (const graphene_simd4f_t a,
702 const graphene_simd4f_t b)
703{
704 return graphene_simd4f_min (a, b);
705}
706
707/**
708 * graphene_simd4f_max:
709 * @a: a #graphene_simd4f_t
710 * @b: a #graphene_simd4f_t
711 *
712 * Creates a new #graphene_simd4f_t that contains the
713 * maximum value of each component of @a and @b.
714 *
715 * Returns: the new maximum vector
716 *
717 * Since: 1.0
718 */
719graphene_simd4f_t
720(graphene_simd4f_max) (const graphene_simd4f_t a,
721 const graphene_simd4f_t b)
722{
723 return graphene_simd4f_max (a, b);
724}
725
726/**
727 * graphene_simd4f_shuffle_wxyz:
728 * @s: a #graphene_simd4f_t
729 *
730 * Creates a new #graphene_simd4f_t that contains the
731 * re-ordered values of the W, X, Y, and Z components
732 * of @s.
733 *
734 * Returns: the new vector
735 *
736 * Since: 1.0
737 */
738graphene_simd4f_t
739(graphene_simd4f_shuffle_wxyz) (const graphene_simd4f_t s)
740{
741 return graphene_simd4f_shuffle_wxyz (s);
742}
743
744/**
745 * graphene_simd4f_shuffle_zwxy:
746 * @s: a #graphene_simd4f_t
747 *
748 * Creates a new #graphene_simd4f_t that contains the
749 * re-ordered values of the Z, W, X, and Y components
750 * of @s.
751 *
752 * Returns: the new vector
753 *
754 * Since: 1.0
755 */
756graphene_simd4f_t
757(graphene_simd4f_shuffle_zwxy) (const graphene_simd4f_t s)
758{
759 return graphene_simd4f_shuffle_zwxy (s);
760}
761
762/**
763 * graphene_simd4f_shuffle_yzwx:
764 * @s: a #graphene_simd4f_t
765 *
766 * Creates a new #graphene_simd4f_t that contains the
767 * re-ordered values of the Y, Z, W, and X components
768 * of @s.
769 *
770 * Returns: the new vector
771 *
772 * Since: 1.0
773 */
774graphene_simd4f_t
775(graphene_simd4f_shuffle_yzwx) (const graphene_simd4f_t s)
776{
777 return graphene_simd4f_shuffle_yzwx (s);
778}
779
780/**
781 * graphene_simd4f_zero_w:
782 * @s: a #graphene_simd4f_t
783 *
784 * Creates a new #graphene_simd4f_t that contains the
785 * same values of the given @s vector, except for the
786 * W component, which is set to 0.
787 *
788 * Returns: the new vector
789 *
790 * Since: 1.0
791 */
792graphene_simd4f_t
793(graphene_simd4f_zero_w) (const graphene_simd4f_t s)
794{
795 return graphene_simd4f_zero_w (s);
796}
797
798/**
799 * graphene_simd4f_zero_zw:
800 * @s: a #graphene_simd4f_t
801 *
802 * Creates a new #graphene_simd4f_t that contains the
803 * same values of the given @s vector, except for the
804 * Z and W components, which are set to 0.
805 *
806 * Returns: the new vector
807 *
808 * Since: 1.0
809 */
810graphene_simd4f_t
811(graphene_simd4f_zero_zw) (const graphene_simd4f_t s)
812{
813 return graphene_simd4f_zero_zw (s);
814}
815
816/**
817 * graphene_simd4f_merge_w:
818 * @s: a #graphene_simd4f_t
819 * @v: the new value of the W component
820 *
821 * Creates a new #graphene_simd4f_t that contains the
822 * same values of the given @s vector, except for the
823 * W component, which is set to @v.
824 *
825 * Returns: the new vector
826 *
827 * Since: 1.0
828 */
829graphene_simd4f_t
830(graphene_simd4f_merge_w) (const graphene_simd4f_t s,
831 float v)
832{
833 return graphene_simd4f_merge_w (s, v);
834}
835
836/**
837 * graphene_simd4f_merge_high:
838 * @a: a #graphene_simd4f_t
839 * @b: a #graphene_simd4f_t
840 *
841 * Creates a new #graphene_simd4f_t that contains the
842 * last two components of the vector @a and the last
843 * two components of the vector @b.
844 *
845 * Returns: the new vector
846 *
847 * Since: 1.0
848 */
849graphene_simd4f_t
850(graphene_simd4f_merge_high) (const graphene_simd4f_t a,
851 const graphene_simd4f_t b)
852{
853 return graphene_simd4f_merge_high (a, b);
854}
855
856/**
857 * graphene_simd4f_merge_low:
858 * @a: a #graphene_simd4f_t
859 * @b: a #graphene_simd4f_t
860 *
861 * Creates a new #graphene_simd4f_t that contains the
862 * first two components of the vector @a and the first
863 * two components of the vector @b.
864 *
865 * Returns: the new vector
866 *
867 * Since: 1.0
868 */
869graphene_simd4f_t
870(graphene_simd4f_merge_low) (const graphene_simd4f_t a,
871 const graphene_simd4f_t b)
872{
873 return graphene_simd4f_merge_low (a, b);
874}
875
876/**
877 * graphene_simd4f_flip_sign_0101:
878 * @s: a #graphene_simd4f_t
879 *
880 * Flips the signs of the second and fourth components of
881 * the given vector @s.
882 *
883 * Returns: the new vector, with the changed signs
884 *
885 * Since: 1.0
886 */
887graphene_simd4f_t
888(graphene_simd4f_flip_sign_0101) (const graphene_simd4f_t s)
889{
890 return graphene_simd4f_flip_sign_0101 (s);
891}
892
893/**
894 * graphene_simd4f_flip_sign_1010:
895 * @s: a #graphene_simd4f_t
896 *
897 * Flips the signs of the first and third components of
898 * the given vector @s.
899 *
900 * Returns: the new vector, with the changed signs
901 *
902 * Since: 1.0
903 */
904graphene_simd4f_t
905(graphene_simd4f_flip_sign_1010) (const graphene_simd4f_t s)
906{
907 return graphene_simd4f_flip_sign_1010 (s);
908}
909
910/**
911 * graphene_simd4f_cmp_eq:
912 * @a: a #graphene_simd4f_t
913 * @b: a #graphene_simd4f_t
914 *
915 * Checks if the two given #graphene_simd4f_t are equal.
916 *
917 * Returns: `true` if the values of the vectors are equal
918 *
919 * Since: 1.0
920 */
921bool
922(graphene_simd4f_cmp_eq) (const graphene_simd4f_t a,
923 const graphene_simd4f_t b)
924{
925 return graphene_simd4f_cmp_eq (a, b);
926}
927
928/**
929 * graphene_simd4f_cmp_neq:
930 * @a: a #graphene_simd4f_t
931 * @b: a #graphene_simd4f_t
932 *
933 * Checks if the two given #graphene_simd4f_t are not equal.
934 *
935 * Returns: `true` if the values of the vectors are not equal
936 *
937 * Since: 1.0
938 */
939bool
940(graphene_simd4f_cmp_neq) (const graphene_simd4f_t a,
941 const graphene_simd4f_t b)
942{
943 return graphene_simd4f_cmp_neq (a, b);
944}
945
946/**
947 * graphene_simd4f_cmp_lt:
948 * @a: a #graphene_simd4f_t
949 * @b: a #graphene_simd4f_t
950 *
951 * Compares two #graphene_simd4f_t and checks if all components
952 * of the vector @a are less than the respective components of
953 * the vector @b.
954 *
955 * Returns: `true` if vector @a is less than @b
956 *
957 * Since: 1.2
958 */
959bool
960(graphene_simd4f_cmp_lt) (const graphene_simd4f_t a,
961 const graphene_simd4f_t b)
962{
963 return graphene_simd4f_cmp_lt (a, b);
964}
965
966/**
967 * graphene_simd4f_cmp_le:
968 * @a: a #graphene_simd4f_t
969 * @b: a #graphene_simd4f_t
970 *
971 * Compares two #graphene_simd4f_t and checks if all components
972 * of the vector @a are less than or equal to the respective components
973 * of the vector @b.
974 *
975 * Returns: `true` if vector @a is less than or equal to @b
976 *
977 * Since: 1.2
978 */
979bool
980(graphene_simd4f_cmp_le) (const graphene_simd4f_t a,
981 const graphene_simd4f_t b)
982{
983 return graphene_simd4f_cmp_le (a, b);
984}
985
986/**
987 * graphene_simd4f_cmp_ge:
988 * @a: a #graphene_simd4f_t
989 * @b: a #graphene_simd4f_t
990 *
991 * Compares two #graphene_simd4f_t and checks if all components
992 * of the vector @a are greater than or equal to the respective
993 * components of the vector @b.
994 *
995 * Returns: `true` if vector @a is greater than or equal to @b
996 *
997 * Since: 1.0
998 */
999bool
1000(graphene_simd4f_cmp_ge) (const graphene_simd4f_t a,
1001 const graphene_simd4f_t b)
1002{
1003 return graphene_simd4f_cmp_ge (a, b);
1004}
1005
1006/**
1007 * graphene_simd4f_cmp_gt:
1008 * @a: a #graphene_simd4f_t
1009 * @b: a #graphene_simd4f_t
1010 *
1011 * Compares two #graphene_simd4f_t and checks if all components
1012 * of the vector @a are greater than the respective components of
1013 * the vector @b.
1014 *
1015 * Returns: `true` if vector @a is greater than @b
1016 *
1017 * Since: 1.0
1018 */
1019bool
1020(graphene_simd4f_cmp_gt) (const graphene_simd4f_t a,
1021 const graphene_simd4f_t b)
1022{
1023 return graphene_simd4f_cmp_gt (a, b);
1024}
1025
1026/**
1027 * graphene_simd4f_neg:
1028 * @s: a #graphene_simd4f_t
1029 *
1030 * Negates the values of @s.
1031 *
1032 * Returns: the negated vector
1033 *
1034 * Since: 1.0
1035 */
1036graphene_simd4f_t
1037(graphene_simd4f_neg) (const graphene_simd4f_t s)
1038{
1039 return graphene_simd4f_neg (s);
1040}
1041
1042#else /* GRAPHENE_USE_SCALAR */
1043
1044graphene_simd4f_t
1045(graphene_simd4f_init) (float x,
1046 float y,
1047 float z,
1048 float w)
1049{
1050 graphene_simd4f_t s = { x, y, z, w };
1051 return s;
1052}
1053
1054graphene_simd4f_t
1055(graphene_simd4f_init_zero) (void)
1056{
1057 return graphene_simd4f_init (0.f, 0.f, 0.f, 0.f);
1058}
1059
1060graphene_simd4f_t
1061(graphene_simd4f_init_4f) (const float *v)
1062{
1063 return graphene_simd4f_init (v[0], v[1], v[2], v[3]);
1064}
1065
1066graphene_simd4f_t
1067(graphene_simd4f_init_3f) (const float *v)
1068{
1069 return graphene_simd4f_init (v[0], v[1], v[2], 0.f);
1070}
1071
1072graphene_simd4f_t
1073(graphene_simd4f_init_2f) (const float *v)
1074{
1075 return graphene_simd4f_init (v[0], v[1], 0.f, 0.f);
1076}
1077
1078void
1079(graphene_simd4f_dup_4f) (const graphene_simd4f_t s,
1080 float *v)
1081{
1082 memcpy (v, &s, sizeof (float) * 4);
1083}
1084
1085void
1086(graphene_simd4f_dup_3f) (const graphene_simd4f_t s,
1087 float *v)
1088{
1089 memcpy (v, &s, sizeof (float) * 3);
1090}
1091
1092void
1093(graphene_simd4f_dup_2f) (const graphene_simd4f_t s,
1094 float *v)
1095{
1096 memcpy (v, &s, sizeof (float) * 2);
1097}
1098
1099float
1100(graphene_simd4f_get) (const graphene_simd4f_t s,
1101 unsigned int i)
1102{
1103 switch (i)
1104 {
1105 case 0:
1106 return s.x;
1107 case 1:
1108 return s.y;
1109 case 2:
1110 return s.z;
1111 case 3:
1112 return s.w;
1113 }
1114
1115 return 0;
1116}
1117
1118float
1119(graphene_simd4f_get_x) (const graphene_simd4f_t s)
1120{
1121 return s.x;
1122}
1123
1124float
1125(graphene_simd4f_get_y) (const graphene_simd4f_t s)
1126{
1127 return s.y;
1128}
1129
1130float
1131(graphene_simd4f_get_z) (const graphene_simd4f_t s)
1132{
1133 return s.z;
1134}
1135
1136float
1137(graphene_simd4f_get_w) (const graphene_simd4f_t s)
1138{
1139 return s.w;
1140}
1141
1142graphene_simd4f_t
1143(graphene_simd4f_splat) (float v)
1144{
1145 graphene_simd4f_t s = { v, v, v, v };
1146 return s;
1147}
1148
1149graphene_simd4f_t
1150(graphene_simd4f_splat_x) (graphene_simd4f_t v)
1151{
1152 graphene_simd4f_t s = { v.x, v.x, v.x, v.x };
1153 return s;
1154}
1155
1156graphene_simd4f_t
1157(graphene_simd4f_splat_y) (graphene_simd4f_t v)
1158{
1159 graphene_simd4f_t s = { v.y, v.y, v.y, v.y };
1160 return s;
1161}
1162
1163graphene_simd4f_t
1164(graphene_simd4f_splat_z) (graphene_simd4f_t v)
1165{
1166 graphene_simd4f_t s = { v.z, v.z, v.z, v.z };
1167 return s;
1168}
1169
1170graphene_simd4f_t
1171(graphene_simd4f_splat_w) (graphene_simd4f_t v)
1172{
1173 graphene_simd4f_t s = { v.w, v.w, v.w, v.w };
1174 return s;
1175}
1176
1177graphene_simd4f_t
1178(graphene_simd4f_reciprocal) (graphene_simd4f_t v)
1179{
1180 graphene_simd4f_t s = {
1181 fabsf (v.x) > FLT_EPSILON ? 1.0f / v.x : 0.f,
1182 fabsf (v.y) > FLT_EPSILON ? 1.0f / v.y : 0.f,
1183 fabsf (v.z) > FLT_EPSILON ? 1.0f / v.z : 0.f,
1184 fabsf (v.w) > FLT_EPSILON ? 1.0f / v.w : 0.f
1185 };
1186 return s;
1187}
1188
1189graphene_simd4f_t
1190(graphene_simd4f_sqrt) (graphene_simd4f_t v)
1191{
1192 graphene_simd4f_t s = {
1193 sqrtf (v.x),
1194 sqrtf (v.y),
1195 sqrtf (v.z),
1196 sqrtf (v.w)
1197 };
1198 return s;
1199}
1200
1201graphene_simd4f_t
1202(graphene_simd4f_rsqrt) (graphene_simd4f_t v)
1203{
1204 graphene_simd4f_t s = {
1205 fabsf (v.x) > FLT_EPSILON ? 1.0f / sqrtf (v.x) : 0.f,
1206 fabsf (v.y) > FLT_EPSILON ? 1.0f / sqrtf (v.y) : 0.f,
1207 fabsf (v.z) > FLT_EPSILON ? 1.0f / sqrtf (v.z) : 0.f,
1208 fabsf (v.w) > FLT_EPSILON ? 1.0f / sqrtf (v.w) : 0.f
1209 };
1210 return s;
1211}
1212
1213graphene_simd4f_t
1214(graphene_simd4f_add) (const graphene_simd4f_t a,
1215 const graphene_simd4f_t b)
1216{
1217 graphene_simd4f_t s = {
1218 a.x + b.x,
1219 a.y + b.y,
1220 a.z + b.z,
1221 a.w + b.w
1222 };
1223 return s;
1224}
1225
1226graphene_simd4f_t
1227(graphene_simd4f_sub) (const graphene_simd4f_t a,
1228 const graphene_simd4f_t b)
1229{
1230 graphene_simd4f_t s = {
1231 a.x - b.x,
1232 a.y - b.y,
1233 a.z - b.z,
1234 a.w - b.w
1235 };
1236 return s;
1237}
1238
1239graphene_simd4f_t
1240(graphene_simd4f_mul) (const graphene_simd4f_t a,
1241 const graphene_simd4f_t b)
1242{
1243 graphene_simd4f_t s = {
1244 a.x * b.x,
1245 a.y * b.y,
1246 a.z * b.z,
1247 a.w * b.w
1248 };
1249 return s;
1250}
1251
1252graphene_simd4f_t
1253(graphene_simd4f_div) (const graphene_simd4f_t a,
1254 const graphene_simd4f_t b)
1255{
1256 graphene_simd4f_t s = {
1257 fabsf (b.x) > FLT_EPSILON ? a.x / b.x : 0.f,
1258 fabsf (b.y) > FLT_EPSILON ? a.y / b.y : 0.f,
1259 fabsf (b.z) > FLT_EPSILON ? a.z / b.z : 0.f,
1260 fabsf (b.w) > FLT_EPSILON ? a.w / b.w : 0.f
1261 };
1262 return s;
1263}
1264
1265graphene_simd4f_t
1266(graphene_simd4f_cross3) (const graphene_simd4f_t a,
1267 const graphene_simd4f_t b)
1268{
1269 return graphene_simd4f_init (a.y * b.z - a.z * b.y,
1270 a.z * b.x - a.x * b.z,
1271 a.x * b.y - a.y * b.x,
1272 0.f);
1273}
1274
1275graphene_simd4f_t
1276(graphene_simd4f_dot3) (const graphene_simd4f_t a,
1277 const graphene_simd4f_t b)
1278{
1279 return graphene_simd4f_splat (graphene_simd4f_dot3_scalar (a, b));
1280}
1281
1282float
1283(graphene_simd4f_dot3_scalar) (const graphene_simd4f_t a,
1284 const graphene_simd4f_t b)
1285{
1286 return a.x * b.x + a.y * b.y + a.z * b.z;
1287}
1288
1289graphene_simd4f_t
1290(graphene_simd4f_min) (const graphene_simd4f_t a,
1291 const graphene_simd4f_t b)
1292{
1293 return graphene_simd4f_init (a.x < b.x ? a.x : b.x,
1294 a.y < b.y ? a.y : b.y,
1295 a.z < b.z ? a.z : b.z,
1296 a.w < b.w ? a.w : b.w);
1297}
1298
1299graphene_simd4f_t
1300(graphene_simd4f_max) (const graphene_simd4f_t a,
1301 const graphene_simd4f_t b)
1302{
1303 return graphene_simd4f_init (a.x > b.x ? a.x : b.x,
1304 a.y > b.y ? a.y : b.y,
1305 a.z > b.z ? a.z : b.z,
1306 a.w > b.w ? a.w : b.w);
1307}
1308
1309graphene_simd4f_t
1310(graphene_simd4f_shuffle_wxyz) (const graphene_simd4f_t s)
1311{
1312 return graphene_simd4f_init (s.w, s.x, s.y, s.z);
1313}
1314
1315graphene_simd4f_t
1316(graphene_simd4f_shuffle_zwxy) (const graphene_simd4f_t s)
1317{
1318 return graphene_simd4f_init (s.z, s.w, s.x, s.y);
1319}
1320
1321graphene_simd4f_t
1322(graphene_simd4f_shuffle_yzwx) (const graphene_simd4f_t s)
1323{
1324 return graphene_simd4f_init (s.y, s.z, s.w, s.x);
1325}
1326
1327graphene_simd4f_t
1328(graphene_simd4f_zero_w) (const graphene_simd4f_t s)
1329{
1330 return graphene_simd4f_init (s.x, s.y, s.z, 0.0f);
1331}
1332
1333graphene_simd4f_t
1334(graphene_simd4f_zero_zw) (const graphene_simd4f_t s)
1335{
1336 return graphene_simd4f_init (s.x, s.y, 0.0f, 0.0f);
1337}
1338
1339graphene_simd4f_t
1340(graphene_simd4f_merge_w) (const graphene_simd4f_t s,
1341 float v)
1342{
1343 return graphene_simd4f_init (s.x, s.y, s.z, v);
1344}
1345
1346graphene_simd4f_t
1347(graphene_simd4f_merge_high) (const graphene_simd4f_t a,
1348 const graphene_simd4f_t b)
1349{
1350 return graphene_simd4f_init (a.z, a.w, b.z, b.w);
1351}
1352
1353graphene_simd4f_t
1354(graphene_simd4f_merge_low) (const graphene_simd4f_t a,
1355 const graphene_simd4f_t b)
1356{
1357 return graphene_simd4f_init (a.x, a.y, b.x, b.y);
1358}
1359
1360graphene_simd4f_t
1361(graphene_simd4f_flip_sign_0101) (const graphene_simd4f_t s)
1362{
1363 return graphene_simd4f_init (s.x, -s.y, s.z, -s.w);
1364}
1365
1366graphene_simd4f_t
1367(graphene_simd4f_flip_sign_1010) (const graphene_simd4f_t s)
1368{
1369 return graphene_simd4f_init (-s.x, s.y, -s.z, s.w);
1370}
1371
1372static inline bool
1373approx_equal (float a,
1374 float b,
1375 float epsilon)
1376{
1377#ifdef HAVE_ISINFF
1378 if (isinff (a) && isinff (b))
1379 return true;
1380#else
1381 if (fpclassify (a) == FP_INFINITE && fpclassify (b) == FP_INFINITE)
1382 return true;
1383#endif
1384
1385 float diff = fabsf (a - b);
1386 if (isnan (diff))
1387 return true;
1388
1389 if (diff <= epsilon)
1390 return true;
1391
1392 float abs_a = fabsf (a);
1393 float abs_b = fabsf (b);
1394
1395 float largest = abs_b > abs_a ? abs_b : abs_a;
1396
1397 return diff <= largest * epsilon;
1398}
1399
1400bool
1401(graphene_simd4f_cmp_eq) (const graphene_simd4f_t a,
1402 const graphene_simd4f_t b)
1403{
1404 return approx_equal (a.x, b.x, FLT_EPSILON) &&
1405 approx_equal (a.y, b.y, FLT_EPSILON) &&
1406 approx_equal (a.z, b.z, FLT_EPSILON) &&
1407 approx_equal (a.w, b.w, FLT_EPSILON);
1408}
1409
1410bool
1411(graphene_simd4f_cmp_neq) (const graphene_simd4f_t a,
1412 const graphene_simd4f_t b)
1413{
1414 return !approx_equal (a.x, b.x, FLT_EPSILON) ||
1415 !approx_equal (a.y, b.y, FLT_EPSILON) ||
1416 !approx_equal (a.z, b.z, FLT_EPSILON) ||
1417 !approx_equal (a.w, b.w, FLT_EPSILON);
1418}
1419
1420bool
1421(graphene_simd4f_cmp_lt) (const graphene_simd4f_t a,
1422 const graphene_simd4f_t b)
1423{
1424 return a.x < b.x &&
1425 a.y < b.y &&
1426 a.z < b.z &&
1427 a.w < b.w;
1428}
1429
1430bool
1431(graphene_simd4f_cmp_le) (const graphene_simd4f_t a,
1432 const graphene_simd4f_t b)
1433{
1434 return a.x <= b.x &&
1435 a.y <= b.y &&
1436 a.z <= b.z &&
1437 a.w <= b.w;
1438}
1439
1440bool
1441(graphene_simd4f_cmp_ge) (const graphene_simd4f_t a,
1442 const graphene_simd4f_t b)
1443{
1444 return a.x >= b.x &&
1445 a.y >= b.y &&
1446 a.z >= b.z &&
1447 a.w >= b.w;
1448}
1449
1450bool
1451(graphene_simd4f_cmp_gt) (const graphene_simd4f_t a,
1452 const graphene_simd4f_t b)
1453{
1454 return a.x > b.x &&
1455 a.y > b.y &&
1456 a.z > b.z &&
1457 a.w > b.w;
1458}
1459
1460graphene_simd4f_t
1461(graphene_simd4f_neg) (const graphene_simd4f_t s)
1462{
1463 return graphene_simd4f_init (-s.x, -s.y, -s.z, -s.w);
1464}
1465
1466#endif /* GRAPHENE_USE_SCALAR */
1467

source code of gtk/subprojects/graphene/src/graphene-simd4f.c