Line data Source code
1 : // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 : // SPDX-License-Identifier: Apache-2.0
3 :
4 : #ifndef PALACE_UTILS_PRETTY_PRINT_HPP
5 : #define PALACE_UTILS_PRETTY_PRINT_HPP
6 :
7 : #include <string>
8 : #include <type_traits>
9 : #include <vector>
10 : #include <mfem.hpp>
11 : #include "utils/communication.hpp"
12 :
13 : namespace palace::utils
14 : {
15 :
16 : //
17 : // Utility functions for formatted printing.
18 : //
19 :
20 : namespace internal
21 : {
22 :
23 : constexpr std::size_t max_width = 80;
24 :
25 : template <typename T>
26 : inline std::size_t GetSize(const T &v)
27 : {
28 : return v.size();
29 : }
30 :
31 : template <typename T>
32 : inline std::size_t GetSize(const mfem::Array<T> &v)
33 : {
34 : return v.Size();
35 : }
36 :
37 119 : inline std::size_t PrePrint(MPI_Comm comm, std::size_t w, std::size_t wv, std::size_t lead)
38 : {
39 119 : auto end = w + 2 + wv + 1; // Consider space for trailing comma
40 119 : if (w > 0 && end > max_width - lead)
41 : {
42 0 : Mpi::Print(comm, ",\n{}", std::string(lead, ' ')); // Line break
43 : w = 0;
44 : }
45 : if (w)
46 : {
47 96 : Mpi::Print(comm, ", ");
48 96 : return w + 2;
49 : }
50 : else
51 : {
52 23 : Mpi::Print(comm, " ");
53 23 : return w + 1;
54 : }
55 : }
56 :
57 : } // namespace internal
58 :
59 : // Fixed column width wrapped printing for the contents of an array, with range notation for
60 : // integral types.
61 : template <template <typename...> class Container, typename T, typename... U>
62 23 : inline void PrettyPrint(const Container<T, U...> &data, T scale,
63 : const std::string &prefix = "", MPI_Comm comm = MPI_COMM_WORLD)
64 : {
65 : std::size_t w = 0, lead = prefix.length();
66 23 : Mpi::Print(comm, prefix);
67 : auto i = data.begin();
68 142 : while (i != data.end())
69 : {
70 : if constexpr (std::is_integral<T>::value)
71 : {
72 : auto j = i;
73 119 : if (scale == 1)
74 : {
75 247 : while ((std::next(j) != data.end()) && *std::next(j) == (*j) + 1)
76 : {
77 : j++;
78 : }
79 : }
80 119 : if (i == j)
81 : {
82 103 : auto wi = 1 + static_cast<T>(std::log10((*i) + 1));
83 103 : w = internal::PrePrint(comm, w, wi, lead) + wi;
84 103 : Mpi::Print(comm, "{:d}", (*i) * scale);
85 : }
86 : else
87 : {
88 16 : auto wi =
89 16 : 3 + static_cast<T>(std::log10((*i) + 1)) + static_cast<T>(std::log10((*j) + 1));
90 16 : w = internal::PrePrint(comm, w, wi, lead) + wi;
91 16 : Mpi::Print(comm, "{:d}-{:d}", (*i) * scale, (*j) * scale);
92 : }
93 : i = std::next(j);
94 : }
95 : else
96 : {
97 0 : constexpr auto pv = 3; // Value precision
98 : constexpr auto wv = pv + 6; // Total printed width of a value
99 0 : w = internal::PrePrint(comm, w, wv, lead) + wv;
100 0 : Mpi::Print(comm, "{:.{}e}", (*i) * scale, pv);
101 : i++;
102 : }
103 : }
104 23 : Mpi::Print(comm, "\n");
105 23 : }
106 :
107 : template <template <typename...> class Container, typename T, typename... U>
108 : inline void PrettyPrint(const Container<T, U...> &data, const std::string &prefix = "",
109 : MPI_Comm comm = MPI_COMM_WORLD)
110 : {
111 23 : PrettyPrint(data, T(1), prefix, comm);
112 23 : }
113 :
114 : } // namespace palace::utils
115 :
116 : #endif // PALACE_UTILS_PRETTY_PRINT_HPP
|