Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 9 Mar 2017 12:14:09 -0800
From:      Steve Kargl <sgk@troutmask.apl.washington.edu>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        freebsd-numerics@freebsd.org
Subject:   Re: Bit twiddling question
Message-ID:  <20170309201409.GA37219@troutmask.apl.washington.edu>
In-Reply-To: <20170309195134.GA36213@troutmask.apl.washington.edu>
References:  <20170308202417.GA23103@troutmask.apl.washington.edu> <20170309173152.F1269@besplex.bde.org> <20170309075236.GA30199@troutmask.apl.washington.edu> <20170309152307.GA32781@troutmask.apl.washington.edu> <20170310025417.U3723@besplex.bde.org> <20170309195134.GA36213@troutmask.apl.washington.edu>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, Mar 09, 2017 at 11:51:34AM -0800, Steve Kargl wrote:
> On Fri, Mar 10, 2017 at 05:02:13AM +1100, Bruce Evans wrote:
> > >
> > > Something similar can be applied to ld128, but reduction may take
> > > two rounds (ie., a comparison with UINT64_MAX and then UINT32_MAX).
> > 
> > I don't like that much.  The 0x1p52 magic is tricky and probably buggy.
> > s_rint.c uses the same magic but needs many complications to avoid
> > double rounding.
> 
> Yep. Seems to have some issue.  From my working copy of s_sinpif(x),
> I tried
> 
> #if 0
> 		ix = (uint32_t)ax;
> 		a = ax == ix ? zero : __compute_sinpif(ax - ix);
> 		if (ix & 1) ax = -ax;
> 		return ((hx & 0x80000000) ? -ax : ax);
> #else
> 		volatile float vx;
> 		float y;
> 		vx = ax + 0x1p23F;
> 		y = vx - 0x1p23F;
> 		ix = (uint32_t)y;
> 		ax = ax == y ? zero : __compute_sinpif(ax - ix);
> 		if (ix & 1) ax = -ax;
> 		return ((hx & 0x80000000) ? -ax : ax);
> #endif	
> 
> My max ULP went from 0.5 to 0.50398505 for exhaustive testing
> in the interval [1,100].  If I grab the worse case x and use the
> '#if 1' code, I see
> 
> ./testf -S -a 1.50121641e+00f
> a =  1.50121641e+00f, /* 0x3fc027dc */
> sinpif(a) = -9.99992669e-01f, /* 0xbf7fff85 */
> sin(pi*a) = -9.99992669e-01f, /* 0xbf7fff85 */  MPFR 96-bits rounded 24-bits.
> ULP: 0.49601495
> 
> The '#if 0' code gives
> 
>  ./testf -S -a 1.50121641e+00f
> a =  1.50121641e+00f, /* 0x3fc027dc */
> sinpif(a) = -9.99992728e-01f, /* 0xbf7fff86 */
> sin(pi*a) = -9.99992669e-01f, /* 0xbf7fff85 */  MPFR 96-bits rounded 24-bits.
> ULP: 0.50398505
> 

Certainly looks like a double rounding issue.  An instrumented copy
of the code shows that y = 2 instead of 1 in the above.

a =  1.50121641e+00f, /* 0x3fc027dc */
1.50121641e+00
2.00000000e+00
sinpif(a) = -9.99992728e-01f, /* 0xbf7fff86 */
sin(pi*a) = -9.99992669e-01f, /* 0xbf7fff85 */
ULP: 0.50398505

-- 
Steve
20161221 https://www.youtube.com/watch?v=IbCHE-hONow



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20170309201409.GA37219>