@bitReverse em Zig — Referência e Exemplos

@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

  1. FFT: Bit-reversal permutation é passo fundamental da FFT.
  2. CRC: Alguns algoritmos CRC exigem reflexão de bits.
  3. Protocolos seriais: LSB-first para MSB-first e vice-versa.
  4. 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

Tutoriais relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.