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
next prev 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