pp.h(3)
✨ 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
stackdoes not overlap with other buffers.
Регулярность (Regularity)
todo— yes bestie, they literally left it astodo💀
✨ Модулярная арифметика ✨
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
beither does not overlap or coincides with buffera.
Возвращает (Returns)
- Word of carry
carry.
Схема расчета глубины stack (Stack depth calculation scheme)
ppAddMulW_deep(n).
Аргументы (Arguments)
b— слагаемое / сумма (addend / sum)a— первый множитель (first multiplier)n— длинаaв машинных словах (length ofain 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 toSIZE_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
reither does not overlap with buffera, orr == a. - Buffers
qandrdo not overlap.
Схема расчета глубины stack (Stack depth calculation scheme)
ppDiv_deep(n, m).
Аргументы (Arguments)
q— частное (quotient)r— остаток (remainder)a— делимое (dividend)n— длинаaв машинных словах (length ofain machine words)b— делитель (divisor)m— длинаbв машинных словах (length ofbin 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
- fedora 44: bee2-devel 2.2.0-1.fc44 · GPL-3.0-only and GPL-3.0-or-later
- fedora 44: bee2-devel 2.2.0-1.fc44 · GPL-3.0-only and GPL-3.0-or-later
- 💖 girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms