-- Find Greatest Common Divisor (GCD) of X and Y. -- It is also defined that GCD(0, 0) = 0. procedure FZ_Greatest_Common_Divisor(X : in FZ; Y : in FZ; Result : out FZ) is -- Widths of X, Y, and Result are equal subtype Width is Word_Index range X'Range; -- Result (initially 0; if degenerate case, will remain 0) GCD : FZ(Width) := (others => 0); -- Working buffers for GCD computation, initially equal to the inputs A : FZ(Width) := X; B : FZ(Width) := Y; -- Evenness (negation of lowest bit) of A and B respectively Ae, Be : WBool; -- Scratch for shifts T : FZ(Width); -- Shared power-of-2 factor Twos : Word := 0; -- |A - B| D : FZ(Width); -- This flag is set iff A < B A_lt_B : WBool; -- Whether we have the degenerate case, where A and B is 0 Degen : constant WBool := FZ_ZeroP(A) and FZ_ZeroP(B); begin -- For convergence, requires number of shots equal to 2 * FZ_Bitness: for i in 1 .. 2 * FZ_Bitness(X) loop -- If A is even, A := A >> 1; otherwise A := A Ae := 1 - FZ_OddP(A); FZ_ShiftRight(A, T, 1); FZ_Mux(X => A, Y => T, Result => A, Sel => Ae); -- If B is even, B := B >> 1; otherwise B := B Be := 1 - FZ_OddP(B); FZ_ShiftRight(B, T, 1); FZ_Mux(X => B, Y => T, Result => B, Sel => Be); -- If both A and B were even, increment the Shared Twos counter Twos := Twos + (Ae and Be); -- D := |A - B| FZ_Sub_Abs(X => A, Y => B, Difference => D, Underflow => A_lt_B); -- B' := min(A, B) FZ_Mux(X => B, Y => A, Result => B, Sel => A_lt_B); -- A' := |A - B| A := D; end loop; -- If we have the degenerate case (A and B is 0), then GCD := 0; -- Otherwise, GCD := A. FZ_Mux(X => A, Y => GCD, Result => GCD, Sel => Degen); -- Reintroduce the shared power-of-2 factor stored in 'Twos' FZ_Quiet_ShiftLeft(N => GCD, ShiftedN => GCD, Count => Indices(Twos)); -- Output result Result := GCD; end FZ_Greatest_Common_Divisor;