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