{$mode objfpc} unit VLInt1; interface const base = 10000; digits = 5000; // <--- type TLong = record len: integer; arr: array[1 .. digits] of integer; end; operator := (value: ansistring): TLong; // string->TLong operator := (value: integer): TLong; // integer->TLong operator := (const a: TLong): ansistring; // TLong->string operator + (const A, B: TLong): TLong; // result := A + B operator - (const A, B: TLong): TLong; // result := A - B (A > B) operator * (const A, B: TLong): TLong; // result := A * B operator * (const A: TLong; const k: longint): TLong; // result := A * k operator > (const A, B: TLong): boolean; operator >= (const A, B: TLong): boolean; operator < (const A, B: TLong): boolean; operator <= (const A, B: TLong): boolean; operator = (const A, B: TLong): boolean; operator div (const A, B: TLong): TLong; operator mod (const A, B: TLong): TLong; operator div (const A: TLong; const B: integer): TLong; operator mod (const A: TLong; const B: integer): TLong; var nill: TLong; // TLong(0) implementation uses sysutils; operator := (value: integer): TLong; var i: integer; begin fillchar(result.arr, sizeof(result.arr), 0); i := 0; repeat // if i = maxLen then ErrorMsg(vliOverflow, 'Assign'); inc(i); result.arr[i] := value mod base; value := value div base until value = 0; result.len := i; end; operator := (value: ansistring): TLong; var i: integer; curr: integer; begin fillchar(result.arr, sizeof(result.arr), 0); result.len := 1; for curr := 1 to length(value) do begin for i:=result.len downto 1 do begin result.arr[i+1] := result.arr[i+1] + (longint(result.arr[i])*10) div base; result.arr[i] := (longint(result.arr[i])*10) mod base; end; result.arr[1] := result.arr[1] + ord(value[curr]) - ord('0'); if result.arr[result.len+1] > 0 then inc(result.len); end; end; operator := (const a: TLong): ansistring; var ls, s: ansistring; i: integer; begin // str(base div 10, ls); ls := inttostr(base div 10); result := inttostr(a.arr[a.len]); for i := a.len - 1 downto 1 do begin s := inttostr(a.arr[i]); while length(s) < length(ls) do s := '0' + s; result := result + s; end; end; operator + (const A, B: TLong): TLong; var i, k: integer; begin fillchar(result.arr, sizeof(result.arr), 0); if A.len > B.len then k:=A.len else k:=B.len; for i := 1 to k do begin result.arr[i+1] := (result.arr[i] + A.arr[i] + B.arr[i]) div base; result.arr[i] := (result.arr[i] + A.arr[i] + B.arr[i]) mod base; end; if result.arr[k+1] = 0 then result.len:=k else result.len:=k+1; end; operator * (const A, B: TLong): TLong; var i, j: integer; dv: longint; begin fillchar(result.arr, sizeof(result.arr), 0); for i := 1 to A.len do for j := 1 to B.len do begin dv := longint(A.arr[i])*B.arr[j] + result.arr[i+j-1]; result.arr[i+j] := result.arr[i+j] + (dv div base); result.arr[i+j-1] := dv mod base; end; result.len := A.len+B.len; while (result.len>1) and (result.arr[result.len]=0) do dec(result.len); end; operator = (const A, B: TLong): boolean; var i: integer; begin if A.len = B.len then begin i := 1; while (i <= A.len) and (A.arr[i] = B.arr[i]) do inc(i); result := (i = a.len + 1); end else result := false; end; operator > (const A, B: TLong): boolean; var i: integer; begin if A.len < B.len then result := false else if A.len > B.len then result := true else begin i := A.len; while (i > 0) and (A.arr[i] = B.arr[i]) do dec(i); if i = 0 then result := false else result := (A.arr[i] > B.arr[i]); end; end; operator >= (const A, B: TLong): boolean; begin result := (A > B) or (A = B); end; operator <= (const A, B: TLong): boolean; begin result := not (A > B); end; operator < (const A, B: TLong): boolean; begin result := not ((A > B) or (A = B)); end; function MoreSdvigLong(const A, B: Tlong; const sdvig: integer): byte; var i: integer; begin if A.len > (B.len + sdvig) then result := 0 else if A.len < (B.len + sdvig) then result := 1 else begin i := A.len; while (i > sdvig) and (A.arr[i] = B.arr[i - sdvig]) do dec(i); if i = sdvig then begin for i := 1 to sdvig do if A.arr[i] > 0 then exit(0); result := 2; end else result := byte(A.arr[i] < B.arr[i - sdvig]); {0 -- false(a>b) ;1 -- true(a 1) and (A.arr[i] = 0) do dec(i); A.len := i; end; procedure MulLongShort(const A: Tlong; const k: longint; var C: Tlong); var i: integer; begin fillchar(C.arr, sizeof(C.arr), 0); if k = 0 then inc(C.len) else begin for i := 1 to A.len do begin C.arr[i+1] := (A.arr[i]*k + C.arr[i]) div base; C.arr[i] := (A.arr[i]*k + C.arr[i]) mod base; end; if C.arr[A.len + 1] > 0 then C.len := A.len + 1 else C.len := A.len; end; end; function FindBin(var ost: TLong; const B: Tlong; const sp: integer): longint; var up, down: word; C: Tlong; begin down := 0; up := base; while up - 1 > down do begin MulLongShort(B, (up+down) div 2, C); case MoreSdvigLong(ost, C, sp) of 0: down := (up + down) div 2; 1: up := (up + down) div 2; 2: begin up := (up + down) div 2; down := up; end; end; end; MulLongShort(B, (up + down) div 2, C); if MoreSdvigLong(ost, C, 0) = 0 then SubLongTwo(ost, C, sp) else begin SubLongTwo(C, ost, sp); ost := C; end; result := (up + down) div 2; end; procedure MakeDel(const A, B: TLong; var res, ost: Tlong); var sp: integer; begin ost := A; sp := A.len - B.len; if MoreSdvigLong(A, B, sp) = 1 then dec(sp); res.len := sp + 1; while sp >= 0 do begin res.arr[sp+1] := FindBin(ost, B, sp); dec(sp); end; end; procedure DivLongTwo(const A, B: TLong; var res, ost: Tlong); begin res := nill; ost := nill; case MoreSdvigLong(A, B, 0) of 0: MakeDel(A, B, res, ost); 1: ost := A; 2: res.arr[1] := 1; end; end; operator - (const A, B: TLong): TLong; begin result := A; SubLongTwo(result, B, 0); end; operator * (const A: TLong; const k: longint): TLong; begin MulLongShort(A, k, result); end; operator div (const A, B: TLong): TLong; var ost: TLong; begin DivLongTwo(A, B, result, ost); end; operator mod (const A, B: TLong): TLong; var res: TLong; begin DivLongTwo(A, B, res, result); end; operator div (const A: TLong; const B: integer): TLong; var ost: TLong; begin DivLongTwo(A, B, result, ost); end; operator mod (const A: TLong; const B: integer): TLong; var res: TLong; begin DivLongTwo(A, B, res, result); end; initialization nill := 0; end.