in include/half.hpp [3007:3050]
inline half expm1(half arg)
{
#if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
return half(detail::binary, detail::float2half<half::round_style>(std::expm1(detail::half2float<detail::internal_t>(arg.data_))));
#else
unsigned int abs = arg.data_ & 0x7FFF, sign = arg.data_ & 0x8000;
if(!abs)
return arg;
if(abs >= 0x7C00)
return half(detail::binary, (abs==0x7C00) ? (0x7C00+(sign>>1)) : detail::signal(arg.data_));
if(abs >= 0x4A00)
return half(detail::binary, (arg.data_&0x8000) ? detail::rounded<half::round_style,true>(0xBBFF, 1, 1) : detail::overflow<half::round_style>());
detail::uint32 m = detail::multiply64(static_cast<detail::uint32>((abs&0x3FF)+((abs>0x3FF)<<10))<<21, 0xB8AA3B29);
int e = (abs>>10) + (abs<=0x3FF), exp;
if(e < 14)
{
exp = 0;
m >>= 14 - e;
}
else
{
exp = m >> (45-e);
m = (m<<(e-14)) & 0x7FFFFFFF;
}
m = detail::exp2(m);
if(sign)
{
int s = 0;
if(m > 0x80000000)
{
++exp;
m = detail::divide64(0x80000000, m, s);
}
m = 0x80000000 - ((m>>exp)|((m&((static_cast<detail::uint32>(1)<<exp)-1))!=0)|s);
exp = 0;
}
else
m -= (exp<31) ? (0x80000000>>exp) : 1;
for(exp+=14; m<0x80000000 && exp; m<<=1,--exp) ;
if(exp > 29)
return half(detail::binary, detail::overflow<half::round_style>());
return half(detail::binary, detail::rounded<half::round_style,true>(sign+(exp<<10)+(m>>21), (m>>20)&1, (m&0xFFFFF)!=0));
#endif
}