|
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... |
|
|
| Back to top |
|
| 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 |
|
|
| Back to top |
|
| xorque |
Posted: Wed Jul 29, 2009 7:39 pm |
|
|
|
Guest
|
Unfortunate how dangerous this stuff is, really.
Thanks, all. |
|
|
| Back to top |
|
| 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 |
|
|
| Back to top |
|
| 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
. @ . |
|
|
| Back to top |
|
| 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 |
|
|
| Back to top |
|
| |