pp.h(3)

📦
version 2.2.0 · 2 versions
, in fedora 44

✨ pp.h(3) — Двоичные многочлены (Binary polynomials) ✨

okay bestie, welcome to the polynomial party 🎉 this is from the Library Functions Manual, and it's literally all about binary polynomials. no cap, it's giving math girlie energy and I'm obsessed 💅.


🌸 NAME 🌸

pp.h — Двоичные многочлены (Binary polynomials). periodt.


✨ SYNOPSIS ✨

#include 'bee2/defs.h'

🎀 Классы 🎀

  • struct pp_trinom_st — Описание трехчлена (description of a trinomial) 🦋
  • struct pp_pentanom_st — Описание пятичлена (description of a pentanomial) 🌸

🎀 Функции 🎀

  • size_t ppDeg (const word a[], size_t n) — Степень многочлена (polynomial degree) 👑
  • word ppMulW (word b[], const word a[], size_t n, register word w, void *stack) — Умножение многочлена на слово (multiply polynomial by a word) ✨
  • word ppAddMulW (word b[], const word a[], size_t n, register word w, void *stack) — Сложение с произведением многочлена на слово (add with product of polynomial and word) 💅
  • void ppMul (word c[], const word a[], size_t n, const word b[], size_t m, void *stack) — Умножение многочленов (multiply polynomials) 🦋
  • void ppSqr (word b[], const word a[], size_t n, void *stack) — Возведение многочлена в квадрат (square polynomial) 🌸
  • void ppDiv (word q[], word r[], const word a[], size_t n, const word b[], size_t m, void *stack) — Деление многочленов (divide polynomials) 💖
  • void ppMod (word r[], const word a[], size_t n, const word b[], size_t m, void *stack) — Остаток от деления многочленов (remainder of polynomial division) 🎀
  • void ppGCD (word d[], const word a[], size_t n, const word b[], size_t m, void *stack) — Наибольший общий делитель (greatest common divisor) 🔥
  • void ppExGCD (word d[], word da[], word db[], const word a[], size_t n, const word b[], size_t m, void *stack) — Расширенный алгоритм Евклида (extended Euclidean algorithm) 👑
  • void ppMulMod (word c[], const word a[], const word b[], const word mod[], size_t n, void *stack) — Умножение многочленов по модулю (multiply polynomials modulo) 💜
  • void ppSqrMod (word b[], const word a[], const word mod[], size_t n, void *stack) — Возведение многочлена в квадрат по модулю (square polynomial modulo) 🌈
  • void ppInvMod (word b[], const word a[], const word mod[], size_t n, void *stack) — Обращение по модулю (inversion modulo) ⭐
  • void ppDivMod (word b[], const word divident[], const word a[], const word mod[], size_t n, void * stack) — Деление по модулю (division modulo) 💀
  • void ppRed (word a[], const word mod[], size_t n, void *stack) — Стандартная редукция (standard reduction) 🍓
  • void ppRedTrinomial (word a[], const pp_trinom_st *p) — Редукция по модулю трехчлена (reduction modulo trinomial) 🧚
  • void ppRedPentanomial (word a[], const pp_pentanom_st *p) — Редукция по модулю пятичлена (reduction modulo pentanomial) 💜
  • void ppRedBelt (word a[]) — Редукция по модулю многочлена Belt. (reduction modulo Belt polynomial) 🔥
  • bool_t ppIsIrred (const word a[], size_t n, void *stack) — Проверка неприводимости (irreducibility check) ✨
  • void ppMinPoly (word b[], const word a[], size_t l, void *stack) — Минимальный многочлен последовательности (minimal polynomial of a sequence) 🌸
  • void ppMinPolyMod (word b[], const word a[], const word mod[], size_t n, void *stack) — Минимальный многочлен по модулю многочлена (minimal polynomial modulo a polynomial) 🦋

✨ Подробное описание (Detailed description) ✨

okay so operations with polynomials over a binary field are implemented. literally the main character energy of this library.

A polynomial p(x) is given by an array of machine words: word p[n]. The free term is stored in the least significant bit of p[0], and the coefficient of the highest monomial is in the most significant bit of p[n - 1]. 💅

In the function descriptions, X = x^{B_PER_W}. In particular, p(x) = p[n - 1]X^{n - 1} + ... + p[1] X + p[0]. ✨

An empty polynomial (n = 0) is considered zero. no cap.

For manipulations with the array of machine words, functions declared in file ww.h can be used. For example, polynomial addition is implemented by function wwXor(). 🦋

In some functions, an auxiliary buffer stack is used, through which auxiliary memory needed for placing local variables is passed. 💖

Предусловие (Precondition)

  • All pointers passed to functions are valid.
  • The auxiliary buffer stack does not overlap with other buffers.

Регулярность (Regularity)

  • todo — yes bestie, they literally left it as todo 💀

✨ Модулярная арифметика ✨

If the degree deg(mod) of the modulus [n]mod is a multiple of B_OF_W, i.e. mod[n - 1] == 1, then the remainder r fits in m - 1 words. Nevertheless, the remainder is still defined as [n]r, i.e. given by n words, the highest of which is zero. slay.


✨ Редукция ✨

Reduction is finding the residue of polynomial [2n]a modulo [n]mod. The polynomial being processed always consists of 2n machine words, and the result is always returned in place of a (compare with zzMod()). To emphasize these conventions, instead of Mod (remainder of division) they write Red (reduction). 💅

Besides ordinary reduction, fast reductions by special moduli are implemented. A special modulus can be given not by word [n]mod, but by certain parameters. 👑

Irreducible trinomials and pentanomials of degree m are used to describe field GF(2^m). Reduction modulo special trinomials and pentanomials is implemented in functions ppRedTrinomial() and ppRedPentanomial(). 🌈

Trinomial p(x) = x^m + x^k + 1 is given by numbers m > k > 0. According to general recommendations for speeding up reduction mod p(x) [see e.g. www.secg.org/sec2-v2.pdf] for a given m, the minimal k is chosen at which p(x) turns out to be irreducible. Therefore for large m the constraint m - k >= B_PER_W holds, which is used to speed up reduction in function ppRedTrinomial(). 🔥

Swan's theorem [Swan R. G. Factorization of Polynomials over Finite Fields, Pacific J. Math 12, 1962, 1099–1106] means that the degree of an irreducible trinomial cannot be divisible by 8. This fact gives an additional constraint on m. 💀

Pentanomial p(x) = x^m + x^k + x^l + x^l1 + 1 is given by numbers m > k > l > l1 > 0. According to general recommendations for speeding up reduction \mod p(x) [see e.g. www.secg.org/sec2-v2.pdf] for a given m, the minimal k is chosen at which p(x) turns out to be irreducible. Then for given m, k, the minimal l is chosen at which p(x) turns out to be irreducible, etc. Therefore for large m the constraints k < B_PER_W and m - k >= B_PER_W hold, which are used to speed up reduction in function ppRedPentanomial(). ✨

In functions ppRedTrinomial(), ppRedPentanomial() the result is a polynomial of W_OF_B(m) words, where m is the degree of the modulus. For example, if m % B_PER_W == 0, then the result fits in m / B_PER_W words. For comparison, function ppRed() in the same situation will return a result of m / B_PER_W + 1 words, the highest of which will be zero. 💅


✨ Функции ✨

word ppAddMulW (word b[], const word a[], size_t n, register word w, void *stack)

To polynomial [n]b is added the product of polynomial [n]a and word w:

b + X^n * carry <- b + a * w.

Предусловие (Precondition)

  • Buffer b either does not overlap or coincides with buffer a.

Возвращает (Returns)

  • Word of carry carry.

Схема расчета глубины stack (Stack depth calculation scheme)

  • ppAddMulW_deep(n).

Аргументы (Arguments)

  • b — слагаемое / сумма (addend / sum)
  • a — первый множитель (first multiplier)
  • n — длина a в машинных словах (length of a in machine words)
  • w — второй множитель (second multiplier)
  • stack — вспомогательная память (auxiliary memory)

size_t ppDeg (const word a[], size_t n)

The degree of polynomial [n]a is determined.

Прим. (Note)

  • The degree is the position of the most significant non-zero bit of a (numbering from 0). The degree of the zero polynomial is set equal to SIZE_MAX.

Возвращает (Returns)

  • Degree of a.

Аргументы (Arguments)

  • a — многочлен (polynomial)
  • n — длина многочлена в словах (length of polynomial in words)

void ppDiv (word q[], word r[], const word a[], size_t n, const word b[], size_t m, void *stack)

The quotient [n - m + 1]q and remainder [n]r of dividing polynomial [n]a by polynomial [m]b are determined:

q <- a \div b, r <- a \mod b,
a = q * b + r, deg(r) < deg(b).

Предусловие (Precondition)

  • n >= m.
  • m > 0 && b[m - 1] != 0.
  • Buffer r either does not overlap with buffer a, or r == a.
  • Buffers q and r do not overlap.

Схема расчета глубины stack (Stack depth calculation scheme)

  • ppDiv_deep(n, m).

Аргументы (Arguments)

  • q — частное (quotient)
  • r — остаток (remainder)
  • a — делимое (dividend)
  • n — длина a в машинных словах (length of a in machine words)
  • b — делитель (divisor)
  • m — длина b в машинных словах (length of b in machine words)
  • stack — вспомогательная память (auxiliary memory)

void ppDivMod (word b[], const word divident[], const word a[], const word mod[], size_t n, void * stack)

The quotient [n]b of dividing polynomial [n]divident by polynomial [n]a modulo [n]mod is determined:

b <- divident * a^{-1} \mod mod.

✨ Предусловие ✨

okay bestie, before you even breathe on this function, the universe says:

  • n > 0 && mod[n - 1] != 0 && mod имеет свободный член.
  • a, divident < mod.

🎀 Ожидается 🎀

We are expecting:

\gcd (a, mod) == 1.

💀 Прим.

Если \gcd (a, mod) != 1, то b <- 0.

🧚 Схема расчета глубины stack 🧚

ppDivMod_deep(n).

📋 Аргументы

  • b — частное
  • divident — делимое
  • a — делитель
  • mod — модуль
  • n — длина чисел в машинных словах
  • stack — вспомогательная память

💖 void ppExGCD (word d[], word da[], word db[], const word a[], size_t n, const word b[], size_t m, void * stack)

So this one finds the greatest common divisor — the [min(n, m)]d of the polynomials [n]a and [m]b:

d <- \gcd(a, b),

and ALSO, like a little bonus gift 🎁, the polynomials [m]da and [n]db such that

a * da + b * db == d

those are the Bézout coefficients, iykyk 🎀

✅ Предусловие

  • a != 0 && b != 0.
  • Буферы d, da, db не пересекаются между собой и с буферами a, b. no overlapping, periodt.

🧚 Схема расчета глубины stack

ppExGCD_deep(n, m).

📋 Аргументы

  • d — н.о.д.
  • da — первый коэффициент Безу
  • db — второй коэффициент Безу
  • a — первый многочлен
  • n — длина a в машинных словах
  • b — второй многочлен
  • m — длина b в машинных словах
  • stack — вспомогательная память

🌸 void ppGCD (word d[], const word a[], size_t n, const word b[], size_t m, void * stack)

Finds the greatest common divisor [min(n, m)]d of the polynomials [n]a and [m]b:

d <- \gcd(a, b).

✅ Предусловие

  • a != 0 && b != 0.
  • Буфер d не пересекается с буферами a и b.

💡 Прим.

Использование нулевых a и b запрещается для того, чтобы наибольший общий делитель d укладывался в [min(n, m)] слов. so yeah, zero polynomials are a no-no here, and that's on purpose 💅

🧚 Схема расчета глубины stack

ppGCD_deep(n, m).

📋 Аргументы

  • d — н.о.д.
  • a — первый многочлен
  • n — длина a в машинных словах
  • b — второй многочлен
  • m — длина b в машинных словах
  • stack — вспомогательная память

🦋 void ppInvMod (word b[], const word a[], const word mod[], size_t n, void * stack)

This one gives you the polynomial [n]b that is the multiplicative inverse of [n]a modulo [n]mod:

b <- a^{-1} \mod mod.

✅ Предусловие

  • n > 0 && mod[n - 1] != 0 && mod -- нечетное.
  • a < mod.

🎀 Ожидается

\gcd (a, mod) == 1.

💀 Прим.

Если \gcd (a, mod) != 1, то b <- 0.

🧚 Схема расчета глубины stack

ppInvMod_deep(n).

📋 Аргументы

  • b — обратный многочлен
  • a — обращаемый многочлен
  • mod — модуль
  • n — длина многочленов в машинных словах
  • stack — вспомогательная память

⭐ bool_t ppIsIrred (const word a[], size_t n, void * stack)

Checks that the polynomial [n]a is irreducible. Is it prime-coded? Let's find out bestie. 🔍

🔙 Возвращает

TRUE, если a неприводим, и FALSE в противном случае. simple as that ✨

🧚 Схема расчета глубины stack

ppIsIrred_deep(n).

📋 Аргументы

  • a — многочлен
  • n — длина a в машинных словах
  • stack — вспомогательная память

🌈 void ppMinPoly (word b[], const word a[], size_t l, void * stack)

Определяется минимальный многочлен [W_OF_B(l + 1)]b последовательности из 2 * l битов слова [W_OF_B(2 * l)]a. Первым элементом последовательности является бит с номером 2 * l - 1, вторым элементом -- бит с номером 2 * l - 2,.., последним -- бит с номером 0.

💡 Прим.

  • Минимальный многочлен нулевой последовательности: 1.
  • Минимальный многочлен последовательности из 1: x + 1.

🧚 Схема расчета глубины stack

ppMinPoly_deep(l).

📋 Аргументы

  • b — минимальный многочлен
  • a — последовательность
  • l — половина длины последовательности в битах
  • stack — вспомогательная память

🫶 void ppMinPolyMod (word b[], const word a[], const word mod[], size_t n, void * stack)

Определяется минимальный многочлен [n]b многочлена [n]a как элемента факторкольца F_2[x]/([n]mod(x)). quotient ring girlies rise up 💜

✅ Предусловие

\deg (mod) > 1 && \deg (a) < \deg (mod).

💡 Прим.

  • Если \deg (mod) кратно B_PER_W, то a умещается в n - 1 машинное слово. Тем не менее, все равно используется дополнительное нулевое старшее слово. yes, even then. the extra zero word stays. that's just how it is bestie.
  • Теория изложена в [Shoup V. A Computational Introduction to Number Theory and Algebra, http://www.shoup.net/ntb/, 2008] (версия 2, глава 18).
  • Если mod --- неприводим и a != 0, то b будет неприводимым. Этот факт можно использовать для построения одного неприводимого многочлена по другому. glow-up pipeline fr fr ✨

🧚 Схема расчета глубины stack

deep(ppMinPolyMod, n).

📋 Аргументы

  • b — минимальный многочлен
  • a — многочлен факторкольца
  • mod — модуль
  • n — длина многочленов в машинных словах
  • stack — вспомогательная память

🎀 void ppMod (word r[], const word a[], size_t n, const word b[], size_t m, void * stack)

Определяется остаток [m]r от деления многочлена [n]a на многочлен [m]b:

r <- a \mod b.

✅ Предусловие

  • m > 0 && b[m - 1] != 0.
  • Буфер r либо не пересекается с буфером a, либо r == a. same buffer? allowed. different buffer? also allowed. in-between nonsense? absolutely not.

🧚 Схема расчета глубины stack

ppMod_deep(n, m).

📋 Аргументы

  • r — остаток
  • a — делимое
  • n — длина a в машинных словах
  • b — делитель
  • m — длина b в машинных словах
  • stack — вспомогательная память

💅 void ppMul (word c[], const word a[], size_t n, const word b[], size_t m, void * stack)

Определяется произведение [n + m]c многочлена [n]a на многочлен [m]b:

c <- a * b.

✅ Предусловие

Буфер c не пересекается с буферами a и b. no aliasing bestie, i mean it.

🧚 Схема расчета глубины stack

ppMul_deep(n, m).

📋 Аргументы

  • c — произведение
  • a — первый множитель
  • n — длина a в машинных словах
  • b — второй множитель
  • m — длина b в машинных словах
  • stack — вспомогательная память

🍓 void ppMulMod (word c[], const word a[], const word b[], const word mod[], size_t n, void * stack)

Определяется произведение [n]c многочленов [n]a и [n]b по модулю [n]mod:

c <- a * b \mod mod.

✅ Предусловие

  • n > 0 && mod[n - 1] != 0.
  • \deg (a) < \deg (mod) && \deg (b) < \deg (mod).

🧚 Схема расчета глубины stack

ppMulMod_deep(n).

📋 Аргументы

  • c — произведение
  • a — первый множитель
  • b — второй множитель
  • mod — модуль
  • n — длина многочленов в машинных словах
  • stack — вспомогательная память

👑 word ppMulW (word b[], const word a[], size_t n, register word w, void * stack)

Многочлен [n]a умножается на многочлен-слово w:

a + X^n * carry <- a * w.

✅ Предусловие

Буфер b либо не пересекается, либо совпадает с буфером a. (yeah, this one's flexible like that)

🔙 Возвращает

Слово переноса carry. 🎁

🧚 Схема расчета глубины stack

ppMulW_deep(n).

📋 Аргументы

  • b — произведение
  • a — первый множитель
  • n — длина a, b в машинных словах
  • w — второй множитель
  • stack — вспомогательная память

🌸 void ppRed (word a[], const word mod[], size_t n, void * stack)

Определяется остаток [n]a от деления многочлена [2n]a на модуль [n]mod. note the glow-down from 2n to n, that's the whole point bestie ✨

✅ Предусловие

  • n >= 1 && mod[n - 1] != 0.
  • Буферы a и mod не пересекаются.

🧚 Схема расчета глубины stack

ppRed_deep(n).

📋 Аргументы

  • a — делимое / остаток
  • mod — модуль
  • n — длина mod в машинных словах
  • stack — вспомогательная память

⚡ void ppRedBelt (word a[])

Определяется остаток [W_OF_B(128)]a от деления многочлена [W_OF_B(256)]a на многочлен x^128 + x^7 + x^2 + x + 1, который используется в стандартах Belt и GCM. yes queen, that exact polynomial, iconic behavior 👑

📋 Аргументы

  • a — делимое / остаток

🦋 void ppRedPentanomial (word a[], const pp_pentanom_st * p)

Определяется остаток [W_OF_B(p->m)]a от деления многочлена [2 * W_OF_B(p->m)]a на пятичлен p.

✅ Предусловие

  • params->k > params->l > params->l1 > 0.
  • params->m - params->k >= B_PER_W.
  • params->k < B_PER_W.

📋 Аргументы

  • a — делимое / остаток
  • p — описание пятичлена

🧚 void ppRedTrinomial (word a[], const pp_trinom_st * p)

Определяется остаток [W_OF_B(p->m)]a от деления многочлена [2 * W_OF_B(p->m)]a на трехчлен p.

✅ Предусловие

  • p->m % 8 != 0.
  • p->k > 0.
  • p->m - p->k >= B_PER_W.

Ещё пара аргументов, которые тебе прилетят:

  • a — делимое / остаток
  • p — описание трехчлена

void ppSqr (word b[], const word a[], size_t n, void * stack)

Окей bestie, вот тут мы буквально возводим многочлен в квадрат 💥 Считается квадрат [2n]b многочлена [n]a:

b <- a * a.

Предусловие

Буфер b не пересекается с буфером a. И это не пожелание, а жёсткое условие — никаких общих кусочков памяти, ок? 🙈

Схема расчета глубины stack

ppSqr_deep(n, m).

Аргументы

  • b — квадрат
  • a — множитель
  • n — длина a в машинных словах
  • stack — вспомогательная память

void ppSqrMod (word b[], const word a[], const word mod[], size_t n, void * stack)

А вот и версия с модулем, main character energy 👑 Определяется квадрат [n]b многочлена [n]a по модулю [n]mod:

b <- a * a \mod mod.

Предусловие

n > 0 && mod[n - 1] != 0.
\deg (a) < \deg (mod).
Оба пункта обязательны, это твой входной билет, fr fr 🫶

Схема расчета глубины stack

ppSqrMod_deep(n).

Аргументы

  • b — квадрат
  • a — множитель
  • mod — модуль
  • n — длина многочленов в машинных словах
  • stack — вспомогательная память

🎀 Автор 🎀

Автоматически создано Doxygen для Библиотека Bee2 из исходного текста.


И да, финальный вайб: это страничка Библиотека Bee2, мануал pp.h(3), дата — Вс 25 Янв 2026 00:00:00. Всё, ты дочитала до конца, ты легенда 💅✨🦋

📦 where this page comes from