blas_blasfeo.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  *
8  * CasADi is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 3 of the License, or (at your option) any later version.
12  *
13  * CasADi is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with CasADi; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23 
24 
25 #include "blas_blasfeo.hpp"
26 #include "casadi/core/code_generator.hpp"
27 #include "casadi/core/exception.hpp"
28 
29 #include <climits>
30 
31 namespace casadi {
32 
33  static void blasfeo_dgemm(int transa, int transb,
34  casadi_int m, casadi_int n, casadi_int k,
35  double alpha,
36  const double* A, casadi_int lda,
37  const double* B, casadi_int ldb,
38  double beta,
39  double* C, casadi_int ldc) {
40  casadi_assert(m <= INT_MAX && n <= INT_MAX && k <= INT_MAX
41  && lda <= INT_MAX && ldb <= INT_MAX && ldc <= INT_MAX,
42  "BLAS 'blasfeo' plugin: matrix dimension exceeds 32-bit BLAS ABI.");
43 
44  char ta = (transa == CASADI_BLAS_TRANS) ? 'T' : 'N';
45  char tb = (transb == CASADI_BLAS_TRANS) ? 'T' : 'N';
46  int m_ = static_cast<int>(m), n_ = static_cast<int>(n), k_ = static_cast<int>(k);
47  int lda_ = static_cast<int>(lda), ldb_ = static_cast<int>(ldb), ldc_ = static_cast<int>(ldc);
48 
49  // BLASFEO header takes non-const pointers; semantics are still read-only
50  // for A, B, alpha, beta. const_cast is safe here.
51  blasfeo_blas_dgemm(&ta, &tb, &m_, &n_, &k_, &alpha,
52  const_cast<double*>(A), &lda_,
53  const_cast<double*>(B), &ldb_,
54  &beta, C, &ldc_);
55  }
56 
57  // -------------- L1 runtime forwarders (subset BLASFEO provides) --------------
58 
59  static void blasfeo_daxpy(casadi_int n, double alpha,
60  const double* x, double* y) {
61  casadi_assert(n <= INT_MAX,
62  "BLAS 'blasfeo' plugin: vector length exceeds 32-bit BLAS ABI.");
63  int n_ = static_cast<int>(n), inc = 1;
64  blasfeo_blas_daxpy(&n_, &alpha,
65  const_cast<double*>(x), &inc, y, &inc);
66  }
67 
68  static double blasfeo_ddot(casadi_int n,
69  const double* x, const double* y) {
70  casadi_assert(n <= INT_MAX,
71  "BLAS 'blasfeo' plugin: vector length exceeds 32-bit BLAS ABI.");
72  int n_ = static_cast<int>(n), inc = 1;
73  return blasfeo_blas_ddot(&n_,
74  const_cast<double*>(x), &inc,
75  const_cast<double*>(y), &inc);
76  }
77 
78  static const char* BLASFEO_DECL =
79  "/* BLAS \"blasfeo\" plugin: namespaced Fortran ABI, link with -lblasfeo */\n"
80  "extern void blasfeo_blas_dgemm(char* transa, char* transb,\n"
81  " int* m, int* n, int* k,\n"
82  " double* alpha,\n"
83  " double* A, int* lda,\n"
84  " double* B, int* ldb,\n"
85  " double* beta,\n"
86  " double* C, int* ldc);";
87 
88  static const char* BLASFEO_DAXPY_DECL =
89  "extern void blasfeo_blas_daxpy(int* n, double* alpha,\n"
90  " double* x, int* incx,\n"
91  " double* y, int* incy);";
92 
93  static const char* BLASFEO_DDOT_DECL =
94  "extern double blasfeo_blas_ddot(int* n,\n"
95  " double* x, int* incx,\n"
96  " double* y, int* incy);";
97 
99  const std::string& A, casadi_int m, casadi_int k,
100  const std::string& B, casadi_int n, const std::string& C) {
102  g.local("blas_tn", "char"); g.init_local("blas_tn", "'N'");
103  g.local("blas_one", "double"); g.init_local("blas_one", "1.0");
104  g.local("blas_m", "int");
105  g.local("blas_n", "int");
106  g.local("blas_k", "int");
107  g << "blas_m = " << m << "; blas_n = " << n << "; blas_k = " << k << ";\n";
108  g << "blasfeo_blas_dgemm(&blas_tn, &blas_tn, &blas_m, &blas_n, &blas_k, "
109  "&blas_one, (double*)" << A << ", &blas_m, (double*)" << B
110  << ", &blas_k, &blas_one, " << C << ", &blas_m);\n";
111  }
112 
113  // L1 codegen aux emitters. As with the classic plugin, externs go inline
114  // in `auxiliaries` so the wrappers referencing them see them defined.
115  // BLASFEO's APIs take non-const pointers; we cast away const at use sites.
116 
118  const std::vector<std::string>& inst) {
119  static const char* SRC =
120  "// SYMBOL \"axpy\"\n"
121  "void casadi_axpy(casadi_int n, casadi_real alpha,\n"
122  " const casadi_real* x, casadi_real* y) {\n"
123  " int n_ = (int)n, inc = 1;\n"
124  " blasfeo_blas_daxpy(&n_, &alpha, (double*)x, &inc, y, &inc);\n"
125  "}\n";
126  g.auxiliaries << BLASFEO_DAXPY_DECL << "\n";
127  g.auxiliaries << g.sanitize_source(SRC, inst);
128  }
129 
130  // See classic plugin's analogous emitters for why we run the wrapper
131  // through sanitize_source (registers the shorthand, applies aux_static
132  // / aux_inline) but write the extern decl verbatim (it's a forward
133  // declaration, not a function body).
135  const std::vector<std::string>& inst) {
136  static const char* SRC =
137  "// SYMBOL \"dot\"\n"
138  "casadi_real casadi_dot(casadi_int n,\n"
139  " const casadi_real* x, const casadi_real* y) {\n"
140  " int n_ = (int)n, inc = 1;\n"
141  " return blasfeo_blas_ddot(&n_, (double*)x, &inc, (double*)y, &inc);\n"
142  "}\n";
143  g.auxiliaries << BLASFEO_DDOT_DECL << "\n";
144  g.auxiliaries << g.sanitize_source(SRC, inst);
145  }
146 
147  extern "C" int CASADI_BLAS_BLASFEO_EXPORT
148  casadi_register_blas_blasfeo(Blas::Plugin* plugin) {
149  plugin->name = "blasfeo";
150  plugin->doc = BlasBlasfeo::meta_doc.c_str();
151  plugin->version = CASADI_VERSION;
152  plugin->exposed.dgemm = &blasfeo_dgemm;
153  plugin->exposed.codegen_mtimes = &blasfeo_codegen_mtimes;
154  plugin->exposed.daxpy = &blasfeo_daxpy;
155  plugin->exposed.ddot = &blasfeo_ddot;
156  plugin->exposed.dscal = nullptr;
157  plugin->exposed.dnrm2 = nullptr;
158  plugin->exposed.dasum = nullptr;
159  plugin->exposed.dcopy = nullptr;
160  plugin->exposed.codegen_axpy_aux = &blasfeo_codegen_axpy_aux;
161  plugin->exposed.codegen_dot_aux = &blasfeo_codegen_dot_aux;
162  plugin->exposed.codegen_scal_aux = nullptr;
163  plugin->exposed.codegen_nrm2_aux = nullptr;
164  plugin->exposed.codegen_asum_aux = nullptr;
165  plugin->options = nullptr;
166  plugin->deserialize = nullptr;
167  plugin->creator = nullptr;
168  return 0;
169  }
170 
171  extern "C" void CASADI_BLAS_BLASFEO_EXPORT casadi_load_blas_blasfeo() {
173  }
174 
175 } // namespace casadi
static const std::string meta_doc
A documentation string.
Helper class for C code generation.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
void add_external(const std::string &new_external)
Add an external function declaration.
void init_local(const std::string &name, const std::string &def)
Specify the default value for a local variable.
std::string sanitize_source(const std::string &src, const std::vector< std::string > &inst, bool add_shorthand=true)
Sanitize source files for codegen.
std::stringstream auxiliaries
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
The casadi namespace.
Definition: archiver.cpp:28
int CASADI_BLAS_BLASFEO_EXPORT casadi_register_blas_blasfeo(Blas::Plugin *plugin)
static const char * BLASFEO_DDOT_DECL
static void blasfeo_daxpy(casadi_int n, double alpha, const double *x, double *y)
static void blasfeo_codegen_dot_aux(CodeGenerator &g, const std::vector< std::string > &inst)
void CASADI_BLAS_BLASFEO_EXPORT casadi_load_blas_blasfeo()
@ CASADI_BLAS_TRANS
Definition: blas_impl.hpp:42
static void blasfeo_codegen_mtimes(CodeGenerator &g, const std::string &A, casadi_int m, casadi_int k, const std::string &B, casadi_int n, const std::string &C)
static void blasfeo_dgemm(int transa, int transb, casadi_int m, casadi_int n, casadi_int k, double alpha, const double *A, casadi_int lda, const double *B, casadi_int ldb, double beta, double *C, casadi_int ldc)
static void blasfeo_codegen_axpy_aux(CodeGenerator &g, const std::vector< std::string > &inst)
static const char * BLASFEO_DECL
static double blasfeo_ddot(casadi_int n, const double *x, const double *y)
static const char * BLASFEO_DAXPY_DECL