1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
5 -- S Y S T E M . A R I T H _ 6 4 --
9 -- Copyright (C) 1992-2023, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 -- This unit provides software routines for doing arithmetic on 64-bit
33 -- signed integer values in cases where either overflow checking is
34 -- required, or intermediate results are longer than 64 bits.
36 pragma Restrictions
(No_Elaboration_Code
);
37 -- Allow direct call from gigi generated code
39 -- Preconditions in this unit are meant for analysis only, not for run-time
40 -- checking, so that the expected exceptions are raised. This is enforced
41 -- by setting the corresponding assertion policy to Ignore. Postconditions
42 -- and contract cases should not be executed at runtime as well, in order
43 -- not to slow down the execution of these functions.
45 pragma Assertion_Policy
(Pre
=> Ignore
,
47 Contract_Cases
=> Ignore
,
50 with Ada
.Numerics
.Big_Numbers
.Big_Integers_Ghost
;
53 package System
.Arith_64
56 use type Ada
.Numerics
.Big_Numbers
.Big_Integers_Ghost
.Big_Integer
;
57 use type Interfaces
.Integer_64
;
59 subtype Int64
is Interfaces
.Integer_64
;
61 subtype Big_Integer
is
62 Ada
.Numerics
.Big_Numbers
.Big_Integers_Ghost
.Big_Integer
65 package Signed_Conversion
is new
66 Ada
.Numerics
.Big_Numbers
.Big_Integers_Ghost
.Signed_Conversions
69 function Big
(Arg
: Int64
) return Big_Integer
is
70 (Signed_Conversion
.To_Big_Integer
(Arg
))
73 function In_Int64_Range
(Arg
: Big_Integer
) return Boolean is
74 (Ada
.Numerics
.Big_Numbers
.Big_Integers_Ghost
.In_Range
75 (Arg
, Big
(Int64
'First), Big
(Int64
'Last)))
78 function Add_With_Ovflo_Check64
(X
, Y
: Int64
) return Int64
80 Pre
=> In_Int64_Range
(Big
(X
) + Big
(Y
)),
81 Post
=> Add_With_Ovflo_Check64
'Result = X
+ Y
;
82 -- Raises Constraint_Error if sum of operands overflows 64 bits,
83 -- otherwise returns the 64-bit signed integer sum.
85 function Subtract_With_Ovflo_Check64
(X
, Y
: Int64
) return Int64
87 Pre
=> In_Int64_Range
(Big
(X
) - Big
(Y
)),
88 Post
=> Subtract_With_Ovflo_Check64
'Result = X
- Y
;
89 -- Raises Constraint_Error if difference of operands overflows 64
90 -- bits, otherwise returns the 64-bit signed integer difference.
92 function Multiply_With_Ovflo_Check64
(X
, Y
: Int64
) return Int64
94 Pre
=> In_Int64_Range
(Big
(X
) * Big
(Y
)),
95 Post
=> Multiply_With_Ovflo_Check64
'Result = X
* Y
;
96 pragma Export
(C
, Multiply_With_Ovflo_Check64
, "__gnat_mulv64");
97 -- Raises Constraint_Error if product of operands overflows 64
98 -- bits, otherwise returns the 64-bit signed integer product.
99 -- Gigi may also call this routine directly.
101 function Same_Sign
(X
, Y
: Big_Integer
) return Boolean is
103 or else Y = Big (Int64'(0))
104 or else (X
< Big
(Int64
'(0))) = (Y < Big (Int64'(0))))
107 function Round_Quotient
(X
, Y
, Q
, R
: Big_Integer
) return Big_Integer
is
108 (if abs R
> (abs Y
- Big
(Int64
'(1))) / Big (Int64'(2)) then
109 (if Same_Sign
(X
, Y
) then Q
+ Big
(Int64
'(1))
110 else Q - Big (Int64'(1)))
115 Pre
=> Y
/= 0 and then Q
= X
/ Y
and then R
= X
rem Y
;
117 procedure Scaled_Divide64
123 and then In_Int64_Range
124 (if Round
then Round_Quotient
(Big
(X
) * Big
(Y
), Big
(Z
),
125 Big
(X
) * Big
(Y
) / Big
(Z
),
126 Big
(X
) * Big
(Y
) rem Big
(Z
))
127 else Big
(X
) * Big
(Y
) / Big
(Z
)),
128 Post
=> Big
(R
) = Big
(X
) * Big
(Y
) rem Big
(Z
)
131 Big
(Q
) = Round_Quotient
(Big
(X
) * Big
(Y
), Big
(Z
),
132 Big
(X
) * Big
(Y
) / Big
(Z
), Big
(R
))
134 Big
(Q
) = Big
(X
) * Big
(Y
) / Big
(Z
));
135 -- Performs the division of (X * Y) / Z, storing the quotient in Q
136 -- and the remainder in R. Constraint_Error is raised if Z is zero,
137 -- or if the quotient does not fit in 64 bits. Round indicates if
138 -- the result should be rounded. If Round is False, then Q, R are
139 -- the normal quotient and remainder from a truncating division.
140 -- If Round is True, then Q is the rounded quotient. The remainder
141 -- R is not affected by the setting of the Round flag.
143 procedure Scaled_Divide
146 Round
: Boolean) renames Scaled_Divide64
;
147 -- Renamed procedure to preserve compatibility with earlier versions
149 procedure Double_Divide64
156 and then In_Int64_Range
157 (if Round
then Round_Quotient
(Big
(X
), Big
(Y
) * Big
(Z
),
158 Big
(X
) / (Big
(Y
) * Big
(Z
)),
159 Big
(X
) rem (Big
(Y
) * Big
(Z
)))
160 else Big
(X
) / (Big
(Y
) * Big
(Z
))),
161 Post
=> Big
(R
) = Big
(X
) rem (Big
(Y
) * Big
(Z
))
164 Big
(Q
) = Round_Quotient
(Big
(X
), Big
(Y
) * Big
(Z
),
165 Big
(X
) / (Big
(Y
) * Big
(Z
)), Big
(R
))
167 Big
(Q
) = Big
(X
) / (Big
(Y
) * Big
(Z
)));
168 -- Performs the division X / (Y * Z), storing the quotient in Q and
169 -- the remainder in R. Constraint_Error is raised if Y or Z is zero,
170 -- or if the quotient does not fit in 64 bits. Round indicates if the
171 -- result should be rounded. If Round is False, then Q, R are the normal
172 -- quotient and remainder from a truncating division. If Round is True,
173 -- then Q is the rounded quotient. The remainder R is not affected by the
174 -- setting of the Round flag.
176 procedure Double_Divide
179 Round
: Boolean) renames Double_Divide64
;
180 -- Renamed procedure to preserve compatibility with earlier versions