![]() |
|
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.