[Cfp-interest] implementing tgmath for constant rounding modes
Joel C. Salomon
joelcsalomon at gmail.com
Thu Jun 7 17:43:58 PDT 2012
On 06/07/2012 03:48 PM, Fred J. Tydeman wrote:
>
> On Sat, 2 Jun 2012 08:22:55 -0700 Jim Thomas wrote:
>>
>> Take the example of cbrt. <math.h> could have
>>
>> #define cbrt(x) __roundwise_cbrt(x)
>>
>> Then the translator would have to keep track of whether a constant rounding mode is in effect at
>> each call site for __roundwise_cbrt and, if so, what the rounding direction is.
>
> So, in effect, __roundwise_cbrt becomes a special keyword/token/symbol to the compiler.
> And the same for all the other math functions (that is a lot of names to treat special).
<snip>
> Would it be better to add just one new attribute, eg,
> #define cbrt(x) [[ROUNDWISE]] cbrt(x)
> that would be the same for all compilers?
A question about implementing this, at the library level: How is the
static mode being passed to the function we're calling?
This can be faked by setting the dynamic rounding mode to the
currently-selected static mode before the function call, but this adds
the overhead of setting & checking the dynamic mode. Is that at all
significant?
E.g., assume the following declarations of highly-efficient,
1ulp-accurate functions:
double __cbrt_round_downward(double),
__cbrt_round_tonearest(double),
__cbrt_round_towardzero(double),
__cbrt_round_upward(double);
The following then becomes possible:
inline double cbrt(double x) {
#pragma STDC FENV_ACCESS ON
switch (fegetround()) {
case FE_DOWNWARD: __cbrt_rnd_downward(x); break;
case FE_TONEAREST: __cbrt_rnd_tonearest(x); break;
case FE_TOWARDZERO: __cbrt_rnd_towardzero(x); break;
case FE_UPWARD: __cbrt_rnd_upward(x); break;
}
}
Apply the appropriate compiler magic:
#define cbrt(x) [[ROUNDWISE]] cbrt(x)
and we then have this use:
{
#pragma STDC FENV_ROUND FE_DOWNWARD
/* stuff */
x = cbrt(8.0);
/* more stuff */
}
which the compiler turns into
{
#pragma STDC FENV_ROUND FE_DOWNWARD
/* stuff */
#pragma STDC FENV_ROUND FE_DYNAMIC
fesetround(FE_DOWNWARD);
x = cbrt(8.0);
#pragma STDC FENV_ROUND FE_DOWNWARD
/* more stuff */
}
On a system optimized for static rounding modes, this seems to me
somewhat odd -- but it can work. (Or is it not odd at all?)
An alternative (which I proposed in my email of April 19, see
<http://mailman.oakapple.net/pipermail/cfp-interest/2012-April/000354.html>)
is a compiler intrinsic that behaves like fegetround(), but at compile
time; this requires less magic insertion of fesetround().
--Joel
More information about the Cfp-interest
mailing list