casadi_norm_inf_mul.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 "norm_inf_mul"
21 template<typename T1>
22 T1 casadi_norm_inf_mul(const T1* x, const casadi_int* sp_x, const T1* y, const casadi_int* sp_y, T1* dwork, casadi_int* iwork) { // NOLINT(whitespace/line_length)
23  casadi_int nrow_x, ncol_x, ncol_y, i, jj, kk, nnz;
24  const casadi_int *colind_x, *row_x, *colind_y, *row_y;
25  casadi_int *mask, *next;
26 
27  T1 res = 0;
28  // Get sparsities
29  nrow_x = sp_x[0]; ncol_x = sp_x[1];
30  colind_x = sp_x+2; row_x = sp_x + 2 + ncol_x+1;
31  ncol_y = sp_y[1];
32  colind_y = sp_y+2; row_y = sp_y + 2 + ncol_y+1;
33 
34  // Implementation inspired on Scipy's sparsetools/csr.h
35  // method that uses O(n) temp storage
36  mask = iwork + ncol_y+1;
37 
38  // Pass 1
39  for (i=0; i<nrow_x; ++i) mask[i] = -1;
40  iwork[0] = 0;
41  nnz = 0;
42  for (i=0; i<ncol_y; ++i) {
43  casadi_int next_nnz;
44  casadi_int row_nnz = 0;
45  for (jj=colind_y[i]; jj < colind_y[i+1]; jj++) {
46  casadi_int j = row_y[jj];
47  for (kk=colind_x[j]; kk < colind_x[j+1]; kk++) {
48  casadi_int k = row_x[kk];
49  if (mask[k] != i) {
50  mask[k] = i;
51  row_nnz++;
52  }
53  }
54  }
55  next_nnz = nnz + row_nnz;
56  nnz = next_nnz;
57  iwork[i+1] = nnz;
58  }
59 
60  // Pass 2
61  next = iwork + ncol_y+1;
62  for (i=0; i<nrow_x; ++i) next[i] = -1;
63  T1* sums = dwork;
64  for (i=0; i<nrow_x; ++i) sums[i] = 0;
65  nnz = 0;
66  iwork[0] = 0;
67  for (i=0; i<ncol_y; ++i) {
68  casadi_int head, length, jj_start, jj_end;
69  head = -2;
70  length = 0;
71  jj_start = colind_y[i];
72  jj_end = colind_y[i+1];
73  for (jj=jj_start; jj<jj_end; ++jj) {
74  casadi_int j, kk_start, kk_end;
75  T1 v;
76  j = row_y[jj];
77  v = y[jj];
78  kk_start = colind_x[j];
79  kk_end = colind_x[j+1];
80  for (kk = kk_start; kk<kk_end; ++kk) {
81  casadi_int k = row_x[kk];
82  sums[k] += v*x[kk];
83  if (next[k] == -1) {
84  next[k] = head;
85  head = k;
86  length++;
87  }
88  }
89  }
90  for (jj=0; jj<length; ++jj) {
91  casadi_int temp;
92  if (!is_zero(sums[head])) {
93  T1 a = fabs(sums[head]);
94  res = fmax(res, a);
95  nnz++;
96  }
97  temp = head;
98  head = next[head];
99  next[temp] = -1; //clear arrays
100  sums[temp] = 0;
101  }
102  iwork[i+1] = nnz;
103  }
104  return res;
105 }
bool is_zero(const T &x)