jk-jeon / dragonbox

Reference implementation of Dragonbox in C++
Apache License 2.0
588 stars 37 forks source link

fix bugs in compute_right_closed_directed #22

Closed yotann closed 2 years ago

yotann commented 2 years ago

These bugs only affect the rounding modes toward_plus_infinity, toward_minus_infinity, and away_from_zero.

In the paper, Algorithm A.1 step 7 currently says:

x = (fc - 1/2) * 2^e * 10^k = (2*fc - 1) * 2^{e-1} * 10^k for the normal interval case

x = (fc - 1/4) * 2^e * 10^k = (4*fc - 1) * 2^{e-2} * 10^k for the shorter interval case

These are incorrect for right-closed directed rounding, which uses w-; see the definition of w- in section 2.2. The correct values are:

x = (fc - 1) * 2^e * 10^k = (2*fc - 2) * 2^{e-1} * 10^k for the normal interval case

x = (fc - 1/2) * 2^e * 10^k = (2*fc - 1) * 2^{e-1} * 10^k for the shorter interval case

Test program

#include <iomanip>
#include <iostream>
#include <limits>

#include "dragonbox/dragonbox.h"

template<typename Float>
static void away_from_zero(Float f) {
    auto v = jkj::dragonbox::to_decimal(f, jkj::dragonbox::policy::decimal_to_binary_rounding::away_from_zero);
    std::cout << std::scientific;
    std::cout << std::setprecision(std::numeric_limits<Float>::digits10 + 5);
    std::cout << f << ": " << v.significand << "E" << v.exponent << "\n";
}

int main(int argc, char **argv) {
    away_from_zero(5e-324);
    away_from_zero(3.33e-321);
    away_from_zero(3.335e-321);
    away_from_zero(1.547425049106725e+26);
    away_from_zero(1.5474250491067252e+26);
    away_from_zero(35184369991680.0f);
    away_from_zero(35184372088832.0f);
    return 0;
}

Incorrect output

4.94065645841246544177e-324: 0E-307
3.33000245297000170775e-321: 333E-323
3.33494310942841417319e-321: 333E-323
1.54742504910672500003e+26: 1547425049106725E11
1.54742504910672517183e+26: 1547425049106725E11
3.51843699917e+13: 35184369E6
3.51843720888e+13: 35184372E6

Fixed output

4.94065645841246544177e-324: 4E-324
3.33000245297000170775e-321: 333E-323
3.33494310942841417319e-321: 3334E-324
1.54742504910672500003e+26: 1547425049106725E11
1.54742504910672517183e+26: 15474250491067251E10
3.51843699917e+13: 35184369E6
3.51843720888e+13: 3518437E7
jk-jeon commented 2 years ago

Thanks a lot for catching this!