【Applied Algebra】扩域(Galois域)上的乘加法表构造

【Applied Algebra】扩域(Galois域)上的乘法表构造

【Applied Algebra】扩域(Galois域)上的乘加法表构造_第1张图片


在之前的文章里,我们讨论了扩域上(Galois域)的计算及其实现,但是侧重的是扩域中元素之间运算的细节实现,而如果想描述整个域的结构,就需要构造乘法表和加法表;实现仍然是基于c++和符号计算库GiNaC;

运算表及其设计

考虑 F p n \mathbb{F}_{p^n} Fpn上的元素,根据 F p n ≅ F p / f ( x ) \mathbb{F}_{p^n} \cong \mathbb{F}_{p}/f(x) FpnFp/f(x),比如计算 F 2 4 \mathbb{F}_{2^4} F24上的元素,根据 F 2 4 ≅ F 2 / f ( x ) \mathbb{F}_{2^4} \cong \mathbb{F}_{2}/f(x) F24F2/f(x),这里设 f ( x ) = x 4 + x 3 + 1 f(x) = x^4+x^3+1 f(x)=x4+x3+1为不可约多项式; F 2 4 \mathbb{F}_{2^4} F24中洽有 16 16 16个元素, F 2 / f ( x ) \mathbb{F}_{2}/f(x) F2/f(x)中的元素可以表示为小于 4 4 4次的多项式,根据每一项出现与否( { x 3 , x 2 , x , 1 } \{x^3,x^2,x,1\} {x3,x2,x,1})也恰有16个多项式,那么和 F 2 4 \mathbb{F}_{2^4} F24中的元素一一对应,因此 F 2 4 \mathbb{F}_{2^4} F24亦可表示为:

F 2 4 = { 0000 , 0001 , . . . , 1111 } \mathbb{F}_{2^4} = \{0000,0001,...,1111\} F24={0000,0001,...,1111}

更一般地,我们设 F p n \mathbb{F}_{p^n} Fpn形如 F p n = { g 1 , g 2 , ⋯   , g N } \mathbb{F}_{p^n} = \{g_1,g_2,\cdots,g_N\} Fpn={g1,g2,,gN},其中 N N N是域的阶.那么 F p n \mathbb{F}_{p^n} Fpn中任何元素 g i g_i gi都可看作 n n n p p p进制数字串,它的每一位若一一对应地看作 { x n − 1 , . . . , x 2 , x , 1 } \{x^{n-1},...,x^2,x,1\} {xn1,...,x2,x,1}的系数,那么就和多项式环 F p / f ( x ) \mathbb{F}_{p}/f(x) Fp/f(x)中的元素一一对应了.

综上所述,乘法表或者加法表的构造就是,利用扩域 F p n \mathbb{F}_{p^n} Fpn和多项式环 F p / f ( x ) \mathbb{F}_{p}/f(x) Fp/f(x)中元素的一一对应,通过多项式环 F p / f ( x ) \mathbb{F}_{p}/f(x) Fp/f(x)中的元素的运算结果来对应还原扩域 F p n \mathbb{F}_{p^n} Fpn的结构,我们首先设计一个类来抽象扩域 F p n \mathbb{F}_{p^n} Fpn:

class extension_field_class
{
public:
    extension_field* pt_EXT_FIELD;
    GiNaC::ex IRRED_POLY;
    int ORDER_NUM;
    std::vector<extension_field_element> ELEMENTS_SET;
    GiNaC::exmap TAB_POLY2INDEX;
    std::map<extension_field_element, int> TAB_ELEMENT2INDEX;
    std::vector<std::vector<int> > TAB_MULTI;
    std::vector<std::vector<int> > TAB_DIV;
    std::vector<std::vector<int> > TAB_ADD;
    std::vector<std::vector<int> > TAB_SUB;
    extension_field_class(extension_field* pt_EXT_FIELD,const GiNaC::ex& IRRED_POLY);
    extension_field_element multi_computing(const extension_field_element& ELEMENT_1,const extension_field_element& ELEMENT_2);
    extension_field_element add_computing(const extension_field_element& ELEMENT_1,const extension_field_element& ELEMENT_2);
    extension_field_element div_computing(const extension_field_element& ELEMENT_1,const extension_field_element& ELEMENT_2);
    extension_field_element sub_computing(const extension_field_element& ELEMENT_1,const extension_field_element& ELEMENT_2);
    void print_multi_tab();
};

其中 TAB_MULTI 和 TAB_ADD 就通过域元素的序号存储了对应两个元素的乘法和加法运算结果.

运算表及其实现

我们在上一节里构造了扩域元素的类 extension_field_element,因此实现运算表构造的功能就是基于我们之前弄的乘法和加法运算符,但在明确任意两个元素相乘的结果之前,我们首先要构造所有的域元素,这是之前没有实现的功能:

// --------- Constructing ELEMENTS_SET; ---------
    std::vector<int> COEFF_VEC;std::vector<GiNaC::ex> MONOMIALS;
    for (int INDEX_j = 0; INDEX_j < this->pt_EXT_FIELD->EXTEN_NUM; ++INDEX_j){COEFF_VEC.push_back(0);}
    for (int INDEX_j = 0; INDEX_j < this->pt_EXT_FIELD->EXTEN_NUM; ++INDEX_j)
    {
        GiNaC::ex MONOMIAL = 1;
        if (INDEX_j==0){MONOMIALS.push_back(MONOMIAL);continue;}
        for (int INDEX_k = 1; INDEX_k <= INDEX_j; ++INDEX_k){MONOMIAL*=a;}
        MONOMIALS.push_back(MONOMIAL);
    }
    for (int INDEX_i = 1; INDEX_i < this->ORDER_NUM; ++INDEX_i)
    {
        GiNaC::ex POLYNOMIAL = 0;
        func_decimal_conv(INDEX_i,this->pt_EXT_FIELD->PRIME_NUM,this->pt_EXT_FIELD->EXTEN_NUM,COEFF_VEC);
        for (int INDEX_j = 0; INDEX_j < this->pt_EXT_FIELD->EXTEN_NUM; ++INDEX_j)
        {
            POLYNOMIAL += COEFF_VEC[INDEX_j]*MONOMIALS[INDEX_j];
        }
        extension_field_element EXT_FIELD_ELE(this->pt_EXT_FIELD,POLYNOMIAL);
        EXT_FIELD_ELE.ELEMENT_INDEX = INDEX_i-1;
        this->ELEMENTS_SET.push_back(EXT_FIELD_ELE);
        this->TAB_POLY2INDEX[POLYNOMIAL] = EXT_FIELD_ELE.ELEMENT_INDEX;
        this->TAB_ELEMENT2INDEX[EXT_FIELD_ELE] = EXT_FIELD_ELE.ELEMENT_INDEX;
    }

其中 TAB_POLY2INDEX 和 TAB_ELEMENT2INDEX 可以帮助我们以线性复杂度 O ( 1 ) O(1) O(1)根据多项式或域元素类定位该元素的下标,这有利于后续算法的效率,注意 TAB_ELEMENT2INDEX 是map类型,当extension_field_element作为key的时候,需要实现它的"大小比较功能"(这是由于map是基于红黑树实现的),在此不加赘述.构造完所有元素之后,即可来构造乘法表和加法表:

// --------- Constructing TAB_MULTI and TAB_DIV; ---------
    std::vector<std::vector<int> > TAB_NEW = init_all_tab(this->ORDER_NUM-1);
    this->TAB_MULTI = TAB_NEW;this->TAB_ADD = TAB_NEW;this->TAB_DIV = TAB_NEW;this->TAB_SUB = TAB_NEW;
    for (int INDEX_i = 0; INDEX_i < this->ORDER_NUM-1; ++INDEX_i)
    {
        for (int INDEX_j = 0; INDEX_j <= INDEX_i; ++INDEX_j)
        {
            GiNaC::ex POLYNOMIAL = (this->ELEMENTS_SET[INDEX_i]*this->ELEMENTS_SET[INDEX_j]).POLYNOMIAL;
            this->TAB_MULTI[INDEX_i][INDEX_j] = GiNaC::ex_to<GiNaC::numeric>(this->TAB_POLY2INDEX[POLYNOMIAL]).to_int();
            this->TAB_MULTI[INDEX_j][INDEX_i] = GiNaC::ex_to<GiNaC::numeric>(this->TAB_POLY2INDEX[POLYNOMIAL]).to_int();
            this->TAB_DIV[ TAB_MULTI[INDEX_j][INDEX_i] ][INDEX_i] = INDEX_j;
            this->TAB_DIV[ TAB_MULTI[INDEX_j][INDEX_i] ][INDEX_j] = INDEX_i;
        }
    }
    // --------- Constructing TAB_ADD; ---------
    for (int INDEX_i = 0; INDEX_i < this->ORDER_NUM-1; ++INDEX_i)
    {
        for (int INDEX_j = 0; INDEX_j <= INDEX_i; ++INDEX_j)
        {
            GiNaC::ex POLYNOMIAL = (this->ELEMENTS_SET[INDEX_i] + this->ELEMENTS_SET[INDEX_j]).POLYNOMIAL;
            this->TAB_ADD[INDEX_i][INDEX_j] = GiNaC::ex_to<GiNaC::numeric>(this->TAB_POLY2INDEX[POLYNOMIAL]).to_int();
            this->TAB_ADD[INDEX_j][INDEX_i] = GiNaC::ex_to<GiNaC::numeric>(this->TAB_POLY2INDEX[POLYNOMIAL]).to_int();
        }
    }

这里顺带构造了除法表,减法表有点特殊,思考一下为什么(提示:涉及到特殊元素 0 0 0).

通过这样的功能实现,我们可以打印任意扩域 F p n \mathbb{F}_{p^n} Fpn的运算表,在这里我们尝试构造扩域 F 3 3 \mathbb{F}_{3^3} F33的乘法表:

GiNaC::ex IRRED_POLY = a*a*a + 2*a*a + 1;
struct extension_field EXT_FIELD;
EXT_FIELD.PRIME_NUM = 3;EXT_FIELD.EXTEN_NUM = 3;EXT_FIELD.IRRED_POLY = IRRED_POLY;
extension_field_class EXT_FIELD_CLASS(&EXT_FIELD,IRRED_POLY);
EXT_FIELD_CLASS.print_multi_tab();

结果如下:

 ====================== Multiplication Table of GF(3^3) ======================
*    | g_0  |g_1  |g_2  |g_3  |g_4  |g_5  |g_6  |g_7  |g_8  |g_9  |g_10 |g_11 |g_12 |g_13 |g_14 |g_15 |g_16 |g_17 |g_18 |g_19 |g_20 |g_21 |g_22 |g_23 |g_24 |g_25 |
g_0  | g_0   g_1   g_2   g_3   g_4   g_5   g_6   g_7   g_8   g_9   g_10  g_11  g_12  g_13  g_14  g_15  g_16  g_17  g_18  g_19  g_20  g_21  g_22  g_23  g_24  g_25  
g_1  | g_1   g_0   g_5   g_7   g_6   g_2   g_4   g_3   g_17  g_19  g_18  g_23  g_25  g_24  g_20  g_22  g_21  g_8   g_10  g_9   g_14  g_16  g_15  g_11  g_13  g_12  
g_2  | g_2   g_5   g_8   g_11  g_14  g_17  g_20  g_23  g_10  g_13  g_16  g_19  g_22  g_25  g_1   g_4   g_7   g_18  g_21  g_24  g_0   g_3   g_6   g_9   g_12  g_15  
g_3  | g_3   g_7   g_11  g_15  g_10  g_23  g_18  g_22  g_19  g_20  g_24  g_4   g_5   g_0   g_16  g_8   g_12  g_9   g_13  g_14  g_21  g_25  g_17  g_6   g_1   g_2   
g_4  | g_4   g_6   g_14  g_10  g_12  g_20  g_25  g_18  g_1   g_3   g_5   g_16  g_9   g_11  g_22  g_24  g_17  g_0   g_2   g_7   g_15  g_8   g_13  g_21  g_23  g_19  
g_5  | g_5   g_2   g_17  g_23  g_20  g_8   g_14  g_11  g_18  g_24  g_21  g_9   g_15  g_12  g_0   g_6   g_3   g_10  g_16  g_13  g_1   g_7   g_4   g_19  g_25  g_22  
g_6  | g_6   g_4   g_20  g_18  g_25  g_14  g_12  g_10  g_0   g_7   g_2   g_21  g_19  g_23  g_15  g_13  g_8   g_1   g_5   g_3   g_22  g_17  g_24  g_16  g_11  g_9   
g_7  | g_7   g_3   g_23  g_22  g_18  g_11  g_10  g_15  g_9   g_14  g_13  g_6   g_2   g_1   g_21  g_17  g_25  g_19  g_24  g_20  g_16  g_12  g_8   g_4   g_0   g_5   
g_8  | g_8   g_17  g_10  g_19  g_1   g_18  g_0   g_9   g_16  g_25  g_7   g_24  g_6   g_15  g_5   g_14  g_23  g_21  g_3   g_12  g_2   g_11  g_20  g_13  g_22  g_4   
g_9  | g_9   g_19  g_13  g_20  g_3   g_24  g_7   g_14  g_25  g_5   g_15  g_0   g_10  g_17  g_11  g_21  g_4   g_12  g_22  g_2   g_23  g_6   g_16  g_1   g_8   g_18  
g_10 | g_10  g_18  g_16  g_24  g_5   g_21  g_2   g_13  g_7   g_15  g_23  g_12  g_20  g_4   g_17  g_1   g_9   g_3   g_11  g_22  g_8   g_19  g_0   g_25  g_6   g_14  
g_11 | g_11  g_23  g_19  g_4   g_16  g_9   g_21  g_6   g_24  g_0   g_12  g_14  g_17  g_2   g_7   g_10  g_22  g_13  g_25  g_1   g_3   g_15  g_18  g_20  g_5   g_8   
g_12 | g_12  g_25  g_22  g_5   g_9   g_15  g_19  g_2   g_6   g_10  g_20  g_17  g_3   g_16  g_13  g_23  g_0   g_4   g_14  g_18  g_24  g_1   g_11  g_8   g_21  g_7   
g_13 | g_13  g_24  g_25  g_0   g_11  g_12  g_23  g_1   g_15  g_17  g_4   g_2   g_16  g_18  g_19  g_3   g_14  g_22  g_6   g_8   g_9   g_20  g_7   g_5   g_10  g_21  
g_14 | g_14  g_20  g_1   g_16  g_22  g_0   g_15  g_21  g_5   g_11  g_17  g_7   g_13  g_19  g_6   g_12  g_18  g_2   g_8   g_23  g_4   g_10  g_25  g_3   g_9   g_24  
g_15 | g_15  g_22  g_4   g_8   g_24  g_6   g_13  g_17  g_14  g_21  g_1   g_10  g_23  g_3   g_12  g_19  g_5   g_20  g_0   g_16  g_25  g_2   g_9   g_18  g_7   g_11  
g_16 | g_16  g_21  g_7   g_12  g_17  g_3   g_8   g_25  g_23  g_4   g_9   g_22  g_0   g_14  g_18  g_5   g_13  g_11  g_19  g_6   g_10  g_24  g_2   g_15  g_20  g_1   
g_17 | g_17  g_8   g_18  g_9   g_0   g_10  g_1   g_19  g_21  g_12  g_3   g_13  g_4   g_22  g_2   g_20  g_11  g_16  g_7   g_25  g_5   g_23  g_14  g_24  g_15  g_6   
g_18 | g_18  g_10  g_21  g_13  g_2   g_16  g_5   g_24  g_3   g_22  g_11  g_25  g_14  g_6   g_8   g_0   g_19  g_7   g_23  g_15  g_17  g_9   g_1   g_12  g_4   g_20  
g_19 | g_19  g_9   g_24  g_14  g_7   g_13  g_3   g_20  g_12  g_2   g_22  g_1   g_18  g_8   g_23  g_16  g_6   g_25  g_15  g_5   g_11  g_4   g_21  g_0   g_17  g_10  
g_20 | g_20  g_14  g_0   g_21  g_15  g_1   g_22  g_16  g_2   g_23  g_8   g_3   g_24  g_9   g_4   g_25  g_10  g_5   g_17  g_11  g_6   g_18  g_12  g_7   g_19  g_13  
g_21 | g_21  g_16  g_3   g_25  g_8   g_7   g_17  g_12  g_11  g_6   g_19  g_15  g_1   g_20  g_10  g_2   g_24  g_23  g_9   g_4   g_18  g_13  g_5   g_22  g_14  g_0   
g_22 | g_22  g_15  g_6   g_17  g_13  g_4   g_24  g_8   g_20  g_16  g_0   g_18  g_11  g_7   g_25  g_9   g_2   g_14  g_1   g_21  g_12  g_5   g_19  g_10  g_3   g_23  
g_23 | g_23  g_11  g_9   g_6   g_21  g_19  g_16  g_4   g_13  g_1   g_25  g_20  g_8   g_5   g_3   g_18  g_15  g_24  g_12  g_0   g_7   g_22  g_10  g_14  g_2   g_17  
g_24 | g_24  g_13  g_12  g_1   g_23  g_25  g_11  g_0   g_22  g_8   g_6   g_5   g_21  g_10  g_9   g_7   g_20  g_15  g_4   g_17  g_19  g_14  g_3   g_2   g_18  g_16  
g_25 | g_25  g_12  g_15  g_2   g_19  g_22  g_9   g_5   g_4   g_18  g_14  g_8   g_7   g_21  g_24  g_11  g_1   g_6   g_20  g_10  g_13  g_0   g_23  g_17  g_16  g_3   


一个额外的思考():仍然考虑多项式环 F p n [ x 1 , ⋯   , x m ] \mathbb{F}_{p^n}[x_1,\cdots,x_m] Fpn[x1,,xm]上的方程组,由于我们已经计算得到了 F p n \mathbb{F}_{p^n} Fpn上的加法乘法表 T × \mathcal{T}_{\times} T×,加法表 T + \mathcal{T}_{+} T+,除法表 T / \mathcal{T}_{/} T/,则我们可以查表得到 T ( g i , g j , + ) = g k \mathcal{T}(g_i,g_j,+)=g_k T(gi,gj,+)=gk T ( g i , g j , × ) = g l \mathcal{T}(g_i,g_j,\times)=g_l T(gi,gj,×)=gl乃至 T ( g i , g j , / ) = g h \mathcal{T}(g_i,g_j,/)=g_h T(gi,gj,/)=gh来获得符号运算结果,那多项式环 F p n [ x 1 , ⋯   , x m ] \mathbb{F}_{p^n}[x_1,\cdots,x_m] Fpn[x1,,xm]的多项式 g ( x ) g(x) g(x)形如:

g ( x ) ∈ { ∑ i g i M i ∣ g i ∈ F p n , M i = x 1 α i . . . x n α n } g(x) \in \{\sum_i g_{i}M_i |g_i \in \mathbb{F}_{p^n},M_i = x^{\alpha_i}_1...x^{\alpha_n}_n\} g(x){igiMigiFpn,Mi=x1αi...xnαn}

请你思考一下如何实现这种方程组的高斯消元算法(回忆线性代数里的做法,对齐项 M i M_i Mi即可…).


参考资料

[1] Modern abstract algebra, Anderson, M. and Feil, T.,2014.
[2] 应用近世代数(第三版),胡冠章,清华大学出版社.

你可能感兴趣的:(算法,密码学)