v2 / vlib / math / bits / bits.c.v
186 lines · 171 sloc · 4.09 KB · a87a4d73b9ab25cfff0822f4e94cf2a2d9e64323
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module bits
5
6fn C.__builtin_clz(x u32) i32
7fn C.__builtin_clzll(x u64) i32
8fn C.__lzcnt(x u32) i32
9fn C.__lzcnt64(x u64) i32
10
11// --- LeadingZeros ---
12// leading_zeros_8 returns the number of leading zero bits in x; the result is 8 for x == 0.
13@[inline]
14pub fn leading_zeros_8(x u8) int {
15 if x == 0 {
16 return 8
17 }
18 $if msvc {
19 return C.__lzcnt(x) - 24
20 } $else $if !tinyc {
21 return C.__builtin_clz(x) - 24
22 }
23 return leading_zeros_8_default(x)
24}
25
26// leading_zeros_16 returns the number of leading zero bits in x; the result is 16 for x == 0.
27@[inline]
28pub fn leading_zeros_16(x u16) int {
29 if x == 0 {
30 return 16
31 }
32 $if msvc {
33 return C.__lzcnt(x) - 16
34 } $else $if !tinyc {
35 return C.__builtin_clz(x) - 16
36 }
37 return leading_zeros_16_default(x)
38}
39
40// leading_zeros_32 returns the number of leading zero bits in x; the result is 32 for x == 0.
41@[inline]
42pub fn leading_zeros_32(x u32) int {
43 if x == 0 {
44 return 32
45 }
46 $if msvc {
47 return C.__lzcnt(x)
48 } $else $if !tinyc {
49 return C.__builtin_clz(x)
50 }
51 return leading_zeros_32_default(x)
52}
53
54// leading_zeros_64 returns the number of leading zero bits in x; the result is 64 for x == 0.
55@[inline]
56pub fn leading_zeros_64(x u64) int {
57 if x == 0 {
58 return 64
59 }
60 $if msvc {
61 return C.__lzcnt64(x)
62 } $else $if !tinyc {
63 return C.__builtin_clzll(x)
64 }
65 return leading_zeros_64_default(x)
66}
67
68fn C.__builtin_ctz(x u32) i32
69fn C.__builtin_ctzll(x u64) i32
70fn C._BitScanForward(pos &int, x u32) u8
71fn C._BitScanForward64(pos &int, x u64) u8
72
73// --- TrailingZeros ---
74// trailing_zeros_8 returns the number of trailing zero bits in x; the result is 8 for x == 0.
75@[inline]
76pub fn trailing_zeros_8(x u8) int {
77 if x == 0 {
78 return 8
79 }
80 $if msvc {
81 mut pos := 0
82 _ := C._BitScanForward(&pos, x)
83 return pos
84 } $else $if !tinyc {
85 return C.__builtin_ctz(x)
86 }
87 return trailing_zeros_8_default(x)
88}
89
90// trailing_zeros_16 returns the number of trailing zero bits in x; the result is 16 for x == 0.
91@[inline]
92pub fn trailing_zeros_16(x u16) int {
93 if x == 0 {
94 return 16
95 }
96 $if msvc {
97 mut pos := 0
98 _ := C._BitScanForward(&pos, x)
99 return pos
100 } $else $if !tinyc {
101 return C.__builtin_ctz(x)
102 }
103 return trailing_zeros_16_default(x)
104}
105
106// trailing_zeros_32 returns the number of trailing zero bits in x; the result is 32 for x == 0.
107@[inline]
108pub fn trailing_zeros_32(x u32) int {
109 if x == 0 {
110 return 32
111 }
112 $if msvc {
113 mut pos := 0
114 _ := C._BitScanForward(&pos, x)
115 return pos
116 } $else $if !tinyc {
117 return C.__builtin_ctz(x)
118 }
119 return trailing_zeros_32_default(x)
120}
121
122// trailing_zeros_64 returns the number of trailing zero bits in x; the result is 64 for x == 0.
123@[inline]
124pub fn trailing_zeros_64(x u64) int {
125 if x == 0 {
126 return 64
127 }
128 $if msvc {
129 mut pos := 0
130 _ := C._BitScanForward64(&pos, x)
131 return pos
132 } $else $if !tinyc {
133 return C.__builtin_ctzll(x)
134 }
135 return trailing_zeros_64_default(x)
136}
137
138fn C.__builtin_popcount(x u32) i32
139fn C.__builtin_popcountll(x u64) i32
140fn C.__popcnt(x u32) i32
141fn C.__popcnt64(x u64) i32
142
143// --- OnesCount ---
144// ones_count_8 returns the number of one bits ("population count") in x.
145@[inline]
146pub fn ones_count_8(x u8) int {
147 $if msvc {
148 return C.__popcnt(x)
149 } $else $if !tinyc {
150 return C.__builtin_popcount(x)
151 }
152 return ones_count_8_default(x)
153}
154
155// ones_count_16 returns the number of one bits ("population count") in x.
156@[inline]
157pub fn ones_count_16(x u16) int {
158 $if msvc {
159 return C.__popcnt(x)
160 } $else $if !tinyc {
161 return C.__builtin_popcount(x)
162 }
163 return ones_count_16_default(x)
164}
165
166// ones_count_32 returns the number of one bits ("population count") in x.
167@[inline]
168pub fn ones_count_32(x u32) int {
169 $if msvc {
170 return C.__popcnt(x)
171 } $else $if !tinyc {
172 return C.__builtin_popcount(x)
173 }
174 return ones_count_32_default(x)
175}
176
177// ones_count_64 returns the number of one bits ("population count") in x.
178@[inline]
179pub fn ones_count_64(x u64) int {
180 $if msvc {
181 return C.__popcnt64(x)
182 } $else $if !tinyc {
183 return C.__builtin_popcountll(x)
184 }
185 return ones_count_64_default(x)
186}
187