anchor.diff:    H, K: array[0..2] of Int64;
     X, D, N: Int64;
     I: Integer;
  -  Neg: Boolean;
  +  LNegative: Boolean;
     MustBreak: Boolean;
   begin
     H[0] := 0; H[1] := 1; H[2] := 0;
  
positive.code:     Exit;
    end;
  
    Neg := F < 0;
    if Neg then
      F := -F;
  
    while (F <> System.Trunc(F)) and (N < (High(Int64) shr 1)) do
  
negative.code: //                                                                                                                  //
  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  
  (*
  function ConvertDoubleToRational(Value, Epsilon: Double; MaxIterations: Integer; var FNumerator, FDenominator: Int64): Double; overload;
  *)
  var
    LNegative: Boolean;
    LQuot: Double;
    LError: Double;
    I: Integer;
    NewRatio, Ratio: Double;
    Rest, Rest0, Inverse, Inverse0: Double;
    K, H: array[0..2] of Int64;
    A: Int64;
    LNum, LDenom: BigInteger;
  begin
    LQuot := 0.0;
  
    if IsInfinite(Value) or IsNaN(Value) then
      Error(ecInvalidArg, ['Double']);
  
    LNegative := Value < 0;
    if LNegative then
      Value := -Value;
  
    if Value > MaxInt then
    begin
      // reduce Value to range [0..MaxInt)
      LQuot := Int(Value / MaxInt) * MaxInt;
      Value := Value - LQuot;
      // Hmmm... turn it into a suitable range
      // FloatMod(Value, MaxInt, Quot, Rem);
      // Quot := Int(Value / MaxInt);
      // Value := Value - Quot * MaxInt;
      // work on rem --> value, remember quot;
      // raise EOverflow.CreateFmt('Value %g cannot be converted to an integer ratio', [Value]);
    end;
  
    if Value = 0.0 then
    begin
      FNumerator := BigInteger.Zero;
      FDenominator := BigInteger.One;
      Exit;
    end;
  
    if Epsilon = 0 then
      Epsilon := 5e-10;
  
    I := 0;
    while I < MaxIterations do
    begin
      if I = 0 then
      begin
        A := Trunc(Value);
        Rest := Value - A;
        if Rest = 0.0 then
        begin
          FNumerator := A;
          FDenominator := 1;
          Exit;
        end;
        Inverse := 1.0 / Rest;
        K[2] := A;
        H[2] := 1;
        NewRatio := K[2] / H[2];
        LError := System.Abs(Value - NewRatio);
      end
      else
      begin
        A := Trunc(Inverse0);
        Rest := Inverse0 - A;
        if Rest = 0.0 then
          Rest := Epsilon;
        Inverse := 1.0 / Rest;
        if I = 1 then
        begin
          K[2] := A * K[1] + 1;
          H[2] := A * H[1];
        end
        else
        begin
          if (A > MaxInt) or (K[1] > MaxInt) or (H[1] > MaxInt) then
            Break;
          K[2] := A * K[1] + K[0];
          H[2] := A * H[1] + H[0];
        end;
        NewRatio := K[2] / H[2];
        LError := System.Abs(NewRatio - Ratio);
      end;
      if LError < Epsilon then
        Break
      else
        Ratio := NewRatio;
      Inc(I);
      K[0] := K[1];
      K[1] := K[2];
      H[0] := H[1];
      H[1] := H[2];
      Inverse0 := Inverse;
      Rest0 := Rest;
      if Inverse0 > MaxInt then
        Break;
    end;
    LNum := K[1];
    LDenom := H[1];
    if LQuot > 0.0 then
      LNum := LNum + BigInteger(LQuot) * LDenom;
    if LNegative then
      LNum := -LNum;
  
    FNumerator := LNum;
    FDenominator := LDenom;
    Normalize;
  end;
  
  class function BigRational.Compare(const Left, Right: BigRational): Integer;
  