Gem #26: The Mod Attribute
by Bob Duff —AdaCore
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