10 std::span<real_t> qr) {
11 auto [N, nx, nu, ny, ny_N] = ocp.
dim;
12 BATMAT_ASSERT(
static_cast<index_t
>(qr.size()) == N * (nx + nu) + nx);
13 auto n_ref =
static_cast<index_t
>(ref.size());
14 if (n_ref == N * (nx + nu) + nx) {
15 auto H0 = ocp.
H(0), HN = ocp.
H(N);
17 real_t{-1}, H0.data, H0.outer_stride,
18 H0.outer_stride * H0.cols, ref.data(), index_t{1},
19 nx + nu, real_t{0}, qr.data(), index_t{1}, nx + nu, N);
20 index_t off_N = N * (nx + nu);
22 HN.outer_stride, &ref[off_N], index_t{1}, real_t{0}, &qr[off_N],
24 }
else if (n_ref == 2 * nx + nu) {
25 auto H0 = ocp.
H(0), HN = ocp.
H(N);
27 CblasColMajor, CblasNoTrans, nx + nu, nx + nu, real_t{-1}, H0.data, H0.outer_stride,
28 H0.outer_stride * H0.cols, ref.data(), index_t{1}, index_t{0}, real_t{0}, qr.data(),
29 index_t{1}, nx + nu, N);
30 index_t off_N = N * (nx + nu);
32 HN.outer_stride, &ref[nx + nu], index_t{1}, real_t{0}, &qr[off_N],
47 auto [N, nx, nu, ny, ny_N] = ocp.
dim;
49 qp.n = N * (nx + nu) + nx;
50 index_t nnz_Q = N * (nx + nu) * (nx + nu + 1) / 2 + nx * (nx + 1) / 2;
52 qp.Q_outer_ptr.reserve(
qp.n + 1);
53 qp.Q_inner_idx.reserve(nnz_Q);
54 qp.Q_values.reserve(nnz_Q);
56 for (index_t i = 0; i < N; ++i) {
58 for (index_t c = 0; c < nx + nu; ++c) {
59 auto nnz =
static_cast<index_t
>(
qp.Q_inner_idx.size());
60 qp.Q_outer_ptr.push_back(nnz);
61 for (index_t r = c; r < nx + nu; ++r) {
62 qp.Q_inner_idx.push_back(r_off + r);
63 qp.Q_values.push_back(Hi(r, c));
69 for (index_t c = 0; c < nx; ++c) {
70 auto nnz =
static_cast<index_t
>(
qp.Q_inner_idx.size());
71 qp.Q_outer_ptr.push_back(nnz);
72 for (index_t r = c; r < nx; ++r) {
73 qp.Q_inner_idx.push_back(r_off + r);
74 qp.Q_values.push_back(HN(r, c));
77 qp.Q_outer_ptr.push_back(nnz_Q);
78 assert(r_off + nx ==
qp.n);
79 assert(
qp.Q_outer_ptr.size() ==
static_cast<size_t>(
qp.n + 1));
80 assert(
qp.Q_inner_idx.size() ==
static_cast<size_t>(nnz_Q));
81 assert(
qp.Q_values.size() ==
static_cast<size_t>(nnz_Q));
85 .symmetry = Symmetry::Lower,
86 .inner_idx =
qp.Q_inner_idx,
87 .outer_ptr =
qp.Q_outer_ptr,
92 qp.m_eq = (N + 1) * nx;
93 qp.m_ineq = N * ny + ny_N;
94 index_t m =
qp.m_eq +
qp.m_ineq;
95 index_t nnz_A_eq =
qp.m_eq + N * nx * (nx + nu);
96 index_t nnz_A_ineq = N * ny * (nx + nu) + ny_N * nx;
97 index_t nnz_A = nnz_A_eq + nnz_A_ineq;
99 qp.A_outer_ptr.reserve(
qp.n + 1);
100 qp.A_inner_idx.reserve(nnz_A);
101 qp.A_values.reserve(nnz_A);
102 index_t r_off_eq = 0, r_off_ineq =
qp.m_eq;
103 for (index_t i = 0; i < N; ++i) {
104 auto ABi = ocp.
AB(i), CDi = ocp.
CD(i);
105 for (index_t c = 0; c < nx + nu; ++c) {
106 auto nnz =
static_cast<index_t
>(
qp.A_inner_idx.size());
107 qp.A_outer_ptr.push_back(nnz);
109 qp.A_inner_idx.push_back(r_off_eq + c);
110 qp.A_values.push_back(-1);
112 for (index_t r = 0; r < nx; ++r) {
113 qp.A_inner_idx.push_back(r_off_eq + nx + r);
114 qp.A_values.push_back(ABi(r, c));
116 for (index_t r = 0; r < ny; ++r) {
117 qp.A_inner_idx.push_back(r_off_ineq + r);
118 qp.A_values.push_back(CDi(r, c));
124 auto CDi = ocp.
CD(N);
125 for (index_t c = 0; c < nx; ++c) {
126 auto nnz =
static_cast<index_t
>(
qp.A_inner_idx.size());
127 qp.A_outer_ptr.push_back(nnz);
128 qp.A_inner_idx.push_back(r_off_eq + c);
129 qp.A_values.push_back(-1);
130 for (index_t r = 0; r < ny_N; ++r) {
131 qp.A_inner_idx.push_back(r_off_ineq + r);
132 qp.A_values.push_back(CDi(r, c));
135 qp.A_outer_ptr.push_back(nnz_A);
136 assert(r_off_eq + nx ==
qp.m_eq);
137 assert(r_off_ineq + ny_N == m);
138 assert(
qp.A_outer_ptr.size() ==
static_cast<size_t>(
qp.n + 1));
139 assert(
qp.A_inner_idx.size() ==
static_cast<size_t>(nnz_A));
140 assert(
qp.A_values.size() ==
static_cast<size_t>(nnz_A));
141 qp.A_sparsity = {.rows = m,
143 .symmetry = Symmetry::Unsymmetric,
144 .inner_idx =
qp.A_inner_idx,
145 .outer_ptr =
qp.A_outer_ptr,
152 std::span<const bool> J)
const ->
KKTMatrix {
157 K.
values.reserve(nnz_max);
158 assert(
static_cast<index_t
>(J.size()) ==
m_ineq);
159 assert(
static_cast<index_t
>(Σ.size()) ==
m_ineq);
160 std::vector<index_t> constr_indices(
m_ineq + 1);
161 std::inclusive_scan(J.begin(), J.end(), constr_indices.begin() + 1, std::plus{}, index_t{0});
162 const index_t m_ineq_active = constr_indices.back();
163 real_t inv_S = 1 / S;
164 for (index_t c = 0; c <
n; ++c) {
169 while (Q_ptr < Q_end) {
179 auto A_ineq_ptr =
static_cast<index_t
>(A_ineq_it -
A_inner_idx.begin());
180 const auto A_eq_end = A_ineq_ptr;
181 while (A_ineq_ptr < A_end) {
190 while (A_eq_ptr < A_eq_end) {
197 for (index_t r = 0; r <
m_ineq; ++r) {
201 K.
values.push_back(-1 / Σ[r]);
205 static_cast<index_t
>(K.
inner_idx.size()));
208 .cols =
n + m_ineq_active +
m_eq,
209 .symmetry = Symmetry::Lower,
212 .order =
decltype(K.
sparsity)::SortedRows};
void xgemv_batch_strided(CBLAS_LAYOUT layout, CBLAS_TRANSPOSE trans, I m, I n, std::type_identity_t< T > alpha, std::type_identity_t< const T * > a, I lda, I stridea, std::type_identity_t< const T * > x, I incx, I stridex, std::type_identity_t< T > beta, T *y, I incy, I stridey, I batch_size)
void xgemv(CBLAS_LAYOUT Layout, CBLAS_TRANSPOSE TransA, I M, I N, std::type_identity_t< T > alpha, std::type_identity_t< const T * > A, I lda, std::type_identity_t< const T * > X, I incX, std::type_identity_t< T > beta, T *Y, I incY)