diff --git a/autotest/itos/itos.cpp b/autotest/itos/itos.cpp new file mode 100644 index 000000000..75a40df06 --- /dev/null +++ b/autotest/itos/itos.cpp @@ -0,0 +1,56 @@ +#include + +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"); +} diff --git a/autotest/itos/itos.upp b/autotest/itos/itos.upp new file mode 100644 index 000000000..2e98e1e92 --- /dev/null +++ b/autotest/itos/itos.upp @@ -0,0 +1,9 @@ +uses + Core; + +file + itos.cpp; + +mainconfig + "" = ""; + diff --git a/uppsrc/Core/Convert.hpp b/uppsrc/Core/Convert.hpp index cb0817362..1502dce1f 100644 --- a/uppsrc/Core/Convert.hpp +++ b/uppsrc/Core/Convert.hpp @@ -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); + }); +} diff --git a/uppsrc/Core/Format.cpp b/uppsrc/Core/Format.cpp index 6ab51bd1c..8540d2370 100644 --- a/uppsrc/Core/Format.cpp +++ b/uppsrc/Core/Format.cpp @@ -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]; diff --git a/uppsrc/Core/Format.h b/uppsrc/Core/Format.h index e726ca10b..24a267f7f 100644 --- a/uppsrc/Core/Format.h +++ b/uppsrc/Core/Format.h @@ -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 { diff --git a/uppsrc/Core/String.h b/uppsrc/Core/String.h index fa38f1871..a40cecd2e 100644 --- a/uppsrc/Core/String.h +++ b/uppsrc/Core/String.h @@ -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 + 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()); } diff --git a/uppsrc/Core/src.tpp/FormatFn_en-us.tpp b/uppsrc/Core/src.tpp/FormatFn_en-us.tpp index e3e72a9ca..ce7b6bd9f 100644 --- a/uppsrc/Core/src.tpp/FormatFn_en-us.tpp +++ b/uppsrc/Core/src.tpp/FormatFn_en-us.tpp @@ -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;%% ]] \ No newline at end of file +[s0; ]] \ No newline at end of file