- 449D20BE8CE3646757DCD06D68BAF7FC83A5B32C085B5D617D30500C7EB4377CAA2E74B3679C2751F5277660B5E9C8C2955608C696B3268C7D294CAFFA99E442
+ 0934AF47E0703889B29836CA23503EDDFBDEDF1548FB43315E76A2651C88D9F5742A1D957A2A6D6052AC77F2E260D380131149289F30EA11DCE018A9C0342285
ffa/libffa/fz_divis.adb
(19 . 6)(19 . 7)
5
6 with Words; use Words;
7 with W_Pred; use W_Pred;
8 with W_Shifts; use W_Shifts;
9 with FZ_Basic; use FZ_Basic;
10 with FZ_Arith; use FZ_Arith;
11 with FZ_BitOp; use FZ_BitOp;
(82 . 15)(83 . 92)
13 pragma Inline_Always(FZ_Div);
14
15
16 -- Exactly same thing as IDiv, but keep only the Remainder
17 -- Modulus. Permits the asymmetric Dividend and Divisor in FZ_Mod_Exp.
18 procedure FZ_Mod(Dividend : in FZ;
19 Divisor : in FZ;
20 Remainder : out FZ) is
21 Quotient : FZ(Dividend'Range);
22 pragma Unreferenced(Quotient);
23
24 -- Length of Divisor and Remainder; <= Dividend'Length
25 L : constant Indices := Divisor'Length;
26
27 -- Remainder register, starts as zero
28 R : FZ(1 .. L) := (others => 0);
29
30 -- Indices into the words of Dividend
31 subtype Dividend_Index is Word_Index range Dividend'Range;
32
33 -- Permissible 'cuts' for the Slice operation
34 subtype Divisor_Cuts is Word_Index range 2 .. Divisor'Length;
35
36 -- Performs Restoring Division on a given segment of Dividend:Divisor
37 procedure Slice(Index : Dividend_Index;
38 Cut : Divisor_Cuts) is
39 begin
40
41 declare
42
43 -- Borrow, from comparator
44 C : WBool;
45
46 -- Left-Shift Overflow
47 LsO : WBool;
48
49 -- Current cut of Remainder register
50 Rs : FZ renames R(1 .. Cut);
51
52 -- Current cut of Divisor
53 Ds : FZ renames Divisor(1 .. Cut);
54
55 -- Current word of Dividend, starting from the highest
56 W : Word := Dividend(Dividend'Last + 1 - Index);
57
58 begin
59
60 -- For each bit in the current Dividend word:
61 for b in 1 .. Bitness loop
62
63 -- Send top bit of current Dividend word to the bottom of W
64 W := Rotate_Left(W, 1);
65
66 -- Advance Rs, shifting in the current Dividend bit
67 FZ_ShiftLeft_O_I(N => Rs, ShiftedN => Rs, Count => 1,
68 OF_In => W and 1,
69 Overflow => LsO);
70
71 -- Subtract Divisor-Cut from R-Cut; Underflow goes into C
72 FZ_Sub(X => Rs, Y => Ds, Difference => Rs, Underflow => C);
73
74 -- If C=1, subtraction underflowed, and we must undo it:
75 FZ_Add_Gated(X => Rs, Y => Ds, Sum => Rs,
76 Gate => C and W_Not(LsO));
77
78 end loop;
79
80 end;
81
82 end Slice;
83
84 begin
85 FZ_IDiv(Dividend, Divisor, Quotient, Remainder);
86
87 -- Process bottom half of dividend:
88 for i in 1 .. L - 1 loop
89
90 Slice(i, i + 1); -- stay ahead by a word to handle carry
91
92 end loop;
93
94 -- Process top half of dividend
95 for i in L .. Dividend'Length loop
96
97 Slice(i, L);
98
99 end loop;
100
101 -- Output the Remainder.
102 Remainder := R;
103
104 end FZ_Mod;
105 pragma Inline_Always(FZ_Mod);
106
107
108 end FZ_Divis;