qr.h(3)

📦
version 2.2.0 · 2 versions
, in fedora 44

🎀 NAME 🎀

okay so bestie, gather round 💖 this is qr.h — the Кольца вычетов header, aka residue rings ✨. It lives in the Library Functions Manual, section 3 (yes, the C-library section, we love a section 3 moment 👑). If you're messing with modular arithmetic and ring vibes, this is literally your girl.


🌈 SYNOPSIS 🌈

first things first, you gotta pull in the includes, no cap:

#include 'bee2/defs.h'
#include 'bee2/core/mem.h'
#include 'bee2/core/obj.h'

then we got classes, typedefs and functions — the whole trio, the holy trinity, the vibe check 💅

🦋 Классы (Classes) 🦋

  • struct qr_o — Описание кольца вычетов — like, a whole description of a residue ring. this struct is the blueprint, the main character 🫶

✨ Определения типов (Typedefs) ✨

okay this is the part where the ring gets pluggable — every single one of these is a function-pointer type that says "here's how you do THIS operation inside a residue ring". obsessed.

  • qr_from_i — Импорт элемента кольца вычетов — import of an element of the residue ring:
typedef bool_t(* qr_from_i) (word b[], const octet a[], const struct qr_o *r, void *stack)
  • qr_to_i — Экспорт элемента кольца вычетов — export of an element of the residue ring:
typedef void(* qr_to_i) (octet b[], const word a[], const struct qr_o *r, void *stack)
  • qr_add_i — Сложение в кольце вычетов — addition in the residue ring:
typedef void(* qr_add_i) (word c[], const word a[], const word b[], const struct qr_o *r)
  • qr_sub_i — Вычитание в кольце вычетов — subtraction in the residue ring:
typedef void(* qr_sub_i) (word c[], const word a[], const word b[], const struct qr_o *r)
  • qr_neg_i — Аддитивное обращение в кольце вычетов — additive inversion in the residue ring:
typedef void(* qr_neg_i) (word b[], const word a[], const struct qr_o *r)
  • qr_mul_i — Умножение в кольце вычетов — multiplication in the residue ring:
typedef void(* qr_mul_i) (word c[], const word a[], const word b[], const struct qr_o *r, void *stack)
  • qr_sqr_i — Возведение в квадрат в кольце вычетов — squaring in the residue ring:
typedef void(* qr_sqr_i) (word b[], const word a[], const struct qr_o *r, void *stack)
  • qr_inv_i — Мультипликативное обращение в кольце вычетов — multiplicative inversion in the residue ring:
typedef void(* qr_inv_i) (word b[], const word a[], const struct qr_o *r, void *stack)
  • qr_div_i — Деление в кольце вычетов — division in the residue ring:
typedef void(* qr_div_i) (word b[], const word divident[], const word a[], const struct qr_o *r, void *stack)
  • qr_o — Описание кольца вычетов — the struct qr_o itself, typedef'd, because we keep it cute and convenient:
typedef struct qr_o qr_o

💖 Функции (Functions) 💖

and now the actual calls you're gonna be making, bestie:

  • bool_t qrIsOperable(const qr_o *r) — Описание кольца вычетов работоспособно? — is this residue-ring description actually operable? like, does it work? vibe check on the ring 🩺✨
  • void qrPower(word c[], const word a[], const word b[], size_t m, const qr_o *r, void *stack) — Возведение в степень в кольце вычетов — exponentiation in the residue ring. go off, raise that thing to a power 🔥

<div style="display:none">and that's where part one wraps, no goodbye yet</div>

that's chunk one, bestie — the ring's whole personality is on the table, and there's more where that came from

💖 Подробное описание 💖

окей бести, ща будет математика, но она красивая, обещаю.

Пусть R — кольцо, I — его идеал. Кольцом вычетов называется кольцо R / I, в котором сложение и умножение элементов выполняются по модулю I:

(a + I) + (b + I) = (a + b) + I, (a + I) * (b + I) = (a * b) + I.

В интересующих нас случаях кольцо R является коммутативным, а идеал I — главным, т.е. порожденным единственным элементом mod ∈ R: I = (mod) = {mod * a: a ∈ R}. В этих случаях приведение по модулю I состоит в редукции (определении вычета) по модулю mod.

Кольцо вычетов описывается структурой типа qr_o.


🌸 Структура qr_o проектировалась с прицелом на поддержку следующих колец 🌸

  • R = Z, mod = n — произвольное натуральное [кольцо вычетов целых чисел ZZ_n];
  • R = Z, mod = p — простое число [простое поле GF(p)];
  • R = GF(2)[x], mod = f(x) — неприводимый многочлен степени e [поле GF(2^e)].

В этих кольцах может применяться умножение Монтгомери, умножение в нормальном базисе и другие ускоренные мультипликативные операции. Особенные операции требуют особенного описания кольца и особенного представления его элементов. В связи с этим вводится структура qr_o, которая задает:

  • описание кольца вычетов;
  • описание элементов кольца;
  • интерфейсы арифметических операций в кольце.

Идеал I описывается модулем mod. Для ускорения редукции по модулю mod могут использоваться параметры params. Параметры params могут рассчитываться по mod при создании кольца, могут дублировать mod, или заменять его. Параметры params имеют самостоятельное значение и могут использоваться не только для редукции. iykyk ✨

Элемент кольца представляется массивом из n машинных слов. Размерность n определяется при построении кольца и сохраняется в его описании.

Нулевому элементу всегда соответствует нулевой массив.

Мультипликативные единицы могут отличаться. Мультипликативная единица unity инициализируется при построении кольца.

Размерность модуля mod жестко не регламентируется. Эта размерность определяется в функциях работы с элементами кольца по params и (или) n. В кольцах чисел mod задается n словами. Если mod = 2^{B_PER_W * (n - 1)}, то последнее слово mod равняется 1, а последние слова элементов поля всегда равняются 0. В кольцах многочленов mod задается n или n + 1 словом (в зависимости от выполнения равенства deg(mod) == B_PER_W * n).

Элементы кольца экспортируются в строки октетов и импортируются из этих строк. Длина строки no определяется при построении кольца и сохраняется в его описании. Для экспорта / импорта элементов кольца используются функции типов qr_to_i, qr_from_i. Способ определения длины строки указывается при описании колец конкретных типов. Нулевому элементу обязательно соответствует нулевая строка.

Аддитивные операции в кольце, как правило, не меняются при различных его описаниях. Тем не менее, в структуру qr_o включены функции интерфейсов qr_add_i, qr_sub_i и qr_neg_i, которые определяют аддитивные операции.

Мультипликативные операции в кольце задаются интерфейсами qr_mul_i и qr_sqr_i.

Некоторые элементы кольца допускают мультипликативное обращение и, следовательно, определенные пары элементов можно делить друг на друга. Обращение и деление поддерживается интерфейсами qr_inv_i, qr_div_i.

Описание кольца организовано как объект, и можно применять функции, описанные в заголовочном файле obj.h. 💅


🎀 Создание кольца 🎀

Кольцо должно создаваться специальной функцией qrCreate(), которая является аналогом конструктора. В эту функцию должен передаваться указатель r на структуру типа qr_o. По этому указателю будет размещаться описание (состояние) кольца. По адресу r может быть зарезервировано больше памяти, чем sizeof(qr_o). Дело в том, что значения mod, unity, params могут размещаться в поле descr открытого размера. Функция qrCreate() должна сопровождаться функцией qrCreate_keep(), которая поддерживает расчет длины состояния (в октетах).

Функция qrCreate_keep() должна оценивать длину состояния сверху. Оценка может быть неточной. Точная длина состояния фиксируется при непосредственном выполнении qrCreate() и сохраняется в поле keep описания кольца.

В функцию qrCreate() должен передаваться указатель на память для стека. Функция qrCreate() должна сопровождаться функцией qrCreate_deep(), которая выполняет расчет глубины стека. При расчете глубины следует предполагать, что в qrCreate() явно или неявно вызываются все функции кольца. Получив результат работы qrCreate_deep(), внешние программы могут определить, сколько вспомогательной памяти потребуется при всевозможных способах работы с кольцом.

В описании qrCreate() должны быть даны оценки сверху для размерностей n и no. Эти оценки могут использоваться высокоуровневыми функциями при подготовке памяти для размещения элементов кольца.

Оценка глубины стека, определяемая функцией qrCreate_deep(), может быть неточной. Точная глубина фиксируется при непосредственном выполнении qrCreate() и сохраняется в поле deep описания кольца. ✨


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

  • Все указатели действительны.
  • Буферы элементов кольца или их кодовых представлений не пересекаются с буферами, поддерживающими описание кольца.

⚠️ Предупреждения ⚠️

В интерфейсах мультипликативных функций не предполагается, что буфер результата либо не пересекается, либо совпадает с буферами входных элементов. так что не надейся, бести, следи за буферами сама 😭

🦋 Регулярность 🦋

todo

(да, буквально todo. не я это придумала, это в исходнике, не стреляйте в пианистку 🫶)

🌈 ТИПЫ ✨ (Types)

okay bestie, this is the type zoo and honestly? it ate. 🦋 Every one of these is a function-pointer type that a ring description qr_o hands you so you can actually do math in the residue ring. The contract is: you give it the buffers, it does the thing. Let's go one by one, no skipping. 💅


qr_add_i 💖

typedef void(* qr_add_i) (word c[], const word a[], const word b[], const struct qr_o *r)

The sum of the [r->n]c elements of [r->n]a and [r->n]b in the residue ring r gets computed:

c <- a + b.

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

  • The ring description r is operable.
  • The buffer c either doesn't overlap, or coincides with each of the buffers a, b.
  • The elements a and b belong to r.

Expected (Ожидается) ✨

  • The ring description r is correct.

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

  • c — the sum
  • a — the first addend
  • b — the second addend
  • r — the ring description

qr_div_i 🌸

typedef void(* qr_div_i) (word b[], const word divident[], const word a[], const struct qr_o *r, void *stack)

The quotient [r->n]b from dividing the element [r->n]divident by the element [r->n]a in the residue ring r gets computed:

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

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

  • The ring description r is operable.
  • The elements divident and a belong to r.

Expected (Ожидается) ✨

  • The ring description r is correct.

Expected (Ожидается) ✨

  • The element a is invertible. If a is not invertible, then b may be anything.

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

  • b — the quotient
  • divident — the dividend
  • a — the divisor
  • r — the ring description
  • stack — auxiliary memory

qr_from_i 🧚

typedef bool_t(* qr_from_i) (word b[], const octet a[], const struct qr_o *r, void *stack)

From the code representation [r->no]a, the element [r->n]b of the residue ring r gets built.

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

  • The ring description r is operable.
  • The buffers a and b either don't overlap, or the pointers a and b coincide.

Expected (Ожидается) ✨

  • The ring description r is correct.

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

  • TRUE if the code representation is correct and the import was performed successfully, and FALSE otherwise.

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

  • b — the ring element
  • a — the code representation of the ring element
  • r — the ring description
  • stack — auxiliary memory

qr_inv_i 👑

typedef void(* qr_inv_i) (word b[], const word a[], const struct qr_o *r, void *stack)

The element [r->n]b of the ring r gets computed, multiplicatively inverse to the element [r->n]a:

b <- a^{-1}.

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

  • The ring description r is operable.
  • The element a belongs to r.

Expected (Ожидается) ✨

  • The ring description r is correct.

Expected (Ожидается) ✨

  • The element a is invertible. If a is not invertible, then b may be anything.

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

  • b — the inverse element
  • a — the element being inverted
  • r — the ring description
  • stack — auxiliary memory

qr_mul_i 🔥

typedef void(* qr_mul_i) (word c[], const word a[], const word b[], const struct qr_o *r, void *stack)

The product [r->n]c of the elements [r->n]a and [r->n]b of the residue ring r gets computed:

с <- a * b.

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

  • The ring description r is operable.
  • The elements a and b belong to r.

Expected (Ожидается) ✨

  • The ring description r is correct.

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

  • c — the product
  • a — the first factor
  • b — the second factor
  • r — the ring description
  • stack — auxiliary memory

qr_neg_i 🌙

typedef void(* qr_neg_i) (word b[], const word a[], const struct qr_o *r)

The element [r->n]b of the ring r gets computed, additively inverse to [r->n]a:

b <- -a.

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

  • The ring description r is operable.
  • The buffer b either doesn't overlap, or coincides with the buffer a.
  • The element a belongs to r.

Expected (Ожидается) ✨

  • The ring description r is correct.

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

  • b — the inverse element
  • a — the element being inverted
  • r — the ring description

qr_o 💅

typedef struct qr_o qr_o

This is the whole vibe: it describes a residue ring, the rules for representing its elements, and the functions that implement the operations in the ring. main character energy fr. 👑

Note (Прим.) ⭐

  • The table of pointers of the ring description, as an object, includes the fields mod, unity, params.

qr_sqr_i 🌸

typedef void(* qr_sqr_i) (word b[], const word a[], const struct qr_o *r, void *stack)

The square [r->n]b of the element [r->n]a of the ring r gets computed:

с <- a * a.

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

  • The ring description r is operable.
  • The element a belongs to r.

Expected (Ожидается) ✨

  • The ring description r is correct.

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

  • b — the square
  • a — the factor
  • r — the ring description
  • stack — auxiliary memory

qr_sub_i 🍓

typedef void(* qr_sub_i) (word c[], const word a[], const word b[], const struct qr_o *r)

The difference [r->n]c of the elements [r->n]a and [r->n]b of the residue ring r gets computed:

c <- a - b.

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

  • The ring description r is operable.
  • The buffer c either doesn't overlap, or coincides with each of the buffers a, b.
  • The elements a and b belong to r.

Expected (Ожидается) ✨

  • The ring description r is correct.

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

  • c — the difference
  • a — the minuend
  • b — the subtrahend
  • r — the ring description

qr_to_i 🦋

typedef void(* qr_to_i) (octet b[], const word a[], const struct qr_o *r, void *stack)

The code representation [r->no]b of the element [r->n]a of the residue ring r gets built.

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

  • The ring description r is operable.
  • The buffers a and b either don't overlap, or the pointers a and b coincide.

Expected (Ожидается) ✨

  • The ring description r is correct.

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

  • b — the code representation of the ring element
  • a — the ring element
  • r — the ring description
  • stack — auxiliary memory

💫 ФУНКЦИИ ✨ (Functions)

okay two functions, both iconic, let's get into it. 😤

qrIsOperable 🔍

bool_t qrIsOperable (const qr_o * r)

It checks the operability of the ring description r. The following conditions get checked:

  • the object r is operable;
  • objKeep(r) >= sizeof(qr_o);
  • objPCount(r) == 3 && objOCount(r) == 0;
  • the pointer r->unity is correct;
  • r->n > 0 && r->no > 0;
  • the pointers r->from, r->to, ..., r->div are correct.

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

  • The operability flag.

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

  • r — the ring description

qrPower ⚡

void qrPower (word c[], const word a[], const word b[], size_t m, const qr_o * r, void * stack)

In the residue ring r, the element [r->n]c gets computed, which is the [m]b-th power of the element [r->n]a:

c <- a^b.

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

  • The ring description r is operable.
  • The element a belongs to r.

Expected (Ожидается) ✨

  • The ring description r is correct.

Note (Прим.) ⭐

  • When b == 0, r->unity gets returned.

Scheme for computing the depth of stack (Схема расчета глубины stack) 🌊

qrPower_deep(r->n, m, r->deep).

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

  • c — the power
  • a — the base
  • b — the exponent
  • m — the length of b in machine words
  • r — the ring description
  • stack — auxiliary memory

🫶 АВТОР ✨ (Author)

Automatically generated by Doxygen for the Bee2 Library from the source text. not me getting auto-generated 😭 still iconic tho.


okay bestie that's the whole page, we made it, and lowkey it was a journey. 💖 This one came from the Bee2 Library, dated Вс 25 Янв 2026 00:00:00 (that's Sunday, January 25, 2026, 00:00:00 for the calendar girlies 🗓️✨), and it lives at qr.h(3). slay, go forth and do ring math responsibly, periodt. 💅🌈

📦 where this page comes from