Program Listing for File arrayViewString.hpp#

Return to documentation for file (librapid/include/librapid/array/arrayViewString.hpp)

#ifndef LIBRAPID_ARRAY_ARRAY_VIEW_STRING_HPP
#define LIBRAPID_ARRAY_ARRAY_VIEW_STRING_HPP

namespace librapid {
    namespace detail {
        template<typename T, typename std::enable_if_t<std::is_fundamental_v<T>, int> = 0>
        LIBRAPID_INLINE std::pair<int64_t, int64_t> countWidth(const T &val,
                                                               const std::string &format) {
            std::string str = fmt::format(format, val);
            auto point      = str.find('.');
            if (point == std::string::npos) { return {str.size(), 0}; }
            return {point, str.size() - point};
        }

        template<typename T, typename std::enable_if_t<!std::is_fundamental_v<T>, int> = 0>
        LIBRAPID_INLINE std::pair<int64_t, int64_t> countWidth(const T &val,
                                                               const std::string &format) {
            std::string str = fmt::format(format, val);
            return {str.size(), 0};
        }

        template<typename T>
        std::vector<std::pair<int64_t, int64_t>> countColumnWidths(const array::ArrayView<T> &view,
                                                                   const std::string &format) {
            if (view.ndim() == 0) {
                // Scalar
                return {countWidth(view.scalar(0), format)};
            } else if (view.ndim() == 1) {
                // Vector
                std::vector<std::pair<int64_t, int64_t>> widths(view.shape()[0]);
                for (int64_t i = 0; i < static_cast<int64_t>(view.shape()[0]); ++i) {
                    widths[i] = countWidth(view.scalar(i), format);
                }
                return widths;
            } else {
                // General
                std::vector<std::pair<int64_t, int64_t>> widths =
                  countColumnWidths(view[0], format);
                for (int64_t i = 1; i < static_cast<int64_t>(view.shape()[0]); ++i) {
                    auto subWidths = countColumnWidths(view[i], format);
                    for (int64_t j = 0; j < static_cast<int64_t>(widths.size()); ++j) {
                        widths[j].first  = ::librapid::max(widths[j].first, subWidths[j].first);
                        widths[j].second = ::librapid::max(widths[j].second, subWidths[j].second);
                    }
                }
                return widths;
            }
        }

        template<typename T>
        std::string arrayViewToString(const array::ArrayView<T> &view, const std::string &format,
                                      const std::vector<std::pair<int64_t, int64_t>> &widths,
                                      int64_t indent) {
            if (view.ndim() == 0) { return fmt::format(format, view.scalar(0)); }

            if (view.ndim() == 1) {
                std::string str = "[";
                for (int64_t i = 0; i < static_cast<int64_t>(view.shape()[0]); i++) {
                    std::pair<int64_t, int64_t> width = detail::countWidth(view.scalar(i), format);
                    str += fmt::format("{:>{}}{}{:>{}}",
                                       "",
                                       widths[i].first - width.first,
                                       fmt::format(format, view.scalar(i)),
                                       "",
                                       widths[i].second - width.second);
                    if (i != view.shape()[0] - 1) { str += " "; }
                }
                str += "]";
                return str;
            }

            std::string str = "[";
            for (int64_t i = 0; i < static_cast<int64_t>(view.shape()[0]); i++) {
                if (i > 0) str += std::string(indent + 1, ' ');
                str += arrayViewToString(view[i], format, widths, indent + 1);
                if (i != view.shape()[0] - 1) {
                    str += "\n";
                    if (view.ndim() > 2) { str += "\n"; }
                }
            }
            str += "]";
            return str;
        }
    } // namespace detail

    namespace array {
        template<typename T>
        auto ArrayView<T>::str(const std::string &format) const -> std::string {
            std::vector<std::pair<int64_t, int64_t>> widths =
              detail::countColumnWidths(*this, format);
            return detail::arrayViewToString(*this, format, widths, 0);
        }
    } // namespace array
} // namespace librapid

#endif // LIBRAPID_ARRAY_ARRAY_VIEW_STRING_HPP