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