Core: Integer formatting optimised

This commit is contained in:
Mirek Fidler 2021-08-04 11:24:05 +02:00
parent c92411c84d
commit 1d018151f1
7 changed files with 386 additions and 174 deletions

56
autotest/itos/itos.cpp Normal file
View file

@ -0,0 +1,56 @@
#include <Core/Core.h>
using namespace Upp;
void Test(int64 x)
{
for(int pass = 0; pass < 2; pass++) {
ASSERT(AsString((int16)x) == String(std::to_string((int16)x)));
ASSERT(AsString((uint16)x) == String(std::to_string((uint16)x)));
if(IsNull((int)x))
ASSERT(AsString((int)x).GetCount() == 0);
else
ASSERT(AsString((int32)x) == String(std::to_string((int32)x)));
ASSERT(AsString((uint32)x) == String(std::to_string((uint32)x)));
if(IsNull((int64)x))
ASSERT(AsString((int64)x).GetCount() == 0);
else
ASSERT(AsString((int64)x) == String(std::to_string((int64)x)));
ASSERT(AsString((uint64)x) == String(std::to_string((uint64)x)));
x = -x;
}
}
CONSOLE_APP_MAIN
{
StdLogSetup(LOG_COUT|LOG_FILE);
/*
DDUMP(AsString((uint64)-2));
DDUMP(String(std::to_string((uint64)-2)));
return;
*/
for(int q = 2; q < 10; q++) {
uint64 qq = q;
for(int i = 0; i < 64; i++) {
DUMP(qq);
Test(qq);
qq += qq;
}
}
for(int q = 2; q < 10; q++) {
uint64 qq = q;
for(int i = 0; i < 64; i++) {
DUMP(qq);
Test(qq);
qq += qq - 1;
}
}
for(int i = 0; i < 1000000; i++)
Test(Random64());
Test((int)Null);
Test((int64)Null);
LOG("================ OK");
}

9
autotest/itos/itos.upp Normal file
View file

@ -0,0 +1,9 @@
uses
Core;
file
itos.cpp;
mainconfig
"" = "";

View file

@ -205,3 +205,23 @@ const CHAR *ScanDbl(double& result, const CHAR *s, int alt_dp = '.')
result = number;
return s;
}
inline
String FormatUnsigned(dword w)
{
return String::MakeSmall([&](char *s) { return utoa32(w, s); });
}
inline
String FormatInt(int i)
{
return String::MakeSmall([&](char *s) {
if(IsNull(i))
return 0;
if(i < 0) {
*s++ = '-';
return utoa32(-i, s) + 1;
}
return utoa32(i, s);
});
}

View file

@ -27,6 +27,159 @@ String VFormat(const char *fmt, va_list ptr) {
// Formatting routines ---------------------------
// utoa32, utoa64 inspired by
// https://github.com/miloyip/itoa-benchmark/blob/940542a7770155ee3e9f2777ebc178dc899b43e0/src/branchlut.cpp
// by Milo Yip
namespace utoa_private {
const char s100[] =
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
;
force_inline
void Do2(char *t, dword d) {
#ifdef CPU_UNALIGNED
*(word *)t = *((word *)s100 + d);
#else
auto Copy2 = [](char *t, dword d) {
t[0] = s[2 * d];
t[1] = s[2 * d + 1];
};
#endif
};
force_inline
void Do4(char *t, dword value) {
Do2(t, value / 100);
Do2(t + 2, value % 100);
}
force_inline
void Do8(char *t, dword value) {
Do4(t, value / 10000);
Do4(t + 4, value % 10000);
}
};
int utoa32(dword value, char *buffer)
{
using namespace utoa_private;
if (value < 10000) {
if(value < 100) {
if(value < 10) {
*buffer = value + '0';
return 1;
}
Do2(buffer, value % 100);
return 2;
}
if(value < 1000) {
*buffer = value / 100 + '0';
Do2(buffer + 1, value % 100);
return 3;
}
Do4(buffer, value);
return 4;
}
else if (value < 100000000) {
if(value < 10000000) {
if(value < 100000) {
*buffer = value / 10000 + '0';
Do4(buffer + 1, value % 10000);
return 5;
}
if(value < 1000000) {
Do2(buffer, value / 10000);
Do4(buffer + 2, value % 10000);
return 6;
}
*buffer = value / 1000000 + '0';
Do2(buffer + 1, value / 10000 % 100);
Do4(buffer + 3, value % 10000);
return 7;
}
Do8(buffer, value);
return 8;
}
else {
dword a = value / 100000000; // 2 digits
value %= 100000000;
if(a < 10) {
*buffer = a + '0';
Do8(buffer + 1, value);
return 9;
}
Do2(buffer, a);
Do8(buffer + 2, value);
return 10;
}
}
int utoa64(uint64 value, char *buffer)
{
using namespace utoa_private;
if(value <= 0xffffffff)
return utoa32((dword)value, buffer);
if(value < (uint64)1000000000 * 100000000) {
int q = utoa32(value / 100000000, buffer);
Do8(buffer + q, value % 100000000);
return q + 8;
}
int q = utoa32(value / ((uint64)100000000 * 100000000), buffer);
Do8(buffer + q, value / 100000000 % 100000000);
Do8(buffer + 8 + q, value % 100000000);
return q + 16;
}
String FormatUInt64(uint64 w)
{
if(w < 100000000000000)
return String::MakeSmall([&](char *s) { return utoa64(w, s); });
char h[32];
return String(h, utoa64(w, h));
}
String FormatInt64(int64 i)
{
if(IsNull(i))
return String();
if(i < 0) {
i = -i;
if(i < 10000000000000) {
return String::MakeSmall([&](char *s) {
*s++ = '-';
return utoa64(i, s) + 1;
});
}
char h[32];
*h = '-';
return String(h, utoa64(i, h + 1) + 1);
}
if(i < 100000000000000) {
return String::MakeSmall([&](char *s) { return utoa64(i, s); });
}
char h[32];
return String(h, utoa64(i, h));
}
String FormatIntBase(int i, int base, int width, char lpad, int sign, bool upper)
{
enum { BUFFER = sizeof(int) * 8 + 1 };
@ -67,11 +220,6 @@ String FormatIntBase(int i, int base, int width, char lpad, int sign, bool upper
return String(out);
}
String FormatInt(int i)
{
return FormatIntBase(i, 10, 0, ' ', 0);
}
String FormatIntDec(int i, int width, char lpad, bool always_sign)
{
return FormatIntBase(i, 10, width, lpad, always_sign ? 1 : 0);
@ -152,18 +300,6 @@ String FormatIntRoman(int i, bool upper)
return out;
}
String Format64(uint64 a)
{
char b[50];
char *p = b + 50;
do {
*--p = char(a % 10 + '0');
a /= 10;
}
while(a);
return String(p, b + 50);
}
String Format64Hex(uint64 a)
{
char b[50];
@ -176,17 +312,10 @@ String Format64Hex(uint64 a)
return String(p, b + 50);
}
String FormatInteger(int a) { return IsNull(a) ? String() : FormatInt(a); }
String FormatUnsigned(unsigned long a) { return Sprintf("%u", a); }
String FormatDouble(double a) { return IsNull(a) ? String() : IsNaN(a) || IsInf(a) ? "?" : FormatDouble(a, 17, FD_REL); }
String FormatBool(bool a) { return a ? "true" : "false"; }
String FormatPtr(const void *p) { return "0x" + FormatHex(p); }
String FormatInt64(int64 a)
{
return IsNull(a) ? String() : a < 0 ? "-" + Format64(-a) : Format64(a);
}
static char *PutDigits(char *out, unsigned number, int count)
{
char temp[10];

View file

@ -1,12 +1,18 @@
int utoa32(dword value, char *buffer);
int utoa64(uint64 value, char *buffer);
String FormatUnsigned(dword w);
String FormatInt(int i);
String FormatUInt64(uint64 w);
String FormatInt64(int64 i);
String FormatIntBase(int i, int base, int width = 0, char lpad = ' ', int sign = 0, bool upper = false);
String FormatInt(int i);
String FormatIntDec(int i, int width, char lpad = ' ', bool always_sign = false);
String FormatIntHex(int i, int width = 8, char lpad = '0');
String FormatIntHexUpper(int i, int width = 8, char lpad = '0');
String FormatIntOct(int i, int width = 12, char lpad = '0');
String FormatIntRoman(int i, bool upper = false);
String FormatIntAlpha(int i, bool upper = true);
String Format64(uint64 a);
String Format64Hex(uint64 a);
#ifdef CPU_64
@ -17,22 +23,23 @@ inline String FormatIntHex(const void *ptr) { return FormatIntHex((int)(uintptr
inline String FormatHex(const void *ptr) { return FormatIntHex((int)(uintptr_t)ptr); }
#endif
String FormatInteger(int a);
String FormatInt64(int64 a);
String FormatUnsigned(unsigned long a);
String FormatDouble(double a);
String FormatBool(bool a);
template<> inline String AsString(const short& a) { return FormatInteger(a); }
template<> inline String AsString(const short& a) { return FormatInt(a); }
template<> inline String AsString(const unsigned short& a) { return FormatUnsigned(a); }
template<> inline String AsString(const int& a) { return FormatInteger(a); }
template<> inline String AsString(const int& a) { return FormatInt(a); }
template<> inline String AsString(const unsigned int& a) { return FormatUnsigned(a); }
template<> inline String AsString(const long& a) { return FormatInt64(a); }
template<> inline String AsString(const unsigned long& a) { return Format64(a); }
template<> inline String AsString(const unsigned long& a) { return FormatUInt64(a); }
template<> inline String AsString(const int64& a) { return FormatInt64(a); }
template<> inline String AsString(const uint64& a) { return FormatUInt64(a); }
template<> inline String AsString(const double& a) { return FormatDouble(a); }
template<> inline String AsString(const float& a) { return FormatDouble(a); }
template<> inline String AsString(const int64& a) { return FormatInt64(a); }
template<> inline String AsString(const uint64& a) { return Format64(a); }
// deprecated
inline String FormatInteger(int a) { return FormatInt(a); }
inline String Format64(uint64 a) { return FormatUInt64(a); }
enum
{

View file

@ -337,8 +337,6 @@ public:
void Reserve(int r);
// String0& operator=(const String0& s) { Free(); Set0(s); return *this; }
String0() {}
~String0() { Free(); }
};
@ -398,14 +396,13 @@ public:
static String GetVoid();
bool IsVoid() const;
enum SmallHint { SMALL_HINT };
String(const char *s, int n, SmallHint) { ASSERT(n <= 14); Zero(); SLen() = n; memcpy8(chr, s, n); Dsyn(); }
friend void Swap(String& a, String& b) { a.Swap(b); }
String(const std::string& s) { String0::Set0(s.c_str(), (int)s.length()); }
std::string ToStd() const { return std::string(Begin(), End()); }
template <class Maker>
static String MakeSmall(Maker m) { String s; int n = m(s.chr); ASSERT(n <= 14); s.SLen() = n; s.Dsyn(); return s; }
};
inline std::string to_string(const String& s) { return std::string(s.Begin(), s.End()); }

View file

@ -1,5 +1,4 @@
topic "Formatting functions";
[2 $$0,0#00000000000000000000000000000000:Default]
[i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class]
[l288;2 $$2,0#27521748481378242620020725143825:desc]
[0 $$3,0#96390100711032703541132217272105:end]
@ -9,131 +8,126 @@ topic "Formatting functions";
[l288;i1121;b17;O9;~~~.1408;2 $$7,0#10431211400427159095818037425705:param]
[i448;b42;O9;2 $$8,8#61672508125594000341940100500538:tparam]
[b42;2 $$9,9#13035079074754324216151401829390:normal]
[{_}
[ {{10000@(113.42.0) [s0;%% [*@7;4 Number formatting]]}}&]
[2 $$0,0#00000000000000000000000000000000:Default]
[{_}%EN-US
[ {{10000@(113.42.0) [s0; [*@7;4 Number formatting]]}}&]
[s3;%- &]
[s4;%- &]
[s5;:Upp`:`:FormatUnsigned`(Upp`:`:dword`):%- [_^Upp`:`:String^ String]_[* FormatUnsigned
]([_^Upp`:`:dword^ dword]_[*@3 w])&]
[s2; Returns argument as decimal string.&]
[s3; &]
[s5;:FormatIntBase`(int`,int`,int`,char`,int`,bool`): String_[* FormatIntBase]([@(0.0.255) i
[s4; &]
[s5;:FormatInt`(int`):%- [_^String^ String]_[* FormatInt]([@(0.0.255) int]_[*@3 i])&]
[s2; Returns integer as decimal string. If argument is Null, returns
empty string.&]
[s3; &]
[s4;%- &]
[s5;:Upp`:`:FormatUInt64`(Upp`:`:uint64`):%- [_^Upp`:`:String^ String]_[* FormatUInt64]([_^Upp`:`:uint64^ u
int64]_[*@3 w])&]
[s2; Returns argument as decimal string.&]
[s3; &]
[s4;%- &]
[s5;:FormatInt64`(int64`):%- [_^String^ String]_[* FormatInt64]([_^int64^ int64]_[*@3 a])&]
[s2; Returns integer as decimal string. If argument is Null, returns
empty string.&]
[s3; &]
[s4; &]
[s5;:FormatIntBase`(int`,int`,int`,char`,int`,bool`):%- String_[* FormatIntBase]([@(0.0.255) i
nt]_[*@3 i], [@(0.0.255) int]_[*@3 radix], [@(0.0.255) int]_[*@3 width]_`=_[@3 0],
[@(0.0.255) char]_[*@3 lpad]_`=_`'_`', [@(0.0.255) int]_[*@3 sign]_`=_[@3 0],
[@(0.0.255) bool]_[*@3 upper]_`=_[@(0.0.255) false])&]
[s2;%% Formats a signed or unsigned integer [%-*@3 i] in a given [%-*@3 radix]
[s2; Formats a signed or unsigned integer [%-*@3 i] in a given [%-*@3 radix]
with left padding to given [%-*@3 width] with a given [%-*@3 lpad]
character. If [*@3 sign ]is `+1 `= always prepend `'`+`'/`-, if
0 `= auto (`'`-`' only), if `-1, format as unsigned. If [%-*@3 upper]
is true, letters for base > 10 are uppercase. If [%-*@3 i] is Null,
returns empty String.&]
[s3;%% &]
[s4; &]
[s5;:FormatInt`(int`): [_^String^ String]_[* FormatInt]([@(0.0.255) int]_[*@3 i])&]
[s2;%% Outputs decimally formatted signed integer [%-*@3 i] without
`+ or any paddings. Supposed to be quite fast. Equivalent to
FormatIntBase(i, 10).&]
[s3;%% &]
[s4; &]
[s5;:FormatIntDec`(int`,int`,char`,bool`): [_^String^ String]_[* FormatIntDec]([@(0.0.255) i
[s3; &]
[s3; &]
[s4;%- &]
[s5;:FormatIntDec`(int`,int`,char`,bool`):%- [_^String^ String]_[* FormatIntDec]([@(0.0.255) i
nt]_[*@3 i], [@(0.0.255) int]_[*@3 width], [@(0.0.255) char]_[*@3 lpad]_`=_`'_`',
[@(0.0.255) bool]_[*@3 always`_sign]_`=_[@(0.0.255) false])&]
[s2;%% Formats a signed decimal integer [%-*@3 i] with left padding
up to given [%-*@3 width] characters (output longer than this is
not padded) with a given [%-*@3 lpad] character. If [%-*@3 always`_sign
[s2; Formats a signed decimal integer [%-*@3 i] with left padding up
to given [%-*@3 width] characters (output longer than this is not
padded) with a given [%-*@3 lpad] character. If [%-*@3 always`_sign
]is true, start positive numbers with `'`+`' (negative numbers
always start with `'`-`').&]
[s3;%% &]
[s4; &]
[s5;:FormatIntHex`(int`,int`,char`): [_^String^ String]_[* FormatIntHex]([@(0.0.255) int]_[*@3 i
], [@(0.0.255) int]_[*@3 width]_`=_[@3 8], [@(0.0.255) char]_[*@3 lpad]_`=_`'[@3 0]`')&]
[s2;~~~.1152;%% Formats an unsigned hexadecimal (radix 16) integer
[s3; &]
[s4;%- &]
[s5;:FormatIntHex`(int`,int`,char`):%- [_^String^ String]_[* FormatIntHex]([@(0.0.255) int]_
[*@3 i], [@(0.0.255) int]_[*@3 width]_`=_[@3 8], [@(0.0.255) char]_[*@3 lpad]_`=_`'[@3 0]`')&]
[s2;~~~.1152; Formats an unsigned hexadecimal (radix 16) integer
[%-*@3 i] with left padding up to given [%-*@3 width] characters
(output longer than this is not padded) with a given [%-*@3 lpad]
character.&]
[s3;%% &]
[s4; &]
[s5;:FormatIntOct`(int`,int`,char`): [_^String^ String]_[* FormatIntOct]([@(0.0.255) int]_[*@3 i
], [@(0.0.255) int]_[*@3 width]_`=_[@3 12], [@(0.0.255) char]_[*@3 lpad]_`=_`'[@3 0]`')&]
[s2;%% Formats an unsigned octal (radix 8) integer [%-*@3 i] with left
[s3; &]
[s4;%- &]
[s5;:FormatIntOct`(int`,int`,char`):%- [_^String^ String]_[* FormatIntOct]([@(0.0.255) int]_
[*@3 i], [@(0.0.255) int]_[*@3 width]_`=_[@3 12], [@(0.0.255) char]_[*@3 lpad]_`=_`'[@3 0]`')&]
[s2; Formats an unsigned octal (radix 8) integer [%-*@3 i] with left
padding up to given [%-*@3 width] characters (output longer than
this is not padded) with a given [%-*@3 lpad] character.&]
[s3;%% &]
[s4; &]
[s5;:FormatIntRoman`(int`,bool`): [_^String^ String]_[* FormatIntRoman]([@(0.0.255) int]_[*@3 i
], [@(0.0.255) bool]_[*@3 upper]_`=_[@(0.0.255) false])&]
[s2;%% Formats a signed integer [%-*@3 i] in Roman numerals. The biggest
[s3; &]
[s4;%- &]
[s5;:FormatIntRoman`(int`,bool`):%- [_^String^ String]_[* FormatIntRoman]([@(0.0.255) int]_
[*@3 i], [@(0.0.255) bool]_[*@3 upper]_`=_[@(0.0.255) false])&]
[s2; Formats a signed integer [%-*@3 i] in Roman numerals. The biggest
`"implemented`" numeral is M (1000), so expect quite a long return
string when formatting a billion. Negative numbers are prepended
with `[`-`], 0 or Null is output as a Null String. If [%-*@3 upper]
is true, use uppercase `[true`] or lowercase `[false`] letters&]
[s3;%% &]
[s4; &]
[s5;:FormatIntAlpha`(int`,bool`): [_^String^ String]_[* FormatIntAlpha]([@(0.0.255) int]_[*@3 i
], [@(0.0.255) bool]_[*@3 upper]_`=_[@(0.0.255) true])&]
[s2;%% Formats a signed integer [%-*@3 i] in length`-first lexicographic
[s3; &]
[s4;%- &]
[s5;:FormatIntAlpha`(int`,bool`):%- [_^String^ String]_[* FormatIntAlpha]([@(0.0.255) int]_
[*@3 i], [@(0.0.255) bool]_[*@3 upper]_`=_[@(0.0.255) true])&]
[s2; Formats a signed integer [%-*@3 i] in length`-first lexicographic
index, i.e. excel column numbering (1 `= A,2 `= B.. 26 `= Z,
27 `= AA, 28 `= AB .. 52 `= AZ, 53 `= BA ... 78 `= BZ etc). 0
or Null is output as a Null String. Only negative numbers are
prepended with a `[`-`]. If [%-*@3 upper] is true, use uppercase
letter.&]
[s3;%% &]
[s4; &]
[s5;:Format64`(uint64`): [_^String^ String]_[* Format64]([_^uint64^ uint64]_[*@3 a])&]
[s2;%% Formats an unsigned decimal 64`-bit integer [%-*@3 a]. Supposed
to be quite fast.&]
[s3;%% &]
[s4; &]
[s5;:Format64Hex`(uint64`): [_^String^ String]_[* Format64Hex]([_^uint64^ uint64]_[*@3 a])&]
[s2;%% Formats an unsigned hexadecimal [%-*@3 a] (radix 16) 64`-bit
integer. Supposed to be quite fast. Lowecase letters a`-f are
used for digits `[10`] through `[15`].&]
[s3;%% &]
[s4; &]
[s5;:FormatIntHex`(const void`*`): [_^String^ String]_[* FormatIntHex]([@(0.0.255) const]_[@(0.0.255) v
oid]_`*[*@3 ptr])&]
[s2;%% Formats the pointer address [%-*@3 ptr] as a hexadecimal (base
[s3; &]
[s4;%- &]
[s5;:Format64Hex`(uint64`):%- [_^String^ String]_[* Format64Hex]([_^uint64^ uint64]_[*@3 a])&]
[s2; Formats an unsigned hexadecimal [%-*@3 a] (radix 16) 64`-bit integer.
Supposed to be quite fast. Lowecase letters a`-f are used for
digits `[10`] through `[15`].&]
[s3; &]
[s4;%- &]
[s5;:FormatIntHex`(const void`*`):%- [_^String^ String]_[* FormatIntHex]([@(0.0.255) const]_
[@(0.0.255) void]_`*[*@3 ptr])&]
[s2; Formats the pointer address [%-*@3 ptr] as a hexadecimal (base
16) number zero`-padded to the number of digits appropriate for
the memory model (8 digits in 32`-bit systems, 16 digits in 64`-bit
systems). Useful for logging and debugging purposes. Equivalent
to FormatHex, god knows why there are two of them.&]
[s3;%% &]
[s4; &]
[s5;:FormatHex`(const void`*`): [_^String^ String]_[* FormatHex]([@(0.0.255) const]_[@(0.0.255) v
[s3; &]
[s4;%- &]
[s5;:FormatHex`(const void`*`):%- [_^String^ String]_[* FormatHex]([@(0.0.255) const]_[@(0.0.255) v
oid]_`*[*@3 ptr])&]
[s2;%% Same as FormatIntHex.&]
[s3;%% &]
[s4; &]
[s5;:FormatInteger`(int`): [_^String^ String]_[* FormatInteger]([@(0.0.255) int]_[*@3 a])&]
[s2;%% Formats a signed decimal integer without padding. In comparison
to FormatInt it returns String(Null) when given int(Null) whereas
FormatInt returns a plain empty string.&]
[s3;%% &]
[s4; &]
[s5;:FormatUnsigned`(unsigned long`): [_^String^ String]_[* FormatUnsigned]([@(0.0.255) uns
igned]_[@(0.0.255) long]_[*@3 a])&]
[s2;%% A very old freak, implemented through Sprintf(`"%u`", a).
Deprecated.&]
[s3;%% &]
[s4; &]
[s5;:FormatDouble`(double`): [_^String^ String]_[* FormatDouble]([@(0.0.255) double]_[*@3 a])
&]
[s2;%% Formats a floating point [%-*@3 a] in decimal notation automatically
[s2; Same as FormatIntHex.&]
[s3; &]
[s4;%- &]
[s5;:FormatDouble`(double`):%- [_^String^ String]_[* FormatDouble]([@(0.0.255) double]_[*@3 a
])&]
[s2; Formats a floating point [%-*@3 a] in decimal notation automatically
selecting ordinary or scientific (exponential) notation according
to the absolute value of a. In ordinary notation, the number
is formatted to 10 significant digits; in exponential notation,
the mantissa is formatted to 10 decimal digits.&]
[s3;%% &]
[s4; &]
[s5;:FormatBool`(bool`): [_^String^ String]_[* FormatBool]([@(0.0.255) bool]_[*@3 a])&]
[s2;%% Formats a boolean [%-*@3 a] as one of the fixed words `"true`"
[s3; &]
[s4;%- &]
[s5;:FormatBool`(bool`):%- [_^String^ String]_[* FormatBool]([@(0.0.255) bool]_[*@3 a])&]
[s2; Formats a boolean [%-*@3 a] as one of the fixed words `"true`"
or `"false`" (regardless of language settings).&]
[s3;%% &]
[s4; &]
[s5;:FormatInt64`(int64`): [_^String^ String]_[* FormatInt64]([_^int64^ int64]_[*@3 a])&]
[s2;%% Formats a signed decimal 64`-bit integer [%-*@3 a] without any
padding. Only negative numbers are prepended with a `[`-`].&]
[s3;%% &]
[s4; &]
[s5;:FormatDouble`(double`,int`,int`,int`): [_^String^ String]_[* FormatDouble]([@(0.0.255) d
[s3; &]
[s4;%- &]
[s5;:FormatDouble`(double`,int`,int`,int`):%- [_^String^ String]_[* FormatDouble]([@(0.0.255) d
ouble]_[*@3 d], [@(0.0.255) int]_[*@3 digits], [@(0.0.255) int]_[*@3 flags]_`=_[@3 0],
[@(0.0.255) int]_[*@3 fill`_exp]_`=_[@3 0])&]
[s2;%% Formats a floating point number [%-*@3 d] in decimal notation
[s2; Formats a floating point number [%-*@3 d] in decimal notation
automatically selecting ordinary or scientific (exponential)
notation according to the absolute value of a and the given number
of [%-*@3 digits]. In the (default) absolute decimal mode, a number
@ -143,66 +137,66 @@ decimal mode (FD`_REL), a number is formatted in exponential
notation whenever its absolute value exceeds the interval `[10`^`-<2
`* digits>, 10`^`+<2 `* digits>`]. [%-*@3 flags] can be a binary
combination ([@(0.0.255) `|]) of&]
[s0;%% &]
[ {{2098:7902<288;h1; [s0;%% FD`_SIGN]
:: [s0;%% [/ always prepend sign (`+10)]]
:: [s0;%% FD`_REL]
:: [s0;%% [/ relative decimal places (valid digits)]]
:: [s0;%% FD`_SIGN`_EXP]
:: [s0;%% [/ always prepend sign to exponent (1e`+2)]]
:: [s0;%% FD`_CAP`_E]
:: [s0;%% [/ capital E for exponent (1E10)]]
:: [s0;%% FD`_ZERO]
:: [s0;%% [/ keep trailing zeros (1.25000)]]
:: [s0;%% FD`_FIX]
:: [s0;%% [/ always use fixed notation (FormatDouble only)]]
:: [s0;%% FD`_EXP]
:: [s0;%% [/ always use exponential notation (FormatDouble only)]]}}&]
[s2;%% &]
[s2;%% [*@3 fill`_exp ]is left zero`-padding of exponent in exponential
[s0; &]
[ {{2098:7902<288;h1; [s0; FD`_SIGN]
:: [s0; [/ always prepend sign (`+10)]]
:: [s0; FD`_REL]
:: [s0; [/ relative decimal places (valid digits)]]
:: [s0; FD`_SIGN`_EXP]
:: [s0; [/ always prepend sign to exponent (1e`+2)]]
:: [s0; FD`_CAP`_E]
:: [s0; [/ capital E for exponent (1E10)]]
:: [s0; FD`_ZERO]
:: [s0; [/ keep trailing zeros (1.25000)]]
:: [s0; FD`_FIX]
:: [s0; [/ always use fixed notation (FormatDouble only)]]
:: [s0; FD`_EXP]
:: [s0; [/ always use exponential notation (FormatDouble only)]]}}&]
[s2; &]
[s2; [*@3 fill`_exp ]is left zero`-padding of exponent in exponential
notation&]
[s3;%% &]
[s4; &]
[s5;:FormatDoubleFix`(double`,int`,int`): [_^String^ String]_[* FormatDoubleFix]([@(0.0.255) d
[s3; &]
[s4;%- &]
[s5;:FormatDoubleFix`(double`,int`,int`):%- [_^String^ String]_[* FormatDoubleFix]([@(0.0.255) d
ouble]_[*@3 d], [@(0.0.255) int]_[*@3 digits], [@(0.0.255) int]_[*@3 flags]_`=_[@3 0])&]
[s2;%% Formats a floating point number [%-*@3 d] in ordinary decimal
[s2; Formats a floating point number [%-*@3 d] in ordinary decimal
notation (whole part, comma, decimal part). Then number of [%-*@3 digits]
can be interpreted either as the absolute number of decimal digits
(the default mode) or the relative number of significant digits
excluding leading zeros. Decimal point is always output as a
period independent on language settings. [%-*@3 flags] can be a
binary combination ([@(0.0.255) `|]) of&]
[s0;%% &]
[ {{2098:7902<288;h1; [s0;%% FD`_SIGN]
:: [s0;%% [/ always prepend sign (`+10)]]
:: [s0;%% FD`_REL]
:: [s0;%% [/ relative decimal places (valid digits)]]
:: [s0;%% FD`_ZERO]
:: [s0;%% [/ keep trailing zeros (1.25000)]]}}&]
[s3;%% &]
[s4; &]
[s5;:FormatDoubleExp`(double`,int`,int`,int`): [_^String^ String]_[* FormatDoubleExp]([@(0.0.255) d
[s0; &]
[ {{2098:7902<288;h1; [s0; FD`_SIGN]
:: [s0; [/ always prepend sign (`+10)]]
:: [s0; FD`_REL]
:: [s0; [/ relative decimal places (valid digits)]]
:: [s0; FD`_ZERO]
:: [s0; [/ keep trailing zeros (1.25000)]]}}&]
[s3; &]
[s4;%- &]
[s5;:FormatDoubleExp`(double`,int`,int`,int`):%- [_^String^ String]_[* FormatDoubleExp]([@(0.0.255) d
ouble]_[*@3 d], [@(0.0.255) int]_[*@3 digits], [@(0.0.255) int]_[*@3 flags]_`=_[@3 0],
[@(0.0.255) int]_[*@3 fill`_exp]_`=_[@3 0])&]
[s2;%% Formats a floating point number [%-*@3 d] in scientific / exponential
[s2; Formats a floating point number [%-*@3 d] in scientific / exponential
notation (sign, single digit, period, decimal part, `"e`" decimal
exponent) with given number of [%-*@3 digits]. [%-*@3 flags] can
be a binary combination ([@(0.0.255) `|]) of&]
[s2;%% &]
[ {{2098:7902<288;h1; [s0;%% FD`_SIGN]
:: [s0;%% [/ always prepend sign (`+10)]]
:: [s0;%% FD`_SIGN`_EXP]
:: [s0;%% [/ always prepend sign to exponent (1e`+2)]]
:: [s0;%% FD`_CAP`_E]
:: [s0;%% [/ capital E for exponent (1E10)]]
:: [s0;%% FD`_ZERO]
:: [s0;%% [/ keep trailing zeros (1.25000)]]}}&]
[s2;%% &]
[s2;%% [*@3 fill`_exp ]is left zero`-padding of exponent in exponential
[s2; &]
[ {{2098:7902<288;h1; [s0; FD`_SIGN]
:: [s0; [/ always prepend sign (`+10)]]
:: [s0; FD`_SIGN`_EXP]
:: [s0; [/ always prepend sign to exponent (1e`+2)]]
:: [s0; FD`_CAP`_E]
:: [s0; [/ capital E for exponent (1E10)]]
:: [s0; FD`_ZERO]
:: [s0; [/ keep trailing zeros (1.25000)]]}}&]
[s2; &]
[s2; [*@3 fill`_exp ]is left zero`-padding of exponent in exponential
notation&]
[s3;%% &]
[s4; &]
[s5;:FormatIntBase`(int`,int`,int`,char`,int`): [_^String^ String]_[* FormatIntBase]([@(0.0.255) i
[s3; &]
[s4;%- &]
[s5;:FormatIntBase`(int`,int`,int`,char`,int`):%- [_^String^ String]_[* FormatIntBase]([@(0.0.255) i
nt]_[*@3 i], [@(0.0.255) int]_[*@3 base], [@(0.0.255) int]_[*@3 width]_`=_[@3 0],
[@(0.0.255) char]_[*@3 lpad]_`=_`'_`', [@(0.0.255) int]_[*@3 sign]_`=_[@3 0])&]
[s0;%% ]]
[s0; ]]