
Gem #26: The Mod Attribute
Let's get started…
Ada has two kinds of integer type: signed and modular:
type Signed_Integer is range 1..1_000_000;
type Modular is mod 2**32;
Operations on signed integers can overflow: if the result is outside the base range, Constraint_Error will be raised. The base range of Signed_Integer is the range of Signed_Integer'Base, which is chosen by the compiler, but is likely to be something like -2**31..2**31-1.
Operations on modular integers use modular (wraparound) arithmetic.
For example:
X : Modular := 1;
X := - X;
Negating X gives -1, which wraps around to 2**32-1, i.e. all-one-bits.
But what about a type conversion from signed to modular? Is that a signed operation (so it should overflow) or is it a modular operation (so it should wrap around)? The answer in Ada is the former -- that is, if you try to convert, say, Integer'(-1) to Modular, you will get Constraint_Error:
I : Integer := -1;
X := Modular (I); -- raises Constraint_Error
In Ada 95, the only way to do that conversion is to use Unchecked_Conversion, which is somewhat uncomfortable. Furthermore, if you're trying to convert to a generic formal modular type, how do you know what size of signed integer type to use? Note that Unchecked_Conversion might malfunction if the source and target types are of different sizes.
A small feature added to Ada 2005 solves the problem: the Mod attribute:
generic
type Formal_Modular is mod <>;
package Mod_Attribute is
function F return Formal_Modular;
end Mod_Attribute;
package body Mod_Attribute is
A_Signed_Integer : Integer := -1;
function F return Formal_Modular is
begin
return Formal_Modular'Mod (A_Signed_Integer);
end F;
end Mod_Attribute;The Mod attribute will correctly convert from any integer type to a given modular type, using wraparound semantics. Thus, F will return the all-ones bit pattern, for whatever modular type is passed to Formal_Modular.
Related Source Code
Ada Gems example files are distributed by AdaCore and may be used or modified for any purpose without restrictions.
gem_26.ada




