QuietUnrar/libunrar/rs.cpp

144 lines
3.0 KiB
C++

#include "rar.hpp"
#define Clean(D,S) {for (int I=0;I<(S);I++) (D)[I]=0;}
RSCoder::RSCoder(int ParSize)
{
RSCoder::ParSize=ParSize;
FirstBlockDone=false;
gfInit();
pnInit();
}
void RSCoder::gfInit()
{
for (int I=0,J=1;I<MAXPAR;I++)
{
gfLog[J]=I;
gfExp[I]=J;
if ((J<<=1)&256)
J^=285;
}
for (int I=MAXPAR;I<MAXPOL;I++)
gfExp[I]=gfExp[I-MAXPAR];
}
inline int RSCoder::gfMult(int a,int b)
{
return(a==0 || b == 0 ? 0:gfExp[gfLog[a]+gfLog[b]]);
}
void RSCoder::pnInit()
{
int p1[MAXPAR+1],p2[MAXPAR+1];
Clean(p2,ParSize);
p2[0]=1;
for (int I=1;I<=ParSize;I++)
{
Clean(p1,ParSize);
p1[0]=gfExp[I];
p1[1]=1;
pnMult(p1,p2,GXPol);
for (int J=0;J<ParSize;J++)
p2[J]=GXPol[J];
}
}
void RSCoder::pnMult(int *p1,int *p2,int *r)
{
Clean(r,ParSize);
for (int I=0;I<ParSize;I++)
if (p1[I]!=0)
for(int J=0;J<ParSize-I;J++)
r[I+J]^=gfMult(p1[I],p2[J]);
}
void RSCoder::Encode(byte *Data,int DataSize,byte *DestData)
{
int ShiftReg[MAXPAR+1];
Clean(ShiftReg,ParSize+1);
for (int I=0;I<DataSize;I++)
{
int D=Data[I]^ShiftReg[ParSize-1];
for (int J=ParSize-1;J>0;J--)
ShiftReg[J]=ShiftReg[J-1]^gfMult(GXPol[J],D);
ShiftReg[0]=gfMult(GXPol[0],D);
}
for (int I=0;I<ParSize;I++)
DestData[I]=ShiftReg[ParSize-I-1];
}
bool RSCoder::Decode(byte *Data,int DataSize,int *EraLoc,int EraSize)
{
int SynData[MAXPOL];
bool AllZeroes=true;
for (int I=0;I<ParSize;I++)
{
int Sum=Data[0],J=1,Exp=gfExp[I+1];
for (;J+8<=DataSize;J+=8)
{
Sum=Data[J]^gfMult(Exp,Sum);
Sum=Data[J+1]^gfMult(Exp,Sum);
Sum=Data[J+2]^gfMult(Exp,Sum);
Sum=Data[J+3]^gfMult(Exp,Sum);
Sum=Data[J+4]^gfMult(Exp,Sum);
Sum=Data[J+5]^gfMult(Exp,Sum);
Sum=Data[J+6]^gfMult(Exp,Sum);
Sum=Data[J+7]^gfMult(Exp,Sum);
}
for (;J<DataSize;J++)
Sum=Data[J]^gfMult(Exp,Sum);
if ((SynData[I]=Sum)!=0)
AllZeroes=false;
}
if (AllZeroes)
return(true);
if (!FirstBlockDone)
{
FirstBlockDone=true;
Clean(PolB,ParSize+1);
PolB[0]=1;
for (int EraPos=0;EraPos<EraSize;EraPos++)
for (int I=ParSize,M=gfExp[DataSize-EraLoc[EraPos]-1];I>0;I--)
PolB[I]^=gfMult(M,PolB[I-1]);
ErrCount=0;
for (int Root=MAXPAR-DataSize;Root<MAXPAR+1;Root++)
{
int Sum=0;
for (int B=0;B<ParSize+1;B++)
Sum^=gfMult(gfExp[(B*Root)%MAXPAR],PolB[B]);
if (Sum==0)
{
Dn[ErrCount]=0;
for (int I=1;I<ParSize+1;I+=2)
Dn[ErrCount]^= gfMult(PolB[I],gfExp[Root*(I-1)%MAXPAR]);
ErrorLocs[ErrCount++]=MAXPAR-Root;
}
}
}
int PolD[MAXPOL];
pnMult(PolB,SynData,PolD);
if ((ErrCount<=ParSize) && ErrCount>0)
for (int I=0;I<ErrCount;I++)
{
int Loc=ErrorLocs[I],DLoc=MAXPAR-Loc,N=0;
for (int J=0;J<ParSize;J++)
N^=gfMult(PolD[J],gfExp[DLoc*J%MAXPAR]);
int DataPos=DataSize-Loc-1;
if (DataPos>=0 && DataPos<DataSize)
Data[DataPos]^=gfMult(N,gfExp[MAXPAR-gfLog[Dn[I]]]);
}
return(ErrCount<=ParSize);
}