Repository: JuliaLang/julia
File: src/rtutils.c (C)

Code before:
}

static size_t jl_static_show_float(JL_STREAM *out, double v,
                                   jl_datatype_t *vt) JL_NOTSAFEPOINT
{
    size_t n = 0;
    // TODO: non-canonical NaNs do not round-trip
    // TOOD: BFloat16
    const char *size_suffix = vt == jl_float16_type ? "16" :
                              vt == jl_float32_type ? "32" :
                                                      "";
    // Digits required to print p significand bits: ceil(p * log(10, 2))
    //   Float16   4
    //   Float32   8
    //   Float64  17
    if (isnan(v)) {
        n += jl_printf(out, "NaN%s", size_suffix);
    }
    else if (isinf(v)) {
        n += jl_printf(out, "%sInf%s", v < 0 ? "-" : "", size_suffix);
    }
    else if (vt == jl_float64_type) {
        // If no decimal point or exponent will be printed, we must add ".0"
        double ipart, fpart;
        fpart = modf(v, &ipart);
        int dotzero = v == 0 || (fpart == 0.0 && fabs(ipart) < 1e17);
        n += jl_printf(out, "%.17g%s", v, dotzero ? ".0" : "");
    }
    else if (vt == jl_float32_type) {
        n += jl_printf(out, "Float32(%.8g)", v);
    }
    else {
        assert(vt == jl_float16_type);
        n += jl_printf(out, "Float16(%.4g)", v);
    }
    return n;
}

// `v` might be pointing to a field inlined in a structure therefore
// `jl_typeof(v)` may not be the same with `vt` and only `vt` should be
// used to determine the type of the value.
// This is necessary to make sure that this function doesn't allocate any
// memory through the Julia GC
static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt,
                                struct recur_list *depth, jl_static_show_config_t ctx) JL_NOTSAFEPOINT
{
    size_t n = 0;
    if ((uintptr_t)vt < 4096U) {
        n += jl_printf(out, "<?#%p::%p>", (void*)v, (void*)vt);
    }
    else if ((uintptr_t)v < 4096U) {

Review comment (suggestion):
This seems likely prone to mistakes with double-rounding errors and implementation-defined choices of representations. I recommend changing this to `snprintf` to a small stack buffer and then outputting that with '%s' and then checking explicitly if it already contains `.`, rather than trying to guess

Code after:
            return 0;
        } else if (vt == jl_function_type) {
            return 1;
        }
        vt = vt->super;
        _iter_count += 1;
    }
    return 0;
}

static size_t jl_static_show_float(JL_STREAM *out, double v,
                                   jl_datatype_t *vt) JL_NOTSAFEPOINT
{
    size_t n = 0;
    // TODO: non-canonical NaNs do not round-trip
    // TOOD: BFloat16
    const char *size_suffix = vt == jl_float16_type ? "16" :
                              vt == jl_float32_type ? "32" :
                                                      "";
    // Requires minimum 1 (sign) + 17 (sig) + 1 (dot) + 5 ("e-123") + 1 (null)
    char buf[32];
    // Base B significand digits required to print n base-b significand bits
    // (including leading 1):  N = 2 + floor(n/log(b, B))
    //   Float16   5
    //   Float32   9
    //   Float64  17
    // REF: https://dl.acm.org/doi/pdf/10.1145/93542.93559
    if (isnan(v)) {
        n += jl_printf(out, "NaN%s", size_suffix);
    }
    else if (isinf(v)) {
        n += jl_printf(out, "%sInf%s", v < 0 ? "-" : "", size_suffix);
    }
    else if (vt == jl_float64_type) {
        n += jl_printf(out, "%#.17g", v);
    }
    else if (vt == jl_float32_type) {
        size_t m = snprintf(buf, sizeof buf, "%.9g", v);
        // If the exponent was printed, replace it with 'f'
        char *p = (char *)memchr(buf, 'e', m);
        if (p)
            *p = 'f';
        jl_uv_puts(out, buf, m);
        n += m;
        // If no exponent was printed, we must add one
        if (!p)
            n += jl_printf(out, "f0");
    }
    else {
        assert(vt == jl_float16_type);
        n += jl_printf(out, "Float16(%#.5g)", v);