Changeset 55 for branches/ByteArray/BigInt.pas
- Timestamp:
- Nov 22, 2023, 10:09:35 PM (20 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/ByteArray/BigInt.pas
r52 r55 36 36 class operator Implicit(A: TBigInt): Int64; 37 37 class operator Implicit(A: TBigInt): PByte; 38 class operator Negative(A: TBigInt): TBigInt; 38 39 class operator Inc(A: TBigInt) : TBigInt; 39 40 class operator Dec(A: TBigInt) : TBigInt; … … 46 47 class operator GreaterThan(A, B: TBigInt): Boolean; 47 48 class operator GreaterThanOrEqual(A, B: TBigInt): Boolean; 49 class operator BitwiseXor(A, B: TBigInt): TBigInt; 50 class operator BitwiseAnd(A, B: TBigInt): TBigInt; 51 class operator BitwiseOr(A, B: TBigInt): TBigInt; 52 class operator LeftShift(A: TBigInt; B: Integer): TBigInt; 53 class operator RightShift(A: TBigInt; B: Integer): TBigInt; 54 class operator Modulus(A, B: TBigInt): TBigInt; 55 class operator IntDivide(A, B: TBigInt): TBigInt; 48 56 procedure Shrink; 49 57 function IsNegative: Boolean; 50 58 function IsZero: Boolean; 51 59 function IsPositive: Boolean; 60 procedure Invert; 52 61 procedure SetByteArray(AData: TArrayOfByte; ASize: TBigIntSize); 53 62 procedure GetByteArray(var AData: TArrayOfByte; ASize: TBigIntSize); 54 function Copy(Size: TBigIntSize): TBigInt; 63 function Copy(Size: TBigIntSize): TBigInt; overload; 64 function Copy: TBigInt; overload; 55 65 property Size: TBigIntSize read GetSize write SetSize; 56 66 property Data[Index: TBigIntSize]: Byte read GetData write SetData; … … 58 68 59 69 function TryStrToBigInt(const S: string; out I: TBigInt): Boolean; 70 function IntToStr(Value: TBigInt): string; overload; 71 function IntToHex(Value: TBigInt): string; overload; 72 function IntToHex(Value: TBigInt; Digits: Integer): string; overload; 60 73 61 74 … … 64 77 resourcestring 65 78 SUnsupportedByteSize = 'Unsupported byte size'; 79 SOutOfRange = 'Out of range'; 80 81 const 82 HexDigits: array[0..15] of Char = '0123456789ABCDEF'; 66 83 67 84 function TryStrToBigInt(const S: string; out I: TBigInt): Boolean; … … 73 90 end; 74 91 92 function IntToHex(Value: TBigInt): string; 93 begin 94 Result := ''; 95 while Value <> 0 do begin 96 Result := HexDigits[Value and 15] + Result; 97 Value := Value shr 4; 98 end; 99 if Result = '' then Result := '0'; 100 end; 101 102 function IntToHex(Value: TBigInt; Digits: Integer): string; 103 var 104 I: Integer; 105 begin 106 if Digits = 0 then 107 Digits := 1; 108 Result := ''; 109 SetLength(Result, Digits); 110 for I := 0 to Digits - 1 do 111 begin 112 Result[Digits - I] := HexDigits[Value and 15]; 113 Value := Value shr 4; 114 end ; 115 while Value <> 0 do begin 116 Result := HexDigits[Value and 15] + Result; 117 Value := Value shr 4; 118 end; 119 end; 120 121 function IntToStr(Value: TBigInt): string; 122 begin 123 Result := ''; 124 if Value < 0 then begin 125 Value := -Value; 126 while Value > 9 do begin 127 Result := Chr(Ord('0') + (Value mod 10)) + Result; 128 Value := Value div 10; 129 end; 130 Result := '-' + Chr(Ord('0') + (Value mod 10)) + Result; 131 end else begin 132 while Value > 9 do begin 133 Result := Chr(Ord('0') + (Value mod 10)) + Result; 134 Value := Value div 10; 135 end; 136 Result := Chr(Ord('0') + Value) + Result; 137 end; 138 end; 139 75 140 { TBigInt } 76 141 … … 88 153 procedure TBigInt.SetData(Index: TBigIntSize; AValue: Byte); 89 154 begin 90 if Index > Integer(Size) - 1 then Size := Index + 1;155 if Index >= Integer(Size) then raise Exception.Create(SOutOfRange); 91 156 FData[Index] := AValue; 92 157 end; … … 209 274 end; 210 275 276 class operator TBigInt.Negative(A: TBigInt): TBigInt; 277 begin 278 Result := A.Copy(A.Size); 279 Result.Invert; 280 Result := Result + 1; 281 end; 282 211 283 class operator TBigInt.Inc(A: TBigInt): TBigInt; 212 284 begin … … 224 296 V: SmallInt; 225 297 Carry: Byte; 226 begin 227 Result.Size := Max(A.Size, B.Size); 298 Size: Byte; 299 begin 300 Size := Max(A.Size, B.Size); 301 Result.Size := Size; 228 302 Carry := 0; 229 303 I := 0; 230 while (I < Result.Size) or (Carry > 0) do begin 304 while (I < Size) or (Carry > 0) do begin 305 if I >= Result.Size then Result.Size := I + 1; 231 306 V := A.Data[I] + B.Data[I] + Carry; 232 307 if V >= 256 then begin … … 240 315 class operator TBigInt.Subtract(A, B: TBigInt): TBigInt; 241 316 var 242 I: Integer; 243 V: SmallInt; 244 Carry: Byte; 245 begin 246 Result.Size := Max(A.Size, B.Size); 247 Carry := 0; 248 I := 0; 249 while (I < Result.Size) or (Carry > 0) do begin 250 V := A.Data[I] - B.Data[I] - Carry; 251 if V < 0 then begin 252 Carry := 1; 253 end else Carry := 0; 254 Result.Data[I] := V and $ff; 255 Inc(I); 256 end; 317 Size: TBigIntSize; 318 begin 319 Size := Max(A.Size, B.Size); 320 Result := A + -B; 321 Result.Size := Size; 322 Result.Shrink; 257 323 end; 258 324 … … 316 382 end; 317 383 384 class operator TBigInt.BitwiseXor(A, B: TBigInt): TBigInt; 385 var 386 I: TBigIntSize; 387 begin 388 Result.Size := Max(A.Size, B.Size); 389 for I := 0 to Result.Size - 1 do 390 Result.Data[I] := A.Data[I] xor B.Data[I]; 391 Result.Shrink; 392 end; 393 394 class operator TBigInt.BitwiseAnd(A, B: TBigInt): TBigInt; 395 var 396 I: TBigIntSize; 397 begin 398 Result.Size := Max(A.Size, B.Size); 399 for I := 0 to Result.Size - 1 do 400 Result.Data[I] := A.Data[I] and B.Data[I]; 401 Result.Shrink; 402 end; 403 404 class operator TBigInt.BitwiseOr(A, B: TBigInt): TBigInt; 405 var 406 I: TBigIntSize; 407 begin 408 Result.Size := Max(A.Size, B.Size); 409 for I := 0 to Result.Size - 1 do 410 Result.Data[I] := A.Data[I] or B.Data[I]; 411 Result.Shrink; 412 end; 413 414 class operator TBigInt.LeftShift(A: TBigInt; B: Integer): TBigInt; 415 var 416 ByteShift: TBigIntSize; 417 BitShift: Byte; 418 I: Integer; 419 begin 420 if (B and 7) = 0 then begin 421 // Full byte shift 422 ByteShift := B shr 3; 423 Result.Size := A.Size + ByteShift; 424 Move(A.FData[0], Result.FData[ByteShift], A.Size); 425 FillChar(Result.FData[0], ByteShift, 0); 426 end else begin 427 // Partial byte shift 428 ByteShift := B shr 3; 429 BitShift := B - ByteShift; 430 Result.Size := Result.Size + ByteShift + 1; 431 for I := 0 to A.Size - 1 do begin 432 Result.FData[I + ByteShift] := (A.FData[I] shl BitShift) and $ff; 433 if I > 0 then Result.FData[I + ByteShift] := Result.FData[I + ByteShift] or (A.FData[I] shl BitShift shl 8); 434 end; 435 end; 436 Result.Shrink; 437 end; 438 439 class operator TBigInt.RightShift(A: TBigInt; B: Integer): TBigInt; 440 var 441 ByteShift: TBigIntSize; 442 BitShift: Byte; 443 I: Integer; 444 begin 445 if (B and 7) = 0 then begin 446 // Full byte shift 447 ByteShift := B shr 3; 448 Result.Size := A.Size - ByteShift; 449 Move(A.FData[ByteShift], Result.FData[0], A.Size); 450 end else begin 451 // Partial byte shift 452 ByteShift := B shr 3; 453 BitShift := B - ByteShift; 454 Result.Size := Result.Size - ByteShift; 455 for I := 0 to A.Size - 1 do begin 456 Result.FData[I] := (A.FData[I + ByteShift] shr BitShift) and $ff; 457 if I < (A.Size - 1) then Result.FData[I] := Result.FData[I] or (((A.FData[I + ByteShift] shl 8) shr BitShift) and $ff); 458 end; 459 end; 460 Result.Shrink; 461 end; 462 463 class operator TBigInt.Modulus(A, B: TBigInt): TBigInt; 464 begin 465 466 end; 467 468 class operator TBigInt.IntDivide(A, B: TBigInt): TBigInt; 469 begin 470 471 end; 472 318 473 procedure TBigInt.Shrink; 319 474 var … … 346 501 begin 347 502 Result := (FData[Size - 1] and $80) = 0; 503 end; 504 505 procedure TBigInt.Invert; 506 var 507 I: Byte; 508 begin 509 for I := 0 to Size - 1 do 510 FData[I] := FData[I] xor $ff; 348 511 end; 349 512 … … 372 535 end; 373 536 537 function TBigInt.Copy: TBigInt; 538 begin 539 Result := Copy(Size); 540 end; 541 374 542 end. 375 543
Note:
See TracChangeset
for help on using the changeset viewer.