Re: [libm] Implementations for rsqrt[fl].

Steve Kargl <[email protected]>
Newsgroups gmane.os.freebsd.devel.hackers
Message-ID <[email protected]>
On 5/7/26 22:55, Paul Zimmermann wrote:
>         Hi Steve,
> 
> I'll try to exercise your code when I return from vacation.

Thanks, I would appreciate someone else testing the code.

>
>> I submitted https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=295089
>> which contains an implementation of rsqrt[fl](x)=1/sqrt[fl](x).  These
>> appear in C23 7.12.7.9 and F.10.4.9 as well as IEEE-754 2008.  Under
>> IEEE-754, the functions are required(?)/recommended to be correctly
>> rounded in all rounding modes.  I have only checked round-to-nearest.
>> Using my testing franework, I see
>>
>> % ./tlibm rsqrt -fPED -x 0x1p-127 -X 0x1p126 -s 0
>> Interval tested for rsqrtf: [5.87747e-39,8.50706e+37]
>> 1000000 calls, 0.011062 secs, 0.01106 usecs/call
>>          ulp <= 0.5: 100.000% 2118123393 | 100.000% 2118123393
>> 0.5 <  ulp <  0.6:  0.000%     127 | 100.000% 2118123520
> 
> what does this 127 mean?

I haven't completely identified the cause of the 127
values that yield a not correctly rounded value.  My
testing framework is not set up to record each and
every value that does not yield 0.5 ULP.  If I
reduce the interval for exhaustive testing and change
the reported output I, for example, see

% ./tlibm rsqrt -fPE -x 8 -X 17
Interval tested for rsqrtf: [8,17]
       ulp <= 0.5: 100.000% 8912895 |  100.000% 8912895
0.5 < ulp <= 0.6:  0.000%       1 | 100.000% 8912896
Max ulp: 5.00000060e-01 at 1.59999981e+01, 0x1.fffffcp+3

Here, the rogue value is nearly 16, i.e., a power of 2.
The reference result is from mpfr_rec_sqrt() with the
precision of MPFR set to 4*24=96 bits.  I can increase
the precision, but the result does not change.

% ./tlibm rsqrt -fa 0x1.fffffcp3 -p 96
    x =  1.59999981e+01f, /* 0x417ffffe */
libm =  2.50000000e-01f, /* 0x3e800000 */
mpfr =  2.50000030e-01f, /* 0x3e800001 */
  ULP = 0.50000006
% ./tlibm rsqrt -fa 0x1.fffffcp3 -p 256
    x =  1.59999981e+01f, /* 0x417ffffe */
libm =  2.50000000e-01f, /* 0x3e800000 */
mpfr =  2.50000030e-01f, /* 0x3e800001 */
  ULP = 0.50000006

Note, I use strtof() to convert 0x1.fffffcp3
to the float value, and the reported mpfr
value is from use of mpfr_get_flt().  As x
is slightly less than 16, I'm incline to
accept MPFR as correct.

>> Max ulp: 0.500000 at 1.17549421e-38
>> %./tlibm rsqrt -fa  1.17549421e-38
>>      x =  1.17549421e-38f, /* 0x007fffff */
>> libm =  9.22337204e+18f, /* 0x5f000000 */
>> mpfr =  9.22337314e+18f, /* 0x5f000001 */
>>    ULP = 0.50000
> 
> it seems libm is not correctly rounded in this example.
> Do you plan to fix that?

If I knew how, yes. :-).

> 
> Side remark: the ULP value should be rounded up to 0.50001.
> 

The testing framework was setup to look at functions with
ULP's that exceed 0.5 by tenths.  For me, the 5th decimal
place is cosmetic.  For example,

% ./tlibm j0 -fPED -x 1 -X 2
Interval tested for j0f: [1,2]
       ulp <= 0.5: 64.738% 5430646 |  64.738% 5430646
0.5 < ulp <= 0.6:  8.870%  744080 |  73.608% 6174726
0.6 < ulp <= 0.7:  7.148%  599657 |  80.757% 6774383
0.7 < ulp <= 0.8:  5.760%  483165 |  86.517% 7257548
0.8 < ulp <= 0.9:  4.488%  376474 |  91.005% 7634022
0.9 < ulp <= 1.0:  3.110%  260863 |  94.114% 7894885
1.0 < ulp <= 1.5:  5.271%  442161 |  99.385% 8337046
1.5 < ulp <= 2.0:  0.481%   40354 |  99.866% 8377400
2.0 < ulp <= 3.0:  0.132%   11081 |  99.998% 8388481
3.0 < ulp       :  0.002%     127 | 100.000% 8388608
Max ulp: 3.66519642 at 1.99708652e+00, 0x1.ff4110p+0

-- 
steve
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.