rs.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "rar.hpp"
  2. #define Clean(D,S) {for (int I=0;I<(S);I++) (D)[I]=0;}
  3. RSCoder::RSCoder(int ParSize)
  4. {
  5. RSCoder::ParSize=ParSize; // Store the number of recovery volumes.
  6. FirstBlockDone=false;
  7. gfInit();
  8. pnInit();
  9. }
  10. // Initialize logarithms and exponents Galois field tables.
  11. void RSCoder::gfInit()
  12. {
  13. for (int I=0,J=1;I<MAXPAR;I++)
  14. {
  15. gfLog[J]=I;
  16. gfExp[I]=J;
  17. J<<=1;
  18. if (J & 0x100)
  19. J^=0x11D; // 0x11D field-generator polynomial (x^8+x^4+x^3+x^2+1).
  20. }
  21. for (int I=MAXPAR;I<MAXPOL;I++)
  22. gfExp[I]=gfExp[I-MAXPAR];
  23. }
  24. // Multiplication over Galois field.
  25. inline int RSCoder::gfMult(int a,int b)
  26. {
  27. return(a==0 || b == 0 ? 0:gfExp[gfLog[a]+gfLog[b]]);
  28. }
  29. // Create the generator polynomial g(x).
  30. // g(x)=(x-a)(x-a^2)(x-a^3)..(x-a^N)
  31. void RSCoder::pnInit()
  32. {
  33. int p2[MAXPAR+1]; // Currently calculated part of g(x).
  34. Clean(p2,ParSize);
  35. p2[0]=1; // Set p2 polynomial to 1.
  36. for (int I=1;I<=ParSize;I++)
  37. {
  38. int p1[MAXPAR+1]; // We use p1 as current (x+a^i) expression.
  39. Clean(p1,ParSize);
  40. p1[0]=gfExp[I];
  41. p1[1]=1; // Set p1 polynomial to x+a^i.
  42. // Multiply the already calucated part of g(x) to next (x+a^i).
  43. pnMult(p1,p2,GXPol);
  44. // p2=g(x).
  45. for (int J=0;J<ParSize;J++)
  46. p2[J]=GXPol[J];
  47. }
  48. }
  49. // Multiply polynomial 'p1' to 'p2' and store the result in 'r'.
  50. void RSCoder::pnMult(int *p1,int *p2,int *r)
  51. {
  52. Clean(r,ParSize);
  53. for (int I=0;I<ParSize;I++)
  54. if (p1[I]!=0)
  55. for(int J=0;J<ParSize-I;J++)
  56. r[I+J]^=gfMult(p1[I],p2[J]);
  57. }
  58. void RSCoder::Encode(byte *Data,int DataSize,byte *DestData)
  59. {
  60. int ShiftReg[MAXPAR+1]; // Linear Feedback Shift Register.
  61. Clean(ShiftReg,ParSize+1);
  62. for (int I=0;I<DataSize;I++)
  63. {
  64. int D=Data[I]^ShiftReg[ParSize-1];
  65. // Use g(x) to define feedback taps.
  66. for (int J=ParSize-1;J>0;J--)
  67. ShiftReg[J]=ShiftReg[J-1]^gfMult(GXPol[J],D);
  68. ShiftReg[0]=gfMult(GXPol[0],D);
  69. }
  70. for (int I=0;I<ParSize;I++)
  71. DestData[I]=ShiftReg[ParSize-I-1];
  72. }
  73. bool RSCoder::Decode(byte *Data,int DataSize,int *EraLoc,int EraSize)
  74. {
  75. int SynData[MAXPOL]; // Syndrome data.
  76. bool AllZeroes=true;
  77. for (int I=0;I<ParSize;I++)
  78. {
  79. int Sum=Data[0],J=1,Exp=gfExp[I+1];
  80. for (;J+8<=DataSize;J+=8) // Unroll the loop for speed.
  81. {
  82. Sum=Data[J]^gfMult(Exp,Sum);
  83. Sum=Data[J+1]^gfMult(Exp,Sum);
  84. Sum=Data[J+2]^gfMult(Exp,Sum);
  85. Sum=Data[J+3]^gfMult(Exp,Sum);
  86. Sum=Data[J+4]^gfMult(Exp,Sum);
  87. Sum=Data[J+5]^gfMult(Exp,Sum);
  88. Sum=Data[J+6]^gfMult(Exp,Sum);
  89. Sum=Data[J+7]^gfMult(Exp,Sum);
  90. }
  91. for (;J<DataSize;J++)
  92. Sum=Data[J]^gfMult(Exp,Sum);
  93. if ((SynData[I]=Sum)!=0)
  94. AllZeroes=false;
  95. }
  96. // If all syndrome numbers are zero, message does not have errors.
  97. if (AllZeroes)
  98. return(true);
  99. if (!FirstBlockDone) // Do things which we need to do once for all data.
  100. {
  101. FirstBlockDone=true;
  102. // Calculate the error locator polynomial.
  103. Clean(ELPol,ParSize+1);
  104. ELPol[0]=1;
  105. for (int EraPos=0;EraPos<EraSize;EraPos++)
  106. for (int I=ParSize,M=gfExp[DataSize-EraLoc[EraPos]-1];I>0;I--)
  107. ELPol[I]^=gfMult(M,ELPol[I-1]);
  108. ErrCount=0;
  109. // Find roots of error locator polynomial.
  110. for (int Root=MAXPAR-DataSize;Root<MAXPAR+1;Root++)
  111. {
  112. int Sum=0;
  113. for (int B=0;B<ParSize+1;B++)
  114. Sum^=gfMult(gfExp[(B*Root)%MAXPAR],ELPol[B]);
  115. if (Sum==0) // Root found.
  116. {
  117. ErrorLocs[ErrCount]=MAXPAR-Root; // Location of error.
  118. // Calculate the denominator for every error location.
  119. Dnm[ErrCount]=0;
  120. for (int I=1;I<ParSize+1;I+=2)
  121. Dnm[ErrCount]^= gfMult(ELPol[I],gfExp[Root*(I-1)%MAXPAR]);
  122. ErrCount++;
  123. }
  124. }
  125. }
  126. int EEPol[MAXPOL]; // Error Evaluator Polynomial.
  127. pnMult(ELPol,SynData,EEPol);
  128. // If errors are present and their number is correctable.
  129. if ((ErrCount<=ParSize) && ErrCount>0)
  130. for (int I=0;I<ErrCount;I++)
  131. {
  132. int Loc=ErrorLocs[I],DLoc=MAXPAR-Loc,N=0;
  133. for (int J=0;J<ParSize;J++)
  134. N^=gfMult(EEPol[J],gfExp[DLoc*J%MAXPAR]);
  135. int DataPos=DataSize-Loc-1;
  136. // Perform bounds check and correct the data error.
  137. if (DataPos>=0 && DataPos<DataSize)
  138. Data[DataPos]^=gfMult(N,gfExp[MAXPAR-gfLog[Dnm[I]]]);
  139. }
  140. return(ErrCount<=ParSize); // Return true if success.
  141. }