-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.h
106 lines (86 loc) · 2.61 KB
/
util.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define MIN(a, b) ((a)<(b)?(a):(b))
#define MAX(a, b) ((a)>(b)?(a):(b))
#define lenof(a) (sizeof(a)/sizeof(*(a)))
#define endof(a) (a + lenof(a))
typedef struct { int32_t x, y; } Vec;
static const Vec vec_zero = {0, 0};
/* returns integer (floored) square root of x, capped at 2^bits
* fast, gcc tends to unroll with constant bits at -O3
*/
static inline int32_t isqrt(int64_t x, unsigned bits) {
uint32_t y = 0;
while (bits-- > 0) {
uint64_t a = (y + (1 << bits)) << bits;
if (x >= a) {
x -= a;
y |= 2 << bits;
}
}
return y >> 1;
}
/* returns the norm (length) squared of vector v
* this is faster than vec_norm because it avoids sqrt
*/
static inline int64_t vec_normsq(Vec v) {
return (int64_t)v.x * v.x + (int64_t)v.y * v.y;
}
/* returns the norm (length) of vector v */
static inline int32_t vec_norm(Vec v) {
return isqrt(vec_normsq(v), CHAR_BIT*sizeof(v.x));
}
/* returns the sum of vectors a and b, overflow-unsafe */
static inline Vec vec_add(Vec a, Vec b) {
return (Vec){a.x + b.x, a.y + b.y};
}
/* scales vector v by the fraction num/denom
* overflow-unsafe except when |denom|>=|num|
*/
static inline Vec vec_scale(Vec v, int32_t num, int64_t denom) {
return (Vec){
(int32_t)(((int64_t)v.x * num) / denom),
(int32_t)(((int64_t)v.y * num) / denom)
};
}
/* negates vector v */
static inline Vec vec_neg(Vec v) {
return vec_scale(v, -1, 1);
}
/* returns a vector with same angle as v, and specified magnitude */
static inline Vec vec_normalize(Vec v, int32_t magnitude) {
return vec_scale(v, magnitude, vec_norm(v));
}
/* returns a random vector inside a rectangle using rand() */
/*static inline Vec vec_rand(Vec min, Vec max) {
return (Vec){
rand() % ((int64_t)max.x + 1) + min.x,
rand() % ((int64_t)max.y + 1) + min.y
};
}*/
static inline Vec vec_min(Vec a, Vec b) {
return (Vec){a.x < b.x ? a.x : b.x, a.y < b.y ? a.y : b.y};
}
static inline Vec vec_max(Vec a, Vec b) {
return (Vec){a.x > b.x ? a.x : b.x, a.y > b.y ? a.y : b.y};
}
static inline Vec vec_mul(Vec a, Vec b) {
return (Vec){a.x * b.x, a.y * b.y};
}
static inline Vec vec_div(Vec a, Vec b) {
return (Vec){a.x / b.x, a.y / b.y};
}
static inline Vec vec_mod(Vec a, Vec b) {
return (Vec){a.x % b.x, a.y % b.y};
}
/* returns true if vector v is inside the rectangle with tl and br as top-left
* and bottom-right corners
*/
static inline bool vec_isinside(Vec v, Vec tl, Vec br) {
return v.x >= tl.x && v.x <= br.x && v.y >= tl.y && v.y <= br.y;
}
static inline int64_t vec_grad(Vec a){
return (((int64_t)a.y)<<32)/((((int64_t) a.x)<<32)+1);
}