123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- #include "rar.hpp"
- RSCoder16::RSCoder16()
- {
- Decoding=false;
- ND=NR=NE=0;
- ValidFlags=NULL;
- MX=NULL;
- DataLog=NULL;
- DataLogSize=0;
- gfInit();
- }
- RSCoder16::~RSCoder16()
- {
- delete[] gfExp;
- delete[] gfLog;
- delete[] DataLog;
- delete[] MX;
- delete[] ValidFlags;
- }
- void RSCoder16::gfInit()
- {
- gfExp=new uint[4*gfSize+1];
- gfLog=new uint[gfSize+1];
- for (uint L=0,E=1;L<gfSize;L++)
- {
- gfLog[E]=L;
- gfExp[L]=E;
- gfExp[L+gfSize]=E;
- E<<=1;
- if (E>gfSize)
- E^=0x1100B;
- }
-
-
- gfLog[0]= 2*gfSize;
- for (uint I=2*gfSize;I<=4*gfSize;I++)
- gfExp[I]=0;
- }
- uint RSCoder16::gfAdd(uint a,uint b)
- {
- return a^b;
- }
- uint RSCoder16::gfMul(uint a,uint b)
- {
- return gfExp[gfLog[a]+gfLog[b]];
- }
- uint RSCoder16::gfInv(uint a)
- {
- return a==0 ? 0:gfExp[gfSize-gfLog[a]];
- }
- bool RSCoder16::Init(uint DataCount, uint RecCount, bool *ValidityFlags)
- {
- ND = DataCount;
- NR = RecCount;
- NE = 0;
- Decoding=ValidityFlags!=NULL;
- if (Decoding)
- {
- delete[] ValidFlags;
- ValidFlags=new bool[ND + NR];
- for (uint I = 0; I < ND + NR; I++)
- ValidFlags[I]=ValidityFlags[I];
- for (uint I = 0; I < ND; I++)
- if (!ValidFlags[I])
- NE++;
- uint ValidECC=0;
- for (uint I = ND; I < ND + NR; I++)
- if (ValidFlags[I])
- ValidECC++;
- if (NE > ValidECC || NE == 0 || ValidECC == 0)
- return false;
- }
-
- if (ND + NR > gfSize || ND == 0 || NR == 0)
- return false;
- delete[] MX;
- if (Decoding)
- {
- MX=new uint[NE * ND];
- MakeDecoderMatrix();
- InvertDecoderMatrix();
- }
- else
- {
- MX=new uint[NR * ND];
- MakeEncoderMatrix();
- }
- return true;
- }
- void RSCoder16::MakeEncoderMatrix()
- {
-
-
- for (uint I = 0; I < NR; I++)
- for (uint J = 0; J < ND; J++)
- MX[I * ND + J] = gfInv( gfAdd( (I+ND), J) );
- }
- void RSCoder16::MakeDecoderMatrix()
- {
-
-
-
-
-
- for (uint Flag=0, R=ND, Dest=0; Flag < ND; Flag++)
- if (!ValidFlags[Flag])
- {
- while (!ValidFlags[R])
- R++;
- for (uint J = 0; J < ND; J++)
- MX[Dest*ND + J] = gfInv( gfAdd(R,J) );
- Dest++;
- R++;
- }
- }
- void RSCoder16::InvertDecoderMatrix()
- {
- uint *MI=new uint[NE * ND];
- memset(MI, 0, ND * NE * sizeof(*MI));
- for (uint Kr = 0, Kf = 0; Kr < NE; Kr++, Kf++)
- {
- while (ValidFlags[Kf])
- Kf++;
- MI[Kr * ND + Kf] = 1;
- }
-
-
-
-
- for (uint Kr = 0, Kf = 0; Kf < ND; Kr++, Kf++)
- {
- while (ValidFlags[Kf] && Kf < ND)
- {
-
-
-
-
- for (uint I = 0; I < NE; I++)
- MI[I * ND + Kf] ^= MX[I * ND + Kf];
- Kf++;
- }
- if (Kf == ND)
- break;
- uint *MXk = MX + Kr * ND;
- uint *MIk = MI + Kr * ND;
- uint PInv = gfInv( MXk[Kf] );
-
- for (uint I = 0; I < ND; I++)
- {
- MXk[I] = gfMul( MXk[I], PInv );
- MIk[I] = gfMul( MIk[I], PInv );
- }
- for (uint I = 0; I < NE; I++)
- if (I != Kr)
- {
-
-
- uint *MXi = MX + I * ND;
- uint *MIi = MI + I * ND;
- uint Mik = MXi[Kf];
- for (uint J = 0; J < ND; J++)
- {
- MXi[J] ^= gfMul(MXk[J] , Mik);
- MIi[J] ^= gfMul(MIk[J] , Mik);
- }
- }
- }
-
- for (uint I = 0; I < NE * ND; I++)
- MX[I] = MI[I];
- delete[] MI;
- }
- #if 0
- void RSCoder16::Process(const uint *Data, uint *Out)
- {
- uint ProcData[gfSize];
- for (uint I = 0; I < ND; I++)
- ProcData[I]=Data[I];
- if (Decoding)
- {
-
-
- for (uint I=0, R=ND, Dest=0; I < ND; I++)
- if (!ValidFlags[I])
- {
- while (!ValidFlags[R])
- R++;
- ProcData[I]=Data[R];
- R++;
- }
- }
- uint H=Decoding ? NE : NR;
- for (uint I = 0; I < H; I++)
- {
- uint R = 0;
- uint *MXi=MX + I * ND;
- for (uint J = 0; J < ND; J++)
- R ^= gfMul(MXi[J], ProcData[J]);
- Out[I] = R;
- }
- }
- #endif
- void RSCoder16::UpdateECC(uint DataNum, uint ECCNum, const byte *Data, byte *ECC, size_t BlockSize)
- {
- if (DataNum==0)
- memset(ECC, 0, BlockSize);
- bool DirectAccess;
- #ifdef LITTLE_ENDIAN
-
- DirectAccess=sizeof(ushort)==2;
- #else
- DirectAccess=false;
- #endif
- #ifdef USE_SSE
- if (DirectAccess && SSE_UpdateECC(DataNum,ECCNum,Data,ECC,BlockSize))
- return;
- #endif
- if (ECCNum==0)
- {
- if (DataLogSize!=BlockSize)
- {
- delete[] DataLog;
- DataLog=new uint[BlockSize];
- DataLogSize=BlockSize;
- }
- if (DirectAccess)
- for (size_t I=0; I<BlockSize; I+=2)
- DataLog[I] = gfLog[ *(ushort*)(Data+I) ];
- else
- for (size_t I=0; I<BlockSize; I+=2)
- {
- uint D=Data[I]+Data[I+1]*256;
- DataLog[I] = gfLog[ D ];
- }
- }
- uint ML = gfLog[ MX[ECCNum * ND + DataNum] ];
- if (DirectAccess)
- for (size_t I=0; I<BlockSize; I+=2)
- *(ushort*)(ECC+I) ^= gfExp[ ML + DataLog[I] ];
- else
- for (size_t I=0; I<BlockSize; I+=2)
- {
- uint R=gfExp[ ML + DataLog[I] ];
- ECC[I]^=byte(R);
- ECC[I+1]^=byte(R/256);
- }
- }
- #ifdef USE_SSE
- bool RSCoder16::SSE_UpdateECC(uint DataNum, uint ECCNum, const byte *Data, byte *ECC, size_t BlockSize)
- {
-
- if ((size_t(Data) & (SSE_ALIGNMENT-1))!=0 || (size_t(ECC) & (SSE_ALIGNMENT-1))!=0 ||
- _SSE_Version<SSE_SSSE3)
- return false;
- uint M=MX[ECCNum * ND + DataNum];
-
-
-
- __m128i T0L,T1L,T2L,T3L;
- __m128i T0H,T1H,T2H,T3H;
- for (uint I=0;I<16;I++)
- {
- ((byte *)&T0L)[I]=gfMul(I,M);
- ((byte *)&T0H)[I]=gfMul(I,M)>>8;
- ((byte *)&T1L)[I]=gfMul(I<<4,M);
- ((byte *)&T1H)[I]=gfMul(I<<4,M)>>8;
- ((byte *)&T2L)[I]=gfMul(I<<8,M);
- ((byte *)&T2H)[I]=gfMul(I<<8,M)>>8;
- ((byte *)&T3L)[I]=gfMul(I<<12,M);
- ((byte *)&T3H)[I]=gfMul(I<<12,M)>>8;
- }
- size_t Pos=0;
- __m128i LowByteMask=_mm_set1_epi16(0xff);
- __m128i Low4Mask=_mm_set1_epi8(0xf);
- __m128i High4Mask=_mm_slli_epi16(Low4Mask,4);
- for (; Pos+2*sizeof(__m128i)<=BlockSize; Pos+=2*sizeof(__m128i))
- {
-
- __m128i *D=(__m128i *)(Data+Pos);
-
-
-
- __m128i HighBytes0=_mm_srli_epi16(D[0],8);
- __m128i LowBytes0=_mm_and_si128(D[0],LowByteMask);
- __m128i HighBytes1=_mm_srli_epi16(D[1],8);
- __m128i LowBytes1=_mm_and_si128(D[1],LowByteMask);
- __m128i HighBytes=_mm_packus_epi16(HighBytes0,HighBytes1);
- __m128i LowBytes=_mm_packus_epi16(LowBytes0,LowBytes1);
-
-
- __m128i LowBytesLow4=_mm_and_si128(LowBytes,Low4Mask);
- __m128i LowBytesMultSum=_mm_shuffle_epi8(T0L,LowBytesLow4);
- __m128i HighBytesMultSum=_mm_shuffle_epi8(T0H,LowBytesLow4);
-
- __m128i LowBytesHigh4=_mm_and_si128(LowBytes,High4Mask);
- LowBytesHigh4=_mm_srli_epi16(LowBytesHigh4,4);
- __m128i LowBytesHigh4MultLow=_mm_shuffle_epi8(T1L,LowBytesHigh4);
- __m128i LowBytesHigh4MultHigh=_mm_shuffle_epi8(T1H,LowBytesHigh4);
-
- LowBytesMultSum=_mm_xor_si128(LowBytesMultSum,LowBytesHigh4MultLow);
- HighBytesMultSum=_mm_xor_si128(HighBytesMultSum,LowBytesHigh4MultHigh);
-
- __m128i HighBytesLow4=_mm_and_si128(HighBytes,Low4Mask);
- __m128i HighBytesLow4MultLow=_mm_shuffle_epi8(T2L,HighBytesLow4);
- __m128i HighBytesLow4MultHigh=_mm_shuffle_epi8(T2H,HighBytesLow4);
-
- LowBytesMultSum=_mm_xor_si128(LowBytesMultSum,HighBytesLow4MultLow);
- HighBytesMultSum=_mm_xor_si128(HighBytesMultSum,HighBytesLow4MultHigh);
-
- __m128i HighBytesHigh4=_mm_and_si128(HighBytes,High4Mask);
- HighBytesHigh4=_mm_srli_epi16(HighBytesHigh4,4);
- __m128i HighBytesHigh4MultLow=_mm_shuffle_epi8(T3L,HighBytesHigh4);
- __m128i HighBytesHigh4MultHigh=_mm_shuffle_epi8(T3H,HighBytesHigh4);
-
- LowBytesMultSum=_mm_xor_si128(LowBytesMultSum,HighBytesHigh4MultLow);
- HighBytesMultSum=_mm_xor_si128(HighBytesMultSum,HighBytesHigh4MultHigh);
-
- __m128i HighBytesHigh4Mult0=_mm_unpacklo_epi8(LowBytesMultSum,HighBytesMultSum);
- __m128i HighBytesHigh4Mult1=_mm_unpackhi_epi8(LowBytesMultSum,HighBytesMultSum);
-
- __m128i *StoreECC=(__m128i *)(ECC+Pos);
- StoreECC[0]=_mm_xor_si128(StoreECC[0],HighBytesHigh4Mult0);
- StoreECC[1]=_mm_xor_si128(StoreECC[1],HighBytesHigh4Mult1);
- }
-
-
-
- for (; Pos<BlockSize; Pos+=2)
- *(ushort*)(ECC+Pos) ^= gfMul( M, *(ushort*)(Data+Pos) );
- return true;
- }
- #endif
|