Navigation: Main Page » Computer / Recreational / Science / Society / Television
 
Web N-N-A.com
         
Computer Groups Forum Index  »  Computer Programming Language - Ada  »  Saturation arithmetic woes.
Page 1 of 1    
Author Message
xorque
Posted: Wed Jul 29, 2009 5:03 pm
Guest
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...
Martin
Posted: Wed Jul 29, 2009 5:13 pm
Guest
On Jul 29, 6:03 pm, xorque <xorquew...@googlemail.com> wrote:
Quote:
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
xorque
Posted: Wed Jul 29, 2009 7:39 pm
Guest
Unfortunate how dangerous this stuff is, really.

Thanks, all.
Jeffrey R. Carter
Posted: Wed Jul 29, 2009 10:14 pm
Guest
xorque wrote:
Quote:
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
Niklas Holsti
Posted: Wed Jul 29, 2009 11:14 pm
Guest
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:
Quote:
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
. @ .
Jean-Pierre Rosen
Posted: Thu Jul 30, 2009 1:09 pm
Guest
Niklas Holsti a écrit :
Quote:
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
 
Page 1 of 1       All times are GMT
The time now is Thu Jun 20, 2013 2:32 am