in include/half.hpp [3336:3390]
inline half hypot(half x, half y, half z)
{
#ifdef HALF_ARITHMETIC_TYPE
detail::internal_t fx = detail::half2float<detail::internal_t>(x.data_), fy = detail::half2float<detail::internal_t>(y.data_), fz = detail::half2float<detail::internal_t>(z.data_);
return half(detail::binary, detail::float2half<half::round_style>(std::sqrt(fx*fx+fy*fy+fz*fz)));
#else
int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, absz = z.data_ & 0x7FFF, expx = 0, expy = 0, expz = 0;
if(!absx)
return hypot(y, z);
if(!absy)
return hypot(x, z);
if(!absz)
return hypot(x, y);
if(absx >= 0x7C00 || absy >= 0x7C00 || absz >= 0x7C00)
return half(detail::binary, (absx==0x7C00) ? detail::select(0x7C00, detail::select(y.data_, z.data_)) :
(absy==0x7C00) ? detail::select(0x7C00, detail::select(x.data_, z.data_)) :
(absz==0x7C00) ? detail::select(0x7C00, detail::select(x.data_, y.data_)) :
detail::signal(x.data_, y.data_, z.data_));
if(absz > absy)
std::swap(absy, absz);
if(absy > absx)
std::swap(absx, absy);
if(absz > absy)
std::swap(absy, absz);
for(; absx<0x400; absx<<=1,--expx) ;
for(; absy<0x400; absy<<=1,--expy) ;
for(; absz<0x400; absz<<=1,--expz) ;
detail::uint32 mx = (absx&0x3FF) | 0x400, my = (absy&0x3FF) | 0x400, mz = (absz&0x3FF) | 0x400;
mx *= mx;
my *= my;
mz *= mz;
int ix = mx >> 21, iy = my >> 21, iz = mz >> 21;
expx = 2*(expx+(absx>>10)) - 15 + ix;
expy = 2*(expy+(absy>>10)) - 15 + iy;
expz = 2*(expz+(absz>>10)) - 15 + iz;
mx <<= 10 - ix;
my <<= 10 - iy;
mz <<= 10 - iz;
int d = expy - expz;
mz = (d<30) ? ((mz>>d)|((mz&((static_cast<detail::uint32>(1)<<d)-1))!=0)) : 1;
my += mz;
if(my & 0x80000000)
{
my = (my>>1) | (my&1);
if(++expy > expx)
{
std::swap(mx, my);
std::swap(expx, expy);
}
}
d = expx - expy;
my = (d<30) ? ((my>>d)|((my&((static_cast<detail::uint32>(1)<<d)-1))!=0)) : 1;
return half(detail::binary, detail::hypot_post<half::round_style>(mx+my, expx));
#endif
}