1 | /* |
2 | * Licensed to the Apache Software Foundation (ASF) under one |
3 | * or more contributor license agreements. See the NOTICE file |
4 | * distributed with this work for additional information |
5 | * regarding copyright ownership. The ASF licenses this file |
6 | * to you under the Apache License, Version 2.0 (the |
7 | * "License"); you may not use this file except in compliance |
8 | * with the License. You may obtain a copy of the License at |
9 | * |
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | * |
12 | * Unless required by applicable law or agreed to in writing, |
13 | * software distributed under the License is distributed on an |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
15 | * KIND, either express or implied. See the License for the |
16 | * specific language governing permissions and limitations |
17 | * under the License. |
18 | */ |
19 | #ifndef TVM_SUPPORT_TABLE_PRINTER_H_ |
20 | #define TVM_SUPPORT_TABLE_PRINTER_H_ |
21 | |
22 | #include <tvm/runtime/logging.h> |
23 | |
24 | #include <algorithm> |
25 | #include <iomanip> |
26 | #include <iostream> |
27 | #include <numeric> |
28 | #include <sstream> |
29 | #include <string> |
30 | #include <vector> |
31 | |
32 | namespace tvm { |
33 | namespace support { |
34 | |
35 | /*! |
36 | * \brief TablePrinter is a helper class to print a table. |
37 | * |
38 | * \code |
39 | * |
40 | * TablePrinter p; |
41 | * p.Row() << "ID" |
42 | * << "Latency (ms)" |
43 | * << "Speed (GFLOPS)" |
44 | * << "Trials"; |
45 | * p.Separator(); |
46 | * p.Row() << 0 << 0.072 << 4208.59 << 6656; |
47 | * p.Row() << 1 << 0.020 << 3804.24 << 7296; |
48 | * p.Row() << 2 << 0.003 << 1368.10 << 320; |
49 | * p.Row() << 3 << 0.010 << 117.75 << 128; |
50 | * p.Row() << 4 << 0.002 << 23.75 << 320; |
51 | * p.Row() << 5 << 0.004 << 1696.18 << 704; |
52 | * p.Row() << 6 << 0.002 << 69.89 << 320; |
53 | * p.Row() << 7 << 0.047 << 6394.42 << 4352; |
54 | * p.Separator(); |
55 | * std::cout << tab.AsStr(); |
56 | * |
57 | * \endcode |
58 | */ |
59 | class TablePrinter { |
60 | struct Line; |
61 | |
62 | public: |
63 | /*! \brief Create a new row */ |
64 | inline Line Row(); |
65 | /*! \brief Create a row separator */ |
66 | inline void Separator(); |
67 | /*! \brief Converts TablePrinter to a string */ |
68 | inline std::string AsStr() const; |
69 | |
70 | private: |
71 | std::vector<std::vector<std::string>> tab_; |
72 | friend struct Line; |
73 | |
74 | /*! \brief A helper class to print a specific row in the table */ |
75 | struct Line { |
76 | inline Line& operator<<(int x); |
77 | inline Line& operator<<(int64_t x); |
78 | inline Line& operator<<(double x); |
79 | inline Line& operator<<(const std::string& x); |
80 | |
81 | private: |
82 | TablePrinter* p; |
83 | friend class TablePrinter; |
84 | }; |
85 | }; |
86 | |
87 | inline TablePrinter::Line& TablePrinter::Line::operator<<(int x) { |
88 | p->tab_.back().push_back(std::to_string(x)); |
89 | return *this; |
90 | } |
91 | |
92 | inline TablePrinter::Line& TablePrinter::Line::operator<<(int64_t x) { |
93 | p->tab_.back().push_back(std::to_string(x)); |
94 | return *this; |
95 | } |
96 | |
97 | inline TablePrinter::Line& TablePrinter::Line::operator<<(double x) { |
98 | std::ostringstream os; |
99 | os << std::fixed << std::setprecision(4) << x; |
100 | p->tab_.back().push_back(os.str()); |
101 | return *this; |
102 | } |
103 | |
104 | inline TablePrinter::Line& TablePrinter::Line::operator<<(const std::string& x) { |
105 | p->tab_.back().push_back(x); |
106 | return *this; |
107 | } |
108 | |
109 | inline TablePrinter::Line TablePrinter::Row() { |
110 | tab_.emplace_back(); |
111 | Line line; |
112 | line.p = this; |
113 | return line; |
114 | } |
115 | |
116 | inline void TablePrinter::Separator() { tab_.emplace_back(); } |
117 | |
118 | inline std::string TablePrinter::AsStr() const { |
119 | constexpr char kRowSep = '-'; |
120 | constexpr char kColSep = '|'; |
121 | if (tab_.empty()) return "" ; |
122 | std::vector<size_t> column_width; |
123 | for (const std::vector<std::string>& row : tab_) { |
124 | if (row.size() > column_width.size()) { |
125 | column_width.resize(row.size(), 0); |
126 | } |
127 | for (size_t i = 0; i < row.size(); ++i) { |
128 | column_width[i] = std::max(column_width[i], row[i].size()); |
129 | } |
130 | } |
131 | ICHECK(!column_width.empty()); |
132 | size_t total_width = |
133 | std::accumulate(column_width.begin(), column_width.end(), 0) + 3 * column_width.size() - 1; |
134 | bool is_first = true; |
135 | std::ostringstream os; |
136 | for (const std::vector<std::string>& row : tab_) { |
137 | if (is_first) { |
138 | is_first = false; |
139 | } else { |
140 | os << '\n'; |
141 | } |
142 | if (row.empty()) { |
143 | os << std::string(total_width, kRowSep); |
144 | continue; |
145 | } |
146 | for (size_t i = 0; i < column_width.size(); ++i) { |
147 | if (i != 0) { |
148 | os << kColSep; |
149 | } |
150 | std::string s = (i < row.size()) ? row[i] : "" ; |
151 | os << std::string(column_width[i] + 1 - s.size(), ' ') << s << ' '; |
152 | } |
153 | } |
154 | return os.str(); |
155 | } |
156 | |
157 | } // namespace support |
158 | } // namespace tvm |
159 | |
160 | #endif // TVM_SUPPORT_TABLE_PRINTER_H_ |
161 | |