4#include "Stroika/Foundation/StroikaPreComp.h"
15#include "Stroika/Foundation/Containers/Common.h"
19#include "Stroika/Foundation/Math/Common.h"
21#include "FloatConversion.h"
25using namespace Stroika::Foundation::Memory;
37 sb <<
"Precision:"sv << *fPrecision_;
56 sb <<
"Precision:"sv << *fPrecision_ <<
","sv;
64 if (fTrimTrailingZeros_) {
65 sb <<
"Trim-Trailing-Zeros: "sv << *fTrimTrailingZeros_ <<
","sv;
68 sb <<
"Scientific-Notation: "sv << (int)*fFloatFormat_ <<
","sv;
75 inline char* mkFmtWithPrecisionArg_ (
char* formatBufferStart, [[maybe_unused]]
char* formatBufferEnd,
char _Spec)
77 char* fmtPtr = formatBufferStart;
87 Require (fmtPtr < formatBufferEnd);
88 return formatBufferStart;
91 template <
typename FLOAT_TYPE>
94 Require (not isnan (f));
95 Require (not isinf (f));
99 static thread_local stringstream s;
100 static const ios_base::fmtflags kDefaultIOSFmtFlags_ = s.flags ();
108 s.flags (options.GetIOSFmtFlags ().value_or (kDefaultIOSFmtFlags_));
111 unsigned int usePrecision = options.GetPrecision ().value_or (
FloatConversion::Precision{}).GetEffectivePrecision<FLOAT_TYPE> ();
112 s.precision (usePrecision);
115 optional<ios_base::fmtflags> useFloatField;
116 switch (options.GetFloatFormat ().value_or (FloatConversion::FloatFormatType::eDEFAULT)) {
117 case FloatConversion::FloatFormatType::eScientific:
118 useFloatField = ios_base::scientific;
120 case FloatConversion::FloatFormatType::eDefaultFloat:
122 case FloatConversion::FloatFormatType::eFixedPoint:
123 useFloatField = ios_base::fixed;
125 case FloatConversion::FloatFormatType::eAutomaticScientific: {
126 bool useScientificNotation = abs (f) >= pow (10, usePrecision / 2) or
127 (f != 0 and abs (f) < pow (10, -static_cast<
int> (usePrecision) / 2));
128 if (useScientificNotation) {
129 useFloatField = ios_base::scientific;
137 s.setf (*useFloatField, ios_base::floatfield);
140 s.unsetf (ios_base::floatfield);
147 if (options.GetTrimTrailingZeros ().value_or (FloatConversion::ToStringOptions::kDefaultTrimTrailingZeros)) {
148 Characters::FloatConversion::Private_::TrimTrailingZeros_ (&tmp);
152 template <
typename FLOAT_TYPE>
155 switch (fpclassify (f)) {
159 static const String kNEG_INF_STR_{
"-INF"_k};
160 static const String kINF_STR_{
"INF"_k};
161 return f > 0 ? kINF_STR_ : kNEG_INF_STR_;
166 static const String kNAN_STR_{
"NAN"_k};
171 if (Debug::IsRunningUnderValgrind ()) {
173 DbgTrace (
"fpclassify ({}) = {}"_f, (
double)f, fpclassify (f));
174 static const String kNEG_INF_STR_{
"-INF"_k};
175 static const String kINF_STR_{
"INF"_k};
176 return f > 0 ? kINF_STR_ : kNEG_INF_STR_;
184 return Float2String_GenericCase_<FLOAT_TYPE> (f, options);
#define RequireNotReached()
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
Include this file VERY EARLY ON - before including stuff like <cstdio> - to allow use of Valgrind (so...
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
static String FromNarrowString(const char *from, const locale &l)
static String FromNarrowSDKString(const char *from)
String ToString(T &&t, ARGS... args)
Return a debug-friendly, display version of the argument: not guaranteed parsable or usable except fo...
nonvirtual String ToString() const
nonvirtual locale GetUseLocale() const
return the selected locale object
nonvirtual String ToString() const
nonvirtual bool GetUsingLocaleClassic() const
return true if locale used is locale::classic() - the 'C' locale; mostly used as optimization/special...