ctarbi.de - dag64 · dag encoding · 64bit

Denormals Are Gone encoding for IEEE754 doubles, because they, the subnormals, are not good anyway.

This is the product of a detailed observation of the IEEE754 format.

Remapped Ranges

            zero -> 0x0000000000000000 -> 0.000000e+00 (int) 0
               1 -> 0x0000000000000001 -> 1.000000e+00 (int) 1
        2^51 - 1 -> 0x0007ffffffffffff -> 2.251800e+15 (int) 2251799813685247
        2^52 - 1 -> 0x000fffffffffffff -> -1.000000e+00 (int) 4503599627370495 or -1
        custom 1 -> 0x0011111111111111 -> -nan (custom 1) 0x1111111111111
(+) first normal -> 0x0020000000000000 -> 2.225074e-308 (normal)
 (+) last normal -> 0x7fffffffffffffff -> 1.797693e+308 (normal)
(-) first normal -> 0x8000000000000000 -> -2.225074e-308 (normal)
 (-) last normal -> 0xffdfffffffffffff -> -1.797693e+308 (normal)
        custom 2 -> 0xffe2222222222222 -> -nan (custom 2) 0x2222222222222
            dnan -> 0xfff0000000000000 -> -nan (special 0: -nan)
            +inf -> 0xfff0000000000001 -> inf (special 1: inf)
            -inf -> 0xfff0000000000002 -> -inf (special 2: -inf)

Glossary

Comparing against original format

Features

Key Functions

dag64

void
dag64(void)
{
    show_long_bits("zero", create_double(0, 0, 0, 0));
    show_long_bits("1", create_double(0, 0, 0, 1));
    show_long_bits("2^51 - 1", create_double(0, 0, 0x7ffff, 0xffffffff));
    show_long_bits("2^52 - 1", create_double(0, 0, 0xfffff, 0xffffffff));

    show_long_bits("custom 1", create_custom_1(0x11111, 0x11111111).d);

    show_long_bits("(+) first normal", create_normal(0, E_MIN, 0, 0).d);
    show_long_bits("(+) last normal",  create_normal(0, E_MAX, 0xfffff, 0xffffffff).d);
    show_long_bits("(-) first normal", create_normal(1, E_MIN, 0, 0).d);
    show_long_bits("(-) last normal",  create_normal(1, E_MAX, 0xfffff, 0xffffffff).d);

    show_long_bits("custom 2", create_custom_2(0x22222, 0x22222222).d);

    show_long_bits("dnan", create_special(SPECIAL_DNAN).d);
    show_long_bits("+inf", create_special(SPECIAL_P_INF).d);
    show_long_bits("-inf", create_special(SPECIAL_N_INF).d);
}

show_long_bits

void
show_long_bits(char *label, double x)
{
    char buf[100];
    union double_value dv;
    uint32_t type;

    dv.d = x;
    type = (dv.u32.hi + 0x00200000u) >> 20u;

    if (type < 4u) {
        /* type in [0,3], right? */
        enum { CUSTOM_2, SPECIAL, INTEGER, CUSTOM_1 } type_e = type;
        switch (type_e) {
        case INTEGER: {
                int64_t i = (int64_t)((dv.u ^ BIT_52_SET) - BIT_52_SET);
                if (i < 0) {
                    snprintf(buf, sizeof buf, "(int) %"PRId64" or %"PRId64, dv.i, i);
                } else {
                    snprintf(buf, sizeof buf, "(int) %"PRId64, i);
                }
            }
            break;
        case CUSTOM_1: {
                uint64_t payload = dv.u & LO52_MASK;
                snprintf(buf, sizeof buf, "(custom 1) 0x%013"PRIx64, payload);
            }
            break;
        case CUSTOM_2: {
                uint64_t payload = dv.u & LO52_MASK;
                snprintf(buf, sizeof buf, "(custom 2) 0x%013"PRIx64, payload);
            }
            break;
        case SPECIAL: {
                unsigned idx = dv.u32.lo & SPECIALS_ARRAY_MASK;
                snprintf(buf, sizeof buf, "(special %d: %f)", idx, specials[idx].d);
            }
            break;
        }
    } else {
        snprintf(buf, sizeof buf, "(normal)");
    }

    printf("%16.16s -> 0x%.016"PRIx64" -> %e %s\n",
        label, dv.u, as_double(dv.d), buf);
}

Sources Listing

References

More details in the link below.

This page was last modified on March 18, 2024 at 14:56:59 UTC.