comp.lang.ada
 help / color / mirror / Atom feed
From: Natasha Kerensikova <lithiumcat@gmail.com>
Subject: Re: How to round to the nearest fixed-point value?
Date: Sun, 26 Jan 2014 14:19:11 +0000 (UTC)
Date: 2014-01-26T14:19:11+00:00	[thread overview]
Message-ID: <slrnlea6aj.1lme.lithiumcat@sigil.instinctive.eu> (raw)
In-Reply-To: lbupic$4pd$1@loke.gir.dk

On 2014-01-24, Randy Brukardt <randy@rrsoftware.com> wrote:
> "Natasha Kerensikova" <lithiumcat@gmail.com> wrote in message 
>> In case anyone is interested, the following rewrite works around the
>> problem:
>>
>>   function Convert (Value : High) return Low is
>>   begin
>>      return Low'Round (Value * 1.0);
>>   end Convert;
>
> I believe the above should be illegal - but in any case, it's not clear from 
> the RM what this means.
>
> The only multiply operations available for fixed point types either have one 
> operand that is an integer (not the case above), or produce a 
> Universal_Fixed result. 4.5.5(19.1/2) requires that the result be used in a 
> context where the result type is identified, and specifically disallows the 
> result from being Universal_Fixed.
>
> The type of the operand of 'Round is Universal_Real. This appears to meet 
> the letter of the rule, but not the intent (which is that the expected type 
> determine the scaling and respresentation for the result).

Could it be somehow be "made legal" by G.2.3(4), merging "*" and
Low'Round into a single operation? (sounds a bit weird though, that
would mean an optional annex affecting legality)

This gets me worried, because in the "real" application where I
encountered this, Low'Round (Value) is one possibility of a case
statement, and all others are like Low'Round (Value * decimal_literal)
most of those literals being more precise than what can be handled by
High or Low (e.g. 6.55957). I expected the math to be handled properly,
but maybe I should look a bit closer at those cases too.

Is there a better way of expressing it?

Maybe something along the lines of
Low'Round (Value * High'(6.559) + (Value / 1000) * High'(0.57))
but with better thought on rounding.
However I would expect the compiler to be better than me at coming up
with a formula to accurately compute that.

On a site note, using Low'Round (Value * 1) behave in the same (wrong?)
way as Low'Round (Value).

>> I would have thought that the optimizer would have quickly brought both
>> version to the same generated code, but from -O0 to -O3 I get the
>> correct rounding with the latter but not with the former.
>
> No, the result of the operand here is Universal_Real. I believe the language 
> says that runtime universal values are evaluated using the largest possible 
> numeric type; in this case, that would be a large float type. It's very 
> difficult to optimize out float operations (because of precision issues - 
> you have to be very careful that the precision of the result is the same 
> after optimization), so it probably can't be changed. So you're getting 
> vastly different code.

Funnily, both versions lead to very similar code in GNAT internal
ada-ish language (output by -gnatD):

Low'Round (Value) yields:
T2b : constant lib__TlowB := lib__TlowB?({lib__TlowB?(value #{/} 1.0E-2)});

Low'Round (Value * 1.0) yeilds:
T2b : constant lib__TlowB := lib__TlowB?({lib__TlowB?(value #@{/} 1.0E-2)});

As far as 64-bit intel assembly code goes, it indeed looks vastly
different, but it involves only integer arithmetic, without any obvious
bound restriction.



Thanks for your help,
Natasha

  parent reply	other threads:[~2014-01-26 14:19 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-22 16:48 How to round to the nearest fixed-point value? Natasha Kerensikova
2014-01-22 17:53 ` G.B.
2014-01-22 22:26   ` adambeneschan
2014-01-23  9:21     ` Georg Bauhaus
2014-01-22 22:45 ` adambeneschan
2014-01-23  5:29   ` J-P. Rosen
2014-01-23  7:00     ` Natasha Kerensikova
2014-01-23  9:42     ` Georg Bauhaus
2014-01-23  7:02   ` Natasha Kerensikova
2014-01-23 16:41     ` adambeneschan
2014-01-24  9:58 ` Natasha Kerensikova
2014-01-24 22:30   ` Randy Brukardt
2014-01-24 22:47     ` Randy Brukardt
2014-01-26 14:19     ` Natasha Kerensikova [this message]
2014-01-28 23:43       ` Randy Brukardt
replies disabled

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