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