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