TRIQS/triqs_modest 3.3.0
Brillouin zone summation
Loading...
Searching...
No Matches
nda_pretty_printer.hpp
Go to the documentation of this file.
1// Copyright (c) 2025--present, The Simons Foundation
2// This file is part of TRIQS/modest and is licensed under the terms of GPLv3 or later.
3// SPDX-License-Identifier: GPL-3.0-or-later
4// See LICENSE in the root of this distribution for details.
5
6#pragma once
7#include <complex>
8#include <nda/nda.hpp>
9#include <fmt/format.h>
10#include <fmt/ranges.h>
11
12// WARNING no namespace here, it is in fmt::
13
14// HARD TO FIND. Need to disable the range formatter for the matrix, array
15#ifdef FMT_RANGES_H_
16template <typename T, typename Char> struct fmt::is_range<nda::matrix<T>, Char> : std::false_type {};
17template <typename T, typename Char> struct fmt::is_range<nda::array<T, 2>, Char> : std::false_type {};
18#endif
19
20//-------------------------------------------------------
21
22template <typename U> struct fmt::formatter<nda::matrix<U>> {
23 static_assert(fmt::is_formattable<U>::value, "Cannot format nda::matrix<U>: U must be formattable");
24
25 //
26 //constexpr auto parse(format_parse_context &ctx) { return ctx.begin(); }
27 // Format specifier for elements of type U
28 fmt::formatter<U> value_formatter;
29
30 // Parse the format specifier for U
31 constexpr auto parse(format_parse_context &ctx) {
32 // Let the value formatter handle the parsing
33 return value_formatter.parse(ctx);
34 }
35
36 //
37 auto format(auto const &mat, format_context &ctx) const {
38 auto out = ctx.out();
39 int max_width = std::ranges::max(mat | std::views::transform([](auto &&x) { return fmt::format("{}", x).length(); }));
40 for (long i = 0; i < mat.extent(0); ++i) {
41 if (i == 0)
42 fmt::format_to(out, "\n[[");
43 else
44 fmt::format_to(out, " [");
45 for (long j = 0; j < mat.extent(1); ++j) fmt::format_to(out, "{:>{}}", fmt::format("{}", mat(i, j)), max_width);
46 if (i != mat.extent(0) - 1)
47 fmt::format_to(out, "]\n");
48 else
49 fmt::format_to(out, "]]\n");
50 }
51 return out;
52 }
53};
54
55// -----------------------------------------
56
57template <typename U> struct fmt::formatter<nda::array<U, 2>> : fmt::formatter<nda::matrix<U>> {};
58
60// Specialization of fmt::formatter for nda::matrix<std::complex<T>>
61template <typename T> struct fmt::formatter<nda::matrix<std::complex<T>>> : fmt::formatter<double> {
62 int precision = 4; // Default precision
63
64 // Parse format specifiers
65 constexpr auto parse(format_parse_context &ctx) {
66 auto it = ctx.begin();
67 if (it != ctx.end()) {
68 if (*it >= '0' && *it <= '9') {
69 precision = *it - '0'; // Extract precision
70 ++it;
71 }
72 }
73 return it;
74 }
75
76 // Format function
77 template <typename FormatContext> auto format(const nda::matrix<std::complex<T>> &mat, FormatContext &ctx) const {
78 auto out = ctx.out();
79
80 int max_width_r = std::ranges::max(mat | std::views::transform([&](auto &&x) { return fmt::format("{:.{}f}", x.real(), precision).length(); }));
81 int max_width_i = std::ranges::max(mat | std::views::transform([&](auto &&x) { return fmt::format("{:.{}f}", x.imag(), precision).length(); }));
82 int max_width = std::max(max_width_r, max_width_i);
83
84 for (size_t i = 0; i < mat.extent(0); ++i) {
85 if (i == 0)
86 fmt::format_to(out, "\n[[");
87 else
88 fmt::format_to(out, " [");
89 for (size_t j = 0; j < mat.extent(1); ++j) {
90 const auto &c = mat(i, j);
91 fmt::format_to(out, "{2:{0}.{1}f}{3:+{0}.{1}f}i ", max_width, precision, c.real(), c.imag(), precision);
92 }
93 if (i != mat.extent(0) - 1)
94 fmt::format_to(out, "]\n");
95 else
96 fmt::format_to(out, "]]\n");
97 }
98 return out;
99 }
100};
101
102namespace nda {
103
112 // FIXME : use a matrix<std::string> then a map() in the code
113 void format_as_table(std::ostream &out, nda::Matrix auto const &mat, auto const &row_labels, auto const &col_labels) {
114 namespace stdv = std::views;
115 namespace stdr = std::ranges;
116 auto [rows, cols] = mat.shape();
117
118 // Width of first column (row labels)
119 long first_col_width = stdr::max(row_labels | stdv::transform([](auto &&s) { return long(s.size()); }));
120
121 // Widths of each column: max(label, all formatted elements)
122 std::vector<long> col_widths(cols, 0);
123 for (long j : range(cols)) {
124 auto formatted_column = stdv::iota(0L, rows) | stdv::transform([&](long i) { return long(fmt::format("{}", mat(i, j)).size()); });
125 col_widths[j] = std::max(long(col_labels[j].size()), stdr::max(formatted_column));
126 }
127
128 // Header row (centered labels)
129 out << fmt::format("{:<{}} | ", "", first_col_width);
130 for (long j : range(cols)) out << fmt::format("{:^{}} ", col_labels[j], col_widths[j]);
131 out << '\n';
132
133 // Separator line
134 out << fmt::format("{:-<{}}-+-", "", first_col_width);
135 for (long j : range(cols)) out << fmt::format("{:-<{}}-+", "", col_widths[j]);
136 out << '\n';
137
138 // Data rows (right-aligned)
139 for (long i : range(rows)) {
140 if (mat(i, 0).imp_idx == -1) continue; // HL: skip alpha which do not map to an impurity (OP review)
141 out << fmt::format("{:<{}} | ", row_labels[i], first_col_width);
142 for (long j : range(cols)) { out << fmt::format("{:>{}} ", fmt::format("{}", mat(i, j)), col_widths[j]); };
143 out << '\n';
144 }
145 }
146} // namespace nda
void format_as_table(std::ostream &out, nda::Matrix auto const &mat, auto const &row_labels, auto const &col_labels)
Format the matrix mat as a table, with row/col_labels.
auto format(auto const &mat, format_context &ctx) const
constexpr auto parse(format_parse_context &ctx)
auto format(const nda::matrix< std::complex< T > > &mat, FormatContext &ctx) const
constexpr auto parse(format_parse_context &ctx)