From fc249f327a08458962ac85ccc45383a39245bc3f Mon Sep 17 00:00:00 2001 From: SacredFloof Date: Thu, 26 Mar 2026 20:24:22 +0100 Subject: [PATCH] Add project files. --- XStringUtils.slnx | 3 + XStringUtils/Prettify.cs | 113 +++++++++++++++++++++++++++++++ XStringUtils/XStringUtils.csproj | 34 ++++++++++ 3 files changed, 150 insertions(+) create mode 100644 XStringUtils.slnx create mode 100644 XStringUtils/Prettify.cs create mode 100644 XStringUtils/XStringUtils.csproj diff --git a/XStringUtils.slnx b/XStringUtils.slnx new file mode 100644 index 0000000..6f40209 --- /dev/null +++ b/XStringUtils.slnx @@ -0,0 +1,3 @@ + + + diff --git a/XStringUtils/Prettify.cs b/XStringUtils/Prettify.cs new file mode 100644 index 0000000..88af9a6 --- /dev/null +++ b/XStringUtils/Prettify.cs @@ -0,0 +1,113 @@ +using System.Globalization; +using System.Numerics; + +namespace XStringUtils; + +public static partial class XStringUtils +{ + public static string PrettifyTiny(double number) + { + return number > 0.0001 + ? number.ToString("F4", CultureInfo.InvariantCulture) + : number.ToString("E3", CultureInfo.InvariantCulture); + } + + public enum Notation + { + KMB, + Logarithmic10, + LogarithmicE, + } + + extension(T number) where T : IFloatingPoint, ILogarithmicFunctions, IPowerFunctions + { + public string Prettify(Notation notation = Notation.KMB) + { + if (!T.IsFinite(number)) + { + return "∞"; + } + + if (number == T.Zero) + { + return PrettifySub(0.0); + } + + if (number < T.Zero) + { + return "-" + Prettify(-number, notation); + } + + if (number < T.CreateChecked(0.005)) + { + return number.ToString("E2", CultureInfo.InvariantCulture); + } + + int @base = int.CreateChecked(T.Floor(T.Log(number) / T.Log(T.CreateChecked(1000)))); + + if (@base <= 0) + { + return PrettifySub(number); + } + + if (notation == Notation.Logarithmic10 || notation == Notation.LogarithmicE) + { + T logBase = notation == Notation.Logarithmic10 ? T.CreateChecked(10) : T.E; + T exponent = T.Log(number, logBase); + return PrettifySub(exponent) + "L" + logBase; + } + + T thousand = T.CreateChecked(1000); + T tbase = T.CreateChecked(@base); + + number /= T.Pow(thousand, tbase); + + // Prevent 1000K, 1000M, etc. + if (number >= T.CreateChecked(999.5)) + { + number /= thousand; + @base++; + } + + string suffix = ResolveSuffix(@base); + + return PrettifySub(number) + suffix; + } + } + + private static string PrettifySub(T number) where T : IFloatingPoint + { + T floor = T.Floor(number); + + if (number == floor) + { + return number.ToString(null, CultureInfo.InvariantCulture); + } + + int precision = 3 - floor.ToString(null, CultureInfo.InvariantCulture).Length; + + return number.ToString("F" + precision, CultureInfo.InvariantCulture); + } + + private static readonly string[] Suffices = + [ + "K","M","B","T","Qa","Qi","Sx","Sp","Oc","No","Dc","Ud", + "Dd","Td","Qad","Qid","Sxd","Spd","Od","Nd","V","Uv","Dv", + "Tv","Qav","Qiv","Sxv","Spv","Ov","Nv","Tg","Utg","Dtg","Ttg", + "Qatg","Qitg","Sxtg","Sptg","Otg","Ntg","Qaa","Uqa","Dqa","Tqa", + "Qaqa","Qiqa","Sxqa","Spqa","Oqa","Nqa","Qia","Uqi","Dqi", + "Tqi","Qaqi","Qiqi","Sxqi","Spqi","Oqi","Nqi","Sxa","Usx", + "Dsx","Tsx","Qasx","Qisx","Sxsx","Spsx","Osx","Nsx","Spa", + "Usp","Dsp","Tsp","Qasp","Qisp","Sxsp","Spsp","Osp","Nsp", + "Og","Uog","Dog","Tog","Qaog","Qiog","Sxog","Spog","Oog", + "Nog","Na","Un","Dn","Tn","Qan","Qin","Sxn","Spn","On", + "Nn","Ct","Uc" + ]; + + private static string ResolveSuffix(int @base) + { + return @base <= Suffices.Length + ? Suffices[@base - 1] + : "e" + (@base * 3); + } +} diff --git a/XStringUtils/XStringUtils.csproj b/XStringUtils/XStringUtils.csproj new file mode 100644 index 0000000..ce8a890 --- /dev/null +++ b/XStringUtils/XStringUtils.csproj @@ -0,0 +1,34 @@ + + + + net10.0 + enable + enable + False + True + XStringUtils + SacredFloof + SacredFloof + Small string utilities. AOT-friendly + SacredFloof 2026 + Utility + 1.0.1 + + + + True + True + True + + + + True + True + True + + + + + + +