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
32namespace tvm {
33namespace 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 */
59class 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
87inline TablePrinter::Line& TablePrinter::Line::operator<<(int x) {
88 p->tab_.back().push_back(std::to_string(x));
89 return *this;
90}
91
92inline TablePrinter::Line& TablePrinter::Line::operator<<(int64_t x) {
93 p->tab_.back().push_back(std::to_string(x));
94 return *this;
95}
96
97inline 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
104inline TablePrinter::Line& TablePrinter::Line::operator<<(const std::string& x) {
105 p->tab_.back().push_back(x);
106 return *this;
107}
108
109inline TablePrinter::Line TablePrinter::Row() {
110 tab_.emplace_back();
111 Line line;
112 line.p = this;
113 return line;
114}
115
116inline void TablePrinter::Separator() { tab_.emplace_back(); }
117
118inline 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