Is there a correct constant-expression, in terms of a float, for its msb?

后端 未结 3 613
孤城傲影
孤城傲影 2021-01-21 14:45

The problem: given a floating point constant expression, can we write a macro that evaluates to a constant expression whose value is a power of two equal to the most significant

3条回答
  •  庸人自扰
    2021-01-21 15:06

    Here is code for finding the ULP. It was inspired by algorithm 3.5 in Accurate floating-Point Summation by Siegfriend M. Rump, Takeshi Ogita, and Shin’ichi Oishi (which calculates 2⌈log2 |p|⌉):

    double ULP(double q)
    {
        // SmallestPositive is the smallest positive floating-point number.
        static const double SmallestPositive = DBL_EPSILON * DBL_MIN;
    
        /*  Scale is .75 ULP, so multiplying it by any significand in [1, 2) yields
            something in [.75 ULP, 1.5 ULP) (even with rounding).
        */
        static const double Scale = 0.75 * DBL_EPSILON;
    
        q = fabs(q);
    
        // Handle denormals, and get the lowest normal exponent as a bonus.
        if (q < 2*DBL_MIN)
            return SmallestPositive;
    
        /*  Subtract from q something more than .5 ULP but less than 1.5 ULP.  That
            must produce q - 1 ULP.  Then subtract that from q, and we get 1 ULP.
    
            The significand 1 is of particular interest.  We subtract .75 ULP from
            q, which is midway between the greatest two floating-point numbers less
            than q.  Since we round to even, the lesser one is selected, which is
            less than q by 1 ULP of q, although 2 ULP of itself.
        */
        return q - (q - q * Scale);
    }
    

    The fabs and if can be replaced with ?:.

    For reference, the 2⌈log2 |p|⌉ algorithm is:

    q = p / FLT_EPSILON
    L = |(q+p) - q|
    if L = 0
        L = |p|
    

提交回复
热议问题