Этот репозиторий является частью проекта контроллера NAND Flash на основе LDPC.
За последние годы низкоденные коды проверочной суммы (Low-Density Parity-Check Codes, LDPC) получили широкое признание благодаря относительно низкой сложности кодирования/декодирования и отличной способности к исправлению ошибок. При одинаковой длине кода и скорости кодирования, производительность LDPC-кодов над полем Галуа превосходит производительность двоичных LDPC-кодов. Этот набор предназначен для решения задач аппаратного кодирования/декодирования LDPC и выполняет следующие действия:* Библиотека для вычислений над полями Галуа и операций с матрицами над этими полями, которая позволяет выполнять вычисления в полях различных порядков и с различными примитивными многочленами, а также генерировать таблицы умножения.
Чтобы создать кодирующую матрицу, используются несколько малых матриц размером n x n
, где диагональные элементы случайны. Эти малые матрицы располагаются в большую матрицу H
таким образом, что каждая строка содержит r
таких матриц, а каждый столбец — c
. Схематическое представление показано ниже:
Наша кодирующая матрица основана на циклическом правом сдвиге большой матрицы H
. Для этого требуется выполнение следующих шагов:
i
малых матриц.j
позиций (циклический сдвиг — это перемещение каждого ненулевого элемента вправо до соседней позиции; если элемент уже находится справа, он перемещается обратно в начало).H
. Если количество четырёхциклов минимально, эта матрица временно сохраняется.
Цикл продолжается до достижения условия прекращения, которое может зависеть от конкретной ситуации. В наших экспериментах, когда число столбцов матрицы H
равно 256, можно быстро найти матрицу с количеством четырёхциклов равным нулю. Поэтому условием прекращения является достижение нуля количества четырёхциклов.### Соответствующий код
Заголовочный файл genH.h
содержит класс-генератор HGenerator
, который используется для создания кодирующей матрицы. Перед использованием необходимо установить параметры пространства имён genH
для указания размера требуемой кодирующей матрицы.Параметры включают:
diagSize
H
— cNum
H
— rNum
Затем создается объект-генератор, который позволяет начать генерацию кодирующей матрицы. В созданном объекте диагональные элементы малых матриц равны единице. Такое начальное условие используется потому что некоторые считают, что сначала следует уменьшить количество четырёхциклических матриц в GF(2), а затем случайным образом заменять диагональные элементы на фактические элементы GF(n). Это основано на том, что возможно существуют некоторые замены от GF(n) до которых невозможно достичь минимального количества четырёхциклических матриц. Поэтому можно оптимизировать несколько различных случайных замен на основе оптимизированной GF(2) и выбрать лучший вариант. Однако в наших экспериментах при количестве столбцов матрицы H равном 256, все попытки замены быстро привели к матрице с нулевым количеством четырёхциклических матриц. Таким образом, прямая замена на GF(n) также возможна и это значительно увеличивает скорость оптимизации.Пример кода для создания кодирующей матрицы с использованием генератора:HGenerator hg;
hg.permutationGF(); // замена на элементы GF(n)
uint usefulNum;
for(int i = 0; true; i++)
{
if(hg.moveDetection())
usefulNum = i;
if(hg.tetracyclicNum == 0)
break; // выход из цикла при достижении нулевого количества четырехциклических матриц
}
std::cout << "usefulNum" << usefulNum << std::endl;
matIO::saveMatFile("D:/result.csv", hg.getH()); // сохранение матрицы
На основе полученной нижней треугольной кодирующей матрицы H
, мы можем закодировать сообщение. Сначала необходимо разделить H
следующим образом:
Затем используйте следующее уравнение для вычисления проверочных битов p1
и p2
(информационные биты — s
):
Раскрыв уравнение, можно заметить, что некоторые промежуточные шаги могут быть кэшированы для ускорения выполнения. В реальном процессе кодирования требуются матрицы Φi + E · Ti + C
, Ti · A
, Ti · B
(где i
представляет обратную матрицу; в конечном поле сложение противоположных значений остается тем же значением, поэтому все минусы убраны). Поэтому эти матрицы вычисляются заранее. Соответствующий код представлен ниже:
// Вычисляем матрицы заранее
Matrix Phi_i_plus_E_Ti_C = calculatePhiETiC(i);
Matrix Ti_A = calculateTiA(i);
Matrix Ti_B = calculateTiB(i);
// Кодируем сообщение
vector<int> encodedMessage = encode(s, Phi_i_plus_E_Ti_C, Ti_A, Ti_B);
Для декодирования сообщения используется обратная процедура. Декодирование начинается с вычисления информационных битов s
из закодированного сообщения и проверочных битов p1
и p2
.```cpp
matrix H = matIO::ReadMatFile("D:/H(339x3070).csv", 339, 3070); // чтение кодирующей матрицы из файла
cLength = H.getc();
sLength = cLength - H.getr();
uint g = H.getr() - 113; // параметр g для разделения должен быть указан вручную, здесь он равен 113
uint mg = H.getr() - g;
uint nm = H.getc() - H.getr();
matrix T = H.cut(nm + g, 0, H.getc() - 1, mg - 1);
matrix Ti = T.inv();
matrix E = H.cut(nm + g, mg, H.getc() - 1, H.getr() - 1);
matrix B = H.cut(nm, 0, nm + g - 1, mg - 1);
matrix D = H.cut(nm, mg, nm + g - 1, H.getr() - 1);
matrix fi = E.dot(Ti);
fi = fi.dot(B);
fi = fi.add(D);
matrix fii = fi.inv();
fii.dot(fi).output();
matrix C = H.cut(0, mg, nm - 1, H.getr() - 1);
// Вычисление требуемых значений
matrix fii_ETiA_C = E.dot(Ti).dot(A).add(C);
fii_ETiA_C = fii.dot(fii_ETiA_C); // Здесь ранее был оператор взятия обратной компоненты поэлементно, но так как это не влияло на результат, его убрали
matrix TiA = Ti.dot(A); // Здесь ранее был оператор взятия обратной компоненты поэлементно, но так как это не влияло на результат, его убрали
matrix TiB = Ti.dot(B); // Здесь ранее был оператор взятия обратной компоненты поэлементно, но так как это не влияло на результат, его убрали
`fii_ETiA_C`, `TiA`, `TiB` являются искомыми значениями.
Затем можно приступить к кодированию, соответствующий код представлен ниже:
```cpp
matrix sT = s.transpose(); // s — сообщение
matrix p1T = fii_ETiA_C.dot(sT);
matrix ii = TiA.dot(sT);
matrix ii2 = TiB.dot(p1T);
matrix p2T = ii.add(ii2);
p1T
, p2T
являются искомыми значениями.
Имея информационные биты и проверочные биты, можно получить закодированное слово:
matrix c(1, cLength);
for (uint i = 0; i < sLength; i++) // Копирование информационных битов по одному
c.m[0][i] = s.m[0][i];
for (uint i = sLength; i < sLength + p1.getc(); i++) // Проверочный бит 1
c.m[0][i] = p1.m[0][i - sLength];
const uint offset2 = sLength + p1.getc();
for (uint i = offset2; i < cLength; i++) // Проверочный бит 2
c.m[0][i] = p2.m[0][i - offset2];
c
является закодированным словом.Согласно литературе по LDPC-кодированию, только когда вектор ( H \cdot c^T ) (где ( T ) представляет транспонированный матричный) равен нулевому вектору, возможно правильное декодирование. Это зависит от корректности матрицы кодирования ( H ). После того, как мы сгенерируем ( H ), обычно случайным образом генерируются некоторые сообщения для кодирования, после чего вычисляется ( H \cdot c^T ) для проверки корректности данной матрицы кодирования. При наличии закодированного слова проверка может быть выполнена с помощью функции библиотеки errorCorrection::check(c, H)
.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )