(*******************************************************************
 *
 *  TTCalc.Pas                                                  1.2
 *
 *    Arithmetic and Vectorial Computations (specification)
 *
 *  Copyright 1996 David Turner, Robert Wilhelm and Werner Lemberg
 *
 *  This file is part of the FreeType project, and may only be used
 *  modified and distributed under the terms of the FreeType project
 *  license, LICENSE.TXT. By continuing to use, modify or distribute
 *  this file you indicate that you have read the license and
 *  understand and accept it fully.
 *
 *  NOTES : All vector operations were moved to the interpreter
 *
 ******************************************************************)

unit TTCalc;

interface

type
  (* IntN types :                                                       *)
  (*                                                                    *)
  (*  These types are used as a way to garantee the size of some        *)
  (*  specific integers.                                                *)
  (*                                                                    *)
  (*  Of course, they are equivalent to Short, UShort, Long, etc ..     *)
  (*  but parts of this unit could be used by different programs.       *)
  (*                                                                    *)

  Int16  = Integer;            (* 16 bits integer  *)
  Int32  = LongInt;            (* 32 bits integer  *)

  Word16 = Word;               (* 16-bits unsigned *)
  Word32 = LongInt;            (* 32 bits 'unsigned'. Note that there's *)
                               (* no unsigned long in Pascal..          *)

  Int64  = record              (* 64 ""            *)
            Lo,
            Hi  : LongInt;
          end;

function MulDiv( A, B, C : Int32 ): Int32;

function MulDiv_Round( A, B, C : Int32 ): Int32;

procedure Add64( var X, Y, Z : Int64 );
procedure Sub64( var X, Y, Z : Int64 );

procedure MulTo64( X, Y : Int32; var Z : Int64 );

function  Div64by32( var X : Int64; Y : Int32 ) : Int32;

function Order64( var Z : Int64 ) : integer;
function Order32(     Z : Int32 ) : integer;

function Sqrt32( L : LongInt ): LongInt;
function Sqrt64( L : Int64 ): LongInt;

implementation


{$I TTCALC.INC}

const
  Roots : array[0..62] of LongInt
        = (
               1,    1,    2,     3,     4,     5,     8,    11,
              16,   22,   32,    45,    64,    90,   128,   181,
             256,  362,  512,   724,  1024,  1448,  2048,  2896,
            4096, 5892, 8192, 11585, 16384, 23170, 32768, 46340,

              65536,   92681,  131072,   185363,   262144,   370727,
             524288,  741455, 1048576,  1482910,  2097152,  2965820,
            4194304, 5931641, 8388608, 11863283, 16777216, 23726566,

              33554432,   47453132,   67108864,   94906265,
             134217728,  189812531,  268435456,  379625062,
             536870912,  759250125, 1073741824, 1518500250,
            2147483647
          );


(**************************************************)
(* Integer Square Root                            *)

function Sqrt32( L : LongInt ): LongInt;
var
  R, S : LongInt;
begin
  if L<=0 then Sqrt32:=0 else
  if L=1 then Sqrt32:=1 else
   begin
    R:=Roots[ Order32(L) ];

    Repeat
     S:=R;
     R:=( R+ L div R ) shr 1;
    until ( R <= S ) and ( R*R <= L );

    Sqrt32:=R;
   end;
end;


(**************************************************)
(* Integer Square Root                            *)

function Sqrt64( L : Int64 ): LongInt;
var
  L2   : Int64;
  R, S : LongInt;
begin
   if L.Hi < 0 then Sqrt64:=0 else
   begin
    S := Order64(L);
    if S = 0 then Sqrt64:=1 else
     begin
      R := Roots[S];

      Repeat

       S := R;
       R := ( R+Div64by32(L,R) ) shr 1;
       MulTo64( R,  R, L2 );
       Sub64  ( L, L2, L2 );

      until ( R <= S ) and ( L2.Hi >= 0 );

      Sqrt64 := R;
     end
   end
end;

end.
