]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/lib/bits.qh
Merge branch 'master' into martin-t/mg-solidpen
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / bits.qh
1 #pragma once
2
3 #include "log.qh"
4
5 /// Only ever assign into the first 24 bits in QC (so max is BIT(23)).
6 /// QC converts the float to int, performs the bit operation, then converts it back.
7 /// Assigning to the highest bits means some of the low ones might get lost due to float precision.
8 #define BIT(n) (1 << (n))
9 #define BITS(n) (BIT(n) - 1)
10 #ifndef BRANCHLESS_BITSET
11         #define BITSET(var, mask, flag) (flag ? (var) | (mask) : (var) & ~(mask))
12 #else
13         #define BITSET(var, mask, flag) ((var) ^ (-(flag) ^ (var)) & (mask))
14 #endif
15
16 ERASEABLE
17 int lowestbit(int f)
18 {
19         f &= ~(f << 1);
20         f &= ~(f << 2);
21         f &= ~(f << 4);
22         f &= ~(f << 8);
23         f &= ~(f << 16);
24         return f;
25 }
26
27 ERASEABLE
28 int randombit(int bits)
29 {
30         if (!(bits & (bits - 1)))  // this ONLY holds for powers of two!
31                 return bits;
32
33         int r = random();
34         int b = 0;
35         int n = 0;
36
37         for (int f = 1; f <= bits; f *= 2)
38         {
39                 if (bits & f)
40                 {
41                         ++n;
42                         r *= n;
43                         if (r <= 1) b = f;
44                         else r = (r - 1) / (n - 1);
45                 }
46         }
47         return b;
48 }
49
50 ERASEABLE
51 int randombits(int bits, int k, bool error_return)
52 {
53         int r = 0;
54         while (k > 0 && bits != r)
55         {
56                 r += randombit(bits - r);
57                 --k;
58         }
59         if (error_return)
60                 if (k > 0) return -1;
61         // all
62         return r;
63 }
64
65 /*
66 void randombit_test(int bits, int iter)
67 {
68         while (iter > 0)
69         {
70                 LOG_INFO(ftos(randombit(bits)), "\n");
71                 --iter;
72         }
73 }
74 */
75
76 enum {
77         OP_SET,
78         OP_MIN,
79         OP_MAX,
80         OP_PLUS,
81         OP_MINUS
82 };
83
84 ERASEABLE
85 bool GiveBit(entity e, .int fld, int bit, int op, int val)
86 {
87         int v0 = (e.(fld) & bit);
88         switch (op)
89         {
90                 case OP_SET:
91                         if (val > 0) e.(fld) |= bit;
92                         else e.(fld) &= ~bit;
93                         break;
94                 case OP_MIN:
95                 case OP_PLUS:
96                         if (val > 0) e.(fld) |= bit;
97                         break;
98                 case OP_MAX:
99                         if (val <= 0) e.(fld) &= ~bit;
100                         break;
101                 case OP_MINUS:
102                         if (val > 0) e.(fld) &= ~bit;
103                         break;
104         }
105         int v1 = (e.(fld) & bit);
106         return v0 != v1;
107 }
108
109 ERASEABLE
110 bool GiveValue(entity e, .int fld, int op, int val)
111 {
112         int v0 = e.(fld);
113         switch (op)
114         {
115                 case OP_SET:
116                         e.(fld) = val;
117                         break;
118                 case OP_MIN:
119                         e.(fld) = max(e.(fld), val);  // min 100 cells = at least 100 cells
120                         break;
121                 case OP_MAX:
122                         e.(fld) = min(e.(fld), val);
123                         break;
124                 case OP_PLUS:
125                         e.(fld) += val;
126                         break;
127                 case OP_MINUS:
128                         e.(fld) -= val;
129                         break;
130         }
131         int v1 = e.(fld);
132         return v0 != v1;
133 }