transpose.cpp
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 #include "transpose.hpp"
27 #include "serializing_stream.hpp"
28 
29 namespace casadi {
30 
32  set_dep(x);
33  set_sparsity(x.sparsity().T());
34  }
35 
38  s.pack("Transpose::dense", false);
39  }
40 
42  MXNode::serialize_type(s); // NOLINT
43  s.pack("Transpose::dense", true);
44  }
45 
47  bool t;
48  s.unpack("Transpose::dense", t);
49  if (t) {
50  return new DenseTranspose(s);
51  } else {
52  return new Transpose(s);
53  }
54  }
55 
56  int Transpose::eval(const double** arg, double** res, casadi_int* iw, double* w) const {
57  return eval_gen<double>(arg, res, iw, w);
58  }
59 
60  int DenseTranspose::eval(const double** arg, double** res, casadi_int* iw, double* w) const {
61  return eval_gen<double>(arg, res, iw, w);
62  }
63 
65  eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w) const {
66  return eval_gen<SXElem>(arg, res, iw, w);
67  }
68 
70  eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w) const {
71  return eval_gen<SXElem>(arg, res, iw, w);
72  }
73 
74  template<typename T>
75  int Transpose::eval_gen(const T* const* arg, T* const* res,
76  casadi_int* iw, T* w) const {
77  // Get sparsity patterns
78  //const std::vector<casadi_int>& x_colind = input[0]->colind();
79  const casadi_int* x_row = dep(0).row();
80  casadi_int x_sz = dep(0).nnz();
81  const casadi_int* xT_colind = sparsity().colind();
82  casadi_int xT_ncol = sparsity().size2();
83 
84  const T* x = arg[0];
85  T* xT = res[0];
86 
87  // Transpose
88  std::copy(xT_colind, xT_colind+xT_ncol+1, iw);
89  for (casadi_int el=0; el<x_sz; ++el) {
90  xT[iw[x_row[el]]++] = x[el];
91  }
92  return 0;
93  }
94 
95  template<typename T>
96  int DenseTranspose::eval_gen(const T* const* arg, T* const* res,
97  casadi_int* iw, T* w) const {
98  // Get sparsity patterns
99  casadi_int x_nrow = dep().size1();
100  casadi_int x_ncol = dep().size2();
101 
102  const T* x = arg[0];
103  T* xT = res[0];
104  for (casadi_int i=0; i<x_ncol; ++i) {
105  for (casadi_int j=0; j<x_nrow; ++j) {
106  xT[i+j*x_ncol] = x[j+i*x_nrow];
107  }
108  }
109  return 0;
110  }
111 
113  sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
114  // Shorthands
115  const bvec_t *x = arg[0];
116  bvec_t *xT = res[0];
117 
118  // Get sparsity
119  casadi_int nz = nnz();
120  const casadi_int* x_row = dep().row();
121  const casadi_int* xT_colind = sparsity().colind();
122  casadi_int xT_ncol = sparsity().size2();
123 
124  // Loop over the nonzeros of the argument
125  std::copy(xT_colind, xT_colind+xT_ncol+1, iw);
126  for (casadi_int el=0; el<nz; ++el) {
127  xT[iw[*x_row++]++] = *x++;
128  }
129  return 0;
130  }
131 
133  sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
134  // Shorthands
135  bvec_t *x = arg[0];
136  bvec_t *xT = res[0];
137 
138  // Get sparsity
139  casadi_int nz = nnz();
140  const casadi_int* x_row = dep().row();
141  const casadi_int* xT_colind = sparsity().colind();
142  casadi_int xT_ncol = sparsity().size2();
143 
144  // Loop over the nonzeros of the argument
145  std::copy(xT_colind, xT_colind+xT_ncol+1, iw);
146  for (casadi_int el=0; el<nz; ++el) {
147  casadi_int elT = iw[*x_row++]++;
148  *x++ |= xT[elT];
149  xT[elT] = 0;
150  }
151  return 0;
152  }
153 
155  sp_forward(const bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
156  // Shorthands
157  const bvec_t *x = arg[0];
158  bvec_t *xT = res[0];
159  casadi_int x_nrow = dep().size1();
160  casadi_int x_ncol = dep().size2();
161 
162  // Loop over the elements
163  for (casadi_int rr=0; rr<x_nrow; ++rr) {
164  for (casadi_int cc=0; cc<x_ncol; ++cc) {
165  *xT++ = x[rr+cc*x_nrow];
166  }
167  }
168  return 0;
169  }
170 
172  sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w) const {
173  // Shorthands
174  bvec_t *x = arg[0];
175  bvec_t *xT = res[0];
176  casadi_int x_nrow = dep().size1();
177  casadi_int x_ncol = dep().size2();
178 
179  // Loop over the elements
180  for (casadi_int rr=0; rr<x_nrow; ++rr) {
181  for (casadi_int cc=0; cc<x_ncol; ++cc) {
182  x[rr+cc*x_nrow] |= *xT;
183  *xT++ = 0;
184  }
185  }
186  return 0;
187  }
188 
189  std::string Transpose::disp(const std::vector<std::string>& arg) const {
190  return arg.at(0) + "'";
191  }
192 
193  void Transpose::eval_mx(const std::vector<MX>& arg, std::vector<MX>& res) const {
194  res[0] = arg[0].T();
195  }
196 
197  void Transpose::ad_forward(const std::vector<std::vector<MX> >& fseed,
198  std::vector<std::vector<MX> >& fsens) const {
199  for (casadi_int d=0; d<fsens.size(); ++d) {
200  fsens[d][0] = fseed[d][0].T();
201  }
202  }
203 
204  void Transpose::ad_reverse(const std::vector<std::vector<MX> >& aseed,
205  std::vector<std::vector<MX> >& asens) const {
206  for (casadi_int d=0; d<aseed.size(); ++d) {
207  asens[d][0] += aseed[d][0].T();
208  }
209  }
210 
212  const std::vector<casadi_int>& arg,
213  const std::vector<casadi_int>& res,
214  const std::vector<bool>& arg_is_ref,
215  std::vector<bool>& res_is_ref) const {
216  g << g.trans(g.work(arg[0], nnz(), arg_is_ref[0]), dep().sparsity(),
217  g.work(res[0], nnz(), false), sparsity(), "iw") << ";\n";
218  }
219 
221  const std::vector<casadi_int>& arg,
222  const std::vector<casadi_int>& res,
223  const std::vector<bool>& arg_is_ref,
224  std::vector<bool>& res_is_ref) const {
225  g.local("cs", "const casadi_real", "*");
226  g.local("rr", "casadi_real", "*");
227  g.local("i", "casadi_int");
228  g.local("j", "casadi_int");
229  g << "for (i=0, rr=" << g.work(res[0], nnz(), false) << ", "
230  << "cs=" << g.work(arg[0], nnz(), arg_is_ref[0]) << "; i<" << dep().size2() << "; ++i) "
231  << "for (j=0; j<" << dep().size1() << "; ++j) "
232  << "rr[i+j*" << dep().size2() << "] = *cs++;\n";
233  }
234 
235 } // namespace casadi
Helper class for C code generation.
std::string work(casadi_int n, casadi_int sz, bool is_ref) const
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
std::string trans(const std::string &x, const Sparsity &sp_x, const std::string &y, const Sparsity &sp_y, const std::string &iw)
Transpose.
Matrix transpose (dense)
Definition: transpose.hpp:177
int eval(const double **arg, double **res, casadi_int *iw, double *w) const override
Evaluate the function numerically.
Definition: transpose.cpp:60
int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w) const override
Evaluate the function symbolically (SX)
Definition: transpose.cpp:70
void generate(CodeGenerator &g, const std::vector< casadi_int > &arg, const std::vector< casadi_int > &res, const std::vector< bool > &arg_is_ref, std::vector< bool > &res_is_ref) const override
Generate code for the operation.
Definition: transpose.cpp:220
void serialize_type(SerializingStream &s) const override
Serialize type information.
Definition: transpose.cpp:41
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity forward.
Definition: transpose.cpp:155
int eval_gen(const T *const *arg, T *const *res, casadi_int *iw, T *w) const
Evaluate the function (template)
Definition: transpose.cpp:96
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity backwards.
Definition: transpose.cpp:172
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
casadi_int nnz() const
Get the number of (structural) non-zero elements.
casadi_int size2() const
Get the second dimension (i.e. number of columns)
casadi_int size1() const
Get the first dimension (i.e. number of rows)
const casadi_int * row() const
Get the sparsity pattern. See the Sparsity class for details.
Node class for MX objects.
Definition: mx_node.hpp:51
virtual void serialize_type(SerializingStream &s) const
Serialize type information.
Definition: mx_node.cpp:528
const Sparsity & sparsity() const
Get the sparsity.
Definition: mx_node.hpp:372
casadi_int nnz(casadi_int i=0) const
Definition: mx_node.hpp:389
const MX & dep(casadi_int ind=0) const
dependencies - functions that have to be evaluated before this one
Definition: mx_node.hpp:354
void set_sparsity(const Sparsity &sparsity)
Set the sparsity.
Definition: mx_node.cpp:222
void set_dep(const MX &dep)
Set unary dependency.
Definition: mx_node.cpp:226
MX - Matrix expression.
Definition: mx.hpp:92
const Sparsity & sparsity() const
Get the sparsity pattern.
Definition: mx.cpp:592
The basic scalar symbolic class of CasADi.
Definition: sx_elem.hpp:75
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
Sparsity T() const
Transpose the matrix.
Definition: sparsity.cpp:394
casadi_int size2() const
Get the number of columns.
Definition: sparsity.cpp:128
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
Definition: sparsity.cpp:168
int eval(const double **arg, double **res, casadi_int *iw, double *w) const override
Evaluate the function numerically.
Definition: transpose.cpp:56
void ad_forward(const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens) const override
Calculate forward mode directional derivatives.
Definition: transpose.cpp:197
int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w) const override
Evaluate the function symbolically (SX)
Definition: transpose.cpp:65
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity forward.
Definition: transpose.cpp:113
int eval_gen(const T *const *arg, T *const *res, casadi_int *iw, T *w) const
Evaluate the function (template)
Definition: transpose.cpp:75
void eval_mx(const std::vector< MX > &arg, std::vector< MX > &res) const override
Evaluate symbolically (MX)
Definition: transpose.cpp:193
std::string disp(const std::vector< std::string > &arg) const override
Print expression.
Definition: transpose.cpp:189
static MXNode * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Definition: transpose.cpp:46
Transpose(const MX &x)
Constructor.
Definition: transpose.cpp:31
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w) const override
Propagate sparsity backwards.
Definition: transpose.cpp:133
void generate(CodeGenerator &g, const std::vector< casadi_int > &arg, const std::vector< casadi_int > &res, const std::vector< bool > &arg_is_ref, std::vector< bool > &res_is_ref) const override
Generate code for the operation.
Definition: transpose.cpp:211
void ad_reverse(const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens) const override
Calculate reverse mode directional derivatives.
Definition: transpose.cpp:204
void serialize_type(SerializingStream &s) const override
Serialize type information.
Definition: transpose.cpp:36
The casadi namespace.
Definition: archiver.cpp:28
unsigned long long bvec_t