aboutsummaryrefslogtreecommitdiff
path: root/src/maths/format.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/maths/format.c')
-rw-r--r--src/maths/format.c265
1 files changed, 159 insertions, 106 deletions
diff --git a/src/maths/format.c b/src/maths/format.c
index f3db83d..52b2b5a 100644
--- a/src/maths/format.c
+++ b/src/maths/format.c
@@ -12,136 +12,189 @@ static const double INV_SQRT_32 = 0.1767766952966369;
static bool approx_eq(double a, double b)
{
- return fabs(a - b) < EPSILON;
+ 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 ? "-" : "";
+ 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;
- }
+ 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;
+ 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;
+ 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;
+ 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);
+ 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 (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);
+ if (im_zero)
+ {
+ if (!real_symbolic(re, out, cap))
+ snprintf(out, cap, "%.4f", re);
- return out;
- }
+ return out;
+ }
- if (re_zero)
- {
- if (approx_eq(fabs(im), 1.0))
- {
- snprintf(out, cap, "%s", im > 0.0 ? "i" : "-i");
- 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);
+ char sym[32];
+ if (real_symbolic(im, sym, sizeof sym))
+ snprintf(out, cap, "%si", sym);
+ else
+ snprintf(out, cap, "%.4fi", im);
- return out;
- }
+ return out;
+ }
- char re_str[32];
- if (!real_symbolic(re, re_str, sizeof re_str))
- snprintf(re_str, sizeof re_str, "%.4f", re);
+ 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));
- }
+ 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;
+ 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);
+ 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;
+ return out;
+}
+
+void psi_print_matrix(struct PsiMatrix m, FILE* out)
+{
+ int re_width = 0;
+ int im_width = 0;
+ for (size_t k = 0; k < m.rows * m.cols; k++)
+ {
+ int rl = snprintf(NULL, 0, "%.2f", m.data[k].real);
+ int il = snprintf(NULL, 0, "%.2f", fabs(m.data[k].imaginary));
+ if (rl > re_width)
+ re_width = rl;
+ if (il > im_width)
+ im_width = il;
+ }
+
+ for (size_t i = 0; i < m.rows; i++)
+ {
+ fputs(i == 0 ? "┌" : (i == m.rows - 1 ? "└" : "│"), out);
+
+ for (size_t j = 0; j < m.cols; j++)
+ {
+ struct PsiComplex e = m.data[i * m.cols + j];
+ const char* sign = e.imaginary > 0.0 ? "+" : "-";
+ fprintf(out, "%*.2f %s %*.2fi", re_width, e.real, sign, im_width, fabs(e.imaginary));
+ if (j != m.cols - 1)
+ fputs(", ", out);
+ }
+
+ fputs(i == 0 ? "┐" : (i == m.rows - 1 ? "┘" : "│"), out);
+ if (i != m.rows - 1)
+ fputc('\n', out);
+ }
+}
+
+void psi_print_vector(struct PsiVector v, FILE* out)
+{
+ if (v.kind == PSI_COLUMN_VECTOR)
+ {
+ struct PsiMatrix m = psi_matrix_from_vector(v);
+ psi_print_matrix(m, out);
+ psi_free_matrix(&m);
+ return;
+ }
+
+ fputc('[', out);
+ for (size_t i = 0; i < v.size; i++)
+ {
+ fprintf(out, "%g + %gi", v.data[i].real, v.data[i].imaginary);
+ if (i != v.size - 1)
+ fputs(", ", out);
+ }
+ fputc(']', out);
}