DoxigAlpha

formatDecimal

Write a FloatDecimal to a buffer in decimal form.

The buffer provided must be greater than min_buffer_size bytes in length. If no precision is specified, this may still return an error. If precision is specified, 2 + precision bytes will always be written.

Function parameters

Parameters

#
T:type
buf:[]u8
f_:FloatDecimal(T)
precision:?usize

Type definitions in this namespace

Types

#

Returns the minimum buffer size needed to print every float of a specific type and format.

Functions

#
bufferSize
Returns the minimum buffer size needed to print every float of a specific type and format.
render
Format a floating-point value and write it to buffer.
formatScientific
Write a FloatDecimal to a buffer in scientific form.
formatDecimal
Write a FloatDecimal to a buffer in decimal form.
binaryToDecimal
Convert a binary float representation to decimal.

Error sets in this namespace

Error Sets

#

Any buffer used for `format` must be at least this large.

Values

#
min_buffer_size
Any buffer used for `format` must be at least this large.

Source

Implementation

#
pub fn formatDecimal(comptime T: type, buf: []u8, f_: FloatDecimal(T), precision: ?usize) Error![]const u8 {
    std.debug.assert(buf.len >= min_buffer_size);
    var f = f_;

    if (f.exponent == special_exponent) {
        return copySpecialStr(buf, f);
    }

    if (precision) |prec| {
        f = round(T, f, .decimal, prec);
    }

    var output = f.mantissa;
    const olength = decimalLength(output);

    // fixed bound: leading_digit(1) + point(1)
    const req_bytes = if (f.exponent >= 0)
        @as(usize, 2) + @abs(f.exponent) + olength + (precision orelse 0)
    else
        @as(usize, 2) + @max(@abs(f.exponent) + olength, precision orelse 0);
    if (buf.len < req_bytes) {
        return error.BufferTooSmall;
    }

    // Step 5: Print the decimal representation
    var index: usize = 0;
    if (f.sign) {
        buf[index] = '-';
        index += 1;
    }

    const dp_offset = f.exponent + cast_i32(olength);
    if (dp_offset <= 0) {
        // 0.000001234
        buf[index] = '0';
        buf[index + 1] = '.';
        index += 2;
        const dp_index = index;

        const dp_poffset: u32 = @intCast(-dp_offset);
        @memset(buf[index..][0..dp_poffset], '0');
        index += dp_poffset;
        writeDecimal(buf[index..], &output, olength);
        index += olength;

        if (precision) |prec| {
            const dp_written = index - dp_index;
            if (prec > dp_written) {
                @memset(buf[index..][0 .. prec - dp_written], '0');
            }
            index = dp_index + prec - @intFromBool(prec == 0);
        }
    } else {
        // 123456000
        const dp_uoffset: usize = @intCast(dp_offset);
        if (dp_uoffset >= olength) {
            writeDecimal(buf[index..], &output, olength);
            index += olength;
            @memset(buf[index..][0 .. dp_uoffset - olength], '0');
            index += dp_uoffset - olength;

            if (precision) |prec| {
                if (prec != 0) {
                    buf[index] = '.';
                    index += 1;
                    @memset(buf[index..][0..prec], '0');
                    index += prec;
                }
            }
        } else {
            // 12345.6789
            writeDecimal(buf[index + dp_uoffset + 1 ..], &output, olength - dp_uoffset);
            buf[index + dp_uoffset] = '.';
            const dp_index = index + dp_uoffset + 1;
            writeDecimal(buf[index..], &output, dp_uoffset);
            index += olength + 1;

            if (precision) |prec| {
                const dp_written = olength - dp_uoffset;
                if (prec > dp_written) {
                    @memset(buf[index..][0 .. prec - dp_written], '0');
                }
                index = dp_index + prec - @intFromBool(prec == 0);
            }
        }
    }

    return buf[0..index];
}