Merge changes to reals formatting from master
This commit is contained in:
		@@ -17,11 +17,138 @@ module tanya.format;
 | 
			
		||||
import tanya.container.string;
 | 
			
		||||
import tanya.encoding.ascii;
 | 
			
		||||
public import tanya.format.conv;
 | 
			
		||||
import tanya.math;
 | 
			
		||||
import tanya.memory.op;
 | 
			
		||||
import tanya.meta.metafunction;
 | 
			
		||||
import tanya.meta.trait;
 | 
			
		||||
import tanya.range.array;
 | 
			
		||||
 | 
			
		||||
// Integer and floating point to string conversion is based on stb_sprintf
 | 
			
		||||
// written by Jeff Roberts.
 | 
			
		||||
 | 
			
		||||
// Returns the last part of buffer with converted number.
 | 
			
		||||
package(tanya) char[] integral2String(T)(T number, return ref char[21] buffer)
 | 
			
		||||
if (isIntegral!T)
 | 
			
		||||
{
 | 
			
		||||
    // abs the integer.
 | 
			
		||||
    ulong n64 = number < 0 ? -cast(long) number : number;
 | 
			
		||||
 | 
			
		||||
    char* start = buffer[].ptr + buffer.sizeof - 1;
 | 
			
		||||
 | 
			
		||||
    while (true)
 | 
			
		||||
    {
 | 
			
		||||
        // Do in 32-bit chunks (avoid lots of 64-bit divides even with constant
 | 
			
		||||
        // denominators).
 | 
			
		||||
        char* o = start - 8;
 | 
			
		||||
        uint n;
 | 
			
		||||
        if (n64 >= 100000000)
 | 
			
		||||
        {
 | 
			
		||||
            n = n64 % 100000000;
 | 
			
		||||
            n64 /= 100000000;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            n = cast(uint) n64;
 | 
			
		||||
            n64 = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        while (n)
 | 
			
		||||
        {
 | 
			
		||||
            *--start = cast(char) (n % 10) + '0';
 | 
			
		||||
            n /= 10;
 | 
			
		||||
        }
 | 
			
		||||
        // Ignore the leading zero if it was the last part of the integer.
 | 
			
		||||
        if (n64 == 0)
 | 
			
		||||
        {
 | 
			
		||||
            if ((start[0] == '0')
 | 
			
		||||
             && (start != (buffer[].ptr + buffer.sizeof -1)))
 | 
			
		||||
            {
 | 
			
		||||
                ++start;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        // Copy leading zeros if it wasn't the most significant part of the
 | 
			
		||||
        // integer.
 | 
			
		||||
        while (start != o)
 | 
			
		||||
        {
 | 
			
		||||
            *--start = '0';
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get the length that we have copied.
 | 
			
		||||
    uint l = cast(uint) ((buffer[].ptr + buffer.sizeof - 1) - start);
 | 
			
		||||
    if (l == 0)
 | 
			
		||||
    {
 | 
			
		||||
        *--start = '0';
 | 
			
		||||
        l = 1;
 | 
			
		||||
    }
 | 
			
		||||
    else if (number < 0) // Set the sign.
 | 
			
		||||
    {
 | 
			
		||||
        *--start = '-';
 | 
			
		||||
        ++l;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return buffer[$ - l - 1 .. $ - 1];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Converting an integer to string.
 | 
			
		||||
@nogc nothrow pure @system unittest
 | 
			
		||||
{
 | 
			
		||||
    char[21] buf;
 | 
			
		||||
 | 
			
		||||
    assert(integral2String(80, buf) == "80");
 | 
			
		||||
    assert(integral2String(-80, buf) == "-80");
 | 
			
		||||
    assert(integral2String(0, buf) == "0");
 | 
			
		||||
    assert(integral2String(uint.max, buf) == "4294967295");
 | 
			
		||||
    assert(integral2String(int.min, buf) == "-2147483648");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Double-double high-precision floating point number.
 | 
			
		||||
 *
 | 
			
		||||
 * The first element is a base value corresponding to the nearest approximation
 | 
			
		||||
 * of the target $(D_PSYMBOL HP) value, and the second element is an offset
 | 
			
		||||
 * value corresponding to the difference between the target value and the base.
 | 
			
		||||
 * Thus, the $(D_PSYMBOL HP) value represented is the sum of the base and the
 | 
			
		||||
 * offset.
 | 
			
		||||
 */
 | 
			
		||||
private struct HP
 | 
			
		||||
{
 | 
			
		||||
    private double base;
 | 
			
		||||
    private double offset = 0.0;
 | 
			
		||||
 | 
			
		||||
    private void normalize() @nogc nothrow pure @safe
 | 
			
		||||
    {
 | 
			
		||||
        const double target = this.base + this.offset;
 | 
			
		||||
        this.offset -= target - this.base;
 | 
			
		||||
        this.base = target;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void multiply(ref const HP x, ref const HP y)
 | 
			
		||||
    @nogc nothrow pure @safe
 | 
			
		||||
    {
 | 
			
		||||
        HP a, b;
 | 
			
		||||
        long bt;
 | 
			
		||||
 | 
			
		||||
        this.base = x.base * y.base;
 | 
			
		||||
        copyFp(x.base, bt);
 | 
			
		||||
        bt &= ulong.max << 27;
 | 
			
		||||
        copyFp(bt, a.base);
 | 
			
		||||
 | 
			
		||||
        a.offset = x.base - a.base;
 | 
			
		||||
        copyFp(y.base, bt);
 | 
			
		||||
        bt &= ulong.max << 27;
 | 
			
		||||
        copyFp(bt, b.base);
 | 
			
		||||
 | 
			
		||||
        b.offset = y.base - b.base;
 | 
			
		||||
        this.offset = a.base * b.base - this.base
 | 
			
		||||
                    + a.base * b.offset
 | 
			
		||||
                    + a.offset * b.base
 | 
			
		||||
                    + a.offset * b.offset;
 | 
			
		||||
        this.offset += x.base * y.offset + x.offset * y.base;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private enum special = 0x7000;
 | 
			
		||||
private enum char period = '.';
 | 
			
		||||
 | 
			
		||||
@@ -48,145 +175,121 @@ private static const ulong[20] powersOf10 = [
 | 
			
		||||
    10000000000000000000UL,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
private static const char[201] digitpair =
 | 
			
		||||
private static const char[201] digitPairs =
 | 
			
		||||
    "0001020304050607080910111213141516171819202122232425262728293031323334353"
 | 
			
		||||
  ~ "6373839404142434445464748495051525354555657585960616263646566676869707172"
 | 
			
		||||
  ~ "737475767778798081828384858687888990919293949596979899";
 | 
			
		||||
 | 
			
		||||
private static const double[23] bottom = [
 | 
			
		||||
    1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008,
 | 
			
		||||
    1e+009, 1e+010, 1e+011, 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017,
 | 
			
		||||
    1e+018, 1e+019, 1e+020, 1e+021, 1e+022,
 | 
			
		||||
private static const HP[23] bottom = [
 | 
			
		||||
    HP(1e+000), HP(1e+001), HP(1e+002), HP(1e+003), HP(1e+004), HP(1e+005),
 | 
			
		||||
    HP(1e+006), HP(1e+007), HP(1e+008), HP(1e+009), HP(1e+010), HP(1e+011),
 | 
			
		||||
    HP(1e+012), HP(1e+013), HP(1e+014), HP(1e+015), HP(1e+016), HP(1e+017),
 | 
			
		||||
    HP(1e+018), HP(1e+019), HP(1e+020), HP(1e+021), HP(1e+022),
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
private static const double[22] negativeBottom = [
 | 
			
		||||
    1e-001, 1e-002, 1e-003, 1e-004, 1e-005, 1e-006, 1e-007, 1e-008, 1e-009,
 | 
			
		||||
    1e-010, 1e-011, 1e-012, 1e-013, 1e-014, 1e-015, 1e-016, 1e-017, 1e-018,
 | 
			
		||||
    1e-019, 1e-020, 1e-021, 1e-022,
 | 
			
		||||
private static const HP[22] negativeBottom = [
 | 
			
		||||
    HP(1e-001, -5.551115123125783e-018),
 | 
			
		||||
    HP(1e-002, -2.0816681711721684e-019),
 | 
			
		||||
    HP(1e-003, -2.0816681711721686e-020),
 | 
			
		||||
    HP(1e-004, -4.7921736023859299e-021),
 | 
			
		||||
    HP(1e-005, -8.1803053914031305e-022),
 | 
			
		||||
    HP(1e-006, 4.5251888174113741e-023),
 | 
			
		||||
    HP(1e-007, 4.5251888174113739e-024),
 | 
			
		||||
    HP(1e-008, -2.0922560830128471e-025),
 | 
			
		||||
    HP(1e-009, -6.2281591457779853e-026),
 | 
			
		||||
    HP(1e-010, -3.6432197315497743e-027),
 | 
			
		||||
    HP(1e-011, 6.0503030718060191e-028),
 | 
			
		||||
    HP(1e-012, 2.0113352370744385e-029),
 | 
			
		||||
    HP(1e-013, -3.0373745563400371e-030),
 | 
			
		||||
    HP(1e-014, 1.1806906454401013e-032),
 | 
			
		||||
    HP(1e-015, -7.7705399876661076e-032),
 | 
			
		||||
    HP(1e-016, 2.0902213275965398e-033),
 | 
			
		||||
    HP(1e-017, -7.1542424054621921e-034),
 | 
			
		||||
    HP(1e-018, -7.1542424054621926e-035),
 | 
			
		||||
    HP(1e-019, 2.4754073164739869e-036),
 | 
			
		||||
    HP(1e-020, 5.4846728545790429e-037),
 | 
			
		||||
    HP(1e-021, 9.2462547772103625e-038),
 | 
			
		||||
    HP(1e-022, -4.8596774326570872e-039),
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
private static const double[13] top = [
 | 
			
		||||
    1e+023, 1e+046, 1e+069, 1e+092, 1e+115, 1e+138, 1e+161, 1e+184, 1e+207,
 | 
			
		||||
    1e+230, 1e+253, 1e+276, 1e+299,
 | 
			
		||||
private static const HP[13] top = [
 | 
			
		||||
    HP(1e+023, 8388608),
 | 
			
		||||
    HP(1e+046, 6.8601809640529717e+028),
 | 
			
		||||
    HP(1e+069, -7.253143638152921e+052),
 | 
			
		||||
    HP(1e+092, -4.3377296974619174e+075),
 | 
			
		||||
    HP(1e+115, -1.5559416129466825e+098),
 | 
			
		||||
    HP(1e+138, -3.2841562489204913e+121),
 | 
			
		||||
    HP(1e+161, -3.7745893248228135e+144),
 | 
			
		||||
    HP(1e+184, -1.7356668416969134e+167),
 | 
			
		||||
    HP(1e+207, -3.8893577551088374e+190),
 | 
			
		||||
    HP(1e+230, -9.9566444326005119e+213),
 | 
			
		||||
    HP(1e+253, 6.3641293062232429e+236),
 | 
			
		||||
    HP(1e+276, -5.2069140800249813e+259),
 | 
			
		||||
    HP(1e+299, -5.2504760255204387e+282),
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
private static const double[13] negativeTop = [
 | 
			
		||||
    1e-023, 1e-046, 1e-069, 1e-092, 1e-115, 1e-138, 1e-161, 1e-184, 1e-207,
 | 
			
		||||
    1e-230, 1e-253, 1e-276, 1e-299,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
private static const double[13] topError = [
 | 
			
		||||
    8388608, 6.8601809640529717e+028, -7.253143638152921e+052,
 | 
			
		||||
    -4.3377296974619174e+075, -1.5559416129466825e+098,
 | 
			
		||||
    -3.2841562489204913e+121, -3.7745893248228135e+144,
 | 
			
		||||
    -1.7356668416969134e+167, -3.8893577551088374e+190,
 | 
			
		||||
    -9.9566444326005119e+213, 6.3641293062232429e+236,
 | 
			
		||||
    -5.2069140800249813e+259, -5.2504760255204387e+282,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
private static const double[22] negativeBottomError = [
 | 
			
		||||
    -5.551115123125783e-018, -2.0816681711721684e-019,
 | 
			
		||||
    -2.0816681711721686e-020, -4.7921736023859299e-021,
 | 
			
		||||
    -8.1803053914031305e-022, 4.5251888174113741e-023,
 | 
			
		||||
    4.5251888174113739e-024, -2.0922560830128471e-025,
 | 
			
		||||
    -6.2281591457779853e-026, -3.6432197315497743e-027,
 | 
			
		||||
    6.0503030718060191e-028, 2.0113352370744385e-029, -3.0373745563400371e-030,
 | 
			
		||||
    1.1806906454401013e-032, -7.7705399876661076e-032, 2.0902213275965398e-033,
 | 
			
		||||
    -7.1542424054621921e-034, -7.1542424054621926e-035,
 | 
			
		||||
    2.4754073164739869e-036, 5.4846728545790429e-037, 9.2462547772103625e-038,
 | 
			
		||||
    -4.8596774326570872e-039,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
private static const double[13] negativeTopError = [
 | 
			
		||||
    3.9565301985100693e-040, -2.299904345391321e-063, 3.6506201437945798e-086,
 | 
			
		||||
    1.1875228833981544e-109, -5.0644902316928607e-132,
 | 
			
		||||
    -6.7156837247865426e-155, -2.812077463003139e-178,
 | 
			
		||||
    -5.7778912386589953e-201, 7.4997100559334532e-224,
 | 
			
		||||
    -4.6439668915134491e-247, -6.3691100762962136e-270,
 | 
			
		||||
    -9.436808465446358e-293, // 8.0970921678014997e-317,
 | 
			
		||||
private static const HP[13] negativeTop = [
 | 
			
		||||
    HP(1e-023, 3.9565301985100693e-040L),
 | 
			
		||||
    HP(1e-046, -2.299904345391321e-063L),
 | 
			
		||||
    HP(1e-069, 3.6506201437945798e-086L),
 | 
			
		||||
    HP(1e-092, 1.1875228833981544e-109L),
 | 
			
		||||
    HP(1e-115, -5.0644902316928607e-132L),
 | 
			
		||||
    HP(1e-138, -6.7156837247865426e-155L),
 | 
			
		||||
    HP(1e-161, -2.812077463003139e-178L),
 | 
			
		||||
    HP(1e-184, -5.7778912386589953e-201L),
 | 
			
		||||
    HP(1e-207, 7.4997100559334532e-224L),
 | 
			
		||||
    HP(1e-230, -4.6439668915134491e-247L),
 | 
			
		||||
    HP(1e-253, -6.3691100762962136e-270L),
 | 
			
		||||
    HP(1e-276, -9.436808465446358e-293L),
 | 
			
		||||
    HP(1e-299, 8.0970921678014997e-317L),
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
private enum ulong tenTo19th = 1000000000000000000UL;
 | 
			
		||||
 | 
			
		||||
private void ddmultlo(A, B, C, D, E, F)(ref A oh,
 | 
			
		||||
                                        ref B ol,
 | 
			
		||||
                                        ref C xh,
 | 
			
		||||
                                        ref D xl,
 | 
			
		||||
                                        ref E yh,
 | 
			
		||||
                                        ref F yl)
 | 
			
		||||
{
 | 
			
		||||
    ol = ol + (xh * yl + xl * yh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private void ddmultlos(A, B, C, D)(ref A oh, ref B ol, ref C xh, ref D yl)
 | 
			
		||||
{
 | 
			
		||||
    ol = ol + (xh * yl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private void ddrenorm(T, U)(ref T oh, ref U ol)
 | 
			
		||||
{
 | 
			
		||||
    double s;
 | 
			
		||||
    s = oh + ol;
 | 
			
		||||
    ol = ol - (s - oh);
 | 
			
		||||
    oh = s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Power can be -323 to +350.
 | 
			
		||||
private void raise2Power10(double* ohi,
 | 
			
		||||
                           double* olo,
 | 
			
		||||
                           double d,
 | 
			
		||||
                           int power) @nogc nothrow pure
 | 
			
		||||
private HP raise2Power10(const HP value, int power)
 | 
			
		||||
@nogc nothrow pure @safe
 | 
			
		||||
{
 | 
			
		||||
    double ph, pl;
 | 
			
		||||
    HP result;
 | 
			
		||||
    if ((power >= 0) && (power <= 22))
 | 
			
		||||
    {
 | 
			
		||||
        ddmulthi(ph, pl, d, bottom[power]);
 | 
			
		||||
        result.multiply(value, bottom[power]);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        int e, et, eb;
 | 
			
		||||
        double p2h, p2l;
 | 
			
		||||
        HP p2;
 | 
			
		||||
        int e = power;
 | 
			
		||||
 | 
			
		||||
        e = power;
 | 
			
		||||
        if (power < 0)
 | 
			
		||||
        {
 | 
			
		||||
            e = -e;
 | 
			
		||||
        }
 | 
			
		||||
        et = (e * 0x2c9) >> 14; /* %23 */
 | 
			
		||||
        int et = (e * 0x2c9) >> 14; // % 23
 | 
			
		||||
        if (et > 13)
 | 
			
		||||
        {
 | 
			
		||||
            et = 13;
 | 
			
		||||
        }
 | 
			
		||||
        eb = e - (et * 23);
 | 
			
		||||
        int eb = e - (et * 23);
 | 
			
		||||
 | 
			
		||||
        ph = d;
 | 
			
		||||
        pl = 0.0;
 | 
			
		||||
        result = value;
 | 
			
		||||
        if (power < 0)
 | 
			
		||||
        {
 | 
			
		||||
            if (eb)
 | 
			
		||||
            if (eb != 0)
 | 
			
		||||
            {
 | 
			
		||||
                --eb;
 | 
			
		||||
                ddmulthi(ph, pl, d, negativeBottom[eb]);
 | 
			
		||||
                ddmultlos(ph, pl, d, negativeBottomError[eb]);
 | 
			
		||||
                result.multiply(value, negativeBottom[eb]);
 | 
			
		||||
            }
 | 
			
		||||
            if (et)
 | 
			
		||||
            {
 | 
			
		||||
                ddrenorm(ph, pl);
 | 
			
		||||
                result.normalize();
 | 
			
		||||
                --et;
 | 
			
		||||
                ddmulthi(p2h, p2l, ph, negativeTop[et]);
 | 
			
		||||
                ddmultlo(p2h,
 | 
			
		||||
                         p2l,
 | 
			
		||||
                         ph,
 | 
			
		||||
                         pl,
 | 
			
		||||
                         negativeTop[et],
 | 
			
		||||
                         negativeTopError[et]);
 | 
			
		||||
                ph = p2h;
 | 
			
		||||
                pl = p2l;
 | 
			
		||||
                p2.multiply(result, negativeTop[et]);
 | 
			
		||||
                result = p2;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (eb)
 | 
			
		||||
            if (eb != 0)
 | 
			
		||||
            {
 | 
			
		||||
                e = eb;
 | 
			
		||||
                if (eb > 22)
 | 
			
		||||
@@ -194,168 +297,141 @@ private void raise2Power10(double* ohi,
 | 
			
		||||
                    eb = 22;
 | 
			
		||||
                }
 | 
			
		||||
                e -= eb;
 | 
			
		||||
                ddmulthi(ph, pl, d, bottom[eb]);
 | 
			
		||||
                result.multiply(value, bottom[eb]);
 | 
			
		||||
                if (e)
 | 
			
		||||
                {
 | 
			
		||||
                    ddrenorm(ph, pl);
 | 
			
		||||
                    ddmulthi(p2h, p2l, ph, bottom[e]);
 | 
			
		||||
                    ddmultlos(p2h, p2l, bottom[e], pl);
 | 
			
		||||
                    ph = p2h;
 | 
			
		||||
                    pl = p2l;
 | 
			
		||||
                    result.normalize();
 | 
			
		||||
                    p2.multiply(result, bottom[e]);
 | 
			
		||||
                    result = p2;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (et)
 | 
			
		||||
            if (et != 0)
 | 
			
		||||
            {
 | 
			
		||||
                ddrenorm(ph, pl);
 | 
			
		||||
                result.normalize();
 | 
			
		||||
                --et;
 | 
			
		||||
                ddmulthi(p2h, p2l, ph, top[et]);
 | 
			
		||||
                ddmultlo(p2h, p2l, ph, pl, top[et], topError[et]);
 | 
			
		||||
                ph = p2h;
 | 
			
		||||
                pl = p2l;
 | 
			
		||||
                p2.multiply(result, top[et]);
 | 
			
		||||
                result = p2;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    ddrenorm(ph, pl);
 | 
			
		||||
    *ohi = ph;
 | 
			
		||||
    *olo = pl;
 | 
			
		||||
    result.normalize();
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Given a float value, returns the significant bits in bits, and the position
 | 
			
		||||
 * of the decimal point in decimalPos. +/-Inf and NaN are specified by special
 | 
			
		||||
 * values returned in the decimalPos parameter.
 | 
			
		||||
 * fracDigits is absolute normally, but if you want from first significant
 | 
			
		||||
 * digits (got %g), or in 0x80000000
 | 
			
		||||
 * of the decimal point in $(D_PARAM exponent). +/-Inf and NaN are specified
 | 
			
		||||
 * by special values returned in the $(D_PARAM exponent). Sing bit is set in
 | 
			
		||||
 * $(D_PARAM sign).
 | 
			
		||||
 */
 | 
			
		||||
private int real2String(ref const(char)* start,
 | 
			
		||||
                        ref uint len,
 | 
			
		||||
                        char* out_,
 | 
			
		||||
                        out int decimalPos,
 | 
			
		||||
                        double value,
 | 
			
		||||
                        uint fracDigits) @nogc nothrow pure
 | 
			
		||||
private const(char)[] real2String(double value,
 | 
			
		||||
                                  ref char[512] buffer,
 | 
			
		||||
                                  out int exponent,
 | 
			
		||||
                                  out bool sign) @nogc nothrow pure @trusted
 | 
			
		||||
{
 | 
			
		||||
    long bits = 0;
 | 
			
		||||
    int e, tens;
 | 
			
		||||
    long bits;
 | 
			
		||||
    copyFp(value, bits);
 | 
			
		||||
 | 
			
		||||
    double d = value;
 | 
			
		||||
    copyFp(bits, d);
 | 
			
		||||
    auto exponent = cast(int) ((bits >> 52) & 2047);
 | 
			
		||||
    auto ng = cast(int) (bits >> 63);
 | 
			
		||||
    if (ng)
 | 
			
		||||
    exponent = (bits >> 52) & 0x7ff;
 | 
			
		||||
    sign = signBit(value);
 | 
			
		||||
    if (sign)
 | 
			
		||||
    {
 | 
			
		||||
        d = -d;
 | 
			
		||||
        value = -value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (exponent == 2047) // Is NaN or inf?
 | 
			
		||||
    if (exponent == 2047) // Is NaN or Inf?
 | 
			
		||||
    {
 | 
			
		||||
        start = (bits & (((cast(ulong) 1) << 52) - 1)) ? "NaN" : "Inf";
 | 
			
		||||
        decimalPos = special;
 | 
			
		||||
        len = 3;
 | 
			
		||||
        return ng;
 | 
			
		||||
        exponent = special;
 | 
			
		||||
        return (bits & ((1UL << 52) - 1)) != 0 ? "NaN" : "Inf";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (exponent == 0) // Is zero or denormal?
 | 
			
		||||
    {
 | 
			
		||||
        if ((bits << 1) == 0) // Do zero.
 | 
			
		||||
        if ((bits << 1) == 0) // Zero.
 | 
			
		||||
        {
 | 
			
		||||
            decimalPos = 1;
 | 
			
		||||
            start = out_;
 | 
			
		||||
            out_[0] = '0';
 | 
			
		||||
            len = 1;
 | 
			
		||||
            return ng;
 | 
			
		||||
            exponent = 1;
 | 
			
		||||
            buffer[0] = '0';
 | 
			
		||||
            return buffer[0 .. 1];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Find the right exponent for denormals.
 | 
			
		||||
        {
 | 
			
		||||
            long v = (cast(ulong) 1) << 51;
 | 
			
		||||
            while ((bits & v) == 0)
 | 
			
		||||
        for (long cursor = 1UL << 51; (bits & cursor) == 0; cursor >>= 1)
 | 
			
		||||
        {
 | 
			
		||||
            --exponent;
 | 
			
		||||
                v >>= 1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Find the decimal exponent as well as the decimal bits of the value.
 | 
			
		||||
    {
 | 
			
		||||
        double ph, pl;
 | 
			
		||||
 | 
			
		||||
        // log10 estimate - very specifically tweaked to hit or undershoot by
 | 
			
		||||
        // no more than 1 of log10 of all exponents 1..2046.
 | 
			
		||||
        tens = exponent - 1023;
 | 
			
		||||
    // "617 / 2048" and "1233 / 4096" are estimations for the common logarithm
 | 
			
		||||
    // (log10) of 2. Multiplied by a binary number it tells how big the number
 | 
			
		||||
    // is in decimals, so it translates the binary exponent into decimal
 | 
			
		||||
    // format. The estimation is tweaked to hit or undershoot by no more than
 | 
			
		||||
    // 1 of log10 of all exponents 1..2046.
 | 
			
		||||
    int tens = exponent - 1023; // Bias.
 | 
			
		||||
    if (tens < 0)
 | 
			
		||||
    {
 | 
			
		||||
            tens = (tens * 617) / 2048;
 | 
			
		||||
        tens = tens * 617 / 2048;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
            tens = ((tens * 1233) / 4096) + 1;
 | 
			
		||||
        tens = tens * 1233 / 4096 + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Move the significant bits into position and stick them into an int.
 | 
			
		||||
        raise2Power10(&ph, &pl, d, 18 - tens);
 | 
			
		||||
    HP p = raise2Power10(HP(value), 18 - tens);
 | 
			
		||||
 | 
			
		||||
    // Get full as much precision from double-double as possible.
 | 
			
		||||
        bits = cast(long) ph;
 | 
			
		||||
    bits = cast(long) p.base;
 | 
			
		||||
    double vh = cast(double) bits;
 | 
			
		||||
        double ahi = (ph - vh);
 | 
			
		||||
        double t = (ahi - ph);
 | 
			
		||||
        double alo = (ph - (ahi - t)) - (vh + t);
 | 
			
		||||
        bits += cast(long) (ahi + alo + pl);
 | 
			
		||||
    auto a = HP(p.base - vh);
 | 
			
		||||
    double t = a.base - p.base;
 | 
			
		||||
    a.offset = p.base - a.base + t - vh - t;
 | 
			
		||||
    bits += cast(long) (a.base + a.offset + p.offset);
 | 
			
		||||
 | 
			
		||||
        // Check if we undershot.
 | 
			
		||||
        if ((cast(ulong) bits) >= tenTo19th)
 | 
			
		||||
    // Check if we undershot (bits >= 10 ^ 19).
 | 
			
		||||
    if ((cast(ulong) bits) >= 1000000000000000000UL)
 | 
			
		||||
    {
 | 
			
		||||
        ++tens;
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Now do the rounding in integer land.
 | 
			
		||||
    if (fracDigits & 0x80000000)
 | 
			
		||||
    {
 | 
			
		||||
        fracDigits =  (fracDigits & 0x7ffffff) + 1;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        fracDigits = tens + fracDigits;
 | 
			
		||||
    }
 | 
			
		||||
    if ((fracDigits < 24))
 | 
			
		||||
    {
 | 
			
		||||
    enum uint fracDigits = 6;
 | 
			
		||||
 | 
			
		||||
    uint dg = 1;
 | 
			
		||||
        if (cast(ulong) bits >= powersOf10[9])
 | 
			
		||||
    if ((cast(ulong) bits) >= powersOf10[9])
 | 
			
		||||
    {
 | 
			
		||||
        dg = 10;
 | 
			
		||||
    }
 | 
			
		||||
        while (cast(ulong) bits >= powersOf10[dg])
 | 
			
		||||
    uint length;
 | 
			
		||||
    while ((cast(ulong) bits) >= powersOf10[dg])
 | 
			
		||||
    {
 | 
			
		||||
        ++dg;
 | 
			
		||||
        if (dg == 20)
 | 
			
		||||
        {
 | 
			
		||||
                goto noround;
 | 
			
		||||
            goto NoRound;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (fracDigits < dg)
 | 
			
		||||
    {
 | 
			
		||||
        // Add 0.5 at the right position and round.
 | 
			
		||||
            e = dg - fracDigits;
 | 
			
		||||
            if (cast(uint) e >= 24)
 | 
			
		||||
        length = dg - fracDigits;
 | 
			
		||||
        if (length >= 24)
 | 
			
		||||
        {
 | 
			
		||||
                goto noround;
 | 
			
		||||
            goto NoRound;
 | 
			
		||||
        }
 | 
			
		||||
            ulong r = powersOf10[e];
 | 
			
		||||
        ulong r = powersOf10[length];
 | 
			
		||||
        bits = bits + (r / 2);
 | 
			
		||||
            if (cast(ulong) bits >= powersOf10[dg])
 | 
			
		||||
        if ((cast(ulong) bits) >= powersOf10[dg])
 | 
			
		||||
        {
 | 
			
		||||
            ++tens;
 | 
			
		||||
        }
 | 
			
		||||
        bits /= r;
 | 
			
		||||
    }
 | 
			
		||||
    noround:
 | 
			
		||||
    }
 | 
			
		||||
NoRound:
 | 
			
		||||
 | 
			
		||||
    // Kill long trailing runs of zeros.
 | 
			
		||||
    if (bits)
 | 
			
		||||
    {
 | 
			
		||||
        uint n;
 | 
			
		||||
        for (;;)
 | 
			
		||||
        {
 | 
			
		||||
            if (bits <= 0xffffffff)
 | 
			
		||||
@@ -364,26 +440,26 @@ private int real2String(ref const(char)* start,
 | 
			
		||||
            }
 | 
			
		||||
            if (bits % 1000)
 | 
			
		||||
            {
 | 
			
		||||
                goto donez;
 | 
			
		||||
                goto Zeroed;
 | 
			
		||||
            }
 | 
			
		||||
            bits /= 1000;
 | 
			
		||||
        }
 | 
			
		||||
        n = cast(uint) bits;
 | 
			
		||||
        auto n = cast(uint) bits;
 | 
			
		||||
        while ((n % 1000) == 0)
 | 
			
		||||
        {
 | 
			
		||||
            n /= 1000;
 | 
			
		||||
        }
 | 
			
		||||
        bits = n;
 | 
			
		||||
    donez:
 | 
			
		||||
    }
 | 
			
		||||
Zeroed:
 | 
			
		||||
 | 
			
		||||
    // Convert to string.
 | 
			
		||||
    out_ += 64;
 | 
			
		||||
    e = 0;
 | 
			
		||||
    for (;;)
 | 
			
		||||
    auto result = buffer.ptr + 64;
 | 
			
		||||
    length = 0;
 | 
			
		||||
    while (true)
 | 
			
		||||
    {
 | 
			
		||||
        uint n;
 | 
			
		||||
        char *o = out_ - 8;
 | 
			
		||||
        char* o = result - 8;
 | 
			
		||||
        // Do the conversion in chunks of U32s (avoid most 64-bit divides,
 | 
			
		||||
        // worth it, constant denomiators be damned).
 | 
			
		||||
        if (bits >= 100000000)
 | 
			
		||||
@@ -398,35 +474,31 @@ private int real2String(ref const(char)* start,
 | 
			
		||||
        }
 | 
			
		||||
        while (n)
 | 
			
		||||
        {
 | 
			
		||||
            out_ -= 2;
 | 
			
		||||
            *cast(ushort*) out_ = *cast(ushort*) &digitpair[(n % 100) * 2];
 | 
			
		||||
            result -= 2;
 | 
			
		||||
            *cast(ushort*) result = *cast(ushort*) &digitPairs[(n % 100) * 2];
 | 
			
		||||
            n /= 100;
 | 
			
		||||
            e += 2;
 | 
			
		||||
            length += 2;
 | 
			
		||||
        }
 | 
			
		||||
        if (bits == 0)
 | 
			
		||||
        {
 | 
			
		||||
            if ((e) && (out_[0] == '0'))
 | 
			
		||||
            if ((length != 0) && (result[0] == '0'))
 | 
			
		||||
            {
 | 
			
		||||
                ++out_;
 | 
			
		||||
                --e;
 | 
			
		||||
                ++result;
 | 
			
		||||
                --length;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        while (out_ != o)
 | 
			
		||||
        for (; result !is o; ++length, --result)
 | 
			
		||||
        {
 | 
			
		||||
            *--out_ = '0';
 | 
			
		||||
            ++e;
 | 
			
		||||
            *result = '0';
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    decimalPos = tens;
 | 
			
		||||
    start = out_;
 | 
			
		||||
    len = e;
 | 
			
		||||
    return ng;
 | 
			
		||||
    exponent = tens;
 | 
			
		||||
    return result[0 .. length];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private void leadSign(bool negative, ref char[8] sign)
 | 
			
		||||
@nogc nothrow pure
 | 
			
		||||
@nogc nothrow pure @safe
 | 
			
		||||
{
 | 
			
		||||
    sign[0] = 0;
 | 
			
		||||
    if (negative)
 | 
			
		||||
@@ -436,13 +508,13 @@ private void leadSign(bool negative, ref char[8] sign)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Copies d to bits w/ strict aliasing (this compiles to nothing on /Ox).
 | 
			
		||||
private void copyFp(T, U)(ref T dest, ref U src)
 | 
			
		||||
/*
 | 
			
		||||
 * Copies double into long and back bitwise.
 | 
			
		||||
 */
 | 
			
		||||
private void copyFp(T, U)(ref const U src, ref T dest) @trusted
 | 
			
		||||
if (T.sizeof == U.sizeof)
 | 
			
		||||
{
 | 
			
		||||
    for (int count = 0; count < 8; ++count)
 | 
			
		||||
    {
 | 
			
		||||
        (cast(char*) &dest)[count] = (cast(char*) &src)[count];
 | 
			
		||||
    }
 | 
			
		||||
    copy((&src)[0 .. 1], (&dest)[0 .. 1]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private void ddmulthi(ref double oh,
 | 
			
		||||
@@ -453,13 +525,13 @@ private void ddmulthi(ref double oh,
 | 
			
		||||
    double ahi, bhi;
 | 
			
		||||
    long bt;
 | 
			
		||||
    oh = xh * yh;
 | 
			
		||||
    copyFp(bt, xh);
 | 
			
		||||
    copyFp(xh, bt);
 | 
			
		||||
    bt &= ((~cast(ulong) 0) << 27);
 | 
			
		||||
    copyFp(ahi, bt);
 | 
			
		||||
    copyFp(bt, ahi);
 | 
			
		||||
    double alo = xh - ahi;
 | 
			
		||||
    copyFp(bt, yh);
 | 
			
		||||
    copyFp(yh, bt);
 | 
			
		||||
    bt &= ((~cast(ulong) 0) << 27);
 | 
			
		||||
    copyFp(bhi, bt);
 | 
			
		||||
    copyFp(bt, bhi);
 | 
			
		||||
    double blo = yh - bhi;
 | 
			
		||||
    ol = ((ahi * bhi - oh) + ahi * blo + alo * bhi) + alo * blo;
 | 
			
		||||
}
 | 
			
		||||
@@ -467,25 +539,6 @@ private void ddmulthi(ref double oh,
 | 
			
		||||
package(tanya) String format(string fmt, Args...)(char[] buf, Args args)
 | 
			
		||||
{
 | 
			
		||||
    String result;
 | 
			
		||||
    char* bf = buf.ptr;
 | 
			
		||||
 | 
			
		||||
    // Ok, we have a percent, read the modifiers first.
 | 
			
		||||
    int precision = -1;
 | 
			
		||||
    int tz = 0;
 | 
			
		||||
    bool negative;
 | 
			
		||||
 | 
			
		||||
    // Handle each replacement.
 | 
			
		||||
    char[512] num; // Big enough for e308 (with commas) or e-307.
 | 
			
		||||
    char[8] lead;
 | 
			
		||||
    char[8] tail;
 | 
			
		||||
    char *s;
 | 
			
		||||
    uint l, n;
 | 
			
		||||
    ulong n64;
 | 
			
		||||
 | 
			
		||||
    double fv;
 | 
			
		||||
 | 
			
		||||
    int decimalPos;
 | 
			
		||||
    const(char)* sn;
 | 
			
		||||
 | 
			
		||||
    static if (isSomeString!(Args[0])) // String
 | 
			
		||||
    {
 | 
			
		||||
@@ -504,28 +557,23 @@ package(tanya) String format(string fmt, Args...)(char[] buf, Args args)
 | 
			
		||||
    }
 | 
			
		||||
    else static if (isFloatingPoint!(Args[0])) // Float
 | 
			
		||||
    {
 | 
			
		||||
        fv = args[0];
 | 
			
		||||
        if (precision == -1)
 | 
			
		||||
        {
 | 
			
		||||
            precision = 6;
 | 
			
		||||
        }
 | 
			
		||||
        else if (precision == 0)
 | 
			
		||||
        {
 | 
			
		||||
            precision = 1; // Default is 6.
 | 
			
		||||
        }
 | 
			
		||||
        char[512] num; // Big enough for e308 (with commas) or e-307.
 | 
			
		||||
        char[8] lead;
 | 
			
		||||
        char[8] tail = 0;
 | 
			
		||||
        char *s;
 | 
			
		||||
        int precision = 6;
 | 
			
		||||
        int tz;
 | 
			
		||||
        bool negative;
 | 
			
		||||
        char* bf = buf.ptr;
 | 
			
		||||
        int decimalPos;
 | 
			
		||||
 | 
			
		||||
        // Read the double into a string.
 | 
			
		||||
        if (real2String(sn,
 | 
			
		||||
                        l,
 | 
			
		||||
                        num.ptr,
 | 
			
		||||
                        decimalPos,
 | 
			
		||||
                        fv,
 | 
			
		||||
                        (precision - 1) | 0x80000000))
 | 
			
		||||
        {
 | 
			
		||||
            negative = true;
 | 
			
		||||
        }
 | 
			
		||||
        auto fv = real2String(args[0], num, decimalPos, negative);
 | 
			
		||||
        const(char)* sn = fv.ptr;
 | 
			
		||||
        auto l = cast(uint) fv.length;
 | 
			
		||||
 | 
			
		||||
        // Clamp the precision and delete extra zeros after clamp.
 | 
			
		||||
        n = precision;
 | 
			
		||||
        uint n = precision;
 | 
			
		||||
        if (l > cast(uint) precision)
 | 
			
		||||
        {
 | 
			
		||||
            l = precision;
 | 
			
		||||
@@ -570,7 +618,6 @@ package(tanya) String format(string fmt, Args...)(char[] buf, Args args)
 | 
			
		||||
        goto dofloatfromg;
 | 
			
		||||
 | 
			
		||||
    doexpfromg:
 | 
			
		||||
        tail[0] = 0;
 | 
			
		||||
        leadSign(negative, lead);
 | 
			
		||||
        if (decimalPos == special)
 | 
			
		||||
        {
 | 
			
		||||
@@ -628,7 +675,6 @@ package(tanya) String format(string fmt, Args...)(char[] buf, Args args)
 | 
			
		||||
        goto flt_lead;
 | 
			
		||||
 | 
			
		||||
    dofloatfromg:
 | 
			
		||||
        tail[0] = 0;
 | 
			
		||||
        leadSign(negative, lead);
 | 
			
		||||
        if (decimalPos == special)
 | 
			
		||||
        {
 | 
			
		||||
@@ -765,121 +811,7 @@ package(tanya) String format(string fmt, Args...)(char[] buf, Args args)
 | 
			
		||||
        // Get the length that we copied.
 | 
			
		||||
        l = cast(uint) (s - (num.ptr + 64));
 | 
			
		||||
        s = num.ptr + 64;
 | 
			
		||||
    }
 | 
			
		||||
    else static if (isPointer!(Args[0])) // Pointer
 | 
			
		||||
    {
 | 
			
		||||
        // Get the number.
 | 
			
		||||
        n64 = cast(size_t) args[0];
 | 
			
		||||
        size_t position = num.length;
 | 
			
		||||
 | 
			
		||||
        do // Write at least "0" if the pointer is null.
 | 
			
		||||
        {
 | 
			
		||||
            num[--position] = lowerHexDigits[cast(size_t) (n64 & 15)];
 | 
			
		||||
            n64 >>= 4;
 | 
			
		||||
        }
 | 
			
		||||
        while (n64 != 0);
 | 
			
		||||
 | 
			
		||||
        result.insertBack("0x");
 | 
			
		||||
        result.insertBack(num[position .. $]);
 | 
			
		||||
    }
 | 
			
		||||
    else static if (isIntegral!(Args[0])) // Integer
 | 
			
		||||
    {
 | 
			
		||||
        // Get the integer and abs it.
 | 
			
		||||
        static if (Args[0].sizeof == 8)
 | 
			
		||||
        {
 | 
			
		||||
            long k64 = args[0];
 | 
			
		||||
            n64 = cast(ulong) k64;
 | 
			
		||||
            static if (isSigned!(Args[0]))
 | 
			
		||||
            {
 | 
			
		||||
                if (k64 < 0)
 | 
			
		||||
                {
 | 
			
		||||
                    n64 = cast(ulong) -k64;
 | 
			
		||||
                    negative = true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            int k = args[0];
 | 
			
		||||
            n64 = cast(uint) k;
 | 
			
		||||
            static if (isSigned!(Args[0]))
 | 
			
		||||
            {
 | 
			
		||||
                if (k < 0)
 | 
			
		||||
                {
 | 
			
		||||
                    n64 = cast(uint) -k;
 | 
			
		||||
                    negative = true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Convert to string.
 | 
			
		||||
        s = num.ptr + num.length;
 | 
			
		||||
        l = 0;
 | 
			
		||||
 | 
			
		||||
        for (;;)
 | 
			
		||||
        {
 | 
			
		||||
            // Do in 32-bit chunks (avoid lots of 64-bit divides even
 | 
			
		||||
            // with constant denominators).
 | 
			
		||||
            char *o = s - 8;
 | 
			
		||||
            if (n64 >= 100000000)
 | 
			
		||||
            {
 | 
			
		||||
                n = cast(uint) (n64 % 100000000);
 | 
			
		||||
                n64 /= 100000000;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                n = cast(uint) n64;
 | 
			
		||||
                n64 = 0;
 | 
			
		||||
            }
 | 
			
		||||
            while (n)
 | 
			
		||||
            {
 | 
			
		||||
                s -= 2;
 | 
			
		||||
                *cast(ushort*) s = *cast(ushort*) &digitpair[(n % 100) * 2];
 | 
			
		||||
                n /= 100;
 | 
			
		||||
            }
 | 
			
		||||
            while (n)
 | 
			
		||||
            {
 | 
			
		||||
                *--s = cast(char) (n % 10) + '0';
 | 
			
		||||
                n /= 10;
 | 
			
		||||
            }
 | 
			
		||||
            if (n64 == 0)
 | 
			
		||||
            {
 | 
			
		||||
                if ((s[0] == '0') && (s != (num.ptr + num.length)))
 | 
			
		||||
                {
 | 
			
		||||
                    ++s;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            while (s != o)
 | 
			
		||||
            {
 | 
			
		||||
                *--s = '0';
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        tail[0] = 0;
 | 
			
		||||
        leadSign(negative, lead);
 | 
			
		||||
 | 
			
		||||
        // Get the length that we copied.
 | 
			
		||||
        l = cast(uint) ((num.ptr + num.length) - s);
 | 
			
		||||
        if (l == 0)
 | 
			
		||||
        {
 | 
			
		||||
            *--s = '0';
 | 
			
		||||
            l = 1;
 | 
			
		||||
        }
 | 
			
		||||
        if (precision < 0)
 | 
			
		||||
        {
 | 
			
		||||
            precision = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        static assert(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (result.length > 0)
 | 
			
		||||
    {
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
    scopy:
 | 
			
		||||
        // Get fw=leading/trailing space, precision=leading zeros.
 | 
			
		||||
        if (precision < cast(int) l)
 | 
			
		||||
@@ -1004,6 +936,33 @@ scopy:
 | 
			
		||||
 | 
			
		||||
        *bf = 0;
 | 
			
		||||
        result = String(buf[0 .. cast(int) (bf - buf.ptr)]);
 | 
			
		||||
    }
 | 
			
		||||
    else static if (isPointer!(Args[0])) // Pointer
 | 
			
		||||
    {
 | 
			
		||||
        char[size_t.sizeof * 2] buffer;
 | 
			
		||||
        size_t position = buffer.length;
 | 
			
		||||
        auto address = cast(size_t) args[0];
 | 
			
		||||
 | 
			
		||||
        do // Write at least "0" if the pointer is null.
 | 
			
		||||
        {
 | 
			
		||||
            buffer[--position] = lowerHexDigits[cast(size_t) (address & 15)];
 | 
			
		||||
            address >>= 4;
 | 
			
		||||
        }
 | 
			
		||||
        while (address != 0);
 | 
			
		||||
 | 
			
		||||
        result.insertBack("0x");
 | 
			
		||||
        result.insertBack(buffer[position .. $]);
 | 
			
		||||
    }
 | 
			
		||||
    else static if (isIntegral!(Args[0])) // Integer
 | 
			
		||||
    {
 | 
			
		||||
        char[21] buffer;
 | 
			
		||||
        result.insertBack(integral2String(args[0], buffer));
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        static assert(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user