Changeset 47 for branches/ByteArray/BigInt.pas
- Timestamp:
- Oct 25, 2023, 12:33:07 AM (7 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/ByteArray/BigInt.pas
r46 r47 9 9 TArrayOfByte = array of Byte; 10 10 11 TBigIntSize = Byte; 12 11 13 { TBigInt } 12 14 13 15 TBigInt = record 14 16 private 15 function GetSize: Byte; 16 procedure SetSize(AValue: Byte); 17 FData: array of Byte; 18 function GetData(Index: TBigIntSize): Byte; 19 function GetSize: TBigIntSize; 20 procedure SetData(Index: TBigIntSize; AValue: Byte); 21 procedure SetSize(AValue: TBigIntSize); 17 22 public 18 Data: array of Byte;19 23 class operator Implicit(A: Byte): TBigInt; 20 24 class operator Implicit(A: Word): TBigInt; … … 33 37 class operator Implicit(A: TBigInt): PByte; 34 38 class operator Inc(A: TBigInt) : TBigInt; 39 class operator Dec(A: TBigInt) : TBigInt; 35 40 class operator Add(A, B: TBigInt): TBigInt; 36 41 class operator Subtract(A, B: TBigInt): TBigInt; … … 42 47 class operator GreaterThanOrEqual(A, B: TBigInt): Boolean; 43 48 procedure Shrink; 44 procedure SetByteArray(AData: TArrayOfByte; ASize: Byte);45 procedure GetByteArray(var AData: TArrayOfByte; ASize: Byte);46 function Copy(Size: Byte): TBigInt;49 procedure SetByteArray(AData: TArrayOfByte; ASize: TBigIntSize); 50 procedure GetByteArray(var AData: TArrayOfByte; ASize: TBigIntSize); 51 function Copy(Size: TBigIntSize): TBigInt; 47 52 property Size: Byte read GetSize write SetSize; 48 end; 49 50 function TryStrToBigInt(const S: string; Out I: TBigInt): Boolean; 53 property Data[Index: TBigIntSize]: Byte read GetData write SetData; 54 end; 55 56 function TryStrToBigInt(const S: string; out I: TBigInt): Boolean; 57 51 58 52 59 implementation 53 60 54 function TryStrToBigInt(const S: string; Out I: TBigInt): Boolean; 61 resourcestring 62 SUnsupportedByteSize = 'Unsupported byte size'; 63 64 function TryStrToBigInt(const S: string; out I: TBigInt): Boolean; 55 65 var 56 66 Value: Int64; … … 62 72 { TBigInt } 63 73 64 function TBigInt.GetSize: Byte; 65 begin 66 Result := Length(Data); 67 end; 68 69 procedure TBigInt.SetSize(AValue: Byte); 70 var 71 LastSize: Byte; 74 function TBigInt.GetSize: TBigIntSize; 75 begin 76 Result := Length(FData); 77 end; 78 79 function TBigInt.GetData(Index: TBigIntSize): Byte; 80 begin 81 if Index < Size then Result := FData[Index] 82 else Result := 0; 83 end; 84 85 procedure TBigInt.SetData(Index: TBigIntSize; AValue: Byte); 86 begin 87 if Index > Size - 1 then Size := Index + 1; 88 FData[Index] := AValue; 89 end; 90 91 procedure TBigInt.SetSize(AValue: TBigIntSize); 92 var 93 LastSize: TBigIntSize; 72 94 begin 73 95 LastSize := GetSize; 74 SetLength( Data, AValue);96 SetLength(FData, AValue); 75 97 if AValue > LastSize then 76 FillChar( Data[LastSize], AValue - LastSize, 0);98 FillChar(FData[LastSize], AValue - LastSize, 0); 77 99 end; 78 100 … … 80 102 begin 81 103 Result.Size := 1; 82 Result. Data[0] := A;104 Result.FData[0] := A; 83 105 end; 84 106 … … 86 108 begin 87 109 Result.Size := 2; 88 PWord(@Result. Data[0])^ := A;110 PWord(@Result.FData[0])^ := A; 89 111 Result.Shrink; 90 112 end; … … 93 115 begin 94 116 Result.Size := 1; 95 PByte(@Result. Data[0])^ := A;117 PByte(@Result.FData[0])^ := A; 96 118 Result.Shrink; 97 119 end; … … 100 122 begin 101 123 Result.Size := 4; 102 PInteger(@Result. Data[0])^ := A;124 PInteger(@Result.FData[0])^ := A; 103 125 Result.Shrink; 104 126 end; … … 107 129 begin 108 130 Result.Size := 8; 109 PQWord(@Result. Data[0])^ := A;131 PQWord(@Result.FData[0])^ := A; 110 132 Result.Shrink; 111 133 end; … … 114 136 begin 115 137 Result.Size := 8; 116 PInt64(@Result. Data[0])^ := A;138 PInt64(@Result.FData[0])^ := A; 117 139 Result.Shrink; 118 140 end; … … 120 142 class operator TBigInt.Implicit(A: TBigInt): UInt8; 121 143 begin 122 if A.Size = 1 then Result := A. Data[0]123 else raise Exception.Create( 'x');144 if A.Size = 1 then Result := A.FData[0] 145 else raise Exception.Create(SUnsupportedByteSize); 124 146 end; 125 147 126 148 class operator TBigInt.Implicit(A: TBigInt): Int8; 127 149 begin 128 if A.Size = 1 then Result := A. Data[0]129 else raise Exception.Create( 'x');150 if A.Size = 1 then Result := A.FData[0] 151 else raise Exception.Create(SUnsupportedByteSize); 130 152 end; 131 153 132 154 class operator TBigInt.Implicit(A: TBigInt): UInt16; 133 155 begin 134 if A.Size = 2 then Result := PUInt16(@A. Data[0])^135 else raise Exception.Create( 'x');156 if A.Size = 2 then Result := PUInt16(@A.FData[0])^ 157 else raise Exception.Create(SUnsupportedByteSize); 136 158 end; 137 159 138 160 class operator TBigInt.Implicit(A: TBigInt): Int16; 139 161 begin 140 if A.Size = 2 then Result := PInt16(@A. Data[0])^141 else raise Exception.Create( 'x');162 if A.Size = 2 then Result := PInt16(@A.FData[0])^ 163 else raise Exception.Create(SUnsupportedByteSize); 142 164 end; 143 165 … … 145 167 begin 146 168 case A.Size of 147 1: Result := PByte(@A.Data[0])^; 148 2: Result := PWord(@A.Data[0])^; 149 4: Result := PDWord(@A.Data[0])^; 150 8: Result := PQWord(@A.Data[0])^; 151 else raise Exception.Create('x'); 169 1: Result := PByte(@A.FData[0])^; 170 2: Result := PWord(@A.FData[0])^; 171 3: Result := PWord(@A.FData[0])^ or (PByte(@A.FData[2])^ shl 16); 172 4: Result := PDWord(@A.FData[0])^; 173 8: Result := PQWord(@A.FData[0])^; 174 else raise Exception.Create(SUnsupportedByteSize); 152 175 end; 153 176 end; … … 155 178 class operator TBigInt.Implicit(A: TBigInt): UInt32; 156 179 begin 157 if A.Size = 4 then Result := PInt32(@A. Data[0])^158 else raise Exception.Create( 'x');180 if A.Size = 4 then Result := PInt32(@A.FData[0])^ 181 else raise Exception.Create(SUnsupportedByteSize); 159 182 end; 160 183 161 184 class operator TBigInt.Implicit(A: TBigInt): UInt64; 162 185 begin 163 if A.Size = 8 then Result := PUInt64(@A. Data[0])^164 else raise Exception.Create( 'x');186 if A.Size = 8 then Result := PUInt64(@A.FData[0])^ 187 else raise Exception.Create(SUnsupportedByteSize); 165 188 end; 166 189 167 190 class operator TBigInt.Implicit(A: TBigInt): Int64; 168 191 begin 169 if A.Size = 8 then Result := PInt64(@A. Data[0])^170 else raise Exception.Create( 'x');192 if A.Size = 8 then Result := PInt64(@A.FData[0])^ 193 else raise Exception.Create(SUnsupportedByteSize); 171 194 end; 172 195 173 196 class operator TBigInt.Implicit(A: TBigInt): PByte; 174 197 begin 175 if A.Size = 4 then Result := PByte(@PInteger(@A. Data[0])^)176 else raise Exception.Create( 'x');198 if A.Size = 4 then Result := PByte(@PInteger(@A.FData[0])^) 199 else raise Exception.Create(SUnsupportedByteSize); 177 200 end; 178 201 179 202 class operator TBigInt.Inc(A: TBigInt): TBigInt; 180 203 begin 204 Result := A + 1; 205 end; 206 207 class operator TBigInt.Dec(A: TBigInt): TBigInt; 208 begin 209 Result := A - 1; 210 end; 211 212 class operator TBigInt.Add(A, B: TBigInt): TBigInt; 213 var 214 I: Integer; 215 V: SmallInt; 216 Carry: Byte; 217 begin 218 Result.Size := Max(A.Size, B.Size); 219 Carry := 0; 220 I := 0; 221 while (I < Result.Size) or (Carry > 0) do begin 222 V := A.Data[I] + B.Data[I] + Carry; 223 if V >= 256 then begin 224 Carry := 1; 225 end else Carry := 0; 226 Result.Data[I] := V and $ff; 227 Inc(I); 228 end; 229 end; 230 231 class operator TBigInt.Subtract(A, B: TBigInt): TBigInt; 232 var 233 I: Integer; 234 V: SmallInt; 235 Carry: Byte; 236 begin 181 237 Result.Size := A.Size; 182 case Result.Size of 183 1: PByte(@Result.Data[0])^ := PByte(@A.Data[0])^ + 1; 184 2: PWord(@Result.Data[0])^ := PWord(@A.Data[0])^ + 1; 185 4: PDWord(@Result.Data[0])^ := PDWord(@A.Data[0])^ + 1; 186 8: PQWord(@Result.Data[0])^ := PQWord(@A.Data[0])^ + 1; 187 end; 188 end; 189 190 class operator TBigInt.Add(A, B: TBigInt): TBigInt; 191 var 192 CommonSize: Byte; 193 begin 194 CommonSize := Max(A.Size, B.Size); 195 A.Size := CommonSize; 196 B.Size := CommonSize; 197 Result.Size := CommonSize; 198 case Result.Size of 199 1: PByte(@Result.Data[0])^ := PByte(@A.Data[0])^ + PByte(@B.Data[0])^; 200 2: PWord(@Result.Data[0])^ := PWord(@A.Data[0])^ + PWord(@B.Data[0])^; 201 4: PDWord(@Result.Data[0])^ := PDWord(@A.Data[0])^ + PDWord(@B.Data[0])^; 202 8: PQWord(@Result.Data[0])^ := PQWord(@A.Data[0])^ + PQWord(@B.Data[0])^; 203 end; 204 end; 205 206 class operator TBigInt.Subtract(A, B: TBigInt): TBigInt; 207 var 208 CommonSize: Byte; 209 begin 210 CommonSize := Max(A.Size, B.Size); 211 A.Size := CommonSize; 212 B.Size := CommonSize; 213 Result.Size := CommonSize; 214 case Result.Size of 215 1: PByte(@Result.Data[0])^ := PByte(@A.Data[0])^ - PByte(@B.Data[0])^; 216 2: PWord(@Result.Data[0])^ := PWord(@A.Data[0])^ - PWord(@B.Data[0])^; 217 4: PDWord(@Result.Data[0])^ := PDWord(@A.Data[0])^ - PDWord(@B.Data[0])^; 218 8: PQWord(@Result.Data[0])^ := PQWord(@A.Data[0])^ - PQWord(@B.Data[0])^; 238 Carry := 0; 239 I := 0; 240 while (I < Result.Size) or (Carry > 0) do begin 241 V := A.Data[I] - B.Data[I] - Carry; 242 if V < 0 then begin 243 Carry := 1; 244 end else Carry := 0; 245 Result.Data[I] := V and $ff; 246 Inc(I); 219 247 end; 220 248 end; 221 249 222 250 class operator TBigInt.Equal(A, B: TBigInt): Boolean; 223 begin 224 251 var 252 I: Byte; 253 begin 254 Result := A.Size = B.Size; 255 for I := 0 to A.Size - 1 do 256 if A.FData[I] <> B.FData[I] then begin 257 Result := False; 258 Break; 259 end; 225 260 end; 226 261 227 262 class operator TBigInt.NotEqual(A, B: TBigInt): Boolean; 228 begin 229 263 var 264 I: Byte; 265 begin 266 Result := A.Size = B.Size; 267 for I := 0 to A.Size - 1 do 268 if A.FData[I] <> B.FData[I] then begin 269 Result := False; 270 Break; 271 end; 272 Result := not Result; 230 273 end; 231 274 … … 255 298 begin 256 299 I := Size - 1; 257 while (I > 0) and ( Data[I] = 0) do300 while (I > 0) and (FData[I] = 0) do 258 301 Dec(I); 259 302 Size := I + 1; 260 303 end; 261 304 262 procedure TBigInt.SetByteArray(AData: TArrayOfByte; ASize: Byte);305 procedure TBigInt.SetByteArray(AData: TArrayOfByte; ASize: TBigIntSize); 263 306 begin 264 307 Size := ASize; 265 Move(AData[0], Data[0], Size);266 end; 267 268 procedure TBigInt.GetByteArray(var AData: TArrayOfByte; ASize: Byte);308 Move(AData[0], FData[0], Size); 309 end; 310 311 procedure TBigInt.GetByteArray(var AData: TArrayOfByte; ASize: TBigIntSize); 269 312 begin 270 313 SetLength(AData, ASize); 271 Move( Data[0], AData[0], Size);272 end; 273 274 function TBigInt.Copy(Size: Byte): TBigInt;314 Move(FData[0], AData[0], Size); 315 end; 316 317 function TBigInt.Copy(Size: TBigIntSize): TBigInt; 275 318 begin 276 319 Result.Size := Size; 277 320 case Result.Size of 278 1: PByte(@Result. Data[0])^ := PByte(@Data[0])^;279 2: PWord(@Result. Data[0])^ := PWord(@Data[0])^;280 4: PDWord(@Result. Data[0])^ := PDWord(@Data[0])^;281 8: PQWord(@Result. Data[0])^ := PQWord(@Data[0])^;321 1: PByte(@Result.FData[0])^ := PByte(@FData[0])^; 322 2: PWord(@Result.FData[0])^ := PWord(@FData[0])^; 323 4: PDWord(@Result.FData[0])^ := PDWord(@FData[0])^; 324 8: PQWord(@Result.FData[0])^ := PQWord(@FData[0])^; 282 325 end; 283 326 end;
Note:
See TracChangeset
for help on using the changeset viewer.