setnonzeros_param_impl.hpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #ifndef CASADI_SETNONZEROS_PARAM_IMPL_HPP
27 #define CASADI_SETNONZEROS_PARAM_IMPL_HPP
28 
29 #include "setnonzeros_param.hpp"
30 #include "casadi_misc.hpp"
31 #include "serializing_stream.hpp"
32 
34 
35 namespace casadi {
36 
37  template<bool Add>
38  MX SetNonzerosParam<Add>::create(const MX& y, const MX& x, const MX& nz) {
39  return MX::create(new SetNonzerosParamVector<Add>(y, x, nz));
40  }
41 
42  template<bool Add>
43  MX SetNonzerosParam<Add>::create(const MX& y, const MX& x, const Slice& inner, const MX& outer) {
44  casadi_assert(outer.is_vector() && outer.is_dense(), "outer must be dense vector");
45  return MX::create(new SetNonzerosSliceParam<Add>(y, x, inner, outer));
46  }
47 
48  template<bool Add>
49  MX SetNonzerosParam<Add>::create(const MX& y, const MX& x, const MX& inner, const Slice& outer) {
50  casadi_assert(inner.is_vector() && inner.is_dense(), "inner must be dense vector");
51  return MX::create(new SetNonzerosParamSlice<Add>(y, x, inner, outer));
52  }
53 
54  template<bool Add>
55  MX SetNonzerosParam<Add>::create(const MX& y, const MX& x, const MX& inner, const MX& outer) {
56  casadi_assert(inner.is_vector() && inner.is_dense(), "inner must be dense vector");
57  casadi_assert(outer.is_vector() && outer.is_dense(), "outer must be dense vector");
58  return MX::create(new SetNonzerosParamParam<Add>(y, x, inner, outer));
59  }
60 
61  template<bool Add>
62  SetNonzerosParam<Add>::SetNonzerosParam(const MX& y, const MX& x, const MX& nz) {
63  this->set_sparsity(y.sparsity());
64  this->set_dep(y, x, nz);
65  }
66 
67  template<bool Add>
68  SetNonzerosParam<Add>::SetNonzerosParam(const MX& y, const MX& x, const MX& nz, const MX& nz2) {
69  this->set_sparsity(y.sparsity());
70  this->set_dep({y, x, nz, nz2});
71  }
72 
73  template<bool Add>
74  SetNonzerosParamVector<Add>::SetNonzerosParamVector(const MX& y, const MX& x,
75  const MX& nz) : SetNonzerosParam<Add>(y, x, nz) {
76  }
77 
78  template<bool Add>
79  SetNonzerosParam<Add>:: ~SetNonzerosParam() {
80  }
81 
82  template<bool Add>
83  void SetNonzerosParamVector<Add>::
84  eval_mx(const std::vector<MX>& arg, std::vector<MX>& res) const {
85  // Add to the element to the sensitivity, if any
86  MX arg0 = project(arg[0], this->dep(0).sparsity());
87  MX arg1 = project(arg[1], this->dep(1).sparsity());
88  MX nz = arg[2];
89  if (Add) {
90  res[0] = arg1->get_nzadd(arg0, nz);
91  } else {
92  res[0] = arg1->get_nzassign(arg0, nz);
93  }
94  }
95 
96  template<bool Add>
97  void SetNonzerosParamSlice<Add>::
98  eval_mx(const std::vector<MX>& arg, std::vector<MX>& res) const {
99  // Add to the element to the sensitivity, if any
100  MX arg0 = project(arg[0], this->dep(0).sparsity());
101  MX arg1 = project(arg[1], this->dep(1).sparsity());
102  MX inner = arg[2];
103  if (Add) {
104  res[0] = arg1->get_nzadd(arg0, inner, outer_);
105  } else {
106  res[0] = arg1->get_nzassign(arg0, inner, outer_);
107  }
108  }
109 
110  template<bool Add>
111  void SetNonzerosSliceParam<Add>::
112  eval_mx(const std::vector<MX>& arg, std::vector<MX>& res) const {
113  // Add to the element to the sensitivity, if any
114  MX arg0 = project(arg[0], this->dep(0).sparsity());
115  MX arg1 = project(arg[1], this->dep(1).sparsity());
116  MX outer = arg[2];
117  if (Add) {
118  res[0] = arg1->get_nzadd(arg0, inner_, outer);
119  } else {
120  res[0] = arg1->get_nzassign(arg0, inner_, outer);
121  }
122  }
123 
124  template<bool Add>
125  void SetNonzerosParamParam<Add>::
126  eval_mx(const std::vector<MX>& arg, std::vector<MX>& res) const {
127  // Add to the element to the sensitivity, if any
128  MX arg0 = project(arg[0], this->dep(0).sparsity());
129  MX arg1 = project(arg[1], this->dep(1).sparsity());
130  MX inner = arg[2];
131  MX outer = arg[3];
132  if (Add) {
133  res[0] = arg1->get_nzadd(arg0, inner, outer);
134  } else {
135  res[0] = arg1->get_nzassign(arg0, inner, outer);
136  }
137  }
138 
139  template<bool Add>
140  void SetNonzerosParamVector<Add>::ad_forward(const std::vector<std::vector<MX> >& fseed,
141  std::vector<std::vector<MX> >& fsens) const {
142  const MX& nz = this->dep(2);
143  // Nondifferentiated function and forward sensitivities
144  for (casadi_int d=0; d<fsens.size(); ++d) {
145 
146  // Get references to arguments and results
147  MX arg0 = project(fseed[d][0], this->dep(0).sparsity());
148  MX arg1 = project(fseed[d][1], this->dep(1).sparsity());
149 
150  /*
151  dep(0) <-> y
152  dep(1) <-> x
153 
154  y[nz]+=x
155 
156  dot(y)[nz]+=dot(x)
157 
158  dot(x)->get_nzadd(dot(y), nz)
159 
160  */
161 
162  MX& res = fsens[d][0];
163  res = arg0;
164 
165  if (Add) {
166  res = arg1->get_nzadd(res, nz);
167  } else {
168  res = arg1->get_nzassign(res, nz);
169  }
170  }
171  }
172 
173  template<bool Add>
174  void SetNonzerosParamVector<Add>::ad_reverse(const std::vector<std::vector<MX> >& aseed,
175  std::vector<std::vector<MX> >& asens) const {
176  const MX& nz = this->dep(2);
177  for (casadi_int d=0; d<aseed.size(); ++d) {
178  MX seed = project(aseed[d][0], this->sparsity());
179 
180  /*
181  dep(0) <-> y
182  dep(1) <-> x
183 
184  z: y[nz]+=x
185 
186  bar(x) += bar(z)[nz]
187  bar(y) += bar(z)
188  */
189  asens[d][1] += seed->get_nz_ref(nz);
190  if (!Add) {
191  asens[d][0] += MX::zeros(this->dep(1).sparsity())->get_nzassign(seed, nz);
192  } else {
193  asens[d][0] += seed;
194  }
195  }
196  }
197 
198 
199  template<bool Add>
200  void SetNonzerosParamSlice<Add>::ad_forward(const std::vector<std::vector<MX> >& fseed,
201  std::vector<std::vector<MX> >& fsens) const {
202  const MX& inner = this->dep(2);
203  for (casadi_int d=0; d<fsens.size(); ++d) {
204  MX arg0 = project(fseed[d][0], this->dep(0).sparsity());
205  MX arg1 = project(fseed[d][1], this->dep(1).sparsity());
206 
207  MX& res = fsens[d][0];
208  res = arg0;
209 
210  if (Add) {
211  res = arg1->get_nzadd(res, inner, outer_);
212  } else {
213  res = arg1->get_nzassign(res, inner, outer_);
214  }
215  }
216  }
217 
218  template<bool Add>
219  void SetNonzerosParamSlice<Add>::ad_reverse(const std::vector<std::vector<MX> >& aseed,
220  std::vector<std::vector<MX> >& asens) const {
221  const MX& inner = this->dep(2);
222  for (casadi_int d=0; d<aseed.size(); ++d) {
223  MX seed = project(aseed[d][0], this->sparsity());
224  asens[d][1] += seed->get_nz_ref(inner, outer_);
225  if (!Add) {
226  asens[d][0] += MX::zeros(this->dep(1).sparsity())->get_nzassign(seed, inner, outer_);
227  } else {
228  asens[d][0] += seed;
229  }
230  }
231  }
232 
233  template<bool Add>
234  void SetNonzerosSliceParam<Add>::ad_forward(const std::vector<std::vector<MX> >& fseed,
235  std::vector<std::vector<MX> >& fsens) const {
236  const MX& outer = this->dep(2);
237  for (casadi_int d=0; d<fsens.size(); ++d) {
238  MX arg0 = project(fseed[d][0], this->dep(0).sparsity());
239  MX arg1 = project(fseed[d][1], this->dep(1).sparsity());
240 
241  MX& res = fsens[d][0];
242  res = arg0;
243 
244  if (Add) {
245  res = arg1->get_nzadd(res, inner_, outer);
246  } else {
247  res = arg1->get_nzassign(res, inner_, outer);
248  }
249  }
250  }
251 
252  template<bool Add>
253  void SetNonzerosSliceParam<Add>::ad_reverse(const std::vector<std::vector<MX> >& aseed,
254  std::vector<std::vector<MX> >& asens) const {
255  const MX& outer = this->dep(2);
256  for (casadi_int d=0; d<aseed.size(); ++d) {
257  MX seed = project(aseed[d][0], this->sparsity());
258  asens[d][1] += seed->get_nz_ref(inner_, outer);
259  if (!Add) {
260  asens[d][0] += MX::zeros(this->dep(1).sparsity())->get_nzassign(seed, inner_, outer);
261  } else {
262  asens[d][0] += seed;
263  }
264  }
265  }
266 
267  template<bool Add>
268  void SetNonzerosParamParam<Add>::ad_forward(const std::vector<std::vector<MX> >& fseed,
269  std::vector<std::vector<MX> >& fsens) const {
270  const MX& inner = this->dep(2);
271  const MX& outer = this->dep(3);
272  for (casadi_int d=0; d<fsens.size(); ++d) {
273  MX arg0 = project(fseed[d][0], this->dep(0).sparsity());
274  MX arg1 = project(fseed[d][1], this->dep(1).sparsity());
275 
276  MX& res = fsens[d][0];
277  res = arg0;
278 
279  if (Add) {
280  res = arg1->get_nzadd(res, inner, outer);
281  } else {
282  res = arg1->get_nzassign(res, inner, outer);
283  }
284  }
285  }
286 
287  template<bool Add>
288  void SetNonzerosParamParam<Add>::ad_reverse(const std::vector<std::vector<MX> >& aseed,
289  std::vector<std::vector<MX> >& asens) const {
290  const MX& inner = this->dep(2);
291  const MX& outer = this->dep(3);
292  for (casadi_int d=0; d<aseed.size(); ++d) {
293  MX seed = project(aseed[d][0], this->sparsity());
294  asens[d][1] += seed->get_nz_ref(inner, outer);
295  if (!Add) {
296  asens[d][0] += MX::zeros(this->dep(1).sparsity())->get_nzassign(seed, inner, outer);
297  } else {
298  asens[d][0] += seed;
299  }
300  }
301  }
302 
303  template<bool Add>
304  int SetNonzerosParamVector<Add>::
305  eval(const double** arg, double** res, casadi_int* iw, double* w) const {
306  const double* idata0 = arg[0];
307  const double* idata = arg[1];
308  const double* nz = arg[2];
309  double* odata = res[0];
310  // Dimensions
311  casadi_int nnz = this->dep(2).nnz();
312  casadi_int max_ind = this->dep(0).nnz();
313  if (idata0 != odata) {
314  std::copy(idata0, idata0+this->dep(0).nnz(), odata);
315  }
316  for (casadi_int k=0; k<nnz; ++k) {
317  // Get index
318  casadi_int index = static_cast<casadi_int>(*nz++);
319  if (Add) {
320  if (index>=0 && index<max_ind) odata[index] += *idata;
321  } else {
322  if (index>=0 && index<max_ind) odata[index] = *idata;
323  }
324  idata++;
325  }
326  return 0;
327  }
328 
329  template<bool Add>
330  int SetNonzerosParamSlice<Add>::
331  eval(const double** arg, double** res, casadi_int* iw, double* w) const {
332  const double* idata0 = arg[0];
333  const double* idata = arg[1];
334  const double* nz = arg[2];
335  double* odata = res[0];
336  // Dimensions
337  casadi_int nnz = this->dep(2).nnz();
338  casadi_int max_ind = this->dep(0).nnz();
339  if (idata0 != odata) {
340  std::copy(idata0, idata0+this->dep(0).nnz(), odata);
341  }
342 
343  casadi_int* inner = iw; iw += nnz;
344  for (casadi_int i=0; i<nnz; ++i) {
345  // Get index
346  inner[i] = static_cast<casadi_int>(*nz++);
347  }
348  for (casadi_int i=outer_.start;i<outer_.stop;i+= outer_.step) {
349  // Get index
350  for (casadi_int* inner_it=inner; inner_it!=inner+nnz; ++inner_it) {
351  casadi_int index = i+*inner_it;
352  if (Add) {
353  if (index>=0 && index<max_ind) odata[index] += *idata;
354  } else {
355  if (index>=0 && index<max_ind) odata[index] = *idata;
356  }
357  idata++;
358  }
359  }
360  return 0;
361  }
362 
363  template<bool Add>
364  int SetNonzerosSliceParam<Add>::
365  eval(const double** arg, double** res, casadi_int* iw, double* w) const {
366  const double* idata0 = arg[0];
367  const double* idata = arg[1];
368  const double* nz = arg[2];
369  double* odata = res[0];
370  // Dimensions
371  casadi_int nnz = this->dep(2).nnz();
372  casadi_int max_ind = this->dep(0).nnz();
373  if (idata0 != odata) {
374  std::copy(idata0, idata0+this->dep(0).nnz(), odata);
375  }
376  for (casadi_int k=0; k<nnz; ++k) {
377  // Get index
378  casadi_int ind = static_cast<casadi_int>(*nz++);
379  for (casadi_int j=0;j<inner_.stop;j+= inner_.step) {
380  casadi_int index = ind+j;
381  if (Add) {
382  if (index>=0 && index<max_ind) odata[index] += *idata;
383  } else {
384  if (index>=0 && index<max_ind) odata[index] = *idata;
385  }
386  idata++;
387  }
388  }
389  return 0;
390  }
391 
392  template<bool Add>
393  int SetNonzerosParamParam<Add>::
394  eval(const double** arg, double** res, casadi_int* iw, double* w) const {
395  const double* idata0 = arg[0];
396  const double* idata = arg[1];
397  const double* nz = arg[2];
398  const double* nz2 = arg[3];
399  double* odata = res[0];
400  // Dimensions
401  casadi_int nnz = this->dep(2).nnz();
402  casadi_int nnz2 = this->dep(3).nnz();
403  casadi_int max_ind = this->dep(0).nnz();
404  if (idata0 != odata) {
405  std::copy(idata0, idata0+this->dep(0).nnz(), odata);
406  }
407 
408  casadi_int* inner = iw; iw += nnz;
409  for (casadi_int i=0; i<nnz; ++i) {
410  // Get index
411  inner[i] = static_cast<casadi_int>(*nz++);
412  }
413 
414  for (casadi_int k=0; k<nnz2; ++k) {
415  // Get index
416  casadi_int ind = static_cast<casadi_int>(*nz2++);
417  for (casadi_int* inner_it=inner; inner_it!=inner+nnz; ++inner_it) {
418  casadi_int index = ind+*inner_it;
419  if (Add) {
420  if (index>=0 && index<max_ind) odata[index] += *idata;
421  } else {
422  if (index>=0 && index<max_ind) odata[index] = *idata;
423  }
424  idata++;
425  }
426  }
427  return 0;
428  }
429 
430  template<bool Add>
431  size_t SetNonzerosParamSlice<Add>::
432  sz_iw() const {
433  return this->dep(2).nnz();
434  }
435 
436  template<bool Add>
437  size_t SetNonzerosParamParam<Add>::
438  sz_iw() const {
439  return this->dep(2).nnz();
440  }
441 
442 
443  template<bool Add>
444  int SetNonzerosParam<Add>::
445  sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
446  // Parametric index -> any input disturbance propagates to any output
447  bvec_t arg0 = bvec_or(arg[0], this->dep(0).nnz());
448  bvec_t arg1 = bvec_or(arg[1], this->dep(1).nnz());
449 
450  bvec_t *r = res[0];
451  std::fill(r, r+this->nnz(), arg0 | arg1);
452  return 0;
453  }
454 
455  template<bool Add>
456  int SetNonzerosParam<Add>::
457  sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
458  bvec_t *arg0 = arg[0];
459  bvec_t *arg1 = arg[1];
460  bvec_t r = bvec_or(res[0], this->nnz());
461  std::fill(res[0], res[0]+this->nnz(), bvec_t(0));
462 
463  for (casadi_int i=0;i<this->dep(0).nnz();++i) {
464  *arg0++ |= r;
465  }
466  for (casadi_int i=0;i<this->dep(1).nnz();++i) {
467  *arg1++ |= r;
468  }
469  return 0;
470  }
471 
472  template<bool Add>
473  std::string SetNonzerosParamVector<Add>::disp(const std::vector<std::string>& arg) const {
474  std::stringstream ss;
475  ss << "(" << arg.at(0) << "[" << arg.at(2) << "]";
476  ss << (Add ? " += " : " = ") << arg.at(1) << ")";
477  return ss.str();
478  }
479 
480  template<bool Add>
481  std::string SetNonzerosParamSlice<Add>::disp(const std::vector<std::string>& arg) const {
482  std::stringstream ss;
483  ss << "(" << arg.at(0) << "[(" << arg.at(2) << ";" << outer_ << ")]";
484  ss << (Add ? " += " : " = ") << arg.at(1) << ")";
485  return ss.str();
486  }
487 
488  template<bool Add>
489  std::string SetNonzerosSliceParam<Add>::disp(const std::vector<std::string>& arg) const {
490  std::stringstream ss;
491  ss << "(" << arg.at(0) << "[(" << inner_ << ";" << arg.at(2) << ")]";
492  ss << (Add ? " += " : " = ") << arg.at(1) << ")";
493  return ss.str();
494  }
495 
496  template<bool Add>
497  std::string SetNonzerosParamParam<Add>::disp(const std::vector<std::string>& arg) const {
498  std::stringstream ss;
499  ss << "(" << arg.at(0) << "[(" << arg.at(2) << ";" << arg.at(3) << ")]";
500  ss << (Add ? " += " : " = ") << arg.at(1) << ")";
501  return ss.str();
502  }
503 
504  template<bool Add>
505  void SetNonzerosParam<Add>::
506  generate(CodeGenerator& g,
507  const std::vector<casadi_int>& arg, const std::vector<casadi_int>& res) const {
508  // Copy first argument if not inplace
509  if (arg[0]!=res[0]) {
510  g << g.copy(g.work(arg[0], this->dep(0).nnz()), this->nnz(),
511  g.work(res[0], this->nnz())) << '\n';
512  }
513  }
514 
515  template<bool Add>
516  void SetNonzerosParamVector<Add>::
517  generate(CodeGenerator& g,
518  const std::vector<casadi_int>& arg, const std::vector<casadi_int>& res) const {
519  SetNonzerosParam<Add>::generate(g, arg, res);
520 
521  casadi_int n = this->dep(1).nnz();
522 
523  g.local("i", "casadi_int");
524  g.local("cr", "const casadi_real", "*");
525  g.local("cs", "const casadi_real", "*");
526  g << "for (cs=" << g.work(arg[1], n) << ", cr=" << g.work(arg[2], n)
527  << "; cs!=" << g.work(arg[1], n) << "+" << n
528  << "; ++cs) { i=(int) *cr++; if (i>=0 && i<" << this->dep(0).nnz() << ") "
529  << g.work(res[0], this->nnz()) << "[i] " << (Add?"+= ":"= ")
530  << "*cs; }\n";
531  }
532 
533  template<bool Add>
534  void SetNonzerosParamSlice<Add>::
535  generate(CodeGenerator& g,
536  const std::vector<casadi_int>& arg, const std::vector<casadi_int>& res) const {
537  SetNonzerosParam<Add>::generate(g, arg, res);
538 
539  casadi_int n = this->dep(1).nnz();
540  casadi_int n_inner = this->dep(2).nnz();
541 
542  g.local("cii", "const casadi_int", "*");
543  g.local("i", "casadi_int");
544  g << "for (i=0;i<" << n_inner << ";++i) iw[i] = (int) "
545  << g.work(arg[2], n_inner) << "[i];\n";
546 
547  g.local("cs", "const casadi_real", "*");
548  g.local("k", "casadi_int");
549  g << "for (cs=" << g.work(arg[1], n)
550  << ", k=" << outer_.start << ";k<" << outer_.stop << ";k+=" << outer_.step << ") ";
551  g << "for (cii=iw; cii!=iw" << "+" << n_inner << "; ++cii) { i=k+*cii; "
552  << "if (i>=0 && i<" << this->dep(0).nnz() << ") "
553  << g.work(res[0], this->nnz()) << "[i] " << (Add?"+= ":"= ")
554  << "*cs; cs++; }\n";
555  }
556 
557  template<bool Add>
558  void SetNonzerosSliceParam<Add>::
559  generate(CodeGenerator& g,
560  const std::vector<casadi_int>& arg, const std::vector<casadi_int>& res) const {
561  SetNonzerosParam<Add>::generate(g, arg, res);
562 
563  casadi_int n = this->dep(1).nnz();
564  casadi_int n_outer = this->dep(2).nnz();
565 
566  g.local("i", "casadi_int");
567  g.local("j", "casadi_int");
568  g.local("k", "casadi_int");
569  g.local("cr", "const casadi_real", "*");
570  g.local("cs", "const casadi_real", "*");
571  g << "for (cr=" << g.work(arg[2], n_outer)
572  << ", cs=" << g.work(arg[1], n)
573  << "; cr!=" << g.work(arg[2], n_outer) << "+" << n_outer
574  << "; ++cr) ";
575  g << "for (j=(int) *cr, "
576  << "k=" << inner_.start << ";k<" << inner_.stop << ";k+=" << inner_.step << ") ";
577  g << "{ i=k+j; "
578  << "if (i>=0 && i<" << this->dep(0).nnz() << ") "
579  << g.work(res[0], this->nnz()) << "[i] " << (Add?"+= ":"= ")
580  << "*cs; cs++; }\n";
581  }
582 
583  template<bool Add>
584  void SetNonzerosParamParam<Add>::
585  generate(CodeGenerator& g,
586  const std::vector<casadi_int>& arg, const std::vector<casadi_int>& res) const {
587  SetNonzerosParam<Add>::generate(g, arg, res);
588  casadi_int n = this->dep(1).nnz();
589  casadi_int n_outer = this->dep(3).nnz();
590  casadi_int n_inner = this->dep(2).nnz();
591 
592  g.local("cii", "const casadi_int", "*");
593  g.local("i", "casadi_int");
594  g << "for (i=0;i<" << n_inner << ";++i) iw[i] = (int) "
595  << g.work(arg[2], n_inner) << "[i];\n";
596 
597  g.local("j", "casadi_int");
598  g.local("cr", "const casadi_real", "*");
599  g.local("cs", "const casadi_real", "*");
600  g << "for (cr=" << g.work(arg[3], n_outer)
601  << ", cs=" << g.work(arg[1], n)
602  << "; cr!=" << g.work(arg[3], n_outer) << "+" << n_outer
603  << "; ++cr) ";
604  g << "for (j=(int) *cr, cii=iw; cii!=iw" << "+" << n_inner << "; ++cii) { i=j+*cii; "
605  << "if (i>=0 && i<" << this->dep(0).nnz() << ") "
606  << g.work(res[0], this->nnz()) << "[i] " << (Add?"+= ":"= ")
607  << "*cs; cs++; }\n";
608  }
609 
610  template<bool Add>
611  void SetNonzerosParamVector<Add>::serialize_body(SerializingStream& s) const {
612  MXNode::serialize_body(s);
613  }
614 
615  template<bool Add>
616  SetNonzerosParamVector<Add>::SetNonzerosParamVector(DeserializingStream& s) :
617  SetNonzerosParam<Add>(s) {
618  }
619 
620  template<bool Add>
621  void SetNonzerosParamVector<Add>::serialize_type(SerializingStream& s) const {
622  MXNode::serialize_type(s);
623  s.pack("SetNonzerosParam::type", 'a');
624  }
625 
626  template<bool Add>
627  void SetNonzerosParamSlice<Add>::serialize_body(SerializingStream& s) const {
628  MXNode::serialize_body(s);
629  s.pack("SetNonzerosParamSlice::outer", outer_);
630  }
631 
632  template<bool Add>
633  SetNonzerosParamSlice<Add>::SetNonzerosParamSlice(DeserializingStream& s) :
634  SetNonzerosParam<Add>(s) {
635  s.unpack("SetNonzerosParamSlice::outer", outer_);
636  }
637 
638  template<bool Add>
639  void SetNonzerosParamSlice<Add>::serialize_type(SerializingStream& s) const {
640  MXNode::serialize_type(s);
641  s.pack("SetNonzerosParam::type", 'b');
642  }
643 
644  template<bool Add>
645  void SetNonzerosSliceParam<Add>::serialize_body(SerializingStream& s) const {
646  MXNode::serialize_body(s);
647  s.pack("SetNonzerosSliceParam::inner", inner_);
648  }
649 
650  template<bool Add>
651  SetNonzerosSliceParam<Add>::SetNonzerosSliceParam(DeserializingStream& s) :
652  SetNonzerosParam<Add>(s) {
653  s.unpack("SetNonzerosSliceParam::inner", inner_);
654  }
655 
656  template<bool Add>
657  void SetNonzerosSliceParam<Add>::serialize_type(SerializingStream& s) const {
658  MXNode::serialize_type(s);
659  s.pack("SetNonzerosParam::type", 'c');
660  }
661 
662 
663  template<bool Add>
664  void SetNonzerosParamParam<Add>::serialize_type(SerializingStream& s) const {
665  MXNode::serialize_type(s);
666  s.pack("SetNonzerosParam::type", 'd');
667  }
668 
669  template<bool Add>
670  SetNonzerosParamParam<Add>::SetNonzerosParamParam(DeserializingStream& s) :
671  SetNonzerosParam<Add>(s) {
672  }
673 
674  template<bool Add>
675  MXNode* SetNonzerosParam<Add>::deserialize(DeserializingStream& s) {
676  char t;
677  s.unpack("SetNonzerosParam::type", t);
678  switch (t) {
679  case 'a': return new SetNonzerosParamVector<Add>(s);
680  case 'b': return new SetNonzerosParamSlice<Add>(s);
681  case 'c': return new SetNonzerosSliceParam<Add>(s);
682  case 'd': return new SetNonzerosParamParam<Add>(s);
683  default: casadi_assert_dev(false);
684  }
685  }
686 
687 } // namespace casadi
688 
690 
691 #endif // CASADI_SETNONZEROS_PARAM_IMPL_HPP
The casadi namespace.