Commit fd339ba3 by Yannick Moy Committed by Pierre-Marie de Rodat

[Ada] Minor fixes mostly in comments of runtime arithmetic unit

Multiple comments in functions Double_Divide and Scaled_Divide were
incorrect. Now fixed.

Also change the expression (if Zhi /= 0 then Ylo * Zhi else 0) to the
simpler equivalent (Ylo * Zhi) in Double_Divide.

Also add a comment explaining why the implementation of Algorithm D for
multiple-precision division from the 2nd Edition of The Art of Computer
Programming does not suffer from two bugs discovered on that version.

There is no impact on execution, hence no test.

2019-09-17  Yannick Moy  <moy@adacore.com>

gcc/ada/

	* libgnat/s-arit64.adb (Double_Divide): Simplify needlessly
	complex computation. Fix comments.
	(Scaled_Divide): Fix comments. Explain why implementation does
	not suffer from bugs in Algorithm D from 2nd Edition of TAOCP.

From-SVN: r275792
parent d4ba72cb
2019-09-17 Yannick Moy <moy@adacore.com> 2019-09-17 Yannick Moy <moy@adacore.com>
* libgnat/s-arit64.adb (Double_Divide): Simplify needlessly
complex computation. Fix comments.
(Scaled_Divide): Fix comments. Explain why implementation does
not suffer from bugs in Algorithm D from 2nd Edition of TAOCP.
2019-09-17 Yannick Moy <moy@adacore.com>
* libgnat/s-arit64.adb (Scaled_Divide): Add protection against * libgnat/s-arit64.adb (Scaled_Divide): Add protection against
undesirable wrap-around. undesirable wrap-around.
......
...@@ -161,7 +161,7 @@ package body System.Arith_64 is ...@@ -161,7 +161,7 @@ package body System.Arith_64 is
end if; end if;
else else
T2 := (if Zhi /= 0 then Ylo * Zhi else 0); T2 := Ylo * Zhi;
end if; end if;
T1 := Ylo * Zlo; T1 := Ylo * Zlo;
...@@ -179,7 +179,7 @@ package body System.Arith_64 is ...@@ -179,7 +179,7 @@ package body System.Arith_64 is
Den_Pos := (Y < 0) = (Z < 0); Den_Pos := (Y < 0) = (Z < 0);
-- Check overflow case of largest negative number divided by 1 -- Check overflow case of largest negative number divided by -1
if X = Int64'First and then Du = 1 and then not Den_Pos then if X = Int64'First and then Du = 1 and then not Den_Pos then
Raise_Error; Raise_Error;
...@@ -404,15 +404,16 @@ package body System.Arith_64 is ...@@ -404,15 +404,16 @@ package body System.Arith_64 is
Ru := T2 rem Zlo; Ru := T2 rem Zlo;
end if; end if;
-- If divisor is double digit and too large, raise error -- If divisor is double digit and dividend is too large, raise error
elsif (D (1) & D (2)) >= Zu then elsif (D (1) & D (2)) >= Zu then
Raise_Error; Raise_Error;
-- This is the complex case where we definitely have a double digit -- This is the complex case where we definitely have a double digit
-- divisor and a dividend of at least three digits. We use the classical -- divisor and a dividend of at least three digits. We use the classical
-- multiple division algorithm (see section (4.3.1) of Knuth's "The Art -- multiple-precision division algorithm (see section (4.3.1) of Knuth's
-- of Computer Programming", Vol. 2 for a description (algorithm D). -- "The Art of Computer Programming", Vol. 2 for a description
-- (algorithm D).
else else
-- First normalize the divisor so that it has the leading bit on. -- First normalize the divisor so that it has the leading bit on.
...@@ -450,7 +451,7 @@ package body System.Arith_64 is ...@@ -450,7 +451,7 @@ package body System.Arith_64 is
-- Note that when we scale up the dividend, it still fits in four -- Note that when we scale up the dividend, it still fits in four
-- digits, since we already tested for overflow, and scaling does -- digits, since we already tested for overflow, and scaling does
-- not change the invariant that (D (1) & D (2)) >= Zu. -- not change the invariant that (D (1) & D (2)) < Zu.
T1 := Shift_Left (D (1) & D (2), Scale); T1 := Shift_Left (D (1) & D (2), Scale);
D (1) := Hi (T1); D (1) := Hi (T1);
...@@ -485,6 +486,19 @@ package body System.Arith_64 is ...@@ -485,6 +486,19 @@ package body System.Arith_64 is
-- Adjust quotient digit if it was too high -- Adjust quotient digit if it was too high
-- We use the version of the algorithm in the 2nd Edition of
-- "The Art of Computer Programming". This had a bug not
-- discovered till 1995, see Vol 2 errata:
-- http://www-cs-faculty.stanford.edu/~uno/err2-2e.ps.gz.
-- Under rare circumstances the expression in the test could
-- overflow. This version was further corrected in 2005, see
-- Vol 2 errata:
-- http://www-cs-faculty.stanford.edu/~uno/all2-pre.ps.gz.
-- This implementation is not impacted by these bugs, due to the
-- use of a word-size comparison done in function Le3 instead of
-- a comparison on two-word integer quantities in the original
-- algorithm.
loop loop
exit when Le3 (S1, S2, S3, D (J + 1), D (J + 2), D (J + 3)); exit when Le3 (S1, S2, S3, D (J + 1), D (J + 2), D (J + 3));
Qd (J + 1) := Qd (J + 1) - 1; Qd (J + 1) := Qd (J + 1) - 1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment