@bitReverse em Zig
O @bitReverse inverte a ordem de todos os bits de um valor inteiro — o bit mais significativo se torna o menos significativo e vice-versa. Diferente de @byteSwap que inverte bytes, @bitReverse inverte cada bit individual. Usado em FFT (Fast Fourier Transform), CRC, protocolos seriais e algoritmos de hashing.
Sintaxe
@bitReverse(value: T) T
Parâmetros
- value (
T): Valor inteiro cujos bits serão invertidos.
Valor de retorno
Retorna T — o valor com a ordem dos bits completamente invertida.
Exemplos práticos
Exemplo 1: Inversão básica de bits
const std = @import("std");
pub fn main() void {
const a: u8 = 0b10110001;
const b = @bitReverse(a);
std.debug.print("Original: 0b{b:0>8}\n", .{a}); // 0b10110001
std.debug.print("Invertido: 0b{b:0>8}\n", .{b}); // 0b10001101
// Para u16
const c: u16 = 0b1000000000000000;
const d = @bitReverse(c);
std.debug.print("u16: 0b{b:0>16} -> 0b{b:0>16}\n", .{ c, d });
// 0b1000000000000000 -> 0b0000000000000001
}
Exemplo 2: Bit-reversal permutation (para FFT)
const std = @import("std");
fn bitReversalPermutation(comptime N: usize, dados: *[N]f32) void {
const bits = @ctz(@as(usize, N)); // log2(N)
for (0..N) |i| {
const j = @bitReverse(@as(std.meta.Int(.unsigned, bits), @intCast(i)));
if (i < j) {
const temp = dados[i];
dados[i] = dados[j];
dados[j] = temp;
}
}
}
pub fn main() void {
var dados = [_]f32{ 0, 1, 2, 3, 4, 5, 6, 7 };
bitReversalPermutation(8, &dados);
std.debug.print("Permutação: ", .{});
for (dados) |v| {
std.debug.print("{d:.0} ", .{v});
}
std.debug.print("\n", .{}); // 0 4 2 6 1 5 3 7
}
Exemplo 3: CRC com bit reversal
const std = @import("std");
fn refletir8(valor: u8) u8 {
return @bitReverse(valor);
}
pub fn main() void {
// Em CRC, dados são frequentemente refletidos
const byte: u8 = 0b11010010;
const refletido = refletir8(byte);
std.debug.print("Original: 0b{b:0>8}\n", .{byte});
std.debug.print("Refletido: 0b{b:0>8}\n", .{refletido});
}
Casos de uso comuns
- FFT: Bit-reversal permutation é passo fundamental da FFT.
- CRC: Alguns algoritmos CRC exigem reflexão de bits.
- Protocolos seriais: LSB-first para MSB-first e vice-versa.
- Criptografia: Transformações de bits em cifras.
@bitReverse vs @byteSwap
É fácil confundir os dois. A diferença é clara com um exemplo:
const valor: u32 = 0xABCD1234;
// @byteSwap inverte a ordem dos BYTES
// 0xABCD1234 -> 0x3412CDAB
const bytes_invertidos = @byteSwap(valor);
// @bitReverse inverte a ordem de todos os BITS individuais
// Cada bit é refletido em torno do centro
const bits_invertidos = @bitReverse(valor);
Use @byteSwap para converter endianness. Use @bitReverse quando precisar de inversão bit-a-bit (FFT, CRC, protocolos seriais).
Equivalente em C
Em C não existe builtin portável para inversão de bits. A implementação manual é verbosa:
uint8_t bit_reverse_u8(uint8_t x) {
x = ((x & 0xF0) >> 4) | ((x & 0x0F) << 4);
x = ((x & 0xCC) >> 2) | ((x & 0x33) << 2);
x = ((x & 0xAA) >> 1) | ((x & 0x55) << 1);
return x;
}
GCC e Clang oferecem __builtin_bitreverse8/16/32/64 como extensão não-portável. O Zig mapeia @bitReverse diretamente para essas instruções quando disponíveis.
Considerações de performance
O compilador Zig gera código otimizado para @bitReverse. Em arquiteturas que têm instrução nativa de bit reversal (como ARM com RBIT), o compilador emite diretamente essa instrução. Em x86, onde não há instrução nativa, o compilador usa uma sequência eficiente de shifts e masks — geralmente mais eficiente que qualquer implementação manual.
Tipos suportados
@bitReverse funciona com qualquer tipo inteiro, incluindo tipos não-padrão:
const a = @bitReverse(@as(u3, 0b101)); // 0b101 -> 0b101 (simétrico)
const b = @bitReverse(@as(u4, 0b1001)); // 0b1001 -> 0b1001 (simétrico)
const c = @bitReverse(@as(u4, 0b1100)); // 0b1100 -> 0b0011
Perguntas Frequentes
@bitReverse de zero retorna zero?
Sim. Todos os bits zero invertidos continuam sendo zero. Igualmente, @bitReverse do valor máximo (todos bits 1) retorna o valor máximo.
Qual a diferença entre @bitReverse e NOT bit-a-bit?
NOT (operador ~) inverte o valor de cada bit (0→1, 1→0). @bitReverse mantém os valores dos bits mas inverte a posição deles (bit 0 vai para a posição N-1, bit 1 para N-2, etc.).
@bitReverse funciona com inteiros signed?
Sim. O builtin trata os bits como representação binária bruta, independente de sinal. O resultado é o valor signed com os bits na ordem inversa.
Builtins relacionados
- @byteSwap — Inverter ordem dos bytes (não bits)
- @clz — Contar zeros à esquerda
- @ctz — Contar zeros à direita
- @popCount — Contar bits em 1