maths.bits: fix ambiguous expressions, remove special case in the checker (#24815)

This commit is contained in:
Laurent Cheylus 2025-06-30 21:02:24 +02:00 committed by GitHub
parent 65a5e968d7
commit aadb0e9435
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 17 additions and 19 deletions

View File

@ -106,7 +106,7 @@ pub fn ones_count_16(x u16) int {
// ones_count_32 returns the number of one bits ("population count") in x. // ones_count_32 returns the number of one bits ("population count") in x.
@[direct_array_access] @[direct_array_access]
pub fn ones_count_32(x u32) int { pub fn ones_count_32(x u32) int {
return int(pop_8_tab[x >> 24] + pop_8_tab[x >> 16 & 0xff] + pop_8_tab[x >> 8 & 0xff] + return int(pop_8_tab[x >> 24] + pop_8_tab[(x >> 16) & 0xff] + pop_8_tab[(x >> 8) & 0xff] +
pop_8_tab[x & u32(0xff)]) pop_8_tab[x & u32(0xff)])
} }
@ -131,8 +131,8 @@ pub fn ones_count_64(x u64) int {
// Per "Hacker's Delight", the first line can be simplified // Per "Hacker's Delight", the first line can be simplified
// more, but it saves at best one instruction, so we leave // more, but it saves at best one instruction, so we leave
// it alone for clarity. // it alone for clarity.
mut y := (x >> u64(1) & (m0 & max_u64)) + (x & (m0 & max_u64)) mut y := ((x >> u64(1)) & (m0 & max_u64)) + (x & (m0 & max_u64))
y = (y >> u64(2) & (m1 & max_u64)) + (y & (m1 & max_u64)) y = ((y >> u64(2)) & (m1 & max_u64)) + (y & (m1 & max_u64))
y = ((y >> 4) + y) & (m2 & max_u64) y = ((y >> 4) + y) & (m2 & max_u64)
y += y >> 8 y += y >> 8
y += y >> 16 y += y >> 16
@ -202,18 +202,18 @@ pub fn reverse_16(x u16) u16 {
// reverse_32 returns the value of x with its bits in reversed order. // reverse_32 returns the value of x with its bits in reversed order.
@[inline] @[inline]
pub fn reverse_32(x u32) u32 { pub fn reverse_32(x u32) u32 {
mut y := ((x >> u32(1) & (m0 & max_u32)) | ((x & (m0 & max_u32)) << 1)) mut y := (((x >> u32(1)) & (m0 & max_u32)) | ((x & (m0 & max_u32)) << 1))
y = ((y >> u32(2) & (m1 & max_u32)) | ((y & (m1 & max_u32)) << u32(2))) y = (((y >> u32(2)) & (m1 & max_u32)) | ((y & (m1 & max_u32)) << u32(2)))
y = ((y >> u32(4) & (m2 & max_u32)) | ((y & (m2 & max_u32)) << u32(4))) y = (((y >> u32(4)) & (m2 & max_u32)) | ((y & (m2 & max_u32)) << u32(4)))
return reverse_bytes_32(u32(y)) return reverse_bytes_32(u32(y))
} }
// reverse_64 returns the value of x with its bits in reversed order. // reverse_64 returns the value of x with its bits in reversed order.
@[inline] @[inline]
pub fn reverse_64(x u64) u64 { pub fn reverse_64(x u64) u64 {
mut y := ((x >> u64(1) & (m0 & max_u64)) | ((x & (m0 & max_u64)) << 1)) mut y := (((x >> u64(1)) & (m0 & max_u64)) | ((x & (m0 & max_u64)) << 1))
y = ((y >> u64(2) & (m1 & max_u64)) | ((y & (m1 & max_u64)) << 2)) y = (((y >> u64(2)) & (m1 & max_u64)) | ((y & (m1 & max_u64)) << 2))
y = ((y >> u64(4) & (m2 & max_u64)) | ((y & (m2 & max_u64)) << 4)) y = (((y >> u64(4)) & (m2 & max_u64)) | ((y & (m2 & max_u64)) << 4))
return reverse_bytes_64(y) return reverse_bytes_64(y)
} }
@ -231,7 +231,7 @@ pub fn reverse_bytes_16(x u16) u16 {
// This function's execution time does not depend on the inputs. // This function's execution time does not depend on the inputs.
@[inline] @[inline]
pub fn reverse_bytes_32(x u32) u32 { pub fn reverse_bytes_32(x u32) u32 {
y := ((x >> u32(8) & (m3 & max_u32)) | ((x & (m3 & max_u32)) << u32(8))) y := (((x >> u32(8)) & (m3 & max_u32)) | ((x & (m3 & max_u32)) << u32(8)))
return u32((y >> 16) | (y << 16)) return u32((y >> 16) | (y << 16))
} }
@ -240,8 +240,8 @@ pub fn reverse_bytes_32(x u32) u32 {
// This function's execution time does not depend on the inputs. // This function's execution time does not depend on the inputs.
@[inline] @[inline]
pub fn reverse_bytes_64(x u64) u64 { pub fn reverse_bytes_64(x u64) u64 {
mut y := ((x >> u64(8) & (m3 & max_u64)) | ((x & (m3 & max_u64)) << u64(8))) mut y := (((x >> u64(8)) & (m3 & max_u64)) | ((x & (m3 & max_u64)) << u64(8)))
y = ((y >> u64(16) & (m4 & max_u64)) | ((y & (m4 & max_u64)) << u64(16))) y = (((y >> u64(16)) & (m4 & max_u64)) | ((y & (m4 & max_u64)) << u64(16)))
return (y >> 32) | (y << 32) return (y >> 32) | (y << 32)
} }

View File

@ -806,7 +806,6 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
} }
// Do an ambiguous expression check for << >> and &, since they all have the same precedence (unlike in C) // Do an ambiguous expression check for << >> and &, since they all have the same precedence (unlike in C)
if !c.is_builtin_mod && node.op in [.amp, .left_shift, .right_shift] { if !c.is_builtin_mod && node.op in [.amp, .left_shift, .right_shift] {
if !c.mod.starts_with('math') { // TODO fix all warnings in math
if mut node.left is ast.InfixExpr { if mut node.left is ast.InfixExpr {
if node.left.op != node.op && node.left.op in [.amp, .left_shift, .right_shift] { if node.left.op != node.op && node.left.op in [.amp, .left_shift, .right_shift] {
// for example: `(a << b) & c` instead of `a << b & c` // for example: `(a << b) & c` instead of `a << b & c`
@ -815,7 +814,6 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
} }
} }
} }
}
// TODO: Absorb this block into the above single side check block to accelerate. // TODO: Absorb this block into the above single side check block to accelerate.
if left_type == ast.bool_type && node.op !in [.eq, .ne, .logical_or, .and] { if left_type == ast.bool_type && node.op !in [.eq, .ne, .logical_or, .and] {
c.error('bool types only have the following operators defined: `==`, `!=`, `||`, and `&&`', c.error('bool types only have the following operators defined: `==`, `!=`, `||`, and `&&`',