inline half pow()

in include/half.hpp [3402:3449]


	inline half pow(half x, half y)
	{
	#ifdef HALF_ARITHMETIC_TYPE
		return half(detail::binary, detail::float2half<half::round_style>(std::pow(detail::half2float<detail::internal_t>(x.data_), detail::half2float<detail::internal_t>(y.data_))));
	#else
		int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, exp = -15;
		if(!absy || x.data_ == 0x3C00)
			return half(detail::binary, detail::select(0x3C00, (x.data_==0x3C00) ? y.data_ : x.data_));
		bool is_int = absy >= 0x6400 || (absy>=0x3C00 && !(absy&((1<<(25-(absy>>10)))-1)));
		unsigned int sign = x.data_ & (static_cast<unsigned>((absy<0x6800)&&is_int&&((absy>>(25-(absy>>10)))&1))<<15);
		if(absx >= 0x7C00 || absy >= 0x7C00)
			return half(detail::binary,	(absx>0x7C00 || absy>0x7C00) ? detail::signal(x.data_, y.data_) :
										(absy==0x7C00) ? ((absx==0x3C00) ? 0x3C00 : (!absx && y.data_==0xFC00) ? detail::pole() :
										(0x7C00&-((y.data_>>15)^(absx>0x3C00)))) : (sign|(0x7C00&((y.data_>>15)-1U))));
		if(!absx)
			return half(detail::binary, (y.data_&0x8000) ? detail::pole(sign) : sign);
		if((x.data_&0x8000) && !is_int)
			return half(detail::binary, detail::invalid());
		if(x.data_ == 0xBC00)
			return half(detail::binary, sign|0x3C00);
		if(y.data_ == 0x3800)
			return sqrt(x);
		if(y.data_ == 0x3C00)
			return half(detail::binary, detail::check_underflow(x.data_));
		if(y.data_ == 0x4000)
			return x * x;
		for(; absx<0x400; absx<<=1,--exp) ;
		detail::uint32 ilog = exp + (absx>>10), msign = detail::sign_mask(ilog), f, m = 
			(((ilog<<27)+((detail::log2(static_cast<detail::uint32>((absx&0x3FF)|0x400)<<20)+8)>>4))^msign) - msign;
		for(exp=-11; m<0x80000000; m<<=1,--exp) ;
		for(; absy<0x400; absy<<=1,--exp) ;
		m = detail::multiply64(m, static_cast<detail::uint32>((absy&0x3FF)|0x400)<<21);
		int i = m >> 31;
		exp += (absy>>10) + i;
		m <<= 1 - i;
		if(exp < 0)
		{
			f = m >> -exp;
			exp = 0;
		}
		else
		{
			f = (m<<exp) & 0x7FFFFFFF;
			exp = m >> (31-exp);
		}
		return half(detail::binary, detail::exp2_post<half::round_style,false>(detail::exp2(f), exp, ((msign&1)^(y.data_>>15))!=0, sign));
	#endif
	}