之前对于编码和解码的讨论都仅限于编/解码矩阵的操作,很少谈到如果将文件读入并和矩阵相乘(关于NCCloud 有部分文件如果利用矩阵进行编解码),今天在实际编码中就遇到了这样的问题:如何将文件读入缓存,高效的运算并写入到新的文件?
问题描述
我们可以假设文件的大小是k 的整数倍(对应的(n, k) 编码),编码会将原始读入到缓存,保存为一个线性数组的结构,而矩阵是一个n×k 大小的二维数组,将缓存中线性数组的结构分为k 段,然后编码为n 段,同样放在一个线性数组中保存,然后写回到编码后的文件。解码则是相反的过程,但编解码缓存都是k 段。
如果将上面编码/解码公共部分提取出来,编解码可以写成一个编码(coding)的接口,输入编解码矩阵、源数据地址指针、编码后数据地址指针以及原始数据长度即可。
1: /* Encode/Decode the data using Matrix8g matrix *
2: * mat is the Encode/Decode matrix *
3: * p_des store the data after Encode/Decode *
4: * p_src store the data before Encode/Decode *
5: * length represent the length of the data to deal with */
6: int NC_code(Matrix8g mat, unsigned char *p_des, unsigned char *p_src, int length);
在这个函数中具体只要处理的就是矩阵mat 和p_src 地址中数据的乘法,将结果保存至p_des 中,如果mat(n 行,k 列,解码时n=k )矩阵为:
m11 m12 m13 …… m1k
m21 m22 m23 …… m2k
m31 m32 m33 …… m3k
… … … ……
mn1 mn2 mn3 …… mnk
缓存数据数组表示为D = d1 d2 d3 …… dBUFFSIZE 大小为BUFFSIZE 为k 的倍数,将D 看做一个矩阵,按照顺序分为k 行,每行BUFFSIZE/k 个数据:
d11 d12 d13 …… d1BUFFSIZE/k
d21 d22………………………..
…………………………………
dk1 dk2……………..dkBUFFSIZE/k
然后将两个矩阵相乘得到编码后的数据矩阵(n 行,BUFFSIEZ/k 列,^ 表示异或,即域上的加法):
r11 = m11·d11 ^ m12· d21 ^ m13· d31 ^ ……
r12 = m11·d12 ^ m12· d22 ^ m13· d32 ^ ……
r13 = m11·d13 ^ m12· d23 ^ m13· d33 ^ ……
……………………………………………….
r21 = m21·d11 ^ m22· d21 ^ m23· d31 ^ ……
………………………………………………..
而编码前的数据D(d1 d2 …) 和编码后的数据R(r1 r2 …) 有着相同的线性顺序:
d11 d12 d13 …… d1BUFFSIZE/k d21 d22 …… …… dkBUFFSIZE/k
r11 r12 r13 …… r1BUFFSIZE/k r21 r22 …… …… rnBUFFSIZE/k
虽然是这样说,因为galois 提供的快速乘法说明如下:
void galois_w08_region_multiply(char *region, int multby, int nbytes, char *r2, int add);
These multiply the region of bytes specified by region and nbytes by the number multby in the field
specified by the procedure's name. Region should be long-word aligned, otherwise these routines will
generate a bus error. There are three separate functionalities of these procedures denoted by the
values of r2 and add.
If r2 is NULL, the bytes in region are replaced by their products with multby.
If r2 is not NULL and add is zero, then the products are placed in the nbytes of memory
starting with r2. The two regions should not overlap unlessr2 is less than region.
If r2 is not NULL and add is one, then the products are calculated and then XOR'd into
existing bytes of r2.
需要说明的是如果add 不为零,则nbytes 就失效了,r2 指针所指向的数据全部会被region 所指数据和multby 相乘的结果XOR 之。
所以在具体实现数据D 和矩阵mat 相乘还得 有些技巧,即对于每个矩阵mat 中每个元素均首先处理完其和所辖范围数据的乘法,保存在输出缓存中,后面矩阵中其他元素和所辖数据乘积得到的结果就和之前保存的数据进行异或,比如如下首先处理矩阵mat 第一行第一列元素m11 和前BUFFSIZE/k 个数据相乘,保存在输出缓存前BUFFSIZE/k个位置中。
r11 = m11·d11 ^ m12· d21 ^ m13· d31 ^ ……
r12 = m11·d12 ^ m12· d22 ^ m13· d32 ^ ……
r13 = m11·d13 ^ m12· d23 ^ m13· d33 ^ ……
……..……..…………………………………
r21 = m21·d11 ^ m22· d21 ^ m23· d31 ^ ……
………………………………………………..
源码:
1:
2: /* Encode/Decode the data using Matrix8g matrix *
3: * mat is the Encode/Decode matrix *
4: * p_des store the data after Encode/Decode *
5: * p_src store the data before Encode/Decode *
6: * length represent the length of the data to deal with */
7: int NC_code(Matrix8g mat, unsigned char *p_des, unsigned char *p_src, int length){
8: int n, k;
9: int i, j, t;
10: int if_add;
11: uint8_t mres;
12: unsigned char *pd, *ps, *pdes;
13: int len_seg;
14:
15: k = mat.cc;
16: n = mat.rr;
17: assert(length%mat.cc == 0);
18: len_seg = length/k;
19:
20: memset(p_des, 0, length*n/k);
21: pdes = (unsigned char*)malloc(len_seg*sizeof(unsigned char));
22: for(i = 0; i < n; i++){
23: for(j = 0; j < k; j++){
24: /*******************************************************
25: *** This part of program will help you to understand ***
26: ps = p_src + j*len_seg;
27: pd = p_des + i*len_seg;
28: for(t = 0; t < len_seg; t++){
29: mres = galois_single_multiply(mat.Get(i,j), *(ps+t), 8);
30: *(pd+t) = (*(pd+t))^mres;
31: }
32: ********************************************************/
33: /********************************************************/
34: galois_w08_region_multiply(p_src+j*len_seg, mat.Get(i, j),
35: len_seg, pdes, 0);
36: for(t = 0; t < len_seg; t++){
37: *(p_des+i*len_seg+t) =(*(p_des+i*len_seg+t))^(*(pdes+t)) ;
38: }
39: /********************************************************/
40: }
41: }
42: return length;
43: }