Skip to content

Commit d9f93cc

Browse files
committed
add bits
1 parent 577ae6d commit d9f93cc

File tree

5 files changed

+464
-19
lines changed

5 files changed

+464
-19
lines changed

index.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
export * from './lib/utils';
2+
3+
// NOTE: there is no syntax for: export {* as bits} from './lib/bits';
4+
import * as bits_ from './lib/bits';
5+
export let bits = bits_;
6+
27
export { default as vec2 } from './lib/vec2';
38
export { default as vec3 } from './lib/vec3';
49
export { default as vec4 } from './lib/vec4';

lib/bits.js

+296
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/**
2+
* Bit twiddling hacks for JavaScript.
3+
*
4+
* Author: Mikola Lysenko
5+
*
6+
* Ported from Stanford bit twiddling hack library:
7+
* http://graphics.stanford.edu/~seander/bithacks.html
8+
*/
9+
10+
'use strict';
11+
'use restrict';
12+
13+
// Number of bits in an integer
14+
export const INT_BITS = 32;
15+
export const INT_MAX = 0x7fffffff;
16+
export const INT_MIN = -1<<(INT_BITS-1);
17+
18+
/**
19+
* Returns -1, 0, +1 depending on sign of x
20+
*
21+
* @param {number} v
22+
* @returns {number}
23+
*/
24+
export function sign(v) {
25+
return (v > 0) - (v < 0);
26+
}
27+
28+
/**
29+
* Computes absolute value of integer
30+
*
31+
* @param {number} v
32+
* @returns {number}
33+
*/
34+
export function abs(v) {
35+
let mask = v >> (INT_BITS-1);
36+
return (v ^ mask) - mask;
37+
}
38+
39+
/**
40+
* Computes minimum of integers x and y
41+
*
42+
* @param {number} x
43+
* @param {number} y
44+
* @returns {number}
45+
*/
46+
export function min(x, y) {
47+
return y ^ ((x ^ y) & -(x < y));
48+
}
49+
50+
/**
51+
* Computes maximum of integers x and y
52+
*
53+
* @param {number} x
54+
* @param {number} y
55+
* @returns {number}
56+
*/
57+
export function max(x, y) {
58+
return x ^ ((x ^ y) & -(x < y));
59+
}
60+
61+
/**
62+
* Checks if a number is a power of two
63+
*
64+
* @param {number} v
65+
* @returns {boolean}
66+
*/
67+
export function isPow2(v) {
68+
return !(v & (v-1)) && (!!v);
69+
}
70+
71+
/**
72+
* Computes log base 2 of v
73+
*
74+
* @param {number} v
75+
* @returns {number}
76+
*/
77+
export function log2(v) {
78+
let r, shift;
79+
r = (v > 0xFFFF) << 4; v >>>= r;
80+
shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift;
81+
shift = (v > 0xF ) << 2; v >>>= shift; r |= shift;
82+
shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift;
83+
return r | (v >> 1);
84+
}
85+
86+
/**
87+
* Computes log base 10 of v
88+
*
89+
* @param {number} v
90+
* @returns {number}
91+
*/
92+
export function log10(v) {
93+
return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 :
94+
(v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 :
95+
(v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0;
96+
}
97+
98+
/**
99+
* Counts number of bits
100+
*
101+
* @param {number} v
102+
* @returns {number}
103+
*/
104+
export function popCount(v) {
105+
v = v - ((v >>> 1) & 0x55555555);
106+
v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);
107+
return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
108+
}
109+
110+
/**
111+
* Counts number of trailing zeros
112+
*
113+
* @param {number} v
114+
* @returns {number}
115+
*/
116+
export function countTrailingZeros(v) {
117+
let c = 32;
118+
v &= -v;
119+
if (v) c--;
120+
if (v & 0x0000FFFF) c -= 16;
121+
if (v & 0x00FF00FF) c -= 8;
122+
if (v & 0x0F0F0F0F) c -= 4;
123+
if (v & 0x33333333) c -= 2;
124+
if (v & 0x55555555) c -= 1;
125+
return c;
126+
}
127+
128+
/**
129+
* Rounds to next power of 2
130+
*
131+
* @param {number} v
132+
* @returns {number}
133+
*/
134+
export function nextPow2(v) {
135+
v += v === 0;
136+
--v;
137+
v |= v >>> 1;
138+
v |= v >>> 2;
139+
v |= v >>> 4;
140+
v |= v >>> 8;
141+
v |= v >>> 16;
142+
return v + 1;
143+
}
144+
145+
/**
146+
* Rounds down to previous power of 2
147+
*
148+
* @param {number} v
149+
* @returns {number}
150+
*/
151+
export function prevPow2(v) {
152+
v |= v >>> 1;
153+
v |= v >>> 2;
154+
v |= v >>> 4;
155+
v |= v >>> 8;
156+
v |= v >>> 16;
157+
return v - (v>>>1);
158+
}
159+
160+
/**
161+
* Computes parity of word
162+
*
163+
* @param {number} v
164+
* @returns {number}
165+
*/
166+
export function parity(v) {
167+
v ^= v >>> 16;
168+
v ^= v >>> 8;
169+
v ^= v >>> 4;
170+
v &= 0xf;
171+
return (0x6996 >>> v) & 1;
172+
}
173+
174+
const REVERSE_TABLE = new Array(256);
175+
176+
(function(tab) {
177+
for(let i=0; i<256; ++i) {
178+
let v = i, r = i, s = 7;
179+
for (v >>>= 1; v; v >>>= 1) {
180+
r <<= 1;
181+
r |= v & 1;
182+
--s;
183+
}
184+
tab[i] = (r << s) & 0xff;
185+
}
186+
})(REVERSE_TABLE);
187+
188+
/**
189+
* Reverse bits in a 32 bit word
190+
*
191+
* @param {number} v
192+
* @returns {number}
193+
*/
194+
export function reverse(v) {
195+
return (REVERSE_TABLE[v & 0xff] << 24) |
196+
(REVERSE_TABLE[(v >>> 8) & 0xff] << 16) |
197+
(REVERSE_TABLE[(v >>> 16) & 0xff] << 8) |
198+
REVERSE_TABLE[(v >>> 24) & 0xff];
199+
}
200+
201+
/**
202+
* Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes
203+
*
204+
* @param {number} x
205+
* @param {number} y
206+
* @returns {number}
207+
*/
208+
export function interleave2(x, y) {
209+
x &= 0xFFFF;
210+
x = (x | (x << 8)) & 0x00FF00FF;
211+
x = (x | (x << 4)) & 0x0F0F0F0F;
212+
x = (x | (x << 2)) & 0x33333333;
213+
x = (x | (x << 1)) & 0x55555555;
214+
215+
y &= 0xFFFF;
216+
y = (y | (y << 8)) & 0x00FF00FF;
217+
y = (y | (y << 4)) & 0x0F0F0F0F;
218+
y = (y | (y << 2)) & 0x33333333;
219+
y = (y | (y << 1)) & 0x55555555;
220+
221+
return x | (y << 1);
222+
}
223+
224+
/**
225+
* Extracts the nth interleaved component
226+
*
227+
* @param {number} v
228+
* @param {number} n
229+
* @returns {number}
230+
*/
231+
export function deinterleave2(v, n) {
232+
v = (v >>> n) & 0x55555555;
233+
v = (v | (v >>> 1)) & 0x33333333;
234+
v = (v | (v >>> 2)) & 0x0F0F0F0F;
235+
v = (v | (v >>> 4)) & 0x00FF00FF;
236+
v = (v | (v >>> 16)) & 0x000FFFF;
237+
return (v << 16) >> 16;
238+
}
239+
240+
/**
241+
* Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes
242+
*
243+
* @param {number} x
244+
* @param {number} y
245+
* @param {number} z
246+
* @returns {number}
247+
*/
248+
export function interleave3(x, y, z) {
249+
x &= 0x3FF;
250+
x = (x | (x<<16)) & 4278190335;
251+
x = (x | (x<<8)) & 251719695;
252+
x = (x | (x<<4)) & 3272356035;
253+
x = (x | (x<<2)) & 1227133513;
254+
255+
y &= 0x3FF;
256+
y = (y | (y<<16)) & 4278190335;
257+
y = (y | (y<<8)) & 251719695;
258+
y = (y | (y<<4)) & 3272356035;
259+
y = (y | (y<<2)) & 1227133513;
260+
x |= (y << 1);
261+
262+
z &= 0x3FF;
263+
z = (z | (z<<16)) & 4278190335;
264+
z = (z | (z<<8)) & 251719695;
265+
z = (z | (z<<4)) & 3272356035;
266+
z = (z | (z<<2)) & 1227133513;
267+
268+
return x | (z << 2);
269+
}
270+
271+
/**
272+
* Extracts nth interleaved component of a 3-tuple
273+
*
274+
* @param {number} v
275+
* @param {number} n
276+
* @returns {number}
277+
*/
278+
export function deinterleave3(v, n) {
279+
v = (v >>> n) & 1227133513;
280+
v = (v | (v>>>2)) & 3272356035;
281+
v = (v | (v>>>4)) & 251719695;
282+
v = (v | (v>>>8)) & 4278190335;
283+
v = (v | (v>>>16)) & 0x3FF;
284+
return (v<<22)>>22;
285+
}
286+
287+
/**
288+
* Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page)
289+
*
290+
* @param {number} v
291+
* @returns {number}
292+
*/
293+
export function nextCombination(v) {
294+
let t = v | (v - 1);
295+
return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1));
296+
}

lib/utils.js

-11
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,6 @@ export function clamp01(val) {
5656
return val < 0 ? 0 : val > 1 ? 1 : val;
5757
}
5858

59-
/**
60-
* Returns true if argument is a power-of-two and false otherwise.
61-
*
62-
* @method powof2
63-
* @param {number} x Number to check for power-of-two property.
64-
* @returns {boolean} true if power-of-two and false otherwise.
65-
*/
66-
export function powof2(x) {
67-
return ((x !== 0) && !(x & (x - 1)));
68-
}
69-
7059
/**
7160
* @method lerp
7261
* @param {number} from

0 commit comments

Comments
 (0)