日韩一区二区三区毛片_少妇被猛烈进入到喷白浆_午夜一区视频_久久精品视频91_国产福利免费在线_日韩在线播放av_国产亚洲精品合集久久久久_内射少妇36p亚洲区_超碰男人天堂_在线免费91_国产成人精品a视频一区_国产精品久久久久久久第一福利_色老板精品凹凸在线视频观看_亚洲成人在线播放视频_狠狠色狠狠综合久久_8天堂资源在线_狠狠色丁香久久婷婷综合蜜芽五月_爱逼综合_日本黄色www_少妇伦子伦精品无码styles

模塊化算法和 NTT(有限域 DFT)優(yōu)化

Modular arithmetics and NTT (finite field DFT) optimizations(模塊化算法和 NTT(有限域 DFT)優(yōu)化)
本文介紹了模塊化算法和 NTT(有限域 DFT)優(yōu)化的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!

問題描述

我想使用 NTT 進行快速平方(請參閱快速 bignum 平方計算),但即使對于非常大的數(shù)字……超過 12000 位.

I wanted to use NTT for fast squaring (see Fast bignum square computation), but the result is slow even for really big numbers .. more than 12000 bits.

所以我的問題是:

  1. 有沒有辦法優(yōu)化我的 NTT 轉(zhuǎn)換?我并不是要通過并行(線程)來加速它;這只是低級層.
  2. 有沒有辦法加快我的模塊化算術(shù)的速度?

這是我在 C++ 中為 NTT 編寫的(已經(jīng)優(yōu)化的)源代碼(它是完整的并且 100% 在 C++ 中工作,不需要第三方庫,并且還應(yīng)該是線程安全的.注意源數(shù)組被用作臨時!!!, 也不能將數(shù)組轉(zhuǎn)化為自身).

This is my (already optimized) source code in C++ for NTT (it's complete and 100% working in C++ whitout any need for third-party libs and should also be thread-safe. Beware the source array is used as a temporary!!!, Also it cannot transform the array to itself).

//---------------------------------------------------------------------------
class fourier_NTT                                    // Number theoretic transform
    {

public:
    DWORD r,L,p,N;
    DWORD W,iW,rN;
    fourier_NTT(){ r=0; L=0; p=0; W=0; iW=0; rN=0; }

    // main interface
    void  NTT(DWORD *dst,DWORD *src,DWORD n=0);               // DWORD dst[n] = fast  NTT(DWORD src[n])
    void INTT(DWORD *dst,DWORD *src,DWORD n=0);               // DWORD dst[n] = fast INTT(DWORD src[n])

    // Helper functions
    bool init(DWORD n);                                       // init r,L,p,W,iW,rN
    void  NTT_fast(DWORD *dst,DWORD *src,DWORD n,DWORD w);    // DWORD dst[n] = fast  NTT(DWORD src[n])

    // Only for testing
    void  NTT_slow(DWORD *dst,DWORD *src,DWORD n,DWORD w);    // DWORD dst[n] = slow  NTT(DWORD src[n])
    void INTT_slow(DWORD *dst,DWORD *src,DWORD n,DWORD w);    // DWORD dst[n] = slow INTT(DWORD src[n])

    // DWORD arithmetics
    DWORD shl(DWORD a);
    DWORD shr(DWORD a);

    // Modular arithmetics
    DWORD mod(DWORD a);
    DWORD modadd(DWORD a,DWORD b);
    DWORD modsub(DWORD a,DWORD b);
    DWORD modmul(DWORD a,DWORD b);
    DWORD modpow(DWORD a,DWORD b);
    };

//---------------------------------------------------------------------------
void fourier_NTT:: NTT(DWORD *dst,DWORD *src,DWORD n)
    {
    if (n>0) init(n);
    NTT_fast(dst,src,N,W);
//    NTT_slow(dst,src,N,W);
    }

//---------------------------------------------------------------------------
void fourier_NTT::INTT(DWORD *dst,DWORD *src,DWORD n)
    {
    if (n>0) init(n);
    NTT_fast(dst,src,N,iW);
    for (DWORD i=0;i<N;i++) dst[i]=modmul(dst[i],rN);
       //    INTT_slow(dst,src,N,W);
    }

//---------------------------------------------------------------------------
bool fourier_NTT::init(DWORD n)
    {
    // (max(src[])^2)*n < p else NTT overflow can ocur !!!
    r=2; p=0xC0000001; if ((n<2)||(n>0x10000000)) { r=0; L=0; p=0; W=0; iW=0; rN=0; N=0; return false; } L=0x30000000/n; // 32:30 bit best for unsigned 32 bit
//    r=2; p=0x78000001; if ((n<2)||(n>0x04000000)) { r=0; L=0; p=0; W=0; iW=0; rN=0; N=0; return false; } L=0x3c000000/n; // 31:27 bit best for signed 32 bit
//    r=2; p=0x00010001; if ((n<2)||(n>0x00000020)) { r=0; L=0; p=0; W=0; iW=0; rN=0; N=0; return false; } L=0x00000020/n; // 17:16 bit best for 16 bit
//    r=2; p=0x0a000001; if ((n<2)||(n>0x01000000)) { r=0; L=0; p=0; W=0; iW=0; rN=0; N=0; return false; } L=0x01000000/n; // 28:25 bit
     N=n;                // size of vectors [DWORDs]
     W=modpow(r,    L);    // Wn for NTT
    iW=modpow(r,p-1-L);    // Wn for INTT
    rN=modpow(n,p-2  );    // scale for INTT
    return true;
    }

//---------------------------------------------------------------------------
void fourier_NTT:: NTT_fast(DWORD *dst,DWORD *src,DWORD n,DWORD w)
    {
    if (n<=1) { if (n==1) dst[0]=src[0]; return; }
    DWORD i,j,a0,a1,n2=n>>1,w2=modmul(w,w);
    // reorder even,odd
    for (i=0,j=0;i<n2;i++,j+=2) dst[i]=src[j];
    for (    j=1;i<n ;i++,j+=2) dst[i]=src[j];
    // recursion
    NTT_fast(src   ,dst   ,n2,w2);    // even
    NTT_fast(src+n2,dst+n2,n2,w2);    // odd
    // restore results
    for (w2=1,i=0,j=n2;i<n2;i++,j++,w2=modmul(w2,w))
        {
        a0=src[i];
        a1=modmul(src[j],w2);
        dst[i]=modadd(a0,a1);
        dst[j]=modsub(a0,a1);
        }
    }

//---------------------------------------------------------------------------
void fourier_NTT:: NTT_slow(DWORD *dst,DWORD *src,DWORD n,DWORD w)
    {
    DWORD i,j,wj,wi,a,n2=n>>1;
    for (wj=1,j=0;j<n;j++)
        {
        a=0;
        for (wi=1,i=0;i<n;i++)
            {
            a=modadd(a,modmul(wi,src[i]));
            wi=modmul(wi,wj);
            }
        dst[j]=a;
        wj=modmul(wj,w);
        }
    }

//---------------------------------------------------------------------------
void fourier_NTT::INTT_slow(DWORD *dst,DWORD *src,DWORD n,DWORD w)
    {
    DWORD i,j,wi=1,wj=1,a,n2=n>>1;
    for (wj=1,j=0;j<n;j++)
        {
        a=0;
        for (wi=1,i=0;i<n;i++)
            {
            a=modadd(a,modmul(wi,src[i]));
            wi=modmul(wi,wj);
            }
        dst[j]=modmul(a,rN);
        wj=modmul(wj,iW);
        }
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::shl(DWORD a) { return (a<<1)&0xFFFFFFFE; }
DWORD fourier_NTT::shr(DWORD a) { return (a>>1)&0x7FFFFFFF; }

//---------------------------------------------------------------------------
DWORD fourier_NTT::mod(DWORD a)
    {
    DWORD bb;
    for (bb=p;(DWORD(a)>DWORD(bb))&&(!DWORD(bb&0x80000000));bb=shl(bb));
    for (;;)
        {
        if (DWORD(a)>=DWORD(bb)) a-=bb;
        if (bb==p) break;
        bb =shr(bb);
        }
    return a;
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::modadd(DWORD a,DWORD b)
    {
    DWORD d,cy;
    a=mod(a);
    b=mod(b);
    d=a+b;
    cy=(shr(a)+shr(b)+shr((a&1)+(b&1)))&0x80000000;
    if (cy) d-=p;
    if (DWORD(d)>=DWORD(p)) d-=p;
    return d;
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::modsub(DWORD a,DWORD b)
    {
    DWORD d;
    a=mod(a);
    b=mod(b);
    d=a-b; if (DWORD(a)<DWORD(b)) d+=p;
    if (DWORD(d)>=DWORD(p)) d-=p;
    return d;
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::modmul(DWORD a,DWORD b)
    {    // b bez orezania !
    int i;
    DWORD d;
    a=mod(a);
    for (d=0,i=0;i<32;i++)
        {
        if (DWORD(a&1))    d=modadd(d,b);
        a=shr(a);
        b=modadd(b,b);
        }
    return d;
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::modpow(DWORD a,DWORD b)
    {    // a,b bez orezania !
    int i;
    DWORD d=1;
    for (i=0;i<32;i++)
        {
        d=modmul(d,d);
        if (DWORD(b&0x80000000)) d=modmul(d,a);
        b=shl(b);
        }
    return d;
    }
//---------------------------------------------------------------------------

我的 NTT 類的使用示例:

Example of usage of my NTT class:

fourier_NTT ntt;
const DWORD n=32
DWORD x[N]={0,1,2,3,....31},y[N]={32,33,34,35,...63},z[N];

ntt.NTT(z,x,N);    // z[N]=NTT(x[N]), also init constants for N
ntt.NTT(x,y);    // x[N]=NTT(y[N]), no recompute of constants, use last N
// modular convolution y[]=z[].x[]
for (i=0;i<n;i++) y[i]=ntt.modmul(z[i],x[i]);
ntt.INTT(x,y);    // x[N]=INTT(y[N]), no recompute of constants, use last N
// x[]=convolution of original x[].y[]

優(yōu)化前的一些測量(非 NTT 類):

Some measurements before optimizations (non Class NTT):

a = 0.98765588997654321000 | 389*32 bits
looped 1x times
sqr1[ 3.177 ms ] fast sqr
sqr2[ 720.419 ms ] NTT sqr
mul1[ 5.588 ms ] simpe mul
mul2[ 3.172 ms ] karatsuba mul
mul3[ 1053.382 ms ] NTT mul

我優(yōu)化后的一些測量(當(dāng)前代碼、較低的遞歸參數(shù)大小/計數(shù)和更好的模塊化算法):

Some measurements after my optimizations (current code, lower recursion parameter size/count, and better modular arithmetics):

a = 0.98765588997654321000 | 389*32 bits
looped 1x times
sqr1[ 3.214 ms ] fast sqr
sqr2[ 208.298 ms ] NTT sqr
mul1[ 5.564 ms ] simpe mul
mul2[ 3.113 ms ] karatsuba mul
mul3[ 302.740 ms ] NTT mul

檢查 NTT mul 和 NTT sqr 時間(我的優(yōu)化加快了 3 倍多一點).它只有 1 倍循環(huán),所以它不是很精確(誤差 ~ 10%),但即使現(xiàn)在加速也很明顯(通常我循環(huán)它 1000 倍甚至更多,但我的 NTT 太慢了).

Check the NTT mul and NTT sqr times (my optimizations speed it up little over 3x times). It's only 1x times loop so it's not very precise (error ~ 10%), but the speedup is noticeable even now (normally I loop it 1000x and more, but my NTT is too slow for that).

您可以自由使用我的代碼...只需將我的昵稱和/或指向此頁面的鏈接保留在某處(rem in code、readme.txt、about 或其他內(nèi)容).我希望它有幫助......(我沒有在任何地方看到快速 NTT 的 C++ 源代碼,所以我不得不自己編寫).對所有接受的 N 都測試了統(tǒng)一根,請參閱 fourier_NTT::init(DWORD n) 函數(shù).

You can use my code freely... Just keep my nick and/or link to this page somewhere (rem in code, readme.txt, about or whatever). I hope it helps... (I did not see C++ source for fast NTTs anywhere so I had to write it by myself). Roots of unity were tested for all accepted N, see the fourier_NTT::init(DWORD n) function.

P.S.:有關(guān) NTT 的更多信息,請參閱從復(fù)雜 FFT 到有限域 FFT 的轉(zhuǎn)換.此代碼基于我在該鏈接中的帖子.

P.S.: For more information about NTT, see Translation from Complex-FFT to Finite-Field-FFT. This code is based on my posts inside that link.

[edit1:] 代碼的進一步變化

通過利用模素數(shù)始終為 0xC0000001 并消除不必要的調(diào)用,我設(shè)法進一步優(yōu)化了我的模算術(shù).由此產(chǎn)生的加速現(xiàn)在令人驚嘆(超過 40 倍),并且在大約 1500 * 32 位閾值之后,NTT 乘法比 karatsuba 更快.順便說一句,我的 NTT 的速度現(xiàn)在與我在 64 位雙打上優(yōu)化的 DFFT 的速度相同.

I managed to further optimize my modular arithmetics, by exploiting that modulo prime is allways 0xC0000001 and eliminating unnecessary calls. The resulting speedup is stunning (more than 40x times) now and NTT multiplication is faster than karatsuba after about the 1500 * 32 bits threshold. BTW, the speed of my NTT is now the same as my optimized DFFT on 64-bit doubles.

一些測量:

a = 0.98765588997654321000 | 1553*32bits
looped 10x times
mul2[ 28.585 ms ] karatsuba mul
mul3[ 26.311 ms ] NTT mul

模塊化算術(shù)的新源代碼:

New source code for modular arithmetics:

//---------------------------------------------------------------------------
DWORD fourier_NTT::mod(DWORD a)
    {
    if (a>p) a-=p;
    return a;
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::modadd(DWORD a,DWORD b)
    {
    DWORD d,cy;
    if (a>p) a-=p;
    if (b>p) b-=p;
    d=a+b;
    cy=((a>>1)+(b>>1)+(((a&1)+(b&1))>>1))&0x80000000;
    if (cy ) d-=p;
    if (d>p) d-=p;
    return d;
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::modsub(DWORD a,DWORD b)
    {
    DWORD d;
    if (a>p) a-=p;
    if (b>p) b-=p;
    d=a-b;
    if (a<b) d+=p;
    if (d>p) d-=p;
    return d;
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::modmul(DWORD a,DWORD b)
    {
    DWORD _a,_b,_p;
    _a=a;
    _b=b;
    _p=p;
    asm    {
        mov    eax,_a
        mov    ebx,_b
        mul    ebx        // H(edx),L(eax) = eax * ebx
        mov    ebx,_p
        div    ebx        // eax = H(edx),L(eax) / ebx
        mov    _a,edx    // edx = H(edx),L(eax) % ebx
        }
    return _a;
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::modpow(DWORD a,DWORD b)
    {    // b bez orezania!
    int i;
    DWORD d=1;
    if (a>p) a-=p;
    for (i=0;i<32;i++)
        {
        d=modmul(d,d);
        if (DWORD(b&0x80000000)) d=modmul(d,a);
        b<<=1;
        }
    return d;
    }

//---------------------------------------------------------------------------

如您所見,函數(shù) shlshr?? 不再使用.我認(rèn)為 modpow 可以進一步優(yōu)化,但它不是一個關(guān)鍵函數(shù),因為它只被調(diào)用了很少的次數(shù).最關(guān)鍵的函數(shù)是 modmul,它似乎處于最佳狀態(tài).

As you can see, functions shl and shr are no more used. I think that modpow can be further optimized, but it's not a critical function because it is called only very few times. The most critical function is modmul, and that seems to be in the best shape possible.

其他問題:

  • 還有其他方法可以加速 NTT 嗎?
  • 我對模塊化算法的優(yōu)化安全嗎?(結(jié)果似乎是一樣的,但我可能會遺漏一些東西.)

[edit2] 新的優(yōu)化

a = 0.99991970486 | 2000*32 bits
looped 10x
sqr1[  13.908 ms ] fast sqr
sqr2[  13.649 ms ] NTT sqr
mul1[  19.726 ms ] simpe mul
mul2[  31.808 ms ] karatsuba mul
mul3[  19.373 ms ] NTT mul

我從你的所有評論中實現(xiàn)了所有可用的東西(感謝你的洞察力).

I implemented all the usable stuff from all of your comments (thanks for the insight).

加速:

  • 通過移除不必要的安全模組(Mandalf The Beige)+2.5%
  • +34.9% 通過使用預(yù)先計算的 W,iW 功率(神秘)
  • +35% 總計

實際完整源代碼:

//---------------------------------------------------------------------------
//--- Number theoretic transforms: 2.03 -------------------------------------
//---------------------------------------------------------------------------
#ifndef _fourier_NTT_h
#define _fourier_NTT_h
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
class fourier_NTT        // Number theoretic transform
    {
public:
    DWORD r,L,p,N;
    DWORD W,iW,rN;        // W=(r^L) mod p, iW=inverse W, rN = inverse N
    DWORD *WW,*iWW,NN;    // Precomputed (W,iW)^(0,..,NN-1) powers

    // Internals
    fourier_NTT(){ r=0; L=0; p=0; W=0; iW=0; rN=0; WW=NULL; iWW=NULL; NN=0; }
    ~fourier_NTT(){ _free(); }
    void _free();                                            // Free precomputed W,iW powers tables
    void _alloc(DWORD n);                                    // Allocate and precompute W,iW powers tables

    // Main interface
    void  NTT(DWORD *dst,DWORD *src,DWORD n=0);                // DWORD dst[n] = fast  NTT(DWORD src[n])
    void iNTT(DWORD *dst,DWORD *src,DWORD n=0);               // DWORD dst[n] = fast INTT(DWORD src[n])

    // Helper functions
    bool init(DWORD n);                                          // init r,L,p,W,iW,rN
    void  NTT_fast(DWORD *dst,DWORD *src,DWORD n,DWORD w);    // DWORD dst[n] = fast  NTT(DWORD src[n])
    void  NTT_fast(DWORD *dst,DWORD *src,DWORD n,DWORD *w2,DWORD i2);

    // Only for testing
    void  NTT_slow(DWORD *dst,DWORD *src,DWORD n,DWORD w);    // DWORD dst[n] = slow  NTT(DWORD src[n])
    void iNTT_slow(DWORD *dst,DWORD *src,DWORD n,DWORD w);    // DWORD dst[n] = slow INTT(DWORD src[n])

    // Modular arithmetics (optimized, but it works only for p >= 0x80000000!!!)
    DWORD mod(DWORD a);
    DWORD modadd(DWORD a,DWORD b);
    DWORD modsub(DWORD a,DWORD b);
    DWORD modmul(DWORD a,DWORD b);
    DWORD modpow(DWORD a,DWORD b);
    };
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
void fourier_NTT::_free()
    {
    NN=0;
    if ( WW) delete[]  WW;  WW=NULL;
    if (iWW) delete[] iWW; iWW=NULL;
    }

//---------------------------------------------------------------------------
void fourier_NTT::_alloc(DWORD n)
    {
    if (n<=NN) return;
    DWORD *tmp,i,w;
    tmp=new DWORD[n]; if ((NN)&&( WW)) for (i=0;i<NN;i++) tmp[i]= WW[i]; if ( WW) delete[]  WW;  WW=tmp;  WW[0]=1; for (i=NN?NN:1,w= WW[i-1];i<n;i++){ w=modmul(w, W);  WW[i]=w; }
    tmp=new DWORD[n]; if ((NN)&&(iWW)) for (i=0;i<NN;i++) tmp[i]=iWW[i]; if (iWW) delete[] iWW; iWW=tmp; iWW[0]=1; for (i=NN?NN:1,w=iWW[i-1];i<n;i++){ w=modmul(w,iW); iWW[i]=w; }
    NN=n;
    }

//---------------------------------------------------------------------------
void fourier_NTT:: NTT(DWORD *dst,DWORD *src,DWORD n)
    {
    if (n>0) init(n);
    NTT_fast(dst,src,N,WW,1);
//    NTT_fast(dst,src,N,W);
//    NTT_slow(dst,src,N,W);
    }

//---------------------------------------------------------------------------
void fourier_NTT::iNTT(DWORD *dst,DWORD *src,DWORD n)
    {
    if (n>0) init(n);
    NTT_fast(dst,src,N,iWW,1);
//    NTT_fast(dst,src,N,iW);
    for (DWORD i=0;i<N;i++) dst[i]=modmul(dst[i],rN);
//    iNTT_slow(dst,src,N,W);
    }

//---------------------------------------------------------------------------
bool fourier_NTT::init(DWORD n)
    {
    // (max(src[])^2)*n < p else NTT overflow can ocur!!!
    r=2; p=0xC0000001; if ((n<2)||(n>0x10000000)) { r=0; L=0; p=0; W=0; iW=0; rN=0; N=0; return false; } L=0x30000000/n; // 32:30 bit best for unsigned 32 bit
//    r=2; p=0x78000001; if ((n<2)||(n>0x04000000)) { r=0; L=0; p=0; W=0; iW=0; rN=0; N=0; return false; } L=0x3c000000/n; // 31:27 bit best for signed 32 bit
//    r=2; p=0x00010001; if ((n<2)||(n>0x00000020)) { r=0; L=0; p=0; W=0; iW=0; rN=0; N=0; return false; } L=0x00000020/n; // 17:16 bit best for 16 bit
//    r=2; p=0x0a000001; if ((n<2)||(n>0x01000000)) { r=0; L=0; p=0; W=0; iW=0; rN=0; N=0; return false; } L=0x01000000/n; // 28:25 bit
     N=n;                // Size of vectors [DWORDs]
     W=modpow(r,    L);  // Wn for NTT
    iW=modpow(r,p-1-L);  // Wn for INTT
    rN=modpow(n,p-2  );  // Scale for INTT
    _alloc(n>>1);        // Precompute W,iW powers
    return true;
    }

//---------------------------------------------------------------------------
void fourier_NTT:: NTT_fast(DWORD *dst,DWORD *src,DWORD n,DWORD w)
    {
    if (n<=1) { if (n==1) dst[0]=src[0]; return; }
    DWORD i,j,a0,a1,n2=n>>1,w2=modmul(w,w);

    // Reorder even,odd
    for (i=0,j=0;i<n2;i++,j+=2) dst[i]=src[j];
    for (    j=1;i<n ;i++,j+=2) dst[i]=src[j];

    // Recursion
    NTT_fast(src   ,dst   ,n2,w2);    // Even
    NTT_fast(src+n2,dst+n2,n2,w2);    // Odd

    // Restore results
    for (w2=1,i=0,j=n2;i<n2;i++,j++,w2=modmul(w2,w))
        {
        a0=src[i];
        a1=modmul(src[j],w2);
        dst[i]=modadd(a0,a1);
        dst[j]=modsub(a0,a1);
        }
    }

//---------------------------------------------------------------------------
void fourier_NTT:: NTT_fast(DWORD *dst,DWORD *src,DWORD n,DWORD *w2,DWORD i2)
    {
    if (n<=1) { if (n==1) dst[0]=src[0]; return; }
    DWORD i,j,a0,a1,n2=n>>1;

    // Reorder even,odd
    for (i=0,j=0;i<n2;i++,j+=2) dst[i]=src[j];
    for (    j=1;i<n ;i++,j+=2) dst[i]=src[j];

    // Recursion
    i=i2<<1;
    NTT_fast(src   ,dst   ,n2,w2,i);    // Even
    NTT_fast(src+n2,dst+n2,n2,w2,i);    // Odd

    // Restore results
    for (i=0,j=n2;i<n2;i++,j++,w2+=i2)
        {
        a0=src[i];
        a1=modmul(src[j],*w2);
        dst[i]=modadd(a0,a1);
        dst[j]=modsub(a0,a1);
        }
    }

//---------------------------------------------------------------------------
void fourier_NTT:: NTT_slow(DWORD *dst,DWORD *src,DWORD n,DWORD w)
    {
    DWORD i,j,wj,wi,a;
    for (wj=1,j=0;j<n;j++)
        {
        a=0;
        for (wi=1,i=0;i<n;i++)
            {
            a=modadd(a,modmul(wi,src[i]));
            wi=modmul(wi,wj);
            }
        dst[j]=a;
        wj=modmul(wj,w);
        }
    }

//---------------------------------------------------------------------------
void fourier_NTT::iNTT_slow(DWORD *dst,DWORD *src,DWORD n,DWORD w)
    {
    DWORD i,j,wi=1,wj=1,a;
    for (wj=1,j=0;j<n;j++)
        {
        a=0;
        for (wi=1,i=0;i<n;i++)
            {
            a=modadd(a,modmul(wi,src[i]));
            wi=modmul(wi,wj);
            }
        dst[j]=modmul(a,rN);
        wj=modmul(wj,iW);
        }
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::mod(DWORD a)
    {
    if (a>p) a-=p;
    return a;
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::modadd(DWORD a,DWORD b)
    {
    DWORD d,cy;
    //if (a>p) a-=p;
    //if (b>p) b-=p;
    d=a+b;
    cy=((a>>1)+(b>>1)+(((a&1)+(b&1))>>1))&0x80000000;
    if (cy ) d-=p;
    if (d>p) d-=p;
    return d;
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::modsub(DWORD a,DWORD b)
    {
    DWORD d;
    //if (a>p) a-=p;
    //if (b>p) b-=p;
    d=a-b;
    if (a<b) d+=p;
    if (d>p) d-=p;
    return d;
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::modmul(DWORD a,DWORD b)
    {
    DWORD _a,_b,_p;
    _a=a;
    _b=b;
    _p=p;
    asm    {
        mov    eax,_a
        mov    ebx,_b
        mul    ebx        // H(edx),L(eax) = eax * ebx
        mov    ebx,_p
        div    ebx        // eax = H(edx),L(eax) / ebx
        mov    _a,edx    // edx = H(edx),L(eax) % ebx
        }
    return _a;
    }

//---------------------------------------------------------------------------
DWORD fourier_NTT::modpow(DWORD a,DWORD b)
    {    // b is not mod(p)!
    int i;
    DWORD d=1;
    //if (a>p) a-=p;
    for (i=0;i<32;i++)
        {
        d=modmul(d,d);
        if (DWORD(b&0x80000000)) d=modmul(d,a);
        b<<=1;
        }
    return d;
    }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

通過將 NTT_fast 分成兩個函數(shù),仍然有可能使用更少的堆垃圾.一個帶有 WW[],另一個帶有 iWW[],這導(dǎo)致遞歸調(diào)用中的一個參數(shù)減少.但我對它的期望并不高(僅限 32 位指針),而是有一個功能可以在未來更好地管理代碼.許多函數(shù)現(xiàn)在處于休眠狀態(tài)(用于測試),例如慢變體、mod 和較舊的快速函數(shù)(使用 w 參數(shù)代替 *w2,i2).

There is still the possibility to use less heap trashing by separating NTT_fast to two functions. One with WW[] and the other with iWW[] which leads to one parameter less in recursion calls. But I do not expect much from it (32-bit pointer only) and rather have one function for better code management in the future. Many functions are dormant now (for testing) Like slow variants, mod and the older fast function (with w parameter instead of *w2,i2).

為避免大數(shù)據(jù)集溢出,將輸入數(shù)字限制為 p/4 位. 其中 p 是每個 的位數(shù)NTT 元素,因此對于此 32 位版本,請使用最大 (32 位/4 -> 8 位) 輸入值.

To avoid overflows for big datasets, limit input numbers to p/4 bits. Where p is number of bits per NTT element so for this 32 bit version use max (32 bit/4 -> 8 bit) input values.

[edit3] 用于測試的簡單字符串 bigint 乘法

[edit3] Simple string bigint multiplication for testing

//---------------------------------------------------------------------------
char* mul_NTT(const char *sx,const char *sy)
    {
    char *s;
    int i,j,k,n;
    // n = min power of 2 <= 2 max length(x,y)
    for (i=0;sx[i];i++); for (n=1;n<i;n<<=1);        i--;
    for (j=0;sx[j];j++); for (n=1;n<j;n<<=1); n<<=1; j--;
    DWORD *x,*y,*xx,*yy,a;
    x=new DWORD[n]; xx=new DWORD[n];
    y=new DWORD[n]; yy=new DWORD[n];

    // Zero padding
    for (k=0;i>=0;i--,k++) x[k]=sx[i]-'0'; for (;k<n;k++) x[k]=0;
    for (k=0;j>=0;j--,k++) y[k]=sy[j]-'0'; for (;k<n;k++) y[k]=0;

    //NTT
    fourier_NTT ntt;
    ntt.NTT(xx,x,n);
    ntt.NTT(yy,y);

    // Convolution
    for (i=0;i<n;i++) xx[i]=ntt.modmul(xx[i],yy[i]);

    //INTT
    ntt.iNTT(yy,xx);

    //suma
    a=0; s=new char[n+1]; for (i=0;i<n;i++) { a+=yy[i]; s[n-i-1]=(a%10)+'0'; a/=10; } s[n]=0;
    delete[] x; delete[] xx;
    delete[] y; delete[] yy;

    return s;
    }
//---------------------------------------------------------------------------

我使用AnsiString,所以我希望將它移植到char*,我沒有做錯.看起來它工作正常(與 AnsiString 版本相比).

I use AnsiString's, so I port it to char* hopefully, I did not do some mistake. It looks like it works properly (in comparison to the AnsiString version).

  • sx,sy 是十進制整數(shù)
  • 返回分配的字符串(char*)=sx*sy
  • sx,sy are decadic integer numbers
  • Returns allocated string (char*)=sx*sy

每 32 位數(shù)據(jù)字只有 ~4 位,因此沒有溢出的風(fēng)險,但當(dāng)然速度較慢.在我的 bignum 庫中,我使用二進制表示,并為 NTT 每 32 位 WORD 使用 8 位 塊.如果 N 很大,那么風(fēng)險更大......

This is only ~4 bit per 32 bit data word so there is no risk of overflow, but it is slower of course. In my bignum lib I use a binary representation and use 8 bit chunks per 32-bit WORD for NTT. More than that is risky if N is big ...

玩得開心

推薦答案

首先,非常感謝您發(fā)布并免費使用它.我真的很感激.

First off, thank you very much for posting and making it free to use. I really appreciate that.

我能夠使用一些小技巧來消除一些分支,重新排列主循環(huán)并修改程序集,并且能夠獲得 1.35 倍的加速.

I was able to use some bit tricks to eliminate some branching, rearranged the main loop, and modified the assembly, and was able to get a 1.35x speedup.

另外,我為 64 位添加了一個預(yù)處理器條件,因為 Visual Studio 不允許在 64 位模式下進行內(nèi)聯(lián)匯編(謝謝微軟;你可以自己搞砸了).

Also, I added a preprocessor condition for 64 bit, seeing as Visual Studio doesn't allow inline assembly in 64 bit mode (thank you Microsoft; feel free to go screw yourself).

在優(yōu)化 modsub() 函數(shù)時發(fā)生了一些奇怪的事情.我像 modadd 一樣使用 bit hacks 重寫了它(速度更快).但出于某種原因,modsub 的位明智版本較慢.不知道為什么.可能只是我的電腦.

Something strange happened when I was optimizing the modsub() function. I rewrote it using bit hacks like I did modadd (which was faster). But for some reason, the bit wise version of modsub was slower. Not sure why. Might just be my computer.

//
// Mandalf The Beige
// Based on:
// Spektre
// http://stackoverflow.com/questions/18577076/modular-arithmetics-and-ntt-finite-field-dft-optimizations
//
// This code may be freely used however you choose, so long as it is accompanied by this notice.
//




#ifndef H__OPTIMIZED_NUMBER_THEORETIC_TRANSFORM__HDR
#define H__OPTIMIZED_NUMBER_THEORETIC_TRANSFORM__HDR

#include <string.h>

#ifndef uint32
#define uint32 unsigned long int
#endif

#ifndef uint64
#define uint64 unsigned long long int
#endif


class fast_ntt                                   // number theoretic transform
{
    public:
    fast_ntt()
    {
        r = 0; L = 0;
        W = 0; iW = 0; rN = 0;
    }
    // main interface
    void  NTT(uint32 *dst, uint32 *src, uint32 n = 0);             // uint32 dst[n] = fast  NTT(uint32 src[n])
    void INTT(uint32 *dst, uint32 *src, uint32 n = 0);             // uint32 dst[n] = fast INTT(uint32 src[n])
    // helper functions

    private:
    bool init(uint32 n);                                     // init r,L,p,W,iW,rN
    void NTT_calc(uint32 *dst, uint32 *src, uint32 n, uint32 w);  // uint32 dst[n] = fast  NTT(uint32 src[n])

    void  NTT_fast(uint32 *dst, uint32 *src, uint32 n, uint32 w);  // uint32 dst[n] = fast  NTT(uint32 src[n])
    void NTT_fast(uint32 *dst, const uint32 *src, uint32 n, uint32 w);
    // only for testing
    void  NTT_slow(uint32 *dst, uint32 *src, uint32 n, uint32 w);  // uint32 dst[n] = slow  NTT(uint32 src[n])
    void INTT_slow(uint32 *dst, uint32 *src, uint32 n, uint32 w);  // uint32 dst[n] = slow INTT(uint32 src[n])
    // uint32 arithmetics


    // modular arithmetics
    inline uint32 modadd(uint32 a, uint32 b);
    inline uint32 modsub(uint32 a, uint32 b);
    inline uint32 modmul(uint32 a, uint32 b);
    inline uint32 modpow(uint32 a, uint32 b);

    uint32 r, L, N;//, p;
    uint32 W, iW, rN;

    const uint32 p = 0xC0000001;
};

//---------------------------------------------------------------------------
void fast_ntt::NTT(uint32 *dst, uint32 *src, uint32 n)
{
    if (n > 0)
    {
        init(n);
    }
    NTT_fast(dst, src, N, W);
    //  NTT_slow(dst,src,N,W);
}

//---------------------------------------------------------------------------
void fast_ntt::INTT(uint32 *dst, uint32 *src, uint32 n)
{
    if (n > 0)
    {
        init(n);
    }
    NTT_fast(dst, src, N, iW);
    for (uint32 i = 0; i<N; i++)
    {
        dst[i] = modmul(dst[i], rN);
    }
    //  INTT_slow(dst,src,N,W);
}

//---------------------------------------------------------------------------
bool fast_ntt::init(uint32 n)
{
    // (max(src[])^2)*n < p else NTT overflow can ocur !!!
    r = 2;
    //p = 0xC0000001;
    if ((n < 2) || (n > 0x10000000))
    {
        r = 0; L = 0; W = 0; // p = 0;
        iW = 0; rN = 0; N = 0;
        return false;
    }
    L = 0x30000000 / n; // 32:30 bit best for unsigned 32 bit
    //  r=2; p=0x78000001; if ((n<2)||(n>0x04000000)) { r=0; L=0; p=0; W=0; iW=0; rN=0; N=0; return false; } L=0x3c000000/n; // 31:27 bit best for signed 32 bit
    //  r=2; p=0x00010001; if ((n<2)||(n>0x00000020)) { r=0; L=0; p=0; W=0; iW=0; rN=0; N=0; return false; } L=0x00000020/n; // 17:16 bit best for 16 bit
    //  r=2; p=0x0a000001; if ((n<2)||(n>0x01000000)) { r=0; L=0; p=0; W=0; iW=0; rN=0; N=0; return false; } L=0x01000000/n; // 28:25 bit
    N = n;               // size of vectors [uint32s]
    W = modpow(r, L); // Wn for NTT
    iW = modpow(r, p - 1 - L); // Wn for INTT
    rN = modpow(n, p - 2); // scale for INTT
    return true;
}

//---------------------------------------------------------------------------

void fast_ntt::NTT_fast(uint32 *dst, uint32 *src, uint32 n, uint32 w)
{
    if(n > 1)
    {
        if(dst != src)
        {
            NTT_calc(dst, src, n, w);
        }
        else
        {
            uint32* temp = new uint32[n];
            NTT_calc(temp, src, n, w);
            memcpy(dst, temp, n * sizeof(uint32));
            delete [] temp;
        }
    }
    else if(n == 1)
    {
        dst[0] = src[0];
    }
}

void fast_ntt::NTT_fast(uint32 *dst, const uint32 *src, uint32 n, uint32 w)
{
    if (n > 1)
    {
        uint32* temp = new uint32[n];
        memcpy(temp, src, n * sizeof(uint32));
        NTT_calc(dst, temp, n, w);
        delete[] temp;
    }
    else if (n == 1)
    {
        dst[0] = src[0];
    }
}



void fast_ntt::NTT_calc(uint32 *dst, uint32 *src, uint32 n, uint32 w)
{
    if(n > 1)
    {
        uint32 i, j, a0, a1,
        n2 = n >> 1,
        w2 = modmul(w, w);

        // reorder even,odd
        for (i = 0, j = 0; i < n2; i++, j += 2)
        {
            dst[i] = src[j];
        }
        for (j = 1; i < n; i++, j += 2)
        {
            dst[i] = src[j];
        }
        // recursion
        if(n2 > 1)
        {
            NTT_calc(src, dst, n2, w2);  // even
            NTT_calc(src + n2, dst + n2, n2, w2);  // odd
        }
        else if(n2 == 1)
        {
            src[0] = dst[0];
            src[1] = dst[1];
        }

        // restore results

        w2 = 1, i = 0, j = n2;
        a0 = src[i];
        a1 = src[j];
        dst[i] = modadd(a0, a1);
        dst[j] = modsub(a0, a1);
        while (++i < n2)
        {
            w2 = modmul(w2, w);
            j++;
            a0 = src[i];
            a1 = modmul(src[j], w2);
            dst[i] = modadd(a0, a1);
            dst[j] = modsub(a0, a1);
        }
    }
}

//---------------------------------------------------------------------------
void fast_ntt::NTT_slow(uint32 *dst, uint32 *src, uint32 n, uint32 w)
{
    uint32 i, j, wj, wi, a,
        n2 = n >> 1;
    for (wj = 1, j = 0; j < n; j++)
    {
        a = 0;
        for (wi = 1, i = 0; i < n; i++)
        {
            a = modadd(a, modmul(wi, src[i]));
            wi = modmul(wi, wj);
        }
        dst[j] = a;
        wj = modmul(wj, w);
    }
}

//---------------------------------------------------------------------------
void fast_ntt::INTT_slow(uint32 *dst, uint32 *src, uint32 n, uint32 w)
{
    uint32 i, j, wi = 1, wj = 1, a, n2 = n >> 1;

    for (wj = 1, j = 0; j < n; j++)
    {
        a = 0;
        for (wi = 1, i = 0; i < n; i++)
        {
            a = modadd(a, modmul(wi, src[i]));
            wi = modmul(wi, wj);
        }
        dst[j] = modmul(a, rN);
        wj = modmul(wj, iW);
    }
}    


//---------------------------------------------------------------------------
uint32 fast_ntt::modadd(uint32 a, uint32 b)
{
    uint32 d;
    d = a + b;

    if(d < a)
    {
        d -= p;
    }
    if (d >= p)
    {
        d -= p;
    }
    return d;
}

//---------------------------------------------------------------------------
uint32 fast_ntt::modsub(uint32 a, uint32 b)
{
    uint32 d;
    d = a - b;
    if (d > a)
    {
        d += p;
    }
    return d;
}

//---------------------------------------------------------------------------
uint32 fast_ntt::modmul(uint32 a, uint32 b)
{
    uint32 _a = a;
    uint32 _b = b;

    // Original
    uint32 _p = p;
    __asm
    {
        mov eax, _a;
        mul _b;
        div _p;
        mov eax, edx;
    };
}


uint32 fast_ntt::modpow(uint32 a, uint32 b)
{
    //*
    uint64 D, M, A, P;

    P = p; A = a;
    M = 0llu - (b & 1);
    D = (M & A) | ((~M) & 1);

    while ((b >>= 1) != 0)
    {
        A = modmul(A, A);
        //A = (A * A) % P;

        if ((b & 1) == 1)
        {
            //D = (D * A) % P;
            D = modmul(D, A);
        }
    }
    return (uint32)D;
}

新模塊

uint32 fast_ntt::modmul(uint32 a, uint32 b)
{
    uint32 _a = a;
    uint32 _b = b;   

    __asm
    {
    mov eax, a;
    mul b;
    mov ebx, eax;
    mov eax, 2863311530;
    mov ecx, edx;
    mul edx;
    shld edx, eax, 1;
    mov eax, 3221225473;

    mul edx;
    sub ebx, eax;
    mov eax, 3221225473;
    sbb ecx, edx;
    jc addback;

            neg ecx;
            and ecx, eax;
            sub ebx, ecx;

    sub ebx, eax;
    sbb edx, edx;
    and eax, edx;
            addback:
    add eax, ebx;          
    };  
}

Spektre,根據(jù)您的反饋,我更改了 modadd &modsub 回到原來的狀態(tài).我也意識到我對遞歸 NTT 函數(shù)做了一些我不應(yīng)該做的更改.

Spektre, based on your feedback I changed the modadd & modsub back to their original. I also realized I made some changes to the recursive NTT function I shouldn't have.

刪除了不需要的 if 語句和按位函數(shù).

Removed unneeded if statements and bitwise functions.

添加了新的 modmul 內(nèi)聯(lián)程序集.

Added new modmul inline assembly.

這篇關(guān)于模塊化算法和 NTT(有限域 DFT)優(yōu)化的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!

【網(wǎng)站聲明】本站部分內(nèi)容來源于互聯(lián)網(wǎng),旨在幫助大家更快的解決問題,如果有圖片或者內(nèi)容侵犯了您的權(quán)益,請聯(lián)系我們刪除處理,感謝您的支持!

相關(guān)文檔推薦

Algorithm to convert RGB to HSV and HSV to RGB in range 0-255 for both(將 RGB 轉(zhuǎn)換為 HSV 并將 HSV 轉(zhuǎn)換為 RGB 的算法,范圍為 0-255)
How to convert an enum type variable to a string?(如何將枚舉類型變量轉(zhuǎn)換為字符串?)
When to use inline function and when not to use it?(什么時候使用內(nèi)聯(lián)函數(shù),什么時候不使用?)
Examples of good gotos in C or C++(C 或 C++ 中好的 goto 示例)
Significance of ios_base::sync_with_stdio(false); cin.tie(NULL);(ios_base::sync_with_stdio(false) 的意義;cin.tie(NULL);)
Is TCHAR still relevant?(TCHAR 仍然相關(guān)嗎?)
主站蜘蛛池模板: 亿光电子 中山 有限公司| 徐州水利工程建设有限公司 | 惠丰农业发展有限公司| 山东力士德工程机械有限公司| 深圳崇德物业有限公司| 上海雄机电设备有限公司| 常州电力装备有限公司| 苏州石油设备有限公司| 洛阳金诺机械工程有限公司| 济南鑫塑料有限公司| 深圳市亚泰电子有限公司| 广州冷热设备有限公司| 郑州工业产品设计有限公司| 北京六智信息技术有限公司| 诺贝尔福基机电有限公司| 锦明装饰工程有限公司| 杭州意博高科有限公司| 中油恒燃石油燃气有限公司| 梁子时装实业有限公司| 南京埃斯顿自动化有限公司| 长城成套电气有限公司| 江西南昌化工有限公司| 广州市机械设备租赁有限公司| 名尚装饰工程有限公司| 荣成 玻璃 有限公司| 河北乙连生物有限公司| 南京有机玻璃有限公司| 乐迪餐饮北京有限公司| 佛山三水家具有限公司| 广州华俊医疗有限公司| 博海环保设备有限公司| 平湖德实机械有限公司| 漯河嘉吉食品有限公司| 华润燃气有限公司待遇| 蚌埠医疗器械有限公司| 宗艺石材发展有限公司| 欧普集成吊顶有限公司| 车易信息技术有限公司| 时代建筑设计院有限公司| 桃花季服饰有限公司| 电厂 环保有限公司| 山西光宇照明有限公司| 山东阳谷钎具有限公司| 贵阳包装材料有限公司| 华天成电器有限公司| 中润兴认证有限公司| 武汉 实验室设备有限公司| 南昌汽车贸易有限公司| 长城电子工程技术有限公司| 宏桥新型材料有限公司| 博思格苏州有限公司| 东莞市铜材有限公司| 埃克森美孚太仓石油有限公司| 广州国际纸业有限公司| 金湖建设工程有限公司| 盛泽水处理有限公司| 奥瑞拓石油机械有限公司| 味香园食品有限公司| 青牛北京技术有限公司| 保定九孚生化有限公司| 乐屋遮阳帘技术有限公司| 珠海上富电技有限公司| 开封肉类食品有限公司| 三力士橡胶 有限公司| 上海亚华湖有限公司| 深圳市源鸿贸易有限公司| 台福(福州)有限公司| 博思格钢铁有限公司| 古蔺郎酒销售有限公司| 上海志如汽销有限公司| 高丽雅娜化妆品有限公司| 常州 塑钢有限公司| 陕西汽车贸易有限公司招聘| 钦联(上海)资产有限公司| 广州装饰装修有限公司| 远东石化)有限公司| 深圳市筑道建筑工程设计有限公司| 沈阳谷酒业有限公司| 深圳泰盈电子有限公司| 都德利电子有限公司| 天益食品 徐州 有限公司| 沈阳港有限公司招聘信息| 华通人商用信息有限公司| 达洋有限公司怎么样| 中山市劳务派遣有限公司| 中山华科电器有限公司| 上海自控阀门有限公司招聘| 山东厚丰散热器有限公司| 横店电影院线有限公司| 不锈钢有限公司简介| 广东优果农业有限公司| 杭州雅莱贸易有限公司| 贵州塑胶有限公司招聘| 广州嘉艺工艺品有限公司| 北京市机电技术有限公司| 医美医院有限公司招聘| 黄冈 建材有限公司| 驻马店纺织有限公司| 光时信息技术有限公司| 合肥 景观设计有限公司| 浙江电力设备制造有限公司| 浙江教育设备有限公司| 诸暨汽车配件有限公司| 韩泰轮胎(嘉兴)有限公司| 日银微电子有限公司| 三兄弟食品有限公司| 南京资讯有限公司怎么样| 浙江巨力电机成套设备有限公司| 深圳市域鑫有限公司| 大自然纸业有限公司| 四川沱牌舍得酒业有限公司| 北京名饮贸易有限公司| 宁晋县食品有限公司| 辽宁医药有限公司招聘| 五洲无线技术有限公司| 科世佳电子有限公司| 河北迈特贸易有限公司| 常州常蒸蒸发器有限公司| 清华苑建筑设计有限公司| 招商局重工 江苏 有限公司| 上海东方拍卖有限公司| 工业吸尘器有限公司| 彬台机械 苏州 有限公司| 广州蝶恋花有限公司| 东柏彩印深圳有限公司| 有限公司 项目 落户| 深圳雨伞业有限公司| 苏州凯而高电子有限公司| 万通保险销售有限公司| 茌平密度板有限公司| 中电投山西铝业有限公司| 上海全景数字技术有限公司| 心连心餐饮有限公司| 山西和信基业有限公司| 重庆卓创国际设计有限公司| 上海纳沙泰尔手表有限公司| 村邦信息技术有限公司| 德居装饰工程有限公司| 易锻精密机械有限公司| 广州市蓝服装有限公司| 万得国际贸易有限公司| 商丘佳食食品有限公司| 江西九江化工有限公司| 无锡怡生医疗设备有限公司 | 福建巨龙光学有限公司| 三拓识别技术有限公司| 广州安机械设备有限公司| 菲斯达精密部件有限公司| 安格斯机械有限公司| 翔鸿建筑工程有限公司| 万都汽车部件有限公司| 海南互联网有限公司| 梅州市客品食品有限公司| 皇嘉贵金属经营有限公司| 富葵精密深圳有限公司| 日立空调(苏州)有限公司| 丹阳 混凝土有限公司| 杭州华电半山发电有限公司| 索菲亚 廊坊 有限公司| 泰克互感器有限公司| 上海特钢有限公司地址| 广州科奥信息技术有限公司| 福建电动车有限公司| 招远黄金矿业有限公司| 烟台金子生物工程有限公司| 深圳市康讯电子有限公司| 库博信息技术有限公司| 杭州灌溉 有限公司| 采埃孚 天津 风电有限公司| 空气化工广州有限公司| 上海雕塑设计有限公司| 万国太阳白卡纸有限公司| 其胜生物制剂有限公司| 云川装饰工程有限公司| 厦门了帝食品有限公司| 法雷奥汽车零部件贸易有限公司| 上海驰达汽车有限公司| 德阳建筑工程有限公司| 南昌辉门密封件有限公司| 台湾自动化有限公司| 济南鑫塑料有限公司| 天宝有限公司怎么样| 沈阳东亿机械有限公司| 上海比灿信息技术有限公司| 高正农用化工有限公司| 浙江海德曼机床有限公司| 安顺交通设施有限公司| 上海古猿人有限公司| 上海 咖啡有限公司招聘| 万机创意电子有限公司| 东营 仪器有限公司| 康拜恩电器有限公司| 东莞工业器材有限公司| 江西雅星纺织有限公司| 皮拉图斯飞机有限公司| 东莞塘厦五金有限公司| 黑美人茶业有限公司| 中核中原对外工程有限公司| 重庆佳佳食品有限公司| 鑫美化妆品有限公司| 施塔德电梯有限公司| 苏州瑞中电子有限公司| 迅达电子苏州有限公司| 日东自动化设备有限公司 | 广州仪德科学有限公司| 南源置业(武汉)有限公司| 中源汽车零部件有限公司| 昆山欣兴同泰有限公司| 大自然纸业有限公司| 联发科电子有限公司| 爱维门业 昆山 有限公司| 武汉桥梁监理有限公司| 依蝶化妆品有限公司| 美的制冷设备有限公司招聘| 杭州方圆塑料有限公司| 东北阜丰生物有限公司| 友威光电惠州有限公司| 深圳电池新能源有限公司| 联合赛尔生物工程有限公司| 深圳凯亚电子有限公司| 长城装饰设计工程有限公司| 中建电气成套设备有限公司| 海南美佳精细化工有限公司| 上海住友重机械有限公司| 金源浩进出口有限公司| 三麦机械(珠海)有限公司| 华必和餐饮有限公司| 河南食爱食品有限公司| 徐州龙 泵业有限公司| 佛山点庆贸易有限公司| 东莞市巨塑塑胶有限公司| 国际层压板有限公司| 芜湖伯特利有限公司| 大连海尔空调有限公司| 鸿大装饰工程有限公司| 厦门盛达贸易有限公司| 广西设备招标有限公司| 广州宝农饲料有限公司| 华贸深圳有限公司招聘| 福伊特驱动技术系统有限公司| 诺丹舜蒲胶辊有限公司| 江苏九龙汽车有限公司| 宏丰工艺品有限公司| 吉利迪新能源汽车有限公司| 鑫凌龙贵金属经营有限公司| 健福堂北京有限公司| 常州铭赛机器人有限公司| 康怡 卫生用品有限公司| 青海可可西里食品有限公司| 潍坊电子技术有限公司| 天津新阳化工有限公司| 恒富金属制品有限公司| 积水置业沈阳有限公司| 上虞绍风化工化工有限公司| 河南利达工程有限公司| 天涯国际旅行社有限公司| 青岛德盛食品有限公司| 扬子江石化有限公司| 安维斯橡胶减震器有限公司| 达州川虎食品有限公司| 南通太平洋海洋工程有限公司| 四川国锂锂材料有限公司| 中铝山西铝业有限公司| 德士达光电有限公司| 阿贝尔苏州有限公司| 中山市 照明电气有限公司| 东莞环仪仪器有限公司| 北京开元贸易有限公司| 上海金易久大酒业有限公司| 比瑞吉宠物用品有限公司| 佛山市嘉美照明有限公司| 四川南玻玻璃有限公司| 霸州三强金属有限公司| 利安人寿保险有限公司| 嘉得力清洁设备有限公司| 佛山电子厂有限公司| 奥托斯电子有限公司| 江西电动汽车有限公司| 佛山市石油化工有限公司| 乐金电子天津有限公司| 江苏丹顶鹤建设有限公司| 柳州压缩机有限公司| 上海维华节水灌溉有限公司| 苏州工业园区建屋发展有限公司 | 青岛阳光贸易有限公司| 佛山市建电子有限公司| 宏达医疗器械有限公司| 银鹏动力设备有限公司| 厦门五金制造有限公司| 西果记果业有限公司| 广东中矿矿业有限公司| 黄山医疗器械有限公司| 上海正章实业有限公司| 浙江长兴耐火材料有限公司| 船舶与海洋工程发展有限公司| 协顺灯饰惠州有限公司| 上海金东唐有限公司| 海得新能源有限公司| 欧拓重庆防音配件有限公司| 欣贺厦门服饰有限公司| 基胜工业(上海)有限公司| 苏州散热器有限公司| 金利珠宝首饰有限公司| 亿龙汽车销售有限公司| 道然进出口有限公司| 新华密封件有限公司| 安吉鼎吉家具有限公司| 苏州圣万提注塑有限公司| 洛阳永生食品有限公司| 中诺质检仪器设备有限公司| 诺柯佳贸易有限公司| 东阳实业有限公司招聘| 品联激光技术有限公司| 虎虎侠贸易有限公司| 神州数码融信有限公司| 世纪美服饰有限公司| 三门峡 耐火材料有限公司| 五洲无线技术有限公司| 上海石田衡器有限公司| 安徽淮酒酒业有限公司| 广州依纯服装有限公司| 广州幕墙设计有限公司| 苏沂州煤焦化有限公司| 广州光电子技术有限公司| 御嘉装饰工程有限公司| 华东电子深圳有限公司| 嘉鹏新能源有限公司| 亮科装饰工程有限公司| 惠利普电机有限公司| 上海市北高新有限公司| 久久信息技术有限公司| 佛山市华特气体有限公司| 云南电力安装工程有限公司| 南亚工程机械有限公司| 深圳市亿时代有限公司| 上海得保国际贸易有限公司| 厦门建材有限公司招聘信息| 北京资生生物有限公司| 聚升有限公司怎么样| 合肥太古可乐有限公司| 泛博制动部件 苏州 有限公司| 博尔德能源有限公司| 同捷汽车设计有限公司| 广州新沙港务有限公司| 康瑞思信息技术有限公司| 深圳索信达实业有限公司| 石家庄市安装工程有限公司| 宁波金鑫混凝土有限公司| 黄鹤楼餐饮有限公司| 河北品特贸易有限公司| 芜湖工业设备有限公司| 河南嵩山建筑安装有限公司 | 广州安机械设备有限公司| 深圳隆科电子有限公司| 喜盈门家具制品有限公司| 迪凯特电子有限公司| 津宏电子上海有限公司| 凯达金属制品有限公司| 九江 服装有限公司| 温州鑫鞋业有限公司| 深圳迈诺电子有限公司| 禾绿回转寿司饮食有限公司| 兰凯机械制造有限公司| 奥凯医疗设备有限公司| 长安新能源汽车有限公司| 丰联实业发展有限公司| 青岛毕勤电子有限公司| 罗姆电子(天津)有限公司| 许昌鸿洋生化实业有限公司| 优派信息技术有限公司| 祥宇医疗器械有限公司| 云南 铸造有限公司| 四季青园林花卉有限公司| 陶瓷国际贸易有限公司| 徐州市钢结构工程有限公司| 江苏天地钢有限公司| 嘉宝莉河北有限公司| 厦门燃气工程有限公司| 金瑞包装机械有限公司| 南方钢结构有限公司| 华美建设工程有限公司| 佛瑞德工业有限公司| 大华医药化工有限公司| 林州市华通建设有限公司| 澳信 深圳有限公司| 凯蓝 深圳有限公司| 宝诚电子有限公司招聘| 宁波明大机械有限公司| 北京悦康凯悦制药有限公司| 川崎精密机械有限公司| 光隆羽绒制品有限公司| 沈阳万科地产有限公司| 伟诚建设工程有限公司| 仕达利恩(南京)有限公司| 武汉明达玻璃有限公司| 苏州好特斯模具有限公司| 江苏林洋新能源有限公司| 光大通信设备有限公司| 上海东聚电线有限公司| 河南养殖设备有限公司| 南通博建设工程有限公司| 黑牛食品工业有限公司| 歌莉娅服饰有限公司| 达亚进出口有限公司| 北方工业发展有限公司| 深圳水务工程有限公司| 新恒机械制造有限公司| 华苏国际贸易有限公司| 湖南消防器材有限公司| 齐鲁制药有限公司待遇| 远东电缆有限公司北京| 国投中鲁果汁有限公司| 宿州矿山机械有限公司| 新盛机械设备有限公司| 中科机器人有限公司怎么样| 隆都兴强食品有限公司| 苏州光普电子有限公司| 江西建筑材料有限公司| 平顶山纺织品有限公司| 墙体彩绘 有限公司| 普瑞科精密压铸有限公司| 广州耐火材料有限公司| 苏州易达电子有限公司| 佛山天朋温控器有限公司| 天津龙紫金贵金属有限公司| 苏明国际贸易有限公司| 江苏环宇工程有限公司| 福建戴姆勒工业有限公司| 国电财务有限公司待遇| 四川康贝药房连锁有限公司| 巢湖路桥工程有限公司| 天津安费诺电子有限公司| 龙基服装深圳有限公司| 广州超力混凝土有限公司| 阿乐斯(广州)有限公司| 广东温氏畜牧有限公司| 瑞得信息技术有限公司| 欧米特机械有限公司| 大乘环保建材有限公司| 百信信息技术有限公司| 苏州万诺电子有限公司| 嘉里建设(上海)有限公司| 东营 仪器有限公司| 凯赫威精密制造有限公司| 唐山味源食品有限公司| 金牌厨柜厦门有限公司| 天津渤海有限公司招聘| 苏州建屋发展有限公司| 国电光伏(江苏)有限公司| 智方建设工程有限公司| 上海城投水务有限公司| 宁夏源林生物发电有限公司| 博森美国际香港有限公司| 惠州tcl电器有限公司电话| 中山市生物工程有限公司| 广州大拇指有限公司| 辰辉建筑工程有限公司| 雄峰特殊钢有限公司| 无锡市 轮胎有限公司| 四川液压设备有限公司| 上海欧尚超市有限公司| 诺亚生物工程有限公司| 天津爱达零部件有限公司| 一缆电线电缆有限公司| 广州比朗仪器有限公司| 广东优果农业有限公司| 苏州市热电有限公司| 昆山宏塑光电有限公司| 斯丹德汽车系统 苏州 有限公司| 润禾生物医药有限公司| 苏州首户电气有限公司| 上海高饰装饰设计工程有限公司| 万康保健品有限公司| 贵州 老窖酒业有限公司| 恒基机电工程有限公司 | 湖南药业有限公司招聘| 云测信息技术有限公司| 仕瑞达自动化设备有限公司| 如皋市双马化工有限公司| 宁德进出口有限公司| 洪都电动车有限公司| 湖北福人药业有限公司| 北京石油在线技术有限公司 | 深圳劳斯实业有限公司| 秦皇康泰医学系统有限公司| 新昌县铜业有限公司| 豪迈木业机械有限公司| 捷高国际货运有限公司| 圣翰医疗器械有限公司| 恩宜天津工程有限公司| 杭州卓越置业有限公司| 中山市威尔电器有限公司| 建滔(河北)焦化有限公司| 陕西意景园林有限公司| 杭州杭升服装有限公司| 江西天化学有限公司| 天津九安医疗有限公司| 东方久乐汽车安全气囊有限公司| 广东康力药业有限公司| 东瑞机电设备有限公司| 苏州佳彩精密有限公司| 沱牌舍得酒业有限公司| 哈尔滨量具有限公司| 申隆包装材料有限公司| 四川省新鹿药业有限公司| 广东环凯微生物有限公司| 茂名 石化有限公司 招聘| 广州市花都机械有限公司| 虹桥包装实业有限公司| 灵思远景营销顾问有限公司| 池州市 化工有限公司| 北京中晟达有限公司| 上海达联电子有限公司| 歌诗玛化妆品有限公司| 贝亲母婴用品有限公司| 常州包装容器有限公司| 铁骑力士实业有限公司| asm深圳有限公司| 上海捷密精密机械有限公司| 盐城市锅炉制造有限公司| 苏州斯达克听力有限公司| 泰美包装材料有限公司| 贺氏苏州特殊材料有限公司| 北京蓝星化工机械有限公司| 鑫汇进出口有限公司| 派派食品有限公司怎么样| 广州京龙机械有限公司| 杰信汽车部件有限公司| 哈尔滨中顺有限公司| 大连三轴轴承有限公司| 浙江汽车技术有限公司| 濮阳钢结构有限公司| 新纪元实业有限公司| 广州华安实业有限公司| 深圳建辰实业有限公司| 深圳华友能源技术有限公司| 华兴金属制品有限公司| 深圳市伟特电子有限公司| 正大食品洛阳有限公司| 杭州立昂微电子有限公司| 飞利浦香港有限公司| 佳鸿贸易发展有限公司| 浙江哈尔斯有限公司| 人和装饰工程有限公司| 珠海西默电气有限公司| 上海市航运有限公司| 中金融资租赁有限公司| 深圳富迪电子有限公司| 湖南炎帝生物有限公司| 微信营销有限公司怎么样的| 湖南怡清源茶业有限公司| 焦作金的食品有限公司| 深圳聚电电子有限公司| 广汽丰田销售有限公司| 豪亿装饰工程有限公司| 杭州嘉隆 有限公司| 江门市卫生用品有限公司| 中石化新奥能源有限公司| 艾斯工程机械有限公司| 江苏剑牌农化有限公司| 美亚金属制品有限公司| 天润一舟(北京)有限公司| 上海不二贸易有限公司| 番华金银珠宝有限公司| 泰山耐火材料有限公司| 宜兴市安装有限公司| 成都英格刀具有限公司| 日立苏州医疗系统有限公司| 景涛景观设计有限公司| 张家港低温装备有限公司| 阿特维斯佛山制药有限公司| 上海三本照明有限公司| 广东惠州发电有限公司| 东莞达利盛时装有限公司| 世迈国际贸易有限公司| 北京兄弟搬家有限公司| 微流体技术有限公司| 武汉华源电气有限公司| 东莞市市政工程有限公司| 北京绿海食品有限公司| 菲菲诗化妆品有限公司| 光大通信设备有限公司| 中山品尚服饰有限公司| 昂科信息技术有限公司| 泰山工程机械有限公司| 诺光照明(苏州)有限公司| 四川源川建筑有限公司| 万事顺电子有限公司| 美太保健制品有限公司| 希门凯电子有限公司| 2014一人有限公司章程| 深圳宝源贸易有限公司| 三井住友融资租赁有限公司| 冠香园食品有限公司| 杏辉天力杭州药业有限公司| 四川暖通设备工程有限公司| 四川 阀业有限公司| 春金油脂工业有限公司| 瑞安捷电子有限公司| 长沙建设机械有限公司| 福伊特水电设备有限公司| 诺信深圳有限公司怎么样| 福州可的食品有限公司| 福盛电子技术有限公司| 鑫鑫生物能源有限公司| 西安重型机械有限公司| 伟创力金属有限公司| 广州莉都化妆品有限公司| 佛山市 印刷有限公司招聘| 好思家涂料有限公司| 山东雪花啤酒有限公司| 中山品尚服饰有限公司| 有限公司是独立法人| 天津五市政公路工程有限公司| 保利进出口有限公司| 深圳优博讯有限公司| 深圳华佳业有限公司| 上海 阁 有限公司怎么样| 郑州华鑫机械有限公司| 毕博信息技术有限公司| 深圳茂业百货有限公司| 南通印染机械有限公司| 科太环境技术有限公司| 义乌市打火机有限公司| bhp国际持股有限公司| 上海柏宜照明有限公司| 上海升和服饰有限公司| tcm叉车有限公司| 浙江海宁服饰有限公司| 广州星逸贸易有限公司| 健康产业园有限公司| 海开环球置业有限公司| 米高上海汽车配件有限公司| 四海一家餐饮有限公司| 武汉鑫越工贸有限公司| 江苏苏科医疗器械有限公司| 中奥建工程设计有限公司| 亿通电力工程有限公司| 业成光电深圳有限公司| 上海拓衡实业有限公司| 武汉人天包装技术有限公司| 史密斯医疗器械有限公司| 深圳立讯精密工业有限公司| 英皇钟表珠宝有限公司| 万向123系统有限公司| 万可电子(天津)有限公司| 三星胶制品有限公司| 广州创威电子有限公司| 派派食品有限公司怎么样| 富山阀门实业 苏州 有限公司| 瓦锡兰苏州有限公司| 湖南中科电气有限公司| 清雅化妆品有限公司| 京龙电子技术有限公司| 鞍山市政工程有限公司| 石家庄三利有限公司| 麦克维尔武汉制冷有限公司| 广州市柏盛有限公司| 东方 橡胶制品有限公司| 迪恩士上海有限公司| 上海宝农发展有限公司| 曼透平机械常州有限公司| 中山市生物工程有限公司| 莆田涵江鞋业有限公司| 环保 天津有限公司待遇|