casadi_kron_contract_inner_sparse_dense.hpp
1 //
2 // MIT No Attribution
3 //
4 // Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl, KU Leuven.
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy of this
7 // software and associated documentation files (the "Software"), to deal in the Software
8 // without restriction, including without limitation the rights to use, copy, modify,
9 // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13 // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
15 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
16 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
17 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 //
19 
20 // SYMBOL "kron_contract_inner_sparse_dense"
21 // y[i,j] = sum_{r,s} m[i*mB+r, j*nB+s] * b[r,s]
22 // where m has CSC sparsity sp_m (mA*mB, nA*nB), b is dense (mB, nB),
23 // y has CSC sparsity sp_y (mA, nA). Walks m's nonzeros only; no densify-into-w
24 // step needed since b is already dense.
25 template<typename T1>
26 void casadi_kron_contract_inner_sparse_dense(const T1* m, const casadi_int* sp_m,
27  const T1* b, casadi_int mB, casadi_int nB,
28  T1* y, const casadi_int* sp_y) {
29  casadi_int nA = sp_y[1];
30  const casadi_int* y_colind = sp_y+2;
31  const casadi_int* y_row = sp_y+2+nA+1;
32  casadi_int m_ncol = sp_m[1];
33  const casadi_int* m_colind = sp_m+2;
34  const casadi_int* m_row = sp_m+2+m_ncol+1;
35  casadi_int cc, j, s, el, rr, i, r, y_el, y_col_start, y_col_end, k;
36  T1 b_val;
37  for (k=0; k<y_colind[nA]; ++k) y[k] = 0;
38  // Nested (j, s) loop avoids per-column cc / nB and cc % nB.
39  for (j=0; j<nA; ++j) {
40  y_col_start = y_colind[j];
41  y_col_end = y_colind[j+1];
42  if (y_col_start == y_col_end) continue;
43  for (s=0; s<nB; ++s) {
44  cc = j*nB + s;
45  for (el=m_colind[cc]; el<m_colind[cc+1]; ++el) {
46  rr = m_row[el];
47  i = rr / mB;
48  r = rr % mB;
49  b_val = b[s*mB + r];
50  for (y_el=y_col_start; y_el<y_col_end; ++y_el) {
51  if (y_row[y_el] == i) { y[y_el] += m[el] * b_val; break; }
52  if (y_row[y_el] > i) break;
53  }
54  }
55  }
56  }
57 }