Nuklear
This is a minimal-state, immediate-mode graphical user interface toolkit written in ANSI C and licensed under public domain. It was designed as a simple embeddable user interface for application and does not have any dependencies, a default render backend or OS window/input handling but instead provides a highly modular, library-based approach, with simple input state for input and draw commands describing primitive shapes as output. So instead of providing a layered library that tries to abstract over a number of platform and render backends, it focuses only on the actual UI.
 
Loading...
Searching...
No Matches
nuklear_math.c
1#include "nuklear.h"
2#include "nuklear_internal.h"
3
4/* ===============================================================
5 *
6 * MATH
7 *
8 * ===============================================================*/
9/*/// ### Math
36*/
37#ifdef NK_INV_SQRT_NEEDED
38NK_LIB float
39nk_inv_sqrt(float n)
40{
41 float x2;
42 const float threehalfs = 1.5f;
43 union {nk_uint i; float f;} conv = {0};
44 conv.f = n;
45 x2 = n * 0.5f;
46 conv.i = 0x5f375A84 - (conv.i >> 1);
47 conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
48 return conv.f;
49}
50#endif
51#ifdef NK_SIN_NEEDED
52NK_LIB float
53nk_sin(float x)
54{
55 NK_STORAGE const float a0 = +1.91059300966915117e-31f;
56 NK_STORAGE const float a1 = +1.00086760103908896f;
57 NK_STORAGE const float a2 = -1.21276126894734565e-2f;
58 NK_STORAGE const float a3 = -1.38078780785773762e-1f;
59 NK_STORAGE const float a4 = -2.67353392911981221e-2f;
60 NK_STORAGE const float a5 = +2.08026600266304389e-2f;
61 NK_STORAGE const float a6 = -3.03996055049204407e-3f;
62 NK_STORAGE const float a7 = +1.38235642404333740e-4f;
63 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
64}
65#endif
66#ifdef NK_COS_NEEDED
67NK_LIB float
68nk_cos(float x)
69{
70 /* New implementation. Also generated using lolremez. */
71 /* Old version significantly deviated from expected results. */
72 NK_STORAGE const float a0 = 9.9995999154986614e-1f;
73 NK_STORAGE const float a1 = 1.2548995793001028e-3f;
74 NK_STORAGE const float a2 = -5.0648546280678015e-1f;
75 NK_STORAGE const float a3 = 1.2942246466519995e-2f;
76 NK_STORAGE const float a4 = 2.8668384702547972e-2f;
77 NK_STORAGE const float a5 = 7.3726485210586547e-3f;
78 NK_STORAGE const float a6 = -3.8510875386947414e-3f;
79 NK_STORAGE const float a7 = 4.7196604604366623e-4f;
80 NK_STORAGE const float a8 = -1.8776444013090451e-5f;
81 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*(a7 + x*a8)))))));
82}
83#endif
84#ifdef NK_ATAN_NEEDED
85NK_LIB float
86nk_atan(float x)
87{
88 /* ./lolremez --progress --float -d 9 -r "0:pi*2" "atan(x)" */
89 float u = -1.0989005e-05f;
90 NK_ASSERT(x >= 0.0f && "TODO support negative floats");
91 u = u * x + 0.00034117949f;
92 u = u * x + -0.0044932296f;
93 u = u * x + 0.032596264f;
94 u = u * x + -0.14088021f;
95 u = u * x + 0.36040401f;
96 u = u * x + -0.47017866f;
97 u = u * x + 0.00050198776f;
98 u = u * x + 1.0077682f;
99 u = u * x + -0.0004765437f;
100 return u;
101}
102#endif
103#ifdef NK_ATAN2_NEEDED
104NK_LIB float
105nk_atan2(float y, float x)
106{
107 float ax = NK_ABS(x),
108 ay = NK_ABS(y);
109 /* 0 = +y +x 1 = -y +x
110 2 = +y -x 3 = -y -x */
111 nk_uint signs = (y < 0) | ((x < 0) << 1);
112
113 float a;
114 if(y == 0.0 && x == 0.0) return 0.0f;
115 a = (ay > ax)
116 ? NK_PI_HALF - NK_ATAN(ax / ay)
117 : NK_ATAN(ay / ax);
118
119 switch(signs){
120 case 0: return a;
121 case 1: return -a;
122 case 2: return -a + NK_PI;
123 case 3: return a - NK_PI;
124 }
125 return 0.0f; /* prevents warning */
126}
127#endif
128NK_LIB nk_uint
129nk_round_up_pow2(nk_uint v)
130{
131 v--;
132 v |= v >> 1;
133 v |= v >> 2;
134 v |= v >> 4;
135 v |= v >> 8;
136 v |= v >> 16;
137 v++;
138 return v;
139}
140#ifdef NK_DTOA_NEEDED
141NK_LIB double
142nk_pow(double x, int n)
143{
144 /* check the sign of n */
145 double r = 1;
146 int plus = n >= 0;
147 n = (plus) ? n : -n;
148 while (n > 0) {
149 if ((n & 1) == 1)
150 r *= x;
151 n /= 2;
152 x *= x;
153 }
154 return plus ? r : 1.0 / r;
155}
156#endif
157#ifdef NK_DTOA_NEEDED
158NK_LIB int
159nk_ifloord(double x)
160{
161 x = (double)((int)x - ((x < 0.0) ? 1 : 0));
162 return (int)x;
163}
164#endif
165NK_LIB int
166nk_ifloorf(float x)
167{
168 x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
169 return (int)x;
170}
171NK_LIB int
172nk_iceilf(float x)
173{
174 if (x >= 0) {
175 int i = (int)x;
176 return (x > i) ? i+1: i;
177 } else {
178 int t = (int)x;
179 float r = x - (float)t;
180 return (r > 0.0f) ? t+1: t;
181 }
182}
183#ifdef NK_DTOA_NEEDED
184NK_LIB int
185nk_log10(double n)
186{
187 int neg;
188 int ret;
189 int exp = 0;
190
191 neg = (n < 0) ? 1 : 0;
192 ret = (neg) ? (int)-n : (int)n;
193 while ((ret / 10) > 0) {
194 ret /= 10;
195 exp++;
196 }
197 if (neg) exp = -exp;
198 return exp;
199}
200#endif
201NK_LIB float
202nk_roundf(float x)
203{
204 return (x >= 0.0f) ? (float)nk_ifloorf(x + 0.5f) : (float)nk_iceilf(x - 0.5f);
205}
206NK_API struct nk_rect
207nk_get_null_rect(void)
208{
209 return nk_null_rect;
210}
211NK_API struct nk_rect
212nk_rect(float x, float y, float w, float h)
213{
214 struct nk_rect r;
215 r.x = x; r.y = y;
216 r.w = w; r.h = h;
217 return r;
218}
219NK_API struct nk_rect
220nk_recti(int x, int y, int w, int h)
221{
222 struct nk_rect r;
223 r.x = (float)x;
224 r.y = (float)y;
225 r.w = (float)w;
226 r.h = (float)h;
227 return r;
228}
229NK_API struct nk_rect
230nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
231{
232 return nk_rect(pos.x, pos.y, size.x, size.y);
233}
234NK_API struct nk_rect
235nk_rectv(const float *r)
236{
237 return nk_rect(r[0], r[1], r[2], r[3]);
238}
239NK_API struct nk_rect
240nk_rectiv(const int *r)
241{
242 return nk_recti(r[0], r[1], r[2], r[3]);
243}
244NK_API struct nk_vec2
245nk_rect_pos(struct nk_rect r)
246{
247 struct nk_vec2 ret;
248 ret.x = r.x; ret.y = r.y;
249 return ret;
250}
251NK_API struct nk_vec2
252nk_rect_size(struct nk_rect r)
253{
254 struct nk_vec2 ret;
255 ret.x = r.w; ret.y = r.h;
256 return ret;
257}
258NK_LIB struct nk_rect
259nk_shrink_rect(struct nk_rect r, float amount)
260{
261 struct nk_rect res;
262 r.w = NK_MAX(r.w, 2 * amount);
263 r.h = NK_MAX(r.h, 2 * amount);
264 res.x = r.x + amount;
265 res.y = r.y + amount;
266 res.w = r.w - 2 * amount;
267 res.h = r.h - 2 * amount;
268 return res;
269}
270NK_LIB struct nk_rect
271nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
272{
273 r.w = NK_MAX(r.w, 2 * pad.x);
274 r.h = NK_MAX(r.h, 2 * pad.y);
275 r.x += pad.x; r.y += pad.y;
276 r.w -= 2 * pad.x;
277 r.h -= 2 * pad.y;
278 return r;
279}
280NK_API struct nk_vec2
281nk_vec2(float x, float y)
282{
283 struct nk_vec2 ret;
284 ret.x = x; ret.y = y;
285 return ret;
286}
287NK_API struct nk_vec2
288nk_vec2i(int x, int y)
289{
290 struct nk_vec2 ret;
291 ret.x = (float)x;
292 ret.y = (float)y;
293 return ret;
294}
295NK_API struct nk_vec2
296nk_vec2v(const float *v)
297{
298 return nk_vec2(v[0], v[1]);
299}
300NK_API struct nk_vec2
301nk_vec2iv(const int *v)
302{
303 return nk_vec2i(v[0], v[1]);
304}
305NK_LIB void
306nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
307 float x1, float y1)
308{
309 NK_ASSERT(a);
310 NK_ASSERT(clip);
311 clip->x = NK_MAX(a->x, x0);
312 clip->y = NK_MAX(a->y, y0);
313 clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
314 clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
315 clip->w = NK_MAX(0, clip->w);
316 clip->h = NK_MAX(0, clip->h);
317}
318
319NK_API void
320nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r,
321 float pad_x, float pad_y, enum nk_heading direction)
322{
323 float w_half, h_half;
324 NK_ASSERT(result);
325
326 r.w = NK_MAX(2 * pad_x, r.w);
327 r.h = NK_MAX(2 * pad_y, r.h);
328 r.w = r.w - 2 * pad_x;
329 r.h = r.h - 2 * pad_y;
330
331 r.x = r.x + pad_x;
332 r.y = r.y + pad_y;
333
334 w_half = r.w / 2.0f;
335 h_half = r.h / 2.0f;
336
337 if (direction == NK_UP) {
338 result[0] = nk_vec2(r.x + w_half, r.y);
339 result[1] = nk_vec2(r.x + r.w, r.y + r.h);
340 result[2] = nk_vec2(r.x, r.y + r.h);
341 } else if (direction == NK_RIGHT) {
342 result[0] = nk_vec2(r.x, r.y);
343 result[1] = nk_vec2(r.x + r.w, r.y + h_half);
344 result[2] = nk_vec2(r.x, r.y + r.h);
345 } else if (direction == NK_DOWN) {
346 result[0] = nk_vec2(r.x, r.y);
347 result[1] = nk_vec2(r.x + r.w, r.y);
348 result[2] = nk_vec2(r.x + w_half, r.y + r.h);
349 } else {
350 result[0] = nk_vec2(r.x, r.y + h_half);
351 result[1] = nk_vec2(r.x + r.w, r.y);
352 result[2] = nk_vec2(r.x + r.w, r.y + r.h);
353 }
354}
355
main API and documentation file