comp.lang.ada
 help / color / mirror / Atom feed
* Saturation arithmetic woes.
@ 2009-07-29 17:03 xorque
  2009-07-29 17:13 ` Martin
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: xorque @ 2009-07-29 17:03 UTC (permalink / raw)


generic
  type Discrete_Type is (<>);

package Saturation is

  type Saturated_Type is new Discrete_Type;

  function "+"
    (Left  : Saturated_Type;
     Right : Saturated_Type) return Saturated_Type;

end Saturation;

package body Saturation is

  function "+"
    (Left  : Saturated_Type;
     Right : Saturated_Type) return Saturated_Type
  is
    Temp_Left  : constant Discrete_Type := Discrete_Type (Left);
    Temp_Right : constant Discrete_Type := Discrete_Type (Right);
  begin
    if Temp_Left + Temp_Right > Discrete_Type'Last then
      return Saturated_Type (Discrete_Type'Last);
    end if;
    if Temp_Left + Temp_Right < Discrete_Type'First then
      return Saturated_Type (Discrete_Type'First);
    end if;

    return Saturated_Type (Temp_Left + Temp_Right);
  end "+";

end Saturation;

with Saturation;
with Ada.Text_IO;

procedure Main is
  type T is range 1 .. 10;

  package T_Saturated is new Saturation (T);
  package IO          renames Ada.Text_IO;
  package TIO         is new Ada.Text_IO.Integer_IO
(T_Saturated.Saturated_Type);

  use type T_Saturated.Saturated_Type;

  X : constant T_Saturated.Saturated_Type := 5;
  Y : constant T_Saturated.Saturated_Type := 9;
begin
  TIO.Put (X + Y); -- 10
  IO.New_Line;
end Main;

saturation.adb:10:18: there is no applicable operator "+" for type
"Discrete_Type" defined at saturation.ads:2
saturation.adb:13:18: there is no applicable operator "+" for type
"Discrete_Type" defined at saturation.ads:2
saturation.adb:17:38: there is no applicable operator "+" for type
"Discrete_Type" defined at saturation.ads:2

I'm afraid I'm not well versed in the rules regarding operator name
resolution...



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

* Re: Saturation arithmetic woes.
  2009-07-29 17:03 Saturation arithmetic woes xorque
@ 2009-07-29 17:13 ` Martin
  2009-07-29 18:14 ` Jeffrey R. Carter
  2009-07-29 19:14 ` Niklas Holsti
  2 siblings, 0 replies; 7+ messages in thread
From: Martin @ 2009-07-29 17:13 UTC (permalink / raw)


On Jul 29, 6:03 pm, xorque <xorquew...@googlemail.com> wrote:
> generic
>   type Discrete_Type is (<>);
>
> package Saturation is
>
>   type Saturated_Type is new Discrete_Type;
>
>   function "+"
>     (Left  : Saturated_Type;
>      Right : Saturated_Type) return Saturated_Type;
>
> end Saturation;
>
> package body Saturation is
>
>   function "+"
>     (Left  : Saturated_Type;
>      Right : Saturated_Type) return Saturated_Type
>   is
>     Temp_Left  : constant Discrete_Type := Discrete_Type (Left);
>     Temp_Right : constant Discrete_Type := Discrete_Type (Right);
>   begin
>     if Temp_Left + Temp_Right > Discrete_Type'Last then
>       return Saturated_Type (Discrete_Type'Last);
>     end if;
>     if Temp_Left + Temp_Right < Discrete_Type'First then
>       return Saturated_Type (Discrete_Type'First);
>     end if;
>
>     return Saturated_Type (Temp_Left + Temp_Right);
>   end "+";
>
> end Saturation;
>
> with Saturation;
> with Ada.Text_IO;
>
> procedure Main is
>   type T is range 1 .. 10;
>
>   package T_Saturated is new Saturation (T);
>   package IO          renames Ada.Text_IO;
>   package TIO         is new Ada.Text_IO.Integer_IO
> (T_Saturated.Saturated_Type);
>
>   use type T_Saturated.Saturated_Type;
>
>   X : constant T_Saturated.Saturated_Type := 5;
>   Y : constant T_Saturated.Saturated_Type := 9;
> begin
>   TIO.Put (X + Y); -- 10
>   IO.New_Line;
> end Main;
>
> saturation.adb:10:18: there is no applicable operator "+" for type
> "Discrete_Type" defined at saturation.ads:2
> saturation.adb:13:18: there is no applicable operator "+" for type
> "Discrete_Type" defined at saturation.ads:2
> saturation.adb:17:38: there is no applicable operator "+" for type
> "Discrete_Type" defined at saturation.ads:2
>
> I'm afraid I'm not well versed in the rules regarding operator name
> resolution...

generic
  type Discrete_Type is (<>);
  with function "+" (L, R : Discrete_Type) return Discrete_Type is <>;
package Saturation is

You need to provide a suitable "+" operator.

Cheers
-- Martin



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

* Re: Saturation arithmetic woes.
  2009-07-29 17:03 Saturation arithmetic woes xorque
  2009-07-29 17:13 ` Martin
@ 2009-07-29 18:14 ` Jeffrey R. Carter
  2009-07-29 19:14 ` Niklas Holsti
  2 siblings, 0 replies; 7+ messages in thread
From: Jeffrey R. Carter @ 2009-07-29 18:14 UTC (permalink / raw)


xorque wrote:
> generic
>   type Discrete_Type is (<>);

This may be any discrete type, including an enumeration type. Arithmetic is not 
defined for enumeration types, so you do not automatically get "+" for this. You 
either need to explicitly require a "+" function ("with function "+" ...), or 
use a generic formal type that does include "+": "is range <>" or "is mod <>".

-- 
Jeff Carter
"What I wouldn't give for a large sock with horse manure in it."
Annie Hall
42



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

* Re: Saturation arithmetic woes.
  2009-07-29 17:03 Saturation arithmetic woes xorque
  2009-07-29 17:13 ` Martin
  2009-07-29 18:14 ` Jeffrey R. Carter
@ 2009-07-29 19:14 ` Niklas Holsti
  2009-07-29 19:39   ` xorque
  2009-07-30  9:09   ` Jean-Pierre Rosen
  2 siblings, 2 replies; 7+ messages in thread
From: Niklas Holsti @ 2009-07-29 19:14 UTC (permalink / raw)


In addition to the replies from Martin and Dmitry regarding the absence 
of a "+" operator for Discrete_Type, I would like to comment on the 
logic of your saturated-"+":

xorque wrote:
> package body Saturation is
> 
>   function "+"
>     (Left  : Saturated_Type;
>      Right : Saturated_Type) return Saturated_Type
>   is
>     Temp_Left  : constant Discrete_Type := Discrete_Type (Left);
>     Temp_Right : constant Discrete_Type := Discrete_Type (Right);
>   begin
>     if Temp_Left + Temp_Right > Discrete_Type'Last then

Depending on the actual type associated with Discrete_Type (and assuming 
you use the predefined "+" for that type), you risk getting an overflow 
on Temp_Left + Temp_Right. If you have overflow checks disabled (as Gnat 
has by default) the sum may "wrap around" and seem to be less than 
Discrete_Type'Last, giving you the wrong result. If you have overflow 
checks enabled, you get a Constraint_Error instead of 
Discrete_Type'Last. Ditto for underflow and Discrete_Type'First.

One option is to have two formal types, one that defines the range for 
saturation (as Discrete_Type in your code) and another that is wide 
enough to compute the sum of Left and Right without under- or overflow.

If the other type is called Wide_Type, you could then replace Temp_Left 
and Temp_Right with

    Sum : constant Wide_Type := Wide_Type (Left) + Wide_Type (Right);

which would simplify your code a bit. Or just write one expression:

    return Discrete_Type (
       Wide_Type'Min (Wide_Type (Discrete_Type'Last),
       Wide_Type'Max (Wide_Type (Discrete_Type'First),
                      Wide_Type (Left) + Wide_Type (Right))));

That assumes that the formal Wide_Type is defined as an integer type, 
not just as any discrete type.

HTH,

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



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

* Re: Saturation arithmetic woes.
  2009-07-29 19:14 ` Niklas Holsti
@ 2009-07-29 19:39   ` xorque
  2009-07-30  9:09   ` Jean-Pierre Rosen
  1 sibling, 0 replies; 7+ messages in thread
From: xorque @ 2009-07-29 19:39 UTC (permalink / raw)


Unfortunate how dangerous this stuff is, really.

Thanks, all.



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

* Re: Saturation arithmetic woes.
  2009-07-29 19:14 ` Niklas Holsti
  2009-07-29 19:39   ` xorque
@ 2009-07-30  9:09   ` Jean-Pierre Rosen
  2009-07-30 11:51     ` Martin
  1 sibling, 1 reply; 7+ messages in thread
From: Jean-Pierre Rosen @ 2009-07-30  9:09 UTC (permalink / raw)


Niklas Holsti a �crit :
>> package body Saturation is
>>
>>   function "+"
>>     (Left  : Saturated_Type;
>>      Right : Saturated_Type) return Saturated_Type
>>   is
>>     Temp_Left  : constant Discrete_Type := Discrete_Type (Left);
>>     Temp_Right : constant Discrete_Type := Discrete_Type (Right);
>>   begin
>>     if Temp_Left + Temp_Right > Discrete_Type'Last then
> 
> Depending on the actual type associated with Discrete_Type (and assuming
> you use the predefined "+" for that type), you risk getting an overflow
> on Temp_Left + Temp_Right. If you have overflow checks disabled (as Gnat
> has by default) the sum may "wrap around" and seem to be less than
> Discrete_Type'Last, giving you the wrong result. If you have overflow
> checks enabled, you get a Constraint_Error instead of
> Discrete_Type'Last. Ditto for underflow and Discrete_Type'First.
> 
But of course, the simplest way to check is to write:
   if Temp_Left > Discrete_Type'Last - Temp_Right then

No overflow, ever! Of course, you need a "-" operator, and I assume it
is consistent with "+"...
-- 
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



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

* Re: Saturation arithmetic woes.
  2009-07-30  9:09   ` Jean-Pierre Rosen
@ 2009-07-30 11:51     ` Martin
  0 siblings, 0 replies; 7+ messages in thread
From: Martin @ 2009-07-30 11:51 UTC (permalink / raw)


On Jul 30, 10:09 am, Jean-Pierre Rosen <ro...@adalog.fr> wrote:
> Niklas Holsti a écrit :
>
> >> package body Saturation is
>
> >>   function "+"
> >>     (Left  : Saturated_Type;
> >>      Right : Saturated_Type) return Saturated_Type
> >>   is
> >>     Temp_Left  : constant Discrete_Type := Discrete_Type (Left);
> >>     Temp_Right : constant Discrete_Type := Discrete_Type (Right);
> >>   begin
> >>     if Temp_Left + Temp_Right > Discrete_Type'Last then
>
> > Depending on the actual type associated with Discrete_Type (and assuming
> > you use the predefined "+" for that type), you risk getting an overflow
> > on Temp_Left + Temp_Right. If you have overflow checks disabled (as Gnat
> > has by default) the sum may "wrap around" and seem to be less than
> > Discrete_Type'Last, giving you the wrong result. If you have overflow
> > checks enabled, you get a Constraint_Error instead of
> > Discrete_Type'Last. Ditto for underflow and Discrete_Type'First.
>
> But of course, the simplest way to check is to write:
>    if Temp_Left > Discrete_Type'Last - Temp_Right then
>
> No overflow, ever! Of course, you need a "-" operator, and I assume it
> is consistent with "+"...
> --
> ---------------------------------------------------------
>            J-P. Rosen (ro...@adalog.fr)
> Visit Adalog's web site athttp://www.adalog.fr

Temp_Right = -1 ?

Cheers
-- Martin




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

end of thread, other threads:[~2009-07-30 11:51 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-07-29 17:03 Saturation arithmetic woes xorque
2009-07-29 17:13 ` Martin
2009-07-29 18:14 ` Jeffrey R. Carter
2009-07-29 19:14 ` Niklas Holsti
2009-07-29 19:39   ` xorque
2009-07-30  9:09   ` Jean-Pierre Rosen
2009-07-30 11:51     ` Martin

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