Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <67395818-5d95-f74f-5c50-435fc157dda@esi.com.au>
Date: Wed, 19 Jun 2024 18:17:21 +1000 (AEST)
From: Damian McGuckin <damianm@....com.au>
To: MUSL <musl@...ts.openwall.com>
Subject: Re: roundf() (and round(), and ...)


On Tue, 18 Jun 2024, Szabolcs Nagy wrote:

>> Also, I have not used anything except for the now default 
>> FLT_EVAL_METHOD so I need guidance as to where to use 'float_t'. 
>> However, the only place where such arithmetic (here) might be affected 
>> is the expression 'a + a' which is exact anyway so I think it is 
>> irrelevant.
>
> note that it is unspecified if your algorithm raises inexact or not.
> (iirc musl asm implementations don't raise inexact, the c code does,
> c23 now requires no inexact which i guess is what you tried to follow,

Yes.

> but that is hard to do in c)

Yes, well for certain (and across multiple architectures).

> otherwise i think your style is fine, but i added some comments.
>
> FLT_EVAL_METHOD is not relevant for this code.

That was my placeholder as in 'Memo to Self'.

I have not used anything other than 'FLT_EVAL_METHOD=0' for decades so
I am likely to not handle the other scenarios properly, i.e. using the
types 'float_t' and 'double_t' as appropriate. So I am worried that my
code is buggy in that context.

> benchmark data may be useful (or code size e.g. on a soft-float target)
> because that may be a valid justification to use this implementation.

It is much less assembler size on a hard-float target.

I have no experience on a soft-float target.

In my testing on X86-64, it is faster than either existing MUSL code or 
GLIBM, but not as fast as assembler using 'ROUNDSS/ROUNDSD'.  Not that 
these routines are going to be performance killers.

> i used to use explicit unions then switched to helper function asuint(x)
> because i found that a bit clearer and compiler optimizes it just fine.
> and some ppl complained that memcpy is more correct than union, so it is
> better hidden away behind a helper function if somebody wants to switch.

I initially wrote these routines using these helper functions but went 
back to unions because I had some issues. Unions are the only things which 
work at compile-time.

But I am happy to go back to helper function. I just redid them routines 
and I notices that they read quite well. They also map nicely into things 
like Rust's or Chapel's 'transmute' feature although they work at compile 
time and these helper functions do not.

I had also tried implementing these routines with <ieee754.h> from Linux 
to see how well that worked. I have very little experience with the use of 
'memcpy" as this also has problems at compile time.

> nowadays i'd probably write
>
>  if (asuint(a) >> 23 < asuint(0x1p23f) >> 23)

I wish it was asuint32 rather than asuint() but maybe I am too picky.

I would prefer to define the bias 'b' and precision 'p' and write it as

 	if ((asuint(a) >> (p - 1)) < b + (p - 1))

But I was worried that would be a change too far. Also, I use different 
languages in a given week so I probably us more coercions (or casts) and 
parentheses than MUSL prefers for C.

>>         /*
>>          * this should achieve rounding to nearest with any
>>          * ties (half-way cases) being rounded away-from-zero.
>>          * (is it wise to use uint32_t instead of int32_t here?)
>>          */
>>         const uint32_t rf = ((uint32_t) (a + a)) - (uint32_t) a;
>>
>>         x = (r.f = (float) rf, r._f |= s, r.f);
>
> it is isa dependent if int32_t or uint32_t is better, but i'd
> expect signed convert is more widely supported than unsigned.

Thanks for the advice - I am just testing that change now - Damian

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.