comp.lang.ada
 help / color / mirror / Atom feed
From: "Robert I. Eachus" <rieachus@comcast.net>
Subject: Re: Newbie Question: Casting Issue
Date: Wed, 05 May 2004 19:07:06 -0400
Date: 2004-05-05T19:07:06-04:00	[thread overview]
Message-ID: <TMKdnQkt1-IG7gTdRVn-jA@comcast.com> (raw)
In-Reply-To: <c77nbu$5f0$1@e3k.asi.ansaldo.it>

(In what follows I used capitalization consistant with the original 
poster's.  If that bothers anyone, tough. ;-)

Davide wrote:
> I need your help, please, to solve a casting issue.
> 
> I have an Ada operation, say FLOAT_POINT_OP, which returns a floating point
> type, say: FLOAT_POINT_TYPE is digits 9.
> 
> The result of this operation must be assigned to a fixed point type
> variable, say: FIX_POINT_TYPE is delta 0.0625 range -10.0 .. 36.5.
> 
> I cannot use Ada exceptions and I must ensure that the assignment will not
> throw a type constraint error at run-time.
> Then I perform this check:
> 
> FLOAT_VAR >= FLOAT_POINT_TYPE(FIX_POINT_TYPE'FIRST)
> and
> FLOAT_VAR <= FLOAT_POINT_TYPE(FIX_POINT_TYPE'LAST)
> 
> (where FLOAT_VAR is the floating point type result returned by
> FLOAT_POINT_OP)
> 
> and if the check passes then I perform the "crucial" assignment:
> 
> FIX_VAR := FLOAT_VAR.
> 
> Do you think it works fine?

Probably, in this case.

> Have you better solutions?

Yes.

> My worry is about the FLOAT_POINT_TYPE(FIX_POINT_TYPE'FIRST) casting. In
> particular about the possibility of an introduction of additional decimal
> digits, after the last decimal digit of the FIX_POINT_TYPE bounds. I think
> that everything should work if the casting preserves at least the number of
> decimal digits specified for delta (in this case 4 digits, being delta =
> 0.0625) adding possible digits after the fourth. There is some Ada standard
> directive about that?

Oh,yes.  Lots of them.  First, RM 3.5.9(8): "The set of values of a 
fixed point type comprise the integral multiples of a number called the 
small of the type.  For a type defined by an 
ordinary_fixed_point_definition (an ordinary fixed point type), the 
small may be specified by an attribute_definition_clause (see 13.3); if 
so specified, it shall be no greater than the delta of the type. If not 
specified, the small of an ordinary fixed point type is an 
implementation-defined power of two less than or equal to the delta."

If you are concerned about representable values, which you should be in 
this case, you will want to add an attribute_definition_clause for 
FIX_POINT_TYPE'SMALL.   The real reason for doing this is portability. 
If you fix 'SMALL to be the same value as 'DELTA, then you control 
whether or not there can be representable values of the type that are 
not multiples of 'SMALL.

But there is more: RM 3.5.9(13) "An ordinary_fixed_point_definition 
defines an ordinary fixed point type whose base range includes at least 
all multiples of small that are between the bounds specified in the 
real_range_specification. The base range of the type does not 
necessarily include the specified bounds themselves."

Yes, that does say that 'FIRST and 'LAST need not be representable 
values of the fixed-point type, and this is deliberate.  However, 'FIRST 
and 'LAST are within 'SMALL of some representable value of the type. 
(Whew!)  Finally, if you check RM 3.5 you will find that 'FIRST and 
'LAST are values of the type.  (So even if an end-point of the range of 
a fixed point type is a multiple of 'SMALL that is not a representable 
value of the type, assigning in your example:

FIX_VAR := FIX_POINT_TYPE'FIRST; -- or
FIX_VAR := FIX_POINT_TYPE'LAST;

will always work.  The problem that can occur is that you are using 
equality tests on floating point numbers.  It is possible with some 
implementations that the value you are testing compares equal to say 
FIX_POINT_TYPE'LAST, but in fact is slightly larger than that value. 
Even if FIX_POINT_TYPE'LAST is a model number of FLOAT_POINT_TYPE, a 
value of type FLOAT_POINT_TYPE, say in an 80-bit register will be 
slightly larger than FIX_POINT_TYPE'LAST but compare equal to it.  Then 
the language does not gaurantee that the conversion of that value to 
FIX_POINT_TYPE will not raise Constraint_Error.

The easy way to fix that is to test:

if FLOAT_VAR > FLOAT_POINT_TYPE(FIX_POINT_TYPE'FIRST)
  and FLOAT_VAR < FLOAT_POINT_TYPE(FIX_POINT_TYPE'LAST)
then
   FIX_VAR := FLOAT_VAR.
else
   ...

What if you want values of -10.0 and 36.5 to convert cleanly?  Easy 
enough, choose the bounds of FIX_POINT_TYPE so that FIX_POINT_TYPE'FIRST 
is less than -10.0, and FIX_POINT_TYPE'LAST is greater than 36.5.  In 
your example, change your declaration to, say:

type FIX_POINT_TYPE is delta 0.0625 range -10.0001 .. 36.5001;
for FIX_POINT_TYPE'SMALL use 0.0625;

Notice, of course, that the values in the type declaration will 
determine the range of values that will be converted to FIX_POINT_TYPE, 
even though after the conversion, all of the values will be multiples of 
FIX_POINT_TYPE'SMALL.  I can't tell you how to deal with that issue, you 
will have to look at your requirements.  Yes sometimes those issues are 
a pain, but getting them right is defined by the problem, not by Ada.

-- 

                                           Robert I. Eachus

"The terrorist enemy holds no territory, defends no population, is 
unconstrained by rules of warfare, and respects no law of morality. Such 
an enemy cannot be deterred, contained, appeased or negotiated with. It 
can only be destroyed--and that, ladies and gentlemen, is the business 
at hand."  -- Dick Cheney




  parent reply	other threads:[~2004-05-05 23:07 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-05-04  9:22 Newbie Question: Casting Issue Davide
2004-05-04 17:40 ` Jeffrey Carter
2004-05-05 23:07 ` Robert I. Eachus [this message]
2004-05-05 23:25   ` Robert I. Eachus
2004-05-07  7:10     ` Davide
replies disabled

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