GF16 (Bouncy Castle Library 1.85 API Specification)
Date: 2026-07-12

org.bouncycastle.math.raw

## Class GF16

- java.lang.Object
- - org.bouncycastle.math.raw.GF16

-     public class GF16
      extends java.lang.Object

- - ### Constructor Summary

    Constructors
    Constructor and Description
    `GF16()`

  - ### Method Summary

    All Methods Static Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `static void` | `decode(byte[] input, byte[] output, int outputLen)` Decodes an encoded byte array.
    `static void` | `decode(byte[] input, int inOff, byte[] output, int outOff, int outputLen)`
    `static void` | `encode(byte[] input, byte[] output, int inputLen)` Encodes an array of 4-bit values into a byte array.
    `static void` | `encode(byte[] input, byte[] output, int outOff, int inputLen)`
    `static byte` | `innerProduct(byte[] a, int aOff, byte[] b, int bOff, int rank)`
    `static byte` | `inv(byte a)` Multiplicative inverse in GF(16), table-free: a^14 = a^-1 (since a^15 = 1 for a !
    `static int` | `inv(int a)` Multiplicative inverse in GF(16); table-free, branch-free (see `inv(byte)`).
    `static byte` | `mul(byte a, byte b)` GF(16) multiplication mod x^4 + x + 1.
    `static int` | `mul(int a, int b)` GF(16) multiplication mod x^4 + x + 1; table-free, branch-free (see `mul(byte, byte)`).
    `static long` | `mulAddStep16(long v, long m0, long m1, long m2, long m3)` One step of the bitsliced, word-parallel GF(16) scalar-times-vector multiply-accumulate.
    `static long` | `mulFx8(int a, long b)` Byte-lane parallel GF(16) multiply: multiplies the single GF(16) scalar `a` into up to eight GF(16) elements packed one-per-byte in `b` (each in the low nibble of its byte), all at once and table-free.
    `static int` | `sqr(int a)` Constant-time GF(16) squaring over x^4 + x + 1.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

    - #### GF16

          public GF16()

  - ### Method Detail

    - #### mulAddStep16

          public static long mulAddStep16(long v,
                                          long m0,
                                          long m1,
                                          long m2,
                                          long m3)

      One step of the bitsliced, word-parallel GF(16) scalar-times-vector multiply-accumulate. Returns the contribution to XOR into the accumulator for a single 16-nibble packed input limb `v`, given the four broadcast scalar-bit masks `m0..m3` (each 0 or -1, one per bit of the GF(16) scalar). The caller hoists the mask computation outside its limb loop.

      This is the constant-time, table-free GF(16) kernel shared by UOV's `GF.vecMadd16` and MAYO's `GF16Utils.mVecMulAdd`: a mask-select on the scalar bits plus a SWAR multiply-by-x that folds x+1 (0x3) per nibble for the field polynomial x^4 + x + 1. No data-dependent branch and no secret-indexed table.

      Parameters:
        `v` - 16 GF(16) nibbles packed into a long.
        `m0` - broadcast mask (0 or -1) for scalar bit 0.
        `m1` - broadcast mask (0 or -1) for scalar bit 1.
        `m2` - broadcast mask (0 or -1) for scalar bit 2.
        `m3` - broadcast mask (0 or -1) for scalar bit 3.
      Returns:
        the multiply-accumulate contribution for this limb.

    - #### mul

          public static byte mul(byte a,
                                 byte b)

      GF(16) multiplication mod x^4 + x + 1.

      Table-free, branch-free carryless multiply followed by reduction modulo x^4 + x + 1, so the multiply carries no secret-indexed memory access (no L3 cache-timing side channel) — the form used by the SNOVA and MAYO reference implementations' production (Opt / AVX2) builds. Please ensure a <= 0x0F and b <= 0x0F.

      Parameters:
        `a` - an element in GF(16) (only the lower 4 bits are used)
        `b` - an element in GF(16) (only the lower 4 bits are used)
      Returns:
        the product a * b in GF(16)

    - #### mul

          public static int mul(int a,
                                int b)

      GF(16) multiplication mod x^4 + x + 1; table-free, branch-free (see `mul(byte, byte)`). Please ensure a <= 0x0F and b <= 0x0F.
      Parameters:
        `a` - an element in GF(16) (only the lower 4 bits are used)
        `b` - an element in GF(16) (only the lower 4 bits are used)
      Returns:
        the product a * b in GF(16)

    - #### mulFx8

          public static long mulFx8(int a,
                                    long b)

      Byte-lane parallel GF(16) multiply: multiplies the single GF(16) scalar `a` into up to eight GF(16) elements packed one-per-byte in `b` (each in the low nibble of its byte), all at once and table-free. The batched, constant-time form of `mul(int, int)` used to multiply a scalar by a whole packed matrix row (the SNOVA / MAYO `mul_fx8`).
      Parameters:
        `a` - a GF(16) scalar (only the lower 4 bits are used)
        `b` - up to eight GF(16) elements, one per byte lane
      Returns:
        the eight products, one per byte lane

    - #### sqr

          public static int sqr(int a)

      Constant-time GF(16) squaring over x^4 + x + 1. Squaring is GF(2)-linear, so `a^2` is just the bit-spread of `a` (interleave a zero between each bit, via `Interleave.expand4to8(int)`) reduced mod 0x13. `x^4 = x + 1` means the folded-down high nibble multiplies by 0x3, computed branchlessly as `d ^ (d<<1)` = `d * (1 + x)`; one fold suffices here (unlike GF(256)) because 0x3 is degree 1. Returns the same value as `mul(a, a)` but with no per-term work — table-free, branchless, and faster (~1.35x on HotSpot C2), so it replaces the squarings in `inv(int)`.

    - #### inv

          public static byte inv(byte a)

      Multiplicative inverse in GF(16), table-free: a^14 = a^-1 (since a^15 = 1 for a != 0; 0 maps to 0), so the inverse carries no secret-indexed memory access. Matches the SNOVA / MAYO reference `gf16_inv` / `inverse_f`.

    - #### inv

          public static int inv(int a)

      Multiplicative inverse in GF(16); table-free, branch-free (see `inv(byte)`). The three squarings go through `sqr(int)`; the two genuine products through `mul(int, int)`.
      Parameters:
        `a` - an element in GF(16) (only the lower 4 bits are used)
      Returns:
        the inverse a^-1 in GF(16), or 0 when `a == 0`

    - #### decode

          public static void decode(byte[] input,
                                    byte[] output,
                                    int outputLen)

      Decodes an encoded byte array. Each byte in the input contains two nibbles (4-bit values); the lower nibble is stored first, followed by the upper nibble.
      Parameters:
        `input` - the input byte array (each byte holds two 4-bit values)
        `output` - the output array that will hold the decoded nibbles (one per byte)
        `outputLen` - the total number of nibbles to decode

    - #### decode

          public static void decode(byte[] input,
                                    int inOff,
                                    byte[] output,
                                    int outOff,
                                    int outputLen)

    - #### encode

          public static void encode(byte[] input,
                                    byte[] output,
                                    int inputLen)

      Encodes an array of 4-bit values into a byte array. Two 4-bit values are packed into one byte, with the first nibble stored in the lower 4 bits and the second nibble stored in the upper 4 bits.
      Parameters:
        `input` - the input array of 4-bit values (stored as bytes, only lower 4 bits used)
        `output` - the output byte array that will hold the encoded bytes
        `inputLen` - the number of nibbles in the input array

    - #### encode

          public static void encode(byte[] input,
                                    byte[] output,
                                    int outOff,
                                    int inputLen)

    - #### innerProduct

          public static byte innerProduct(byte[] a,
                                          int aOff,
                                          byte[] b,
                                          int bOff,
                                          int rank)