blob: b61d2d30676afb9b659e237f087986bb283591b8 [file] [log] [blame]
Austin Schuh9a24b372018-01-28 16:12:29 -08001/**************************************************************************************************
2* *
3* This file is part of BLASFEO. *
4* *
5* BLASFEO -- BLAS For Embedded Optimization. *
6* Copyright (C) 2016-2017 by Gianluca Frison. *
7* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. *
8* All rights reserved. *
9* *
10* HPMPC is free software; you can redistribute it and/or *
11* modify it under the terms of the GNU Lesser General Public *
12* License as published by the Free Software Foundation; either *
13* version 2.1 of the License, or (at your option) any later version. *
14* *
15* HPMPC is distributed in the hope that it will be useful, *
16* but WITHOUT ANY WARRANTY; without even the implied warranty of *
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
18* See the GNU Lesser General Public License for more details. *
19* *
20* You should have received a copy of the GNU Lesser General Public *
21* License along with HPMPC; if not, write to the Free Software *
22* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
23* *
24* Author: Gianluca Frison, giaf (at) dtu.dk *
25* gianluca.frison (at) imtek.uni-freiburg.de *
26* *
27**************************************************************************************************/
28
29#include <stdlib.h>
30#include <stdio.h>
31#include <sys/time.h>
32
33#include "tools.h"
34
35#include "../include/blasfeo_common.h"
36#include "../include/blasfeo_i_aux.h"
37#include "../include/blasfeo_d_aux.h"
38#include "../include/blasfeo_d_kernel.h"
39#include "../include/blasfeo_d_blas.h"
40
41
42
43void d_back_ric_sv_libstr(int N, int *nx, int *nu, struct d_strmat *hsBAbt, struct d_strmat *hsRSQrq, struct d_strmat *hsL, struct d_strmat *hsLxt, struct d_strvec *hsux, struct d_strvec *hspi, struct d_strmat *hswork_mat, struct d_strvec *hswork_vec)
44 {
45
46 int nn;
47
48 // factorization and backward substitution
49
50 // last stage
51 dpotrf_l_libstr(nx[N]+1, nx[N], &hsRSQrq[N], 0, 0, &hsL[N], 0, 0);
52 dtrtr_l_libstr(nx[N], &hsL[N], 0, 0, &hsLxt[N], 0, 0);
53
54 // middle stages
55 for(nn=0; nn<N; nn++)
56 {
57 dtrmm_rutn_libstr(nu[N-nn-1]+nx[N-nn-1]+1, nx[N-nn], 1.0, &hsBAbt[N-nn-1], 0, 0, &hsLxt[N-nn], 0, 0, 0.0, &hswork_mat[0], 0, 0, &hswork_mat[0], 0, 0);
58 dgead_libstr(1, nx[N-nn], 1.0, &hsL[N-nn], nu[N-nn]+nx[N-nn], nu[N-nn], &hswork_mat[0], nu[N-nn-1]+nx[N-nn-1], 0);
59#if 1
60 dsyrk_dpotrf_ln_libstr(nu[N-nn-1]+nx[N-nn-1]+1, nu[N-nn-1]+nx[N-nn-1], nx[N-nn], &hswork_mat[0], 0, 0, &hswork_mat[0], 0, 0, &hsRSQrq[N-nn-1], 0, 0, &hsL[N-nn-1], 0, 0);
61#else
62 dsyrk_ln_libstr(nu[N-nn-1]+nx[N-nn-1]+1, nu[N-nn-1]+nx[N-nn-1], nx[N-nn], 1.0, &hswork_mat[0], 0, 0, &hswork_mat[0], 0, 0, 1.0, &hsRSQrq[N-nn-1], 0, 0, &hsL[N-nn-1], 0, 0);
63 dpotrf_l_libstr(nu[N-nn-1]+nx[N-nn-1]+1, nu[N-nn-1]+nx[N-nn-1], &hsL[N-nn-1], 0, 0, &hsL[N-nn-1], 0, 0);
64#endif
65 dtrtr_l_libstr(nx[N-nn-1], &hsL[N-nn-1], nu[N-nn-1], nu[N-nn-1], &hsLxt[N-nn-1], 0, 0);
66 }
67
68 // forward substitution
69
70 // first stage
71 nn = 0;
72 drowex_libstr(nu[nn]+nx[nn], -1.0, &hsL[nn], nu[nn]+nx[nn], 0, &hsux[nn], 0);
73 dtrsv_ltn_libstr(nu[nn]+nx[nn], nu[nn]+nx[nn], &hsL[nn], 0, 0, &hsux[nn], 0, &hsux[nn], 0);
74 drowex_libstr(nx[nn+1], 1.0, &hsBAbt[nn], nu[nn]+nx[nn], 0, &hsux[nn+1], nu[nn+1]);
75 dgemv_t_libstr(nu[nn]+nx[nn], nx[nn+1], 1.0, &hsBAbt[nn], 0, 0, &hsux[nn], 0, 1.0, &hsux[nn+1], nu[nn+1], &hsux[nn+1], nu[nn+1]);
76 dveccp_libstr(nx[nn+1], 1.0, &hsux[nn+1], nu[nn+1], &hspi[nn], 0);
77 drowex_libstr(nx[nn+1], 1.0, &hsL[nn+1], nu[nn+1]+nx[nn+1], nu[nn+1], &hswork_vec[0], 0);
78 dtrmv_unn_libstr(nx[nn+1], &hsLxt[nn+1], 0, 0, &hspi[nn], 0, &hspi[nn], 0);
79 daxpy_libstr(nx[nn+1], 1.0, &hswork_vec[0], 0, &hspi[nn], 0);
80 dtrmv_utn_libstr(nx[nn+1], &hsLxt[nn+1], 0, 0, &hspi[nn], 0, &hspi[nn], 0);
81
82 // middle stages
83 for(nn=1; nn<N; nn++)
84 {
85 drowex_libstr(nu[nn], -1.0, &hsL[nn], nu[nn]+nx[nn], 0, &hsux[nn], 0);
86 dtrsv_ltn_libstr(nu[nn]+nx[nn], nu[nn], &hsL[nn], 0, 0, &hsux[nn], 0, &hsux[nn], 0);
87 drowex_libstr(nx[nn+1], 1.0, &hsBAbt[nn], nu[nn]+nx[nn], 0, &hsux[nn+1], nu[nn+1]);
88 dgemv_t_libstr(nu[nn]+nx[nn], nx[nn+1], 1.0, &hsBAbt[nn], 0, 0, &hsux[nn], 0, 1.0, &hsux[nn+1], nu[nn+1], &hsux[nn+1], nu[nn+1]);
89 dveccp_libstr(nx[nn+1], 1.0, &hsux[nn+1], nu[nn+1], &hspi[nn], 0);
90 drowex_libstr(nx[nn+1], 1.0, &hsL[nn+1], nu[nn+1]+nx[nn+1], nu[nn+1], &hswork_vec[0], 0);
91 dtrmv_unn_libstr(nx[nn+1], &hsLxt[nn+1], 0, 0, &hspi[nn], 0, &hspi[nn], 0);
92 daxpy_libstr(nx[nn+1], 1.0, &hswork_vec[0], 0, &hspi[nn], 0);
93 dtrmv_utn_libstr(nx[nn+1], &hsLxt[nn+1], 0, 0, &hspi[nn], 0, &hspi[nn], 0);
94 }
95
96 return;
97
98 }
99
100
101
102void d_back_ric_trf_funnel1_libstr(int md, int *nx, int *nu, struct d_strmat *hsBAbt, struct d_strmat *hsRSQrq, struct d_strmat *hsL, struct d_strmat *hsLxt_old, struct d_strmat *hsLxt_new, struct d_strmat *hswork_mat)
103 {
104
105 int ii;
106
107 ii = 0;
108 dtrmm_rutn_libstr(nu[0]+nx[0], nx[1], 1.0, &hsBAbt[ii], 0, 0, &hsLxt_old[ii], 0, 0, 0.0, &hswork_mat[0], 0, 0, &hswork_mat[0], 0, 0);
109 dsyrk_ln_libstr(nu[0]+nx[0], nu[0]+nx[0], nx[1], 1.0, &hswork_mat[0], 0, 0, &hswork_mat[0], 0, 0, 1.0, &hsRSQrq[0], 0, 0, &hsL[0], 0, 0);
110 for(ii=1; ii<md; ii++)
111 {
112 dtrmm_rutn_libstr(nu[0]+nx[0], nx[1], 1.0, &hsBAbt[ii], 0, 0, &hsLxt_old[ii], 0, 0, 0.0, &hswork_mat[0], 0, 0, &hswork_mat[0], 0, 0);
113 dsyrk_ln_libstr(nu[0]+nx[0], nu[0]+nx[0], nx[1], 1.0, &hswork_mat[0], 0, 0, &hswork_mat[0], 0, 0, 1.0, &hsL[0], 0, 0, &hsL[0], 0, 0);
114 }
115
116 dpotrf_l_libstr(nu[0]+nx[0], nu[0]+nx[0], &hsL[0], 0, 0, &hsL[0], 0, 0);
117 dtrtr_l_libstr(nx[0], &hsL[0], nu[0], nu[0], &hsLxt_new[0], 0, 0);
118
119 return;
120
121 }
122
123
124
125void d_back_ric_trf_step1_libstr(int *nx, int *nu, struct d_strmat *hsBAbt, struct d_strmat *hsRSQrq, struct d_strmat *hsL, struct d_strmat *hsLxt, struct d_strmat *hswork_mat)
126 {
127
128 dtrmm_rutn_libstr(nu[0]+nx[0], nx[1], 1.0, &hsBAbt[0], 0, 0, &hsLxt[1], 0, 0, 0.0, &hswork_mat[0], 0, 0, &hswork_mat[0], 0, 0);
129 dsyrk_ln_libstr(nu[0]+nx[0], nu[0]+nx[0], nx[1], 1.0, &hswork_mat[0], 0, 0, &hswork_mat[0], 0, 0, 1.0, &hsRSQrq[0], 0, 0, &hsL[0], 0, 0);
130 dpotrf_l_libstr(nu[0]+nx[0], nu[0]+nx[0], &hsL[0], 0, 0, &hsL[0], 0, 0);
131 dtrtr_l_libstr(nx[0], &hsL[0], nu[0], nu[0], &hsLxt[0], 0, 0);
132
133 return;
134
135 }
136
137
138
139void d_back_ric_trf_stepN_libstr(int *nx, struct d_strmat *hsRSQrq, struct d_strmat *hsL, struct d_strmat *hsLxt)
140 {
141
142 dpotrf_l_libstr(nx[0], nx[0], &hsRSQrq[0], 0, 0, &hsL[0], 0, 0);
143 dtrtr_l_libstr(nx[0], &hsL[0], 0, 0, &hsLxt[0], 0, 0);
144
145 return;
146
147 }
148
149
150
151void d_back_ric_trf_libstr(int N, int *nx, int *nu, struct d_strmat *hsBAbt, struct d_strmat *hsRSQrq, struct d_strmat *hsL, struct d_strmat *hsLxt, struct d_strmat *hswork_mat)
152 {
153
154 int nn;
155
156 // factorization
157
158 // last stage
159 d_back_ric_trf_stepN_libstr(&nx[N], &hsRSQrq[N], &hsL[N], &hsLxt[N]);
160
161 // middle stages
162 for(nn=0; nn<N; nn++)
163 {
164 d_back_ric_trf_step1_libstr(&nx[N-nn-1], &nu[N-nn-1], &hsBAbt[N-nn-1], &hsRSQrq[N-nn-1], &hsL[N-nn-1], &hsLxt[N-nn-1], hswork_mat);
165 }
166
167 return;
168
169 }
170
171
172
173void d_back_ric_trs_libstr(int N, int *nx, int *nu, struct d_strmat *hsBAbt, struct d_strvec *hsb, struct d_strvec *hsrq, struct d_strmat *hsL, struct d_strmat *hsLxt, struct d_strvec *hsPb, struct d_strvec *hsux, struct d_strvec *hspi, struct d_strvec *hswork_vec)
174 {
175
176 int nn;
177
178 // backward substitution
179
180 // last stage
181 dveccp_libstr(nu[N]+nx[N], 1.0, &hsrq[N], 0, &hsux[N], 0);
182
183 // middle stages
184 for(nn=0; nn<N-1; nn++)
185 {
186 // compute Pb
187 dtrmv_unn_libstr(nx[N-nn], &hsLxt[N-nn], 0, 0, &hsb[N-nn-1], 0, &hsPb[N-nn-1], 0);
188 dtrmv_utn_libstr(nx[N-nn], &hsLxt[N-nn], 0, 0, &hsPb[N-nn-1], 0, &hsPb[N-nn-1], 0);
189 dveccp_libstr(nu[N-nn-1]+nx[N-nn-1], 1.0, &hsrq[N-nn-1], 0, &hsux[N-nn-1], 0);
190 dveccp_libstr(nx[N-nn], 1.0, &hsPb[N-nn-1], 0, &hswork_vec[0], 0);
191 daxpy_libstr(nx[N-nn], 1.0, &hsux[N-nn], nu[N-nn], &hswork_vec[0], 0);
192 dgemv_n_libstr(nu[N-nn-1]+nx[N-nn-1], nx[N-nn], 1.0, &hsBAbt[N-nn-1], 0, 0, &hswork_vec[0], 0, 1.0, &hsux[N-nn-1], 0, &hsux[N-nn-1], 0);
193 dtrsv_lnn_libstr(nu[N-nn-1]+nx[N-nn-1], nu[N-nn-1], &hsL[N-nn-1], 0, 0, &hsux[N-nn-1], 0, &hsux[N-nn-1], 0);
194 }
195
196 // first stage
197 nn = N-1;
198 dtrmv_unn_libstr(nx[N-nn], &hsLxt[N-nn], 0, 0, &hsb[N-nn-1], 0, &hsPb[N-nn-1], 0);
199 dtrmv_utn_libstr(nx[N-nn], &hsLxt[N-nn], 0, 0, &hsPb[N-nn-1], 0, &hsPb[N-nn-1], 0);
200 dveccp_libstr(nu[N-nn-1]+nx[N-nn-1], 1.0, &hsrq[N-nn-1], 0, &hsux[N-nn-1], 0);
201 dveccp_libstr(nx[N-nn], 1.0, &hsPb[N-nn-1], 0, &hswork_vec[0], 0);
202 daxpy_libstr(nx[N-nn], 1.0, &hsux[N-nn], nu[N-nn], &hswork_vec[0], 0);
203 dgemv_n_libstr(nu[N-nn-1]+nx[N-nn-1], nx[N-nn], 1.0, &hsBAbt[N-nn-1], 0, 0, &hswork_vec[0], 0, 1.0, &hsux[N-nn-1], 0, &hsux[N-nn-1], 0);
204 dtrsv_lnn_libstr(nu[N-nn-1]+nx[N-nn-1], nu[N-nn-1]+nx[N-nn-1], &hsL[N-nn-1], 0, 0, &hsux[N-nn-1], 0, &hsux[N-nn-1], 0);
205
206 // forward substitution
207
208 // first stage
209 nn = 0;
210 dveccp_libstr(nx[nn+1], 1.0, &hsux[nn+1], nu[nn+1], &hspi[nn], 0);
211 dveccp_libstr(nu[nn]+nx[nn], -1.0, &hsux[nn], 0, &hsux[nn], 0);
212 dtrsv_ltn_libstr(nu[nn]+nx[nn], nu[nn]+nx[nn], &hsL[nn], 0, 0, &hsux[nn], 0, &hsux[nn], 0);
213 dgemv_t_libstr(nu[nn]+nx[nn], nx[nn+1], 1.0, &hsBAbt[nn], 0, 0, &hsux[nn], 0, 1.0, &hsb[nn], 0, &hsux[nn+1], nu[nn+1]);
214 dveccp_libstr(nx[nn+1], 1.0, &hsux[nn+1], nu[nn+1], &hswork_vec[0], 0);
215 dtrmv_unn_libstr(nx[nn+1], &hsLxt[nn+1], 0, 0, &hswork_vec[0], 0, &hswork_vec[0], 0);
216 dtrmv_utn_libstr(nx[nn+1], &hsLxt[nn+1], 0, 0, &hswork_vec[0], 0, &hswork_vec[0], 0);
217 daxpy_libstr(nx[nn+1], 1.0, &hswork_vec[0], 0, &hspi[nn], 0);
218
219 // middle stages
220 for(nn=1; nn<N; nn++)
221 {
222 dveccp_libstr(nx[nn+1], 1.0, &hsux[nn+1], nu[nn+1], &hspi[nn], 0);
223 dveccp_libstr(nu[nn], -1.0, &hsux[nn], 0, &hsux[nn], 0);
224 dtrsv_ltn_libstr(nu[nn]+nx[nn], nu[nn], &hsL[nn], 0, 0, &hsux[nn], 0, &hsux[nn], 0);
225 dgemv_t_libstr(nu[nn]+nx[nn], nx[nn+1], 1.0, &hsBAbt[nn], 0, 0, &hsux[nn], 0, 1.0, &hsb[nn], 0, &hsux[nn+1], nu[nn+1]);
226 dveccp_libstr(nx[nn+1], 1.0, &hsux[nn+1], nu[nn+1], &hswork_vec[0], 0);
227 dtrmv_unn_libstr(nx[nn+1], &hsLxt[nn+1], 0, 0, &hswork_vec[0], 0, &hswork_vec[0], 0);
228 dtrmv_utn_libstr(nx[nn+1], &hsLxt[nn+1], 0, 0, &hswork_vec[0], 0, &hswork_vec[0], 0);
229 daxpy_libstr(nx[nn+1], 1.0, &hswork_vec[0], 0, &hspi[nn], 0);
230 }
231
232 return;
233
234 }
235
236
237
238/************************************************
239Mass-spring system: nx/2 masses connected each other with springs (in a row), and the first and the last one to walls. nu (<=nx) controls act on the first nu masses. The system is sampled with sampling time Ts.
240************************************************/
241void mass_spring_system(double Ts, int nx, int nu, int N, double *A, double *B, double *b, double *x0)
242 {
243
244 int nx2 = nx*nx;
245
246 int info = 0;
247
248 int pp = nx/2; // number of masses
249
250/************************************************
251* build the continuous time system
252************************************************/
253
254 double *T; d_zeros(&T, pp, pp);
255 int ii;
256 for(ii=0; ii<pp; ii++) T[ii*(pp+1)] = -2;
257 for(ii=0; ii<pp-1; ii++) T[ii*(pp+1)+1] = 1;
258 for(ii=1; ii<pp; ii++) T[ii*(pp+1)-1] = 1;
259
260 double *Z; d_zeros(&Z, pp, pp);
261 double *I; d_zeros(&I, pp, pp); for(ii=0; ii<pp; ii++) I[ii*(pp+1)]=1.0; // = eye(pp);
262 double *Ac; d_zeros(&Ac, nx, nx);
263 dmcopy(pp, pp, Z, pp, Ac, nx);
264 dmcopy(pp, pp, T, pp, Ac+pp, nx);
265 dmcopy(pp, pp, I, pp, Ac+pp*nx, nx);
266 dmcopy(pp, pp, Z, pp, Ac+pp*(nx+1), nx);
267 free(T);
268 free(Z);
269 free(I);
270
271 d_zeros(&I, nu, nu); for(ii=0; ii<nu; ii++) I[ii*(nu+1)]=1.0; //I = eye(nu);
272 double *Bc; d_zeros(&Bc, nx, nu);
273 dmcopy(nu, nu, I, nu, Bc+pp, nx);
274 free(I);
275
276/************************************************
277* compute the discrete time system
278************************************************/
279
280 double *bb; d_zeros(&bb, nx, 1);
281 dmcopy(nx, 1, bb, nx, b, nx);
282
283 dmcopy(nx, nx, Ac, nx, A, nx);
284 dscal_3l(nx2, Ts, A);
285 expm(nx, A);
286
287 d_zeros(&T, nx, nx);
288 d_zeros(&I, nx, nx); for(ii=0; ii<nx; ii++) I[ii*(nx+1)]=1.0; //I = eye(nx);
289 dmcopy(nx, nx, A, nx, T, nx);
290 daxpy_3l(nx2, -1.0, I, T);
291 dgemm_nn_3l(nx, nu, nx, T, nx, Bc, nx, B, nx);
292 free(T);
293 free(I);
294
295 int *ipiv = (int *) malloc(nx*sizeof(int));
296 dgesv_3l(nx, nu, Ac, nx, ipiv, B, nx, &info);
297 free(ipiv);
298
299 free(Ac);
300 free(Bc);
301 free(bb);
302
303
304/************************************************
305* initial state
306************************************************/
307
308 if(nx==4)
309 {
310 x0[0] = 5;
311 x0[1] = 10;
312 x0[2] = 15;
313 x0[3] = 20;
314 }
315 else
316 {
317 int jj;
318 for(jj=0; jj<nx; jj++)
319 x0[jj] = 1;
320 }
321
322 }
323
324
325
326int main()
327 {
328
329 printf("\nExample of LU factorization and backsolve\n\n");
330
331#if defined(LA_HIGH_PERFORMANCE)
332
333 printf("\nLA provided by BLASFEO\n\n");
334
335#elif defined(LA_BLAS)
336
337 printf("\nLA provided by BLAS\n\n");
338
339#else
340
341 printf("\nLA provided by ???\n\n");
342 exit(2);
343
344#endif
345
346 // loop index
347 int ii;
348
349/************************************************
350* problem size
351************************************************/
352
353 // problem size
354 int N = 4;
355 int nx_ = 8;
356 int nu_ = 3;
357
358 // stage-wise variant size
359 int nx[N+1];
360 nx[0] = 0;
361 for(ii=1; ii<=N; ii++)
362 nx[ii] = nx_;
363 nx[N] = nx_;
364
365 int nu[N+1];
366 for(ii=0; ii<N; ii++)
367 nu[ii] = nu_;
368 nu[N] = 0;
369
370/************************************************
371* dynamical system
372************************************************/
373
374 double *A; d_zeros(&A, nx_, nx_); // states update matrix
375
376 double *B; d_zeros(&B, nx_, nu_); // inputs matrix
377
378 double *b; d_zeros(&b, nx_, 1); // states offset
379 double *x0; d_zeros_align(&x0, nx_, 1); // initial state
380
381 double Ts = 0.5; // sampling time
382 mass_spring_system(Ts, nx_, nu_, N, A, B, b, x0);
383
384 for(ii=0; ii<nx_; ii++)
385 b[ii] = 0.1;
386
387 for(ii=0; ii<nx_; ii++)
388 x0[ii] = 0;
389 x0[0] = 2.5;
390 x0[1] = 2.5;
391
392 d_print_mat(nx_, nx_, A, nx_);
393 d_print_mat(nx_, nu_, B, nx_);
394 d_print_mat(1, nx_, b, 1);
395 d_print_mat(1, nx_, x0, 1);
396
397/************************************************
398* cost function
399************************************************/
400
401 double *R; d_zeros(&R, nu_, nu_);
402 for(ii=0; ii<nu_; ii++) R[ii*(nu_+1)] = 2.0;
403
404 double *S; d_zeros(&S, nu_, nx_);
405
406 double *Q; d_zeros(&Q, nx_, nx_);
407 for(ii=0; ii<nx_; ii++) Q[ii*(nx_+1)] = 1.0;
408
409 double *r; d_zeros(&r, nu_, 1);
410 for(ii=0; ii<nu_; ii++) r[ii] = 0.2;
411
412 double *q; d_zeros(&q, nx_, 1);
413 for(ii=0; ii<nx_; ii++) q[ii] = 0.1;
414
415 d_print_mat(nu_, nu_, R, nu_);
416 d_print_mat(nu_, nx_, S, nu_);
417 d_print_mat(nx_, nx_, Q, nx_);
418 d_print_mat(1, nu_, r, 1);
419 d_print_mat(1, nx_, q, 1);
420
421/************************************************
422* matrices as strmat
423************************************************/
424
425 struct d_strmat sA;
426 d_allocate_strmat(nx_, nx_, &sA);
427 d_cvt_mat2strmat(nx_, nx_, A, nx_, &sA, 0, 0);
428 struct d_strvec sb;
429 d_allocate_strvec(nx_, &sb);
430 d_cvt_vec2strvec(nx_, b, &sb, 0);
431 struct d_strvec sx0;
432 d_allocate_strvec(nx_, &sx0);
433 d_cvt_vec2strvec(nx_, x0, &sx0, 0);
434 struct d_strvec sb0;
435 d_allocate_strvec(nx_, &sb0);
436 double *b0; d_zeros(&b0, nx_, 1); // states offset
437 dgemv_n_libstr(nx_, nx_, 1.0, &sA, 0, 0, &sx0, 0, 1.0, &sb, 0, &sb0, 0);
438 d_print_tran_strvec(nx_, &sb0, 0);
439
440 struct d_strmat sBbt0;
441 d_allocate_strmat(nu_+nx_+1, nx_, &sBbt0);
442 d_cvt_tran_mat2strmat(nx_, nx_, B, nx_, &sBbt0, 0, 0);
443 drowin_libstr(nx_, 1.0, &sb0, 0, &sBbt0, nu_, 0);
444 d_print_strmat(nu_+1, nx_, &sBbt0, 0, 0);
445
446 struct d_strmat sBAbt1;
447 d_allocate_strmat(nu_+nx_+1, nx_, &sBAbt1);
448 d_cvt_tran_mat2strmat(nx_, nu_, B, nx_, &sBAbt1, 0, 0);
449 d_cvt_tran_mat2strmat(nx_, nx_, A, nx_, &sBAbt1, nu_, 0);
450 d_cvt_tran_mat2strmat(nx_, 1, b, nx_, &sBAbt1, nu_+nx_, 0);
451 d_print_strmat(nu_+nx_+1, nx_, &sBAbt1, 0, 0);
452
453 struct d_strvec sr0; // XXX no need to update r0 since S=0
454 d_allocate_strvec(nu_, &sr0);
455 d_cvt_vec2strvec(nu_, r, &sr0, 0);
456
457 struct d_strmat sRr0;
458 d_allocate_strmat(nu_+1, nu_, &sRr0);
459 d_cvt_mat2strmat(nu_, nu_, R, nu_, &sRr0, 0, 0);
460 drowin_libstr(nu_, 1.0, &sr0, 0, &sRr0, nu_, 0);
461 d_print_strmat(nu_+1, nu_, &sRr0, 0, 0);
462
463 struct d_strvec srq1;
464 d_allocate_strvec(nu_+nx_, &srq1);
465 d_cvt_vec2strvec(nu_, r, &srq1, 0);
466 d_cvt_vec2strvec(nx_, q, &srq1, nu_);
467
468 struct d_strmat sRSQrq1;
469 d_allocate_strmat(nu_+nx_+1, nu_+nx_, &sRSQrq1);
470 d_cvt_mat2strmat(nu_, nu_, R, nu_, &sRSQrq1, 0, 0);
471 d_cvt_tran_mat2strmat(nu_, nx_, S, nu_, &sRSQrq1, nu_, 0);
472 d_cvt_mat2strmat(nx_, nx_, Q, nx_, &sRSQrq1, nu_, nu_);
473 drowin_libstr(nu_+nx_, 1.0, &srq1, 0, &sRSQrq1, nu_+nx_, 0);
474 d_print_strmat(nu_+nx_+1, nu_+nx_, &sRSQrq1, 0, 0);
475
476 struct d_strvec sqN;
477 d_allocate_strvec(nx_, &sqN);
478 d_cvt_vec2strvec(nx_, q, &sqN, 0);
479
480 struct d_strmat sQqN;
481 d_allocate_strmat(nx_+1, nx_, &sQqN);
482 d_cvt_mat2strmat(nx_, nx_, Q, nx_, &sQqN, 0, 0);
483 drowin_libstr(nx_, 1.0, &sqN, 0, &sQqN, nx_, 0);
484 d_print_strmat(nx_+1, nx_, &sQqN, 0, 0);
485
486/************************************************
487* array of matrices
488************************************************/
489
490 struct d_strmat hsBAbt[N];
491 struct d_strvec hsb[N];
492 struct d_strmat hsRSQrq[N+1];
493 struct d_strvec hsrq[N+1];
494 struct d_strmat hsL[N+1];
495 struct d_strmat hsLxt[N+1];
496 struct d_strvec hsPb[N];
497 struct d_strvec hsux[N+1];
498 struct d_strvec hspi[N];
499 struct d_strmat hswork_mat[1];
500 struct d_strvec hswork_vec[1];
501
502 hsBAbt[0] = sBbt0;
503 hsb[0] = sb0;
504 hsRSQrq[0] = sRr0;
505 hsrq[0] = sr0;
506 d_allocate_strmat(nu_+1, nu_, &hsL[0]);
507// d_allocate_strmat(nu_+1, nu_, &hsLxt[0]);
508 d_allocate_strvec(nx_, &hsPb[0]);
509 d_allocate_strvec(nx_+nu_+1, &hsux[0]);
510 d_allocate_strvec(nx_, &hspi[0]);
511 for(ii=1; ii<N; ii++)
512 {
513 hsBAbt[ii] = sBAbt1;
514 hsb[ii] = sb;
515 hsRSQrq[ii] = sRSQrq1;
516 hsrq[ii] = srq1;
517 d_allocate_strmat(nu_+nx_+1, nu_+nx_, &hsL[ii]);
518 d_allocate_strmat(nx_, nu_+nx_, &hsLxt[ii]);
519 d_allocate_strvec(nx_, &hsPb[ii]);
520 d_allocate_strvec(nx_+nu_+1, &hsux[ii]);
521 d_allocate_strvec(nx_, &hspi[ii]);
522 }
523 hsRSQrq[N] = sQqN;
524 hsrq[N] = sqN;
525 d_allocate_strmat(nx_+1, nx_, &hsL[N]);
526 d_allocate_strmat(nx_, nx_, &hsLxt[N]);
527 d_allocate_strvec(nx_+nu_+1, &hsux[N]);
528 d_allocate_strmat(nu_+nx_+1, nx_, &hswork_mat[0]);
529 d_allocate_strvec(nx_, &hswork_vec[0]);
530
531// for(ii=0; ii<N; ii++)
532// d_print_strmat(nu[ii]+nx[ii]+1, nx[ii+1], &hsBAbt[ii], 0, 0);
533// return 0;
534
535/************************************************
536* call Riccati solver
537************************************************/
538
539 // timing
540 struct timeval tv0, tv1, tv2, tv3;
541 int nrep = 1000;
542 int rep;
543
544 gettimeofday(&tv0, NULL); // time
545
546 for(rep=0; rep<nrep; rep++)
547 {
548// d_back_ric_sv_libstr(N, nx, nu, hsBAbt, hsRSQrq, hsL, hsLxt, hsux, hspi, hswork_mat, hswork_vec);
549 }
550
551 gettimeofday(&tv1, NULL); // time
552
553 for(rep=0; rep<nrep; rep++)
554 {
555 d_back_ric_trf_libstr(N, nx, nu, hsBAbt, hsRSQrq, hsL, hsLxt, hswork_mat);
556 }
557
558 gettimeofday(&tv2, NULL); // time
559
560 for(rep=0; rep<nrep; rep++)
561 {
562 d_back_ric_trs_libstr(N, nx, nu, hsBAbt, hsb, hsrq, hsL, hsLxt, hsPb, hsux, hspi, hswork_vec);
563 }
564
565 gettimeofday(&tv3, NULL); // time
566
567 float time_sv = (float) (tv1.tv_sec-tv0.tv_sec)/(nrep+0.0)+(tv1.tv_usec-tv0.tv_usec)/(nrep*1e6);
568 float time_trf = (float) (tv2.tv_sec-tv1.tv_sec)/(nrep+0.0)+(tv2.tv_usec-tv1.tv_usec)/(nrep*1e6);
569 float time_trs = (float) (tv3.tv_sec-tv2.tv_sec)/(nrep+0.0)+(tv3.tv_usec-tv2.tv_usec)/(nrep*1e6);
570
571 // print sol
572 printf("\nux = \n\n");
573 for(ii=0; ii<=N; ii++)
574 d_print_tran_strvec(nu[ii]+nx[ii], &hsux[ii], 0);
575
576 printf("\npi = \n\n");
577 for(ii=0; ii<N; ii++)
578 d_print_tran_strvec(nx[ii+1], &hspi[ii], 0);
579
580 printf("\ntime sv\t\ttime trf\t\ttime trs\n");
581 printf("\n%e\t%e\t%e\n", time_sv, time_trf, time_trs);
582 printf("\n");
583
584/************************************************
585* free memory
586************************************************/
587
588 d_free(A);
589 d_free(B);
590 d_free(b);
591 d_free_align(x0);
592 d_free(R);
593 d_free(S);
594 d_free(Q);
595 d_free(r);
596 d_free(q);
597 d_free(b0);
598 d_free_strmat(&sA);
599 d_free_strvec(&sb);
600 d_free_strmat(&sBbt0);
601 d_free_strvec(&sb0);
602 d_free_strmat(&sBAbt1);
603 d_free_strmat(&sRr0);
604 d_free_strvec(&sr0);
605 d_free_strmat(&sRSQrq1);
606 d_free_strvec(&srq1);
607 d_free_strmat(&sQqN);
608 d_free_strvec(&sqN);
609 d_free_strmat(&hsL[0]);
610// d_free_strmat(&hsLxt[0]);
611 d_free_strvec(&hsPb[0]);
612 d_free_strvec(&hsux[0]);
613 d_free_strvec(&hspi[0]);
614 for(ii=1; ii<N; ii++)
615 {
616 d_free_strmat(&hsL[ii]);
617 d_free_strmat(&hsLxt[ii]);
618 d_free_strvec(&hsPb[ii]);
619 d_free_strvec(&hsux[ii]);
620 d_free_strvec(&hspi[ii]);
621 }
622 d_free_strmat(&hsL[N]);
623 d_free_strmat(&hsLxt[N]);
624 d_free_strvec(&hsux[N]);
625 d_free_strmat(&hswork_mat[0]);
626 d_free_strvec(&hswork_vec[0]);
627
628
629/************************************************
630* return
631************************************************/
632
633 return 0;
634
635 }
636
637
638