//Copyright (c) 2019 by Jason Southwell // //Permission is hereby granted, free of charge, to any person obtaining a copy //of this software and associated documentation files (the "Software"), to deal //in the Software without restriction, including without limitation the rights //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell //copies of the Software, and to permit persons to whom the Software is //furnished to do so, subject to the following conditions: // //The above copyright notice and this permission notice shall be included in all //copies or substantial portions of the Software. // //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE //SOFTWARE. unit qr.rs; interface uses System.SysUtils, System.Classes; type EReedSolomonException = exception; TReedSolomonGenerator = class(TObject) private FCoefficients : TArray; public constructor Create(Degree : integer); function GetRemaineder(const Data : TArray) : TArray; function Multiply(x, y : Byte) : Byte; end; implementation { TReedSolomonGenerator } constructor TReedSolomonGenerator.Create(Degree: integer); var i, j : integer; root : Byte; begin if (Degree < 1) or (Degree > 255) then raise EReedSolomonException.Create('Degree out of range'); inherited Create; SetLength(FCoefficients,Degree); for i := 0 to degree-2 do FCoefficients[i] := 0; FCoefficients[Degree-1] := 1; root := 1; for i := 0 to degree-1 do begin for j := 0 to Length(FCoefficients)-1 do begin FCoefficients[j] := Multiply(FCoefficients[j], root); if (j + 1 < length(FCoefficients)) then FCoefficients[j] := FCoefficients[j] xor FCoefficients[j + 1]; end; root := Multiply(root, 2); end; end; function TReedSolomonGenerator.GetRemaineder(const Data: TArray): TArray; var i: Integer; ary : TArray; b, factor : Byte; j: Integer; begin SetLength(Result, Length(FCoefficients)); for i := 0 to Length(FCoefficients)-1 do Result[i] := 0; ary := Data; for i := 0 to Length(ary)-1 do begin b := ary[i]; factor := b xor Result[0]; Delete(Result,0,1); SetLength(Result, Length(Result)+1); Result[Length(Result)-1] := 0; for j := 0 to Length(FCoefficients)-1 do begin Result[j] := Result[j] xor Multiply(FCoefficients[j], factor); end; end; end; function TReedSolomonGenerator.Multiply(x, y : Byte): Byte; var i : integer; bResult : Byte; begin if (x shr 8 <> 0) or (y shr 8 <> 0) then raise EReedSolomonException.Create('Byte out of range.'); bResult := 0; for i := 7 downto 0 do begin bResult := (bResult shl 1) xor ((bResult shr 7) * $11D); bResult := (bResult xor (((y shr i) and 1) * x)); end; if bResult shr 8 <> 0 then raise EReedSolomonException.Create('Assertion Error'); Result := bResult; end; end.