comp.lang.ada
 help / color / mirror / Atom feed
* Signed integer to modular type conversion
@ 2002-05-15  2:53 Adam Beneschan
  2002-05-15  3:34 ` Jim Rogers
                   ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: Adam Beneschan @ 2002-05-15  2:53 UTC (permalink / raw)


Supposing Standard.Integer is a 32-bit signed integer type.  I have a
modular type

    type ModType is mod 2**32;

    X : Integer;
    Y : ModType;

I'd like to set Y := X mod 2**32 (which should essentially just treat
X as an unsigned integer without changing the data).  However, I can't
figure out a good way to do this in Ada.  Using "mod" won't work,
because there is no integer type that can be used as a parameter to
"mod" that will take 2**32 as a parameter (I'm assuming that 32 bits
is the largest integer type supported by the compiler).  A type
conversion won't work, because it will raise Constraint_Error if X is
negative.  I could do something like

    if X < 0 then
	Y := ModType (X + ModType'Modulus/2) + ModType'Modulus/2;
    else
	Y := ModType (X);
    end if;

but this seems awfully silly for something that really should be just
a no-op on the machine.

Am I missing something, or is Unchecked_Conversion (or Pragma
Suppress) really the only reasonable way to accomplish this?  Unless
I've forgotten something, it seems quite odd that Ada provides modular
types but does not provide a solution for this (other than going
through the "back door" by using Unchecked_Conversion or Suppress).

If there is no solution, I'd like to propose adding an attribute so
that you could write something like

    Y := ModType'Mod (X);

This attribute would be defined for modular types and would return
X/ModType'Modulus.  I know, "Mod" is a bad name for the attribute.

My apologies if this has been discussed at length before.

				-- Adam



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-15  2:53 Adam Beneschan
@ 2002-05-15  3:34 ` Jim Rogers
  2002-05-15 14:01 ` Mark Johnson
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 17+ messages in thread
From: Jim Rogers @ 2002-05-15  3:34 UTC (permalink / raw)


Adam Beneschan wrote:

> Supposing Standard.Integer is a 32-bit signed integer type.  I have a
> modular type
> 
>     type ModType is mod 2**32;
> 
>     X : Integer;
>     Y : ModType;
> 
> I'd like to set Y := X mod 2**32 (which should essentially just treat
> X as an unsigned integer without changing the data).  However, I can't
> figure out a good way to do this in Ada.  


Try the following example.

with Ada.Text_Io;
procedure Convert is
    type ModType is mod 2**32;
    X: Integer;
    Y: ModType := ModType'First;
begin
    loop
       X := Integer(Y);
       Ada.Text_IO.Put_Line("Value:" & Integer'Image(X));
       exit when Y = ModType'Last;
       Y := Y + 1;
    end loop;
end Convert;

You can see that the only real issue is converting the modular type
to an Integer, which is done with simple type coercion.

Jim Rogers




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
@ 2002-05-15  5:43 Grein, Christoph
  0 siblings, 0 replies; 17+ messages in thread
From: Grein, Christoph @ 2002-05-15  5:43 UTC (permalink / raw)


> Am I missing something, or is Unchecked_Conversion (or Pragma
> Suppress)

No, you're not missing something. Unchecked_Conversion is just there to perform 
a "type cast" if the representation does not change.

pragma Suppress is there for different reasons.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-15  2:53 Adam Beneschan
  2002-05-15  3:34 ` Jim Rogers
@ 2002-05-15 14:01 ` Mark Johnson
  2002-05-16  0:02   ` Adam Beneschan
  2002-05-15 19:12 ` Robert Dewar
  2002-05-15 20:28 ` Adam Beneschan
  3 siblings, 1 reply; 17+ messages in thread
From: Mark Johnson @ 2002-05-15 14:01 UTC (permalink / raw)


Adam Beneschan wrote:
> 
> Supposing Standard.Integer is a 32-bit signed integer type.  I have a
> modular type
> 
>     type ModType is mod 2**32;
> 
>     X : Integer;
>     Y : ModType;
> 
> I'd like to set Y := X mod 2**32 (which should essentially just treat
> X as an unsigned integer without changing the data).
A reasonably efficient way to do this is Unchecked_Conversion. This for
types of the same size (as in this case), it will copy the bytes from
the source to destination. As you noted in the rest of your message, the
direct type conversion doesn't do what you want and the arithmetic is an
inefficient method. There are a lot of reasons not to use
Unchecked_Conversion, but this doesn't appear to be one of them.
  --Mark

PS: I don't generally recommend this solution because many use it to
excess. Try...
  with Unchecked_Conversion;
  function "+" is new Unchecked_Conversion(Integer, Mod_Type);
Then your example assignment will be...
  Y := +X;
The abuse comes from using this method for all sorts of type
conversions, avoiding type safety, etc.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-15  2:53 Adam Beneschan
  2002-05-15  3:34 ` Jim Rogers
  2002-05-15 14:01 ` Mark Johnson
@ 2002-05-15 19:12 ` Robert Dewar
  2002-05-15 20:28 ` Adam Beneschan
  3 siblings, 0 replies; 17+ messages in thread
From: Robert Dewar @ 2002-05-15 19:12 UTC (permalink / raw)


adam@irvine.com (Adam Beneschan) wrote in message news:<b4682ab7.0205141853.7e835874@posting.google.com>...
> Am I missing something, or is Unchecked_Conversion (or 
> Pragma Suppress) really the only reasonable way to 
> accomplish this?  Unless
> I've forgotten something, it seems quite odd that Ada 
> provides modular types but does not provide a solution 
> for this (other than going through the "back door" by 
> using Unchecked_Conversion or Suppress).

To me it seems quite appropriate to use UC here, since the
meaning of this conversion is quite target dependent. For
instance the unchecked conversion is only equivalent to
mod 2 ** 32 on a 2's complement machine. On a 1's complement machine
these are different and you need
to be sure what you are requiring.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-15  2:53 Adam Beneschan
                   ` (2 preceding siblings ...)
  2002-05-15 19:12 ` Robert Dewar
@ 2002-05-15 20:28 ` Adam Beneschan
  3 siblings, 0 replies; 17+ messages in thread
From: Adam Beneschan @ 2002-05-15 20:28 UTC (permalink / raw)


adam@irvine.com (Adam Beneschan) wrote in message news:<b4682ab7.0205141853.7e835874@posting.google.com>...

> If there is no solution, I'd like to propose adding an attribute so
> that you could write something like
> 
>     Y := ModType'Mod (X);
> 
> This attribute would be defined for modular types and would return
> X/ModType'Modulus. 

I meant to say "X mod ModType'Modulus".

				-- Adam



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-15 14:01 ` Mark Johnson
@ 2002-05-16  0:02   ` Adam Beneschan
  2002-05-16  2:26     ` Steven Deller
                       ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Adam Beneschan @ 2002-05-16  0:02 UTC (permalink / raw)


Mark Johnson <mark_h_johnson@raytheon.com> wrote in message news:<3CE26A21.3EC6F802@raytheon.com>...
> Adam Beneschan wrote:
> > 
> > Supposing Standard.Integer is a 32-bit signed integer type.  I have a
> > modular type
> > 
> >     type ModType is mod 2**32;
> > 
> >     X : Integer;
> >     Y : ModType;
> > 
> > I'd like to set Y := X mod 2**32 (which should essentially just treat
> > X as an unsigned integer without changing the data).

> A reasonably efficient way to do this is Unchecked_Conversion. This for
> types of the same size (as in this case), it will copy the bytes from
> the source to destination. As you noted in the rest of your message, the
> direct type conversion doesn't do what you want and the arithmetic is an
> inefficient method. There are a lot of reasons not to use
> Unchecked_Conversion, but this doesn't appear to be one of them.
>   --Mark

OK, let me try a variation, and see if you still think
Unchecked_Conversion an appropriate way (or the best way) to handle
it.

I have two integer values.  One is in the range 0 .. 2**32-1, and the
other is in the range -2**31 .. 2**31-1.  I want to find the
mathematical sum of these two integers.  Let's assume that I expect
the result to be in the range 0..2**32-1, and am not worried about
what happens if it isn't.

    type ModType is mod 2**32;
    X : ModType;
    Y : Integer;
    Z : ModType;

I want to compute Z := X + Y, but of course I can't write this.  Z :=
X + ModType(Y) won't work if Y is negative; this is what led me to ask
the previous question, since I was trying to find a way to convert Y
to a ModType.

Again, I believe this is something that can be computed with one
machine instruction, so I'd like to avoid time-wasters like

    if Y < 0 then
	Z := X - ModType(-Y);
    else
	Z := X + ModType(Y);
    end if;

Would you still use something like Z := X + ToModType(Y) [where
ToModType is an instance of Unchecked_Conversion]?

				-- Adam



^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: Signed integer to modular type conversion
  2002-05-16  0:02   ` Adam Beneschan
@ 2002-05-16  2:26     ` Steven Deller
  2002-05-16  9:53     ` Robert Dewar
  2002-05-16 13:55     ` Mark Johnson
  2 siblings, 0 replies; 17+ messages in thread
From: Steven Deller @ 2002-05-16  2:26 UTC (permalink / raw)


Compute in "integer" (the wider type) and then coerce into your modtype.

Y := modtype( X mod 2**32 ) ;
Z := modtype( integer(X) + Y ) ;

Makes it clear that the computation is done as "integer" with an
expected result that fits into "modtype".

You could also do:
   function "+" ( L : modtype ; R : integer ) return modtype is
   begin
       return modtype( integer(L) + R ) ;
   end "+"; 

and then write
    z := x + y ;

But unless mixing the two types is done a lot and you write "all" mixing
functions in a package (which can lead to disambiguation difficulties),
this is not good technique.

Some of your difficulty may be from looking at types as simply sets of
"the same" numeric values, rather than as abstractions of distinctly
different values that just happen to use the same "untyped" number set
to name the values.  

When you leave out abstraction, modtype simply looks like an integer
with some values taken out, and "+" looks like a single operator.

The real meaning of the values and operators depends on the abstraction
you are trying to model with each different type.  Usually, when the
full abstraction is considered, I find the problem of "mixing" types
resolves rather easily, or reveals an incorrect mix or incorrect
abstraction.

Regards,
Steve

> -----Original Message-----
> > Adam Beneschan wrote:
> > > 
> > > Supposing Standard.Integer is a 32-bit signed integer 
> type.  I have 
> > > a modular type
> > > 
> > >     type ModType is mod 2**32;
> > > 
> > >     X : Integer;
> > >     Y : ModType;
> > > 
> > > I'd like to set Y := X mod 2**32 (which should essentially just 
> > > treat X as an unsigned integer without changing the data).
...
> OK, let me try a variation, and see if you still think 
> Unchecked_Conversion an appropriate way (or the best way) to 
> handle it.
> 
> I have two integer values.  One is in the range 0 .. 2**32-1, 
> and the other is in the range -2**31 .. 2**31-1.  I want to 
> find the mathematical sum of these two integers.  Let's 
> assume that I expect the result to be in the range 
> 0..2**32-1, and am not worried about what happens if it isn't.
> 
>     type ModType is mod 2**32;
>     X : ModType;
>     Y : Integer;
>     Z : ModType;
> 
> I want to compute Z := X + Y, but of course I can't write 
> this.  Z := X + ModType(Y) won't work if Y is negative; this 
> is what led me to ask the previous question, since I was 
> trying to find a way to convert Y to a ModType.
> 
> Again, I believe this is something that can be computed with 
> one machine instruction, so I'd like to avoid time-wasters like
> 
>     if Y < 0 then
> 	Z := X - ModType(-Y);
>     else
> 	Z := X + ModType(Y);
>     end if;
> 
> Would you still use something like Z := X + ToModType(Y) 
> [where ToModType is an instance of Unchecked_Conversion]?
> 
> 				-- Adam
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org 
> http://ada.eu.org/mailman/listinfo/comp.lang.ad> a
> 




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
@ 2002-05-16  4:39 Grein, Christoph
  2002-05-16 14:13 ` Mark Johnson
  0 siblings, 1 reply; 17+ messages in thread
From: Grein, Christoph @ 2002-05-16  4:39 UTC (permalink / raw)


From: Mark Johnson <mark_h_johnson@raytheon.com>
> PS: I don't generally recommend this solution because many use it to
> excess. Try...
>   with Unchecked_Conversion;
>   function "+" is new Unchecked_Conversion(Integer, Mod_Type);
> Then your example assignment will be...
>   Y := +X;
> The abuse comes from using this method for all sorts of type
> conversions, avoiding type safety, etc.

Did you really observe much abuse? This affords so much more wording than a 
simple type conversion, so why should someone abuse it?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-16  0:02   ` Adam Beneschan
  2002-05-16  2:26     ` Steven Deller
@ 2002-05-16  9:53     ` Robert Dewar
  2002-05-16 13:46       ` Steve Doiel
                         ` (2 more replies)
  2002-05-16 13:55     ` Mark Johnson
  2 siblings, 3 replies; 17+ messages in thread
From: Robert Dewar @ 2002-05-16  9:53 UTC (permalink / raw)


adam@irvine.com (Adam Beneschan) wrote in message news:<b4682ab7.0205151602.3c564c9e@posting.google.com>...


> Would you still use something like Z := X + ToModType(Y) [where
> ToModType is an instance of Unchecked_Conversion]?

No, I would use a 64-bit type to compute. If you have a deficient
compiler that does not support 64-bit integers, then you have trouble,
but so what? You could have equally asked to deal with numbers in the
range 2**44, and then you would have needed a larger type anyway.

These days, all compilers should support 64-bit integers.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-16  9:53     ` Robert Dewar
@ 2002-05-16 13:46       ` Steve Doiel
  2002-05-16 14:00       ` Mark Johnson
  2002-05-16 15:52       ` Adam Beneschan
  2 siblings, 0 replies; 17+ messages in thread
From: Steve Doiel @ 2002-05-16 13:46 UTC (permalink / raw)


"Robert Dewar" <dewar@gnat.com> wrote in message
news:5ee5b646.0205160153.75230135@posting.google.com...
[snip]
>
> These days, all compilers should support 64-bit integers.

ObjectAda 7.2 does not.

SteveD






^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-16  0:02   ` Adam Beneschan
  2002-05-16  2:26     ` Steven Deller
  2002-05-16  9:53     ` Robert Dewar
@ 2002-05-16 13:55     ` Mark Johnson
  2 siblings, 0 replies; 17+ messages in thread
From: Mark Johnson @ 2002-05-16 13:55 UTC (permalink / raw)


Adam Beneschan wrote:
> 
> I have two integer values.  One is in the range 0 .. 2**32-1, and the
> other is in the range -2**31 .. 2**31-1.  I want to find the
> mathematical sum of these two integers.  Let's assume that I expect
> the result to be in the range 0..2**32-1, and am not worried about
> what happens if it isn't.
> 
>     type ModType is mod 2**32;
>     X : ModType;
>     Y : Integer;
>     Z : ModType;
> 
> I want to compute Z := X + Y, but of course I can't write this.
Why not? You can if you define the "+" operator for the right parameter
as integer and the left as your ModType (and the associative version as
well...). I will also assume I have the unary plus operator
(Unchecked_Conversion) as previously described....
  function "+"(Left: Integer; Right:ModType) return ModType is
    Temp : ModType := +Left; -- convert to ModType
  begin
    return Temp+Right;
  end "+";
Which converts the left operator to ModType and uses modular add to get
the result. Let's try some examples...
  1+2000 is 2001
  -1+2000 is 1999
The modular arithmetic should do the "right thing" for the unsigned
addition.
  --Mark



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-16  9:53     ` Robert Dewar
  2002-05-16 13:46       ` Steve Doiel
@ 2002-05-16 14:00       ` Mark Johnson
  2002-05-16 15:52       ` Adam Beneschan
  2 siblings, 0 replies; 17+ messages in thread
From: Mark Johnson @ 2002-05-16 14:00 UTC (permalink / raw)


Robert Dewar wrote:
> 
> adam@irvine.com (Adam Beneschan) wrote in message news:<b4682ab7.0205151602.3c564c9e@posting.google.com>...
> 
> > Would you still use something like Z := X + ToModType(Y) [where
> > ToModType is an instance of Unchecked_Conversion]?
> 
> No, I would use a 64-bit type to compute. If you have a deficient
> compiler that does not support 64-bit integers, then you have trouble,
> but so what? You could have equally asked to deal with numbers in the
> range 2**44, and then you would have needed a larger type anyway.
> 
> These days, all compilers should support 64-bit integers.

That's a little heavy if all he wants is a 32 bit value computed using
modular arithmetic. I sent a separate reply showing the alternative by
defining the mixed type arithmetic that should get the results he is
looking for.
  --Mark
PS: A long time ago, in the days of fixed point arithmetic, we used this
kind of trick to do a lot of our calculations. (e.g., represent the
angles of a circle as the range 0 .. 1-(1/2**15) which allowed natural
ways to add angles yet preserve good precision)



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-16  4:39 Grein, Christoph
@ 2002-05-16 14:13 ` Mark Johnson
  0 siblings, 0 replies; 17+ messages in thread
From: Mark Johnson @ 2002-05-16 14:13 UTC (permalink / raw)


"Grein, Christoph" wrote:
> 
> From: Mark Johnson <mark_h_johnson@raytheon.com>
> > PS: I don't generally recommend this solution because many use it to
> > excess. Try...
> >   with Unchecked_Conversion;
> >   function "+" is new Unchecked_Conversion(Integer, Mod_Type);
> > Then your example assignment will be...
> >   Y := +X;
> > The abuse comes from using this method for all sorts of type
> > conversions, avoiding type safety, etc.
> 
> Did you really observe much abuse? This affords so much more wording than a
> simple type conversion, so why should someone abuse it?

We develop large real time simulations of systems. I find examples all
over the place in code that was developed by people skilled in the
system they are simulating (and not so skilled in Ada). Most are pretty
silly such as a converting between 16 and 32 bit values which a simple
type conversion is adequate. When you go through code you see the Y :=
+X; you have to ask which "+" is it and why it is there.

Also, we are rehosting software and switching compiler vendors. Using
GNAT, we get good warnings about Unchecked_Conversion between different
sizes and can evaluate if that is the "Right Choice". The three choices
are zero extend, sign extend, or "unspecified value" - its the latter
one which causes us the most problems and we generally have to fix code
that might have worked OK on the old machine but will likely be broke on
the new one.
  --Mark



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-16  9:53     ` Robert Dewar
  2002-05-16 13:46       ` Steve Doiel
  2002-05-16 14:00       ` Mark Johnson
@ 2002-05-16 15:52       ` Adam Beneschan
  2002-05-17  2:26         ` Robert Dewar
  2 siblings, 1 reply; 17+ messages in thread
From: Adam Beneschan @ 2002-05-16 15:52 UTC (permalink / raw)


dewar@gnat.com (Robert Dewar) wrote in message news:<5ee5b646.0205160153.75230135@posting.google.com>...
> adam@irvine.com (Adam Beneschan) wrote in message news:<b4682ab7.0205151602.3c564c9e@posting.google.com>...
> 
> 
> > Would you still use something like Z := X + ToModType(Y) [where
> > ToModType is an instance of Unchecked_Conversion]?
> 
> No, I would use a 64-bit type to compute. If you have a deficient
> compiler that does not support 64-bit integers, then you have trouble,
> but so what? You could have equally asked to deal with numbers in the
> range 2**44, and then you would have needed a larger type anyway.
> 
> These days, all compilers should support 64-bit integers.

If the compiler supports 64-bit integers, then change my question so
that I have a number in the range 0..2**64-1 and a number in the range
-2**63 to 2**63-1 and wish to add them.  Now my question still stands.
 (Unless you want to answer by saying that these days all compilers
should support 128-bit integers.)

				-- Adam



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-16 15:52       ` Adam Beneschan
@ 2002-05-17  2:26         ` Robert Dewar
  2002-05-17 16:44           ` Frank J. Lhota
  0 siblings, 1 reply; 17+ messages in thread
From: Robert Dewar @ 2002-05-17  2:26 UTC (permalink / raw)


adam@irvine.com (Adam Beneschan) wrote in message news:<b4682ab7.0205160752.3f973bcc@posting.google.com>...

> If the compiler supports 64-bit integers, then change my question so
> that I have a number in the range 0..2**64-1 and a number in the range
> -2**63 to 2**63-1 and wish to add them.  Now my question still stands.
>  (Unless you want to answer by saying that these days all compilers
> should support 128-bit integers.)

First, you quoted two complete levels of complete messages, there really
is no need to have this much context in a threaded topic, please quote
more selectively.

Second, why should I get upset about you not being able to do this for the
-2**63 case, if you change the 63 to 64, then you would not be expecting
to be able to do it. There are lots of marginal cases where you can do
something at the hardware level that you can't map easily into a high
level language (one of the most obvious ones is (A*B)/C with a double
length intermediate value (of commonly used languages, only COBOL can
handle this cleanly).



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Signed integer to modular type conversion
  2002-05-17  2:26         ` Robert Dewar
@ 2002-05-17 16:44           ` Frank J. Lhota
  0 siblings, 0 replies; 17+ messages in thread
From: Frank J. Lhota @ 2002-05-17 16:44 UTC (permalink / raw)


> There are lots of marginal cases where you can do
> something at the hardware level that you can't map easily into a high
> level language (one of the most obvious ones is (A*B)/C with a double
> length intermediate value (of commonly used languages, only COBOL can
> handle this cleanly).

Forth also handles this cleanly.





^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2002-05-17 16:44 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-05-15  5:43 Signed integer to modular type conversion Grein, Christoph
  -- strict thread matches above, loose matches on Subject: below --
2002-05-16  4:39 Grein, Christoph
2002-05-16 14:13 ` Mark Johnson
2002-05-15  2:53 Adam Beneschan
2002-05-15  3:34 ` Jim Rogers
2002-05-15 14:01 ` Mark Johnson
2002-05-16  0:02   ` Adam Beneschan
2002-05-16  2:26     ` Steven Deller
2002-05-16  9:53     ` Robert Dewar
2002-05-16 13:46       ` Steve Doiel
2002-05-16 14:00       ` Mark Johnson
2002-05-16 15:52       ` Adam Beneschan
2002-05-17  2:26         ` Robert Dewar
2002-05-17 16:44           ` Frank J. Lhota
2002-05-16 13:55     ` Mark Johnson
2002-05-15 19:12 ` Robert Dewar
2002-05-15 20:28 ` Adam Beneschan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox