inline half log2()

in include/half.hpp [3124:3155]


	inline half log2(half arg)
	{
	#if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
		return half(detail::binary, detail::float2half<half::round_style>(std::log2(detail::half2float<detail::internal_t>(arg.data_))));
	#else
		int abs = arg.data_ & 0x7FFF, exp = -15, s = 0;
		if(!abs)
			return half(detail::binary, detail::pole(0x8000));
		if(arg.data_ & 0x8000)
			return half(detail::binary, (arg.data_<=0xFC00) ? detail::invalid() : detail::signal(arg.data_));
		if(abs >= 0x7C00)
			return (abs==0x7C00) ? arg : half(detail::binary, detail::signal(arg.data_));
		if(abs == 0x3C00)
			return half(detail::binary, 0);
		for(; abs<0x400; abs<<=1,--exp) ;
		exp += (abs>>10);
		if(!(abs&0x3FF))
		{
			unsigned int value = static_cast<unsigned>(exp<0) << 15, m = std::abs(exp) << 6;
			for(exp=18; m<0x400; m<<=1,--exp) ;
			return half(detail::binary, value+(exp<<10)+m);
		}
		detail::uint32 ilog = exp, sign = detail::sign_mask(ilog), m = 
			(((ilog<<27)+(detail::log2(static_cast<detail::uint32>((abs&0x3FF)|0x400)<<20, 28)>>4))^sign) - sign;
		if(!m)
			return half(detail::binary, 0);
		for(exp=14; m<0x8000000 && exp; m<<=1,--exp) ;
		for(; m>0xFFFFFFF; m>>=1,++exp)
			s |= m & 1;
		return half(detail::binary, detail::fixed2half<half::round_style,27,false,false,true>(m, exp, sign&0x8000, s));
	#endif
	}