fix spelling

This commit is contained in:
2026-07-05 21:04:54 +03:00
parent 02eb7d5034
commit f7671826d4
+31 -31
View File
@@ -45,7 +45,7 @@ struct set *set_free(struct set *set);
### `set_new()`
Создаёт пустой объект `struct set` — контейнер для строк символов и их будущих hash-значений.
Из релизации:
Из реализации:
> internally struct set is just a bag of strings and their hash values.
@@ -81,7 +81,7 @@ set_add(s, "malloc@@GLIBC_2.2.5");
```
массив строк
| (Jenkins OATT)
| (Jenkins OAAT)
v
массив хэшей
| (qsort)
@@ -100,7 +100,7 @@ set-строка
### hash
Для каждого элемента (строки) высчитывается 32-битный хэш и обрезается до `bpp` младщих бит
Для каждого элемента (строки) высчитывается 32-битный хэш и обрезается до `bpp` младших бит
```c
unsigned mask = (1u << bpp) - 1;
@@ -109,7 +109,7 @@ set->sv[i].v = hash(set->sv[i].s) & mask;
В качестве хэш-функции используется `Jenkins OAAT`.
Получившийся массив сортируется по хэш значениям по возрастанию. При коллизии, печатается `warning: hash collision` в `stderr`
Получившийся массив сортируется по хэш-значениям по возрастанию. При коллизии печатается `warning: hash collision` в `stderr`
С помощью функции `uniqv()` в массиве остаются только уникальные значения, возвращаемое значение - размер массива после удаления повторов.
@@ -136,7 +136,7 @@ unsigned *v = {1, 3, 12, 8};
> `encode_golomb()` - main golomb encoding routine: package integers into bits.
Для сокращения длины итоговой строки применяется Rice-Golomb кодирование, которое позволяет с параметром `Mshift` записать число `n` как `n >> Mshift`, записанный последовательностью нулей и `n & 2^Mshift` записанный стандартным двоичным кодированием. Целая часть и остаток разделяется единичном битом.
Для сокращения длины итоговой строки применяется Rice-Golomb кодирование, которое позволяет с параметром `Mshift` записать число `n` как `n >> Mshift`, записанный последовательностью нулей, и `n & 2^Mshift`, записанный стандартным двоичным кодированием. Целая часть и остаток разделяются единичным битом.
`Mshift` выбирается как `bpp - log2(c) - 1`, т.к. при равномерном распределении `c` хэшей по диапазону `2^bpp`, средняя `delta` будет равна `2^bpp / c`
@@ -161,13 +161,13 @@ bits = 00 1 00101010
Алфавитом для кодирования является `0-9,a-z,A-Z`, но символ `Z` кодирует сразу 61, 62 и 63 следующим образом:
1. в битовую последовательность после кодированием `Z` добавляется 2 бита:
1. в битовую последовательность после кодирования `Z` добавляется 2 бита:
- `00` для 61
- `01` для 62
- `10` для 63
2. битовая последовательность продолжает кодироваться стандартным образом
Заметим, что данным образом невозможно получить поседовательность `ZZ`, т.к. символ `Z` требует двух старших бит выставленных в `11`
Заметим, что данным образом невозможно получить последовательность `ZZ`, т.к. символ `Z` требует двух старших бит, выставленных в `11`
Пример преобразования:
@@ -188,7 +188,7 @@ bits = 101111 001000 10
101111 = 1*1 + 0*2 + 1*4 + 1*8 + 1*16 + 1*32 = 61 = Z
```
Тогда в последовательность добавляется два бита `00` сразу после бит, кодирующих Z.
Тогда в последовательность добавляется два бита `00` сразу после битов, кодирующих Z.
```
bits = 101111 000010 0010
@@ -204,7 +204,7 @@ bits = 101111 000010 0010
## Сравнение set-строк
При сравнении set-строк происходит обратный процесс преобразования до получений хэш-значений
При сравнении set-строк происходит обратный процесс преобразования до получения хэш-значений
```
set-строка
@@ -229,7 +229,7 @@ set-строка
4. для каждого массива хэшей (`v1` и `v2`) создаётся два буферных массива `v(1|2)buf(A|B)` для функции `downsample_set()`
5. С помощью функции `downsample_set()` `bpp` обоих хэшей выравнивается до минимального из `bpp1` и `bpp2`.
6. Создаётся два флага `ge` и `le`, для определения вложенности множеств
7. Вложенность множеств проверяется с помощью 3х макросов: `IFGE` `IFLT4` `IFLT8`
7. Вложенность множеств проверяется с помощью трёх макросов: `IFGE` `IFLT4` `IFLT8`
8. Возвращается значение в зависимости от вложенности:
- 1: set1 > set2
- 0: set1 == set2
@@ -244,7 +244,7 @@ set-строка
### `decode_base62_golomb()`
`decode_base62_golomb()` - оптимизированная версия стадий `decode_base62` и `decode_golomb`. Функция считывает сразу по два байта, пользуясь таблицей `word_to_num` преобразовывает их в битовую последовательность, после, набирая до 24х байт, декодирует по Rice-Golomb.
`decode_base62_golomb()` - оптимизированная версия стадий `decode_base62` и `decode_golomb`. Функция считывает сразу по два байта, с помощью таблицы `word_to_num` преобразует их в битовую последовательность, затем, набирая до 24 бит, декодирует по Rice-Golomb.
#### `enum`
@@ -273,37 +273,37 @@ enum {
static const unsigned short word_to_num[65536];
```
pre-compiled таблица соответствия любой комбинации из двух байт, битовому представлению из 12 символов + возможный флаг
Предварительно скомпилированная таблица соответствия любой комбинации из двух байт с битовым представлением из 12 бит + возможный флаг
Таблица строится следующим образом:
1. все значения заполняются `W_EE` как ошибоные
1. все значения заполняются `W_EE` как ошибочные
2. с помощью макроса `AA1` строятся макросы `AA1x2`, `AA1x25` и т.д. вплоть до `AA10x10` и ему аналогичных.
- итоговые макросы позволяют быстро заполнить таблицу значениями `[CCI(c1, c2)] = (c1 - b1) | ((c2 - b2) << 6)`
3. аналогичный процесс заполнения для `AZ`, но с добавлением флага `W_AZ` к значениям в таблице.
4. заполняется таблица для `ZA` значений с флагом `W_ZA`. Невозможности старших бит `11` во втором символе (т.е. символы с 48 номера) проверяется лишь внутри функций, `W_EE` для таких значений не возвращается
4. заполняется таблица для `ZA` значений с флагом `W_ZA`. Недопустимость старших бит `11` во втором символе (т.е. символы со значения 48) проверяется лишь внутри функций, `W_EE` для таких значений не возвращается
5. заполняется таблица для `A0` и `0X` значений с флагами `W_A0` и `W_0X` соответственно.
#### Считывание
Функция считывает с помощью макросов `GetXX` несколько бит (стандартно блоками до 24х бит) и передаёт их на декодирование
Функция считывает с помощью макросов `GetXX` несколько бит (стандартно блоками до 24 бит) и передаёт их на декодирование
при 24 битах:
- берутся именно 4 base62-символа (по два пары)
- берутся именно 4 base62-символа (две пары)
- значение помещается в 32-битный `unsigned`
- при ограничении `Mshift >= 7` в одну последовательность может поместиться максимум 3 закодированных golomb числа.
- при ограничении `Mshift >= 7` в одну последовательность может поместиться максимум 3 закодированных Golomb-числа.
"12 бит" считыватель используется в ситуациях, когда первая пара обычная, а вторая содержит специальный случай
"10 бит" считыватель используется в ситуциях с Z-escape
"10 бит" считыватель используется в ситуациях с Z-escape
"6 бит" считыватель используется для одного символа.
#### Rice-Golomb декодер
Декодер постоянно находится в двух состояних:
Декодер постоянно находится в двух состояниях:
- `q-state`: ищет unary-префикс и разделительную `1`
- `r-state`: добирает Mshift бит остатка `r`
@@ -318,9 +318,9 @@ value = (q << Mshift) | r;
Для обработки Z-escape используются макросы `Esc1` и `Esc2`.
`Esc1` вызывается при обнаружении `Z` символа и считывает старшие 2 бита у следующего символа. В результате `Esc1` получит 10 бит для golumb-декодера
`Esc1` вызывается при обнаружении символа `Z` и считывает старшие 2 бита у следующего символа. В результате `Esc1` получает 10 бит для Golomb-декодера
`Esc2` вызывается после завершения escape-пары и решает что делать дальше:
`Esc2` вызывается после завершения escape-пары и решает, что делать дальше:
- обычный символ — обработать 6 бит
- конец строки — завершить декодирование
@@ -329,9 +329,9 @@ value = (q << Mshift) | r;
#### `QMake` и `RMake` макросы
`QMake` ищет разделительную единицу в текущем блоке бит. Если блок содержит только нули, все они добавляются к q, после чего функция читает следующий блок.
`QMake` ищет разделительную единицу в текущем блоке бит. Если блок содержит только нули, все они добавляются к `q`, после чего функция читает следующий блок.
Если в блоке есть единица, используется `__builtin_ffs(bits)` для определеия позиции первого бита, разделительной для golomb-кода. Оставшиеся биты заполняют r.
Если в блоке есть единица, используется `__builtin_ffs(bits)` для определения позиции первого бита, разделительной для Golomb-кода. Оставшиеся биты заполняют `r`.
`RMake` проверяет, набралось ли `Mshift` бит остатка, записывает готовое значение
@@ -360,7 +360,7 @@ value = (q << Mshift) | r;
unsigned hash = str[0] | (str[2] << 8) | (str[3] << 16);
```
массивы `hv` и `ev` представляют из себя аналог LRU кэша размером `CACHE_SIZE=256`.
массивы `hv` и `ev` представляют собой аналог LRU-кэша размером `CACHE_SIZE=256`.
Если fingerprint set-строки на декодирование совпал с имеющимся в `hv` массиве, проверяется полное соответствие строки с `ev[i]->str`. В случае hit - элемент помещается на нулевую позицию, остальные элементы сдвигаются.
При неудачной проверке полной set-строки, поиск по кэшу продолжается.
@@ -370,9 +370,9 @@ unsigned hash = str[0] | (str[2] << 8) | (str[3] << 16);
- Если кэш не заполнен, декодируемая строка записывается на первую свободную позицию
- Если кэш заполнен, элемент ставится на `PIVOT_SIZE=243` позицию, элементы с этой позиции сдвигаются.
#### `SENTINELS` биты
#### `SENTINELS` значения
Данные `~0u` биты необходимы при дальнейшем проходе по массиву внутри функции `rpmsetcmp()`, т.к. там происходят прыжки по 4 и 8 элементов.
Данные `~0u` значения необходимы при дальнейшем проходе по массиву внутри функции `rpmsetcmp()`, т.к. там происходят прыжки по 4 и 8 элементов.
### `downsample_set()`
@@ -382,7 +382,7 @@ unsigned hash = str[0] | (str[2] << 8) | (str[3] << 16);
Итоговый массив будет доступен по указателю `w`.
Возвращаемое значение - количество элементов в новом массиве `w`.
Т.к. первоначальный входной массив отсортирован, после обрезания до `bpp` бит, массив будет поделён на две части, обе из которых будут отсортированны. Деление массива будет происходить в месте, где старший бит на позции `bpp+1` становится равным `1`.
Т.к. первоначальный входной массив отсортирован, после обрезания до `bpp` бит массив будет поделён на две части, обе из которых будут отсортированы. Деление массива будет происходить в месте, где старший бит на позиции `bpp+1` становится равным `1`.
Далее обе половины массива объединяются в буфере `w`, дубликаты значений удаляются.
@@ -401,7 +401,7 @@ return value = 5
#### Макросы `IFLT*`
`IFLT8` быстро продвигают `v1`, пока `*v1 < v2val`. Сперва макрос "грубо" прыгает по 8 элементов, далее уточняет с шагом 4, 2, 1.
`IFLT8` быстро продвигает `v1`, пока `*v1 < v2val`. Сперва макрос "грубо" прыгает по 8 элементов, далее уточняет с шагом 4, 2, 1.
```text
+8 +8 +8 ... // грубый поиск
@@ -434,11 +434,11 @@ ge = 0;
v2++;
```
## `SEFT_TEST` флаг
## `SELF_TEST` флаг
При выставленном `SEFT_TEST` флаге происходит следующее:
При выставленном `SELF_TEST` флаге происходит следующее:
1. Явно отклчючается `NDEBUG` для работы `assert()`
1. Явно отключается `NDEBUG` для работы `assert()`
2. Компилируются `test_*` функции
3. Компилируется `main()`, запускающая все `test_*` функции