unit dint96;

interface

type
  //UInt96 = array[0 .. 2] of UInt32;
  UInt96 = record
    Low: UInt64;
    High: UInt32;
  end;

procedure Set96(out Dst: UInt96; I: UInt64);
function Str96(const Src: UInt96): AnsiString;
procedure Add96(var Dst: UInt96; const Src: UInt96); inline;
procedure Sub96(var Dst: UInt96; const Src: UInt96); inline;
procedure Shr96(out Dst: UInt96; const Src: UInt96); inline; overload;
procedure Shl96(out Dst: UInt96; const Src: UInt96); inline; overload;
procedure Shr96(out Dst: UInt96; const Src: UInt96; P: LongInt); inline; overload;
procedure Shl96(out Dst: UInt96; const Src: UInt96; P: LongInt); inline; overload;

implementation

procedure Set96(out Dst: UInt96; I: UInt64);
begin
  Dst.Low := I;
  Dst.High := 0;
end;

function Str96(const Src: UInt96): AnsiString;
begin
  Result := HexStr(Src.High, 8) + HexStr(Src.Low, 16);
end;

procedure Add96(var Dst: UInt96; const Src: UInt96);
var
  Carry: UInt64;
begin
  Carry := (Dst.Low and Src.Low) shr 63;
  Dst.Low := UInt64(Dst.Low) + UInt64(Src.Low);
  Dst.High := UInt64(Dst.High) + UInt64(Src.High) + Carry;
end;

procedure Sub96(var Dst: UInt96; const Src: UInt96);
var
  Carry: UInt64;
begin
  Carry := ((not Dst.Low) and Src.Low) shr 63;
  Dst.Low := UInt64(Dst.Low) - UInt64(Src.Low);
  Dst.High := UInt64(Dst.High) - UInt64(Src.High) - Carry;
end;

procedure Shr96(out Dst: UInt96; const Src: UInt96);
begin
  Dst.Low := (Src.Low shr 1) or ((Src.High and 1) shl 63);
  Dst.High := Src.High shr 1;
end;

procedure Shl96(out Dst: UInt96; const Src: UInt96);
begin
  Dst.High := (Src.High shl 1) or (Src.Low shr 63);
  Dst.Low := Src.Low shl 1;
end;

procedure Shr96(out Dst: UInt96; const Src: UInt96; P: LongInt);
begin
  Dst.Low := (Src.Low shr P) or (Src.High shl (32 - P));
  Dst.High := Src.High shr P;
end;

procedure Shl96(out Dst: UInt96; const Src: UInt96; P: LongInt);
begin
  Dst.High := (Src.High shl P) or (Src.Low shr (64 - P));
  Dst.Low := Src.Low shl P;
end;

end.
