diff --git a/Docs/set:version.md b/Docs/set:version.md index 019db87..fcf306c 100644 --- a/Docs/set:version.md +++ b/Docs/set:version.md @@ -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 ... // грубый поиск @@ -427,18 +427,18 @@ return value = 5 То есть текущий элемент `v2val` есть во втором множестве, но отсутствует в первом. -Следовательно `v1` уже не может быть над множеством `v2`: +Следовательно `v1` уже не может быть надмножеством `v2`: ```c ge = 0; v2++; ``` -## `SEFT_TEST` флаг +## `SELF_TEST` флаг -При выставленном `SEFT_TEST` флаге происходит следующее: +При выставленном `SELF_TEST` флаге происходит следующее: -1. Явно отклчючается `NDEBUG` для работы `assert()` +1. Явно отключается `NDEBUG` для работы `assert()` 2. Компилируются `test_*` функции 3. Компилируется `main()`, запускающая все `test_*` функции