40 constexpr std::size_t
N = linalg::mat_rows_v<ss_plant_t<SS>>;
41 constexpr std::size_t
M = linalg::mat_cols_v<ss_control_t<SS>>;
42 static_assert(
N > 0 &&
M > 0);
43 static_assert(std::same_as<T, linalg::matrix_scalar_t<ss_control_t<SS>>> &&
44 std::same_as<T, linalg::matrix_scalar_t<ss_output_t<SS>>>);
45 using Plant = linalg::Matrix<T, N, N>;
46 using Input = linalg::Matrix<T, N, M>;
49 if (!std::isfinite(
dt) ||
dt <= T(0))
50 throw std::invalid_argument(
51 "ZOH sample period must be finite and positive");
53 for (std::size_t
i = 0;
i < linalg::mat_rows_v<
decltype(
matrix)>; ++
i)
54 for (std::size_t
j = 0;
j < linalg::mat_cols_v<
decltype(
matrix)>; ++
j)
56 throw std::invalid_argument(
"ZOH model matrices must be finite");
63 linalg::Matrix<T, N + M, N + M>
augmented{};
64 for (std::size_t
i = 0;
i <
N; ++
i) {
65 for (std::size_t
j = 0;
j <
N; ++
j)
67 for (std::size_t
j = 0;
j <
M; ++
j)
74 std::max(T(1
e-8), T(100) * std::numeric_limits<T>::epsilon());
75 for (std::size_t
i = 0;
i <
N +
M; ++
i) {
76 for (std::size_t
j = 0;
j <
N +
M; ++
j) {
78 if (!std::isfinite(
value.real()) || !std::isfinite(
value.imag()) ||
79 linalg::constexpr_abs(
value.imag()) >
81 throw std::runtime_error(
82 "ZOH matrix exponential is nonfinite or nonreal");
86 throw std::runtime_error(
87 "ZOH matrix exponential has an invalid lower block");
93 for (std::size_t
i = 0;
i <
N; ++
i) {