diff options
| author | hachem <im@hachem.wtf> | 2026-09-12 00:39:59 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-12 00:39:59 +0200 |
| commit | 00d22403a3ddad8692252a7974d586f32cf745bf (patch) | |
| tree | eab7fbcbdf139a61f01125770744c87e2ac548d0 /src/maths/format.c | |
| parent | 7e093e9726d7017943f5b9c45470a2acd9024d70 (diff) | |
feat: symbolic amplitude and probability formatting
Diffstat (limited to 'src/maths/format.c')
| -rw-r--r-- | src/maths/format.c | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/maths/format.c b/src/maths/format.c new file mode 100644 index 0000000..ad80ff0 --- /dev/null +++ b/src/maths/format.c @@ -0,0 +1,147 @@ +#include "maths/format.h" + +#include <math.h> +#include <stdbool.h> +#include <stdio.h> + +static const double EPSILON = 1e-10; +static const double SQRT_2 = 1.4142135623730951; +static const double INV_SQRT_2 = 0.7071067811865475; +static const double INV_SQRT_8 = 0.3535533905932738; +static const double INV_SQRT_32 = 0.1767766952966369; + +static bool approx_eq(double a, double b) +{ + return fabs(a - b) < EPSILON; +} + +static bool real_symbolic(double v, char *out, size_t cap) +{ + double abs_v = fabs(v); + const char *sign = v < 0.0 ? "-" : ""; + + if (approx_eq(abs_v, 0.0)) + { + snprintf(out, cap, "%s", "0"); + return true; + } + + const char *sym = NULL; + if (approx_eq(abs_v, 1.0)) + sym = "1"; + else if (approx_eq(abs_v, 0.5)) + sym = "½"; + else if (approx_eq(abs_v, 0.25)) + sym = "¼"; + else if (approx_eq(abs_v, 0.75)) + sym = "¾"; + else if (approx_eq(abs_v, 0.125)) + sym = "⅛"; + else if (approx_eq(abs_v, SQRT_2)) + sym = "√2"; + else if (approx_eq(abs_v, INV_SQRT_2)) + sym = "¹⁄√2"; + else if (approx_eq(abs_v, INV_SQRT_8)) + sym = "¹⁄√8"; + else if (approx_eq(abs_v, INV_SQRT_32)) + sym = "¹⁄√32"; + else if (approx_eq(abs_v, 2.0)) + sym = "2"; + else if (approx_eq(abs_v, 1.0 / 3.0)) + sym = "⅓"; + else if (approx_eq(abs_v, 2.0 / 3.0)) + sym = "⅔"; + else + return false; + + snprintf(out, cap, "%s%s", sign, sym); + return true; +} + +char *psi_format_amplitude(struct PsiComplex c, char *out, size_t cap) +{ + double re = c.real; + double im = c.imaginary; + + bool re_zero = approx_eq(fabs(re), 0.0); + bool im_zero = approx_eq(fabs(im), 0.0); + + if (re_zero && im_zero) + { + snprintf(out, cap, "%s", "0"); + return out; + } + + if (im_zero) + { + if (!real_symbolic(re, out, cap)) + snprintf(out, cap, "%.4f", re); + + return out; + } + + if (re_zero) + { + if (approx_eq(fabs(im), 1.0)) + { + snprintf(out, cap, "%s", im > 0.0 ? "i" : "-i"); + return out; + } + + char sym[32]; + if (real_symbolic(im, sym, sizeof sym)) + snprintf(out, cap, "%si", sym); + else + snprintf(out, cap, "%.4fi", im); + + return out; + } + + char re_str[32]; + if (!real_symbolic(re, re_str, sizeof re_str)) + snprintf(re_str, sizeof re_str, "%.4f", re); + + char im_str[32]; + if (approx_eq(fabs(im), 1.0)) + { + snprintf(im_str, sizeof im_str, "%s", im > 0.0 ? "+i" : "-i"); + } + else + { + const char *sign = im > 0.0 ? "+" : "-"; + char sym[32]; + if (real_symbolic(fabs(im), sym, sizeof sym)) + snprintf(im_str, sizeof im_str, "%s%si", sign, sym); + else + snprintf(im_str, sizeof im_str, "%s%.4fi", sign, fabs(im)); + } + + snprintf(out, cap, "%s%s", re_str, im_str); + return out; +} + +char *psi_format_probability(double p, char *out, size_t cap) +{ + if (approx_eq(p, 0.0)) + snprintf(out, cap, "%s", "0"); + else if (approx_eq(p, 1.0)) + snprintf(out, cap, "%s", "1"); + else if (approx_eq(p, 0.5)) + snprintf(out, cap, "%s", "½"); + else if (approx_eq(p, 0.25)) + snprintf(out, cap, "%s", "¼"); + else if (approx_eq(p, 0.75)) + snprintf(out, cap, "%s", "¾"); + else if (approx_eq(p, 0.125)) + snprintf(out, cap, "%s", "⅛"); + else if (approx_eq(p, 0.0625)) + snprintf(out, cap, "%s", "¹⁄₁₆"); + else if (approx_eq(p, 1.0 / 3.0)) + snprintf(out, cap, "%s", "⅓"); + else if (approx_eq(p, 2.0 / 3.0)) + snprintf(out, cap, "%s", "⅔"); + else + snprintf(out, cap, "%.4f", p); + + return out; +} |
