1 | /* graphene-private.h: Private header |
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 | #pragma once |
27 | |
28 | #include "config.h" |
29 | #ifdef HAVE_INIT_ONCE |
30 | #define _WIN32_WINNT 0x0600 |
31 | #include <windows.h> |
32 | #endif |
33 | #include "graphene-macros.h" |
34 | #include <stdlib.h> |
35 | #include <math.h> |
36 | #include <float.h> |
37 | |
38 | #define GRAPHENE_FLOAT_EPSILON FLT_EPSILON |
39 | |
40 | #ifndef MIN |
41 | # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) |
42 | # define MIN(a,b) \ |
43 | __extension__({ \ |
44 | __auto_type _a = (a); \ |
45 | __auto_type _b = (b); \ |
46 | _a < _b ? _a : _b; \ |
47 | }) |
48 | # else |
49 | # define MIN(a,b) ((a) < (b) ? (a) : (b)) |
50 | # endif |
51 | #endif |
52 | |
53 | #ifndef MAX |
54 | # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) |
55 | # define MAX(a,b) \ |
56 | __extension__({ \ |
57 | __auto_type _a = (a); \ |
58 | __auto_type _b = (b); \ |
59 | _a > _b ? _a : _b; \ |
60 | }) |
61 | # else |
62 | # define MAX(a,b) ((a) > (b) ? (a) : (b)) |
63 | # endif |
64 | #endif |
65 | |
66 | #ifndef CLAMP |
67 | # if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) |
68 | # define CLAMP(v,min,max) \ |
69 | __extension__({ \ |
70 | __auto_type _v = (v); \ |
71 | __auto_type _min = (min); \ |
72 | __auto_type _max = (max); \ |
73 | _v < _min ? _min : (_v > _max ? _max : _v); \ |
74 | }) |
75 | # else |
76 | # define CLAMP(v,min,max) ((v) < (min) ? (min) : ((v) > (max) ? (max) : (v))) |
77 | # endif |
78 | #endif |
79 | |
80 | #if defined(__GNUC__) && __GNUC__ > 3 |
81 | # define likely(x) (__builtin_expect((x) ? 1 : 0, 1)) |
82 | # define unlikely(x) (__builtin_expect((x) ? 1 : 0, 0)) |
83 | #else |
84 | # define likely(x) (x) |
85 | # define unlikely(x) (x) |
86 | #endif |
87 | |
88 | #define GRAPHENE_DEG_TO_RAD(x) ((x) * (GRAPHENE_PI / 180.f)) |
89 | #define GRAPHENE_RAD_TO_DEG(x) ((x) * (180.f / GRAPHENE_PI)) |
90 | |
91 | #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) |
92 | /* Use typeof on GCC */ |
93 | # define graphene_fuzzy_equals(n1,n2,epsilon) \ |
94 | __extension__({ \ |
95 | __auto_type _n1 = (n1); \ |
96 | __auto_type _n2 = (n2); \ |
97 | __auto_type _epsilon = (epsilon); \ |
98 | (bool) ((_n1 > _n2 ? (_n1 - _n2) : (_n2 - _n1)) < _epsilon); \ |
99 | }) |
100 | |
101 | #else |
102 | /* fallback for Visual Studio, typeof not supported */ |
103 | # define graphene_fuzzy_equals(n1,n2,epsilon) \ |
104 | (((n1) > (n2) ? ((n1) - (n2)) : ((n2) - (n1))) < (epsilon)) |
105 | |
106 | #endif /* __GNUC__ */ |
107 | |
108 | static inline bool |
109 | graphene_approx_val (float a, float b) |
110 | { |
111 | return graphene_fuzzy_equals (a, b, FLT_EPSILON); |
112 | } |
113 | |
114 | static inline float |
115 | graphene_flerpf (float a, float b, double factor) |
116 | { |
117 | return (float) (((1.0 - factor) * (double) a) + (factor * (double) b)); |
118 | } |
119 | |
120 | static inline double |
121 | graphene_flerp (double a, double b, double factor) |
122 | { |
123 | return ((1.0 - factor) * a) + (factor * b); |
124 | } |
125 | |
126 | static inline int |
127 | graphene_ilerp (int a, int b, double factor) |
128 | { |
129 | return (int) (((1.0 - factor) * (double) a) + (factor * (double) b)); |
130 | } |
131 | |
132 | #if defined(__GNUC__) && \ |
133 | ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) && \ |
134 | (__STDC_VERSION__ >= 201112L || !defined(__STRICT_ANSI__)) && \ |
135 | !defined(__cplusplus) |
136 | # define USE_C11_GENERIC 1 |
137 | #endif |
138 | |
139 | #ifdef USE_C11_GENERIC |
140 | # define graphene_lerp(a,b,f) \ |
141 | _Generic((a), \ |
142 | double: graphene_flerp, \ |
143 | float: graphene_flerpf, \ |
144 | int: graphene_ilerp, \ |
145 | default: graphene_flerp) ((a), (b), (f)) |
146 | |
147 | #else |
148 | # define graphene_lerp graphene_flerpf |
149 | #endif |
150 | |
151 | static inline void |
152 | graphene_sincos (float angle, float *sin_out, float *cos_out) |
153 | { |
154 | #ifdef HAVE_SINCOSF |
155 | sincosf (x: angle, sinx: sin_out, cosx: cos_out); |
156 | #else |
157 | if (sin_out != NULL) |
158 | *sin_out = sinf (angle); |
159 | if (cos_out != NULL) |
160 | *cos_out = cosf (angle); |
161 | #endif /* HAVE_SINCOSF */ |
162 | } |
163 | |
164 | typedef bool (* graphene_compare_func_t) (const void *p1, const void *p2); |
165 | |
166 | static inline bool |
167 | graphene_pointer_equal (const void *p1, |
168 | const void *p2, |
169 | graphene_compare_func_t func) |
170 | { |
171 | if (p1 == p2) |
172 | return true; |
173 | |
174 | if (p1 == NULL || p2 == NULL) |
175 | return false; |
176 | |
177 | if (func == NULL) |
178 | return true; |
179 | |
180 | return func (p1, p2); |
181 | } |
182 | |