mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-12 13:00:32 +00:00
Add hex float printf support to utf8printf
This commit is contained in:
@@ -433,12 +433,17 @@ void PrintInteger(bool typeUnsigned, uint64_t argu, int base, uint64_t numbits,
|
||||
}
|
||||
}
|
||||
|
||||
void PrintFloat0(bool e, bool f, FormatterParams formatter, char prepend, char *&output,
|
||||
size_t &actualsize, char *end)
|
||||
void PrintFloat0(bool e, bool f, bool a, bool uppercaseDigits, FormatterParams formatter,
|
||||
char prepend, char *&output, size_t &actualsize, char *end)
|
||||
{
|
||||
int numwidth = 0;
|
||||
|
||||
if(e)
|
||||
if(a && formatter.Precision == FormatterParams::NoPrecision)
|
||||
formatter.Precision = 0;
|
||||
|
||||
if(a)
|
||||
numwidth = formatter.Precision + 1 + 5; // 0 plus precision plus 0xp+0
|
||||
else if(e)
|
||||
numwidth = formatter.Precision + 1 + 4; // 0 plus precision plus e+00
|
||||
else if(f || formatter.Flags & AlternateForm)
|
||||
numwidth = formatter.Precision + 1; // 0 plus precision
|
||||
@@ -446,10 +451,10 @@ void PrintFloat0(bool e, bool f, FormatterParams formatter, char prepend, char *
|
||||
numwidth = 1;
|
||||
|
||||
// alternate form means . is included even if no digits after .
|
||||
if(((e || f) && formatter.Precision > 0) || (formatter.Flags & AlternateForm))
|
||||
if(((e || f || a) && formatter.Precision > 0) || (formatter.Flags & AlternateForm))
|
||||
numwidth++; // .
|
||||
|
||||
if(!e && !f && (formatter.Flags & AlwaysDecimal))
|
||||
if(!e && !f && !a && (formatter.Flags & AlwaysDecimal))
|
||||
{
|
||||
numwidth += 2; // .0
|
||||
}
|
||||
@@ -465,6 +470,9 @@ void PrintFloat0(bool e, bool f, FormatterParams formatter, char prepend, char *
|
||||
|
||||
if(formatter.Flags & PadZeroes)
|
||||
{
|
||||
if(a)
|
||||
appendstring(output, actualsize, end, uppercaseDigits ? "0X" : "0x");
|
||||
|
||||
if(prepend)
|
||||
addchar(output, actualsize, end, prepend);
|
||||
addchars(output, actualsize, end, size_t(padlen), '0');
|
||||
@@ -474,11 +482,17 @@ void PrintFloat0(bool e, bool f, FormatterParams formatter, char prepend, char *
|
||||
addchars(output, actualsize, end, size_t(padlen), ' ');
|
||||
if(prepend)
|
||||
addchar(output, actualsize, end, prepend);
|
||||
|
||||
if(a)
|
||||
appendstring(output, actualsize, end, uppercaseDigits ? "0X" : "0x");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(prepend)
|
||||
addchar(output, actualsize, end, prepend);
|
||||
|
||||
if(a)
|
||||
appendstring(output, actualsize, end, uppercaseDigits ? "0X" : "0x");
|
||||
}
|
||||
|
||||
// print a .0 for all cases except non-alternate %g
|
||||
@@ -492,6 +506,18 @@ void PrintFloat0(bool e, bool f, FormatterParams formatter, char prepend, char *
|
||||
if(e)
|
||||
appendstring(output, actualsize, end, "e+00");
|
||||
}
|
||||
else if(a)
|
||||
{
|
||||
if(formatter.Precision == 0)
|
||||
{
|
||||
addchar(output, actualsize, end, '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
appendstring(output, actualsize, end, "0.");
|
||||
addchars(output, actualsize, end, size_t(formatter.Precision), '0');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addchar(output, actualsize, end, '0');
|
||||
@@ -503,13 +529,16 @@ void PrintFloat0(bool e, bool f, FormatterParams formatter, char prepend, char *
|
||||
}
|
||||
}
|
||||
|
||||
if(a)
|
||||
appendstring(output, actualsize, end, "p+0");
|
||||
|
||||
if(padlen > 0 && (formatter.Flags & LeftJustify))
|
||||
{
|
||||
addchars(output, actualsize, end, size_t(padlen), ' ');
|
||||
}
|
||||
}
|
||||
|
||||
void PrintFloat(double argd, FormatterParams &formatter, bool e, bool f, bool g,
|
||||
void PrintFloat(double argd, FormatterParams &formatter, bool e, bool f, bool g, bool a,
|
||||
bool uppercaseDigits, char *&output, size_t &actualsize, char *end)
|
||||
{
|
||||
// extract the pieces out of the double
|
||||
@@ -531,7 +560,7 @@ void PrintFloat(double argd, FormatterParams &formatter, bool e, bool f, bool g,
|
||||
// special-case handling of printing 0
|
||||
if(rawexp == 0 && mantissa == 0)
|
||||
{
|
||||
PrintFloat0(e, f, formatter, prepend, output, actualsize, end);
|
||||
PrintFloat0(e, f, a, uppercaseDigits, formatter, prepend, output, actualsize, end);
|
||||
}
|
||||
// handle 'special' values, inf and nan
|
||||
else if(rawexp == 0x7ff)
|
||||
@@ -548,6 +577,198 @@ void PrintFloat(double argd, FormatterParams &formatter, bool e, bool f, bool g,
|
||||
appendstring(output, actualsize, end, uppercaseDigits ? "NAN" : "nan");
|
||||
}
|
||||
}
|
||||
else if(a)
|
||||
{
|
||||
char digits[18] = {0};
|
||||
int ndigits = 0;
|
||||
|
||||
for(int d = 12; mantissa && d >= 0; d--)
|
||||
{
|
||||
const uint64_t mask = 0xfULL << (d * 4);
|
||||
const uint64_t digit = (mantissa & mask) >> (d * 4);
|
||||
|
||||
char c = char('0' + digit);
|
||||
if(digit >= 10)
|
||||
c = char((uppercaseDigits ? 'A' : 'a') + digit - 10);
|
||||
|
||||
digits[ndigits++] = c;
|
||||
|
||||
mantissa &= ~mask;
|
||||
}
|
||||
|
||||
// if no precision is specified, drop trailing 0s and ensure we don't pad or trim
|
||||
if(formatter.Precision == FormatterParams::NoPrecision)
|
||||
{
|
||||
while(ndigits > 0 && digits[ndigits - 1] == '0')
|
||||
ndigits--;
|
||||
|
||||
formatter.Precision = ndigits;
|
||||
}
|
||||
|
||||
// hold the carry bit because if it's needed we have no decimals and need to format 0x2p+E
|
||||
// instead of 0x1.Mp+E
|
||||
bool carry = false;
|
||||
|
||||
// see if we need to trim and round
|
||||
if(ndigits > formatter.Precision)
|
||||
{
|
||||
int removedigs = ndigits - formatter.Precision;
|
||||
|
||||
// if we're removing all digits, just check the first to see if it should be
|
||||
// rounded up or down
|
||||
if(removedigs == ndigits)
|
||||
{
|
||||
ndigits = 0;
|
||||
// all hex digits are above '8' in ascii order, so we can do just one comparison
|
||||
carry = (digits[0] >= '8');
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove the specified number of digits
|
||||
ndigits -= removedigs;
|
||||
|
||||
// round up the last digit (continually rolling up if necessary)
|
||||
// note this will look 'ahead' into the last removed digits at first
|
||||
carry = true;
|
||||
for(int i = ndigits - 1; i >= 0; i--)
|
||||
{
|
||||
// should we round up?
|
||||
if(digits[i + 1] >= '8')
|
||||
{
|
||||
digits[i + 1] = 0;
|
||||
|
||||
// unless current digit is an f, we can just increment it and stop
|
||||
if(digits[i] != 'f' && digits[i] != 'F')
|
||||
{
|
||||
if(digits[i] != '9')
|
||||
digits[i]++;
|
||||
else
|
||||
digits[i] = uppercaseDigits ? 'A' : 'a';
|
||||
carry = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// continue (carry to next digit)
|
||||
}
|
||||
else
|
||||
{
|
||||
// didn't need to round up, everything's fine.
|
||||
carry = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// trim off a digit (was an f/F)
|
||||
ndigits--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(digits[0] == '0' && !carry && ndigits == 0)
|
||||
{
|
||||
// if we rounded off to a 0.0, print it with special handling
|
||||
PrintFloat0(e, f, a, uppercaseDigits, formatter, prepend, output, actualsize, end);
|
||||
}
|
||||
|
||||
int padtrailing0s = formatter.Precision - ndigits;
|
||||
|
||||
{
|
||||
int numwidth = 0;
|
||||
|
||||
// first calculate the width of the produced output, so we can calculate any padding
|
||||
|
||||
numwidth = 3; // 0x1
|
||||
numwidth += ndigits; // post-decimal digits
|
||||
if(ndigits > 0 || (formatter.Flags & AlternateForm) || padtrailing0s > 0)
|
||||
numwidth++; // '.'
|
||||
numwidth += padtrailing0s;
|
||||
numwidth += 2; // 'p+' or 'p-'
|
||||
if(exponent >= 0xff || exponent <= -0xff)
|
||||
numwidth += 3;
|
||||
else if(exponent >= 0xf || exponent <= -0xf)
|
||||
numwidth += 2;
|
||||
else
|
||||
numwidth += 1;
|
||||
if(prepend)
|
||||
numwidth++; // +, - or ' '
|
||||
|
||||
int padlen = 0;
|
||||
|
||||
if(formatter.Width != FormatterParams::NoWidth && formatter.Width > numwidth)
|
||||
padlen = formatter.Width - numwidth;
|
||||
|
||||
// pad with 0s or ' 's and insert the sign character
|
||||
if(formatter.Flags & PadZeroes)
|
||||
{
|
||||
if(a)
|
||||
appendstring(output, actualsize, end, uppercaseDigits ? "0X" : "0x");
|
||||
|
||||
if(prepend)
|
||||
addchar(output, actualsize, end, prepend);
|
||||
addchars(output, actualsize, end, size_t(padlen), '0');
|
||||
}
|
||||
else if(padlen > 0 && (formatter.Flags & LeftJustify) == 0)
|
||||
{
|
||||
addchars(output, actualsize, end, size_t(padlen), ' ');
|
||||
if(prepend)
|
||||
addchar(output, actualsize, end, prepend);
|
||||
|
||||
if(a)
|
||||
appendstring(output, actualsize, end, uppercaseDigits ? "0X" : "0x");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(prepend)
|
||||
addchar(output, actualsize, end, prepend);
|
||||
|
||||
if(a)
|
||||
appendstring(output, actualsize, end, uppercaseDigits ? "0X" : "0x");
|
||||
}
|
||||
|
||||
if(carry)
|
||||
addchar(output, actualsize, end, '2');
|
||||
else
|
||||
addchar(output, actualsize, end, '1');
|
||||
|
||||
// insert the decimals
|
||||
if(ndigits > 0 || (formatter.Flags & AlternateForm) || padtrailing0s > 0)
|
||||
addchar(output, actualsize, end, '.');
|
||||
for(int i = 0; i < ndigits; i++)
|
||||
addchar(output, actualsize, end, digits[i]);
|
||||
|
||||
// add the trailing 0s here
|
||||
if(padtrailing0s > 0)
|
||||
addchars(output, actualsize, end, size_t(padtrailing0s), '0');
|
||||
|
||||
// print the p+XXX exponential
|
||||
addchar(output, actualsize, end, uppercaseDigits ? 'P' : 'p');
|
||||
if(exponent >= 0)
|
||||
addchar(output, actualsize, end, '+');
|
||||
else
|
||||
addchar(output, actualsize, end, '-');
|
||||
|
||||
int exponaccum = exponent >= 0 ? exponent : -exponent;
|
||||
|
||||
if(exponaccum >= 1000)
|
||||
addchar(output, actualsize, end, '0' + char(exponaccum / 1000));
|
||||
exponaccum %= 1000;
|
||||
|
||||
if(exponaccum >= 100)
|
||||
addchar(output, actualsize, end, '0' + char(exponaccum / 100));
|
||||
exponaccum %= 100;
|
||||
|
||||
if(exponaccum >= 10)
|
||||
addchar(output, actualsize, end, '0' + char(exponaccum / 10));
|
||||
exponaccum %= 10;
|
||||
|
||||
addchar(output, actualsize, end, '0' + char(exponaccum));
|
||||
|
||||
if(padlen > 0 && (formatter.Flags & LeftJustify))
|
||||
{
|
||||
addchars(output, actualsize, end, size_t(padlen), ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// call out to grisu2 to generate digits + exponent
|
||||
@@ -763,7 +984,7 @@ void PrintFloat(double argd, FormatterParams &formatter, bool e, bool f, bool g,
|
||||
else if(digits[0] == '0' && ndigits == 1)
|
||||
{
|
||||
// if we rounded off to a 0.0, print it with special handling
|
||||
PrintFloat0(e, f, formatter, prepend, output, actualsize, end);
|
||||
PrintFloat0(e, f, a, uppercaseDigits, formatter, prepend, output, actualsize, end);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1151,19 +1372,25 @@ void formatargument(char type, void *rawarg, FormatterParams formatter, char *&o
|
||||
PrintInteger(typeUnsigned, argu, base, numbits, formatter, uppercaseDigits, output, actualsize,
|
||||
end);
|
||||
}
|
||||
else if(type == 'e' || type == 'E' || type == 'f' || type == 'F' || type == 'g' || type == 'G'
|
||||
//|| type == 'a' || type == 'A' // hex floats not supported
|
||||
)
|
||||
else if(type == 'e' || type == 'E' || type == 'f' || type == 'F' || type == 'g' || type == 'G' ||
|
||||
type == 'a' || type == 'A')
|
||||
{
|
||||
bool uppercaseDigits = type < 'a';
|
||||
double argd = *(double *)rawarg;
|
||||
|
||||
if(formatter.Precision == FormatterParams::NoPrecision)
|
||||
bool e = (type == 'e' || type == 'E');
|
||||
bool f = (type == 'f' || type == 'F');
|
||||
bool g = (type == 'g' || type == 'G');
|
||||
bool a = (type == 'a' || type == 'A');
|
||||
|
||||
if(!a && formatter.Precision == FormatterParams::NoPrecision)
|
||||
{
|
||||
formatter.Precision = 6;
|
||||
|
||||
formatter.Precision = RDCMAX(0, formatter.Precision);
|
||||
formatter.Precision = RDCMAX(0, formatter.Precision);
|
||||
}
|
||||
|
||||
if(formatter.Precision == 0)
|
||||
if(!a && formatter.Precision == 0)
|
||||
{
|
||||
if(argd > 0.0f && argd < 1.0f)
|
||||
argd = argd < 0.5f ? 0.0f : 1.0f;
|
||||
@@ -1171,11 +1398,7 @@ void formatargument(char type, void *rawarg, FormatterParams formatter, char *&o
|
||||
argd = argd > -0.5f ? 0.0f : -1.0f;
|
||||
}
|
||||
|
||||
bool e = (type == 'e' || type == 'E');
|
||||
bool f = (type == 'f' || type == 'F');
|
||||
bool g = (type == 'g' || type == 'G');
|
||||
|
||||
PrintFloat(argd, formatter, e, f, g, uppercaseDigits, output, actualsize, end);
|
||||
PrintFloat(argd, formatter, e, f, g, a, uppercaseDigits, output, actualsize, end);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1295,25 +1518,33 @@ int utf8printv(char *buf, size_t bufsize, const char *fmt, va_list args)
|
||||
{
|
||||
iter++;
|
||||
|
||||
// invalid character following '.' it should be an integer
|
||||
// note standard printf supports * here to read precision from a vararg
|
||||
if(*iter < '0' || *iter > '9')
|
||||
RDCDUMPMSG("Unexpected character expecting precision");
|
||||
|
||||
formatter.Precision = int(*iter - '0');
|
||||
iter++; // step to next character
|
||||
|
||||
// continue while encountering digits, accumulating into width
|
||||
while(*iter >= '0' && *iter <= '9')
|
||||
if(*iter == '*')
|
||||
{
|
||||
formatter.Precision *= 10;
|
||||
formatter.Precision += int(*iter - '0');
|
||||
iter++;
|
||||
RDCDUMPMSG("Unexpected character * expecting precision");
|
||||
}
|
||||
// if there's no value for the precision, it is 0
|
||||
else if(*iter < '0' || *iter > '9')
|
||||
{
|
||||
formatter.Precision = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
formatter.Precision = int(*iter - '0');
|
||||
iter++; // step to next character
|
||||
|
||||
// unterminated formatter
|
||||
if(*iter == 0)
|
||||
RDCDUMPMSG("Unterminated % formatter found after precision");
|
||||
// continue while encountering digits, accumulating into width
|
||||
while(*iter >= '0' && *iter <= '9')
|
||||
{
|
||||
formatter.Precision *= 10;
|
||||
formatter.Precision += int(*iter - '0');
|
||||
iter++;
|
||||
}
|
||||
|
||||
// unterminated formatter
|
||||
if(*iter == 0)
|
||||
RDCDUMPMSG("Unterminated % formatter found after precision");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1376,7 +1607,8 @@ int utf8printv(char *buf, size_t bufsize, const char *fmt, va_list args)
|
||||
void **p = (void **)arg;
|
||||
*p = va_arg(args, void *);
|
||||
}
|
||||
else if(type == 'e' || type == 'E' || type == 'f' || type == 'F' || type == 'g' || type == 'G')
|
||||
else if(type == 'e' || type == 'E' || type == 'f' || type == 'F' || type == 'g' ||
|
||||
type == 'G' || type == 'a' || type == 'A')
|
||||
{
|
||||
double *i = (double *)arg;
|
||||
*i = va_arg(args, double);
|
||||
@@ -1841,6 +2073,36 @@ TEST_CASE("utf8printf printing floats", "[utf8printf]")
|
||||
CHECK(StringFormat::Fmt("%F", sqrt(negone)) == "NAN");
|
||||
CHECK(StringFormat::Fmt("%F", -sqrt(negone)) == "NAN");
|
||||
|
||||
CHECK(StringFormat::Fmt("%g", one / zero) == "+inf");
|
||||
CHECK(StringFormat::Fmt("%g", negone / zero) == "-inf");
|
||||
CHECK(StringFormat::Fmt("%g", sqrt(negone)) == "nan");
|
||||
CHECK(StringFormat::Fmt("%g", -sqrt(negone)) == "nan");
|
||||
|
||||
CHECK(StringFormat::Fmt("%G", one / zero) == "+INF");
|
||||
CHECK(StringFormat::Fmt("%G", negone / zero) == "-INF");
|
||||
CHECK(StringFormat::Fmt("%G", sqrt(negone)) == "NAN");
|
||||
CHECK(StringFormat::Fmt("%G", -sqrt(negone)) == "NAN");
|
||||
|
||||
CHECK(StringFormat::Fmt("%e", one / zero) == "+inf");
|
||||
CHECK(StringFormat::Fmt("%e", negone / zero) == "-inf");
|
||||
CHECK(StringFormat::Fmt("%e", sqrt(negone)) == "nan");
|
||||
CHECK(StringFormat::Fmt("%e", -sqrt(negone)) == "nan");
|
||||
|
||||
CHECK(StringFormat::Fmt("%E", one / zero) == "+INF");
|
||||
CHECK(StringFormat::Fmt("%E", negone / zero) == "-INF");
|
||||
CHECK(StringFormat::Fmt("%E", sqrt(negone)) == "NAN");
|
||||
CHECK(StringFormat::Fmt("%E", -sqrt(negone)) == "NAN");
|
||||
|
||||
CHECK(StringFormat::Fmt("%a", one / zero) == "+inf");
|
||||
CHECK(StringFormat::Fmt("%a", negone / zero) == "-inf");
|
||||
CHECK(StringFormat::Fmt("%a", sqrt(negone)) == "nan");
|
||||
CHECK(StringFormat::Fmt("%a", -sqrt(negone)) == "nan");
|
||||
|
||||
CHECK(StringFormat::Fmt("%A", one / zero) == "+INF");
|
||||
CHECK(StringFormat::Fmt("%A", negone / zero) == "-INF");
|
||||
CHECK(StringFormat::Fmt("%A", sqrt(negone)) == "NAN");
|
||||
CHECK(StringFormat::Fmt("%A", -sqrt(negone)) == "NAN");
|
||||
|
||||
// subnormal value
|
||||
CHECK(StringFormat::Fmt("%.8e", 1.23456789e-310) == "1.23456789e-310");
|
||||
CHECK(StringFormat::Fmt("%.8e", -1.23456789e-310) == "-1.23456789e-310");
|
||||
@@ -1949,6 +2211,66 @@ TEST_CASE("utf8printf printing floats", "[utf8printf]")
|
||||
CHECK(StringFormat::Fmt("%-10.3f", 1.0) == "1.000 ");
|
||||
CHECK(StringFormat::Fmt("%010.3f", 1.0) == "000001.000");
|
||||
};
|
||||
|
||||
SECTION("Hex float printing")
|
||||
{
|
||||
SECTION("Basics")
|
||||
{
|
||||
CHECK(StringFormat::Fmt("%a", 0.0) == "0x0p+0");
|
||||
CHECK(StringFormat::Fmt("%a", 1.0) == "0x1p+0");
|
||||
CHECK(StringFormat::Fmt("%a", 2.0) == "0x1p+1");
|
||||
CHECK(StringFormat::Fmt("%a", 3.0) == "0x1.8p+1");
|
||||
CHECK(StringFormat::Fmt("%a", 5.0) == "0x1.4p+2");
|
||||
CHECK(StringFormat::Fmt("%a", 0.1) == "0x1.999999999999ap-4");
|
||||
CHECK(StringFormat::Fmt("%a", 0.2) == "0x1.999999999999ap-3");
|
||||
CHECK(StringFormat::Fmt("%a", 0.25) == "0x1p-2");
|
||||
CHECK(StringFormat::Fmt("%a", 0.75) == "0x1.8p-1");
|
||||
CHECK(StringFormat::Fmt("%a", 1.234567890123456) == "0x1.3c0ca428c59f8p+0");
|
||||
CHECK(StringFormat::Fmt("%a", 1.234567123456) == "0x1.3c0c974bf5d73p+0");
|
||||
CHECK(StringFormat::Fmt("%a", 12345671234.56) == "0x1.6fedff2147ae1p+33");
|
||||
CHECK(StringFormat::Fmt("%a", 12345671234.56e+20) == "0x1.f2a33fa95047cp+99");
|
||||
CHECK(StringFormat::Fmt("%a", 12345671234.56e-20) == "0x1.0f7bf351a448p-33");
|
||||
|
||||
CHECK(StringFormat::Fmt("%A", 1.234567890123456) == "0X1.3C0CA428C59F8P+0");
|
||||
CHECK(StringFormat::Fmt("%A", 1.234567123456) == "0X1.3C0C974BF5D73P+0");
|
||||
CHECK(StringFormat::Fmt("%A", 12345671234.56) == "0X1.6FEDFF2147AE1P+33");
|
||||
CHECK(StringFormat::Fmt("%A", 12345671234.56e+20) == "0X1.F2A33FA95047CP+99");
|
||||
CHECK(StringFormat::Fmt("%A", 12345671234.56e-20) == "0X1.0F7BF351A448P-33");
|
||||
};
|
||||
|
||||
SECTION("Padding")
|
||||
{
|
||||
CHECK(StringFormat::Fmt("%10.3a", 1.2345) == "0x1.3c1p+0");
|
||||
CHECK(StringFormat::Fmt("%15.3a", 1.2345) == " 0x1.3c1p+0");
|
||||
CHECK(StringFormat::Fmt("%-15.3a", 1.2345) == "0x1.3c1p+0 ");
|
||||
CHECK(StringFormat::Fmt("%015.3a", 1.2345) == "0x000001.3c1p+0");
|
||||
};
|
||||
|
||||
SECTION("Precision")
|
||||
{
|
||||
CHECK(StringFormat::Fmt("%.3a", 0.0) == "0x0.000p+0");
|
||||
CHECK(StringFormat::Fmt("%.3a", 1.0) == "0x1.000p+0");
|
||||
CHECK(StringFormat::Fmt("%.3a", 2.0) == "0x1.000p+1");
|
||||
CHECK(StringFormat::Fmt("%.3a", 0.1) == "0x1.99ap-4");
|
||||
CHECK(StringFormat::Fmt("%.3a", 0.2) == "0x1.99ap-3");
|
||||
CHECK(StringFormat::Fmt("%.3a", 1.2313) == "0x1.3b3p+0");
|
||||
|
||||
CHECK(StringFormat::Fmt("%.0a", 0.0) == "0x0p+0");
|
||||
|
||||
CHECK(StringFormat::Fmt("%.1a", 0.2) == "0x1.ap-3");
|
||||
CHECK(StringFormat::Fmt("%.0a", 0.2) == "0x2p-3");
|
||||
CHECK(StringFormat::Fmt("%.a", 0.2) == "0x2p-3");
|
||||
};
|
||||
|
||||
SECTION("Rounding")
|
||||
{
|
||||
CHECK(StringFormat::Fmt("%.5a", 0.12345) == "0x1.f9a6bp-4");
|
||||
CHECK(StringFormat::Fmt("%.6a", 0.12345) == "0x1.f9a6b5p-4");
|
||||
|
||||
CHECK(StringFormat::Fmt("%.5a", 0.12345002) == "0x1.f9a6cp-4");
|
||||
CHECK(StringFormat::Fmt("%.6a", 0.12345002) == "0x1.f9a6bap-4");
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#endif // ENABLED(ENABLE_UNIT_TESTS)
|
||||
|
||||
Reference in New Issue
Block a user