WPILibC++ 2027.0.0-alpha-2
Loading...
Searching...
No Matches
spy.hpp
Go to the documentation of this file.
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#ifndef SLEIPNIR_DISABLE_DIAGNOSTICS
6
7#include <stdint.h>
8
9#include <bit>
10#include <fstream>
11#include <string>
12#include <string_view>
13
14#include <Eigen/SparseCore>
15#include <wpi/bit.h>
16
18
19namespace slp {
20
21/**
22 * Writes the sparsity pattern of a sparse matrix to a file.
23 *
24 * Each file represents the sparsity pattern of one matrix over time. <a
25 * href="https://github.com/SleipnirGroup/Sleipnir/blob/main/tools/spy.py">spy.py</a>
26 * can display it as an animation.
27 *
28 * The file starts with the following header:
29 * <ol>
30 * <li>Plot title (length as a little-endian int32, then characters)</li>
31 * <li>Row label (length as a little-endian int32, then characters)</li>
32 * <li>Column label (length as a little-endian int32, then characters)</li>
33 * </ol>
34 *
35 * Then, each sparsity pattern starts with:
36 * <ol>
37 * <li>Number of coordinates as a little-endian int32</li>
38 * </ol>
39 *
40 * followed by that many coordinates in the following format:
41 * <ol>
42 * <li>Row index as a little-endian int32</li>
43 * <li>Column index as a little-endian int32</li>
44 * <li>Sign as a character ('+' for positive, '-' for negative, or '0' for
45 * zero)</li>
46 * </ol>
47 *
48 * @param[out] file A file stream.
49 * @param[in] mat The sparse matrix.
50 */
52 public:
53 /**
54 * Constructs a Spy instance.
55 *
56 * @param filename The filename.
57 * @param title Plot title.
58 * @param row_label Row label.
59 * @param col_label Column label.
60 * @param rows The sparse matrix's number of rows.
61 * @param cols The sparse matrix's number of columns.
62 */
63 Spy(std::string_view filename, std::string_view title,
64 std::string_view row_label, std::string_view col_label, int rows,
65 int cols)
66 : m_file{std::string{filename}, std::ios::binary} {
67 // Write title
68 write32le(title.size());
69 m_file.write(title.data(), title.size());
70
71 // Write row label
72 write32le(row_label.size());
73 m_file.write(row_label.data(), row_label.size());
74
75 // Write column label
76 write32le(col_label.size());
77 m_file.write(col_label.data(), col_label.size());
78
79 // Write row and column counts
80 write32le(rows);
81 write32le(cols);
82 }
83
84 /**
85 * Adds a matrix to the file.
86 *
87 * @param mat The matrix.
88 */
89 void add(const Eigen::SparseMatrix<double>& mat) {
90 // Write number of coordinates
91 write32le(mat.nonZeros());
92
93 // Write coordinates
94 for (int k = 0; k < mat.outerSize(); ++k) {
95 for (Eigen::SparseMatrix<double>::InnerIterator it{mat, k}; it; ++it) {
96 write32le(it.row());
97 write32le(it.col());
98 if (it.value() > 0.0) {
99 m_file << '+';
100 } else if (it.value() < 0.0) {
101 m_file << '-';
102 } else {
103 m_file << '0';
104 }
105 }
106 }
107 }
108
109 private:
110 std::ofstream m_file;
111
112 /**
113 * Writes a 32-bit signed integer to the file as little-endian.
114 *
115 * @param num A 32-bit signed integer.
116 */
117 void write32le(int32_t num) {
118 if constexpr (std::endian::native != std::endian::little) {
119 num = wpi::byteswap(num);
120 }
121 m_file.write(reinterpret_cast<char*>(&num), sizeof(num));
122 }
123};
124
125} // namespace slp
126
127#endif
This file implements the C++20 <bit> header.
Writes the sparsity pattern of a sparse matrix to a file.
Definition spy.hpp:51
void add(const Eigen::SparseMatrix< double > &mat)
Adds a matrix to the file.
Definition spy.hpp:89
Spy(std::string_view filename, std::string_view title, std::string_view row_label, std::string_view col_label, int rows, int cols)
Constructs a Spy instance.
Definition spy.hpp:63
Definition expression_graph.hpp:11
Definition PointerIntPair.h:280
constexpr T byteswap(T V) noexcept
Reverses the bytes in the given integer value V.
Definition bit.h:63
#define SLEIPNIR_DLLEXPORT
Definition symbol_exports.hpp:34