This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Ada: fix bugs in 64 bit arithmetic


Tested on x86-linux

This patch fixes some instances of incorrect results in Scaled_Divide.
The problem arose in the case where the quotient was incorrectly estimated
and needed correction, and the correction involves certain cases of carries
on the subtractions. These cases are pretty rare. The test program k.adb
shows two cases of direct calls to Scaled_Divide that trigger this bug,
and without this patch, this program will raise Program_Error. The
expected results are as indicated by the explicit tests in the test
program. Scaled_Divide is used for certain (somewhat unusual) cases
of division of 64-bit fixed-point numbers. This means that there is a
sequence of unlikely events to trigger the wrong results in an actual
Ada program, and we have not been able to devise an Ada test program
with a fixed-point division showing the problem, but likely there are
such cases. In any case, the fix is clearly needed. At the same time,
the code has been streamlined to avoid a considerable amount of
duplication of (incorrect) code in the original version.

with Text_IO; use Text_IO;
with System.Arith_64; use System.Arith_64;
with Interfaces; use Interfaces;
procedure k is
   X, Y, Z, Q, R : Int64;
begin
   X := Int64'Last; Y := Int64'Last; Z := Int64'Last;
   Scaled_Divide (X, Y, Z, Q, R, False);
   Put_Line ("L = " & Int64'Image (Int64'Last));
   Put_Line ("Q = " & Q'Img);
   Put_Line ("R = " & R'Img);
   if Q /= Z or else R /= 0 then
      raise Program_Error;
   end if;
   X := 2305843009213628416; Y := 2305580303244001280; Z := 2305843009213693696;
   Scaled_Divide (X, Y, Z, Q, R, False);
   Put_Line ("Q = " & Q'Img);
   Put_Line ("R = " & R'Img);
   if Q /= 2305580303243936007 or else R /= 1008544637025060608 then
      raise Program_Error;
   end if;
end;

2004-10-26  Robert Dewar  <dewar@gnat.com>

	* s-arit64.adb: (Le3): New function, used by Scaled_Divide
	(Sub3): New procedure, used by Scaled_Divide
	(Scaled_Divide): Substantial rewrite, avoid duplicated code, and also
	correct more than one instance of failure to propagate carries
	correctly.
	(Double_Divide): Handle overflow case of largest negative number
	divided by minus one.

	* s-arit64.ads (Double_Divide): Document that overflow can occur in
	the case of a quotient value out of range.
	Fix comments.

Attachment: difs.23
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]