MCPcopy Create free account
hub / github.com/apache/singa / fma

Function fma

include/half.hpp:2808–2869  ·  view source on GitHub ↗

Fused multiply add. This function is exact to rounding for all rounding modes. See also:** Documentation for [std::fma](https://en.cppreference.com/w/cpp/numeric/math/fma). \param x first operand \param y second operand \param z third operand \return ( \a x * \a y ) + \a z rounded as one operation. \exception FE_INVALID according to operator*() and operator+() unless any argument is a quiet NaN a

Source from the content-addressed store, hash-verified

2806 /// \exception FE_INVALID according to operator*() and operator+() unless any argument is a quiet NaN and no argument is a signaling NaN
2807 /// \exception FE_OVERFLOW, ...UNDERFLOW, ...INEXACT according to rounding the final addition
2808 inline half fma(half x, half y, half z)
2809 {
2810 #ifdef HALF_ARITHMETIC_TYPE
2811 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_);
2812 #if HALF_ENABLE_CPP11_CMATH && FP_FAST_FMA
2813 return half(detail::binary, detail::float2half<half::round_style>(std::fma(fx, fy, fz)));
2814 #else
2815 return half(detail::binary, detail::float2half<half::round_style>(fx*fy+fz));
2816 #endif
2817 #else
2818 int absx = x.data_ & 0x7FFF, absy = y.data_ & 0x7FFF, absz = z.data_ & 0x7FFF, exp = -15;
2819 unsigned int sign = (x.data_^y.data_) & 0x8000;
2820 bool sub = ((sign^z.data_)&0x8000) != 0;
2821 if(absx >= 0x7C00 || absy >= 0x7C00 || absz >= 0x7C00)
2822 return (absx>0x7C00 || absy>0x7C00 || absz>0x7C00) ? half(detail::binary, detail::signal(x.data_, y.data_, z.data_)) :
2823 (absx==0x7C00) ? half(detail::binary, (!absy || (sub && absz==0x7C00)) ? detail::invalid() : (sign|0x7C00)) :
2824 (absy==0x7C00) ? half(detail::binary, (!absx || (sub && absz==0x7C00)) ? detail::invalid() : (sign|0x7C00)) : z;
2825 if(!absx || !absy)
2826 return absz ? z : half(detail::binary, (half::round_style==std::round_toward_neg_infinity) ? (z.data_|sign) : (z.data_&sign));
2827 for(; absx<0x400; absx<<=1,--exp) ;
2828 for(; absy<0x400; absy<<=1,--exp) ;
2829 detail::uint32 m = static_cast<detail::uint32>((absx&0x3FF)|0x400) * static_cast<detail::uint32>((absy&0x3FF)|0x400);
2830 int i = m >> 21;
2831 exp += (absx>>10) + (absy>>10) + i;
2832 m <<= 3 - i;
2833 if(absz)
2834 {
2835 int expz = 0;
2836 for(; absz<0x400; absz<<=1,--expz) ;
2837 expz += absz >> 10;
2838 detail::uint32 mz = static_cast<detail::uint32>((absz&0x3FF)|0x400) << 13;
2839 if(expz > exp || (expz == exp && mz > m))
2840 {
2841 std::swap(m, mz);
2842 std::swap(exp, expz);
2843 if(sub)
2844 sign = z.data_ & 0x8000;
2845 }
2846 int d = exp - expz;
2847 mz = (d<23) ? ((mz>>d)|((mz&((static_cast<detail::uint32>(1)<<d)-1))!=0)) : 1;
2848 if(sub)
2849 {
2850 m = m - mz;
2851 if(!m)
2852 return half(detail::binary, static_cast<unsigned>(half::round_style==std::round_toward_neg_infinity)<<15);
2853 for(; m<0x800000; m<<=1,--exp) ;
2854 }
2855 else
2856 {
2857 m += mz;
2858 i = m >> 24;
2859 m = (m>>i) | (m&i);
2860 exp += i;
2861 }
2862 }
2863 if(exp > 30)
2864 return half(detail::binary, detail::overflow<half::round_style>(sign));
2865 else if(exp < -10)

Callers

nothing calls this directly

Calls 3

halfClass · 0.85
signalFunction · 0.85
invalidFunction · 0.85

Tested by

no test coverage detected