unit HugeUtil; interface const HugeMax = $8000-16; type Huge = record len : word; dat : array[1..HugeMax] of word; end; HugePtr = ^Huge; procedure AddHuge (var Answer, Add : Huge); procedure MulHuge (var A : Huge; Mul : integer; var Answer : Huge); procedure DivHuge (var A : Huge; Del : integer; var Answer : Huge; var Remainder : integer); procedure SubHuge (var Answer, Sub : Huge); procedure ZeroHuge (var L : Huge; Size : word); procedure CopyHuge (var Fra,Til : Huge); procedure GetHuge (var P : HugePtr; Size : word); procedure WriteHuge(var L : Huge; Size: word); implementation procedure AddHuge; assembler; asm cld push ds lds di,Answer les si,Add seges lodsw mov cx,ax clc @l1: seges lodsw adc [si-2],ax loop @l1 jnb @done @l2: add word [si],1 inc si inc si jc @l2 @done: mov si,di lodsw shl ax,1 add si,ax lodsw or ax,ax je @d2 inc word [di] @d2: pop ds end; procedure MulHuge; assembler; asm cld push ds lds si,A mov bx,Mul les di,Answer mov cx,[si] mov dx,si inc di inc di clc @l1: mov ax,[di] pushf mul bx popf adc ax,si stosw mov si,dx loop @l1 adc si,0 mov es:[di],si lds di,A mov di,[di] mov ax,[di+2] or ax,ax je @l2 inc di inc di @l2: lds si,Answer mov [si],di pop ds end; procedure DivHuge; assembler; asm std push ds lds si,A mov bx,Del les di,Answer mov cx,[si] mov di,cx add di,cx xor dx,dx @l1: mov ax,[di] div bx stosw loop @l1 lds si,Remainder mov [si],dx lds si,A mov ax,[si] lds di,Answer mov [di],ax mov si,[di] shl si,1 @d3: lodsw or ax,ax jne @d2 dec word [di] jne @d3 inc word [di] @d2: pop ds end; procedure SubHuge; assembler; asm cld push ds lds di,Answer les si,Sub seges lodsw mov cx,ax clc @l1: seges lodsw sbb [si-2],ax loop @l1 jnb @done @l2: sub word [si],1 inc si inc si jc @l2 @done: mov si,[di] shl si,1 std @d3: lodsw or ax,ax jne @d2 dec word [di] jne @d3 inc word [di] @d2: pop ds end; procedure WriteHuge; var L1, L2, I, R, R1, X : integer; begin with L do begin L1 := Len; L2 := L1 - 1; I := 1; write(dat[L1],'.'); X := 0; for I := 1 to Size div 4 do begin Dat[L1] := 0; Len := L2; MulHuge(L,10000,L); R := dat[L1]; R1 := R div 100; R := R mod 100; write(chr(R1 div 10+48), chr(R1 mod 10+48), chr(R div 10+48), chr(R mod 10+48)); inc(X); write(' '); if X > 14 then begin writeln; write(' '); X := 0 end end end; writeln end; { WriteHuge } procedure ZeroHuge; begin fillchar(L.Dat, Size * 2, #0); L.Len := Size end; procedure CopyHuge; begin move(Fra, Til, Fra.Len * 2 + 2) end; procedure GetHuge; var D : ^byte; Tries, Bytes : word; begin Bytes := 2 * (Size + 1); Tries:=0; repeat getmem(P,Bytes); { To make it possible to use maximally large arrays, and to increase the speed of the computations, all records of type Huge MUST start at a segment boundary! } if ofs(P^) = 0 then begin ZeroHuge(P^,Size); exit end; inc(Tries); freemem(P,Bytes); new(D) until Tries>10; { if not done yet, it's not likely we ever will be } writeln('Couldn''t get memory for array'); halt(1) end; { GetHuge } end.