-
+ 449D20BE8CE3646757DCD06D68BAF7FC83A5B32C085B5D617D30500C7EB4377CAA2E74B3679C2751F5277660B5E9C8C2955608C696B3268C7D294CAFFA99E442ffa/libffa/fz_divis.adb(0 . 0)(1 . 96)
182 ------------------------------------------------------------------------------
183 ------------------------------------------------------------------------------
184 -- This file is part of 'Finite Field Arithmetic', aka 'FFA'. --
185 -- --
186 -- (C) 2017 Stanislav Datskovskiy ( www.loper-os.org ) --
187 -- http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html --
188 -- --
189 -- You do not have, nor can you ever acquire the right to use, copy or --
190 -- distribute this software ; Should you use this software for any purpose, --
191 -- or copy and distribute it to anyone or in any manner, you are breaking --
192 -- the laws of whatever soi-disant jurisdiction, and you promise to --
193 -- continue doing so for the indefinite future. In any case, please --
194 -- always : read and understand any software ; verify any PGP signatures --
195 -- that you use - for any purpose. --
196 -- --
197 -- See also http://trilema.com/2015/a-new-software-licensing-paradigm . --
198 ------------------------------------------------------------------------------
199 ------------------------------------------------------------------------------
200
201 with Words; use Words;
202 with W_Pred; use W_Pred;
203 with FZ_Basic; use FZ_Basic;
204 with FZ_Arith; use FZ_Arith;
205 with FZ_BitOp; use FZ_BitOp;
206 with FZ_Shift; use FZ_Shift;
207
208
209 package body FZ_Divis is
210
211 -- Dividend is divided by Divisor, producing Quotient and Remainder.
212 -- WARNING: NO div0 test here! Caller must test.
213 procedure FZ_IDiv(Dividend : in FZ;
214 Divisor : in FZ;
215 Quotient : out FZ;
216 Remainder : out FZ) is
217
218 -- The working register
219 QR : FZ(1 .. Dividend'Length + Divisor'Length);
220
221 -- Bottom seg of Z will end up containing the Quotient; top - remainder
222 Q : FZ renames QR(1 .. Dividend'Length); -- Quotient
223 R : FZ renames QR(Dividend'Length + 1 .. QR'Last); -- Remainder
224
225 C : WBool := 0; -- Borrow, from comparator
226 begin
227 Q := Dividend; -- Q begins with the Dividend
228 FZ_Clear(R); -- R begins empty
229
230 -- For each bit of Dividend:
231 for i in 1 .. FZ_Bitness(Dividend) loop
232
233 -- Advance QR by 1 bit:
234 FZ_ShiftLeft(QR, QR, 1);
235
236 -- Subtract Divisor from R; Underflow goes into C
237 FZ_Sub(X => R, Y => Divisor, Difference => R, Underflow => C);
238
239 -- If C=1, subtraction underflowed, and then Divisor gets added back:
240 FZ_Add_Gated(X => R, Y => Divisor, Gate => C, Sum => R);
241
242 -- Current result-bit is equal to Not-C, i.e. 1 if Divisor 'went in'
243 FZ_Or_W(Q, W_Not(C));
244
245 end loop;
246
247 Quotient := Q; -- Output the Quotient.
248 Remainder := R; -- Output the Remainder.
249
250 end FZ_IDiv;
251 pragma Inline_Always(FZ_IDiv);
252
253
254 -- Exactly same thing as IDiv, but keep only the Quotient
255 procedure FZ_Div(Dividend : in FZ;
256 Divisor : in FZ;
257 Quotient : out FZ) is
258 Remainder : FZ(Divisor'Range);
259 pragma Unreferenced(Remainder);
260 begin
261 FZ_IDiv(Dividend, Divisor, Quotient, Remainder);
262 end FZ_Div;
263 pragma Inline_Always(FZ_Div);
264
265
266 -- Exactly same thing as IDiv, but keep only the Remainder
267 procedure FZ_Mod(Dividend : in FZ;
268 Divisor : in FZ;
269 Remainder : out FZ) is
270 Quotient : FZ(Dividend'Range);
271 pragma Unreferenced(Quotient);
272 begin
273 FZ_IDiv(Dividend, Divisor, Quotient, Remainder);
274 end FZ_Mod;
275 pragma Inline_Always(FZ_Mod);
276
277 end FZ_Divis;