Line data Source code
1 : /*************************************************************************
2 : ALGLIB 3.17.0 (source code generated 2020-12-27)
3 : Copyright (c) Sergey Bochkanov (ALGLIB project).
4 :
5 : >>> SOURCE LICENSE >>>
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation (www.fsf.org); either version 2 of the
9 : License, or (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : A copy of the GNU General Public License is available at
17 : http://www.fsf.org/licensing/licenses
18 : >>> END OF LICENSE >>>
19 : *************************************************************************/
20 : #ifdef _MSC_VER
21 : #define _CRT_SECURE_NO_WARNINGS
22 : #endif
23 : #include "stdafx.h"
24 : #include "linalg.h"
25 :
26 : // disable some irrelevant warnings
27 : #if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS)
28 : #pragma warning(disable:4100)
29 : #pragma warning(disable:4127)
30 : #pragma warning(disable:4611)
31 : #pragma warning(disable:4702)
32 : #pragma warning(disable:4996)
33 : #endif
34 :
35 : /////////////////////////////////////////////////////////////////////////
36 : //
37 : // THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE
38 : //
39 : /////////////////////////////////////////////////////////////////////////
40 : namespace alglib
41 : {
42 :
43 : #if defined(AE_COMPILE_SPARSE) || !defined(AE_PARTIAL_BUILD)
44 :
45 : #endif
46 :
47 : #if defined(AE_COMPILE_ABLAS) || !defined(AE_PARTIAL_BUILD)
48 :
49 : #endif
50 :
51 : #if defined(AE_COMPILE_DLU) || !defined(AE_PARTIAL_BUILD)
52 :
53 : #endif
54 :
55 : #if defined(AE_COMPILE_SPTRF) || !defined(AE_PARTIAL_BUILD)
56 :
57 : #endif
58 :
59 : #if defined(AE_COMPILE_AMDORDERING) || !defined(AE_PARTIAL_BUILD)
60 :
61 : #endif
62 :
63 : #if defined(AE_COMPILE_SPCHOL) || !defined(AE_PARTIAL_BUILD)
64 :
65 : #endif
66 :
67 : #if defined(AE_COMPILE_MATGEN) || !defined(AE_PARTIAL_BUILD)
68 :
69 : #endif
70 :
71 : #if defined(AE_COMPILE_TRFAC) || !defined(AE_PARTIAL_BUILD)
72 :
73 : #endif
74 :
75 : #if defined(AE_COMPILE_RCOND) || !defined(AE_PARTIAL_BUILD)
76 :
77 : #endif
78 :
79 : #if defined(AE_COMPILE_MATINV) || !defined(AE_PARTIAL_BUILD)
80 :
81 : #endif
82 :
83 : #if defined(AE_COMPILE_ORTFAC) || !defined(AE_PARTIAL_BUILD)
84 :
85 : #endif
86 :
87 : #if defined(AE_COMPILE_FBLS) || !defined(AE_PARTIAL_BUILD)
88 :
89 : #endif
90 :
91 : #if defined(AE_COMPILE_BDSVD) || !defined(AE_PARTIAL_BUILD)
92 :
93 : #endif
94 :
95 : #if defined(AE_COMPILE_SVD) || !defined(AE_PARTIAL_BUILD)
96 :
97 : #endif
98 :
99 : #if defined(AE_COMPILE_NORMESTIMATOR) || !defined(AE_PARTIAL_BUILD)
100 :
101 : #endif
102 :
103 : #if defined(AE_COMPILE_HSSCHUR) || !defined(AE_PARTIAL_BUILD)
104 :
105 : #endif
106 :
107 : #if defined(AE_COMPILE_EVD) || !defined(AE_PARTIAL_BUILD)
108 :
109 : #endif
110 :
111 : #if defined(AE_COMPILE_SCHUR) || !defined(AE_PARTIAL_BUILD)
112 :
113 : #endif
114 :
115 : #if defined(AE_COMPILE_SPDGEVD) || !defined(AE_PARTIAL_BUILD)
116 :
117 : #endif
118 :
119 : #if defined(AE_COMPILE_INVERSEUPDATE) || !defined(AE_PARTIAL_BUILD)
120 :
121 : #endif
122 :
123 : #if defined(AE_COMPILE_MATDET) || !defined(AE_PARTIAL_BUILD)
124 :
125 : #endif
126 :
127 : #if defined(AE_COMPILE_SPARSE) || !defined(AE_PARTIAL_BUILD)
128 : /*************************************************************************
129 : Sparse matrix structure.
130 :
131 : You should use ALGLIB functions to work with sparse matrix. Never try to
132 : access its fields directly!
133 :
134 : NOTES ON THE SPARSE STORAGE FORMATS
135 :
136 : Sparse matrices can be stored using several formats:
137 : * Hash-Table representation
138 : * Compressed Row Storage (CRS)
139 : * Skyline matrix storage (SKS)
140 :
141 : Each of the formats has benefits and drawbacks:
142 : * Hash-table is good for dynamic operations (insertion of new elements),
143 : but does not support linear algebra operations
144 : * CRS is good for operations like matrix-vector or matrix-matrix products,
145 : but its initialization is less convenient - you have to tell row sizes
146 : at the initialization, and you have to fill matrix only row by row,
147 : from left to right.
148 : * SKS is a special format which is used to store triangular factors from
149 : Cholesky factorization. It does not support dynamic modification, and
150 : support for linear algebra operations is very limited.
151 :
152 : Tables below outline information about these two formats:
153 :
154 : OPERATIONS WITH MATRIX HASH CRS SKS
155 : creation + + +
156 : SparseGet + + +
157 : SparseExists + + +
158 : SparseRewriteExisting + + +
159 : SparseSet + + +
160 : SparseAdd +
161 : SparseGetRow + +
162 : SparseGetCompressedRow + +
163 : sparse-dense linear algebra + +
164 : *************************************************************************/
165 0 : _sparsematrix_owner::_sparsematrix_owner()
166 : {
167 : jmp_buf _break_jump;
168 : alglib_impl::ae_state _state;
169 :
170 0 : alglib_impl::ae_state_init(&_state);
171 0 : if( setjmp(_break_jump) )
172 : {
173 0 : if( p_struct!=NULL )
174 : {
175 0 : alglib_impl::_sparsematrix_destroy(p_struct);
176 0 : alglib_impl::ae_free(p_struct);
177 : }
178 0 : p_struct = NULL;
179 : #if !defined(AE_NO_EXCEPTIONS)
180 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
181 : #else
182 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
183 : return;
184 : #endif
185 : }
186 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
187 0 : p_struct = NULL;
188 0 : p_struct = (alglib_impl::sparsematrix*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsematrix), &_state);
189 0 : memset(p_struct, 0, sizeof(alglib_impl::sparsematrix));
190 0 : alglib_impl::_sparsematrix_init(p_struct, &_state, ae_false);
191 0 : ae_state_clear(&_state);
192 0 : }
193 :
194 0 : _sparsematrix_owner::_sparsematrix_owner(const _sparsematrix_owner &rhs)
195 : {
196 : jmp_buf _break_jump;
197 : alglib_impl::ae_state _state;
198 :
199 0 : alglib_impl::ae_state_init(&_state);
200 0 : if( setjmp(_break_jump) )
201 : {
202 0 : if( p_struct!=NULL )
203 : {
204 0 : alglib_impl::_sparsematrix_destroy(p_struct);
205 0 : alglib_impl::ae_free(p_struct);
206 : }
207 0 : p_struct = NULL;
208 : #if !defined(AE_NO_EXCEPTIONS)
209 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
210 : #else
211 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
212 : return;
213 : #endif
214 : }
215 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
216 0 : p_struct = NULL;
217 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsematrix copy constructor failure (source is not initialized)", &_state);
218 0 : p_struct = (alglib_impl::sparsematrix*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsematrix), &_state);
219 0 : memset(p_struct, 0, sizeof(alglib_impl::sparsematrix));
220 0 : alglib_impl::_sparsematrix_init_copy(p_struct, const_cast<alglib_impl::sparsematrix*>(rhs.p_struct), &_state, ae_false);
221 0 : ae_state_clear(&_state);
222 0 : }
223 :
224 0 : _sparsematrix_owner& _sparsematrix_owner::operator=(const _sparsematrix_owner &rhs)
225 : {
226 0 : if( this==&rhs )
227 0 : return *this;
228 : jmp_buf _break_jump;
229 : alglib_impl::ae_state _state;
230 :
231 0 : alglib_impl::ae_state_init(&_state);
232 0 : if( setjmp(_break_jump) )
233 : {
234 : #if !defined(AE_NO_EXCEPTIONS)
235 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
236 : #else
237 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
238 : return *this;
239 : #endif
240 : }
241 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
242 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: sparsematrix assignment constructor failure (destination is not initialized)", &_state);
243 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsematrix assignment constructor failure (source is not initialized)", &_state);
244 0 : alglib_impl::_sparsematrix_destroy(p_struct);
245 0 : memset(p_struct, 0, sizeof(alglib_impl::sparsematrix));
246 0 : alglib_impl::_sparsematrix_init_copy(p_struct, const_cast<alglib_impl::sparsematrix*>(rhs.p_struct), &_state, ae_false);
247 0 : ae_state_clear(&_state);
248 0 : return *this;
249 : }
250 :
251 0 : _sparsematrix_owner::~_sparsematrix_owner()
252 : {
253 0 : if( p_struct!=NULL )
254 : {
255 0 : alglib_impl::_sparsematrix_destroy(p_struct);
256 0 : ae_free(p_struct);
257 : }
258 0 : }
259 :
260 0 : alglib_impl::sparsematrix* _sparsematrix_owner::c_ptr()
261 : {
262 0 : return p_struct;
263 : }
264 :
265 0 : alglib_impl::sparsematrix* _sparsematrix_owner::c_ptr() const
266 : {
267 0 : return const_cast<alglib_impl::sparsematrix*>(p_struct);
268 : }
269 0 : sparsematrix::sparsematrix() : _sparsematrix_owner()
270 : {
271 0 : }
272 :
273 0 : sparsematrix::sparsematrix(const sparsematrix &rhs):_sparsematrix_owner(rhs)
274 : {
275 0 : }
276 :
277 0 : sparsematrix& sparsematrix::operator=(const sparsematrix &rhs)
278 : {
279 0 : if( this==&rhs )
280 0 : return *this;
281 0 : _sparsematrix_owner::operator=(rhs);
282 0 : return *this;
283 : }
284 :
285 0 : sparsematrix::~sparsematrix()
286 : {
287 0 : }
288 :
289 :
290 : /*************************************************************************
291 : Temporary buffers for sparse matrix operations.
292 :
293 : You should pass an instance of this structure to factorization functions.
294 : It allows to reuse memory during repeated sparse factorizations. You do
295 : not have to call some initialization function - simply passing an instance
296 : to factorization function is enough.
297 : *************************************************************************/
298 0 : _sparsebuffers_owner::_sparsebuffers_owner()
299 : {
300 : jmp_buf _break_jump;
301 : alglib_impl::ae_state _state;
302 :
303 0 : alglib_impl::ae_state_init(&_state);
304 0 : if( setjmp(_break_jump) )
305 : {
306 0 : if( p_struct!=NULL )
307 : {
308 0 : alglib_impl::_sparsebuffers_destroy(p_struct);
309 0 : alglib_impl::ae_free(p_struct);
310 : }
311 0 : p_struct = NULL;
312 : #if !defined(AE_NO_EXCEPTIONS)
313 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
314 : #else
315 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
316 : return;
317 : #endif
318 : }
319 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
320 0 : p_struct = NULL;
321 0 : p_struct = (alglib_impl::sparsebuffers*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsebuffers), &_state);
322 0 : memset(p_struct, 0, sizeof(alglib_impl::sparsebuffers));
323 0 : alglib_impl::_sparsebuffers_init(p_struct, &_state, ae_false);
324 0 : ae_state_clear(&_state);
325 0 : }
326 :
327 0 : _sparsebuffers_owner::_sparsebuffers_owner(const _sparsebuffers_owner &rhs)
328 : {
329 : jmp_buf _break_jump;
330 : alglib_impl::ae_state _state;
331 :
332 0 : alglib_impl::ae_state_init(&_state);
333 0 : if( setjmp(_break_jump) )
334 : {
335 0 : if( p_struct!=NULL )
336 : {
337 0 : alglib_impl::_sparsebuffers_destroy(p_struct);
338 0 : alglib_impl::ae_free(p_struct);
339 : }
340 0 : p_struct = NULL;
341 : #if !defined(AE_NO_EXCEPTIONS)
342 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
343 : #else
344 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
345 : return;
346 : #endif
347 : }
348 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
349 0 : p_struct = NULL;
350 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsebuffers copy constructor failure (source is not initialized)", &_state);
351 0 : p_struct = (alglib_impl::sparsebuffers*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsebuffers), &_state);
352 0 : memset(p_struct, 0, sizeof(alglib_impl::sparsebuffers));
353 0 : alglib_impl::_sparsebuffers_init_copy(p_struct, const_cast<alglib_impl::sparsebuffers*>(rhs.p_struct), &_state, ae_false);
354 0 : ae_state_clear(&_state);
355 0 : }
356 :
357 0 : _sparsebuffers_owner& _sparsebuffers_owner::operator=(const _sparsebuffers_owner &rhs)
358 : {
359 0 : if( this==&rhs )
360 0 : return *this;
361 : jmp_buf _break_jump;
362 : alglib_impl::ae_state _state;
363 :
364 0 : alglib_impl::ae_state_init(&_state);
365 0 : if( setjmp(_break_jump) )
366 : {
367 : #if !defined(AE_NO_EXCEPTIONS)
368 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
369 : #else
370 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
371 : return *this;
372 : #endif
373 : }
374 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
375 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: sparsebuffers assignment constructor failure (destination is not initialized)", &_state);
376 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsebuffers assignment constructor failure (source is not initialized)", &_state);
377 0 : alglib_impl::_sparsebuffers_destroy(p_struct);
378 0 : memset(p_struct, 0, sizeof(alglib_impl::sparsebuffers));
379 0 : alglib_impl::_sparsebuffers_init_copy(p_struct, const_cast<alglib_impl::sparsebuffers*>(rhs.p_struct), &_state, ae_false);
380 0 : ae_state_clear(&_state);
381 0 : return *this;
382 : }
383 :
384 0 : _sparsebuffers_owner::~_sparsebuffers_owner()
385 : {
386 0 : if( p_struct!=NULL )
387 : {
388 0 : alglib_impl::_sparsebuffers_destroy(p_struct);
389 0 : ae_free(p_struct);
390 : }
391 0 : }
392 :
393 0 : alglib_impl::sparsebuffers* _sparsebuffers_owner::c_ptr()
394 : {
395 0 : return p_struct;
396 : }
397 :
398 0 : alglib_impl::sparsebuffers* _sparsebuffers_owner::c_ptr() const
399 : {
400 0 : return const_cast<alglib_impl::sparsebuffers*>(p_struct);
401 : }
402 0 : sparsebuffers::sparsebuffers() : _sparsebuffers_owner()
403 : {
404 0 : }
405 :
406 0 : sparsebuffers::sparsebuffers(const sparsebuffers &rhs):_sparsebuffers_owner(rhs)
407 : {
408 0 : }
409 :
410 0 : sparsebuffers& sparsebuffers::operator=(const sparsebuffers &rhs)
411 : {
412 0 : if( this==&rhs )
413 0 : return *this;
414 0 : _sparsebuffers_owner::operator=(rhs);
415 0 : return *this;
416 : }
417 :
418 0 : sparsebuffers::~sparsebuffers()
419 : {
420 0 : }
421 :
422 : /*************************************************************************
423 : This function creates sparse matrix in a Hash-Table format.
424 :
425 : This function creates Hast-Table matrix, which can be converted to CRS
426 : format after its initialization is over. Typical usage scenario for a
427 : sparse matrix is:
428 : 1. creation in a Hash-Table format
429 : 2. insertion of the matrix elements
430 : 3. conversion to the CRS representation
431 : 4. matrix is passed to some linear algebra algorithm
432 :
433 : Some information about different matrix formats can be found below, in
434 : the "NOTES" section.
435 :
436 : INPUT PARAMETERS
437 : M - number of rows in a matrix, M>=1
438 : N - number of columns in a matrix, N>=1
439 : K - K>=0, expected number of non-zero elements in a matrix.
440 : K can be inexact approximation, can be less than actual
441 : number of elements (table will grow when needed) or
442 : even zero).
443 : It is important to understand that although hash-table
444 : may grow automatically, it is better to provide good
445 : estimate of data size.
446 :
447 : OUTPUT PARAMETERS
448 : S - sparse M*N matrix in Hash-Table representation.
449 : All elements of the matrix are zero.
450 :
451 : NOTE 1
452 :
453 : Hash-tables use memory inefficiently, and they have to keep some amount
454 : of the "spare memory" in order to have good performance. Hash table for
455 : matrix with K non-zero elements will need C*K*(8+2*sizeof(int)) bytes,
456 : where C is a small constant, about 1.5-2 in magnitude.
457 :
458 : CRS storage, from the other side, is more memory-efficient, and needs
459 : just K*(8+sizeof(int))+M*sizeof(int) bytes, where M is a number of rows
460 : in a matrix.
461 :
462 : When you convert from the Hash-Table to CRS representation, all unneeded
463 : memory will be freed.
464 :
465 : NOTE 2
466 :
467 : Comments of SparseMatrix structure outline information about different
468 : sparse storage formats. We recommend you to read them before starting to
469 : use ALGLIB sparse matrices.
470 :
471 : NOTE 3
472 :
473 : This function completely overwrites S with new sparse matrix. Previously
474 : allocated storage is NOT reused. If you want to reuse already allocated
475 : memory, call SparseCreateBuf function.
476 :
477 : -- ALGLIB PROJECT --
478 : Copyright 14.10.2011 by Bochkanov Sergey
479 : *************************************************************************/
480 0 : void sparsecreate(const ae_int_t m, const ae_int_t n, const ae_int_t k, sparsematrix &s, const xparams _xparams)
481 : {
482 : jmp_buf _break_jump;
483 : alglib_impl::ae_state _alglib_env_state;
484 0 : alglib_impl::ae_state_init(&_alglib_env_state);
485 0 : if( setjmp(_break_jump) )
486 : {
487 : #if !defined(AE_NO_EXCEPTIONS)
488 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
489 : #else
490 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
491 : return;
492 : #endif
493 : }
494 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
495 0 : if( _xparams.flags!=0x0 )
496 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
497 0 : alglib_impl::sparsecreate(m, n, k, const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
498 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
499 0 : return;
500 : }
501 :
502 : /*************************************************************************
503 : This function creates sparse matrix in a Hash-Table format.
504 :
505 : This function creates Hast-Table matrix, which can be converted to CRS
506 : format after its initialization is over. Typical usage scenario for a
507 : sparse matrix is:
508 : 1. creation in a Hash-Table format
509 : 2. insertion of the matrix elements
510 : 3. conversion to the CRS representation
511 : 4. matrix is passed to some linear algebra algorithm
512 :
513 : Some information about different matrix formats can be found below, in
514 : the "NOTES" section.
515 :
516 : INPUT PARAMETERS
517 : M - number of rows in a matrix, M>=1
518 : N - number of columns in a matrix, N>=1
519 : K - K>=0, expected number of non-zero elements in a matrix.
520 : K can be inexact approximation, can be less than actual
521 : number of elements (table will grow when needed) or
522 : even zero).
523 : It is important to understand that although hash-table
524 : may grow automatically, it is better to provide good
525 : estimate of data size.
526 :
527 : OUTPUT PARAMETERS
528 : S - sparse M*N matrix in Hash-Table representation.
529 : All elements of the matrix are zero.
530 :
531 : NOTE 1
532 :
533 : Hash-tables use memory inefficiently, and they have to keep some amount
534 : of the "spare memory" in order to have good performance. Hash table for
535 : matrix with K non-zero elements will need C*K*(8+2*sizeof(int)) bytes,
536 : where C is a small constant, about 1.5-2 in magnitude.
537 :
538 : CRS storage, from the other side, is more memory-efficient, and needs
539 : just K*(8+sizeof(int))+M*sizeof(int) bytes, where M is a number of rows
540 : in a matrix.
541 :
542 : When you convert from the Hash-Table to CRS representation, all unneeded
543 : memory will be freed.
544 :
545 : NOTE 2
546 :
547 : Comments of SparseMatrix structure outline information about different
548 : sparse storage formats. We recommend you to read them before starting to
549 : use ALGLIB sparse matrices.
550 :
551 : NOTE 3
552 :
553 : This function completely overwrites S with new sparse matrix. Previously
554 : allocated storage is NOT reused. If you want to reuse already allocated
555 : memory, call SparseCreateBuf function.
556 :
557 : -- ALGLIB PROJECT --
558 : Copyright 14.10.2011 by Bochkanov Sergey
559 : *************************************************************************/
560 : #if !defined(AE_NO_EXCEPTIONS)
561 0 : void sparsecreate(const ae_int_t m, const ae_int_t n, sparsematrix &s, const xparams _xparams)
562 : {
563 : jmp_buf _break_jump;
564 : alglib_impl::ae_state _alglib_env_state;
565 : ae_int_t k;
566 :
567 0 : k = 0;
568 0 : alglib_impl::ae_state_init(&_alglib_env_state);
569 0 : if( setjmp(_break_jump) )
570 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
571 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
572 0 : if( _xparams.flags!=0x0 )
573 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
574 0 : alglib_impl::sparsecreate(m, n, k, const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
575 :
576 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
577 0 : return;
578 : }
579 : #endif
580 :
581 : /*************************************************************************
582 : This version of SparseCreate function creates sparse matrix in Hash-Table
583 : format, reusing previously allocated storage as much as possible. Read
584 : comments for SparseCreate() for more information.
585 :
586 : INPUT PARAMETERS
587 : M - number of rows in a matrix, M>=1
588 : N - number of columns in a matrix, N>=1
589 : K - K>=0, expected number of non-zero elements in a matrix.
590 : K can be inexact approximation, can be less than actual
591 : number of elements (table will grow when needed) or
592 : even zero).
593 : It is important to understand that although hash-table
594 : may grow automatically, it is better to provide good
595 : estimate of data size.
596 : S - SparseMatrix structure which MAY contain some already
597 : allocated storage.
598 :
599 : OUTPUT PARAMETERS
600 : S - sparse M*N matrix in Hash-Table representation.
601 : All elements of the matrix are zero.
602 : Previously allocated storage is reused, if its size
603 : is compatible with expected number of non-zeros K.
604 :
605 : -- ALGLIB PROJECT --
606 : Copyright 14.01.2014 by Bochkanov Sergey
607 : *************************************************************************/
608 0 : void sparsecreatebuf(const ae_int_t m, const ae_int_t n, const ae_int_t k, const sparsematrix &s, const xparams _xparams)
609 : {
610 : jmp_buf _break_jump;
611 : alglib_impl::ae_state _alglib_env_state;
612 0 : alglib_impl::ae_state_init(&_alglib_env_state);
613 0 : if( setjmp(_break_jump) )
614 : {
615 : #if !defined(AE_NO_EXCEPTIONS)
616 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
617 : #else
618 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
619 : return;
620 : #endif
621 : }
622 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
623 0 : if( _xparams.flags!=0x0 )
624 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
625 0 : alglib_impl::sparsecreatebuf(m, n, k, const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
626 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
627 0 : return;
628 : }
629 :
630 : /*************************************************************************
631 : This version of SparseCreate function creates sparse matrix in Hash-Table
632 : format, reusing previously allocated storage as much as possible. Read
633 : comments for SparseCreate() for more information.
634 :
635 : INPUT PARAMETERS
636 : M - number of rows in a matrix, M>=1
637 : N - number of columns in a matrix, N>=1
638 : K - K>=0, expected number of non-zero elements in a matrix.
639 : K can be inexact approximation, can be less than actual
640 : number of elements (table will grow when needed) or
641 : even zero).
642 : It is important to understand that although hash-table
643 : may grow automatically, it is better to provide good
644 : estimate of data size.
645 : S - SparseMatrix structure which MAY contain some already
646 : allocated storage.
647 :
648 : OUTPUT PARAMETERS
649 : S - sparse M*N matrix in Hash-Table representation.
650 : All elements of the matrix are zero.
651 : Previously allocated storage is reused, if its size
652 : is compatible with expected number of non-zeros K.
653 :
654 : -- ALGLIB PROJECT --
655 : Copyright 14.01.2014 by Bochkanov Sergey
656 : *************************************************************************/
657 : #if !defined(AE_NO_EXCEPTIONS)
658 0 : void sparsecreatebuf(const ae_int_t m, const ae_int_t n, const sparsematrix &s, const xparams _xparams)
659 : {
660 : jmp_buf _break_jump;
661 : alglib_impl::ae_state _alglib_env_state;
662 : ae_int_t k;
663 :
664 0 : k = 0;
665 0 : alglib_impl::ae_state_init(&_alglib_env_state);
666 0 : if( setjmp(_break_jump) )
667 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
668 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
669 0 : if( _xparams.flags!=0x0 )
670 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
671 0 : alglib_impl::sparsecreatebuf(m, n, k, const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
672 :
673 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
674 0 : return;
675 : }
676 : #endif
677 :
678 : /*************************************************************************
679 : This function creates sparse matrix in a CRS format (expert function for
680 : situations when you are running out of memory).
681 :
682 : This function creates CRS matrix. Typical usage scenario for a CRS matrix
683 : is:
684 : 1. creation (you have to tell number of non-zero elements at each row at
685 : this moment)
686 : 2. insertion of the matrix elements (row by row, from left to right)
687 : 3. matrix is passed to some linear algebra algorithm
688 :
689 : This function is a memory-efficient alternative to SparseCreate(), but it
690 : is more complex because it requires you to know in advance how large your
691 : matrix is. Some information about different matrix formats can be found
692 : in comments on SparseMatrix structure. We recommend you to read them
693 : before starting to use ALGLIB sparse matrices..
694 :
695 : INPUT PARAMETERS
696 : M - number of rows in a matrix, M>=1
697 : N - number of columns in a matrix, N>=1
698 : NER - number of elements at each row, array[M], NER[I]>=0
699 :
700 : OUTPUT PARAMETERS
701 : S - sparse M*N matrix in CRS representation.
702 : You have to fill ALL non-zero elements by calling
703 : SparseSet() BEFORE you try to use this matrix.
704 :
705 : NOTE: this function completely overwrites S with new sparse matrix.
706 : Previously allocated storage is NOT reused. If you want to reuse
707 : already allocated memory, call SparseCreateCRSBuf function.
708 :
709 : -- ALGLIB PROJECT --
710 : Copyright 14.10.2011 by Bochkanov Sergey
711 : *************************************************************************/
712 0 : void sparsecreatecrs(const ae_int_t m, const ae_int_t n, const integer_1d_array &ner, sparsematrix &s, const xparams _xparams)
713 : {
714 : jmp_buf _break_jump;
715 : alglib_impl::ae_state _alglib_env_state;
716 0 : alglib_impl::ae_state_init(&_alglib_env_state);
717 0 : if( setjmp(_break_jump) )
718 : {
719 : #if !defined(AE_NO_EXCEPTIONS)
720 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
721 : #else
722 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
723 : return;
724 : #endif
725 : }
726 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
727 0 : if( _xparams.flags!=0x0 )
728 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
729 0 : alglib_impl::sparsecreatecrs(m, n, const_cast<alglib_impl::ae_vector*>(ner.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
730 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
731 0 : return;
732 : }
733 :
734 : /*************************************************************************
735 : This function creates sparse matrix in a CRS format (expert function for
736 : situations when you are running out of memory). This version of CRS
737 : matrix creation function may reuse memory already allocated in S.
738 :
739 : This function creates CRS matrix. Typical usage scenario for a CRS matrix
740 : is:
741 : 1. creation (you have to tell number of non-zero elements at each row at
742 : this moment)
743 : 2. insertion of the matrix elements (row by row, from left to right)
744 : 3. matrix is passed to some linear algebra algorithm
745 :
746 : This function is a memory-efficient alternative to SparseCreate(), but it
747 : is more complex because it requires you to know in advance how large your
748 : matrix is. Some information about different matrix formats can be found
749 : in comments on SparseMatrix structure. We recommend you to read them
750 : before starting to use ALGLIB sparse matrices..
751 :
752 : INPUT PARAMETERS
753 : M - number of rows in a matrix, M>=1
754 : N - number of columns in a matrix, N>=1
755 : NER - number of elements at each row, array[M], NER[I]>=0
756 : S - sparse matrix structure with possibly preallocated
757 : memory.
758 :
759 : OUTPUT PARAMETERS
760 : S - sparse M*N matrix in CRS representation.
761 : You have to fill ALL non-zero elements by calling
762 : SparseSet() BEFORE you try to use this matrix.
763 :
764 : -- ALGLIB PROJECT --
765 : Copyright 14.10.2011 by Bochkanov Sergey
766 : *************************************************************************/
767 0 : void sparsecreatecrsbuf(const ae_int_t m, const ae_int_t n, const integer_1d_array &ner, const sparsematrix &s, const xparams _xparams)
768 : {
769 : jmp_buf _break_jump;
770 : alglib_impl::ae_state _alglib_env_state;
771 0 : alglib_impl::ae_state_init(&_alglib_env_state);
772 0 : if( setjmp(_break_jump) )
773 : {
774 : #if !defined(AE_NO_EXCEPTIONS)
775 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
776 : #else
777 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
778 : return;
779 : #endif
780 : }
781 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
782 0 : if( _xparams.flags!=0x0 )
783 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
784 0 : alglib_impl::sparsecreatecrsbuf(m, n, const_cast<alglib_impl::ae_vector*>(ner.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
785 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
786 0 : return;
787 : }
788 :
789 : /*************************************************************************
790 : This function creates sparse matrix in a SKS format (skyline storage
791 : format). In most cases you do not need this function - CRS format better
792 : suits most use cases.
793 :
794 : INPUT PARAMETERS
795 : M, N - number of rows(M) and columns (N) in a matrix:
796 : * M=N (as for now, ALGLIB supports only square SKS)
797 : * N>=1
798 : * M>=1
799 : D - "bottom" bandwidths, array[M], D[I]>=0.
800 : I-th element stores number of non-zeros at I-th row,
801 : below the diagonal (diagonal itself is not included)
802 : U - "top" bandwidths, array[N], U[I]>=0.
803 : I-th element stores number of non-zeros at I-th row,
804 : above the diagonal (diagonal itself is not included)
805 :
806 : OUTPUT PARAMETERS
807 : S - sparse M*N matrix in SKS representation.
808 : All elements are filled by zeros.
809 : You may use sparseset() to change their values.
810 :
811 : NOTE: this function completely overwrites S with new sparse matrix.
812 : Previously allocated storage is NOT reused. If you want to reuse
813 : already allocated memory, call SparseCreateSKSBuf function.
814 :
815 : -- ALGLIB PROJECT --
816 : Copyright 13.01.2014 by Bochkanov Sergey
817 : *************************************************************************/
818 0 : void sparsecreatesks(const ae_int_t m, const ae_int_t n, const integer_1d_array &d, const integer_1d_array &u, sparsematrix &s, const xparams _xparams)
819 : {
820 : jmp_buf _break_jump;
821 : alglib_impl::ae_state _alglib_env_state;
822 0 : alglib_impl::ae_state_init(&_alglib_env_state);
823 0 : if( setjmp(_break_jump) )
824 : {
825 : #if !defined(AE_NO_EXCEPTIONS)
826 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
827 : #else
828 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
829 : return;
830 : #endif
831 : }
832 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
833 0 : if( _xparams.flags!=0x0 )
834 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
835 0 : alglib_impl::sparsecreatesks(m, n, const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_vector*>(u.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
836 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
837 0 : return;
838 : }
839 :
840 : /*************************************************************************
841 : This is "buffered" version of SparseCreateSKS() which reuses memory
842 : previously allocated in S (of course, memory is reallocated if needed).
843 :
844 : This function creates sparse matrix in a SKS format (skyline storage
845 : format). In most cases you do not need this function - CRS format better
846 : suits most use cases.
847 :
848 : INPUT PARAMETERS
849 : M, N - number of rows(M) and columns (N) in a matrix:
850 : * M=N (as for now, ALGLIB supports only square SKS)
851 : * N>=1
852 : * M>=1
853 : D - "bottom" bandwidths, array[M], 0<=D[I]<=I.
854 : I-th element stores number of non-zeros at I-th row,
855 : below the diagonal (diagonal itself is not included)
856 : U - "top" bandwidths, array[N], 0<=U[I]<=I.
857 : I-th element stores number of non-zeros at I-th row,
858 : above the diagonal (diagonal itself is not included)
859 :
860 : OUTPUT PARAMETERS
861 : S - sparse M*N matrix in SKS representation.
862 : All elements are filled by zeros.
863 : You may use sparseset() to change their values.
864 :
865 : -- ALGLIB PROJECT --
866 : Copyright 13.01.2014 by Bochkanov Sergey
867 : *************************************************************************/
868 0 : void sparsecreatesksbuf(const ae_int_t m, const ae_int_t n, const integer_1d_array &d, const integer_1d_array &u, const sparsematrix &s, const xparams _xparams)
869 : {
870 : jmp_buf _break_jump;
871 : alglib_impl::ae_state _alglib_env_state;
872 0 : alglib_impl::ae_state_init(&_alglib_env_state);
873 0 : if( setjmp(_break_jump) )
874 : {
875 : #if !defined(AE_NO_EXCEPTIONS)
876 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
877 : #else
878 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
879 : return;
880 : #endif
881 : }
882 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
883 0 : if( _xparams.flags!=0x0 )
884 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
885 0 : alglib_impl::sparsecreatesksbuf(m, n, const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_vector*>(u.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
886 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
887 0 : return;
888 : }
889 :
890 : /*************************************************************************
891 : This function creates sparse matrix in a SKS format (skyline storage
892 : format). Unlike more general sparsecreatesks(), this function creates
893 : sparse matrix with constant bandwidth.
894 :
895 : You may want to use this function instead of sparsecreatesks() when your
896 : matrix has constant or nearly-constant bandwidth, and you want to
897 : simplify source code.
898 :
899 : INPUT PARAMETERS
900 : M, N - number of rows(M) and columns (N) in a matrix:
901 : * M=N (as for now, ALGLIB supports only square SKS)
902 : * N>=1
903 : * M>=1
904 : BW - matrix bandwidth, BW>=0
905 :
906 : OUTPUT PARAMETERS
907 : S - sparse M*N matrix in SKS representation.
908 : All elements are filled by zeros.
909 : You may use sparseset() to change their values.
910 :
911 : NOTE: this function completely overwrites S with new sparse matrix.
912 : Previously allocated storage is NOT reused. If you want to reuse
913 : already allocated memory, call sparsecreatesksbandbuf function.
914 :
915 : -- ALGLIB PROJECT --
916 : Copyright 25.12.2017 by Bochkanov Sergey
917 : *************************************************************************/
918 0 : void sparsecreatesksband(const ae_int_t m, const ae_int_t n, const ae_int_t bw, sparsematrix &s, const xparams _xparams)
919 : {
920 : jmp_buf _break_jump;
921 : alglib_impl::ae_state _alglib_env_state;
922 0 : alglib_impl::ae_state_init(&_alglib_env_state);
923 0 : if( setjmp(_break_jump) )
924 : {
925 : #if !defined(AE_NO_EXCEPTIONS)
926 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
927 : #else
928 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
929 : return;
930 : #endif
931 : }
932 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
933 0 : if( _xparams.flags!=0x0 )
934 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
935 0 : alglib_impl::sparsecreatesksband(m, n, bw, const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
936 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
937 0 : return;
938 : }
939 :
940 : /*************************************************************************
941 : This is "buffered" version of sparsecreatesksband() which reuses memory
942 : previously allocated in S (of course, memory is reallocated if needed).
943 :
944 : You may want to use this function instead of sparsecreatesksbuf() when
945 : your matrix has constant or nearly-constant bandwidth, and you want to
946 : simplify source code.
947 :
948 : INPUT PARAMETERS
949 : M, N - number of rows(M) and columns (N) in a matrix:
950 : * M=N (as for now, ALGLIB supports only square SKS)
951 : * N>=1
952 : * M>=1
953 : BW - bandwidth, BW>=0
954 :
955 : OUTPUT PARAMETERS
956 : S - sparse M*N matrix in SKS representation.
957 : All elements are filled by zeros.
958 : You may use sparseset() to change their values.
959 :
960 : -- ALGLIB PROJECT --
961 : Copyright 13.01.2014 by Bochkanov Sergey
962 : *************************************************************************/
963 0 : void sparsecreatesksbandbuf(const ae_int_t m, const ae_int_t n, const ae_int_t bw, const sparsematrix &s, const xparams _xparams)
964 : {
965 : jmp_buf _break_jump;
966 : alglib_impl::ae_state _alglib_env_state;
967 0 : alglib_impl::ae_state_init(&_alglib_env_state);
968 0 : if( setjmp(_break_jump) )
969 : {
970 : #if !defined(AE_NO_EXCEPTIONS)
971 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
972 : #else
973 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
974 : return;
975 : #endif
976 : }
977 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
978 0 : if( _xparams.flags!=0x0 )
979 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
980 0 : alglib_impl::sparsecreatesksbandbuf(m, n, bw, const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
981 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
982 0 : return;
983 : }
984 :
985 : /*************************************************************************
986 : This function copies S0 to S1.
987 : This function completely deallocates memory owned by S1 before creating a
988 : copy of S0. If you want to reuse memory, use SparseCopyBuf.
989 :
990 : NOTE: this function does not verify its arguments, it just copies all
991 : fields of the structure.
992 :
993 : -- ALGLIB PROJECT --
994 : Copyright 14.10.2011 by Bochkanov Sergey
995 : *************************************************************************/
996 0 : void sparsecopy(const sparsematrix &s0, sparsematrix &s1, const xparams _xparams)
997 : {
998 : jmp_buf _break_jump;
999 : alglib_impl::ae_state _alglib_env_state;
1000 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1001 0 : if( setjmp(_break_jump) )
1002 : {
1003 : #if !defined(AE_NO_EXCEPTIONS)
1004 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1005 : #else
1006 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1007 : return;
1008 : #endif
1009 : }
1010 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1011 0 : if( _xparams.flags!=0x0 )
1012 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1013 0 : alglib_impl::sparsecopy(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s1.c_ptr()), &_alglib_env_state);
1014 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1015 0 : return;
1016 : }
1017 :
1018 : /*************************************************************************
1019 : This function copies S0 to S1.
1020 : Memory already allocated in S1 is reused as much as possible.
1021 :
1022 : NOTE: this function does not verify its arguments, it just copies all
1023 : fields of the structure.
1024 :
1025 : -- ALGLIB PROJECT --
1026 : Copyright 14.10.2011 by Bochkanov Sergey
1027 : *************************************************************************/
1028 0 : void sparsecopybuf(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams)
1029 : {
1030 : jmp_buf _break_jump;
1031 : alglib_impl::ae_state _alglib_env_state;
1032 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1033 0 : if( setjmp(_break_jump) )
1034 : {
1035 : #if !defined(AE_NO_EXCEPTIONS)
1036 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1037 : #else
1038 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1039 : return;
1040 : #endif
1041 : }
1042 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1043 0 : if( _xparams.flags!=0x0 )
1044 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1045 0 : alglib_impl::sparsecopybuf(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s1.c_ptr()), &_alglib_env_state);
1046 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1047 0 : return;
1048 : }
1049 :
1050 : /*************************************************************************
1051 : This function efficiently swaps contents of S0 and S1.
1052 :
1053 : -- ALGLIB PROJECT --
1054 : Copyright 16.01.2014 by Bochkanov Sergey
1055 : *************************************************************************/
1056 0 : void sparseswap(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams)
1057 : {
1058 : jmp_buf _break_jump;
1059 : alglib_impl::ae_state _alglib_env_state;
1060 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1061 0 : if( setjmp(_break_jump) )
1062 : {
1063 : #if !defined(AE_NO_EXCEPTIONS)
1064 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1065 : #else
1066 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1067 : return;
1068 : #endif
1069 : }
1070 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1071 0 : if( _xparams.flags!=0x0 )
1072 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1073 0 : alglib_impl::sparseswap(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s1.c_ptr()), &_alglib_env_state);
1074 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1075 0 : return;
1076 : }
1077 :
1078 : /*************************************************************************
1079 : This function adds value to S[i,j] - element of the sparse matrix. Matrix
1080 : must be in a Hash-Table mode.
1081 :
1082 : In case S[i,j] already exists in the table, V i added to its value. In
1083 : case S[i,j] is non-existent, it is inserted in the table. Table
1084 : automatically grows when necessary.
1085 :
1086 : INPUT PARAMETERS
1087 : S - sparse M*N matrix in Hash-Table representation.
1088 : Exception will be thrown for CRS matrix.
1089 : I - row index of the element to modify, 0<=I<M
1090 : J - column index of the element to modify, 0<=J<N
1091 : V - value to add, must be finite number
1092 :
1093 : OUTPUT PARAMETERS
1094 : S - modified matrix
1095 :
1096 : NOTE 1: when S[i,j] is exactly zero after modification, it is deleted
1097 : from the table.
1098 :
1099 : -- ALGLIB PROJECT --
1100 : Copyright 14.10.2011 by Bochkanov Sergey
1101 : *************************************************************************/
1102 0 : void sparseadd(const sparsematrix &s, const ae_int_t i, const ae_int_t j, const double v, const xparams _xparams)
1103 : {
1104 : jmp_buf _break_jump;
1105 : alglib_impl::ae_state _alglib_env_state;
1106 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1107 0 : if( setjmp(_break_jump) )
1108 : {
1109 : #if !defined(AE_NO_EXCEPTIONS)
1110 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1111 : #else
1112 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1113 : return;
1114 : #endif
1115 : }
1116 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1117 0 : if( _xparams.flags!=0x0 )
1118 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1119 0 : alglib_impl::sparseadd(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), i, j, v, &_alglib_env_state);
1120 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1121 0 : return;
1122 : }
1123 :
1124 : /*************************************************************************
1125 : This function modifies S[i,j] - element of the sparse matrix.
1126 :
1127 : For Hash-based storage format:
1128 : * this function can be called at any moment - during matrix initialization
1129 : or later
1130 : * new value can be zero or non-zero. In case new value of S[i,j] is zero,
1131 : this element is deleted from the table.
1132 : * this function has no effect when called with zero V for non-existent
1133 : element.
1134 :
1135 : For CRS-bases storage format:
1136 : * this function can be called ONLY DURING MATRIX INITIALIZATION
1137 : * zero values are stored in the matrix similarly to non-zero ones
1138 : * elements must be initialized in correct order - from top row to bottom,
1139 : within row - from left to right.
1140 :
1141 : For SKS storage:
1142 : * this function can be called at any moment - during matrix initialization
1143 : or later
1144 : * zero values are stored in the matrix similarly to non-zero ones
1145 : * this function CAN NOT be called for non-existent (outside of the band
1146 : specified during SKS matrix creation) elements. Say, if you created SKS
1147 : matrix with bandwidth=2 and tried to call sparseset(s,0,10,VAL), an
1148 : exception will be generated.
1149 :
1150 : INPUT PARAMETERS
1151 : S - sparse M*N matrix in Hash-Table, SKS or CRS format.
1152 : I - row index of the element to modify, 0<=I<M
1153 : J - column index of the element to modify, 0<=J<N
1154 : V - value to set, must be finite number, can be zero
1155 :
1156 : OUTPUT PARAMETERS
1157 : S - modified matrix
1158 :
1159 : -- ALGLIB PROJECT --
1160 : Copyright 14.10.2011 by Bochkanov Sergey
1161 : *************************************************************************/
1162 0 : void sparseset(const sparsematrix &s, const ae_int_t i, const ae_int_t j, const double v, const xparams _xparams)
1163 : {
1164 : jmp_buf _break_jump;
1165 : alglib_impl::ae_state _alglib_env_state;
1166 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1167 0 : if( setjmp(_break_jump) )
1168 : {
1169 : #if !defined(AE_NO_EXCEPTIONS)
1170 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1171 : #else
1172 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1173 : return;
1174 : #endif
1175 : }
1176 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1177 0 : if( _xparams.flags!=0x0 )
1178 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1179 0 : alglib_impl::sparseset(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), i, j, v, &_alglib_env_state);
1180 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1181 0 : return;
1182 : }
1183 :
1184 : /*************************************************************************
1185 : This function returns S[i,j] - element of the sparse matrix. Matrix can
1186 : be in any mode (Hash-Table, CRS, SKS), but this function is less efficient
1187 : for CRS matrices. Hash-Table and SKS matrices can find element in O(1)
1188 : time, while CRS matrices need O(log(RS)) time, where RS is an number of
1189 : non-zero elements in a row.
1190 :
1191 : INPUT PARAMETERS
1192 : S - sparse M*N matrix
1193 : I - row index of the element to modify, 0<=I<M
1194 : J - column index of the element to modify, 0<=J<N
1195 :
1196 : RESULT
1197 : value of S[I,J] or zero (in case no element with such index is found)
1198 :
1199 : -- ALGLIB PROJECT --
1200 : Copyright 14.10.2011 by Bochkanov Sergey
1201 : *************************************************************************/
1202 0 : double sparseget(const sparsematrix &s, const ae_int_t i, const ae_int_t j, const xparams _xparams)
1203 : {
1204 : jmp_buf _break_jump;
1205 : alglib_impl::ae_state _alglib_env_state;
1206 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1207 0 : if( setjmp(_break_jump) )
1208 : {
1209 : #if !defined(AE_NO_EXCEPTIONS)
1210 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1211 : #else
1212 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1213 : return 0;
1214 : #endif
1215 : }
1216 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1217 0 : if( _xparams.flags!=0x0 )
1218 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1219 0 : double result = alglib_impl::sparseget(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), i, j, &_alglib_env_state);
1220 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1221 0 : return *(reinterpret_cast<double*>(&result));
1222 : }
1223 :
1224 : /*************************************************************************
1225 : This function checks whether S[i,j] is present in the sparse matrix. It
1226 : returns True even for elements that are numerically zero (but still
1227 : have place allocated for them).
1228 :
1229 : The matrix can be in any mode (Hash-Table, CRS, SKS), but this function
1230 : is less efficient for CRS matrices. Hash-Table and SKS matrices can find
1231 : element in O(1) time, while CRS matrices need O(log(RS)) time, where RS
1232 : is an number of non-zero elements in a row.
1233 :
1234 : INPUT PARAMETERS
1235 : S - sparse M*N matrix
1236 : I - row index of the element to modify, 0<=I<M
1237 : J - column index of the element to modify, 0<=J<N
1238 :
1239 : RESULT
1240 : whether S[I,J] is present in the data structure or not
1241 :
1242 : -- ALGLIB PROJECT --
1243 : Copyright 14.10.2020 by Bochkanov Sergey
1244 : *************************************************************************/
1245 0 : bool sparseexists(const sparsematrix &s, const ae_int_t i, const ae_int_t j, const xparams _xparams)
1246 : {
1247 : jmp_buf _break_jump;
1248 : alglib_impl::ae_state _alglib_env_state;
1249 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1250 0 : if( setjmp(_break_jump) )
1251 : {
1252 : #if !defined(AE_NO_EXCEPTIONS)
1253 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1254 : #else
1255 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1256 : return 0;
1257 : #endif
1258 : }
1259 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1260 0 : if( _xparams.flags!=0x0 )
1261 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1262 0 : ae_bool result = alglib_impl::sparseexists(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), i, j, &_alglib_env_state);
1263 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1264 0 : return *(reinterpret_cast<bool*>(&result));
1265 : }
1266 :
1267 : /*************************************************************************
1268 : This function returns I-th diagonal element of the sparse matrix.
1269 :
1270 : Matrix can be in any mode (Hash-Table or CRS storage), but this function
1271 : is most efficient for CRS matrices - it requires less than 50 CPU cycles
1272 : to extract diagonal element. For Hash-Table matrices we still have O(1)
1273 : query time, but function is many times slower.
1274 :
1275 : INPUT PARAMETERS
1276 : S - sparse M*N matrix in Hash-Table representation.
1277 : Exception will be thrown for CRS matrix.
1278 : I - index of the element to modify, 0<=I<min(M,N)
1279 :
1280 : RESULT
1281 : value of S[I,I] or zero (in case no element with such index is found)
1282 :
1283 : -- ALGLIB PROJECT --
1284 : Copyright 14.10.2011 by Bochkanov Sergey
1285 : *************************************************************************/
1286 0 : double sparsegetdiagonal(const sparsematrix &s, const ae_int_t i, const xparams _xparams)
1287 : {
1288 : jmp_buf _break_jump;
1289 : alglib_impl::ae_state _alglib_env_state;
1290 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1291 0 : if( setjmp(_break_jump) )
1292 : {
1293 : #if !defined(AE_NO_EXCEPTIONS)
1294 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1295 : #else
1296 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1297 : return 0;
1298 : #endif
1299 : }
1300 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1301 0 : if( _xparams.flags!=0x0 )
1302 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1303 0 : double result = alglib_impl::sparsegetdiagonal(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), i, &_alglib_env_state);
1304 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1305 0 : return *(reinterpret_cast<double*>(&result));
1306 : }
1307 :
1308 : /*************************************************************************
1309 : This function calculates matrix-vector product S*x. Matrix S must be
1310 : stored in CRS or SKS format (exception will be thrown otherwise).
1311 :
1312 : INPUT PARAMETERS
1313 : S - sparse M*N matrix in CRS or SKS format.
1314 : X - array[N], input vector. For performance reasons we
1315 : make only quick checks - we check that array size is
1316 : at least N, but we do not check for NAN's or INF's.
1317 : Y - output buffer, possibly preallocated. In case buffer
1318 : size is too small to store result, this buffer is
1319 : automatically resized.
1320 :
1321 : OUTPUT PARAMETERS
1322 : Y - array[M], S*x
1323 :
1324 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
1325 : You must convert your matrix with SparseConvertToCRS/SKS() before using
1326 : this function.
1327 :
1328 : -- ALGLIB PROJECT --
1329 : Copyright 14.10.2011 by Bochkanov Sergey
1330 : *************************************************************************/
1331 0 : void sparsemv(const sparsematrix &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams)
1332 : {
1333 : jmp_buf _break_jump;
1334 : alglib_impl::ae_state _alglib_env_state;
1335 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1336 0 : if( setjmp(_break_jump) )
1337 : {
1338 : #if !defined(AE_NO_EXCEPTIONS)
1339 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1340 : #else
1341 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1342 : return;
1343 : #endif
1344 : }
1345 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1346 0 : if( _xparams.flags!=0x0 )
1347 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1348 0 : alglib_impl::sparsemv(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
1349 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1350 0 : return;
1351 : }
1352 :
1353 : /*************************************************************************
1354 : This function calculates matrix-vector product S^T*x. Matrix S must be
1355 : stored in CRS or SKS format (exception will be thrown otherwise).
1356 :
1357 : INPUT PARAMETERS
1358 : S - sparse M*N matrix in CRS or SKS format.
1359 : X - array[M], input vector. For performance reasons we
1360 : make only quick checks - we check that array size is
1361 : at least M, but we do not check for NAN's or INF's.
1362 : Y - output buffer, possibly preallocated. In case buffer
1363 : size is too small to store result, this buffer is
1364 : automatically resized.
1365 :
1366 : OUTPUT PARAMETERS
1367 : Y - array[N], S^T*x
1368 :
1369 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
1370 : You must convert your matrix with SparseConvertToCRS/SKS() before using
1371 : this function.
1372 :
1373 : -- ALGLIB PROJECT --
1374 : Copyright 14.10.2011 by Bochkanov Sergey
1375 : *************************************************************************/
1376 0 : void sparsemtv(const sparsematrix &s, const real_1d_array &x, real_1d_array &y, const xparams _xparams)
1377 : {
1378 : jmp_buf _break_jump;
1379 : alglib_impl::ae_state _alglib_env_state;
1380 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1381 0 : if( setjmp(_break_jump) )
1382 : {
1383 : #if !defined(AE_NO_EXCEPTIONS)
1384 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1385 : #else
1386 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1387 : return;
1388 : #endif
1389 : }
1390 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1391 0 : if( _xparams.flags!=0x0 )
1392 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1393 0 : alglib_impl::sparsemtv(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
1394 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1395 0 : return;
1396 : }
1397 :
1398 : /*************************************************************************
1399 : This function calculates generalized sparse matrix-vector product
1400 :
1401 : y := alpha*op(S)*x + beta*y
1402 :
1403 : Matrix S must be stored in CRS or SKS format (exception will be thrown
1404 : otherwise). op(S) can be either S or S^T.
1405 :
1406 : NOTE: this function expects Y to be large enough to store result. No
1407 : automatic preallocation happens for smaller arrays.
1408 :
1409 : INPUT PARAMETERS
1410 : S - sparse matrix in CRS or SKS format.
1411 : Alpha - source coefficient
1412 : OpS - operation type:
1413 : * OpS=0 => op(S) = S
1414 : * OpS=1 => op(S) = S^T
1415 : X - input vector, must have at least Cols(op(S))+IX elements
1416 : IX - subvector offset
1417 : Beta - destination coefficient
1418 : Y - preallocated output array, must have at least Rows(op(S))+IY elements
1419 : IY - subvector offset
1420 :
1421 : OUTPUT PARAMETERS
1422 : Y - elements [IY...IY+Rows(op(S))-1] are replaced by result,
1423 : other elements are not modified
1424 :
1425 : HANDLING OF SPECIAL CASES:
1426 : * below M=Rows(op(S)) and N=Cols(op(S)). Although current ALGLIB version
1427 : does not allow you to create zero-sized sparse matrices, internally
1428 : ALGLIB can deal with such matrices. So, comments for M or N equal to
1429 : zero are for internal use only.
1430 : * if M=0, then subroutine does nothing. It does not even touch arrays.
1431 : * if N=0 or Alpha=0.0, then:
1432 : * if Beta=0, then Y is filled by zeros. S and X are not referenced at
1433 : all. Initial values of Y are ignored (we do not multiply Y by zero,
1434 : we just rewrite it by zeros)
1435 : * if Beta<>0, then Y is replaced by Beta*Y
1436 : * if M>0, N>0, Alpha<>0, but Beta=0, then Y is replaced by alpha*op(S)*x
1437 : initial state of Y is ignored (rewritten without initial multiplication
1438 : by zeros).
1439 :
1440 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
1441 : You must convert your matrix with SparseConvertToCRS/SKS() before using
1442 : this function.
1443 :
1444 : -- ALGLIB PROJECT --
1445 : Copyright 10.12.2019 by Bochkanov Sergey
1446 : *************************************************************************/
1447 0 : void sparsegemv(const sparsematrix &s, const double alpha, const ae_int_t ops, const real_1d_array &x, const ae_int_t ix, const double beta, const real_1d_array &y, const ae_int_t iy, const xparams _xparams)
1448 : {
1449 : jmp_buf _break_jump;
1450 : alglib_impl::ae_state _alglib_env_state;
1451 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1452 0 : if( setjmp(_break_jump) )
1453 : {
1454 : #if !defined(AE_NO_EXCEPTIONS)
1455 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1456 : #else
1457 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1458 : return;
1459 : #endif
1460 : }
1461 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1462 0 : if( _xparams.flags!=0x0 )
1463 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1464 0 : alglib_impl::sparsegemv(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), alpha, ops, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), ix, beta, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), iy, &_alglib_env_state);
1465 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1466 0 : return;
1467 : }
1468 :
1469 : /*************************************************************************
1470 : This function simultaneously calculates two matrix-vector products:
1471 : S*x and S^T*x.
1472 : S must be square (non-rectangular) matrix stored in CRS or SKS format
1473 : (exception will be thrown otherwise).
1474 :
1475 : INPUT PARAMETERS
1476 : S - sparse N*N matrix in CRS or SKS format.
1477 : X - array[N], input vector. For performance reasons we
1478 : make only quick checks - we check that array size is
1479 : at least N, but we do not check for NAN's or INF's.
1480 : Y0 - output buffer, possibly preallocated. In case buffer
1481 : size is too small to store result, this buffer is
1482 : automatically resized.
1483 : Y1 - output buffer, possibly preallocated. In case buffer
1484 : size is too small to store result, this buffer is
1485 : automatically resized.
1486 :
1487 : OUTPUT PARAMETERS
1488 : Y0 - array[N], S*x
1489 : Y1 - array[N], S^T*x
1490 :
1491 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
1492 : You must convert your matrix with SparseConvertToCRS/SKS() before using
1493 : this function.
1494 :
1495 : -- ALGLIB PROJECT --
1496 : Copyright 14.10.2011 by Bochkanov Sergey
1497 : *************************************************************************/
1498 0 : void sparsemv2(const sparsematrix &s, const real_1d_array &x, real_1d_array &y0, real_1d_array &y1, const xparams _xparams)
1499 : {
1500 : jmp_buf _break_jump;
1501 : alglib_impl::ae_state _alglib_env_state;
1502 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1503 0 : if( setjmp(_break_jump) )
1504 : {
1505 : #if !defined(AE_NO_EXCEPTIONS)
1506 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1507 : #else
1508 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1509 : return;
1510 : #endif
1511 : }
1512 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1513 0 : if( _xparams.flags!=0x0 )
1514 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1515 0 : alglib_impl::sparsemv2(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y0.c_ptr()), const_cast<alglib_impl::ae_vector*>(y1.c_ptr()), &_alglib_env_state);
1516 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1517 0 : return;
1518 : }
1519 :
1520 : /*************************************************************************
1521 : This function calculates matrix-vector product S*x, when S is symmetric
1522 : matrix. Matrix S must be stored in CRS or SKS format (exception will be
1523 : thrown otherwise).
1524 :
1525 : INPUT PARAMETERS
1526 : S - sparse M*M matrix in CRS or SKS format.
1527 : IsUpper - whether upper or lower triangle of S is given:
1528 : * if upper triangle is given, only S[i,j] for j>=i
1529 : are used, and lower triangle is ignored (it can be
1530 : empty - these elements are not referenced at all).
1531 : * if lower triangle is given, only S[i,j] for j<=i
1532 : are used, and upper triangle is ignored.
1533 : X - array[N], input vector. For performance reasons we
1534 : make only quick checks - we check that array size is
1535 : at least N, but we do not check for NAN's or INF's.
1536 : Y - output buffer, possibly preallocated. In case buffer
1537 : size is too small to store result, this buffer is
1538 : automatically resized.
1539 :
1540 : OUTPUT PARAMETERS
1541 : Y - array[M], S*x
1542 :
1543 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
1544 : You must convert your matrix with SparseConvertToCRS/SKS() before using
1545 : this function.
1546 :
1547 : -- ALGLIB PROJECT --
1548 : Copyright 14.10.2011 by Bochkanov Sergey
1549 : *************************************************************************/
1550 0 : void sparsesmv(const sparsematrix &s, const bool isupper, const real_1d_array &x, real_1d_array &y, const xparams _xparams)
1551 : {
1552 : jmp_buf _break_jump;
1553 : alglib_impl::ae_state _alglib_env_state;
1554 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1555 0 : if( setjmp(_break_jump) )
1556 : {
1557 : #if !defined(AE_NO_EXCEPTIONS)
1558 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1559 : #else
1560 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1561 : return;
1562 : #endif
1563 : }
1564 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1565 0 : if( _xparams.flags!=0x0 )
1566 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1567 0 : alglib_impl::sparsesmv(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), isupper, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
1568 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1569 0 : return;
1570 : }
1571 :
1572 : /*************************************************************************
1573 : This function calculates vector-matrix-vector product x'*S*x, where S is
1574 : symmetric matrix. Matrix S must be stored in CRS or SKS format (exception
1575 : will be thrown otherwise).
1576 :
1577 : INPUT PARAMETERS
1578 : S - sparse M*M matrix in CRS or SKS format.
1579 : IsUpper - whether upper or lower triangle of S is given:
1580 : * if upper triangle is given, only S[i,j] for j>=i
1581 : are used, and lower triangle is ignored (it can be
1582 : empty - these elements are not referenced at all).
1583 : * if lower triangle is given, only S[i,j] for j<=i
1584 : are used, and upper triangle is ignored.
1585 : X - array[N], input vector. For performance reasons we
1586 : make only quick checks - we check that array size is
1587 : at least N, but we do not check for NAN's or INF's.
1588 :
1589 : RESULT
1590 : x'*S*x
1591 :
1592 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
1593 : You must convert your matrix with SparseConvertToCRS/SKS() before using
1594 : this function.
1595 :
1596 : -- ALGLIB PROJECT --
1597 : Copyright 27.01.2014 by Bochkanov Sergey
1598 : *************************************************************************/
1599 0 : double sparsevsmv(const sparsematrix &s, const bool isupper, const real_1d_array &x, const xparams _xparams)
1600 : {
1601 : jmp_buf _break_jump;
1602 : alglib_impl::ae_state _alglib_env_state;
1603 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1604 0 : if( setjmp(_break_jump) )
1605 : {
1606 : #if !defined(AE_NO_EXCEPTIONS)
1607 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1608 : #else
1609 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1610 : return 0;
1611 : #endif
1612 : }
1613 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1614 0 : if( _xparams.flags!=0x0 )
1615 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1616 0 : double result = alglib_impl::sparsevsmv(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), isupper, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
1617 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1618 0 : return *(reinterpret_cast<double*>(&result));
1619 : }
1620 :
1621 : /*************************************************************************
1622 : This function calculates matrix-matrix product S*A. Matrix S must be
1623 : stored in CRS or SKS format (exception will be thrown otherwise).
1624 :
1625 : INPUT PARAMETERS
1626 : S - sparse M*N matrix in CRS or SKS format.
1627 : A - array[N][K], input dense matrix. For performance reasons
1628 : we make only quick checks - we check that array size
1629 : is at least N, but we do not check for NAN's or INF's.
1630 : K - number of columns of matrix (A).
1631 : B - output buffer, possibly preallocated. In case buffer
1632 : size is too small to store result, this buffer is
1633 : automatically resized.
1634 :
1635 : OUTPUT PARAMETERS
1636 : B - array[M][K], S*A
1637 :
1638 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
1639 : You must convert your matrix with SparseConvertToCRS/SKS() before using
1640 : this function.
1641 :
1642 : -- ALGLIB PROJECT --
1643 : Copyright 14.10.2011 by Bochkanov Sergey
1644 : *************************************************************************/
1645 0 : void sparsemm(const sparsematrix &s, const real_2d_array &a, const ae_int_t k, real_2d_array &b, const xparams _xparams)
1646 : {
1647 : jmp_buf _break_jump;
1648 : alglib_impl::ae_state _alglib_env_state;
1649 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1650 0 : if( setjmp(_break_jump) )
1651 : {
1652 : #if !defined(AE_NO_EXCEPTIONS)
1653 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1654 : #else
1655 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1656 : return;
1657 : #endif
1658 : }
1659 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1660 0 : if( _xparams.flags!=0x0 )
1661 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1662 0 : alglib_impl::sparsemm(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), k, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), &_alglib_env_state);
1663 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1664 0 : return;
1665 : }
1666 :
1667 : /*************************************************************************
1668 : This function calculates matrix-matrix product S^T*A. Matrix S must be
1669 : stored in CRS or SKS format (exception will be thrown otherwise).
1670 :
1671 : INPUT PARAMETERS
1672 : S - sparse M*N matrix in CRS or SKS format.
1673 : A - array[M][K], input dense matrix. For performance reasons
1674 : we make only quick checks - we check that array size is
1675 : at least M, but we do not check for NAN's or INF's.
1676 : K - number of columns of matrix (A).
1677 : B - output buffer, possibly preallocated. In case buffer
1678 : size is too small to store result, this buffer is
1679 : automatically resized.
1680 :
1681 : OUTPUT PARAMETERS
1682 : B - array[N][K], S^T*A
1683 :
1684 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
1685 : You must convert your matrix with SparseConvertToCRS/SKS() before using
1686 : this function.
1687 :
1688 : -- ALGLIB PROJECT --
1689 : Copyright 14.10.2011 by Bochkanov Sergey
1690 : *************************************************************************/
1691 0 : void sparsemtm(const sparsematrix &s, const real_2d_array &a, const ae_int_t k, real_2d_array &b, const xparams _xparams)
1692 : {
1693 : jmp_buf _break_jump;
1694 : alglib_impl::ae_state _alglib_env_state;
1695 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1696 0 : if( setjmp(_break_jump) )
1697 : {
1698 : #if !defined(AE_NO_EXCEPTIONS)
1699 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1700 : #else
1701 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1702 : return;
1703 : #endif
1704 : }
1705 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1706 0 : if( _xparams.flags!=0x0 )
1707 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1708 0 : alglib_impl::sparsemtm(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), k, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), &_alglib_env_state);
1709 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1710 0 : return;
1711 : }
1712 :
1713 : /*************************************************************************
1714 : This function simultaneously calculates two matrix-matrix products:
1715 : S*A and S^T*A.
1716 : S must be square (non-rectangular) matrix stored in CRS or SKS format
1717 : (exception will be thrown otherwise).
1718 :
1719 : INPUT PARAMETERS
1720 : S - sparse N*N matrix in CRS or SKS format.
1721 : A - array[N][K], input dense matrix. For performance reasons
1722 : we make only quick checks - we check that array size is
1723 : at least N, but we do not check for NAN's or INF's.
1724 : K - number of columns of matrix (A).
1725 : B0 - output buffer, possibly preallocated. In case buffer
1726 : size is too small to store result, this buffer is
1727 : automatically resized.
1728 : B1 - output buffer, possibly preallocated. In case buffer
1729 : size is too small to store result, this buffer is
1730 : automatically resized.
1731 :
1732 : OUTPUT PARAMETERS
1733 : B0 - array[N][K], S*A
1734 : B1 - array[N][K], S^T*A
1735 :
1736 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
1737 : You must convert your matrix with SparseConvertToCRS/SKS() before using
1738 : this function.
1739 :
1740 : -- ALGLIB PROJECT --
1741 : Copyright 14.10.2011 by Bochkanov Sergey
1742 : *************************************************************************/
1743 0 : void sparsemm2(const sparsematrix &s, const real_2d_array &a, const ae_int_t k, real_2d_array &b0, real_2d_array &b1, const xparams _xparams)
1744 : {
1745 : jmp_buf _break_jump;
1746 : alglib_impl::ae_state _alglib_env_state;
1747 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1748 0 : if( setjmp(_break_jump) )
1749 : {
1750 : #if !defined(AE_NO_EXCEPTIONS)
1751 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1752 : #else
1753 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1754 : return;
1755 : #endif
1756 : }
1757 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1758 0 : if( _xparams.flags!=0x0 )
1759 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1760 0 : alglib_impl::sparsemm2(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), k, const_cast<alglib_impl::ae_matrix*>(b0.c_ptr()), const_cast<alglib_impl::ae_matrix*>(b1.c_ptr()), &_alglib_env_state);
1761 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1762 0 : return;
1763 : }
1764 :
1765 : /*************************************************************************
1766 : This function calculates matrix-matrix product S*A, when S is symmetric
1767 : matrix. Matrix S must be stored in CRS or SKS format (exception will be
1768 : thrown otherwise).
1769 :
1770 : INPUT PARAMETERS
1771 : S - sparse M*M matrix in CRS or SKS format.
1772 : IsUpper - whether upper or lower triangle of S is given:
1773 : * if upper triangle is given, only S[i,j] for j>=i
1774 : are used, and lower triangle is ignored (it can be
1775 : empty - these elements are not referenced at all).
1776 : * if lower triangle is given, only S[i,j] for j<=i
1777 : are used, and upper triangle is ignored.
1778 : A - array[N][K], input dense matrix. For performance reasons
1779 : we make only quick checks - we check that array size is
1780 : at least N, but we do not check for NAN's or INF's.
1781 : K - number of columns of matrix (A).
1782 : B - output buffer, possibly preallocated. In case buffer
1783 : size is too small to store result, this buffer is
1784 : automatically resized.
1785 :
1786 : OUTPUT PARAMETERS
1787 : B - array[M][K], S*A
1788 :
1789 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
1790 : You must convert your matrix with SparseConvertToCRS/SKS() before using
1791 : this function.
1792 :
1793 : -- ALGLIB PROJECT --
1794 : Copyright 14.10.2011 by Bochkanov Sergey
1795 : *************************************************************************/
1796 0 : void sparsesmm(const sparsematrix &s, const bool isupper, const real_2d_array &a, const ae_int_t k, real_2d_array &b, const xparams _xparams)
1797 : {
1798 : jmp_buf _break_jump;
1799 : alglib_impl::ae_state _alglib_env_state;
1800 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1801 0 : if( setjmp(_break_jump) )
1802 : {
1803 : #if !defined(AE_NO_EXCEPTIONS)
1804 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1805 : #else
1806 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1807 : return;
1808 : #endif
1809 : }
1810 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1811 0 : if( _xparams.flags!=0x0 )
1812 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1813 0 : alglib_impl::sparsesmm(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), isupper, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), k, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), &_alglib_env_state);
1814 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1815 0 : return;
1816 : }
1817 :
1818 : /*************************************************************************
1819 : This function calculates matrix-vector product op(S)*x, when x is vector,
1820 : S is symmetric triangular matrix, op(S) is transposition or no operation.
1821 : Matrix S must be stored in CRS or SKS format (exception will be thrown
1822 : otherwise).
1823 :
1824 : INPUT PARAMETERS
1825 : S - sparse square matrix in CRS or SKS format.
1826 : IsUpper - whether upper or lower triangle of S is used:
1827 : * if upper triangle is given, only S[i,j] for j>=i
1828 : are used, and lower triangle is ignored (it can be
1829 : empty - these elements are not referenced at all).
1830 : * if lower triangle is given, only S[i,j] for j<=i
1831 : are used, and upper triangle is ignored.
1832 : IsUnit - unit or non-unit diagonal:
1833 : * if True, diagonal elements of triangular matrix are
1834 : considered equal to 1.0. Actual elements stored in
1835 : S are not referenced at all.
1836 : * if False, diagonal stored in S is used
1837 : OpType - operation type:
1838 : * if 0, S*x is calculated
1839 : * if 1, (S^T)*x is calculated (transposition)
1840 : X - array[N] which stores input vector. For performance
1841 : reasons we make only quick checks - we check that
1842 : array size is at least N, but we do not check for
1843 : NAN's or INF's.
1844 : Y - possibly preallocated input buffer. Automatically
1845 : resized if its size is too small.
1846 :
1847 : OUTPUT PARAMETERS
1848 : Y - array[N], op(S)*x
1849 :
1850 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
1851 : You must convert your matrix with SparseConvertToCRS/SKS() before using
1852 : this function.
1853 :
1854 : -- ALGLIB PROJECT --
1855 : Copyright 20.01.2014 by Bochkanov Sergey
1856 : *************************************************************************/
1857 0 : void sparsetrmv(const sparsematrix &s, const bool isupper, const bool isunit, const ae_int_t optype, const real_1d_array &x, real_1d_array &y, const xparams _xparams)
1858 : {
1859 : jmp_buf _break_jump;
1860 : alglib_impl::ae_state _alglib_env_state;
1861 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1862 0 : if( setjmp(_break_jump) )
1863 : {
1864 : #if !defined(AE_NO_EXCEPTIONS)
1865 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1866 : #else
1867 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1868 : return;
1869 : #endif
1870 : }
1871 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1872 0 : if( _xparams.flags!=0x0 )
1873 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1874 0 : alglib_impl::sparsetrmv(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), isupper, isunit, optype, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::ae_vector*>(y.c_ptr()), &_alglib_env_state);
1875 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1876 0 : return;
1877 : }
1878 :
1879 : /*************************************************************************
1880 : This function solves linear system op(S)*y=x where x is vector, S is
1881 : symmetric triangular matrix, op(S) is transposition or no operation.
1882 : Matrix S must be stored in CRS or SKS format (exception will be thrown
1883 : otherwise).
1884 :
1885 : INPUT PARAMETERS
1886 : S - sparse square matrix in CRS or SKS format.
1887 : IsUpper - whether upper or lower triangle of S is used:
1888 : * if upper triangle is given, only S[i,j] for j>=i
1889 : are used, and lower triangle is ignored (it can be
1890 : empty - these elements are not referenced at all).
1891 : * if lower triangle is given, only S[i,j] for j<=i
1892 : are used, and upper triangle is ignored.
1893 : IsUnit - unit or non-unit diagonal:
1894 : * if True, diagonal elements of triangular matrix are
1895 : considered equal to 1.0. Actual elements stored in
1896 : S are not referenced at all.
1897 : * if False, diagonal stored in S is used. It is your
1898 : responsibility to make sure that diagonal is
1899 : non-zero.
1900 : OpType - operation type:
1901 : * if 0, S*x is calculated
1902 : * if 1, (S^T)*x is calculated (transposition)
1903 : X - array[N] which stores input vector. For performance
1904 : reasons we make only quick checks - we check that
1905 : array size is at least N, but we do not check for
1906 : NAN's or INF's.
1907 :
1908 : OUTPUT PARAMETERS
1909 : X - array[N], inv(op(S))*x
1910 :
1911 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
1912 : You must convert your matrix with SparseConvertToCRS/SKS() before
1913 : using this function.
1914 :
1915 : NOTE: no assertion or tests are done during algorithm operation. It is
1916 : your responsibility to provide invertible matrix to algorithm.
1917 :
1918 : -- ALGLIB PROJECT --
1919 : Copyright 20.01.2014 by Bochkanov Sergey
1920 : *************************************************************************/
1921 0 : void sparsetrsv(const sparsematrix &s, const bool isupper, const bool isunit, const ae_int_t optype, const real_1d_array &x, const xparams _xparams)
1922 : {
1923 : jmp_buf _break_jump;
1924 : alglib_impl::ae_state _alglib_env_state;
1925 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1926 0 : if( setjmp(_break_jump) )
1927 : {
1928 : #if !defined(AE_NO_EXCEPTIONS)
1929 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1930 : #else
1931 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1932 : return;
1933 : #endif
1934 : }
1935 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1936 0 : if( _xparams.flags!=0x0 )
1937 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1938 0 : alglib_impl::sparsetrsv(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), isupper, isunit, optype, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
1939 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1940 0 : return;
1941 : }
1942 :
1943 : /*************************************************************************
1944 : This function applies permutation given by permutation table P (as opposed
1945 : to product form of permutation) to sparse symmetric matrix A, given by
1946 : either upper or lower triangle: B := P*A*P'.
1947 :
1948 : This function allocates completely new instance of B. Use buffered version
1949 : SparseSymmPermTblBuf() if you want to reuse already allocated structure.
1950 :
1951 : INPUT PARAMETERS
1952 : A - sparse square matrix in CRS format.
1953 : IsUpper - whether upper or lower triangle of A is used:
1954 : * if upper triangle is given, only A[i,j] for j>=i
1955 : are used, and lower triangle is ignored (it can be
1956 : empty - these elements are not referenced at all).
1957 : * if lower triangle is given, only A[i,j] for j<=i
1958 : are used, and upper triangle is ignored.
1959 : P - array[N] which stores permutation table; P[I]=J means
1960 : that I-th row/column of matrix A is moved to J-th
1961 : position. For performance reasons we do NOT check that
1962 : P[] is a correct permutation (that there is no
1963 : repetitions, just that all its elements are in [0,N)
1964 : range.
1965 :
1966 : OUTPUT PARAMETERS
1967 : B - permuted matrix. Permutation is applied to A from
1968 : the both sides, only upper or lower triangle (depending
1969 : on IsUpper) is stored.
1970 :
1971 : NOTE: this function throws exception when called for non-CRS matrix. You
1972 : must convert your matrix with SparseConvertToCRS() before using this
1973 : function.
1974 :
1975 : -- ALGLIB PROJECT --
1976 : Copyright 05.10.2020 by Bochkanov Sergey.
1977 : *************************************************************************/
1978 0 : void sparsesymmpermtbl(const sparsematrix &a, const bool isupper, const integer_1d_array &p, sparsematrix &b, const xparams _xparams)
1979 : {
1980 : jmp_buf _break_jump;
1981 : alglib_impl::ae_state _alglib_env_state;
1982 0 : alglib_impl::ae_state_init(&_alglib_env_state);
1983 0 : if( setjmp(_break_jump) )
1984 : {
1985 : #if !defined(AE_NO_EXCEPTIONS)
1986 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
1987 : #else
1988 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
1989 : return;
1990 : #endif
1991 : }
1992 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
1993 0 : if( _xparams.flags!=0x0 )
1994 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
1995 0 : alglib_impl::sparsesymmpermtbl(const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), isupper, const_cast<alglib_impl::ae_vector*>(p.c_ptr()), const_cast<alglib_impl::sparsematrix*>(b.c_ptr()), &_alglib_env_state);
1996 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
1997 0 : return;
1998 : }
1999 :
2000 : /*************************************************************************
2001 : This function is a buffered version of SparseSymmPermTbl() that reuses
2002 : previously allocated storage in B as much as possible.
2003 :
2004 : This function applies permutation given by permutation table P (as opposed
2005 : to product form of permutation) to sparse symmetric matrix A, given by
2006 : either upper or lower triangle: B := P*A*P'.
2007 :
2008 : INPUT PARAMETERS
2009 : A - sparse square matrix in CRS format.
2010 : IsUpper - whether upper or lower triangle of A is used:
2011 : * if upper triangle is given, only A[i,j] for j>=i
2012 : are used, and lower triangle is ignored (it can be
2013 : empty - these elements are not referenced at all).
2014 : * if lower triangle is given, only A[i,j] for j<=i
2015 : are used, and upper triangle is ignored.
2016 : P - array[N] which stores permutation table; P[I]=J means
2017 : that I-th row/column of matrix A is moved to J-th
2018 : position. For performance reasons we do NOT check that
2019 : P[] is a correct permutation (that there is no
2020 : repetitions, just that all its elements are in [0,N)
2021 : range.
2022 : B - sparse matrix object that will hold output.
2023 : Previously allocated memory will be reused as much as
2024 : possible.
2025 :
2026 : OUTPUT PARAMETERS
2027 : B - permuted matrix. Permutation is applied to A from
2028 : the both sides, only upper or lower triangle (depending
2029 : on IsUpper) is stored.
2030 :
2031 : NOTE: this function throws exception when called for non-CRS matrix. You
2032 : must convert your matrix with SparseConvertToCRS() before using this
2033 : function.
2034 :
2035 : -- ALGLIB PROJECT --
2036 : Copyright 05.10.2020 by Bochkanov Sergey.
2037 : *************************************************************************/
2038 0 : void sparsesymmpermtblbuf(const sparsematrix &a, const bool isupper, const integer_1d_array &p, const sparsematrix &b, const xparams _xparams)
2039 : {
2040 : jmp_buf _break_jump;
2041 : alglib_impl::ae_state _alglib_env_state;
2042 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2043 0 : if( setjmp(_break_jump) )
2044 : {
2045 : #if !defined(AE_NO_EXCEPTIONS)
2046 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2047 : #else
2048 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2049 : return;
2050 : #endif
2051 : }
2052 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2053 0 : if( _xparams.flags!=0x0 )
2054 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2055 0 : alglib_impl::sparsesymmpermtblbuf(const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), isupper, const_cast<alglib_impl::ae_vector*>(p.c_ptr()), const_cast<alglib_impl::sparsematrix*>(b.c_ptr()), &_alglib_env_state);
2056 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2057 0 : return;
2058 : }
2059 :
2060 : /*************************************************************************
2061 : This procedure resizes Hash-Table matrix. It can be called when you have
2062 : deleted too many elements from the matrix, and you want to free unneeded
2063 : memory.
2064 :
2065 : -- ALGLIB PROJECT --
2066 : Copyright 14.10.2011 by Bochkanov Sergey
2067 : *************************************************************************/
2068 0 : void sparseresizematrix(const sparsematrix &s, const xparams _xparams)
2069 : {
2070 : jmp_buf _break_jump;
2071 : alglib_impl::ae_state _alglib_env_state;
2072 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2073 0 : if( setjmp(_break_jump) )
2074 : {
2075 : #if !defined(AE_NO_EXCEPTIONS)
2076 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2077 : #else
2078 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2079 : return;
2080 : #endif
2081 : }
2082 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2083 0 : if( _xparams.flags!=0x0 )
2084 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2085 0 : alglib_impl::sparseresizematrix(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
2086 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2087 0 : return;
2088 : }
2089 :
2090 : /*************************************************************************
2091 : This function is used to enumerate all elements of the sparse matrix.
2092 : Before first call user initializes T0 and T1 counters by zero. These
2093 : counters are used to remember current position in a matrix; after each
2094 : call they are updated by the function.
2095 :
2096 : Subsequent calls to this function return non-zero elements of the sparse
2097 : matrix, one by one. If you enumerate CRS matrix, matrix is traversed from
2098 : left to right, from top to bottom. In case you enumerate matrix stored as
2099 : Hash table, elements are returned in random order.
2100 :
2101 : EXAMPLE
2102 : > T0=0
2103 : > T1=0
2104 : > while SparseEnumerate(S,T0,T1,I,J,V) do
2105 : > ....do something with I,J,V
2106 :
2107 : INPUT PARAMETERS
2108 : S - sparse M*N matrix in Hash-Table or CRS representation.
2109 : T0 - internal counter
2110 : T1 - internal counter
2111 :
2112 : OUTPUT PARAMETERS
2113 : T0 - new value of the internal counter
2114 : T1 - new value of the internal counter
2115 : I - row index of non-zero element, 0<=I<M.
2116 : J - column index of non-zero element, 0<=J<N
2117 : V - value of the T-th element
2118 :
2119 : RESULT
2120 : True in case of success (next non-zero element was retrieved)
2121 : False in case all non-zero elements were enumerated
2122 :
2123 : NOTE: you may call SparseRewriteExisting() during enumeration, but it is
2124 : THE ONLY matrix modification function you can call!!! Other
2125 : matrix modification functions should not be called during enumeration!
2126 :
2127 : -- ALGLIB PROJECT --
2128 : Copyright 14.03.2012 by Bochkanov Sergey
2129 : *************************************************************************/
2130 0 : bool sparseenumerate(const sparsematrix &s, ae_int_t &t0, ae_int_t &t1, ae_int_t &i, ae_int_t &j, double &v, const xparams _xparams)
2131 : {
2132 : jmp_buf _break_jump;
2133 : alglib_impl::ae_state _alglib_env_state;
2134 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2135 0 : if( setjmp(_break_jump) )
2136 : {
2137 : #if !defined(AE_NO_EXCEPTIONS)
2138 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2139 : #else
2140 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2141 : return 0;
2142 : #endif
2143 : }
2144 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2145 0 : if( _xparams.flags!=0x0 )
2146 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2147 0 : ae_bool result = alglib_impl::sparseenumerate(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &t0, &t1, &i, &j, &v, &_alglib_env_state);
2148 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2149 0 : return *(reinterpret_cast<bool*>(&result));
2150 : }
2151 :
2152 : /*************************************************************************
2153 : This function rewrites existing (non-zero) element. It returns True if
2154 : element exists or False, when it is called for non-existing (zero)
2155 : element.
2156 :
2157 : This function works with any kind of the matrix.
2158 :
2159 : The purpose of this function is to provide convenient thread-safe way to
2160 : modify sparse matrix. Such modification (already existing element is
2161 : rewritten) is guaranteed to be thread-safe without any synchronization, as
2162 : long as different threads modify different elements.
2163 :
2164 : INPUT PARAMETERS
2165 : S - sparse M*N matrix in any kind of representation
2166 : (Hash, SKS, CRS).
2167 : I - row index of non-zero element to modify, 0<=I<M
2168 : J - column index of non-zero element to modify, 0<=J<N
2169 : V - value to rewrite, must be finite number
2170 :
2171 : OUTPUT PARAMETERS
2172 : S - modified matrix
2173 : RESULT
2174 : True in case when element exists
2175 : False in case when element doesn't exist or it is zero
2176 :
2177 : -- ALGLIB PROJECT --
2178 : Copyright 14.03.2012 by Bochkanov Sergey
2179 : *************************************************************************/
2180 0 : bool sparserewriteexisting(const sparsematrix &s, const ae_int_t i, const ae_int_t j, const double v, const xparams _xparams)
2181 : {
2182 : jmp_buf _break_jump;
2183 : alglib_impl::ae_state _alglib_env_state;
2184 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2185 0 : if( setjmp(_break_jump) )
2186 : {
2187 : #if !defined(AE_NO_EXCEPTIONS)
2188 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2189 : #else
2190 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2191 : return 0;
2192 : #endif
2193 : }
2194 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2195 0 : if( _xparams.flags!=0x0 )
2196 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2197 0 : ae_bool result = alglib_impl::sparserewriteexisting(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), i, j, v, &_alglib_env_state);
2198 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2199 0 : return *(reinterpret_cast<bool*>(&result));
2200 : }
2201 :
2202 : /*************************************************************************
2203 : This function returns I-th row of the sparse matrix. Matrix must be stored
2204 : in CRS or SKS format.
2205 :
2206 : INPUT PARAMETERS:
2207 : S - sparse M*N matrix in CRS format
2208 : I - row index, 0<=I<M
2209 : IRow - output buffer, can be preallocated. In case buffer
2210 : size is too small to store I-th row, it is
2211 : automatically reallocated.
2212 :
2213 : OUTPUT PARAMETERS:
2214 : IRow - array[M], I-th row.
2215 :
2216 : NOTE: this function has O(N) running time, where N is a column count. It
2217 : allocates and fills N-element array, even although most of its
2218 : elemets are zero.
2219 :
2220 : NOTE: If you have O(non-zeros-per-row) time and memory requirements, use
2221 : SparseGetCompressedRow() function. It returns data in compressed
2222 : format.
2223 :
2224 : NOTE: when incorrect I (outside of [0,M-1]) or matrix (non CRS/SKS)
2225 : is passed, this function throws exception.
2226 :
2227 : -- ALGLIB PROJECT --
2228 : Copyright 10.12.2014 by Bochkanov Sergey
2229 : *************************************************************************/
2230 0 : void sparsegetrow(const sparsematrix &s, const ae_int_t i, real_1d_array &irow, const xparams _xparams)
2231 : {
2232 : jmp_buf _break_jump;
2233 : alglib_impl::ae_state _alglib_env_state;
2234 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2235 0 : if( setjmp(_break_jump) )
2236 : {
2237 : #if !defined(AE_NO_EXCEPTIONS)
2238 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2239 : #else
2240 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2241 : return;
2242 : #endif
2243 : }
2244 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2245 0 : if( _xparams.flags!=0x0 )
2246 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2247 0 : alglib_impl::sparsegetrow(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), i, const_cast<alglib_impl::ae_vector*>(irow.c_ptr()), &_alglib_env_state);
2248 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2249 0 : return;
2250 : }
2251 :
2252 : /*************************************************************************
2253 : This function returns I-th row of the sparse matrix IN COMPRESSED FORMAT -
2254 : only non-zero elements are returned (with their indexes). Matrix must be
2255 : stored in CRS or SKS format.
2256 :
2257 : INPUT PARAMETERS:
2258 : S - sparse M*N matrix in CRS format
2259 : I - row index, 0<=I<M
2260 : ColIdx - output buffer for column indexes, can be preallocated.
2261 : In case buffer size is too small to store I-th row, it
2262 : is automatically reallocated.
2263 : Vals - output buffer for values, can be preallocated. In case
2264 : buffer size is too small to store I-th row, it is
2265 : automatically reallocated.
2266 :
2267 : OUTPUT PARAMETERS:
2268 : ColIdx - column indexes of non-zero elements, sorted by
2269 : ascending. Symbolically non-zero elements are counted
2270 : (i.e. if you allocated place for element, but it has
2271 : zero numerical value - it is counted).
2272 : Vals - values. Vals[K] stores value of matrix element with
2273 : indexes (I,ColIdx[K]). Symbolically non-zero elements
2274 : are counted (i.e. if you allocated place for element,
2275 : but it has zero numerical value - it is counted).
2276 : NZCnt - number of symbolically non-zero elements per row.
2277 :
2278 : NOTE: when incorrect I (outside of [0,M-1]) or matrix (non CRS/SKS)
2279 : is passed, this function throws exception.
2280 :
2281 : NOTE: this function may allocate additional, unnecessary place for ColIdx
2282 : and Vals arrays. It is dictated by performance reasons - on SKS
2283 : matrices it is faster to allocate space at the beginning with
2284 : some "extra"-space, than performing two passes over matrix - first
2285 : time to calculate exact space required for data, second time - to
2286 : store data itself.
2287 :
2288 : -- ALGLIB PROJECT --
2289 : Copyright 10.12.2014 by Bochkanov Sergey
2290 : *************************************************************************/
2291 0 : void sparsegetcompressedrow(const sparsematrix &s, const ae_int_t i, integer_1d_array &colidx, real_1d_array &vals, ae_int_t &nzcnt, const xparams _xparams)
2292 : {
2293 : jmp_buf _break_jump;
2294 : alglib_impl::ae_state _alglib_env_state;
2295 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2296 0 : if( setjmp(_break_jump) )
2297 : {
2298 : #if !defined(AE_NO_EXCEPTIONS)
2299 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2300 : #else
2301 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2302 : return;
2303 : #endif
2304 : }
2305 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2306 0 : if( _xparams.flags!=0x0 )
2307 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2308 0 : alglib_impl::sparsegetcompressedrow(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), i, const_cast<alglib_impl::ae_vector*>(colidx.c_ptr()), const_cast<alglib_impl::ae_vector*>(vals.c_ptr()), &nzcnt, &_alglib_env_state);
2309 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2310 0 : return;
2311 : }
2312 :
2313 : /*************************************************************************
2314 : This function performs efficient in-place transpose of SKS matrix. No
2315 : additional memory is allocated during transposition.
2316 :
2317 : This function supports only skyline storage format (SKS).
2318 :
2319 : INPUT PARAMETERS
2320 : S - sparse matrix in SKS format.
2321 :
2322 : OUTPUT PARAMETERS
2323 : S - sparse matrix, transposed.
2324 :
2325 : -- ALGLIB PROJECT --
2326 : Copyright 16.01.2014 by Bochkanov Sergey
2327 : *************************************************************************/
2328 0 : void sparsetransposesks(const sparsematrix &s, const xparams _xparams)
2329 : {
2330 : jmp_buf _break_jump;
2331 : alglib_impl::ae_state _alglib_env_state;
2332 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2333 0 : if( setjmp(_break_jump) )
2334 : {
2335 : #if !defined(AE_NO_EXCEPTIONS)
2336 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2337 : #else
2338 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2339 : return;
2340 : #endif
2341 : }
2342 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2343 0 : if( _xparams.flags!=0x0 )
2344 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2345 0 : alglib_impl::sparsetransposesks(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
2346 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2347 0 : return;
2348 : }
2349 :
2350 : /*************************************************************************
2351 : This function performs transpose of CRS matrix.
2352 :
2353 : INPUT PARAMETERS
2354 : S - sparse matrix in CRS format.
2355 :
2356 : OUTPUT PARAMETERS
2357 : S - sparse matrix, transposed.
2358 :
2359 : NOTE: internal temporary copy is allocated for the purposes of
2360 : transposition. It is deallocated after transposition.
2361 :
2362 : -- ALGLIB PROJECT --
2363 : Copyright 30.01.2018 by Bochkanov Sergey
2364 : *************************************************************************/
2365 0 : void sparsetransposecrs(const sparsematrix &s, const xparams _xparams)
2366 : {
2367 : jmp_buf _break_jump;
2368 : alglib_impl::ae_state _alglib_env_state;
2369 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2370 0 : if( setjmp(_break_jump) )
2371 : {
2372 : #if !defined(AE_NO_EXCEPTIONS)
2373 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2374 : #else
2375 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2376 : return;
2377 : #endif
2378 : }
2379 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2380 0 : if( _xparams.flags!=0x0 )
2381 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2382 0 : alglib_impl::sparsetransposecrs(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
2383 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2384 0 : return;
2385 : }
2386 :
2387 : /*************************************************************************
2388 : This function performs copying with transposition of CRS matrix.
2389 :
2390 : INPUT PARAMETERS
2391 : S0 - sparse matrix in CRS format.
2392 :
2393 : OUTPUT PARAMETERS
2394 : S1 - sparse matrix, transposed
2395 :
2396 : -- ALGLIB PROJECT --
2397 : Copyright 23.07.2018 by Bochkanov Sergey
2398 : *************************************************************************/
2399 0 : void sparsecopytransposecrs(const sparsematrix &s0, sparsematrix &s1, const xparams _xparams)
2400 : {
2401 : jmp_buf _break_jump;
2402 : alglib_impl::ae_state _alglib_env_state;
2403 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2404 0 : if( setjmp(_break_jump) )
2405 : {
2406 : #if !defined(AE_NO_EXCEPTIONS)
2407 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2408 : #else
2409 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2410 : return;
2411 : #endif
2412 : }
2413 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2414 0 : if( _xparams.flags!=0x0 )
2415 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2416 0 : alglib_impl::sparsecopytransposecrs(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s1.c_ptr()), &_alglib_env_state);
2417 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2418 0 : return;
2419 : }
2420 :
2421 : /*************************************************************************
2422 : This function performs copying with transposition of CRS matrix (buffered
2423 : version which reuses memory already allocated by the target as much as
2424 : possible).
2425 :
2426 : INPUT PARAMETERS
2427 : S0 - sparse matrix in CRS format.
2428 :
2429 : OUTPUT PARAMETERS
2430 : S1 - sparse matrix, transposed; previously allocated memory is
2431 : reused if possible.
2432 :
2433 : -- ALGLIB PROJECT --
2434 : Copyright 23.07.2018 by Bochkanov Sergey
2435 : *************************************************************************/
2436 0 : void sparsecopytransposecrsbuf(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams)
2437 : {
2438 : jmp_buf _break_jump;
2439 : alglib_impl::ae_state _alglib_env_state;
2440 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2441 0 : if( setjmp(_break_jump) )
2442 : {
2443 : #if !defined(AE_NO_EXCEPTIONS)
2444 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2445 : #else
2446 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2447 : return;
2448 : #endif
2449 : }
2450 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2451 0 : if( _xparams.flags!=0x0 )
2452 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2453 0 : alglib_impl::sparsecopytransposecrsbuf(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s1.c_ptr()), &_alglib_env_state);
2454 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2455 0 : return;
2456 : }
2457 :
2458 : /*************************************************************************
2459 : This function performs in-place conversion to desired sparse storage
2460 : format.
2461 :
2462 : INPUT PARAMETERS
2463 : S0 - sparse matrix in any format.
2464 : Fmt - desired storage format of the output, as returned by
2465 : SparseGetMatrixType() function:
2466 : * 0 for hash-based storage
2467 : * 1 for CRS
2468 : * 2 for SKS
2469 :
2470 : OUTPUT PARAMETERS
2471 : S0 - sparse matrix in requested format.
2472 :
2473 : NOTE: in-place conversion wastes a lot of memory which is used to store
2474 : temporaries. If you perform a lot of repeated conversions, we
2475 : recommend to use out-of-place buffered conversion functions, like
2476 : SparseCopyToBuf(), which can reuse already allocated memory.
2477 :
2478 : -- ALGLIB PROJECT --
2479 : Copyright 16.01.2014 by Bochkanov Sergey
2480 : *************************************************************************/
2481 0 : void sparseconvertto(const sparsematrix &s0, const ae_int_t fmt, const xparams _xparams)
2482 : {
2483 : jmp_buf _break_jump;
2484 : alglib_impl::ae_state _alglib_env_state;
2485 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2486 0 : if( setjmp(_break_jump) )
2487 : {
2488 : #if !defined(AE_NO_EXCEPTIONS)
2489 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2490 : #else
2491 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2492 : return;
2493 : #endif
2494 : }
2495 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2496 0 : if( _xparams.flags!=0x0 )
2497 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2498 0 : alglib_impl::sparseconvertto(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), fmt, &_alglib_env_state);
2499 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2500 0 : return;
2501 : }
2502 :
2503 : /*************************************************************************
2504 : This function performs out-of-place conversion to desired sparse storage
2505 : format. S0 is copied to S1 and converted on-the-fly. Memory allocated in
2506 : S1 is reused to maximum extent possible.
2507 :
2508 : INPUT PARAMETERS
2509 : S0 - sparse matrix in any format.
2510 : Fmt - desired storage format of the output, as returned by
2511 : SparseGetMatrixType() function:
2512 : * 0 for hash-based storage
2513 : * 1 for CRS
2514 : * 2 for SKS
2515 :
2516 : OUTPUT PARAMETERS
2517 : S1 - sparse matrix in requested format.
2518 :
2519 : -- ALGLIB PROJECT --
2520 : Copyright 16.01.2014 by Bochkanov Sergey
2521 : *************************************************************************/
2522 0 : void sparsecopytobuf(const sparsematrix &s0, const ae_int_t fmt, const sparsematrix &s1, const xparams _xparams)
2523 : {
2524 : jmp_buf _break_jump;
2525 : alglib_impl::ae_state _alglib_env_state;
2526 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2527 0 : if( setjmp(_break_jump) )
2528 : {
2529 : #if !defined(AE_NO_EXCEPTIONS)
2530 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2531 : #else
2532 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2533 : return;
2534 : #endif
2535 : }
2536 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2537 0 : if( _xparams.flags!=0x0 )
2538 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2539 0 : alglib_impl::sparsecopytobuf(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), fmt, const_cast<alglib_impl::sparsematrix*>(s1.c_ptr()), &_alglib_env_state);
2540 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2541 0 : return;
2542 : }
2543 :
2544 : /*************************************************************************
2545 : This function performs in-place conversion to Hash table storage.
2546 :
2547 : INPUT PARAMETERS
2548 : S - sparse matrix in CRS format.
2549 :
2550 : OUTPUT PARAMETERS
2551 : S - sparse matrix in Hash table format.
2552 :
2553 : NOTE: this function has no effect when called with matrix which is
2554 : already in Hash table mode.
2555 :
2556 : NOTE: in-place conversion involves allocation of temporary arrays. If you
2557 : perform a lot of repeated in- place conversions, it may lead to
2558 : memory fragmentation. Consider using out-of-place SparseCopyToHashBuf()
2559 : function in this case.
2560 :
2561 : -- ALGLIB PROJECT --
2562 : Copyright 20.07.2012 by Bochkanov Sergey
2563 : *************************************************************************/
2564 0 : void sparseconverttohash(const sparsematrix &s, const xparams _xparams)
2565 : {
2566 : jmp_buf _break_jump;
2567 : alglib_impl::ae_state _alglib_env_state;
2568 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2569 0 : if( setjmp(_break_jump) )
2570 : {
2571 : #if !defined(AE_NO_EXCEPTIONS)
2572 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2573 : #else
2574 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2575 : return;
2576 : #endif
2577 : }
2578 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2579 0 : if( _xparams.flags!=0x0 )
2580 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2581 0 : alglib_impl::sparseconverttohash(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
2582 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2583 0 : return;
2584 : }
2585 :
2586 : /*************************************************************************
2587 : This function performs out-of-place conversion to Hash table storage
2588 : format. S0 is copied to S1 and converted on-the-fly.
2589 :
2590 : INPUT PARAMETERS
2591 : S0 - sparse matrix in any format.
2592 :
2593 : OUTPUT PARAMETERS
2594 : S1 - sparse matrix in Hash table format.
2595 :
2596 : NOTE: if S0 is stored as Hash-table, it is just copied without conversion.
2597 :
2598 : NOTE: this function de-allocates memory occupied by S1 before starting
2599 : conversion. If you perform a lot of repeated conversions, it may
2600 : lead to memory fragmentation. In this case we recommend you to use
2601 : SparseCopyToHashBuf() function which re-uses memory in S1 as much as
2602 : possible.
2603 :
2604 : -- ALGLIB PROJECT --
2605 : Copyright 20.07.2012 by Bochkanov Sergey
2606 : *************************************************************************/
2607 0 : void sparsecopytohash(const sparsematrix &s0, sparsematrix &s1, const xparams _xparams)
2608 : {
2609 : jmp_buf _break_jump;
2610 : alglib_impl::ae_state _alglib_env_state;
2611 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2612 0 : if( setjmp(_break_jump) )
2613 : {
2614 : #if !defined(AE_NO_EXCEPTIONS)
2615 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2616 : #else
2617 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2618 : return;
2619 : #endif
2620 : }
2621 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2622 0 : if( _xparams.flags!=0x0 )
2623 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2624 0 : alglib_impl::sparsecopytohash(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s1.c_ptr()), &_alglib_env_state);
2625 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2626 0 : return;
2627 : }
2628 :
2629 : /*************************************************************************
2630 : This function performs out-of-place conversion to Hash table storage
2631 : format. S0 is copied to S1 and converted on-the-fly. Memory allocated in
2632 : S1 is reused to maximum extent possible.
2633 :
2634 : INPUT PARAMETERS
2635 : S0 - sparse matrix in any format.
2636 :
2637 : OUTPUT PARAMETERS
2638 : S1 - sparse matrix in Hash table format.
2639 :
2640 : NOTE: if S0 is stored as Hash-table, it is just copied without conversion.
2641 :
2642 : -- ALGLIB PROJECT --
2643 : Copyright 20.07.2012 by Bochkanov Sergey
2644 : *************************************************************************/
2645 0 : void sparsecopytohashbuf(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams)
2646 : {
2647 : jmp_buf _break_jump;
2648 : alglib_impl::ae_state _alglib_env_state;
2649 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2650 0 : if( setjmp(_break_jump) )
2651 : {
2652 : #if !defined(AE_NO_EXCEPTIONS)
2653 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2654 : #else
2655 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2656 : return;
2657 : #endif
2658 : }
2659 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2660 0 : if( _xparams.flags!=0x0 )
2661 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2662 0 : alglib_impl::sparsecopytohashbuf(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s1.c_ptr()), &_alglib_env_state);
2663 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2664 0 : return;
2665 : }
2666 :
2667 : /*************************************************************************
2668 : This function converts matrix to CRS format.
2669 :
2670 : Some algorithms (linear algebra ones, for example) require matrices in
2671 : CRS format. This function allows to perform in-place conversion.
2672 :
2673 : INPUT PARAMETERS
2674 : S - sparse M*N matrix in any format
2675 :
2676 : OUTPUT PARAMETERS
2677 : S - matrix in CRS format
2678 :
2679 : NOTE: this function has no effect when called with matrix which is
2680 : already in CRS mode.
2681 :
2682 : NOTE: this function allocates temporary memory to store a copy of the
2683 : matrix. If you perform a lot of repeated conversions, we recommend
2684 : you to use SparseCopyToCRSBuf() function, which can reuse
2685 : previously allocated memory.
2686 :
2687 : -- ALGLIB PROJECT --
2688 : Copyright 14.10.2011 by Bochkanov Sergey
2689 : *************************************************************************/
2690 0 : void sparseconverttocrs(const sparsematrix &s, const xparams _xparams)
2691 : {
2692 : jmp_buf _break_jump;
2693 : alglib_impl::ae_state _alglib_env_state;
2694 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2695 0 : if( setjmp(_break_jump) )
2696 : {
2697 : #if !defined(AE_NO_EXCEPTIONS)
2698 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2699 : #else
2700 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2701 : return;
2702 : #endif
2703 : }
2704 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2705 0 : if( _xparams.flags!=0x0 )
2706 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2707 0 : alglib_impl::sparseconverttocrs(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
2708 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2709 0 : return;
2710 : }
2711 :
2712 : /*************************************************************************
2713 : This function performs out-of-place conversion to CRS format. S0 is
2714 : copied to S1 and converted on-the-fly.
2715 :
2716 : INPUT PARAMETERS
2717 : S0 - sparse matrix in any format.
2718 :
2719 : OUTPUT PARAMETERS
2720 : S1 - sparse matrix in CRS format.
2721 :
2722 : NOTE: if S0 is stored as CRS, it is just copied without conversion.
2723 :
2724 : NOTE: this function de-allocates memory occupied by S1 before starting CRS
2725 : conversion. If you perform a lot of repeated CRS conversions, it may
2726 : lead to memory fragmentation. In this case we recommend you to use
2727 : SparseCopyToCRSBuf() function which re-uses memory in S1 as much as
2728 : possible.
2729 :
2730 : -- ALGLIB PROJECT --
2731 : Copyright 20.07.2012 by Bochkanov Sergey
2732 : *************************************************************************/
2733 0 : void sparsecopytocrs(const sparsematrix &s0, sparsematrix &s1, const xparams _xparams)
2734 : {
2735 : jmp_buf _break_jump;
2736 : alglib_impl::ae_state _alglib_env_state;
2737 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2738 0 : if( setjmp(_break_jump) )
2739 : {
2740 : #if !defined(AE_NO_EXCEPTIONS)
2741 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2742 : #else
2743 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2744 : return;
2745 : #endif
2746 : }
2747 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2748 0 : if( _xparams.flags!=0x0 )
2749 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2750 0 : alglib_impl::sparsecopytocrs(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s1.c_ptr()), &_alglib_env_state);
2751 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2752 0 : return;
2753 : }
2754 :
2755 : /*************************************************************************
2756 : This function performs out-of-place conversion to CRS format. S0 is
2757 : copied to S1 and converted on-the-fly. Memory allocated in S1 is reused to
2758 : maximum extent possible.
2759 :
2760 : INPUT PARAMETERS
2761 : S0 - sparse matrix in any format.
2762 : S1 - matrix which may contain some pre-allocated memory, or
2763 : can be just uninitialized structure.
2764 :
2765 : OUTPUT PARAMETERS
2766 : S1 - sparse matrix in CRS format.
2767 :
2768 : NOTE: if S0 is stored as CRS, it is just copied without conversion.
2769 :
2770 : -- ALGLIB PROJECT --
2771 : Copyright 20.07.2012 by Bochkanov Sergey
2772 : *************************************************************************/
2773 0 : void sparsecopytocrsbuf(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams)
2774 : {
2775 : jmp_buf _break_jump;
2776 : alglib_impl::ae_state _alglib_env_state;
2777 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2778 0 : if( setjmp(_break_jump) )
2779 : {
2780 : #if !defined(AE_NO_EXCEPTIONS)
2781 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2782 : #else
2783 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2784 : return;
2785 : #endif
2786 : }
2787 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2788 0 : if( _xparams.flags!=0x0 )
2789 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2790 0 : alglib_impl::sparsecopytocrsbuf(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s1.c_ptr()), &_alglib_env_state);
2791 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2792 0 : return;
2793 : }
2794 :
2795 : /*************************************************************************
2796 : This function performs in-place conversion to SKS format.
2797 :
2798 : INPUT PARAMETERS
2799 : S - sparse matrix in any format.
2800 :
2801 : OUTPUT PARAMETERS
2802 : S - sparse matrix in SKS format.
2803 :
2804 : NOTE: this function has no effect when called with matrix which is
2805 : already in SKS mode.
2806 :
2807 : NOTE: in-place conversion involves allocation of temporary arrays. If you
2808 : perform a lot of repeated in- place conversions, it may lead to
2809 : memory fragmentation. Consider using out-of-place SparseCopyToSKSBuf()
2810 : function in this case.
2811 :
2812 : -- ALGLIB PROJECT --
2813 : Copyright 15.01.2014 by Bochkanov Sergey
2814 : *************************************************************************/
2815 0 : void sparseconverttosks(const sparsematrix &s, const xparams _xparams)
2816 : {
2817 : jmp_buf _break_jump;
2818 : alglib_impl::ae_state _alglib_env_state;
2819 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2820 0 : if( setjmp(_break_jump) )
2821 : {
2822 : #if !defined(AE_NO_EXCEPTIONS)
2823 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2824 : #else
2825 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2826 : return;
2827 : #endif
2828 : }
2829 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2830 0 : if( _xparams.flags!=0x0 )
2831 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2832 0 : alglib_impl::sparseconverttosks(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
2833 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2834 0 : return;
2835 : }
2836 :
2837 : /*************************************************************************
2838 : This function performs out-of-place conversion to SKS storage format.
2839 : S0 is copied to S1 and converted on-the-fly.
2840 :
2841 : INPUT PARAMETERS
2842 : S0 - sparse matrix in any format.
2843 :
2844 : OUTPUT PARAMETERS
2845 : S1 - sparse matrix in SKS format.
2846 :
2847 : NOTE: if S0 is stored as SKS, it is just copied without conversion.
2848 :
2849 : NOTE: this function de-allocates memory occupied by S1 before starting
2850 : conversion. If you perform a lot of repeated conversions, it may
2851 : lead to memory fragmentation. In this case we recommend you to use
2852 : SparseCopyToSKSBuf() function which re-uses memory in S1 as much as
2853 : possible.
2854 :
2855 : -- ALGLIB PROJECT --
2856 : Copyright 20.07.2012 by Bochkanov Sergey
2857 : *************************************************************************/
2858 0 : void sparsecopytosks(const sparsematrix &s0, sparsematrix &s1, const xparams _xparams)
2859 : {
2860 : jmp_buf _break_jump;
2861 : alglib_impl::ae_state _alglib_env_state;
2862 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2863 0 : if( setjmp(_break_jump) )
2864 : {
2865 : #if !defined(AE_NO_EXCEPTIONS)
2866 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2867 : #else
2868 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2869 : return;
2870 : #endif
2871 : }
2872 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2873 0 : if( _xparams.flags!=0x0 )
2874 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2875 0 : alglib_impl::sparsecopytosks(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s1.c_ptr()), &_alglib_env_state);
2876 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2877 0 : return;
2878 : }
2879 :
2880 : /*************************************************************************
2881 : This function performs out-of-place conversion to SKS format. S0 is
2882 : copied to S1 and converted on-the-fly. Memory allocated in S1 is reused
2883 : to maximum extent possible.
2884 :
2885 : INPUT PARAMETERS
2886 : S0 - sparse matrix in any format.
2887 :
2888 : OUTPUT PARAMETERS
2889 : S1 - sparse matrix in SKS format.
2890 :
2891 : NOTE: if S0 is stored as SKS, it is just copied without conversion.
2892 :
2893 : -- ALGLIB PROJECT --
2894 : Copyright 20.07.2012 by Bochkanov Sergey
2895 : *************************************************************************/
2896 0 : void sparsecopytosksbuf(const sparsematrix &s0, const sparsematrix &s1, const xparams _xparams)
2897 : {
2898 : jmp_buf _break_jump;
2899 : alglib_impl::ae_state _alglib_env_state;
2900 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2901 0 : if( setjmp(_break_jump) )
2902 : {
2903 : #if !defined(AE_NO_EXCEPTIONS)
2904 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2905 : #else
2906 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2907 : return;
2908 : #endif
2909 : }
2910 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2911 0 : if( _xparams.flags!=0x0 )
2912 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2913 0 : alglib_impl::sparsecopytosksbuf(const_cast<alglib_impl::sparsematrix*>(s0.c_ptr()), const_cast<alglib_impl::sparsematrix*>(s1.c_ptr()), &_alglib_env_state);
2914 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2915 0 : return;
2916 : }
2917 :
2918 : /*************************************************************************
2919 : This function returns type of the matrix storage format.
2920 :
2921 : INPUT PARAMETERS:
2922 : S - sparse matrix.
2923 :
2924 : RESULT:
2925 : sparse storage format used by matrix:
2926 : 0 - Hash-table
2927 : 1 - CRS (compressed row storage)
2928 : 2 - SKS (skyline)
2929 :
2930 : NOTE: future versions of ALGLIB may include additional sparse storage
2931 : formats.
2932 :
2933 :
2934 : -- ALGLIB PROJECT --
2935 : Copyright 20.07.2012 by Bochkanov Sergey
2936 : *************************************************************************/
2937 0 : ae_int_t sparsegetmatrixtype(const sparsematrix &s, const xparams _xparams)
2938 : {
2939 : jmp_buf _break_jump;
2940 : alglib_impl::ae_state _alglib_env_state;
2941 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2942 0 : if( setjmp(_break_jump) )
2943 : {
2944 : #if !defined(AE_NO_EXCEPTIONS)
2945 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2946 : #else
2947 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2948 : return 0;
2949 : #endif
2950 : }
2951 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2952 0 : if( _xparams.flags!=0x0 )
2953 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2954 0 : alglib_impl::ae_int_t result = alglib_impl::sparsegetmatrixtype(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
2955 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2956 0 : return *(reinterpret_cast<ae_int_t*>(&result));
2957 : }
2958 :
2959 : /*************************************************************************
2960 : This function checks matrix storage format and returns True when matrix is
2961 : stored using Hash table representation.
2962 :
2963 : INPUT PARAMETERS:
2964 : S - sparse matrix.
2965 :
2966 : RESULT:
2967 : True if matrix type is Hash table
2968 : False if matrix type is not Hash table
2969 :
2970 : -- ALGLIB PROJECT --
2971 : Copyright 20.07.2012 by Bochkanov Sergey
2972 : *************************************************************************/
2973 0 : bool sparseishash(const sparsematrix &s, const xparams _xparams)
2974 : {
2975 : jmp_buf _break_jump;
2976 : alglib_impl::ae_state _alglib_env_state;
2977 0 : alglib_impl::ae_state_init(&_alglib_env_state);
2978 0 : if( setjmp(_break_jump) )
2979 : {
2980 : #if !defined(AE_NO_EXCEPTIONS)
2981 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
2982 : #else
2983 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
2984 : return 0;
2985 : #endif
2986 : }
2987 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
2988 0 : if( _xparams.flags!=0x0 )
2989 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
2990 0 : ae_bool result = alglib_impl::sparseishash(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
2991 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
2992 0 : return *(reinterpret_cast<bool*>(&result));
2993 : }
2994 :
2995 : /*************************************************************************
2996 : This function checks matrix storage format and returns True when matrix is
2997 : stored using CRS representation.
2998 :
2999 : INPUT PARAMETERS:
3000 : S - sparse matrix.
3001 :
3002 : RESULT:
3003 : True if matrix type is CRS
3004 : False if matrix type is not CRS
3005 :
3006 : -- ALGLIB PROJECT --
3007 : Copyright 20.07.2012 by Bochkanov Sergey
3008 : *************************************************************************/
3009 0 : bool sparseiscrs(const sparsematrix &s, const xparams _xparams)
3010 : {
3011 : jmp_buf _break_jump;
3012 : alglib_impl::ae_state _alglib_env_state;
3013 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3014 0 : if( setjmp(_break_jump) )
3015 : {
3016 : #if !defined(AE_NO_EXCEPTIONS)
3017 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3018 : #else
3019 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3020 : return 0;
3021 : #endif
3022 : }
3023 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3024 0 : if( _xparams.flags!=0x0 )
3025 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3026 0 : ae_bool result = alglib_impl::sparseiscrs(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
3027 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3028 0 : return *(reinterpret_cast<bool*>(&result));
3029 : }
3030 :
3031 : /*************************************************************************
3032 : This function checks matrix storage format and returns True when matrix is
3033 : stored using SKS representation.
3034 :
3035 : INPUT PARAMETERS:
3036 : S - sparse matrix.
3037 :
3038 : RESULT:
3039 : True if matrix type is SKS
3040 : False if matrix type is not SKS
3041 :
3042 : -- ALGLIB PROJECT --
3043 : Copyright 20.07.2012 by Bochkanov Sergey
3044 : *************************************************************************/
3045 0 : bool sparseissks(const sparsematrix &s, const xparams _xparams)
3046 : {
3047 : jmp_buf _break_jump;
3048 : alglib_impl::ae_state _alglib_env_state;
3049 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3050 0 : if( setjmp(_break_jump) )
3051 : {
3052 : #if !defined(AE_NO_EXCEPTIONS)
3053 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3054 : #else
3055 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3056 : return 0;
3057 : #endif
3058 : }
3059 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3060 0 : if( _xparams.flags!=0x0 )
3061 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3062 0 : ae_bool result = alglib_impl::sparseissks(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
3063 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3064 0 : return *(reinterpret_cast<bool*>(&result));
3065 : }
3066 :
3067 : /*************************************************************************
3068 : The function frees all memory occupied by sparse matrix. Sparse matrix
3069 : structure becomes unusable after this call.
3070 :
3071 : OUTPUT PARAMETERS
3072 : S - sparse matrix to delete
3073 :
3074 : -- ALGLIB PROJECT --
3075 : Copyright 24.07.2012 by Bochkanov Sergey
3076 : *************************************************************************/
3077 0 : void sparsefree(sparsematrix &s, const xparams _xparams)
3078 : {
3079 : jmp_buf _break_jump;
3080 : alglib_impl::ae_state _alglib_env_state;
3081 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3082 0 : if( setjmp(_break_jump) )
3083 : {
3084 : #if !defined(AE_NO_EXCEPTIONS)
3085 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3086 : #else
3087 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3088 : return;
3089 : #endif
3090 : }
3091 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3092 0 : if( _xparams.flags!=0x0 )
3093 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3094 0 : alglib_impl::sparsefree(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
3095 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3096 0 : return;
3097 : }
3098 :
3099 : /*************************************************************************
3100 : The function returns number of rows of a sparse matrix.
3101 :
3102 : RESULT: number of rows of a sparse matrix.
3103 :
3104 : -- ALGLIB PROJECT --
3105 : Copyright 23.08.2012 by Bochkanov Sergey
3106 : *************************************************************************/
3107 0 : ae_int_t sparsegetnrows(const sparsematrix &s, const xparams _xparams)
3108 : {
3109 : jmp_buf _break_jump;
3110 : alglib_impl::ae_state _alglib_env_state;
3111 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3112 0 : if( setjmp(_break_jump) )
3113 : {
3114 : #if !defined(AE_NO_EXCEPTIONS)
3115 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3116 : #else
3117 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3118 : return 0;
3119 : #endif
3120 : }
3121 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3122 0 : if( _xparams.flags!=0x0 )
3123 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3124 0 : alglib_impl::ae_int_t result = alglib_impl::sparsegetnrows(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
3125 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3126 0 : return *(reinterpret_cast<ae_int_t*>(&result));
3127 : }
3128 :
3129 : /*************************************************************************
3130 : The function returns number of columns of a sparse matrix.
3131 :
3132 : RESULT: number of columns of a sparse matrix.
3133 :
3134 : -- ALGLIB PROJECT --
3135 : Copyright 23.08.2012 by Bochkanov Sergey
3136 : *************************************************************************/
3137 0 : ae_int_t sparsegetncols(const sparsematrix &s, const xparams _xparams)
3138 : {
3139 : jmp_buf _break_jump;
3140 : alglib_impl::ae_state _alglib_env_state;
3141 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3142 0 : if( setjmp(_break_jump) )
3143 : {
3144 : #if !defined(AE_NO_EXCEPTIONS)
3145 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3146 : #else
3147 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3148 : return 0;
3149 : #endif
3150 : }
3151 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3152 0 : if( _xparams.flags!=0x0 )
3153 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3154 0 : alglib_impl::ae_int_t result = alglib_impl::sparsegetncols(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
3155 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3156 0 : return *(reinterpret_cast<ae_int_t*>(&result));
3157 : }
3158 :
3159 : /*************************************************************************
3160 : The function returns number of strictly upper triangular non-zero elements
3161 : in the matrix. It counts SYMBOLICALLY non-zero elements, i.e. entries
3162 : in the sparse matrix data structure. If some element has zero numerical
3163 : value, it is still counted.
3164 :
3165 : This function has different cost for different types of matrices:
3166 : * for hash-based matrices it involves complete pass over entire hash-table
3167 : with O(NNZ) cost, where NNZ is number of non-zero elements
3168 : * for CRS and SKS matrix types cost of counting is O(N) (N - matrix size).
3169 :
3170 : RESULT: number of non-zero elements strictly above main diagonal
3171 :
3172 : -- ALGLIB PROJECT --
3173 : Copyright 12.02.2014 by Bochkanov Sergey
3174 : *************************************************************************/
3175 0 : ae_int_t sparsegetuppercount(const sparsematrix &s, const xparams _xparams)
3176 : {
3177 : jmp_buf _break_jump;
3178 : alglib_impl::ae_state _alglib_env_state;
3179 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3180 0 : if( setjmp(_break_jump) )
3181 : {
3182 : #if !defined(AE_NO_EXCEPTIONS)
3183 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3184 : #else
3185 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3186 : return 0;
3187 : #endif
3188 : }
3189 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3190 0 : if( _xparams.flags!=0x0 )
3191 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3192 0 : alglib_impl::ae_int_t result = alglib_impl::sparsegetuppercount(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
3193 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3194 0 : return *(reinterpret_cast<ae_int_t*>(&result));
3195 : }
3196 :
3197 : /*************************************************************************
3198 : The function returns number of strictly lower triangular non-zero elements
3199 : in the matrix. It counts SYMBOLICALLY non-zero elements, i.e. entries
3200 : in the sparse matrix data structure. If some element has zero numerical
3201 : value, it is still counted.
3202 :
3203 : This function has different cost for different types of matrices:
3204 : * for hash-based matrices it involves complete pass over entire hash-table
3205 : with O(NNZ) cost, where NNZ is number of non-zero elements
3206 : * for CRS and SKS matrix types cost of counting is O(N) (N - matrix size).
3207 :
3208 : RESULT: number of non-zero elements strictly below main diagonal
3209 :
3210 : -- ALGLIB PROJECT --
3211 : Copyright 12.02.2014 by Bochkanov Sergey
3212 : *************************************************************************/
3213 0 : ae_int_t sparsegetlowercount(const sparsematrix &s, const xparams _xparams)
3214 : {
3215 : jmp_buf _break_jump;
3216 : alglib_impl::ae_state _alglib_env_state;
3217 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3218 0 : if( setjmp(_break_jump) )
3219 : {
3220 : #if !defined(AE_NO_EXCEPTIONS)
3221 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3222 : #else
3223 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3224 : return 0;
3225 : #endif
3226 : }
3227 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3228 0 : if( _xparams.flags!=0x0 )
3229 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3230 0 : alglib_impl::ae_int_t result = alglib_impl::sparsegetlowercount(const_cast<alglib_impl::sparsematrix*>(s.c_ptr()), &_alglib_env_state);
3231 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3232 0 : return *(reinterpret_cast<ae_int_t*>(&result));
3233 : }
3234 : #endif
3235 :
3236 : #if defined(AE_COMPILE_ABLAS) || !defined(AE_PARTIAL_BUILD)
3237 : /*************************************************************************
3238 : Cache-oblivous complex "copy-and-transpose"
3239 :
3240 : Input parameters:
3241 : M - number of rows
3242 : N - number of columns
3243 : A - source matrix, MxN submatrix is copied and transposed
3244 : IA - submatrix offset (row index)
3245 : JA - submatrix offset (column index)
3246 : B - destination matrix, must be large enough to store result
3247 : IB - submatrix offset (row index)
3248 : JB - submatrix offset (column index)
3249 : *************************************************************************/
3250 0 : void cmatrixtranspose(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, complex_2d_array &b, const ae_int_t ib, const ae_int_t jb, const xparams _xparams)
3251 : {
3252 : jmp_buf _break_jump;
3253 : alglib_impl::ae_state _alglib_env_state;
3254 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3255 0 : if( setjmp(_break_jump) )
3256 : {
3257 : #if !defined(AE_NO_EXCEPTIONS)
3258 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3259 : #else
3260 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3261 : return;
3262 : #endif
3263 : }
3264 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3265 0 : if( _xparams.flags!=0x0 )
3266 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3267 0 : alglib_impl::cmatrixtranspose(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), ib, jb, &_alglib_env_state);
3268 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3269 0 : return;
3270 : }
3271 :
3272 : /*************************************************************************
3273 : Cache-oblivous real "copy-and-transpose"
3274 :
3275 : Input parameters:
3276 : M - number of rows
3277 : N - number of columns
3278 : A - source matrix, MxN submatrix is copied and transposed
3279 : IA - submatrix offset (row index)
3280 : JA - submatrix offset (column index)
3281 : B - destination matrix, must be large enough to store result
3282 : IB - submatrix offset (row index)
3283 : JB - submatrix offset (column index)
3284 : *************************************************************************/
3285 0 : void rmatrixtranspose(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const real_2d_array &b, const ae_int_t ib, const ae_int_t jb, const xparams _xparams)
3286 : {
3287 : jmp_buf _break_jump;
3288 : alglib_impl::ae_state _alglib_env_state;
3289 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3290 0 : if( setjmp(_break_jump) )
3291 : {
3292 : #if !defined(AE_NO_EXCEPTIONS)
3293 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3294 : #else
3295 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3296 : return;
3297 : #endif
3298 : }
3299 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3300 0 : if( _xparams.flags!=0x0 )
3301 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3302 0 : alglib_impl::rmatrixtranspose(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), ib, jb, &_alglib_env_state);
3303 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3304 0 : return;
3305 : }
3306 :
3307 : /*************************************************************************
3308 : This code enforces symmetricy of the matrix by copying Upper part to lower
3309 : one (or vice versa).
3310 :
3311 : INPUT PARAMETERS:
3312 : A - matrix
3313 : N - number of rows/columns
3314 : IsUpper - whether we want to copy upper triangle to lower one (True)
3315 : or vice versa (False).
3316 : *************************************************************************/
3317 0 : void rmatrixenforcesymmetricity(const real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams)
3318 : {
3319 : jmp_buf _break_jump;
3320 : alglib_impl::ae_state _alglib_env_state;
3321 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3322 0 : if( setjmp(_break_jump) )
3323 : {
3324 : #if !defined(AE_NO_EXCEPTIONS)
3325 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3326 : #else
3327 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3328 : return;
3329 : #endif
3330 : }
3331 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3332 0 : if( _xparams.flags!=0x0 )
3333 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3334 0 : alglib_impl::rmatrixenforcesymmetricity(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &_alglib_env_state);
3335 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3336 0 : return;
3337 : }
3338 :
3339 : /*************************************************************************
3340 : Copy
3341 :
3342 : Input parameters:
3343 : M - number of rows
3344 : N - number of columns
3345 : A - source matrix, MxN submatrix is copied and transposed
3346 : IA - submatrix offset (row index)
3347 : JA - submatrix offset (column index)
3348 : B - destination matrix, must be large enough to store result
3349 : IB - submatrix offset (row index)
3350 : JB - submatrix offset (column index)
3351 : *************************************************************************/
3352 0 : void cmatrixcopy(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, complex_2d_array &b, const ae_int_t ib, const ae_int_t jb, const xparams _xparams)
3353 : {
3354 : jmp_buf _break_jump;
3355 : alglib_impl::ae_state _alglib_env_state;
3356 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3357 0 : if( setjmp(_break_jump) )
3358 : {
3359 : #if !defined(AE_NO_EXCEPTIONS)
3360 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3361 : #else
3362 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3363 : return;
3364 : #endif
3365 : }
3366 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3367 0 : if( _xparams.flags!=0x0 )
3368 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3369 0 : alglib_impl::cmatrixcopy(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), ib, jb, &_alglib_env_state);
3370 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3371 0 : return;
3372 : }
3373 :
3374 : /*************************************************************************
3375 : Copy
3376 :
3377 : Input parameters:
3378 : N - subvector size
3379 : A - source vector, N elements are copied
3380 : IA - source offset (first element index)
3381 : B - destination vector, must be large enough to store result
3382 : IB - destination offset (first element index)
3383 : *************************************************************************/
3384 0 : void rvectorcopy(const ae_int_t n, const real_1d_array &a, const ae_int_t ia, const real_1d_array &b, const ae_int_t ib, const xparams _xparams)
3385 : {
3386 : jmp_buf _break_jump;
3387 : alglib_impl::ae_state _alglib_env_state;
3388 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3389 0 : if( setjmp(_break_jump) )
3390 : {
3391 : #if !defined(AE_NO_EXCEPTIONS)
3392 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3393 : #else
3394 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3395 : return;
3396 : #endif
3397 : }
3398 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3399 0 : if( _xparams.flags!=0x0 )
3400 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3401 0 : alglib_impl::rvectorcopy(n, const_cast<alglib_impl::ae_vector*>(a.c_ptr()), ia, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), ib, &_alglib_env_state);
3402 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3403 0 : return;
3404 : }
3405 :
3406 : /*************************************************************************
3407 : Copy
3408 :
3409 : Input parameters:
3410 : M - number of rows
3411 : N - number of columns
3412 : A - source matrix, MxN submatrix is copied and transposed
3413 : IA - submatrix offset (row index)
3414 : JA - submatrix offset (column index)
3415 : B - destination matrix, must be large enough to store result
3416 : IB - submatrix offset (row index)
3417 : JB - submatrix offset (column index)
3418 : *************************************************************************/
3419 0 : void rmatrixcopy(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const real_2d_array &b, const ae_int_t ib, const ae_int_t jb, const xparams _xparams)
3420 : {
3421 : jmp_buf _break_jump;
3422 : alglib_impl::ae_state _alglib_env_state;
3423 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3424 0 : if( setjmp(_break_jump) )
3425 : {
3426 : #if !defined(AE_NO_EXCEPTIONS)
3427 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3428 : #else
3429 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3430 : return;
3431 : #endif
3432 : }
3433 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3434 0 : if( _xparams.flags!=0x0 )
3435 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3436 0 : alglib_impl::rmatrixcopy(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), ib, jb, &_alglib_env_state);
3437 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3438 0 : return;
3439 : }
3440 :
3441 : /*************************************************************************
3442 : Performs generalized copy: B := Beta*B + Alpha*A.
3443 :
3444 : If Beta=0, then previous contents of B is simply ignored. If Alpha=0, then
3445 : A is ignored and not referenced. If both Alpha and Beta are zero, B is
3446 : filled by zeros.
3447 :
3448 : Input parameters:
3449 : M - number of rows
3450 : N - number of columns
3451 : Alpha- coefficient
3452 : A - source matrix, MxN submatrix is copied and transposed
3453 : IA - submatrix offset (row index)
3454 : JA - submatrix offset (column index)
3455 : Beta- coefficient
3456 : B - destination matrix, must be large enough to store result
3457 : IB - submatrix offset (row index)
3458 : JB - submatrix offset (column index)
3459 : *************************************************************************/
3460 0 : void rmatrixgencopy(const ae_int_t m, const ae_int_t n, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const double beta, const real_2d_array &b, const ae_int_t ib, const ae_int_t jb, const xparams _xparams)
3461 : {
3462 : jmp_buf _break_jump;
3463 : alglib_impl::ae_state _alglib_env_state;
3464 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3465 0 : if( setjmp(_break_jump) )
3466 : {
3467 : #if !defined(AE_NO_EXCEPTIONS)
3468 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3469 : #else
3470 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3471 : return;
3472 : #endif
3473 : }
3474 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3475 0 : if( _xparams.flags!=0x0 )
3476 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3477 0 : alglib_impl::rmatrixgencopy(m, n, alpha, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, beta, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), ib, jb, &_alglib_env_state);
3478 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3479 0 : return;
3480 : }
3481 :
3482 : /*************************************************************************
3483 : Rank-1 correction: A := A + alpha*u*v'
3484 :
3485 : NOTE: this function expects A to be large enough to store result. No
3486 : automatic preallocation happens for smaller arrays. No integrity
3487 : checks is performed for sizes of A, u, v.
3488 :
3489 : INPUT PARAMETERS:
3490 : M - number of rows
3491 : N - number of columns
3492 : A - target matrix, MxN submatrix is updated
3493 : IA - submatrix offset (row index)
3494 : JA - submatrix offset (column index)
3495 : Alpha- coefficient
3496 : U - vector #1
3497 : IU - subvector offset
3498 : V - vector #2
3499 : IV - subvector offset
3500 :
3501 :
3502 : -- ALGLIB routine --
3503 :
3504 : 16.10.2017
3505 : Bochkanov Sergey
3506 : *************************************************************************/
3507 0 : void rmatrixger(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const double alpha, const real_1d_array &u, const ae_int_t iu, const real_1d_array &v, const ae_int_t iv, const xparams _xparams)
3508 : {
3509 : jmp_buf _break_jump;
3510 : alglib_impl::ae_state _alglib_env_state;
3511 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3512 0 : if( setjmp(_break_jump) )
3513 : {
3514 : #if !defined(AE_NO_EXCEPTIONS)
3515 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3516 : #else
3517 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3518 : return;
3519 : #endif
3520 : }
3521 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3522 0 : if( _xparams.flags!=0x0 )
3523 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3524 0 : alglib_impl::rmatrixger(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, alpha, const_cast<alglib_impl::ae_vector*>(u.c_ptr()), iu, const_cast<alglib_impl::ae_vector*>(v.c_ptr()), iv, &_alglib_env_state);
3525 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3526 0 : return;
3527 : }
3528 :
3529 : /*************************************************************************
3530 : Rank-1 correction: A := A + u*v'
3531 :
3532 : INPUT PARAMETERS:
3533 : M - number of rows
3534 : N - number of columns
3535 : A - target matrix, MxN submatrix is updated
3536 : IA - submatrix offset (row index)
3537 : JA - submatrix offset (column index)
3538 : U - vector #1
3539 : IU - subvector offset
3540 : V - vector #2
3541 : IV - subvector offset
3542 : *************************************************************************/
3543 0 : void cmatrixrank1(const ae_int_t m, const ae_int_t n, complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, complex_1d_array &u, const ae_int_t iu, complex_1d_array &v, const ae_int_t iv, const xparams _xparams)
3544 : {
3545 : jmp_buf _break_jump;
3546 : alglib_impl::ae_state _alglib_env_state;
3547 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3548 0 : if( setjmp(_break_jump) )
3549 : {
3550 : #if !defined(AE_NO_EXCEPTIONS)
3551 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3552 : #else
3553 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3554 : return;
3555 : #endif
3556 : }
3557 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3558 0 : if( _xparams.flags!=0x0 )
3559 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3560 0 : alglib_impl::cmatrixrank1(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, const_cast<alglib_impl::ae_vector*>(u.c_ptr()), iu, const_cast<alglib_impl::ae_vector*>(v.c_ptr()), iv, &_alglib_env_state);
3561 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3562 0 : return;
3563 : }
3564 :
3565 : /*************************************************************************
3566 : IMPORTANT: this function is deprecated since ALGLIB 3.13. Use RMatrixGER()
3567 : which is more generic version of this function.
3568 :
3569 : Rank-1 correction: A := A + u*v'
3570 :
3571 : INPUT PARAMETERS:
3572 : M - number of rows
3573 : N - number of columns
3574 : A - target matrix, MxN submatrix is updated
3575 : IA - submatrix offset (row index)
3576 : JA - submatrix offset (column index)
3577 : U - vector #1
3578 : IU - subvector offset
3579 : V - vector #2
3580 : IV - subvector offset
3581 : *************************************************************************/
3582 0 : void rmatrixrank1(const ae_int_t m, const ae_int_t n, real_2d_array &a, const ae_int_t ia, const ae_int_t ja, real_1d_array &u, const ae_int_t iu, real_1d_array &v, const ae_int_t iv, const xparams _xparams)
3583 : {
3584 : jmp_buf _break_jump;
3585 : alglib_impl::ae_state _alglib_env_state;
3586 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3587 0 : if( setjmp(_break_jump) )
3588 : {
3589 : #if !defined(AE_NO_EXCEPTIONS)
3590 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3591 : #else
3592 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3593 : return;
3594 : #endif
3595 : }
3596 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3597 0 : if( _xparams.flags!=0x0 )
3598 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3599 0 : alglib_impl::rmatrixrank1(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, const_cast<alglib_impl::ae_vector*>(u.c_ptr()), iu, const_cast<alglib_impl::ae_vector*>(v.c_ptr()), iv, &_alglib_env_state);
3600 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3601 0 : return;
3602 : }
3603 :
3604 : /*************************************************************************
3605 :
3606 : *************************************************************************/
3607 0 : void rmatrixgemv(const ae_int_t m, const ae_int_t n, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t opa, const real_1d_array &x, const ae_int_t ix, const double beta, const real_1d_array &y, const ae_int_t iy, const xparams _xparams)
3608 : {
3609 : jmp_buf _break_jump;
3610 : alglib_impl::ae_state _alglib_env_state;
3611 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3612 0 : if( setjmp(_break_jump) )
3613 : {
3614 : #if !defined(AE_NO_EXCEPTIONS)
3615 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3616 : #else
3617 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3618 : return;
3619 : #endif
3620 : }
3621 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3622 0 : if( _xparams.flags!=0x0 )
3623 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3624 0 : alglib_impl::rmatrixgemv(m, n, alpha, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, opa, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), ix, beta, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), iy, &_alglib_env_state);
3625 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3626 0 : return;
3627 : }
3628 :
3629 : /*************************************************************************
3630 : Matrix-vector product: y := op(A)*x
3631 :
3632 : INPUT PARAMETERS:
3633 : M - number of rows of op(A)
3634 : M>=0
3635 : N - number of columns of op(A)
3636 : N>=0
3637 : A - target matrix
3638 : IA - submatrix offset (row index)
3639 : JA - submatrix offset (column index)
3640 : OpA - operation type:
3641 : * OpA=0 => op(A) = A
3642 : * OpA=1 => op(A) = A^T
3643 : * OpA=2 => op(A) = A^H
3644 : X - input vector
3645 : IX - subvector offset
3646 : IY - subvector offset
3647 : Y - preallocated matrix, must be large enough to store result
3648 :
3649 : OUTPUT PARAMETERS:
3650 : Y - vector which stores result
3651 :
3652 : if M=0, then subroutine does nothing.
3653 : if N=0, Y is filled by zeros.
3654 :
3655 :
3656 : -- ALGLIB routine --
3657 :
3658 : 28.01.2010
3659 : Bochkanov Sergey
3660 : *************************************************************************/
3661 0 : void cmatrixmv(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t opa, const complex_1d_array &x, const ae_int_t ix, complex_1d_array &y, const ae_int_t iy, const xparams _xparams)
3662 : {
3663 : jmp_buf _break_jump;
3664 : alglib_impl::ae_state _alglib_env_state;
3665 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3666 0 : if( setjmp(_break_jump) )
3667 : {
3668 : #if !defined(AE_NO_EXCEPTIONS)
3669 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3670 : #else
3671 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3672 : return;
3673 : #endif
3674 : }
3675 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3676 0 : if( _xparams.flags!=0x0 )
3677 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3678 0 : alglib_impl::cmatrixmv(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, opa, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), ix, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), iy, &_alglib_env_state);
3679 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3680 0 : return;
3681 : }
3682 :
3683 : /*************************************************************************
3684 : IMPORTANT: this function is deprecated since ALGLIB 3.13. Use RMatrixGEMV()
3685 : which is more generic version of this function.
3686 :
3687 : Matrix-vector product: y := op(A)*x
3688 :
3689 : INPUT PARAMETERS:
3690 : M - number of rows of op(A)
3691 : N - number of columns of op(A)
3692 : A - target matrix
3693 : IA - submatrix offset (row index)
3694 : JA - submatrix offset (column index)
3695 : OpA - operation type:
3696 : * OpA=0 => op(A) = A
3697 : * OpA=1 => op(A) = A^T
3698 : X - input vector
3699 : IX - subvector offset
3700 : IY - subvector offset
3701 : Y - preallocated matrix, must be large enough to store result
3702 :
3703 : OUTPUT PARAMETERS:
3704 : Y - vector which stores result
3705 :
3706 : if M=0, then subroutine does nothing.
3707 : if N=0, Y is filled by zeros.
3708 :
3709 :
3710 : -- ALGLIB routine --
3711 :
3712 : 28.01.2010
3713 : Bochkanov Sergey
3714 : *************************************************************************/
3715 0 : void rmatrixmv(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t opa, const real_1d_array &x, const ae_int_t ix, const real_1d_array &y, const ae_int_t iy, const xparams _xparams)
3716 : {
3717 : jmp_buf _break_jump;
3718 : alglib_impl::ae_state _alglib_env_state;
3719 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3720 0 : if( setjmp(_break_jump) )
3721 : {
3722 : #if !defined(AE_NO_EXCEPTIONS)
3723 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3724 : #else
3725 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3726 : return;
3727 : #endif
3728 : }
3729 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3730 0 : if( _xparams.flags!=0x0 )
3731 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3732 0 : alglib_impl::rmatrixmv(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, opa, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), ix, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), iy, &_alglib_env_state);
3733 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3734 0 : return;
3735 : }
3736 :
3737 : /*************************************************************************
3738 :
3739 : *************************************************************************/
3740 0 : void rmatrixsymv(const ae_int_t n, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const bool isupper, const real_1d_array &x, const ae_int_t ix, const double beta, const real_1d_array &y, const ae_int_t iy, const xparams _xparams)
3741 : {
3742 : jmp_buf _break_jump;
3743 : alglib_impl::ae_state _alglib_env_state;
3744 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3745 0 : if( setjmp(_break_jump) )
3746 : {
3747 : #if !defined(AE_NO_EXCEPTIONS)
3748 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3749 : #else
3750 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3751 : return;
3752 : #endif
3753 : }
3754 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3755 0 : if( _xparams.flags!=0x0 )
3756 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3757 0 : alglib_impl::rmatrixsymv(n, alpha, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, isupper, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), ix, beta, const_cast<alglib_impl::ae_vector*>(y.c_ptr()), iy, &_alglib_env_state);
3758 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3759 0 : return;
3760 : }
3761 :
3762 : /*************************************************************************
3763 :
3764 : *************************************************************************/
3765 0 : double rmatrixsyvmv(const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const bool isupper, const real_1d_array &x, const ae_int_t ix, const real_1d_array &tmp, const xparams _xparams)
3766 : {
3767 : jmp_buf _break_jump;
3768 : alglib_impl::ae_state _alglib_env_state;
3769 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3770 0 : if( setjmp(_break_jump) )
3771 : {
3772 : #if !defined(AE_NO_EXCEPTIONS)
3773 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3774 : #else
3775 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3776 : return 0;
3777 : #endif
3778 : }
3779 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3780 0 : if( _xparams.flags!=0x0 )
3781 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3782 0 : double result = alglib_impl::rmatrixsyvmv(n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, isupper, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), ix, const_cast<alglib_impl::ae_vector*>(tmp.c_ptr()), &_alglib_env_state);
3783 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3784 0 : return *(reinterpret_cast<double*>(&result));
3785 : }
3786 :
3787 : /*************************************************************************
3788 : This subroutine solves linear system op(A)*x=b where:
3789 : * A is NxN upper/lower triangular/unitriangular matrix
3790 : * X and B are Nx1 vectors
3791 : * "op" may be identity transformation, transposition, conjugate transposition
3792 :
3793 : Solution replaces X.
3794 :
3795 : IMPORTANT: * no overflow/underflow/denegeracy tests is performed.
3796 : * no integrity checks for operand sizes, out-of-bounds accesses
3797 : and so on is performed
3798 :
3799 : INPUT PARAMETERS
3800 : N - matrix size, N>=0
3801 : A - matrix, actial matrix is stored in A[IA:IA+N-1,JA:JA+N-1]
3802 : IA - submatrix offset
3803 : JA - submatrix offset
3804 : IsUpper - whether matrix is upper triangular
3805 : IsUnit - whether matrix is unitriangular
3806 : OpType - transformation type:
3807 : * 0 - no transformation
3808 : * 1 - transposition
3809 : X - right part, actual vector is stored in X[IX:IX+N-1]
3810 : IX - offset
3811 :
3812 : OUTPUT PARAMETERS
3813 : X - solution replaces elements X[IX:IX+N-1]
3814 :
3815 : -- ALGLIB routine / remastering of LAPACK's DTRSV --
3816 : (c) 2017 Bochkanov Sergey - converted to ALGLIB
3817 : (c) 2016 Reference BLAS level1 routine (LAPACK version 3.7.0)
3818 : Reference BLAS is a software package provided by Univ. of Tennessee,
3819 : Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.
3820 : *************************************************************************/
3821 0 : void rmatrixtrsv(const ae_int_t n, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const bool isupper, const bool isunit, const ae_int_t optype, const real_1d_array &x, const ae_int_t ix, const xparams _xparams)
3822 : {
3823 : jmp_buf _break_jump;
3824 : alglib_impl::ae_state _alglib_env_state;
3825 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3826 0 : if( setjmp(_break_jump) )
3827 : {
3828 : #if !defined(AE_NO_EXCEPTIONS)
3829 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3830 : #else
3831 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3832 : return;
3833 : #endif
3834 : }
3835 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3836 0 : if( _xparams.flags!=0x0 )
3837 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3838 0 : alglib_impl::rmatrixtrsv(n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, isupper, isunit, optype, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), ix, &_alglib_env_state);
3839 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3840 0 : return;
3841 : }
3842 :
3843 : /*************************************************************************
3844 : This subroutine calculates X*op(A^-1) where:
3845 : * X is MxN general matrix
3846 : * A is NxN upper/lower triangular/unitriangular matrix
3847 : * "op" may be identity transformation, transposition, conjugate transposition
3848 : Multiplication result replaces X.
3849 :
3850 : ! COMMERCIAL EDITION OF ALGLIB:
3851 : !
3852 : ! Commercial Edition of ALGLIB includes following important improvements
3853 : ! of this function:
3854 : ! * high-performance native backend with same C# interface (C# version)
3855 : ! * multithreading support (C++ and C# versions)
3856 : ! * hardware vendor (Intel) implementations of linear algebra primitives
3857 : ! (C++ and C# versions, x86/x64 platform)
3858 : !
3859 : ! We recommend you to read 'Working with commercial version' section of
3860 : ! ALGLIB Reference Manual in order to find out how to use performance-
3861 : ! related features provided by commercial edition of ALGLIB.
3862 :
3863 : INPUT PARAMETERS
3864 : N - matrix size, N>=0
3865 : M - matrix size, N>=0
3866 : A - matrix, actial matrix is stored in A[I1:I1+N-1,J1:J1+N-1]
3867 : I1 - submatrix offset
3868 : J1 - submatrix offset
3869 : IsUpper - whether matrix is upper triangular
3870 : IsUnit - whether matrix is unitriangular
3871 : OpType - transformation type:
3872 : * 0 - no transformation
3873 : * 1 - transposition
3874 : * 2 - conjugate transposition
3875 : X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1]
3876 : I2 - submatrix offset
3877 : J2 - submatrix offset
3878 :
3879 : -- ALGLIB routine --
3880 : 20.01.2018
3881 : Bochkanov Sergey
3882 : *************************************************************************/
3883 0 : void cmatrixrighttrsm(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const complex_2d_array &x, const ae_int_t i2, const ae_int_t j2, const xparams _xparams)
3884 : {
3885 : jmp_buf _break_jump;
3886 : alglib_impl::ae_state _alglib_env_state;
3887 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3888 0 : if( setjmp(_break_jump) )
3889 : {
3890 : #if !defined(AE_NO_EXCEPTIONS)
3891 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3892 : #else
3893 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3894 : return;
3895 : #endif
3896 : }
3897 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3898 0 : if( _xparams.flags!=0x0 )
3899 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3900 0 : alglib_impl::cmatrixrighttrsm(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), i1, j1, isupper, isunit, optype, const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), i2, j2, &_alglib_env_state);
3901 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3902 0 : return;
3903 : }
3904 :
3905 : /*************************************************************************
3906 : This subroutine calculates op(A^-1)*X where:
3907 : * X is MxN general matrix
3908 : * A is MxM upper/lower triangular/unitriangular matrix
3909 : * "op" may be identity transformation, transposition, conjugate transposition
3910 : Multiplication result replaces X.
3911 :
3912 : ! COMMERCIAL EDITION OF ALGLIB:
3913 : !
3914 : ! Commercial Edition of ALGLIB includes following important improvements
3915 : ! of this function:
3916 : ! * high-performance native backend with same C# interface (C# version)
3917 : ! * multithreading support (C++ and C# versions)
3918 : ! * hardware vendor (Intel) implementations of linear algebra primitives
3919 : ! (C++ and C# versions, x86/x64 platform)
3920 : !
3921 : ! We recommend you to read 'Working with commercial version' section of
3922 : ! ALGLIB Reference Manual in order to find out how to use performance-
3923 : ! related features provided by commercial edition of ALGLIB.
3924 :
3925 : INPUT PARAMETERS
3926 : N - matrix size, N>=0
3927 : M - matrix size, N>=0
3928 : A - matrix, actial matrix is stored in A[I1:I1+M-1,J1:J1+M-1]
3929 : I1 - submatrix offset
3930 : J1 - submatrix offset
3931 : IsUpper - whether matrix is upper triangular
3932 : IsUnit - whether matrix is unitriangular
3933 : OpType - transformation type:
3934 : * 0 - no transformation
3935 : * 1 - transposition
3936 : * 2 - conjugate transposition
3937 : X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1]
3938 : I2 - submatrix offset
3939 : J2 - submatrix offset
3940 :
3941 : -- ALGLIB routine --
3942 : 15.12.2009-22.01.2018
3943 : Bochkanov Sergey
3944 : *************************************************************************/
3945 0 : void cmatrixlefttrsm(const ae_int_t m, const ae_int_t n, const complex_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const complex_2d_array &x, const ae_int_t i2, const ae_int_t j2, const xparams _xparams)
3946 : {
3947 : jmp_buf _break_jump;
3948 : alglib_impl::ae_state _alglib_env_state;
3949 0 : alglib_impl::ae_state_init(&_alglib_env_state);
3950 0 : if( setjmp(_break_jump) )
3951 : {
3952 : #if !defined(AE_NO_EXCEPTIONS)
3953 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
3954 : #else
3955 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
3956 : return;
3957 : #endif
3958 : }
3959 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
3960 0 : if( _xparams.flags!=0x0 )
3961 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
3962 0 : alglib_impl::cmatrixlefttrsm(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), i1, j1, isupper, isunit, optype, const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), i2, j2, &_alglib_env_state);
3963 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
3964 0 : return;
3965 : }
3966 :
3967 : /*************************************************************************
3968 : This subroutine calculates X*op(A^-1) where:
3969 : * X is MxN general matrix
3970 : * A is NxN upper/lower triangular/unitriangular matrix
3971 : * "op" may be identity transformation, transposition
3972 : Multiplication result replaces X.
3973 :
3974 : ! COMMERCIAL EDITION OF ALGLIB:
3975 : !
3976 : ! Commercial Edition of ALGLIB includes following important improvements
3977 : ! of this function:
3978 : ! * high-performance native backend with same C# interface (C# version)
3979 : ! * multithreading support (C++ and C# versions)
3980 : ! * hardware vendor (Intel) implementations of linear algebra primitives
3981 : ! (C++ and C# versions, x86/x64 platform)
3982 : !
3983 : ! We recommend you to read 'Working with commercial version' section of
3984 : ! ALGLIB Reference Manual in order to find out how to use performance-
3985 : ! related features provided by commercial edition of ALGLIB.
3986 :
3987 : INPUT PARAMETERS
3988 : N - matrix size, N>=0
3989 : M - matrix size, N>=0
3990 : A - matrix, actial matrix is stored in A[I1:I1+N-1,J1:J1+N-1]
3991 : I1 - submatrix offset
3992 : J1 - submatrix offset
3993 : IsUpper - whether matrix is upper triangular
3994 : IsUnit - whether matrix is unitriangular
3995 : OpType - transformation type:
3996 : * 0 - no transformation
3997 : * 1 - transposition
3998 : X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1]
3999 : I2 - submatrix offset
4000 : J2 - submatrix offset
4001 :
4002 : -- ALGLIB routine --
4003 : 15.12.2009-22.01.2018
4004 : Bochkanov Sergey
4005 : *************************************************************************/
4006 0 : void rmatrixrighttrsm(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const real_2d_array &x, const ae_int_t i2, const ae_int_t j2, const xparams _xparams)
4007 : {
4008 : jmp_buf _break_jump;
4009 : alglib_impl::ae_state _alglib_env_state;
4010 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4011 0 : if( setjmp(_break_jump) )
4012 : {
4013 : #if !defined(AE_NO_EXCEPTIONS)
4014 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4015 : #else
4016 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4017 : return;
4018 : #endif
4019 : }
4020 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4021 0 : if( _xparams.flags!=0x0 )
4022 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4023 0 : alglib_impl::rmatrixrighttrsm(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), i1, j1, isupper, isunit, optype, const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), i2, j2, &_alglib_env_state);
4024 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4025 0 : return;
4026 : }
4027 :
4028 : /*************************************************************************
4029 : This subroutine calculates op(A^-1)*X where:
4030 : * X is MxN general matrix
4031 : * A is MxM upper/lower triangular/unitriangular matrix
4032 : * "op" may be identity transformation, transposition
4033 : Multiplication result replaces X.
4034 :
4035 : ! COMMERCIAL EDITION OF ALGLIB:
4036 : !
4037 : ! Commercial Edition of ALGLIB includes following important improvements
4038 : ! of this function:
4039 : ! * high-performance native backend with same C# interface (C# version)
4040 : ! * multithreading support (C++ and C# versions)
4041 : ! * hardware vendor (Intel) implementations of linear algebra primitives
4042 : ! (C++ and C# versions, x86/x64 platform)
4043 : !
4044 : ! We recommend you to read 'Working with commercial version' section of
4045 : ! ALGLIB Reference Manual in order to find out how to use performance-
4046 : ! related features provided by commercial edition of ALGLIB.
4047 :
4048 : INPUT PARAMETERS
4049 : N - matrix size, N>=0
4050 : M - matrix size, N>=0
4051 : A - matrix, actial matrix is stored in A[I1:I1+M-1,J1:J1+M-1]
4052 : I1 - submatrix offset
4053 : J1 - submatrix offset
4054 : IsUpper - whether matrix is upper triangular
4055 : IsUnit - whether matrix is unitriangular
4056 : OpType - transformation type:
4057 : * 0 - no transformation
4058 : * 1 - transposition
4059 : X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1]
4060 : I2 - submatrix offset
4061 : J2 - submatrix offset
4062 :
4063 : -- ALGLIB routine --
4064 : 15.12.2009-22.01.2018
4065 : Bochkanov Sergey
4066 : *************************************************************************/
4067 0 : void rmatrixlefttrsm(const ae_int_t m, const ae_int_t n, const real_2d_array &a, const ae_int_t i1, const ae_int_t j1, const bool isupper, const bool isunit, const ae_int_t optype, const real_2d_array &x, const ae_int_t i2, const ae_int_t j2, const xparams _xparams)
4068 : {
4069 : jmp_buf _break_jump;
4070 : alglib_impl::ae_state _alglib_env_state;
4071 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4072 0 : if( setjmp(_break_jump) )
4073 : {
4074 : #if !defined(AE_NO_EXCEPTIONS)
4075 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4076 : #else
4077 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4078 : return;
4079 : #endif
4080 : }
4081 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4082 0 : if( _xparams.flags!=0x0 )
4083 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4084 0 : alglib_impl::rmatrixlefttrsm(m, n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), i1, j1, isupper, isunit, optype, const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), i2, j2, &_alglib_env_state);
4085 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4086 0 : return;
4087 : }
4088 :
4089 : /*************************************************************************
4090 : This subroutine calculates C=alpha*A*A^H+beta*C or C=alpha*A^H*A+beta*C
4091 : where:
4092 : * C is NxN Hermitian matrix given by its upper/lower triangle
4093 : * A is NxK matrix when A*A^H is calculated, KxN matrix otherwise
4094 :
4095 : Additional info:
4096 : * multiplication result replaces C. If Beta=0, C elements are not used in
4097 : calculations (not multiplied by zero - just not referenced)
4098 : * if Alpha=0, A is not used (not multiplied by zero - just not referenced)
4099 : * if both Beta and Alpha are zero, C is filled by zeros.
4100 :
4101 : ! COMMERCIAL EDITION OF ALGLIB:
4102 : !
4103 : ! Commercial Edition of ALGLIB includes following important improvements
4104 : ! of this function:
4105 : ! * high-performance native backend with same C# interface (C# version)
4106 : ! * multithreading support (C++ and C# versions)
4107 : ! * hardware vendor (Intel) implementations of linear algebra primitives
4108 : ! (C++ and C# versions, x86/x64 platform)
4109 : !
4110 : ! We recommend you to read 'Working with commercial version' section of
4111 : ! ALGLIB Reference Manual in order to find out how to use performance-
4112 : ! related features provided by commercial edition of ALGLIB.
4113 :
4114 : INPUT PARAMETERS
4115 : N - matrix size, N>=0
4116 : K - matrix size, K>=0
4117 : Alpha - coefficient
4118 : A - matrix
4119 : IA - submatrix offset (row index)
4120 : JA - submatrix offset (column index)
4121 : OpTypeA - multiplication type:
4122 : * 0 - A*A^H is calculated
4123 : * 2 - A^H*A is calculated
4124 : Beta - coefficient
4125 : C - preallocated input/output matrix
4126 : IC - submatrix offset (row index)
4127 : JC - submatrix offset (column index)
4128 : IsUpper - whether upper or lower triangle of C is updated;
4129 : this function updates only one half of C, leaving
4130 : other half unchanged (not referenced at all).
4131 :
4132 : -- ALGLIB routine --
4133 : 16.12.2009-22.01.2018
4134 : Bochkanov Sergey
4135 : *************************************************************************/
4136 0 : void cmatrixherk(const ae_int_t n, const ae_int_t k, const double alpha, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const double beta, const complex_2d_array &c, const ae_int_t ic, const ae_int_t jc, const bool isupper, const xparams _xparams)
4137 : {
4138 : jmp_buf _break_jump;
4139 : alglib_impl::ae_state _alglib_env_state;
4140 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4141 0 : if( setjmp(_break_jump) )
4142 : {
4143 : #if !defined(AE_NO_EXCEPTIONS)
4144 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4145 : #else
4146 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4147 : return;
4148 : #endif
4149 : }
4150 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4151 0 : if( _xparams.flags!=0x0 )
4152 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4153 0 : alglib_impl::cmatrixherk(n, k, alpha, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, optypea, beta, const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), ic, jc, isupper, &_alglib_env_state);
4154 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4155 0 : return;
4156 : }
4157 :
4158 : /*************************************************************************
4159 : This subroutine calculates C=alpha*A*A^T+beta*C or C=alpha*A^T*A+beta*C
4160 : where:
4161 : * C is NxN symmetric matrix given by its upper/lower triangle
4162 : * A is NxK matrix when A*A^T is calculated, KxN matrix otherwise
4163 :
4164 : Additional info:
4165 : * multiplication result replaces C. If Beta=0, C elements are not used in
4166 : calculations (not multiplied by zero - just not referenced)
4167 : * if Alpha=0, A is not used (not multiplied by zero - just not referenced)
4168 : * if both Beta and Alpha are zero, C is filled by zeros.
4169 :
4170 : ! COMMERCIAL EDITION OF ALGLIB:
4171 : !
4172 : ! Commercial Edition of ALGLIB includes following important improvements
4173 : ! of this function:
4174 : ! * high-performance native backend with same C# interface (C# version)
4175 : ! * multithreading support (C++ and C# versions)
4176 : ! * hardware vendor (Intel) implementations of linear algebra primitives
4177 : ! (C++ and C# versions, x86/x64 platform)
4178 : !
4179 : ! We recommend you to read 'Working with commercial version' section of
4180 : ! ALGLIB Reference Manual in order to find out how to use performance-
4181 : ! related features provided by commercial edition of ALGLIB.
4182 :
4183 : INPUT PARAMETERS
4184 : N - matrix size, N>=0
4185 : K - matrix size, K>=0
4186 : Alpha - coefficient
4187 : A - matrix
4188 : IA - submatrix offset (row index)
4189 : JA - submatrix offset (column index)
4190 : OpTypeA - multiplication type:
4191 : * 0 - A*A^T is calculated
4192 : * 2 - A^T*A is calculated
4193 : Beta - coefficient
4194 : C - preallocated input/output matrix
4195 : IC - submatrix offset (row index)
4196 : JC - submatrix offset (column index)
4197 : IsUpper - whether C is upper triangular or lower triangular
4198 :
4199 : -- ALGLIB routine --
4200 : 16.12.2009-22.01.2018
4201 : Bochkanov Sergey
4202 : *************************************************************************/
4203 0 : void rmatrixsyrk(const ae_int_t n, const ae_int_t k, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const double beta, const real_2d_array &c, const ae_int_t ic, const ae_int_t jc, const bool isupper, const xparams _xparams)
4204 : {
4205 : jmp_buf _break_jump;
4206 : alglib_impl::ae_state _alglib_env_state;
4207 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4208 0 : if( setjmp(_break_jump) )
4209 : {
4210 : #if !defined(AE_NO_EXCEPTIONS)
4211 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4212 : #else
4213 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4214 : return;
4215 : #endif
4216 : }
4217 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4218 0 : if( _xparams.flags!=0x0 )
4219 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4220 0 : alglib_impl::rmatrixsyrk(n, k, alpha, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, optypea, beta, const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), ic, jc, isupper, &_alglib_env_state);
4221 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4222 0 : return;
4223 : }
4224 :
4225 : /*************************************************************************
4226 : This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where:
4227 : * C is MxN general matrix
4228 : * op1(A) is MxK matrix
4229 : * op2(B) is KxN matrix
4230 : * "op" may be identity transformation, transposition, conjugate transposition
4231 :
4232 : Additional info:
4233 : * cache-oblivious algorithm is used.
4234 : * multiplication result replaces C. If Beta=0, C elements are not used in
4235 : calculations (not multiplied by zero - just not referenced)
4236 : * if Alpha=0, A is not used (not multiplied by zero - just not referenced)
4237 : * if both Beta and Alpha are zero, C is filled by zeros.
4238 :
4239 : ! COMMERCIAL EDITION OF ALGLIB:
4240 : !
4241 : ! Commercial Edition of ALGLIB includes following important improvements
4242 : ! of this function:
4243 : ! * high-performance native backend with same C# interface (C# version)
4244 : ! * multithreading support (C++ and C# versions)
4245 : ! * hardware vendor (Intel) implementations of linear algebra primitives
4246 : ! (C++ and C# versions, x86/x64 platform)
4247 : !
4248 : ! We recommend you to read 'Working with commercial version' section of
4249 : ! ALGLIB Reference Manual in order to find out how to use performance-
4250 : ! related features provided by commercial edition of ALGLIB.
4251 :
4252 : IMPORTANT:
4253 :
4254 : This function does NOT preallocate output matrix C, it MUST be preallocated
4255 : by caller prior to calling this function. In case C does not have enough
4256 : space to store result, exception will be generated.
4257 :
4258 : INPUT PARAMETERS
4259 : M - matrix size, M>0
4260 : N - matrix size, N>0
4261 : K - matrix size, K>0
4262 : Alpha - coefficient
4263 : A - matrix
4264 : IA - submatrix offset
4265 : JA - submatrix offset
4266 : OpTypeA - transformation type:
4267 : * 0 - no transformation
4268 : * 1 - transposition
4269 : * 2 - conjugate transposition
4270 : B - matrix
4271 : IB - submatrix offset
4272 : JB - submatrix offset
4273 : OpTypeB - transformation type:
4274 : * 0 - no transformation
4275 : * 1 - transposition
4276 : * 2 - conjugate transposition
4277 : Beta - coefficient
4278 : C - matrix (PREALLOCATED, large enough to store result)
4279 : IC - submatrix offset
4280 : JC - submatrix offset
4281 :
4282 : -- ALGLIB routine --
4283 : 2009-2019
4284 : Bochkanov Sergey
4285 : *************************************************************************/
4286 0 : void cmatrixgemm(const ae_int_t m, const ae_int_t n, const ae_int_t k, const alglib::complex alpha, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const complex_2d_array &b, const ae_int_t ib, const ae_int_t jb, const ae_int_t optypeb, const alglib::complex beta, const complex_2d_array &c, const ae_int_t ic, const ae_int_t jc, const xparams _xparams)
4287 : {
4288 : jmp_buf _break_jump;
4289 : alglib_impl::ae_state _alglib_env_state;
4290 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4291 0 : if( setjmp(_break_jump) )
4292 : {
4293 : #if !defined(AE_NO_EXCEPTIONS)
4294 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4295 : #else
4296 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4297 : return;
4298 : #endif
4299 : }
4300 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4301 0 : if( _xparams.flags!=0x0 )
4302 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4303 0 : alglib_impl::cmatrixgemm(m, n, k, *alpha.c_ptr(), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, optypea, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), ib, jb, optypeb, *beta.c_ptr(), const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), ic, jc, &_alglib_env_state);
4304 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4305 0 : return;
4306 : }
4307 :
4308 : /*************************************************************************
4309 : This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where:
4310 : * C is MxN general matrix
4311 : * op1(A) is MxK matrix
4312 : * op2(B) is KxN matrix
4313 : * "op" may be identity transformation, transposition
4314 :
4315 : Additional info:
4316 : * cache-oblivious algorithm is used.
4317 : * multiplication result replaces C. If Beta=0, C elements are not used in
4318 : calculations (not multiplied by zero - just not referenced)
4319 : * if Alpha=0, A is not used (not multiplied by zero - just not referenced)
4320 : * if both Beta and Alpha are zero, C is filled by zeros.
4321 :
4322 : ! COMMERCIAL EDITION OF ALGLIB:
4323 : !
4324 : ! Commercial Edition of ALGLIB includes following important improvements
4325 : ! of this function:
4326 : ! * high-performance native backend with same C# interface (C# version)
4327 : ! * multithreading support (C++ and C# versions)
4328 : ! * hardware vendor (Intel) implementations of linear algebra primitives
4329 : ! (C++ and C# versions, x86/x64 platform)
4330 : !
4331 : ! We recommend you to read 'Working with commercial version' section of
4332 : ! ALGLIB Reference Manual in order to find out how to use performance-
4333 : ! related features provided by commercial edition of ALGLIB.
4334 :
4335 : IMPORTANT:
4336 :
4337 : This function does NOT preallocate output matrix C, it MUST be preallocated
4338 : by caller prior to calling this function. In case C does not have enough
4339 : space to store result, exception will be generated.
4340 :
4341 : INPUT PARAMETERS
4342 : M - matrix size, M>0
4343 : N - matrix size, N>0
4344 : K - matrix size, K>0
4345 : Alpha - coefficient
4346 : A - matrix
4347 : IA - submatrix offset
4348 : JA - submatrix offset
4349 : OpTypeA - transformation type:
4350 : * 0 - no transformation
4351 : * 1 - transposition
4352 : B - matrix
4353 : IB - submatrix offset
4354 : JB - submatrix offset
4355 : OpTypeB - transformation type:
4356 : * 0 - no transformation
4357 : * 1 - transposition
4358 : Beta - coefficient
4359 : C - PREALLOCATED output matrix, large enough to store result
4360 : IC - submatrix offset
4361 : JC - submatrix offset
4362 :
4363 : -- ALGLIB routine --
4364 : 2009-2019
4365 : Bochkanov Sergey
4366 : *************************************************************************/
4367 0 : void rmatrixgemm(const ae_int_t m, const ae_int_t n, const ae_int_t k, const double alpha, const real_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const real_2d_array &b, const ae_int_t ib, const ae_int_t jb, const ae_int_t optypeb, const double beta, const real_2d_array &c, const ae_int_t ic, const ae_int_t jc, const xparams _xparams)
4368 : {
4369 : jmp_buf _break_jump;
4370 : alglib_impl::ae_state _alglib_env_state;
4371 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4372 0 : if( setjmp(_break_jump) )
4373 : {
4374 : #if !defined(AE_NO_EXCEPTIONS)
4375 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4376 : #else
4377 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4378 : return;
4379 : #endif
4380 : }
4381 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4382 0 : if( _xparams.flags!=0x0 )
4383 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4384 0 : alglib_impl::rmatrixgemm(m, n, k, alpha, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, optypea, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), ib, jb, optypeb, beta, const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), ic, jc, &_alglib_env_state);
4385 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4386 0 : return;
4387 : }
4388 :
4389 : /*************************************************************************
4390 : This subroutine is an older version of CMatrixHERK(), one with wrong name
4391 : (it is HErmitian update, not SYmmetric). It is left here for backward
4392 : compatibility.
4393 :
4394 : -- ALGLIB routine --
4395 : 16.12.2009
4396 : Bochkanov Sergey
4397 : *************************************************************************/
4398 0 : void cmatrixsyrk(const ae_int_t n, const ae_int_t k, const double alpha, const complex_2d_array &a, const ae_int_t ia, const ae_int_t ja, const ae_int_t optypea, const double beta, const complex_2d_array &c, const ae_int_t ic, const ae_int_t jc, const bool isupper, const xparams _xparams)
4399 : {
4400 : jmp_buf _break_jump;
4401 : alglib_impl::ae_state _alglib_env_state;
4402 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4403 0 : if( setjmp(_break_jump) )
4404 : {
4405 : #if !defined(AE_NO_EXCEPTIONS)
4406 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4407 : #else
4408 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4409 : return;
4410 : #endif
4411 : }
4412 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4413 0 : if( _xparams.flags!=0x0 )
4414 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4415 0 : alglib_impl::cmatrixsyrk(n, k, alpha, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), ia, ja, optypea, beta, const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), ic, jc, isupper, &_alglib_env_state);
4416 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4417 0 : return;
4418 : }
4419 : #endif
4420 :
4421 : #if defined(AE_COMPILE_DLU) || !defined(AE_PARTIAL_BUILD)
4422 :
4423 : #endif
4424 :
4425 : #if defined(AE_COMPILE_SPTRF) || !defined(AE_PARTIAL_BUILD)
4426 :
4427 : #endif
4428 :
4429 : #if defined(AE_COMPILE_AMDORDERING) || !defined(AE_PARTIAL_BUILD)
4430 :
4431 : #endif
4432 :
4433 : #if defined(AE_COMPILE_SPCHOL) || !defined(AE_PARTIAL_BUILD)
4434 :
4435 : #endif
4436 :
4437 : #if defined(AE_COMPILE_MATGEN) || !defined(AE_PARTIAL_BUILD)
4438 : /*************************************************************************
4439 : Generation of a random uniformly distributed (Haar) orthogonal matrix
4440 :
4441 : INPUT PARAMETERS:
4442 : N - matrix size, N>=1
4443 :
4444 : OUTPUT PARAMETERS:
4445 : A - orthogonal NxN matrix, array[0..N-1,0..N-1]
4446 :
4447 : NOTE: this function uses algorithm described in Stewart, G. W. (1980),
4448 : "The Efficient Generation of Random Orthogonal Matrices with an
4449 : Application to Condition Estimators".
4450 :
4451 : Speaking short, to generate an (N+1)x(N+1) orthogonal matrix, it:
4452 : * takes an NxN one
4453 : * takes uniformly distributed unit vector of dimension N+1.
4454 : * constructs a Householder reflection from the vector, then applies
4455 : it to the smaller matrix (embedded in the larger size with a 1 at
4456 : the bottom right corner).
4457 :
4458 : -- ALGLIB routine --
4459 : 04.12.2009
4460 : Bochkanov Sergey
4461 : *************************************************************************/
4462 0 : void rmatrixrndorthogonal(const ae_int_t n, real_2d_array &a, const xparams _xparams)
4463 : {
4464 : jmp_buf _break_jump;
4465 : alglib_impl::ae_state _alglib_env_state;
4466 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4467 0 : if( setjmp(_break_jump) )
4468 : {
4469 : #if !defined(AE_NO_EXCEPTIONS)
4470 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4471 : #else
4472 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4473 : return;
4474 : #endif
4475 : }
4476 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4477 0 : if( _xparams.flags!=0x0 )
4478 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4479 0 : alglib_impl::rmatrixrndorthogonal(n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), &_alglib_env_state);
4480 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4481 0 : return;
4482 : }
4483 :
4484 : /*************************************************************************
4485 : Generation of random NxN matrix with given condition number and norm2(A)=1
4486 :
4487 : INPUT PARAMETERS:
4488 : N - matrix size
4489 : C - condition number (in 2-norm)
4490 :
4491 : OUTPUT PARAMETERS:
4492 : A - random matrix with norm2(A)=1 and cond(A)=C
4493 :
4494 : -- ALGLIB routine --
4495 : 04.12.2009
4496 : Bochkanov Sergey
4497 : *************************************************************************/
4498 0 : void rmatrixrndcond(const ae_int_t n, const double c, real_2d_array &a, const xparams _xparams)
4499 : {
4500 : jmp_buf _break_jump;
4501 : alglib_impl::ae_state _alglib_env_state;
4502 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4503 0 : if( setjmp(_break_jump) )
4504 : {
4505 : #if !defined(AE_NO_EXCEPTIONS)
4506 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4507 : #else
4508 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4509 : return;
4510 : #endif
4511 : }
4512 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4513 0 : if( _xparams.flags!=0x0 )
4514 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4515 0 : alglib_impl::rmatrixrndcond(n, c, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), &_alglib_env_state);
4516 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4517 0 : return;
4518 : }
4519 :
4520 : /*************************************************************************
4521 : Generation of a random Haar distributed orthogonal complex matrix
4522 :
4523 : INPUT PARAMETERS:
4524 : N - matrix size, N>=1
4525 :
4526 : OUTPUT PARAMETERS:
4527 : A - orthogonal NxN matrix, array[0..N-1,0..N-1]
4528 :
4529 : NOTE: this function uses algorithm described in Stewart, G. W. (1980),
4530 : "The Efficient Generation of Random Orthogonal Matrices with an
4531 : Application to Condition Estimators".
4532 :
4533 : Speaking short, to generate an (N+1)x(N+1) orthogonal matrix, it:
4534 : * takes an NxN one
4535 : * takes uniformly distributed unit vector of dimension N+1.
4536 : * constructs a Householder reflection from the vector, then applies
4537 : it to the smaller matrix (embedded in the larger size with a 1 at
4538 : the bottom right corner).
4539 :
4540 : -- ALGLIB routine --
4541 : 04.12.2009
4542 : Bochkanov Sergey
4543 : *************************************************************************/
4544 0 : void cmatrixrndorthogonal(const ae_int_t n, complex_2d_array &a, const xparams _xparams)
4545 : {
4546 : jmp_buf _break_jump;
4547 : alglib_impl::ae_state _alglib_env_state;
4548 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4549 0 : if( setjmp(_break_jump) )
4550 : {
4551 : #if !defined(AE_NO_EXCEPTIONS)
4552 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4553 : #else
4554 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4555 : return;
4556 : #endif
4557 : }
4558 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4559 0 : if( _xparams.flags!=0x0 )
4560 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4561 0 : alglib_impl::cmatrixrndorthogonal(n, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), &_alglib_env_state);
4562 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4563 0 : return;
4564 : }
4565 :
4566 : /*************************************************************************
4567 : Generation of random NxN complex matrix with given condition number C and
4568 : norm2(A)=1
4569 :
4570 : INPUT PARAMETERS:
4571 : N - matrix size
4572 : C - condition number (in 2-norm)
4573 :
4574 : OUTPUT PARAMETERS:
4575 : A - random matrix with norm2(A)=1 and cond(A)=C
4576 :
4577 : -- ALGLIB routine --
4578 : 04.12.2009
4579 : Bochkanov Sergey
4580 : *************************************************************************/
4581 0 : void cmatrixrndcond(const ae_int_t n, const double c, complex_2d_array &a, const xparams _xparams)
4582 : {
4583 : jmp_buf _break_jump;
4584 : alglib_impl::ae_state _alglib_env_state;
4585 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4586 0 : if( setjmp(_break_jump) )
4587 : {
4588 : #if !defined(AE_NO_EXCEPTIONS)
4589 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4590 : #else
4591 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4592 : return;
4593 : #endif
4594 : }
4595 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4596 0 : if( _xparams.flags!=0x0 )
4597 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4598 0 : alglib_impl::cmatrixrndcond(n, c, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), &_alglib_env_state);
4599 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4600 0 : return;
4601 : }
4602 :
4603 : /*************************************************************************
4604 : Generation of random NxN symmetric matrix with given condition number and
4605 : norm2(A)=1
4606 :
4607 : INPUT PARAMETERS:
4608 : N - matrix size
4609 : C - condition number (in 2-norm)
4610 :
4611 : OUTPUT PARAMETERS:
4612 : A - random matrix with norm2(A)=1 and cond(A)=C
4613 :
4614 : -- ALGLIB routine --
4615 : 04.12.2009
4616 : Bochkanov Sergey
4617 : *************************************************************************/
4618 0 : void smatrixrndcond(const ae_int_t n, const double c, real_2d_array &a, const xparams _xparams)
4619 : {
4620 : jmp_buf _break_jump;
4621 : alglib_impl::ae_state _alglib_env_state;
4622 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4623 0 : if( setjmp(_break_jump) )
4624 : {
4625 : #if !defined(AE_NO_EXCEPTIONS)
4626 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4627 : #else
4628 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4629 : return;
4630 : #endif
4631 : }
4632 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4633 0 : if( _xparams.flags!=0x0 )
4634 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4635 0 : alglib_impl::smatrixrndcond(n, c, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), &_alglib_env_state);
4636 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4637 0 : return;
4638 : }
4639 :
4640 : /*************************************************************************
4641 : Generation of random NxN symmetric positive definite matrix with given
4642 : condition number and norm2(A)=1
4643 :
4644 : INPUT PARAMETERS:
4645 : N - matrix size
4646 : C - condition number (in 2-norm)
4647 :
4648 : OUTPUT PARAMETERS:
4649 : A - random SPD matrix with norm2(A)=1 and cond(A)=C
4650 :
4651 : -- ALGLIB routine --
4652 : 04.12.2009
4653 : Bochkanov Sergey
4654 : *************************************************************************/
4655 0 : void spdmatrixrndcond(const ae_int_t n, const double c, real_2d_array &a, const xparams _xparams)
4656 : {
4657 : jmp_buf _break_jump;
4658 : alglib_impl::ae_state _alglib_env_state;
4659 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4660 0 : if( setjmp(_break_jump) )
4661 : {
4662 : #if !defined(AE_NO_EXCEPTIONS)
4663 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4664 : #else
4665 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4666 : return;
4667 : #endif
4668 : }
4669 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4670 0 : if( _xparams.flags!=0x0 )
4671 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4672 0 : alglib_impl::spdmatrixrndcond(n, c, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), &_alglib_env_state);
4673 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4674 0 : return;
4675 : }
4676 :
4677 : /*************************************************************************
4678 : Generation of random NxN Hermitian matrix with given condition number and
4679 : norm2(A)=1
4680 :
4681 : INPUT PARAMETERS:
4682 : N - matrix size
4683 : C - condition number (in 2-norm)
4684 :
4685 : OUTPUT PARAMETERS:
4686 : A - random matrix with norm2(A)=1 and cond(A)=C
4687 :
4688 : -- ALGLIB routine --
4689 : 04.12.2009
4690 : Bochkanov Sergey
4691 : *************************************************************************/
4692 0 : void hmatrixrndcond(const ae_int_t n, const double c, complex_2d_array &a, const xparams _xparams)
4693 : {
4694 : jmp_buf _break_jump;
4695 : alglib_impl::ae_state _alglib_env_state;
4696 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4697 0 : if( setjmp(_break_jump) )
4698 : {
4699 : #if !defined(AE_NO_EXCEPTIONS)
4700 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4701 : #else
4702 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4703 : return;
4704 : #endif
4705 : }
4706 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4707 0 : if( _xparams.flags!=0x0 )
4708 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4709 0 : alglib_impl::hmatrixrndcond(n, c, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), &_alglib_env_state);
4710 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4711 0 : return;
4712 : }
4713 :
4714 : /*************************************************************************
4715 : Generation of random NxN Hermitian positive definite matrix with given
4716 : condition number and norm2(A)=1
4717 :
4718 : INPUT PARAMETERS:
4719 : N - matrix size
4720 : C - condition number (in 2-norm)
4721 :
4722 : OUTPUT PARAMETERS:
4723 : A - random HPD matrix with norm2(A)=1 and cond(A)=C
4724 :
4725 : -- ALGLIB routine --
4726 : 04.12.2009
4727 : Bochkanov Sergey
4728 : *************************************************************************/
4729 0 : void hpdmatrixrndcond(const ae_int_t n, const double c, complex_2d_array &a, const xparams _xparams)
4730 : {
4731 : jmp_buf _break_jump;
4732 : alglib_impl::ae_state _alglib_env_state;
4733 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4734 0 : if( setjmp(_break_jump) )
4735 : {
4736 : #if !defined(AE_NO_EXCEPTIONS)
4737 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4738 : #else
4739 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4740 : return;
4741 : #endif
4742 : }
4743 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4744 0 : if( _xparams.flags!=0x0 )
4745 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4746 0 : alglib_impl::hpdmatrixrndcond(n, c, const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), &_alglib_env_state);
4747 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4748 0 : return;
4749 : }
4750 :
4751 : /*************************************************************************
4752 : Multiplication of MxN matrix by NxN random Haar distributed orthogonal matrix
4753 :
4754 : INPUT PARAMETERS:
4755 : A - matrix, array[0..M-1, 0..N-1]
4756 : M, N- matrix size
4757 :
4758 : OUTPUT PARAMETERS:
4759 : A - A*Q, where Q is random NxN orthogonal matrix
4760 :
4761 : -- ALGLIB routine --
4762 : 04.12.2009
4763 : Bochkanov Sergey
4764 : *************************************************************************/
4765 0 : void rmatrixrndorthogonalfromtheright(real_2d_array &a, const ae_int_t m, const ae_int_t n, const xparams _xparams)
4766 : {
4767 : jmp_buf _break_jump;
4768 : alglib_impl::ae_state _alglib_env_state;
4769 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4770 0 : if( setjmp(_break_jump) )
4771 : {
4772 : #if !defined(AE_NO_EXCEPTIONS)
4773 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4774 : #else
4775 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4776 : return;
4777 : #endif
4778 : }
4779 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4780 0 : if( _xparams.flags!=0x0 )
4781 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4782 0 : alglib_impl::rmatrixrndorthogonalfromtheright(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, &_alglib_env_state);
4783 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4784 0 : return;
4785 : }
4786 :
4787 : /*************************************************************************
4788 : Multiplication of MxN matrix by MxM random Haar distributed orthogonal matrix
4789 :
4790 : INPUT PARAMETERS:
4791 : A - matrix, array[0..M-1, 0..N-1]
4792 : M, N- matrix size
4793 :
4794 : OUTPUT PARAMETERS:
4795 : A - Q*A, where Q is random MxM orthogonal matrix
4796 :
4797 : -- ALGLIB routine --
4798 : 04.12.2009
4799 : Bochkanov Sergey
4800 : *************************************************************************/
4801 0 : void rmatrixrndorthogonalfromtheleft(real_2d_array &a, const ae_int_t m, const ae_int_t n, const xparams _xparams)
4802 : {
4803 : jmp_buf _break_jump;
4804 : alglib_impl::ae_state _alglib_env_state;
4805 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4806 0 : if( setjmp(_break_jump) )
4807 : {
4808 : #if !defined(AE_NO_EXCEPTIONS)
4809 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4810 : #else
4811 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4812 : return;
4813 : #endif
4814 : }
4815 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4816 0 : if( _xparams.flags!=0x0 )
4817 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4818 0 : alglib_impl::rmatrixrndorthogonalfromtheleft(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, &_alglib_env_state);
4819 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4820 0 : return;
4821 : }
4822 :
4823 : /*************************************************************************
4824 : Multiplication of MxN complex matrix by NxN random Haar distributed
4825 : complex orthogonal matrix
4826 :
4827 : INPUT PARAMETERS:
4828 : A - matrix, array[0..M-1, 0..N-1]
4829 : M, N- matrix size
4830 :
4831 : OUTPUT PARAMETERS:
4832 : A - A*Q, where Q is random NxN orthogonal matrix
4833 :
4834 : -- ALGLIB routine --
4835 : 04.12.2009
4836 : Bochkanov Sergey
4837 : *************************************************************************/
4838 0 : void cmatrixrndorthogonalfromtheright(complex_2d_array &a, const ae_int_t m, const ae_int_t n, const xparams _xparams)
4839 : {
4840 : jmp_buf _break_jump;
4841 : alglib_impl::ae_state _alglib_env_state;
4842 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4843 0 : if( setjmp(_break_jump) )
4844 : {
4845 : #if !defined(AE_NO_EXCEPTIONS)
4846 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4847 : #else
4848 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4849 : return;
4850 : #endif
4851 : }
4852 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4853 0 : if( _xparams.flags!=0x0 )
4854 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4855 0 : alglib_impl::cmatrixrndorthogonalfromtheright(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, &_alglib_env_state);
4856 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4857 0 : return;
4858 : }
4859 :
4860 : /*************************************************************************
4861 : Multiplication of MxN complex matrix by MxM random Haar distributed
4862 : complex orthogonal matrix
4863 :
4864 : INPUT PARAMETERS:
4865 : A - matrix, array[0..M-1, 0..N-1]
4866 : M, N- matrix size
4867 :
4868 : OUTPUT PARAMETERS:
4869 : A - Q*A, where Q is random MxM orthogonal matrix
4870 :
4871 : -- ALGLIB routine --
4872 : 04.12.2009
4873 : Bochkanov Sergey
4874 : *************************************************************************/
4875 0 : void cmatrixrndorthogonalfromtheleft(complex_2d_array &a, const ae_int_t m, const ae_int_t n, const xparams _xparams)
4876 : {
4877 : jmp_buf _break_jump;
4878 : alglib_impl::ae_state _alglib_env_state;
4879 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4880 0 : if( setjmp(_break_jump) )
4881 : {
4882 : #if !defined(AE_NO_EXCEPTIONS)
4883 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4884 : #else
4885 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4886 : return;
4887 : #endif
4888 : }
4889 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4890 0 : if( _xparams.flags!=0x0 )
4891 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4892 0 : alglib_impl::cmatrixrndorthogonalfromtheleft(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, &_alglib_env_state);
4893 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4894 0 : return;
4895 : }
4896 :
4897 : /*************************************************************************
4898 : Symmetric multiplication of NxN matrix by random Haar distributed
4899 : orthogonal matrix
4900 :
4901 : INPUT PARAMETERS:
4902 : A - matrix, array[0..N-1, 0..N-1]
4903 : N - matrix size
4904 :
4905 : OUTPUT PARAMETERS:
4906 : A - Q'*A*Q, where Q is random NxN orthogonal matrix
4907 :
4908 : -- ALGLIB routine --
4909 : 04.12.2009
4910 : Bochkanov Sergey
4911 : *************************************************************************/
4912 0 : void smatrixrndmultiply(real_2d_array &a, const ae_int_t n, const xparams _xparams)
4913 : {
4914 : jmp_buf _break_jump;
4915 : alglib_impl::ae_state _alglib_env_state;
4916 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4917 0 : if( setjmp(_break_jump) )
4918 : {
4919 : #if !defined(AE_NO_EXCEPTIONS)
4920 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4921 : #else
4922 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4923 : return;
4924 : #endif
4925 : }
4926 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4927 0 : if( _xparams.flags!=0x0 )
4928 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4929 0 : alglib_impl::smatrixrndmultiply(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &_alglib_env_state);
4930 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4931 0 : return;
4932 : }
4933 :
4934 : /*************************************************************************
4935 : Hermitian multiplication of NxN matrix by random Haar distributed
4936 : complex orthogonal matrix
4937 :
4938 : INPUT PARAMETERS:
4939 : A - matrix, array[0..N-1, 0..N-1]
4940 : N - matrix size
4941 :
4942 : OUTPUT PARAMETERS:
4943 : A - Q^H*A*Q, where Q is random NxN orthogonal matrix
4944 :
4945 : -- ALGLIB routine --
4946 : 04.12.2009
4947 : Bochkanov Sergey
4948 : *************************************************************************/
4949 0 : void hmatrixrndmultiply(complex_2d_array &a, const ae_int_t n, const xparams _xparams)
4950 : {
4951 : jmp_buf _break_jump;
4952 : alglib_impl::ae_state _alglib_env_state;
4953 0 : alglib_impl::ae_state_init(&_alglib_env_state);
4954 0 : if( setjmp(_break_jump) )
4955 : {
4956 : #if !defined(AE_NO_EXCEPTIONS)
4957 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
4958 : #else
4959 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
4960 : return;
4961 : #endif
4962 : }
4963 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
4964 0 : if( _xparams.flags!=0x0 )
4965 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
4966 0 : alglib_impl::hmatrixrndmultiply(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &_alglib_env_state);
4967 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
4968 0 : return;
4969 : }
4970 : #endif
4971 :
4972 : #if defined(AE_COMPILE_TRFAC) || !defined(AE_PARTIAL_BUILD)
4973 : /*************************************************************************
4974 : An analysis of the sparse matrix decomposition, performed prior to actual
4975 : numerical factorization. You should not directly access fields of this
4976 : object - use appropriate ALGLIB functions to work with this object.
4977 : *************************************************************************/
4978 0 : _sparsedecompositionanalysis_owner::_sparsedecompositionanalysis_owner()
4979 : {
4980 : jmp_buf _break_jump;
4981 : alglib_impl::ae_state _state;
4982 :
4983 0 : alglib_impl::ae_state_init(&_state);
4984 0 : if( setjmp(_break_jump) )
4985 : {
4986 0 : if( p_struct!=NULL )
4987 : {
4988 0 : alglib_impl::_sparsedecompositionanalysis_destroy(p_struct);
4989 0 : alglib_impl::ae_free(p_struct);
4990 : }
4991 0 : p_struct = NULL;
4992 : #if !defined(AE_NO_EXCEPTIONS)
4993 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
4994 : #else
4995 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
4996 : return;
4997 : #endif
4998 : }
4999 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
5000 0 : p_struct = NULL;
5001 0 : p_struct = (alglib_impl::sparsedecompositionanalysis*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsedecompositionanalysis), &_state);
5002 0 : memset(p_struct, 0, sizeof(alglib_impl::sparsedecompositionanalysis));
5003 0 : alglib_impl::_sparsedecompositionanalysis_init(p_struct, &_state, ae_false);
5004 0 : ae_state_clear(&_state);
5005 0 : }
5006 :
5007 0 : _sparsedecompositionanalysis_owner::_sparsedecompositionanalysis_owner(const _sparsedecompositionanalysis_owner &rhs)
5008 : {
5009 : jmp_buf _break_jump;
5010 : alglib_impl::ae_state _state;
5011 :
5012 0 : alglib_impl::ae_state_init(&_state);
5013 0 : if( setjmp(_break_jump) )
5014 : {
5015 0 : if( p_struct!=NULL )
5016 : {
5017 0 : alglib_impl::_sparsedecompositionanalysis_destroy(p_struct);
5018 0 : alglib_impl::ae_free(p_struct);
5019 : }
5020 0 : p_struct = NULL;
5021 : #if !defined(AE_NO_EXCEPTIONS)
5022 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
5023 : #else
5024 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
5025 : return;
5026 : #endif
5027 : }
5028 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
5029 0 : p_struct = NULL;
5030 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsedecompositionanalysis copy constructor failure (source is not initialized)", &_state);
5031 0 : p_struct = (alglib_impl::sparsedecompositionanalysis*)alglib_impl::ae_malloc(sizeof(alglib_impl::sparsedecompositionanalysis), &_state);
5032 0 : memset(p_struct, 0, sizeof(alglib_impl::sparsedecompositionanalysis));
5033 0 : alglib_impl::_sparsedecompositionanalysis_init_copy(p_struct, const_cast<alglib_impl::sparsedecompositionanalysis*>(rhs.p_struct), &_state, ae_false);
5034 0 : ae_state_clear(&_state);
5035 0 : }
5036 :
5037 0 : _sparsedecompositionanalysis_owner& _sparsedecompositionanalysis_owner::operator=(const _sparsedecompositionanalysis_owner &rhs)
5038 : {
5039 0 : if( this==&rhs )
5040 0 : return *this;
5041 : jmp_buf _break_jump;
5042 : alglib_impl::ae_state _state;
5043 :
5044 0 : alglib_impl::ae_state_init(&_state);
5045 0 : if( setjmp(_break_jump) )
5046 : {
5047 : #if !defined(AE_NO_EXCEPTIONS)
5048 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
5049 : #else
5050 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
5051 : return *this;
5052 : #endif
5053 : }
5054 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
5055 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: sparsedecompositionanalysis assignment constructor failure (destination is not initialized)", &_state);
5056 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: sparsedecompositionanalysis assignment constructor failure (source is not initialized)", &_state);
5057 0 : alglib_impl::_sparsedecompositionanalysis_destroy(p_struct);
5058 0 : memset(p_struct, 0, sizeof(alglib_impl::sparsedecompositionanalysis));
5059 0 : alglib_impl::_sparsedecompositionanalysis_init_copy(p_struct, const_cast<alglib_impl::sparsedecompositionanalysis*>(rhs.p_struct), &_state, ae_false);
5060 0 : ae_state_clear(&_state);
5061 0 : return *this;
5062 : }
5063 :
5064 0 : _sparsedecompositionanalysis_owner::~_sparsedecompositionanalysis_owner()
5065 : {
5066 0 : if( p_struct!=NULL )
5067 : {
5068 0 : alglib_impl::_sparsedecompositionanalysis_destroy(p_struct);
5069 0 : ae_free(p_struct);
5070 : }
5071 0 : }
5072 :
5073 0 : alglib_impl::sparsedecompositionanalysis* _sparsedecompositionanalysis_owner::c_ptr()
5074 : {
5075 0 : return p_struct;
5076 : }
5077 :
5078 0 : alglib_impl::sparsedecompositionanalysis* _sparsedecompositionanalysis_owner::c_ptr() const
5079 : {
5080 0 : return const_cast<alglib_impl::sparsedecompositionanalysis*>(p_struct);
5081 : }
5082 0 : sparsedecompositionanalysis::sparsedecompositionanalysis() : _sparsedecompositionanalysis_owner()
5083 : {
5084 0 : }
5085 :
5086 0 : sparsedecompositionanalysis::sparsedecompositionanalysis(const sparsedecompositionanalysis &rhs):_sparsedecompositionanalysis_owner(rhs)
5087 : {
5088 0 : }
5089 :
5090 0 : sparsedecompositionanalysis& sparsedecompositionanalysis::operator=(const sparsedecompositionanalysis &rhs)
5091 : {
5092 0 : if( this==&rhs )
5093 0 : return *this;
5094 0 : _sparsedecompositionanalysis_owner::operator=(rhs);
5095 0 : return *this;
5096 : }
5097 :
5098 0 : sparsedecompositionanalysis::~sparsedecompositionanalysis()
5099 : {
5100 0 : }
5101 :
5102 : /*************************************************************************
5103 : LU decomposition of a general real matrix with row pivoting
5104 :
5105 : A is represented as A = P*L*U, where:
5106 : * L is lower unitriangular matrix
5107 : * U is upper triangular matrix
5108 : * P = P0*P1*...*PK, K=min(M,N)-1,
5109 : Pi - permutation matrix for I and Pivots[I]
5110 :
5111 : ! COMMERCIAL EDITION OF ALGLIB:
5112 : !
5113 : ! Commercial Edition of ALGLIB includes following important improvements
5114 : ! of this function:
5115 : ! * high-performance native backend with same C# interface (C# version)
5116 : ! * multithreading support (C++ and C# versions)
5117 : ! * hardware vendor (Intel) implementations of linear algebra primitives
5118 : ! (C++ and C# versions, x86/x64 platform)
5119 : !
5120 : ! We recommend you to read 'Working with commercial version' section of
5121 : ! ALGLIB Reference Manual in order to find out how to use performance-
5122 : ! related features provided by commercial edition of ALGLIB.
5123 :
5124 : INPUT PARAMETERS:
5125 : A - array[0..M-1, 0..N-1].
5126 : M - number of rows in matrix A.
5127 : N - number of columns in matrix A.
5128 :
5129 :
5130 : OUTPUT PARAMETERS:
5131 : A - matrices L and U in compact form:
5132 : * L is stored under main diagonal
5133 : * U is stored on and above main diagonal
5134 : Pivots - permutation matrix in compact form.
5135 : array[0..Min(M-1,N-1)].
5136 :
5137 : -- ALGLIB routine --
5138 : 10.01.2010
5139 : Bochkanov Sergey
5140 : *************************************************************************/
5141 0 : void rmatrixlu(real_2d_array &a, const ae_int_t m, const ae_int_t n, integer_1d_array &pivots, const xparams _xparams)
5142 : {
5143 : jmp_buf _break_jump;
5144 : alglib_impl::ae_state _alglib_env_state;
5145 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5146 0 : if( setjmp(_break_jump) )
5147 : {
5148 : #if !defined(AE_NO_EXCEPTIONS)
5149 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5150 : #else
5151 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5152 : return;
5153 : #endif
5154 : }
5155 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5156 0 : if( _xparams.flags!=0x0 )
5157 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5158 0 : alglib_impl::rmatrixlu(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(pivots.c_ptr()), &_alglib_env_state);
5159 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5160 0 : return;
5161 : }
5162 :
5163 : /*************************************************************************
5164 : LU decomposition of a general complex matrix with row pivoting
5165 :
5166 : A is represented as A = P*L*U, where:
5167 : * L is lower unitriangular matrix
5168 : * U is upper triangular matrix
5169 : * P = P0*P1*...*PK, K=min(M,N)-1,
5170 : Pi - permutation matrix for I and Pivots[I]
5171 :
5172 : ! COMMERCIAL EDITION OF ALGLIB:
5173 : !
5174 : ! Commercial Edition of ALGLIB includes following important improvements
5175 : ! of this function:
5176 : ! * high-performance native backend with same C# interface (C# version)
5177 : ! * multithreading support (C++ and C# versions)
5178 : ! * hardware vendor (Intel) implementations of linear algebra primitives
5179 : ! (C++ and C# versions, x86/x64 platform)
5180 : !
5181 : ! We recommend you to read 'Working with commercial version' section of
5182 : ! ALGLIB Reference Manual in order to find out how to use performance-
5183 : ! related features provided by commercial edition of ALGLIB.
5184 :
5185 : INPUT PARAMETERS:
5186 : A - array[0..M-1, 0..N-1].
5187 : M - number of rows in matrix A.
5188 : N - number of columns in matrix A.
5189 :
5190 :
5191 : OUTPUT PARAMETERS:
5192 : A - matrices L and U in compact form:
5193 : * L is stored under main diagonal
5194 : * U is stored on and above main diagonal
5195 : Pivots - permutation matrix in compact form.
5196 : array[0..Min(M-1,N-1)].
5197 :
5198 : -- ALGLIB routine --
5199 : 10.01.2010
5200 : Bochkanov Sergey
5201 : *************************************************************************/
5202 0 : void cmatrixlu(complex_2d_array &a, const ae_int_t m, const ae_int_t n, integer_1d_array &pivots, const xparams _xparams)
5203 : {
5204 : jmp_buf _break_jump;
5205 : alglib_impl::ae_state _alglib_env_state;
5206 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5207 0 : if( setjmp(_break_jump) )
5208 : {
5209 : #if !defined(AE_NO_EXCEPTIONS)
5210 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5211 : #else
5212 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5213 : return;
5214 : #endif
5215 : }
5216 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5217 0 : if( _xparams.flags!=0x0 )
5218 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5219 0 : alglib_impl::cmatrixlu(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(pivots.c_ptr()), &_alglib_env_state);
5220 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5221 0 : return;
5222 : }
5223 :
5224 : /*************************************************************************
5225 : Cache-oblivious Cholesky decomposition
5226 :
5227 : The algorithm computes Cholesky decomposition of a Hermitian positive-
5228 : definite matrix. The result of an algorithm is a representation of A as
5229 : A=U'*U or A=L*L' (here X' denotes conj(X^T)).
5230 :
5231 : ! COMMERCIAL EDITION OF ALGLIB:
5232 : !
5233 : ! Commercial Edition of ALGLIB includes following important improvements
5234 : ! of this function:
5235 : ! * high-performance native backend with same C# interface (C# version)
5236 : ! * multithreading support (C++ and C# versions)
5237 : ! * hardware vendor (Intel) implementations of linear algebra primitives
5238 : ! (C++ and C# versions, x86/x64 platform)
5239 : !
5240 : ! We recommend you to read 'Working with commercial version' section of
5241 : ! ALGLIB Reference Manual in order to find out how to use performance-
5242 : ! related features provided by commercial edition of ALGLIB.
5243 :
5244 : INPUT PARAMETERS:
5245 : A - upper or lower triangle of a factorized matrix.
5246 : array with elements [0..N-1, 0..N-1].
5247 : N - size of matrix A.
5248 : IsUpper - if IsUpper=True, then A contains an upper triangle of
5249 : a symmetric matrix, otherwise A contains a lower one.
5250 :
5251 : OUTPUT PARAMETERS:
5252 : A - the result of factorization. If IsUpper=True, then
5253 : the upper triangle contains matrix U, so that A = U'*U,
5254 : and the elements below the main diagonal are not modified.
5255 : Similarly, if IsUpper = False.
5256 :
5257 : RESULT:
5258 : If the matrix is positive-definite, the function returns True.
5259 : Otherwise, the function returns False. Contents of A is not determined
5260 : in such case.
5261 :
5262 : -- ALGLIB routine --
5263 : 15.12.2009-22.01.2018
5264 : Bochkanov Sergey
5265 : *************************************************************************/
5266 0 : bool hpdmatrixcholesky(complex_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams)
5267 : {
5268 : jmp_buf _break_jump;
5269 : alglib_impl::ae_state _alglib_env_state;
5270 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5271 0 : if( setjmp(_break_jump) )
5272 : {
5273 : #if !defined(AE_NO_EXCEPTIONS)
5274 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5275 : #else
5276 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5277 : return 0;
5278 : #endif
5279 : }
5280 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5281 0 : if( _xparams.flags!=0x0 )
5282 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5283 0 : ae_bool result = alglib_impl::hpdmatrixcholesky(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &_alglib_env_state);
5284 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5285 0 : return *(reinterpret_cast<bool*>(&result));
5286 : }
5287 :
5288 : /*************************************************************************
5289 : Cache-oblivious Cholesky decomposition
5290 :
5291 : The algorithm computes Cholesky decomposition of a symmetric positive-
5292 : definite matrix. The result of an algorithm is a representation of A as
5293 : A=U^T*U or A=L*L^T
5294 :
5295 : ! COMMERCIAL EDITION OF ALGLIB:
5296 : !
5297 : ! Commercial Edition of ALGLIB includes following important improvements
5298 : ! of this function:
5299 : ! * high-performance native backend with same C# interface (C# version)
5300 : ! * multithreading support (C++ and C# versions)
5301 : ! * hardware vendor (Intel) implementations of linear algebra primitives
5302 : ! (C++ and C# versions, x86/x64 platform)
5303 : !
5304 : ! We recommend you to read 'Working with commercial version' section of
5305 : ! ALGLIB Reference Manual in order to find out how to use performance-
5306 : ! related features provided by commercial edition of ALGLIB.
5307 :
5308 : INPUT PARAMETERS:
5309 : A - upper or lower triangle of a factorized matrix.
5310 : array with elements [0..N-1, 0..N-1].
5311 : N - size of matrix A.
5312 : IsUpper - if IsUpper=True, then A contains an upper triangle of
5313 : a symmetric matrix, otherwise A contains a lower one.
5314 :
5315 : OUTPUT PARAMETERS:
5316 : A - the result of factorization. If IsUpper=True, then
5317 : the upper triangle contains matrix U, so that A = U^T*U,
5318 : and the elements below the main diagonal are not modified.
5319 : Similarly, if IsUpper = False.
5320 :
5321 : RESULT:
5322 : If the matrix is positive-definite, the function returns True.
5323 : Otherwise, the function returns False. Contents of A is not determined
5324 : in such case.
5325 :
5326 : -- ALGLIB routine --
5327 : 15.12.2009
5328 : Bochkanov Sergey
5329 : *************************************************************************/
5330 0 : bool spdmatrixcholesky(real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams)
5331 : {
5332 : jmp_buf _break_jump;
5333 : alglib_impl::ae_state _alglib_env_state;
5334 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5335 0 : if( setjmp(_break_jump) )
5336 : {
5337 : #if !defined(AE_NO_EXCEPTIONS)
5338 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5339 : #else
5340 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5341 : return 0;
5342 : #endif
5343 : }
5344 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5345 0 : if( _xparams.flags!=0x0 )
5346 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5347 0 : ae_bool result = alglib_impl::spdmatrixcholesky(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &_alglib_env_state);
5348 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5349 0 : return *(reinterpret_cast<bool*>(&result));
5350 : }
5351 :
5352 : /*************************************************************************
5353 : Update of Cholesky decomposition: rank-1 update to original A. "Buffered"
5354 : version which uses preallocated buffer which is saved between subsequent
5355 : function calls.
5356 :
5357 : This function uses internally allocated buffer which is not saved between
5358 : subsequent calls. So, if you perform a lot of subsequent updates,
5359 : we recommend you to use "buffered" version of this function:
5360 : SPDMatrixCholeskyUpdateAdd1Buf().
5361 :
5362 : INPUT PARAMETERS:
5363 : A - upper or lower Cholesky factor.
5364 : array with elements [0..N-1, 0..N-1].
5365 : Exception is thrown if array size is too small.
5366 : N - size of matrix A, N>0
5367 : IsUpper - if IsUpper=True, then A contains upper Cholesky factor;
5368 : otherwise A contains a lower one.
5369 : U - array[N], rank-1 update to A: A_mod = A + u*u'
5370 : Exception is thrown if array size is too small.
5371 : BufR - possibly preallocated buffer; automatically resized if
5372 : needed. It is recommended to reuse this buffer if you
5373 : perform a lot of subsequent decompositions.
5374 :
5375 : OUTPUT PARAMETERS:
5376 : A - updated factorization. If IsUpper=True, then the upper
5377 : triangle contains matrix U, and the elements below the main
5378 : diagonal are not modified. Similarly, if IsUpper = False.
5379 :
5380 : NOTE: this function always succeeds, so it does not return completion code
5381 :
5382 : NOTE: this function checks sizes of input arrays, but it does NOT checks
5383 : for presence of infinities or NAN's.
5384 :
5385 : -- ALGLIB --
5386 : 03.02.2014
5387 : Sergey Bochkanov
5388 : *************************************************************************/
5389 0 : void spdmatrixcholeskyupdateadd1(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &u, const xparams _xparams)
5390 : {
5391 : jmp_buf _break_jump;
5392 : alglib_impl::ae_state _alglib_env_state;
5393 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5394 0 : if( setjmp(_break_jump) )
5395 : {
5396 : #if !defined(AE_NO_EXCEPTIONS)
5397 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5398 : #else
5399 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5400 : return;
5401 : #endif
5402 : }
5403 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5404 0 : if( _xparams.flags!=0x0 )
5405 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5406 0 : alglib_impl::spdmatrixcholeskyupdateadd1(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, const_cast<alglib_impl::ae_vector*>(u.c_ptr()), &_alglib_env_state);
5407 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5408 0 : return;
5409 : }
5410 :
5411 : /*************************************************************************
5412 : Update of Cholesky decomposition: "fixing" some variables.
5413 :
5414 : This function uses internally allocated buffer which is not saved between
5415 : subsequent calls. So, if you perform a lot of subsequent updates,
5416 : we recommend you to use "buffered" version of this function:
5417 : SPDMatrixCholeskyUpdateFixBuf().
5418 :
5419 : "FIXING" EXPLAINED:
5420 :
5421 : Suppose we have N*N positive definite matrix A. "Fixing" some variable
5422 : means filling corresponding row/column of A by zeros, and setting
5423 : diagonal element to 1.
5424 :
5425 : For example, if we fix 2nd variable in 4*4 matrix A, it becomes Af:
5426 :
5427 : ( A00 A01 A02 A03 ) ( Af00 0 Af02 Af03 )
5428 : ( A10 A11 A12 A13 ) ( 0 1 0 0 )
5429 : ( A20 A21 A22 A23 ) => ( Af20 0 Af22 Af23 )
5430 : ( A30 A31 A32 A33 ) ( Af30 0 Af32 Af33 )
5431 :
5432 : If we have Cholesky decomposition of A, it must be recalculated after
5433 : variables were fixed. However, it is possible to use efficient
5434 : algorithm, which needs O(K*N^2) time to "fix" K variables, given
5435 : Cholesky decomposition of original, "unfixed" A.
5436 :
5437 : INPUT PARAMETERS:
5438 : A - upper or lower Cholesky factor.
5439 : array with elements [0..N-1, 0..N-1].
5440 : Exception is thrown if array size is too small.
5441 : N - size of matrix A, N>0
5442 : IsUpper - if IsUpper=True, then A contains upper Cholesky factor;
5443 : otherwise A contains a lower one.
5444 : Fix - array[N], I-th element is True if I-th variable must be
5445 : fixed. Exception is thrown if array size is too small.
5446 : BufR - possibly preallocated buffer; automatically resized if
5447 : needed. It is recommended to reuse this buffer if you
5448 : perform a lot of subsequent decompositions.
5449 :
5450 : OUTPUT PARAMETERS:
5451 : A - updated factorization. If IsUpper=True, then the upper
5452 : triangle contains matrix U, and the elements below the main
5453 : diagonal are not modified. Similarly, if IsUpper = False.
5454 :
5455 : NOTE: this function always succeeds, so it does not return completion code
5456 :
5457 : NOTE: this function checks sizes of input arrays, but it does NOT checks
5458 : for presence of infinities or NAN's.
5459 :
5460 : NOTE: this function is efficient only for moderate amount of updated
5461 : variables - say, 0.1*N or 0.3*N. For larger amount of variables it
5462 : will still work, but you may get better performance with
5463 : straightforward Cholesky.
5464 :
5465 : -- ALGLIB --
5466 : 03.02.2014
5467 : Sergey Bochkanov
5468 : *************************************************************************/
5469 0 : void spdmatrixcholeskyupdatefix(const real_2d_array &a, const ae_int_t n, const bool isupper, const boolean_1d_array &fix, const xparams _xparams)
5470 : {
5471 : jmp_buf _break_jump;
5472 : alglib_impl::ae_state _alglib_env_state;
5473 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5474 0 : if( setjmp(_break_jump) )
5475 : {
5476 : #if !defined(AE_NO_EXCEPTIONS)
5477 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5478 : #else
5479 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5480 : return;
5481 : #endif
5482 : }
5483 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5484 0 : if( _xparams.flags!=0x0 )
5485 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5486 0 : alglib_impl::spdmatrixcholeskyupdatefix(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, const_cast<alglib_impl::ae_vector*>(fix.c_ptr()), &_alglib_env_state);
5487 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5488 0 : return;
5489 : }
5490 :
5491 : /*************************************************************************
5492 : Update of Cholesky decomposition: rank-1 update to original A. "Buffered"
5493 : version which uses preallocated buffer which is saved between subsequent
5494 : function calls.
5495 :
5496 : See comments for SPDMatrixCholeskyUpdateAdd1() for more information.
5497 :
5498 : INPUT PARAMETERS:
5499 : A - upper or lower Cholesky factor.
5500 : array with elements [0..N-1, 0..N-1].
5501 : Exception is thrown if array size is too small.
5502 : N - size of matrix A, N>0
5503 : IsUpper - if IsUpper=True, then A contains upper Cholesky factor;
5504 : otherwise A contains a lower one.
5505 : U - array[N], rank-1 update to A: A_mod = A + u*u'
5506 : Exception is thrown if array size is too small.
5507 : BufR - possibly preallocated buffer; automatically resized if
5508 : needed. It is recommended to reuse this buffer if you
5509 : perform a lot of subsequent decompositions.
5510 :
5511 : OUTPUT PARAMETERS:
5512 : A - updated factorization. If IsUpper=True, then the upper
5513 : triangle contains matrix U, and the elements below the main
5514 : diagonal are not modified. Similarly, if IsUpper = False.
5515 :
5516 : -- ALGLIB --
5517 : 03.02.2014
5518 : Sergey Bochkanov
5519 : *************************************************************************/
5520 0 : void spdmatrixcholeskyupdateadd1buf(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &u, real_1d_array &bufr, const xparams _xparams)
5521 : {
5522 : jmp_buf _break_jump;
5523 : alglib_impl::ae_state _alglib_env_state;
5524 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5525 0 : if( setjmp(_break_jump) )
5526 : {
5527 : #if !defined(AE_NO_EXCEPTIONS)
5528 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5529 : #else
5530 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5531 : return;
5532 : #endif
5533 : }
5534 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5535 0 : if( _xparams.flags!=0x0 )
5536 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5537 0 : alglib_impl::spdmatrixcholeskyupdateadd1buf(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, const_cast<alglib_impl::ae_vector*>(u.c_ptr()), const_cast<alglib_impl::ae_vector*>(bufr.c_ptr()), &_alglib_env_state);
5538 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5539 0 : return;
5540 : }
5541 :
5542 : /*************************************************************************
5543 : Update of Cholesky decomposition: "fixing" some variables. "Buffered"
5544 : version which uses preallocated buffer which is saved between subsequent
5545 : function calls.
5546 :
5547 : See comments for SPDMatrixCholeskyUpdateFix() for more information.
5548 :
5549 : INPUT PARAMETERS:
5550 : A - upper or lower Cholesky factor.
5551 : array with elements [0..N-1, 0..N-1].
5552 : Exception is thrown if array size is too small.
5553 : N - size of matrix A, N>0
5554 : IsUpper - if IsUpper=True, then A contains upper Cholesky factor;
5555 : otherwise A contains a lower one.
5556 : Fix - array[N], I-th element is True if I-th variable must be
5557 : fixed. Exception is thrown if array size is too small.
5558 : BufR - possibly preallocated buffer; automatically resized if
5559 : needed. It is recommended to reuse this buffer if you
5560 : perform a lot of subsequent decompositions.
5561 :
5562 : OUTPUT PARAMETERS:
5563 : A - updated factorization. If IsUpper=True, then the upper
5564 : triangle contains matrix U, and the elements below the main
5565 : diagonal are not modified. Similarly, if IsUpper = False.
5566 :
5567 : -- ALGLIB --
5568 : 03.02.2014
5569 : Sergey Bochkanov
5570 : *************************************************************************/
5571 0 : void spdmatrixcholeskyupdatefixbuf(const real_2d_array &a, const ae_int_t n, const bool isupper, const boolean_1d_array &fix, real_1d_array &bufr, const xparams _xparams)
5572 : {
5573 : jmp_buf _break_jump;
5574 : alglib_impl::ae_state _alglib_env_state;
5575 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5576 0 : if( setjmp(_break_jump) )
5577 : {
5578 : #if !defined(AE_NO_EXCEPTIONS)
5579 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5580 : #else
5581 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5582 : return;
5583 : #endif
5584 : }
5585 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5586 0 : if( _xparams.flags!=0x0 )
5587 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5588 0 : alglib_impl::spdmatrixcholeskyupdatefixbuf(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, const_cast<alglib_impl::ae_vector*>(fix.c_ptr()), const_cast<alglib_impl::ae_vector*>(bufr.c_ptr()), &_alglib_env_state);
5589 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5590 0 : return;
5591 : }
5592 :
5593 : /*************************************************************************
5594 : Sparse LU decomposition with column pivoting for sparsity and row pivoting
5595 : for stability. Input must be square sparse matrix stored in CRS format.
5596 :
5597 : The algorithm computes LU decomposition of a general square matrix
5598 : (rectangular ones are not supported). The result of an algorithm is a
5599 : representation of A as A = P*L*U*Q, where:
5600 : * L is lower unitriangular matrix
5601 : * U is upper triangular matrix
5602 : * P = P0*P1*...*PK, K=N-1, Pi - permutation matrix for I and P[I]
5603 : * Q = QK*...*Q1*Q0, K=N-1, Qi - permutation matrix for I and Q[I]
5604 :
5605 : This function pivots columns for higher sparsity, and then pivots rows for
5606 : stability (larger element at the diagonal).
5607 :
5608 : INPUT PARAMETERS:
5609 : A - sparse NxN matrix in CRS format. An exception is generated
5610 : if matrix is non-CRS or non-square.
5611 : PivotType- pivoting strategy:
5612 : * 0 for best pivoting available (2 in current version)
5613 : * 1 for row-only pivoting (NOT RECOMMENDED)
5614 : * 2 for complete pivoting which produces most sparse outputs
5615 :
5616 : OUTPUT PARAMETERS:
5617 : A - the result of factorization, matrices L and U stored in
5618 : compact form using CRS sparse storage format:
5619 : * lower unitriangular L is stored strictly under main diagonal
5620 : * upper triangilar U is stored ON and ABOVE main diagonal
5621 : P - row permutation matrix in compact form, array[N]
5622 : Q - col permutation matrix in compact form, array[N]
5623 :
5624 : This function always succeeds, i.e. it ALWAYS returns valid factorization,
5625 : but for your convenience it also returns boolean value which helps to
5626 : detect symbolically degenerate matrices:
5627 : * function returns TRUE, if the matrix was factorized AND symbolically
5628 : non-degenerate
5629 : * function returns FALSE, if the matrix was factorized but U has strictly
5630 : zero elements at the diagonal (the factorization is returned anyway).
5631 :
5632 :
5633 : -- ALGLIB routine --
5634 : 03.09.2018
5635 : Bochkanov Sergey
5636 : *************************************************************************/
5637 0 : bool sparselu(const sparsematrix &a, const ae_int_t pivottype, integer_1d_array &p, integer_1d_array &q, const xparams _xparams)
5638 : {
5639 : jmp_buf _break_jump;
5640 : alglib_impl::ae_state _alglib_env_state;
5641 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5642 0 : if( setjmp(_break_jump) )
5643 : {
5644 : #if !defined(AE_NO_EXCEPTIONS)
5645 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5646 : #else
5647 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5648 : return 0;
5649 : #endif
5650 : }
5651 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5652 0 : if( _xparams.flags!=0x0 )
5653 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5654 0 : ae_bool result = alglib_impl::sparselu(const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), pivottype, const_cast<alglib_impl::ae_vector*>(p.c_ptr()), const_cast<alglib_impl::ae_vector*>(q.c_ptr()), &_alglib_env_state);
5655 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5656 0 : return *(reinterpret_cast<bool*>(&result));
5657 : }
5658 :
5659 : /*************************************************************************
5660 : Sparse Cholesky decomposition for skyline matrixm using in-place algorithm
5661 : without allocating additional storage.
5662 :
5663 : The algorithm computes Cholesky decomposition of a symmetric positive-
5664 : definite sparse matrix. The result of an algorithm is a representation of
5665 : A as A=U^T*U or A=L*L^T
5666 :
5667 : This function allows to perform very efficient decomposition of low-profile
5668 : matrices (average bandwidth is ~5-10 elements). For larger matrices it is
5669 : recommended to use supernodal Cholesky decomposition: SparseCholeskyP() or
5670 : SparseCholeskyAnalyze()/SparseCholeskyFactorize().
5671 :
5672 : INPUT PARAMETERS:
5673 : A - sparse matrix in skyline storage (SKS) format.
5674 : N - size of matrix A (can be smaller than actual size of A)
5675 : IsUpper - if IsUpper=True, then factorization is performed on upper
5676 : triangle. Another triangle is ignored (it may contant some
5677 : data, but it is not changed).
5678 :
5679 :
5680 : OUTPUT PARAMETERS:
5681 : A - the result of factorization, stored in SKS. If IsUpper=True,
5682 : then the upper triangle contains matrix U, such that
5683 : A = U^T*U. Lower triangle is not changed.
5684 : Similarly, if IsUpper = False. In this case L is returned,
5685 : and we have A = L*(L^T).
5686 : Note that THIS function does not perform permutation of
5687 : rows to reduce bandwidth.
5688 :
5689 : RESULT:
5690 : If the matrix is positive-definite, the function returns True.
5691 : Otherwise, the function returns False. Contents of A is not determined
5692 : in such case.
5693 :
5694 : NOTE: for performance reasons this function does NOT check that input
5695 : matrix includes only finite values. It is your responsibility to
5696 : make sure that there are no infinite or NAN values in the matrix.
5697 :
5698 : -- ALGLIB routine --
5699 : 16.01.2014
5700 : Bochkanov Sergey
5701 : *************************************************************************/
5702 0 : bool sparsecholeskyskyline(const sparsematrix &a, const ae_int_t n, const bool isupper, const xparams _xparams)
5703 : {
5704 : jmp_buf _break_jump;
5705 : alglib_impl::ae_state _alglib_env_state;
5706 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5707 0 : if( setjmp(_break_jump) )
5708 : {
5709 : #if !defined(AE_NO_EXCEPTIONS)
5710 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5711 : #else
5712 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5713 : return 0;
5714 : #endif
5715 : }
5716 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5717 0 : if( _xparams.flags!=0x0 )
5718 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5719 0 : ae_bool result = alglib_impl::sparsecholeskyskyline(const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), n, isupper, &_alglib_env_state);
5720 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5721 0 : return *(reinterpret_cast<bool*>(&result));
5722 : }
5723 :
5724 : /*************************************************************************
5725 : Sparse Cholesky decomposition for a matrix stored in any sparse storage,
5726 : without rows/cols permutation.
5727 :
5728 : This function is the most convenient (less parameters to specify), although
5729 : less efficient, version of sparse Cholesky.
5730 :
5731 : Internally it:
5732 : * calls SparseCholeskyAnalyze() function to perform symbolic analysis
5733 : phase with no permutation being configured.
5734 : * calls SparseCholeskyFactorize() function to perform numerical phase of
5735 : the factorization
5736 :
5737 : Following alternatives may result in better performance:
5738 : * using SparseCholeskyP(), which selects best pivoting available, which
5739 : almost always results in improved sparsity and cache locality
5740 : * using SparseCholeskyAnalyze() and SparseCholeskyFactorize() functions
5741 : directly, which may improve performance of repetitive factorizations
5742 : with same sparsity patterns.
5743 :
5744 : The latter also allows one to perform LDLT factorization of indefinite
5745 : matrix (one with strictly diagonal D, which is known to be stable only
5746 : in few special cases, like quasi-definite matrices).
5747 :
5748 : INPUT PARAMETERS:
5749 : A - a square NxN sparse matrix, stored in any storage format.
5750 : IsUpper - if IsUpper=True, then factorization is performed on upper
5751 : triangle. Another triangle is ignored on input, dropped
5752 : on output. Similarly, if IsUpper=False, the lower triangle
5753 : is processed.
5754 :
5755 : OUTPUT PARAMETERS:
5756 : A - the result of factorization, stored in CRS format:
5757 : * if IsUpper=True, then the upper triangle contains matrix
5758 : U such that A = U^T*U and the lower triangle is empty.
5759 : * similarly, if IsUpper=False, then lower triangular L is
5760 : returned and we have A = L*(L^T).
5761 : Note that THIS function does not perform permutation of
5762 : the rows to reduce fill-in.
5763 :
5764 : RESULT:
5765 : If the matrix is positive-definite, the function returns True.
5766 : Otherwise, the function returns False. Contents of A is undefined
5767 : in such case.
5768 :
5769 : NOTE: for performance reasons this function does NOT check that input
5770 : matrix includes only finite values. It is your responsibility to
5771 : make sure that there are no infinite or NAN values in the matrix.
5772 :
5773 : -- ALGLIB routine --
5774 : 16.09.2020
5775 : Bochkanov Sergey
5776 : *************************************************************************/
5777 0 : bool sparsecholesky(const sparsematrix &a, const bool isupper, const xparams _xparams)
5778 : {
5779 : jmp_buf _break_jump;
5780 : alglib_impl::ae_state _alglib_env_state;
5781 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5782 0 : if( setjmp(_break_jump) )
5783 : {
5784 : #if !defined(AE_NO_EXCEPTIONS)
5785 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5786 : #else
5787 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5788 : return 0;
5789 : #endif
5790 : }
5791 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5792 0 : if( _xparams.flags!=0x0 )
5793 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5794 0 : ae_bool result = alglib_impl::sparsecholesky(const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), isupper, &_alglib_env_state);
5795 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5796 0 : return *(reinterpret_cast<bool*>(&result));
5797 : }
5798 :
5799 : /*************************************************************************
5800 : Sparse Cholesky decomposition for a matrix stored in any sparse storage
5801 : format, with performance-enhancing permutation of rows/cols.
5802 :
5803 : Present version is configured to perform supernodal permutation which
5804 : sparsity reducing ordering.
5805 :
5806 : This function is a wrapper around generic sparse decomposition functions
5807 : that internally:
5808 : * calls SparseCholeskyAnalyze() function to perform symbolic analysis
5809 : phase with best available permutation being configured.
5810 : * calls SparseCholeskyFactorize() function to perform numerical phase of
5811 : the factorization.
5812 :
5813 : NOTE: using SparseCholeskyAnalyze() and SparseCholeskyFactorize() directly
5814 : may improve performance of repetitive factorizations with same
5815 : sparsity patterns. It also allows one to perform LDLT factorization
5816 : of indefinite matrix - a factorization with strictly diagonal D,
5817 : which is known to be stable only in few special cases, like quasi-
5818 : definite matrices.
5819 :
5820 : INPUT PARAMETERS:
5821 : A - a square NxN sparse matrix, stored in any storage format.
5822 : IsUpper - if IsUpper=True, then factorization is performed on upper
5823 : triangle. Another triangle is ignored on input, dropped
5824 : on output. Similarly, if IsUpper=False, the lower triangle
5825 : is processed.
5826 :
5827 : OUTPUT PARAMETERS:
5828 : A - the result of factorization, stored in CRS format:
5829 : * if IsUpper=True, then the upper triangle contains matrix
5830 : U such that A = U^T*U and the lower triangle is empty.
5831 : * similarly, if IsUpper=False, then lower triangular L is
5832 : returned and we have A = L*(L^T).
5833 : P - a row/column permutation, a product of P0*P1*...*Pk, k=N-1,
5834 : with Pi being permutation of rows/cols I and P[I]
5835 :
5836 : RESULT:
5837 : If the matrix is positive-definite, the function returns True.
5838 : Otherwise, the function returns False. Contents of A is undefined
5839 : in such case.
5840 :
5841 : NOTE: for performance reasons this function does NOT check that input
5842 : matrix includes only finite values. It is your responsibility to
5843 : make sure that there are no infinite or NAN values in the matrix.
5844 :
5845 : -- ALGLIB routine --
5846 : 16.09.2020
5847 : Bochkanov Sergey
5848 : *************************************************************************/
5849 0 : bool sparsecholeskyp(const sparsematrix &a, const bool isupper, integer_1d_array &p, const xparams _xparams)
5850 : {
5851 : jmp_buf _break_jump;
5852 : alglib_impl::ae_state _alglib_env_state;
5853 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5854 0 : if( setjmp(_break_jump) )
5855 : {
5856 : #if !defined(AE_NO_EXCEPTIONS)
5857 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5858 : #else
5859 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5860 : return 0;
5861 : #endif
5862 : }
5863 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5864 0 : if( _xparams.flags!=0x0 )
5865 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5866 0 : ae_bool result = alglib_impl::sparsecholeskyp(const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), isupper, const_cast<alglib_impl::ae_vector*>(p.c_ptr()), &_alglib_env_state);
5867 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5868 0 : return *(reinterpret_cast<bool*>(&result));
5869 : }
5870 :
5871 : /*************************************************************************
5872 : Sparse Cholesky/LDLT decomposition: symbolic analysis phase.
5873 :
5874 : This function is a part of the 'expert' sparse Cholesky API:
5875 : * SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads
5876 : matrix to be factorized into internal storage
5877 : * SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT
5878 : with lower bounds on pivot magnitudes and additional overflow safeguards
5879 : * SparseCholeskyFactorize(), that performs numeric factorization using
5880 : precomputed symbolic analysis and internally stored matrix - and outputs
5881 : result
5882 : * SparseCholeskyReload(), that reloads one more matrix with same sparsity
5883 : pattern into internal storage so one may reuse previously allocated
5884 : temporaries and previously performed symbolic analysis
5885 :
5886 : This specific function performs preliminary analysis of the Cholesky/LDLT
5887 : factorization. It allows to choose different permutation types and to
5888 : choose between classic Cholesky and indefinite LDLT factorization (the
5889 : latter is computed with strictly diagonal D, i.e. without Bunch-Kauffman
5890 : pivoting).
5891 :
5892 : NOTE: L*D*LT family of factorization may be used to factorize indefinite
5893 : matrices. However, numerical stability is guaranteed ONLY for a class
5894 : of quasi-definite matrices.
5895 :
5896 : NOTE: all internal processing is performed with lower triangular matrices
5897 : stored in CRS format. Any other storage formats and/or upper
5898 : triangular storage means that one format conversion and/or one
5899 : transposition will be performed internally for the analysis and
5900 : factorization phases. Thus, highest performance is achieved when
5901 : input is a lower triangular CRS matrix.
5902 :
5903 : INPUT PARAMETERS:
5904 : A - sparse square matrix in any sparse storage format.
5905 : IsUpper - whether upper or lower triangle is decomposed (the
5906 : other one is ignored).
5907 : FactType - factorization type:
5908 : * 0 for traditional Cholesky of SPD matrix
5909 : * 1 for LDLT decomposition with strictly diagonal D,
5910 : which may have non-positive entries.
5911 : PermType - permutation type:
5912 : *-1 for absence of permutation
5913 : * 0 for best fill-in reducing permutation available
5914 : * 1 for supernodal ordering (improves locality and
5915 : performance, does NOT change fill-in factor)
5916 : * 2 for AMD (approximate minimum degree) ordering
5917 :
5918 : OUTPUT PARAMETERS:
5919 : Analysis - contains:
5920 : * symbolic analysis of the matrix structure which will
5921 : be used later to guide numerical factorization.
5922 : * specific numeric values loaded into internal memory
5923 : waiting for the factorization to be performed
5924 :
5925 : This function fails if and only if the matrix A is symbolically degenerate
5926 : i.e. has diagonal element which is exactly zero. In such case False is
5927 : returned, contents of Analysis object is undefined.
5928 :
5929 : -- ALGLIB routine --
5930 : 20.09.2020
5931 : Bochkanov Sergey
5932 : *************************************************************************/
5933 0 : bool sparsecholeskyanalyze(const sparsematrix &a, const bool isupper, const ae_int_t facttype, const ae_int_t permtype, sparsedecompositionanalysis &analysis, const xparams _xparams)
5934 : {
5935 : jmp_buf _break_jump;
5936 : alglib_impl::ae_state _alglib_env_state;
5937 0 : alglib_impl::ae_state_init(&_alglib_env_state);
5938 0 : if( setjmp(_break_jump) )
5939 : {
5940 : #if !defined(AE_NO_EXCEPTIONS)
5941 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
5942 : #else
5943 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
5944 : return 0;
5945 : #endif
5946 : }
5947 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
5948 0 : if( _xparams.flags!=0x0 )
5949 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
5950 0 : ae_bool result = alglib_impl::sparsecholeskyanalyze(const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), isupper, facttype, permtype, const_cast<alglib_impl::sparsedecompositionanalysis*>(analysis.c_ptr()), &_alglib_env_state);
5951 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
5952 0 : return *(reinterpret_cast<bool*>(&result));
5953 : }
5954 :
5955 : /*************************************************************************
5956 : Sparse Cholesky decomposition: numerical analysis phase.
5957 :
5958 : This function is a part of the 'expert' sparse Cholesky API:
5959 : * SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads
5960 : matrix to be factorized into internal storage
5961 : * SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT
5962 : with lower bounds on pivot magnitudes and additional overflow safeguards
5963 : * SparseCholeskyFactorize(), that performs numeric factorization using
5964 : precomputed symbolic analysis and internally stored matrix - and outputs
5965 : result
5966 : * SparseCholeskyReload(), that reloads one more matrix with same sparsity
5967 : pattern into internal storage so one may reuse previously allocated
5968 : temporaries and previously performed symbolic analysis
5969 :
5970 : Depending on settings specified during SparseCholeskyAnalyze() call it may
5971 : produce classic Cholesky or L*D*LT decomposition (with strictly diagonal
5972 : D), without permutation or with performance-enhancing permutation P.
5973 :
5974 : NOTE: all internal processing is performed with lower triangular matrices
5975 : stored in CRS format. Any other storage formats and/or upper
5976 : triangular storage means that one format conversion and/or one
5977 : transposition will be performed internally for the analysis and
5978 : factorization phases. Thus, highest performance is achieved when
5979 : input is a lower triangular CRS matrix, and lower triangular output
5980 : is requested.
5981 :
5982 : NOTE: L*D*LT family of factorization may be used to factorize indefinite
5983 : matrices. However, numerical stability is guaranteed ONLY for a class
5984 : of quasi-definite matrices.
5985 :
5986 : INPUT PARAMETERS:
5987 : Analysis - prior analysis with internally stored matrix which will
5988 : be factorized
5989 : NeedUpper - whether upper triangular or lower triangular output is
5990 : needed
5991 :
5992 : OUTPUT PARAMETERS:
5993 : A - Cholesky decomposition of A stored in lower triangular
5994 : CRS format, i.e. A=L*L' (or upper triangular CRS, with
5995 : A=U'*U, depending on NeedUpper parameter).
5996 : D - array[N], diagonal factor. If no diagonal factor was
5997 : required during analysis phase, still returned but
5998 : filled with 1's
5999 : P - array[N], pivots. Permutation matrix P is a product of
6000 : P(0)*P(1)*...*P(N-1), where P(i) is a permutation of
6001 : row/col I and P[I] (with P[I]>=I).
6002 : If no permutation was requested during analysis phase,
6003 : still returned but filled with identity permutation.
6004 :
6005 : The function returns True when factorization resulted in nondegenerate
6006 : matrix. False is returned when factorization fails (Cholesky factorization
6007 : of indefinite matrix) or LDLT factorization has exactly zero elements at
6008 : the diagonal. In the latter case contents of A, D and P is undefined.
6009 :
6010 : The analysis object is not changed during the factorization. Subsequent
6011 : calls to SparseCholeskyFactorize() will result in same factorization being
6012 : performed one more time.
6013 :
6014 : -- ALGLIB routine --
6015 : 20.09.2020
6016 : Bochkanov Sergey
6017 : *************************************************************************/
6018 0 : bool sparsecholeskyfactorize(const sparsedecompositionanalysis &analysis, const bool needupper, sparsematrix &a, real_1d_array &d, integer_1d_array &p, const xparams _xparams)
6019 : {
6020 : jmp_buf _break_jump;
6021 : alglib_impl::ae_state _alglib_env_state;
6022 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6023 0 : if( setjmp(_break_jump) )
6024 : {
6025 : #if !defined(AE_NO_EXCEPTIONS)
6026 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6027 : #else
6028 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6029 : return 0;
6030 : #endif
6031 : }
6032 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6033 0 : if( _xparams.flags!=0x0 )
6034 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6035 0 : ae_bool result = alglib_impl::sparsecholeskyfactorize(const_cast<alglib_impl::sparsedecompositionanalysis*>(analysis.c_ptr()), needupper, const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_vector*>(p.c_ptr()), &_alglib_env_state);
6036 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6037 0 : return *(reinterpret_cast<bool*>(&result));
6038 : }
6039 :
6040 : /*************************************************************************
6041 : Sparse Cholesky decomposition: update internally stored matrix with
6042 : another one with exactly same sparsity pattern.
6043 :
6044 : This function is a part of the 'expert' sparse Cholesky API:
6045 : * SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads
6046 : matrix to be factorized into internal storage
6047 : * SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT
6048 : with lower bounds on pivot magnitudes and additional overflow safeguards
6049 : * SparseCholeskyFactorize(), that performs numeric factorization using
6050 : precomputed symbolic analysis and internally stored matrix - and outputs
6051 : result
6052 : * SparseCholeskyReload(), that reloads one more matrix with same sparsity
6053 : pattern into internal storage so one may reuse previously allocated
6054 : temporaries and previously performed symbolic analysis
6055 :
6056 : This specific function replaces internally stored numerical values with
6057 : ones from another sparse matrix (but having exactly same sparsity pattern
6058 : as one that was used for initial SparseCholeskyAnalyze() call).
6059 :
6060 : NOTE: all internal processing is performed with lower triangular matrices
6061 : stored in CRS format. Any other storage formats and/or upper
6062 : triangular storage means that one format conversion and/or one
6063 : transposition will be performed internally for the analysis and
6064 : factorization phases. Thus, highest performance is achieved when
6065 : input is a lower triangular CRS matrix.
6066 :
6067 : INPUT PARAMETERS:
6068 : Analysis - analysis object
6069 : A - sparse square matrix in any sparse storage format. It
6070 : MUST have exactly same sparsity pattern as that of the
6071 : matrix that was passed to SparseCholeskyAnalyze().
6072 : Any difference (missing elements or additional elements)
6073 : may result in unpredictable and undefined behavior -
6074 : an algorithm may fail due to memory access violation.
6075 : IsUpper - whether upper or lower triangle is decomposed (the
6076 : other one is ignored).
6077 :
6078 : OUTPUT PARAMETERS:
6079 : Analysis - contains:
6080 : * symbolic analysis of the matrix structure which will
6081 : be used later to guide numerical factorization.
6082 : * specific numeric values loaded into internal memory
6083 : waiting for the factorization to be performed
6084 :
6085 : -- ALGLIB routine --
6086 : 20.09.2020
6087 : Bochkanov Sergey
6088 : *************************************************************************/
6089 0 : void sparsecholeskyreload(const sparsedecompositionanalysis &analysis, const sparsematrix &a, const bool isupper, const xparams _xparams)
6090 : {
6091 : jmp_buf _break_jump;
6092 : alglib_impl::ae_state _alglib_env_state;
6093 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6094 0 : if( setjmp(_break_jump) )
6095 : {
6096 : #if !defined(AE_NO_EXCEPTIONS)
6097 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6098 : #else
6099 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6100 : return;
6101 : #endif
6102 : }
6103 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6104 0 : if( _xparams.flags!=0x0 )
6105 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6106 0 : alglib_impl::sparsecholeskyreload(const_cast<alglib_impl::sparsedecompositionanalysis*>(analysis.c_ptr()), const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), isupper, &_alglib_env_state);
6107 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6108 0 : return;
6109 : }
6110 : #endif
6111 :
6112 : #if defined(AE_COMPILE_RCOND) || !defined(AE_PARTIAL_BUILD)
6113 : /*************************************************************************
6114 : Estimate of a matrix condition number (1-norm)
6115 :
6116 : The algorithm calculates a lower bound of the condition number. In this case,
6117 : the algorithm does not return a lower bound of the condition number, but an
6118 : inverse number (to avoid an overflow in case of a singular matrix).
6119 :
6120 : Input parameters:
6121 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
6122 : N - size of matrix A.
6123 :
6124 : Result: 1/LowerBound(cond(A))
6125 :
6126 : NOTE:
6127 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6128 : 0.0 is returned in such cases.
6129 : *************************************************************************/
6130 0 : double rmatrixrcond1(const real_2d_array &a, const ae_int_t n, const xparams _xparams)
6131 : {
6132 : jmp_buf _break_jump;
6133 : alglib_impl::ae_state _alglib_env_state;
6134 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6135 0 : if( setjmp(_break_jump) )
6136 : {
6137 : #if !defined(AE_NO_EXCEPTIONS)
6138 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6139 : #else
6140 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6141 : return 0;
6142 : #endif
6143 : }
6144 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6145 0 : if( _xparams.flags!=0x0 )
6146 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6147 0 : double result = alglib_impl::rmatrixrcond1(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &_alglib_env_state);
6148 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6149 0 : return *(reinterpret_cast<double*>(&result));
6150 : }
6151 :
6152 : /*************************************************************************
6153 : Estimate of a matrix condition number (infinity-norm).
6154 :
6155 : The algorithm calculates a lower bound of the condition number. In this case,
6156 : the algorithm does not return a lower bound of the condition number, but an
6157 : inverse number (to avoid an overflow in case of a singular matrix).
6158 :
6159 : Input parameters:
6160 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
6161 : N - size of matrix A.
6162 :
6163 : Result: 1/LowerBound(cond(A))
6164 :
6165 : NOTE:
6166 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6167 : 0.0 is returned in such cases.
6168 : *************************************************************************/
6169 0 : double rmatrixrcondinf(const real_2d_array &a, const ae_int_t n, const xparams _xparams)
6170 : {
6171 : jmp_buf _break_jump;
6172 : alglib_impl::ae_state _alglib_env_state;
6173 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6174 0 : if( setjmp(_break_jump) )
6175 : {
6176 : #if !defined(AE_NO_EXCEPTIONS)
6177 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6178 : #else
6179 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6180 : return 0;
6181 : #endif
6182 : }
6183 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6184 0 : if( _xparams.flags!=0x0 )
6185 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6186 0 : double result = alglib_impl::rmatrixrcondinf(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &_alglib_env_state);
6187 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6188 0 : return *(reinterpret_cast<double*>(&result));
6189 : }
6190 :
6191 : /*************************************************************************
6192 : Condition number estimate of a symmetric positive definite matrix.
6193 :
6194 : The algorithm calculates a lower bound of the condition number. In this case,
6195 : the algorithm does not return a lower bound of the condition number, but an
6196 : inverse number (to avoid an overflow in case of a singular matrix).
6197 :
6198 : It should be noted that 1-norm and inf-norm of condition numbers of symmetric
6199 : matrices are equal, so the algorithm doesn't take into account the
6200 : differences between these types of norms.
6201 :
6202 : Input parameters:
6203 : A - symmetric positive definite matrix which is given by its
6204 : upper or lower triangle depending on the value of
6205 : IsUpper. Array with elements [0..N-1, 0..N-1].
6206 : N - size of matrix A.
6207 : IsUpper - storage format.
6208 :
6209 : Result:
6210 : 1/LowerBound(cond(A)), if matrix A is positive definite,
6211 : -1, if matrix A is not positive definite, and its condition number
6212 : could not be found by this algorithm.
6213 :
6214 : NOTE:
6215 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6216 : 0.0 is returned in such cases.
6217 : *************************************************************************/
6218 0 : double spdmatrixrcond(const real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams)
6219 : {
6220 : jmp_buf _break_jump;
6221 : alglib_impl::ae_state _alglib_env_state;
6222 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6223 0 : if( setjmp(_break_jump) )
6224 : {
6225 : #if !defined(AE_NO_EXCEPTIONS)
6226 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6227 : #else
6228 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6229 : return 0;
6230 : #endif
6231 : }
6232 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6233 0 : if( _xparams.flags!=0x0 )
6234 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6235 0 : double result = alglib_impl::spdmatrixrcond(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &_alglib_env_state);
6236 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6237 0 : return *(reinterpret_cast<double*>(&result));
6238 : }
6239 :
6240 : /*************************************************************************
6241 : Triangular matrix: estimate of a condition number (1-norm)
6242 :
6243 : The algorithm calculates a lower bound of the condition number. In this case,
6244 : the algorithm does not return a lower bound of the condition number, but an
6245 : inverse number (to avoid an overflow in case of a singular matrix).
6246 :
6247 : Input parameters:
6248 : A - matrix. Array[0..N-1, 0..N-1].
6249 : N - size of A.
6250 : IsUpper - True, if the matrix is upper triangular.
6251 : IsUnit - True, if the matrix has a unit diagonal.
6252 :
6253 : Result: 1/LowerBound(cond(A))
6254 :
6255 : NOTE:
6256 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6257 : 0.0 is returned in such cases.
6258 : *************************************************************************/
6259 0 : double rmatrixtrrcond1(const real_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, const xparams _xparams)
6260 : {
6261 : jmp_buf _break_jump;
6262 : alglib_impl::ae_state _alglib_env_state;
6263 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6264 0 : if( setjmp(_break_jump) )
6265 : {
6266 : #if !defined(AE_NO_EXCEPTIONS)
6267 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6268 : #else
6269 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6270 : return 0;
6271 : #endif
6272 : }
6273 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6274 0 : if( _xparams.flags!=0x0 )
6275 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6276 0 : double result = alglib_impl::rmatrixtrrcond1(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, isunit, &_alglib_env_state);
6277 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6278 0 : return *(reinterpret_cast<double*>(&result));
6279 : }
6280 :
6281 : /*************************************************************************
6282 : Triangular matrix: estimate of a matrix condition number (infinity-norm).
6283 :
6284 : The algorithm calculates a lower bound of the condition number. In this case,
6285 : the algorithm does not return a lower bound of the condition number, but an
6286 : inverse number (to avoid an overflow in case of a singular matrix).
6287 :
6288 : Input parameters:
6289 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
6290 : N - size of matrix A.
6291 : IsUpper - True, if the matrix is upper triangular.
6292 : IsUnit - True, if the matrix has a unit diagonal.
6293 :
6294 : Result: 1/LowerBound(cond(A))
6295 :
6296 : NOTE:
6297 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6298 : 0.0 is returned in such cases.
6299 : *************************************************************************/
6300 0 : double rmatrixtrrcondinf(const real_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, const xparams _xparams)
6301 : {
6302 : jmp_buf _break_jump;
6303 : alglib_impl::ae_state _alglib_env_state;
6304 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6305 0 : if( setjmp(_break_jump) )
6306 : {
6307 : #if !defined(AE_NO_EXCEPTIONS)
6308 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6309 : #else
6310 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6311 : return 0;
6312 : #endif
6313 : }
6314 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6315 0 : if( _xparams.flags!=0x0 )
6316 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6317 0 : double result = alglib_impl::rmatrixtrrcondinf(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, isunit, &_alglib_env_state);
6318 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6319 0 : return *(reinterpret_cast<double*>(&result));
6320 : }
6321 :
6322 : /*************************************************************************
6323 : Condition number estimate of a Hermitian positive definite matrix.
6324 :
6325 : The algorithm calculates a lower bound of the condition number. In this case,
6326 : the algorithm does not return a lower bound of the condition number, but an
6327 : inverse number (to avoid an overflow in case of a singular matrix).
6328 :
6329 : It should be noted that 1-norm and inf-norm of condition numbers of symmetric
6330 : matrices are equal, so the algorithm doesn't take into account the
6331 : differences between these types of norms.
6332 :
6333 : Input parameters:
6334 : A - Hermitian positive definite matrix which is given by its
6335 : upper or lower triangle depending on the value of
6336 : IsUpper. Array with elements [0..N-1, 0..N-1].
6337 : N - size of matrix A.
6338 : IsUpper - storage format.
6339 :
6340 : Result:
6341 : 1/LowerBound(cond(A)), if matrix A is positive definite,
6342 : -1, if matrix A is not positive definite, and its condition number
6343 : could not be found by this algorithm.
6344 :
6345 : NOTE:
6346 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6347 : 0.0 is returned in such cases.
6348 : *************************************************************************/
6349 0 : double hpdmatrixrcond(const complex_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams)
6350 : {
6351 : jmp_buf _break_jump;
6352 : alglib_impl::ae_state _alglib_env_state;
6353 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6354 0 : if( setjmp(_break_jump) )
6355 : {
6356 : #if !defined(AE_NO_EXCEPTIONS)
6357 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6358 : #else
6359 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6360 : return 0;
6361 : #endif
6362 : }
6363 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6364 0 : if( _xparams.flags!=0x0 )
6365 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6366 0 : double result = alglib_impl::hpdmatrixrcond(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &_alglib_env_state);
6367 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6368 0 : return *(reinterpret_cast<double*>(&result));
6369 : }
6370 :
6371 : /*************************************************************************
6372 : Estimate of a matrix condition number (1-norm)
6373 :
6374 : The algorithm calculates a lower bound of the condition number. In this case,
6375 : the algorithm does not return a lower bound of the condition number, but an
6376 : inverse number (to avoid an overflow in case of a singular matrix).
6377 :
6378 : Input parameters:
6379 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
6380 : N - size of matrix A.
6381 :
6382 : Result: 1/LowerBound(cond(A))
6383 :
6384 : NOTE:
6385 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6386 : 0.0 is returned in such cases.
6387 : *************************************************************************/
6388 0 : double cmatrixrcond1(const complex_2d_array &a, const ae_int_t n, const xparams _xparams)
6389 : {
6390 : jmp_buf _break_jump;
6391 : alglib_impl::ae_state _alglib_env_state;
6392 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6393 0 : if( setjmp(_break_jump) )
6394 : {
6395 : #if !defined(AE_NO_EXCEPTIONS)
6396 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6397 : #else
6398 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6399 : return 0;
6400 : #endif
6401 : }
6402 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6403 0 : if( _xparams.flags!=0x0 )
6404 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6405 0 : double result = alglib_impl::cmatrixrcond1(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &_alglib_env_state);
6406 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6407 0 : return *(reinterpret_cast<double*>(&result));
6408 : }
6409 :
6410 : /*************************************************************************
6411 : Estimate of a matrix condition number (infinity-norm).
6412 :
6413 : The algorithm calculates a lower bound of the condition number. In this case,
6414 : the algorithm does not return a lower bound of the condition number, but an
6415 : inverse number (to avoid an overflow in case of a singular matrix).
6416 :
6417 : Input parameters:
6418 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
6419 : N - size of matrix A.
6420 :
6421 : Result: 1/LowerBound(cond(A))
6422 :
6423 : NOTE:
6424 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6425 : 0.0 is returned in such cases.
6426 : *************************************************************************/
6427 0 : double cmatrixrcondinf(const complex_2d_array &a, const ae_int_t n, const xparams _xparams)
6428 : {
6429 : jmp_buf _break_jump;
6430 : alglib_impl::ae_state _alglib_env_state;
6431 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6432 0 : if( setjmp(_break_jump) )
6433 : {
6434 : #if !defined(AE_NO_EXCEPTIONS)
6435 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6436 : #else
6437 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6438 : return 0;
6439 : #endif
6440 : }
6441 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6442 0 : if( _xparams.flags!=0x0 )
6443 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6444 0 : double result = alglib_impl::cmatrixrcondinf(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &_alglib_env_state);
6445 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6446 0 : return *(reinterpret_cast<double*>(&result));
6447 : }
6448 :
6449 : /*************************************************************************
6450 : Estimate of the condition number of a matrix given by its LU decomposition (1-norm)
6451 :
6452 : The algorithm calculates a lower bound of the condition number. In this case,
6453 : the algorithm does not return a lower bound of the condition number, but an
6454 : inverse number (to avoid an overflow in case of a singular matrix).
6455 :
6456 : Input parameters:
6457 : LUA - LU decomposition of a matrix in compact form. Output of
6458 : the RMatrixLU subroutine.
6459 : N - size of matrix A.
6460 :
6461 : Result: 1/LowerBound(cond(A))
6462 :
6463 : NOTE:
6464 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6465 : 0.0 is returned in such cases.
6466 : *************************************************************************/
6467 0 : double rmatrixlurcond1(const real_2d_array &lua, const ae_int_t n, const xparams _xparams)
6468 : {
6469 : jmp_buf _break_jump;
6470 : alglib_impl::ae_state _alglib_env_state;
6471 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6472 0 : if( setjmp(_break_jump) )
6473 : {
6474 : #if !defined(AE_NO_EXCEPTIONS)
6475 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6476 : #else
6477 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6478 : return 0;
6479 : #endif
6480 : }
6481 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6482 0 : if( _xparams.flags!=0x0 )
6483 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6484 0 : double result = alglib_impl::rmatrixlurcond1(const_cast<alglib_impl::ae_matrix*>(lua.c_ptr()), n, &_alglib_env_state);
6485 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6486 0 : return *(reinterpret_cast<double*>(&result));
6487 : }
6488 :
6489 : /*************************************************************************
6490 : Estimate of the condition number of a matrix given by its LU decomposition
6491 : (infinity norm).
6492 :
6493 : The algorithm calculates a lower bound of the condition number. In this case,
6494 : the algorithm does not return a lower bound of the condition number, but an
6495 : inverse number (to avoid an overflow in case of a singular matrix).
6496 :
6497 : Input parameters:
6498 : LUA - LU decomposition of a matrix in compact form. Output of
6499 : the RMatrixLU subroutine.
6500 : N - size of matrix A.
6501 :
6502 : Result: 1/LowerBound(cond(A))
6503 :
6504 : NOTE:
6505 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6506 : 0.0 is returned in such cases.
6507 : *************************************************************************/
6508 0 : double rmatrixlurcondinf(const real_2d_array &lua, const ae_int_t n, const xparams _xparams)
6509 : {
6510 : jmp_buf _break_jump;
6511 : alglib_impl::ae_state _alglib_env_state;
6512 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6513 0 : if( setjmp(_break_jump) )
6514 : {
6515 : #if !defined(AE_NO_EXCEPTIONS)
6516 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6517 : #else
6518 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6519 : return 0;
6520 : #endif
6521 : }
6522 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6523 0 : if( _xparams.flags!=0x0 )
6524 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6525 0 : double result = alglib_impl::rmatrixlurcondinf(const_cast<alglib_impl::ae_matrix*>(lua.c_ptr()), n, &_alglib_env_state);
6526 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6527 0 : return *(reinterpret_cast<double*>(&result));
6528 : }
6529 :
6530 : /*************************************************************************
6531 : Condition number estimate of a symmetric positive definite matrix given by
6532 : Cholesky decomposition.
6533 :
6534 : The algorithm calculates a lower bound of the condition number. In this
6535 : case, the algorithm does not return a lower bound of the condition number,
6536 : but an inverse number (to avoid an overflow in case of a singular matrix).
6537 :
6538 : It should be noted that 1-norm and inf-norm condition numbers of symmetric
6539 : matrices are equal, so the algorithm doesn't take into account the
6540 : differences between these types of norms.
6541 :
6542 : Input parameters:
6543 : CD - Cholesky decomposition of matrix A,
6544 : output of SMatrixCholesky subroutine.
6545 : N - size of matrix A.
6546 :
6547 : Result: 1/LowerBound(cond(A))
6548 :
6549 : NOTE:
6550 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6551 : 0.0 is returned in such cases.
6552 : *************************************************************************/
6553 0 : double spdmatrixcholeskyrcond(const real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams)
6554 : {
6555 : jmp_buf _break_jump;
6556 : alglib_impl::ae_state _alglib_env_state;
6557 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6558 0 : if( setjmp(_break_jump) )
6559 : {
6560 : #if !defined(AE_NO_EXCEPTIONS)
6561 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6562 : #else
6563 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6564 : return 0;
6565 : #endif
6566 : }
6567 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6568 0 : if( _xparams.flags!=0x0 )
6569 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6570 0 : double result = alglib_impl::spdmatrixcholeskyrcond(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &_alglib_env_state);
6571 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6572 0 : return *(reinterpret_cast<double*>(&result));
6573 : }
6574 :
6575 : /*************************************************************************
6576 : Condition number estimate of a Hermitian positive definite matrix given by
6577 : Cholesky decomposition.
6578 :
6579 : The algorithm calculates a lower bound of the condition number. In this
6580 : case, the algorithm does not return a lower bound of the condition number,
6581 : but an inverse number (to avoid an overflow in case of a singular matrix).
6582 :
6583 : It should be noted that 1-norm and inf-norm condition numbers of symmetric
6584 : matrices are equal, so the algorithm doesn't take into account the
6585 : differences between these types of norms.
6586 :
6587 : Input parameters:
6588 : CD - Cholesky decomposition of matrix A,
6589 : output of SMatrixCholesky subroutine.
6590 : N - size of matrix A.
6591 :
6592 : Result: 1/LowerBound(cond(A))
6593 :
6594 : NOTE:
6595 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6596 : 0.0 is returned in such cases.
6597 : *************************************************************************/
6598 0 : double hpdmatrixcholeskyrcond(const complex_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams)
6599 : {
6600 : jmp_buf _break_jump;
6601 : alglib_impl::ae_state _alglib_env_state;
6602 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6603 0 : if( setjmp(_break_jump) )
6604 : {
6605 : #if !defined(AE_NO_EXCEPTIONS)
6606 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6607 : #else
6608 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6609 : return 0;
6610 : #endif
6611 : }
6612 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6613 0 : if( _xparams.flags!=0x0 )
6614 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6615 0 : double result = alglib_impl::hpdmatrixcholeskyrcond(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &_alglib_env_state);
6616 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6617 0 : return *(reinterpret_cast<double*>(&result));
6618 : }
6619 :
6620 : /*************************************************************************
6621 : Estimate of the condition number of a matrix given by its LU decomposition (1-norm)
6622 :
6623 : The algorithm calculates a lower bound of the condition number. In this case,
6624 : the algorithm does not return a lower bound of the condition number, but an
6625 : inverse number (to avoid an overflow in case of a singular matrix).
6626 :
6627 : Input parameters:
6628 : LUA - LU decomposition of a matrix in compact form. Output of
6629 : the CMatrixLU subroutine.
6630 : N - size of matrix A.
6631 :
6632 : Result: 1/LowerBound(cond(A))
6633 :
6634 : NOTE:
6635 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6636 : 0.0 is returned in such cases.
6637 : *************************************************************************/
6638 0 : double cmatrixlurcond1(const complex_2d_array &lua, const ae_int_t n, const xparams _xparams)
6639 : {
6640 : jmp_buf _break_jump;
6641 : alglib_impl::ae_state _alglib_env_state;
6642 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6643 0 : if( setjmp(_break_jump) )
6644 : {
6645 : #if !defined(AE_NO_EXCEPTIONS)
6646 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6647 : #else
6648 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6649 : return 0;
6650 : #endif
6651 : }
6652 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6653 0 : if( _xparams.flags!=0x0 )
6654 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6655 0 : double result = alglib_impl::cmatrixlurcond1(const_cast<alglib_impl::ae_matrix*>(lua.c_ptr()), n, &_alglib_env_state);
6656 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6657 0 : return *(reinterpret_cast<double*>(&result));
6658 : }
6659 :
6660 : /*************************************************************************
6661 : Estimate of the condition number of a matrix given by its LU decomposition
6662 : (infinity norm).
6663 :
6664 : The algorithm calculates a lower bound of the condition number. In this case,
6665 : the algorithm does not return a lower bound of the condition number, but an
6666 : inverse number (to avoid an overflow in case of a singular matrix).
6667 :
6668 : Input parameters:
6669 : LUA - LU decomposition of a matrix in compact form. Output of
6670 : the CMatrixLU subroutine.
6671 : N - size of matrix A.
6672 :
6673 : Result: 1/LowerBound(cond(A))
6674 :
6675 : NOTE:
6676 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6677 : 0.0 is returned in such cases.
6678 : *************************************************************************/
6679 0 : double cmatrixlurcondinf(const complex_2d_array &lua, const ae_int_t n, const xparams _xparams)
6680 : {
6681 : jmp_buf _break_jump;
6682 : alglib_impl::ae_state _alglib_env_state;
6683 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6684 0 : if( setjmp(_break_jump) )
6685 : {
6686 : #if !defined(AE_NO_EXCEPTIONS)
6687 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6688 : #else
6689 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6690 : return 0;
6691 : #endif
6692 : }
6693 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6694 0 : if( _xparams.flags!=0x0 )
6695 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6696 0 : double result = alglib_impl::cmatrixlurcondinf(const_cast<alglib_impl::ae_matrix*>(lua.c_ptr()), n, &_alglib_env_state);
6697 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6698 0 : return *(reinterpret_cast<double*>(&result));
6699 : }
6700 :
6701 : /*************************************************************************
6702 : Triangular matrix: estimate of a condition number (1-norm)
6703 :
6704 : The algorithm calculates a lower bound of the condition number. In this case,
6705 : the algorithm does not return a lower bound of the condition number, but an
6706 : inverse number (to avoid an overflow in case of a singular matrix).
6707 :
6708 : Input parameters:
6709 : A - matrix. Array[0..N-1, 0..N-1].
6710 : N - size of A.
6711 : IsUpper - True, if the matrix is upper triangular.
6712 : IsUnit - True, if the matrix has a unit diagonal.
6713 :
6714 : Result: 1/LowerBound(cond(A))
6715 :
6716 : NOTE:
6717 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6718 : 0.0 is returned in such cases.
6719 : *************************************************************************/
6720 0 : double cmatrixtrrcond1(const complex_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, const xparams _xparams)
6721 : {
6722 : jmp_buf _break_jump;
6723 : alglib_impl::ae_state _alglib_env_state;
6724 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6725 0 : if( setjmp(_break_jump) )
6726 : {
6727 : #if !defined(AE_NO_EXCEPTIONS)
6728 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6729 : #else
6730 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6731 : return 0;
6732 : #endif
6733 : }
6734 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6735 0 : if( _xparams.flags!=0x0 )
6736 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6737 0 : double result = alglib_impl::cmatrixtrrcond1(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, isunit, &_alglib_env_state);
6738 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6739 0 : return *(reinterpret_cast<double*>(&result));
6740 : }
6741 :
6742 : /*************************************************************************
6743 : Triangular matrix: estimate of a matrix condition number (infinity-norm).
6744 :
6745 : The algorithm calculates a lower bound of the condition number. In this case,
6746 : the algorithm does not return a lower bound of the condition number, but an
6747 : inverse number (to avoid an overflow in case of a singular matrix).
6748 :
6749 : Input parameters:
6750 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
6751 : N - size of matrix A.
6752 : IsUpper - True, if the matrix is upper triangular.
6753 : IsUnit - True, if the matrix has a unit diagonal.
6754 :
6755 : Result: 1/LowerBound(cond(A))
6756 :
6757 : NOTE:
6758 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
6759 : 0.0 is returned in such cases.
6760 : *************************************************************************/
6761 0 : double cmatrixtrrcondinf(const complex_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, const xparams _xparams)
6762 : {
6763 : jmp_buf _break_jump;
6764 : alglib_impl::ae_state _alglib_env_state;
6765 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6766 0 : if( setjmp(_break_jump) )
6767 : {
6768 : #if !defined(AE_NO_EXCEPTIONS)
6769 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6770 : #else
6771 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6772 : return 0;
6773 : #endif
6774 : }
6775 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6776 0 : if( _xparams.flags!=0x0 )
6777 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6778 0 : double result = alglib_impl::cmatrixtrrcondinf(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, isunit, &_alglib_env_state);
6779 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6780 0 : return *(reinterpret_cast<double*>(&result));
6781 : }
6782 : #endif
6783 :
6784 : #if defined(AE_COMPILE_MATINV) || !defined(AE_PARTIAL_BUILD)
6785 : /*************************************************************************
6786 : Matrix inverse report:
6787 : * R1 reciprocal of condition number in 1-norm
6788 : * RInf reciprocal of condition number in inf-norm
6789 : *************************************************************************/
6790 0 : _matinvreport_owner::_matinvreport_owner()
6791 : {
6792 : jmp_buf _break_jump;
6793 : alglib_impl::ae_state _state;
6794 :
6795 0 : alglib_impl::ae_state_init(&_state);
6796 0 : if( setjmp(_break_jump) )
6797 : {
6798 0 : if( p_struct!=NULL )
6799 : {
6800 0 : alglib_impl::_matinvreport_destroy(p_struct);
6801 0 : alglib_impl::ae_free(p_struct);
6802 : }
6803 0 : p_struct = NULL;
6804 : #if !defined(AE_NO_EXCEPTIONS)
6805 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
6806 : #else
6807 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
6808 : return;
6809 : #endif
6810 : }
6811 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
6812 0 : p_struct = NULL;
6813 0 : p_struct = (alglib_impl::matinvreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::matinvreport), &_state);
6814 0 : memset(p_struct, 0, sizeof(alglib_impl::matinvreport));
6815 0 : alglib_impl::_matinvreport_init(p_struct, &_state, ae_false);
6816 0 : ae_state_clear(&_state);
6817 0 : }
6818 :
6819 0 : _matinvreport_owner::_matinvreport_owner(const _matinvreport_owner &rhs)
6820 : {
6821 : jmp_buf _break_jump;
6822 : alglib_impl::ae_state _state;
6823 :
6824 0 : alglib_impl::ae_state_init(&_state);
6825 0 : if( setjmp(_break_jump) )
6826 : {
6827 0 : if( p_struct!=NULL )
6828 : {
6829 0 : alglib_impl::_matinvreport_destroy(p_struct);
6830 0 : alglib_impl::ae_free(p_struct);
6831 : }
6832 0 : p_struct = NULL;
6833 : #if !defined(AE_NO_EXCEPTIONS)
6834 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
6835 : #else
6836 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
6837 : return;
6838 : #endif
6839 : }
6840 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
6841 0 : p_struct = NULL;
6842 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: matinvreport copy constructor failure (source is not initialized)", &_state);
6843 0 : p_struct = (alglib_impl::matinvreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::matinvreport), &_state);
6844 0 : memset(p_struct, 0, sizeof(alglib_impl::matinvreport));
6845 0 : alglib_impl::_matinvreport_init_copy(p_struct, const_cast<alglib_impl::matinvreport*>(rhs.p_struct), &_state, ae_false);
6846 0 : ae_state_clear(&_state);
6847 0 : }
6848 :
6849 0 : _matinvreport_owner& _matinvreport_owner::operator=(const _matinvreport_owner &rhs)
6850 : {
6851 0 : if( this==&rhs )
6852 0 : return *this;
6853 : jmp_buf _break_jump;
6854 : alglib_impl::ae_state _state;
6855 :
6856 0 : alglib_impl::ae_state_init(&_state);
6857 0 : if( setjmp(_break_jump) )
6858 : {
6859 : #if !defined(AE_NO_EXCEPTIONS)
6860 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
6861 : #else
6862 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
6863 : return *this;
6864 : #endif
6865 : }
6866 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
6867 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: matinvreport assignment constructor failure (destination is not initialized)", &_state);
6868 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: matinvreport assignment constructor failure (source is not initialized)", &_state);
6869 0 : alglib_impl::_matinvreport_destroy(p_struct);
6870 0 : memset(p_struct, 0, sizeof(alglib_impl::matinvreport));
6871 0 : alglib_impl::_matinvreport_init_copy(p_struct, const_cast<alglib_impl::matinvreport*>(rhs.p_struct), &_state, ae_false);
6872 0 : ae_state_clear(&_state);
6873 0 : return *this;
6874 : }
6875 :
6876 0 : _matinvreport_owner::~_matinvreport_owner()
6877 : {
6878 0 : if( p_struct!=NULL )
6879 : {
6880 0 : alglib_impl::_matinvreport_destroy(p_struct);
6881 0 : ae_free(p_struct);
6882 : }
6883 0 : }
6884 :
6885 0 : alglib_impl::matinvreport* _matinvreport_owner::c_ptr()
6886 : {
6887 0 : return p_struct;
6888 : }
6889 :
6890 0 : alglib_impl::matinvreport* _matinvreport_owner::c_ptr() const
6891 : {
6892 0 : return const_cast<alglib_impl::matinvreport*>(p_struct);
6893 : }
6894 0 : matinvreport::matinvreport() : _matinvreport_owner() ,r1(p_struct->r1),rinf(p_struct->rinf)
6895 : {
6896 0 : }
6897 :
6898 0 : matinvreport::matinvreport(const matinvreport &rhs):_matinvreport_owner(rhs) ,r1(p_struct->r1),rinf(p_struct->rinf)
6899 : {
6900 0 : }
6901 :
6902 0 : matinvreport& matinvreport::operator=(const matinvreport &rhs)
6903 : {
6904 0 : if( this==&rhs )
6905 0 : return *this;
6906 0 : _matinvreport_owner::operator=(rhs);
6907 0 : return *this;
6908 : }
6909 :
6910 0 : matinvreport::~matinvreport()
6911 : {
6912 0 : }
6913 :
6914 : /*************************************************************************
6915 : Inversion of a matrix given by its LU decomposition.
6916 :
6917 : ! COMMERCIAL EDITION OF ALGLIB:
6918 : !
6919 : ! Commercial Edition of ALGLIB includes following important improvements
6920 : ! of this function:
6921 : ! * high-performance native backend with same C# interface (C# version)
6922 : ! * multithreading support (C++ and C# versions)
6923 : ! * hardware vendor (Intel) implementations of linear algebra primitives
6924 : ! (C++ and C# versions, x86/x64 platform)
6925 : !
6926 : ! We recommend you to read 'Working with commercial version' section of
6927 : ! ALGLIB Reference Manual in order to find out how to use performance-
6928 : ! related features provided by commercial edition of ALGLIB.
6929 :
6930 : INPUT PARAMETERS:
6931 : A - LU decomposition of the matrix
6932 : (output of RMatrixLU subroutine).
6933 : Pivots - table of permutations
6934 : (the output of RMatrixLU subroutine).
6935 : N - size of matrix A (optional) :
6936 : * if given, only principal NxN submatrix is processed and
6937 : overwritten. other elements are unchanged.
6938 : * if not given, size is automatically determined from
6939 : matrix size (A must be square matrix)
6940 :
6941 : OUTPUT PARAMETERS:
6942 : Info - return code:
6943 : * -3 A is singular, or VERY close to singular.
6944 : it is filled by zeros in such cases.
6945 : * 1 task is solved (but matrix A may be ill-conditioned,
6946 : check R1/RInf parameters for condition numbers).
6947 : Rep - solver report, see below for more info
6948 : A - inverse of matrix A.
6949 : Array whose indexes range within [0..N-1, 0..N-1].
6950 :
6951 : SOLVER REPORT
6952 :
6953 : Subroutine sets following fields of the Rep structure:
6954 : * R1 reciprocal of condition number: 1/cond(A), 1-norm.
6955 : * RInf reciprocal of condition number: 1/cond(A), inf-norm.
6956 :
6957 : -- ALGLIB routine --
6958 : 05.02.2010
6959 : Bochkanov Sergey
6960 : *************************************************************************/
6961 0 : void rmatrixluinverse(real_2d_array &a, const integer_1d_array &pivots, const ae_int_t n, ae_int_t &info, matinvreport &rep, const xparams _xparams)
6962 : {
6963 : jmp_buf _break_jump;
6964 : alglib_impl::ae_state _alglib_env_state;
6965 0 : alglib_impl::ae_state_init(&_alglib_env_state);
6966 0 : if( setjmp(_break_jump) )
6967 : {
6968 : #if !defined(AE_NO_EXCEPTIONS)
6969 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
6970 : #else
6971 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
6972 : return;
6973 : #endif
6974 : }
6975 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
6976 0 : if( _xparams.flags!=0x0 )
6977 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
6978 0 : alglib_impl::rmatrixluinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(pivots.c_ptr()), n, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
6979 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
6980 0 : return;
6981 : }
6982 :
6983 : /*************************************************************************
6984 : Inversion of a matrix given by its LU decomposition.
6985 :
6986 : ! COMMERCIAL EDITION OF ALGLIB:
6987 : !
6988 : ! Commercial Edition of ALGLIB includes following important improvements
6989 : ! of this function:
6990 : ! * high-performance native backend with same C# interface (C# version)
6991 : ! * multithreading support (C++ and C# versions)
6992 : ! * hardware vendor (Intel) implementations of linear algebra primitives
6993 : ! (C++ and C# versions, x86/x64 platform)
6994 : !
6995 : ! We recommend you to read 'Working with commercial version' section of
6996 : ! ALGLIB Reference Manual in order to find out how to use performance-
6997 : ! related features provided by commercial edition of ALGLIB.
6998 :
6999 : INPUT PARAMETERS:
7000 : A - LU decomposition of the matrix
7001 : (output of RMatrixLU subroutine).
7002 : Pivots - table of permutations
7003 : (the output of RMatrixLU subroutine).
7004 : N - size of matrix A (optional) :
7005 : * if given, only principal NxN submatrix is processed and
7006 : overwritten. other elements are unchanged.
7007 : * if not given, size is automatically determined from
7008 : matrix size (A must be square matrix)
7009 :
7010 : OUTPUT PARAMETERS:
7011 : Info - return code:
7012 : * -3 A is singular, or VERY close to singular.
7013 : it is filled by zeros in such cases.
7014 : * 1 task is solved (but matrix A may be ill-conditioned,
7015 : check R1/RInf parameters for condition numbers).
7016 : Rep - solver report, see below for more info
7017 : A - inverse of matrix A.
7018 : Array whose indexes range within [0..N-1, 0..N-1].
7019 :
7020 : SOLVER REPORT
7021 :
7022 : Subroutine sets following fields of the Rep structure:
7023 : * R1 reciprocal of condition number: 1/cond(A), 1-norm.
7024 : * RInf reciprocal of condition number: 1/cond(A), inf-norm.
7025 :
7026 : -- ALGLIB routine --
7027 : 05.02.2010
7028 : Bochkanov Sergey
7029 : *************************************************************************/
7030 : #if !defined(AE_NO_EXCEPTIONS)
7031 0 : void rmatrixluinverse(real_2d_array &a, const integer_1d_array &pivots, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7032 : {
7033 : jmp_buf _break_jump;
7034 : alglib_impl::ae_state _alglib_env_state;
7035 : ae_int_t n;
7036 0 : if( (a.cols()!=a.rows()) || (a.cols()!=pivots.length()))
7037 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'rmatrixluinverse': looks like one of arguments has wrong size");
7038 0 : n = a.cols();
7039 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7040 0 : if( setjmp(_break_jump) )
7041 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7042 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7043 0 : if( _xparams.flags!=0x0 )
7044 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7045 0 : alglib_impl::rmatrixluinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(pivots.c_ptr()), n, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7046 :
7047 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7048 0 : return;
7049 : }
7050 : #endif
7051 :
7052 : /*************************************************************************
7053 : Inversion of a general matrix.
7054 :
7055 : ! COMMERCIAL EDITION OF ALGLIB:
7056 : !
7057 : ! Commercial Edition of ALGLIB includes following important improvements
7058 : ! of this function:
7059 : ! * high-performance native backend with same C# interface (C# version)
7060 : ! * multithreading support (C++ and C# versions)
7061 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7062 : ! (C++ and C# versions, x86/x64 platform)
7063 : !
7064 : ! We recommend you to read 'Working with commercial version' section of
7065 : ! ALGLIB Reference Manual in order to find out how to use performance-
7066 : ! related features provided by commercial edition of ALGLIB.
7067 :
7068 : Input parameters:
7069 : A - matrix.
7070 : N - size of matrix A (optional) :
7071 : * if given, only principal NxN submatrix is processed and
7072 : overwritten. other elements are unchanged.
7073 : * if not given, size is automatically determined from
7074 : matrix size (A must be square matrix)
7075 :
7076 : Output parameters:
7077 : Info - return code, same as in RMatrixLUInverse
7078 : Rep - solver report, same as in RMatrixLUInverse
7079 : A - inverse of matrix A, same as in RMatrixLUInverse
7080 :
7081 : Result:
7082 : True, if the matrix is not singular.
7083 : False, if the matrix is singular.
7084 :
7085 : -- ALGLIB --
7086 : Copyright 2005-2010 by Bochkanov Sergey
7087 : *************************************************************************/
7088 0 : void rmatrixinverse(real_2d_array &a, const ae_int_t n, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7089 : {
7090 : jmp_buf _break_jump;
7091 : alglib_impl::ae_state _alglib_env_state;
7092 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7093 0 : if( setjmp(_break_jump) )
7094 : {
7095 : #if !defined(AE_NO_EXCEPTIONS)
7096 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7097 : #else
7098 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7099 : return;
7100 : #endif
7101 : }
7102 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7103 0 : if( _xparams.flags!=0x0 )
7104 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7105 0 : alglib_impl::rmatrixinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7106 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7107 0 : return;
7108 : }
7109 :
7110 : /*************************************************************************
7111 : Inversion of a general matrix.
7112 :
7113 : ! COMMERCIAL EDITION OF ALGLIB:
7114 : !
7115 : ! Commercial Edition of ALGLIB includes following important improvements
7116 : ! of this function:
7117 : ! * high-performance native backend with same C# interface (C# version)
7118 : ! * multithreading support (C++ and C# versions)
7119 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7120 : ! (C++ and C# versions, x86/x64 platform)
7121 : !
7122 : ! We recommend you to read 'Working with commercial version' section of
7123 : ! ALGLIB Reference Manual in order to find out how to use performance-
7124 : ! related features provided by commercial edition of ALGLIB.
7125 :
7126 : Input parameters:
7127 : A - matrix.
7128 : N - size of matrix A (optional) :
7129 : * if given, only principal NxN submatrix is processed and
7130 : overwritten. other elements are unchanged.
7131 : * if not given, size is automatically determined from
7132 : matrix size (A must be square matrix)
7133 :
7134 : Output parameters:
7135 : Info - return code, same as in RMatrixLUInverse
7136 : Rep - solver report, same as in RMatrixLUInverse
7137 : A - inverse of matrix A, same as in RMatrixLUInverse
7138 :
7139 : Result:
7140 : True, if the matrix is not singular.
7141 : False, if the matrix is singular.
7142 :
7143 : -- ALGLIB --
7144 : Copyright 2005-2010 by Bochkanov Sergey
7145 : *************************************************************************/
7146 : #if !defined(AE_NO_EXCEPTIONS)
7147 0 : void rmatrixinverse(real_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7148 : {
7149 : jmp_buf _break_jump;
7150 : alglib_impl::ae_state _alglib_env_state;
7151 : ae_int_t n;
7152 0 : if( (a.cols()!=a.rows()))
7153 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'rmatrixinverse': looks like one of arguments has wrong size");
7154 0 : n = a.cols();
7155 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7156 0 : if( setjmp(_break_jump) )
7157 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7158 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7159 0 : if( _xparams.flags!=0x0 )
7160 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7161 0 : alglib_impl::rmatrixinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7162 :
7163 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7164 0 : return;
7165 : }
7166 : #endif
7167 :
7168 : /*************************************************************************
7169 : Inversion of a matrix given by its LU decomposition.
7170 :
7171 : ! COMMERCIAL EDITION OF ALGLIB:
7172 : !
7173 : ! Commercial Edition of ALGLIB includes following important improvements
7174 : ! of this function:
7175 : ! * high-performance native backend with same C# interface (C# version)
7176 : ! * multithreading support (C++ and C# versions)
7177 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7178 : ! (C++ and C# versions, x86/x64 platform)
7179 : !
7180 : ! We recommend you to read 'Working with commercial version' section of
7181 : ! ALGLIB Reference Manual in order to find out how to use performance-
7182 : ! related features provided by commercial edition of ALGLIB.
7183 :
7184 : INPUT PARAMETERS:
7185 : A - LU decomposition of the matrix
7186 : (output of CMatrixLU subroutine).
7187 : Pivots - table of permutations
7188 : (the output of CMatrixLU subroutine).
7189 : N - size of matrix A (optional) :
7190 : * if given, only principal NxN submatrix is processed and
7191 : overwritten. other elements are unchanged.
7192 : * if not given, size is automatically determined from
7193 : matrix size (A must be square matrix)
7194 :
7195 : OUTPUT PARAMETERS:
7196 : Info - return code, same as in RMatrixLUInverse
7197 : Rep - solver report, same as in RMatrixLUInverse
7198 : A - inverse of matrix A, same as in RMatrixLUInverse
7199 :
7200 : -- ALGLIB routine --
7201 : 05.02.2010
7202 : Bochkanov Sergey
7203 : *************************************************************************/
7204 0 : void cmatrixluinverse(complex_2d_array &a, const integer_1d_array &pivots, const ae_int_t n, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7205 : {
7206 : jmp_buf _break_jump;
7207 : alglib_impl::ae_state _alglib_env_state;
7208 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7209 0 : if( setjmp(_break_jump) )
7210 : {
7211 : #if !defined(AE_NO_EXCEPTIONS)
7212 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7213 : #else
7214 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7215 : return;
7216 : #endif
7217 : }
7218 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7219 0 : if( _xparams.flags!=0x0 )
7220 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7221 0 : alglib_impl::cmatrixluinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(pivots.c_ptr()), n, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7222 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7223 0 : return;
7224 : }
7225 :
7226 : /*************************************************************************
7227 : Inversion of a matrix given by its LU decomposition.
7228 :
7229 : ! COMMERCIAL EDITION OF ALGLIB:
7230 : !
7231 : ! Commercial Edition of ALGLIB includes following important improvements
7232 : ! of this function:
7233 : ! * high-performance native backend with same C# interface (C# version)
7234 : ! * multithreading support (C++ and C# versions)
7235 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7236 : ! (C++ and C# versions, x86/x64 platform)
7237 : !
7238 : ! We recommend you to read 'Working with commercial version' section of
7239 : ! ALGLIB Reference Manual in order to find out how to use performance-
7240 : ! related features provided by commercial edition of ALGLIB.
7241 :
7242 : INPUT PARAMETERS:
7243 : A - LU decomposition of the matrix
7244 : (output of CMatrixLU subroutine).
7245 : Pivots - table of permutations
7246 : (the output of CMatrixLU subroutine).
7247 : N - size of matrix A (optional) :
7248 : * if given, only principal NxN submatrix is processed and
7249 : overwritten. other elements are unchanged.
7250 : * if not given, size is automatically determined from
7251 : matrix size (A must be square matrix)
7252 :
7253 : OUTPUT PARAMETERS:
7254 : Info - return code, same as in RMatrixLUInverse
7255 : Rep - solver report, same as in RMatrixLUInverse
7256 : A - inverse of matrix A, same as in RMatrixLUInverse
7257 :
7258 : -- ALGLIB routine --
7259 : 05.02.2010
7260 : Bochkanov Sergey
7261 : *************************************************************************/
7262 : #if !defined(AE_NO_EXCEPTIONS)
7263 0 : void cmatrixluinverse(complex_2d_array &a, const integer_1d_array &pivots, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7264 : {
7265 : jmp_buf _break_jump;
7266 : alglib_impl::ae_state _alglib_env_state;
7267 : ae_int_t n;
7268 0 : if( (a.cols()!=a.rows()) || (a.cols()!=pivots.length()))
7269 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'cmatrixluinverse': looks like one of arguments has wrong size");
7270 0 : n = a.cols();
7271 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7272 0 : if( setjmp(_break_jump) )
7273 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7274 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7275 0 : if( _xparams.flags!=0x0 )
7276 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7277 0 : alglib_impl::cmatrixluinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(pivots.c_ptr()), n, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7278 :
7279 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7280 0 : return;
7281 : }
7282 : #endif
7283 :
7284 : /*************************************************************************
7285 : Inversion of a general matrix.
7286 :
7287 : ! COMMERCIAL EDITION OF ALGLIB:
7288 : !
7289 : ! Commercial Edition of ALGLIB includes following important improvements
7290 : ! of this function:
7291 : ! * high-performance native backend with same C# interface (C# version)
7292 : ! * multithreading support (C++ and C# versions)
7293 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7294 : ! (C++ and C# versions, x86/x64 platform)
7295 : !
7296 : ! We recommend you to read 'Working with commercial version' section of
7297 : ! ALGLIB Reference Manual in order to find out how to use performance-
7298 : ! related features provided by commercial edition of ALGLIB.
7299 :
7300 : Input parameters:
7301 : A - matrix
7302 : N - size of matrix A (optional) :
7303 : * if given, only principal NxN submatrix is processed and
7304 : overwritten. other elements are unchanged.
7305 : * if not given, size is automatically determined from
7306 : matrix size (A must be square matrix)
7307 :
7308 : Output parameters:
7309 : Info - return code, same as in RMatrixLUInverse
7310 : Rep - solver report, same as in RMatrixLUInverse
7311 : A - inverse of matrix A, same as in RMatrixLUInverse
7312 :
7313 : -- ALGLIB --
7314 : Copyright 2005 by Bochkanov Sergey
7315 : *************************************************************************/
7316 0 : void cmatrixinverse(complex_2d_array &a, const ae_int_t n, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7317 : {
7318 : jmp_buf _break_jump;
7319 : alglib_impl::ae_state _alglib_env_state;
7320 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7321 0 : if( setjmp(_break_jump) )
7322 : {
7323 : #if !defined(AE_NO_EXCEPTIONS)
7324 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7325 : #else
7326 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7327 : return;
7328 : #endif
7329 : }
7330 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7331 0 : if( _xparams.flags!=0x0 )
7332 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7333 0 : alglib_impl::cmatrixinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7334 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7335 0 : return;
7336 : }
7337 :
7338 : /*************************************************************************
7339 : Inversion of a general matrix.
7340 :
7341 : ! COMMERCIAL EDITION OF ALGLIB:
7342 : !
7343 : ! Commercial Edition of ALGLIB includes following important improvements
7344 : ! of this function:
7345 : ! * high-performance native backend with same C# interface (C# version)
7346 : ! * multithreading support (C++ and C# versions)
7347 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7348 : ! (C++ and C# versions, x86/x64 platform)
7349 : !
7350 : ! We recommend you to read 'Working with commercial version' section of
7351 : ! ALGLIB Reference Manual in order to find out how to use performance-
7352 : ! related features provided by commercial edition of ALGLIB.
7353 :
7354 : Input parameters:
7355 : A - matrix
7356 : N - size of matrix A (optional) :
7357 : * if given, only principal NxN submatrix is processed and
7358 : overwritten. other elements are unchanged.
7359 : * if not given, size is automatically determined from
7360 : matrix size (A must be square matrix)
7361 :
7362 : Output parameters:
7363 : Info - return code, same as in RMatrixLUInverse
7364 : Rep - solver report, same as in RMatrixLUInverse
7365 : A - inverse of matrix A, same as in RMatrixLUInverse
7366 :
7367 : -- ALGLIB --
7368 : Copyright 2005 by Bochkanov Sergey
7369 : *************************************************************************/
7370 : #if !defined(AE_NO_EXCEPTIONS)
7371 0 : void cmatrixinverse(complex_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7372 : {
7373 : jmp_buf _break_jump;
7374 : alglib_impl::ae_state _alglib_env_state;
7375 : ae_int_t n;
7376 0 : if( (a.cols()!=a.rows()))
7377 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'cmatrixinverse': looks like one of arguments has wrong size");
7378 0 : n = a.cols();
7379 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7380 0 : if( setjmp(_break_jump) )
7381 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7382 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7383 0 : if( _xparams.flags!=0x0 )
7384 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7385 0 : alglib_impl::cmatrixinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7386 :
7387 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7388 0 : return;
7389 : }
7390 : #endif
7391 :
7392 : /*************************************************************************
7393 : Inversion of a symmetric positive definite matrix which is given
7394 : by Cholesky decomposition.
7395 :
7396 : ! COMMERCIAL EDITION OF ALGLIB:
7397 : !
7398 : ! Commercial Edition of ALGLIB includes following important improvements
7399 : ! of this function:
7400 : ! * high-performance native backend with same C# interface (C# version)
7401 : ! * multithreading support (C++ and C# versions)
7402 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7403 : ! (C++ and C# versions, x86/x64 platform)
7404 : !
7405 : ! We recommend you to read 'Working with commercial version' section of
7406 : ! ALGLIB Reference Manual in order to find out how to use performance-
7407 : ! related features provided by commercial edition of ALGLIB.
7408 :
7409 : Input parameters:
7410 : A - Cholesky decomposition of the matrix to be inverted:
7411 : A=U'*U or A = L*L'.
7412 : Output of SPDMatrixCholesky subroutine.
7413 : N - size of matrix A (optional) :
7414 : * if given, only principal NxN submatrix is processed and
7415 : overwritten. other elements are unchanged.
7416 : * if not given, size is automatically determined from
7417 : matrix size (A must be square matrix)
7418 : IsUpper - storage type (optional):
7419 : * if True, symmetric matrix A is given by its upper
7420 : triangle, and the lower triangle isn't used/changed by
7421 : function
7422 : * if False, symmetric matrix A is given by its lower
7423 : triangle, and the upper triangle isn't used/changed by
7424 : function
7425 : * if not given, lower half is used.
7426 :
7427 : Output parameters:
7428 : Info - return code, same as in RMatrixLUInverse
7429 : Rep - solver report, same as in RMatrixLUInverse
7430 : A - inverse of matrix A, same as in RMatrixLUInverse
7431 :
7432 : -- ALGLIB routine --
7433 : 10.02.2010
7434 : Bochkanov Sergey
7435 : *************************************************************************/
7436 0 : void spdmatrixcholeskyinverse(real_2d_array &a, const ae_int_t n, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7437 : {
7438 : jmp_buf _break_jump;
7439 : alglib_impl::ae_state _alglib_env_state;
7440 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7441 0 : if( setjmp(_break_jump) )
7442 : {
7443 : #if !defined(AE_NO_EXCEPTIONS)
7444 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7445 : #else
7446 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7447 : return;
7448 : #endif
7449 : }
7450 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7451 0 : if( _xparams.flags!=0x0 )
7452 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7453 0 : alglib_impl::spdmatrixcholeskyinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7454 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7455 0 : return;
7456 : }
7457 :
7458 : /*************************************************************************
7459 : Inversion of a symmetric positive definite matrix which is given
7460 : by Cholesky decomposition.
7461 :
7462 : ! COMMERCIAL EDITION OF ALGLIB:
7463 : !
7464 : ! Commercial Edition of ALGLIB includes following important improvements
7465 : ! of this function:
7466 : ! * high-performance native backend with same C# interface (C# version)
7467 : ! * multithreading support (C++ and C# versions)
7468 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7469 : ! (C++ and C# versions, x86/x64 platform)
7470 : !
7471 : ! We recommend you to read 'Working with commercial version' section of
7472 : ! ALGLIB Reference Manual in order to find out how to use performance-
7473 : ! related features provided by commercial edition of ALGLIB.
7474 :
7475 : Input parameters:
7476 : A - Cholesky decomposition of the matrix to be inverted:
7477 : A=U'*U or A = L*L'.
7478 : Output of SPDMatrixCholesky subroutine.
7479 : N - size of matrix A (optional) :
7480 : * if given, only principal NxN submatrix is processed and
7481 : overwritten. other elements are unchanged.
7482 : * if not given, size is automatically determined from
7483 : matrix size (A must be square matrix)
7484 : IsUpper - storage type (optional):
7485 : * if True, symmetric matrix A is given by its upper
7486 : triangle, and the lower triangle isn't used/changed by
7487 : function
7488 : * if False, symmetric matrix A is given by its lower
7489 : triangle, and the upper triangle isn't used/changed by
7490 : function
7491 : * if not given, lower half is used.
7492 :
7493 : Output parameters:
7494 : Info - return code, same as in RMatrixLUInverse
7495 : Rep - solver report, same as in RMatrixLUInverse
7496 : A - inverse of matrix A, same as in RMatrixLUInverse
7497 :
7498 : -- ALGLIB routine --
7499 : 10.02.2010
7500 : Bochkanov Sergey
7501 : *************************************************************************/
7502 : #if !defined(AE_NO_EXCEPTIONS)
7503 0 : void spdmatrixcholeskyinverse(real_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7504 : {
7505 : jmp_buf _break_jump;
7506 : alglib_impl::ae_state _alglib_env_state;
7507 : ae_int_t n;
7508 : bool isupper;
7509 0 : if( (a.cols()!=a.rows()))
7510 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spdmatrixcholeskyinverse': looks like one of arguments has wrong size");
7511 0 : n = a.cols();
7512 0 : isupper = false;
7513 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7514 0 : if( setjmp(_break_jump) )
7515 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7516 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7517 0 : if( _xparams.flags!=0x0 )
7518 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7519 0 : alglib_impl::spdmatrixcholeskyinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7520 :
7521 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7522 0 : return;
7523 : }
7524 : #endif
7525 :
7526 : /*************************************************************************
7527 : Inversion of a symmetric positive definite matrix.
7528 :
7529 : Given an upper or lower triangle of a symmetric positive definite matrix,
7530 : the algorithm generates matrix A^-1 and saves the upper or lower triangle
7531 : depending on the input.
7532 :
7533 : ! COMMERCIAL EDITION OF ALGLIB:
7534 : !
7535 : ! Commercial Edition of ALGLIB includes following important improvements
7536 : ! of this function:
7537 : ! * high-performance native backend with same C# interface (C# version)
7538 : ! * multithreading support (C++ and C# versions)
7539 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7540 : ! (C++ and C# versions, x86/x64 platform)
7541 : !
7542 : ! We recommend you to read 'Working with commercial version' section of
7543 : ! ALGLIB Reference Manual in order to find out how to use performance-
7544 : ! related features provided by commercial edition of ALGLIB.
7545 :
7546 : Input parameters:
7547 : A - matrix to be inverted (upper or lower triangle).
7548 : Array with elements [0..N-1,0..N-1].
7549 : N - size of matrix A (optional) :
7550 : * if given, only principal NxN submatrix is processed and
7551 : overwritten. other elements are unchanged.
7552 : * if not given, size is automatically determined from
7553 : matrix size (A must be square matrix)
7554 : IsUpper - storage type (optional):
7555 : * if True, symmetric matrix A is given by its upper
7556 : triangle, and the lower triangle isn't used/changed by
7557 : function
7558 : * if False, symmetric matrix A is given by its lower
7559 : triangle, and the upper triangle isn't used/changed by
7560 : function
7561 : * if not given, both lower and upper triangles must be
7562 : filled.
7563 :
7564 : Output parameters:
7565 : Info - return code, same as in RMatrixLUInverse
7566 : Rep - solver report, same as in RMatrixLUInverse
7567 : A - inverse of matrix A, same as in RMatrixLUInverse
7568 :
7569 : -- ALGLIB routine --
7570 : 10.02.2010
7571 : Bochkanov Sergey
7572 : *************************************************************************/
7573 0 : void spdmatrixinverse(real_2d_array &a, const ae_int_t n, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7574 : {
7575 : jmp_buf _break_jump;
7576 : alglib_impl::ae_state _alglib_env_state;
7577 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7578 0 : if( setjmp(_break_jump) )
7579 : {
7580 : #if !defined(AE_NO_EXCEPTIONS)
7581 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7582 : #else
7583 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7584 : return;
7585 : #endif
7586 : }
7587 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7588 0 : if( _xparams.flags!=0x0 )
7589 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7590 0 : alglib_impl::spdmatrixinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7591 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7592 0 : return;
7593 : }
7594 :
7595 : /*************************************************************************
7596 : Inversion of a symmetric positive definite matrix.
7597 :
7598 : Given an upper or lower triangle of a symmetric positive definite matrix,
7599 : the algorithm generates matrix A^-1 and saves the upper or lower triangle
7600 : depending on the input.
7601 :
7602 : ! COMMERCIAL EDITION OF ALGLIB:
7603 : !
7604 : ! Commercial Edition of ALGLIB includes following important improvements
7605 : ! of this function:
7606 : ! * high-performance native backend with same C# interface (C# version)
7607 : ! * multithreading support (C++ and C# versions)
7608 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7609 : ! (C++ and C# versions, x86/x64 platform)
7610 : !
7611 : ! We recommend you to read 'Working with commercial version' section of
7612 : ! ALGLIB Reference Manual in order to find out how to use performance-
7613 : ! related features provided by commercial edition of ALGLIB.
7614 :
7615 : Input parameters:
7616 : A - matrix to be inverted (upper or lower triangle).
7617 : Array with elements [0..N-1,0..N-1].
7618 : N - size of matrix A (optional) :
7619 : * if given, only principal NxN submatrix is processed and
7620 : overwritten. other elements are unchanged.
7621 : * if not given, size is automatically determined from
7622 : matrix size (A must be square matrix)
7623 : IsUpper - storage type (optional):
7624 : * if True, symmetric matrix A is given by its upper
7625 : triangle, and the lower triangle isn't used/changed by
7626 : function
7627 : * if False, symmetric matrix A is given by its lower
7628 : triangle, and the upper triangle isn't used/changed by
7629 : function
7630 : * if not given, both lower and upper triangles must be
7631 : filled.
7632 :
7633 : Output parameters:
7634 : Info - return code, same as in RMatrixLUInverse
7635 : Rep - solver report, same as in RMatrixLUInverse
7636 : A - inverse of matrix A, same as in RMatrixLUInverse
7637 :
7638 : -- ALGLIB routine --
7639 : 10.02.2010
7640 : Bochkanov Sergey
7641 : *************************************************************************/
7642 : #if !defined(AE_NO_EXCEPTIONS)
7643 0 : void spdmatrixinverse(real_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7644 : {
7645 : jmp_buf _break_jump;
7646 : alglib_impl::ae_state _alglib_env_state;
7647 : ae_int_t n;
7648 : bool isupper;
7649 0 : if( (a.cols()!=a.rows()))
7650 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spdmatrixinverse': looks like one of arguments has wrong size");
7651 0 : if( !alglib_impl::ae_is_symmetric(const_cast<alglib_impl::ae_matrix*>(a.c_ptr())) )
7652 0 : _ALGLIB_CPP_EXCEPTION("'a' parameter is not symmetric matrix");
7653 0 : n = a.cols();
7654 0 : isupper = false;
7655 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7656 0 : if( setjmp(_break_jump) )
7657 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7658 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7659 0 : if( _xparams.flags!=0x0 )
7660 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7661 0 : alglib_impl::spdmatrixinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7662 0 : if( !alglib_impl::ae_force_symmetric(const_cast<alglib_impl::ae_matrix*>(a.c_ptr())) )
7663 0 : _ALGLIB_CPP_EXCEPTION("Internal error while forcing symmetricity of 'a' parameter");
7664 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7665 0 : return;
7666 : }
7667 : #endif
7668 :
7669 : /*************************************************************************
7670 : Inversion of a Hermitian positive definite matrix which is given
7671 : by Cholesky decomposition.
7672 :
7673 : ! COMMERCIAL EDITION OF ALGLIB:
7674 : !
7675 : ! Commercial Edition of ALGLIB includes following important improvements
7676 : ! of this function:
7677 : ! * high-performance native backend with same C# interface (C# version)
7678 : ! * multithreading support (C++ and C# versions)
7679 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7680 : ! (C++ and C# versions, x86/x64 platform)
7681 : !
7682 : ! We recommend you to read 'Working with commercial version' section of
7683 : ! ALGLIB Reference Manual in order to find out how to use performance-
7684 : ! related features provided by commercial edition of ALGLIB.
7685 :
7686 : Input parameters:
7687 : A - Cholesky decomposition of the matrix to be inverted:
7688 : A=U'*U or A = L*L'.
7689 : Output of HPDMatrixCholesky subroutine.
7690 : N - size of matrix A (optional) :
7691 : * if given, only principal NxN submatrix is processed and
7692 : overwritten. other elements are unchanged.
7693 : * if not given, size is automatically determined from
7694 : matrix size (A must be square matrix)
7695 : IsUpper - storage type (optional):
7696 : * if True, symmetric matrix A is given by its upper
7697 : triangle, and the lower triangle isn't used/changed by
7698 : function
7699 : * if False, symmetric matrix A is given by its lower
7700 : triangle, and the upper triangle isn't used/changed by
7701 : function
7702 : * if not given, lower half is used.
7703 :
7704 : Output parameters:
7705 : Info - return code, same as in RMatrixLUInverse
7706 : Rep - solver report, same as in RMatrixLUInverse
7707 : A - inverse of matrix A, same as in RMatrixLUInverse
7708 :
7709 : -- ALGLIB routine --
7710 : 10.02.2010
7711 : Bochkanov Sergey
7712 : *************************************************************************/
7713 0 : void hpdmatrixcholeskyinverse(complex_2d_array &a, const ae_int_t n, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7714 : {
7715 : jmp_buf _break_jump;
7716 : alglib_impl::ae_state _alglib_env_state;
7717 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7718 0 : if( setjmp(_break_jump) )
7719 : {
7720 : #if !defined(AE_NO_EXCEPTIONS)
7721 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7722 : #else
7723 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7724 : return;
7725 : #endif
7726 : }
7727 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7728 0 : if( _xparams.flags!=0x0 )
7729 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7730 0 : alglib_impl::hpdmatrixcholeskyinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7731 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7732 0 : return;
7733 : }
7734 :
7735 : /*************************************************************************
7736 : Inversion of a Hermitian positive definite matrix which is given
7737 : by Cholesky decomposition.
7738 :
7739 : ! COMMERCIAL EDITION OF ALGLIB:
7740 : !
7741 : ! Commercial Edition of ALGLIB includes following important improvements
7742 : ! of this function:
7743 : ! * high-performance native backend with same C# interface (C# version)
7744 : ! * multithreading support (C++ and C# versions)
7745 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7746 : ! (C++ and C# versions, x86/x64 platform)
7747 : !
7748 : ! We recommend you to read 'Working with commercial version' section of
7749 : ! ALGLIB Reference Manual in order to find out how to use performance-
7750 : ! related features provided by commercial edition of ALGLIB.
7751 :
7752 : Input parameters:
7753 : A - Cholesky decomposition of the matrix to be inverted:
7754 : A=U'*U or A = L*L'.
7755 : Output of HPDMatrixCholesky subroutine.
7756 : N - size of matrix A (optional) :
7757 : * if given, only principal NxN submatrix is processed and
7758 : overwritten. other elements are unchanged.
7759 : * if not given, size is automatically determined from
7760 : matrix size (A must be square matrix)
7761 : IsUpper - storage type (optional):
7762 : * if True, symmetric matrix A is given by its upper
7763 : triangle, and the lower triangle isn't used/changed by
7764 : function
7765 : * if False, symmetric matrix A is given by its lower
7766 : triangle, and the upper triangle isn't used/changed by
7767 : function
7768 : * if not given, lower half is used.
7769 :
7770 : Output parameters:
7771 : Info - return code, same as in RMatrixLUInverse
7772 : Rep - solver report, same as in RMatrixLUInverse
7773 : A - inverse of matrix A, same as in RMatrixLUInverse
7774 :
7775 : -- ALGLIB routine --
7776 : 10.02.2010
7777 : Bochkanov Sergey
7778 : *************************************************************************/
7779 : #if !defined(AE_NO_EXCEPTIONS)
7780 0 : void hpdmatrixcholeskyinverse(complex_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7781 : {
7782 : jmp_buf _break_jump;
7783 : alglib_impl::ae_state _alglib_env_state;
7784 : ae_int_t n;
7785 : bool isupper;
7786 0 : if( (a.cols()!=a.rows()))
7787 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'hpdmatrixcholeskyinverse': looks like one of arguments has wrong size");
7788 0 : n = a.cols();
7789 0 : isupper = false;
7790 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7791 0 : if( setjmp(_break_jump) )
7792 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7793 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7794 0 : if( _xparams.flags!=0x0 )
7795 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7796 0 : alglib_impl::hpdmatrixcholeskyinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7797 :
7798 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7799 0 : return;
7800 : }
7801 : #endif
7802 :
7803 : /*************************************************************************
7804 : Inversion of a Hermitian positive definite matrix.
7805 :
7806 : Given an upper or lower triangle of a Hermitian positive definite matrix,
7807 : the algorithm generates matrix A^-1 and saves the upper or lower triangle
7808 : depending on the input.
7809 :
7810 : ! COMMERCIAL EDITION OF ALGLIB:
7811 : !
7812 : ! Commercial Edition of ALGLIB includes following important improvements
7813 : ! of this function:
7814 : ! * high-performance native backend with same C# interface (C# version)
7815 : ! * multithreading support (C++ and C# versions)
7816 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7817 : ! (C++ and C# versions, x86/x64 platform)
7818 : !
7819 : ! We recommend you to read 'Working with commercial version' section of
7820 : ! ALGLIB Reference Manual in order to find out how to use performance-
7821 : ! related features provided by commercial edition of ALGLIB.
7822 :
7823 : Input parameters:
7824 : A - matrix to be inverted (upper or lower triangle).
7825 : Array with elements [0..N-1,0..N-1].
7826 : N - size of matrix A (optional) :
7827 : * if given, only principal NxN submatrix is processed and
7828 : overwritten. other elements are unchanged.
7829 : * if not given, size is automatically determined from
7830 : matrix size (A must be square matrix)
7831 : IsUpper - storage type (optional):
7832 : * if True, symmetric matrix A is given by its upper
7833 : triangle, and the lower triangle isn't used/changed by
7834 : function
7835 : * if False, symmetric matrix A is given by its lower
7836 : triangle, and the upper triangle isn't used/changed by
7837 : function
7838 : * if not given, both lower and upper triangles must be
7839 : filled.
7840 :
7841 : Output parameters:
7842 : Info - return code, same as in RMatrixLUInverse
7843 : Rep - solver report, same as in RMatrixLUInverse
7844 : A - inverse of matrix A, same as in RMatrixLUInverse
7845 :
7846 : -- ALGLIB routine --
7847 : 10.02.2010
7848 : Bochkanov Sergey
7849 : *************************************************************************/
7850 0 : void hpdmatrixinverse(complex_2d_array &a, const ae_int_t n, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7851 : {
7852 : jmp_buf _break_jump;
7853 : alglib_impl::ae_state _alglib_env_state;
7854 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7855 0 : if( setjmp(_break_jump) )
7856 : {
7857 : #if !defined(AE_NO_EXCEPTIONS)
7858 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7859 : #else
7860 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
7861 : return;
7862 : #endif
7863 : }
7864 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7865 0 : if( _xparams.flags!=0x0 )
7866 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7867 0 : alglib_impl::hpdmatrixinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7868 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7869 0 : return;
7870 : }
7871 :
7872 : /*************************************************************************
7873 : Inversion of a Hermitian positive definite matrix.
7874 :
7875 : Given an upper or lower triangle of a Hermitian positive definite matrix,
7876 : the algorithm generates matrix A^-1 and saves the upper or lower triangle
7877 : depending on the input.
7878 :
7879 : ! COMMERCIAL EDITION OF ALGLIB:
7880 : !
7881 : ! Commercial Edition of ALGLIB includes following important improvements
7882 : ! of this function:
7883 : ! * high-performance native backend with same C# interface (C# version)
7884 : ! * multithreading support (C++ and C# versions)
7885 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7886 : ! (C++ and C# versions, x86/x64 platform)
7887 : !
7888 : ! We recommend you to read 'Working with commercial version' section of
7889 : ! ALGLIB Reference Manual in order to find out how to use performance-
7890 : ! related features provided by commercial edition of ALGLIB.
7891 :
7892 : Input parameters:
7893 : A - matrix to be inverted (upper or lower triangle).
7894 : Array with elements [0..N-1,0..N-1].
7895 : N - size of matrix A (optional) :
7896 : * if given, only principal NxN submatrix is processed and
7897 : overwritten. other elements are unchanged.
7898 : * if not given, size is automatically determined from
7899 : matrix size (A must be square matrix)
7900 : IsUpper - storage type (optional):
7901 : * if True, symmetric matrix A is given by its upper
7902 : triangle, and the lower triangle isn't used/changed by
7903 : function
7904 : * if False, symmetric matrix A is given by its lower
7905 : triangle, and the upper triangle isn't used/changed by
7906 : function
7907 : * if not given, both lower and upper triangles must be
7908 : filled.
7909 :
7910 : Output parameters:
7911 : Info - return code, same as in RMatrixLUInverse
7912 : Rep - solver report, same as in RMatrixLUInverse
7913 : A - inverse of matrix A, same as in RMatrixLUInverse
7914 :
7915 : -- ALGLIB routine --
7916 : 10.02.2010
7917 : Bochkanov Sergey
7918 : *************************************************************************/
7919 : #if !defined(AE_NO_EXCEPTIONS)
7920 0 : void hpdmatrixinverse(complex_2d_array &a, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7921 : {
7922 : jmp_buf _break_jump;
7923 : alglib_impl::ae_state _alglib_env_state;
7924 : ae_int_t n;
7925 : bool isupper;
7926 0 : if( (a.cols()!=a.rows()))
7927 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'hpdmatrixinverse': looks like one of arguments has wrong size");
7928 0 : if( !alglib_impl::ae_is_hermitian(const_cast<alglib_impl::ae_matrix*>(a.c_ptr())) )
7929 0 : _ALGLIB_CPP_EXCEPTION("'a' parameter is not Hermitian matrix");
7930 0 : n = a.cols();
7931 0 : isupper = false;
7932 0 : alglib_impl::ae_state_init(&_alglib_env_state);
7933 0 : if( setjmp(_break_jump) )
7934 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
7935 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
7936 0 : if( _xparams.flags!=0x0 )
7937 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
7938 0 : alglib_impl::hpdmatrixinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
7939 0 : if( !alglib_impl::ae_force_hermitian(const_cast<alglib_impl::ae_matrix*>(a.c_ptr())) )
7940 0 : _ALGLIB_CPP_EXCEPTION("Internal error while forcing Hermitian properties of 'a' parameter");
7941 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
7942 0 : return;
7943 : }
7944 : #endif
7945 :
7946 : /*************************************************************************
7947 : Triangular matrix inverse (real)
7948 :
7949 : The subroutine inverts the following types of matrices:
7950 : * upper triangular
7951 : * upper triangular with unit diagonal
7952 : * lower triangular
7953 : * lower triangular with unit diagonal
7954 :
7955 : In case of an upper (lower) triangular matrix, the inverse matrix will
7956 : also be upper (lower) triangular, and after the end of the algorithm, the
7957 : inverse matrix replaces the source matrix. The elements below (above) the
7958 : main diagonal are not changed by the algorithm.
7959 :
7960 : If the matrix has a unit diagonal, the inverse matrix also has a unit
7961 : diagonal, and the diagonal elements are not passed to the algorithm.
7962 :
7963 : ! COMMERCIAL EDITION OF ALGLIB:
7964 : !
7965 : ! Commercial Edition of ALGLIB includes following important improvements
7966 : ! of this function:
7967 : ! * high-performance native backend with same C# interface (C# version)
7968 : ! * multithreading support (C++ and C# versions)
7969 : ! * hardware vendor (Intel) implementations of linear algebra primitives
7970 : ! (C++ and C# versions, x86/x64 platform)
7971 : !
7972 : ! We recommend you to read 'Working with commercial version' section of
7973 : ! ALGLIB Reference Manual in order to find out how to use performance-
7974 : ! related features provided by commercial edition of ALGLIB.
7975 :
7976 : Input parameters:
7977 : A - matrix, array[0..N-1, 0..N-1].
7978 : N - size of matrix A (optional) :
7979 : * if given, only principal NxN submatrix is processed and
7980 : overwritten. other elements are unchanged.
7981 : * if not given, size is automatically determined from
7982 : matrix size (A must be square matrix)
7983 : IsUpper - True, if the matrix is upper triangular.
7984 : IsUnit - diagonal type (optional):
7985 : * if True, matrix has unit diagonal (a[i,i] are NOT used)
7986 : * if False, matrix diagonal is arbitrary
7987 : * if not given, False is assumed
7988 :
7989 : Output parameters:
7990 : Info - same as for RMatrixLUInverse
7991 : Rep - same as for RMatrixLUInverse
7992 : A - same as for RMatrixLUInverse.
7993 :
7994 : -- ALGLIB --
7995 : Copyright 05.02.2010 by Bochkanov Sergey
7996 : *************************************************************************/
7997 0 : void rmatrixtrinverse(real_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, ae_int_t &info, matinvreport &rep, const xparams _xparams)
7998 : {
7999 : jmp_buf _break_jump;
8000 : alglib_impl::ae_state _alglib_env_state;
8001 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8002 0 : if( setjmp(_break_jump) )
8003 : {
8004 : #if !defined(AE_NO_EXCEPTIONS)
8005 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8006 : #else
8007 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8008 : return;
8009 : #endif
8010 : }
8011 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8012 0 : if( _xparams.flags!=0x0 )
8013 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8014 0 : alglib_impl::rmatrixtrinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, isunit, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
8015 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8016 0 : return;
8017 : }
8018 :
8019 : /*************************************************************************
8020 : Triangular matrix inverse (real)
8021 :
8022 : The subroutine inverts the following types of matrices:
8023 : * upper triangular
8024 : * upper triangular with unit diagonal
8025 : * lower triangular
8026 : * lower triangular with unit diagonal
8027 :
8028 : In case of an upper (lower) triangular matrix, the inverse matrix will
8029 : also be upper (lower) triangular, and after the end of the algorithm, the
8030 : inverse matrix replaces the source matrix. The elements below (above) the
8031 : main diagonal are not changed by the algorithm.
8032 :
8033 : If the matrix has a unit diagonal, the inverse matrix also has a unit
8034 : diagonal, and the diagonal elements are not passed to the algorithm.
8035 :
8036 : ! COMMERCIAL EDITION OF ALGLIB:
8037 : !
8038 : ! Commercial Edition of ALGLIB includes following important improvements
8039 : ! of this function:
8040 : ! * high-performance native backend with same C# interface (C# version)
8041 : ! * multithreading support (C++ and C# versions)
8042 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8043 : ! (C++ and C# versions, x86/x64 platform)
8044 : !
8045 : ! We recommend you to read 'Working with commercial version' section of
8046 : ! ALGLIB Reference Manual in order to find out how to use performance-
8047 : ! related features provided by commercial edition of ALGLIB.
8048 :
8049 : Input parameters:
8050 : A - matrix, array[0..N-1, 0..N-1].
8051 : N - size of matrix A (optional) :
8052 : * if given, only principal NxN submatrix is processed and
8053 : overwritten. other elements are unchanged.
8054 : * if not given, size is automatically determined from
8055 : matrix size (A must be square matrix)
8056 : IsUpper - True, if the matrix is upper triangular.
8057 : IsUnit - diagonal type (optional):
8058 : * if True, matrix has unit diagonal (a[i,i] are NOT used)
8059 : * if False, matrix diagonal is arbitrary
8060 : * if not given, False is assumed
8061 :
8062 : Output parameters:
8063 : Info - same as for RMatrixLUInverse
8064 : Rep - same as for RMatrixLUInverse
8065 : A - same as for RMatrixLUInverse.
8066 :
8067 : -- ALGLIB --
8068 : Copyright 05.02.2010 by Bochkanov Sergey
8069 : *************************************************************************/
8070 : #if !defined(AE_NO_EXCEPTIONS)
8071 0 : void rmatrixtrinverse(real_2d_array &a, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams)
8072 : {
8073 : jmp_buf _break_jump;
8074 : alglib_impl::ae_state _alglib_env_state;
8075 : ae_int_t n;
8076 : bool isunit;
8077 0 : if( (a.cols()!=a.rows()))
8078 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'rmatrixtrinverse': looks like one of arguments has wrong size");
8079 0 : n = a.cols();
8080 0 : isunit = false;
8081 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8082 0 : if( setjmp(_break_jump) )
8083 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8084 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8085 0 : if( _xparams.flags!=0x0 )
8086 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8087 0 : alglib_impl::rmatrixtrinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, isunit, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
8088 :
8089 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8090 0 : return;
8091 : }
8092 : #endif
8093 :
8094 : /*************************************************************************
8095 : Triangular matrix inverse (complex)
8096 :
8097 : The subroutine inverts the following types of matrices:
8098 : * upper triangular
8099 : * upper triangular with unit diagonal
8100 : * lower triangular
8101 : * lower triangular with unit diagonal
8102 :
8103 : In case of an upper (lower) triangular matrix, the inverse matrix will
8104 : also be upper (lower) triangular, and after the end of the algorithm, the
8105 : inverse matrix replaces the source matrix. The elements below (above) the
8106 : main diagonal are not changed by the algorithm.
8107 :
8108 : If the matrix has a unit diagonal, the inverse matrix also has a unit
8109 : diagonal, and the diagonal elements are not passed to the algorithm.
8110 :
8111 : ! COMMERCIAL EDITION OF ALGLIB:
8112 : !
8113 : ! Commercial Edition of ALGLIB includes following important improvements
8114 : ! of this function:
8115 : ! * high-performance native backend with same C# interface (C# version)
8116 : ! * multithreading support (C++ and C# versions)
8117 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8118 : ! (C++ and C# versions, x86/x64 platform)
8119 : !
8120 : ! We recommend you to read 'Working with commercial version' section of
8121 : ! ALGLIB Reference Manual in order to find out how to use performance-
8122 : ! related features provided by commercial edition of ALGLIB.
8123 :
8124 : Input parameters:
8125 : A - matrix, array[0..N-1, 0..N-1].
8126 : N - size of matrix A (optional) :
8127 : * if given, only principal NxN submatrix is processed and
8128 : overwritten. other elements are unchanged.
8129 : * if not given, size is automatically determined from
8130 : matrix size (A must be square matrix)
8131 : IsUpper - True, if the matrix is upper triangular.
8132 : IsUnit - diagonal type (optional):
8133 : * if True, matrix has unit diagonal (a[i,i] are NOT used)
8134 : * if False, matrix diagonal is arbitrary
8135 : * if not given, False is assumed
8136 :
8137 : Output parameters:
8138 : Info - same as for RMatrixLUInverse
8139 : Rep - same as for RMatrixLUInverse
8140 : A - same as for RMatrixLUInverse.
8141 :
8142 : -- ALGLIB --
8143 : Copyright 05.02.2010 by Bochkanov Sergey
8144 : *************************************************************************/
8145 0 : void cmatrixtrinverse(complex_2d_array &a, const ae_int_t n, const bool isupper, const bool isunit, ae_int_t &info, matinvreport &rep, const xparams _xparams)
8146 : {
8147 : jmp_buf _break_jump;
8148 : alglib_impl::ae_state _alglib_env_state;
8149 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8150 0 : if( setjmp(_break_jump) )
8151 : {
8152 : #if !defined(AE_NO_EXCEPTIONS)
8153 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8154 : #else
8155 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8156 : return;
8157 : #endif
8158 : }
8159 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8160 0 : if( _xparams.flags!=0x0 )
8161 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8162 0 : alglib_impl::cmatrixtrinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, isunit, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
8163 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8164 0 : return;
8165 : }
8166 :
8167 : /*************************************************************************
8168 : Triangular matrix inverse (complex)
8169 :
8170 : The subroutine inverts the following types of matrices:
8171 : * upper triangular
8172 : * upper triangular with unit diagonal
8173 : * lower triangular
8174 : * lower triangular with unit diagonal
8175 :
8176 : In case of an upper (lower) triangular matrix, the inverse matrix will
8177 : also be upper (lower) triangular, and after the end of the algorithm, the
8178 : inverse matrix replaces the source matrix. The elements below (above) the
8179 : main diagonal are not changed by the algorithm.
8180 :
8181 : If the matrix has a unit diagonal, the inverse matrix also has a unit
8182 : diagonal, and the diagonal elements are not passed to the algorithm.
8183 :
8184 : ! COMMERCIAL EDITION OF ALGLIB:
8185 : !
8186 : ! Commercial Edition of ALGLIB includes following important improvements
8187 : ! of this function:
8188 : ! * high-performance native backend with same C# interface (C# version)
8189 : ! * multithreading support (C++ and C# versions)
8190 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8191 : ! (C++ and C# versions, x86/x64 platform)
8192 : !
8193 : ! We recommend you to read 'Working with commercial version' section of
8194 : ! ALGLIB Reference Manual in order to find out how to use performance-
8195 : ! related features provided by commercial edition of ALGLIB.
8196 :
8197 : Input parameters:
8198 : A - matrix, array[0..N-1, 0..N-1].
8199 : N - size of matrix A (optional) :
8200 : * if given, only principal NxN submatrix is processed and
8201 : overwritten. other elements are unchanged.
8202 : * if not given, size is automatically determined from
8203 : matrix size (A must be square matrix)
8204 : IsUpper - True, if the matrix is upper triangular.
8205 : IsUnit - diagonal type (optional):
8206 : * if True, matrix has unit diagonal (a[i,i] are NOT used)
8207 : * if False, matrix diagonal is arbitrary
8208 : * if not given, False is assumed
8209 :
8210 : Output parameters:
8211 : Info - same as for RMatrixLUInverse
8212 : Rep - same as for RMatrixLUInverse
8213 : A - same as for RMatrixLUInverse.
8214 :
8215 : -- ALGLIB --
8216 : Copyright 05.02.2010 by Bochkanov Sergey
8217 : *************************************************************************/
8218 : #if !defined(AE_NO_EXCEPTIONS)
8219 0 : void cmatrixtrinverse(complex_2d_array &a, const bool isupper, ae_int_t &info, matinvreport &rep, const xparams _xparams)
8220 : {
8221 : jmp_buf _break_jump;
8222 : alglib_impl::ae_state _alglib_env_state;
8223 : ae_int_t n;
8224 : bool isunit;
8225 0 : if( (a.cols()!=a.rows()))
8226 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'cmatrixtrinverse': looks like one of arguments has wrong size");
8227 0 : n = a.cols();
8228 0 : isunit = false;
8229 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8230 0 : if( setjmp(_break_jump) )
8231 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8232 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8233 0 : if( _xparams.flags!=0x0 )
8234 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8235 0 : alglib_impl::cmatrixtrinverse(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, isunit, &info, const_cast<alglib_impl::matinvreport*>(rep.c_ptr()), &_alglib_env_state);
8236 :
8237 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8238 0 : return;
8239 : }
8240 : #endif
8241 : #endif
8242 :
8243 : #if defined(AE_COMPILE_ORTFAC) || !defined(AE_PARTIAL_BUILD)
8244 : /*************************************************************************
8245 : QR decomposition of a rectangular matrix of size MxN
8246 :
8247 : ! COMMERCIAL EDITION OF ALGLIB:
8248 : !
8249 : ! Commercial Edition of ALGLIB includes following important improvements
8250 : ! of this function:
8251 : ! * high-performance native backend with same C# interface (C# version)
8252 : ! * multithreading support (C++ and C# versions)
8253 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8254 : ! (C++ and C# versions, x86/x64 platform)
8255 : !
8256 : ! We recommend you to read 'Working with commercial version' section of
8257 : ! ALGLIB Reference Manual in order to find out how to use performance-
8258 : ! related features provided by commercial edition of ALGLIB.
8259 :
8260 : Input parameters:
8261 : A - matrix A whose indexes range within [0..M-1, 0..N-1].
8262 : M - number of rows in matrix A.
8263 : N - number of columns in matrix A.
8264 :
8265 : Output parameters:
8266 : A - matrices Q and R in compact form (see below).
8267 : Tau - array of scalar factors which are used to form
8268 : matrix Q. Array whose index ranges within [0.. Min(M-1,N-1)].
8269 :
8270 : Matrix A is represented as A = QR, where Q is an orthogonal matrix of size
8271 : MxM, R - upper triangular (or upper trapezoid) matrix of size M x N.
8272 :
8273 : The elements of matrix R are located on and above the main diagonal of
8274 : matrix A. The elements which are located in Tau array and below the main
8275 : diagonal of matrix A are used to form matrix Q as follows:
8276 :
8277 : Matrix Q is represented as a product of elementary reflections
8278 :
8279 : Q = H(0)*H(2)*...*H(k-1),
8280 :
8281 : where k = min(m,n), and each H(i) is in the form
8282 :
8283 : H(i) = 1 - tau * v * (v^T)
8284 :
8285 : where tau is a scalar stored in Tau[I]; v - real vector,
8286 : so that v(0:i-1) = 0, v(i) = 1, v(i+1:m-1) stored in A(i+1:m-1,i).
8287 :
8288 : -- ALGLIB routine --
8289 : 17.02.2010
8290 : Bochkanov Sergey
8291 : *************************************************************************/
8292 0 : void rmatrixqr(real_2d_array &a, const ae_int_t m, const ae_int_t n, real_1d_array &tau, const xparams _xparams)
8293 : {
8294 : jmp_buf _break_jump;
8295 : alglib_impl::ae_state _alglib_env_state;
8296 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8297 0 : if( setjmp(_break_jump) )
8298 : {
8299 : #if !defined(AE_NO_EXCEPTIONS)
8300 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8301 : #else
8302 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8303 : return;
8304 : #endif
8305 : }
8306 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8307 0 : if( _xparams.flags!=0x0 )
8308 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8309 0 : alglib_impl::rmatrixqr(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), &_alglib_env_state);
8310 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8311 0 : return;
8312 : }
8313 :
8314 : /*************************************************************************
8315 : LQ decomposition of a rectangular matrix of size MxN
8316 :
8317 : ! COMMERCIAL EDITION OF ALGLIB:
8318 : !
8319 : ! Commercial Edition of ALGLIB includes following important improvements
8320 : ! of this function:
8321 : ! * high-performance native backend with same C# interface (C# version)
8322 : ! * multithreading support (C++ and C# versions)
8323 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8324 : ! (C++ and C# versions, x86/x64 platform)
8325 : !
8326 : ! We recommend you to read 'Working with commercial version' section of
8327 : ! ALGLIB Reference Manual in order to find out how to use performance-
8328 : ! related features provided by commercial edition of ALGLIB.
8329 :
8330 : Input parameters:
8331 : A - matrix A whose indexes range within [0..M-1, 0..N-1].
8332 : M - number of rows in matrix A.
8333 : N - number of columns in matrix A.
8334 :
8335 : Output parameters:
8336 : A - matrices L and Q in compact form (see below)
8337 : Tau - array of scalar factors which are used to form
8338 : matrix Q. Array whose index ranges within [0..Min(M,N)-1].
8339 :
8340 : Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size
8341 : MxM, L - lower triangular (or lower trapezoid) matrix of size M x N.
8342 :
8343 : The elements of matrix L are located on and below the main diagonal of
8344 : matrix A. The elements which are located in Tau array and above the main
8345 : diagonal of matrix A are used to form matrix Q as follows:
8346 :
8347 : Matrix Q is represented as a product of elementary reflections
8348 :
8349 : Q = H(k-1)*H(k-2)*...*H(1)*H(0),
8350 :
8351 : where k = min(m,n), and each H(i) is of the form
8352 :
8353 : H(i) = 1 - tau * v * (v^T)
8354 :
8355 : where tau is a scalar stored in Tau[I]; v - real vector, so that v(0:i-1)=0,
8356 : v(i) = 1, v(i+1:n-1) stored in A(i,i+1:n-1).
8357 :
8358 : -- ALGLIB routine --
8359 : 17.02.2010
8360 : Bochkanov Sergey
8361 : *************************************************************************/
8362 0 : void rmatrixlq(real_2d_array &a, const ae_int_t m, const ae_int_t n, real_1d_array &tau, const xparams _xparams)
8363 : {
8364 : jmp_buf _break_jump;
8365 : alglib_impl::ae_state _alglib_env_state;
8366 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8367 0 : if( setjmp(_break_jump) )
8368 : {
8369 : #if !defined(AE_NO_EXCEPTIONS)
8370 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8371 : #else
8372 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8373 : return;
8374 : #endif
8375 : }
8376 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8377 0 : if( _xparams.flags!=0x0 )
8378 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8379 0 : alglib_impl::rmatrixlq(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), &_alglib_env_state);
8380 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8381 0 : return;
8382 : }
8383 :
8384 : /*************************************************************************
8385 : QR decomposition of a rectangular complex matrix of size MxN
8386 :
8387 : ! COMMERCIAL EDITION OF ALGLIB:
8388 : !
8389 : ! Commercial Edition of ALGLIB includes following important improvements
8390 : ! of this function:
8391 : ! * high-performance native backend with same C# interface (C# version)
8392 : ! * multithreading support (C++ and C# versions)
8393 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8394 : ! (C++ and C# versions, x86/x64 platform)
8395 : !
8396 : ! We recommend you to read 'Working with commercial version' section of
8397 : ! ALGLIB Reference Manual in order to find out how to use performance-
8398 : ! related features provided by commercial edition of ALGLIB.
8399 :
8400 : Input parameters:
8401 : A - matrix A whose indexes range within [0..M-1, 0..N-1]
8402 : M - number of rows in matrix A.
8403 : N - number of columns in matrix A.
8404 :
8405 : Output parameters:
8406 : A - matrices Q and R in compact form
8407 : Tau - array of scalar factors which are used to form matrix Q. Array
8408 : whose indexes range within [0.. Min(M,N)-1]
8409 :
8410 : Matrix A is represented as A = QR, where Q is an orthogonal matrix of size
8411 : MxM, R - upper triangular (or upper trapezoid) matrix of size MxN.
8412 :
8413 : -- LAPACK routine (version 3.0) --
8414 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
8415 : Courant Institute, Argonne National Lab, and Rice University
8416 : September 30, 1994
8417 : *************************************************************************/
8418 0 : void cmatrixqr(complex_2d_array &a, const ae_int_t m, const ae_int_t n, complex_1d_array &tau, const xparams _xparams)
8419 : {
8420 : jmp_buf _break_jump;
8421 : alglib_impl::ae_state _alglib_env_state;
8422 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8423 0 : if( setjmp(_break_jump) )
8424 : {
8425 : #if !defined(AE_NO_EXCEPTIONS)
8426 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8427 : #else
8428 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8429 : return;
8430 : #endif
8431 : }
8432 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8433 0 : if( _xparams.flags!=0x0 )
8434 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8435 0 : alglib_impl::cmatrixqr(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), &_alglib_env_state);
8436 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8437 0 : return;
8438 : }
8439 :
8440 : /*************************************************************************
8441 : LQ decomposition of a rectangular complex matrix of size MxN
8442 :
8443 : ! COMMERCIAL EDITION OF ALGLIB:
8444 : !
8445 : ! Commercial Edition of ALGLIB includes following important improvements
8446 : ! of this function:
8447 : ! * high-performance native backend with same C# interface (C# version)
8448 : ! * multithreading support (C++ and C# versions)
8449 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8450 : ! (C++ and C# versions, x86/x64 platform)
8451 : !
8452 : ! We recommend you to read 'Working with commercial version' section of
8453 : ! ALGLIB Reference Manual in order to find out how to use performance-
8454 : ! related features provided by commercial edition of ALGLIB.
8455 :
8456 : Input parameters:
8457 : A - matrix A whose indexes range within [0..M-1, 0..N-1]
8458 : M - number of rows in matrix A.
8459 : N - number of columns in matrix A.
8460 :
8461 : Output parameters:
8462 : A - matrices Q and L in compact form
8463 : Tau - array of scalar factors which are used to form matrix Q. Array
8464 : whose indexes range within [0.. Min(M,N)-1]
8465 :
8466 : Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size
8467 : MxM, L - lower triangular (or lower trapezoid) matrix of size MxN.
8468 :
8469 : -- LAPACK routine (version 3.0) --
8470 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
8471 : Courant Institute, Argonne National Lab, and Rice University
8472 : September 30, 1994
8473 : *************************************************************************/
8474 0 : void cmatrixlq(complex_2d_array &a, const ae_int_t m, const ae_int_t n, complex_1d_array &tau, const xparams _xparams)
8475 : {
8476 : jmp_buf _break_jump;
8477 : alglib_impl::ae_state _alglib_env_state;
8478 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8479 0 : if( setjmp(_break_jump) )
8480 : {
8481 : #if !defined(AE_NO_EXCEPTIONS)
8482 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8483 : #else
8484 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8485 : return;
8486 : #endif
8487 : }
8488 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8489 0 : if( _xparams.flags!=0x0 )
8490 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8491 0 : alglib_impl::cmatrixlq(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), &_alglib_env_state);
8492 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8493 0 : return;
8494 : }
8495 :
8496 : /*************************************************************************
8497 : Partial unpacking of matrix Q from the QR decomposition of a matrix A
8498 :
8499 : ! COMMERCIAL EDITION OF ALGLIB:
8500 : !
8501 : ! Commercial Edition of ALGLIB includes following important improvements
8502 : ! of this function:
8503 : ! * high-performance native backend with same C# interface (C# version)
8504 : ! * multithreading support (C++ and C# versions)
8505 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8506 : ! (C++ and C# versions, x86/x64 platform)
8507 : !
8508 : ! We recommend you to read 'Working with commercial version' section of
8509 : ! ALGLIB Reference Manual in order to find out how to use performance-
8510 : ! related features provided by commercial edition of ALGLIB.
8511 :
8512 : Input parameters:
8513 : A - matrices Q and R in compact form.
8514 : Output of RMatrixQR subroutine.
8515 : M - number of rows in given matrix A. M>=0.
8516 : N - number of columns in given matrix A. N>=0.
8517 : Tau - scalar factors which are used to form Q.
8518 : Output of the RMatrixQR subroutine.
8519 : QColumns - required number of columns of matrix Q. M>=QColumns>=0.
8520 :
8521 : Output parameters:
8522 : Q - first QColumns columns of matrix Q.
8523 : Array whose indexes range within [0..M-1, 0..QColumns-1].
8524 : If QColumns=0, the array remains unchanged.
8525 :
8526 : -- ALGLIB routine --
8527 : 17.02.2010
8528 : Bochkanov Sergey
8529 : *************************************************************************/
8530 0 : void rmatrixqrunpackq(const real_2d_array &a, const ae_int_t m, const ae_int_t n, const real_1d_array &tau, const ae_int_t qcolumns, real_2d_array &q, const xparams _xparams)
8531 : {
8532 : jmp_buf _break_jump;
8533 : alglib_impl::ae_state _alglib_env_state;
8534 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8535 0 : if( setjmp(_break_jump) )
8536 : {
8537 : #if !defined(AE_NO_EXCEPTIONS)
8538 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8539 : #else
8540 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8541 : return;
8542 : #endif
8543 : }
8544 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8545 0 : if( _xparams.flags!=0x0 )
8546 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8547 0 : alglib_impl::rmatrixqrunpackq(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), qcolumns, const_cast<alglib_impl::ae_matrix*>(q.c_ptr()), &_alglib_env_state);
8548 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8549 0 : return;
8550 : }
8551 :
8552 : /*************************************************************************
8553 : Unpacking of matrix R from the QR decomposition of a matrix A
8554 :
8555 : Input parameters:
8556 : A - matrices Q and R in compact form.
8557 : Output of RMatrixQR subroutine.
8558 : M - number of rows in given matrix A. M>=0.
8559 : N - number of columns in given matrix A. N>=0.
8560 :
8561 : Output parameters:
8562 : R - matrix R, array[0..M-1, 0..N-1].
8563 :
8564 : -- ALGLIB routine --
8565 : 17.02.2010
8566 : Bochkanov Sergey
8567 : *************************************************************************/
8568 0 : void rmatrixqrunpackr(const real_2d_array &a, const ae_int_t m, const ae_int_t n, real_2d_array &r, const xparams _xparams)
8569 : {
8570 : jmp_buf _break_jump;
8571 : alglib_impl::ae_state _alglib_env_state;
8572 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8573 0 : if( setjmp(_break_jump) )
8574 : {
8575 : #if !defined(AE_NO_EXCEPTIONS)
8576 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8577 : #else
8578 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8579 : return;
8580 : #endif
8581 : }
8582 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8583 0 : if( _xparams.flags!=0x0 )
8584 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8585 0 : alglib_impl::rmatrixqrunpackr(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_matrix*>(r.c_ptr()), &_alglib_env_state);
8586 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8587 0 : return;
8588 : }
8589 :
8590 : /*************************************************************************
8591 : Partial unpacking of matrix Q from the LQ decomposition of a matrix A
8592 :
8593 : ! COMMERCIAL EDITION OF ALGLIB:
8594 : !
8595 : ! Commercial Edition of ALGLIB includes following important improvements
8596 : ! of this function:
8597 : ! * high-performance native backend with same C# interface (C# version)
8598 : ! * multithreading support (C++ and C# versions)
8599 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8600 : ! (C++ and C# versions, x86/x64 platform)
8601 : !
8602 : ! We recommend you to read 'Working with commercial version' section of
8603 : ! ALGLIB Reference Manual in order to find out how to use performance-
8604 : ! related features provided by commercial edition of ALGLIB.
8605 :
8606 : Input parameters:
8607 : A - matrices L and Q in compact form.
8608 : Output of RMatrixLQ subroutine.
8609 : M - number of rows in given matrix A. M>=0.
8610 : N - number of columns in given matrix A. N>=0.
8611 : Tau - scalar factors which are used to form Q.
8612 : Output of the RMatrixLQ subroutine.
8613 : QRows - required number of rows in matrix Q. N>=QRows>=0.
8614 :
8615 : Output parameters:
8616 : Q - first QRows rows of matrix Q. Array whose indexes range
8617 : within [0..QRows-1, 0..N-1]. If QRows=0, the array remains
8618 : unchanged.
8619 :
8620 : -- ALGLIB routine --
8621 : 17.02.2010
8622 : Bochkanov Sergey
8623 : *************************************************************************/
8624 0 : void rmatrixlqunpackq(const real_2d_array &a, const ae_int_t m, const ae_int_t n, const real_1d_array &tau, const ae_int_t qrows, real_2d_array &q, const xparams _xparams)
8625 : {
8626 : jmp_buf _break_jump;
8627 : alglib_impl::ae_state _alglib_env_state;
8628 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8629 0 : if( setjmp(_break_jump) )
8630 : {
8631 : #if !defined(AE_NO_EXCEPTIONS)
8632 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8633 : #else
8634 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8635 : return;
8636 : #endif
8637 : }
8638 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8639 0 : if( _xparams.flags!=0x0 )
8640 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8641 0 : alglib_impl::rmatrixlqunpackq(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), qrows, const_cast<alglib_impl::ae_matrix*>(q.c_ptr()), &_alglib_env_state);
8642 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8643 0 : return;
8644 : }
8645 :
8646 : /*************************************************************************
8647 : Unpacking of matrix L from the LQ decomposition of a matrix A
8648 :
8649 : Input parameters:
8650 : A - matrices Q and L in compact form.
8651 : Output of RMatrixLQ subroutine.
8652 : M - number of rows in given matrix A. M>=0.
8653 : N - number of columns in given matrix A. N>=0.
8654 :
8655 : Output parameters:
8656 : L - matrix L, array[0..M-1, 0..N-1].
8657 :
8658 : -- ALGLIB routine --
8659 : 17.02.2010
8660 : Bochkanov Sergey
8661 : *************************************************************************/
8662 0 : void rmatrixlqunpackl(const real_2d_array &a, const ae_int_t m, const ae_int_t n, real_2d_array &l, const xparams _xparams)
8663 : {
8664 : jmp_buf _break_jump;
8665 : alglib_impl::ae_state _alglib_env_state;
8666 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8667 0 : if( setjmp(_break_jump) )
8668 : {
8669 : #if !defined(AE_NO_EXCEPTIONS)
8670 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8671 : #else
8672 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8673 : return;
8674 : #endif
8675 : }
8676 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8677 0 : if( _xparams.flags!=0x0 )
8678 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8679 0 : alglib_impl::rmatrixlqunpackl(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_matrix*>(l.c_ptr()), &_alglib_env_state);
8680 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8681 0 : return;
8682 : }
8683 :
8684 : /*************************************************************************
8685 : Partial unpacking of matrix Q from QR decomposition of a complex matrix A.
8686 :
8687 : ! COMMERCIAL EDITION OF ALGLIB:
8688 : !
8689 : ! Commercial Edition of ALGLIB includes following important improvements
8690 : ! of this function:
8691 : ! * high-performance native backend with same C# interface (C# version)
8692 : ! * multithreading support (C++ and C# versions)
8693 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8694 : ! (C++ and C# versions, x86/x64 platform)
8695 : !
8696 : ! We recommend you to read 'Working with commercial version' section of
8697 : ! ALGLIB Reference Manual in order to find out how to use performance-
8698 : ! related features provided by commercial edition of ALGLIB.
8699 :
8700 : Input parameters:
8701 : A - matrices Q and R in compact form.
8702 : Output of CMatrixQR subroutine .
8703 : M - number of rows in matrix A. M>=0.
8704 : N - number of columns in matrix A. N>=0.
8705 : Tau - scalar factors which are used to form Q.
8706 : Output of CMatrixQR subroutine .
8707 : QColumns - required number of columns in matrix Q. M>=QColumns>=0.
8708 :
8709 : Output parameters:
8710 : Q - first QColumns columns of matrix Q.
8711 : Array whose index ranges within [0..M-1, 0..QColumns-1].
8712 : If QColumns=0, array isn't changed.
8713 :
8714 : -- ALGLIB routine --
8715 : 17.02.2010
8716 : Bochkanov Sergey
8717 : *************************************************************************/
8718 0 : void cmatrixqrunpackq(const complex_2d_array &a, const ae_int_t m, const ae_int_t n, const complex_1d_array &tau, const ae_int_t qcolumns, complex_2d_array &q, const xparams _xparams)
8719 : {
8720 : jmp_buf _break_jump;
8721 : alglib_impl::ae_state _alglib_env_state;
8722 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8723 0 : if( setjmp(_break_jump) )
8724 : {
8725 : #if !defined(AE_NO_EXCEPTIONS)
8726 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8727 : #else
8728 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8729 : return;
8730 : #endif
8731 : }
8732 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8733 0 : if( _xparams.flags!=0x0 )
8734 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8735 0 : alglib_impl::cmatrixqrunpackq(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), qcolumns, const_cast<alglib_impl::ae_matrix*>(q.c_ptr()), &_alglib_env_state);
8736 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8737 0 : return;
8738 : }
8739 :
8740 : /*************************************************************************
8741 : Unpacking of matrix R from the QR decomposition of a matrix A
8742 :
8743 : Input parameters:
8744 : A - matrices Q and R in compact form.
8745 : Output of CMatrixQR subroutine.
8746 : M - number of rows in given matrix A. M>=0.
8747 : N - number of columns in given matrix A. N>=0.
8748 :
8749 : Output parameters:
8750 : R - matrix R, array[0..M-1, 0..N-1].
8751 :
8752 : -- ALGLIB routine --
8753 : 17.02.2010
8754 : Bochkanov Sergey
8755 : *************************************************************************/
8756 0 : void cmatrixqrunpackr(const complex_2d_array &a, const ae_int_t m, const ae_int_t n, complex_2d_array &r, const xparams _xparams)
8757 : {
8758 : jmp_buf _break_jump;
8759 : alglib_impl::ae_state _alglib_env_state;
8760 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8761 0 : if( setjmp(_break_jump) )
8762 : {
8763 : #if !defined(AE_NO_EXCEPTIONS)
8764 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8765 : #else
8766 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8767 : return;
8768 : #endif
8769 : }
8770 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8771 0 : if( _xparams.flags!=0x0 )
8772 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8773 0 : alglib_impl::cmatrixqrunpackr(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_matrix*>(r.c_ptr()), &_alglib_env_state);
8774 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8775 0 : return;
8776 : }
8777 :
8778 : /*************************************************************************
8779 : Partial unpacking of matrix Q from LQ decomposition of a complex matrix A.
8780 :
8781 : ! COMMERCIAL EDITION OF ALGLIB:
8782 : !
8783 : ! Commercial Edition of ALGLIB includes following important improvements
8784 : ! of this function:
8785 : ! * high-performance native backend with same C# interface (C# version)
8786 : ! * multithreading support (C++ and C# versions)
8787 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8788 : ! (C++ and C# versions, x86/x64 platform)
8789 : !
8790 : ! We recommend you to read 'Working with commercial version' section of
8791 : ! ALGLIB Reference Manual in order to find out how to use performance-
8792 : ! related features provided by commercial edition of ALGLIB.
8793 :
8794 : Input parameters:
8795 : A - matrices Q and R in compact form.
8796 : Output of CMatrixLQ subroutine .
8797 : M - number of rows in matrix A. M>=0.
8798 : N - number of columns in matrix A. N>=0.
8799 : Tau - scalar factors which are used to form Q.
8800 : Output of CMatrixLQ subroutine .
8801 : QRows - required number of rows in matrix Q. N>=QColumns>=0.
8802 :
8803 : Output parameters:
8804 : Q - first QRows rows of matrix Q.
8805 : Array whose index ranges within [0..QRows-1, 0..N-1].
8806 : If QRows=0, array isn't changed.
8807 :
8808 : -- ALGLIB routine --
8809 : 17.02.2010
8810 : Bochkanov Sergey
8811 : *************************************************************************/
8812 0 : void cmatrixlqunpackq(const complex_2d_array &a, const ae_int_t m, const ae_int_t n, const complex_1d_array &tau, const ae_int_t qrows, complex_2d_array &q, const xparams _xparams)
8813 : {
8814 : jmp_buf _break_jump;
8815 : alglib_impl::ae_state _alglib_env_state;
8816 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8817 0 : if( setjmp(_break_jump) )
8818 : {
8819 : #if !defined(AE_NO_EXCEPTIONS)
8820 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8821 : #else
8822 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8823 : return;
8824 : #endif
8825 : }
8826 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8827 0 : if( _xparams.flags!=0x0 )
8828 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8829 0 : alglib_impl::cmatrixlqunpackq(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), qrows, const_cast<alglib_impl::ae_matrix*>(q.c_ptr()), &_alglib_env_state);
8830 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8831 0 : return;
8832 : }
8833 :
8834 : /*************************************************************************
8835 : Unpacking of matrix L from the LQ decomposition of a matrix A
8836 :
8837 : Input parameters:
8838 : A - matrices Q and L in compact form.
8839 : Output of CMatrixLQ subroutine.
8840 : M - number of rows in given matrix A. M>=0.
8841 : N - number of columns in given matrix A. N>=0.
8842 :
8843 : Output parameters:
8844 : L - matrix L, array[0..M-1, 0..N-1].
8845 :
8846 : -- ALGLIB routine --
8847 : 17.02.2010
8848 : Bochkanov Sergey
8849 : *************************************************************************/
8850 0 : void cmatrixlqunpackl(const complex_2d_array &a, const ae_int_t m, const ae_int_t n, complex_2d_array &l, const xparams _xparams)
8851 : {
8852 : jmp_buf _break_jump;
8853 : alglib_impl::ae_state _alglib_env_state;
8854 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8855 0 : if( setjmp(_break_jump) )
8856 : {
8857 : #if !defined(AE_NO_EXCEPTIONS)
8858 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8859 : #else
8860 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8861 : return;
8862 : #endif
8863 : }
8864 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8865 0 : if( _xparams.flags!=0x0 )
8866 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8867 0 : alglib_impl::cmatrixlqunpackl(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_matrix*>(l.c_ptr()), &_alglib_env_state);
8868 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8869 0 : return;
8870 : }
8871 :
8872 : /*************************************************************************
8873 : Reduction of a rectangular matrix to bidiagonal form
8874 :
8875 : The algorithm reduces the rectangular matrix A to bidiagonal form by
8876 : orthogonal transformations P and Q: A = Q*B*(P^T).
8877 :
8878 : ! COMMERCIAL EDITION OF ALGLIB:
8879 : !
8880 : ! Commercial Edition of ALGLIB includes following important improvements
8881 : ! of this function:
8882 : ! * high-performance native backend with same C# interface (C# version)
8883 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8884 : ! (C++ and C# versions, x86/x64 platform)
8885 : !
8886 : ! We recommend you to read 'Working with commercial version' section of
8887 : ! ALGLIB Reference Manual in order to find out how to use performance-
8888 : ! related features provided by commercial edition of ALGLIB.
8889 :
8890 : Input parameters:
8891 : A - source matrix. array[0..M-1, 0..N-1]
8892 : M - number of rows in matrix A.
8893 : N - number of columns in matrix A.
8894 :
8895 : Output parameters:
8896 : A - matrices Q, B, P in compact form (see below).
8897 : TauQ - scalar factors which are used to form matrix Q.
8898 : TauP - scalar factors which are used to form matrix P.
8899 :
8900 : The main diagonal and one of the secondary diagonals of matrix A are
8901 : replaced with bidiagonal matrix B. Other elements contain elementary
8902 : reflections which form MxM matrix Q and NxN matrix P, respectively.
8903 :
8904 : If M>=N, B is the upper bidiagonal MxN matrix and is stored in the
8905 : corresponding elements of matrix A. Matrix Q is represented as a
8906 : product of elementary reflections Q = H(0)*H(1)*...*H(n-1), where
8907 : H(i) = 1-tau*v*v'. Here tau is a scalar which is stored in TauQ[i], and
8908 : vector v has the following structure: v(0:i-1)=0, v(i)=1, v(i+1:m-1) is
8909 : stored in elements A(i+1:m-1,i). Matrix P is as follows: P =
8910 : G(0)*G(1)*...*G(n-2), where G(i) = 1 - tau*u*u'. Tau is stored in TauP[i],
8911 : u(0:i)=0, u(i+1)=1, u(i+2:n-1) is stored in elements A(i,i+2:n-1).
8912 :
8913 : If M<N, B is the lower bidiagonal MxN matrix and is stored in the
8914 : corresponding elements of matrix A. Q = H(0)*H(1)*...*H(m-2), where
8915 : H(i) = 1 - tau*v*v', tau is stored in TauQ, v(0:i)=0, v(i+1)=1, v(i+2:m-1)
8916 : is stored in elements A(i+2:m-1,i). P = G(0)*G(1)*...*G(m-1),
8917 : G(i) = 1-tau*u*u', tau is stored in TauP, u(0:i-1)=0, u(i)=1, u(i+1:n-1)
8918 : is stored in A(i,i+1:n-1).
8919 :
8920 : EXAMPLE:
8921 :
8922 : m=6, n=5 (m > n): m=5, n=6 (m < n):
8923 :
8924 : ( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 )
8925 : ( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 )
8926 : ( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 )
8927 : ( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 )
8928 : ( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 )
8929 : ( v1 v2 v3 v4 v5 )
8930 :
8931 : Here vi and ui are vectors which form H(i) and G(i), and d and e -
8932 : are the diagonal and off-diagonal elements of matrix B.
8933 :
8934 : -- LAPACK routine (version 3.0) --
8935 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
8936 : Courant Institute, Argonne National Lab, and Rice University
8937 : September 30, 1994.
8938 : Sergey Bochkanov, ALGLIB project, translation from FORTRAN to
8939 : pseudocode, 2007-2010.
8940 : *************************************************************************/
8941 0 : void rmatrixbd(real_2d_array &a, const ae_int_t m, const ae_int_t n, real_1d_array &tauq, real_1d_array &taup, const xparams _xparams)
8942 : {
8943 : jmp_buf _break_jump;
8944 : alglib_impl::ae_state _alglib_env_state;
8945 0 : alglib_impl::ae_state_init(&_alglib_env_state);
8946 0 : if( setjmp(_break_jump) )
8947 : {
8948 : #if !defined(AE_NO_EXCEPTIONS)
8949 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
8950 : #else
8951 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
8952 : return;
8953 : #endif
8954 : }
8955 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
8956 0 : if( _xparams.flags!=0x0 )
8957 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
8958 0 : alglib_impl::rmatrixbd(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(tauq.c_ptr()), const_cast<alglib_impl::ae_vector*>(taup.c_ptr()), &_alglib_env_state);
8959 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
8960 0 : return;
8961 : }
8962 :
8963 : /*************************************************************************
8964 : Unpacking matrix Q which reduces a matrix to bidiagonal form.
8965 :
8966 : ! COMMERCIAL EDITION OF ALGLIB:
8967 : !
8968 : ! Commercial Edition of ALGLIB includes following important improvements
8969 : ! of this function:
8970 : ! * high-performance native backend with same C# interface (C# version)
8971 : ! * hardware vendor (Intel) implementations of linear algebra primitives
8972 : ! (C++ and C# versions, x86/x64 platform)
8973 : !
8974 : ! We recommend you to read 'Working with commercial version' section of
8975 : ! ALGLIB Reference Manual in order to find out how to use performance-
8976 : ! related features provided by commercial edition of ALGLIB.
8977 :
8978 : Input parameters:
8979 : QP - matrices Q and P in compact form.
8980 : Output of ToBidiagonal subroutine.
8981 : M - number of rows in matrix A.
8982 : N - number of columns in matrix A.
8983 : TAUQ - scalar factors which are used to form Q.
8984 : Output of ToBidiagonal subroutine.
8985 : QColumns - required number of columns in matrix Q.
8986 : M>=QColumns>=0.
8987 :
8988 : Output parameters:
8989 : Q - first QColumns columns of matrix Q.
8990 : Array[0..M-1, 0..QColumns-1]
8991 : If QColumns=0, the array is not modified.
8992 :
8993 : -- ALGLIB --
8994 : 2005-2010
8995 : Bochkanov Sergey
8996 : *************************************************************************/
8997 0 : void rmatrixbdunpackq(const real_2d_array &qp, const ae_int_t m, const ae_int_t n, const real_1d_array &tauq, const ae_int_t qcolumns, real_2d_array &q, const xparams _xparams)
8998 : {
8999 : jmp_buf _break_jump;
9000 : alglib_impl::ae_state _alglib_env_state;
9001 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9002 0 : if( setjmp(_break_jump) )
9003 : {
9004 : #if !defined(AE_NO_EXCEPTIONS)
9005 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9006 : #else
9007 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9008 : return;
9009 : #endif
9010 : }
9011 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9012 0 : if( _xparams.flags!=0x0 )
9013 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9014 0 : alglib_impl::rmatrixbdunpackq(const_cast<alglib_impl::ae_matrix*>(qp.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(tauq.c_ptr()), qcolumns, const_cast<alglib_impl::ae_matrix*>(q.c_ptr()), &_alglib_env_state);
9015 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9016 0 : return;
9017 : }
9018 :
9019 : /*************************************************************************
9020 : Multiplication by matrix Q which reduces matrix A to bidiagonal form.
9021 :
9022 : The algorithm allows pre- or post-multiply by Q or Q'.
9023 :
9024 : ! COMMERCIAL EDITION OF ALGLIB:
9025 : !
9026 : ! Commercial Edition of ALGLIB includes following important improvements
9027 : ! of this function:
9028 : ! * high-performance native backend with same C# interface (C# version)
9029 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9030 : ! (C++ and C# versions, x86/x64 platform)
9031 : !
9032 : ! We recommend you to read 'Working with commercial version' section of
9033 : ! ALGLIB Reference Manual in order to find out how to use performance-
9034 : ! related features provided by commercial edition of ALGLIB.
9035 :
9036 : Input parameters:
9037 : QP - matrices Q and P in compact form.
9038 : Output of ToBidiagonal subroutine.
9039 : M - number of rows in matrix A.
9040 : N - number of columns in matrix A.
9041 : TAUQ - scalar factors which are used to form Q.
9042 : Output of ToBidiagonal subroutine.
9043 : Z - multiplied matrix.
9044 : array[0..ZRows-1,0..ZColumns-1]
9045 : ZRows - number of rows in matrix Z. If FromTheRight=False,
9046 : ZRows=M, otherwise ZRows can be arbitrary.
9047 : ZColumns - number of columns in matrix Z. If FromTheRight=True,
9048 : ZColumns=M, otherwise ZColumns can be arbitrary.
9049 : FromTheRight - pre- or post-multiply.
9050 : DoTranspose - multiply by Q or Q'.
9051 :
9052 : Output parameters:
9053 : Z - product of Z and Q.
9054 : Array[0..ZRows-1,0..ZColumns-1]
9055 : If ZRows=0 or ZColumns=0, the array is not modified.
9056 :
9057 : -- ALGLIB --
9058 : 2005-2010
9059 : Bochkanov Sergey
9060 : *************************************************************************/
9061 0 : void rmatrixbdmultiplybyq(const real_2d_array &qp, const ae_int_t m, const ae_int_t n, const real_1d_array &tauq, real_2d_array &z, const ae_int_t zrows, const ae_int_t zcolumns, const bool fromtheright, const bool dotranspose, const xparams _xparams)
9062 : {
9063 : jmp_buf _break_jump;
9064 : alglib_impl::ae_state _alglib_env_state;
9065 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9066 0 : if( setjmp(_break_jump) )
9067 : {
9068 : #if !defined(AE_NO_EXCEPTIONS)
9069 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9070 : #else
9071 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9072 : return;
9073 : #endif
9074 : }
9075 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9076 0 : if( _xparams.flags!=0x0 )
9077 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9078 0 : alglib_impl::rmatrixbdmultiplybyq(const_cast<alglib_impl::ae_matrix*>(qp.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(tauq.c_ptr()), const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), zrows, zcolumns, fromtheright, dotranspose, &_alglib_env_state);
9079 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9080 0 : return;
9081 : }
9082 :
9083 : /*************************************************************************
9084 : Unpacking matrix P which reduces matrix A to bidiagonal form.
9085 : The subroutine returns transposed matrix P.
9086 :
9087 : Input parameters:
9088 : QP - matrices Q and P in compact form.
9089 : Output of ToBidiagonal subroutine.
9090 : M - number of rows in matrix A.
9091 : N - number of columns in matrix A.
9092 : TAUP - scalar factors which are used to form P.
9093 : Output of ToBidiagonal subroutine.
9094 : PTRows - required number of rows of matrix P^T. N >= PTRows >= 0.
9095 :
9096 : Output parameters:
9097 : PT - first PTRows columns of matrix P^T
9098 : Array[0..PTRows-1, 0..N-1]
9099 : If PTRows=0, the array is not modified.
9100 :
9101 : -- ALGLIB --
9102 : 2005-2010
9103 : Bochkanov Sergey
9104 : *************************************************************************/
9105 0 : void rmatrixbdunpackpt(const real_2d_array &qp, const ae_int_t m, const ae_int_t n, const real_1d_array &taup, const ae_int_t ptrows, real_2d_array &pt, const xparams _xparams)
9106 : {
9107 : jmp_buf _break_jump;
9108 : alglib_impl::ae_state _alglib_env_state;
9109 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9110 0 : if( setjmp(_break_jump) )
9111 : {
9112 : #if !defined(AE_NO_EXCEPTIONS)
9113 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9114 : #else
9115 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9116 : return;
9117 : #endif
9118 : }
9119 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9120 0 : if( _xparams.flags!=0x0 )
9121 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9122 0 : alglib_impl::rmatrixbdunpackpt(const_cast<alglib_impl::ae_matrix*>(qp.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(taup.c_ptr()), ptrows, const_cast<alglib_impl::ae_matrix*>(pt.c_ptr()), &_alglib_env_state);
9123 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9124 0 : return;
9125 : }
9126 :
9127 : /*************************************************************************
9128 : Multiplication by matrix P which reduces matrix A to bidiagonal form.
9129 :
9130 : The algorithm allows pre- or post-multiply by P or P'.
9131 :
9132 : Input parameters:
9133 : QP - matrices Q and P in compact form.
9134 : Output of RMatrixBD subroutine.
9135 : M - number of rows in matrix A.
9136 : N - number of columns in matrix A.
9137 : TAUP - scalar factors which are used to form P.
9138 : Output of RMatrixBD subroutine.
9139 : Z - multiplied matrix.
9140 : Array whose indexes range within [0..ZRows-1,0..ZColumns-1].
9141 : ZRows - number of rows in matrix Z. If FromTheRight=False,
9142 : ZRows=N, otherwise ZRows can be arbitrary.
9143 : ZColumns - number of columns in matrix Z. If FromTheRight=True,
9144 : ZColumns=N, otherwise ZColumns can be arbitrary.
9145 : FromTheRight - pre- or post-multiply.
9146 : DoTranspose - multiply by P or P'.
9147 :
9148 : Output parameters:
9149 : Z - product of Z and P.
9150 : Array whose indexes range within [0..ZRows-1,0..ZColumns-1].
9151 : If ZRows=0 or ZColumns=0, the array is not modified.
9152 :
9153 : -- ALGLIB --
9154 : 2005-2010
9155 : Bochkanov Sergey
9156 : *************************************************************************/
9157 0 : void rmatrixbdmultiplybyp(const real_2d_array &qp, const ae_int_t m, const ae_int_t n, const real_1d_array &taup, real_2d_array &z, const ae_int_t zrows, const ae_int_t zcolumns, const bool fromtheright, const bool dotranspose, const xparams _xparams)
9158 : {
9159 : jmp_buf _break_jump;
9160 : alglib_impl::ae_state _alglib_env_state;
9161 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9162 0 : if( setjmp(_break_jump) )
9163 : {
9164 : #if !defined(AE_NO_EXCEPTIONS)
9165 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9166 : #else
9167 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9168 : return;
9169 : #endif
9170 : }
9171 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9172 0 : if( _xparams.flags!=0x0 )
9173 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9174 0 : alglib_impl::rmatrixbdmultiplybyp(const_cast<alglib_impl::ae_matrix*>(qp.c_ptr()), m, n, const_cast<alglib_impl::ae_vector*>(taup.c_ptr()), const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), zrows, zcolumns, fromtheright, dotranspose, &_alglib_env_state);
9175 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9176 0 : return;
9177 : }
9178 :
9179 : /*************************************************************************
9180 : Unpacking of the main and secondary diagonals of bidiagonal decomposition
9181 : of matrix A.
9182 :
9183 : Input parameters:
9184 : B - output of RMatrixBD subroutine.
9185 : M - number of rows in matrix B.
9186 : N - number of columns in matrix B.
9187 :
9188 : Output parameters:
9189 : IsUpper - True, if the matrix is upper bidiagonal.
9190 : otherwise IsUpper is False.
9191 : D - the main diagonal.
9192 : Array whose index ranges within [0..Min(M,N)-1].
9193 : E - the secondary diagonal (upper or lower, depending on
9194 : the value of IsUpper).
9195 : Array index ranges within [0..Min(M,N)-1], the last
9196 : element is not used.
9197 :
9198 : -- ALGLIB --
9199 : 2005-2010
9200 : Bochkanov Sergey
9201 : *************************************************************************/
9202 0 : void rmatrixbdunpackdiagonals(const real_2d_array &b, const ae_int_t m, const ae_int_t n, bool &isupper, real_1d_array &d, real_1d_array &e, const xparams _xparams)
9203 : {
9204 : jmp_buf _break_jump;
9205 : alglib_impl::ae_state _alglib_env_state;
9206 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9207 0 : if( setjmp(_break_jump) )
9208 : {
9209 : #if !defined(AE_NO_EXCEPTIONS)
9210 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9211 : #else
9212 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9213 : return;
9214 : #endif
9215 : }
9216 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9217 0 : if( _xparams.flags!=0x0 )
9218 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9219 0 : alglib_impl::rmatrixbdunpackdiagonals(const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), m, n, &isupper, const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_vector*>(e.c_ptr()), &_alglib_env_state);
9220 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9221 0 : return;
9222 : }
9223 :
9224 : /*************************************************************************
9225 : Reduction of a square matrix to upper Hessenberg form: Q'*A*Q = H,
9226 : where Q is an orthogonal matrix, H - Hessenberg matrix.
9227 :
9228 : ! COMMERCIAL EDITION OF ALGLIB:
9229 : !
9230 : ! Commercial Edition of ALGLIB includes following important improvements
9231 : ! of this function:
9232 : ! * high-performance native backend with same C# interface (C# version)
9233 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9234 : ! (C++ and C# versions, x86/x64 platform)
9235 : !
9236 : ! We recommend you to read 'Working with commercial version' section of
9237 : ! ALGLIB Reference Manual in order to find out how to use performance-
9238 : ! related features provided by commercial edition of ALGLIB.
9239 :
9240 : Input parameters:
9241 : A - matrix A with elements [0..N-1, 0..N-1]
9242 : N - size of matrix A.
9243 :
9244 : Output parameters:
9245 : A - matrices Q and P in compact form (see below).
9246 : Tau - array of scalar factors which are used to form matrix Q.
9247 : Array whose index ranges within [0..N-2]
9248 :
9249 : Matrix H is located on the main diagonal, on the lower secondary diagonal
9250 : and above the main diagonal of matrix A. The elements which are used to
9251 : form matrix Q are situated in array Tau and below the lower secondary
9252 : diagonal of matrix A as follows:
9253 :
9254 : Matrix Q is represented as a product of elementary reflections
9255 :
9256 : Q = H(0)*H(2)*...*H(n-2),
9257 :
9258 : where each H(i) is given by
9259 :
9260 : H(i) = 1 - tau * v * (v^T)
9261 :
9262 : where tau is a scalar stored in Tau[I]; v - is a real vector,
9263 : so that v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) stored in A(i+2:n-1,i).
9264 :
9265 : -- LAPACK routine (version 3.0) --
9266 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
9267 : Courant Institute, Argonne National Lab, and Rice University
9268 : October 31, 1992
9269 : *************************************************************************/
9270 0 : void rmatrixhessenberg(real_2d_array &a, const ae_int_t n, real_1d_array &tau, const xparams _xparams)
9271 : {
9272 : jmp_buf _break_jump;
9273 : alglib_impl::ae_state _alglib_env_state;
9274 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9275 0 : if( setjmp(_break_jump) )
9276 : {
9277 : #if !defined(AE_NO_EXCEPTIONS)
9278 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9279 : #else
9280 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9281 : return;
9282 : #endif
9283 : }
9284 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9285 0 : if( _xparams.flags!=0x0 )
9286 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9287 0 : alglib_impl::rmatrixhessenberg(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), &_alglib_env_state);
9288 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9289 0 : return;
9290 : }
9291 :
9292 : /*************************************************************************
9293 : Unpacking matrix Q which reduces matrix A to upper Hessenberg form
9294 :
9295 : ! COMMERCIAL EDITION OF ALGLIB:
9296 : !
9297 : ! Commercial Edition of ALGLIB includes following important improvements
9298 : ! of this function:
9299 : ! * high-performance native backend with same C# interface (C# version)
9300 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9301 : ! (C++ and C# versions, x86/x64 platform)
9302 : !
9303 : ! We recommend you to read 'Working with commercial version' section of
9304 : ! ALGLIB Reference Manual in order to find out how to use performance-
9305 : ! related features provided by commercial edition of ALGLIB.
9306 :
9307 : Input parameters:
9308 : A - output of RMatrixHessenberg subroutine.
9309 : N - size of matrix A.
9310 : Tau - scalar factors which are used to form Q.
9311 : Output of RMatrixHessenberg subroutine.
9312 :
9313 : Output parameters:
9314 : Q - matrix Q.
9315 : Array whose indexes range within [0..N-1, 0..N-1].
9316 :
9317 : -- ALGLIB --
9318 : 2005-2010
9319 : Bochkanov Sergey
9320 : *************************************************************************/
9321 0 : void rmatrixhessenbergunpackq(const real_2d_array &a, const ae_int_t n, const real_1d_array &tau, real_2d_array &q, const xparams _xparams)
9322 : {
9323 : jmp_buf _break_jump;
9324 : alglib_impl::ae_state _alglib_env_state;
9325 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9326 0 : if( setjmp(_break_jump) )
9327 : {
9328 : #if !defined(AE_NO_EXCEPTIONS)
9329 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9330 : #else
9331 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9332 : return;
9333 : #endif
9334 : }
9335 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9336 0 : if( _xparams.flags!=0x0 )
9337 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9338 0 : alglib_impl::rmatrixhessenbergunpackq(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), const_cast<alglib_impl::ae_matrix*>(q.c_ptr()), &_alglib_env_state);
9339 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9340 0 : return;
9341 : }
9342 :
9343 : /*************************************************************************
9344 : Unpacking matrix H (the result of matrix A reduction to upper Hessenberg form)
9345 :
9346 : Input parameters:
9347 : A - output of RMatrixHessenberg subroutine.
9348 : N - size of matrix A.
9349 :
9350 : Output parameters:
9351 : H - matrix H. Array whose indexes range within [0..N-1, 0..N-1].
9352 :
9353 : -- ALGLIB --
9354 : 2005-2010
9355 : Bochkanov Sergey
9356 : *************************************************************************/
9357 0 : void rmatrixhessenbergunpackh(const real_2d_array &a, const ae_int_t n, real_2d_array &h, const xparams _xparams)
9358 : {
9359 : jmp_buf _break_jump;
9360 : alglib_impl::ae_state _alglib_env_state;
9361 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9362 0 : if( setjmp(_break_jump) )
9363 : {
9364 : #if !defined(AE_NO_EXCEPTIONS)
9365 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9366 : #else
9367 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9368 : return;
9369 : #endif
9370 : }
9371 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9372 0 : if( _xparams.flags!=0x0 )
9373 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9374 0 : alglib_impl::rmatrixhessenbergunpackh(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, const_cast<alglib_impl::ae_matrix*>(h.c_ptr()), &_alglib_env_state);
9375 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9376 0 : return;
9377 : }
9378 :
9379 : /*************************************************************************
9380 : Reduction of a symmetric matrix which is given by its higher or lower
9381 : triangular part to a tridiagonal matrix using orthogonal similarity
9382 : transformation: Q'*A*Q=T.
9383 :
9384 : ! COMMERCIAL EDITION OF ALGLIB:
9385 : !
9386 : ! Commercial Edition of ALGLIB includes following important improvements
9387 : ! of this function:
9388 : ! * high-performance native backend with same C# interface (C# version)
9389 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9390 : ! (C++ and C# versions, x86/x64 platform)
9391 : !
9392 : ! We recommend you to read 'Working with commercial version' section of
9393 : ! ALGLIB Reference Manual in order to find out how to use performance-
9394 : ! related features provided by commercial edition of ALGLIB.
9395 :
9396 : Input parameters:
9397 : A - matrix to be transformed
9398 : array with elements [0..N-1, 0..N-1].
9399 : N - size of matrix A.
9400 : IsUpper - storage format. If IsUpper = True, then matrix A is given
9401 : by its upper triangle, and the lower triangle is not used
9402 : and not modified by the algorithm, and vice versa
9403 : if IsUpper = False.
9404 :
9405 : Output parameters:
9406 : A - matrices T and Q in compact form (see lower)
9407 : Tau - array of factors which are forming matrices H(i)
9408 : array with elements [0..N-2].
9409 : D - main diagonal of symmetric matrix T.
9410 : array with elements [0..N-1].
9411 : E - secondary diagonal of symmetric matrix T.
9412 : array with elements [0..N-2].
9413 :
9414 :
9415 : If IsUpper=True, the matrix Q is represented as a product of elementary
9416 : reflectors
9417 :
9418 : Q = H(n-2) . . . H(2) H(0).
9419 :
9420 : Each H(i) has the form
9421 :
9422 : H(i) = I - tau * v * v'
9423 :
9424 : where tau is a real scalar, and v is a real vector with
9425 : v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in
9426 : A(0:i-1,i+1), and tau in TAU(i).
9427 :
9428 : If IsUpper=False, the matrix Q is represented as a product of elementary
9429 : reflectors
9430 :
9431 : Q = H(0) H(2) . . . H(n-2).
9432 :
9433 : Each H(i) has the form
9434 :
9435 : H(i) = I - tau * v * v'
9436 :
9437 : where tau is a real scalar, and v is a real vector with
9438 : v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i),
9439 : and tau in TAU(i).
9440 :
9441 : The contents of A on exit are illustrated by the following examples
9442 : with n = 5:
9443 :
9444 : if UPLO = 'U': if UPLO = 'L':
9445 :
9446 : ( d e v1 v2 v3 ) ( d )
9447 : ( d e v2 v3 ) ( e d )
9448 : ( d e v3 ) ( v0 e d )
9449 : ( d e ) ( v0 v1 e d )
9450 : ( d ) ( v0 v1 v2 e d )
9451 :
9452 : where d and e denote diagonal and off-diagonal elements of T, and vi
9453 : denotes an element of the vector defining H(i).
9454 :
9455 : -- LAPACK routine (version 3.0) --
9456 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
9457 : Courant Institute, Argonne National Lab, and Rice University
9458 : October 31, 1992
9459 : *************************************************************************/
9460 0 : void smatrixtd(real_2d_array &a, const ae_int_t n, const bool isupper, real_1d_array &tau, real_1d_array &d, real_1d_array &e, const xparams _xparams)
9461 : {
9462 : jmp_buf _break_jump;
9463 : alglib_impl::ae_state _alglib_env_state;
9464 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9465 0 : if( setjmp(_break_jump) )
9466 : {
9467 : #if !defined(AE_NO_EXCEPTIONS)
9468 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9469 : #else
9470 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9471 : return;
9472 : #endif
9473 : }
9474 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9475 0 : if( _xparams.flags!=0x0 )
9476 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9477 0 : alglib_impl::smatrixtd(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_vector*>(e.c_ptr()), &_alglib_env_state);
9478 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9479 0 : return;
9480 : }
9481 :
9482 : /*************************************************************************
9483 : Unpacking matrix Q which reduces symmetric matrix to a tridiagonal
9484 : form.
9485 :
9486 : ! COMMERCIAL EDITION OF ALGLIB:
9487 : !
9488 : ! Commercial Edition of ALGLIB includes following important improvements
9489 : ! of this function:
9490 : ! * high-performance native backend with same C# interface (C# version)
9491 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9492 : ! (C++ and C# versions, x86/x64 platform)
9493 : !
9494 : ! We recommend you to read 'Working with commercial version' section of
9495 : ! ALGLIB Reference Manual in order to find out how to use performance-
9496 : ! related features provided by commercial edition of ALGLIB.
9497 :
9498 : Input parameters:
9499 : A - the result of a SMatrixTD subroutine
9500 : N - size of matrix A.
9501 : IsUpper - storage format (a parameter of SMatrixTD subroutine)
9502 : Tau - the result of a SMatrixTD subroutine
9503 :
9504 : Output parameters:
9505 : Q - transformation matrix.
9506 : array with elements [0..N-1, 0..N-1].
9507 :
9508 : -- ALGLIB --
9509 : Copyright 2005-2010 by Bochkanov Sergey
9510 : *************************************************************************/
9511 0 : void smatrixtdunpackq(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &tau, real_2d_array &q, const xparams _xparams)
9512 : {
9513 : jmp_buf _break_jump;
9514 : alglib_impl::ae_state _alglib_env_state;
9515 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9516 0 : if( setjmp(_break_jump) )
9517 : {
9518 : #if !defined(AE_NO_EXCEPTIONS)
9519 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9520 : #else
9521 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9522 : return;
9523 : #endif
9524 : }
9525 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9526 0 : if( _xparams.flags!=0x0 )
9527 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9528 0 : alglib_impl::smatrixtdunpackq(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), const_cast<alglib_impl::ae_matrix*>(q.c_ptr()), &_alglib_env_state);
9529 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9530 0 : return;
9531 : }
9532 :
9533 : /*************************************************************************
9534 : Reduction of a Hermitian matrix which is given by its higher or lower
9535 : triangular part to a real tridiagonal matrix using unitary similarity
9536 : transformation: Q'*A*Q = T.
9537 :
9538 : ! COMMERCIAL EDITION OF ALGLIB:
9539 : !
9540 : ! Commercial Edition of ALGLIB includes following important improvements
9541 : ! of this function:
9542 : ! * high-performance native backend with same C# interface (C# version)
9543 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9544 : ! (C++ and C# versions, x86/x64 platform)
9545 : !
9546 : ! We recommend you to read 'Working with commercial version' section of
9547 : ! ALGLIB Reference Manual in order to find out how to use performance-
9548 : ! related features provided by commercial edition of ALGLIB.
9549 :
9550 : Input parameters:
9551 : A - matrix to be transformed
9552 : array with elements [0..N-1, 0..N-1].
9553 : N - size of matrix A.
9554 : IsUpper - storage format. If IsUpper = True, then matrix A is given
9555 : by its upper triangle, and the lower triangle is not used
9556 : and not modified by the algorithm, and vice versa
9557 : if IsUpper = False.
9558 :
9559 : Output parameters:
9560 : A - matrices T and Q in compact form (see lower)
9561 : Tau - array of factors which are forming matrices H(i)
9562 : array with elements [0..N-2].
9563 : D - main diagonal of real symmetric matrix T.
9564 : array with elements [0..N-1].
9565 : E - secondary diagonal of real symmetric matrix T.
9566 : array with elements [0..N-2].
9567 :
9568 :
9569 : If IsUpper=True, the matrix Q is represented as a product of elementary
9570 : reflectors
9571 :
9572 : Q = H(n-2) . . . H(2) H(0).
9573 :
9574 : Each H(i) has the form
9575 :
9576 : H(i) = I - tau * v * v'
9577 :
9578 : where tau is a complex scalar, and v is a complex vector with
9579 : v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in
9580 : A(0:i-1,i+1), and tau in TAU(i).
9581 :
9582 : If IsUpper=False, the matrix Q is represented as a product of elementary
9583 : reflectors
9584 :
9585 : Q = H(0) H(2) . . . H(n-2).
9586 :
9587 : Each H(i) has the form
9588 :
9589 : H(i) = I - tau * v * v'
9590 :
9591 : where tau is a complex scalar, and v is a complex vector with
9592 : v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i),
9593 : and tau in TAU(i).
9594 :
9595 : The contents of A on exit are illustrated by the following examples
9596 : with n = 5:
9597 :
9598 : if UPLO = 'U': if UPLO = 'L':
9599 :
9600 : ( d e v1 v2 v3 ) ( d )
9601 : ( d e v2 v3 ) ( e d )
9602 : ( d e v3 ) ( v0 e d )
9603 : ( d e ) ( v0 v1 e d )
9604 : ( d ) ( v0 v1 v2 e d )
9605 :
9606 : where d and e denote diagonal and off-diagonal elements of T, and vi
9607 : denotes an element of the vector defining H(i).
9608 :
9609 : -- LAPACK routine (version 3.0) --
9610 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
9611 : Courant Institute, Argonne National Lab, and Rice University
9612 : October 31, 1992
9613 : *************************************************************************/
9614 0 : void hmatrixtd(complex_2d_array &a, const ae_int_t n, const bool isupper, complex_1d_array &tau, real_1d_array &d, real_1d_array &e, const xparams _xparams)
9615 : {
9616 : jmp_buf _break_jump;
9617 : alglib_impl::ae_state _alglib_env_state;
9618 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9619 0 : if( setjmp(_break_jump) )
9620 : {
9621 : #if !defined(AE_NO_EXCEPTIONS)
9622 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9623 : #else
9624 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9625 : return;
9626 : #endif
9627 : }
9628 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9629 0 : if( _xparams.flags!=0x0 )
9630 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9631 0 : alglib_impl::hmatrixtd(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_vector*>(e.c_ptr()), &_alglib_env_state);
9632 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9633 0 : return;
9634 : }
9635 :
9636 : /*************************************************************************
9637 : Unpacking matrix Q which reduces a Hermitian matrix to a real tridiagonal
9638 : form.
9639 :
9640 : ! COMMERCIAL EDITION OF ALGLIB:
9641 : !
9642 : ! Commercial Edition of ALGLIB includes following important improvements
9643 : ! of this function:
9644 : ! * high-performance native backend with same C# interface (C# version)
9645 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9646 : ! (C++ and C# versions, x86/x64 platform)
9647 : !
9648 : ! We recommend you to read 'Working with commercial version' section of
9649 : ! ALGLIB Reference Manual in order to find out how to use performance-
9650 : ! related features provided by commercial edition of ALGLIB.
9651 :
9652 : Input parameters:
9653 : A - the result of a HMatrixTD subroutine
9654 : N - size of matrix A.
9655 : IsUpper - storage format (a parameter of HMatrixTD subroutine)
9656 : Tau - the result of a HMatrixTD subroutine
9657 :
9658 : Output parameters:
9659 : Q - transformation matrix.
9660 : array with elements [0..N-1, 0..N-1].
9661 :
9662 : -- ALGLIB --
9663 : Copyright 2005-2010 by Bochkanov Sergey
9664 : *************************************************************************/
9665 0 : void hmatrixtdunpackq(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_1d_array &tau, complex_2d_array &q, const xparams _xparams)
9666 : {
9667 : jmp_buf _break_jump;
9668 : alglib_impl::ae_state _alglib_env_state;
9669 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9670 0 : if( setjmp(_break_jump) )
9671 : {
9672 : #if !defined(AE_NO_EXCEPTIONS)
9673 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9674 : #else
9675 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9676 : return;
9677 : #endif
9678 : }
9679 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9680 0 : if( _xparams.flags!=0x0 )
9681 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9682 0 : alglib_impl::hmatrixtdunpackq(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, const_cast<alglib_impl::ae_vector*>(tau.c_ptr()), const_cast<alglib_impl::ae_matrix*>(q.c_ptr()), &_alglib_env_state);
9683 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9684 0 : return;
9685 : }
9686 : #endif
9687 :
9688 : #if defined(AE_COMPILE_FBLS) || !defined(AE_PARTIAL_BUILD)
9689 :
9690 : #endif
9691 :
9692 : #if defined(AE_COMPILE_BDSVD) || !defined(AE_PARTIAL_BUILD)
9693 : /*************************************************************************
9694 : Singular value decomposition of a bidiagonal matrix (extended algorithm)
9695 :
9696 : COMMERCIAL EDITION OF ALGLIB:
9697 :
9698 : ! Commercial version of ALGLIB includes one important improvement of
9699 : ! this function, which can be used from C++ and C#:
9700 : ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB)
9701 : !
9702 : ! Intel MKL gives approximately constant (with respect to number of
9703 : ! worker threads) acceleration factor which depends on CPU being used,
9704 : ! problem size and "baseline" ALGLIB edition which is used for
9705 : ! comparison.
9706 : !
9707 : ! Generally, commercial ALGLIB is several times faster than open-source
9708 : ! generic C edition, and many times faster than open-source C# edition.
9709 : !
9710 : ! Multithreaded acceleration is NOT supported for this function.
9711 : !
9712 : ! We recommend you to read 'Working with commercial version' section of
9713 : ! ALGLIB Reference Manual in order to find out how to use performance-
9714 : ! related features provided by commercial edition of ALGLIB.
9715 :
9716 : The algorithm performs the singular value decomposition of a bidiagonal
9717 : matrix B (upper or lower) representing it as B = Q*S*P^T, where Q and P -
9718 : orthogonal matrices, S - diagonal matrix with non-negative elements on the
9719 : main diagonal, in descending order.
9720 :
9721 : The algorithm finds singular values. In addition, the algorithm can
9722 : calculate matrices Q and P (more precisely, not the matrices, but their
9723 : product with given matrices U and VT - U*Q and (P^T)*VT)). Of course,
9724 : matrices U and VT can be of any type, including identity. Furthermore, the
9725 : algorithm can calculate Q'*C (this product is calculated more effectively
9726 : than U*Q, because this calculation operates with rows instead of matrix
9727 : columns).
9728 :
9729 : The feature of the algorithm is its ability to find all singular values
9730 : including those which are arbitrarily close to 0 with relative accuracy
9731 : close to machine precision. If the parameter IsFractionalAccuracyRequired
9732 : is set to True, all singular values will have high relative accuracy close
9733 : to machine precision. If the parameter is set to False, only the biggest
9734 : singular value will have relative accuracy close to machine precision.
9735 : The absolute error of other singular values is equal to the absolute error
9736 : of the biggest singular value.
9737 :
9738 : Input parameters:
9739 : D - main diagonal of matrix B.
9740 : Array whose index ranges within [0..N-1].
9741 : E - superdiagonal (or subdiagonal) of matrix B.
9742 : Array whose index ranges within [0..N-2].
9743 : N - size of matrix B.
9744 : IsUpper - True, if the matrix is upper bidiagonal.
9745 : IsFractionalAccuracyRequired -
9746 : THIS PARAMETER IS IGNORED SINCE ALGLIB 3.5.0
9747 : SINGULAR VALUES ARE ALWAYS SEARCHED WITH HIGH ACCURACY.
9748 : U - matrix to be multiplied by Q.
9749 : Array whose indexes range within [0..NRU-1, 0..N-1].
9750 : The matrix can be bigger, in that case only the submatrix
9751 : [0..NRU-1, 0..N-1] will be multiplied by Q.
9752 : NRU - number of rows in matrix U.
9753 : C - matrix to be multiplied by Q'.
9754 : Array whose indexes range within [0..N-1, 0..NCC-1].
9755 : The matrix can be bigger, in that case only the submatrix
9756 : [0..N-1, 0..NCC-1] will be multiplied by Q'.
9757 : NCC - number of columns in matrix C.
9758 : VT - matrix to be multiplied by P^T.
9759 : Array whose indexes range within [0..N-1, 0..NCVT-1].
9760 : The matrix can be bigger, in that case only the submatrix
9761 : [0..N-1, 0..NCVT-1] will be multiplied by P^T.
9762 : NCVT - number of columns in matrix VT.
9763 :
9764 : Output parameters:
9765 : D - singular values of matrix B in descending order.
9766 : U - if NRU>0, contains matrix U*Q.
9767 : VT - if NCVT>0, contains matrix (P^T)*VT.
9768 : C - if NCC>0, contains matrix Q'*C.
9769 :
9770 : Result:
9771 : True, if the algorithm has converged.
9772 : False, if the algorithm hasn't converged (rare case).
9773 :
9774 : NOTE: multiplication U*Q is performed by means of transposition to internal
9775 : buffer, multiplication and backward transposition. It helps to avoid
9776 : costly columnwise operations and speed-up algorithm.
9777 :
9778 : Additional information:
9779 : The type of convergence is controlled by the internal parameter TOL.
9780 : If the parameter is greater than 0, the singular values will have
9781 : relative accuracy TOL. If TOL<0, the singular values will have
9782 : absolute accuracy ABS(TOL)*norm(B).
9783 : By default, |TOL| falls within the range of 10*Epsilon and 100*Epsilon,
9784 : where Epsilon is the machine precision. It is not recommended to use
9785 : TOL less than 10*Epsilon since this will considerably slow down the
9786 : algorithm and may not lead to error decreasing.
9787 :
9788 : History:
9789 : * 31 March, 2007.
9790 : changed MAXITR from 6 to 12.
9791 :
9792 : -- LAPACK routine (version 3.0) --
9793 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
9794 : Courant Institute, Argonne National Lab, and Rice University
9795 : October 31, 1999.
9796 : *************************************************************************/
9797 0 : bool rmatrixbdsvd(real_1d_array &d, const real_1d_array &e, const ae_int_t n, const bool isupper, const bool isfractionalaccuracyrequired, real_2d_array &u, const ae_int_t nru, real_2d_array &c, const ae_int_t ncc, real_2d_array &vt, const ae_int_t ncvt, const xparams _xparams)
9798 : {
9799 : jmp_buf _break_jump;
9800 : alglib_impl::ae_state _alglib_env_state;
9801 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9802 0 : if( setjmp(_break_jump) )
9803 : {
9804 : #if !defined(AE_NO_EXCEPTIONS)
9805 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9806 : #else
9807 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9808 : return 0;
9809 : #endif
9810 : }
9811 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9812 0 : if( _xparams.flags!=0x0 )
9813 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9814 0 : ae_bool result = alglib_impl::rmatrixbdsvd(const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_vector*>(e.c_ptr()), n, isupper, isfractionalaccuracyrequired, const_cast<alglib_impl::ae_matrix*>(u.c_ptr()), nru, const_cast<alglib_impl::ae_matrix*>(c.c_ptr()), ncc, const_cast<alglib_impl::ae_matrix*>(vt.c_ptr()), ncvt, &_alglib_env_state);
9815 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9816 0 : return *(reinterpret_cast<bool*>(&result));
9817 : }
9818 : #endif
9819 :
9820 : #if defined(AE_COMPILE_SVD) || !defined(AE_PARTIAL_BUILD)
9821 : /*************************************************************************
9822 : Singular value decomposition of a rectangular matrix.
9823 :
9824 : ! COMMERCIAL EDITION OF ALGLIB:
9825 : !
9826 : ! Commercial Edition of ALGLIB includes following important improvements
9827 : ! of this function:
9828 : ! * high-performance native backend with same C# interface (C# version)
9829 : ! * hardware vendor (Intel) implementations of linear algebra primitives
9830 : ! (C++ and C# versions, x86/x64 platform)
9831 : !
9832 : ! We recommend you to read 'Working with commercial version' section of
9833 : ! ALGLIB Reference Manual in order to find out how to use performance-
9834 : ! related features provided by commercial edition of ALGLIB.
9835 :
9836 : The algorithm calculates the singular value decomposition of a matrix of
9837 : size MxN: A = U * S * V^T
9838 :
9839 : The algorithm finds the singular values and, optionally, matrices U and V^T.
9840 : The algorithm can find both first min(M,N) columns of matrix U and rows of
9841 : matrix V^T (singular vectors), and matrices U and V^T wholly (of sizes MxM
9842 : and NxN respectively).
9843 :
9844 : Take into account that the subroutine does not return matrix V but V^T.
9845 :
9846 : Input parameters:
9847 : A - matrix to be decomposed.
9848 : Array whose indexes range within [0..M-1, 0..N-1].
9849 : M - number of rows in matrix A.
9850 : N - number of columns in matrix A.
9851 : UNeeded - 0, 1 or 2. See the description of the parameter U.
9852 : VTNeeded - 0, 1 or 2. See the description of the parameter VT.
9853 : AdditionalMemory -
9854 : If the parameter:
9855 : * equals 0, the algorithm doesn't use additional
9856 : memory (lower requirements, lower performance).
9857 : * equals 1, the algorithm uses additional
9858 : memory of size min(M,N)*min(M,N) of real numbers.
9859 : It often speeds up the algorithm.
9860 : * equals 2, the algorithm uses additional
9861 : memory of size M*min(M,N) of real numbers.
9862 : It allows to get a maximum performance.
9863 : The recommended value of the parameter is 2.
9864 :
9865 : Output parameters:
9866 : W - contains singular values in descending order.
9867 : U - if UNeeded=0, U isn't changed, the left singular vectors
9868 : are not calculated.
9869 : if Uneeded=1, U contains left singular vectors (first
9870 : min(M,N) columns of matrix U). Array whose indexes range
9871 : within [0..M-1, 0..Min(M,N)-1].
9872 : if UNeeded=2, U contains matrix U wholly. Array whose
9873 : indexes range within [0..M-1, 0..M-1].
9874 : VT - if VTNeeded=0, VT isn't changed, the right singular vectors
9875 : are not calculated.
9876 : if VTNeeded=1, VT contains right singular vectors (first
9877 : min(M,N) rows of matrix V^T). Array whose indexes range
9878 : within [0..min(M,N)-1, 0..N-1].
9879 : if VTNeeded=2, VT contains matrix V^T wholly. Array whose
9880 : indexes range within [0..N-1, 0..N-1].
9881 :
9882 : -- ALGLIB --
9883 : Copyright 2005 by Bochkanov Sergey
9884 : *************************************************************************/
9885 0 : bool rmatrixsvd(const real_2d_array &a, const ae_int_t m, const ae_int_t n, const ae_int_t uneeded, const ae_int_t vtneeded, const ae_int_t additionalmemory, real_1d_array &w, real_2d_array &u, real_2d_array &vt, const xparams _xparams)
9886 : {
9887 : jmp_buf _break_jump;
9888 : alglib_impl::ae_state _alglib_env_state;
9889 0 : alglib_impl::ae_state_init(&_alglib_env_state);
9890 0 : if( setjmp(_break_jump) )
9891 : {
9892 : #if !defined(AE_NO_EXCEPTIONS)
9893 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
9894 : #else
9895 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
9896 : return 0;
9897 : #endif
9898 : }
9899 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
9900 0 : if( _xparams.flags!=0x0 )
9901 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
9902 0 : ae_bool result = alglib_impl::rmatrixsvd(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), m, n, uneeded, vtneeded, additionalmemory, const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_matrix*>(u.c_ptr()), const_cast<alglib_impl::ae_matrix*>(vt.c_ptr()), &_alglib_env_state);
9903 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
9904 0 : return *(reinterpret_cast<bool*>(&result));
9905 : }
9906 : #endif
9907 :
9908 : #if defined(AE_COMPILE_NORMESTIMATOR) || !defined(AE_PARTIAL_BUILD)
9909 : /*************************************************************************
9910 : This object stores state of the iterative norm estimation algorithm.
9911 :
9912 : You should use ALGLIB functions to work with this object.
9913 : *************************************************************************/
9914 0 : _normestimatorstate_owner::_normestimatorstate_owner()
9915 : {
9916 : jmp_buf _break_jump;
9917 : alglib_impl::ae_state _state;
9918 :
9919 0 : alglib_impl::ae_state_init(&_state);
9920 0 : if( setjmp(_break_jump) )
9921 : {
9922 0 : if( p_struct!=NULL )
9923 : {
9924 0 : alglib_impl::_normestimatorstate_destroy(p_struct);
9925 0 : alglib_impl::ae_free(p_struct);
9926 : }
9927 0 : p_struct = NULL;
9928 : #if !defined(AE_NO_EXCEPTIONS)
9929 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
9930 : #else
9931 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
9932 : return;
9933 : #endif
9934 : }
9935 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
9936 0 : p_struct = NULL;
9937 0 : p_struct = (alglib_impl::normestimatorstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::normestimatorstate), &_state);
9938 0 : memset(p_struct, 0, sizeof(alglib_impl::normestimatorstate));
9939 0 : alglib_impl::_normestimatorstate_init(p_struct, &_state, ae_false);
9940 0 : ae_state_clear(&_state);
9941 0 : }
9942 :
9943 0 : _normestimatorstate_owner::_normestimatorstate_owner(const _normestimatorstate_owner &rhs)
9944 : {
9945 : jmp_buf _break_jump;
9946 : alglib_impl::ae_state _state;
9947 :
9948 0 : alglib_impl::ae_state_init(&_state);
9949 0 : if( setjmp(_break_jump) )
9950 : {
9951 0 : if( p_struct!=NULL )
9952 : {
9953 0 : alglib_impl::_normestimatorstate_destroy(p_struct);
9954 0 : alglib_impl::ae_free(p_struct);
9955 : }
9956 0 : p_struct = NULL;
9957 : #if !defined(AE_NO_EXCEPTIONS)
9958 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
9959 : #else
9960 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
9961 : return;
9962 : #endif
9963 : }
9964 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
9965 0 : p_struct = NULL;
9966 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: normestimatorstate copy constructor failure (source is not initialized)", &_state);
9967 0 : p_struct = (alglib_impl::normestimatorstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::normestimatorstate), &_state);
9968 0 : memset(p_struct, 0, sizeof(alglib_impl::normestimatorstate));
9969 0 : alglib_impl::_normestimatorstate_init_copy(p_struct, const_cast<alglib_impl::normestimatorstate*>(rhs.p_struct), &_state, ae_false);
9970 0 : ae_state_clear(&_state);
9971 0 : }
9972 :
9973 0 : _normestimatorstate_owner& _normestimatorstate_owner::operator=(const _normestimatorstate_owner &rhs)
9974 : {
9975 0 : if( this==&rhs )
9976 0 : return *this;
9977 : jmp_buf _break_jump;
9978 : alglib_impl::ae_state _state;
9979 :
9980 0 : alglib_impl::ae_state_init(&_state);
9981 0 : if( setjmp(_break_jump) )
9982 : {
9983 : #if !defined(AE_NO_EXCEPTIONS)
9984 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
9985 : #else
9986 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
9987 : return *this;
9988 : #endif
9989 : }
9990 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
9991 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: normestimatorstate assignment constructor failure (destination is not initialized)", &_state);
9992 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: normestimatorstate assignment constructor failure (source is not initialized)", &_state);
9993 0 : alglib_impl::_normestimatorstate_destroy(p_struct);
9994 0 : memset(p_struct, 0, sizeof(alglib_impl::normestimatorstate));
9995 0 : alglib_impl::_normestimatorstate_init_copy(p_struct, const_cast<alglib_impl::normestimatorstate*>(rhs.p_struct), &_state, ae_false);
9996 0 : ae_state_clear(&_state);
9997 0 : return *this;
9998 : }
9999 :
10000 0 : _normestimatorstate_owner::~_normestimatorstate_owner()
10001 : {
10002 0 : if( p_struct!=NULL )
10003 : {
10004 0 : alglib_impl::_normestimatorstate_destroy(p_struct);
10005 0 : ae_free(p_struct);
10006 : }
10007 0 : }
10008 :
10009 0 : alglib_impl::normestimatorstate* _normestimatorstate_owner::c_ptr()
10010 : {
10011 0 : return p_struct;
10012 : }
10013 :
10014 0 : alglib_impl::normestimatorstate* _normestimatorstate_owner::c_ptr() const
10015 : {
10016 0 : return const_cast<alglib_impl::normestimatorstate*>(p_struct);
10017 : }
10018 0 : normestimatorstate::normestimatorstate() : _normestimatorstate_owner()
10019 : {
10020 0 : }
10021 :
10022 0 : normestimatorstate::normestimatorstate(const normestimatorstate &rhs):_normestimatorstate_owner(rhs)
10023 : {
10024 0 : }
10025 :
10026 0 : normestimatorstate& normestimatorstate::operator=(const normestimatorstate &rhs)
10027 : {
10028 0 : if( this==&rhs )
10029 0 : return *this;
10030 0 : _normestimatorstate_owner::operator=(rhs);
10031 0 : return *this;
10032 : }
10033 :
10034 0 : normestimatorstate::~normestimatorstate()
10035 : {
10036 0 : }
10037 :
10038 : /*************************************************************************
10039 : This procedure initializes matrix norm estimator.
10040 :
10041 : USAGE:
10042 : 1. User initializes algorithm state with NormEstimatorCreate() call
10043 : 2. User calls NormEstimatorEstimateSparse() (or NormEstimatorIteration())
10044 : 3. User calls NormEstimatorResults() to get solution.
10045 :
10046 : INPUT PARAMETERS:
10047 : M - number of rows in the matrix being estimated, M>0
10048 : N - number of columns in the matrix being estimated, N>0
10049 : NStart - number of random starting vectors
10050 : recommended value - at least 5.
10051 : NIts - number of iterations to do with best starting vector
10052 : recommended value - at least 5.
10053 :
10054 : OUTPUT PARAMETERS:
10055 : State - structure which stores algorithm state
10056 :
10057 :
10058 : NOTE: this algorithm is effectively deterministic, i.e. it always returns
10059 : same result when repeatedly called for the same matrix. In fact, algorithm
10060 : uses randomized starting vectors, but internal random numbers generator
10061 : always generates same sequence of the random values (it is a feature, not
10062 : bug).
10063 :
10064 : Algorithm can be made non-deterministic with NormEstimatorSetSeed(0) call.
10065 :
10066 : -- ALGLIB --
10067 : Copyright 06.12.2011 by Bochkanov Sergey
10068 : *************************************************************************/
10069 0 : void normestimatorcreate(const ae_int_t m, const ae_int_t n, const ae_int_t nstart, const ae_int_t nits, normestimatorstate &state, const xparams _xparams)
10070 : {
10071 : jmp_buf _break_jump;
10072 : alglib_impl::ae_state _alglib_env_state;
10073 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10074 0 : if( setjmp(_break_jump) )
10075 : {
10076 : #if !defined(AE_NO_EXCEPTIONS)
10077 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10078 : #else
10079 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10080 : return;
10081 : #endif
10082 : }
10083 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10084 0 : if( _xparams.flags!=0x0 )
10085 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10086 0 : alglib_impl::normestimatorcreate(m, n, nstart, nits, const_cast<alglib_impl::normestimatorstate*>(state.c_ptr()), &_alglib_env_state);
10087 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10088 0 : return;
10089 : }
10090 :
10091 : /*************************************************************************
10092 : This function changes seed value used by algorithm. In some cases we need
10093 : deterministic processing, i.e. subsequent calls must return equal results,
10094 : in other cases we need non-deterministic algorithm which returns different
10095 : results for the same matrix on every pass.
10096 :
10097 : Setting zero seed will lead to non-deterministic algorithm, while non-zero
10098 : value will make our algorithm deterministic.
10099 :
10100 : INPUT PARAMETERS:
10101 : State - norm estimator state, must be initialized with a call
10102 : to NormEstimatorCreate()
10103 : SeedVal - seed value, >=0. Zero value = non-deterministic algo.
10104 :
10105 : -- ALGLIB --
10106 : Copyright 06.12.2011 by Bochkanov Sergey
10107 : *************************************************************************/
10108 0 : void normestimatorsetseed(const normestimatorstate &state, const ae_int_t seedval, const xparams _xparams)
10109 : {
10110 : jmp_buf _break_jump;
10111 : alglib_impl::ae_state _alglib_env_state;
10112 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10113 0 : if( setjmp(_break_jump) )
10114 : {
10115 : #if !defined(AE_NO_EXCEPTIONS)
10116 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10117 : #else
10118 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10119 : return;
10120 : #endif
10121 : }
10122 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10123 0 : if( _xparams.flags!=0x0 )
10124 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10125 0 : alglib_impl::normestimatorsetseed(const_cast<alglib_impl::normestimatorstate*>(state.c_ptr()), seedval, &_alglib_env_state);
10126 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10127 0 : return;
10128 : }
10129 :
10130 : /*************************************************************************
10131 : This function estimates norm of the sparse M*N matrix A.
10132 :
10133 : INPUT PARAMETERS:
10134 : State - norm estimator state, must be initialized with a call
10135 : to NormEstimatorCreate()
10136 : A - sparse M*N matrix, must be converted to CRS format
10137 : prior to calling this function.
10138 :
10139 : After this function is over you can call NormEstimatorResults() to get
10140 : estimate of the norm(A).
10141 :
10142 : -- ALGLIB --
10143 : Copyright 06.12.2011 by Bochkanov Sergey
10144 : *************************************************************************/
10145 0 : void normestimatorestimatesparse(const normestimatorstate &state, const sparsematrix &a, const xparams _xparams)
10146 : {
10147 : jmp_buf _break_jump;
10148 : alglib_impl::ae_state _alglib_env_state;
10149 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10150 0 : if( setjmp(_break_jump) )
10151 : {
10152 : #if !defined(AE_NO_EXCEPTIONS)
10153 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10154 : #else
10155 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10156 : return;
10157 : #endif
10158 : }
10159 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10160 0 : if( _xparams.flags!=0x0 )
10161 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10162 0 : alglib_impl::normestimatorestimatesparse(const_cast<alglib_impl::normestimatorstate*>(state.c_ptr()), const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), &_alglib_env_state);
10163 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10164 0 : return;
10165 : }
10166 :
10167 : /*************************************************************************
10168 : Matrix norm estimation results
10169 :
10170 : INPUT PARAMETERS:
10171 : State - algorithm state
10172 :
10173 : OUTPUT PARAMETERS:
10174 : Nrm - estimate of the matrix norm, Nrm>=0
10175 :
10176 : -- ALGLIB --
10177 : Copyright 06.12.2011 by Bochkanov Sergey
10178 : *************************************************************************/
10179 0 : void normestimatorresults(const normestimatorstate &state, double &nrm, const xparams _xparams)
10180 : {
10181 : jmp_buf _break_jump;
10182 : alglib_impl::ae_state _alglib_env_state;
10183 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10184 0 : if( setjmp(_break_jump) )
10185 : {
10186 : #if !defined(AE_NO_EXCEPTIONS)
10187 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10188 : #else
10189 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10190 : return;
10191 : #endif
10192 : }
10193 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10194 0 : if( _xparams.flags!=0x0 )
10195 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10196 0 : alglib_impl::normestimatorresults(const_cast<alglib_impl::normestimatorstate*>(state.c_ptr()), &nrm, &_alglib_env_state);
10197 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10198 0 : return;
10199 : }
10200 : #endif
10201 :
10202 : #if defined(AE_COMPILE_HSSCHUR) || !defined(AE_PARTIAL_BUILD)
10203 :
10204 : #endif
10205 :
10206 : #if defined(AE_COMPILE_EVD) || !defined(AE_PARTIAL_BUILD)
10207 : /*************************************************************************
10208 : This object stores state of the subspace iteration algorithm.
10209 :
10210 : You should use ALGLIB functions to work with this object.
10211 : *************************************************************************/
10212 0 : _eigsubspacestate_owner::_eigsubspacestate_owner()
10213 : {
10214 : jmp_buf _break_jump;
10215 : alglib_impl::ae_state _state;
10216 :
10217 0 : alglib_impl::ae_state_init(&_state);
10218 0 : if( setjmp(_break_jump) )
10219 : {
10220 0 : if( p_struct!=NULL )
10221 : {
10222 0 : alglib_impl::_eigsubspacestate_destroy(p_struct);
10223 0 : alglib_impl::ae_free(p_struct);
10224 : }
10225 0 : p_struct = NULL;
10226 : #if !defined(AE_NO_EXCEPTIONS)
10227 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
10228 : #else
10229 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
10230 : return;
10231 : #endif
10232 : }
10233 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
10234 0 : p_struct = NULL;
10235 0 : p_struct = (alglib_impl::eigsubspacestate*)alglib_impl::ae_malloc(sizeof(alglib_impl::eigsubspacestate), &_state);
10236 0 : memset(p_struct, 0, sizeof(alglib_impl::eigsubspacestate));
10237 0 : alglib_impl::_eigsubspacestate_init(p_struct, &_state, ae_false);
10238 0 : ae_state_clear(&_state);
10239 0 : }
10240 :
10241 0 : _eigsubspacestate_owner::_eigsubspacestate_owner(const _eigsubspacestate_owner &rhs)
10242 : {
10243 : jmp_buf _break_jump;
10244 : alglib_impl::ae_state _state;
10245 :
10246 0 : alglib_impl::ae_state_init(&_state);
10247 0 : if( setjmp(_break_jump) )
10248 : {
10249 0 : if( p_struct!=NULL )
10250 : {
10251 0 : alglib_impl::_eigsubspacestate_destroy(p_struct);
10252 0 : alglib_impl::ae_free(p_struct);
10253 : }
10254 0 : p_struct = NULL;
10255 : #if !defined(AE_NO_EXCEPTIONS)
10256 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
10257 : #else
10258 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
10259 : return;
10260 : #endif
10261 : }
10262 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
10263 0 : p_struct = NULL;
10264 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: eigsubspacestate copy constructor failure (source is not initialized)", &_state);
10265 0 : p_struct = (alglib_impl::eigsubspacestate*)alglib_impl::ae_malloc(sizeof(alglib_impl::eigsubspacestate), &_state);
10266 0 : memset(p_struct, 0, sizeof(alglib_impl::eigsubspacestate));
10267 0 : alglib_impl::_eigsubspacestate_init_copy(p_struct, const_cast<alglib_impl::eigsubspacestate*>(rhs.p_struct), &_state, ae_false);
10268 0 : ae_state_clear(&_state);
10269 0 : }
10270 :
10271 0 : _eigsubspacestate_owner& _eigsubspacestate_owner::operator=(const _eigsubspacestate_owner &rhs)
10272 : {
10273 0 : if( this==&rhs )
10274 0 : return *this;
10275 : jmp_buf _break_jump;
10276 : alglib_impl::ae_state _state;
10277 :
10278 0 : alglib_impl::ae_state_init(&_state);
10279 0 : if( setjmp(_break_jump) )
10280 : {
10281 : #if !defined(AE_NO_EXCEPTIONS)
10282 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
10283 : #else
10284 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
10285 : return *this;
10286 : #endif
10287 : }
10288 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
10289 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: eigsubspacestate assignment constructor failure (destination is not initialized)", &_state);
10290 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: eigsubspacestate assignment constructor failure (source is not initialized)", &_state);
10291 0 : alglib_impl::_eigsubspacestate_destroy(p_struct);
10292 0 : memset(p_struct, 0, sizeof(alglib_impl::eigsubspacestate));
10293 0 : alglib_impl::_eigsubspacestate_init_copy(p_struct, const_cast<alglib_impl::eigsubspacestate*>(rhs.p_struct), &_state, ae_false);
10294 0 : ae_state_clear(&_state);
10295 0 : return *this;
10296 : }
10297 :
10298 0 : _eigsubspacestate_owner::~_eigsubspacestate_owner()
10299 : {
10300 0 : if( p_struct!=NULL )
10301 : {
10302 0 : alglib_impl::_eigsubspacestate_destroy(p_struct);
10303 0 : ae_free(p_struct);
10304 : }
10305 0 : }
10306 :
10307 0 : alglib_impl::eigsubspacestate* _eigsubspacestate_owner::c_ptr()
10308 : {
10309 0 : return p_struct;
10310 : }
10311 :
10312 0 : alglib_impl::eigsubspacestate* _eigsubspacestate_owner::c_ptr() const
10313 : {
10314 0 : return const_cast<alglib_impl::eigsubspacestate*>(p_struct);
10315 : }
10316 0 : eigsubspacestate::eigsubspacestate() : _eigsubspacestate_owner()
10317 : {
10318 0 : }
10319 :
10320 0 : eigsubspacestate::eigsubspacestate(const eigsubspacestate &rhs):_eigsubspacestate_owner(rhs)
10321 : {
10322 0 : }
10323 :
10324 0 : eigsubspacestate& eigsubspacestate::operator=(const eigsubspacestate &rhs)
10325 : {
10326 0 : if( this==&rhs )
10327 0 : return *this;
10328 0 : _eigsubspacestate_owner::operator=(rhs);
10329 0 : return *this;
10330 : }
10331 :
10332 0 : eigsubspacestate::~eigsubspacestate()
10333 : {
10334 0 : }
10335 :
10336 :
10337 : /*************************************************************************
10338 : This object stores state of the subspace iteration algorithm.
10339 :
10340 : You should use ALGLIB functions to work with this object.
10341 : *************************************************************************/
10342 0 : _eigsubspacereport_owner::_eigsubspacereport_owner()
10343 : {
10344 : jmp_buf _break_jump;
10345 : alglib_impl::ae_state _state;
10346 :
10347 0 : alglib_impl::ae_state_init(&_state);
10348 0 : if( setjmp(_break_jump) )
10349 : {
10350 0 : if( p_struct!=NULL )
10351 : {
10352 0 : alglib_impl::_eigsubspacereport_destroy(p_struct);
10353 0 : alglib_impl::ae_free(p_struct);
10354 : }
10355 0 : p_struct = NULL;
10356 : #if !defined(AE_NO_EXCEPTIONS)
10357 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
10358 : #else
10359 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
10360 : return;
10361 : #endif
10362 : }
10363 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
10364 0 : p_struct = NULL;
10365 0 : p_struct = (alglib_impl::eigsubspacereport*)alglib_impl::ae_malloc(sizeof(alglib_impl::eigsubspacereport), &_state);
10366 0 : memset(p_struct, 0, sizeof(alglib_impl::eigsubspacereport));
10367 0 : alglib_impl::_eigsubspacereport_init(p_struct, &_state, ae_false);
10368 0 : ae_state_clear(&_state);
10369 0 : }
10370 :
10371 0 : _eigsubspacereport_owner::_eigsubspacereport_owner(const _eigsubspacereport_owner &rhs)
10372 : {
10373 : jmp_buf _break_jump;
10374 : alglib_impl::ae_state _state;
10375 :
10376 0 : alglib_impl::ae_state_init(&_state);
10377 0 : if( setjmp(_break_jump) )
10378 : {
10379 0 : if( p_struct!=NULL )
10380 : {
10381 0 : alglib_impl::_eigsubspacereport_destroy(p_struct);
10382 0 : alglib_impl::ae_free(p_struct);
10383 : }
10384 0 : p_struct = NULL;
10385 : #if !defined(AE_NO_EXCEPTIONS)
10386 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
10387 : #else
10388 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
10389 : return;
10390 : #endif
10391 : }
10392 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
10393 0 : p_struct = NULL;
10394 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: eigsubspacereport copy constructor failure (source is not initialized)", &_state);
10395 0 : p_struct = (alglib_impl::eigsubspacereport*)alglib_impl::ae_malloc(sizeof(alglib_impl::eigsubspacereport), &_state);
10396 0 : memset(p_struct, 0, sizeof(alglib_impl::eigsubspacereport));
10397 0 : alglib_impl::_eigsubspacereport_init_copy(p_struct, const_cast<alglib_impl::eigsubspacereport*>(rhs.p_struct), &_state, ae_false);
10398 0 : ae_state_clear(&_state);
10399 0 : }
10400 :
10401 0 : _eigsubspacereport_owner& _eigsubspacereport_owner::operator=(const _eigsubspacereport_owner &rhs)
10402 : {
10403 0 : if( this==&rhs )
10404 0 : return *this;
10405 : jmp_buf _break_jump;
10406 : alglib_impl::ae_state _state;
10407 :
10408 0 : alglib_impl::ae_state_init(&_state);
10409 0 : if( setjmp(_break_jump) )
10410 : {
10411 : #if !defined(AE_NO_EXCEPTIONS)
10412 0 : _ALGLIB_CPP_EXCEPTION(_state.error_msg);
10413 : #else
10414 : _ALGLIB_SET_ERROR_FLAG(_state.error_msg);
10415 : return *this;
10416 : #endif
10417 : }
10418 0 : alglib_impl::ae_state_set_break_jump(&_state, &_break_jump);
10419 0 : alglib_impl::ae_assert(p_struct!=NULL, "ALGLIB: eigsubspacereport assignment constructor failure (destination is not initialized)", &_state);
10420 0 : alglib_impl::ae_assert(rhs.p_struct!=NULL, "ALGLIB: eigsubspacereport assignment constructor failure (source is not initialized)", &_state);
10421 0 : alglib_impl::_eigsubspacereport_destroy(p_struct);
10422 0 : memset(p_struct, 0, sizeof(alglib_impl::eigsubspacereport));
10423 0 : alglib_impl::_eigsubspacereport_init_copy(p_struct, const_cast<alglib_impl::eigsubspacereport*>(rhs.p_struct), &_state, ae_false);
10424 0 : ae_state_clear(&_state);
10425 0 : return *this;
10426 : }
10427 :
10428 0 : _eigsubspacereport_owner::~_eigsubspacereport_owner()
10429 : {
10430 0 : if( p_struct!=NULL )
10431 : {
10432 0 : alglib_impl::_eigsubspacereport_destroy(p_struct);
10433 0 : ae_free(p_struct);
10434 : }
10435 0 : }
10436 :
10437 0 : alglib_impl::eigsubspacereport* _eigsubspacereport_owner::c_ptr()
10438 : {
10439 0 : return p_struct;
10440 : }
10441 :
10442 0 : alglib_impl::eigsubspacereport* _eigsubspacereport_owner::c_ptr() const
10443 : {
10444 0 : return const_cast<alglib_impl::eigsubspacereport*>(p_struct);
10445 : }
10446 0 : eigsubspacereport::eigsubspacereport() : _eigsubspacereport_owner() ,iterationscount(p_struct->iterationscount)
10447 : {
10448 0 : }
10449 :
10450 0 : eigsubspacereport::eigsubspacereport(const eigsubspacereport &rhs):_eigsubspacereport_owner(rhs) ,iterationscount(p_struct->iterationscount)
10451 : {
10452 0 : }
10453 :
10454 0 : eigsubspacereport& eigsubspacereport::operator=(const eigsubspacereport &rhs)
10455 : {
10456 0 : if( this==&rhs )
10457 0 : return *this;
10458 0 : _eigsubspacereport_owner::operator=(rhs);
10459 0 : return *this;
10460 : }
10461 :
10462 0 : eigsubspacereport::~eigsubspacereport()
10463 : {
10464 0 : }
10465 :
10466 : /*************************************************************************
10467 : This function initializes subspace iteration solver. This solver is used
10468 : to solve symmetric real eigenproblems where just a few (top K) eigenvalues
10469 : and corresponding eigenvectors is required.
10470 :
10471 : This solver can be significantly faster than complete EVD decomposition
10472 : in the following case:
10473 : * when only just a small fraction of top eigenpairs of dense matrix is
10474 : required. When K approaches N, this solver is slower than complete dense
10475 : EVD
10476 : * when problem matrix is sparse (and/or is not known explicitly, i.e. only
10477 : matrix-matrix product can be performed)
10478 :
10479 : USAGE (explicit dense/sparse matrix):
10480 : 1. User initializes algorithm state with eigsubspacecreate() call
10481 : 2. [optional] User tunes solver parameters by calling eigsubspacesetcond()
10482 : or other functions
10483 : 3. User calls eigsubspacesolvedense() or eigsubspacesolvesparse() methods,
10484 : which take algorithm state and 2D array or alglib.sparsematrix object.
10485 :
10486 : USAGE (out-of-core mode):
10487 : 1. User initializes algorithm state with eigsubspacecreate() call
10488 : 2. [optional] User tunes solver parameters by calling eigsubspacesetcond()
10489 : or other functions
10490 : 3. User activates out-of-core mode of the solver and repeatedly calls
10491 : communication functions in a loop like below:
10492 : > alglib.eigsubspaceoocstart(state)
10493 : > while alglib.eigsubspaceooccontinue(state) do
10494 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
10495 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
10496 : > [calculate Y=A*X, with X=R^NxM]
10497 : > alglib.eigsubspaceoocsendresult(state, in Y)
10498 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
10499 :
10500 : INPUT PARAMETERS:
10501 : N - problem dimensionality, N>0
10502 : K - number of top eigenvector to calculate, 0<K<=N.
10503 :
10504 : OUTPUT PARAMETERS:
10505 : State - structure which stores algorithm state
10506 :
10507 : NOTE: if you solve many similar EVD problems you may find it useful to
10508 : reuse previous subspace as warm-start point for new EVD problem. It
10509 : can be done with eigsubspacesetwarmstart() function.
10510 :
10511 : -- ALGLIB --
10512 : Copyright 16.01.2017 by Bochkanov Sergey
10513 : *************************************************************************/
10514 0 : void eigsubspacecreate(const ae_int_t n, const ae_int_t k, eigsubspacestate &state, const xparams _xparams)
10515 : {
10516 : jmp_buf _break_jump;
10517 : alglib_impl::ae_state _alglib_env_state;
10518 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10519 0 : if( setjmp(_break_jump) )
10520 : {
10521 : #if !defined(AE_NO_EXCEPTIONS)
10522 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10523 : #else
10524 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10525 : return;
10526 : #endif
10527 : }
10528 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10529 0 : if( _xparams.flags!=0x0 )
10530 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10531 0 : alglib_impl::eigsubspacecreate(n, k, const_cast<alglib_impl::eigsubspacestate*>(state.c_ptr()), &_alglib_env_state);
10532 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10533 0 : return;
10534 : }
10535 :
10536 : /*************************************************************************
10537 : Buffered version of constructor which aims to reuse previously allocated
10538 : memory as much as possible.
10539 :
10540 : -- ALGLIB --
10541 : Copyright 16.01.2017 by Bochkanov Sergey
10542 : *************************************************************************/
10543 0 : void eigsubspacecreatebuf(const ae_int_t n, const ae_int_t k, const eigsubspacestate &state, const xparams _xparams)
10544 : {
10545 : jmp_buf _break_jump;
10546 : alglib_impl::ae_state _alglib_env_state;
10547 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10548 0 : if( setjmp(_break_jump) )
10549 : {
10550 : #if !defined(AE_NO_EXCEPTIONS)
10551 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10552 : #else
10553 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10554 : return;
10555 : #endif
10556 : }
10557 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10558 0 : if( _xparams.flags!=0x0 )
10559 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10560 0 : alglib_impl::eigsubspacecreatebuf(n, k, const_cast<alglib_impl::eigsubspacestate*>(state.c_ptr()), &_alglib_env_state);
10561 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10562 0 : return;
10563 : }
10564 :
10565 : /*************************************************************************
10566 : This function sets stopping critera for the solver:
10567 : * error in eigenvector/value allowed by solver
10568 : * maximum number of iterations to perform
10569 :
10570 : INPUT PARAMETERS:
10571 : State - solver structure
10572 : Eps - eps>=0, with non-zero value used to tell solver that
10573 : it can stop after all eigenvalues converged with
10574 : error roughly proportional to eps*MAX(LAMBDA_MAX),
10575 : where LAMBDA_MAX is a maximum eigenvalue.
10576 : Zero value means that no check for precision is
10577 : performed.
10578 : MaxIts - maxits>=0, with non-zero value used to tell solver
10579 : that it can stop after maxits steps (no matter how
10580 : precise current estimate is)
10581 :
10582 : NOTE: passing eps=0 and maxits=0 results in automatic selection of
10583 : moderate eps as stopping criteria (1.0E-6 in current implementation,
10584 : but it may change without notice).
10585 :
10586 : NOTE: very small values of eps are possible (say, 1.0E-12), although the
10587 : larger problem you solve (N and/or K), the harder it is to find
10588 : precise eigenvectors because rounding errors tend to accumulate.
10589 :
10590 : NOTE: passing non-zero eps results in some performance penalty, roughly
10591 : equal to 2N*(2K)^2 FLOPs per iteration. These additional computations
10592 : are required in order to estimate current error in eigenvalues via
10593 : Rayleigh-Ritz process.
10594 : Most of this additional time is spent in construction of ~2Kx2K
10595 : symmetric subproblem whose eigenvalues are checked with exact
10596 : eigensolver.
10597 : This additional time is negligible if you search for eigenvalues of
10598 : the large dense matrix, but may become noticeable on highly sparse
10599 : EVD problems, where cost of matrix-matrix product is low.
10600 : If you set eps to exactly zero, Rayleigh-Ritz phase is completely
10601 : turned off.
10602 :
10603 : -- ALGLIB --
10604 : Copyright 16.01.2017 by Bochkanov Sergey
10605 : *************************************************************************/
10606 0 : void eigsubspacesetcond(const eigsubspacestate &state, const double eps, const ae_int_t maxits, const xparams _xparams)
10607 : {
10608 : jmp_buf _break_jump;
10609 : alglib_impl::ae_state _alglib_env_state;
10610 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10611 0 : if( setjmp(_break_jump) )
10612 : {
10613 : #if !defined(AE_NO_EXCEPTIONS)
10614 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10615 : #else
10616 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10617 : return;
10618 : #endif
10619 : }
10620 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10621 0 : if( _xparams.flags!=0x0 )
10622 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10623 0 : alglib_impl::eigsubspacesetcond(const_cast<alglib_impl::eigsubspacestate*>(state.c_ptr()), eps, maxits, &_alglib_env_state);
10624 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10625 0 : return;
10626 : }
10627 :
10628 : /*************************************************************************
10629 : This function sets warm-start mode of the solver: next call to the solver
10630 : will reuse previous subspace as warm-start point. It can significantly
10631 : speed-up convergence when you solve many similar eigenproblems.
10632 :
10633 : INPUT PARAMETERS:
10634 : State - solver structure
10635 : UseWarmStart- either True or False
10636 :
10637 : -- ALGLIB --
10638 : Copyright 12.11.2017 by Bochkanov Sergey
10639 : *************************************************************************/
10640 0 : void eigsubspacesetwarmstart(const eigsubspacestate &state, const bool usewarmstart, const xparams _xparams)
10641 : {
10642 : jmp_buf _break_jump;
10643 : alglib_impl::ae_state _alglib_env_state;
10644 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10645 0 : if( setjmp(_break_jump) )
10646 : {
10647 : #if !defined(AE_NO_EXCEPTIONS)
10648 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10649 : #else
10650 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10651 : return;
10652 : #endif
10653 : }
10654 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10655 0 : if( _xparams.flags!=0x0 )
10656 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10657 0 : alglib_impl::eigsubspacesetwarmstart(const_cast<alglib_impl::eigsubspacestate*>(state.c_ptr()), usewarmstart, &_alglib_env_state);
10658 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10659 0 : return;
10660 : }
10661 :
10662 : /*************************************************************************
10663 : This function initiates out-of-core mode of subspace eigensolver. It
10664 : should be used in conjunction with other out-of-core-related functions of
10665 : this subspackage in a loop like below:
10666 :
10667 : > alglib.eigsubspaceoocstart(state)
10668 : > while alglib.eigsubspaceooccontinue(state) do
10669 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
10670 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
10671 : > [calculate Y=A*X, with X=R^NxM]
10672 : > alglib.eigsubspaceoocsendresult(state, in Y)
10673 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
10674 :
10675 : INPUT PARAMETERS:
10676 : State - solver object
10677 : MType - matrix type:
10678 : * 0 for real symmetric matrix (solver assumes that
10679 : matrix being processed is symmetric; symmetric
10680 : direct eigensolver is used for smaller subproblems
10681 : arising during solution of larger "full" task)
10682 : Future versions of ALGLIB may introduce support for
10683 : other matrix types; for now, only symmetric
10684 : eigenproblems are supported.
10685 :
10686 :
10687 : -- ALGLIB --
10688 : Copyright 16.01.2017 by Bochkanov Sergey
10689 : *************************************************************************/
10690 0 : void eigsubspaceoocstart(const eigsubspacestate &state, const ae_int_t mtype, const xparams _xparams)
10691 : {
10692 : jmp_buf _break_jump;
10693 : alglib_impl::ae_state _alglib_env_state;
10694 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10695 0 : if( setjmp(_break_jump) )
10696 : {
10697 : #if !defined(AE_NO_EXCEPTIONS)
10698 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10699 : #else
10700 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10701 : return;
10702 : #endif
10703 : }
10704 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10705 0 : if( _xparams.flags!=0x0 )
10706 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10707 0 : alglib_impl::eigsubspaceoocstart(const_cast<alglib_impl::eigsubspacestate*>(state.c_ptr()), mtype, &_alglib_env_state);
10708 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10709 0 : return;
10710 : }
10711 :
10712 : /*************************************************************************
10713 : This function performs subspace iteration in the out-of-core mode. It
10714 : should be used in conjunction with other out-of-core-related functions of
10715 : this subspackage in a loop like below:
10716 :
10717 : > alglib.eigsubspaceoocstart(state)
10718 : > while alglib.eigsubspaceooccontinue(state) do
10719 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
10720 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
10721 : > [calculate Y=A*X, with X=R^NxM]
10722 : > alglib.eigsubspaceoocsendresult(state, in Y)
10723 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
10724 :
10725 :
10726 : -- ALGLIB --
10727 : Copyright 16.01.2017 by Bochkanov Sergey
10728 : *************************************************************************/
10729 0 : bool eigsubspaceooccontinue(const eigsubspacestate &state, const xparams _xparams)
10730 : {
10731 : jmp_buf _break_jump;
10732 : alglib_impl::ae_state _alglib_env_state;
10733 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10734 0 : if( setjmp(_break_jump) )
10735 : {
10736 : #if !defined(AE_NO_EXCEPTIONS)
10737 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10738 : #else
10739 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10740 : return 0;
10741 : #endif
10742 : }
10743 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10744 0 : if( _xparams.flags!=0x0 )
10745 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10746 0 : ae_bool result = alglib_impl::eigsubspaceooccontinue(const_cast<alglib_impl::eigsubspacestate*>(state.c_ptr()), &_alglib_env_state);
10747 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10748 0 : return *(reinterpret_cast<bool*>(&result));
10749 : }
10750 :
10751 : /*************************************************************************
10752 : This function is used to retrieve information about out-of-core request
10753 : sent by solver to user code: request type (current version of the solver
10754 : sends only requests for matrix-matrix products) and request size (size of
10755 : the matrices being multiplied).
10756 :
10757 : This function returns just request metrics; in order to get contents of
10758 : the matrices being multiplied, use eigsubspaceoocgetrequestdata().
10759 :
10760 : It should be used in conjunction with other out-of-core-related functions
10761 : of this subspackage in a loop like below:
10762 :
10763 : > alglib.eigsubspaceoocstart(state)
10764 : > while alglib.eigsubspaceooccontinue(state) do
10765 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
10766 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
10767 : > [calculate Y=A*X, with X=R^NxM]
10768 : > alglib.eigsubspaceoocsendresult(state, in Y)
10769 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
10770 :
10771 : INPUT PARAMETERS:
10772 : State - solver running in out-of-core mode
10773 :
10774 : OUTPUT PARAMETERS:
10775 : RequestType - type of the request to process:
10776 : * 0 - for matrix-matrix product A*X, with A being
10777 : NxN matrix whose eigenvalues/vectors are needed,
10778 : and X being NxREQUESTSIZE one which is returned
10779 : by the eigsubspaceoocgetrequestdata().
10780 : RequestSize - size of the X matrix (number of columns), usually
10781 : it is several times larger than number of vectors
10782 : K requested by user.
10783 :
10784 :
10785 : -- ALGLIB --
10786 : Copyright 16.01.2017 by Bochkanov Sergey
10787 : *************************************************************************/
10788 0 : void eigsubspaceoocgetrequestinfo(const eigsubspacestate &state, ae_int_t &requesttype, ae_int_t &requestsize, const xparams _xparams)
10789 : {
10790 : jmp_buf _break_jump;
10791 : alglib_impl::ae_state _alglib_env_state;
10792 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10793 0 : if( setjmp(_break_jump) )
10794 : {
10795 : #if !defined(AE_NO_EXCEPTIONS)
10796 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10797 : #else
10798 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10799 : return;
10800 : #endif
10801 : }
10802 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10803 0 : if( _xparams.flags!=0x0 )
10804 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10805 0 : alglib_impl::eigsubspaceoocgetrequestinfo(const_cast<alglib_impl::eigsubspacestate*>(state.c_ptr()), &requesttype, &requestsize, &_alglib_env_state);
10806 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10807 0 : return;
10808 : }
10809 :
10810 : /*************************************************************************
10811 : This function is used to retrieve information about out-of-core request
10812 : sent by solver to user code: matrix X (array[N,RequestSize) which have to
10813 : be multiplied by out-of-core matrix A in a product A*X.
10814 :
10815 : This function returns just request data; in order to get size of the data
10816 : prior to processing requestm, use eigsubspaceoocgetrequestinfo().
10817 :
10818 : It should be used in conjunction with other out-of-core-related functions
10819 : of this subspackage in a loop like below:
10820 :
10821 : > alglib.eigsubspaceoocstart(state)
10822 : > while alglib.eigsubspaceooccontinue(state) do
10823 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
10824 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
10825 : > [calculate Y=A*X, with X=R^NxM]
10826 : > alglib.eigsubspaceoocsendresult(state, in Y)
10827 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
10828 :
10829 : INPUT PARAMETERS:
10830 : State - solver running in out-of-core mode
10831 : X - possibly preallocated storage; reallocated if
10832 : needed, left unchanged, if large enough to store
10833 : request data.
10834 :
10835 : OUTPUT PARAMETERS:
10836 : X - array[N,RequestSize] or larger, leading rectangle
10837 : is filled with dense matrix X.
10838 :
10839 :
10840 : -- ALGLIB --
10841 : Copyright 16.01.2017 by Bochkanov Sergey
10842 : *************************************************************************/
10843 0 : void eigsubspaceoocgetrequestdata(const eigsubspacestate &state, real_2d_array &x, const xparams _xparams)
10844 : {
10845 : jmp_buf _break_jump;
10846 : alglib_impl::ae_state _alglib_env_state;
10847 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10848 0 : if( setjmp(_break_jump) )
10849 : {
10850 : #if !defined(AE_NO_EXCEPTIONS)
10851 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10852 : #else
10853 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10854 : return;
10855 : #endif
10856 : }
10857 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10858 0 : if( _xparams.flags!=0x0 )
10859 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10860 0 : alglib_impl::eigsubspaceoocgetrequestdata(const_cast<alglib_impl::eigsubspacestate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), &_alglib_env_state);
10861 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10862 0 : return;
10863 : }
10864 :
10865 : /*************************************************************************
10866 : This function is used to send user reply to out-of-core request sent by
10867 : solver. Usually it is product A*X for returned by solver matrix X.
10868 :
10869 : It should be used in conjunction with other out-of-core-related functions
10870 : of this subspackage in a loop like below:
10871 :
10872 : > alglib.eigsubspaceoocstart(state)
10873 : > while alglib.eigsubspaceooccontinue(state) do
10874 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
10875 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
10876 : > [calculate Y=A*X, with X=R^NxM]
10877 : > alglib.eigsubspaceoocsendresult(state, in Y)
10878 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
10879 :
10880 : INPUT PARAMETERS:
10881 : State - solver running in out-of-core mode
10882 : AX - array[N,RequestSize] or larger, leading rectangle
10883 : is filled with product A*X.
10884 :
10885 :
10886 : -- ALGLIB --
10887 : Copyright 16.01.2017 by Bochkanov Sergey
10888 : *************************************************************************/
10889 0 : void eigsubspaceoocsendresult(const eigsubspacestate &state, const real_2d_array &ax, const xparams _xparams)
10890 : {
10891 : jmp_buf _break_jump;
10892 : alglib_impl::ae_state _alglib_env_state;
10893 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10894 0 : if( setjmp(_break_jump) )
10895 : {
10896 : #if !defined(AE_NO_EXCEPTIONS)
10897 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10898 : #else
10899 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10900 : return;
10901 : #endif
10902 : }
10903 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10904 0 : if( _xparams.flags!=0x0 )
10905 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10906 0 : alglib_impl::eigsubspaceoocsendresult(const_cast<alglib_impl::eigsubspacestate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(ax.c_ptr()), &_alglib_env_state);
10907 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10908 0 : return;
10909 : }
10910 :
10911 : /*************************************************************************
10912 : This function finalizes out-of-core mode of subspace eigensolver. It
10913 : should be used in conjunction with other out-of-core-related functions of
10914 : this subspackage in a loop like below:
10915 :
10916 : > alglib.eigsubspaceoocstart(state)
10917 : > while alglib.eigsubspaceooccontinue(state) do
10918 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
10919 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
10920 : > [calculate Y=A*X, with X=R^NxM]
10921 : > alglib.eigsubspaceoocsendresult(state, in Y)
10922 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
10923 :
10924 : INPUT PARAMETERS:
10925 : State - solver state
10926 :
10927 : OUTPUT PARAMETERS:
10928 : W - array[K], depending on solver settings:
10929 : * top K eigenvalues ordered by descending - if
10930 : eigenvectors are returned in Z
10931 : * zeros - if invariant subspace is returned in Z
10932 : Z - array[N,K], depending on solver settings either:
10933 : * matrix of eigenvectors found
10934 : * orthogonal basis of K-dimensional invariant subspace
10935 : Rep - report with additional parameters
10936 :
10937 : -- ALGLIB --
10938 : Copyright 16.01.2017 by Bochkanov Sergey
10939 : *************************************************************************/
10940 0 : void eigsubspaceoocstop(const eigsubspacestate &state, real_1d_array &w, real_2d_array &z, eigsubspacereport &rep, const xparams _xparams)
10941 : {
10942 : jmp_buf _break_jump;
10943 : alglib_impl::ae_state _alglib_env_state;
10944 0 : alglib_impl::ae_state_init(&_alglib_env_state);
10945 0 : if( setjmp(_break_jump) )
10946 : {
10947 : #if !defined(AE_NO_EXCEPTIONS)
10948 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
10949 : #else
10950 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
10951 : return;
10952 : #endif
10953 : }
10954 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
10955 0 : if( _xparams.flags!=0x0 )
10956 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
10957 0 : alglib_impl::eigsubspaceoocstop(const_cast<alglib_impl::eigsubspacestate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), const_cast<alglib_impl::eigsubspacereport*>(rep.c_ptr()), &_alglib_env_state);
10958 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
10959 0 : return;
10960 : }
10961 :
10962 : /*************************************************************************
10963 : This function runs eigensolver for dense NxN symmetric matrix A, given by
10964 : upper or lower triangle.
10965 :
10966 : This function can not process nonsymmetric matrices.
10967 :
10968 : ! COMMERCIAL EDITION OF ALGLIB:
10969 : !
10970 : ! Commercial Edition of ALGLIB includes following important improvements
10971 : ! of this function:
10972 : ! * high-performance native backend with same C# interface (C# version)
10973 : ! * multithreading support (C++ and C# versions)
10974 : ! * hardware vendor (Intel) implementations of linear algebra primitives
10975 : ! (C++ and C# versions, x86/x64 platform)
10976 : !
10977 : ! We recommend you to read 'Working with commercial version' section of
10978 : ! ALGLIB Reference Manual in order to find out how to use performance-
10979 : ! related features provided by commercial edition of ALGLIB.
10980 :
10981 : INPUT PARAMETERS:
10982 : State - solver state
10983 : A - array[N,N], symmetric NxN matrix given by one of its
10984 : triangles
10985 : IsUpper - whether upper or lower triangle of A is given (the
10986 : other one is not referenced at all).
10987 :
10988 : OUTPUT PARAMETERS:
10989 : W - array[K], top K eigenvalues ordered by descending
10990 : of their absolute values
10991 : Z - array[N,K], matrix of eigenvectors found
10992 : Rep - report with additional parameters
10993 :
10994 : NOTE: internally this function allocates a copy of NxN dense A. You should
10995 : take it into account when working with very large matrices occupying
10996 : almost all RAM.
10997 :
10998 : -- ALGLIB --
10999 : Copyright 16.01.2017 by Bochkanov Sergey
11000 : *************************************************************************/
11001 0 : void eigsubspacesolvedenses(const eigsubspacestate &state, const real_2d_array &a, const bool isupper, real_1d_array &w, real_2d_array &z, eigsubspacereport &rep, const xparams _xparams)
11002 : {
11003 : jmp_buf _break_jump;
11004 : alglib_impl::ae_state _alglib_env_state;
11005 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11006 0 : if( setjmp(_break_jump) )
11007 : {
11008 : #if !defined(AE_NO_EXCEPTIONS)
11009 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11010 : #else
11011 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11012 : return;
11013 : #endif
11014 : }
11015 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11016 0 : if( _xparams.flags!=0x0 )
11017 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11018 0 : alglib_impl::eigsubspacesolvedenses(const_cast<alglib_impl::eigsubspacestate*>(state.c_ptr()), const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), isupper, const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), const_cast<alglib_impl::eigsubspacereport*>(rep.c_ptr()), &_alglib_env_state);
11019 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11020 0 : return;
11021 : }
11022 :
11023 : /*************************************************************************
11024 : This function runs eigensolver for dense NxN symmetric matrix A, given by
11025 : upper or lower triangle.
11026 :
11027 : This function can not process nonsymmetric matrices.
11028 :
11029 : INPUT PARAMETERS:
11030 : State - solver state
11031 : A - NxN symmetric matrix given by one of its triangles
11032 : IsUpper - whether upper or lower triangle of A is given (the
11033 : other one is not referenced at all).
11034 :
11035 : OUTPUT PARAMETERS:
11036 : W - array[K], top K eigenvalues ordered by descending
11037 : of their absolute values
11038 : Z - array[N,K], matrix of eigenvectors found
11039 : Rep - report with additional parameters
11040 :
11041 : -- ALGLIB --
11042 : Copyright 16.01.2017 by Bochkanov Sergey
11043 : *************************************************************************/
11044 0 : void eigsubspacesolvesparses(const eigsubspacestate &state, const sparsematrix &a, const bool isupper, real_1d_array &w, real_2d_array &z, eigsubspacereport &rep, const xparams _xparams)
11045 : {
11046 : jmp_buf _break_jump;
11047 : alglib_impl::ae_state _alglib_env_state;
11048 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11049 0 : if( setjmp(_break_jump) )
11050 : {
11051 : #if !defined(AE_NO_EXCEPTIONS)
11052 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11053 : #else
11054 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11055 : return;
11056 : #endif
11057 : }
11058 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11059 0 : if( _xparams.flags!=0x0 )
11060 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11061 0 : alglib_impl::eigsubspacesolvesparses(const_cast<alglib_impl::eigsubspacestate*>(state.c_ptr()), const_cast<alglib_impl::sparsematrix*>(a.c_ptr()), isupper, const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), const_cast<alglib_impl::eigsubspacereport*>(rep.c_ptr()), &_alglib_env_state);
11062 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11063 0 : return;
11064 : }
11065 :
11066 : /*************************************************************************
11067 : Finding the eigenvalues and eigenvectors of a symmetric matrix
11068 :
11069 : The algorithm finds eigen pairs of a symmetric matrix by reducing it to
11070 : tridiagonal form and using the QL/QR algorithm.
11071 :
11072 : ! COMMERCIAL EDITION OF ALGLIB:
11073 : !
11074 : ! Commercial Edition of ALGLIB includes following important improvements
11075 : ! of this function:
11076 : ! * high-performance native backend with same C# interface (C# version)
11077 : ! * hardware vendor (Intel) implementations of linear algebra primitives
11078 : ! (C++ and C# versions, x86/x64 platform)
11079 : !
11080 : ! We recommend you to read 'Working with commercial version' section of
11081 : ! ALGLIB Reference Manual in order to find out how to use performance-
11082 : ! related features provided by commercial edition of ALGLIB.
11083 :
11084 : Input parameters:
11085 : A - symmetric matrix which is given by its upper or lower
11086 : triangular part.
11087 : Array whose indexes range within [0..N-1, 0..N-1].
11088 : N - size of matrix A.
11089 : ZNeeded - flag controlling whether the eigenvectors are needed or not.
11090 : If ZNeeded is equal to:
11091 : * 0, the eigenvectors are not returned;
11092 : * 1, the eigenvectors are returned.
11093 : IsUpper - storage format.
11094 :
11095 : Output parameters:
11096 : D - eigenvalues in ascending order.
11097 : Array whose index ranges within [0..N-1].
11098 : Z - if ZNeeded is equal to:
11099 : * 0, Z hasn't changed;
11100 : * 1, Z contains the eigenvectors.
11101 : Array whose indexes range within [0..N-1, 0..N-1].
11102 : The eigenvectors are stored in the matrix columns.
11103 :
11104 : Result:
11105 : True, if the algorithm has converged.
11106 : False, if the algorithm hasn't converged (rare case).
11107 :
11108 : -- ALGLIB --
11109 : Copyright 2005-2008 by Bochkanov Sergey
11110 : *************************************************************************/
11111 0 : bool smatrixevd(const real_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, real_1d_array &d, real_2d_array &z, const xparams _xparams)
11112 : {
11113 : jmp_buf _break_jump;
11114 : alglib_impl::ae_state _alglib_env_state;
11115 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11116 0 : if( setjmp(_break_jump) )
11117 : {
11118 : #if !defined(AE_NO_EXCEPTIONS)
11119 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11120 : #else
11121 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11122 : return 0;
11123 : #endif
11124 : }
11125 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11126 0 : if( _xparams.flags!=0x0 )
11127 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11128 0 : ae_bool result = alglib_impl::smatrixevd(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, zneeded, isupper, const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), &_alglib_env_state);
11129 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11130 0 : return *(reinterpret_cast<bool*>(&result));
11131 : }
11132 :
11133 : /*************************************************************************
11134 : Subroutine for finding the eigenvalues (and eigenvectors) of a symmetric
11135 : matrix in a given half open interval (A, B] by using a bisection and
11136 : inverse iteration
11137 :
11138 : ! COMMERCIAL EDITION OF ALGLIB:
11139 : !
11140 : ! Commercial Edition of ALGLIB includes following important improvements
11141 : ! of this function:
11142 : ! * high-performance native backend with same C# interface (C# version)
11143 : ! * hardware vendor (Intel) implementations of linear algebra primitives
11144 : ! (C++ and C# versions, x86/x64 platform)
11145 : !
11146 : ! We recommend you to read 'Working with commercial version' section of
11147 : ! ALGLIB Reference Manual in order to find out how to use performance-
11148 : ! related features provided by commercial edition of ALGLIB.
11149 :
11150 : Input parameters:
11151 : A - symmetric matrix which is given by its upper or lower
11152 : triangular part. Array [0..N-1, 0..N-1].
11153 : N - size of matrix A.
11154 : ZNeeded - flag controlling whether the eigenvectors are needed or not.
11155 : If ZNeeded is equal to:
11156 : * 0, the eigenvectors are not returned;
11157 : * 1, the eigenvectors are returned.
11158 : IsUpperA - storage format of matrix A.
11159 : B1, B2 - half open interval (B1, B2] to search eigenvalues in.
11160 :
11161 : Output parameters:
11162 : M - number of eigenvalues found in a given half-interval (M>=0).
11163 : W - array of the eigenvalues found.
11164 : Array whose index ranges within [0..M-1].
11165 : Z - if ZNeeded is equal to:
11166 : * 0, Z hasn't changed;
11167 : * 1, Z contains eigenvectors.
11168 : Array whose indexes range within [0..N-1, 0..M-1].
11169 : The eigenvectors are stored in the matrix columns.
11170 :
11171 : Result:
11172 : True, if successful. M contains the number of eigenvalues in the given
11173 : half-interval (could be equal to 0), W contains the eigenvalues,
11174 : Z contains the eigenvectors (if needed).
11175 :
11176 : False, if the bisection method subroutine wasn't able to find the
11177 : eigenvalues in the given interval or if the inverse iteration subroutine
11178 : wasn't able to find all the corresponding eigenvectors.
11179 : In that case, the eigenvalues and eigenvectors are not returned,
11180 : M is equal to 0.
11181 :
11182 : -- ALGLIB --
11183 : Copyright 07.01.2006 by Bochkanov Sergey
11184 : *************************************************************************/
11185 0 : bool smatrixevdr(const real_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, const double b1, const double b2, ae_int_t &m, real_1d_array &w, real_2d_array &z, const xparams _xparams)
11186 : {
11187 : jmp_buf _break_jump;
11188 : alglib_impl::ae_state _alglib_env_state;
11189 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11190 0 : if( setjmp(_break_jump) )
11191 : {
11192 : #if !defined(AE_NO_EXCEPTIONS)
11193 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11194 : #else
11195 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11196 : return 0;
11197 : #endif
11198 : }
11199 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11200 0 : if( _xparams.flags!=0x0 )
11201 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11202 0 : ae_bool result = alglib_impl::smatrixevdr(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, zneeded, isupper, b1, b2, &m, const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), &_alglib_env_state);
11203 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11204 0 : return *(reinterpret_cast<bool*>(&result));
11205 : }
11206 :
11207 : /*************************************************************************
11208 : Subroutine for finding the eigenvalues and eigenvectors of a symmetric
11209 : matrix with given indexes by using bisection and inverse iteration methods.
11210 :
11211 : Input parameters:
11212 : A - symmetric matrix which is given by its upper or lower
11213 : triangular part. Array whose indexes range within [0..N-1, 0..N-1].
11214 : N - size of matrix A.
11215 : ZNeeded - flag controlling whether the eigenvectors are needed or not.
11216 : If ZNeeded is equal to:
11217 : * 0, the eigenvectors are not returned;
11218 : * 1, the eigenvectors are returned.
11219 : IsUpperA - storage format of matrix A.
11220 : I1, I2 - index interval for searching (from I1 to I2).
11221 : 0 <= I1 <= I2 <= N-1.
11222 :
11223 : Output parameters:
11224 : W - array of the eigenvalues found.
11225 : Array whose index ranges within [0..I2-I1].
11226 : Z - if ZNeeded is equal to:
11227 : * 0, Z hasn't changed;
11228 : * 1, Z contains eigenvectors.
11229 : Array whose indexes range within [0..N-1, 0..I2-I1].
11230 : In that case, the eigenvectors are stored in the matrix columns.
11231 :
11232 : Result:
11233 : True, if successful. W contains the eigenvalues, Z contains the
11234 : eigenvectors (if needed).
11235 :
11236 : False, if the bisection method subroutine wasn't able to find the
11237 : eigenvalues in the given interval or if the inverse iteration subroutine
11238 : wasn't able to find all the corresponding eigenvectors.
11239 : In that case, the eigenvalues and eigenvectors are not returned.
11240 :
11241 : -- ALGLIB --
11242 : Copyright 07.01.2006 by Bochkanov Sergey
11243 : *************************************************************************/
11244 0 : bool smatrixevdi(const real_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, const ae_int_t i1, const ae_int_t i2, real_1d_array &w, real_2d_array &z, const xparams _xparams)
11245 : {
11246 : jmp_buf _break_jump;
11247 : alglib_impl::ae_state _alglib_env_state;
11248 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11249 0 : if( setjmp(_break_jump) )
11250 : {
11251 : #if !defined(AE_NO_EXCEPTIONS)
11252 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11253 : #else
11254 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11255 : return 0;
11256 : #endif
11257 : }
11258 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11259 0 : if( _xparams.flags!=0x0 )
11260 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11261 0 : ae_bool result = alglib_impl::smatrixevdi(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, zneeded, isupper, i1, i2, const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), &_alglib_env_state);
11262 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11263 0 : return *(reinterpret_cast<bool*>(&result));
11264 : }
11265 :
11266 : /*************************************************************************
11267 : Finding the eigenvalues and eigenvectors of a Hermitian matrix
11268 :
11269 : The algorithm finds eigen pairs of a Hermitian matrix by reducing it to
11270 : real tridiagonal form and using the QL/QR algorithm.
11271 :
11272 : ! COMMERCIAL EDITION OF ALGLIB:
11273 : !
11274 : ! Commercial Edition of ALGLIB includes following important improvements
11275 : ! of this function:
11276 : ! * high-performance native backend with same C# interface (C# version)
11277 : ! * hardware vendor (Intel) implementations of linear algebra primitives
11278 : ! (C++ and C# versions, x86/x64 platform)
11279 : !
11280 : ! We recommend you to read 'Working with commercial version' section of
11281 : ! ALGLIB Reference Manual in order to find out how to use performance-
11282 : ! related features provided by commercial edition of ALGLIB.
11283 :
11284 : Input parameters:
11285 : A - Hermitian matrix which is given by its upper or lower
11286 : triangular part.
11287 : Array whose indexes range within [0..N-1, 0..N-1].
11288 : N - size of matrix A.
11289 : IsUpper - storage format.
11290 : ZNeeded - flag controlling whether the eigenvectors are needed or
11291 : not. If ZNeeded is equal to:
11292 : * 0, the eigenvectors are not returned;
11293 : * 1, the eigenvectors are returned.
11294 :
11295 : Output parameters:
11296 : D - eigenvalues in ascending order.
11297 : Array whose index ranges within [0..N-1].
11298 : Z - if ZNeeded is equal to:
11299 : * 0, Z hasn't changed;
11300 : * 1, Z contains the eigenvectors.
11301 : Array whose indexes range within [0..N-1, 0..N-1].
11302 : The eigenvectors are stored in the matrix columns.
11303 :
11304 : Result:
11305 : True, if the algorithm has converged.
11306 : False, if the algorithm hasn't converged (rare case).
11307 :
11308 : Note:
11309 : eigenvectors of Hermitian matrix are defined up to multiplication by
11310 : a complex number L, such that |L|=1.
11311 :
11312 : -- ALGLIB --
11313 : Copyright 2005, 23 March 2007 by Bochkanov Sergey
11314 : *************************************************************************/
11315 0 : bool hmatrixevd(const complex_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, real_1d_array &d, complex_2d_array &z, const xparams _xparams)
11316 : {
11317 : jmp_buf _break_jump;
11318 : alglib_impl::ae_state _alglib_env_state;
11319 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11320 0 : if( setjmp(_break_jump) )
11321 : {
11322 : #if !defined(AE_NO_EXCEPTIONS)
11323 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11324 : #else
11325 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11326 : return 0;
11327 : #endif
11328 : }
11329 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11330 0 : if( _xparams.flags!=0x0 )
11331 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11332 0 : ae_bool result = alglib_impl::hmatrixevd(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, zneeded, isupper, const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), &_alglib_env_state);
11333 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11334 0 : return *(reinterpret_cast<bool*>(&result));
11335 : }
11336 :
11337 : /*************************************************************************
11338 : Subroutine for finding the eigenvalues (and eigenvectors) of a Hermitian
11339 : matrix in a given half-interval (A, B] by using a bisection and inverse
11340 : iteration
11341 :
11342 : Input parameters:
11343 : A - Hermitian matrix which is given by its upper or lower
11344 : triangular part. Array whose indexes range within
11345 : [0..N-1, 0..N-1].
11346 : N - size of matrix A.
11347 : ZNeeded - flag controlling whether the eigenvectors are needed or
11348 : not. If ZNeeded is equal to:
11349 : * 0, the eigenvectors are not returned;
11350 : * 1, the eigenvectors are returned.
11351 : IsUpperA - storage format of matrix A.
11352 : B1, B2 - half-interval (B1, B2] to search eigenvalues in.
11353 :
11354 : Output parameters:
11355 : M - number of eigenvalues found in a given half-interval, M>=0
11356 : W - array of the eigenvalues found.
11357 : Array whose index ranges within [0..M-1].
11358 : Z - if ZNeeded is equal to:
11359 : * 0, Z hasn't changed;
11360 : * 1, Z contains eigenvectors.
11361 : Array whose indexes range within [0..N-1, 0..M-1].
11362 : The eigenvectors are stored in the matrix columns.
11363 :
11364 : Result:
11365 : True, if successful. M contains the number of eigenvalues in the given
11366 : half-interval (could be equal to 0), W contains the eigenvalues,
11367 : Z contains the eigenvectors (if needed).
11368 :
11369 : False, if the bisection method subroutine wasn't able to find the
11370 : eigenvalues in the given interval or if the inverse iteration
11371 : subroutine wasn't able to find all the corresponding eigenvectors.
11372 : In that case, the eigenvalues and eigenvectors are not returned, M is
11373 : equal to 0.
11374 :
11375 : Note:
11376 : eigen vectors of Hermitian matrix are defined up to multiplication by
11377 : a complex number L, such as |L|=1.
11378 :
11379 : -- ALGLIB --
11380 : Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey.
11381 : *************************************************************************/
11382 0 : bool hmatrixevdr(const complex_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, const double b1, const double b2, ae_int_t &m, real_1d_array &w, complex_2d_array &z, const xparams _xparams)
11383 : {
11384 : jmp_buf _break_jump;
11385 : alglib_impl::ae_state _alglib_env_state;
11386 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11387 0 : if( setjmp(_break_jump) )
11388 : {
11389 : #if !defined(AE_NO_EXCEPTIONS)
11390 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11391 : #else
11392 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11393 : return 0;
11394 : #endif
11395 : }
11396 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11397 0 : if( _xparams.flags!=0x0 )
11398 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11399 0 : ae_bool result = alglib_impl::hmatrixevdr(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, zneeded, isupper, b1, b2, &m, const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), &_alglib_env_state);
11400 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11401 0 : return *(reinterpret_cast<bool*>(&result));
11402 : }
11403 :
11404 : /*************************************************************************
11405 : Subroutine for finding the eigenvalues and eigenvectors of a Hermitian
11406 : matrix with given indexes by using bisection and inverse iteration methods
11407 :
11408 : Input parameters:
11409 : A - Hermitian matrix which is given by its upper or lower
11410 : triangular part.
11411 : Array whose indexes range within [0..N-1, 0..N-1].
11412 : N - size of matrix A.
11413 : ZNeeded - flag controlling whether the eigenvectors are needed or
11414 : not. If ZNeeded is equal to:
11415 : * 0, the eigenvectors are not returned;
11416 : * 1, the eigenvectors are returned.
11417 : IsUpperA - storage format of matrix A.
11418 : I1, I2 - index interval for searching (from I1 to I2).
11419 : 0 <= I1 <= I2 <= N-1.
11420 :
11421 : Output parameters:
11422 : W - array of the eigenvalues found.
11423 : Array whose index ranges within [0..I2-I1].
11424 : Z - if ZNeeded is equal to:
11425 : * 0, Z hasn't changed;
11426 : * 1, Z contains eigenvectors.
11427 : Array whose indexes range within [0..N-1, 0..I2-I1].
11428 : In that case, the eigenvectors are stored in the matrix
11429 : columns.
11430 :
11431 : Result:
11432 : True, if successful. W contains the eigenvalues, Z contains the
11433 : eigenvectors (if needed).
11434 :
11435 : False, if the bisection method subroutine wasn't able to find the
11436 : eigenvalues in the given interval or if the inverse iteration
11437 : subroutine wasn't able to find all the corresponding eigenvectors.
11438 : In that case, the eigenvalues and eigenvectors are not returned.
11439 :
11440 : Note:
11441 : eigen vectors of Hermitian matrix are defined up to multiplication by
11442 : a complex number L, such as |L|=1.
11443 :
11444 : -- ALGLIB --
11445 : Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey.
11446 : *************************************************************************/
11447 0 : bool hmatrixevdi(const complex_2d_array &a, const ae_int_t n, const ae_int_t zneeded, const bool isupper, const ae_int_t i1, const ae_int_t i2, real_1d_array &w, complex_2d_array &z, const xparams _xparams)
11448 : {
11449 : jmp_buf _break_jump;
11450 : alglib_impl::ae_state _alglib_env_state;
11451 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11452 0 : if( setjmp(_break_jump) )
11453 : {
11454 : #if !defined(AE_NO_EXCEPTIONS)
11455 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11456 : #else
11457 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11458 : return 0;
11459 : #endif
11460 : }
11461 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11462 0 : if( _xparams.flags!=0x0 )
11463 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11464 0 : ae_bool result = alglib_impl::hmatrixevdi(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, zneeded, isupper, i1, i2, const_cast<alglib_impl::ae_vector*>(w.c_ptr()), const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), &_alglib_env_state);
11465 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11466 0 : return *(reinterpret_cast<bool*>(&result));
11467 : }
11468 :
11469 : /*************************************************************************
11470 : Finding the eigenvalues and eigenvectors of a tridiagonal symmetric matrix
11471 :
11472 : The algorithm finds the eigen pairs of a tridiagonal symmetric matrix by
11473 : using an QL/QR algorithm with implicit shifts.
11474 :
11475 : ! COMMERCIAL EDITION OF ALGLIB:
11476 : !
11477 : ! Commercial Edition of ALGLIB includes following important improvements
11478 : ! of this function:
11479 : ! * high-performance native backend with same C# interface (C# version)
11480 : ! * hardware vendor (Intel) implementations of linear algebra primitives
11481 : ! (C++ and C# versions, x86/x64 platform)
11482 : !
11483 : ! We recommend you to read 'Working with commercial version' section of
11484 : ! ALGLIB Reference Manual in order to find out how to use performance-
11485 : ! related features provided by commercial edition of ALGLIB.
11486 :
11487 : Input parameters:
11488 : D - the main diagonal of a tridiagonal matrix.
11489 : Array whose index ranges within [0..N-1].
11490 : E - the secondary diagonal of a tridiagonal matrix.
11491 : Array whose index ranges within [0..N-2].
11492 : N - size of matrix A.
11493 : ZNeeded - flag controlling whether the eigenvectors are needed or not.
11494 : If ZNeeded is equal to:
11495 : * 0, the eigenvectors are not needed;
11496 : * 1, the eigenvectors of a tridiagonal matrix
11497 : are multiplied by the square matrix Z. It is used if the
11498 : tridiagonal matrix is obtained by the similarity
11499 : transformation of a symmetric matrix;
11500 : * 2, the eigenvectors of a tridiagonal matrix replace the
11501 : square matrix Z;
11502 : * 3, matrix Z contains the first row of the eigenvectors
11503 : matrix.
11504 : Z - if ZNeeded=1, Z contains the square matrix by which the
11505 : eigenvectors are multiplied.
11506 : Array whose indexes range within [0..N-1, 0..N-1].
11507 :
11508 : Output parameters:
11509 : D - eigenvalues in ascending order.
11510 : Array whose index ranges within [0..N-1].
11511 : Z - if ZNeeded is equal to:
11512 : * 0, Z hasn't changed;
11513 : * 1, Z contains the product of a given matrix (from the left)
11514 : and the eigenvectors matrix (from the right);
11515 : * 2, Z contains the eigenvectors.
11516 : * 3, Z contains the first row of the eigenvectors matrix.
11517 : If ZNeeded<3, Z is the array whose indexes range within [0..N-1, 0..N-1].
11518 : In that case, the eigenvectors are stored in the matrix columns.
11519 : If ZNeeded=3, Z is the array whose indexes range within [0..0, 0..N-1].
11520 :
11521 : Result:
11522 : True, if the algorithm has converged.
11523 : False, if the algorithm hasn't converged.
11524 :
11525 : -- LAPACK routine (version 3.0) --
11526 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
11527 : Courant Institute, Argonne National Lab, and Rice University
11528 : September 30, 1994
11529 : *************************************************************************/
11530 0 : bool smatrixtdevd(real_1d_array &d, const real_1d_array &e, const ae_int_t n, const ae_int_t zneeded, real_2d_array &z, const xparams _xparams)
11531 : {
11532 : jmp_buf _break_jump;
11533 : alglib_impl::ae_state _alglib_env_state;
11534 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11535 0 : if( setjmp(_break_jump) )
11536 : {
11537 : #if !defined(AE_NO_EXCEPTIONS)
11538 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11539 : #else
11540 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11541 : return 0;
11542 : #endif
11543 : }
11544 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11545 0 : if( _xparams.flags!=0x0 )
11546 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11547 0 : ae_bool result = alglib_impl::smatrixtdevd(const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_vector*>(e.c_ptr()), n, zneeded, const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), &_alglib_env_state);
11548 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11549 0 : return *(reinterpret_cast<bool*>(&result));
11550 : }
11551 :
11552 : /*************************************************************************
11553 : Subroutine for finding the tridiagonal matrix eigenvalues/vectors in a
11554 : given half-interval (A, B] by using bisection and inverse iteration.
11555 :
11556 : Input parameters:
11557 : D - the main diagonal of a tridiagonal matrix.
11558 : Array whose index ranges within [0..N-1].
11559 : E - the secondary diagonal of a tridiagonal matrix.
11560 : Array whose index ranges within [0..N-2].
11561 : N - size of matrix, N>=0.
11562 : ZNeeded - flag controlling whether the eigenvectors are needed or not.
11563 : If ZNeeded is equal to:
11564 : * 0, the eigenvectors are not needed;
11565 : * 1, the eigenvectors of a tridiagonal matrix are multiplied
11566 : by the square matrix Z. It is used if the tridiagonal
11567 : matrix is obtained by the similarity transformation
11568 : of a symmetric matrix.
11569 : * 2, the eigenvectors of a tridiagonal matrix replace matrix Z.
11570 : A, B - half-interval (A, B] to search eigenvalues in.
11571 : Z - if ZNeeded is equal to:
11572 : * 0, Z isn't used and remains unchanged;
11573 : * 1, Z contains the square matrix (array whose indexes range
11574 : within [0..N-1, 0..N-1]) which reduces the given symmetric
11575 : matrix to tridiagonal form;
11576 : * 2, Z isn't used (but changed on the exit).
11577 :
11578 : Output parameters:
11579 : D - array of the eigenvalues found.
11580 : Array whose index ranges within [0..M-1].
11581 : M - number of eigenvalues found in the given half-interval (M>=0).
11582 : Z - if ZNeeded is equal to:
11583 : * 0, doesn't contain any information;
11584 : * 1, contains the product of a given NxN matrix Z (from the
11585 : left) and NxM matrix of the eigenvectors found (from the
11586 : right). Array whose indexes range within [0..N-1, 0..M-1].
11587 : * 2, contains the matrix of the eigenvectors found.
11588 : Array whose indexes range within [0..N-1, 0..M-1].
11589 :
11590 : Result:
11591 :
11592 : True, if successful. In that case, M contains the number of eigenvalues
11593 : in the given half-interval (could be equal to 0), D contains the eigenvalues,
11594 : Z contains the eigenvectors (if needed).
11595 : It should be noted that the subroutine changes the size of arrays D and Z.
11596 :
11597 : False, if the bisection method subroutine wasn't able to find the
11598 : eigenvalues in the given interval or if the inverse iteration subroutine
11599 : wasn't able to find all the corresponding eigenvectors. In that case,
11600 : the eigenvalues and eigenvectors are not returned, M is equal to 0.
11601 :
11602 : -- ALGLIB --
11603 : Copyright 31.03.2008 by Bochkanov Sergey
11604 : *************************************************************************/
11605 0 : bool smatrixtdevdr(real_1d_array &d, const real_1d_array &e, const ae_int_t n, const ae_int_t zneeded, const double a, const double b, ae_int_t &m, real_2d_array &z, const xparams _xparams)
11606 : {
11607 : jmp_buf _break_jump;
11608 : alglib_impl::ae_state _alglib_env_state;
11609 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11610 0 : if( setjmp(_break_jump) )
11611 : {
11612 : #if !defined(AE_NO_EXCEPTIONS)
11613 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11614 : #else
11615 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11616 : return 0;
11617 : #endif
11618 : }
11619 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11620 0 : if( _xparams.flags!=0x0 )
11621 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11622 0 : ae_bool result = alglib_impl::smatrixtdevdr(const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_vector*>(e.c_ptr()), n, zneeded, a, b, &m, const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), &_alglib_env_state);
11623 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11624 0 : return *(reinterpret_cast<bool*>(&result));
11625 : }
11626 :
11627 : /*************************************************************************
11628 : Subroutine for finding tridiagonal matrix eigenvalues/vectors with given
11629 : indexes (in ascending order) by using the bisection and inverse iteraion.
11630 :
11631 : Input parameters:
11632 : D - the main diagonal of a tridiagonal matrix.
11633 : Array whose index ranges within [0..N-1].
11634 : E - the secondary diagonal of a tridiagonal matrix.
11635 : Array whose index ranges within [0..N-2].
11636 : N - size of matrix. N>=0.
11637 : ZNeeded - flag controlling whether the eigenvectors are needed or not.
11638 : If ZNeeded is equal to:
11639 : * 0, the eigenvectors are not needed;
11640 : * 1, the eigenvectors of a tridiagonal matrix are multiplied
11641 : by the square matrix Z. It is used if the
11642 : tridiagonal matrix is obtained by the similarity transformation
11643 : of a symmetric matrix.
11644 : * 2, the eigenvectors of a tridiagonal matrix replace
11645 : matrix Z.
11646 : I1, I2 - index interval for searching (from I1 to I2).
11647 : 0 <= I1 <= I2 <= N-1.
11648 : Z - if ZNeeded is equal to:
11649 : * 0, Z isn't used and remains unchanged;
11650 : * 1, Z contains the square matrix (array whose indexes range within [0..N-1, 0..N-1])
11651 : which reduces the given symmetric matrix to tridiagonal form;
11652 : * 2, Z isn't used (but changed on the exit).
11653 :
11654 : Output parameters:
11655 : D - array of the eigenvalues found.
11656 : Array whose index ranges within [0..I2-I1].
11657 : Z - if ZNeeded is equal to:
11658 : * 0, doesn't contain any information;
11659 : * 1, contains the product of a given NxN matrix Z (from the left) and
11660 : Nx(I2-I1) matrix of the eigenvectors found (from the right).
11661 : Array whose indexes range within [0..N-1, 0..I2-I1].
11662 : * 2, contains the matrix of the eigenvalues found.
11663 : Array whose indexes range within [0..N-1, 0..I2-I1].
11664 :
11665 :
11666 : Result:
11667 :
11668 : True, if successful. In that case, D contains the eigenvalues,
11669 : Z contains the eigenvectors (if needed).
11670 : It should be noted that the subroutine changes the size of arrays D and Z.
11671 :
11672 : False, if the bisection method subroutine wasn't able to find the eigenvalues
11673 : in the given interval or if the inverse iteration subroutine wasn't able
11674 : to find all the corresponding eigenvectors. In that case, the eigenvalues
11675 : and eigenvectors are not returned.
11676 :
11677 : -- ALGLIB --
11678 : Copyright 25.12.2005 by Bochkanov Sergey
11679 : *************************************************************************/
11680 0 : bool smatrixtdevdi(real_1d_array &d, const real_1d_array &e, const ae_int_t n, const ae_int_t zneeded, const ae_int_t i1, const ae_int_t i2, real_2d_array &z, const xparams _xparams)
11681 : {
11682 : jmp_buf _break_jump;
11683 : alglib_impl::ae_state _alglib_env_state;
11684 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11685 0 : if( setjmp(_break_jump) )
11686 : {
11687 : #if !defined(AE_NO_EXCEPTIONS)
11688 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11689 : #else
11690 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11691 : return 0;
11692 : #endif
11693 : }
11694 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11695 0 : if( _xparams.flags!=0x0 )
11696 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11697 0 : ae_bool result = alglib_impl::smatrixtdevdi(const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_vector*>(e.c_ptr()), n, zneeded, i1, i2, const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), &_alglib_env_state);
11698 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11699 0 : return *(reinterpret_cast<bool*>(&result));
11700 : }
11701 :
11702 : /*************************************************************************
11703 : Finding eigenvalues and eigenvectors of a general (unsymmetric) matrix
11704 :
11705 : ! COMMERCIAL EDITION OF ALGLIB:
11706 : !
11707 : ! Commercial Edition of ALGLIB includes following important improvements
11708 : ! of this function:
11709 : ! * high-performance native backend with same C# interface (C# version)
11710 : ! * hardware vendor (Intel) implementations of linear algebra primitives
11711 : ! (C++ and C# versions, x86/x64 platform)
11712 : !
11713 : ! We recommend you to read 'Working with commercial version' section of
11714 : ! ALGLIB Reference Manual in order to find out how to use performance-
11715 : ! related features provided by commercial edition of ALGLIB.
11716 :
11717 : The algorithm finds eigenvalues and eigenvectors of a general matrix by
11718 : using the QR algorithm with multiple shifts. The algorithm can find
11719 : eigenvalues and both left and right eigenvectors.
11720 :
11721 : The right eigenvector is a vector x such that A*x = w*x, and the left
11722 : eigenvector is a vector y such that y'*A = w*y' (here y' implies a complex
11723 : conjugate transposition of vector y).
11724 :
11725 : Input parameters:
11726 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
11727 : N - size of matrix A.
11728 : VNeeded - flag controlling whether eigenvectors are needed or not.
11729 : If VNeeded is equal to:
11730 : * 0, eigenvectors are not returned;
11731 : * 1, right eigenvectors are returned;
11732 : * 2, left eigenvectors are returned;
11733 : * 3, both left and right eigenvectors are returned.
11734 :
11735 : Output parameters:
11736 : WR - real parts of eigenvalues.
11737 : Array whose index ranges within [0..N-1].
11738 : WR - imaginary parts of eigenvalues.
11739 : Array whose index ranges within [0..N-1].
11740 : VL, VR - arrays of left and right eigenvectors (if they are needed).
11741 : If WI[i]=0, the respective eigenvalue is a real number,
11742 : and it corresponds to the column number I of matrices VL/VR.
11743 : If WI[i]>0, we have a pair of complex conjugate numbers with
11744 : positive and negative imaginary parts:
11745 : the first eigenvalue WR[i] + sqrt(-1)*WI[i];
11746 : the second eigenvalue WR[i+1] + sqrt(-1)*WI[i+1];
11747 : WI[i]>0
11748 : WI[i+1] = -WI[i] < 0
11749 : In that case, the eigenvector corresponding to the first
11750 : eigenvalue is located in i and i+1 columns of matrices
11751 : VL/VR (the column number i contains the real part, and the
11752 : column number i+1 contains the imaginary part), and the vector
11753 : corresponding to the second eigenvalue is a complex conjugate to
11754 : the first vector.
11755 : Arrays whose indexes range within [0..N-1, 0..N-1].
11756 :
11757 : Result:
11758 : True, if the algorithm has converged.
11759 : False, if the algorithm has not converged.
11760 :
11761 : Note 1:
11762 : Some users may ask the following question: what if WI[N-1]>0?
11763 : WI[N] must contain an eigenvalue which is complex conjugate to the
11764 : N-th eigenvalue, but the array has only size N?
11765 : The answer is as follows: such a situation cannot occur because the
11766 : algorithm finds a pairs of eigenvalues, therefore, if WI[i]>0, I is
11767 : strictly less than N-1.
11768 :
11769 : Note 2:
11770 : The algorithm performance depends on the value of the internal parameter
11771 : NS of the InternalSchurDecomposition subroutine which defines the number
11772 : of shifts in the QR algorithm (similarly to the block width in block-matrix
11773 : algorithms of linear algebra). If you require maximum performance
11774 : on your machine, it is recommended to adjust this parameter manually.
11775 :
11776 :
11777 : See also the InternalTREVC subroutine.
11778 :
11779 : The algorithm is based on the LAPACK 3.0 library.
11780 : *************************************************************************/
11781 0 : bool rmatrixevd(const real_2d_array &a, const ae_int_t n, const ae_int_t vneeded, real_1d_array &wr, real_1d_array &wi, real_2d_array &vl, real_2d_array &vr, const xparams _xparams)
11782 : {
11783 : jmp_buf _break_jump;
11784 : alglib_impl::ae_state _alglib_env_state;
11785 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11786 0 : if( setjmp(_break_jump) )
11787 : {
11788 : #if !defined(AE_NO_EXCEPTIONS)
11789 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11790 : #else
11791 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11792 : return 0;
11793 : #endif
11794 : }
11795 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11796 0 : if( _xparams.flags!=0x0 )
11797 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11798 0 : ae_bool result = alglib_impl::rmatrixevd(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, vneeded, const_cast<alglib_impl::ae_vector*>(wr.c_ptr()), const_cast<alglib_impl::ae_vector*>(wi.c_ptr()), const_cast<alglib_impl::ae_matrix*>(vl.c_ptr()), const_cast<alglib_impl::ae_matrix*>(vr.c_ptr()), &_alglib_env_state);
11799 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11800 0 : return *(reinterpret_cast<bool*>(&result));
11801 : }
11802 : #endif
11803 :
11804 : #if defined(AE_COMPILE_SCHUR) || !defined(AE_PARTIAL_BUILD)
11805 : /*************************************************************************
11806 : Subroutine performing the Schur decomposition of a general matrix by using
11807 : the QR algorithm with multiple shifts.
11808 :
11809 : COMMERCIAL EDITION OF ALGLIB:
11810 :
11811 : ! Commercial version of ALGLIB includes one important improvement of
11812 : ! this function, which can be used from C++ and C#:
11813 : ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB)
11814 : !
11815 : ! Intel MKL gives approximately constant (with respect to number of
11816 : ! worker threads) acceleration factor which depends on CPU being used,
11817 : ! problem size and "baseline" ALGLIB edition which is used for
11818 : ! comparison.
11819 : !
11820 : ! Multithreaded acceleration is NOT supported for this function.
11821 : !
11822 : ! We recommend you to read 'Working with commercial version' section of
11823 : ! ALGLIB Reference Manual in order to find out how to use performance-
11824 : ! related features provided by commercial edition of ALGLIB.
11825 :
11826 : The source matrix A is represented as S'*A*S = T, where S is an orthogonal
11827 : matrix (Schur vectors), T - upper quasi-triangular matrix (with blocks of
11828 : sizes 1x1 and 2x2 on the main diagonal).
11829 :
11830 : Input parameters:
11831 : A - matrix to be decomposed.
11832 : Array whose indexes range within [0..N-1, 0..N-1].
11833 : N - size of A, N>=0.
11834 :
11835 :
11836 : Output parameters:
11837 : A - contains matrix T.
11838 : Array whose indexes range within [0..N-1, 0..N-1].
11839 : S - contains Schur vectors.
11840 : Array whose indexes range within [0..N-1, 0..N-1].
11841 :
11842 : Note 1:
11843 : The block structure of matrix T can be easily recognized: since all
11844 : the elements below the blocks are zeros, the elements a[i+1,i] which
11845 : are equal to 0 show the block border.
11846 :
11847 : Note 2:
11848 : The algorithm performance depends on the value of the internal parameter
11849 : NS of the InternalSchurDecomposition subroutine which defines the number
11850 : of shifts in the QR algorithm (similarly to the block width in block-matrix
11851 : algorithms in linear algebra). If you require maximum performance on
11852 : your machine, it is recommended to adjust this parameter manually.
11853 :
11854 : Result:
11855 : True,
11856 : if the algorithm has converged and parameters A and S contain the result.
11857 : False,
11858 : if the algorithm has not converged.
11859 :
11860 : Algorithm implemented on the basis of the DHSEQR subroutine (LAPACK 3.0 library).
11861 : *************************************************************************/
11862 0 : bool rmatrixschur(real_2d_array &a, const ae_int_t n, real_2d_array &s, const xparams _xparams)
11863 : {
11864 : jmp_buf _break_jump;
11865 : alglib_impl::ae_state _alglib_env_state;
11866 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11867 0 : if( setjmp(_break_jump) )
11868 : {
11869 : #if !defined(AE_NO_EXCEPTIONS)
11870 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11871 : #else
11872 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11873 : return 0;
11874 : #endif
11875 : }
11876 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11877 0 : if( _xparams.flags!=0x0 )
11878 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11879 0 : ae_bool result = alglib_impl::rmatrixschur(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, const_cast<alglib_impl::ae_matrix*>(s.c_ptr()), &_alglib_env_state);
11880 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11881 0 : return *(reinterpret_cast<bool*>(&result));
11882 : }
11883 : #endif
11884 :
11885 : #if defined(AE_COMPILE_SPDGEVD) || !defined(AE_PARTIAL_BUILD)
11886 : /*************************************************************************
11887 : Algorithm for solving the following generalized symmetric positive-definite
11888 : eigenproblem:
11889 : A*x = lambda*B*x (1) or
11890 : A*B*x = lambda*x (2) or
11891 : B*A*x = lambda*x (3).
11892 : where A is a symmetric matrix, B - symmetric positive-definite matrix.
11893 : The problem is solved by reducing it to an ordinary symmetric eigenvalue
11894 : problem.
11895 :
11896 : Input parameters:
11897 : A - symmetric matrix which is given by its upper or lower
11898 : triangular part.
11899 : Array whose indexes range within [0..N-1, 0..N-1].
11900 : N - size of matrices A and B.
11901 : IsUpperA - storage format of matrix A.
11902 : B - symmetric positive-definite matrix which is given by
11903 : its upper or lower triangular part.
11904 : Array whose indexes range within [0..N-1, 0..N-1].
11905 : IsUpperB - storage format of matrix B.
11906 : ZNeeded - if ZNeeded is equal to:
11907 : * 0, the eigenvectors are not returned;
11908 : * 1, the eigenvectors are returned.
11909 : ProblemType - if ProblemType is equal to:
11910 : * 1, the following problem is solved: A*x = lambda*B*x;
11911 : * 2, the following problem is solved: A*B*x = lambda*x;
11912 : * 3, the following problem is solved: B*A*x = lambda*x.
11913 :
11914 : Output parameters:
11915 : D - eigenvalues in ascending order.
11916 : Array whose index ranges within [0..N-1].
11917 : Z - if ZNeeded is equal to:
11918 : * 0, Z hasn't changed;
11919 : * 1, Z contains eigenvectors.
11920 : Array whose indexes range within [0..N-1, 0..N-1].
11921 : The eigenvectors are stored in matrix columns. It should
11922 : be noted that the eigenvectors in such problems do not
11923 : form an orthogonal system.
11924 :
11925 : Result:
11926 : True, if the problem was solved successfully.
11927 : False, if the error occurred during the Cholesky decomposition of matrix
11928 : B (the matrix isn't positive-definite) or during the work of the iterative
11929 : algorithm for solving the symmetric eigenproblem.
11930 :
11931 : See also the GeneralizedSymmetricDefiniteEVDReduce subroutine.
11932 :
11933 : -- ALGLIB --
11934 : Copyright 1.28.2006 by Bochkanov Sergey
11935 : *************************************************************************/
11936 0 : bool smatrixgevd(const real_2d_array &a, const ae_int_t n, const bool isuppera, const real_2d_array &b, const bool isupperb, const ae_int_t zneeded, const ae_int_t problemtype, real_1d_array &d, real_2d_array &z, const xparams _xparams)
11937 : {
11938 : jmp_buf _break_jump;
11939 : alglib_impl::ae_state _alglib_env_state;
11940 0 : alglib_impl::ae_state_init(&_alglib_env_state);
11941 0 : if( setjmp(_break_jump) )
11942 : {
11943 : #if !defined(AE_NO_EXCEPTIONS)
11944 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
11945 : #else
11946 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
11947 : return 0;
11948 : #endif
11949 : }
11950 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
11951 0 : if( _xparams.flags!=0x0 )
11952 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
11953 0 : ae_bool result = alglib_impl::smatrixgevd(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isuppera, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), isupperb, zneeded, problemtype, const_cast<alglib_impl::ae_vector*>(d.c_ptr()), const_cast<alglib_impl::ae_matrix*>(z.c_ptr()), &_alglib_env_state);
11954 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
11955 0 : return *(reinterpret_cast<bool*>(&result));
11956 : }
11957 :
11958 : /*************************************************************************
11959 : Algorithm for reduction of the following generalized symmetric positive-
11960 : definite eigenvalue problem:
11961 : A*x = lambda*B*x (1) or
11962 : A*B*x = lambda*x (2) or
11963 : B*A*x = lambda*x (3)
11964 : to the symmetric eigenvalues problem C*y = lambda*y (eigenvalues of this and
11965 : the given problems are the same, and the eigenvectors of the given problem
11966 : could be obtained by multiplying the obtained eigenvectors by the
11967 : transformation matrix x = R*y).
11968 :
11969 : Here A is a symmetric matrix, B - symmetric positive-definite matrix.
11970 :
11971 : Input parameters:
11972 : A - symmetric matrix which is given by its upper or lower
11973 : triangular part.
11974 : Array whose indexes range within [0..N-1, 0..N-1].
11975 : N - size of matrices A and B.
11976 : IsUpperA - storage format of matrix A.
11977 : B - symmetric positive-definite matrix which is given by
11978 : its upper or lower triangular part.
11979 : Array whose indexes range within [0..N-1, 0..N-1].
11980 : IsUpperB - storage format of matrix B.
11981 : ProblemType - if ProblemType is equal to:
11982 : * 1, the following problem is solved: A*x = lambda*B*x;
11983 : * 2, the following problem is solved: A*B*x = lambda*x;
11984 : * 3, the following problem is solved: B*A*x = lambda*x.
11985 :
11986 : Output parameters:
11987 : A - symmetric matrix which is given by its upper or lower
11988 : triangle depending on IsUpperA. Contains matrix C.
11989 : Array whose indexes range within [0..N-1, 0..N-1].
11990 : R - upper triangular or low triangular transformation matrix
11991 : which is used to obtain the eigenvectors of a given problem
11992 : as the product of eigenvectors of C (from the right) and
11993 : matrix R (from the left). If the matrix is upper
11994 : triangular, the elements below the main diagonal
11995 : are equal to 0 (and vice versa). Thus, we can perform
11996 : the multiplication without taking into account the
11997 : internal structure (which is an easier though less
11998 : effective way).
11999 : Array whose indexes range within [0..N-1, 0..N-1].
12000 : IsUpperR - type of matrix R (upper or lower triangular).
12001 :
12002 : Result:
12003 : True, if the problem was reduced successfully.
12004 : False, if the error occurred during the Cholesky decomposition of
12005 : matrix B (the matrix is not positive-definite).
12006 :
12007 : -- ALGLIB --
12008 : Copyright 1.28.2006 by Bochkanov Sergey
12009 : *************************************************************************/
12010 0 : bool smatrixgevdreduce(real_2d_array &a, const ae_int_t n, const bool isuppera, const real_2d_array &b, const bool isupperb, const ae_int_t problemtype, real_2d_array &r, bool &isupperr, const xparams _xparams)
12011 : {
12012 : jmp_buf _break_jump;
12013 : alglib_impl::ae_state _alglib_env_state;
12014 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12015 0 : if( setjmp(_break_jump) )
12016 : {
12017 : #if !defined(AE_NO_EXCEPTIONS)
12018 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12019 : #else
12020 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12021 : return 0;
12022 : #endif
12023 : }
12024 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12025 0 : if( _xparams.flags!=0x0 )
12026 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12027 0 : ae_bool result = alglib_impl::smatrixgevdreduce(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isuppera, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), isupperb, problemtype, const_cast<alglib_impl::ae_matrix*>(r.c_ptr()), &isupperr, &_alglib_env_state);
12028 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12029 0 : return *(reinterpret_cast<bool*>(&result));
12030 : }
12031 : #endif
12032 :
12033 : #if defined(AE_COMPILE_INVERSEUPDATE) || !defined(AE_PARTIAL_BUILD)
12034 : /*************************************************************************
12035 : Inverse matrix update by the Sherman-Morrison formula
12036 :
12037 : The algorithm updates matrix A^-1 when adding a number to an element
12038 : of matrix A.
12039 :
12040 : Input parameters:
12041 : InvA - inverse of matrix A.
12042 : Array whose indexes range within [0..N-1, 0..N-1].
12043 : N - size of matrix A.
12044 : UpdRow - row where the element to be updated is stored.
12045 : UpdColumn - column where the element to be updated is stored.
12046 : UpdVal - a number to be added to the element.
12047 :
12048 :
12049 : Output parameters:
12050 : InvA - inverse of modified matrix A.
12051 :
12052 : -- ALGLIB --
12053 : Copyright 2005 by Bochkanov Sergey
12054 : *************************************************************************/
12055 0 : void rmatrixinvupdatesimple(real_2d_array &inva, const ae_int_t n, const ae_int_t updrow, const ae_int_t updcolumn, const double updval, const xparams _xparams)
12056 : {
12057 : jmp_buf _break_jump;
12058 : alglib_impl::ae_state _alglib_env_state;
12059 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12060 0 : if( setjmp(_break_jump) )
12061 : {
12062 : #if !defined(AE_NO_EXCEPTIONS)
12063 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12064 : #else
12065 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12066 : return;
12067 : #endif
12068 : }
12069 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12070 0 : if( _xparams.flags!=0x0 )
12071 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12072 0 : alglib_impl::rmatrixinvupdatesimple(const_cast<alglib_impl::ae_matrix*>(inva.c_ptr()), n, updrow, updcolumn, updval, &_alglib_env_state);
12073 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12074 0 : return;
12075 : }
12076 :
12077 : /*************************************************************************
12078 : Inverse matrix update by the Sherman-Morrison formula
12079 :
12080 : The algorithm updates matrix A^-1 when adding a vector to a row
12081 : of matrix A.
12082 :
12083 : Input parameters:
12084 : InvA - inverse of matrix A.
12085 : Array whose indexes range within [0..N-1, 0..N-1].
12086 : N - size of matrix A.
12087 : UpdRow - the row of A whose vector V was added.
12088 : 0 <= Row <= N-1
12089 : V - the vector to be added to a row.
12090 : Array whose index ranges within [0..N-1].
12091 :
12092 : Output parameters:
12093 : InvA - inverse of modified matrix A.
12094 :
12095 : -- ALGLIB --
12096 : Copyright 2005 by Bochkanov Sergey
12097 : *************************************************************************/
12098 0 : void rmatrixinvupdaterow(real_2d_array &inva, const ae_int_t n, const ae_int_t updrow, const real_1d_array &v, const xparams _xparams)
12099 : {
12100 : jmp_buf _break_jump;
12101 : alglib_impl::ae_state _alglib_env_state;
12102 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12103 0 : if( setjmp(_break_jump) )
12104 : {
12105 : #if !defined(AE_NO_EXCEPTIONS)
12106 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12107 : #else
12108 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12109 : return;
12110 : #endif
12111 : }
12112 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12113 0 : if( _xparams.flags!=0x0 )
12114 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12115 0 : alglib_impl::rmatrixinvupdaterow(const_cast<alglib_impl::ae_matrix*>(inva.c_ptr()), n, updrow, const_cast<alglib_impl::ae_vector*>(v.c_ptr()), &_alglib_env_state);
12116 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12117 0 : return;
12118 : }
12119 :
12120 : /*************************************************************************
12121 : Inverse matrix update by the Sherman-Morrison formula
12122 :
12123 : The algorithm updates matrix A^-1 when adding a vector to a column
12124 : of matrix A.
12125 :
12126 : Input parameters:
12127 : InvA - inverse of matrix A.
12128 : Array whose indexes range within [0..N-1, 0..N-1].
12129 : N - size of matrix A.
12130 : UpdColumn - the column of A whose vector U was added.
12131 : 0 <= UpdColumn <= N-1
12132 : U - the vector to be added to a column.
12133 : Array whose index ranges within [0..N-1].
12134 :
12135 : Output parameters:
12136 : InvA - inverse of modified matrix A.
12137 :
12138 : -- ALGLIB --
12139 : Copyright 2005 by Bochkanov Sergey
12140 : *************************************************************************/
12141 0 : void rmatrixinvupdatecolumn(real_2d_array &inva, const ae_int_t n, const ae_int_t updcolumn, const real_1d_array &u, const xparams _xparams)
12142 : {
12143 : jmp_buf _break_jump;
12144 : alglib_impl::ae_state _alglib_env_state;
12145 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12146 0 : if( setjmp(_break_jump) )
12147 : {
12148 : #if !defined(AE_NO_EXCEPTIONS)
12149 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12150 : #else
12151 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12152 : return;
12153 : #endif
12154 : }
12155 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12156 0 : if( _xparams.flags!=0x0 )
12157 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12158 0 : alglib_impl::rmatrixinvupdatecolumn(const_cast<alglib_impl::ae_matrix*>(inva.c_ptr()), n, updcolumn, const_cast<alglib_impl::ae_vector*>(u.c_ptr()), &_alglib_env_state);
12159 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12160 0 : return;
12161 : }
12162 :
12163 : /*************************************************************************
12164 : Inverse matrix update by the Sherman-Morrison formula
12165 :
12166 : The algorithm computes the inverse of matrix A+u*v' by using the given matrix
12167 : A^-1 and the vectors u and v.
12168 :
12169 : Input parameters:
12170 : InvA - inverse of matrix A.
12171 : Array whose indexes range within [0..N-1, 0..N-1].
12172 : N - size of matrix A.
12173 : U - the vector modifying the matrix.
12174 : Array whose index ranges within [0..N-1].
12175 : V - the vector modifying the matrix.
12176 : Array whose index ranges within [0..N-1].
12177 :
12178 : Output parameters:
12179 : InvA - inverse of matrix A + u*v'.
12180 :
12181 : -- ALGLIB --
12182 : Copyright 2005 by Bochkanov Sergey
12183 : *************************************************************************/
12184 0 : void rmatrixinvupdateuv(real_2d_array &inva, const ae_int_t n, const real_1d_array &u, const real_1d_array &v, const xparams _xparams)
12185 : {
12186 : jmp_buf _break_jump;
12187 : alglib_impl::ae_state _alglib_env_state;
12188 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12189 0 : if( setjmp(_break_jump) )
12190 : {
12191 : #if !defined(AE_NO_EXCEPTIONS)
12192 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12193 : #else
12194 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12195 : return;
12196 : #endif
12197 : }
12198 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12199 0 : if( _xparams.flags!=0x0 )
12200 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12201 0 : alglib_impl::rmatrixinvupdateuv(const_cast<alglib_impl::ae_matrix*>(inva.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(u.c_ptr()), const_cast<alglib_impl::ae_vector*>(v.c_ptr()), &_alglib_env_state);
12202 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12203 0 : return;
12204 : }
12205 : #endif
12206 :
12207 : #if defined(AE_COMPILE_MATDET) || !defined(AE_PARTIAL_BUILD)
12208 : /*************************************************************************
12209 : Determinant calculation of the matrix given by its LU decomposition.
12210 :
12211 : Input parameters:
12212 : A - LU decomposition of the matrix (output of
12213 : RMatrixLU subroutine).
12214 : Pivots - table of permutations which were made during
12215 : the LU decomposition.
12216 : Output of RMatrixLU subroutine.
12217 : N - (optional) size of matrix A:
12218 : * if given, only principal NxN submatrix is processed and
12219 : overwritten. other elements are unchanged.
12220 : * if not given, automatically determined from matrix size
12221 : (A must be square matrix)
12222 :
12223 : Result: matrix determinant.
12224 :
12225 : -- ALGLIB --
12226 : Copyright 2005 by Bochkanov Sergey
12227 : *************************************************************************/
12228 0 : double rmatrixludet(const real_2d_array &a, const integer_1d_array &pivots, const ae_int_t n, const xparams _xparams)
12229 : {
12230 : jmp_buf _break_jump;
12231 : alglib_impl::ae_state _alglib_env_state;
12232 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12233 0 : if( setjmp(_break_jump) )
12234 : {
12235 : #if !defined(AE_NO_EXCEPTIONS)
12236 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12237 : #else
12238 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12239 : return 0;
12240 : #endif
12241 : }
12242 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12243 0 : if( _xparams.flags!=0x0 )
12244 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12245 0 : double result = alglib_impl::rmatrixludet(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(pivots.c_ptr()), n, &_alglib_env_state);
12246 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12247 0 : return *(reinterpret_cast<double*>(&result));
12248 : }
12249 :
12250 : /*************************************************************************
12251 : Determinant calculation of the matrix given by its LU decomposition.
12252 :
12253 : Input parameters:
12254 : A - LU decomposition of the matrix (output of
12255 : RMatrixLU subroutine).
12256 : Pivots - table of permutations which were made during
12257 : the LU decomposition.
12258 : Output of RMatrixLU subroutine.
12259 : N - (optional) size of matrix A:
12260 : * if given, only principal NxN submatrix is processed and
12261 : overwritten. other elements are unchanged.
12262 : * if not given, automatically determined from matrix size
12263 : (A must be square matrix)
12264 :
12265 : Result: matrix determinant.
12266 :
12267 : -- ALGLIB --
12268 : Copyright 2005 by Bochkanov Sergey
12269 : *************************************************************************/
12270 : #if !defined(AE_NO_EXCEPTIONS)
12271 0 : double rmatrixludet(const real_2d_array &a, const integer_1d_array &pivots, const xparams _xparams)
12272 : {
12273 : jmp_buf _break_jump;
12274 : alglib_impl::ae_state _alglib_env_state;
12275 : ae_int_t n;
12276 0 : if( (a.rows()!=a.cols()) || (a.rows()!=pivots.length()))
12277 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'rmatrixludet': looks like one of arguments has wrong size");
12278 0 : n = a.rows();
12279 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12280 0 : if( setjmp(_break_jump) )
12281 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12282 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12283 0 : if( _xparams.flags!=0x0 )
12284 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12285 0 : double result = alglib_impl::rmatrixludet(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(pivots.c_ptr()), n, &_alglib_env_state);
12286 :
12287 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12288 0 : return *(reinterpret_cast<double*>(&result));
12289 : }
12290 : #endif
12291 :
12292 : /*************************************************************************
12293 : Calculation of the determinant of a general matrix
12294 :
12295 : Input parameters:
12296 : A - matrix, array[0..N-1, 0..N-1]
12297 : N - (optional) size of matrix A:
12298 : * if given, only principal NxN submatrix is processed and
12299 : overwritten. other elements are unchanged.
12300 : * if not given, automatically determined from matrix size
12301 : (A must be square matrix)
12302 :
12303 : Result: determinant of matrix A.
12304 :
12305 : -- ALGLIB --
12306 : Copyright 2005 by Bochkanov Sergey
12307 : *************************************************************************/
12308 0 : double rmatrixdet(const real_2d_array &a, const ae_int_t n, const xparams _xparams)
12309 : {
12310 : jmp_buf _break_jump;
12311 : alglib_impl::ae_state _alglib_env_state;
12312 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12313 0 : if( setjmp(_break_jump) )
12314 : {
12315 : #if !defined(AE_NO_EXCEPTIONS)
12316 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12317 : #else
12318 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12319 : return 0;
12320 : #endif
12321 : }
12322 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12323 0 : if( _xparams.flags!=0x0 )
12324 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12325 0 : double result = alglib_impl::rmatrixdet(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &_alglib_env_state);
12326 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12327 0 : return *(reinterpret_cast<double*>(&result));
12328 : }
12329 :
12330 : /*************************************************************************
12331 : Calculation of the determinant of a general matrix
12332 :
12333 : Input parameters:
12334 : A - matrix, array[0..N-1, 0..N-1]
12335 : N - (optional) size of matrix A:
12336 : * if given, only principal NxN submatrix is processed and
12337 : overwritten. other elements are unchanged.
12338 : * if not given, automatically determined from matrix size
12339 : (A must be square matrix)
12340 :
12341 : Result: determinant of matrix A.
12342 :
12343 : -- ALGLIB --
12344 : Copyright 2005 by Bochkanov Sergey
12345 : *************************************************************************/
12346 : #if !defined(AE_NO_EXCEPTIONS)
12347 0 : double rmatrixdet(const real_2d_array &a, const xparams _xparams)
12348 : {
12349 : jmp_buf _break_jump;
12350 : alglib_impl::ae_state _alglib_env_state;
12351 : ae_int_t n;
12352 0 : if( (a.rows()!=a.cols()))
12353 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'rmatrixdet': looks like one of arguments has wrong size");
12354 0 : n = a.rows();
12355 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12356 0 : if( setjmp(_break_jump) )
12357 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12358 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12359 0 : if( _xparams.flags!=0x0 )
12360 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12361 0 : double result = alglib_impl::rmatrixdet(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &_alglib_env_state);
12362 :
12363 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12364 0 : return *(reinterpret_cast<double*>(&result));
12365 : }
12366 : #endif
12367 :
12368 : /*************************************************************************
12369 : Determinant calculation of the matrix given by its LU decomposition.
12370 :
12371 : Input parameters:
12372 : A - LU decomposition of the matrix (output of
12373 : RMatrixLU subroutine).
12374 : Pivots - table of permutations which were made during
12375 : the LU decomposition.
12376 : Output of RMatrixLU subroutine.
12377 : N - (optional) size of matrix A:
12378 : * if given, only principal NxN submatrix is processed and
12379 : overwritten. other elements are unchanged.
12380 : * if not given, automatically determined from matrix size
12381 : (A must be square matrix)
12382 :
12383 : Result: matrix determinant.
12384 :
12385 : -- ALGLIB --
12386 : Copyright 2005 by Bochkanov Sergey
12387 : *************************************************************************/
12388 0 : alglib::complex cmatrixludet(const complex_2d_array &a, const integer_1d_array &pivots, const ae_int_t n, const xparams _xparams)
12389 : {
12390 : jmp_buf _break_jump;
12391 : alglib_impl::ae_state _alglib_env_state;
12392 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12393 0 : if( setjmp(_break_jump) )
12394 : {
12395 : #if !defined(AE_NO_EXCEPTIONS)
12396 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12397 : #else
12398 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12399 : return 0;
12400 : #endif
12401 : }
12402 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12403 0 : if( _xparams.flags!=0x0 )
12404 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12405 0 : alglib_impl::ae_complex result = alglib_impl::cmatrixludet(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(pivots.c_ptr()), n, &_alglib_env_state);
12406 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12407 0 : return *(reinterpret_cast<alglib::complex*>(&result));
12408 : }
12409 :
12410 : /*************************************************************************
12411 : Determinant calculation of the matrix given by its LU decomposition.
12412 :
12413 : Input parameters:
12414 : A - LU decomposition of the matrix (output of
12415 : RMatrixLU subroutine).
12416 : Pivots - table of permutations which were made during
12417 : the LU decomposition.
12418 : Output of RMatrixLU subroutine.
12419 : N - (optional) size of matrix A:
12420 : * if given, only principal NxN submatrix is processed and
12421 : overwritten. other elements are unchanged.
12422 : * if not given, automatically determined from matrix size
12423 : (A must be square matrix)
12424 :
12425 : Result: matrix determinant.
12426 :
12427 : -- ALGLIB --
12428 : Copyright 2005 by Bochkanov Sergey
12429 : *************************************************************************/
12430 : #if !defined(AE_NO_EXCEPTIONS)
12431 0 : alglib::complex cmatrixludet(const complex_2d_array &a, const integer_1d_array &pivots, const xparams _xparams)
12432 : {
12433 : jmp_buf _break_jump;
12434 : alglib_impl::ae_state _alglib_env_state;
12435 : ae_int_t n;
12436 0 : if( (a.rows()!=a.cols()) || (a.rows()!=pivots.length()))
12437 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'cmatrixludet': looks like one of arguments has wrong size");
12438 0 : n = a.rows();
12439 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12440 0 : if( setjmp(_break_jump) )
12441 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12442 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12443 0 : if( _xparams.flags!=0x0 )
12444 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12445 0 : alglib_impl::ae_complex result = alglib_impl::cmatrixludet(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_vector*>(pivots.c_ptr()), n, &_alglib_env_state);
12446 :
12447 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12448 0 : return *(reinterpret_cast<alglib::complex*>(&result));
12449 : }
12450 : #endif
12451 :
12452 : /*************************************************************************
12453 : Calculation of the determinant of a general matrix
12454 :
12455 : Input parameters:
12456 : A - matrix, array[0..N-1, 0..N-1]
12457 : N - (optional) size of matrix A:
12458 : * if given, only principal NxN submatrix is processed and
12459 : overwritten. other elements are unchanged.
12460 : * if not given, automatically determined from matrix size
12461 : (A must be square matrix)
12462 :
12463 : Result: determinant of matrix A.
12464 :
12465 : -- ALGLIB --
12466 : Copyright 2005 by Bochkanov Sergey
12467 : *************************************************************************/
12468 0 : alglib::complex cmatrixdet(const complex_2d_array &a, const ae_int_t n, const xparams _xparams)
12469 : {
12470 : jmp_buf _break_jump;
12471 : alglib_impl::ae_state _alglib_env_state;
12472 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12473 0 : if( setjmp(_break_jump) )
12474 : {
12475 : #if !defined(AE_NO_EXCEPTIONS)
12476 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12477 : #else
12478 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12479 : return 0;
12480 : #endif
12481 : }
12482 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12483 0 : if( _xparams.flags!=0x0 )
12484 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12485 0 : alglib_impl::ae_complex result = alglib_impl::cmatrixdet(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &_alglib_env_state);
12486 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12487 0 : return *(reinterpret_cast<alglib::complex*>(&result));
12488 : }
12489 :
12490 : /*************************************************************************
12491 : Calculation of the determinant of a general matrix
12492 :
12493 : Input parameters:
12494 : A - matrix, array[0..N-1, 0..N-1]
12495 : N - (optional) size of matrix A:
12496 : * if given, only principal NxN submatrix is processed and
12497 : overwritten. other elements are unchanged.
12498 : * if not given, automatically determined from matrix size
12499 : (A must be square matrix)
12500 :
12501 : Result: determinant of matrix A.
12502 :
12503 : -- ALGLIB --
12504 : Copyright 2005 by Bochkanov Sergey
12505 : *************************************************************************/
12506 : #if !defined(AE_NO_EXCEPTIONS)
12507 0 : alglib::complex cmatrixdet(const complex_2d_array &a, const xparams _xparams)
12508 : {
12509 : jmp_buf _break_jump;
12510 : alglib_impl::ae_state _alglib_env_state;
12511 : ae_int_t n;
12512 0 : if( (a.rows()!=a.cols()))
12513 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'cmatrixdet': looks like one of arguments has wrong size");
12514 0 : n = a.rows();
12515 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12516 0 : if( setjmp(_break_jump) )
12517 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12518 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12519 0 : if( _xparams.flags!=0x0 )
12520 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12521 0 : alglib_impl::ae_complex result = alglib_impl::cmatrixdet(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &_alglib_env_state);
12522 :
12523 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12524 0 : return *(reinterpret_cast<alglib::complex*>(&result));
12525 : }
12526 : #endif
12527 :
12528 : /*************************************************************************
12529 : Determinant calculation of the matrix given by the Cholesky decomposition.
12530 :
12531 : Input parameters:
12532 : A - Cholesky decomposition,
12533 : output of SMatrixCholesky subroutine.
12534 : N - (optional) size of matrix A:
12535 : * if given, only principal NxN submatrix is processed and
12536 : overwritten. other elements are unchanged.
12537 : * if not given, automatically determined from matrix size
12538 : (A must be square matrix)
12539 :
12540 : As the determinant is equal to the product of squares of diagonal elements,
12541 : it's not necessary to specify which triangle - lower or upper - the matrix
12542 : is stored in.
12543 :
12544 : Result:
12545 : matrix determinant.
12546 :
12547 : -- ALGLIB --
12548 : Copyright 2005-2008 by Bochkanov Sergey
12549 : *************************************************************************/
12550 0 : double spdmatrixcholeskydet(const real_2d_array &a, const ae_int_t n, const xparams _xparams)
12551 : {
12552 : jmp_buf _break_jump;
12553 : alglib_impl::ae_state _alglib_env_state;
12554 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12555 0 : if( setjmp(_break_jump) )
12556 : {
12557 : #if !defined(AE_NO_EXCEPTIONS)
12558 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12559 : #else
12560 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12561 : return 0;
12562 : #endif
12563 : }
12564 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12565 0 : if( _xparams.flags!=0x0 )
12566 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12567 0 : double result = alglib_impl::spdmatrixcholeskydet(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &_alglib_env_state);
12568 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12569 0 : return *(reinterpret_cast<double*>(&result));
12570 : }
12571 :
12572 : /*************************************************************************
12573 : Determinant calculation of the matrix given by the Cholesky decomposition.
12574 :
12575 : Input parameters:
12576 : A - Cholesky decomposition,
12577 : output of SMatrixCholesky subroutine.
12578 : N - (optional) size of matrix A:
12579 : * if given, only principal NxN submatrix is processed and
12580 : overwritten. other elements are unchanged.
12581 : * if not given, automatically determined from matrix size
12582 : (A must be square matrix)
12583 :
12584 : As the determinant is equal to the product of squares of diagonal elements,
12585 : it's not necessary to specify which triangle - lower or upper - the matrix
12586 : is stored in.
12587 :
12588 : Result:
12589 : matrix determinant.
12590 :
12591 : -- ALGLIB --
12592 : Copyright 2005-2008 by Bochkanov Sergey
12593 : *************************************************************************/
12594 : #if !defined(AE_NO_EXCEPTIONS)
12595 0 : double spdmatrixcholeskydet(const real_2d_array &a, const xparams _xparams)
12596 : {
12597 : jmp_buf _break_jump;
12598 : alglib_impl::ae_state _alglib_env_state;
12599 : ae_int_t n;
12600 0 : if( (a.rows()!=a.cols()))
12601 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spdmatrixcholeskydet': looks like one of arguments has wrong size");
12602 0 : n = a.rows();
12603 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12604 0 : if( setjmp(_break_jump) )
12605 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12606 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12607 0 : if( _xparams.flags!=0x0 )
12608 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12609 0 : double result = alglib_impl::spdmatrixcholeskydet(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, &_alglib_env_state);
12610 :
12611 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12612 0 : return *(reinterpret_cast<double*>(&result));
12613 : }
12614 : #endif
12615 :
12616 : /*************************************************************************
12617 : Determinant calculation of the symmetric positive definite matrix.
12618 :
12619 : Input parameters:
12620 : A - matrix. Array with elements [0..N-1, 0..N-1].
12621 : N - (optional) size of matrix A:
12622 : * if given, only principal NxN submatrix is processed and
12623 : overwritten. other elements are unchanged.
12624 : * if not given, automatically determined from matrix size
12625 : (A must be square matrix)
12626 : IsUpper - (optional) storage type:
12627 : * if True, symmetric matrix A is given by its upper
12628 : triangle, and the lower triangle isn't used/changed by
12629 : function
12630 : * if False, symmetric matrix A is given by its lower
12631 : triangle, and the upper triangle isn't used/changed by
12632 : function
12633 : * if not given, both lower and upper triangles must be
12634 : filled.
12635 :
12636 : Result:
12637 : determinant of matrix A.
12638 : If matrix A is not positive definite, exception is thrown.
12639 :
12640 : -- ALGLIB --
12641 : Copyright 2005-2008 by Bochkanov Sergey
12642 : *************************************************************************/
12643 0 : double spdmatrixdet(const real_2d_array &a, const ae_int_t n, const bool isupper, const xparams _xparams)
12644 : {
12645 : jmp_buf _break_jump;
12646 : alglib_impl::ae_state _alglib_env_state;
12647 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12648 0 : if( setjmp(_break_jump) )
12649 : {
12650 : #if !defined(AE_NO_EXCEPTIONS)
12651 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12652 : #else
12653 : _ALGLIB_SET_ERROR_FLAG(_alglib_env_state.error_msg);
12654 : return 0;
12655 : #endif
12656 : }
12657 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12658 0 : if( _xparams.flags!=0x0 )
12659 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12660 0 : double result = alglib_impl::spdmatrixdet(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &_alglib_env_state);
12661 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12662 0 : return *(reinterpret_cast<double*>(&result));
12663 : }
12664 :
12665 : /*************************************************************************
12666 : Determinant calculation of the symmetric positive definite matrix.
12667 :
12668 : Input parameters:
12669 : A - matrix. Array with elements [0..N-1, 0..N-1].
12670 : N - (optional) size of matrix A:
12671 : * if given, only principal NxN submatrix is processed and
12672 : overwritten. other elements are unchanged.
12673 : * if not given, automatically determined from matrix size
12674 : (A must be square matrix)
12675 : IsUpper - (optional) storage type:
12676 : * if True, symmetric matrix A is given by its upper
12677 : triangle, and the lower triangle isn't used/changed by
12678 : function
12679 : * if False, symmetric matrix A is given by its lower
12680 : triangle, and the upper triangle isn't used/changed by
12681 : function
12682 : * if not given, both lower and upper triangles must be
12683 : filled.
12684 :
12685 : Result:
12686 : determinant of matrix A.
12687 : If matrix A is not positive definite, exception is thrown.
12688 :
12689 : -- ALGLIB --
12690 : Copyright 2005-2008 by Bochkanov Sergey
12691 : *************************************************************************/
12692 : #if !defined(AE_NO_EXCEPTIONS)
12693 0 : double spdmatrixdet(const real_2d_array &a, const xparams _xparams)
12694 : {
12695 : jmp_buf _break_jump;
12696 : alglib_impl::ae_state _alglib_env_state;
12697 : ae_int_t n;
12698 : bool isupper;
12699 0 : if( (a.rows()!=a.cols()))
12700 0 : _ALGLIB_CPP_EXCEPTION("Error while calling 'spdmatrixdet': looks like one of arguments has wrong size");
12701 0 : if( !alglib_impl::ae_is_symmetric(const_cast<alglib_impl::ae_matrix*>(a.c_ptr())) )
12702 0 : _ALGLIB_CPP_EXCEPTION("'a' parameter is not symmetric matrix");
12703 0 : n = a.rows();
12704 0 : isupper = false;
12705 0 : alglib_impl::ae_state_init(&_alglib_env_state);
12706 0 : if( setjmp(_break_jump) )
12707 0 : _ALGLIB_CPP_EXCEPTION(_alglib_env_state.error_msg);
12708 0 : ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
12709 0 : if( _xparams.flags!=0x0 )
12710 0 : ae_state_set_flags(&_alglib_env_state, _xparams.flags);
12711 0 : double result = alglib_impl::spdmatrixdet(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, &_alglib_env_state);
12712 :
12713 0 : alglib_impl::ae_state_clear(&_alglib_env_state);
12714 0 : return *(reinterpret_cast<double*>(&result));
12715 : }
12716 : #endif
12717 : #endif
12718 : }
12719 :
12720 : /////////////////////////////////////////////////////////////////////////
12721 : //
12722 : // THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE
12723 : //
12724 : /////////////////////////////////////////////////////////////////////////
12725 : namespace alglib_impl
12726 : {
12727 : #if defined(AE_COMPILE_SPARSE) || !defined(AE_PARTIAL_BUILD)
12728 : static double sparse_desiredloadfactor = 0.66;
12729 : static double sparse_maxloadfactor = 0.75;
12730 : static double sparse_growfactor = 2.00;
12731 : static ae_int_t sparse_additional = 10;
12732 : static ae_int_t sparse_linalgswitch = 16;
12733 : static ae_int_t sparse_hash(ae_int_t i,
12734 : ae_int_t j,
12735 : ae_int_t tabsize,
12736 : ae_state *_state);
12737 :
12738 :
12739 : #endif
12740 : #if defined(AE_COMPILE_ABLAS) || !defined(AE_PARTIAL_BUILD)
12741 : static ae_int_t ablas_blas2minvendorkernelsize = 8;
12742 : static void ablas_ablasinternalsplitlength(ae_int_t n,
12743 : ae_int_t nb,
12744 : ae_int_t* n1,
12745 : ae_int_t* n2,
12746 : ae_state *_state);
12747 : static void ablas_cmatrixrighttrsm2(ae_int_t m,
12748 : ae_int_t n,
12749 : /* Complex */ ae_matrix* a,
12750 : ae_int_t i1,
12751 : ae_int_t j1,
12752 : ae_bool isupper,
12753 : ae_bool isunit,
12754 : ae_int_t optype,
12755 : /* Complex */ ae_matrix* x,
12756 : ae_int_t i2,
12757 : ae_int_t j2,
12758 : ae_state *_state);
12759 : static void ablas_cmatrixlefttrsm2(ae_int_t m,
12760 : ae_int_t n,
12761 : /* Complex */ ae_matrix* a,
12762 : ae_int_t i1,
12763 : ae_int_t j1,
12764 : ae_bool isupper,
12765 : ae_bool isunit,
12766 : ae_int_t optype,
12767 : /* Complex */ ae_matrix* x,
12768 : ae_int_t i2,
12769 : ae_int_t j2,
12770 : ae_state *_state);
12771 : static void ablas_rmatrixrighttrsm2(ae_int_t m,
12772 : ae_int_t n,
12773 : /* Real */ ae_matrix* a,
12774 : ae_int_t i1,
12775 : ae_int_t j1,
12776 : ae_bool isupper,
12777 : ae_bool isunit,
12778 : ae_int_t optype,
12779 : /* Real */ ae_matrix* x,
12780 : ae_int_t i2,
12781 : ae_int_t j2,
12782 : ae_state *_state);
12783 : static void ablas_rmatrixlefttrsm2(ae_int_t m,
12784 : ae_int_t n,
12785 : /* Real */ ae_matrix* a,
12786 : ae_int_t i1,
12787 : ae_int_t j1,
12788 : ae_bool isupper,
12789 : ae_bool isunit,
12790 : ae_int_t optype,
12791 : /* Real */ ae_matrix* x,
12792 : ae_int_t i2,
12793 : ae_int_t j2,
12794 : ae_state *_state);
12795 : static void ablas_cmatrixherk2(ae_int_t n,
12796 : ae_int_t k,
12797 : double alpha,
12798 : /* Complex */ ae_matrix* a,
12799 : ae_int_t ia,
12800 : ae_int_t ja,
12801 : ae_int_t optypea,
12802 : double beta,
12803 : /* Complex */ ae_matrix* c,
12804 : ae_int_t ic,
12805 : ae_int_t jc,
12806 : ae_bool isupper,
12807 : ae_state *_state);
12808 : static void ablas_rmatrixsyrk2(ae_int_t n,
12809 : ae_int_t k,
12810 : double alpha,
12811 : /* Real */ ae_matrix* a,
12812 : ae_int_t ia,
12813 : ae_int_t ja,
12814 : ae_int_t optypea,
12815 : double beta,
12816 : /* Real */ ae_matrix* c,
12817 : ae_int_t ic,
12818 : ae_int_t jc,
12819 : ae_bool isupper,
12820 : ae_state *_state);
12821 : static void ablas_cmatrixgemmrec(ae_int_t m,
12822 : ae_int_t n,
12823 : ae_int_t k,
12824 : ae_complex alpha,
12825 : /* Complex */ ae_matrix* a,
12826 : ae_int_t ia,
12827 : ae_int_t ja,
12828 : ae_int_t optypea,
12829 : /* Complex */ ae_matrix* b,
12830 : ae_int_t ib,
12831 : ae_int_t jb,
12832 : ae_int_t optypeb,
12833 : ae_complex beta,
12834 : /* Complex */ ae_matrix* c,
12835 : ae_int_t ic,
12836 : ae_int_t jc,
12837 : ae_state *_state);
12838 : ae_bool _trypexec_ablas_cmatrixgemmrec(ae_int_t m,
12839 : ae_int_t n,
12840 : ae_int_t k,
12841 : ae_complex alpha,
12842 : /* Complex */ ae_matrix* a,
12843 : ae_int_t ia,
12844 : ae_int_t ja,
12845 : ae_int_t optypea,
12846 : /* Complex */ ae_matrix* b,
12847 : ae_int_t ib,
12848 : ae_int_t jb,
12849 : ae_int_t optypeb,
12850 : ae_complex beta,
12851 : /* Complex */ ae_matrix* c,
12852 : ae_int_t ic,
12853 : ae_int_t jc, ae_state *_state);
12854 : static void ablas_rmatrixgemmrec(ae_int_t m,
12855 : ae_int_t n,
12856 : ae_int_t k,
12857 : double alpha,
12858 : /* Real */ ae_matrix* a,
12859 : ae_int_t ia,
12860 : ae_int_t ja,
12861 : ae_int_t optypea,
12862 : /* Real */ ae_matrix* b,
12863 : ae_int_t ib,
12864 : ae_int_t jb,
12865 : ae_int_t optypeb,
12866 : double beta,
12867 : /* Real */ ae_matrix* c,
12868 : ae_int_t ic,
12869 : ae_int_t jc,
12870 : ae_state *_state);
12871 : ae_bool _trypexec_ablas_rmatrixgemmrec(ae_int_t m,
12872 : ae_int_t n,
12873 : ae_int_t k,
12874 : double alpha,
12875 : /* Real */ ae_matrix* a,
12876 : ae_int_t ia,
12877 : ae_int_t ja,
12878 : ae_int_t optypea,
12879 : /* Real */ ae_matrix* b,
12880 : ae_int_t ib,
12881 : ae_int_t jb,
12882 : ae_int_t optypeb,
12883 : double beta,
12884 : /* Real */ ae_matrix* c,
12885 : ae_int_t ic,
12886 : ae_int_t jc, ae_state *_state);
12887 :
12888 :
12889 : #endif
12890 : #if defined(AE_COMPILE_DLU) || !defined(AE_PARTIAL_BUILD)
12891 : static void dlu_cmatrixlup2(/* Complex */ ae_matrix* a,
12892 : ae_int_t offs,
12893 : ae_int_t m,
12894 : ae_int_t n,
12895 : /* Integer */ ae_vector* pivots,
12896 : /* Complex */ ae_vector* tmp,
12897 : ae_state *_state);
12898 : static void dlu_rmatrixlup2(/* Real */ ae_matrix* a,
12899 : ae_int_t offs,
12900 : ae_int_t m,
12901 : ae_int_t n,
12902 : /* Integer */ ae_vector* pivots,
12903 : /* Real */ ae_vector* tmp,
12904 : ae_state *_state);
12905 : static void dlu_cmatrixplu2(/* Complex */ ae_matrix* a,
12906 : ae_int_t offs,
12907 : ae_int_t m,
12908 : ae_int_t n,
12909 : /* Integer */ ae_vector* pivots,
12910 : /* Complex */ ae_vector* tmp,
12911 : ae_state *_state);
12912 : static void dlu_rmatrixplu2(/* Real */ ae_matrix* a,
12913 : ae_int_t offs,
12914 : ae_int_t m,
12915 : ae_int_t n,
12916 : /* Integer */ ae_vector* pivots,
12917 : /* Real */ ae_vector* tmp,
12918 : ae_state *_state);
12919 :
12920 :
12921 : #endif
12922 : #if defined(AE_COMPILE_SPTRF) || !defined(AE_PARTIAL_BUILD)
12923 : static double sptrf_densebnd = 0.10;
12924 : static ae_int_t sptrf_slswidth = 8;
12925 : static void sptrf_sluv2list1init(ae_int_t n,
12926 : sluv2list1matrix* a,
12927 : ae_state *_state);
12928 : static void sptrf_sluv2list1swap(sluv2list1matrix* a,
12929 : ae_int_t i,
12930 : ae_int_t j,
12931 : ae_state *_state);
12932 : static void sptrf_sluv2list1dropsequence(sluv2list1matrix* a,
12933 : ae_int_t i,
12934 : ae_state *_state);
12935 : static void sptrf_sluv2list1appendsequencetomatrix(sluv2list1matrix* a,
12936 : ae_int_t src,
12937 : ae_bool hasdiagonal,
12938 : double d,
12939 : ae_int_t nzmax,
12940 : sparsematrix* s,
12941 : ae_int_t dst,
12942 : ae_state *_state);
12943 : static void sptrf_sluv2list1pushsparsevector(sluv2list1matrix* a,
12944 : /* Integer */ ae_vector* si,
12945 : /* Real */ ae_vector* sv,
12946 : ae_int_t nz,
12947 : ae_state *_state);
12948 : static void sptrf_densetrailinit(sluv2densetrail* d,
12949 : ae_int_t n,
12950 : ae_state *_state);
12951 : static void sptrf_densetrailappendcolumn(sluv2densetrail* d,
12952 : /* Real */ ae_vector* x,
12953 : ae_int_t id,
12954 : ae_state *_state);
12955 : static void sptrf_sparsetrailinit(sparsematrix* s,
12956 : sluv2sparsetrail* a,
12957 : ae_state *_state);
12958 : static ae_bool sptrf_sparsetrailfindpivot(sluv2sparsetrail* a,
12959 : ae_int_t pivottype,
12960 : ae_int_t* ipiv,
12961 : ae_int_t* jpiv,
12962 : ae_state *_state);
12963 : static void sptrf_sparsetrailpivotout(sluv2sparsetrail* a,
12964 : ae_int_t ipiv,
12965 : ae_int_t jpiv,
12966 : double* uu,
12967 : /* Integer */ ae_vector* v0i,
12968 : /* Real */ ae_vector* v0r,
12969 : ae_int_t* nz0,
12970 : /* Integer */ ae_vector* v1i,
12971 : /* Real */ ae_vector* v1r,
12972 : ae_int_t* nz1,
12973 : ae_state *_state);
12974 : static void sptrf_sparsetraildensify(sluv2sparsetrail* a,
12975 : ae_int_t i1,
12976 : sluv2list1matrix* bupper,
12977 : sluv2densetrail* dtrail,
12978 : ae_state *_state);
12979 : static void sptrf_sparsetrailupdate(sluv2sparsetrail* a,
12980 : /* Integer */ ae_vector* v0i,
12981 : /* Real */ ae_vector* v0r,
12982 : ae_int_t nz0,
12983 : /* Integer */ ae_vector* v1i,
12984 : /* Real */ ae_vector* v1r,
12985 : ae_int_t nz1,
12986 : sluv2list1matrix* bupper,
12987 : sluv2densetrail* dtrail,
12988 : ae_bool densificationsupported,
12989 : ae_state *_state);
12990 :
12991 :
12992 : #endif
12993 : #if defined(AE_COMPILE_AMDORDERING) || !defined(AE_PARTIAL_BUILD)
12994 : static ae_int_t amdordering_knsheadersize = 2;
12995 : static ae_int_t amdordering_llmentrysize = 6;
12996 : static void amdordering_nsinitemptyslow(ae_int_t n,
12997 : amdnset* sa,
12998 : ae_state *_state);
12999 : static void amdordering_nscopy(amdnset* ssrc,
13000 : amdnset* sdst,
13001 : ae_state *_state);
13002 : static void amdordering_nsaddelement(amdnset* sa,
13003 : ae_int_t k,
13004 : ae_state *_state);
13005 : static void amdordering_nsaddkth(amdnset* sa,
13006 : amdknset* src,
13007 : ae_int_t k,
13008 : ae_state *_state);
13009 : static void amdordering_nssubtractkth(amdnset* sa,
13010 : amdknset* src,
13011 : ae_int_t k,
13012 : ae_state *_state);
13013 : static void amdordering_nsclear(amdnset* sa, ae_state *_state);
13014 : static ae_int_t amdordering_nscount(amdnset* sa, ae_state *_state);
13015 : static ae_int_t amdordering_nscountnotkth(amdnset* sa,
13016 : amdknset* src,
13017 : ae_int_t k,
13018 : ae_state *_state);
13019 : static ae_int_t amdordering_nscountandkth(amdnset* sa,
13020 : amdknset* src,
13021 : ae_int_t k,
13022 : ae_state *_state);
13023 : static ae_bool amdordering_nsequal(amdnset* s0,
13024 : amdnset* s1,
13025 : ae_state *_state);
13026 : static void amdordering_nsstartenumeration(amdnset* sa, ae_state *_state);
13027 : static ae_bool amdordering_nsenumerate(amdnset* sa,
13028 : ae_int_t* i,
13029 : ae_state *_state);
13030 : static void amdordering_knscompressstorage(amdknset* sa, ae_state *_state);
13031 : static void amdordering_knsreallocate(amdknset* sa,
13032 : ae_int_t setidx,
13033 : ae_int_t newallocated,
13034 : ae_state *_state);
13035 : static void amdordering_knsinit(ae_int_t k,
13036 : ae_int_t n,
13037 : ae_int_t kprealloc,
13038 : amdknset* sa,
13039 : ae_state *_state);
13040 : static void amdordering_knsinitfroma(sparsematrix* a,
13041 : ae_int_t n,
13042 : amdknset* sa,
13043 : ae_state *_state);
13044 : static void amdordering_knsstartenumeration(amdknset* sa,
13045 : ae_int_t i,
13046 : ae_state *_state);
13047 : static ae_bool amdordering_knsenumerate(amdknset* sa,
13048 : ae_int_t* i,
13049 : ae_state *_state);
13050 : static void amdordering_knsdirectaccess(amdknset* sa,
13051 : ae_int_t k,
13052 : ae_int_t* idxbegin,
13053 : ae_int_t* idxend,
13054 : ae_state *_state);
13055 : static void amdordering_knsaddnewelement(amdknset* sa,
13056 : ae_int_t i,
13057 : ae_int_t k,
13058 : ae_state *_state);
13059 : static void amdordering_knssubtract1(amdknset* sa,
13060 : ae_int_t i,
13061 : amdnset* src,
13062 : ae_state *_state);
13063 : static void amdordering_knsaddkthdistinct(amdknset* sa,
13064 : ae_int_t i,
13065 : amdknset* src,
13066 : ae_int_t k,
13067 : ae_state *_state);
13068 : static ae_int_t amdordering_knscountkth(amdknset* s0,
13069 : ae_int_t k,
13070 : ae_state *_state);
13071 : static ae_int_t amdordering_knscountnotkth(amdknset* s0,
13072 : ae_int_t i,
13073 : amdknset* s1,
13074 : ae_int_t k,
13075 : ae_state *_state);
13076 : static ae_int_t amdordering_knscountandkth(amdknset* s0,
13077 : ae_int_t i,
13078 : amdknset* s1,
13079 : ae_int_t k,
13080 : ae_state *_state);
13081 : static ae_int_t amdordering_knssumkth(amdknset* s0,
13082 : ae_int_t i,
13083 : ae_state *_state);
13084 : static void amdordering_knsclearkthnoreclaim(amdknset* sa,
13085 : ae_int_t k,
13086 : ae_state *_state);
13087 : static void amdordering_knsclearkthreclaim(amdknset* sa,
13088 : ae_int_t k,
13089 : ae_state *_state);
13090 : static void amdordering_mtxinit(ae_int_t n,
13091 : amdllmatrix* a,
13092 : ae_state *_state);
13093 : static void amdordering_mtxaddcolumnto(amdllmatrix* a,
13094 : ae_int_t j,
13095 : amdnset* s,
13096 : ae_state *_state);
13097 : static void amdordering_mtxinsertnewelement(amdllmatrix* a,
13098 : ae_int_t i,
13099 : ae_int_t j,
13100 : ae_state *_state);
13101 : static ae_int_t amdordering_mtxcountcolumn(amdllmatrix* a,
13102 : ae_int_t j,
13103 : ae_state *_state);
13104 : static void amdordering_mtxclearx(amdllmatrix* a,
13105 : ae_int_t k,
13106 : ae_bool iscol,
13107 : ae_state *_state);
13108 : static void amdordering_mtxclearcolumn(amdllmatrix* a,
13109 : ae_int_t j,
13110 : ae_state *_state);
13111 : static void amdordering_mtxclearrow(amdllmatrix* a,
13112 : ae_int_t j,
13113 : ae_state *_state);
13114 : static void amdordering_vtxinit(sparsematrix* a,
13115 : ae_int_t n,
13116 : ae_bool checkexactdegrees,
13117 : amdvertexset* s,
13118 : ae_state *_state);
13119 : static void amdordering_vtxremovevertex(amdvertexset* s,
13120 : ae_int_t p,
13121 : ae_state *_state);
13122 : static ae_int_t amdordering_vtxgetapprox(amdvertexset* s,
13123 : ae_int_t p,
13124 : ae_state *_state);
13125 : static ae_int_t amdordering_vtxgetexact(amdvertexset* s,
13126 : ae_int_t p,
13127 : ae_state *_state);
13128 : static ae_int_t amdordering_vtxgetapproxmindegree(amdvertexset* s,
13129 : ae_state *_state);
13130 : static void amdordering_vtxupdateapproximatedegree(amdvertexset* s,
13131 : ae_int_t p,
13132 : ae_int_t dnew,
13133 : ae_state *_state);
13134 : static void amdordering_vtxupdateexactdegree(amdvertexset* s,
13135 : ae_int_t p,
13136 : ae_int_t d,
13137 : ae_state *_state);
13138 : static void amdordering_amdselectpivotelement(amdbuffer* buf,
13139 : ae_int_t k,
13140 : ae_int_t* p,
13141 : ae_int_t* nodesize,
13142 : ae_state *_state);
13143 : static void amdordering_amdcomputelp(amdbuffer* buf,
13144 : ae_int_t p,
13145 : ae_state *_state);
13146 : static void amdordering_amdmasselimination(amdbuffer* buf,
13147 : ae_int_t p,
13148 : ae_int_t k,
13149 : ae_state *_state);
13150 : static void amdordering_amddetectsupernodes(amdbuffer* buf,
13151 : ae_state *_state);
13152 :
13153 :
13154 : #endif
13155 : #if defined(AE_COMPILE_SPCHOL) || !defined(AE_PARTIAL_BUILD)
13156 : static ae_int_t spchol_maxsupernode = 4;
13157 : static double spchol_maxmergeinefficiency = 0.25;
13158 : static ae_int_t spchol_smallfakestolerance = 2;
13159 : static ae_int_t spchol_maxfastkernel = 4;
13160 : static ae_bool spchol_relaxedsupernodes = ae_true;
13161 : static void spchol_generatedbgpermutation(sparsematrix* a,
13162 : ae_int_t n,
13163 : /* Integer */ ae_vector* perm,
13164 : /* Integer */ ae_vector* invperm,
13165 : ae_state *_state);
13166 : static void spchol_buildetree(sparsematrix* a,
13167 : ae_int_t n,
13168 : /* Integer */ ae_vector* parent,
13169 : /* Integer */ ae_vector* supernodalpermutation,
13170 : /* Integer */ ae_vector* invsupernodalpermutation,
13171 : /* Integer */ ae_vector* trawparentofrawnode,
13172 : /* Integer */ ae_vector* trawparentofreorderednode,
13173 : /* Integer */ ae_vector* ttmp,
13174 : /* Boolean */ ae_vector* tflagarray,
13175 : ae_state *_state);
13176 : static void spchol_createsupernodalstructure(sparsematrix* at,
13177 : /* Integer */ ae_vector* parent,
13178 : ae_int_t n,
13179 : spcholanalysis* analysis,
13180 : /* Integer */ ae_vector* node2supernode,
13181 : /* Integer */ ae_vector* tchildrenr,
13182 : /* Integer */ ae_vector* tchildreni,
13183 : /* Integer */ ae_vector* tparentnodeofsupernode,
13184 : /* Integer */ ae_vector* tfakenonzeros,
13185 : /* Integer */ ae_vector* ttmp0,
13186 : /* Boolean */ ae_vector* tflagarray,
13187 : ae_state *_state);
13188 : static void spchol_analyzesupernodaldependencies(spcholanalysis* analysis,
13189 : sparsematrix* rawa,
13190 : /* Integer */ ae_vector* node2supernode,
13191 : ae_int_t n,
13192 : /* Integer */ ae_vector* ttmp0,
13193 : /* Integer */ ae_vector* ttmp1,
13194 : /* Boolean */ ae_vector* tflagarray,
13195 : ae_state *_state);
13196 : static void spchol_extractmatrix(spcholanalysis* analysis,
13197 : /* Integer */ ae_vector* offsets,
13198 : /* Integer */ ae_vector* strides,
13199 : /* Real */ ae_vector* rowstorage,
13200 : /* Real */ ae_vector* diagd,
13201 : ae_int_t n,
13202 : sparsematrix* a,
13203 : /* Real */ ae_vector* d,
13204 : /* Integer */ ae_vector* p,
13205 : /* Integer */ ae_vector* tmpp,
13206 : ae_state *_state);
13207 : static void spchol_topologicalpermutation(sparsematrix* a,
13208 : /* Integer */ ae_vector* p,
13209 : sparsematrix* b,
13210 : ae_state *_state);
13211 : static ae_int_t spchol_computenonzeropattern(sparsematrix* wrkat,
13212 : ae_int_t columnidx,
13213 : ae_int_t n,
13214 : /* Integer */ ae_vector* superrowridx,
13215 : /* Integer */ ae_vector* superrowidx,
13216 : ae_int_t nsuper,
13217 : /* Integer */ ae_vector* childrennodesr,
13218 : /* Integer */ ae_vector* childrennodesi,
13219 : /* Integer */ ae_vector* node2supernode,
13220 : /* Boolean */ ae_vector* truearray,
13221 : /* Integer */ ae_vector* tmp0,
13222 : ae_state *_state);
13223 : static ae_int_t spchol_updatesupernode(spcholanalysis* analysis,
13224 : ae_int_t sidx,
13225 : ae_int_t cols0,
13226 : ae_int_t cols1,
13227 : ae_int_t offss,
13228 : /* Integer */ ae_vector* raw2smap,
13229 : ae_int_t uidx,
13230 : ae_int_t wrkrow,
13231 : /* Real */ ae_vector* diagd,
13232 : ae_int_t offsd,
13233 : ae_state *_state);
13234 : static ae_bool spchol_factorizesupernode(spcholanalysis* analysis,
13235 : ae_int_t sidx,
13236 : ae_state *_state);
13237 : static ae_int_t spchol_recommendedstridefor(ae_int_t rowsize,
13238 : ae_state *_state);
13239 : static ae_int_t spchol_alignpositioninarray(ae_int_t offs,
13240 : ae_state *_state);
13241 : static ae_bool spchol_updatekernel4444(/* Real */ ae_vector* rowstorage,
13242 : ae_int_t offss,
13243 : ae_int_t offsu,
13244 : ae_int_t uheight,
13245 : /* Real */ ae_vector* diagd,
13246 : ae_int_t offsd,
13247 : /* Integer */ ae_vector* raw2smap,
13248 : /* Integer */ ae_vector* superrowidx,
13249 : ae_int_t urbase,
13250 : ae_state *_state);
13251 : static ae_bool spchol_updatekernelabc4(/* Real */ ae_vector* rowstorage,
13252 : ae_int_t offss,
13253 : ae_int_t twidth,
13254 : ae_int_t offsu,
13255 : ae_int_t uheight,
13256 : ae_int_t urank,
13257 : ae_int_t urowstride,
13258 : ae_int_t uwidth,
13259 : /* Real */ ae_vector* diagd,
13260 : ae_int_t offsd,
13261 : /* Integer */ ae_vector* raw2smap,
13262 : /* Integer */ ae_vector* superrowidx,
13263 : ae_int_t urbase,
13264 : ae_state *_state);
13265 : static ae_bool spchol_updatekernelrank1(/* Real */ ae_vector* rowstorage,
13266 : ae_int_t offss,
13267 : ae_int_t twidth,
13268 : ae_int_t trowstride,
13269 : ae_int_t offsu,
13270 : ae_int_t uheight,
13271 : ae_int_t uwidth,
13272 : /* Real */ ae_vector* diagd,
13273 : ae_int_t offsd,
13274 : /* Integer */ ae_vector* raw2smap,
13275 : /* Integer */ ae_vector* superrowidx,
13276 : ae_int_t urbase,
13277 : ae_state *_state);
13278 : static ae_bool spchol_updatekernelrank2(/* Real */ ae_vector* rowstorage,
13279 : ae_int_t offss,
13280 : ae_int_t twidth,
13281 : ae_int_t trowstride,
13282 : ae_int_t offsu,
13283 : ae_int_t uheight,
13284 : ae_int_t uwidth,
13285 : /* Real */ ae_vector* diagd,
13286 : ae_int_t offsd,
13287 : /* Integer */ ae_vector* raw2smap,
13288 : /* Integer */ ae_vector* superrowidx,
13289 : ae_int_t urbase,
13290 : ae_state *_state);
13291 :
13292 :
13293 : #endif
13294 : #if defined(AE_COMPILE_MATGEN) || !defined(AE_PARTIAL_BUILD)
13295 :
13296 :
13297 : #endif
13298 : #if defined(AE_COMPILE_TRFAC) || !defined(AE_PARTIAL_BUILD)
13299 : static ae_bool trfac_hpdmatrixcholeskyrec(/* Complex */ ae_matrix* a,
13300 : ae_int_t offs,
13301 : ae_int_t n,
13302 : ae_bool isupper,
13303 : /* Complex */ ae_vector* tmp,
13304 : ae_state *_state);
13305 : static ae_bool trfac_hpdmatrixcholesky2(/* Complex */ ae_matrix* aaa,
13306 : ae_int_t offs,
13307 : ae_int_t n,
13308 : ae_bool isupper,
13309 : /* Complex */ ae_vector* tmp,
13310 : ae_state *_state);
13311 : static ae_bool trfac_spdmatrixcholesky2(/* Real */ ae_matrix* aaa,
13312 : ae_int_t offs,
13313 : ae_int_t n,
13314 : ae_bool isupper,
13315 : /* Real */ ae_vector* tmp,
13316 : ae_state *_state);
13317 :
13318 :
13319 : #endif
13320 : #if defined(AE_COMPILE_RCOND) || !defined(AE_PARTIAL_BUILD)
13321 : static void rcond_rmatrixrcondtrinternal(/* Real */ ae_matrix* a,
13322 : ae_int_t n,
13323 : ae_bool isupper,
13324 : ae_bool isunit,
13325 : ae_bool onenorm,
13326 : double anorm,
13327 : double* rc,
13328 : ae_state *_state);
13329 : static void rcond_cmatrixrcondtrinternal(/* Complex */ ae_matrix* a,
13330 : ae_int_t n,
13331 : ae_bool isupper,
13332 : ae_bool isunit,
13333 : ae_bool onenorm,
13334 : double anorm,
13335 : double* rc,
13336 : ae_state *_state);
13337 : static void rcond_spdmatrixrcondcholeskyinternal(/* Real */ ae_matrix* cha,
13338 : ae_int_t n,
13339 : ae_bool isupper,
13340 : ae_bool isnormprovided,
13341 : double anorm,
13342 : double* rc,
13343 : ae_state *_state);
13344 : static void rcond_hpdmatrixrcondcholeskyinternal(/* Complex */ ae_matrix* cha,
13345 : ae_int_t n,
13346 : ae_bool isupper,
13347 : ae_bool isnormprovided,
13348 : double anorm,
13349 : double* rc,
13350 : ae_state *_state);
13351 : static void rcond_rmatrixrcondluinternal(/* Real */ ae_matrix* lua,
13352 : ae_int_t n,
13353 : ae_bool onenorm,
13354 : ae_bool isanormprovided,
13355 : double anorm,
13356 : double* rc,
13357 : ae_state *_state);
13358 : static void rcond_cmatrixrcondluinternal(/* Complex */ ae_matrix* lua,
13359 : ae_int_t n,
13360 : ae_bool onenorm,
13361 : ae_bool isanormprovided,
13362 : double anorm,
13363 : double* rc,
13364 : ae_state *_state);
13365 : static void rcond_rmatrixestimatenorm(ae_int_t n,
13366 : /* Real */ ae_vector* v,
13367 : /* Real */ ae_vector* x,
13368 : /* Integer */ ae_vector* isgn,
13369 : double* est,
13370 : ae_int_t* kase,
13371 : ae_state *_state);
13372 : static void rcond_cmatrixestimatenorm(ae_int_t n,
13373 : /* Complex */ ae_vector* v,
13374 : /* Complex */ ae_vector* x,
13375 : double* est,
13376 : ae_int_t* kase,
13377 : /* Integer */ ae_vector* isave,
13378 : /* Real */ ae_vector* rsave,
13379 : ae_state *_state);
13380 : static double rcond_internalcomplexrcondscsum1(/* Complex */ ae_vector* x,
13381 : ae_int_t n,
13382 : ae_state *_state);
13383 : static ae_int_t rcond_internalcomplexrcondicmax1(/* Complex */ ae_vector* x,
13384 : ae_int_t n,
13385 : ae_state *_state);
13386 : static void rcond_internalcomplexrcondsaveall(/* Integer */ ae_vector* isave,
13387 : /* Real */ ae_vector* rsave,
13388 : ae_int_t* i,
13389 : ae_int_t* iter,
13390 : ae_int_t* j,
13391 : ae_int_t* jlast,
13392 : ae_int_t* jump,
13393 : double* absxi,
13394 : double* altsgn,
13395 : double* estold,
13396 : double* temp,
13397 : ae_state *_state);
13398 : static void rcond_internalcomplexrcondloadall(/* Integer */ ae_vector* isave,
13399 : /* Real */ ae_vector* rsave,
13400 : ae_int_t* i,
13401 : ae_int_t* iter,
13402 : ae_int_t* j,
13403 : ae_int_t* jlast,
13404 : ae_int_t* jump,
13405 : double* absxi,
13406 : double* altsgn,
13407 : double* estold,
13408 : double* temp,
13409 : ae_state *_state);
13410 :
13411 :
13412 : #endif
13413 : #if defined(AE_COMPILE_MATINV) || !defined(AE_PARTIAL_BUILD)
13414 : static void matinv_rmatrixtrinverserec(/* Real */ ae_matrix* a,
13415 : ae_int_t offs,
13416 : ae_int_t n,
13417 : ae_bool isupper,
13418 : ae_bool isunit,
13419 : /* Real */ ae_vector* tmp,
13420 : sinteger* info,
13421 : ae_state *_state);
13422 : ae_bool _trypexec_matinv_rmatrixtrinverserec(/* Real */ ae_matrix* a,
13423 : ae_int_t offs,
13424 : ae_int_t n,
13425 : ae_bool isupper,
13426 : ae_bool isunit,
13427 : /* Real */ ae_vector* tmp,
13428 : sinteger* info, ae_state *_state);
13429 : static void matinv_cmatrixtrinverserec(/* Complex */ ae_matrix* a,
13430 : ae_int_t offs,
13431 : ae_int_t n,
13432 : ae_bool isupper,
13433 : ae_bool isunit,
13434 : /* Complex */ ae_vector* tmp,
13435 : sinteger* info,
13436 : ae_state *_state);
13437 : ae_bool _trypexec_matinv_cmatrixtrinverserec(/* Complex */ ae_matrix* a,
13438 : ae_int_t offs,
13439 : ae_int_t n,
13440 : ae_bool isupper,
13441 : ae_bool isunit,
13442 : /* Complex */ ae_vector* tmp,
13443 : sinteger* info, ae_state *_state);
13444 : static void matinv_rmatrixluinverserec(/* Real */ ae_matrix* a,
13445 : ae_int_t offs,
13446 : ae_int_t n,
13447 : /* Real */ ae_vector* work,
13448 : sinteger* info,
13449 : matinvreport* rep,
13450 : ae_state *_state);
13451 : ae_bool _trypexec_matinv_rmatrixluinverserec(/* Real */ ae_matrix* a,
13452 : ae_int_t offs,
13453 : ae_int_t n,
13454 : /* Real */ ae_vector* work,
13455 : sinteger* info,
13456 : matinvreport* rep, ae_state *_state);
13457 : static void matinv_cmatrixluinverserec(/* Complex */ ae_matrix* a,
13458 : ae_int_t offs,
13459 : ae_int_t n,
13460 : /* Complex */ ae_vector* work,
13461 : sinteger* ssinfo,
13462 : matinvreport* rep,
13463 : ae_state *_state);
13464 : ae_bool _trypexec_matinv_cmatrixluinverserec(/* Complex */ ae_matrix* a,
13465 : ae_int_t offs,
13466 : ae_int_t n,
13467 : /* Complex */ ae_vector* work,
13468 : sinteger* ssinfo,
13469 : matinvreport* rep, ae_state *_state);
13470 : static void matinv_hpdmatrixcholeskyinverserec(/* Complex */ ae_matrix* a,
13471 : ae_int_t offs,
13472 : ae_int_t n,
13473 : ae_bool isupper,
13474 : /* Complex */ ae_vector* tmp,
13475 : ae_state *_state);
13476 :
13477 :
13478 : #endif
13479 : #if defined(AE_COMPILE_ORTFAC) || !defined(AE_PARTIAL_BUILD)
13480 : static void ortfac_cmatrixqrbasecase(/* Complex */ ae_matrix* a,
13481 : ae_int_t m,
13482 : ae_int_t n,
13483 : /* Complex */ ae_vector* work,
13484 : /* Complex */ ae_vector* t,
13485 : /* Complex */ ae_vector* tau,
13486 : ae_state *_state);
13487 : static void ortfac_cmatrixlqbasecase(/* Complex */ ae_matrix* a,
13488 : ae_int_t m,
13489 : ae_int_t n,
13490 : /* Complex */ ae_vector* work,
13491 : /* Complex */ ae_vector* t,
13492 : /* Complex */ ae_vector* tau,
13493 : ae_state *_state);
13494 : static void ortfac_rmatrixblockreflector(/* Real */ ae_matrix* a,
13495 : /* Real */ ae_vector* tau,
13496 : ae_bool columnwisea,
13497 : ae_int_t lengtha,
13498 : ae_int_t blocksize,
13499 : /* Real */ ae_matrix* t,
13500 : /* Real */ ae_vector* work,
13501 : ae_state *_state);
13502 : static void ortfac_cmatrixblockreflector(/* Complex */ ae_matrix* a,
13503 : /* Complex */ ae_vector* tau,
13504 : ae_bool columnwisea,
13505 : ae_int_t lengtha,
13506 : ae_int_t blocksize,
13507 : /* Complex */ ae_matrix* t,
13508 : /* Complex */ ae_vector* work,
13509 : ae_state *_state);
13510 :
13511 :
13512 : #endif
13513 : #if defined(AE_COMPILE_FBLS) || !defined(AE_PARTIAL_BUILD)
13514 :
13515 :
13516 : #endif
13517 : #if defined(AE_COMPILE_BDSVD) || !defined(AE_PARTIAL_BUILD)
13518 : static ae_bool bdsvd_bidiagonalsvddecompositioninternal(/* Real */ ae_vector* d,
13519 : /* Real */ ae_vector* e,
13520 : ae_int_t n,
13521 : ae_bool isupper,
13522 : ae_bool isfractionalaccuracyrequired,
13523 : /* Real */ ae_matrix* uu,
13524 : ae_int_t ustart,
13525 : ae_int_t nru,
13526 : /* Real */ ae_matrix* c,
13527 : ae_int_t cstart,
13528 : ae_int_t ncc,
13529 : /* Real */ ae_matrix* vt,
13530 : ae_int_t vstart,
13531 : ae_int_t ncvt,
13532 : ae_state *_state);
13533 : static double bdsvd_extsignbdsqr(double a, double b, ae_state *_state);
13534 : static void bdsvd_svd2x2(double f,
13535 : double g,
13536 : double h,
13537 : double* ssmin,
13538 : double* ssmax,
13539 : ae_state *_state);
13540 : static void bdsvd_svdv2x2(double f,
13541 : double g,
13542 : double h,
13543 : double* ssmin,
13544 : double* ssmax,
13545 : double* snr,
13546 : double* csr,
13547 : double* snl,
13548 : double* csl,
13549 : ae_state *_state);
13550 :
13551 :
13552 : #endif
13553 : #if defined(AE_COMPILE_SVD) || !defined(AE_PARTIAL_BUILD)
13554 :
13555 :
13556 : #endif
13557 : #if defined(AE_COMPILE_NORMESTIMATOR) || !defined(AE_PARTIAL_BUILD)
13558 :
13559 :
13560 : #endif
13561 : #if defined(AE_COMPILE_HSSCHUR) || !defined(AE_PARTIAL_BUILD)
13562 : static void hsschur_internalauxschur(ae_bool wantt,
13563 : ae_bool wantz,
13564 : ae_int_t n,
13565 : ae_int_t ilo,
13566 : ae_int_t ihi,
13567 : /* Real */ ae_matrix* h,
13568 : /* Real */ ae_vector* wr,
13569 : /* Real */ ae_vector* wi,
13570 : ae_int_t iloz,
13571 : ae_int_t ihiz,
13572 : /* Real */ ae_matrix* z,
13573 : /* Real */ ae_vector* work,
13574 : /* Real */ ae_vector* workv3,
13575 : /* Real */ ae_vector* workc1,
13576 : /* Real */ ae_vector* works1,
13577 : ae_int_t* info,
13578 : ae_state *_state);
13579 : static void hsschur_aux2x2schur(double* a,
13580 : double* b,
13581 : double* c,
13582 : double* d,
13583 : double* rt1r,
13584 : double* rt1i,
13585 : double* rt2r,
13586 : double* rt2i,
13587 : double* cs,
13588 : double* sn,
13589 : ae_state *_state);
13590 : static double hsschur_extschursign(double a, double b, ae_state *_state);
13591 : static ae_int_t hsschur_extschursigntoone(double b, ae_state *_state);
13592 :
13593 :
13594 : #endif
13595 : #if defined(AE_COMPILE_EVD) || !defined(AE_PARTIAL_BUILD)
13596 : static ae_int_t evd_stepswithintol = 2;
13597 : static void evd_clearrfields(eigsubspacestate* state, ae_state *_state);
13598 : static ae_bool evd_tridiagonalevd(/* Real */ ae_vector* d,
13599 : /* Real */ ae_vector* e,
13600 : ae_int_t n,
13601 : ae_int_t zneeded,
13602 : /* Real */ ae_matrix* z,
13603 : ae_state *_state);
13604 : static void evd_tdevde2(double a,
13605 : double b,
13606 : double c,
13607 : double* rt1,
13608 : double* rt2,
13609 : ae_state *_state);
13610 : static void evd_tdevdev2(double a,
13611 : double b,
13612 : double c,
13613 : double* rt1,
13614 : double* rt2,
13615 : double* cs1,
13616 : double* sn1,
13617 : ae_state *_state);
13618 : static double evd_tdevdpythag(double a, double b, ae_state *_state);
13619 : static double evd_tdevdextsign(double a, double b, ae_state *_state);
13620 : static ae_bool evd_internalbisectioneigenvalues(/* Real */ ae_vector* d,
13621 : /* Real */ ae_vector* e,
13622 : ae_int_t n,
13623 : ae_int_t irange,
13624 : ae_int_t iorder,
13625 : double vl,
13626 : double vu,
13627 : ae_int_t il,
13628 : ae_int_t iu,
13629 : double abstol,
13630 : /* Real */ ae_vector* w,
13631 : ae_int_t* m,
13632 : ae_int_t* nsplit,
13633 : /* Integer */ ae_vector* iblock,
13634 : /* Integer */ ae_vector* isplit,
13635 : ae_int_t* errorcode,
13636 : ae_state *_state);
13637 : static void evd_internaldstein(ae_int_t n,
13638 : /* Real */ ae_vector* d,
13639 : /* Real */ ae_vector* e,
13640 : ae_int_t m,
13641 : /* Real */ ae_vector* w,
13642 : /* Integer */ ae_vector* iblock,
13643 : /* Integer */ ae_vector* isplit,
13644 : /* Real */ ae_matrix* z,
13645 : /* Integer */ ae_vector* ifail,
13646 : ae_int_t* info,
13647 : ae_state *_state);
13648 : static void evd_tdininternaldlagtf(ae_int_t n,
13649 : /* Real */ ae_vector* a,
13650 : double lambdav,
13651 : /* Real */ ae_vector* b,
13652 : /* Real */ ae_vector* c,
13653 : double tol,
13654 : /* Real */ ae_vector* d,
13655 : /* Integer */ ae_vector* iin,
13656 : ae_int_t* info,
13657 : ae_state *_state);
13658 : static void evd_tdininternaldlagts(ae_int_t n,
13659 : /* Real */ ae_vector* a,
13660 : /* Real */ ae_vector* b,
13661 : /* Real */ ae_vector* c,
13662 : /* Real */ ae_vector* d,
13663 : /* Integer */ ae_vector* iin,
13664 : /* Real */ ae_vector* y,
13665 : double* tol,
13666 : ae_int_t* info,
13667 : ae_state *_state);
13668 : static void evd_internaldlaebz(ae_int_t ijob,
13669 : ae_int_t nitmax,
13670 : ae_int_t n,
13671 : ae_int_t mmax,
13672 : ae_int_t minp,
13673 : double abstol,
13674 : double reltol,
13675 : double pivmin,
13676 : /* Real */ ae_vector* d,
13677 : /* Real */ ae_vector* e,
13678 : /* Real */ ae_vector* e2,
13679 : /* Integer */ ae_vector* nval,
13680 : /* Real */ ae_matrix* ab,
13681 : /* Real */ ae_vector* c,
13682 : ae_int_t* mout,
13683 : /* Integer */ ae_matrix* nab,
13684 : /* Real */ ae_vector* work,
13685 : /* Integer */ ae_vector* iwork,
13686 : ae_int_t* info,
13687 : ae_state *_state);
13688 : static void evd_rmatrixinternaltrevc(/* Real */ ae_matrix* t,
13689 : ae_int_t n,
13690 : ae_int_t side,
13691 : ae_int_t howmny,
13692 : /* Boolean */ ae_vector* vselect,
13693 : /* Real */ ae_matrix* vl,
13694 : /* Real */ ae_matrix* vr,
13695 : ae_int_t* m,
13696 : ae_int_t* info,
13697 : ae_state *_state);
13698 : static void evd_internaltrevc(/* Real */ ae_matrix* t,
13699 : ae_int_t n,
13700 : ae_int_t side,
13701 : ae_int_t howmny,
13702 : /* Boolean */ ae_vector* vselect,
13703 : /* Real */ ae_matrix* vl,
13704 : /* Real */ ae_matrix* vr,
13705 : ae_int_t* m,
13706 : ae_int_t* info,
13707 : ae_state *_state);
13708 : static void evd_internalhsevdlaln2(ae_bool ltrans,
13709 : ae_int_t na,
13710 : ae_int_t nw,
13711 : double smin,
13712 : double ca,
13713 : /* Real */ ae_matrix* a,
13714 : double d1,
13715 : double d2,
13716 : /* Real */ ae_matrix* b,
13717 : double wr,
13718 : double wi,
13719 : /* Boolean */ ae_vector* rswap4,
13720 : /* Boolean */ ae_vector* zswap4,
13721 : /* Integer */ ae_matrix* ipivot44,
13722 : /* Real */ ae_vector* civ4,
13723 : /* Real */ ae_vector* crv4,
13724 : /* Real */ ae_matrix* x,
13725 : double* scl,
13726 : double* xnorm,
13727 : ae_int_t* info,
13728 : ae_state *_state);
13729 : static void evd_internalhsevdladiv(double a,
13730 : double b,
13731 : double c,
13732 : double d,
13733 : double* p,
13734 : double* q,
13735 : ae_state *_state);
13736 :
13737 :
13738 : #endif
13739 : #if defined(AE_COMPILE_SCHUR) || !defined(AE_PARTIAL_BUILD)
13740 :
13741 :
13742 : #endif
13743 : #if defined(AE_COMPILE_SPDGEVD) || !defined(AE_PARTIAL_BUILD)
13744 :
13745 :
13746 : #endif
13747 : #if defined(AE_COMPILE_INVERSEUPDATE) || !defined(AE_PARTIAL_BUILD)
13748 :
13749 :
13750 : #endif
13751 : #if defined(AE_COMPILE_MATDET) || !defined(AE_PARTIAL_BUILD)
13752 :
13753 :
13754 : #endif
13755 :
13756 : #if defined(AE_COMPILE_SPARSE) || !defined(AE_PARTIAL_BUILD)
13757 :
13758 :
13759 : /*************************************************************************
13760 : This function creates sparse matrix in a Hash-Table format.
13761 :
13762 : This function creates Hast-Table matrix, which can be converted to CRS
13763 : format after its initialization is over. Typical usage scenario for a
13764 : sparse matrix is:
13765 : 1. creation in a Hash-Table format
13766 : 2. insertion of the matrix elements
13767 : 3. conversion to the CRS representation
13768 : 4. matrix is passed to some linear algebra algorithm
13769 :
13770 : Some information about different matrix formats can be found below, in
13771 : the "NOTES" section.
13772 :
13773 : INPUT PARAMETERS
13774 : M - number of rows in a matrix, M>=1
13775 : N - number of columns in a matrix, N>=1
13776 : K - K>=0, expected number of non-zero elements in a matrix.
13777 : K can be inexact approximation, can be less than actual
13778 : number of elements (table will grow when needed) or
13779 : even zero).
13780 : It is important to understand that although hash-table
13781 : may grow automatically, it is better to provide good
13782 : estimate of data size.
13783 :
13784 : OUTPUT PARAMETERS
13785 : S - sparse M*N matrix in Hash-Table representation.
13786 : All elements of the matrix are zero.
13787 :
13788 : NOTE 1
13789 :
13790 : Hash-tables use memory inefficiently, and they have to keep some amount
13791 : of the "spare memory" in order to have good performance. Hash table for
13792 : matrix with K non-zero elements will need C*K*(8+2*sizeof(int)) bytes,
13793 : where C is a small constant, about 1.5-2 in magnitude.
13794 :
13795 : CRS storage, from the other side, is more memory-efficient, and needs
13796 : just K*(8+sizeof(int))+M*sizeof(int) bytes, where M is a number of rows
13797 : in a matrix.
13798 :
13799 : When you convert from the Hash-Table to CRS representation, all unneeded
13800 : memory will be freed.
13801 :
13802 : NOTE 2
13803 :
13804 : Comments of SparseMatrix structure outline information about different
13805 : sparse storage formats. We recommend you to read them before starting to
13806 : use ALGLIB sparse matrices.
13807 :
13808 : NOTE 3
13809 :
13810 : This function completely overwrites S with new sparse matrix. Previously
13811 : allocated storage is NOT reused. If you want to reuse already allocated
13812 : memory, call SparseCreateBuf function.
13813 :
13814 : -- ALGLIB PROJECT --
13815 : Copyright 14.10.2011 by Bochkanov Sergey
13816 : *************************************************************************/
13817 0 : void sparsecreate(ae_int_t m,
13818 : ae_int_t n,
13819 : ae_int_t k,
13820 : sparsematrix* s,
13821 : ae_state *_state)
13822 : {
13823 :
13824 0 : _sparsematrix_clear(s);
13825 :
13826 0 : sparsecreatebuf(m, n, k, s, _state);
13827 0 : }
13828 :
13829 :
13830 : /*************************************************************************
13831 : This version of SparseCreate function creates sparse matrix in Hash-Table
13832 : format, reusing previously allocated storage as much as possible. Read
13833 : comments for SparseCreate() for more information.
13834 :
13835 : INPUT PARAMETERS
13836 : M - number of rows in a matrix, M>=1
13837 : N - number of columns in a matrix, N>=1
13838 : K - K>=0, expected number of non-zero elements in a matrix.
13839 : K can be inexact approximation, can be less than actual
13840 : number of elements (table will grow when needed) or
13841 : even zero).
13842 : It is important to understand that although hash-table
13843 : may grow automatically, it is better to provide good
13844 : estimate of data size.
13845 : S - SparseMatrix structure which MAY contain some already
13846 : allocated storage.
13847 :
13848 : OUTPUT PARAMETERS
13849 : S - sparse M*N matrix in Hash-Table representation.
13850 : All elements of the matrix are zero.
13851 : Previously allocated storage is reused, if its size
13852 : is compatible with expected number of non-zeros K.
13853 :
13854 : -- ALGLIB PROJECT --
13855 : Copyright 14.01.2014 by Bochkanov Sergey
13856 : *************************************************************************/
13857 0 : void sparsecreatebuf(ae_int_t m,
13858 : ae_int_t n,
13859 : ae_int_t k,
13860 : sparsematrix* s,
13861 : ae_state *_state)
13862 : {
13863 : ae_int_t i;
13864 :
13865 :
13866 0 : ae_assert(m>0, "SparseCreateBuf: M<=0", _state);
13867 0 : ae_assert(n>0, "SparseCreateBuf: N<=0", _state);
13868 0 : ae_assert(k>=0, "SparseCreateBuf: K<0", _state);
13869 :
13870 : /*
13871 : * Hash-table size is max(existing_size,requested_size)
13872 : *
13873 : * NOTE: it is important to use ALL available memory for hash table
13874 : * because it is impossible to efficiently reallocate table
13875 : * without temporary storage. So, if we want table with up to
13876 : * 1.000.000 elements, we have to create such table from the
13877 : * very beginning. Otherwise, the very idea of memory reuse
13878 : * will be compromised.
13879 : */
13880 0 : s->tablesize = ae_round(k/sparse_desiredloadfactor+sparse_additional, _state);
13881 0 : rvectorsetlengthatleast(&s->vals, s->tablesize, _state);
13882 0 : s->tablesize = s->vals.cnt;
13883 :
13884 : /*
13885 : * Initialize other fields
13886 : */
13887 0 : s->matrixtype = 0;
13888 0 : s->m = m;
13889 0 : s->n = n;
13890 0 : s->nfree = s->tablesize;
13891 0 : ivectorsetlengthatleast(&s->idx, 2*s->tablesize, _state);
13892 0 : for(i=0; i<=s->tablesize-1; i++)
13893 : {
13894 0 : s->idx.ptr.p_int[2*i] = -1;
13895 : }
13896 0 : }
13897 :
13898 :
13899 : /*************************************************************************
13900 : This function creates sparse matrix in a CRS format (expert function for
13901 : situations when you are running out of memory).
13902 :
13903 : This function creates CRS matrix. Typical usage scenario for a CRS matrix
13904 : is:
13905 : 1. creation (you have to tell number of non-zero elements at each row at
13906 : this moment)
13907 : 2. insertion of the matrix elements (row by row, from left to right)
13908 : 3. matrix is passed to some linear algebra algorithm
13909 :
13910 : This function is a memory-efficient alternative to SparseCreate(), but it
13911 : is more complex because it requires you to know in advance how large your
13912 : matrix is. Some information about different matrix formats can be found
13913 : in comments on SparseMatrix structure. We recommend you to read them
13914 : before starting to use ALGLIB sparse matrices..
13915 :
13916 : INPUT PARAMETERS
13917 : M - number of rows in a matrix, M>=1
13918 : N - number of columns in a matrix, N>=1
13919 : NER - number of elements at each row, array[M], NER[I]>=0
13920 :
13921 : OUTPUT PARAMETERS
13922 : S - sparse M*N matrix in CRS representation.
13923 : You have to fill ALL non-zero elements by calling
13924 : SparseSet() BEFORE you try to use this matrix.
13925 :
13926 : NOTE: this function completely overwrites S with new sparse matrix.
13927 : Previously allocated storage is NOT reused. If you want to reuse
13928 : already allocated memory, call SparseCreateCRSBuf function.
13929 :
13930 : -- ALGLIB PROJECT --
13931 : Copyright 14.10.2011 by Bochkanov Sergey
13932 : *************************************************************************/
13933 0 : void sparsecreatecrs(ae_int_t m,
13934 : ae_int_t n,
13935 : /* Integer */ ae_vector* ner,
13936 : sparsematrix* s,
13937 : ae_state *_state)
13938 : {
13939 : ae_int_t i;
13940 :
13941 0 : _sparsematrix_clear(s);
13942 :
13943 0 : ae_assert(m>0, "SparseCreateCRS: M<=0", _state);
13944 0 : ae_assert(n>0, "SparseCreateCRS: N<=0", _state);
13945 0 : ae_assert(ner->cnt>=m, "SparseCreateCRS: Length(NER)<M", _state);
13946 0 : for(i=0; i<=m-1; i++)
13947 : {
13948 0 : ae_assert(ner->ptr.p_int[i]>=0, "SparseCreateCRS: NER[] contains negative elements", _state);
13949 : }
13950 0 : sparsecreatecrsbuf(m, n, ner, s, _state);
13951 0 : }
13952 :
13953 :
13954 : /*************************************************************************
13955 : This function creates sparse matrix in a CRS format (expert function for
13956 : situations when you are running out of memory). This version of CRS
13957 : matrix creation function may reuse memory already allocated in S.
13958 :
13959 : This function creates CRS matrix. Typical usage scenario for a CRS matrix
13960 : is:
13961 : 1. creation (you have to tell number of non-zero elements at each row at
13962 : this moment)
13963 : 2. insertion of the matrix elements (row by row, from left to right)
13964 : 3. matrix is passed to some linear algebra algorithm
13965 :
13966 : This function is a memory-efficient alternative to SparseCreate(), but it
13967 : is more complex because it requires you to know in advance how large your
13968 : matrix is. Some information about different matrix formats can be found
13969 : in comments on SparseMatrix structure. We recommend you to read them
13970 : before starting to use ALGLIB sparse matrices..
13971 :
13972 : INPUT PARAMETERS
13973 : M - number of rows in a matrix, M>=1
13974 : N - number of columns in a matrix, N>=1
13975 : NER - number of elements at each row, array[M], NER[I]>=0
13976 : S - sparse matrix structure with possibly preallocated
13977 : memory.
13978 :
13979 : OUTPUT PARAMETERS
13980 : S - sparse M*N matrix in CRS representation.
13981 : You have to fill ALL non-zero elements by calling
13982 : SparseSet() BEFORE you try to use this matrix.
13983 :
13984 : -- ALGLIB PROJECT --
13985 : Copyright 14.10.2011 by Bochkanov Sergey
13986 : *************************************************************************/
13987 0 : void sparsecreatecrsbuf(ae_int_t m,
13988 : ae_int_t n,
13989 : /* Integer */ ae_vector* ner,
13990 : sparsematrix* s,
13991 : ae_state *_state)
13992 : {
13993 : ae_int_t i;
13994 : ae_int_t noe;
13995 :
13996 :
13997 0 : ae_assert(m>0, "SparseCreateCRSBuf: M<=0", _state);
13998 0 : ae_assert(n>0, "SparseCreateCRSBuf: N<=0", _state);
13999 0 : ae_assert(ner->cnt>=m, "SparseCreateCRSBuf: Length(NER)<M", _state);
14000 0 : noe = 0;
14001 0 : s->matrixtype = 1;
14002 0 : s->ninitialized = 0;
14003 0 : s->m = m;
14004 0 : s->n = n;
14005 0 : ivectorsetlengthatleast(&s->ridx, s->m+1, _state);
14006 0 : s->ridx.ptr.p_int[0] = 0;
14007 0 : for(i=0; i<=s->m-1; i++)
14008 : {
14009 0 : ae_assert(ner->ptr.p_int[i]>=0, "SparseCreateCRSBuf: NER[] contains negative elements", _state);
14010 0 : noe = noe+ner->ptr.p_int[i];
14011 0 : s->ridx.ptr.p_int[i+1] = s->ridx.ptr.p_int[i]+ner->ptr.p_int[i];
14012 : }
14013 0 : rvectorsetlengthatleast(&s->vals, noe, _state);
14014 0 : ivectorsetlengthatleast(&s->idx, noe, _state);
14015 0 : if( noe==0 )
14016 : {
14017 0 : sparseinitduidx(s, _state);
14018 : }
14019 0 : }
14020 :
14021 :
14022 : /*************************************************************************
14023 : This function creates sparse matrix in a SKS format (skyline storage
14024 : format). In most cases you do not need this function - CRS format better
14025 : suits most use cases.
14026 :
14027 : INPUT PARAMETERS
14028 : M, N - number of rows(M) and columns (N) in a matrix:
14029 : * M=N (as for now, ALGLIB supports only square SKS)
14030 : * N>=1
14031 : * M>=1
14032 : D - "bottom" bandwidths, array[M], D[I]>=0.
14033 : I-th element stores number of non-zeros at I-th row,
14034 : below the diagonal (diagonal itself is not included)
14035 : U - "top" bandwidths, array[N], U[I]>=0.
14036 : I-th element stores number of non-zeros at I-th row,
14037 : above the diagonal (diagonal itself is not included)
14038 :
14039 : OUTPUT PARAMETERS
14040 : S - sparse M*N matrix in SKS representation.
14041 : All elements are filled by zeros.
14042 : You may use sparseset() to change their values.
14043 :
14044 : NOTE: this function completely overwrites S with new sparse matrix.
14045 : Previously allocated storage is NOT reused. If you want to reuse
14046 : already allocated memory, call SparseCreateSKSBuf function.
14047 :
14048 : -- ALGLIB PROJECT --
14049 : Copyright 13.01.2014 by Bochkanov Sergey
14050 : *************************************************************************/
14051 0 : void sparsecreatesks(ae_int_t m,
14052 : ae_int_t n,
14053 : /* Integer */ ae_vector* d,
14054 : /* Integer */ ae_vector* u,
14055 : sparsematrix* s,
14056 : ae_state *_state)
14057 : {
14058 : ae_int_t i;
14059 :
14060 0 : _sparsematrix_clear(s);
14061 :
14062 0 : ae_assert(m>0, "SparseCreateSKS: M<=0", _state);
14063 0 : ae_assert(n>0, "SparseCreateSKS: N<=0", _state);
14064 0 : ae_assert(m==n, "SparseCreateSKS: M<>N", _state);
14065 0 : ae_assert(d->cnt>=m, "SparseCreateSKS: Length(D)<M", _state);
14066 0 : ae_assert(u->cnt>=n, "SparseCreateSKS: Length(U)<N", _state);
14067 0 : for(i=0; i<=m-1; i++)
14068 : {
14069 0 : ae_assert(d->ptr.p_int[i]>=0, "SparseCreateSKS: D[] contains negative elements", _state);
14070 0 : ae_assert(d->ptr.p_int[i]<=i, "SparseCreateSKS: D[I]>I for some I", _state);
14071 : }
14072 0 : for(i=0; i<=n-1; i++)
14073 : {
14074 0 : ae_assert(u->ptr.p_int[i]>=0, "SparseCreateSKS: U[] contains negative elements", _state);
14075 0 : ae_assert(u->ptr.p_int[i]<=i, "SparseCreateSKS: U[I]>I for some I", _state);
14076 : }
14077 0 : sparsecreatesksbuf(m, n, d, u, s, _state);
14078 0 : }
14079 :
14080 :
14081 : /*************************************************************************
14082 : This is "buffered" version of SparseCreateSKS() which reuses memory
14083 : previously allocated in S (of course, memory is reallocated if needed).
14084 :
14085 : This function creates sparse matrix in a SKS format (skyline storage
14086 : format). In most cases you do not need this function - CRS format better
14087 : suits most use cases.
14088 :
14089 : INPUT PARAMETERS
14090 : M, N - number of rows(M) and columns (N) in a matrix:
14091 : * M=N (as for now, ALGLIB supports only square SKS)
14092 : * N>=1
14093 : * M>=1
14094 : D - "bottom" bandwidths, array[M], 0<=D[I]<=I.
14095 : I-th element stores number of non-zeros at I-th row,
14096 : below the diagonal (diagonal itself is not included)
14097 : U - "top" bandwidths, array[N], 0<=U[I]<=I.
14098 : I-th element stores number of non-zeros at I-th row,
14099 : above the diagonal (diagonal itself is not included)
14100 :
14101 : OUTPUT PARAMETERS
14102 : S - sparse M*N matrix in SKS representation.
14103 : All elements are filled by zeros.
14104 : You may use sparseset() to change their values.
14105 :
14106 : -- ALGLIB PROJECT --
14107 : Copyright 13.01.2014 by Bochkanov Sergey
14108 : *************************************************************************/
14109 0 : void sparsecreatesksbuf(ae_int_t m,
14110 : ae_int_t n,
14111 : /* Integer */ ae_vector* d,
14112 : /* Integer */ ae_vector* u,
14113 : sparsematrix* s,
14114 : ae_state *_state)
14115 : {
14116 : ae_int_t i;
14117 : ae_int_t minmn;
14118 : ae_int_t nz;
14119 : ae_int_t mxd;
14120 : ae_int_t mxu;
14121 :
14122 :
14123 0 : ae_assert(m>0, "SparseCreateSKSBuf: M<=0", _state);
14124 0 : ae_assert(n>0, "SparseCreateSKSBuf: N<=0", _state);
14125 0 : ae_assert(m==n, "SparseCreateSKSBuf: M<>N", _state);
14126 0 : ae_assert(d->cnt>=m, "SparseCreateSKSBuf: Length(D)<M", _state);
14127 0 : ae_assert(u->cnt>=n, "SparseCreateSKSBuf: Length(U)<N", _state);
14128 0 : for(i=0; i<=m-1; i++)
14129 : {
14130 0 : ae_assert(d->ptr.p_int[i]>=0, "SparseCreateSKSBuf: D[] contains negative elements", _state);
14131 0 : ae_assert(d->ptr.p_int[i]<=i, "SparseCreateSKSBuf: D[I]>I for some I", _state);
14132 : }
14133 0 : for(i=0; i<=n-1; i++)
14134 : {
14135 0 : ae_assert(u->ptr.p_int[i]>=0, "SparseCreateSKSBuf: U[] contains negative elements", _state);
14136 0 : ae_assert(u->ptr.p_int[i]<=i, "SparseCreateSKSBuf: U[I]>I for some I", _state);
14137 : }
14138 0 : minmn = ae_minint(m, n, _state);
14139 0 : s->matrixtype = 2;
14140 0 : s->ninitialized = 0;
14141 0 : s->m = m;
14142 0 : s->n = n;
14143 0 : ivectorsetlengthatleast(&s->ridx, minmn+1, _state);
14144 0 : s->ridx.ptr.p_int[0] = 0;
14145 0 : nz = 0;
14146 0 : for(i=0; i<=minmn-1; i++)
14147 : {
14148 0 : nz = nz+1+d->ptr.p_int[i]+u->ptr.p_int[i];
14149 0 : s->ridx.ptr.p_int[i+1] = s->ridx.ptr.p_int[i]+1+d->ptr.p_int[i]+u->ptr.p_int[i];
14150 : }
14151 0 : rvectorsetlengthatleast(&s->vals, nz, _state);
14152 0 : for(i=0; i<=nz-1; i++)
14153 : {
14154 0 : s->vals.ptr.p_double[i] = 0.0;
14155 : }
14156 0 : ivectorsetlengthatleast(&s->didx, m+1, _state);
14157 0 : mxd = 0;
14158 0 : for(i=0; i<=m-1; i++)
14159 : {
14160 0 : s->didx.ptr.p_int[i] = d->ptr.p_int[i];
14161 0 : mxd = ae_maxint(mxd, d->ptr.p_int[i], _state);
14162 : }
14163 0 : s->didx.ptr.p_int[m] = mxd;
14164 0 : ivectorsetlengthatleast(&s->uidx, n+1, _state);
14165 0 : mxu = 0;
14166 0 : for(i=0; i<=n-1; i++)
14167 : {
14168 0 : s->uidx.ptr.p_int[i] = u->ptr.p_int[i];
14169 0 : mxu = ae_maxint(mxu, u->ptr.p_int[i], _state);
14170 : }
14171 0 : s->uidx.ptr.p_int[n] = mxu;
14172 0 : }
14173 :
14174 :
14175 : /*************************************************************************
14176 : This function creates sparse matrix in a SKS format (skyline storage
14177 : format). Unlike more general sparsecreatesks(), this function creates
14178 : sparse matrix with constant bandwidth.
14179 :
14180 : You may want to use this function instead of sparsecreatesks() when your
14181 : matrix has constant or nearly-constant bandwidth, and you want to
14182 : simplify source code.
14183 :
14184 : INPUT PARAMETERS
14185 : M, N - number of rows(M) and columns (N) in a matrix:
14186 : * M=N (as for now, ALGLIB supports only square SKS)
14187 : * N>=1
14188 : * M>=1
14189 : BW - matrix bandwidth, BW>=0
14190 :
14191 : OUTPUT PARAMETERS
14192 : S - sparse M*N matrix in SKS representation.
14193 : All elements are filled by zeros.
14194 : You may use sparseset() to change their values.
14195 :
14196 : NOTE: this function completely overwrites S with new sparse matrix.
14197 : Previously allocated storage is NOT reused. If you want to reuse
14198 : already allocated memory, call sparsecreatesksbandbuf function.
14199 :
14200 : -- ALGLIB PROJECT --
14201 : Copyright 25.12.2017 by Bochkanov Sergey
14202 : *************************************************************************/
14203 0 : void sparsecreatesksband(ae_int_t m,
14204 : ae_int_t n,
14205 : ae_int_t bw,
14206 : sparsematrix* s,
14207 : ae_state *_state)
14208 : {
14209 :
14210 0 : _sparsematrix_clear(s);
14211 :
14212 0 : ae_assert(m>0, "SparseCreateSKSBand: M<=0", _state);
14213 0 : ae_assert(n>0, "SparseCreateSKSBand: N<=0", _state);
14214 0 : ae_assert(bw>=0, "SparseCreateSKSBand: BW<0", _state);
14215 0 : ae_assert(m==n, "SparseCreateSKSBand: M!=N", _state);
14216 0 : sparsecreatesksbandbuf(m, n, bw, s, _state);
14217 0 : }
14218 :
14219 :
14220 : /*************************************************************************
14221 : This is "buffered" version of sparsecreatesksband() which reuses memory
14222 : previously allocated in S (of course, memory is reallocated if needed).
14223 :
14224 : You may want to use this function instead of sparsecreatesksbuf() when
14225 : your matrix has constant or nearly-constant bandwidth, and you want to
14226 : simplify source code.
14227 :
14228 : INPUT PARAMETERS
14229 : M, N - number of rows(M) and columns (N) in a matrix:
14230 : * M=N (as for now, ALGLIB supports only square SKS)
14231 : * N>=1
14232 : * M>=1
14233 : BW - bandwidth, BW>=0
14234 :
14235 : OUTPUT PARAMETERS
14236 : S - sparse M*N matrix in SKS representation.
14237 : All elements are filled by zeros.
14238 : You may use sparseset() to change their values.
14239 :
14240 : -- ALGLIB PROJECT --
14241 : Copyright 13.01.2014 by Bochkanov Sergey
14242 : *************************************************************************/
14243 0 : void sparsecreatesksbandbuf(ae_int_t m,
14244 : ae_int_t n,
14245 : ae_int_t bw,
14246 : sparsematrix* s,
14247 : ae_state *_state)
14248 : {
14249 : ae_int_t i;
14250 : ae_int_t minmn;
14251 : ae_int_t nz;
14252 : ae_int_t mxd;
14253 : ae_int_t mxu;
14254 : ae_int_t dui;
14255 :
14256 :
14257 0 : ae_assert(m>0, "SparseCreateSKSBandBuf: M<=0", _state);
14258 0 : ae_assert(n>0, "SparseCreateSKSBandBuf: N<=0", _state);
14259 0 : ae_assert(m==n, "SparseCreateSKSBandBuf: M!=N", _state);
14260 0 : ae_assert(bw>=0, "SparseCreateSKSBandBuf: BW<0", _state);
14261 0 : minmn = ae_minint(m, n, _state);
14262 0 : s->matrixtype = 2;
14263 0 : s->ninitialized = 0;
14264 0 : s->m = m;
14265 0 : s->n = n;
14266 0 : ivectorsetlengthatleast(&s->ridx, minmn+1, _state);
14267 0 : s->ridx.ptr.p_int[0] = 0;
14268 0 : nz = 0;
14269 0 : for(i=0; i<=minmn-1; i++)
14270 : {
14271 0 : dui = ae_minint(i, bw, _state);
14272 0 : nz = nz+1+2*dui;
14273 0 : s->ridx.ptr.p_int[i+1] = s->ridx.ptr.p_int[i]+1+2*dui;
14274 : }
14275 0 : rvectorsetlengthatleast(&s->vals, nz, _state);
14276 0 : for(i=0; i<=nz-1; i++)
14277 : {
14278 0 : s->vals.ptr.p_double[i] = 0.0;
14279 : }
14280 0 : ivectorsetlengthatleast(&s->didx, m+1, _state);
14281 0 : mxd = 0;
14282 0 : for(i=0; i<=m-1; i++)
14283 : {
14284 0 : dui = ae_minint(i, bw, _state);
14285 0 : s->didx.ptr.p_int[i] = dui;
14286 0 : mxd = ae_maxint(mxd, dui, _state);
14287 : }
14288 0 : s->didx.ptr.p_int[m] = mxd;
14289 0 : ivectorsetlengthatleast(&s->uidx, n+1, _state);
14290 0 : mxu = 0;
14291 0 : for(i=0; i<=n-1; i++)
14292 : {
14293 0 : dui = ae_minint(i, bw, _state);
14294 0 : s->uidx.ptr.p_int[i] = dui;
14295 0 : mxu = ae_maxint(mxu, dui, _state);
14296 : }
14297 0 : s->uidx.ptr.p_int[n] = mxu;
14298 0 : }
14299 :
14300 :
14301 : /*************************************************************************
14302 : This function copies S0 to S1.
14303 : This function completely deallocates memory owned by S1 before creating a
14304 : copy of S0. If you want to reuse memory, use SparseCopyBuf.
14305 :
14306 : NOTE: this function does not verify its arguments, it just copies all
14307 : fields of the structure.
14308 :
14309 : -- ALGLIB PROJECT --
14310 : Copyright 14.10.2011 by Bochkanov Sergey
14311 : *************************************************************************/
14312 0 : void sparsecopy(sparsematrix* s0, sparsematrix* s1, ae_state *_state)
14313 : {
14314 :
14315 0 : _sparsematrix_clear(s1);
14316 :
14317 0 : sparsecopybuf(s0, s1, _state);
14318 0 : }
14319 :
14320 :
14321 : /*************************************************************************
14322 : This function copies S0 to S1.
14323 : Memory already allocated in S1 is reused as much as possible.
14324 :
14325 : NOTE: this function does not verify its arguments, it just copies all
14326 : fields of the structure.
14327 :
14328 : -- ALGLIB PROJECT --
14329 : Copyright 14.10.2011 by Bochkanov Sergey
14330 : *************************************************************************/
14331 0 : void sparsecopybuf(sparsematrix* s0, sparsematrix* s1, ae_state *_state)
14332 : {
14333 : ae_int_t l;
14334 : ae_int_t i;
14335 :
14336 :
14337 0 : s1->matrixtype = s0->matrixtype;
14338 0 : s1->m = s0->m;
14339 0 : s1->n = s0->n;
14340 0 : s1->nfree = s0->nfree;
14341 0 : s1->ninitialized = s0->ninitialized;
14342 0 : s1->tablesize = s0->tablesize;
14343 :
14344 : /*
14345 : * Initialization for arrays
14346 : */
14347 0 : l = s0->vals.cnt;
14348 0 : rvectorsetlengthatleast(&s1->vals, l, _state);
14349 0 : for(i=0; i<=l-1; i++)
14350 : {
14351 0 : s1->vals.ptr.p_double[i] = s0->vals.ptr.p_double[i];
14352 : }
14353 0 : l = s0->ridx.cnt;
14354 0 : ivectorsetlengthatleast(&s1->ridx, l, _state);
14355 0 : for(i=0; i<=l-1; i++)
14356 : {
14357 0 : s1->ridx.ptr.p_int[i] = s0->ridx.ptr.p_int[i];
14358 : }
14359 0 : l = s0->idx.cnt;
14360 0 : ivectorsetlengthatleast(&s1->idx, l, _state);
14361 0 : for(i=0; i<=l-1; i++)
14362 : {
14363 0 : s1->idx.ptr.p_int[i] = s0->idx.ptr.p_int[i];
14364 : }
14365 :
14366 : /*
14367 : * Initalization for CRS-parameters
14368 : */
14369 0 : l = s0->uidx.cnt;
14370 0 : ivectorsetlengthatleast(&s1->uidx, l, _state);
14371 0 : for(i=0; i<=l-1; i++)
14372 : {
14373 0 : s1->uidx.ptr.p_int[i] = s0->uidx.ptr.p_int[i];
14374 : }
14375 0 : l = s0->didx.cnt;
14376 0 : ivectorsetlengthatleast(&s1->didx, l, _state);
14377 0 : for(i=0; i<=l-1; i++)
14378 : {
14379 0 : s1->didx.ptr.p_int[i] = s0->didx.ptr.p_int[i];
14380 : }
14381 0 : }
14382 :
14383 :
14384 : /*************************************************************************
14385 : This function efficiently swaps contents of S0 and S1.
14386 :
14387 : -- ALGLIB PROJECT --
14388 : Copyright 16.01.2014 by Bochkanov Sergey
14389 : *************************************************************************/
14390 0 : void sparseswap(sparsematrix* s0, sparsematrix* s1, ae_state *_state)
14391 : {
14392 :
14393 :
14394 0 : swapi(&s1->matrixtype, &s0->matrixtype, _state);
14395 0 : swapi(&s1->m, &s0->m, _state);
14396 0 : swapi(&s1->n, &s0->n, _state);
14397 0 : swapi(&s1->nfree, &s0->nfree, _state);
14398 0 : swapi(&s1->ninitialized, &s0->ninitialized, _state);
14399 0 : swapi(&s1->tablesize, &s0->tablesize, _state);
14400 0 : ae_swap_vectors(&s1->vals, &s0->vals);
14401 0 : ae_swap_vectors(&s1->ridx, &s0->ridx);
14402 0 : ae_swap_vectors(&s1->idx, &s0->idx);
14403 0 : ae_swap_vectors(&s1->uidx, &s0->uidx);
14404 0 : ae_swap_vectors(&s1->didx, &s0->didx);
14405 0 : }
14406 :
14407 :
14408 : /*************************************************************************
14409 : This function adds value to S[i,j] - element of the sparse matrix. Matrix
14410 : must be in a Hash-Table mode.
14411 :
14412 : In case S[i,j] already exists in the table, V i added to its value. In
14413 : case S[i,j] is non-existent, it is inserted in the table. Table
14414 : automatically grows when necessary.
14415 :
14416 : INPUT PARAMETERS
14417 : S - sparse M*N matrix in Hash-Table representation.
14418 : Exception will be thrown for CRS matrix.
14419 : I - row index of the element to modify, 0<=I<M
14420 : J - column index of the element to modify, 0<=J<N
14421 : V - value to add, must be finite number
14422 :
14423 : OUTPUT PARAMETERS
14424 : S - modified matrix
14425 :
14426 : NOTE 1: when S[i,j] is exactly zero after modification, it is deleted
14427 : from the table.
14428 :
14429 : -- ALGLIB PROJECT --
14430 : Copyright 14.10.2011 by Bochkanov Sergey
14431 : *************************************************************************/
14432 0 : void sparseadd(sparsematrix* s,
14433 : ae_int_t i,
14434 : ae_int_t j,
14435 : double v,
14436 : ae_state *_state)
14437 : {
14438 : ae_int_t hashcode;
14439 : ae_int_t tcode;
14440 : ae_int_t k;
14441 :
14442 :
14443 0 : ae_assert(s->matrixtype==0, "SparseAdd: matrix must be in the Hash-Table mode to do this operation", _state);
14444 0 : ae_assert(i>=0, "SparseAdd: I<0", _state);
14445 0 : ae_assert(i<s->m, "SparseAdd: I>=M", _state);
14446 0 : ae_assert(j>=0, "SparseAdd: J<0", _state);
14447 0 : ae_assert(j<s->n, "SparseAdd: J>=N", _state);
14448 0 : ae_assert(ae_isfinite(v, _state), "SparseAdd: V is not finite number", _state);
14449 0 : if( ae_fp_eq(v,(double)(0)) )
14450 : {
14451 0 : return;
14452 : }
14453 0 : tcode = -1;
14454 0 : k = s->tablesize;
14455 0 : if( ae_fp_greater_eq((1-sparse_maxloadfactor)*k,(double)(s->nfree)) )
14456 : {
14457 0 : sparseresizematrix(s, _state);
14458 0 : k = s->tablesize;
14459 : }
14460 0 : hashcode = sparse_hash(i, j, k, _state);
14461 : for(;;)
14462 : {
14463 0 : if( s->idx.ptr.p_int[2*hashcode]==-1 )
14464 : {
14465 0 : if( tcode!=-1 )
14466 : {
14467 0 : hashcode = tcode;
14468 : }
14469 0 : s->vals.ptr.p_double[hashcode] = v;
14470 0 : s->idx.ptr.p_int[2*hashcode] = i;
14471 0 : s->idx.ptr.p_int[2*hashcode+1] = j;
14472 0 : if( tcode==-1 )
14473 : {
14474 0 : s->nfree = s->nfree-1;
14475 : }
14476 0 : return;
14477 : }
14478 : else
14479 : {
14480 0 : if( s->idx.ptr.p_int[2*hashcode]==i&&s->idx.ptr.p_int[2*hashcode+1]==j )
14481 : {
14482 0 : s->vals.ptr.p_double[hashcode] = s->vals.ptr.p_double[hashcode]+v;
14483 0 : if( ae_fp_eq(s->vals.ptr.p_double[hashcode],(double)(0)) )
14484 : {
14485 0 : s->idx.ptr.p_int[2*hashcode] = -2;
14486 : }
14487 0 : return;
14488 : }
14489 :
14490 : /*
14491 : * Is it deleted element?
14492 : */
14493 0 : if( tcode==-1&&s->idx.ptr.p_int[2*hashcode]==-2 )
14494 : {
14495 0 : tcode = hashcode;
14496 : }
14497 :
14498 : /*
14499 : * Next step
14500 : */
14501 0 : hashcode = (hashcode+1)%k;
14502 : }
14503 : }
14504 : }
14505 :
14506 :
14507 : /*************************************************************************
14508 : This function modifies S[i,j] - element of the sparse matrix.
14509 :
14510 : For Hash-based storage format:
14511 : * this function can be called at any moment - during matrix initialization
14512 : or later
14513 : * new value can be zero or non-zero. In case new value of S[i,j] is zero,
14514 : this element is deleted from the table.
14515 : * this function has no effect when called with zero V for non-existent
14516 : element.
14517 :
14518 : For CRS-bases storage format:
14519 : * this function can be called ONLY DURING MATRIX INITIALIZATION
14520 : * zero values are stored in the matrix similarly to non-zero ones
14521 : * elements must be initialized in correct order - from top row to bottom,
14522 : within row - from left to right.
14523 :
14524 : For SKS storage:
14525 : * this function can be called at any moment - during matrix initialization
14526 : or later
14527 : * zero values are stored in the matrix similarly to non-zero ones
14528 : * this function CAN NOT be called for non-existent (outside of the band
14529 : specified during SKS matrix creation) elements. Say, if you created SKS
14530 : matrix with bandwidth=2 and tried to call sparseset(s,0,10,VAL), an
14531 : exception will be generated.
14532 :
14533 : INPUT PARAMETERS
14534 : S - sparse M*N matrix in Hash-Table, SKS or CRS format.
14535 : I - row index of the element to modify, 0<=I<M
14536 : J - column index of the element to modify, 0<=J<N
14537 : V - value to set, must be finite number, can be zero
14538 :
14539 : OUTPUT PARAMETERS
14540 : S - modified matrix
14541 :
14542 : -- ALGLIB PROJECT --
14543 : Copyright 14.10.2011 by Bochkanov Sergey
14544 : *************************************************************************/
14545 0 : void sparseset(sparsematrix* s,
14546 : ae_int_t i,
14547 : ae_int_t j,
14548 : double v,
14549 : ae_state *_state)
14550 : {
14551 : ae_int_t hashcode;
14552 : ae_int_t tcode;
14553 : ae_int_t k;
14554 : ae_bool b;
14555 :
14556 :
14557 0 : ae_assert((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2, "SparseSet: unsupported matrix storage format", _state);
14558 0 : ae_assert(i>=0, "SparseSet: I<0", _state);
14559 0 : ae_assert(i<s->m, "SparseSet: I>=M", _state);
14560 0 : ae_assert(j>=0, "SparseSet: J<0", _state);
14561 0 : ae_assert(j<s->n, "SparseSet: J>=N", _state);
14562 0 : ae_assert(ae_isfinite(v, _state), "SparseSet: V is not finite number", _state);
14563 :
14564 : /*
14565 : * Hash-table matrix
14566 : */
14567 0 : if( s->matrixtype==0 )
14568 : {
14569 0 : tcode = -1;
14570 0 : k = s->tablesize;
14571 0 : if( ae_fp_greater_eq((1-sparse_maxloadfactor)*k,(double)(s->nfree)) )
14572 : {
14573 0 : sparseresizematrix(s, _state);
14574 0 : k = s->tablesize;
14575 : }
14576 0 : hashcode = sparse_hash(i, j, k, _state);
14577 : for(;;)
14578 : {
14579 0 : if( s->idx.ptr.p_int[2*hashcode]==-1 )
14580 : {
14581 0 : if( ae_fp_neq(v,(double)(0)) )
14582 : {
14583 0 : if( tcode!=-1 )
14584 : {
14585 0 : hashcode = tcode;
14586 : }
14587 0 : s->vals.ptr.p_double[hashcode] = v;
14588 0 : s->idx.ptr.p_int[2*hashcode] = i;
14589 0 : s->idx.ptr.p_int[2*hashcode+1] = j;
14590 0 : if( tcode==-1 )
14591 : {
14592 0 : s->nfree = s->nfree-1;
14593 : }
14594 : }
14595 0 : return;
14596 : }
14597 : else
14598 : {
14599 0 : if( s->idx.ptr.p_int[2*hashcode]==i&&s->idx.ptr.p_int[2*hashcode+1]==j )
14600 : {
14601 0 : if( ae_fp_eq(v,(double)(0)) )
14602 : {
14603 0 : s->idx.ptr.p_int[2*hashcode] = -2;
14604 : }
14605 : else
14606 : {
14607 0 : s->vals.ptr.p_double[hashcode] = v;
14608 : }
14609 0 : return;
14610 : }
14611 0 : if( tcode==-1&&s->idx.ptr.p_int[2*hashcode]==-2 )
14612 : {
14613 0 : tcode = hashcode;
14614 : }
14615 :
14616 : /*
14617 : * Next step
14618 : */
14619 0 : hashcode = (hashcode+1)%k;
14620 : }
14621 : }
14622 : }
14623 :
14624 : /*
14625 : * CRS matrix
14626 : */
14627 0 : if( s->matrixtype==1 )
14628 : {
14629 0 : ae_assert(s->ridx.ptr.p_int[i]<=s->ninitialized, "SparseSet: too few initialized elements at some row (you have promised more when called SparceCreateCRS)", _state);
14630 0 : ae_assert(s->ridx.ptr.p_int[i+1]>s->ninitialized, "SparseSet: too many initialized elements at some row (you have promised less when called SparceCreateCRS)", _state);
14631 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[i]||s->idx.ptr.p_int[s->ninitialized-1]<j, "SparseSet: incorrect column order (you must fill every row from left to right)", _state);
14632 0 : s->vals.ptr.p_double[s->ninitialized] = v;
14633 0 : s->idx.ptr.p_int[s->ninitialized] = j;
14634 0 : s->ninitialized = s->ninitialized+1;
14635 :
14636 : /*
14637 : * If matrix has been created then
14638 : * initiale 'S.UIdx' and 'S.DIdx'
14639 : */
14640 0 : if( s->ninitialized==s->ridx.ptr.p_int[s->m] )
14641 : {
14642 0 : sparseinitduidx(s, _state);
14643 : }
14644 0 : return;
14645 : }
14646 :
14647 : /*
14648 : * SKS matrix
14649 : */
14650 0 : if( s->matrixtype==2 )
14651 : {
14652 0 : b = sparserewriteexisting(s, i, j, v, _state);
14653 0 : ae_assert(b, "SparseSet: an attempt to initialize out-of-band element of the SKS matrix", _state);
14654 0 : return;
14655 : }
14656 : }
14657 :
14658 :
14659 : /*************************************************************************
14660 : This function returns S[i,j] - element of the sparse matrix. Matrix can
14661 : be in any mode (Hash-Table, CRS, SKS), but this function is less efficient
14662 : for CRS matrices. Hash-Table and SKS matrices can find element in O(1)
14663 : time, while CRS matrices need O(log(RS)) time, where RS is an number of
14664 : non-zero elements in a row.
14665 :
14666 : INPUT PARAMETERS
14667 : S - sparse M*N matrix
14668 : I - row index of the element to modify, 0<=I<M
14669 : J - column index of the element to modify, 0<=J<N
14670 :
14671 : RESULT
14672 : value of S[I,J] or zero (in case no element with such index is found)
14673 :
14674 : -- ALGLIB PROJECT --
14675 : Copyright 14.10.2011 by Bochkanov Sergey
14676 : *************************************************************************/
14677 0 : double sparseget(sparsematrix* s,
14678 : ae_int_t i,
14679 : ae_int_t j,
14680 : ae_state *_state)
14681 : {
14682 : ae_int_t hashcode;
14683 : ae_int_t k;
14684 : ae_int_t k0;
14685 : ae_int_t k1;
14686 : double result;
14687 :
14688 :
14689 0 : ae_assert(i>=0, "SparseGet: I<0", _state);
14690 0 : ae_assert(i<s->m, "SparseGet: I>=M", _state);
14691 0 : ae_assert(j>=0, "SparseGet: J<0", _state);
14692 0 : ae_assert(j<s->n, "SparseGet: J>=N", _state);
14693 0 : result = 0.0;
14694 0 : if( s->matrixtype==0 )
14695 : {
14696 :
14697 : /*
14698 : * Hash-based storage
14699 : */
14700 0 : result = (double)(0);
14701 0 : k = s->tablesize;
14702 0 : hashcode = sparse_hash(i, j, k, _state);
14703 : for(;;)
14704 : {
14705 0 : if( s->idx.ptr.p_int[2*hashcode]==-1 )
14706 : {
14707 0 : return result;
14708 : }
14709 0 : if( s->idx.ptr.p_int[2*hashcode]==i&&s->idx.ptr.p_int[2*hashcode+1]==j )
14710 : {
14711 0 : result = s->vals.ptr.p_double[hashcode];
14712 0 : return result;
14713 : }
14714 0 : hashcode = (hashcode+1)%k;
14715 : }
14716 : }
14717 0 : if( s->matrixtype==1 )
14718 : {
14719 :
14720 : /*
14721 : * CRS
14722 : */
14723 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseGet: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
14724 0 : k0 = s->ridx.ptr.p_int[i];
14725 0 : k1 = s->ridx.ptr.p_int[i+1]-1;
14726 0 : result = (double)(0);
14727 0 : while(k0<=k1)
14728 : {
14729 0 : k = (k0+k1)/2;
14730 0 : if( s->idx.ptr.p_int[k]==j )
14731 : {
14732 0 : result = s->vals.ptr.p_double[k];
14733 0 : return result;
14734 : }
14735 0 : if( s->idx.ptr.p_int[k]<j )
14736 : {
14737 0 : k0 = k+1;
14738 : }
14739 : else
14740 : {
14741 0 : k1 = k-1;
14742 : }
14743 : }
14744 0 : return result;
14745 : }
14746 0 : if( s->matrixtype==2 )
14747 : {
14748 :
14749 : /*
14750 : * SKS
14751 : */
14752 0 : ae_assert(s->m==s->n, "SparseGet: non-square SKS matrix not supported", _state);
14753 0 : result = (double)(0);
14754 0 : if( i==j )
14755 : {
14756 :
14757 : /*
14758 : * Return diagonal element
14759 : */
14760 0 : result = s->vals.ptr.p_double[s->ridx.ptr.p_int[i]+s->didx.ptr.p_int[i]];
14761 0 : return result;
14762 : }
14763 0 : if( j<i )
14764 : {
14765 :
14766 : /*
14767 : * Return subdiagonal element at I-th "skyline block"
14768 : */
14769 0 : k = s->didx.ptr.p_int[i];
14770 0 : if( i-j<=k )
14771 : {
14772 0 : result = s->vals.ptr.p_double[s->ridx.ptr.p_int[i]+k+j-i];
14773 : }
14774 : }
14775 : else
14776 : {
14777 :
14778 : /*
14779 : * Return superdiagonal element at J-th "skyline block"
14780 : */
14781 0 : k = s->uidx.ptr.p_int[j];
14782 0 : if( j-i<=k )
14783 : {
14784 0 : result = s->vals.ptr.p_double[s->ridx.ptr.p_int[j+1]-(j-i)];
14785 : }
14786 0 : return result;
14787 : }
14788 0 : return result;
14789 : }
14790 0 : ae_assert(ae_false, "SparseGet: unexpected matrix type", _state);
14791 0 : return result;
14792 : }
14793 :
14794 :
14795 : /*************************************************************************
14796 : This function checks whether S[i,j] is present in the sparse matrix. It
14797 : returns True even for elements that are numerically zero (but still
14798 : have place allocated for them).
14799 :
14800 : The matrix can be in any mode (Hash-Table, CRS, SKS), but this function
14801 : is less efficient for CRS matrices. Hash-Table and SKS matrices can find
14802 : element in O(1) time, while CRS matrices need O(log(RS)) time, where RS
14803 : is an number of non-zero elements in a row.
14804 :
14805 : INPUT PARAMETERS
14806 : S - sparse M*N matrix
14807 : I - row index of the element to modify, 0<=I<M
14808 : J - column index of the element to modify, 0<=J<N
14809 :
14810 : RESULT
14811 : whether S[I,J] is present in the data structure or not
14812 :
14813 : -- ALGLIB PROJECT --
14814 : Copyright 14.10.2020 by Bochkanov Sergey
14815 : *************************************************************************/
14816 0 : ae_bool sparseexists(sparsematrix* s,
14817 : ae_int_t i,
14818 : ae_int_t j,
14819 : ae_state *_state)
14820 : {
14821 : ae_int_t hashcode;
14822 : ae_int_t k;
14823 : ae_int_t k0;
14824 : ae_int_t k1;
14825 : ae_bool result;
14826 :
14827 :
14828 0 : ae_assert(i>=0, "SparseExists: I<0", _state);
14829 0 : ae_assert(i<s->m, "SparseExists: I>=M", _state);
14830 0 : ae_assert(j>=0, "SparseExists: J<0", _state);
14831 0 : ae_assert(j<s->n, "SparseExists: J>=N", _state);
14832 0 : result = ae_false;
14833 0 : if( s->matrixtype==0 )
14834 : {
14835 :
14836 : /*
14837 : * Hash-based storage
14838 : */
14839 0 : k = s->tablesize;
14840 0 : hashcode = sparse_hash(i, j, k, _state);
14841 : for(;;)
14842 : {
14843 0 : if( s->idx.ptr.p_int[2*hashcode]==-1 )
14844 : {
14845 0 : return result;
14846 : }
14847 0 : if( s->idx.ptr.p_int[2*hashcode]==i&&s->idx.ptr.p_int[2*hashcode+1]==j )
14848 : {
14849 0 : result = ae_true;
14850 0 : return result;
14851 : }
14852 0 : hashcode = (hashcode+1)%k;
14853 : }
14854 : }
14855 0 : if( s->matrixtype==1 )
14856 : {
14857 :
14858 : /*
14859 : * CRS
14860 : */
14861 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseExists: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
14862 0 : k0 = s->ridx.ptr.p_int[i];
14863 0 : k1 = s->ridx.ptr.p_int[i+1]-1;
14864 0 : while(k0<=k1)
14865 : {
14866 0 : k = (k0+k1)/2;
14867 0 : if( s->idx.ptr.p_int[k]==j )
14868 : {
14869 0 : result = ae_true;
14870 0 : return result;
14871 : }
14872 0 : if( s->idx.ptr.p_int[k]<j )
14873 : {
14874 0 : k0 = k+1;
14875 : }
14876 : else
14877 : {
14878 0 : k1 = k-1;
14879 : }
14880 : }
14881 0 : return result;
14882 : }
14883 0 : if( s->matrixtype==2 )
14884 : {
14885 :
14886 : /*
14887 : * SKS
14888 : */
14889 0 : ae_assert(s->m==s->n, "SparseExists: non-square SKS matrix not supported", _state);
14890 0 : if( i==j )
14891 : {
14892 :
14893 : /*
14894 : * Return diagonal element
14895 : */
14896 0 : result = ae_true;
14897 0 : return result;
14898 : }
14899 0 : if( j<i )
14900 : {
14901 :
14902 : /*
14903 : * Return subdiagonal element at I-th "skyline block"
14904 : */
14905 0 : if( i-j<=s->didx.ptr.p_int[i] )
14906 : {
14907 0 : result = ae_true;
14908 : }
14909 : }
14910 : else
14911 : {
14912 :
14913 : /*
14914 : * Return superdiagonal element at J-th "skyline block"
14915 : */
14916 0 : if( j-i<=s->uidx.ptr.p_int[j] )
14917 : {
14918 0 : result = ae_true;
14919 : }
14920 0 : return result;
14921 : }
14922 0 : return result;
14923 : }
14924 0 : ae_assert(ae_false, "SparseExists: unexpected matrix type", _state);
14925 0 : return result;
14926 : }
14927 :
14928 :
14929 : /*************************************************************************
14930 : This function returns I-th diagonal element of the sparse matrix.
14931 :
14932 : Matrix can be in any mode (Hash-Table or CRS storage), but this function
14933 : is most efficient for CRS matrices - it requires less than 50 CPU cycles
14934 : to extract diagonal element. For Hash-Table matrices we still have O(1)
14935 : query time, but function is many times slower.
14936 :
14937 : INPUT PARAMETERS
14938 : S - sparse M*N matrix in Hash-Table representation.
14939 : Exception will be thrown for CRS matrix.
14940 : I - index of the element to modify, 0<=I<min(M,N)
14941 :
14942 : RESULT
14943 : value of S[I,I] or zero (in case no element with such index is found)
14944 :
14945 : -- ALGLIB PROJECT --
14946 : Copyright 14.10.2011 by Bochkanov Sergey
14947 : *************************************************************************/
14948 0 : double sparsegetdiagonal(sparsematrix* s, ae_int_t i, ae_state *_state)
14949 : {
14950 : double result;
14951 :
14952 :
14953 0 : ae_assert(i>=0, "SparseGetDiagonal: I<0", _state);
14954 0 : ae_assert(i<s->m, "SparseGetDiagonal: I>=M", _state);
14955 0 : ae_assert(i<s->n, "SparseGetDiagonal: I>=N", _state);
14956 0 : result = (double)(0);
14957 0 : if( s->matrixtype==0 )
14958 : {
14959 0 : result = sparseget(s, i, i, _state);
14960 0 : return result;
14961 : }
14962 0 : if( s->matrixtype==1 )
14963 : {
14964 0 : if( s->didx.ptr.p_int[i]!=s->uidx.ptr.p_int[i] )
14965 : {
14966 0 : result = s->vals.ptr.p_double[s->didx.ptr.p_int[i]];
14967 : }
14968 0 : return result;
14969 : }
14970 0 : if( s->matrixtype==2 )
14971 : {
14972 0 : ae_assert(s->m==s->n, "SparseGetDiagonal: non-square SKS matrix not supported", _state);
14973 0 : result = s->vals.ptr.p_double[s->ridx.ptr.p_int[i]+s->didx.ptr.p_int[i]];
14974 0 : return result;
14975 : }
14976 0 : ae_assert(ae_false, "SparseGetDiagonal: unexpected matrix type", _state);
14977 0 : return result;
14978 : }
14979 :
14980 :
14981 : /*************************************************************************
14982 : This function calculates matrix-vector product S*x. Matrix S must be
14983 : stored in CRS or SKS format (exception will be thrown otherwise).
14984 :
14985 : INPUT PARAMETERS
14986 : S - sparse M*N matrix in CRS or SKS format.
14987 : X - array[N], input vector. For performance reasons we
14988 : make only quick checks - we check that array size is
14989 : at least N, but we do not check for NAN's or INF's.
14990 : Y - output buffer, possibly preallocated. In case buffer
14991 : size is too small to store result, this buffer is
14992 : automatically resized.
14993 :
14994 : OUTPUT PARAMETERS
14995 : Y - array[M], S*x
14996 :
14997 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
14998 : You must convert your matrix with SparseConvertToCRS/SKS() before using
14999 : this function.
15000 :
15001 : -- ALGLIB PROJECT --
15002 : Copyright 14.10.2011 by Bochkanov Sergey
15003 : *************************************************************************/
15004 0 : void sparsemv(sparsematrix* s,
15005 : /* Real */ ae_vector* x,
15006 : /* Real */ ae_vector* y,
15007 : ae_state *_state)
15008 : {
15009 : double tval;
15010 : double v;
15011 : double vv;
15012 : ae_int_t i;
15013 : ae_int_t j;
15014 : ae_int_t lt;
15015 : ae_int_t rt;
15016 : ae_int_t lt1;
15017 : ae_int_t rt1;
15018 : ae_int_t n;
15019 : ae_int_t m;
15020 : ae_int_t d;
15021 : ae_int_t u;
15022 : ae_int_t ri;
15023 : ae_int_t ri1;
15024 :
15025 :
15026 0 : ae_assert(x->cnt>=s->n, "SparseMV: length(X)<N", _state);
15027 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseMV: incorrect matrix type (convert your matrix to CRS/SKS)", _state);
15028 0 : rvectorsetlengthatleast(y, s->m, _state);
15029 0 : n = s->n;
15030 0 : m = s->m;
15031 0 : if( s->matrixtype==1 )
15032 : {
15033 :
15034 : /*
15035 : * CRS format.
15036 : * Perform integrity check.
15037 : */
15038 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseMV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
15039 :
15040 : /*
15041 : * Try vendor kernels
15042 : */
15043 0 : if( sparsegemvcrsmkl(0, s->m, s->n, 1.0, &s->vals, &s->idx, &s->ridx, x, 0, 0.0, y, 0, _state) )
15044 : {
15045 0 : return;
15046 : }
15047 :
15048 : /*
15049 : * Our own implementation
15050 : */
15051 0 : for(i=0; i<=m-1; i++)
15052 : {
15053 0 : tval = (double)(0);
15054 0 : lt = s->ridx.ptr.p_int[i];
15055 0 : rt = s->ridx.ptr.p_int[i+1]-1;
15056 0 : for(j=lt; j<=rt; j++)
15057 : {
15058 0 : tval = tval+x->ptr.p_double[s->idx.ptr.p_int[j]]*s->vals.ptr.p_double[j];
15059 : }
15060 0 : y->ptr.p_double[i] = tval;
15061 : }
15062 0 : return;
15063 : }
15064 0 : if( s->matrixtype==2 )
15065 : {
15066 :
15067 : /*
15068 : * SKS format
15069 : */
15070 0 : ae_assert(s->m==s->n, "SparseMV: non-square SKS matrices are not supported", _state);
15071 0 : for(i=0; i<=n-1; i++)
15072 : {
15073 0 : ri = s->ridx.ptr.p_int[i];
15074 0 : ri1 = s->ridx.ptr.p_int[i+1];
15075 0 : d = s->didx.ptr.p_int[i];
15076 0 : u = s->uidx.ptr.p_int[i];
15077 0 : v = s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i];
15078 0 : if( d>0 )
15079 : {
15080 0 : lt = ri;
15081 0 : rt = ri+d-1;
15082 0 : lt1 = i-d;
15083 0 : rt1 = i-1;
15084 0 : vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt));
15085 0 : v = v+vv;
15086 : }
15087 0 : y->ptr.p_double[i] = v;
15088 0 : if( u>0 )
15089 : {
15090 0 : lt = ri1-u;
15091 0 : rt = ri1-1;
15092 0 : lt1 = i-u;
15093 0 : rt1 = i-1;
15094 0 : v = x->ptr.p_double[i];
15095 0 : ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v);
15096 : }
15097 : }
15098 0 : return;
15099 : }
15100 : }
15101 :
15102 :
15103 : /*************************************************************************
15104 : This function calculates matrix-vector product S^T*x. Matrix S must be
15105 : stored in CRS or SKS format (exception will be thrown otherwise).
15106 :
15107 : INPUT PARAMETERS
15108 : S - sparse M*N matrix in CRS or SKS format.
15109 : X - array[M], input vector. For performance reasons we
15110 : make only quick checks - we check that array size is
15111 : at least M, but we do not check for NAN's or INF's.
15112 : Y - output buffer, possibly preallocated. In case buffer
15113 : size is too small to store result, this buffer is
15114 : automatically resized.
15115 :
15116 : OUTPUT PARAMETERS
15117 : Y - array[N], S^T*x
15118 :
15119 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
15120 : You must convert your matrix with SparseConvertToCRS/SKS() before using
15121 : this function.
15122 :
15123 : -- ALGLIB PROJECT --
15124 : Copyright 14.10.2011 by Bochkanov Sergey
15125 : *************************************************************************/
15126 0 : void sparsemtv(sparsematrix* s,
15127 : /* Real */ ae_vector* x,
15128 : /* Real */ ae_vector* y,
15129 : ae_state *_state)
15130 : {
15131 : ae_int_t i;
15132 : ae_int_t j;
15133 : ae_int_t lt;
15134 : ae_int_t rt;
15135 : ae_int_t ct;
15136 : ae_int_t lt1;
15137 : ae_int_t rt1;
15138 : double v;
15139 : double vv;
15140 : ae_int_t n;
15141 : ae_int_t m;
15142 : ae_int_t ri;
15143 : ae_int_t ri1;
15144 : ae_int_t d;
15145 : ae_int_t u;
15146 :
15147 :
15148 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseMTV: incorrect matrix type (convert your matrix to CRS/SKS)", _state);
15149 0 : ae_assert(x->cnt>=s->m, "SparseMTV: Length(X)<M", _state);
15150 0 : n = s->n;
15151 0 : m = s->m;
15152 0 : rvectorsetlengthatleast(y, n, _state);
15153 0 : for(i=0; i<=n-1; i++)
15154 : {
15155 0 : y->ptr.p_double[i] = (double)(0);
15156 : }
15157 0 : if( s->matrixtype==1 )
15158 : {
15159 :
15160 : /*
15161 : * CRS format
15162 : * Perform integrity check.
15163 : */
15164 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[m], "SparseMTV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
15165 :
15166 : /*
15167 : * Try vendor kernels
15168 : */
15169 0 : if( sparsegemvcrsmkl(1, s->m, s->n, 1.0, &s->vals, &s->idx, &s->ridx, x, 0, 0.0, y, 0, _state) )
15170 : {
15171 0 : return;
15172 : }
15173 :
15174 : /*
15175 : * Our own implementation
15176 : */
15177 0 : for(i=0; i<=m-1; i++)
15178 : {
15179 0 : lt = s->ridx.ptr.p_int[i];
15180 0 : rt = s->ridx.ptr.p_int[i+1];
15181 0 : v = x->ptr.p_double[i];
15182 0 : for(j=lt; j<=rt-1; j++)
15183 : {
15184 0 : ct = s->idx.ptr.p_int[j];
15185 0 : y->ptr.p_double[ct] = y->ptr.p_double[ct]+v*s->vals.ptr.p_double[j];
15186 : }
15187 : }
15188 0 : return;
15189 : }
15190 0 : if( s->matrixtype==2 )
15191 : {
15192 :
15193 : /*
15194 : * SKS format
15195 : */
15196 0 : ae_assert(s->m==s->n, "SparseMV: non-square SKS matrices are not supported", _state);
15197 0 : for(i=0; i<=n-1; i++)
15198 : {
15199 0 : ri = s->ridx.ptr.p_int[i];
15200 0 : ri1 = s->ridx.ptr.p_int[i+1];
15201 0 : d = s->didx.ptr.p_int[i];
15202 0 : u = s->uidx.ptr.p_int[i];
15203 0 : if( d>0 )
15204 : {
15205 0 : lt = ri;
15206 0 : rt = ri+d-1;
15207 0 : lt1 = i-d;
15208 0 : rt1 = i-1;
15209 0 : v = x->ptr.p_double[i];
15210 0 : ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v);
15211 : }
15212 0 : v = s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i];
15213 0 : if( u>0 )
15214 : {
15215 0 : lt = ri1-u;
15216 0 : rt = ri1-1;
15217 0 : lt1 = i-u;
15218 0 : rt1 = i-1;
15219 0 : vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt));
15220 0 : v = v+vv;
15221 : }
15222 0 : y->ptr.p_double[i] = v;
15223 : }
15224 0 : return;
15225 : }
15226 : }
15227 :
15228 :
15229 : /*************************************************************************
15230 : This function calculates generalized sparse matrix-vector product
15231 :
15232 : y := alpha*op(S)*x + beta*y
15233 :
15234 : Matrix S must be stored in CRS or SKS format (exception will be thrown
15235 : otherwise). op(S) can be either S or S^T.
15236 :
15237 : NOTE: this function expects Y to be large enough to store result. No
15238 : automatic preallocation happens for smaller arrays.
15239 :
15240 : INPUT PARAMETERS
15241 : S - sparse matrix in CRS or SKS format.
15242 : Alpha - source coefficient
15243 : OpS - operation type:
15244 : * OpS=0 => op(S) = S
15245 : * OpS=1 => op(S) = S^T
15246 : X - input vector, must have at least Cols(op(S))+IX elements
15247 : IX - subvector offset
15248 : Beta - destination coefficient
15249 : Y - preallocated output array, must have at least Rows(op(S))+IY elements
15250 : IY - subvector offset
15251 :
15252 : OUTPUT PARAMETERS
15253 : Y - elements [IY...IY+Rows(op(S))-1] are replaced by result,
15254 : other elements are not modified
15255 :
15256 : HANDLING OF SPECIAL CASES:
15257 : * below M=Rows(op(S)) and N=Cols(op(S)). Although current ALGLIB version
15258 : does not allow you to create zero-sized sparse matrices, internally
15259 : ALGLIB can deal with such matrices. So, comments for M or N equal to
15260 : zero are for internal use only.
15261 : * if M=0, then subroutine does nothing. It does not even touch arrays.
15262 : * if N=0 or Alpha=0.0, then:
15263 : * if Beta=0, then Y is filled by zeros. S and X are not referenced at
15264 : all. Initial values of Y are ignored (we do not multiply Y by zero,
15265 : we just rewrite it by zeros)
15266 : * if Beta<>0, then Y is replaced by Beta*Y
15267 : * if M>0, N>0, Alpha<>0, but Beta=0, then Y is replaced by alpha*op(S)*x
15268 : initial state of Y is ignored (rewritten without initial multiplication
15269 : by zeros).
15270 :
15271 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
15272 : You must convert your matrix with SparseConvertToCRS/SKS() before using
15273 : this function.
15274 :
15275 : -- ALGLIB PROJECT --
15276 : Copyright 10.12.2019 by Bochkanov Sergey
15277 : *************************************************************************/
15278 0 : void sparsegemv(sparsematrix* s,
15279 : double alpha,
15280 : ae_int_t ops,
15281 : /* Real */ ae_vector* x,
15282 : ae_int_t ix,
15283 : double beta,
15284 : /* Real */ ae_vector* y,
15285 : ae_int_t iy,
15286 : ae_state *_state)
15287 : {
15288 : ae_int_t opm;
15289 : ae_int_t opn;
15290 : ae_int_t rawm;
15291 : ae_int_t rawn;
15292 : ae_int_t i;
15293 : ae_int_t j;
15294 : double tval;
15295 : ae_int_t lt;
15296 : ae_int_t rt;
15297 : ae_int_t ct;
15298 : ae_int_t d;
15299 : ae_int_t u;
15300 : ae_int_t ri;
15301 : ae_int_t ri1;
15302 : double v;
15303 : double vv;
15304 : ae_int_t lt1;
15305 : ae_int_t rt1;
15306 :
15307 :
15308 0 : ae_assert(ops==0||ops==1, "SparseGEMV: incorrect OpS", _state);
15309 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseGEMV: incorrect matrix type (convert your matrix to CRS/SKS)", _state);
15310 0 : if( ops==0 )
15311 : {
15312 0 : opm = s->m;
15313 0 : opn = s->n;
15314 : }
15315 : else
15316 : {
15317 0 : opm = s->n;
15318 0 : opn = s->m;
15319 : }
15320 0 : ae_assert(opm>=0&&opn>=0, "SparseGEMV: op(S) has negative size", _state);
15321 0 : ae_assert(opn==0||x->cnt+ix>=opn, "SparseGEMV: X is too short", _state);
15322 0 : ae_assert(opm==0||y->cnt+iy>=opm, "SparseGEMV: X is too short", _state);
15323 0 : rawm = s->m;
15324 0 : rawn = s->n;
15325 :
15326 : /*
15327 : * Quick exit strategies
15328 : */
15329 0 : if( opm==0 )
15330 : {
15331 0 : return;
15332 : }
15333 0 : if( ae_fp_neq(beta,(double)(0)) )
15334 : {
15335 0 : for(i=0; i<=opm-1; i++)
15336 : {
15337 0 : y->ptr.p_double[iy+i] = beta*y->ptr.p_double[iy+i];
15338 : }
15339 : }
15340 : else
15341 : {
15342 0 : for(i=0; i<=opm-1; i++)
15343 : {
15344 0 : y->ptr.p_double[iy+i] = 0.0;
15345 : }
15346 : }
15347 0 : if( opn==0||ae_fp_eq(alpha,(double)(0)) )
15348 : {
15349 0 : return;
15350 : }
15351 :
15352 : /*
15353 : * Now we have OpM>=1, OpN>=1, Alpha<>0
15354 : */
15355 0 : if( ops==0 )
15356 : {
15357 :
15358 : /*
15359 : * Compute generalized product y := alpha*S*x + beta*y
15360 : * (with "beta*y" part already computed).
15361 : */
15362 0 : if( s->matrixtype==1 )
15363 : {
15364 :
15365 : /*
15366 : * CRS format.
15367 : * Perform integrity check.
15368 : */
15369 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseGEMV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
15370 :
15371 : /*
15372 : * Try vendor kernels
15373 : */
15374 0 : if( sparsegemvcrsmkl(0, s->m, s->n, alpha, &s->vals, &s->idx, &s->ridx, x, ix, 1.0, y, iy, _state) )
15375 : {
15376 0 : return;
15377 : }
15378 :
15379 : /*
15380 : * Our own implementation
15381 : */
15382 0 : for(i=0; i<=rawm-1; i++)
15383 : {
15384 0 : tval = (double)(0);
15385 0 : lt = s->ridx.ptr.p_int[i];
15386 0 : rt = s->ridx.ptr.p_int[i+1]-1;
15387 0 : for(j=lt; j<=rt; j++)
15388 : {
15389 0 : tval = tval+x->ptr.p_double[s->idx.ptr.p_int[j]+ix]*s->vals.ptr.p_double[j];
15390 : }
15391 0 : y->ptr.p_double[i+iy] = alpha*tval+y->ptr.p_double[i+iy];
15392 : }
15393 0 : return;
15394 : }
15395 0 : if( s->matrixtype==2 )
15396 : {
15397 :
15398 : /*
15399 : * SKS format
15400 : */
15401 0 : ae_assert(s->m==s->n, "SparseMV: non-square SKS matrices are not supported", _state);
15402 0 : for(i=0; i<=rawn-1; i++)
15403 : {
15404 0 : ri = s->ridx.ptr.p_int[i];
15405 0 : ri1 = s->ridx.ptr.p_int[i+1];
15406 0 : d = s->didx.ptr.p_int[i];
15407 0 : u = s->uidx.ptr.p_int[i];
15408 0 : v = s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i+ix];
15409 0 : if( d>0 )
15410 : {
15411 0 : lt = ri;
15412 0 : rt = ri+d-1;
15413 0 : lt1 = i-d+ix;
15414 0 : rt1 = i-1+ix;
15415 0 : vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt));
15416 0 : v = v+vv;
15417 : }
15418 0 : y->ptr.p_double[i+iy] = alpha*v+y->ptr.p_double[i+iy];
15419 0 : if( u>0 )
15420 : {
15421 0 : lt = ri1-u;
15422 0 : rt = ri1-1;
15423 0 : lt1 = i-u+iy;
15424 0 : rt1 = i-1+iy;
15425 0 : v = alpha*x->ptr.p_double[i+ix];
15426 0 : ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v);
15427 : }
15428 : }
15429 0 : return;
15430 : }
15431 : }
15432 : else
15433 : {
15434 :
15435 : /*
15436 : * Compute generalized product y := alpha*S^T*x + beta*y
15437 : * (with "beta*y" part already computed).
15438 : */
15439 0 : if( s->matrixtype==1 )
15440 : {
15441 :
15442 : /*
15443 : * CRS format
15444 : * Perform integrity check.
15445 : */
15446 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseGEMV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
15447 :
15448 : /*
15449 : * Try vendor kernels
15450 : */
15451 0 : if( sparsegemvcrsmkl(1, s->m, s->n, alpha, &s->vals, &s->idx, &s->ridx, x, ix, 1.0, y, iy, _state) )
15452 : {
15453 0 : return;
15454 : }
15455 :
15456 : /*
15457 : * Our own implementation
15458 : */
15459 0 : for(i=0; i<=rawm-1; i++)
15460 : {
15461 0 : lt = s->ridx.ptr.p_int[i];
15462 0 : rt = s->ridx.ptr.p_int[i+1];
15463 0 : v = alpha*x->ptr.p_double[i+ix];
15464 0 : for(j=lt; j<=rt-1; j++)
15465 : {
15466 0 : ct = s->idx.ptr.p_int[j]+iy;
15467 0 : y->ptr.p_double[ct] = y->ptr.p_double[ct]+v*s->vals.ptr.p_double[j];
15468 : }
15469 : }
15470 0 : return;
15471 : }
15472 0 : if( s->matrixtype==2 )
15473 : {
15474 :
15475 : /*
15476 : * SKS format
15477 : */
15478 0 : ae_assert(s->m==s->n, "SparseGEMV: non-square SKS matrices are not supported", _state);
15479 0 : for(i=0; i<=rawn-1; i++)
15480 : {
15481 0 : ri = s->ridx.ptr.p_int[i];
15482 0 : ri1 = s->ridx.ptr.p_int[i+1];
15483 0 : d = s->didx.ptr.p_int[i];
15484 0 : u = s->uidx.ptr.p_int[i];
15485 0 : if( d>0 )
15486 : {
15487 0 : lt = ri;
15488 0 : rt = ri+d-1;
15489 0 : lt1 = i-d+iy;
15490 0 : rt1 = i-1+iy;
15491 0 : v = alpha*x->ptr.p_double[i+ix];
15492 0 : ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v);
15493 : }
15494 0 : v = alpha*s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i+ix];
15495 0 : if( u>0 )
15496 : {
15497 0 : lt = ri1-u;
15498 0 : rt = ri1-1;
15499 0 : lt1 = i-u+ix;
15500 0 : rt1 = i-1+ix;
15501 0 : vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt));
15502 0 : v = v+alpha*vv;
15503 : }
15504 0 : y->ptr.p_double[i+iy] = v+y->ptr.p_double[i+iy];
15505 : }
15506 0 : return;
15507 : }
15508 : }
15509 : }
15510 :
15511 :
15512 : /*************************************************************************
15513 : This function simultaneously calculates two matrix-vector products:
15514 : S*x and S^T*x.
15515 : S must be square (non-rectangular) matrix stored in CRS or SKS format
15516 : (exception will be thrown otherwise).
15517 :
15518 : INPUT PARAMETERS
15519 : S - sparse N*N matrix in CRS or SKS format.
15520 : X - array[N], input vector. For performance reasons we
15521 : make only quick checks - we check that array size is
15522 : at least N, but we do not check for NAN's or INF's.
15523 : Y0 - output buffer, possibly preallocated. In case buffer
15524 : size is too small to store result, this buffer is
15525 : automatically resized.
15526 : Y1 - output buffer, possibly preallocated. In case buffer
15527 : size is too small to store result, this buffer is
15528 : automatically resized.
15529 :
15530 : OUTPUT PARAMETERS
15531 : Y0 - array[N], S*x
15532 : Y1 - array[N], S^T*x
15533 :
15534 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
15535 : You must convert your matrix with SparseConvertToCRS/SKS() before using
15536 : this function.
15537 :
15538 : -- ALGLIB PROJECT --
15539 : Copyright 14.10.2011 by Bochkanov Sergey
15540 : *************************************************************************/
15541 0 : void sparsemv2(sparsematrix* s,
15542 : /* Real */ ae_vector* x,
15543 : /* Real */ ae_vector* y0,
15544 : /* Real */ ae_vector* y1,
15545 : ae_state *_state)
15546 : {
15547 : ae_int_t l;
15548 : double tval;
15549 : ae_int_t i;
15550 : ae_int_t j;
15551 : double vx;
15552 : double vs;
15553 : double v;
15554 : double vv;
15555 : double vd0;
15556 : double vd1;
15557 : ae_int_t vi;
15558 : ae_int_t j0;
15559 : ae_int_t j1;
15560 : ae_int_t n;
15561 : ae_int_t ri;
15562 : ae_int_t ri1;
15563 : ae_int_t d;
15564 : ae_int_t u;
15565 : ae_int_t lt;
15566 : ae_int_t rt;
15567 : ae_int_t lt1;
15568 : ae_int_t rt1;
15569 :
15570 :
15571 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseMV2: incorrect matrix type (convert your matrix to CRS/SKS)", _state);
15572 0 : ae_assert(s->m==s->n, "SparseMV2: matrix is non-square", _state);
15573 0 : l = x->cnt;
15574 0 : ae_assert(l>=s->n, "SparseMV2: Length(X)<N", _state);
15575 0 : n = s->n;
15576 0 : rvectorsetlengthatleast(y0, l, _state);
15577 0 : rvectorsetlengthatleast(y1, l, _state);
15578 0 : for(i=0; i<=n-1; i++)
15579 : {
15580 0 : y0->ptr.p_double[i] = (double)(0);
15581 0 : y1->ptr.p_double[i] = (double)(0);
15582 : }
15583 0 : if( s->matrixtype==1 )
15584 : {
15585 :
15586 : /*
15587 : * CRS format
15588 : */
15589 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseMV2: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
15590 0 : for(i=0; i<=s->m-1; i++)
15591 : {
15592 0 : tval = (double)(0);
15593 0 : vx = x->ptr.p_double[i];
15594 0 : j0 = s->ridx.ptr.p_int[i];
15595 0 : j1 = s->ridx.ptr.p_int[i+1]-1;
15596 0 : for(j=j0; j<=j1; j++)
15597 : {
15598 0 : vi = s->idx.ptr.p_int[j];
15599 0 : vs = s->vals.ptr.p_double[j];
15600 0 : tval = tval+x->ptr.p_double[vi]*vs;
15601 0 : y1->ptr.p_double[vi] = y1->ptr.p_double[vi]+vx*vs;
15602 : }
15603 0 : y0->ptr.p_double[i] = tval;
15604 : }
15605 0 : return;
15606 : }
15607 0 : if( s->matrixtype==2 )
15608 : {
15609 :
15610 : /*
15611 : * SKS format
15612 : */
15613 0 : for(i=0; i<=n-1; i++)
15614 : {
15615 0 : ri = s->ridx.ptr.p_int[i];
15616 0 : ri1 = s->ridx.ptr.p_int[i+1];
15617 0 : d = s->didx.ptr.p_int[i];
15618 0 : u = s->uidx.ptr.p_int[i];
15619 0 : vd0 = s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i];
15620 0 : vd1 = vd0;
15621 0 : if( d>0 )
15622 : {
15623 0 : lt = ri;
15624 0 : rt = ri+d-1;
15625 0 : lt1 = i-d;
15626 0 : rt1 = i-1;
15627 0 : v = x->ptr.p_double[i];
15628 0 : ae_v_addd(&y1->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v);
15629 0 : vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt));
15630 0 : vd0 = vd0+vv;
15631 : }
15632 0 : if( u>0 )
15633 : {
15634 0 : lt = ri1-u;
15635 0 : rt = ri1-1;
15636 0 : lt1 = i-u;
15637 0 : rt1 = i-1;
15638 0 : v = x->ptr.p_double[i];
15639 0 : ae_v_addd(&y0->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v);
15640 0 : vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt));
15641 0 : vd1 = vd1+vv;
15642 : }
15643 0 : y0->ptr.p_double[i] = vd0;
15644 0 : y1->ptr.p_double[i] = vd1;
15645 : }
15646 0 : return;
15647 : }
15648 : }
15649 :
15650 :
15651 : /*************************************************************************
15652 : This function calculates matrix-vector product S*x, when S is symmetric
15653 : matrix. Matrix S must be stored in CRS or SKS format (exception will be
15654 : thrown otherwise).
15655 :
15656 : INPUT PARAMETERS
15657 : S - sparse M*M matrix in CRS or SKS format.
15658 : IsUpper - whether upper or lower triangle of S is given:
15659 : * if upper triangle is given, only S[i,j] for j>=i
15660 : are used, and lower triangle is ignored (it can be
15661 : empty - these elements are not referenced at all).
15662 : * if lower triangle is given, only S[i,j] for j<=i
15663 : are used, and upper triangle is ignored.
15664 : X - array[N], input vector. For performance reasons we
15665 : make only quick checks - we check that array size is
15666 : at least N, but we do not check for NAN's or INF's.
15667 : Y - output buffer, possibly preallocated. In case buffer
15668 : size is too small to store result, this buffer is
15669 : automatically resized.
15670 :
15671 : OUTPUT PARAMETERS
15672 : Y - array[M], S*x
15673 :
15674 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
15675 : You must convert your matrix with SparseConvertToCRS/SKS() before using
15676 : this function.
15677 :
15678 : -- ALGLIB PROJECT --
15679 : Copyright 14.10.2011 by Bochkanov Sergey
15680 : *************************************************************************/
15681 0 : void sparsesmv(sparsematrix* s,
15682 : ae_bool isupper,
15683 : /* Real */ ae_vector* x,
15684 : /* Real */ ae_vector* y,
15685 : ae_state *_state)
15686 : {
15687 : ae_int_t n;
15688 : ae_int_t i;
15689 : ae_int_t j;
15690 : ae_int_t id;
15691 : ae_int_t lt;
15692 : ae_int_t rt;
15693 : double v;
15694 : double vv;
15695 : double vy;
15696 : double vx;
15697 : double vd;
15698 : ae_int_t ri;
15699 : ae_int_t ri1;
15700 : ae_int_t d;
15701 : ae_int_t u;
15702 : ae_int_t lt1;
15703 : ae_int_t rt1;
15704 :
15705 :
15706 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseSMV: incorrect matrix type (convert your matrix to CRS/SKS)", _state);
15707 0 : ae_assert(x->cnt>=s->n, "SparseSMV: length(X)<N", _state);
15708 0 : ae_assert(s->m==s->n, "SparseSMV: non-square matrix", _state);
15709 0 : n = s->n;
15710 0 : rvectorsetlengthatleast(y, n, _state);
15711 0 : for(i=0; i<=n-1; i++)
15712 : {
15713 0 : y->ptr.p_double[i] = (double)(0);
15714 : }
15715 0 : if( s->matrixtype==1 )
15716 : {
15717 :
15718 : /*
15719 : * CRS format
15720 : */
15721 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseSMV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
15722 0 : for(i=0; i<=n-1; i++)
15723 : {
15724 0 : if( s->didx.ptr.p_int[i]!=s->uidx.ptr.p_int[i] )
15725 : {
15726 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+s->vals.ptr.p_double[s->didx.ptr.p_int[i]]*x->ptr.p_double[s->idx.ptr.p_int[s->didx.ptr.p_int[i]]];
15727 : }
15728 0 : if( isupper )
15729 : {
15730 0 : lt = s->uidx.ptr.p_int[i];
15731 0 : rt = s->ridx.ptr.p_int[i+1];
15732 0 : vy = (double)(0);
15733 0 : vx = x->ptr.p_double[i];
15734 0 : for(j=lt; j<=rt-1; j++)
15735 : {
15736 0 : id = s->idx.ptr.p_int[j];
15737 0 : v = s->vals.ptr.p_double[j];
15738 0 : vy = vy+x->ptr.p_double[id]*v;
15739 0 : y->ptr.p_double[id] = y->ptr.p_double[id]+vx*v;
15740 : }
15741 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+vy;
15742 : }
15743 : else
15744 : {
15745 0 : lt = s->ridx.ptr.p_int[i];
15746 0 : rt = s->didx.ptr.p_int[i];
15747 0 : vy = (double)(0);
15748 0 : vx = x->ptr.p_double[i];
15749 0 : for(j=lt; j<=rt-1; j++)
15750 : {
15751 0 : id = s->idx.ptr.p_int[j];
15752 0 : v = s->vals.ptr.p_double[j];
15753 0 : vy = vy+x->ptr.p_double[id]*v;
15754 0 : y->ptr.p_double[id] = y->ptr.p_double[id]+vx*v;
15755 : }
15756 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+vy;
15757 : }
15758 : }
15759 0 : return;
15760 : }
15761 0 : if( s->matrixtype==2 )
15762 : {
15763 :
15764 : /*
15765 : * SKS format
15766 : */
15767 0 : for(i=0; i<=n-1; i++)
15768 : {
15769 0 : ri = s->ridx.ptr.p_int[i];
15770 0 : ri1 = s->ridx.ptr.p_int[i+1];
15771 0 : d = s->didx.ptr.p_int[i];
15772 0 : u = s->uidx.ptr.p_int[i];
15773 0 : vd = s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i];
15774 0 : if( d>0&&!isupper )
15775 : {
15776 0 : lt = ri;
15777 0 : rt = ri+d-1;
15778 0 : lt1 = i-d;
15779 0 : rt1 = i-1;
15780 0 : v = x->ptr.p_double[i];
15781 0 : ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v);
15782 0 : vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt));
15783 0 : vd = vd+vv;
15784 : }
15785 0 : if( u>0&&isupper )
15786 : {
15787 0 : lt = ri1-u;
15788 0 : rt = ri1-1;
15789 0 : lt1 = i-u;
15790 0 : rt1 = i-1;
15791 0 : v = x->ptr.p_double[i];
15792 0 : ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v);
15793 0 : vv = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt));
15794 0 : vd = vd+vv;
15795 : }
15796 0 : y->ptr.p_double[i] = vd;
15797 : }
15798 0 : return;
15799 : }
15800 : }
15801 :
15802 :
15803 : /*************************************************************************
15804 : This function calculates vector-matrix-vector product x'*S*x, where S is
15805 : symmetric matrix. Matrix S must be stored in CRS or SKS format (exception
15806 : will be thrown otherwise).
15807 :
15808 : INPUT PARAMETERS
15809 : S - sparse M*M matrix in CRS or SKS format.
15810 : IsUpper - whether upper or lower triangle of S is given:
15811 : * if upper triangle is given, only S[i,j] for j>=i
15812 : are used, and lower triangle is ignored (it can be
15813 : empty - these elements are not referenced at all).
15814 : * if lower triangle is given, only S[i,j] for j<=i
15815 : are used, and upper triangle is ignored.
15816 : X - array[N], input vector. For performance reasons we
15817 : make only quick checks - we check that array size is
15818 : at least N, but we do not check for NAN's or INF's.
15819 :
15820 : RESULT
15821 : x'*S*x
15822 :
15823 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
15824 : You must convert your matrix with SparseConvertToCRS/SKS() before using
15825 : this function.
15826 :
15827 : -- ALGLIB PROJECT --
15828 : Copyright 27.01.2014 by Bochkanov Sergey
15829 : *************************************************************************/
15830 0 : double sparsevsmv(sparsematrix* s,
15831 : ae_bool isupper,
15832 : /* Real */ ae_vector* x,
15833 : ae_state *_state)
15834 : {
15835 : ae_int_t n;
15836 : ae_int_t i;
15837 : ae_int_t j;
15838 : ae_int_t k;
15839 : ae_int_t id;
15840 : ae_int_t lt;
15841 : ae_int_t rt;
15842 : double v;
15843 : double v0;
15844 : double v1;
15845 : ae_int_t ri;
15846 : ae_int_t ri1;
15847 : ae_int_t d;
15848 : ae_int_t u;
15849 : ae_int_t lt1;
15850 : double result;
15851 :
15852 :
15853 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseVSMV: incorrect matrix type (convert your matrix to CRS/SKS)", _state);
15854 0 : ae_assert(x->cnt>=s->n, "SparseVSMV: length(X)<N", _state);
15855 0 : ae_assert(s->m==s->n, "SparseVSMV: non-square matrix", _state);
15856 0 : n = s->n;
15857 0 : result = 0.0;
15858 0 : if( s->matrixtype==1 )
15859 : {
15860 :
15861 : /*
15862 : * CRS format
15863 : */
15864 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseVSMV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
15865 0 : for(i=0; i<=n-1; i++)
15866 : {
15867 0 : if( s->didx.ptr.p_int[i]!=s->uidx.ptr.p_int[i] )
15868 : {
15869 0 : v = x->ptr.p_double[s->idx.ptr.p_int[s->didx.ptr.p_int[i]]];
15870 0 : result = result+v*s->vals.ptr.p_double[s->didx.ptr.p_int[i]]*v;
15871 : }
15872 0 : if( isupper )
15873 : {
15874 0 : lt = s->uidx.ptr.p_int[i];
15875 0 : rt = s->ridx.ptr.p_int[i+1];
15876 : }
15877 : else
15878 : {
15879 0 : lt = s->ridx.ptr.p_int[i];
15880 0 : rt = s->didx.ptr.p_int[i];
15881 : }
15882 0 : v0 = x->ptr.p_double[i];
15883 0 : for(j=lt; j<=rt-1; j++)
15884 : {
15885 0 : id = s->idx.ptr.p_int[j];
15886 0 : v1 = x->ptr.p_double[id];
15887 0 : v = s->vals.ptr.p_double[j];
15888 0 : result = result+2*v0*v1*v;
15889 : }
15890 : }
15891 0 : return result;
15892 : }
15893 0 : if( s->matrixtype==2 )
15894 : {
15895 :
15896 : /*
15897 : * SKS format
15898 : */
15899 0 : for(i=0; i<=n-1; i++)
15900 : {
15901 0 : ri = s->ridx.ptr.p_int[i];
15902 0 : ri1 = s->ridx.ptr.p_int[i+1];
15903 0 : d = s->didx.ptr.p_int[i];
15904 0 : u = s->uidx.ptr.p_int[i];
15905 0 : v = x->ptr.p_double[i];
15906 0 : result = result+v*s->vals.ptr.p_double[ri+d]*v;
15907 0 : if( d>0&&!isupper )
15908 : {
15909 0 : lt = ri;
15910 0 : rt = ri+d-1;
15911 0 : lt1 = i-d;
15912 0 : k = d-1;
15913 0 : v0 = x->ptr.p_double[i];
15914 0 : v = 0.0;
15915 0 : for(j=0; j<=k; j++)
15916 : {
15917 0 : v = v+x->ptr.p_double[lt1+j]*s->vals.ptr.p_double[lt+j];
15918 : }
15919 0 : result = result+2*v0*v;
15920 : }
15921 0 : if( u>0&&isupper )
15922 : {
15923 0 : lt = ri1-u;
15924 0 : rt = ri1-1;
15925 0 : lt1 = i-u;
15926 0 : k = u-1;
15927 0 : v0 = x->ptr.p_double[i];
15928 0 : v = 0.0;
15929 0 : for(j=0; j<=k; j++)
15930 : {
15931 0 : v = v+x->ptr.p_double[lt1+j]*s->vals.ptr.p_double[lt+j];
15932 : }
15933 0 : result = result+2*v0*v;
15934 : }
15935 : }
15936 0 : return result;
15937 : }
15938 0 : return result;
15939 : }
15940 :
15941 :
15942 : /*************************************************************************
15943 : This function calculates matrix-matrix product S*A. Matrix S must be
15944 : stored in CRS or SKS format (exception will be thrown otherwise).
15945 :
15946 : INPUT PARAMETERS
15947 : S - sparse M*N matrix in CRS or SKS format.
15948 : A - array[N][K], input dense matrix. For performance reasons
15949 : we make only quick checks - we check that array size
15950 : is at least N, but we do not check for NAN's or INF's.
15951 : K - number of columns of matrix (A).
15952 : B - output buffer, possibly preallocated. In case buffer
15953 : size is too small to store result, this buffer is
15954 : automatically resized.
15955 :
15956 : OUTPUT PARAMETERS
15957 : B - array[M][K], S*A
15958 :
15959 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
15960 : You must convert your matrix with SparseConvertToCRS/SKS() before using
15961 : this function.
15962 :
15963 : -- ALGLIB PROJECT --
15964 : Copyright 14.10.2011 by Bochkanov Sergey
15965 : *************************************************************************/
15966 0 : void sparsemm(sparsematrix* s,
15967 : /* Real */ ae_matrix* a,
15968 : ae_int_t k,
15969 : /* Real */ ae_matrix* b,
15970 : ae_state *_state)
15971 : {
15972 : double tval;
15973 : double v;
15974 : ae_int_t id;
15975 : ae_int_t i;
15976 : ae_int_t j;
15977 : ae_int_t k0;
15978 : ae_int_t k1;
15979 : ae_int_t lt;
15980 : ae_int_t rt;
15981 : ae_int_t m;
15982 : ae_int_t n;
15983 : ae_int_t ri;
15984 : ae_int_t ri1;
15985 : ae_int_t lt1;
15986 : ae_int_t rt1;
15987 : ae_int_t d;
15988 : ae_int_t u;
15989 : double vd;
15990 :
15991 :
15992 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseMM: incorrect matrix type (convert your matrix to CRS/SKS)", _state);
15993 0 : ae_assert(a->rows>=s->n, "SparseMM: Rows(A)<N", _state);
15994 0 : ae_assert(k>0, "SparseMM: K<=0", _state);
15995 0 : m = s->m;
15996 0 : n = s->n;
15997 0 : k1 = k-1;
15998 0 : rmatrixsetlengthatleast(b, m, k, _state);
15999 0 : for(i=0; i<=m-1; i++)
16000 : {
16001 0 : for(j=0; j<=k-1; j++)
16002 : {
16003 0 : b->ptr.pp_double[i][j] = (double)(0);
16004 : }
16005 : }
16006 0 : if( s->matrixtype==1 )
16007 : {
16008 :
16009 : /*
16010 : * CRS format
16011 : */
16012 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[m], "SparseMM: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
16013 0 : if( k<sparse_linalgswitch )
16014 : {
16015 0 : for(i=0; i<=m-1; i++)
16016 : {
16017 0 : for(j=0; j<=k-1; j++)
16018 : {
16019 0 : tval = (double)(0);
16020 0 : lt = s->ridx.ptr.p_int[i];
16021 0 : rt = s->ridx.ptr.p_int[i+1];
16022 0 : for(k0=lt; k0<=rt-1; k0++)
16023 : {
16024 0 : tval = tval+s->vals.ptr.p_double[k0]*a->ptr.pp_double[s->idx.ptr.p_int[k0]][j];
16025 : }
16026 0 : b->ptr.pp_double[i][j] = tval;
16027 : }
16028 : }
16029 : }
16030 : else
16031 : {
16032 0 : for(i=0; i<=m-1; i++)
16033 : {
16034 0 : lt = s->ridx.ptr.p_int[i];
16035 0 : rt = s->ridx.ptr.p_int[i+1];
16036 0 : for(j=lt; j<=rt-1; j++)
16037 : {
16038 0 : id = s->idx.ptr.p_int[j];
16039 0 : v = s->vals.ptr.p_double[j];
16040 0 : ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[id][0], 1, ae_v_len(0,k-1), v);
16041 : }
16042 : }
16043 : }
16044 0 : return;
16045 : }
16046 0 : if( s->matrixtype==2 )
16047 : {
16048 :
16049 : /*
16050 : * SKS format
16051 : */
16052 0 : ae_assert(m==n, "SparseMM: non-square SKS matrices are not supported", _state);
16053 0 : for(i=0; i<=n-1; i++)
16054 : {
16055 0 : ri = s->ridx.ptr.p_int[i];
16056 0 : ri1 = s->ridx.ptr.p_int[i+1];
16057 0 : d = s->didx.ptr.p_int[i];
16058 0 : u = s->uidx.ptr.p_int[i];
16059 0 : if( d>0 )
16060 : {
16061 0 : lt = ri;
16062 0 : rt = ri+d-1;
16063 0 : lt1 = i-d;
16064 0 : rt1 = i-1;
16065 0 : for(j=lt1; j<=rt1; j++)
16066 : {
16067 0 : v = s->vals.ptr.p_double[lt+(j-lt1)];
16068 0 : if( k<sparse_linalgswitch )
16069 : {
16070 :
16071 : /*
16072 : * Use loop
16073 : */
16074 0 : for(k0=0; k0<=k1; k0++)
16075 : {
16076 0 : b->ptr.pp_double[i][k0] = b->ptr.pp_double[i][k0]+v*a->ptr.pp_double[j][k0];
16077 : }
16078 : }
16079 : else
16080 : {
16081 :
16082 : /*
16083 : * Use vector operation
16084 : */
16085 0 : ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v);
16086 : }
16087 : }
16088 : }
16089 0 : if( u>0 )
16090 : {
16091 0 : lt = ri1-u;
16092 0 : rt = ri1-1;
16093 0 : lt1 = i-u;
16094 0 : rt1 = i-1;
16095 0 : for(j=lt1; j<=rt1; j++)
16096 : {
16097 0 : v = s->vals.ptr.p_double[lt+(j-lt1)];
16098 0 : if( k<sparse_linalgswitch )
16099 : {
16100 :
16101 : /*
16102 : * Use loop
16103 : */
16104 0 : for(k0=0; k0<=k1; k0++)
16105 : {
16106 0 : b->ptr.pp_double[j][k0] = b->ptr.pp_double[j][k0]+v*a->ptr.pp_double[i][k0];
16107 : }
16108 : }
16109 : else
16110 : {
16111 :
16112 : /*
16113 : * Use vector operation
16114 : */
16115 0 : ae_v_addd(&b->ptr.pp_double[j][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16116 : }
16117 : }
16118 : }
16119 0 : vd = s->vals.ptr.p_double[ri+d];
16120 0 : ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), vd);
16121 : }
16122 0 : return;
16123 : }
16124 : }
16125 :
16126 :
16127 : /*************************************************************************
16128 : This function calculates matrix-matrix product S^T*A. Matrix S must be
16129 : stored in CRS or SKS format (exception will be thrown otherwise).
16130 :
16131 : INPUT PARAMETERS
16132 : S - sparse M*N matrix in CRS or SKS format.
16133 : A - array[M][K], input dense matrix. For performance reasons
16134 : we make only quick checks - we check that array size is
16135 : at least M, but we do not check for NAN's or INF's.
16136 : K - number of columns of matrix (A).
16137 : B - output buffer, possibly preallocated. In case buffer
16138 : size is too small to store result, this buffer is
16139 : automatically resized.
16140 :
16141 : OUTPUT PARAMETERS
16142 : B - array[N][K], S^T*A
16143 :
16144 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
16145 : You must convert your matrix with SparseConvertToCRS/SKS() before using
16146 : this function.
16147 :
16148 : -- ALGLIB PROJECT --
16149 : Copyright 14.10.2011 by Bochkanov Sergey
16150 : *************************************************************************/
16151 0 : void sparsemtm(sparsematrix* s,
16152 : /* Real */ ae_matrix* a,
16153 : ae_int_t k,
16154 : /* Real */ ae_matrix* b,
16155 : ae_state *_state)
16156 : {
16157 : ae_int_t i;
16158 : ae_int_t j;
16159 : ae_int_t k0;
16160 : ae_int_t k1;
16161 : ae_int_t lt;
16162 : ae_int_t rt;
16163 : ae_int_t ct;
16164 : double v;
16165 : ae_int_t m;
16166 : ae_int_t n;
16167 : ae_int_t ri;
16168 : ae_int_t ri1;
16169 : ae_int_t lt1;
16170 : ae_int_t rt1;
16171 : ae_int_t d;
16172 : ae_int_t u;
16173 :
16174 :
16175 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseMTM: incorrect matrix type (convert your matrix to CRS/SKS)", _state);
16176 0 : ae_assert(a->rows>=s->m, "SparseMTM: Rows(A)<M", _state);
16177 0 : ae_assert(k>0, "SparseMTM: K<=0", _state);
16178 0 : m = s->m;
16179 0 : n = s->n;
16180 0 : k1 = k-1;
16181 0 : rmatrixsetlengthatleast(b, n, k, _state);
16182 0 : for(i=0; i<=n-1; i++)
16183 : {
16184 0 : for(j=0; j<=k-1; j++)
16185 : {
16186 0 : b->ptr.pp_double[i][j] = (double)(0);
16187 : }
16188 : }
16189 0 : if( s->matrixtype==1 )
16190 : {
16191 :
16192 : /*
16193 : * CRS format
16194 : */
16195 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[m], "SparseMTM: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
16196 0 : if( k<sparse_linalgswitch )
16197 : {
16198 0 : for(i=0; i<=m-1; i++)
16199 : {
16200 0 : lt = s->ridx.ptr.p_int[i];
16201 0 : rt = s->ridx.ptr.p_int[i+1];
16202 0 : for(k0=lt; k0<=rt-1; k0++)
16203 : {
16204 0 : v = s->vals.ptr.p_double[k0];
16205 0 : ct = s->idx.ptr.p_int[k0];
16206 0 : for(j=0; j<=k-1; j++)
16207 : {
16208 0 : b->ptr.pp_double[ct][j] = b->ptr.pp_double[ct][j]+v*a->ptr.pp_double[i][j];
16209 : }
16210 : }
16211 : }
16212 : }
16213 : else
16214 : {
16215 0 : for(i=0; i<=m-1; i++)
16216 : {
16217 0 : lt = s->ridx.ptr.p_int[i];
16218 0 : rt = s->ridx.ptr.p_int[i+1];
16219 0 : for(j=lt; j<=rt-1; j++)
16220 : {
16221 0 : v = s->vals.ptr.p_double[j];
16222 0 : ct = s->idx.ptr.p_int[j];
16223 0 : ae_v_addd(&b->ptr.pp_double[ct][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16224 : }
16225 : }
16226 : }
16227 0 : return;
16228 : }
16229 0 : if( s->matrixtype==2 )
16230 : {
16231 :
16232 : /*
16233 : * SKS format
16234 : */
16235 0 : ae_assert(m==n, "SparseMTM: non-square SKS matrices are not supported", _state);
16236 0 : for(i=0; i<=n-1; i++)
16237 : {
16238 0 : ri = s->ridx.ptr.p_int[i];
16239 0 : ri1 = s->ridx.ptr.p_int[i+1];
16240 0 : d = s->didx.ptr.p_int[i];
16241 0 : u = s->uidx.ptr.p_int[i];
16242 0 : if( d>0 )
16243 : {
16244 0 : lt = ri;
16245 0 : rt = ri+d-1;
16246 0 : lt1 = i-d;
16247 0 : rt1 = i-1;
16248 0 : for(j=lt1; j<=rt1; j++)
16249 : {
16250 0 : v = s->vals.ptr.p_double[lt+(j-lt1)];
16251 0 : if( k<sparse_linalgswitch )
16252 : {
16253 :
16254 : /*
16255 : * Use loop
16256 : */
16257 0 : for(k0=0; k0<=k1; k0++)
16258 : {
16259 0 : b->ptr.pp_double[j][k0] = b->ptr.pp_double[j][k0]+v*a->ptr.pp_double[i][k0];
16260 : }
16261 : }
16262 : else
16263 : {
16264 :
16265 : /*
16266 : * Use vector operation
16267 : */
16268 0 : ae_v_addd(&b->ptr.pp_double[j][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16269 : }
16270 : }
16271 : }
16272 0 : if( u>0 )
16273 : {
16274 0 : lt = ri1-u;
16275 0 : rt = ri1-1;
16276 0 : lt1 = i-u;
16277 0 : rt1 = i-1;
16278 0 : for(j=lt1; j<=rt1; j++)
16279 : {
16280 0 : v = s->vals.ptr.p_double[lt+(j-lt1)];
16281 0 : if( k<sparse_linalgswitch )
16282 : {
16283 :
16284 : /*
16285 : * Use loop
16286 : */
16287 0 : for(k0=0; k0<=k1; k0++)
16288 : {
16289 0 : b->ptr.pp_double[i][k0] = b->ptr.pp_double[i][k0]+v*a->ptr.pp_double[j][k0];
16290 : }
16291 : }
16292 : else
16293 : {
16294 :
16295 : /*
16296 : * Use vector operation
16297 : */
16298 0 : ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v);
16299 : }
16300 : }
16301 : }
16302 0 : v = s->vals.ptr.p_double[ri+d];
16303 0 : ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16304 : }
16305 0 : return;
16306 : }
16307 : }
16308 :
16309 :
16310 : /*************************************************************************
16311 : This function simultaneously calculates two matrix-matrix products:
16312 : S*A and S^T*A.
16313 : S must be square (non-rectangular) matrix stored in CRS or SKS format
16314 : (exception will be thrown otherwise).
16315 :
16316 : INPUT PARAMETERS
16317 : S - sparse N*N matrix in CRS or SKS format.
16318 : A - array[N][K], input dense matrix. For performance reasons
16319 : we make only quick checks - we check that array size is
16320 : at least N, but we do not check for NAN's or INF's.
16321 : K - number of columns of matrix (A).
16322 : B0 - output buffer, possibly preallocated. In case buffer
16323 : size is too small to store result, this buffer is
16324 : automatically resized.
16325 : B1 - output buffer, possibly preallocated. In case buffer
16326 : size is too small to store result, this buffer is
16327 : automatically resized.
16328 :
16329 : OUTPUT PARAMETERS
16330 : B0 - array[N][K], S*A
16331 : B1 - array[N][K], S^T*A
16332 :
16333 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
16334 : You must convert your matrix with SparseConvertToCRS/SKS() before using
16335 : this function.
16336 :
16337 : -- ALGLIB PROJECT --
16338 : Copyright 14.10.2011 by Bochkanov Sergey
16339 : *************************************************************************/
16340 0 : void sparsemm2(sparsematrix* s,
16341 : /* Real */ ae_matrix* a,
16342 : ae_int_t k,
16343 : /* Real */ ae_matrix* b0,
16344 : /* Real */ ae_matrix* b1,
16345 : ae_state *_state)
16346 : {
16347 : ae_int_t i;
16348 : ae_int_t j;
16349 : ae_int_t k0;
16350 : ae_int_t lt;
16351 : ae_int_t rt;
16352 : ae_int_t ct;
16353 : double v;
16354 : double tval;
16355 : ae_int_t n;
16356 : ae_int_t k1;
16357 : ae_int_t ri;
16358 : ae_int_t ri1;
16359 : ae_int_t lt1;
16360 : ae_int_t rt1;
16361 : ae_int_t d;
16362 : ae_int_t u;
16363 :
16364 :
16365 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseMM2: incorrect matrix type (convert your matrix to CRS/SKS)", _state);
16366 0 : ae_assert(s->m==s->n, "SparseMM2: matrix is non-square", _state);
16367 0 : ae_assert(a->rows>=s->n, "SparseMM2: Rows(A)<N", _state);
16368 0 : ae_assert(k>0, "SparseMM2: K<=0", _state);
16369 0 : n = s->n;
16370 0 : k1 = k-1;
16371 0 : rmatrixsetlengthatleast(b0, n, k, _state);
16372 0 : rmatrixsetlengthatleast(b1, n, k, _state);
16373 0 : for(i=0; i<=n-1; i++)
16374 : {
16375 0 : for(j=0; j<=k-1; j++)
16376 : {
16377 0 : b1->ptr.pp_double[i][j] = (double)(0);
16378 0 : b0->ptr.pp_double[i][j] = (double)(0);
16379 : }
16380 : }
16381 0 : if( s->matrixtype==1 )
16382 : {
16383 :
16384 : /*
16385 : * CRS format
16386 : */
16387 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseMM2: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
16388 0 : if( k<sparse_linalgswitch )
16389 : {
16390 0 : for(i=0; i<=n-1; i++)
16391 : {
16392 0 : for(j=0; j<=k-1; j++)
16393 : {
16394 0 : tval = (double)(0);
16395 0 : lt = s->ridx.ptr.p_int[i];
16396 0 : rt = s->ridx.ptr.p_int[i+1];
16397 0 : v = a->ptr.pp_double[i][j];
16398 0 : for(k0=lt; k0<=rt-1; k0++)
16399 : {
16400 0 : ct = s->idx.ptr.p_int[k0];
16401 0 : b1->ptr.pp_double[ct][j] = b1->ptr.pp_double[ct][j]+s->vals.ptr.p_double[k0]*v;
16402 0 : tval = tval+s->vals.ptr.p_double[k0]*a->ptr.pp_double[ct][j];
16403 : }
16404 0 : b0->ptr.pp_double[i][j] = tval;
16405 : }
16406 : }
16407 : }
16408 : else
16409 : {
16410 0 : for(i=0; i<=n-1; i++)
16411 : {
16412 0 : lt = s->ridx.ptr.p_int[i];
16413 0 : rt = s->ridx.ptr.p_int[i+1];
16414 0 : for(j=lt; j<=rt-1; j++)
16415 : {
16416 0 : v = s->vals.ptr.p_double[j];
16417 0 : ct = s->idx.ptr.p_int[j];
16418 0 : ae_v_addd(&b0->ptr.pp_double[i][0], 1, &a->ptr.pp_double[ct][0], 1, ae_v_len(0,k-1), v);
16419 0 : ae_v_addd(&b1->ptr.pp_double[ct][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16420 : }
16421 : }
16422 : }
16423 0 : return;
16424 : }
16425 0 : if( s->matrixtype==2 )
16426 : {
16427 :
16428 : /*
16429 : * SKS format
16430 : */
16431 0 : ae_assert(s->m==s->n, "SparseMM2: non-square SKS matrices are not supported", _state);
16432 0 : for(i=0; i<=n-1; i++)
16433 : {
16434 0 : ri = s->ridx.ptr.p_int[i];
16435 0 : ri1 = s->ridx.ptr.p_int[i+1];
16436 0 : d = s->didx.ptr.p_int[i];
16437 0 : u = s->uidx.ptr.p_int[i];
16438 0 : if( d>0 )
16439 : {
16440 0 : lt = ri;
16441 0 : rt = ri+d-1;
16442 0 : lt1 = i-d;
16443 0 : rt1 = i-1;
16444 0 : for(j=lt1; j<=rt1; j++)
16445 : {
16446 0 : v = s->vals.ptr.p_double[lt+(j-lt1)];
16447 0 : if( k<sparse_linalgswitch )
16448 : {
16449 :
16450 : /*
16451 : * Use loop
16452 : */
16453 0 : for(k0=0; k0<=k1; k0++)
16454 : {
16455 0 : b0->ptr.pp_double[i][k0] = b0->ptr.pp_double[i][k0]+v*a->ptr.pp_double[j][k0];
16456 0 : b1->ptr.pp_double[j][k0] = b1->ptr.pp_double[j][k0]+v*a->ptr.pp_double[i][k0];
16457 : }
16458 : }
16459 : else
16460 : {
16461 :
16462 : /*
16463 : * Use vector operation
16464 : */
16465 0 : ae_v_addd(&b0->ptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v);
16466 0 : ae_v_addd(&b1->ptr.pp_double[j][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16467 : }
16468 : }
16469 : }
16470 0 : if( u>0 )
16471 : {
16472 0 : lt = ri1-u;
16473 0 : rt = ri1-1;
16474 0 : lt1 = i-u;
16475 0 : rt1 = i-1;
16476 0 : for(j=lt1; j<=rt1; j++)
16477 : {
16478 0 : v = s->vals.ptr.p_double[lt+(j-lt1)];
16479 0 : if( k<sparse_linalgswitch )
16480 : {
16481 :
16482 : /*
16483 : * Use loop
16484 : */
16485 0 : for(k0=0; k0<=k1; k0++)
16486 : {
16487 0 : b0->ptr.pp_double[j][k0] = b0->ptr.pp_double[j][k0]+v*a->ptr.pp_double[i][k0];
16488 0 : b1->ptr.pp_double[i][k0] = b1->ptr.pp_double[i][k0]+v*a->ptr.pp_double[j][k0];
16489 : }
16490 : }
16491 : else
16492 : {
16493 :
16494 : /*
16495 : * Use vector operation
16496 : */
16497 0 : ae_v_addd(&b0->ptr.pp_double[j][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16498 0 : ae_v_addd(&b1->ptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v);
16499 : }
16500 : }
16501 : }
16502 0 : v = s->vals.ptr.p_double[ri+d];
16503 0 : ae_v_addd(&b0->ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16504 0 : ae_v_addd(&b1->ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16505 : }
16506 0 : return;
16507 : }
16508 : }
16509 :
16510 :
16511 : /*************************************************************************
16512 : This function calculates matrix-matrix product S*A, when S is symmetric
16513 : matrix. Matrix S must be stored in CRS or SKS format (exception will be
16514 : thrown otherwise).
16515 :
16516 : INPUT PARAMETERS
16517 : S - sparse M*M matrix in CRS or SKS format.
16518 : IsUpper - whether upper or lower triangle of S is given:
16519 : * if upper triangle is given, only S[i,j] for j>=i
16520 : are used, and lower triangle is ignored (it can be
16521 : empty - these elements are not referenced at all).
16522 : * if lower triangle is given, only S[i,j] for j<=i
16523 : are used, and upper triangle is ignored.
16524 : A - array[N][K], input dense matrix. For performance reasons
16525 : we make only quick checks - we check that array size is
16526 : at least N, but we do not check for NAN's or INF's.
16527 : K - number of columns of matrix (A).
16528 : B - output buffer, possibly preallocated. In case buffer
16529 : size is too small to store result, this buffer is
16530 : automatically resized.
16531 :
16532 : OUTPUT PARAMETERS
16533 : B - array[M][K], S*A
16534 :
16535 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
16536 : You must convert your matrix with SparseConvertToCRS/SKS() before using
16537 : this function.
16538 :
16539 : -- ALGLIB PROJECT --
16540 : Copyright 14.10.2011 by Bochkanov Sergey
16541 : *************************************************************************/
16542 0 : void sparsesmm(sparsematrix* s,
16543 : ae_bool isupper,
16544 : /* Real */ ae_matrix* a,
16545 : ae_int_t k,
16546 : /* Real */ ae_matrix* b,
16547 : ae_state *_state)
16548 : {
16549 : ae_int_t i;
16550 : ae_int_t j;
16551 : ae_int_t k0;
16552 : ae_int_t id;
16553 : ae_int_t k1;
16554 : ae_int_t lt;
16555 : ae_int_t rt;
16556 : double v;
16557 : double vb;
16558 : double va;
16559 : ae_int_t n;
16560 : ae_int_t ri;
16561 : ae_int_t ri1;
16562 : ae_int_t lt1;
16563 : ae_int_t rt1;
16564 : ae_int_t d;
16565 : ae_int_t u;
16566 :
16567 :
16568 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseSMM: incorrect matrix type (convert your matrix to CRS/SKS)", _state);
16569 0 : ae_assert(a->rows>=s->n, "SparseSMM: Rows(X)<N", _state);
16570 0 : ae_assert(s->m==s->n, "SparseSMM: matrix is non-square", _state);
16571 0 : n = s->n;
16572 0 : k1 = k-1;
16573 0 : rmatrixsetlengthatleast(b, n, k, _state);
16574 0 : for(i=0; i<=n-1; i++)
16575 : {
16576 0 : for(j=0; j<=k-1; j++)
16577 : {
16578 0 : b->ptr.pp_double[i][j] = (double)(0);
16579 : }
16580 : }
16581 0 : if( s->matrixtype==1 )
16582 : {
16583 :
16584 : /*
16585 : * CRS format
16586 : */
16587 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseSMM: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
16588 0 : if( k>sparse_linalgswitch )
16589 : {
16590 0 : for(i=0; i<=n-1; i++)
16591 : {
16592 0 : for(j=0; j<=k-1; j++)
16593 : {
16594 0 : if( s->didx.ptr.p_int[i]!=s->uidx.ptr.p_int[i] )
16595 : {
16596 0 : id = s->didx.ptr.p_int[i];
16597 0 : b->ptr.pp_double[i][j] = b->ptr.pp_double[i][j]+s->vals.ptr.p_double[id]*a->ptr.pp_double[s->idx.ptr.p_int[id]][j];
16598 : }
16599 0 : if( isupper )
16600 : {
16601 0 : lt = s->uidx.ptr.p_int[i];
16602 0 : rt = s->ridx.ptr.p_int[i+1];
16603 0 : vb = (double)(0);
16604 0 : va = a->ptr.pp_double[i][j];
16605 0 : for(k0=lt; k0<=rt-1; k0++)
16606 : {
16607 0 : id = s->idx.ptr.p_int[k0];
16608 0 : v = s->vals.ptr.p_double[k0];
16609 0 : vb = vb+a->ptr.pp_double[id][j]*v;
16610 0 : b->ptr.pp_double[id][j] = b->ptr.pp_double[id][j]+va*v;
16611 : }
16612 0 : b->ptr.pp_double[i][j] = b->ptr.pp_double[i][j]+vb;
16613 : }
16614 : else
16615 : {
16616 0 : lt = s->ridx.ptr.p_int[i];
16617 0 : rt = s->didx.ptr.p_int[i];
16618 0 : vb = (double)(0);
16619 0 : va = a->ptr.pp_double[i][j];
16620 0 : for(k0=lt; k0<=rt-1; k0++)
16621 : {
16622 0 : id = s->idx.ptr.p_int[k0];
16623 0 : v = s->vals.ptr.p_double[k0];
16624 0 : vb = vb+a->ptr.pp_double[id][j]*v;
16625 0 : b->ptr.pp_double[id][j] = b->ptr.pp_double[id][j]+va*v;
16626 : }
16627 0 : b->ptr.pp_double[i][j] = b->ptr.pp_double[i][j]+vb;
16628 : }
16629 : }
16630 : }
16631 : }
16632 : else
16633 : {
16634 0 : for(i=0; i<=n-1; i++)
16635 : {
16636 0 : if( s->didx.ptr.p_int[i]!=s->uidx.ptr.p_int[i] )
16637 : {
16638 0 : id = s->didx.ptr.p_int[i];
16639 0 : v = s->vals.ptr.p_double[id];
16640 0 : ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[s->idx.ptr.p_int[id]][0], 1, ae_v_len(0,k-1), v);
16641 : }
16642 0 : if( isupper )
16643 : {
16644 0 : lt = s->uidx.ptr.p_int[i];
16645 0 : rt = s->ridx.ptr.p_int[i+1];
16646 0 : for(j=lt; j<=rt-1; j++)
16647 : {
16648 0 : id = s->idx.ptr.p_int[j];
16649 0 : v = s->vals.ptr.p_double[j];
16650 0 : ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[id][0], 1, ae_v_len(0,k-1), v);
16651 0 : ae_v_addd(&b->ptr.pp_double[id][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16652 : }
16653 : }
16654 : else
16655 : {
16656 0 : lt = s->ridx.ptr.p_int[i];
16657 0 : rt = s->didx.ptr.p_int[i];
16658 0 : for(j=lt; j<=rt-1; j++)
16659 : {
16660 0 : id = s->idx.ptr.p_int[j];
16661 0 : v = s->vals.ptr.p_double[j];
16662 0 : ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[id][0], 1, ae_v_len(0,k-1), v);
16663 0 : ae_v_addd(&b->ptr.pp_double[id][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16664 : }
16665 : }
16666 : }
16667 : }
16668 0 : return;
16669 : }
16670 0 : if( s->matrixtype==2 )
16671 : {
16672 :
16673 : /*
16674 : * SKS format
16675 : */
16676 0 : ae_assert(s->m==s->n, "SparseMM2: non-square SKS matrices are not supported", _state);
16677 0 : for(i=0; i<=n-1; i++)
16678 : {
16679 0 : ri = s->ridx.ptr.p_int[i];
16680 0 : ri1 = s->ridx.ptr.p_int[i+1];
16681 0 : d = s->didx.ptr.p_int[i];
16682 0 : u = s->uidx.ptr.p_int[i];
16683 0 : if( d>0&&!isupper )
16684 : {
16685 0 : lt = ri;
16686 0 : rt = ri+d-1;
16687 0 : lt1 = i-d;
16688 0 : rt1 = i-1;
16689 0 : for(j=lt1; j<=rt1; j++)
16690 : {
16691 0 : v = s->vals.ptr.p_double[lt+(j-lt1)];
16692 0 : if( k<sparse_linalgswitch )
16693 : {
16694 :
16695 : /*
16696 : * Use loop
16697 : */
16698 0 : for(k0=0; k0<=k1; k0++)
16699 : {
16700 0 : b->ptr.pp_double[i][k0] = b->ptr.pp_double[i][k0]+v*a->ptr.pp_double[j][k0];
16701 0 : b->ptr.pp_double[j][k0] = b->ptr.pp_double[j][k0]+v*a->ptr.pp_double[i][k0];
16702 : }
16703 : }
16704 : else
16705 : {
16706 :
16707 : /*
16708 : * Use vector operation
16709 : */
16710 0 : ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v);
16711 0 : ae_v_addd(&b->ptr.pp_double[j][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16712 : }
16713 : }
16714 : }
16715 0 : if( u>0&&isupper )
16716 : {
16717 0 : lt = ri1-u;
16718 0 : rt = ri1-1;
16719 0 : lt1 = i-u;
16720 0 : rt1 = i-1;
16721 0 : for(j=lt1; j<=rt1; j++)
16722 : {
16723 0 : v = s->vals.ptr.p_double[lt+(j-lt1)];
16724 0 : if( k<sparse_linalgswitch )
16725 : {
16726 :
16727 : /*
16728 : * Use loop
16729 : */
16730 0 : for(k0=0; k0<=k1; k0++)
16731 : {
16732 0 : b->ptr.pp_double[j][k0] = b->ptr.pp_double[j][k0]+v*a->ptr.pp_double[i][k0];
16733 0 : b->ptr.pp_double[i][k0] = b->ptr.pp_double[i][k0]+v*a->ptr.pp_double[j][k0];
16734 : }
16735 : }
16736 : else
16737 : {
16738 :
16739 : /*
16740 : * Use vector operation
16741 : */
16742 0 : ae_v_addd(&b->ptr.pp_double[j][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16743 0 : ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,k-1), v);
16744 : }
16745 : }
16746 : }
16747 0 : v = s->vals.ptr.p_double[ri+d];
16748 0 : ae_v_addd(&b->ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k-1), v);
16749 : }
16750 0 : return;
16751 : }
16752 : }
16753 :
16754 :
16755 : /*************************************************************************
16756 : This function calculates matrix-vector product op(S)*x, when x is vector,
16757 : S is symmetric triangular matrix, op(S) is transposition or no operation.
16758 : Matrix S must be stored in CRS or SKS format (exception will be thrown
16759 : otherwise).
16760 :
16761 : INPUT PARAMETERS
16762 : S - sparse square matrix in CRS or SKS format.
16763 : IsUpper - whether upper or lower triangle of S is used:
16764 : * if upper triangle is given, only S[i,j] for j>=i
16765 : are used, and lower triangle is ignored (it can be
16766 : empty - these elements are not referenced at all).
16767 : * if lower triangle is given, only S[i,j] for j<=i
16768 : are used, and upper triangle is ignored.
16769 : IsUnit - unit or non-unit diagonal:
16770 : * if True, diagonal elements of triangular matrix are
16771 : considered equal to 1.0. Actual elements stored in
16772 : S are not referenced at all.
16773 : * if False, diagonal stored in S is used
16774 : OpType - operation type:
16775 : * if 0, S*x is calculated
16776 : * if 1, (S^T)*x is calculated (transposition)
16777 : X - array[N] which stores input vector. For performance
16778 : reasons we make only quick checks - we check that
16779 : array size is at least N, but we do not check for
16780 : NAN's or INF's.
16781 : Y - possibly preallocated input buffer. Automatically
16782 : resized if its size is too small.
16783 :
16784 : OUTPUT PARAMETERS
16785 : Y - array[N], op(S)*x
16786 :
16787 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
16788 : You must convert your matrix with SparseConvertToCRS/SKS() before using
16789 : this function.
16790 :
16791 : -- ALGLIB PROJECT --
16792 : Copyright 20.01.2014 by Bochkanov Sergey
16793 : *************************************************************************/
16794 0 : void sparsetrmv(sparsematrix* s,
16795 : ae_bool isupper,
16796 : ae_bool isunit,
16797 : ae_int_t optype,
16798 : /* Real */ ae_vector* x,
16799 : /* Real */ ae_vector* y,
16800 : ae_state *_state)
16801 : {
16802 : ae_int_t n;
16803 : ae_int_t i;
16804 : ae_int_t j;
16805 : ae_int_t k;
16806 : ae_int_t j0;
16807 : ae_int_t j1;
16808 : double v;
16809 : ae_int_t ri;
16810 : ae_int_t ri1;
16811 : ae_int_t d;
16812 : ae_int_t u;
16813 : ae_int_t lt;
16814 : ae_int_t rt;
16815 : ae_int_t lt1;
16816 : ae_int_t rt1;
16817 :
16818 :
16819 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseTRMV: incorrect matrix type (convert your matrix to CRS/SKS)", _state);
16820 0 : ae_assert(optype==0||optype==1, "SparseTRMV: incorrect operation type (must be 0 or 1)", _state);
16821 0 : ae_assert(x->cnt>=s->n, "SparseTRMV: Length(X)<N", _state);
16822 0 : ae_assert(s->m==s->n, "SparseTRMV: matrix is non-square", _state);
16823 0 : n = s->n;
16824 0 : rvectorsetlengthatleast(y, n, _state);
16825 0 : if( isunit )
16826 : {
16827 :
16828 : /*
16829 : * Set initial value of y to x
16830 : */
16831 0 : for(i=0; i<=n-1; i++)
16832 : {
16833 0 : y->ptr.p_double[i] = x->ptr.p_double[i];
16834 : }
16835 : }
16836 : else
16837 : {
16838 :
16839 : /*
16840 : * Set initial value of y to 0
16841 : */
16842 0 : for(i=0; i<=n-1; i++)
16843 : {
16844 0 : y->ptr.p_double[i] = (double)(0);
16845 : }
16846 : }
16847 0 : if( s->matrixtype==1 )
16848 : {
16849 :
16850 : /*
16851 : * CRS format
16852 : */
16853 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseTRMV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
16854 0 : for(i=0; i<=n-1; i++)
16855 : {
16856 :
16857 : /*
16858 : * Depending on IsUpper/IsUnit, select range of indexes to process
16859 : */
16860 0 : if( isupper )
16861 : {
16862 0 : if( isunit||s->didx.ptr.p_int[i]==s->uidx.ptr.p_int[i] )
16863 : {
16864 0 : j0 = s->uidx.ptr.p_int[i];
16865 : }
16866 : else
16867 : {
16868 0 : j0 = s->didx.ptr.p_int[i];
16869 : }
16870 0 : j1 = s->ridx.ptr.p_int[i+1]-1;
16871 : }
16872 : else
16873 : {
16874 0 : j0 = s->ridx.ptr.p_int[i];
16875 0 : if( isunit||s->didx.ptr.p_int[i]==s->uidx.ptr.p_int[i] )
16876 : {
16877 0 : j1 = s->didx.ptr.p_int[i]-1;
16878 : }
16879 : else
16880 : {
16881 0 : j1 = s->didx.ptr.p_int[i];
16882 : }
16883 : }
16884 :
16885 : /*
16886 : * Depending on OpType, process subset of I-th row of input matrix
16887 : */
16888 0 : if( optype==0 )
16889 : {
16890 0 : v = 0.0;
16891 0 : for(j=j0; j<=j1; j++)
16892 : {
16893 0 : v = v+s->vals.ptr.p_double[j]*x->ptr.p_double[s->idx.ptr.p_int[j]];
16894 : }
16895 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+v;
16896 : }
16897 : else
16898 : {
16899 0 : v = x->ptr.p_double[i];
16900 0 : for(j=j0; j<=j1; j++)
16901 : {
16902 0 : k = s->idx.ptr.p_int[j];
16903 0 : y->ptr.p_double[k] = y->ptr.p_double[k]+v*s->vals.ptr.p_double[j];
16904 : }
16905 : }
16906 : }
16907 0 : return;
16908 : }
16909 0 : if( s->matrixtype==2 )
16910 : {
16911 :
16912 : /*
16913 : * SKS format
16914 : */
16915 0 : ae_assert(s->m==s->n, "SparseTRMV: non-square SKS matrices are not supported", _state);
16916 0 : for(i=0; i<=n-1; i++)
16917 : {
16918 0 : ri = s->ridx.ptr.p_int[i];
16919 0 : ri1 = s->ridx.ptr.p_int[i+1];
16920 0 : d = s->didx.ptr.p_int[i];
16921 0 : u = s->uidx.ptr.p_int[i];
16922 0 : if( !isunit )
16923 : {
16924 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+s->vals.ptr.p_double[ri+d]*x->ptr.p_double[i];
16925 : }
16926 0 : if( d>0&&!isupper )
16927 : {
16928 0 : lt = ri;
16929 0 : rt = ri+d-1;
16930 0 : lt1 = i-d;
16931 0 : rt1 = i-1;
16932 0 : if( optype==0 )
16933 : {
16934 0 : v = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt));
16935 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+v;
16936 : }
16937 : else
16938 : {
16939 0 : v = x->ptr.p_double[i];
16940 0 : ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v);
16941 : }
16942 : }
16943 0 : if( u>0&&isupper )
16944 : {
16945 0 : lt = ri1-u;
16946 0 : rt = ri1-1;
16947 0 : lt1 = i-u;
16948 0 : rt1 = i-1;
16949 0 : if( optype==0 )
16950 : {
16951 0 : v = x->ptr.p_double[i];
16952 0 : ae_v_addd(&y->ptr.p_double[lt1], 1, &s->vals.ptr.p_double[lt], 1, ae_v_len(lt1,rt1), v);
16953 : }
16954 : else
16955 : {
16956 0 : v = ae_v_dotproduct(&s->vals.ptr.p_double[lt], 1, &x->ptr.p_double[lt1], 1, ae_v_len(lt,rt));
16957 0 : y->ptr.p_double[i] = y->ptr.p_double[i]+v;
16958 : }
16959 : }
16960 : }
16961 0 : return;
16962 : }
16963 : }
16964 :
16965 :
16966 : /*************************************************************************
16967 : This function solves linear system op(S)*y=x where x is vector, S is
16968 : symmetric triangular matrix, op(S) is transposition or no operation.
16969 : Matrix S must be stored in CRS or SKS format (exception will be thrown
16970 : otherwise).
16971 :
16972 : INPUT PARAMETERS
16973 : S - sparse square matrix in CRS or SKS format.
16974 : IsUpper - whether upper or lower triangle of S is used:
16975 : * if upper triangle is given, only S[i,j] for j>=i
16976 : are used, and lower triangle is ignored (it can be
16977 : empty - these elements are not referenced at all).
16978 : * if lower triangle is given, only S[i,j] for j<=i
16979 : are used, and upper triangle is ignored.
16980 : IsUnit - unit or non-unit diagonal:
16981 : * if True, diagonal elements of triangular matrix are
16982 : considered equal to 1.0. Actual elements stored in
16983 : S are not referenced at all.
16984 : * if False, diagonal stored in S is used. It is your
16985 : responsibility to make sure that diagonal is
16986 : non-zero.
16987 : OpType - operation type:
16988 : * if 0, S*x is calculated
16989 : * if 1, (S^T)*x is calculated (transposition)
16990 : X - array[N] which stores input vector. For performance
16991 : reasons we make only quick checks - we check that
16992 : array size is at least N, but we do not check for
16993 : NAN's or INF's.
16994 :
16995 : OUTPUT PARAMETERS
16996 : X - array[N], inv(op(S))*x
16997 :
16998 : NOTE: this function throws exception when called for non-CRS/SKS matrix.
16999 : You must convert your matrix with SparseConvertToCRS/SKS() before
17000 : using this function.
17001 :
17002 : NOTE: no assertion or tests are done during algorithm operation. It is
17003 : your responsibility to provide invertible matrix to algorithm.
17004 :
17005 : -- ALGLIB PROJECT --
17006 : Copyright 20.01.2014 by Bochkanov Sergey
17007 : *************************************************************************/
17008 0 : void sparsetrsv(sparsematrix* s,
17009 : ae_bool isupper,
17010 : ae_bool isunit,
17011 : ae_int_t optype,
17012 : /* Real */ ae_vector* x,
17013 : ae_state *_state)
17014 : {
17015 : ae_int_t n;
17016 : ae_int_t fst;
17017 : ae_int_t lst;
17018 : ae_int_t stp;
17019 : ae_int_t i;
17020 : ae_int_t j;
17021 : ae_int_t k;
17022 : double v;
17023 : double vd;
17024 : double v0;
17025 : ae_int_t j0;
17026 : ae_int_t j1;
17027 : ae_int_t ri;
17028 : ae_int_t ri1;
17029 : ae_int_t d;
17030 : ae_int_t u;
17031 : ae_int_t lt;
17032 : ae_int_t lt1;
17033 :
17034 :
17035 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseTRSV: incorrect matrix type (convert your matrix to CRS/SKS)", _state);
17036 0 : ae_assert(optype==0||optype==1, "SparseTRSV: incorrect operation type (must be 0 or 1)", _state);
17037 0 : ae_assert(x->cnt>=s->n, "SparseTRSV: Length(X)<N", _state);
17038 0 : ae_assert(s->m==s->n, "SparseTRSV: matrix is non-square", _state);
17039 0 : n = s->n;
17040 0 : if( s->matrixtype==1 )
17041 : {
17042 :
17043 : /*
17044 : * CRS format.
17045 : *
17046 : * Several branches for different combinations of IsUpper and OpType
17047 : */
17048 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseTRSV: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
17049 0 : if( optype==0 )
17050 : {
17051 :
17052 : /*
17053 : * No transposition.
17054 : *
17055 : * S*x=y with upper or lower triangular S.
17056 : */
17057 0 : v0 = (double)(0);
17058 0 : if( isupper )
17059 : {
17060 0 : fst = n-1;
17061 0 : lst = 0;
17062 0 : stp = -1;
17063 : }
17064 : else
17065 : {
17066 0 : fst = 0;
17067 0 : lst = n-1;
17068 0 : stp = 1;
17069 : }
17070 0 : i = fst;
17071 0 : while((stp>0&&i<=lst)||(stp<0&&i>=lst))
17072 : {
17073 :
17074 : /*
17075 : * Select range of indexes to process
17076 : */
17077 0 : if( isupper )
17078 : {
17079 0 : j0 = s->uidx.ptr.p_int[i];
17080 0 : j1 = s->ridx.ptr.p_int[i+1]-1;
17081 : }
17082 : else
17083 : {
17084 0 : j0 = s->ridx.ptr.p_int[i];
17085 0 : j1 = s->didx.ptr.p_int[i]-1;
17086 : }
17087 :
17088 : /*
17089 : * Calculate X[I]
17090 : */
17091 0 : v = 0.0;
17092 0 : for(j=j0; j<=j1; j++)
17093 : {
17094 0 : v = v+s->vals.ptr.p_double[j]*x->ptr.p_double[s->idx.ptr.p_int[j]];
17095 : }
17096 0 : if( !isunit )
17097 : {
17098 0 : if( s->didx.ptr.p_int[i]==s->uidx.ptr.p_int[i] )
17099 : {
17100 0 : vd = (double)(0);
17101 : }
17102 : else
17103 : {
17104 0 : vd = s->vals.ptr.p_double[s->didx.ptr.p_int[i]];
17105 : }
17106 : }
17107 : else
17108 : {
17109 0 : vd = 1.0;
17110 : }
17111 0 : v = (x->ptr.p_double[i]-v)/vd;
17112 0 : x->ptr.p_double[i] = v;
17113 0 : v0 = 0.25*v0+v;
17114 :
17115 : /*
17116 : * Next I
17117 : */
17118 0 : i = i+stp;
17119 : }
17120 0 : ae_assert(ae_isfinite(v0, _state), "SparseTRSV: overflow or division by exact zero", _state);
17121 0 : return;
17122 : }
17123 0 : if( optype==1 )
17124 : {
17125 :
17126 : /*
17127 : * Transposition.
17128 : *
17129 : * (S^T)*x=y with upper or lower triangular S.
17130 : */
17131 0 : if( isupper )
17132 : {
17133 0 : fst = 0;
17134 0 : lst = n-1;
17135 0 : stp = 1;
17136 : }
17137 : else
17138 : {
17139 0 : fst = n-1;
17140 0 : lst = 0;
17141 0 : stp = -1;
17142 : }
17143 0 : i = fst;
17144 0 : v0 = (double)(0);
17145 0 : while((stp>0&&i<=lst)||(stp<0&&i>=lst))
17146 : {
17147 0 : v = x->ptr.p_double[i];
17148 0 : if( v!=0.0 )
17149 : {
17150 :
17151 : /*
17152 : * X[i] already stores A[i,i]*Y[i], the only thing left
17153 : * is to divide by diagonal element.
17154 : */
17155 0 : if( !isunit )
17156 : {
17157 0 : if( s->didx.ptr.p_int[i]==s->uidx.ptr.p_int[i] )
17158 : {
17159 0 : vd = (double)(0);
17160 : }
17161 : else
17162 : {
17163 0 : vd = s->vals.ptr.p_double[s->didx.ptr.p_int[i]];
17164 : }
17165 : }
17166 : else
17167 : {
17168 0 : vd = 1.0;
17169 : }
17170 0 : v = v/vd;
17171 0 : x->ptr.p_double[i] = v;
17172 0 : v0 = 0.25*v0+v;
17173 :
17174 : /*
17175 : * For upper triangular case:
17176 : * subtract X[i]*Ai from X[i+1:N-1]
17177 : *
17178 : * For lower triangular case:
17179 : * subtract X[i]*Ai from X[0:i-1]
17180 : *
17181 : * (here Ai is I-th row of original, untransposed A).
17182 : */
17183 0 : if( isupper )
17184 : {
17185 0 : j0 = s->uidx.ptr.p_int[i];
17186 0 : j1 = s->ridx.ptr.p_int[i+1]-1;
17187 : }
17188 : else
17189 : {
17190 0 : j0 = s->ridx.ptr.p_int[i];
17191 0 : j1 = s->didx.ptr.p_int[i]-1;
17192 : }
17193 0 : for(j=j0; j<=j1; j++)
17194 : {
17195 0 : k = s->idx.ptr.p_int[j];
17196 0 : x->ptr.p_double[k] = x->ptr.p_double[k]-s->vals.ptr.p_double[j]*v;
17197 : }
17198 : }
17199 :
17200 : /*
17201 : * Next I
17202 : */
17203 0 : i = i+stp;
17204 : }
17205 0 : ae_assert(ae_isfinite(v0, _state), "SparseTRSV: overflow or division by exact zero", _state);
17206 0 : return;
17207 : }
17208 0 : ae_assert(ae_false, "SparseTRSV: internal error", _state);
17209 : }
17210 0 : if( s->matrixtype==2 )
17211 : {
17212 :
17213 : /*
17214 : * SKS format
17215 : */
17216 0 : ae_assert(s->m==s->n, "SparseTRSV: non-square SKS matrices are not supported", _state);
17217 0 : if( (optype==0&&!isupper)||(optype==1&&isupper) )
17218 : {
17219 :
17220 : /*
17221 : * Lower triangular op(S) (matrix itself can be upper triangular).
17222 : */
17223 0 : v0 = (double)(0);
17224 0 : for(i=0; i<=n-1; i++)
17225 : {
17226 :
17227 : /*
17228 : * Select range of indexes to process
17229 : */
17230 0 : ri = s->ridx.ptr.p_int[i];
17231 0 : ri1 = s->ridx.ptr.p_int[i+1];
17232 0 : d = s->didx.ptr.p_int[i];
17233 0 : u = s->uidx.ptr.p_int[i];
17234 0 : if( isupper )
17235 : {
17236 0 : lt = i-u;
17237 0 : lt1 = ri1-u;
17238 0 : k = u-1;
17239 : }
17240 : else
17241 : {
17242 0 : lt = i-d;
17243 0 : lt1 = ri;
17244 0 : k = d-1;
17245 : }
17246 :
17247 : /*
17248 : * Calculate X[I]
17249 : */
17250 0 : v = 0.0;
17251 0 : for(j=0; j<=k; j++)
17252 : {
17253 0 : v = v+s->vals.ptr.p_double[lt1+j]*x->ptr.p_double[lt+j];
17254 : }
17255 0 : if( isunit )
17256 : {
17257 0 : vd = (double)(1);
17258 : }
17259 : else
17260 : {
17261 0 : vd = s->vals.ptr.p_double[ri+d];
17262 : }
17263 0 : v = (x->ptr.p_double[i]-v)/vd;
17264 0 : x->ptr.p_double[i] = v;
17265 0 : v0 = 0.25*v0+v;
17266 : }
17267 0 : ae_assert(ae_isfinite(v0, _state), "SparseTRSV: overflow or division by exact zero", _state);
17268 0 : return;
17269 : }
17270 0 : if( (optype==1&&!isupper)||(optype==0&&isupper) )
17271 : {
17272 :
17273 : /*
17274 : * Upper triangular op(S) (matrix itself can be lower triangular).
17275 : */
17276 0 : v0 = (double)(0);
17277 0 : for(i=n-1; i>=0; i--)
17278 : {
17279 0 : ri = s->ridx.ptr.p_int[i];
17280 0 : ri1 = s->ridx.ptr.p_int[i+1];
17281 0 : d = s->didx.ptr.p_int[i];
17282 0 : u = s->uidx.ptr.p_int[i];
17283 :
17284 : /*
17285 : * X[i] already stores A[i,i]*Y[i], the only thing left
17286 : * is to divide by diagonal element.
17287 : */
17288 0 : if( isunit )
17289 : {
17290 0 : vd = (double)(1);
17291 : }
17292 : else
17293 : {
17294 0 : vd = s->vals.ptr.p_double[ri+d];
17295 : }
17296 0 : v = x->ptr.p_double[i]/vd;
17297 0 : x->ptr.p_double[i] = v;
17298 0 : v0 = 0.25*v0+v;
17299 :
17300 : /*
17301 : * Subtract product of X[i] and I-th column of "effective" A from
17302 : * unprocessed variables.
17303 : */
17304 0 : v = x->ptr.p_double[i];
17305 0 : if( isupper )
17306 : {
17307 0 : lt = i-u;
17308 0 : lt1 = ri1-u;
17309 0 : k = u-1;
17310 : }
17311 : else
17312 : {
17313 0 : lt = i-d;
17314 0 : lt1 = ri;
17315 0 : k = d-1;
17316 : }
17317 0 : for(j=0; j<=k; j++)
17318 : {
17319 0 : x->ptr.p_double[lt+j] = x->ptr.p_double[lt+j]-v*s->vals.ptr.p_double[lt1+j];
17320 : }
17321 : }
17322 0 : ae_assert(ae_isfinite(v0, _state), "SparseTRSV: overflow or division by exact zero", _state);
17323 0 : return;
17324 : }
17325 0 : ae_assert(ae_false, "SparseTRSV: internal error", _state);
17326 : }
17327 0 : ae_assert(ae_false, "SparseTRSV: internal error", _state);
17328 : }
17329 :
17330 :
17331 : /*************************************************************************
17332 : This function applies permutation given by permutation table P (as opposed
17333 : to product form of permutation) to sparse symmetric matrix A, given by
17334 : either upper or lower triangle: B := P*A*P'.
17335 :
17336 : This function allocates completely new instance of B. Use buffered version
17337 : SparseSymmPermTblBuf() if you want to reuse already allocated structure.
17338 :
17339 : INPUT PARAMETERS
17340 : A - sparse square matrix in CRS format.
17341 : IsUpper - whether upper or lower triangle of A is used:
17342 : * if upper triangle is given, only A[i,j] for j>=i
17343 : are used, and lower triangle is ignored (it can be
17344 : empty - these elements are not referenced at all).
17345 : * if lower triangle is given, only A[i,j] for j<=i
17346 : are used, and upper triangle is ignored.
17347 : P - array[N] which stores permutation table; P[I]=J means
17348 : that I-th row/column of matrix A is moved to J-th
17349 : position. For performance reasons we do NOT check that
17350 : P[] is a correct permutation (that there is no
17351 : repetitions, just that all its elements are in [0,N)
17352 : range.
17353 :
17354 : OUTPUT PARAMETERS
17355 : B - permuted matrix. Permutation is applied to A from
17356 : the both sides, only upper or lower triangle (depending
17357 : on IsUpper) is stored.
17358 :
17359 : NOTE: this function throws exception when called for non-CRS matrix. You
17360 : must convert your matrix with SparseConvertToCRS() before using this
17361 : function.
17362 :
17363 : -- ALGLIB PROJECT --
17364 : Copyright 05.10.2020 by Bochkanov Sergey.
17365 : *************************************************************************/
17366 0 : void sparsesymmpermtbl(sparsematrix* a,
17367 : ae_bool isupper,
17368 : /* Integer */ ae_vector* p,
17369 : sparsematrix* b,
17370 : ae_state *_state)
17371 : {
17372 :
17373 0 : _sparsematrix_clear(b);
17374 :
17375 0 : sparsesymmpermtblbuf(a, isupper, p, b, _state);
17376 0 : }
17377 :
17378 :
17379 : /*************************************************************************
17380 : This function is a buffered version of SparseSymmPermTbl() that reuses
17381 : previously allocated storage in B as much as possible.
17382 :
17383 : This function applies permutation given by permutation table P (as opposed
17384 : to product form of permutation) to sparse symmetric matrix A, given by
17385 : either upper or lower triangle: B := P*A*P'.
17386 :
17387 : INPUT PARAMETERS
17388 : A - sparse square matrix in CRS format.
17389 : IsUpper - whether upper or lower triangle of A is used:
17390 : * if upper triangle is given, only A[i,j] for j>=i
17391 : are used, and lower triangle is ignored (it can be
17392 : empty - these elements are not referenced at all).
17393 : * if lower triangle is given, only A[i,j] for j<=i
17394 : are used, and upper triangle is ignored.
17395 : P - array[N] which stores permutation table; P[I]=J means
17396 : that I-th row/column of matrix A is moved to J-th
17397 : position. For performance reasons we do NOT check that
17398 : P[] is a correct permutation (that there is no
17399 : repetitions, just that all its elements are in [0,N)
17400 : range.
17401 : B - sparse matrix object that will hold output.
17402 : Previously allocated memory will be reused as much as
17403 : possible.
17404 :
17405 : OUTPUT PARAMETERS
17406 : B - permuted matrix. Permutation is applied to A from
17407 : the both sides, only upper or lower triangle (depending
17408 : on IsUpper) is stored.
17409 :
17410 : NOTE: this function throws exception when called for non-CRS matrix. You
17411 : must convert your matrix with SparseConvertToCRS() before using this
17412 : function.
17413 :
17414 : -- ALGLIB PROJECT --
17415 : Copyright 05.10.2020 by Bochkanov Sergey.
17416 : *************************************************************************/
17417 0 : void sparsesymmpermtblbuf(sparsematrix* a,
17418 : ae_bool isupper,
17419 : /* Integer */ ae_vector* p,
17420 : sparsematrix* b,
17421 : ae_state *_state)
17422 : {
17423 : ae_int_t i;
17424 : ae_int_t j;
17425 : ae_int_t jj;
17426 : ae_int_t j0;
17427 : ae_int_t j1;
17428 : ae_int_t k0;
17429 : ae_int_t k1;
17430 : ae_int_t kk;
17431 : ae_int_t n;
17432 : ae_int_t dst;
17433 : ae_bool bflag;
17434 :
17435 :
17436 0 : ae_assert(a->matrixtype==1, "SparseSymmPermTblBuf: incorrect matrix type (convert your matrix to CRS)", _state);
17437 0 : ae_assert(p->cnt>=a->n, "SparseSymmPermTblBuf: Length(P)<N", _state);
17438 0 : ae_assert(a->m==a->n, "SparseSymmPermTblBuf: matrix is non-square", _state);
17439 0 : bflag = ae_true;
17440 0 : for(i=0; i<=a->n-1; i++)
17441 : {
17442 0 : bflag = (bflag&&p->ptr.p_int[i]>=0)&&p->ptr.p_int[i]<a->n;
17443 : }
17444 0 : ae_assert(bflag, "SparseSymmPermTblBuf: P[] contains values outside of [0,N) range", _state);
17445 0 : n = a->n;
17446 :
17447 : /*
17448 : * Prepare output
17449 : */
17450 0 : ae_assert(a->ninitialized==a->ridx.ptr.p_int[n], "SparseSymmPermTblBuf: integrity check failed", _state);
17451 0 : b->matrixtype = 1;
17452 0 : b->n = n;
17453 0 : b->m = n;
17454 0 : ivectorsetlengthatleast(&b->didx, n, _state);
17455 0 : ivectorsetlengthatleast(&b->uidx, n, _state);
17456 :
17457 : /*
17458 : * Determine row sizes (temporary stored in DIdx) and ranges
17459 : */
17460 0 : isetv(n, 0, &b->didx, _state);
17461 0 : for(i=0; i<=n-1; i++)
17462 : {
17463 0 : if( isupper )
17464 : {
17465 0 : j0 = a->didx.ptr.p_int[i];
17466 0 : j1 = a->ridx.ptr.p_int[i+1]-1;
17467 0 : k0 = p->ptr.p_int[i];
17468 0 : for(jj=j0; jj<=j1; jj++)
17469 : {
17470 0 : k1 = p->ptr.p_int[a->idx.ptr.p_int[jj]];
17471 0 : if( k1<k0 )
17472 : {
17473 0 : b->didx.ptr.p_int[k1] = b->didx.ptr.p_int[k1]+1;
17474 : }
17475 : else
17476 : {
17477 0 : b->didx.ptr.p_int[k0] = b->didx.ptr.p_int[k0]+1;
17478 : }
17479 : }
17480 : }
17481 : else
17482 : {
17483 0 : j0 = a->ridx.ptr.p_int[i];
17484 0 : j1 = a->uidx.ptr.p_int[i]-1;
17485 0 : k0 = p->ptr.p_int[i];
17486 0 : for(jj=j0; jj<=j1; jj++)
17487 : {
17488 0 : k1 = p->ptr.p_int[a->idx.ptr.p_int[jj]];
17489 0 : if( k1>k0 )
17490 : {
17491 0 : b->didx.ptr.p_int[k1] = b->didx.ptr.p_int[k1]+1;
17492 : }
17493 : else
17494 : {
17495 0 : b->didx.ptr.p_int[k0] = b->didx.ptr.p_int[k0]+1;
17496 : }
17497 : }
17498 : }
17499 : }
17500 0 : ivectorsetlengthatleast(&b->ridx, n+1, _state);
17501 0 : b->ridx.ptr.p_int[0] = 0;
17502 0 : for(i=0; i<=n-1; i++)
17503 : {
17504 0 : b->ridx.ptr.p_int[i+1] = b->ridx.ptr.p_int[i]+b->didx.ptr.p_int[i];
17505 : }
17506 0 : b->ninitialized = b->ridx.ptr.p_int[n];
17507 0 : ivectorsetlengthatleast(&b->idx, b->ninitialized, _state);
17508 0 : rvectorsetlengthatleast(&b->vals, b->ninitialized, _state);
17509 :
17510 : /*
17511 : * Process matrix
17512 : */
17513 0 : for(i=0; i<=n-1; i++)
17514 : {
17515 0 : b->uidx.ptr.p_int[i] = b->ridx.ptr.p_int[i];
17516 : }
17517 0 : for(i=0; i<=n-1; i++)
17518 : {
17519 0 : if( isupper )
17520 : {
17521 0 : j0 = a->didx.ptr.p_int[i];
17522 0 : j1 = a->ridx.ptr.p_int[i+1]-1;
17523 0 : for(jj=j0; jj<=j1; jj++)
17524 : {
17525 0 : j = a->idx.ptr.p_int[jj];
17526 0 : k0 = p->ptr.p_int[i];
17527 0 : k1 = p->ptr.p_int[j];
17528 0 : if( k1<k0 )
17529 : {
17530 0 : kk = k0;
17531 0 : k0 = k1;
17532 0 : k1 = kk;
17533 : }
17534 0 : dst = b->uidx.ptr.p_int[k0];
17535 0 : b->idx.ptr.p_int[dst] = k1;
17536 0 : b->vals.ptr.p_double[dst] = a->vals.ptr.p_double[jj];
17537 0 : b->uidx.ptr.p_int[k0] = dst+1;
17538 : }
17539 : }
17540 : else
17541 : {
17542 0 : j0 = a->ridx.ptr.p_int[i];
17543 0 : j1 = a->uidx.ptr.p_int[i]-1;
17544 0 : for(jj=j0; jj<=j1; jj++)
17545 : {
17546 0 : j = a->idx.ptr.p_int[jj];
17547 0 : k0 = p->ptr.p_int[i];
17548 0 : k1 = p->ptr.p_int[j];
17549 0 : if( k1>k0 )
17550 : {
17551 0 : kk = k0;
17552 0 : k0 = k1;
17553 0 : k1 = kk;
17554 : }
17555 0 : dst = b->uidx.ptr.p_int[k0];
17556 0 : b->idx.ptr.p_int[dst] = k1;
17557 0 : b->vals.ptr.p_double[dst] = a->vals.ptr.p_double[jj];
17558 0 : b->uidx.ptr.p_int[k0] = dst+1;
17559 : }
17560 : }
17561 : }
17562 :
17563 : /*
17564 : * Finalize matrix
17565 : */
17566 0 : for(i=0; i<=n-1; i++)
17567 : {
17568 0 : tagsortmiddleir(&b->idx, &b->vals, b->ridx.ptr.p_int[i], b->ridx.ptr.p_int[i+1]-b->ridx.ptr.p_int[i], _state);
17569 : }
17570 0 : sparseinitduidx(b, _state);
17571 0 : }
17572 :
17573 :
17574 : /*************************************************************************
17575 : This procedure resizes Hash-Table matrix. It can be called when you have
17576 : deleted too many elements from the matrix, and you want to free unneeded
17577 : memory.
17578 :
17579 : -- ALGLIB PROJECT --
17580 : Copyright 14.10.2011 by Bochkanov Sergey
17581 : *************************************************************************/
17582 0 : void sparseresizematrix(sparsematrix* s, ae_state *_state)
17583 : {
17584 : ae_frame _frame_block;
17585 : ae_int_t k;
17586 : ae_int_t k1;
17587 : ae_int_t i;
17588 : ae_vector tvals;
17589 : ae_vector tidx;
17590 :
17591 0 : ae_frame_make(_state, &_frame_block);
17592 0 : memset(&tvals, 0, sizeof(tvals));
17593 0 : memset(&tidx, 0, sizeof(tidx));
17594 0 : ae_vector_init(&tvals, 0, DT_REAL, _state, ae_true);
17595 0 : ae_vector_init(&tidx, 0, DT_INT, _state, ae_true);
17596 :
17597 0 : ae_assert(s->matrixtype==0, "SparseResizeMatrix: incorrect matrix type", _state);
17598 :
17599 : /*
17600 : * Initialization for length and number of non-null elementd
17601 : */
17602 0 : k = s->tablesize;
17603 0 : k1 = 0;
17604 :
17605 : /*
17606 : * Calculating number of non-null elements
17607 : */
17608 0 : for(i=0; i<=k-1; i++)
17609 : {
17610 0 : if( s->idx.ptr.p_int[2*i]>=0 )
17611 : {
17612 0 : k1 = k1+1;
17613 : }
17614 : }
17615 :
17616 : /*
17617 : * Initialization value for free space
17618 : */
17619 0 : s->tablesize = ae_round(k1/sparse_desiredloadfactor*sparse_growfactor+sparse_additional, _state);
17620 0 : s->nfree = s->tablesize-k1;
17621 0 : ae_vector_set_length(&tvals, s->tablesize, _state);
17622 0 : ae_vector_set_length(&tidx, 2*s->tablesize, _state);
17623 0 : ae_swap_vectors(&s->vals, &tvals);
17624 0 : ae_swap_vectors(&s->idx, &tidx);
17625 0 : for(i=0; i<=s->tablesize-1; i++)
17626 : {
17627 0 : s->idx.ptr.p_int[2*i] = -1;
17628 : }
17629 0 : for(i=0; i<=k-1; i++)
17630 : {
17631 0 : if( tidx.ptr.p_int[2*i]>=0 )
17632 : {
17633 0 : sparseset(s, tidx.ptr.p_int[2*i], tidx.ptr.p_int[2*i+1], tvals.ptr.p_double[i], _state);
17634 : }
17635 : }
17636 0 : ae_frame_leave(_state);
17637 0 : }
17638 :
17639 :
17640 : /*************************************************************************
17641 : Procedure for initialization 'S.DIdx' and 'S.UIdx'
17642 :
17643 :
17644 : -- ALGLIB PROJECT --
17645 : Copyright 14.10.2011 by Bochkanov Sergey
17646 : *************************************************************************/
17647 0 : void sparseinitduidx(sparsematrix* s, ae_state *_state)
17648 : {
17649 : ae_int_t i;
17650 : ae_int_t j;
17651 : ae_int_t k;
17652 : ae_int_t lt;
17653 : ae_int_t rt;
17654 :
17655 :
17656 0 : ae_assert(s->matrixtype==1, "SparseInitDUIdx: internal error, incorrect matrix type", _state);
17657 0 : ivectorsetlengthatleast(&s->didx, s->m, _state);
17658 0 : ivectorsetlengthatleast(&s->uidx, s->m, _state);
17659 0 : for(i=0; i<=s->m-1; i++)
17660 : {
17661 0 : s->uidx.ptr.p_int[i] = -1;
17662 0 : s->didx.ptr.p_int[i] = -1;
17663 0 : lt = s->ridx.ptr.p_int[i];
17664 0 : rt = s->ridx.ptr.p_int[i+1];
17665 0 : for(j=lt; j<=rt-1; j++)
17666 : {
17667 0 : k = s->idx.ptr.p_int[j];
17668 0 : if( k==i )
17669 : {
17670 0 : s->didx.ptr.p_int[i] = j;
17671 : }
17672 : else
17673 : {
17674 0 : if( k>i&&s->uidx.ptr.p_int[i]==-1 )
17675 : {
17676 0 : s->uidx.ptr.p_int[i] = j;
17677 0 : break;
17678 : }
17679 : }
17680 : }
17681 0 : if( s->uidx.ptr.p_int[i]==-1 )
17682 : {
17683 0 : s->uidx.ptr.p_int[i] = s->ridx.ptr.p_int[i+1];
17684 : }
17685 0 : if( s->didx.ptr.p_int[i]==-1 )
17686 : {
17687 0 : s->didx.ptr.p_int[i] = s->uidx.ptr.p_int[i];
17688 : }
17689 : }
17690 0 : }
17691 :
17692 :
17693 : /*************************************************************************
17694 : This function return average length of chain at hash-table.
17695 :
17696 : -- ALGLIB PROJECT --
17697 : Copyright 14.10.2011 by Bochkanov Sergey
17698 : *************************************************************************/
17699 0 : double sparsegetaveragelengthofchain(sparsematrix* s, ae_state *_state)
17700 : {
17701 : ae_int_t nchains;
17702 : ae_int_t talc;
17703 : ae_int_t l;
17704 : ae_int_t i;
17705 : ae_int_t ind0;
17706 : ae_int_t ind1;
17707 : ae_int_t hashcode;
17708 : double result;
17709 :
17710 :
17711 :
17712 : /*
17713 : * If matrix represent in CRS then return zero and exit
17714 : */
17715 0 : if( s->matrixtype!=0 )
17716 : {
17717 0 : result = (double)(0);
17718 0 : return result;
17719 : }
17720 0 : nchains = 0;
17721 0 : talc = 0;
17722 0 : l = s->tablesize;
17723 0 : for(i=0; i<=l-1; i++)
17724 : {
17725 0 : ind0 = 2*i;
17726 0 : if( s->idx.ptr.p_int[ind0]!=-1 )
17727 : {
17728 0 : nchains = nchains+1;
17729 0 : hashcode = sparse_hash(s->idx.ptr.p_int[ind0], s->idx.ptr.p_int[ind0+1], l, _state);
17730 : for(;;)
17731 : {
17732 0 : talc = talc+1;
17733 0 : ind1 = 2*hashcode;
17734 0 : if( s->idx.ptr.p_int[ind0]==s->idx.ptr.p_int[ind1]&&s->idx.ptr.p_int[ind0+1]==s->idx.ptr.p_int[ind1+1] )
17735 : {
17736 0 : break;
17737 : }
17738 0 : hashcode = (hashcode+1)%l;
17739 : }
17740 : }
17741 : }
17742 0 : if( nchains==0 )
17743 : {
17744 0 : result = (double)(0);
17745 : }
17746 : else
17747 : {
17748 0 : result = (double)talc/(double)nchains;
17749 : }
17750 0 : return result;
17751 : }
17752 :
17753 :
17754 : /*************************************************************************
17755 : This function is used to enumerate all elements of the sparse matrix.
17756 : Before first call user initializes T0 and T1 counters by zero. These
17757 : counters are used to remember current position in a matrix; after each
17758 : call they are updated by the function.
17759 :
17760 : Subsequent calls to this function return non-zero elements of the sparse
17761 : matrix, one by one. If you enumerate CRS matrix, matrix is traversed from
17762 : left to right, from top to bottom. In case you enumerate matrix stored as
17763 : Hash table, elements are returned in random order.
17764 :
17765 : EXAMPLE
17766 : > T0=0
17767 : > T1=0
17768 : > while SparseEnumerate(S,T0,T1,I,J,V) do
17769 : > ....do something with I,J,V
17770 :
17771 : INPUT PARAMETERS
17772 : S - sparse M*N matrix in Hash-Table or CRS representation.
17773 : T0 - internal counter
17774 : T1 - internal counter
17775 :
17776 : OUTPUT PARAMETERS
17777 : T0 - new value of the internal counter
17778 : T1 - new value of the internal counter
17779 : I - row index of non-zero element, 0<=I<M.
17780 : J - column index of non-zero element, 0<=J<N
17781 : V - value of the T-th element
17782 :
17783 : RESULT
17784 : True in case of success (next non-zero element was retrieved)
17785 : False in case all non-zero elements were enumerated
17786 :
17787 : NOTE: you may call SparseRewriteExisting() during enumeration, but it is
17788 : THE ONLY matrix modification function you can call!!! Other
17789 : matrix modification functions should not be called during enumeration!
17790 :
17791 : -- ALGLIB PROJECT --
17792 : Copyright 14.03.2012 by Bochkanov Sergey
17793 : *************************************************************************/
17794 0 : ae_bool sparseenumerate(sparsematrix* s,
17795 : ae_int_t* t0,
17796 : ae_int_t* t1,
17797 : ae_int_t* i,
17798 : ae_int_t* j,
17799 : double* v,
17800 : ae_state *_state)
17801 : {
17802 : ae_int_t sz;
17803 : ae_int_t i0;
17804 : ae_bool result;
17805 :
17806 0 : *i = 0;
17807 0 : *j = 0;
17808 0 : *v = 0;
17809 :
17810 0 : result = ae_false;
17811 0 : if( *t0<0||(s->matrixtype!=0&&*t1<0) )
17812 : {
17813 :
17814 : /*
17815 : * Incorrect T0/T1, terminate enumeration
17816 : */
17817 0 : result = ae_false;
17818 0 : return result;
17819 : }
17820 0 : if( s->matrixtype==0 )
17821 : {
17822 :
17823 : /*
17824 : * Hash-table matrix
17825 : */
17826 0 : sz = s->tablesize;
17827 0 : for(i0=*t0; i0<=sz-1; i0++)
17828 : {
17829 0 : if( s->idx.ptr.p_int[2*i0]==-1||s->idx.ptr.p_int[2*i0]==-2 )
17830 : {
17831 0 : continue;
17832 : }
17833 : else
17834 : {
17835 0 : *i = s->idx.ptr.p_int[2*i0];
17836 0 : *j = s->idx.ptr.p_int[2*i0+1];
17837 0 : *v = s->vals.ptr.p_double[i0];
17838 0 : *t0 = i0+1;
17839 0 : result = ae_true;
17840 0 : return result;
17841 : }
17842 : }
17843 0 : *t0 = 0;
17844 0 : *t1 = 0;
17845 0 : result = ae_false;
17846 0 : return result;
17847 : }
17848 0 : if( s->matrixtype==1 )
17849 : {
17850 :
17851 : /*
17852 : * CRS matrix
17853 : */
17854 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseEnumerate: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
17855 0 : if( *t0>=s->ninitialized )
17856 : {
17857 0 : *t0 = 0;
17858 0 : *t1 = 0;
17859 0 : result = ae_false;
17860 0 : return result;
17861 : }
17862 0 : while(*t0>s->ridx.ptr.p_int[*t1+1]-1&&*t1<s->m)
17863 : {
17864 0 : *t1 = *t1+1;
17865 : }
17866 0 : *i = *t1;
17867 0 : *j = s->idx.ptr.p_int[*t0];
17868 0 : *v = s->vals.ptr.p_double[*t0];
17869 0 : *t0 = *t0+1;
17870 0 : result = ae_true;
17871 0 : return result;
17872 : }
17873 0 : if( s->matrixtype==2 )
17874 : {
17875 :
17876 : /*
17877 : * SKS matrix:
17878 : * * T0 stores current offset in Vals[] array
17879 : * * T1 stores index of the diagonal block
17880 : */
17881 0 : ae_assert(s->m==s->n, "SparseEnumerate: non-square SKS matrices are not supported", _state);
17882 0 : if( *t0>=s->ridx.ptr.p_int[s->m] )
17883 : {
17884 0 : *t0 = 0;
17885 0 : *t1 = 0;
17886 0 : result = ae_false;
17887 0 : return result;
17888 : }
17889 0 : while(*t0>s->ridx.ptr.p_int[*t1+1]-1&&*t1<s->m)
17890 : {
17891 0 : *t1 = *t1+1;
17892 : }
17893 0 : i0 = *t0-s->ridx.ptr.p_int[*t1];
17894 0 : if( i0<s->didx.ptr.p_int[*t1]+1 )
17895 : {
17896 :
17897 : /*
17898 : * subdiagonal or diagonal element, row index is T1.
17899 : */
17900 0 : *i = *t1;
17901 0 : *j = *t1-s->didx.ptr.p_int[*t1]+i0;
17902 : }
17903 : else
17904 : {
17905 :
17906 : /*
17907 : * superdiagonal element, column index is T1.
17908 : */
17909 0 : *i = *t1-(s->ridx.ptr.p_int[*t1+1]-(*t0));
17910 0 : *j = *t1;
17911 : }
17912 0 : *v = s->vals.ptr.p_double[*t0];
17913 0 : *t0 = *t0+1;
17914 0 : result = ae_true;
17915 0 : return result;
17916 : }
17917 0 : ae_assert(ae_false, "SparseEnumerate: unexpected matrix type", _state);
17918 0 : return result;
17919 : }
17920 :
17921 :
17922 : /*************************************************************************
17923 : This function rewrites existing (non-zero) element. It returns True if
17924 : element exists or False, when it is called for non-existing (zero)
17925 : element.
17926 :
17927 : This function works with any kind of the matrix.
17928 :
17929 : The purpose of this function is to provide convenient thread-safe way to
17930 : modify sparse matrix. Such modification (already existing element is
17931 : rewritten) is guaranteed to be thread-safe without any synchronization, as
17932 : long as different threads modify different elements.
17933 :
17934 : INPUT PARAMETERS
17935 : S - sparse M*N matrix in any kind of representation
17936 : (Hash, SKS, CRS).
17937 : I - row index of non-zero element to modify, 0<=I<M
17938 : J - column index of non-zero element to modify, 0<=J<N
17939 : V - value to rewrite, must be finite number
17940 :
17941 : OUTPUT PARAMETERS
17942 : S - modified matrix
17943 : RESULT
17944 : True in case when element exists
17945 : False in case when element doesn't exist or it is zero
17946 :
17947 : -- ALGLIB PROJECT --
17948 : Copyright 14.03.2012 by Bochkanov Sergey
17949 : *************************************************************************/
17950 0 : ae_bool sparserewriteexisting(sparsematrix* s,
17951 : ae_int_t i,
17952 : ae_int_t j,
17953 : double v,
17954 : ae_state *_state)
17955 : {
17956 : ae_int_t hashcode;
17957 : ae_int_t k;
17958 : ae_int_t k0;
17959 : ae_int_t k1;
17960 : ae_bool result;
17961 :
17962 :
17963 0 : ae_assert(0<=i&&i<s->m, "SparseRewriteExisting: invalid argument I(either I<0 or I>=S.M)", _state);
17964 0 : ae_assert(0<=j&&j<s->n, "SparseRewriteExisting: invalid argument J(either J<0 or J>=S.N)", _state);
17965 0 : ae_assert(ae_isfinite(v, _state), "SparseRewriteExisting: invalid argument V(either V is infinite or V is NaN)", _state);
17966 0 : result = ae_false;
17967 :
17968 : /*
17969 : * Hash-table matrix
17970 : */
17971 0 : if( s->matrixtype==0 )
17972 : {
17973 0 : k = s->tablesize;
17974 0 : hashcode = sparse_hash(i, j, k, _state);
17975 : for(;;)
17976 : {
17977 0 : if( s->idx.ptr.p_int[2*hashcode]==-1 )
17978 : {
17979 0 : return result;
17980 : }
17981 0 : if( s->idx.ptr.p_int[2*hashcode]==i&&s->idx.ptr.p_int[2*hashcode+1]==j )
17982 : {
17983 0 : s->vals.ptr.p_double[hashcode] = v;
17984 0 : result = ae_true;
17985 0 : return result;
17986 : }
17987 0 : hashcode = (hashcode+1)%k;
17988 : }
17989 : }
17990 :
17991 : /*
17992 : * CRS matrix
17993 : */
17994 0 : if( s->matrixtype==1 )
17995 : {
17996 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseRewriteExisting: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
17997 0 : k0 = s->ridx.ptr.p_int[i];
17998 0 : k1 = s->ridx.ptr.p_int[i+1]-1;
17999 0 : while(k0<=k1)
18000 : {
18001 0 : k = (k0+k1)/2;
18002 0 : if( s->idx.ptr.p_int[k]==j )
18003 : {
18004 0 : s->vals.ptr.p_double[k] = v;
18005 0 : result = ae_true;
18006 0 : return result;
18007 : }
18008 0 : if( s->idx.ptr.p_int[k]<j )
18009 : {
18010 0 : k0 = k+1;
18011 : }
18012 : else
18013 : {
18014 0 : k1 = k-1;
18015 : }
18016 : }
18017 : }
18018 :
18019 : /*
18020 : * SKS
18021 : */
18022 0 : if( s->matrixtype==2 )
18023 : {
18024 0 : ae_assert(s->m==s->n, "SparseRewriteExisting: non-square SKS matrix not supported", _state);
18025 0 : if( i==j )
18026 : {
18027 :
18028 : /*
18029 : * Rewrite diagonal element
18030 : */
18031 0 : result = ae_true;
18032 0 : s->vals.ptr.p_double[s->ridx.ptr.p_int[i]+s->didx.ptr.p_int[i]] = v;
18033 0 : return result;
18034 : }
18035 0 : if( j<i )
18036 : {
18037 :
18038 : /*
18039 : * Return subdiagonal element at I-th "skyline block"
18040 : */
18041 0 : k = s->didx.ptr.p_int[i];
18042 0 : if( i-j<=k )
18043 : {
18044 0 : s->vals.ptr.p_double[s->ridx.ptr.p_int[i]+k+j-i] = v;
18045 0 : result = ae_true;
18046 : }
18047 : }
18048 : else
18049 : {
18050 :
18051 : /*
18052 : * Return superdiagonal element at J-th "skyline block"
18053 : */
18054 0 : k = s->uidx.ptr.p_int[j];
18055 0 : if( j-i<=k )
18056 : {
18057 0 : s->vals.ptr.p_double[s->ridx.ptr.p_int[j+1]-(j-i)] = v;
18058 0 : result = ae_true;
18059 : }
18060 : }
18061 0 : return result;
18062 : }
18063 0 : return result;
18064 : }
18065 :
18066 :
18067 : /*************************************************************************
18068 : This function returns I-th row of the sparse matrix. Matrix must be stored
18069 : in CRS or SKS format.
18070 :
18071 : INPUT PARAMETERS:
18072 : S - sparse M*N matrix in CRS format
18073 : I - row index, 0<=I<M
18074 : IRow - output buffer, can be preallocated. In case buffer
18075 : size is too small to store I-th row, it is
18076 : automatically reallocated.
18077 :
18078 : OUTPUT PARAMETERS:
18079 : IRow - array[M], I-th row.
18080 :
18081 : NOTE: this function has O(N) running time, where N is a column count. It
18082 : allocates and fills N-element array, even although most of its
18083 : elemets are zero.
18084 :
18085 : NOTE: If you have O(non-zeros-per-row) time and memory requirements, use
18086 : SparseGetCompressedRow() function. It returns data in compressed
18087 : format.
18088 :
18089 : NOTE: when incorrect I (outside of [0,M-1]) or matrix (non CRS/SKS)
18090 : is passed, this function throws exception.
18091 :
18092 : -- ALGLIB PROJECT --
18093 : Copyright 10.12.2014 by Bochkanov Sergey
18094 : *************************************************************************/
18095 0 : void sparsegetrow(sparsematrix* s,
18096 : ae_int_t i,
18097 : /* Real */ ae_vector* irow,
18098 : ae_state *_state)
18099 : {
18100 : ae_int_t i0;
18101 : ae_int_t j0;
18102 : ae_int_t j1;
18103 : ae_int_t j;
18104 : ae_int_t upperprofile;
18105 :
18106 :
18107 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseGetRow: S must be CRS/SKS-based matrix", _state);
18108 0 : ae_assert(i>=0&&i<s->m, "SparseGetRow: I<0 or I>=M", _state);
18109 :
18110 : /*
18111 : * Prepare output buffer
18112 : */
18113 0 : rvectorsetlengthatleast(irow, s->n, _state);
18114 0 : for(i0=0; i0<=s->n-1; i0++)
18115 : {
18116 0 : irow->ptr.p_double[i0] = (double)(0);
18117 : }
18118 :
18119 : /*
18120 : * Output
18121 : */
18122 0 : if( s->matrixtype==1 )
18123 : {
18124 0 : for(i0=s->ridx.ptr.p_int[i]; i0<=s->ridx.ptr.p_int[i+1]-1; i0++)
18125 : {
18126 0 : irow->ptr.p_double[s->idx.ptr.p_int[i0]] = s->vals.ptr.p_double[i0];
18127 : }
18128 0 : return;
18129 : }
18130 0 : if( s->matrixtype==2 )
18131 : {
18132 :
18133 : /*
18134 : * Copy subdiagonal and diagonal parts
18135 : */
18136 0 : ae_assert(s->n==s->m, "SparseGetRow: non-square SKS matrices are not supported", _state);
18137 0 : j0 = i-s->didx.ptr.p_int[i];
18138 0 : i0 = -j0+s->ridx.ptr.p_int[i];
18139 0 : for(j=j0; j<=i; j++)
18140 : {
18141 0 : irow->ptr.p_double[j] = s->vals.ptr.p_double[j+i0];
18142 : }
18143 :
18144 : /*
18145 : * Copy superdiagonal part
18146 : */
18147 0 : upperprofile = s->uidx.ptr.p_int[s->n];
18148 0 : j0 = i+1;
18149 0 : j1 = ae_minint(s->n-1, i+upperprofile, _state);
18150 0 : for(j=j0; j<=j1; j++)
18151 : {
18152 0 : if( j-i<=s->uidx.ptr.p_int[j] )
18153 : {
18154 0 : irow->ptr.p_double[j] = s->vals.ptr.p_double[s->ridx.ptr.p_int[j+1]-(j-i)];
18155 : }
18156 : }
18157 0 : return;
18158 : }
18159 : }
18160 :
18161 :
18162 : /*************************************************************************
18163 : This function returns I-th row of the sparse matrix IN COMPRESSED FORMAT -
18164 : only non-zero elements are returned (with their indexes). Matrix must be
18165 : stored in CRS or SKS format.
18166 :
18167 : INPUT PARAMETERS:
18168 : S - sparse M*N matrix in CRS format
18169 : I - row index, 0<=I<M
18170 : ColIdx - output buffer for column indexes, can be preallocated.
18171 : In case buffer size is too small to store I-th row, it
18172 : is automatically reallocated.
18173 : Vals - output buffer for values, can be preallocated. In case
18174 : buffer size is too small to store I-th row, it is
18175 : automatically reallocated.
18176 :
18177 : OUTPUT PARAMETERS:
18178 : ColIdx - column indexes of non-zero elements, sorted by
18179 : ascending. Symbolically non-zero elements are counted
18180 : (i.e. if you allocated place for element, but it has
18181 : zero numerical value - it is counted).
18182 : Vals - values. Vals[K] stores value of matrix element with
18183 : indexes (I,ColIdx[K]). Symbolically non-zero elements
18184 : are counted (i.e. if you allocated place for element,
18185 : but it has zero numerical value - it is counted).
18186 : NZCnt - number of symbolically non-zero elements per row.
18187 :
18188 : NOTE: when incorrect I (outside of [0,M-1]) or matrix (non CRS/SKS)
18189 : is passed, this function throws exception.
18190 :
18191 : NOTE: this function may allocate additional, unnecessary place for ColIdx
18192 : and Vals arrays. It is dictated by performance reasons - on SKS
18193 : matrices it is faster to allocate space at the beginning with
18194 : some "extra"-space, than performing two passes over matrix - first
18195 : time to calculate exact space required for data, second time - to
18196 : store data itself.
18197 :
18198 : -- ALGLIB PROJECT --
18199 : Copyright 10.12.2014 by Bochkanov Sergey
18200 : *************************************************************************/
18201 0 : void sparsegetcompressedrow(sparsematrix* s,
18202 : ae_int_t i,
18203 : /* Integer */ ae_vector* colidx,
18204 : /* Real */ ae_vector* vals,
18205 : ae_int_t* nzcnt,
18206 : ae_state *_state)
18207 : {
18208 : ae_int_t k;
18209 : ae_int_t k0;
18210 : ae_int_t j;
18211 : ae_int_t j0;
18212 : ae_int_t j1;
18213 : ae_int_t i0;
18214 : ae_int_t upperprofile;
18215 :
18216 0 : *nzcnt = 0;
18217 :
18218 0 : ae_assert(s->matrixtype==1||s->matrixtype==2, "SparseGetRow: S must be CRS/SKS-based matrix", _state);
18219 0 : ae_assert(i>=0&&i<s->m, "SparseGetRow: I<0 or I>=M", _state);
18220 :
18221 : /*
18222 : * Initialize NZCnt
18223 : */
18224 0 : *nzcnt = 0;
18225 :
18226 : /*
18227 : * CRS matrix - just copy data
18228 : */
18229 0 : if( s->matrixtype==1 )
18230 : {
18231 0 : *nzcnt = s->ridx.ptr.p_int[i+1]-s->ridx.ptr.p_int[i];
18232 0 : ivectorsetlengthatleast(colidx, *nzcnt, _state);
18233 0 : rvectorsetlengthatleast(vals, *nzcnt, _state);
18234 0 : k0 = s->ridx.ptr.p_int[i];
18235 0 : for(k=0; k<=*nzcnt-1; k++)
18236 : {
18237 0 : colidx->ptr.p_int[k] = s->idx.ptr.p_int[k0+k];
18238 0 : vals->ptr.p_double[k] = s->vals.ptr.p_double[k0+k];
18239 : }
18240 0 : return;
18241 : }
18242 :
18243 : /*
18244 : * SKS matrix - a bit more complex sequence
18245 : */
18246 0 : if( s->matrixtype==2 )
18247 : {
18248 0 : ae_assert(s->n==s->m, "SparseGetCompressedRow: non-square SKS matrices are not supported", _state);
18249 :
18250 : /*
18251 : * Allocate enough place for storage
18252 : */
18253 0 : upperprofile = s->uidx.ptr.p_int[s->n];
18254 0 : ivectorsetlengthatleast(colidx, s->didx.ptr.p_int[i]+1+upperprofile, _state);
18255 0 : rvectorsetlengthatleast(vals, s->didx.ptr.p_int[i]+1+upperprofile, _state);
18256 :
18257 : /*
18258 : * Copy subdiagonal and diagonal parts
18259 : */
18260 0 : j0 = i-s->didx.ptr.p_int[i];
18261 0 : i0 = -j0+s->ridx.ptr.p_int[i];
18262 0 : for(j=j0; j<=i; j++)
18263 : {
18264 0 : colidx->ptr.p_int[*nzcnt] = j;
18265 0 : vals->ptr.p_double[*nzcnt] = s->vals.ptr.p_double[j+i0];
18266 0 : *nzcnt = *nzcnt+1;
18267 : }
18268 :
18269 : /*
18270 : * Copy superdiagonal part
18271 : */
18272 0 : j0 = i+1;
18273 0 : j1 = ae_minint(s->n-1, i+upperprofile, _state);
18274 0 : for(j=j0; j<=j1; j++)
18275 : {
18276 0 : if( j-i<=s->uidx.ptr.p_int[j] )
18277 : {
18278 0 : colidx->ptr.p_int[*nzcnt] = j;
18279 0 : vals->ptr.p_double[*nzcnt] = s->vals.ptr.p_double[s->ridx.ptr.p_int[j+1]-(j-i)];
18280 0 : *nzcnt = *nzcnt+1;
18281 : }
18282 : }
18283 0 : return;
18284 : }
18285 : }
18286 :
18287 :
18288 : /*************************************************************************
18289 : This function performs efficient in-place transpose of SKS matrix. No
18290 : additional memory is allocated during transposition.
18291 :
18292 : This function supports only skyline storage format (SKS).
18293 :
18294 : INPUT PARAMETERS
18295 : S - sparse matrix in SKS format.
18296 :
18297 : OUTPUT PARAMETERS
18298 : S - sparse matrix, transposed.
18299 :
18300 : -- ALGLIB PROJECT --
18301 : Copyright 16.01.2014 by Bochkanov Sergey
18302 : *************************************************************************/
18303 0 : void sparsetransposesks(sparsematrix* s, ae_state *_state)
18304 : {
18305 : ae_int_t n;
18306 : ae_int_t d;
18307 : ae_int_t u;
18308 : ae_int_t i;
18309 : ae_int_t k;
18310 : ae_int_t t0;
18311 : ae_int_t t1;
18312 : double v;
18313 :
18314 :
18315 0 : ae_assert(s->matrixtype==2, "SparseTransposeSKS: only SKS matrices are supported", _state);
18316 0 : ae_assert(s->m==s->n, "SparseTransposeSKS: non-square SKS matrices are not supported", _state);
18317 0 : n = s->n;
18318 0 : for(i=1; i<=n-1; i++)
18319 : {
18320 0 : d = s->didx.ptr.p_int[i];
18321 0 : u = s->uidx.ptr.p_int[i];
18322 0 : k = s->uidx.ptr.p_int[i];
18323 0 : s->uidx.ptr.p_int[i] = s->didx.ptr.p_int[i];
18324 0 : s->didx.ptr.p_int[i] = k;
18325 0 : if( d==u )
18326 : {
18327 :
18328 : /*
18329 : * Upper skyline height equal to lower skyline height,
18330 : * simple exchange is needed for transposition
18331 : */
18332 0 : t0 = s->ridx.ptr.p_int[i];
18333 0 : for(k=0; k<=d-1; k++)
18334 : {
18335 0 : v = s->vals.ptr.p_double[t0+k];
18336 0 : s->vals.ptr.p_double[t0+k] = s->vals.ptr.p_double[t0+d+1+k];
18337 0 : s->vals.ptr.p_double[t0+d+1+k] = v;
18338 : }
18339 : }
18340 0 : if( d>u )
18341 : {
18342 :
18343 : /*
18344 : * Upper skyline height is less than lower skyline height.
18345 : *
18346 : * Transposition becomes a bit tricky: we have to rearrange
18347 : * "L0 L1 D U" to "U D L0 L1", where |L0|=|U|=u, |L1|=d-u.
18348 : *
18349 : * In order to do this we perform a sequence of swaps and
18350 : * in-place reversals:
18351 : * * swap(L0,U) => "U L1 D L0"
18352 : * * reverse("L1 D L0") => "U L0~ D L1~" (where X~ is a reverse of X)
18353 : * * reverse("L0~ D") => "U D L0 L1~"
18354 : * * reverse("L1") => "U D L0 L1"
18355 : */
18356 0 : t0 = s->ridx.ptr.p_int[i];
18357 0 : t1 = s->ridx.ptr.p_int[i]+d+1;
18358 0 : for(k=0; k<=u-1; k++)
18359 : {
18360 0 : v = s->vals.ptr.p_double[t0+k];
18361 0 : s->vals.ptr.p_double[t0+k] = s->vals.ptr.p_double[t1+k];
18362 0 : s->vals.ptr.p_double[t1+k] = v;
18363 : }
18364 0 : t0 = s->ridx.ptr.p_int[i]+u;
18365 0 : t1 = s->ridx.ptr.p_int[i+1]-1;
18366 0 : while(t1>t0)
18367 : {
18368 0 : v = s->vals.ptr.p_double[t0];
18369 0 : s->vals.ptr.p_double[t0] = s->vals.ptr.p_double[t1];
18370 0 : s->vals.ptr.p_double[t1] = v;
18371 0 : t0 = t0+1;
18372 0 : t1 = t1-1;
18373 : }
18374 0 : t0 = s->ridx.ptr.p_int[i]+u;
18375 0 : t1 = s->ridx.ptr.p_int[i]+u+u;
18376 0 : while(t1>t0)
18377 : {
18378 0 : v = s->vals.ptr.p_double[t0];
18379 0 : s->vals.ptr.p_double[t0] = s->vals.ptr.p_double[t1];
18380 0 : s->vals.ptr.p_double[t1] = v;
18381 0 : t0 = t0+1;
18382 0 : t1 = t1-1;
18383 : }
18384 0 : t0 = s->ridx.ptr.p_int[i+1]-(d-u);
18385 0 : t1 = s->ridx.ptr.p_int[i+1]-1;
18386 0 : while(t1>t0)
18387 : {
18388 0 : v = s->vals.ptr.p_double[t0];
18389 0 : s->vals.ptr.p_double[t0] = s->vals.ptr.p_double[t1];
18390 0 : s->vals.ptr.p_double[t1] = v;
18391 0 : t0 = t0+1;
18392 0 : t1 = t1-1;
18393 : }
18394 : }
18395 0 : if( d<u )
18396 : {
18397 :
18398 : /*
18399 : * Upper skyline height is greater than lower skyline height.
18400 : *
18401 : * Transposition becomes a bit tricky: we have to rearrange
18402 : * "L D U0 U1" to "U0 U1 D L", where |U1|=|L|=d, |U0|=u-d.
18403 : *
18404 : * In order to do this we perform a sequence of swaps and
18405 : * in-place reversals:
18406 : * * swap(L,U1) => "U1 D U0 L"
18407 : * * reverse("U1 D U0") => "U0~ D U1~ L" (where X~ is a reverse of X)
18408 : * * reverse("U0~") => "U0 D U1~ L"
18409 : * * reverse("D U1~") => "U0 U1 D L"
18410 : */
18411 0 : t0 = s->ridx.ptr.p_int[i];
18412 0 : t1 = s->ridx.ptr.p_int[i+1]-d;
18413 0 : for(k=0; k<=d-1; k++)
18414 : {
18415 0 : v = s->vals.ptr.p_double[t0+k];
18416 0 : s->vals.ptr.p_double[t0+k] = s->vals.ptr.p_double[t1+k];
18417 0 : s->vals.ptr.p_double[t1+k] = v;
18418 : }
18419 0 : t0 = s->ridx.ptr.p_int[i];
18420 0 : t1 = s->ridx.ptr.p_int[i]+u;
18421 0 : while(t1>t0)
18422 : {
18423 0 : v = s->vals.ptr.p_double[t0];
18424 0 : s->vals.ptr.p_double[t0] = s->vals.ptr.p_double[t1];
18425 0 : s->vals.ptr.p_double[t1] = v;
18426 0 : t0 = t0+1;
18427 0 : t1 = t1-1;
18428 : }
18429 0 : t0 = s->ridx.ptr.p_int[i];
18430 0 : t1 = s->ridx.ptr.p_int[i]+u-d-1;
18431 0 : while(t1>t0)
18432 : {
18433 0 : v = s->vals.ptr.p_double[t0];
18434 0 : s->vals.ptr.p_double[t0] = s->vals.ptr.p_double[t1];
18435 0 : s->vals.ptr.p_double[t1] = v;
18436 0 : t0 = t0+1;
18437 0 : t1 = t1-1;
18438 : }
18439 0 : t0 = s->ridx.ptr.p_int[i]+u-d;
18440 0 : t1 = s->ridx.ptr.p_int[i+1]-d-1;
18441 0 : while(t1>t0)
18442 : {
18443 0 : v = s->vals.ptr.p_double[t0];
18444 0 : s->vals.ptr.p_double[t0] = s->vals.ptr.p_double[t1];
18445 0 : s->vals.ptr.p_double[t1] = v;
18446 0 : t0 = t0+1;
18447 0 : t1 = t1-1;
18448 : }
18449 : }
18450 : }
18451 0 : k = s->uidx.ptr.p_int[n];
18452 0 : s->uidx.ptr.p_int[n] = s->didx.ptr.p_int[n];
18453 0 : s->didx.ptr.p_int[n] = k;
18454 0 : }
18455 :
18456 :
18457 : /*************************************************************************
18458 : This function performs transpose of CRS matrix.
18459 :
18460 : INPUT PARAMETERS
18461 : S - sparse matrix in CRS format.
18462 :
18463 : OUTPUT PARAMETERS
18464 : S - sparse matrix, transposed.
18465 :
18466 : NOTE: internal temporary copy is allocated for the purposes of
18467 : transposition. It is deallocated after transposition.
18468 :
18469 : -- ALGLIB PROJECT --
18470 : Copyright 30.01.2018 by Bochkanov Sergey
18471 : *************************************************************************/
18472 0 : void sparsetransposecrs(sparsematrix* s, ae_state *_state)
18473 : {
18474 : ae_frame _frame_block;
18475 : ae_vector oldvals;
18476 : ae_vector oldidx;
18477 : ae_vector oldridx;
18478 : ae_int_t oldn;
18479 : ae_int_t oldm;
18480 : ae_int_t newn;
18481 : ae_int_t newm;
18482 : ae_int_t i;
18483 : ae_int_t j;
18484 : ae_int_t k;
18485 : ae_int_t nonne;
18486 : ae_vector counts;
18487 :
18488 0 : ae_frame_make(_state, &_frame_block);
18489 0 : memset(&oldvals, 0, sizeof(oldvals));
18490 0 : memset(&oldidx, 0, sizeof(oldidx));
18491 0 : memset(&oldridx, 0, sizeof(oldridx));
18492 0 : memset(&counts, 0, sizeof(counts));
18493 0 : ae_vector_init(&oldvals, 0, DT_REAL, _state, ae_true);
18494 0 : ae_vector_init(&oldidx, 0, DT_INT, _state, ae_true);
18495 0 : ae_vector_init(&oldridx, 0, DT_INT, _state, ae_true);
18496 0 : ae_vector_init(&counts, 0, DT_INT, _state, ae_true);
18497 :
18498 0 : ae_assert(s->matrixtype==1, "SparseTransposeCRS: only CRS matrices are supported", _state);
18499 0 : ae_swap_vectors(&s->vals, &oldvals);
18500 0 : ae_swap_vectors(&s->idx, &oldidx);
18501 0 : ae_swap_vectors(&s->ridx, &oldridx);
18502 0 : oldn = s->n;
18503 0 : oldm = s->m;
18504 0 : newn = oldm;
18505 0 : newm = oldn;
18506 :
18507 : /*
18508 : * Update matrix size
18509 : */
18510 0 : s->n = newn;
18511 0 : s->m = newm;
18512 :
18513 : /*
18514 : * Fill RIdx by number of elements per row:
18515 : * RIdx[I+1] stores number of elements in I-th row.
18516 : *
18517 : * Convert RIdx from row sizes to row offsets.
18518 : * Set NInitialized
18519 : */
18520 0 : nonne = 0;
18521 0 : ivectorsetlengthatleast(&s->ridx, newm+1, _state);
18522 0 : for(i=0; i<=newm; i++)
18523 : {
18524 0 : s->ridx.ptr.p_int[i] = 0;
18525 : }
18526 0 : for(i=0; i<=oldm-1; i++)
18527 : {
18528 0 : for(j=oldridx.ptr.p_int[i]; j<=oldridx.ptr.p_int[i+1]-1; j++)
18529 : {
18530 0 : k = oldidx.ptr.p_int[j]+1;
18531 0 : s->ridx.ptr.p_int[k] = s->ridx.ptr.p_int[k]+1;
18532 0 : nonne = nonne+1;
18533 : }
18534 : }
18535 0 : for(i=0; i<=newm-1; i++)
18536 : {
18537 0 : s->ridx.ptr.p_int[i+1] = s->ridx.ptr.p_int[i+1]+s->ridx.ptr.p_int[i];
18538 : }
18539 0 : s->ninitialized = s->ridx.ptr.p_int[newm];
18540 :
18541 : /*
18542 : * Allocate memory and move elements to Vals/Idx.
18543 : */
18544 0 : ae_vector_set_length(&counts, newm, _state);
18545 0 : for(i=0; i<=newm-1; i++)
18546 : {
18547 0 : counts.ptr.p_int[i] = 0;
18548 : }
18549 0 : rvectorsetlengthatleast(&s->vals, nonne, _state);
18550 0 : ivectorsetlengthatleast(&s->idx, nonne, _state);
18551 0 : for(i=0; i<=oldm-1; i++)
18552 : {
18553 0 : for(j=oldridx.ptr.p_int[i]; j<=oldridx.ptr.p_int[i+1]-1; j++)
18554 : {
18555 0 : k = oldidx.ptr.p_int[j];
18556 0 : k = s->ridx.ptr.p_int[k]+counts.ptr.p_int[k];
18557 0 : s->idx.ptr.p_int[k] = i;
18558 0 : s->vals.ptr.p_double[k] = oldvals.ptr.p_double[j];
18559 0 : k = oldidx.ptr.p_int[j];
18560 0 : counts.ptr.p_int[k] = counts.ptr.p_int[k]+1;
18561 : }
18562 : }
18563 :
18564 : /*
18565 : * Initialization 'S.UIdx' and 'S.DIdx'
18566 : */
18567 0 : sparseinitduidx(s, _state);
18568 0 : ae_frame_leave(_state);
18569 0 : }
18570 :
18571 :
18572 : /*************************************************************************
18573 : This function performs copying with transposition of CRS matrix.
18574 :
18575 : INPUT PARAMETERS
18576 : S0 - sparse matrix in CRS format.
18577 :
18578 : OUTPUT PARAMETERS
18579 : S1 - sparse matrix, transposed
18580 :
18581 : -- ALGLIB PROJECT --
18582 : Copyright 23.07.2018 by Bochkanov Sergey
18583 : *************************************************************************/
18584 0 : void sparsecopytransposecrs(sparsematrix* s0,
18585 : sparsematrix* s1,
18586 : ae_state *_state)
18587 : {
18588 :
18589 0 : _sparsematrix_clear(s1);
18590 :
18591 0 : sparsecopytransposecrsbuf(s0, s1, _state);
18592 0 : }
18593 :
18594 :
18595 : /*************************************************************************
18596 : This function performs copying with transposition of CRS matrix (buffered
18597 : version which reuses memory already allocated by the target as much as
18598 : possible).
18599 :
18600 : INPUT PARAMETERS
18601 : S0 - sparse matrix in CRS format.
18602 :
18603 : OUTPUT PARAMETERS
18604 : S1 - sparse matrix, transposed; previously allocated memory is
18605 : reused if possible.
18606 :
18607 : -- ALGLIB PROJECT --
18608 : Copyright 23.07.2018 by Bochkanov Sergey
18609 : *************************************************************************/
18610 0 : void sparsecopytransposecrsbuf(sparsematrix* s0,
18611 : sparsematrix* s1,
18612 : ae_state *_state)
18613 : {
18614 : ae_int_t oldn;
18615 : ae_int_t oldm;
18616 : ae_int_t newn;
18617 : ae_int_t newm;
18618 : ae_int_t i;
18619 : ae_int_t j;
18620 : ae_int_t k;
18621 : ae_int_t kk;
18622 : ae_int_t j0;
18623 : ae_int_t j1;
18624 :
18625 :
18626 0 : ae_assert(s0->matrixtype==1, "SparseCopyTransposeCRSBuf: only CRS matrices are supported", _state);
18627 0 : oldn = s0->n;
18628 0 : oldm = s0->m;
18629 0 : newn = oldm;
18630 0 : newm = oldn;
18631 :
18632 : /*
18633 : * Update matrix size
18634 : */
18635 0 : s1->matrixtype = 1;
18636 0 : s1->n = newn;
18637 0 : s1->m = newm;
18638 :
18639 : /*
18640 : * Fill RIdx by number of elements per row:
18641 : * RIdx[I+1] stores number of elements in I-th row.
18642 : *
18643 : * Convert RIdx from row sizes to row offsets.
18644 : * Set NInitialized
18645 : */
18646 0 : isetallocv(newm+1, 0, &s1->ridx, _state);
18647 0 : for(i=0; i<=oldm-1; i++)
18648 : {
18649 0 : j0 = s0->ridx.ptr.p_int[i];
18650 0 : j1 = s0->ridx.ptr.p_int[i+1]-1;
18651 0 : for(j=j0; j<=j1; j++)
18652 : {
18653 0 : k = s0->idx.ptr.p_int[j]+1;
18654 0 : s1->ridx.ptr.p_int[k] = s1->ridx.ptr.p_int[k]+1;
18655 : }
18656 : }
18657 0 : for(i=0; i<=newm-1; i++)
18658 : {
18659 0 : s1->ridx.ptr.p_int[i+1] = s1->ridx.ptr.p_int[i+1]+s1->ridx.ptr.p_int[i];
18660 : }
18661 0 : s1->ninitialized = s1->ridx.ptr.p_int[newm];
18662 :
18663 : /*
18664 : * Allocate memory and move elements to Vals/Idx.
18665 : */
18666 0 : ivectorsetlengthatleast(&s1->didx, newm, _state);
18667 0 : for(i=0; i<=newm-1; i++)
18668 : {
18669 0 : s1->didx.ptr.p_int[i] = s1->ridx.ptr.p_int[i];
18670 : }
18671 0 : rvectorsetlengthatleast(&s1->vals, s1->ninitialized, _state);
18672 0 : ivectorsetlengthatleast(&s1->idx, s1->ninitialized, _state);
18673 0 : for(i=0; i<=oldm-1; i++)
18674 : {
18675 0 : j0 = s0->ridx.ptr.p_int[i];
18676 0 : j1 = s0->ridx.ptr.p_int[i+1]-1;
18677 0 : for(j=j0; j<=j1; j++)
18678 : {
18679 0 : kk = s0->idx.ptr.p_int[j];
18680 0 : k = s1->didx.ptr.p_int[kk];
18681 0 : s1->idx.ptr.p_int[k] = i;
18682 0 : s1->vals.ptr.p_double[k] = s0->vals.ptr.p_double[j];
18683 0 : s1->didx.ptr.p_int[kk] = k+1;
18684 : }
18685 : }
18686 :
18687 : /*
18688 : * Initialization 'S.UIdx' and 'S.DIdx'
18689 : */
18690 0 : sparseinitduidx(s1, _state);
18691 0 : }
18692 :
18693 :
18694 : /*************************************************************************
18695 : This function performs in-place conversion to desired sparse storage
18696 : format.
18697 :
18698 : INPUT PARAMETERS
18699 : S0 - sparse matrix in any format.
18700 : Fmt - desired storage format of the output, as returned by
18701 : SparseGetMatrixType() function:
18702 : * 0 for hash-based storage
18703 : * 1 for CRS
18704 : * 2 for SKS
18705 :
18706 : OUTPUT PARAMETERS
18707 : S0 - sparse matrix in requested format.
18708 :
18709 : NOTE: in-place conversion wastes a lot of memory which is used to store
18710 : temporaries. If you perform a lot of repeated conversions, we
18711 : recommend to use out-of-place buffered conversion functions, like
18712 : SparseCopyToBuf(), which can reuse already allocated memory.
18713 :
18714 : -- ALGLIB PROJECT --
18715 : Copyright 16.01.2014 by Bochkanov Sergey
18716 : *************************************************************************/
18717 0 : void sparseconvertto(sparsematrix* s0, ae_int_t fmt, ae_state *_state)
18718 : {
18719 :
18720 :
18721 0 : ae_assert((fmt==0||fmt==1)||fmt==2, "SparseConvertTo: invalid fmt parameter", _state);
18722 0 : if( fmt==0 )
18723 : {
18724 0 : sparseconverttohash(s0, _state);
18725 0 : return;
18726 : }
18727 0 : if( fmt==1 )
18728 : {
18729 0 : sparseconverttocrs(s0, _state);
18730 0 : return;
18731 : }
18732 0 : if( fmt==2 )
18733 : {
18734 0 : sparseconverttosks(s0, _state);
18735 0 : return;
18736 : }
18737 0 : ae_assert(ae_false, "SparseConvertTo: invalid matrix type", _state);
18738 : }
18739 :
18740 :
18741 : /*************************************************************************
18742 : This function performs out-of-place conversion to desired sparse storage
18743 : format. S0 is copied to S1 and converted on-the-fly. Memory allocated in
18744 : S1 is reused to maximum extent possible.
18745 :
18746 : INPUT PARAMETERS
18747 : S0 - sparse matrix in any format.
18748 : Fmt - desired storage format of the output, as returned by
18749 : SparseGetMatrixType() function:
18750 : * 0 for hash-based storage
18751 : * 1 for CRS
18752 : * 2 for SKS
18753 :
18754 : OUTPUT PARAMETERS
18755 : S1 - sparse matrix in requested format.
18756 :
18757 : -- ALGLIB PROJECT --
18758 : Copyright 16.01.2014 by Bochkanov Sergey
18759 : *************************************************************************/
18760 0 : void sparsecopytobuf(sparsematrix* s0,
18761 : ae_int_t fmt,
18762 : sparsematrix* s1,
18763 : ae_state *_state)
18764 : {
18765 :
18766 :
18767 0 : ae_assert((fmt==0||fmt==1)||fmt==2, "SparseCopyToBuf: invalid fmt parameter", _state);
18768 0 : if( fmt==0 )
18769 : {
18770 0 : sparsecopytohashbuf(s0, s1, _state);
18771 0 : return;
18772 : }
18773 0 : if( fmt==1 )
18774 : {
18775 0 : sparsecopytocrsbuf(s0, s1, _state);
18776 0 : return;
18777 : }
18778 0 : if( fmt==2 )
18779 : {
18780 0 : sparsecopytosksbuf(s0, s1, _state);
18781 0 : return;
18782 : }
18783 0 : ae_assert(ae_false, "SparseCopyToBuf: invalid matrix type", _state);
18784 : }
18785 :
18786 :
18787 : /*************************************************************************
18788 : This function performs in-place conversion to Hash table storage.
18789 :
18790 : INPUT PARAMETERS
18791 : S - sparse matrix in CRS format.
18792 :
18793 : OUTPUT PARAMETERS
18794 : S - sparse matrix in Hash table format.
18795 :
18796 : NOTE: this function has no effect when called with matrix which is
18797 : already in Hash table mode.
18798 :
18799 : NOTE: in-place conversion involves allocation of temporary arrays. If you
18800 : perform a lot of repeated in- place conversions, it may lead to
18801 : memory fragmentation. Consider using out-of-place SparseCopyToHashBuf()
18802 : function in this case.
18803 :
18804 : -- ALGLIB PROJECT --
18805 : Copyright 20.07.2012 by Bochkanov Sergey
18806 : *************************************************************************/
18807 0 : void sparseconverttohash(sparsematrix* s, ae_state *_state)
18808 : {
18809 : ae_frame _frame_block;
18810 : ae_vector tidx;
18811 : ae_vector tridx;
18812 : ae_vector tdidx;
18813 : ae_vector tuidx;
18814 : ae_vector tvals;
18815 : ae_int_t n;
18816 : ae_int_t m;
18817 : ae_int_t offs0;
18818 : ae_int_t i;
18819 : ae_int_t j;
18820 : ae_int_t k;
18821 :
18822 0 : ae_frame_make(_state, &_frame_block);
18823 0 : memset(&tidx, 0, sizeof(tidx));
18824 0 : memset(&tridx, 0, sizeof(tridx));
18825 0 : memset(&tdidx, 0, sizeof(tdidx));
18826 0 : memset(&tuidx, 0, sizeof(tuidx));
18827 0 : memset(&tvals, 0, sizeof(tvals));
18828 0 : ae_vector_init(&tidx, 0, DT_INT, _state, ae_true);
18829 0 : ae_vector_init(&tridx, 0, DT_INT, _state, ae_true);
18830 0 : ae_vector_init(&tdidx, 0, DT_INT, _state, ae_true);
18831 0 : ae_vector_init(&tuidx, 0, DT_INT, _state, ae_true);
18832 0 : ae_vector_init(&tvals, 0, DT_REAL, _state, ae_true);
18833 :
18834 0 : ae_assert((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2, "SparseConvertToHash: invalid matrix type", _state);
18835 0 : if( s->matrixtype==0 )
18836 : {
18837 :
18838 : /*
18839 : * Already in Hash mode
18840 : */
18841 0 : ae_frame_leave(_state);
18842 0 : return;
18843 : }
18844 0 : if( s->matrixtype==1 )
18845 : {
18846 :
18847 : /*
18848 : * From CRS to Hash
18849 : */
18850 0 : s->matrixtype = 0;
18851 0 : m = s->m;
18852 0 : n = s->n;
18853 0 : ae_swap_vectors(&s->idx, &tidx);
18854 0 : ae_swap_vectors(&s->ridx, &tridx);
18855 0 : ae_swap_vectors(&s->vals, &tvals);
18856 0 : sparsecreatebuf(m, n, tridx.ptr.p_int[m], s, _state);
18857 0 : for(i=0; i<=m-1; i++)
18858 : {
18859 0 : for(j=tridx.ptr.p_int[i]; j<=tridx.ptr.p_int[i+1]-1; j++)
18860 : {
18861 0 : sparseset(s, i, tidx.ptr.p_int[j], tvals.ptr.p_double[j], _state);
18862 : }
18863 : }
18864 0 : ae_frame_leave(_state);
18865 0 : return;
18866 : }
18867 0 : if( s->matrixtype==2 )
18868 : {
18869 :
18870 : /*
18871 : * From SKS to Hash
18872 : */
18873 0 : s->matrixtype = 0;
18874 0 : m = s->m;
18875 0 : n = s->n;
18876 0 : ae_swap_vectors(&s->ridx, &tridx);
18877 0 : ae_swap_vectors(&s->didx, &tdidx);
18878 0 : ae_swap_vectors(&s->uidx, &tuidx);
18879 0 : ae_swap_vectors(&s->vals, &tvals);
18880 0 : sparsecreatebuf(m, n, tridx.ptr.p_int[m], s, _state);
18881 0 : for(i=0; i<=m-1; i++)
18882 : {
18883 :
18884 : /*
18885 : * copy subdiagonal and diagonal parts of I-th block
18886 : */
18887 0 : offs0 = tridx.ptr.p_int[i];
18888 0 : k = tdidx.ptr.p_int[i]+1;
18889 0 : for(j=0; j<=k-1; j++)
18890 : {
18891 0 : sparseset(s, i, i-tdidx.ptr.p_int[i]+j, tvals.ptr.p_double[offs0+j], _state);
18892 : }
18893 :
18894 : /*
18895 : * Copy superdiagonal part of I-th block
18896 : */
18897 0 : offs0 = tridx.ptr.p_int[i]+tdidx.ptr.p_int[i]+1;
18898 0 : k = tuidx.ptr.p_int[i];
18899 0 : for(j=0; j<=k-1; j++)
18900 : {
18901 0 : sparseset(s, i-k+j, i, tvals.ptr.p_double[offs0+j], _state);
18902 : }
18903 : }
18904 0 : ae_frame_leave(_state);
18905 0 : return;
18906 : }
18907 0 : ae_assert(ae_false, "SparseConvertToHash: invalid matrix type", _state);
18908 0 : ae_frame_leave(_state);
18909 : }
18910 :
18911 :
18912 : /*************************************************************************
18913 : This function performs out-of-place conversion to Hash table storage
18914 : format. S0 is copied to S1 and converted on-the-fly.
18915 :
18916 : INPUT PARAMETERS
18917 : S0 - sparse matrix in any format.
18918 :
18919 : OUTPUT PARAMETERS
18920 : S1 - sparse matrix in Hash table format.
18921 :
18922 : NOTE: if S0 is stored as Hash-table, it is just copied without conversion.
18923 :
18924 : NOTE: this function de-allocates memory occupied by S1 before starting
18925 : conversion. If you perform a lot of repeated conversions, it may
18926 : lead to memory fragmentation. In this case we recommend you to use
18927 : SparseCopyToHashBuf() function which re-uses memory in S1 as much as
18928 : possible.
18929 :
18930 : -- ALGLIB PROJECT --
18931 : Copyright 20.07.2012 by Bochkanov Sergey
18932 : *************************************************************************/
18933 0 : void sparsecopytohash(sparsematrix* s0,
18934 : sparsematrix* s1,
18935 : ae_state *_state)
18936 : {
18937 :
18938 0 : _sparsematrix_clear(s1);
18939 :
18940 0 : ae_assert((s0->matrixtype==0||s0->matrixtype==1)||s0->matrixtype==2, "SparseCopyToHash: invalid matrix type", _state);
18941 0 : sparsecopytohashbuf(s0, s1, _state);
18942 0 : }
18943 :
18944 :
18945 : /*************************************************************************
18946 : This function performs out-of-place conversion to Hash table storage
18947 : format. S0 is copied to S1 and converted on-the-fly. Memory allocated in
18948 : S1 is reused to maximum extent possible.
18949 :
18950 : INPUT PARAMETERS
18951 : S0 - sparse matrix in any format.
18952 :
18953 : OUTPUT PARAMETERS
18954 : S1 - sparse matrix in Hash table format.
18955 :
18956 : NOTE: if S0 is stored as Hash-table, it is just copied without conversion.
18957 :
18958 : -- ALGLIB PROJECT --
18959 : Copyright 20.07.2012 by Bochkanov Sergey
18960 : *************************************************************************/
18961 0 : void sparsecopytohashbuf(sparsematrix* s0,
18962 : sparsematrix* s1,
18963 : ae_state *_state)
18964 : {
18965 : double val;
18966 : ae_int_t t0;
18967 : ae_int_t t1;
18968 : ae_int_t i;
18969 : ae_int_t j;
18970 :
18971 :
18972 0 : ae_assert((s0->matrixtype==0||s0->matrixtype==1)||s0->matrixtype==2, "SparseCopyToHashBuf: invalid matrix type", _state);
18973 0 : if( s0->matrixtype==0 )
18974 : {
18975 :
18976 : /*
18977 : * Already hash, just copy
18978 : */
18979 0 : sparsecopybuf(s0, s1, _state);
18980 0 : return;
18981 : }
18982 0 : if( s0->matrixtype==1 )
18983 : {
18984 :
18985 : /*
18986 : * CRS storage
18987 : */
18988 0 : t0 = 0;
18989 0 : t1 = 0;
18990 0 : sparsecreatebuf(s0->m, s0->n, s0->ridx.ptr.p_int[s0->m], s1, _state);
18991 0 : while(sparseenumerate(s0, &t0, &t1, &i, &j, &val, _state))
18992 : {
18993 0 : sparseset(s1, i, j, val, _state);
18994 : }
18995 0 : return;
18996 : }
18997 0 : if( s0->matrixtype==2 )
18998 : {
18999 :
19000 : /*
19001 : * SKS storage
19002 : */
19003 0 : t0 = 0;
19004 0 : t1 = 0;
19005 0 : sparsecreatebuf(s0->m, s0->n, s0->ridx.ptr.p_int[s0->m], s1, _state);
19006 0 : while(sparseenumerate(s0, &t0, &t1, &i, &j, &val, _state))
19007 : {
19008 0 : sparseset(s1, i, j, val, _state);
19009 : }
19010 0 : return;
19011 : }
19012 0 : ae_assert(ae_false, "SparseCopyToHashBuf: invalid matrix type", _state);
19013 : }
19014 :
19015 :
19016 : /*************************************************************************
19017 : This function converts matrix to CRS format.
19018 :
19019 : Some algorithms (linear algebra ones, for example) require matrices in
19020 : CRS format. This function allows to perform in-place conversion.
19021 :
19022 : INPUT PARAMETERS
19023 : S - sparse M*N matrix in any format
19024 :
19025 : OUTPUT PARAMETERS
19026 : S - matrix in CRS format
19027 :
19028 : NOTE: this function has no effect when called with matrix which is
19029 : already in CRS mode.
19030 :
19031 : NOTE: this function allocates temporary memory to store a copy of the
19032 : matrix. If you perform a lot of repeated conversions, we recommend
19033 : you to use SparseCopyToCRSBuf() function, which can reuse
19034 : previously allocated memory.
19035 :
19036 : -- ALGLIB PROJECT --
19037 : Copyright 14.10.2011 by Bochkanov Sergey
19038 : *************************************************************************/
19039 0 : void sparseconverttocrs(sparsematrix* s, ae_state *_state)
19040 : {
19041 : ae_frame _frame_block;
19042 : ae_int_t m;
19043 : ae_int_t i;
19044 : ae_int_t j;
19045 : ae_vector tvals;
19046 : ae_vector tidx;
19047 : ae_vector temp;
19048 : ae_vector tridx;
19049 : ae_int_t nonne;
19050 : ae_int_t k;
19051 : ae_int_t offs0;
19052 : ae_int_t offs1;
19053 :
19054 0 : ae_frame_make(_state, &_frame_block);
19055 0 : memset(&tvals, 0, sizeof(tvals));
19056 0 : memset(&tidx, 0, sizeof(tidx));
19057 0 : memset(&temp, 0, sizeof(temp));
19058 0 : memset(&tridx, 0, sizeof(tridx));
19059 0 : ae_vector_init(&tvals, 0, DT_REAL, _state, ae_true);
19060 0 : ae_vector_init(&tidx, 0, DT_INT, _state, ae_true);
19061 0 : ae_vector_init(&temp, 0, DT_INT, _state, ae_true);
19062 0 : ae_vector_init(&tridx, 0, DT_INT, _state, ae_true);
19063 :
19064 0 : m = s->m;
19065 0 : if( s->matrixtype==0 )
19066 : {
19067 :
19068 : /*
19069 : * From Hash-table to CRS.
19070 : * First, create local copy of the hash table.
19071 : */
19072 0 : s->matrixtype = 1;
19073 0 : k = s->tablesize;
19074 0 : ae_swap_vectors(&s->vals, &tvals);
19075 0 : ae_swap_vectors(&s->idx, &tidx);
19076 :
19077 : /*
19078 : * Fill RIdx by number of elements per row:
19079 : * RIdx[I+1] stores number of elements in I-th row.
19080 : *
19081 : * Convert RIdx from row sizes to row offsets.
19082 : * Set NInitialized
19083 : */
19084 0 : nonne = 0;
19085 0 : ivectorsetlengthatleast(&s->ridx, s->m+1, _state);
19086 0 : for(i=0; i<=s->m; i++)
19087 : {
19088 0 : s->ridx.ptr.p_int[i] = 0;
19089 : }
19090 0 : for(i=0; i<=k-1; i++)
19091 : {
19092 0 : if( tidx.ptr.p_int[2*i]>=0 )
19093 : {
19094 0 : s->ridx.ptr.p_int[tidx.ptr.p_int[2*i]+1] = s->ridx.ptr.p_int[tidx.ptr.p_int[2*i]+1]+1;
19095 0 : nonne = nonne+1;
19096 : }
19097 : }
19098 0 : for(i=0; i<=s->m-1; i++)
19099 : {
19100 0 : s->ridx.ptr.p_int[i+1] = s->ridx.ptr.p_int[i+1]+s->ridx.ptr.p_int[i];
19101 : }
19102 0 : s->ninitialized = s->ridx.ptr.p_int[s->m];
19103 :
19104 : /*
19105 : * Allocate memory and move elements to Vals/Idx.
19106 : * Initially, elements are sorted by rows, but unsorted within row.
19107 : * After initial insertion we sort elements within row.
19108 : */
19109 0 : ae_vector_set_length(&temp, s->m, _state);
19110 0 : for(i=0; i<=s->m-1; i++)
19111 : {
19112 0 : temp.ptr.p_int[i] = 0;
19113 : }
19114 0 : rvectorsetlengthatleast(&s->vals, nonne, _state);
19115 0 : ivectorsetlengthatleast(&s->idx, nonne, _state);
19116 0 : for(i=0; i<=k-1; i++)
19117 : {
19118 0 : if( tidx.ptr.p_int[2*i]>=0 )
19119 : {
19120 0 : s->vals.ptr.p_double[s->ridx.ptr.p_int[tidx.ptr.p_int[2*i]]+temp.ptr.p_int[tidx.ptr.p_int[2*i]]] = tvals.ptr.p_double[i];
19121 0 : s->idx.ptr.p_int[s->ridx.ptr.p_int[tidx.ptr.p_int[2*i]]+temp.ptr.p_int[tidx.ptr.p_int[2*i]]] = tidx.ptr.p_int[2*i+1];
19122 0 : temp.ptr.p_int[tidx.ptr.p_int[2*i]] = temp.ptr.p_int[tidx.ptr.p_int[2*i]]+1;
19123 : }
19124 : }
19125 0 : for(i=0; i<=s->m-1; i++)
19126 : {
19127 0 : tagsortmiddleir(&s->idx, &s->vals, s->ridx.ptr.p_int[i], s->ridx.ptr.p_int[i+1]-s->ridx.ptr.p_int[i], _state);
19128 : }
19129 :
19130 : /*
19131 : * Initialization 'S.UIdx' and 'S.DIdx'
19132 : */
19133 0 : sparseinitduidx(s, _state);
19134 0 : ae_frame_leave(_state);
19135 0 : return;
19136 : }
19137 0 : if( s->matrixtype==1 )
19138 : {
19139 :
19140 : /*
19141 : * Already CRS
19142 : */
19143 0 : ae_frame_leave(_state);
19144 0 : return;
19145 : }
19146 0 : if( s->matrixtype==2 )
19147 : {
19148 0 : ae_assert(s->m==s->n, "SparseConvertToCRS: non-square SKS matrices are not supported", _state);
19149 :
19150 : /*
19151 : * From SKS to CRS.
19152 : *
19153 : * First, create local copy of the SKS matrix (Vals,
19154 : * Idx, RIdx are stored; DIdx/UIdx for some time are
19155 : * left in the SparseMatrix structure).
19156 : */
19157 0 : s->matrixtype = 1;
19158 0 : ae_swap_vectors(&s->vals, &tvals);
19159 0 : ae_swap_vectors(&s->idx, &tidx);
19160 0 : ae_swap_vectors(&s->ridx, &tridx);
19161 :
19162 : /*
19163 : * Fill RIdx by number of elements per row:
19164 : * RIdx[I+1] stores number of elements in I-th row.
19165 : *
19166 : * Convert RIdx from row sizes to row offsets.
19167 : * Set NInitialized
19168 : */
19169 0 : ivectorsetlengthatleast(&s->ridx, m+1, _state);
19170 0 : s->ridx.ptr.p_int[0] = 0;
19171 0 : for(i=1; i<=m; i++)
19172 : {
19173 0 : s->ridx.ptr.p_int[i] = 1;
19174 : }
19175 0 : nonne = 0;
19176 0 : for(i=0; i<=m-1; i++)
19177 : {
19178 0 : s->ridx.ptr.p_int[i+1] = s->didx.ptr.p_int[i]+s->ridx.ptr.p_int[i+1];
19179 0 : for(j=i-s->uidx.ptr.p_int[i]; j<=i-1; j++)
19180 : {
19181 0 : s->ridx.ptr.p_int[j+1] = s->ridx.ptr.p_int[j+1]+1;
19182 : }
19183 0 : nonne = nonne+s->didx.ptr.p_int[i]+1+s->uidx.ptr.p_int[i];
19184 : }
19185 0 : for(i=0; i<=s->m-1; i++)
19186 : {
19187 0 : s->ridx.ptr.p_int[i+1] = s->ridx.ptr.p_int[i+1]+s->ridx.ptr.p_int[i];
19188 : }
19189 0 : s->ninitialized = s->ridx.ptr.p_int[s->m];
19190 :
19191 : /*
19192 : * Allocate memory and move elements to Vals/Idx.
19193 : * Initially, elements are sorted by rows, and are sorted within row too.
19194 : * No additional post-sorting is required.
19195 : */
19196 0 : ae_vector_set_length(&temp, m, _state);
19197 0 : for(i=0; i<=m-1; i++)
19198 : {
19199 0 : temp.ptr.p_int[i] = 0;
19200 : }
19201 0 : rvectorsetlengthatleast(&s->vals, nonne, _state);
19202 0 : ivectorsetlengthatleast(&s->idx, nonne, _state);
19203 0 : for(i=0; i<=m-1; i++)
19204 : {
19205 :
19206 : /*
19207 : * copy subdiagonal and diagonal parts of I-th block
19208 : */
19209 0 : offs0 = tridx.ptr.p_int[i];
19210 0 : offs1 = s->ridx.ptr.p_int[i]+temp.ptr.p_int[i];
19211 0 : k = s->didx.ptr.p_int[i]+1;
19212 0 : for(j=0; j<=k-1; j++)
19213 : {
19214 0 : s->vals.ptr.p_double[offs1+j] = tvals.ptr.p_double[offs0+j];
19215 0 : s->idx.ptr.p_int[offs1+j] = i-s->didx.ptr.p_int[i]+j;
19216 : }
19217 0 : temp.ptr.p_int[i] = temp.ptr.p_int[i]+s->didx.ptr.p_int[i]+1;
19218 :
19219 : /*
19220 : * Copy superdiagonal part of I-th block
19221 : */
19222 0 : offs0 = tridx.ptr.p_int[i]+s->didx.ptr.p_int[i]+1;
19223 0 : k = s->uidx.ptr.p_int[i];
19224 0 : for(j=0; j<=k-1; j++)
19225 : {
19226 0 : offs1 = s->ridx.ptr.p_int[i-k+j]+temp.ptr.p_int[i-k+j];
19227 0 : s->vals.ptr.p_double[offs1] = tvals.ptr.p_double[offs0+j];
19228 0 : s->idx.ptr.p_int[offs1] = i;
19229 0 : temp.ptr.p_int[i-k+j] = temp.ptr.p_int[i-k+j]+1;
19230 : }
19231 : }
19232 :
19233 : /*
19234 : * Initialization 'S.UIdx' and 'S.DIdx'
19235 : */
19236 0 : sparseinitduidx(s, _state);
19237 0 : ae_frame_leave(_state);
19238 0 : return;
19239 : }
19240 0 : ae_assert(ae_false, "SparseConvertToCRS: invalid matrix type", _state);
19241 0 : ae_frame_leave(_state);
19242 : }
19243 :
19244 :
19245 : /*************************************************************************
19246 : This function performs out-of-place conversion to CRS format. S0 is
19247 : copied to S1 and converted on-the-fly.
19248 :
19249 : INPUT PARAMETERS
19250 : S0 - sparse matrix in any format.
19251 :
19252 : OUTPUT PARAMETERS
19253 : S1 - sparse matrix in CRS format.
19254 :
19255 : NOTE: if S0 is stored as CRS, it is just copied without conversion.
19256 :
19257 : NOTE: this function de-allocates memory occupied by S1 before starting CRS
19258 : conversion. If you perform a lot of repeated CRS conversions, it may
19259 : lead to memory fragmentation. In this case we recommend you to use
19260 : SparseCopyToCRSBuf() function which re-uses memory in S1 as much as
19261 : possible.
19262 :
19263 : -- ALGLIB PROJECT --
19264 : Copyright 20.07.2012 by Bochkanov Sergey
19265 : *************************************************************************/
19266 0 : void sparsecopytocrs(sparsematrix* s0, sparsematrix* s1, ae_state *_state)
19267 : {
19268 :
19269 0 : _sparsematrix_clear(s1);
19270 :
19271 0 : ae_assert((s0->matrixtype==0||s0->matrixtype==1)||s0->matrixtype==2, "SparseCopyToCRS: invalid matrix type", _state);
19272 0 : sparsecopytocrsbuf(s0, s1, _state);
19273 0 : }
19274 :
19275 :
19276 : /*************************************************************************
19277 : This function performs out-of-place conversion to CRS format. S0 is
19278 : copied to S1 and converted on-the-fly. Memory allocated in S1 is reused to
19279 : maximum extent possible.
19280 :
19281 : INPUT PARAMETERS
19282 : S0 - sparse matrix in any format.
19283 : S1 - matrix which may contain some pre-allocated memory, or
19284 : can be just uninitialized structure.
19285 :
19286 : OUTPUT PARAMETERS
19287 : S1 - sparse matrix in CRS format.
19288 :
19289 : NOTE: if S0 is stored as CRS, it is just copied without conversion.
19290 :
19291 : -- ALGLIB PROJECT --
19292 : Copyright 20.07.2012 by Bochkanov Sergey
19293 : *************************************************************************/
19294 0 : void sparsecopytocrsbuf(sparsematrix* s0,
19295 : sparsematrix* s1,
19296 : ae_state *_state)
19297 : {
19298 : ae_frame _frame_block;
19299 : ae_vector temp;
19300 : ae_int_t nonne;
19301 : ae_int_t i;
19302 : ae_int_t j;
19303 : ae_int_t k;
19304 : ae_int_t offs0;
19305 : ae_int_t offs1;
19306 : ae_int_t m;
19307 :
19308 0 : ae_frame_make(_state, &_frame_block);
19309 0 : memset(&temp, 0, sizeof(temp));
19310 0 : ae_vector_init(&temp, 0, DT_INT, _state, ae_true);
19311 :
19312 0 : ae_assert((s0->matrixtype==0||s0->matrixtype==1)||s0->matrixtype==2, "SparseCopyToCRSBuf: invalid matrix type", _state);
19313 0 : m = s0->m;
19314 0 : if( s0->matrixtype==0 )
19315 : {
19316 :
19317 : /*
19318 : * Convert from hash-table to CRS
19319 : * Done like ConvertToCRS function
19320 : */
19321 0 : s1->matrixtype = 1;
19322 0 : s1->m = s0->m;
19323 0 : s1->n = s0->n;
19324 0 : s1->nfree = s0->nfree;
19325 0 : nonne = 0;
19326 0 : k = s0->tablesize;
19327 0 : ivectorsetlengthatleast(&s1->ridx, s1->m+1, _state);
19328 0 : for(i=0; i<=s1->m; i++)
19329 : {
19330 0 : s1->ridx.ptr.p_int[i] = 0;
19331 : }
19332 0 : ae_vector_set_length(&temp, s1->m, _state);
19333 0 : for(i=0; i<=s1->m-1; i++)
19334 : {
19335 0 : temp.ptr.p_int[i] = 0;
19336 : }
19337 :
19338 : /*
19339 : * Number of elements per row
19340 : */
19341 0 : for(i=0; i<=k-1; i++)
19342 : {
19343 0 : if( s0->idx.ptr.p_int[2*i]>=0 )
19344 : {
19345 0 : s1->ridx.ptr.p_int[s0->idx.ptr.p_int[2*i]+1] = s1->ridx.ptr.p_int[s0->idx.ptr.p_int[2*i]+1]+1;
19346 0 : nonne = nonne+1;
19347 : }
19348 : }
19349 :
19350 : /*
19351 : * Fill RIdx (offsets of rows)
19352 : */
19353 0 : for(i=0; i<=s1->m-1; i++)
19354 : {
19355 0 : s1->ridx.ptr.p_int[i+1] = s1->ridx.ptr.p_int[i+1]+s1->ridx.ptr.p_int[i];
19356 : }
19357 :
19358 : /*
19359 : * Allocate memory
19360 : */
19361 0 : rvectorsetlengthatleast(&s1->vals, nonne, _state);
19362 0 : ivectorsetlengthatleast(&s1->idx, nonne, _state);
19363 0 : for(i=0; i<=k-1; i++)
19364 : {
19365 0 : if( s0->idx.ptr.p_int[2*i]>=0 )
19366 : {
19367 0 : s1->vals.ptr.p_double[s1->ridx.ptr.p_int[s0->idx.ptr.p_int[2*i]]+temp.ptr.p_int[s0->idx.ptr.p_int[2*i]]] = s0->vals.ptr.p_double[i];
19368 0 : s1->idx.ptr.p_int[s1->ridx.ptr.p_int[s0->idx.ptr.p_int[2*i]]+temp.ptr.p_int[s0->idx.ptr.p_int[2*i]]] = s0->idx.ptr.p_int[2*i+1];
19369 0 : temp.ptr.p_int[s0->idx.ptr.p_int[2*i]] = temp.ptr.p_int[s0->idx.ptr.p_int[2*i]]+1;
19370 : }
19371 : }
19372 :
19373 : /*
19374 : * Set NInitialized
19375 : */
19376 0 : s1->ninitialized = s1->ridx.ptr.p_int[s1->m];
19377 :
19378 : /*
19379 : * Sorting of elements
19380 : */
19381 0 : for(i=0; i<=s1->m-1; i++)
19382 : {
19383 0 : tagsortmiddleir(&s1->idx, &s1->vals, s1->ridx.ptr.p_int[i], s1->ridx.ptr.p_int[i+1]-s1->ridx.ptr.p_int[i], _state);
19384 : }
19385 :
19386 : /*
19387 : * Initialization 'S.UIdx' and 'S.DIdx'
19388 : */
19389 0 : sparseinitduidx(s1, _state);
19390 0 : ae_frame_leave(_state);
19391 0 : return;
19392 : }
19393 0 : if( s0->matrixtype==1 )
19394 : {
19395 :
19396 : /*
19397 : * Already CRS, just copy
19398 : */
19399 0 : sparsecopybuf(s0, s1, _state);
19400 0 : ae_frame_leave(_state);
19401 0 : return;
19402 : }
19403 0 : if( s0->matrixtype==2 )
19404 : {
19405 0 : ae_assert(s0->m==s0->n, "SparseCopyToCRS: non-square SKS matrices are not supported", _state);
19406 :
19407 : /*
19408 : * From SKS to CRS.
19409 : */
19410 0 : s1->m = s0->m;
19411 0 : s1->n = s0->n;
19412 0 : s1->matrixtype = 1;
19413 :
19414 : /*
19415 : * Fill RIdx by number of elements per row:
19416 : * RIdx[I+1] stores number of elements in I-th row.
19417 : *
19418 : * Convert RIdx from row sizes to row offsets.
19419 : * Set NInitialized
19420 : */
19421 0 : ivectorsetlengthatleast(&s1->ridx, m+1, _state);
19422 0 : s1->ridx.ptr.p_int[0] = 0;
19423 0 : for(i=1; i<=m; i++)
19424 : {
19425 0 : s1->ridx.ptr.p_int[i] = 1;
19426 : }
19427 0 : nonne = 0;
19428 0 : for(i=0; i<=m-1; i++)
19429 : {
19430 0 : s1->ridx.ptr.p_int[i+1] = s0->didx.ptr.p_int[i]+s1->ridx.ptr.p_int[i+1];
19431 0 : for(j=i-s0->uidx.ptr.p_int[i]; j<=i-1; j++)
19432 : {
19433 0 : s1->ridx.ptr.p_int[j+1] = s1->ridx.ptr.p_int[j+1]+1;
19434 : }
19435 0 : nonne = nonne+s0->didx.ptr.p_int[i]+1+s0->uidx.ptr.p_int[i];
19436 : }
19437 0 : for(i=0; i<=m-1; i++)
19438 : {
19439 0 : s1->ridx.ptr.p_int[i+1] = s1->ridx.ptr.p_int[i+1]+s1->ridx.ptr.p_int[i];
19440 : }
19441 0 : s1->ninitialized = s1->ridx.ptr.p_int[m];
19442 :
19443 : /*
19444 : * Allocate memory and move elements to Vals/Idx.
19445 : * Initially, elements are sorted by rows, and are sorted within row too.
19446 : * No additional post-sorting is required.
19447 : */
19448 0 : ae_vector_set_length(&temp, m, _state);
19449 0 : for(i=0; i<=m-1; i++)
19450 : {
19451 0 : temp.ptr.p_int[i] = 0;
19452 : }
19453 0 : rvectorsetlengthatleast(&s1->vals, nonne, _state);
19454 0 : ivectorsetlengthatleast(&s1->idx, nonne, _state);
19455 0 : for(i=0; i<=m-1; i++)
19456 : {
19457 :
19458 : /*
19459 : * copy subdiagonal and diagonal parts of I-th block
19460 : */
19461 0 : offs0 = s0->ridx.ptr.p_int[i];
19462 0 : offs1 = s1->ridx.ptr.p_int[i]+temp.ptr.p_int[i];
19463 0 : k = s0->didx.ptr.p_int[i]+1;
19464 0 : for(j=0; j<=k-1; j++)
19465 : {
19466 0 : s1->vals.ptr.p_double[offs1+j] = s0->vals.ptr.p_double[offs0+j];
19467 0 : s1->idx.ptr.p_int[offs1+j] = i-s0->didx.ptr.p_int[i]+j;
19468 : }
19469 0 : temp.ptr.p_int[i] = temp.ptr.p_int[i]+s0->didx.ptr.p_int[i]+1;
19470 :
19471 : /*
19472 : * Copy superdiagonal part of I-th block
19473 : */
19474 0 : offs0 = s0->ridx.ptr.p_int[i]+s0->didx.ptr.p_int[i]+1;
19475 0 : k = s0->uidx.ptr.p_int[i];
19476 0 : for(j=0; j<=k-1; j++)
19477 : {
19478 0 : offs1 = s1->ridx.ptr.p_int[i-k+j]+temp.ptr.p_int[i-k+j];
19479 0 : s1->vals.ptr.p_double[offs1] = s0->vals.ptr.p_double[offs0+j];
19480 0 : s1->idx.ptr.p_int[offs1] = i;
19481 0 : temp.ptr.p_int[i-k+j] = temp.ptr.p_int[i-k+j]+1;
19482 : }
19483 : }
19484 :
19485 : /*
19486 : * Initialization 'S.UIdx' and 'S.DIdx'
19487 : */
19488 0 : sparseinitduidx(s1, _state);
19489 0 : ae_frame_leave(_state);
19490 0 : return;
19491 : }
19492 0 : ae_assert(ae_false, "SparseCopyToCRSBuf: unexpected matrix type", _state);
19493 0 : ae_frame_leave(_state);
19494 : }
19495 :
19496 :
19497 : /*************************************************************************
19498 : This function performs in-place conversion to SKS format.
19499 :
19500 : INPUT PARAMETERS
19501 : S - sparse matrix in any format.
19502 :
19503 : OUTPUT PARAMETERS
19504 : S - sparse matrix in SKS format.
19505 :
19506 : NOTE: this function has no effect when called with matrix which is
19507 : already in SKS mode.
19508 :
19509 : NOTE: in-place conversion involves allocation of temporary arrays. If you
19510 : perform a lot of repeated in- place conversions, it may lead to
19511 : memory fragmentation. Consider using out-of-place SparseCopyToSKSBuf()
19512 : function in this case.
19513 :
19514 : -- ALGLIB PROJECT --
19515 : Copyright 15.01.2014 by Bochkanov Sergey
19516 : *************************************************************************/
19517 0 : void sparseconverttosks(sparsematrix* s, ae_state *_state)
19518 : {
19519 : ae_frame _frame_block;
19520 : ae_vector tridx;
19521 : ae_vector tdidx;
19522 : ae_vector tuidx;
19523 : ae_vector tvals;
19524 : ae_int_t n;
19525 : ae_int_t t0;
19526 : ae_int_t t1;
19527 : ae_int_t i;
19528 : ae_int_t j;
19529 : ae_int_t k;
19530 : double v;
19531 :
19532 0 : ae_frame_make(_state, &_frame_block);
19533 0 : memset(&tridx, 0, sizeof(tridx));
19534 0 : memset(&tdidx, 0, sizeof(tdidx));
19535 0 : memset(&tuidx, 0, sizeof(tuidx));
19536 0 : memset(&tvals, 0, sizeof(tvals));
19537 0 : ae_vector_init(&tridx, 0, DT_INT, _state, ae_true);
19538 0 : ae_vector_init(&tdidx, 0, DT_INT, _state, ae_true);
19539 0 : ae_vector_init(&tuidx, 0, DT_INT, _state, ae_true);
19540 0 : ae_vector_init(&tvals, 0, DT_REAL, _state, ae_true);
19541 :
19542 0 : ae_assert((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2, "SparseConvertToSKS: invalid matrix type", _state);
19543 0 : ae_assert(s->m==s->n, "SparseConvertToSKS: rectangular matrices are not supported", _state);
19544 0 : n = s->n;
19545 0 : if( s->matrixtype==2 )
19546 : {
19547 :
19548 : /*
19549 : * Already in SKS mode
19550 : */
19551 0 : ae_frame_leave(_state);
19552 0 : return;
19553 : }
19554 :
19555 : /*
19556 : * Generate internal copy of SKS matrix
19557 : */
19558 0 : ivectorsetlengthatleast(&tdidx, n+1, _state);
19559 0 : ivectorsetlengthatleast(&tuidx, n+1, _state);
19560 0 : for(i=0; i<=n; i++)
19561 : {
19562 0 : tdidx.ptr.p_int[i] = 0;
19563 0 : tuidx.ptr.p_int[i] = 0;
19564 : }
19565 0 : t0 = 0;
19566 0 : t1 = 0;
19567 0 : while(sparseenumerate(s, &t0, &t1, &i, &j, &v, _state))
19568 : {
19569 0 : if( j<i )
19570 : {
19571 0 : tdidx.ptr.p_int[i] = ae_maxint(tdidx.ptr.p_int[i], i-j, _state);
19572 : }
19573 : else
19574 : {
19575 0 : tuidx.ptr.p_int[j] = ae_maxint(tuidx.ptr.p_int[j], j-i, _state);
19576 : }
19577 : }
19578 0 : ivectorsetlengthatleast(&tridx, n+1, _state);
19579 0 : tridx.ptr.p_int[0] = 0;
19580 0 : for(i=1; i<=n; i++)
19581 : {
19582 0 : tridx.ptr.p_int[i] = tridx.ptr.p_int[i-1]+tdidx.ptr.p_int[i-1]+1+tuidx.ptr.p_int[i-1];
19583 : }
19584 0 : rvectorsetlengthatleast(&tvals, tridx.ptr.p_int[n], _state);
19585 0 : k = tridx.ptr.p_int[n];
19586 0 : for(i=0; i<=k-1; i++)
19587 : {
19588 0 : tvals.ptr.p_double[i] = 0.0;
19589 : }
19590 0 : t0 = 0;
19591 0 : t1 = 0;
19592 0 : while(sparseenumerate(s, &t0, &t1, &i, &j, &v, _state))
19593 : {
19594 0 : if( j<=i )
19595 : {
19596 0 : tvals.ptr.p_double[tridx.ptr.p_int[i]+tdidx.ptr.p_int[i]-(i-j)] = v;
19597 : }
19598 : else
19599 : {
19600 0 : tvals.ptr.p_double[tridx.ptr.p_int[j+1]-(j-i)] = v;
19601 : }
19602 : }
19603 0 : for(i=0; i<=n-1; i++)
19604 : {
19605 0 : tdidx.ptr.p_int[n] = ae_maxint(tdidx.ptr.p_int[n], tdidx.ptr.p_int[i], _state);
19606 0 : tuidx.ptr.p_int[n] = ae_maxint(tuidx.ptr.p_int[n], tuidx.ptr.p_int[i], _state);
19607 : }
19608 0 : s->matrixtype = 2;
19609 0 : s->ninitialized = 0;
19610 0 : s->nfree = 0;
19611 0 : s->m = n;
19612 0 : s->n = n;
19613 0 : ae_swap_vectors(&s->didx, &tdidx);
19614 0 : ae_swap_vectors(&s->uidx, &tuidx);
19615 0 : ae_swap_vectors(&s->ridx, &tridx);
19616 0 : ae_swap_vectors(&s->vals, &tvals);
19617 0 : ae_frame_leave(_state);
19618 : }
19619 :
19620 :
19621 : /*************************************************************************
19622 : This function performs out-of-place conversion to SKS storage format.
19623 : S0 is copied to S1 and converted on-the-fly.
19624 :
19625 : INPUT PARAMETERS
19626 : S0 - sparse matrix in any format.
19627 :
19628 : OUTPUT PARAMETERS
19629 : S1 - sparse matrix in SKS format.
19630 :
19631 : NOTE: if S0 is stored as SKS, it is just copied without conversion.
19632 :
19633 : NOTE: this function de-allocates memory occupied by S1 before starting
19634 : conversion. If you perform a lot of repeated conversions, it may
19635 : lead to memory fragmentation. In this case we recommend you to use
19636 : SparseCopyToSKSBuf() function which re-uses memory in S1 as much as
19637 : possible.
19638 :
19639 : -- ALGLIB PROJECT --
19640 : Copyright 20.07.2012 by Bochkanov Sergey
19641 : *************************************************************************/
19642 0 : void sparsecopytosks(sparsematrix* s0, sparsematrix* s1, ae_state *_state)
19643 : {
19644 :
19645 0 : _sparsematrix_clear(s1);
19646 :
19647 0 : ae_assert((s0->matrixtype==0||s0->matrixtype==1)||s0->matrixtype==2, "SparseCopyToSKS: invalid matrix type", _state);
19648 0 : sparsecopytosksbuf(s0, s1, _state);
19649 0 : }
19650 :
19651 :
19652 : /*************************************************************************
19653 : This function performs out-of-place conversion to SKS format. S0 is
19654 : copied to S1 and converted on-the-fly. Memory allocated in S1 is reused
19655 : to maximum extent possible.
19656 :
19657 : INPUT PARAMETERS
19658 : S0 - sparse matrix in any format.
19659 :
19660 : OUTPUT PARAMETERS
19661 : S1 - sparse matrix in SKS format.
19662 :
19663 : NOTE: if S0 is stored as SKS, it is just copied without conversion.
19664 :
19665 : -- ALGLIB PROJECT --
19666 : Copyright 20.07.2012 by Bochkanov Sergey
19667 : *************************************************************************/
19668 0 : void sparsecopytosksbuf(sparsematrix* s0,
19669 : sparsematrix* s1,
19670 : ae_state *_state)
19671 : {
19672 : double v;
19673 : ae_int_t n;
19674 : ae_int_t t0;
19675 : ae_int_t t1;
19676 : ae_int_t i;
19677 : ae_int_t j;
19678 : ae_int_t k;
19679 :
19680 :
19681 0 : ae_assert((s0->matrixtype==0||s0->matrixtype==1)||s0->matrixtype==2, "SparseCopyToSKSBuf: invalid matrix type", _state);
19682 0 : ae_assert(s0->m==s0->n, "SparseCopyToSKSBuf: rectangular matrices are not supported", _state);
19683 0 : n = s0->n;
19684 0 : if( s0->matrixtype==2 )
19685 : {
19686 :
19687 : /*
19688 : * Already SKS, just copy
19689 : */
19690 0 : sparsecopybuf(s0, s1, _state);
19691 0 : return;
19692 : }
19693 :
19694 : /*
19695 : * Generate copy of matrix in the SKS format
19696 : */
19697 0 : ivectorsetlengthatleast(&s1->didx, n+1, _state);
19698 0 : ivectorsetlengthatleast(&s1->uidx, n+1, _state);
19699 0 : for(i=0; i<=n; i++)
19700 : {
19701 0 : s1->didx.ptr.p_int[i] = 0;
19702 0 : s1->uidx.ptr.p_int[i] = 0;
19703 : }
19704 0 : t0 = 0;
19705 0 : t1 = 0;
19706 0 : while(sparseenumerate(s0, &t0, &t1, &i, &j, &v, _state))
19707 : {
19708 0 : if( j<i )
19709 : {
19710 0 : s1->didx.ptr.p_int[i] = ae_maxint(s1->didx.ptr.p_int[i], i-j, _state);
19711 : }
19712 : else
19713 : {
19714 0 : s1->uidx.ptr.p_int[j] = ae_maxint(s1->uidx.ptr.p_int[j], j-i, _state);
19715 : }
19716 : }
19717 0 : ivectorsetlengthatleast(&s1->ridx, n+1, _state);
19718 0 : s1->ridx.ptr.p_int[0] = 0;
19719 0 : for(i=1; i<=n; i++)
19720 : {
19721 0 : s1->ridx.ptr.p_int[i] = s1->ridx.ptr.p_int[i-1]+s1->didx.ptr.p_int[i-1]+1+s1->uidx.ptr.p_int[i-1];
19722 : }
19723 0 : rvectorsetlengthatleast(&s1->vals, s1->ridx.ptr.p_int[n], _state);
19724 0 : k = s1->ridx.ptr.p_int[n];
19725 0 : for(i=0; i<=k-1; i++)
19726 : {
19727 0 : s1->vals.ptr.p_double[i] = 0.0;
19728 : }
19729 0 : t0 = 0;
19730 0 : t1 = 0;
19731 0 : while(sparseenumerate(s0, &t0, &t1, &i, &j, &v, _state))
19732 : {
19733 0 : if( j<=i )
19734 : {
19735 0 : s1->vals.ptr.p_double[s1->ridx.ptr.p_int[i]+s1->didx.ptr.p_int[i]-(i-j)] = v;
19736 : }
19737 : else
19738 : {
19739 0 : s1->vals.ptr.p_double[s1->ridx.ptr.p_int[j+1]-(j-i)] = v;
19740 : }
19741 : }
19742 0 : for(i=0; i<=n-1; i++)
19743 : {
19744 0 : s1->didx.ptr.p_int[n] = ae_maxint(s1->didx.ptr.p_int[n], s1->didx.ptr.p_int[i], _state);
19745 0 : s1->uidx.ptr.p_int[n] = ae_maxint(s1->uidx.ptr.p_int[n], s1->uidx.ptr.p_int[i], _state);
19746 : }
19747 0 : s1->matrixtype = 2;
19748 0 : s1->ninitialized = 0;
19749 0 : s1->nfree = 0;
19750 0 : s1->m = n;
19751 0 : s1->n = n;
19752 : }
19753 :
19754 :
19755 : /*************************************************************************
19756 : This non-accessible to user function performs in-place creation of CRS
19757 : matrix. It is expected that:
19758 : * S.M and S.N are initialized
19759 : * S.RIdx, S.Idx and S.Vals are loaded with values in CRS format used by
19760 : ALGLIB, with elements of S.Idx/S.Vals possibly being unsorted within
19761 : each row (this constructor function may post-sort matrix, assuming that
19762 : it is sorted by rows).
19763 :
19764 : Only 5 fields should be set by caller. Other fields will be rewritten by
19765 : this constructor function.
19766 :
19767 : This function performs integrity check on user-specified values, with the
19768 : only exception being Vals[] array:
19769 : * it does not require values to be non-zero
19770 : * it does not checks for element of Vals[] being finite IEEE-754 values
19771 :
19772 : INPUT PARAMETERS
19773 : S - sparse matrix with corresponding fields set by caller
19774 :
19775 : OUTPUT PARAMETERS
19776 : S - sparse matrix in CRS format.
19777 :
19778 : -- ALGLIB PROJECT --
19779 : Copyright 20.08.2016 by Bochkanov Sergey
19780 : *************************************************************************/
19781 0 : void sparsecreatecrsinplace(sparsematrix* s, ae_state *_state)
19782 : {
19783 : ae_int_t m;
19784 : ae_int_t n;
19785 : ae_int_t i;
19786 : ae_int_t j;
19787 : ae_int_t j0;
19788 : ae_int_t j1;
19789 :
19790 :
19791 0 : m = s->m;
19792 0 : n = s->n;
19793 :
19794 : /*
19795 : * Quick exit for M=0 or N=0
19796 : */
19797 0 : ae_assert(s->m>=0, "SparseCreateCRSInplace: integrity check failed", _state);
19798 0 : ae_assert(s->n>=0, "SparseCreateCRSInplace: integrity check failed", _state);
19799 0 : if( m==0||n==0 )
19800 : {
19801 0 : s->matrixtype = 1;
19802 0 : s->ninitialized = 0;
19803 0 : ivectorsetlengthatleast(&s->ridx, s->m+1, _state);
19804 0 : ivectorsetlengthatleast(&s->didx, s->m, _state);
19805 0 : ivectorsetlengthatleast(&s->uidx, s->m, _state);
19806 0 : for(i=0; i<=s->m-1; i++)
19807 : {
19808 0 : s->ridx.ptr.p_int[i] = 0;
19809 0 : s->uidx.ptr.p_int[i] = 0;
19810 0 : s->didx.ptr.p_int[i] = 0;
19811 : }
19812 0 : s->ridx.ptr.p_int[s->m] = 0;
19813 0 : return;
19814 : }
19815 :
19816 : /*
19817 : * Perform integrity check
19818 : */
19819 0 : ae_assert(s->m>0, "SparseCreateCRSInplace: integrity check failed", _state);
19820 0 : ae_assert(s->n>0, "SparseCreateCRSInplace: integrity check failed", _state);
19821 0 : ae_assert(s->ridx.cnt>=m+1, "SparseCreateCRSInplace: integrity check failed", _state);
19822 0 : for(i=0; i<=m-1; i++)
19823 : {
19824 0 : ae_assert(s->ridx.ptr.p_int[i]>=0&&s->ridx.ptr.p_int[i]<=s->ridx.ptr.p_int[i+1], "SparseCreateCRSInplace: integrity check failed", _state);
19825 : }
19826 0 : ae_assert(s->ridx.ptr.p_int[m]<=s->idx.cnt, "SparseCreateCRSInplace: integrity check failed", _state);
19827 0 : ae_assert(s->ridx.ptr.p_int[m]<=s->vals.cnt, "SparseCreateCRSInplace: integrity check failed", _state);
19828 0 : for(i=0; i<=m-1; i++)
19829 : {
19830 0 : j0 = s->ridx.ptr.p_int[i];
19831 0 : j1 = s->ridx.ptr.p_int[i+1]-1;
19832 0 : for(j=j0; j<=j1; j++)
19833 : {
19834 0 : ae_assert(s->idx.ptr.p_int[j]>=0&&s->idx.ptr.p_int[j]<n, "SparseCreateCRSInplace: integrity check failed", _state);
19835 : }
19836 : }
19837 :
19838 : /*
19839 : * Initialize
19840 : */
19841 0 : s->matrixtype = 1;
19842 0 : s->ninitialized = s->ridx.ptr.p_int[m];
19843 0 : for(i=0; i<=m-1; i++)
19844 : {
19845 0 : tagsortmiddleir(&s->idx, &s->vals, s->ridx.ptr.p_int[i], s->ridx.ptr.p_int[i+1]-s->ridx.ptr.p_int[i], _state);
19846 : }
19847 0 : sparseinitduidx(s, _state);
19848 : }
19849 :
19850 :
19851 : /*************************************************************************
19852 : This function returns type of the matrix storage format.
19853 :
19854 : INPUT PARAMETERS:
19855 : S - sparse matrix.
19856 :
19857 : RESULT:
19858 : sparse storage format used by matrix:
19859 : 0 - Hash-table
19860 : 1 - CRS (compressed row storage)
19861 : 2 - SKS (skyline)
19862 :
19863 : NOTE: future versions of ALGLIB may include additional sparse storage
19864 : formats.
19865 :
19866 :
19867 : -- ALGLIB PROJECT --
19868 : Copyright 20.07.2012 by Bochkanov Sergey
19869 : *************************************************************************/
19870 0 : ae_int_t sparsegetmatrixtype(sparsematrix* s, ae_state *_state)
19871 : {
19872 : ae_int_t result;
19873 :
19874 :
19875 0 : ae_assert((((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2)||s->matrixtype==-10081)||s->matrixtype==-10082, "SparseGetMatrixType: invalid matrix type", _state);
19876 0 : result = s->matrixtype;
19877 0 : return result;
19878 : }
19879 :
19880 :
19881 : /*************************************************************************
19882 : This function checks matrix storage format and returns True when matrix is
19883 : stored using Hash table representation.
19884 :
19885 : INPUT PARAMETERS:
19886 : S - sparse matrix.
19887 :
19888 : RESULT:
19889 : True if matrix type is Hash table
19890 : False if matrix type is not Hash table
19891 :
19892 : -- ALGLIB PROJECT --
19893 : Copyright 20.07.2012 by Bochkanov Sergey
19894 : *************************************************************************/
19895 0 : ae_bool sparseishash(sparsematrix* s, ae_state *_state)
19896 : {
19897 : ae_bool result;
19898 :
19899 :
19900 0 : ae_assert((((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2)||s->matrixtype==-10081)||s->matrixtype==-10082, "SparseIsHash: invalid matrix type", _state);
19901 0 : result = s->matrixtype==0;
19902 0 : return result;
19903 : }
19904 :
19905 :
19906 : /*************************************************************************
19907 : This function checks matrix storage format and returns True when matrix is
19908 : stored using CRS representation.
19909 :
19910 : INPUT PARAMETERS:
19911 : S - sparse matrix.
19912 :
19913 : RESULT:
19914 : True if matrix type is CRS
19915 : False if matrix type is not CRS
19916 :
19917 : -- ALGLIB PROJECT --
19918 : Copyright 20.07.2012 by Bochkanov Sergey
19919 : *************************************************************************/
19920 0 : ae_bool sparseiscrs(sparsematrix* s, ae_state *_state)
19921 : {
19922 : ae_bool result;
19923 :
19924 :
19925 0 : ae_assert((((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2)||s->matrixtype==-10081)||s->matrixtype==-10082, "SparseIsCRS: invalid matrix type", _state);
19926 0 : result = s->matrixtype==1;
19927 0 : return result;
19928 : }
19929 :
19930 :
19931 : /*************************************************************************
19932 : This function checks matrix storage format and returns True when matrix is
19933 : stored using SKS representation.
19934 :
19935 : INPUT PARAMETERS:
19936 : S - sparse matrix.
19937 :
19938 : RESULT:
19939 : True if matrix type is SKS
19940 : False if matrix type is not SKS
19941 :
19942 : -- ALGLIB PROJECT --
19943 : Copyright 20.07.2012 by Bochkanov Sergey
19944 : *************************************************************************/
19945 0 : ae_bool sparseissks(sparsematrix* s, ae_state *_state)
19946 : {
19947 : ae_bool result;
19948 :
19949 :
19950 0 : ae_assert((((s->matrixtype==0||s->matrixtype==1)||s->matrixtype==2)||s->matrixtype==-10081)||s->matrixtype==-10082, "SparseIsSKS: invalid matrix type", _state);
19951 0 : result = s->matrixtype==2;
19952 0 : return result;
19953 : }
19954 :
19955 :
19956 : /*************************************************************************
19957 : The function frees all memory occupied by sparse matrix. Sparse matrix
19958 : structure becomes unusable after this call.
19959 :
19960 : OUTPUT PARAMETERS
19961 : S - sparse matrix to delete
19962 :
19963 : -- ALGLIB PROJECT --
19964 : Copyright 24.07.2012 by Bochkanov Sergey
19965 : *************************************************************************/
19966 0 : void sparsefree(sparsematrix* s, ae_state *_state)
19967 : {
19968 :
19969 0 : _sparsematrix_clear(s);
19970 :
19971 0 : s->matrixtype = -1;
19972 0 : s->m = 0;
19973 0 : s->n = 0;
19974 0 : s->nfree = 0;
19975 0 : s->ninitialized = 0;
19976 0 : s->tablesize = 0;
19977 0 : }
19978 :
19979 :
19980 : /*************************************************************************
19981 : The function returns number of rows of a sparse matrix.
19982 :
19983 : RESULT: number of rows of a sparse matrix.
19984 :
19985 : -- ALGLIB PROJECT --
19986 : Copyright 23.08.2012 by Bochkanov Sergey
19987 : *************************************************************************/
19988 0 : ae_int_t sparsegetnrows(sparsematrix* s, ae_state *_state)
19989 : {
19990 : ae_int_t result;
19991 :
19992 :
19993 0 : result = s->m;
19994 0 : return result;
19995 : }
19996 :
19997 :
19998 : /*************************************************************************
19999 : The function returns number of columns of a sparse matrix.
20000 :
20001 : RESULT: number of columns of a sparse matrix.
20002 :
20003 : -- ALGLIB PROJECT --
20004 : Copyright 23.08.2012 by Bochkanov Sergey
20005 : *************************************************************************/
20006 0 : ae_int_t sparsegetncols(sparsematrix* s, ae_state *_state)
20007 : {
20008 : ae_int_t result;
20009 :
20010 :
20011 0 : result = s->n;
20012 0 : return result;
20013 : }
20014 :
20015 :
20016 : /*************************************************************************
20017 : The function returns number of strictly upper triangular non-zero elements
20018 : in the matrix. It counts SYMBOLICALLY non-zero elements, i.e. entries
20019 : in the sparse matrix data structure. If some element has zero numerical
20020 : value, it is still counted.
20021 :
20022 : This function has different cost for different types of matrices:
20023 : * for hash-based matrices it involves complete pass over entire hash-table
20024 : with O(NNZ) cost, where NNZ is number of non-zero elements
20025 : * for CRS and SKS matrix types cost of counting is O(N) (N - matrix size).
20026 :
20027 : RESULT: number of non-zero elements strictly above main diagonal
20028 :
20029 : -- ALGLIB PROJECT --
20030 : Copyright 12.02.2014 by Bochkanov Sergey
20031 : *************************************************************************/
20032 0 : ae_int_t sparsegetuppercount(sparsematrix* s, ae_state *_state)
20033 : {
20034 : ae_int_t sz;
20035 : ae_int_t i0;
20036 : ae_int_t i;
20037 : ae_int_t result;
20038 :
20039 :
20040 0 : result = -1;
20041 0 : if( s->matrixtype==0 )
20042 : {
20043 :
20044 : /*
20045 : * Hash-table matrix
20046 : */
20047 0 : result = 0;
20048 0 : sz = s->tablesize;
20049 0 : for(i0=0; i0<=sz-1; i0++)
20050 : {
20051 0 : i = s->idx.ptr.p_int[2*i0];
20052 0 : if( i>=0&&s->idx.ptr.p_int[2*i0+1]>i )
20053 : {
20054 0 : result = result+1;
20055 : }
20056 : }
20057 0 : return result;
20058 : }
20059 0 : if( s->matrixtype==1 )
20060 : {
20061 :
20062 : /*
20063 : * CRS matrix
20064 : */
20065 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseGetUpperCount: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
20066 0 : result = 0;
20067 0 : sz = s->m;
20068 0 : for(i=0; i<=sz-1; i++)
20069 : {
20070 0 : result = result+(s->ridx.ptr.p_int[i+1]-s->uidx.ptr.p_int[i]);
20071 : }
20072 0 : return result;
20073 : }
20074 0 : if( s->matrixtype==2 )
20075 : {
20076 :
20077 : /*
20078 : * SKS matrix
20079 : */
20080 0 : ae_assert(s->m==s->n, "SparseGetUpperCount: non-square SKS matrices are not supported", _state);
20081 0 : result = 0;
20082 0 : sz = s->m;
20083 0 : for(i=0; i<=sz-1; i++)
20084 : {
20085 0 : result = result+s->uidx.ptr.p_int[i];
20086 : }
20087 0 : return result;
20088 : }
20089 0 : ae_assert(ae_false, "SparseGetUpperCount: internal error", _state);
20090 0 : return result;
20091 : }
20092 :
20093 :
20094 : /*************************************************************************
20095 : The function returns number of strictly lower triangular non-zero elements
20096 : in the matrix. It counts SYMBOLICALLY non-zero elements, i.e. entries
20097 : in the sparse matrix data structure. If some element has zero numerical
20098 : value, it is still counted.
20099 :
20100 : This function has different cost for different types of matrices:
20101 : * for hash-based matrices it involves complete pass over entire hash-table
20102 : with O(NNZ) cost, where NNZ is number of non-zero elements
20103 : * for CRS and SKS matrix types cost of counting is O(N) (N - matrix size).
20104 :
20105 : RESULT: number of non-zero elements strictly below main diagonal
20106 :
20107 : -- ALGLIB PROJECT --
20108 : Copyright 12.02.2014 by Bochkanov Sergey
20109 : *************************************************************************/
20110 0 : ae_int_t sparsegetlowercount(sparsematrix* s, ae_state *_state)
20111 : {
20112 : ae_int_t sz;
20113 : ae_int_t i0;
20114 : ae_int_t i;
20115 : ae_int_t result;
20116 :
20117 :
20118 0 : result = -1;
20119 0 : if( s->matrixtype==0 )
20120 : {
20121 :
20122 : /*
20123 : * Hash-table matrix
20124 : */
20125 0 : result = 0;
20126 0 : sz = s->tablesize;
20127 0 : for(i0=0; i0<=sz-1; i0++)
20128 : {
20129 0 : i = s->idx.ptr.p_int[2*i0];
20130 0 : if( i>=0&&s->idx.ptr.p_int[2*i0+1]<i )
20131 : {
20132 0 : result = result+1;
20133 : }
20134 : }
20135 0 : return result;
20136 : }
20137 0 : if( s->matrixtype==1 )
20138 : {
20139 :
20140 : /*
20141 : * CRS matrix
20142 : */
20143 0 : ae_assert(s->ninitialized==s->ridx.ptr.p_int[s->m], "SparseGetUpperCount: some rows/elements of the CRS matrix were not initialized (you must initialize everything you promised to SparseCreateCRS)", _state);
20144 0 : result = 0;
20145 0 : sz = s->m;
20146 0 : for(i=0; i<=sz-1; i++)
20147 : {
20148 0 : result = result+(s->didx.ptr.p_int[i]-s->ridx.ptr.p_int[i]);
20149 : }
20150 0 : return result;
20151 : }
20152 0 : if( s->matrixtype==2 )
20153 : {
20154 :
20155 : /*
20156 : * SKS matrix
20157 : */
20158 0 : ae_assert(s->m==s->n, "SparseGetUpperCount: non-square SKS matrices are not supported", _state);
20159 0 : result = 0;
20160 0 : sz = s->m;
20161 0 : for(i=0; i<=sz-1; i++)
20162 : {
20163 0 : result = result+s->didx.ptr.p_int[i];
20164 : }
20165 0 : return result;
20166 : }
20167 0 : ae_assert(ae_false, "SparseGetUpperCount: internal error", _state);
20168 0 : return result;
20169 : }
20170 :
20171 :
20172 : /*************************************************************************
20173 : This is hash function.
20174 :
20175 : -- ALGLIB PROJECT --
20176 : Copyright 14.10.2011 by Bochkanov Sergey
20177 : *************************************************************************/
20178 0 : static ae_int_t sparse_hash(ae_int_t i,
20179 : ae_int_t j,
20180 : ae_int_t tabsize,
20181 : ae_state *_state)
20182 : {
20183 : ae_frame _frame_block;
20184 : hqrndstate r;
20185 : ae_int_t result;
20186 :
20187 0 : ae_frame_make(_state, &_frame_block);
20188 0 : memset(&r, 0, sizeof(r));
20189 0 : _hqrndstate_init(&r, _state, ae_true);
20190 :
20191 0 : hqrndseed(i, j, &r, _state);
20192 0 : result = hqrnduniformi(&r, tabsize, _state);
20193 0 : ae_frame_leave(_state);
20194 0 : return result;
20195 : }
20196 :
20197 :
20198 0 : void _sparsematrix_init(void* _p, ae_state *_state, ae_bool make_automatic)
20199 : {
20200 0 : sparsematrix *p = (sparsematrix*)_p;
20201 0 : ae_touch_ptr((void*)p);
20202 0 : ae_vector_init(&p->vals, 0, DT_REAL, _state, make_automatic);
20203 0 : ae_vector_init(&p->idx, 0, DT_INT, _state, make_automatic);
20204 0 : ae_vector_init(&p->ridx, 0, DT_INT, _state, make_automatic);
20205 0 : ae_vector_init(&p->didx, 0, DT_INT, _state, make_automatic);
20206 0 : ae_vector_init(&p->uidx, 0, DT_INT, _state, make_automatic);
20207 0 : }
20208 :
20209 :
20210 0 : void _sparsematrix_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
20211 : {
20212 0 : sparsematrix *dst = (sparsematrix*)_dst;
20213 0 : sparsematrix *src = (sparsematrix*)_src;
20214 0 : ae_vector_init_copy(&dst->vals, &src->vals, _state, make_automatic);
20215 0 : ae_vector_init_copy(&dst->idx, &src->idx, _state, make_automatic);
20216 0 : ae_vector_init_copy(&dst->ridx, &src->ridx, _state, make_automatic);
20217 0 : ae_vector_init_copy(&dst->didx, &src->didx, _state, make_automatic);
20218 0 : ae_vector_init_copy(&dst->uidx, &src->uidx, _state, make_automatic);
20219 0 : dst->matrixtype = src->matrixtype;
20220 0 : dst->m = src->m;
20221 0 : dst->n = src->n;
20222 0 : dst->nfree = src->nfree;
20223 0 : dst->ninitialized = src->ninitialized;
20224 0 : dst->tablesize = src->tablesize;
20225 0 : }
20226 :
20227 :
20228 0 : void _sparsematrix_clear(void* _p)
20229 : {
20230 0 : sparsematrix *p = (sparsematrix*)_p;
20231 0 : ae_touch_ptr((void*)p);
20232 0 : ae_vector_clear(&p->vals);
20233 0 : ae_vector_clear(&p->idx);
20234 0 : ae_vector_clear(&p->ridx);
20235 0 : ae_vector_clear(&p->didx);
20236 0 : ae_vector_clear(&p->uidx);
20237 0 : }
20238 :
20239 :
20240 0 : void _sparsematrix_destroy(void* _p)
20241 : {
20242 0 : sparsematrix *p = (sparsematrix*)_p;
20243 0 : ae_touch_ptr((void*)p);
20244 0 : ae_vector_destroy(&p->vals);
20245 0 : ae_vector_destroy(&p->idx);
20246 0 : ae_vector_destroy(&p->ridx);
20247 0 : ae_vector_destroy(&p->didx);
20248 0 : ae_vector_destroy(&p->uidx);
20249 0 : }
20250 :
20251 :
20252 0 : void _sparsebuffers_init(void* _p, ae_state *_state, ae_bool make_automatic)
20253 : {
20254 0 : sparsebuffers *p = (sparsebuffers*)_p;
20255 0 : ae_touch_ptr((void*)p);
20256 0 : ae_vector_init(&p->d, 0, DT_INT, _state, make_automatic);
20257 0 : ae_vector_init(&p->u, 0, DT_INT, _state, make_automatic);
20258 0 : _sparsematrix_init(&p->s, _state, make_automatic);
20259 0 : }
20260 :
20261 :
20262 0 : void _sparsebuffers_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
20263 : {
20264 0 : sparsebuffers *dst = (sparsebuffers*)_dst;
20265 0 : sparsebuffers *src = (sparsebuffers*)_src;
20266 0 : ae_vector_init_copy(&dst->d, &src->d, _state, make_automatic);
20267 0 : ae_vector_init_copy(&dst->u, &src->u, _state, make_automatic);
20268 0 : _sparsematrix_init_copy(&dst->s, &src->s, _state, make_automatic);
20269 0 : }
20270 :
20271 :
20272 0 : void _sparsebuffers_clear(void* _p)
20273 : {
20274 0 : sparsebuffers *p = (sparsebuffers*)_p;
20275 0 : ae_touch_ptr((void*)p);
20276 0 : ae_vector_clear(&p->d);
20277 0 : ae_vector_clear(&p->u);
20278 0 : _sparsematrix_clear(&p->s);
20279 0 : }
20280 :
20281 :
20282 0 : void _sparsebuffers_destroy(void* _p)
20283 : {
20284 0 : sparsebuffers *p = (sparsebuffers*)_p;
20285 0 : ae_touch_ptr((void*)p);
20286 0 : ae_vector_destroy(&p->d);
20287 0 : ae_vector_destroy(&p->u);
20288 0 : _sparsematrix_destroy(&p->s);
20289 0 : }
20290 :
20291 :
20292 : #endif
20293 : #if defined(AE_COMPILE_ABLAS) || !defined(AE_PARTIAL_BUILD)
20294 :
20295 :
20296 : /*************************************************************************
20297 : Splits matrix length in two parts, left part should match ABLAS block size
20298 :
20299 : INPUT PARAMETERS
20300 : A - real matrix, is passed to ensure that we didn't split
20301 : complex matrix using real splitting subroutine.
20302 : matrix itself is not changed.
20303 : N - length, N>0
20304 :
20305 : OUTPUT PARAMETERS
20306 : N1 - length
20307 : N2 - length
20308 :
20309 : N1+N2=N, N1>=N2, N2 may be zero
20310 :
20311 : -- ALGLIB routine --
20312 : 15.12.2009
20313 : Bochkanov Sergey
20314 : *************************************************************************/
20315 0 : void ablassplitlength(/* Real */ ae_matrix* a,
20316 : ae_int_t n,
20317 : ae_int_t* n1,
20318 : ae_int_t* n2,
20319 : ae_state *_state)
20320 : {
20321 :
20322 0 : *n1 = 0;
20323 0 : *n2 = 0;
20324 :
20325 0 : if( n>ablasblocksize(a, _state) )
20326 : {
20327 0 : ablas_ablasinternalsplitlength(n, ablasblocksize(a, _state), n1, n2, _state);
20328 : }
20329 : else
20330 : {
20331 0 : ablas_ablasinternalsplitlength(n, ablasmicroblocksize(_state), n1, n2, _state);
20332 : }
20333 0 : }
20334 :
20335 :
20336 : /*************************************************************************
20337 : Complex ABLASSplitLength
20338 :
20339 : -- ALGLIB routine --
20340 : 15.12.2009
20341 : Bochkanov Sergey
20342 : *************************************************************************/
20343 0 : void ablascomplexsplitlength(/* Complex */ ae_matrix* a,
20344 : ae_int_t n,
20345 : ae_int_t* n1,
20346 : ae_int_t* n2,
20347 : ae_state *_state)
20348 : {
20349 :
20350 0 : *n1 = 0;
20351 0 : *n2 = 0;
20352 :
20353 0 : if( n>ablascomplexblocksize(a, _state) )
20354 : {
20355 0 : ablas_ablasinternalsplitlength(n, ablascomplexblocksize(a, _state), n1, n2, _state);
20356 : }
20357 : else
20358 : {
20359 0 : ablas_ablasinternalsplitlength(n, ablasmicroblocksize(_state), n1, n2, _state);
20360 : }
20361 0 : }
20362 :
20363 :
20364 : /*************************************************************************
20365 : Returns switch point for parallelism.
20366 :
20367 : -- ALGLIB routine --
20368 : 15.12.2009
20369 : Bochkanov Sergey
20370 : *************************************************************************/
20371 0 : ae_int_t gemmparallelsize(ae_state *_state)
20372 : {
20373 : ae_int_t result;
20374 :
20375 :
20376 0 : result = 64;
20377 0 : return result;
20378 : }
20379 :
20380 :
20381 : /*************************************************************************
20382 : Returns block size - subdivision size where cache-oblivious soubroutines
20383 : switch to the optimized kernel.
20384 :
20385 : INPUT PARAMETERS
20386 : A - real matrix, is passed to ensure that we didn't split
20387 : complex matrix using real splitting subroutine.
20388 : matrix itself is not changed.
20389 :
20390 : -- ALGLIB routine --
20391 : 15.12.2009
20392 : Bochkanov Sergey
20393 : *************************************************************************/
20394 0 : ae_int_t ablasblocksize(/* Real */ ae_matrix* a, ae_state *_state)
20395 : {
20396 : ae_int_t result;
20397 :
20398 :
20399 0 : result = 32;
20400 0 : return result;
20401 : }
20402 :
20403 :
20404 : /*************************************************************************
20405 : Block size for complex subroutines.
20406 :
20407 : -- ALGLIB routine --
20408 : 15.12.2009
20409 : Bochkanov Sergey
20410 : *************************************************************************/
20411 0 : ae_int_t ablascomplexblocksize(/* Complex */ ae_matrix* a,
20412 : ae_state *_state)
20413 : {
20414 : ae_int_t result;
20415 :
20416 :
20417 0 : result = 24;
20418 0 : return result;
20419 : }
20420 :
20421 :
20422 : /*************************************************************************
20423 : Microblock size
20424 :
20425 : -- ALGLIB routine --
20426 : 15.12.2009
20427 : Bochkanov Sergey
20428 : *************************************************************************/
20429 0 : ae_int_t ablasmicroblocksize(ae_state *_state)
20430 : {
20431 : ae_int_t result;
20432 :
20433 :
20434 0 : result = 8;
20435 0 : return result;
20436 : }
20437 :
20438 :
20439 : /*************************************************************************
20440 : Generation of an elementary reflection transformation
20441 :
20442 : The subroutine generates elementary reflection H of order N, so that, for
20443 : a given X, the following equality holds true:
20444 :
20445 : ( X(1) ) ( Beta )
20446 : H * ( .. ) = ( 0 )
20447 : ( X(n) ) ( 0 )
20448 :
20449 : where
20450 : ( V(1) )
20451 : H = 1 - Tau * ( .. ) * ( V(1), ..., V(n) )
20452 : ( V(n) )
20453 :
20454 : where the first component of vector V equals 1.
20455 :
20456 : Input parameters:
20457 : X - vector. Array whose index ranges within [1..N].
20458 : N - reflection order.
20459 :
20460 : Output parameters:
20461 : X - components from 2 to N are replaced with vector V.
20462 : The first component is replaced with parameter Beta.
20463 : Tau - scalar value Tau. If X is a null vector, Tau equals 0,
20464 : otherwise 1 <= Tau <= 2.
20465 :
20466 : This subroutine is the modification of the DLARFG subroutines from
20467 : the LAPACK library.
20468 :
20469 : MODIFICATIONS:
20470 : 24.12.2005 sign(Alpha) was replaced with an analogous to the Fortran SIGN code.
20471 :
20472 : -- LAPACK auxiliary routine (version 3.0) --
20473 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
20474 : Courant Institute, Argonne National Lab, and Rice University
20475 : September 30, 1994
20476 : *************************************************************************/
20477 0 : void generatereflection(/* Real */ ae_vector* x,
20478 : ae_int_t n,
20479 : double* tau,
20480 : ae_state *_state)
20481 : {
20482 : ae_int_t j;
20483 : double alpha;
20484 : double xnorm;
20485 : double v;
20486 : double beta;
20487 : double mx;
20488 : double s;
20489 :
20490 0 : *tau = 0;
20491 :
20492 0 : if( n<=1 )
20493 : {
20494 0 : *tau = (double)(0);
20495 0 : return;
20496 : }
20497 :
20498 : /*
20499 : * Scale if needed (to avoid overflow/underflow during intermediate
20500 : * calculations).
20501 : */
20502 0 : mx = (double)(0);
20503 0 : for(j=1; j<=n; j++)
20504 : {
20505 0 : mx = ae_maxreal(ae_fabs(x->ptr.p_double[j], _state), mx, _state);
20506 : }
20507 0 : s = (double)(1);
20508 0 : if( ae_fp_neq(mx,(double)(0)) )
20509 : {
20510 0 : if( ae_fp_less_eq(mx,ae_minrealnumber/ae_machineepsilon) )
20511 : {
20512 0 : s = ae_minrealnumber/ae_machineepsilon;
20513 0 : v = 1/s;
20514 0 : ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), v);
20515 0 : mx = mx*v;
20516 : }
20517 : else
20518 : {
20519 0 : if( ae_fp_greater_eq(mx,ae_maxrealnumber*ae_machineepsilon) )
20520 : {
20521 0 : s = ae_maxrealnumber*ae_machineepsilon;
20522 0 : v = 1/s;
20523 0 : ae_v_muld(&x->ptr.p_double[1], 1, ae_v_len(1,n), v);
20524 0 : mx = mx*v;
20525 : }
20526 : }
20527 : }
20528 :
20529 : /*
20530 : * XNORM = DNRM2( N-1, X, INCX )
20531 : */
20532 0 : alpha = x->ptr.p_double[1];
20533 0 : xnorm = (double)(0);
20534 0 : if( ae_fp_neq(mx,(double)(0)) )
20535 : {
20536 0 : for(j=2; j<=n; j++)
20537 : {
20538 0 : xnorm = xnorm+ae_sqr(x->ptr.p_double[j]/mx, _state);
20539 : }
20540 0 : xnorm = ae_sqrt(xnorm, _state)*mx;
20541 : }
20542 0 : if( ae_fp_eq(xnorm,(double)(0)) )
20543 : {
20544 :
20545 : /*
20546 : * H = I
20547 : */
20548 0 : *tau = (double)(0);
20549 0 : x->ptr.p_double[1] = x->ptr.p_double[1]*s;
20550 0 : return;
20551 : }
20552 :
20553 : /*
20554 : * general case
20555 : */
20556 0 : mx = ae_maxreal(ae_fabs(alpha, _state), ae_fabs(xnorm, _state), _state);
20557 0 : beta = -mx*ae_sqrt(ae_sqr(alpha/mx, _state)+ae_sqr(xnorm/mx, _state), _state);
20558 0 : if( ae_fp_less(alpha,(double)(0)) )
20559 : {
20560 0 : beta = -beta;
20561 : }
20562 0 : *tau = (beta-alpha)/beta;
20563 0 : v = 1/(alpha-beta);
20564 0 : ae_v_muld(&x->ptr.p_double[2], 1, ae_v_len(2,n), v);
20565 0 : x->ptr.p_double[1] = beta;
20566 :
20567 : /*
20568 : * Scale back outputs
20569 : */
20570 0 : x->ptr.p_double[1] = x->ptr.p_double[1]*s;
20571 : }
20572 :
20573 :
20574 : /*************************************************************************
20575 : Application of an elementary reflection to a rectangular matrix of size MxN
20576 :
20577 : The algorithm pre-multiplies the matrix by an elementary reflection transformation
20578 : which is given by column V and scalar Tau (see the description of the
20579 : GenerateReflection procedure). Not the whole matrix but only a part of it
20580 : is transformed (rows from M1 to M2, columns from N1 to N2). Only the elements
20581 : of this submatrix are changed.
20582 :
20583 : Input parameters:
20584 : C - matrix to be transformed.
20585 : Tau - scalar defining the transformation.
20586 : V - column defining the transformation.
20587 : Array whose index ranges within [1..M2-M1+1].
20588 : M1, M2 - range of rows to be transformed.
20589 : N1, N2 - range of columns to be transformed.
20590 : WORK - working array whose indexes goes from N1 to N2.
20591 :
20592 : Output parameters:
20593 : C - the result of multiplying the input matrix C by the
20594 : transformation matrix which is given by Tau and V.
20595 : If N1>N2 or M1>M2, C is not modified.
20596 :
20597 : -- LAPACK auxiliary routine (version 3.0) --
20598 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
20599 : Courant Institute, Argonne National Lab, and Rice University
20600 : September 30, 1994
20601 : *************************************************************************/
20602 0 : void applyreflectionfromtheleft(/* Real */ ae_matrix* c,
20603 : double tau,
20604 : /* Real */ ae_vector* v,
20605 : ae_int_t m1,
20606 : ae_int_t m2,
20607 : ae_int_t n1,
20608 : ae_int_t n2,
20609 : /* Real */ ae_vector* work,
20610 : ae_state *_state)
20611 : {
20612 :
20613 :
20614 0 : if( (ae_fp_eq(tau,(double)(0))||n1>n2)||m1>m2 )
20615 : {
20616 0 : return;
20617 : }
20618 0 : rvectorsetlengthatleast(work, n2-n1+1, _state);
20619 0 : rmatrixgemv(n2-n1+1, m2-m1+1, 1.0, c, m1, n1, 1, v, 1, 0.0, work, 0, _state);
20620 0 : rmatrixger(m2-m1+1, n2-n1+1, c, m1, n1, -tau, v, 1, work, 0, _state);
20621 : }
20622 :
20623 :
20624 : /*************************************************************************
20625 : Application of an elementary reflection to a rectangular matrix of size MxN
20626 :
20627 : The algorithm post-multiplies the matrix by an elementary reflection transformation
20628 : which is given by column V and scalar Tau (see the description of the
20629 : GenerateReflection procedure). Not the whole matrix but only a part of it
20630 : is transformed (rows from M1 to M2, columns from N1 to N2). Only the
20631 : elements of this submatrix are changed.
20632 :
20633 : Input parameters:
20634 : C - matrix to be transformed.
20635 : Tau - scalar defining the transformation.
20636 : V - column defining the transformation.
20637 : Array whose index ranges within [1..N2-N1+1].
20638 : M1, M2 - range of rows to be transformed.
20639 : N1, N2 - range of columns to be transformed.
20640 : WORK - working array whose indexes goes from M1 to M2.
20641 :
20642 : Output parameters:
20643 : C - the result of multiplying the input matrix C by the
20644 : transformation matrix which is given by Tau and V.
20645 : If N1>N2 or M1>M2, C is not modified.
20646 :
20647 : -- LAPACK auxiliary routine (version 3.0) --
20648 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
20649 : Courant Institute, Argonne National Lab, and Rice University
20650 : September 30, 1994
20651 : *************************************************************************/
20652 0 : void applyreflectionfromtheright(/* Real */ ae_matrix* c,
20653 : double tau,
20654 : /* Real */ ae_vector* v,
20655 : ae_int_t m1,
20656 : ae_int_t m2,
20657 : ae_int_t n1,
20658 : ae_int_t n2,
20659 : /* Real */ ae_vector* work,
20660 : ae_state *_state)
20661 : {
20662 :
20663 :
20664 0 : if( (ae_fp_eq(tau,(double)(0))||n1>n2)||m1>m2 )
20665 : {
20666 0 : return;
20667 : }
20668 0 : rvectorsetlengthatleast(work, m2-m1+1, _state);
20669 0 : rmatrixgemv(m2-m1+1, n2-n1+1, 1.0, c, m1, n1, 0, v, 1, 0.0, work, 0, _state);
20670 0 : rmatrixger(m2-m1+1, n2-n1+1, c, m1, n1, -tau, work, 0, v, 1, _state);
20671 : }
20672 :
20673 :
20674 : /*************************************************************************
20675 : Cache-oblivous complex "copy-and-transpose"
20676 :
20677 : Input parameters:
20678 : M - number of rows
20679 : N - number of columns
20680 : A - source matrix, MxN submatrix is copied and transposed
20681 : IA - submatrix offset (row index)
20682 : JA - submatrix offset (column index)
20683 : B - destination matrix, must be large enough to store result
20684 : IB - submatrix offset (row index)
20685 : JB - submatrix offset (column index)
20686 : *************************************************************************/
20687 0 : void cmatrixtranspose(ae_int_t m,
20688 : ae_int_t n,
20689 : /* Complex */ ae_matrix* a,
20690 : ae_int_t ia,
20691 : ae_int_t ja,
20692 : /* Complex */ ae_matrix* b,
20693 : ae_int_t ib,
20694 : ae_int_t jb,
20695 : ae_state *_state)
20696 : {
20697 : ae_int_t i;
20698 : ae_int_t s1;
20699 : ae_int_t s2;
20700 :
20701 :
20702 0 : if( m<=2*ablascomplexblocksize(a, _state)&&n<=2*ablascomplexblocksize(a, _state) )
20703 : {
20704 :
20705 : /*
20706 : * base case
20707 : */
20708 0 : for(i=0; i<=m-1; i++)
20709 : {
20710 0 : ae_v_cmove(&b->ptr.pp_complex[ib][jb+i], b->stride, &a->ptr.pp_complex[ia+i][ja], 1, "N", ae_v_len(ib,ib+n-1));
20711 : }
20712 : }
20713 : else
20714 : {
20715 :
20716 : /*
20717 : * Cache-oblivious recursion
20718 : */
20719 0 : if( m>n )
20720 : {
20721 0 : ablascomplexsplitlength(a, m, &s1, &s2, _state);
20722 0 : cmatrixtranspose(s1, n, a, ia, ja, b, ib, jb, _state);
20723 0 : cmatrixtranspose(s2, n, a, ia+s1, ja, b, ib, jb+s1, _state);
20724 : }
20725 : else
20726 : {
20727 0 : ablascomplexsplitlength(a, n, &s1, &s2, _state);
20728 0 : cmatrixtranspose(m, s1, a, ia, ja, b, ib, jb, _state);
20729 0 : cmatrixtranspose(m, s2, a, ia, ja+s1, b, ib+s1, jb, _state);
20730 : }
20731 : }
20732 0 : }
20733 :
20734 :
20735 : /*************************************************************************
20736 : Cache-oblivous real "copy-and-transpose"
20737 :
20738 : Input parameters:
20739 : M - number of rows
20740 : N - number of columns
20741 : A - source matrix, MxN submatrix is copied and transposed
20742 : IA - submatrix offset (row index)
20743 : JA - submatrix offset (column index)
20744 : B - destination matrix, must be large enough to store result
20745 : IB - submatrix offset (row index)
20746 : JB - submatrix offset (column index)
20747 : *************************************************************************/
20748 0 : void rmatrixtranspose(ae_int_t m,
20749 : ae_int_t n,
20750 : /* Real */ ae_matrix* a,
20751 : ae_int_t ia,
20752 : ae_int_t ja,
20753 : /* Real */ ae_matrix* b,
20754 : ae_int_t ib,
20755 : ae_int_t jb,
20756 : ae_state *_state)
20757 : {
20758 : ae_int_t i;
20759 : ae_int_t s1;
20760 : ae_int_t s2;
20761 :
20762 :
20763 0 : if( m<=2*ablasblocksize(a, _state)&&n<=2*ablasblocksize(a, _state) )
20764 : {
20765 :
20766 : /*
20767 : * base case
20768 : */
20769 0 : for(i=0; i<=m-1; i++)
20770 : {
20771 0 : ae_v_move(&b->ptr.pp_double[ib][jb+i], b->stride, &a->ptr.pp_double[ia+i][ja], 1, ae_v_len(ib,ib+n-1));
20772 : }
20773 : }
20774 : else
20775 : {
20776 :
20777 : /*
20778 : * Cache-oblivious recursion
20779 : */
20780 0 : if( m>n )
20781 : {
20782 0 : ablassplitlength(a, m, &s1, &s2, _state);
20783 0 : rmatrixtranspose(s1, n, a, ia, ja, b, ib, jb, _state);
20784 0 : rmatrixtranspose(s2, n, a, ia+s1, ja, b, ib, jb+s1, _state);
20785 : }
20786 : else
20787 : {
20788 0 : ablassplitlength(a, n, &s1, &s2, _state);
20789 0 : rmatrixtranspose(m, s1, a, ia, ja, b, ib, jb, _state);
20790 0 : rmatrixtranspose(m, s2, a, ia, ja+s1, b, ib+s1, jb, _state);
20791 : }
20792 : }
20793 0 : }
20794 :
20795 :
20796 : /*************************************************************************
20797 : This code enforces symmetricy of the matrix by copying Upper part to lower
20798 : one (or vice versa).
20799 :
20800 : INPUT PARAMETERS:
20801 : A - matrix
20802 : N - number of rows/columns
20803 : IsUpper - whether we want to copy upper triangle to lower one (True)
20804 : or vice versa (False).
20805 : *************************************************************************/
20806 0 : void rmatrixenforcesymmetricity(/* Real */ ae_matrix* a,
20807 : ae_int_t n,
20808 : ae_bool isupper,
20809 : ae_state *_state)
20810 : {
20811 : ae_int_t i;
20812 : ae_int_t j;
20813 :
20814 :
20815 0 : if( isupper )
20816 : {
20817 0 : for(i=0; i<=n-1; i++)
20818 : {
20819 0 : for(j=i+1; j<=n-1; j++)
20820 : {
20821 0 : a->ptr.pp_double[j][i] = a->ptr.pp_double[i][j];
20822 : }
20823 : }
20824 : }
20825 : else
20826 : {
20827 0 : for(i=0; i<=n-1; i++)
20828 : {
20829 0 : for(j=i+1; j<=n-1; j++)
20830 : {
20831 0 : a->ptr.pp_double[i][j] = a->ptr.pp_double[j][i];
20832 : }
20833 : }
20834 : }
20835 0 : }
20836 :
20837 :
20838 : /*************************************************************************
20839 : Copy
20840 :
20841 : Input parameters:
20842 : M - number of rows
20843 : N - number of columns
20844 : A - source matrix, MxN submatrix is copied and transposed
20845 : IA - submatrix offset (row index)
20846 : JA - submatrix offset (column index)
20847 : B - destination matrix, must be large enough to store result
20848 : IB - submatrix offset (row index)
20849 : JB - submatrix offset (column index)
20850 : *************************************************************************/
20851 0 : void cmatrixcopy(ae_int_t m,
20852 : ae_int_t n,
20853 : /* Complex */ ae_matrix* a,
20854 : ae_int_t ia,
20855 : ae_int_t ja,
20856 : /* Complex */ ae_matrix* b,
20857 : ae_int_t ib,
20858 : ae_int_t jb,
20859 : ae_state *_state)
20860 : {
20861 : ae_int_t i;
20862 :
20863 :
20864 0 : if( m==0||n==0 )
20865 : {
20866 0 : return;
20867 : }
20868 0 : for(i=0; i<=m-1; i++)
20869 : {
20870 0 : ae_v_cmove(&b->ptr.pp_complex[ib+i][jb], 1, &a->ptr.pp_complex[ia+i][ja], 1, "N", ae_v_len(jb,jb+n-1));
20871 : }
20872 : }
20873 :
20874 :
20875 : /*************************************************************************
20876 : Copy
20877 :
20878 : Input parameters:
20879 : N - subvector size
20880 : A - source vector, N elements are copied
20881 : IA - source offset (first element index)
20882 : B - destination vector, must be large enough to store result
20883 : IB - destination offset (first element index)
20884 : *************************************************************************/
20885 0 : void rvectorcopy(ae_int_t n,
20886 : /* Real */ ae_vector* a,
20887 : ae_int_t ia,
20888 : /* Real */ ae_vector* b,
20889 : ae_int_t ib,
20890 : ae_state *_state)
20891 : {
20892 : ae_int_t i;
20893 :
20894 :
20895 0 : if( n==0 )
20896 : {
20897 0 : return;
20898 : }
20899 0 : for(i=0; i<=n-1; i++)
20900 : {
20901 0 : b->ptr.p_double[ib+i] = a->ptr.p_double[ia+i];
20902 : }
20903 : }
20904 :
20905 :
20906 : /*************************************************************************
20907 : Copy
20908 :
20909 : Input parameters:
20910 : M - number of rows
20911 : N - number of columns
20912 : A - source matrix, MxN submatrix is copied and transposed
20913 : IA - submatrix offset (row index)
20914 : JA - submatrix offset (column index)
20915 : B - destination matrix, must be large enough to store result
20916 : IB - submatrix offset (row index)
20917 : JB - submatrix offset (column index)
20918 : *************************************************************************/
20919 0 : void rmatrixcopy(ae_int_t m,
20920 : ae_int_t n,
20921 : /* Real */ ae_matrix* a,
20922 : ae_int_t ia,
20923 : ae_int_t ja,
20924 : /* Real */ ae_matrix* b,
20925 : ae_int_t ib,
20926 : ae_int_t jb,
20927 : ae_state *_state)
20928 : {
20929 : ae_int_t i;
20930 :
20931 :
20932 0 : if( m==0||n==0 )
20933 : {
20934 0 : return;
20935 : }
20936 0 : for(i=0; i<=m-1; i++)
20937 : {
20938 0 : ae_v_move(&b->ptr.pp_double[ib+i][jb], 1, &a->ptr.pp_double[ia+i][ja], 1, ae_v_len(jb,jb+n-1));
20939 : }
20940 : }
20941 :
20942 :
20943 : /*************************************************************************
20944 : Performs generalized copy: B := Beta*B + Alpha*A.
20945 :
20946 : If Beta=0, then previous contents of B is simply ignored. If Alpha=0, then
20947 : A is ignored and not referenced. If both Alpha and Beta are zero, B is
20948 : filled by zeros.
20949 :
20950 : Input parameters:
20951 : M - number of rows
20952 : N - number of columns
20953 : Alpha- coefficient
20954 : A - source matrix, MxN submatrix is copied and transposed
20955 : IA - submatrix offset (row index)
20956 : JA - submatrix offset (column index)
20957 : Beta- coefficient
20958 : B - destination matrix, must be large enough to store result
20959 : IB - submatrix offset (row index)
20960 : JB - submatrix offset (column index)
20961 : *************************************************************************/
20962 0 : void rmatrixgencopy(ae_int_t m,
20963 : ae_int_t n,
20964 : double alpha,
20965 : /* Real */ ae_matrix* a,
20966 : ae_int_t ia,
20967 : ae_int_t ja,
20968 : double beta,
20969 : /* Real */ ae_matrix* b,
20970 : ae_int_t ib,
20971 : ae_int_t jb,
20972 : ae_state *_state)
20973 : {
20974 : ae_int_t i;
20975 : ae_int_t j;
20976 :
20977 :
20978 0 : if( m==0||n==0 )
20979 : {
20980 0 : return;
20981 : }
20982 :
20983 : /*
20984 : * Zero-fill
20985 : */
20986 0 : if( ae_fp_eq(alpha,(double)(0))&&ae_fp_eq(beta,(double)(0)) )
20987 : {
20988 0 : for(i=0; i<=m-1; i++)
20989 : {
20990 0 : for(j=0; j<=n-1; j++)
20991 : {
20992 0 : b->ptr.pp_double[ib+i][jb+j] = (double)(0);
20993 : }
20994 : }
20995 0 : return;
20996 : }
20997 :
20998 : /*
20999 : * Inplace multiply
21000 : */
21001 0 : if( ae_fp_eq(alpha,(double)(0)) )
21002 : {
21003 0 : for(i=0; i<=m-1; i++)
21004 : {
21005 0 : for(j=0; j<=n-1; j++)
21006 : {
21007 0 : b->ptr.pp_double[ib+i][jb+j] = beta*b->ptr.pp_double[ib+i][jb+j];
21008 : }
21009 : }
21010 0 : return;
21011 : }
21012 :
21013 : /*
21014 : * Multiply and copy
21015 : */
21016 0 : if( ae_fp_eq(beta,(double)(0)) )
21017 : {
21018 0 : for(i=0; i<=m-1; i++)
21019 : {
21020 0 : for(j=0; j<=n-1; j++)
21021 : {
21022 0 : b->ptr.pp_double[ib+i][jb+j] = alpha*a->ptr.pp_double[ia+i][ja+j];
21023 : }
21024 : }
21025 0 : return;
21026 : }
21027 :
21028 : /*
21029 : * Generic
21030 : */
21031 0 : for(i=0; i<=m-1; i++)
21032 : {
21033 0 : for(j=0; j<=n-1; j++)
21034 : {
21035 0 : b->ptr.pp_double[ib+i][jb+j] = alpha*a->ptr.pp_double[ia+i][ja+j]+beta*b->ptr.pp_double[ib+i][jb+j];
21036 : }
21037 : }
21038 : }
21039 :
21040 :
21041 : /*************************************************************************
21042 : Rank-1 correction: A := A + alpha*u*v'
21043 :
21044 : NOTE: this function expects A to be large enough to store result. No
21045 : automatic preallocation happens for smaller arrays. No integrity
21046 : checks is performed for sizes of A, u, v.
21047 :
21048 : INPUT PARAMETERS:
21049 : M - number of rows
21050 : N - number of columns
21051 : A - target matrix, MxN submatrix is updated
21052 : IA - submatrix offset (row index)
21053 : JA - submatrix offset (column index)
21054 : Alpha- coefficient
21055 : U - vector #1
21056 : IU - subvector offset
21057 : V - vector #2
21058 : IV - subvector offset
21059 :
21060 :
21061 : -- ALGLIB routine --
21062 :
21063 : 16.10.2017
21064 : Bochkanov Sergey
21065 : *************************************************************************/
21066 0 : void rmatrixger(ae_int_t m,
21067 : ae_int_t n,
21068 : /* Real */ ae_matrix* a,
21069 : ae_int_t ia,
21070 : ae_int_t ja,
21071 : double alpha,
21072 : /* Real */ ae_vector* u,
21073 : ae_int_t iu,
21074 : /* Real */ ae_vector* v,
21075 : ae_int_t iv,
21076 : ae_state *_state)
21077 : {
21078 : ae_int_t i;
21079 : double s;
21080 :
21081 :
21082 :
21083 : /*
21084 : * Quick exit
21085 : */
21086 0 : if( m<=0||n<=0 )
21087 : {
21088 0 : return;
21089 : }
21090 :
21091 : /*
21092 : * Try fast kernels:
21093 : * * vendor kernel
21094 : * * internal kernel
21095 : */
21096 0 : if( m>ablas_blas2minvendorkernelsize&&n>ablas_blas2minvendorkernelsize )
21097 : {
21098 :
21099 : /*
21100 : * Try MKL kernel first
21101 : */
21102 0 : if( rmatrixgermkl(m, n, a, ia, ja, alpha, u, iu, v, iv, _state) )
21103 : {
21104 0 : return;
21105 : }
21106 : }
21107 0 : if( rmatrixgerf(m, n, a, ia, ja, alpha, u, iu, v, iv, _state) )
21108 : {
21109 0 : return;
21110 : }
21111 :
21112 : /*
21113 : * Generic code
21114 : */
21115 0 : for(i=0; i<=m-1; i++)
21116 : {
21117 0 : s = alpha*u->ptr.p_double[iu+i];
21118 0 : ae_v_addd(&a->ptr.pp_double[ia+i][ja], 1, &v->ptr.p_double[iv], 1, ae_v_len(ja,ja+n-1), s);
21119 : }
21120 : }
21121 :
21122 :
21123 : /*************************************************************************
21124 : Rank-1 correction: A := A + u*v'
21125 :
21126 : INPUT PARAMETERS:
21127 : M - number of rows
21128 : N - number of columns
21129 : A - target matrix, MxN submatrix is updated
21130 : IA - submatrix offset (row index)
21131 : JA - submatrix offset (column index)
21132 : U - vector #1
21133 : IU - subvector offset
21134 : V - vector #2
21135 : IV - subvector offset
21136 : *************************************************************************/
21137 0 : void cmatrixrank1(ae_int_t m,
21138 : ae_int_t n,
21139 : /* Complex */ ae_matrix* a,
21140 : ae_int_t ia,
21141 : ae_int_t ja,
21142 : /* Complex */ ae_vector* u,
21143 : ae_int_t iu,
21144 : /* Complex */ ae_vector* v,
21145 : ae_int_t iv,
21146 : ae_state *_state)
21147 : {
21148 : ae_int_t i;
21149 : ae_complex s;
21150 :
21151 :
21152 :
21153 : /*
21154 : * Quick exit
21155 : */
21156 0 : if( m<=0||n<=0 )
21157 : {
21158 0 : return;
21159 : }
21160 :
21161 : /*
21162 : * Try fast kernels:
21163 : * * vendor kernel
21164 : * * internal kernel
21165 : */
21166 0 : if( m>ablas_blas2minvendorkernelsize&&n>ablas_blas2minvendorkernelsize )
21167 : {
21168 :
21169 : /*
21170 : * Try MKL kernel first
21171 : */
21172 0 : if( cmatrixrank1mkl(m, n, a, ia, ja, u, iu, v, iv, _state) )
21173 : {
21174 0 : return;
21175 : }
21176 : }
21177 0 : if( cmatrixrank1f(m, n, a, ia, ja, u, iu, v, iv, _state) )
21178 : {
21179 0 : return;
21180 : }
21181 :
21182 : /*
21183 : * Generic code
21184 : */
21185 0 : for(i=0; i<=m-1; i++)
21186 : {
21187 0 : s = u->ptr.p_complex[iu+i];
21188 0 : ae_v_caddc(&a->ptr.pp_complex[ia+i][ja], 1, &v->ptr.p_complex[iv], 1, "N", ae_v_len(ja,ja+n-1), s);
21189 : }
21190 : }
21191 :
21192 :
21193 : /*************************************************************************
21194 : IMPORTANT: this function is deprecated since ALGLIB 3.13. Use RMatrixGER()
21195 : which is more generic version of this function.
21196 :
21197 : Rank-1 correction: A := A + u*v'
21198 :
21199 : INPUT PARAMETERS:
21200 : M - number of rows
21201 : N - number of columns
21202 : A - target matrix, MxN submatrix is updated
21203 : IA - submatrix offset (row index)
21204 : JA - submatrix offset (column index)
21205 : U - vector #1
21206 : IU - subvector offset
21207 : V - vector #2
21208 : IV - subvector offset
21209 : *************************************************************************/
21210 0 : void rmatrixrank1(ae_int_t m,
21211 : ae_int_t n,
21212 : /* Real */ ae_matrix* a,
21213 : ae_int_t ia,
21214 : ae_int_t ja,
21215 : /* Real */ ae_vector* u,
21216 : ae_int_t iu,
21217 : /* Real */ ae_vector* v,
21218 : ae_int_t iv,
21219 : ae_state *_state)
21220 : {
21221 : ae_int_t i;
21222 : double s;
21223 :
21224 :
21225 :
21226 : /*
21227 : * Quick exit
21228 : */
21229 0 : if( m<=0||n<=0 )
21230 : {
21231 0 : return;
21232 : }
21233 :
21234 : /*
21235 : * Try fast kernels:
21236 : * * vendor kernel
21237 : * * internal kernel
21238 : */
21239 0 : if( m>ablas_blas2minvendorkernelsize&&n>ablas_blas2minvendorkernelsize )
21240 : {
21241 :
21242 : /*
21243 : * Try MKL kernel first
21244 : */
21245 0 : if( rmatrixrank1mkl(m, n, a, ia, ja, u, iu, v, iv, _state) )
21246 : {
21247 0 : return;
21248 : }
21249 : }
21250 0 : if( rmatrixrank1f(m, n, a, ia, ja, u, iu, v, iv, _state) )
21251 : {
21252 0 : return;
21253 : }
21254 :
21255 : /*
21256 : * Generic code
21257 : */
21258 0 : for(i=0; i<=m-1; i++)
21259 : {
21260 0 : s = u->ptr.p_double[iu+i];
21261 0 : ae_v_addd(&a->ptr.pp_double[ia+i][ja], 1, &v->ptr.p_double[iv], 1, ae_v_len(ja,ja+n-1), s);
21262 : }
21263 : }
21264 :
21265 :
21266 0 : void rmatrixgemv(ae_int_t m,
21267 : ae_int_t n,
21268 : double alpha,
21269 : /* Real */ ae_matrix* a,
21270 : ae_int_t ia,
21271 : ae_int_t ja,
21272 : ae_int_t opa,
21273 : /* Real */ ae_vector* x,
21274 : ae_int_t ix,
21275 : double beta,
21276 : /* Real */ ae_vector* y,
21277 : ae_int_t iy,
21278 : ae_state *_state)
21279 : {
21280 : ae_int_t i;
21281 : double v;
21282 :
21283 :
21284 :
21285 : /*
21286 : * Quick exit for M=0, N=0 or Alpha=0.
21287 : *
21288 : * After this block we have M>0, N>0, Alpha<>0.
21289 : */
21290 0 : if( m<=0 )
21291 : {
21292 0 : return;
21293 : }
21294 0 : if( n<=0||ae_fp_eq(alpha,0.0) )
21295 : {
21296 0 : if( ae_fp_neq(beta,(double)(0)) )
21297 : {
21298 0 : for(i=0; i<=m-1; i++)
21299 : {
21300 0 : y->ptr.p_double[iy+i] = beta*y->ptr.p_double[iy+i];
21301 : }
21302 : }
21303 : else
21304 : {
21305 0 : for(i=0; i<=m-1; i++)
21306 : {
21307 0 : y->ptr.p_double[iy+i] = 0.0;
21308 : }
21309 : }
21310 0 : return;
21311 : }
21312 :
21313 : /*
21314 : * Try fast kernels
21315 : */
21316 0 : if( m>ablas_blas2minvendorkernelsize&&n>ablas_blas2minvendorkernelsize )
21317 : {
21318 :
21319 : /*
21320 : * Try MKL kernel
21321 : */
21322 0 : if( rmatrixgemvmkl(m, n, alpha, a, ia, ja, opa, x, ix, beta, y, iy, _state) )
21323 : {
21324 0 : return;
21325 : }
21326 : }
21327 :
21328 : /*
21329 : * Generic code
21330 : */
21331 0 : if( opa==0 )
21332 : {
21333 :
21334 : /*
21335 : * y = A*x
21336 : */
21337 0 : for(i=0; i<=m-1; i++)
21338 : {
21339 0 : v = ae_v_dotproduct(&a->ptr.pp_double[ia+i][ja], 1, &x->ptr.p_double[ix], 1, ae_v_len(ja,ja+n-1));
21340 0 : if( ae_fp_eq(beta,0.0) )
21341 : {
21342 0 : y->ptr.p_double[iy+i] = alpha*v;
21343 : }
21344 : else
21345 : {
21346 0 : y->ptr.p_double[iy+i] = alpha*v+beta*y->ptr.p_double[iy+i];
21347 : }
21348 : }
21349 0 : return;
21350 : }
21351 0 : if( opa==1 )
21352 : {
21353 :
21354 : /*
21355 : * Prepare output array
21356 : */
21357 0 : if( ae_fp_eq(beta,0.0) )
21358 : {
21359 0 : for(i=0; i<=m-1; i++)
21360 : {
21361 0 : y->ptr.p_double[iy+i] = (double)(0);
21362 : }
21363 : }
21364 : else
21365 : {
21366 0 : for(i=0; i<=m-1; i++)
21367 : {
21368 0 : y->ptr.p_double[iy+i] = beta*y->ptr.p_double[iy+i];
21369 : }
21370 : }
21371 :
21372 : /*
21373 : * y += A^T*x
21374 : */
21375 0 : for(i=0; i<=n-1; i++)
21376 : {
21377 0 : v = alpha*x->ptr.p_double[ix+i];
21378 0 : ae_v_addd(&y->ptr.p_double[iy], 1, &a->ptr.pp_double[ia+i][ja], 1, ae_v_len(iy,iy+m-1), v);
21379 : }
21380 0 : return;
21381 : }
21382 : }
21383 :
21384 :
21385 : /*************************************************************************
21386 : Matrix-vector product: y := op(A)*x
21387 :
21388 : INPUT PARAMETERS:
21389 : M - number of rows of op(A)
21390 : M>=0
21391 : N - number of columns of op(A)
21392 : N>=0
21393 : A - target matrix
21394 : IA - submatrix offset (row index)
21395 : JA - submatrix offset (column index)
21396 : OpA - operation type:
21397 : * OpA=0 => op(A) = A
21398 : * OpA=1 => op(A) = A^T
21399 : * OpA=2 => op(A) = A^H
21400 : X - input vector
21401 : IX - subvector offset
21402 : IY - subvector offset
21403 : Y - preallocated matrix, must be large enough to store result
21404 :
21405 : OUTPUT PARAMETERS:
21406 : Y - vector which stores result
21407 :
21408 : if M=0, then subroutine does nothing.
21409 : if N=0, Y is filled by zeros.
21410 :
21411 :
21412 : -- ALGLIB routine --
21413 :
21414 : 28.01.2010
21415 : Bochkanov Sergey
21416 : *************************************************************************/
21417 0 : void cmatrixmv(ae_int_t m,
21418 : ae_int_t n,
21419 : /* Complex */ ae_matrix* a,
21420 : ae_int_t ia,
21421 : ae_int_t ja,
21422 : ae_int_t opa,
21423 : /* Complex */ ae_vector* x,
21424 : ae_int_t ix,
21425 : /* Complex */ ae_vector* y,
21426 : ae_int_t iy,
21427 : ae_state *_state)
21428 : {
21429 : ae_int_t i;
21430 : ae_complex v;
21431 :
21432 :
21433 :
21434 : /*
21435 : * Quick exit
21436 : */
21437 0 : if( m==0 )
21438 : {
21439 0 : return;
21440 : }
21441 0 : if( n==0 )
21442 : {
21443 0 : for(i=0; i<=m-1; i++)
21444 : {
21445 0 : y->ptr.p_complex[iy+i] = ae_complex_from_i(0);
21446 : }
21447 0 : return;
21448 : }
21449 :
21450 : /*
21451 : * Try fast kernels
21452 : */
21453 0 : if( m>ablas_blas2minvendorkernelsize&&n>ablas_blas2minvendorkernelsize )
21454 : {
21455 :
21456 : /*
21457 : * Try MKL kernel
21458 : */
21459 0 : if( cmatrixmvmkl(m, n, a, ia, ja, opa, x, ix, y, iy, _state) )
21460 : {
21461 0 : return;
21462 : }
21463 : }
21464 :
21465 : /*
21466 : * Generic code
21467 : */
21468 0 : if( opa==0 )
21469 : {
21470 :
21471 : /*
21472 : * y = A*x
21473 : */
21474 0 : for(i=0; i<=m-1; i++)
21475 : {
21476 0 : v = ae_v_cdotproduct(&a->ptr.pp_complex[ia+i][ja], 1, "N", &x->ptr.p_complex[ix], 1, "N", ae_v_len(ja,ja+n-1));
21477 0 : y->ptr.p_complex[iy+i] = v;
21478 : }
21479 0 : return;
21480 : }
21481 0 : if( opa==1 )
21482 : {
21483 :
21484 : /*
21485 : * y = A^T*x
21486 : */
21487 0 : for(i=0; i<=m-1; i++)
21488 : {
21489 0 : y->ptr.p_complex[iy+i] = ae_complex_from_i(0);
21490 : }
21491 0 : for(i=0; i<=n-1; i++)
21492 : {
21493 0 : v = x->ptr.p_complex[ix+i];
21494 0 : ae_v_caddc(&y->ptr.p_complex[iy], 1, &a->ptr.pp_complex[ia+i][ja], 1, "N", ae_v_len(iy,iy+m-1), v);
21495 : }
21496 0 : return;
21497 : }
21498 0 : if( opa==2 )
21499 : {
21500 :
21501 : /*
21502 : * y = A^H*x
21503 : */
21504 0 : for(i=0; i<=m-1; i++)
21505 : {
21506 0 : y->ptr.p_complex[iy+i] = ae_complex_from_i(0);
21507 : }
21508 0 : for(i=0; i<=n-1; i++)
21509 : {
21510 0 : v = x->ptr.p_complex[ix+i];
21511 0 : ae_v_caddc(&y->ptr.p_complex[iy], 1, &a->ptr.pp_complex[ia+i][ja], 1, "Conj", ae_v_len(iy,iy+m-1), v);
21512 : }
21513 0 : return;
21514 : }
21515 : }
21516 :
21517 :
21518 : /*************************************************************************
21519 : IMPORTANT: this function is deprecated since ALGLIB 3.13. Use RMatrixGEMV()
21520 : which is more generic version of this function.
21521 :
21522 : Matrix-vector product: y := op(A)*x
21523 :
21524 : INPUT PARAMETERS:
21525 : M - number of rows of op(A)
21526 : N - number of columns of op(A)
21527 : A - target matrix
21528 : IA - submatrix offset (row index)
21529 : JA - submatrix offset (column index)
21530 : OpA - operation type:
21531 : * OpA=0 => op(A) = A
21532 : * OpA=1 => op(A) = A^T
21533 : X - input vector
21534 : IX - subvector offset
21535 : IY - subvector offset
21536 : Y - preallocated matrix, must be large enough to store result
21537 :
21538 : OUTPUT PARAMETERS:
21539 : Y - vector which stores result
21540 :
21541 : if M=0, then subroutine does nothing.
21542 : if N=0, Y is filled by zeros.
21543 :
21544 :
21545 : -- ALGLIB routine --
21546 :
21547 : 28.01.2010
21548 : Bochkanov Sergey
21549 : *************************************************************************/
21550 0 : void rmatrixmv(ae_int_t m,
21551 : ae_int_t n,
21552 : /* Real */ ae_matrix* a,
21553 : ae_int_t ia,
21554 : ae_int_t ja,
21555 : ae_int_t opa,
21556 : /* Real */ ae_vector* x,
21557 : ae_int_t ix,
21558 : /* Real */ ae_vector* y,
21559 : ae_int_t iy,
21560 : ae_state *_state)
21561 : {
21562 : ae_int_t i;
21563 : double v;
21564 :
21565 :
21566 :
21567 : /*
21568 : * Quick exit
21569 : */
21570 0 : if( m==0 )
21571 : {
21572 0 : return;
21573 : }
21574 0 : if( n==0 )
21575 : {
21576 0 : for(i=0; i<=m-1; i++)
21577 : {
21578 0 : y->ptr.p_double[iy+i] = (double)(0);
21579 : }
21580 0 : return;
21581 : }
21582 :
21583 : /*
21584 : * Try fast kernels
21585 : */
21586 0 : if( m>ablas_blas2minvendorkernelsize&&n>ablas_blas2minvendorkernelsize )
21587 : {
21588 :
21589 : /*
21590 : * Try MKL kernel
21591 : */
21592 0 : if( rmatrixmvmkl(m, n, a, ia, ja, opa, x, ix, y, iy, _state) )
21593 : {
21594 0 : return;
21595 : }
21596 : }
21597 :
21598 : /*
21599 : * Generic code
21600 : */
21601 0 : if( opa==0 )
21602 : {
21603 :
21604 : /*
21605 : * y = A*x
21606 : */
21607 0 : for(i=0; i<=m-1; i++)
21608 : {
21609 0 : v = ae_v_dotproduct(&a->ptr.pp_double[ia+i][ja], 1, &x->ptr.p_double[ix], 1, ae_v_len(ja,ja+n-1));
21610 0 : y->ptr.p_double[iy+i] = v;
21611 : }
21612 0 : return;
21613 : }
21614 0 : if( opa==1 )
21615 : {
21616 :
21617 : /*
21618 : * y = A^T*x
21619 : */
21620 0 : for(i=0; i<=m-1; i++)
21621 : {
21622 0 : y->ptr.p_double[iy+i] = (double)(0);
21623 : }
21624 0 : for(i=0; i<=n-1; i++)
21625 : {
21626 0 : v = x->ptr.p_double[ix+i];
21627 0 : ae_v_addd(&y->ptr.p_double[iy], 1, &a->ptr.pp_double[ia+i][ja], 1, ae_v_len(iy,iy+m-1), v);
21628 : }
21629 0 : return;
21630 : }
21631 : }
21632 :
21633 :
21634 0 : void rmatrixsymv(ae_int_t n,
21635 : double alpha,
21636 : /* Real */ ae_matrix* a,
21637 : ae_int_t ia,
21638 : ae_int_t ja,
21639 : ae_bool isupper,
21640 : /* Real */ ae_vector* x,
21641 : ae_int_t ix,
21642 : double beta,
21643 : /* Real */ ae_vector* y,
21644 : ae_int_t iy,
21645 : ae_state *_state)
21646 : {
21647 : ae_int_t i;
21648 : ae_int_t j;
21649 : double v;
21650 : double vr;
21651 : double vx;
21652 :
21653 :
21654 :
21655 : /*
21656 : * Quick exit for M=0, N=0 or Alpha=0.
21657 : *
21658 : * After this block we have M>0, N>0, Alpha<>0.
21659 : */
21660 0 : if( n<=0 )
21661 : {
21662 0 : return;
21663 : }
21664 0 : if( ae_fp_eq(alpha,0.0) )
21665 : {
21666 0 : if( ae_fp_neq(beta,(double)(0)) )
21667 : {
21668 0 : for(i=0; i<=n-1; i++)
21669 : {
21670 0 : y->ptr.p_double[iy+i] = beta*y->ptr.p_double[iy+i];
21671 : }
21672 : }
21673 : else
21674 : {
21675 0 : for(i=0; i<=n-1; i++)
21676 : {
21677 0 : y->ptr.p_double[iy+i] = 0.0;
21678 : }
21679 : }
21680 0 : return;
21681 : }
21682 :
21683 : /*
21684 : * Try fast kernels
21685 : */
21686 0 : if( n>ablas_blas2minvendorkernelsize )
21687 : {
21688 :
21689 : /*
21690 : * Try MKL kernel
21691 : */
21692 0 : if( rmatrixsymvmkl(n, alpha, a, ia, ja, isupper, x, ix, beta, y, iy, _state) )
21693 : {
21694 0 : return;
21695 : }
21696 : }
21697 :
21698 : /*
21699 : * Generic code
21700 : */
21701 0 : if( ae_fp_neq(beta,(double)(0)) )
21702 : {
21703 0 : for(i=0; i<=n-1; i++)
21704 : {
21705 0 : y->ptr.p_double[iy+i] = beta*y->ptr.p_double[iy+i];
21706 : }
21707 : }
21708 : else
21709 : {
21710 0 : for(i=0; i<=n-1; i++)
21711 : {
21712 0 : y->ptr.p_double[iy+i] = 0.0;
21713 : }
21714 : }
21715 0 : if( isupper )
21716 : {
21717 :
21718 : /*
21719 : * Upper triangle of A is stored
21720 : */
21721 0 : for(i=0; i<=n-1; i++)
21722 : {
21723 :
21724 : /*
21725 : * Process diagonal element
21726 : */
21727 0 : v = alpha*a->ptr.pp_double[ia+i][ja+i];
21728 0 : y->ptr.p_double[iy+i] = y->ptr.p_double[iy+i]+v*x->ptr.p_double[ix+i];
21729 :
21730 : /*
21731 : * Process off-diagonal elements
21732 : */
21733 0 : vr = 0.0;
21734 0 : vx = x->ptr.p_double[ix+i];
21735 0 : for(j=i+1; j<=n-1; j++)
21736 : {
21737 0 : v = alpha*a->ptr.pp_double[ia+i][ja+j];
21738 0 : y->ptr.p_double[iy+j] = y->ptr.p_double[iy+j]+v*vx;
21739 0 : vr = vr+v*x->ptr.p_double[ix+j];
21740 : }
21741 0 : y->ptr.p_double[iy+i] = y->ptr.p_double[iy+i]+vr;
21742 : }
21743 : }
21744 : else
21745 : {
21746 :
21747 : /*
21748 : * Lower triangle of A is stored
21749 : */
21750 0 : for(i=0; i<=n-1; i++)
21751 : {
21752 :
21753 : /*
21754 : * Process diagonal element
21755 : */
21756 0 : v = alpha*a->ptr.pp_double[ia+i][ja+i];
21757 0 : y->ptr.p_double[iy+i] = y->ptr.p_double[iy+i]+v*x->ptr.p_double[ix+i];
21758 :
21759 : /*
21760 : * Process off-diagonal elements
21761 : */
21762 0 : vr = 0.0;
21763 0 : vx = x->ptr.p_double[ix+i];
21764 0 : for(j=0; j<=i-1; j++)
21765 : {
21766 0 : v = alpha*a->ptr.pp_double[ia+i][ja+j];
21767 0 : y->ptr.p_double[iy+j] = y->ptr.p_double[iy+j]+v*vx;
21768 0 : vr = vr+v*x->ptr.p_double[ix+j];
21769 : }
21770 0 : y->ptr.p_double[iy+i] = y->ptr.p_double[iy+i]+vr;
21771 : }
21772 : }
21773 : }
21774 :
21775 :
21776 0 : double rmatrixsyvmv(ae_int_t n,
21777 : /* Real */ ae_matrix* a,
21778 : ae_int_t ia,
21779 : ae_int_t ja,
21780 : ae_bool isupper,
21781 : /* Real */ ae_vector* x,
21782 : ae_int_t ix,
21783 : /* Real */ ae_vector* tmp,
21784 : ae_state *_state)
21785 : {
21786 : ae_int_t i;
21787 : double result;
21788 :
21789 :
21790 :
21791 : /*
21792 : * Quick exit for N=0
21793 : */
21794 0 : if( n<=0 )
21795 : {
21796 0 : result = (double)(0);
21797 0 : return result;
21798 : }
21799 :
21800 : /*
21801 : * Generic code
21802 : */
21803 0 : rmatrixsymv(n, 1.0, a, ia, ja, isupper, x, ix, 0.0, tmp, 0, _state);
21804 0 : result = (double)(0);
21805 0 : for(i=0; i<=n-1; i++)
21806 : {
21807 0 : result = result+x->ptr.p_double[ix+i]*tmp->ptr.p_double[i];
21808 : }
21809 0 : return result;
21810 : }
21811 :
21812 :
21813 : /*************************************************************************
21814 : This subroutine solves linear system op(A)*x=b where:
21815 : * A is NxN upper/lower triangular/unitriangular matrix
21816 : * X and B are Nx1 vectors
21817 : * "op" may be identity transformation, transposition, conjugate transposition
21818 :
21819 : Solution replaces X.
21820 :
21821 : IMPORTANT: * no overflow/underflow/denegeracy tests is performed.
21822 : * no integrity checks for operand sizes, out-of-bounds accesses
21823 : and so on is performed
21824 :
21825 : INPUT PARAMETERS
21826 : N - matrix size, N>=0
21827 : A - matrix, actial matrix is stored in A[IA:IA+N-1,JA:JA+N-1]
21828 : IA - submatrix offset
21829 : JA - submatrix offset
21830 : IsUpper - whether matrix is upper triangular
21831 : IsUnit - whether matrix is unitriangular
21832 : OpType - transformation type:
21833 : * 0 - no transformation
21834 : * 1 - transposition
21835 : X - right part, actual vector is stored in X[IX:IX+N-1]
21836 : IX - offset
21837 :
21838 : OUTPUT PARAMETERS
21839 : X - solution replaces elements X[IX:IX+N-1]
21840 :
21841 : -- ALGLIB routine / remastering of LAPACK's DTRSV --
21842 : (c) 2017 Bochkanov Sergey - converted to ALGLIB
21843 : (c) 2016 Reference BLAS level1 routine (LAPACK version 3.7.0)
21844 : Reference BLAS is a software package provided by Univ. of Tennessee,
21845 : Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd.
21846 : *************************************************************************/
21847 0 : void rmatrixtrsv(ae_int_t n,
21848 : /* Real */ ae_matrix* a,
21849 : ae_int_t ia,
21850 : ae_int_t ja,
21851 : ae_bool isupper,
21852 : ae_bool isunit,
21853 : ae_int_t optype,
21854 : /* Real */ ae_vector* x,
21855 : ae_int_t ix,
21856 : ae_state *_state)
21857 : {
21858 : ae_int_t i;
21859 : ae_int_t j;
21860 : double v;
21861 :
21862 :
21863 :
21864 : /*
21865 : * Quick exit
21866 : */
21867 0 : if( n<=0 )
21868 : {
21869 0 : return;
21870 : }
21871 :
21872 : /*
21873 : * Try fast kernels
21874 : */
21875 0 : if( n>ablas_blas2minvendorkernelsize )
21876 : {
21877 :
21878 : /*
21879 : * Try MKL kernel
21880 : */
21881 0 : if( rmatrixtrsvmkl(n, a, ia, ja, isupper, isunit, optype, x, ix, _state) )
21882 : {
21883 0 : return;
21884 : }
21885 : }
21886 :
21887 : /*
21888 : * Generic code
21889 : */
21890 0 : if( optype==0&&isupper )
21891 : {
21892 0 : for(i=n-1; i>=0; i--)
21893 : {
21894 0 : v = x->ptr.p_double[ix+i];
21895 0 : for(j=i+1; j<=n-1; j++)
21896 : {
21897 0 : v = v-a->ptr.pp_double[ia+i][ja+j]*x->ptr.p_double[ix+j];
21898 : }
21899 0 : if( !isunit )
21900 : {
21901 0 : v = v/a->ptr.pp_double[ia+i][ja+i];
21902 : }
21903 0 : x->ptr.p_double[ix+i] = v;
21904 : }
21905 0 : return;
21906 : }
21907 0 : if( optype==0&&!isupper )
21908 : {
21909 0 : for(i=0; i<=n-1; i++)
21910 : {
21911 0 : v = x->ptr.p_double[ix+i];
21912 0 : for(j=0; j<=i-1; j++)
21913 : {
21914 0 : v = v-a->ptr.pp_double[ia+i][ja+j]*x->ptr.p_double[ix+j];
21915 : }
21916 0 : if( !isunit )
21917 : {
21918 0 : v = v/a->ptr.pp_double[ia+i][ja+i];
21919 : }
21920 0 : x->ptr.p_double[ix+i] = v;
21921 : }
21922 0 : return;
21923 : }
21924 0 : if( optype==1&&isupper )
21925 : {
21926 0 : for(i=0; i<=n-1; i++)
21927 : {
21928 0 : v = x->ptr.p_double[ix+i];
21929 0 : if( !isunit )
21930 : {
21931 0 : v = v/a->ptr.pp_double[ia+i][ja+i];
21932 : }
21933 0 : x->ptr.p_double[ix+i] = v;
21934 0 : if( v==0 )
21935 : {
21936 0 : continue;
21937 : }
21938 0 : for(j=i+1; j<=n-1; j++)
21939 : {
21940 0 : x->ptr.p_double[ix+j] = x->ptr.p_double[ix+j]-v*a->ptr.pp_double[ia+i][ja+j];
21941 : }
21942 : }
21943 0 : return;
21944 : }
21945 0 : if( optype==1&&!isupper )
21946 : {
21947 0 : for(i=n-1; i>=0; i--)
21948 : {
21949 0 : v = x->ptr.p_double[ix+i];
21950 0 : if( !isunit )
21951 : {
21952 0 : v = v/a->ptr.pp_double[ia+i][ja+i];
21953 : }
21954 0 : x->ptr.p_double[ix+i] = v;
21955 0 : if( v==0 )
21956 : {
21957 0 : continue;
21958 : }
21959 0 : for(j=0; j<=i-1; j++)
21960 : {
21961 0 : x->ptr.p_double[ix+j] = x->ptr.p_double[ix+j]-v*a->ptr.pp_double[ia+i][ja+j];
21962 : }
21963 : }
21964 0 : return;
21965 : }
21966 0 : ae_assert(ae_false, "RMatrixTRSV: unexpected operation type", _state);
21967 : }
21968 :
21969 :
21970 : /*************************************************************************
21971 : This subroutine calculates X*op(A^-1) where:
21972 : * X is MxN general matrix
21973 : * A is NxN upper/lower triangular/unitriangular matrix
21974 : * "op" may be identity transformation, transposition, conjugate transposition
21975 : Multiplication result replaces X.
21976 :
21977 : ! COMMERCIAL EDITION OF ALGLIB:
21978 : !
21979 : ! Commercial Edition of ALGLIB includes following important improvements
21980 : ! of this function:
21981 : ! * high-performance native backend with same C# interface (C# version)
21982 : ! * multithreading support (C++ and C# versions)
21983 : ! * hardware vendor (Intel) implementations of linear algebra primitives
21984 : ! (C++ and C# versions, x86/x64 platform)
21985 : !
21986 : ! We recommend you to read 'Working with commercial version' section of
21987 : ! ALGLIB Reference Manual in order to find out how to use performance-
21988 : ! related features provided by commercial edition of ALGLIB.
21989 :
21990 : INPUT PARAMETERS
21991 : N - matrix size, N>=0
21992 : M - matrix size, N>=0
21993 : A - matrix, actial matrix is stored in A[I1:I1+N-1,J1:J1+N-1]
21994 : I1 - submatrix offset
21995 : J1 - submatrix offset
21996 : IsUpper - whether matrix is upper triangular
21997 : IsUnit - whether matrix is unitriangular
21998 : OpType - transformation type:
21999 : * 0 - no transformation
22000 : * 1 - transposition
22001 : * 2 - conjugate transposition
22002 : X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1]
22003 : I2 - submatrix offset
22004 : J2 - submatrix offset
22005 :
22006 : -- ALGLIB routine --
22007 : 20.01.2018
22008 : Bochkanov Sergey
22009 : *************************************************************************/
22010 0 : void cmatrixrighttrsm(ae_int_t m,
22011 : ae_int_t n,
22012 : /* Complex */ ae_matrix* a,
22013 : ae_int_t i1,
22014 : ae_int_t j1,
22015 : ae_bool isupper,
22016 : ae_bool isunit,
22017 : ae_int_t optype,
22018 : /* Complex */ ae_matrix* x,
22019 : ae_int_t i2,
22020 : ae_int_t j2,
22021 : ae_state *_state)
22022 : {
22023 : ae_int_t s1;
22024 : ae_int_t s2;
22025 : ae_int_t tsa;
22026 : ae_int_t tsb;
22027 : ae_int_t tscur;
22028 :
22029 :
22030 0 : tsa = matrixtilesizea(_state)/2;
22031 0 : tsb = matrixtilesizeb(_state);
22032 0 : tscur = tsb;
22033 0 : if( imax2(m, n, _state)<=tsb )
22034 : {
22035 0 : tscur = tsa;
22036 : }
22037 0 : ae_assert(tscur>=1, "CMatrixRightTRSM: integrity check failed", _state);
22038 :
22039 : /*
22040 : * Upper level parallelization:
22041 : * * decide whether it is feasible to activate multithreading
22042 : * * perform optionally parallelized splits on M
22043 : */
22044 0 : if( m>=2*tsb&&ae_fp_greater_eq(4*rmul3((double)(m), (double)(n), (double)(n), _state),smpactivationlevel(_state)) )
22045 : {
22046 0 : if( _trypexec_cmatrixrighttrsm(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2, _state) )
22047 : {
22048 0 : return;
22049 : }
22050 : }
22051 0 : if( m>=2*tsb )
22052 : {
22053 :
22054 : /*
22055 : * Split X: X*A = (X1 X2)^T*A
22056 : */
22057 0 : tiledsplit(m, tsb, &s1, &s2, _state);
22058 0 : cmatrixrighttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22059 0 : cmatrixrighttrsm(s2, n, a, i1, j1, isupper, isunit, optype, x, i2+s1, j2, _state);
22060 0 : return;
22061 : }
22062 :
22063 : /*
22064 : * Basecase: either MKL-supported code or ALGLIB basecase code
22065 : */
22066 0 : if( imax2(m, n, _state)<=tsb )
22067 : {
22068 0 : if( cmatrixrighttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) )
22069 : {
22070 0 : return;
22071 : }
22072 : }
22073 0 : if( imax2(m, n, _state)<=tsa )
22074 : {
22075 0 : ablas_cmatrixrighttrsm2(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22076 0 : return;
22077 : }
22078 :
22079 : /*
22080 : * Recursive subdivision
22081 : */
22082 0 : if( m>=n )
22083 : {
22084 :
22085 : /*
22086 : * Split X: X*A = (X1 X2)^T*A
22087 : */
22088 0 : tiledsplit(m, tscur, &s1, &s2, _state);
22089 0 : cmatrixrighttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22090 0 : cmatrixrighttrsm(s2, n, a, i1, j1, isupper, isunit, optype, x, i2+s1, j2, _state);
22091 : }
22092 : else
22093 : {
22094 :
22095 : /*
22096 : * Split A:
22097 : * (A1 A12)
22098 : * X*op(A) = X*op( )
22099 : * ( A2)
22100 : *
22101 : * Different variants depending on
22102 : * IsUpper/OpType combinations
22103 : */
22104 0 : tiledsplit(n, tscur, &s1, &s2, _state);
22105 0 : if( isupper&&optype==0 )
22106 : {
22107 :
22108 : /*
22109 : * (A1 A12)-1
22110 : * X*A^-1 = (X1 X2)*( )
22111 : * ( A2)
22112 : */
22113 0 : cmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22114 0 : cmatrixgemm(m, s2, s1, ae_complex_from_d(-1.0), x, i2, j2, 0, a, i1, j1+s1, 0, ae_complex_from_d(1.0), x, i2, j2+s1, _state);
22115 0 : cmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state);
22116 : }
22117 0 : if( isupper&&optype!=0 )
22118 : {
22119 :
22120 : /*
22121 : * (A1' )-1
22122 : * X*A^-1 = (X1 X2)*( )
22123 : * (A12' A2')
22124 : */
22125 0 : cmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state);
22126 0 : cmatrixgemm(m, s1, s2, ae_complex_from_d(-1.0), x, i2, j2+s1, 0, a, i1, j1+s1, optype, ae_complex_from_d(1.0), x, i2, j2, _state);
22127 0 : cmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22128 : }
22129 0 : if( !isupper&&optype==0 )
22130 : {
22131 :
22132 : /*
22133 : * (A1 )-1
22134 : * X*A^-1 = (X1 X2)*( )
22135 : * (A21 A2)
22136 : */
22137 0 : cmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state);
22138 0 : cmatrixgemm(m, s1, s2, ae_complex_from_d(-1.0), x, i2, j2+s1, 0, a, i1+s1, j1, 0, ae_complex_from_d(1.0), x, i2, j2, _state);
22139 0 : cmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22140 : }
22141 0 : if( !isupper&&optype!=0 )
22142 : {
22143 :
22144 : /*
22145 : * (A1' A21')-1
22146 : * X*A^-1 = (X1 X2)*( )
22147 : * ( A2')
22148 : */
22149 0 : cmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22150 0 : cmatrixgemm(m, s2, s1, ae_complex_from_d(-1.0), x, i2, j2, 0, a, i1+s1, j1, optype, ae_complex_from_d(1.0), x, i2, j2+s1, _state);
22151 0 : cmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state);
22152 : }
22153 : }
22154 : }
22155 :
22156 :
22157 : /*************************************************************************
22158 : Serial stub for GPL edition.
22159 : *************************************************************************/
22160 0 : ae_bool _trypexec_cmatrixrighttrsm(ae_int_t m,
22161 : ae_int_t n,
22162 : /* Complex */ ae_matrix* a,
22163 : ae_int_t i1,
22164 : ae_int_t j1,
22165 : ae_bool isupper,
22166 : ae_bool isunit,
22167 : ae_int_t optype,
22168 : /* Complex */ ae_matrix* x,
22169 : ae_int_t i2,
22170 : ae_int_t j2,
22171 : ae_state *_state)
22172 : {
22173 0 : return ae_false;
22174 : }
22175 :
22176 :
22177 : /*************************************************************************
22178 : This subroutine calculates op(A^-1)*X where:
22179 : * X is MxN general matrix
22180 : * A is MxM upper/lower triangular/unitriangular matrix
22181 : * "op" may be identity transformation, transposition, conjugate transposition
22182 : Multiplication result replaces X.
22183 :
22184 : ! COMMERCIAL EDITION OF ALGLIB:
22185 : !
22186 : ! Commercial Edition of ALGLIB includes following important improvements
22187 : ! of this function:
22188 : ! * high-performance native backend with same C# interface (C# version)
22189 : ! * multithreading support (C++ and C# versions)
22190 : ! * hardware vendor (Intel) implementations of linear algebra primitives
22191 : ! (C++ and C# versions, x86/x64 platform)
22192 : !
22193 : ! We recommend you to read 'Working with commercial version' section of
22194 : ! ALGLIB Reference Manual in order to find out how to use performance-
22195 : ! related features provided by commercial edition of ALGLIB.
22196 :
22197 : INPUT PARAMETERS
22198 : N - matrix size, N>=0
22199 : M - matrix size, N>=0
22200 : A - matrix, actial matrix is stored in A[I1:I1+M-1,J1:J1+M-1]
22201 : I1 - submatrix offset
22202 : J1 - submatrix offset
22203 : IsUpper - whether matrix is upper triangular
22204 : IsUnit - whether matrix is unitriangular
22205 : OpType - transformation type:
22206 : * 0 - no transformation
22207 : * 1 - transposition
22208 : * 2 - conjugate transposition
22209 : X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1]
22210 : I2 - submatrix offset
22211 : J2 - submatrix offset
22212 :
22213 : -- ALGLIB routine --
22214 : 15.12.2009-22.01.2018
22215 : Bochkanov Sergey
22216 : *************************************************************************/
22217 0 : void cmatrixlefttrsm(ae_int_t m,
22218 : ae_int_t n,
22219 : /* Complex */ ae_matrix* a,
22220 : ae_int_t i1,
22221 : ae_int_t j1,
22222 : ae_bool isupper,
22223 : ae_bool isunit,
22224 : ae_int_t optype,
22225 : /* Complex */ ae_matrix* x,
22226 : ae_int_t i2,
22227 : ae_int_t j2,
22228 : ae_state *_state)
22229 : {
22230 : ae_int_t s1;
22231 : ae_int_t s2;
22232 : ae_int_t tsa;
22233 : ae_int_t tsb;
22234 : ae_int_t tscur;
22235 :
22236 :
22237 0 : tsa = matrixtilesizea(_state)/2;
22238 0 : tsb = matrixtilesizeb(_state);
22239 0 : tscur = tsb;
22240 0 : if( imax2(m, n, _state)<=tsb )
22241 : {
22242 0 : tscur = tsa;
22243 : }
22244 0 : ae_assert(tscur>=1, "CMatrixLeftTRSM: integrity check failed", _state);
22245 :
22246 : /*
22247 : * Upper level parallelization:
22248 : * * decide whether it is feasible to activate multithreading
22249 : * * perform optionally parallelized splits on N
22250 : */
22251 0 : if( n>=2*tsb&&ae_fp_greater_eq(4*rmul3((double)(n), (double)(m), (double)(m), _state),smpactivationlevel(_state)) )
22252 : {
22253 0 : if( _trypexec_cmatrixlefttrsm(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2, _state) )
22254 : {
22255 0 : return;
22256 : }
22257 : }
22258 0 : if( n>=2*tsb )
22259 : {
22260 0 : tiledsplit(n, tscur, &s1, &s2, _state);
22261 0 : cmatrixlefttrsm(m, s2, a, i1, j1, isupper, isunit, optype, x, i2, j2+s1, _state);
22262 0 : cmatrixlefttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22263 0 : return;
22264 : }
22265 :
22266 : /*
22267 : * Basecase: either MKL-supported code or ALGLIB basecase code
22268 : */
22269 0 : if( imax2(m, n, _state)<=tsb )
22270 : {
22271 0 : if( cmatrixlefttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) )
22272 : {
22273 0 : return;
22274 : }
22275 : }
22276 0 : if( imax2(m, n, _state)<=tsa )
22277 : {
22278 0 : ablas_cmatrixlefttrsm2(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22279 0 : return;
22280 : }
22281 :
22282 : /*
22283 : * Recursive subdivision
22284 : */
22285 0 : if( n>=m )
22286 : {
22287 :
22288 : /*
22289 : * Split X: op(A)^-1*X = op(A)^-1*(X1 X2)
22290 : */
22291 0 : tiledsplit(n, tscur, &s1, &s2, _state);
22292 0 : cmatrixlefttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22293 0 : cmatrixlefttrsm(m, s2, a, i1, j1, isupper, isunit, optype, x, i2, j2+s1, _state);
22294 : }
22295 : else
22296 : {
22297 :
22298 : /*
22299 : * Split A
22300 : */
22301 0 : tiledsplit(m, tscur, &s1, &s2, _state);
22302 0 : if( isupper&&optype==0 )
22303 : {
22304 :
22305 : /*
22306 : * (A1 A12)-1 ( X1 )
22307 : * A^-1*X* = ( ) *( )
22308 : * ( A2) ( X2 )
22309 : */
22310 0 : cmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state);
22311 0 : cmatrixgemm(s1, n, s2, ae_complex_from_d(-1.0), a, i1, j1+s1, 0, x, i2+s1, j2, 0, ae_complex_from_d(1.0), x, i2, j2, _state);
22312 0 : cmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22313 : }
22314 0 : if( isupper&&optype!=0 )
22315 : {
22316 :
22317 : /*
22318 : * (A1' )-1 ( X1 )
22319 : * A^-1*X = ( ) *( )
22320 : * (A12' A2') ( X2 )
22321 : */
22322 0 : cmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22323 0 : cmatrixgemm(s2, n, s1, ae_complex_from_d(-1.0), a, i1, j1+s1, optype, x, i2, j2, 0, ae_complex_from_d(1.0), x, i2+s1, j2, _state);
22324 0 : cmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state);
22325 : }
22326 0 : if( !isupper&&optype==0 )
22327 : {
22328 :
22329 : /*
22330 : * (A1 )-1 ( X1 )
22331 : * A^-1*X = ( ) *( )
22332 : * (A21 A2) ( X2 )
22333 : */
22334 0 : cmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22335 0 : cmatrixgemm(s2, n, s1, ae_complex_from_d(-1.0), a, i1+s1, j1, 0, x, i2, j2, 0, ae_complex_from_d(1.0), x, i2+s1, j2, _state);
22336 0 : cmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state);
22337 : }
22338 0 : if( !isupper&&optype!=0 )
22339 : {
22340 :
22341 : /*
22342 : * (A1' A21')-1 ( X1 )
22343 : * A^-1*X = ( ) *( )
22344 : * ( A2') ( X2 )
22345 : */
22346 0 : cmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state);
22347 0 : cmatrixgemm(s1, n, s2, ae_complex_from_d(-1.0), a, i1+s1, j1, optype, x, i2+s1, j2, 0, ae_complex_from_d(1.0), x, i2, j2, _state);
22348 0 : cmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22349 : }
22350 : }
22351 : }
22352 :
22353 :
22354 : /*************************************************************************
22355 : Serial stub for GPL edition.
22356 : *************************************************************************/
22357 0 : ae_bool _trypexec_cmatrixlefttrsm(ae_int_t m,
22358 : ae_int_t n,
22359 : /* Complex */ ae_matrix* a,
22360 : ae_int_t i1,
22361 : ae_int_t j1,
22362 : ae_bool isupper,
22363 : ae_bool isunit,
22364 : ae_int_t optype,
22365 : /* Complex */ ae_matrix* x,
22366 : ae_int_t i2,
22367 : ae_int_t j2,
22368 : ae_state *_state)
22369 : {
22370 0 : return ae_false;
22371 : }
22372 :
22373 :
22374 : /*************************************************************************
22375 : This subroutine calculates X*op(A^-1) where:
22376 : * X is MxN general matrix
22377 : * A is NxN upper/lower triangular/unitriangular matrix
22378 : * "op" may be identity transformation, transposition
22379 : Multiplication result replaces X.
22380 :
22381 : ! COMMERCIAL EDITION OF ALGLIB:
22382 : !
22383 : ! Commercial Edition of ALGLIB includes following important improvements
22384 : ! of this function:
22385 : ! * high-performance native backend with same C# interface (C# version)
22386 : ! * multithreading support (C++ and C# versions)
22387 : ! * hardware vendor (Intel) implementations of linear algebra primitives
22388 : ! (C++ and C# versions, x86/x64 platform)
22389 : !
22390 : ! We recommend you to read 'Working with commercial version' section of
22391 : ! ALGLIB Reference Manual in order to find out how to use performance-
22392 : ! related features provided by commercial edition of ALGLIB.
22393 :
22394 : INPUT PARAMETERS
22395 : N - matrix size, N>=0
22396 : M - matrix size, N>=0
22397 : A - matrix, actial matrix is stored in A[I1:I1+N-1,J1:J1+N-1]
22398 : I1 - submatrix offset
22399 : J1 - submatrix offset
22400 : IsUpper - whether matrix is upper triangular
22401 : IsUnit - whether matrix is unitriangular
22402 : OpType - transformation type:
22403 : * 0 - no transformation
22404 : * 1 - transposition
22405 : X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1]
22406 : I2 - submatrix offset
22407 : J2 - submatrix offset
22408 :
22409 : -- ALGLIB routine --
22410 : 15.12.2009-22.01.2018
22411 : Bochkanov Sergey
22412 : *************************************************************************/
22413 0 : void rmatrixrighttrsm(ae_int_t m,
22414 : ae_int_t n,
22415 : /* Real */ ae_matrix* a,
22416 : ae_int_t i1,
22417 : ae_int_t j1,
22418 : ae_bool isupper,
22419 : ae_bool isunit,
22420 : ae_int_t optype,
22421 : /* Real */ ae_matrix* x,
22422 : ae_int_t i2,
22423 : ae_int_t j2,
22424 : ae_state *_state)
22425 : {
22426 : ae_int_t s1;
22427 : ae_int_t s2;
22428 : ae_int_t tsa;
22429 : ae_int_t tsb;
22430 : ae_int_t tscur;
22431 :
22432 :
22433 0 : tsa = matrixtilesizea(_state);
22434 0 : tsb = matrixtilesizeb(_state);
22435 0 : tscur = tsb;
22436 0 : if( imax2(m, n, _state)<=tsb )
22437 : {
22438 0 : tscur = tsa;
22439 : }
22440 0 : ae_assert(tscur>=1, "RMatrixRightTRSM: integrity check failed", _state);
22441 :
22442 : /*
22443 : * Upper level parallelization:
22444 : * * decide whether it is feasible to activate multithreading
22445 : * * perform optionally parallelized splits on M
22446 : */
22447 0 : if( m>=2*tsb&&ae_fp_greater_eq(rmul3((double)(m), (double)(n), (double)(n), _state),smpactivationlevel(_state)) )
22448 : {
22449 0 : if( _trypexec_rmatrixrighttrsm(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2, _state) )
22450 : {
22451 0 : return;
22452 : }
22453 : }
22454 0 : if( m>=2*tsb )
22455 : {
22456 :
22457 : /*
22458 : * Split X: X*A = (X1 X2)^T*A
22459 : */
22460 0 : tiledsplit(m, tsb, &s1, &s2, _state);
22461 0 : rmatrixrighttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22462 0 : rmatrixrighttrsm(s2, n, a, i1, j1, isupper, isunit, optype, x, i2+s1, j2, _state);
22463 0 : return;
22464 : }
22465 :
22466 : /*
22467 : * Basecase: MKL or ALGLIB code
22468 : */
22469 0 : if( imax2(m, n, _state)<=tsb )
22470 : {
22471 0 : if( rmatrixrighttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) )
22472 : {
22473 0 : return;
22474 : }
22475 : }
22476 0 : if( imax2(m, n, _state)<=tsa )
22477 : {
22478 0 : ablas_rmatrixrighttrsm2(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22479 0 : return;
22480 : }
22481 :
22482 : /*
22483 : * Recursive subdivision
22484 : */
22485 0 : if( m>=n )
22486 : {
22487 :
22488 : /*
22489 : * Split X: X*A = (X1 X2)^T*A
22490 : */
22491 0 : tiledsplit(m, tscur, &s1, &s2, _state);
22492 0 : rmatrixrighttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22493 0 : rmatrixrighttrsm(s2, n, a, i1, j1, isupper, isunit, optype, x, i2+s1, j2, _state);
22494 : }
22495 : else
22496 : {
22497 :
22498 : /*
22499 : * Split A:
22500 : * (A1 A12)
22501 : * X*op(A) = X*op( )
22502 : * ( A2)
22503 : *
22504 : * Different variants depending on
22505 : * IsUpper/OpType combinations
22506 : */
22507 0 : tiledsplit(n, tscur, &s1, &s2, _state);
22508 0 : if( isupper&&optype==0 )
22509 : {
22510 :
22511 : /*
22512 : * (A1 A12)-1
22513 : * X*A^-1 = (X1 X2)*( )
22514 : * ( A2)
22515 : */
22516 0 : rmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22517 0 : rmatrixgemm(m, s2, s1, -1.0, x, i2, j2, 0, a, i1, j1+s1, 0, 1.0, x, i2, j2+s1, _state);
22518 0 : rmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state);
22519 : }
22520 0 : if( isupper&&optype!=0 )
22521 : {
22522 :
22523 : /*
22524 : * (A1' )-1
22525 : * X*A^-1 = (X1 X2)*( )
22526 : * (A12' A2')
22527 : */
22528 0 : rmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state);
22529 0 : rmatrixgemm(m, s1, s2, -1.0, x, i2, j2+s1, 0, a, i1, j1+s1, optype, 1.0, x, i2, j2, _state);
22530 0 : rmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22531 : }
22532 0 : if( !isupper&&optype==0 )
22533 : {
22534 :
22535 : /*
22536 : * (A1 )-1
22537 : * X*A^-1 = (X1 X2)*( )
22538 : * (A21 A2)
22539 : */
22540 0 : rmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state);
22541 0 : rmatrixgemm(m, s1, s2, -1.0, x, i2, j2+s1, 0, a, i1+s1, j1, 0, 1.0, x, i2, j2, _state);
22542 0 : rmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22543 : }
22544 0 : if( !isupper&&optype!=0 )
22545 : {
22546 :
22547 : /*
22548 : * (A1' A21')-1
22549 : * X*A^-1 = (X1 X2)*( )
22550 : * ( A2')
22551 : */
22552 0 : rmatrixrighttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22553 0 : rmatrixgemm(m, s2, s1, -1.0, x, i2, j2, 0, a, i1+s1, j1, optype, 1.0, x, i2, j2+s1, _state);
22554 0 : rmatrixrighttrsm(m, s2, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2, j2+s1, _state);
22555 : }
22556 : }
22557 : }
22558 :
22559 :
22560 : /*************************************************************************
22561 : Serial stub for GPL edition.
22562 : *************************************************************************/
22563 0 : ae_bool _trypexec_rmatrixrighttrsm(ae_int_t m,
22564 : ae_int_t n,
22565 : /* Real */ ae_matrix* a,
22566 : ae_int_t i1,
22567 : ae_int_t j1,
22568 : ae_bool isupper,
22569 : ae_bool isunit,
22570 : ae_int_t optype,
22571 : /* Real */ ae_matrix* x,
22572 : ae_int_t i2,
22573 : ae_int_t j2,
22574 : ae_state *_state)
22575 : {
22576 0 : return ae_false;
22577 : }
22578 :
22579 :
22580 : /*************************************************************************
22581 : This subroutine calculates op(A^-1)*X where:
22582 : * X is MxN general matrix
22583 : * A is MxM upper/lower triangular/unitriangular matrix
22584 : * "op" may be identity transformation, transposition
22585 : Multiplication result replaces X.
22586 :
22587 : ! COMMERCIAL EDITION OF ALGLIB:
22588 : !
22589 : ! Commercial Edition of ALGLIB includes following important improvements
22590 : ! of this function:
22591 : ! * high-performance native backend with same C# interface (C# version)
22592 : ! * multithreading support (C++ and C# versions)
22593 : ! * hardware vendor (Intel) implementations of linear algebra primitives
22594 : ! (C++ and C# versions, x86/x64 platform)
22595 : !
22596 : ! We recommend you to read 'Working with commercial version' section of
22597 : ! ALGLIB Reference Manual in order to find out how to use performance-
22598 : ! related features provided by commercial edition of ALGLIB.
22599 :
22600 : INPUT PARAMETERS
22601 : N - matrix size, N>=0
22602 : M - matrix size, N>=0
22603 : A - matrix, actial matrix is stored in A[I1:I1+M-1,J1:J1+M-1]
22604 : I1 - submatrix offset
22605 : J1 - submatrix offset
22606 : IsUpper - whether matrix is upper triangular
22607 : IsUnit - whether matrix is unitriangular
22608 : OpType - transformation type:
22609 : * 0 - no transformation
22610 : * 1 - transposition
22611 : X - matrix, actial matrix is stored in X[I2:I2+M-1,J2:J2+N-1]
22612 : I2 - submatrix offset
22613 : J2 - submatrix offset
22614 :
22615 : -- ALGLIB routine --
22616 : 15.12.2009-22.01.2018
22617 : Bochkanov Sergey
22618 : *************************************************************************/
22619 0 : void rmatrixlefttrsm(ae_int_t m,
22620 : ae_int_t n,
22621 : /* Real */ ae_matrix* a,
22622 : ae_int_t i1,
22623 : ae_int_t j1,
22624 : ae_bool isupper,
22625 : ae_bool isunit,
22626 : ae_int_t optype,
22627 : /* Real */ ae_matrix* x,
22628 : ae_int_t i2,
22629 : ae_int_t j2,
22630 : ae_state *_state)
22631 : {
22632 : ae_int_t s1;
22633 : ae_int_t s2;
22634 : ae_int_t tsa;
22635 : ae_int_t tsb;
22636 : ae_int_t tscur;
22637 :
22638 :
22639 0 : tsa = matrixtilesizea(_state);
22640 0 : tsb = matrixtilesizeb(_state);
22641 0 : tscur = tsb;
22642 0 : if( imax2(m, n, _state)<=tsb )
22643 : {
22644 0 : tscur = tsa;
22645 : }
22646 0 : ae_assert(tscur>=1, "RMatrixLeftTRSMRec: integrity check failed", _state);
22647 :
22648 : /*
22649 : * Upper level parallelization:
22650 : * * decide whether it is feasible to activate multithreading
22651 : * * perform optionally parallelized splits on N
22652 : */
22653 0 : if( n>=2*tsb&&ae_fp_greater_eq(rmul3((double)(n), (double)(m), (double)(m), _state),smpactivationlevel(_state)) )
22654 : {
22655 0 : if( _trypexec_rmatrixlefttrsm(m,n,a,i1,j1,isupper,isunit,optype,x,i2,j2, _state) )
22656 : {
22657 0 : return;
22658 : }
22659 : }
22660 0 : if( n>=2*tsb )
22661 : {
22662 0 : tiledsplit(n, tscur, &s1, &s2, _state);
22663 0 : rmatrixlefttrsm(m, s2, a, i1, j1, isupper, isunit, optype, x, i2, j2+s1, _state);
22664 0 : rmatrixlefttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22665 0 : return;
22666 : }
22667 :
22668 : /*
22669 : * Basecase: MKL or ALGLIB code
22670 : */
22671 0 : if( imax2(m, n, _state)<=tsb )
22672 : {
22673 0 : if( rmatrixlefttrsmmkl(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) )
22674 : {
22675 0 : return;
22676 : }
22677 : }
22678 0 : if( imax2(m, n, _state)<=tsa )
22679 : {
22680 0 : ablas_rmatrixlefttrsm2(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22681 0 : return;
22682 : }
22683 :
22684 : /*
22685 : * Recursive subdivision
22686 : */
22687 0 : if( n>=m )
22688 : {
22689 :
22690 : /*
22691 : * Split X: op(A)^-1*X = op(A)^-1*(X1 X2)
22692 : */
22693 0 : tiledsplit(n, tscur, &s1, &s2, _state);
22694 0 : rmatrixlefttrsm(m, s1, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22695 0 : rmatrixlefttrsm(m, s2, a, i1, j1, isupper, isunit, optype, x, i2, j2+s1, _state);
22696 : }
22697 : else
22698 : {
22699 :
22700 : /*
22701 : * Split A
22702 : */
22703 0 : tiledsplit(m, tscur, &s1, &s2, _state);
22704 0 : if( isupper&&optype==0 )
22705 : {
22706 :
22707 : /*
22708 : * (A1 A12)-1 ( X1 )
22709 : * A^-1*X* = ( ) *( )
22710 : * ( A2) ( X2 )
22711 : */
22712 0 : rmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state);
22713 0 : rmatrixgemm(s1, n, s2, -1.0, a, i1, j1+s1, 0, x, i2+s1, j2, 0, 1.0, x, i2, j2, _state);
22714 0 : rmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22715 : }
22716 0 : if( isupper&&optype!=0 )
22717 : {
22718 :
22719 : /*
22720 : * (A1' )-1 ( X1 )
22721 : * A^-1*X = ( ) *( )
22722 : * (A12' A2') ( X2 )
22723 : */
22724 0 : rmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22725 0 : rmatrixgemm(s2, n, s1, -1.0, a, i1, j1+s1, optype, x, i2, j2, 0, 1.0, x, i2+s1, j2, _state);
22726 0 : rmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state);
22727 : }
22728 0 : if( !isupper&&optype==0 )
22729 : {
22730 :
22731 : /*
22732 : * (A1 )-1 ( X1 )
22733 : * A^-1*X = ( ) *( )
22734 : * (A21 A2) ( X2 )
22735 : */
22736 0 : rmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22737 0 : rmatrixgemm(s2, n, s1, -1.0, a, i1+s1, j1, 0, x, i2, j2, 0, 1.0, x, i2+s1, j2, _state);
22738 0 : rmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state);
22739 : }
22740 0 : if( !isupper&&optype!=0 )
22741 : {
22742 :
22743 : /*
22744 : * (A1' A21')-1 ( X1 )
22745 : * A^-1*X = ( ) *( )
22746 : * ( A2') ( X2 )
22747 : */
22748 0 : rmatrixlefttrsm(s2, n, a, i1+s1, j1+s1, isupper, isunit, optype, x, i2+s1, j2, _state);
22749 0 : rmatrixgemm(s1, n, s2, -1.0, a, i1+s1, j1, optype, x, i2+s1, j2, 0, 1.0, x, i2, j2, _state);
22750 0 : rmatrixlefttrsm(s1, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state);
22751 : }
22752 : }
22753 : }
22754 :
22755 :
22756 : /*************************************************************************
22757 : Serial stub for GPL edition.
22758 : *************************************************************************/
22759 0 : ae_bool _trypexec_rmatrixlefttrsm(ae_int_t m,
22760 : ae_int_t n,
22761 : /* Real */ ae_matrix* a,
22762 : ae_int_t i1,
22763 : ae_int_t j1,
22764 : ae_bool isupper,
22765 : ae_bool isunit,
22766 : ae_int_t optype,
22767 : /* Real */ ae_matrix* x,
22768 : ae_int_t i2,
22769 : ae_int_t j2,
22770 : ae_state *_state)
22771 : {
22772 0 : return ae_false;
22773 : }
22774 :
22775 :
22776 : /*************************************************************************
22777 : This subroutine calculates C=alpha*A*A^H+beta*C or C=alpha*A^H*A+beta*C
22778 : where:
22779 : * C is NxN Hermitian matrix given by its upper/lower triangle
22780 : * A is NxK matrix when A*A^H is calculated, KxN matrix otherwise
22781 :
22782 : Additional info:
22783 : * multiplication result replaces C. If Beta=0, C elements are not used in
22784 : calculations (not multiplied by zero - just not referenced)
22785 : * if Alpha=0, A is not used (not multiplied by zero - just not referenced)
22786 : * if both Beta and Alpha are zero, C is filled by zeros.
22787 :
22788 : ! COMMERCIAL EDITION OF ALGLIB:
22789 : !
22790 : ! Commercial Edition of ALGLIB includes following important improvements
22791 : ! of this function:
22792 : ! * high-performance native backend with same C# interface (C# version)
22793 : ! * multithreading support (C++ and C# versions)
22794 : ! * hardware vendor (Intel) implementations of linear algebra primitives
22795 : ! (C++ and C# versions, x86/x64 platform)
22796 : !
22797 : ! We recommend you to read 'Working with commercial version' section of
22798 : ! ALGLIB Reference Manual in order to find out how to use performance-
22799 : ! related features provided by commercial edition of ALGLIB.
22800 :
22801 : INPUT PARAMETERS
22802 : N - matrix size, N>=0
22803 : K - matrix size, K>=0
22804 : Alpha - coefficient
22805 : A - matrix
22806 : IA - submatrix offset (row index)
22807 : JA - submatrix offset (column index)
22808 : OpTypeA - multiplication type:
22809 : * 0 - A*A^H is calculated
22810 : * 2 - A^H*A is calculated
22811 : Beta - coefficient
22812 : C - preallocated input/output matrix
22813 : IC - submatrix offset (row index)
22814 : JC - submatrix offset (column index)
22815 : IsUpper - whether upper or lower triangle of C is updated;
22816 : this function updates only one half of C, leaving
22817 : other half unchanged (not referenced at all).
22818 :
22819 : -- ALGLIB routine --
22820 : 16.12.2009-22.01.2018
22821 : Bochkanov Sergey
22822 : *************************************************************************/
22823 0 : void cmatrixherk(ae_int_t n,
22824 : ae_int_t k,
22825 : double alpha,
22826 : /* Complex */ ae_matrix* a,
22827 : ae_int_t ia,
22828 : ae_int_t ja,
22829 : ae_int_t optypea,
22830 : double beta,
22831 : /* Complex */ ae_matrix* c,
22832 : ae_int_t ic,
22833 : ae_int_t jc,
22834 : ae_bool isupper,
22835 : ae_state *_state)
22836 : {
22837 : ae_int_t s1;
22838 : ae_int_t s2;
22839 : ae_int_t tsa;
22840 : ae_int_t tsb;
22841 : ae_int_t tscur;
22842 :
22843 :
22844 0 : tsa = matrixtilesizea(_state)/2;
22845 0 : tsb = matrixtilesizeb(_state);
22846 0 : tscur = tsb;
22847 0 : if( imax2(n, k, _state)<=tsb )
22848 : {
22849 0 : tscur = tsa;
22850 : }
22851 0 : ae_assert(tscur>=1, "CMatrixHERK: integrity check failed", _state);
22852 :
22853 : /*
22854 : * Decide whether it is feasible to activate multithreading
22855 : */
22856 0 : if( n>=2*tsb&&ae_fp_greater_eq(8*rmul3((double)(k), (double)(n), (double)(n), _state)/2,smpactivationlevel(_state)) )
22857 : {
22858 0 : if( _trypexec_cmatrixherk(n,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isupper, _state) )
22859 : {
22860 0 : return;
22861 : }
22862 : }
22863 :
22864 : /*
22865 : * Use MKL or ALGLIB basecase code
22866 : */
22867 0 : if( imax2(n, k, _state)<=tsb )
22868 : {
22869 0 : if( cmatrixherkmkl(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state) )
22870 : {
22871 0 : return;
22872 : }
22873 : }
22874 0 : if( imax2(n, k, _state)<=tsa )
22875 : {
22876 0 : ablas_cmatrixherk2(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
22877 0 : return;
22878 : }
22879 :
22880 : /*
22881 : * Recursive division of the problem
22882 : */
22883 0 : if( k>=n )
22884 : {
22885 :
22886 : /*
22887 : * Split K
22888 : */
22889 0 : tiledsplit(k, tscur, &s1, &s2, _state);
22890 0 : if( optypea==0 )
22891 : {
22892 0 : cmatrixherk(n, s1, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
22893 0 : cmatrixherk(n, s2, alpha, a, ia, ja+s1, optypea, 1.0, c, ic, jc, isupper, _state);
22894 : }
22895 : else
22896 : {
22897 0 : cmatrixherk(n, s1, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
22898 0 : cmatrixherk(n, s2, alpha, a, ia+s1, ja, optypea, 1.0, c, ic, jc, isupper, _state);
22899 : }
22900 : }
22901 : else
22902 : {
22903 :
22904 : /*
22905 : * Split N
22906 : */
22907 0 : tiledsplit(n, tscur, &s1, &s2, _state);
22908 0 : if( optypea==0&&isupper )
22909 : {
22910 0 : cmatrixherk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
22911 0 : cmatrixherk(s2, k, alpha, a, ia+s1, ja, optypea, beta, c, ic+s1, jc+s1, isupper, _state);
22912 0 : cmatrixgemm(s1, s2, k, ae_complex_from_d(alpha), a, ia, ja, 0, a, ia+s1, ja, 2, ae_complex_from_d(beta), c, ic, jc+s1, _state);
22913 : }
22914 0 : if( optypea==0&&!isupper )
22915 : {
22916 0 : cmatrixherk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
22917 0 : cmatrixherk(s2, k, alpha, a, ia+s1, ja, optypea, beta, c, ic+s1, jc+s1, isupper, _state);
22918 0 : cmatrixgemm(s2, s1, k, ae_complex_from_d(alpha), a, ia+s1, ja, 0, a, ia, ja, 2, ae_complex_from_d(beta), c, ic+s1, jc, _state);
22919 : }
22920 0 : if( optypea!=0&&isupper )
22921 : {
22922 0 : cmatrixherk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
22923 0 : cmatrixherk(s2, k, alpha, a, ia, ja+s1, optypea, beta, c, ic+s1, jc+s1, isupper, _state);
22924 0 : cmatrixgemm(s1, s2, k, ae_complex_from_d(alpha), a, ia, ja, 2, a, ia, ja+s1, 0, ae_complex_from_d(beta), c, ic, jc+s1, _state);
22925 : }
22926 0 : if( optypea!=0&&!isupper )
22927 : {
22928 0 : cmatrixherk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
22929 0 : cmatrixherk(s2, k, alpha, a, ia, ja+s1, optypea, beta, c, ic+s1, jc+s1, isupper, _state);
22930 0 : cmatrixgemm(s2, s1, k, ae_complex_from_d(alpha), a, ia, ja+s1, 2, a, ia, ja, 0, ae_complex_from_d(beta), c, ic+s1, jc, _state);
22931 : }
22932 : }
22933 : }
22934 :
22935 :
22936 : /*************************************************************************
22937 : Serial stub for GPL edition.
22938 : *************************************************************************/
22939 0 : ae_bool _trypexec_cmatrixherk(ae_int_t n,
22940 : ae_int_t k,
22941 : double alpha,
22942 : /* Complex */ ae_matrix* a,
22943 : ae_int_t ia,
22944 : ae_int_t ja,
22945 : ae_int_t optypea,
22946 : double beta,
22947 : /* Complex */ ae_matrix* c,
22948 : ae_int_t ic,
22949 : ae_int_t jc,
22950 : ae_bool isupper,
22951 : ae_state *_state)
22952 : {
22953 0 : return ae_false;
22954 : }
22955 :
22956 :
22957 : /*************************************************************************
22958 : This subroutine calculates C=alpha*A*A^T+beta*C or C=alpha*A^T*A+beta*C
22959 : where:
22960 : * C is NxN symmetric matrix given by its upper/lower triangle
22961 : * A is NxK matrix when A*A^T is calculated, KxN matrix otherwise
22962 :
22963 : Additional info:
22964 : * multiplication result replaces C. If Beta=0, C elements are not used in
22965 : calculations (not multiplied by zero - just not referenced)
22966 : * if Alpha=0, A is not used (not multiplied by zero - just not referenced)
22967 : * if both Beta and Alpha are zero, C is filled by zeros.
22968 :
22969 : ! COMMERCIAL EDITION OF ALGLIB:
22970 : !
22971 : ! Commercial Edition of ALGLIB includes following important improvements
22972 : ! of this function:
22973 : ! * high-performance native backend with same C# interface (C# version)
22974 : ! * multithreading support (C++ and C# versions)
22975 : ! * hardware vendor (Intel) implementations of linear algebra primitives
22976 : ! (C++ and C# versions, x86/x64 platform)
22977 : !
22978 : ! We recommend you to read 'Working with commercial version' section of
22979 : ! ALGLIB Reference Manual in order to find out how to use performance-
22980 : ! related features provided by commercial edition of ALGLIB.
22981 :
22982 : INPUT PARAMETERS
22983 : N - matrix size, N>=0
22984 : K - matrix size, K>=0
22985 : Alpha - coefficient
22986 : A - matrix
22987 : IA - submatrix offset (row index)
22988 : JA - submatrix offset (column index)
22989 : OpTypeA - multiplication type:
22990 : * 0 - A*A^T is calculated
22991 : * 2 - A^T*A is calculated
22992 : Beta - coefficient
22993 : C - preallocated input/output matrix
22994 : IC - submatrix offset (row index)
22995 : JC - submatrix offset (column index)
22996 : IsUpper - whether C is upper triangular or lower triangular
22997 :
22998 : -- ALGLIB routine --
22999 : 16.12.2009-22.01.2018
23000 : Bochkanov Sergey
23001 : *************************************************************************/
23002 0 : void rmatrixsyrk(ae_int_t n,
23003 : ae_int_t k,
23004 : double alpha,
23005 : /* Real */ ae_matrix* a,
23006 : ae_int_t ia,
23007 : ae_int_t ja,
23008 : ae_int_t optypea,
23009 : double beta,
23010 : /* Real */ ae_matrix* c,
23011 : ae_int_t ic,
23012 : ae_int_t jc,
23013 : ae_bool isupper,
23014 : ae_state *_state)
23015 : {
23016 : ae_int_t s1;
23017 : ae_int_t s2;
23018 : ae_int_t tsa;
23019 : ae_int_t tsb;
23020 : ae_int_t tscur;
23021 :
23022 :
23023 0 : tsa = matrixtilesizea(_state);
23024 0 : tsb = matrixtilesizeb(_state);
23025 0 : tscur = tsb;
23026 0 : if( imax2(n, k, _state)<=tsb )
23027 : {
23028 0 : tscur = tsa;
23029 : }
23030 0 : ae_assert(tscur>=1, "RMatrixSYRK: integrity check failed", _state);
23031 :
23032 : /*
23033 : * Decide whether it is feasible to activate multithreading
23034 : */
23035 0 : if( n>=2*tsb&&ae_fp_greater_eq(2*rmul3((double)(k), (double)(n), (double)(n), _state)/2,smpactivationlevel(_state)) )
23036 : {
23037 0 : if( _trypexec_rmatrixsyrk(n,k,alpha,a,ia,ja,optypea,beta,c,ic,jc,isupper, _state) )
23038 : {
23039 0 : return;
23040 : }
23041 : }
23042 :
23043 : /*
23044 : * Use MKL or generic basecase code
23045 : */
23046 0 : if( imax2(n, k, _state)<=tsb )
23047 : {
23048 0 : if( rmatrixsyrkmkl(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state) )
23049 : {
23050 0 : return;
23051 : }
23052 : }
23053 0 : if( imax2(n, k, _state)<=tsa )
23054 : {
23055 0 : ablas_rmatrixsyrk2(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
23056 0 : return;
23057 : }
23058 :
23059 : /*
23060 : * Recursive subdivision of the problem
23061 : */
23062 0 : if( k>=n )
23063 : {
23064 :
23065 : /*
23066 : * Split K
23067 : */
23068 0 : tiledsplit(k, tscur, &s1, &s2, _state);
23069 0 : if( optypea==0 )
23070 : {
23071 0 : rmatrixsyrk(n, s1, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
23072 0 : rmatrixsyrk(n, s2, alpha, a, ia, ja+s1, optypea, 1.0, c, ic, jc, isupper, _state);
23073 : }
23074 : else
23075 : {
23076 0 : rmatrixsyrk(n, s1, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
23077 0 : rmatrixsyrk(n, s2, alpha, a, ia+s1, ja, optypea, 1.0, c, ic, jc, isupper, _state);
23078 : }
23079 : }
23080 : else
23081 : {
23082 :
23083 : /*
23084 : * Split N
23085 : */
23086 0 : tiledsplit(n, tscur, &s1, &s2, _state);
23087 0 : if( optypea==0&&isupper )
23088 : {
23089 0 : rmatrixsyrk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
23090 0 : rmatrixsyrk(s2, k, alpha, a, ia+s1, ja, optypea, beta, c, ic+s1, jc+s1, isupper, _state);
23091 0 : rmatrixgemm(s1, s2, k, alpha, a, ia, ja, 0, a, ia+s1, ja, 1, beta, c, ic, jc+s1, _state);
23092 : }
23093 0 : if( optypea==0&&!isupper )
23094 : {
23095 0 : rmatrixsyrk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
23096 0 : rmatrixsyrk(s2, k, alpha, a, ia+s1, ja, optypea, beta, c, ic+s1, jc+s1, isupper, _state);
23097 0 : rmatrixgemm(s2, s1, k, alpha, a, ia+s1, ja, 0, a, ia, ja, 1, beta, c, ic+s1, jc, _state);
23098 : }
23099 0 : if( optypea!=0&&isupper )
23100 : {
23101 0 : rmatrixsyrk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
23102 0 : rmatrixsyrk(s2, k, alpha, a, ia, ja+s1, optypea, beta, c, ic+s1, jc+s1, isupper, _state);
23103 0 : rmatrixgemm(s1, s2, k, alpha, a, ia, ja, 1, a, ia, ja+s1, 0, beta, c, ic, jc+s1, _state);
23104 : }
23105 0 : if( optypea!=0&&!isupper )
23106 : {
23107 0 : rmatrixsyrk(s1, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
23108 0 : rmatrixsyrk(s2, k, alpha, a, ia, ja+s1, optypea, beta, c, ic+s1, jc+s1, isupper, _state);
23109 0 : rmatrixgemm(s2, s1, k, alpha, a, ia, ja+s1, 1, a, ia, ja, 0, beta, c, ic+s1, jc, _state);
23110 : }
23111 : }
23112 : }
23113 :
23114 :
23115 : /*************************************************************************
23116 : Serial stub for GPL edition.
23117 : *************************************************************************/
23118 0 : ae_bool _trypexec_rmatrixsyrk(ae_int_t n,
23119 : ae_int_t k,
23120 : double alpha,
23121 : /* Real */ ae_matrix* a,
23122 : ae_int_t ia,
23123 : ae_int_t ja,
23124 : ae_int_t optypea,
23125 : double beta,
23126 : /* Real */ ae_matrix* c,
23127 : ae_int_t ic,
23128 : ae_int_t jc,
23129 : ae_bool isupper,
23130 : ae_state *_state)
23131 : {
23132 0 : return ae_false;
23133 : }
23134 :
23135 :
23136 : /*************************************************************************
23137 : This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where:
23138 : * C is MxN general matrix
23139 : * op1(A) is MxK matrix
23140 : * op2(B) is KxN matrix
23141 : * "op" may be identity transformation, transposition, conjugate transposition
23142 :
23143 : Additional info:
23144 : * cache-oblivious algorithm is used.
23145 : * multiplication result replaces C. If Beta=0, C elements are not used in
23146 : calculations (not multiplied by zero - just not referenced)
23147 : * if Alpha=0, A is not used (not multiplied by zero - just not referenced)
23148 : * if both Beta and Alpha are zero, C is filled by zeros.
23149 :
23150 : ! COMMERCIAL EDITION OF ALGLIB:
23151 : !
23152 : ! Commercial Edition of ALGLIB includes following important improvements
23153 : ! of this function:
23154 : ! * high-performance native backend with same C# interface (C# version)
23155 : ! * multithreading support (C++ and C# versions)
23156 : ! * hardware vendor (Intel) implementations of linear algebra primitives
23157 : ! (C++ and C# versions, x86/x64 platform)
23158 : !
23159 : ! We recommend you to read 'Working with commercial version' section of
23160 : ! ALGLIB Reference Manual in order to find out how to use performance-
23161 : ! related features provided by commercial edition of ALGLIB.
23162 :
23163 : IMPORTANT:
23164 :
23165 : This function does NOT preallocate output matrix C, it MUST be preallocated
23166 : by caller prior to calling this function. In case C does not have enough
23167 : space to store result, exception will be generated.
23168 :
23169 : INPUT PARAMETERS
23170 : M - matrix size, M>0
23171 : N - matrix size, N>0
23172 : K - matrix size, K>0
23173 : Alpha - coefficient
23174 : A - matrix
23175 : IA - submatrix offset
23176 : JA - submatrix offset
23177 : OpTypeA - transformation type:
23178 : * 0 - no transformation
23179 : * 1 - transposition
23180 : * 2 - conjugate transposition
23181 : B - matrix
23182 : IB - submatrix offset
23183 : JB - submatrix offset
23184 : OpTypeB - transformation type:
23185 : * 0 - no transformation
23186 : * 1 - transposition
23187 : * 2 - conjugate transposition
23188 : Beta - coefficient
23189 : C - matrix (PREALLOCATED, large enough to store result)
23190 : IC - submatrix offset
23191 : JC - submatrix offset
23192 :
23193 : -- ALGLIB routine --
23194 : 2009-2019
23195 : Bochkanov Sergey
23196 : *************************************************************************/
23197 0 : void cmatrixgemm(ae_int_t m,
23198 : ae_int_t n,
23199 : ae_int_t k,
23200 : ae_complex alpha,
23201 : /* Complex */ ae_matrix* a,
23202 : ae_int_t ia,
23203 : ae_int_t ja,
23204 : ae_int_t optypea,
23205 : /* Complex */ ae_matrix* b,
23206 : ae_int_t ib,
23207 : ae_int_t jb,
23208 : ae_int_t optypeb,
23209 : ae_complex beta,
23210 : /* Complex */ ae_matrix* c,
23211 : ae_int_t ic,
23212 : ae_int_t jc,
23213 : ae_state *_state)
23214 : {
23215 : ae_int_t ts;
23216 :
23217 :
23218 0 : ts = matrixtilesizeb(_state);
23219 :
23220 : /*
23221 : * Check input sizes for correctness
23222 : */
23223 0 : ae_assert((optypea==0||optypea==1)||optypea==2, "CMatrixGEMM: incorrect OpTypeA (must be 0 or 1 or 2)", _state);
23224 0 : ae_assert((optypeb==0||optypeb==1)||optypeb==2, "CMatrixGEMM: incorrect OpTypeB (must be 0 or 1 or 2)", _state);
23225 0 : ae_assert(ic+m<=c->rows, "CMatrixGEMM: incorect size of output matrix C", _state);
23226 0 : ae_assert(jc+n<=c->cols, "CMatrixGEMM: incorect size of output matrix C", _state);
23227 :
23228 : /*
23229 : * Decide whether it is feasible to activate multithreading
23230 : */
23231 0 : if( (m>=2*ts||n>=2*ts)&&ae_fp_greater_eq(8*rmul3((double)(m), (double)(n), (double)(k), _state),smpactivationlevel(_state)) )
23232 : {
23233 0 : if( _trypexec_cmatrixgemm(m,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc, _state) )
23234 : {
23235 0 : return;
23236 : }
23237 : }
23238 :
23239 : /*
23240 : * Start actual work
23241 : */
23242 0 : ablas_cmatrixgemmrec(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
23243 : }
23244 :
23245 :
23246 : /*************************************************************************
23247 : Serial stub for GPL edition.
23248 : *************************************************************************/
23249 0 : ae_bool _trypexec_cmatrixgemm(ae_int_t m,
23250 : ae_int_t n,
23251 : ae_int_t k,
23252 : ae_complex alpha,
23253 : /* Complex */ ae_matrix* a,
23254 : ae_int_t ia,
23255 : ae_int_t ja,
23256 : ae_int_t optypea,
23257 : /* Complex */ ae_matrix* b,
23258 : ae_int_t ib,
23259 : ae_int_t jb,
23260 : ae_int_t optypeb,
23261 : ae_complex beta,
23262 : /* Complex */ ae_matrix* c,
23263 : ae_int_t ic,
23264 : ae_int_t jc,
23265 : ae_state *_state)
23266 : {
23267 0 : return ae_false;
23268 : }
23269 :
23270 :
23271 : /*************************************************************************
23272 : This subroutine calculates C = alpha*op1(A)*op2(B) +beta*C where:
23273 : * C is MxN general matrix
23274 : * op1(A) is MxK matrix
23275 : * op2(B) is KxN matrix
23276 : * "op" may be identity transformation, transposition
23277 :
23278 : Additional info:
23279 : * cache-oblivious algorithm is used.
23280 : * multiplication result replaces C. If Beta=0, C elements are not used in
23281 : calculations (not multiplied by zero - just not referenced)
23282 : * if Alpha=0, A is not used (not multiplied by zero - just not referenced)
23283 : * if both Beta and Alpha are zero, C is filled by zeros.
23284 :
23285 : ! COMMERCIAL EDITION OF ALGLIB:
23286 : !
23287 : ! Commercial Edition of ALGLIB includes following important improvements
23288 : ! of this function:
23289 : ! * high-performance native backend with same C# interface (C# version)
23290 : ! * multithreading support (C++ and C# versions)
23291 : ! * hardware vendor (Intel) implementations of linear algebra primitives
23292 : ! (C++ and C# versions, x86/x64 platform)
23293 : !
23294 : ! We recommend you to read 'Working with commercial version' section of
23295 : ! ALGLIB Reference Manual in order to find out how to use performance-
23296 : ! related features provided by commercial edition of ALGLIB.
23297 :
23298 : IMPORTANT:
23299 :
23300 : This function does NOT preallocate output matrix C, it MUST be preallocated
23301 : by caller prior to calling this function. In case C does not have enough
23302 : space to store result, exception will be generated.
23303 :
23304 : INPUT PARAMETERS
23305 : M - matrix size, M>0
23306 : N - matrix size, N>0
23307 : K - matrix size, K>0
23308 : Alpha - coefficient
23309 : A - matrix
23310 : IA - submatrix offset
23311 : JA - submatrix offset
23312 : OpTypeA - transformation type:
23313 : * 0 - no transformation
23314 : * 1 - transposition
23315 : B - matrix
23316 : IB - submatrix offset
23317 : JB - submatrix offset
23318 : OpTypeB - transformation type:
23319 : * 0 - no transformation
23320 : * 1 - transposition
23321 : Beta - coefficient
23322 : C - PREALLOCATED output matrix, large enough to store result
23323 : IC - submatrix offset
23324 : JC - submatrix offset
23325 :
23326 : -- ALGLIB routine --
23327 : 2009-2019
23328 : Bochkanov Sergey
23329 : *************************************************************************/
23330 0 : void rmatrixgemm(ae_int_t m,
23331 : ae_int_t n,
23332 : ae_int_t k,
23333 : double alpha,
23334 : /* Real */ ae_matrix* a,
23335 : ae_int_t ia,
23336 : ae_int_t ja,
23337 : ae_int_t optypea,
23338 : /* Real */ ae_matrix* b,
23339 : ae_int_t ib,
23340 : ae_int_t jb,
23341 : ae_int_t optypeb,
23342 : double beta,
23343 : /* Real */ ae_matrix* c,
23344 : ae_int_t ic,
23345 : ae_int_t jc,
23346 : ae_state *_state)
23347 : {
23348 : ae_int_t ts;
23349 :
23350 :
23351 0 : ts = matrixtilesizeb(_state);
23352 :
23353 : /*
23354 : * Check input sizes for correctness
23355 : */
23356 0 : ae_assert(optypea==0||optypea==1, "RMatrixGEMM: incorrect OpTypeA (must be 0 or 1)", _state);
23357 0 : ae_assert(optypeb==0||optypeb==1, "RMatrixGEMM: incorrect OpTypeB (must be 0 or 1)", _state);
23358 0 : ae_assert(ic+m<=c->rows, "RMatrixGEMM: incorect size of output matrix C", _state);
23359 0 : ae_assert(jc+n<=c->cols, "RMatrixGEMM: incorect size of output matrix C", _state);
23360 :
23361 : /*
23362 : * Decide whether it is feasible to activate multithreading
23363 : */
23364 0 : if( (m>=2*ts||n>=2*ts)&&ae_fp_greater_eq(2*rmul3((double)(m), (double)(n), (double)(k), _state),smpactivationlevel(_state)) )
23365 : {
23366 0 : if( _trypexec_rmatrixgemm(m,n,k,alpha,a,ia,ja,optypea,b,ib,jb,optypeb,beta,c,ic,jc, _state) )
23367 : {
23368 0 : return;
23369 : }
23370 : }
23371 :
23372 : /*
23373 : * Start actual work
23374 : */
23375 0 : ablas_rmatrixgemmrec(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
23376 : }
23377 :
23378 :
23379 : /*************************************************************************
23380 : Serial stub for GPL edition.
23381 : *************************************************************************/
23382 0 : ae_bool _trypexec_rmatrixgemm(ae_int_t m,
23383 : ae_int_t n,
23384 : ae_int_t k,
23385 : double alpha,
23386 : /* Real */ ae_matrix* a,
23387 : ae_int_t ia,
23388 : ae_int_t ja,
23389 : ae_int_t optypea,
23390 : /* Real */ ae_matrix* b,
23391 : ae_int_t ib,
23392 : ae_int_t jb,
23393 : ae_int_t optypeb,
23394 : double beta,
23395 : /* Real */ ae_matrix* c,
23396 : ae_int_t ic,
23397 : ae_int_t jc,
23398 : ae_state *_state)
23399 : {
23400 0 : return ae_false;
23401 : }
23402 :
23403 :
23404 : /*************************************************************************
23405 : This subroutine is an older version of CMatrixHERK(), one with wrong name
23406 : (it is HErmitian update, not SYmmetric). It is left here for backward
23407 : compatibility.
23408 :
23409 : -- ALGLIB routine --
23410 : 16.12.2009
23411 : Bochkanov Sergey
23412 : *************************************************************************/
23413 0 : void cmatrixsyrk(ae_int_t n,
23414 : ae_int_t k,
23415 : double alpha,
23416 : /* Complex */ ae_matrix* a,
23417 : ae_int_t ia,
23418 : ae_int_t ja,
23419 : ae_int_t optypea,
23420 : double beta,
23421 : /* Complex */ ae_matrix* c,
23422 : ae_int_t ic,
23423 : ae_int_t jc,
23424 : ae_bool isupper,
23425 : ae_state *_state)
23426 : {
23427 :
23428 :
23429 0 : cmatrixherk(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state);
23430 0 : }
23431 :
23432 :
23433 : /*************************************************************************
23434 : Performs one step of stable Gram-Schmidt process on vector X[] using
23435 : set of orthonormal rows Q[].
23436 :
23437 : INPUT PARAMETERS:
23438 : Q - array[M,N], matrix with orthonormal rows
23439 : M, N - rows/cols
23440 : X - array[N], vector to process
23441 : NeedQX - whether we need QX or not
23442 :
23443 : OUTPUT PARAMETERS:
23444 : X - stores X - Q'*(Q*X)
23445 : QX - if NeedQX is True, array[M] filled with elements of Q*X,
23446 : reallocated if length is less than M.
23447 : Ignored otherwise.
23448 :
23449 : -- ALGLIB --
23450 : Copyright 20.01.2020 by Bochkanov Sergey
23451 : *************************************************************************/
23452 0 : void rowwisegramschmidt(/* Real */ ae_matrix* q,
23453 : ae_int_t m,
23454 : ae_int_t n,
23455 : /* Real */ ae_vector* x,
23456 : /* Real */ ae_vector* qx,
23457 : ae_bool needqx,
23458 : ae_state *_state)
23459 : {
23460 : ae_int_t i;
23461 : double v;
23462 :
23463 :
23464 0 : if( needqx )
23465 : {
23466 0 : rvectorsetlengthatleast(qx, m, _state);
23467 : }
23468 0 : for(i=0; i<=m-1; i++)
23469 : {
23470 0 : v = rdotvr(n, x, q, i, _state);
23471 0 : raddrv(n, -v, q, i, x, _state);
23472 0 : if( needqx )
23473 : {
23474 0 : qx->ptr.p_double[i] = v;
23475 : }
23476 : }
23477 0 : }
23478 :
23479 :
23480 : /*************************************************************************
23481 : Complex ABLASSplitLength
23482 :
23483 : -- ALGLIB routine --
23484 : 15.12.2009
23485 : Bochkanov Sergey
23486 : *************************************************************************/
23487 0 : static void ablas_ablasinternalsplitlength(ae_int_t n,
23488 : ae_int_t nb,
23489 : ae_int_t* n1,
23490 : ae_int_t* n2,
23491 : ae_state *_state)
23492 : {
23493 : ae_int_t r;
23494 :
23495 0 : *n1 = 0;
23496 0 : *n2 = 0;
23497 :
23498 0 : if( n<=nb )
23499 : {
23500 :
23501 : /*
23502 : * Block size, no further splitting
23503 : */
23504 0 : *n1 = n;
23505 0 : *n2 = 0;
23506 : }
23507 : else
23508 : {
23509 :
23510 : /*
23511 : * Greater than block size
23512 : */
23513 0 : if( n%nb!=0 )
23514 : {
23515 :
23516 : /*
23517 : * Split remainder
23518 : */
23519 0 : *n2 = n%nb;
23520 0 : *n1 = n-(*n2);
23521 : }
23522 : else
23523 : {
23524 :
23525 : /*
23526 : * Split on block boundaries
23527 : */
23528 0 : *n2 = n/2;
23529 0 : *n1 = n-(*n2);
23530 0 : if( *n1%nb==0 )
23531 : {
23532 0 : return;
23533 : }
23534 0 : r = nb-*n1%nb;
23535 0 : *n1 = *n1+r;
23536 0 : *n2 = *n2-r;
23537 : }
23538 : }
23539 : }
23540 :
23541 :
23542 : /*************************************************************************
23543 : Level 2 variant of CMatrixRightTRSM
23544 : *************************************************************************/
23545 0 : static void ablas_cmatrixrighttrsm2(ae_int_t m,
23546 : ae_int_t n,
23547 : /* Complex */ ae_matrix* a,
23548 : ae_int_t i1,
23549 : ae_int_t j1,
23550 : ae_bool isupper,
23551 : ae_bool isunit,
23552 : ae_int_t optype,
23553 : /* Complex */ ae_matrix* x,
23554 : ae_int_t i2,
23555 : ae_int_t j2,
23556 : ae_state *_state)
23557 : {
23558 : ae_int_t i;
23559 : ae_int_t j;
23560 : ae_complex vc;
23561 : ae_complex vd;
23562 :
23563 :
23564 :
23565 : /*
23566 : * Special case
23567 : */
23568 0 : if( n*m==0 )
23569 : {
23570 0 : return;
23571 : }
23572 :
23573 : /*
23574 : * Try to call fast TRSM
23575 : */
23576 0 : if( cmatrixrighttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) )
23577 : {
23578 0 : return;
23579 : }
23580 :
23581 : /*
23582 : * General case
23583 : */
23584 0 : if( isupper )
23585 : {
23586 :
23587 : /*
23588 : * Upper triangular matrix
23589 : */
23590 0 : if( optype==0 )
23591 : {
23592 :
23593 : /*
23594 : * X*A^(-1)
23595 : */
23596 0 : for(i=0; i<=m-1; i++)
23597 : {
23598 0 : for(j=0; j<=n-1; j++)
23599 : {
23600 0 : if( isunit )
23601 : {
23602 0 : vd = ae_complex_from_i(1);
23603 : }
23604 : else
23605 : {
23606 0 : vd = a->ptr.pp_complex[i1+j][j1+j];
23607 : }
23608 0 : x->ptr.pp_complex[i2+i][j2+j] = ae_c_div(x->ptr.pp_complex[i2+i][j2+j],vd);
23609 0 : if( j<n-1 )
23610 : {
23611 0 : vc = x->ptr.pp_complex[i2+i][j2+j];
23612 0 : ae_v_csubc(&x->ptr.pp_complex[i2+i][j2+j+1], 1, &a->ptr.pp_complex[i1+j][j1+j+1], 1, "N", ae_v_len(j2+j+1,j2+n-1), vc);
23613 : }
23614 : }
23615 : }
23616 0 : return;
23617 : }
23618 0 : if( optype==1 )
23619 : {
23620 :
23621 : /*
23622 : * X*A^(-T)
23623 : */
23624 0 : for(i=0; i<=m-1; i++)
23625 : {
23626 0 : for(j=n-1; j>=0; j--)
23627 : {
23628 0 : vc = ae_complex_from_i(0);
23629 0 : vd = ae_complex_from_i(1);
23630 0 : if( j<n-1 )
23631 : {
23632 0 : vc = ae_v_cdotproduct(&x->ptr.pp_complex[i2+i][j2+j+1], 1, "N", &a->ptr.pp_complex[i1+j][j1+j+1], 1, "N", ae_v_len(j2+j+1,j2+n-1));
23633 : }
23634 0 : if( !isunit )
23635 : {
23636 0 : vd = a->ptr.pp_complex[i1+j][j1+j];
23637 : }
23638 0 : x->ptr.pp_complex[i2+i][j2+j] = ae_c_div(ae_c_sub(x->ptr.pp_complex[i2+i][j2+j],vc),vd);
23639 : }
23640 : }
23641 0 : return;
23642 : }
23643 0 : if( optype==2 )
23644 : {
23645 :
23646 : /*
23647 : * X*A^(-H)
23648 : */
23649 0 : for(i=0; i<=m-1; i++)
23650 : {
23651 0 : for(j=n-1; j>=0; j--)
23652 : {
23653 0 : vc = ae_complex_from_i(0);
23654 0 : vd = ae_complex_from_i(1);
23655 0 : if( j<n-1 )
23656 : {
23657 0 : vc = ae_v_cdotproduct(&x->ptr.pp_complex[i2+i][j2+j+1], 1, "N", &a->ptr.pp_complex[i1+j][j1+j+1], 1, "Conj", ae_v_len(j2+j+1,j2+n-1));
23658 : }
23659 0 : if( !isunit )
23660 : {
23661 0 : vd = ae_c_conj(a->ptr.pp_complex[i1+j][j1+j], _state);
23662 : }
23663 0 : x->ptr.pp_complex[i2+i][j2+j] = ae_c_div(ae_c_sub(x->ptr.pp_complex[i2+i][j2+j],vc),vd);
23664 : }
23665 : }
23666 0 : return;
23667 : }
23668 : }
23669 : else
23670 : {
23671 :
23672 : /*
23673 : * Lower triangular matrix
23674 : */
23675 0 : if( optype==0 )
23676 : {
23677 :
23678 : /*
23679 : * X*A^(-1)
23680 : */
23681 0 : for(i=0; i<=m-1; i++)
23682 : {
23683 0 : for(j=n-1; j>=0; j--)
23684 : {
23685 0 : if( isunit )
23686 : {
23687 0 : vd = ae_complex_from_i(1);
23688 : }
23689 : else
23690 : {
23691 0 : vd = a->ptr.pp_complex[i1+j][j1+j];
23692 : }
23693 0 : x->ptr.pp_complex[i2+i][j2+j] = ae_c_div(x->ptr.pp_complex[i2+i][j2+j],vd);
23694 0 : if( j>0 )
23695 : {
23696 0 : vc = x->ptr.pp_complex[i2+i][j2+j];
23697 0 : ae_v_csubc(&x->ptr.pp_complex[i2+i][j2], 1, &a->ptr.pp_complex[i1+j][j1], 1, "N", ae_v_len(j2,j2+j-1), vc);
23698 : }
23699 : }
23700 : }
23701 0 : return;
23702 : }
23703 0 : if( optype==1 )
23704 : {
23705 :
23706 : /*
23707 : * X*A^(-T)
23708 : */
23709 0 : for(i=0; i<=m-1; i++)
23710 : {
23711 0 : for(j=0; j<=n-1; j++)
23712 : {
23713 0 : vc = ae_complex_from_i(0);
23714 0 : vd = ae_complex_from_i(1);
23715 0 : if( j>0 )
23716 : {
23717 0 : vc = ae_v_cdotproduct(&x->ptr.pp_complex[i2+i][j2], 1, "N", &a->ptr.pp_complex[i1+j][j1], 1, "N", ae_v_len(j2,j2+j-1));
23718 : }
23719 0 : if( !isunit )
23720 : {
23721 0 : vd = a->ptr.pp_complex[i1+j][j1+j];
23722 : }
23723 0 : x->ptr.pp_complex[i2+i][j2+j] = ae_c_div(ae_c_sub(x->ptr.pp_complex[i2+i][j2+j],vc),vd);
23724 : }
23725 : }
23726 0 : return;
23727 : }
23728 0 : if( optype==2 )
23729 : {
23730 :
23731 : /*
23732 : * X*A^(-H)
23733 : */
23734 0 : for(i=0; i<=m-1; i++)
23735 : {
23736 0 : for(j=0; j<=n-1; j++)
23737 : {
23738 0 : vc = ae_complex_from_i(0);
23739 0 : vd = ae_complex_from_i(1);
23740 0 : if( j>0 )
23741 : {
23742 0 : vc = ae_v_cdotproduct(&x->ptr.pp_complex[i2+i][j2], 1, "N", &a->ptr.pp_complex[i1+j][j1], 1, "Conj", ae_v_len(j2,j2+j-1));
23743 : }
23744 0 : if( !isunit )
23745 : {
23746 0 : vd = ae_c_conj(a->ptr.pp_complex[i1+j][j1+j], _state);
23747 : }
23748 0 : x->ptr.pp_complex[i2+i][j2+j] = ae_c_div(ae_c_sub(x->ptr.pp_complex[i2+i][j2+j],vc),vd);
23749 : }
23750 : }
23751 0 : return;
23752 : }
23753 : }
23754 : }
23755 :
23756 :
23757 : /*************************************************************************
23758 : Level-2 subroutine
23759 : *************************************************************************/
23760 0 : static void ablas_cmatrixlefttrsm2(ae_int_t m,
23761 : ae_int_t n,
23762 : /* Complex */ ae_matrix* a,
23763 : ae_int_t i1,
23764 : ae_int_t j1,
23765 : ae_bool isupper,
23766 : ae_bool isunit,
23767 : ae_int_t optype,
23768 : /* Complex */ ae_matrix* x,
23769 : ae_int_t i2,
23770 : ae_int_t j2,
23771 : ae_state *_state)
23772 : {
23773 : ae_int_t i;
23774 : ae_int_t j;
23775 : ae_complex vc;
23776 : ae_complex vd;
23777 :
23778 :
23779 :
23780 : /*
23781 : * Special case
23782 : */
23783 0 : if( n*m==0 )
23784 : {
23785 0 : return;
23786 : }
23787 :
23788 : /*
23789 : * Try to call fast TRSM
23790 : */
23791 0 : if( cmatrixlefttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) )
23792 : {
23793 0 : return;
23794 : }
23795 :
23796 : /*
23797 : * General case
23798 : */
23799 0 : if( isupper )
23800 : {
23801 :
23802 : /*
23803 : * Upper triangular matrix
23804 : */
23805 0 : if( optype==0 )
23806 : {
23807 :
23808 : /*
23809 : * A^(-1)*X
23810 : */
23811 0 : for(i=m-1; i>=0; i--)
23812 : {
23813 0 : for(j=i+1; j<=m-1; j++)
23814 : {
23815 0 : vc = a->ptr.pp_complex[i1+i][j1+j];
23816 0 : ae_v_csubc(&x->ptr.pp_complex[i2+i][j2], 1, &x->ptr.pp_complex[i2+j][j2], 1, "N", ae_v_len(j2,j2+n-1), vc);
23817 : }
23818 0 : if( !isunit )
23819 : {
23820 0 : vd = ae_c_d_div(1,a->ptr.pp_complex[i1+i][j1+i]);
23821 0 : ae_v_cmulc(&x->ptr.pp_complex[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd);
23822 : }
23823 : }
23824 0 : return;
23825 : }
23826 0 : if( optype==1 )
23827 : {
23828 :
23829 : /*
23830 : * A^(-T)*X
23831 : */
23832 0 : for(i=0; i<=m-1; i++)
23833 : {
23834 0 : if( isunit )
23835 : {
23836 0 : vd = ae_complex_from_i(1);
23837 : }
23838 : else
23839 : {
23840 0 : vd = ae_c_d_div(1,a->ptr.pp_complex[i1+i][j1+i]);
23841 : }
23842 0 : ae_v_cmulc(&x->ptr.pp_complex[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd);
23843 0 : for(j=i+1; j<=m-1; j++)
23844 : {
23845 0 : vc = a->ptr.pp_complex[i1+i][j1+j];
23846 0 : ae_v_csubc(&x->ptr.pp_complex[i2+j][j2], 1, &x->ptr.pp_complex[i2+i][j2], 1, "N", ae_v_len(j2,j2+n-1), vc);
23847 : }
23848 : }
23849 0 : return;
23850 : }
23851 0 : if( optype==2 )
23852 : {
23853 :
23854 : /*
23855 : * A^(-H)*X
23856 : */
23857 0 : for(i=0; i<=m-1; i++)
23858 : {
23859 0 : if( isunit )
23860 : {
23861 0 : vd = ae_complex_from_i(1);
23862 : }
23863 : else
23864 : {
23865 0 : vd = ae_c_d_div(1,ae_c_conj(a->ptr.pp_complex[i1+i][j1+i], _state));
23866 : }
23867 0 : ae_v_cmulc(&x->ptr.pp_complex[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd);
23868 0 : for(j=i+1; j<=m-1; j++)
23869 : {
23870 0 : vc = ae_c_conj(a->ptr.pp_complex[i1+i][j1+j], _state);
23871 0 : ae_v_csubc(&x->ptr.pp_complex[i2+j][j2], 1, &x->ptr.pp_complex[i2+i][j2], 1, "N", ae_v_len(j2,j2+n-1), vc);
23872 : }
23873 : }
23874 0 : return;
23875 : }
23876 : }
23877 : else
23878 : {
23879 :
23880 : /*
23881 : * Lower triangular matrix
23882 : */
23883 0 : if( optype==0 )
23884 : {
23885 :
23886 : /*
23887 : * A^(-1)*X
23888 : */
23889 0 : for(i=0; i<=m-1; i++)
23890 : {
23891 0 : for(j=0; j<=i-1; j++)
23892 : {
23893 0 : vc = a->ptr.pp_complex[i1+i][j1+j];
23894 0 : ae_v_csubc(&x->ptr.pp_complex[i2+i][j2], 1, &x->ptr.pp_complex[i2+j][j2], 1, "N", ae_v_len(j2,j2+n-1), vc);
23895 : }
23896 0 : if( isunit )
23897 : {
23898 0 : vd = ae_complex_from_i(1);
23899 : }
23900 : else
23901 : {
23902 0 : vd = ae_c_d_div(1,a->ptr.pp_complex[i1+j][j1+j]);
23903 : }
23904 0 : ae_v_cmulc(&x->ptr.pp_complex[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd);
23905 : }
23906 0 : return;
23907 : }
23908 0 : if( optype==1 )
23909 : {
23910 :
23911 : /*
23912 : * A^(-T)*X
23913 : */
23914 0 : for(i=m-1; i>=0; i--)
23915 : {
23916 0 : if( isunit )
23917 : {
23918 0 : vd = ae_complex_from_i(1);
23919 : }
23920 : else
23921 : {
23922 0 : vd = ae_c_d_div(1,a->ptr.pp_complex[i1+i][j1+i]);
23923 : }
23924 0 : ae_v_cmulc(&x->ptr.pp_complex[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd);
23925 0 : for(j=i-1; j>=0; j--)
23926 : {
23927 0 : vc = a->ptr.pp_complex[i1+i][j1+j];
23928 0 : ae_v_csubc(&x->ptr.pp_complex[i2+j][j2], 1, &x->ptr.pp_complex[i2+i][j2], 1, "N", ae_v_len(j2,j2+n-1), vc);
23929 : }
23930 : }
23931 0 : return;
23932 : }
23933 0 : if( optype==2 )
23934 : {
23935 :
23936 : /*
23937 : * A^(-H)*X
23938 : */
23939 0 : for(i=m-1; i>=0; i--)
23940 : {
23941 0 : if( isunit )
23942 : {
23943 0 : vd = ae_complex_from_i(1);
23944 : }
23945 : else
23946 : {
23947 0 : vd = ae_c_d_div(1,ae_c_conj(a->ptr.pp_complex[i1+i][j1+i], _state));
23948 : }
23949 0 : ae_v_cmulc(&x->ptr.pp_complex[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd);
23950 0 : for(j=i-1; j>=0; j--)
23951 : {
23952 0 : vc = ae_c_conj(a->ptr.pp_complex[i1+i][j1+j], _state);
23953 0 : ae_v_csubc(&x->ptr.pp_complex[i2+j][j2], 1, &x->ptr.pp_complex[i2+i][j2], 1, "N", ae_v_len(j2,j2+n-1), vc);
23954 : }
23955 : }
23956 0 : return;
23957 : }
23958 : }
23959 : }
23960 :
23961 :
23962 : /*************************************************************************
23963 : Level 2 subroutine
23964 :
23965 : -- ALGLIB routine --
23966 : 15.12.2009
23967 : Bochkanov Sergey
23968 : *************************************************************************/
23969 0 : static void ablas_rmatrixrighttrsm2(ae_int_t m,
23970 : ae_int_t n,
23971 : /* Real */ ae_matrix* a,
23972 : ae_int_t i1,
23973 : ae_int_t j1,
23974 : ae_bool isupper,
23975 : ae_bool isunit,
23976 : ae_int_t optype,
23977 : /* Real */ ae_matrix* x,
23978 : ae_int_t i2,
23979 : ae_int_t j2,
23980 : ae_state *_state)
23981 : {
23982 : ae_int_t i;
23983 : ae_int_t j;
23984 : double vr;
23985 : double vd;
23986 :
23987 :
23988 :
23989 : /*
23990 : * Special case
23991 : */
23992 0 : if( n*m==0 )
23993 : {
23994 0 : return;
23995 : }
23996 :
23997 : /*
23998 : * Try to use "fast" code
23999 : */
24000 0 : if( rmatrixrighttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) )
24001 : {
24002 0 : return;
24003 : }
24004 :
24005 : /*
24006 : * General case
24007 : */
24008 0 : if( isupper )
24009 : {
24010 :
24011 : /*
24012 : * Upper triangular matrix
24013 : */
24014 0 : if( optype==0 )
24015 : {
24016 :
24017 : /*
24018 : * X*A^(-1)
24019 : */
24020 0 : for(i=0; i<=m-1; i++)
24021 : {
24022 0 : for(j=0; j<=n-1; j++)
24023 : {
24024 0 : if( isunit )
24025 : {
24026 0 : vd = (double)(1);
24027 : }
24028 : else
24029 : {
24030 0 : vd = a->ptr.pp_double[i1+j][j1+j];
24031 : }
24032 0 : x->ptr.pp_double[i2+i][j2+j] = x->ptr.pp_double[i2+i][j2+j]/vd;
24033 0 : if( j<n-1 )
24034 : {
24035 0 : vr = x->ptr.pp_double[i2+i][j2+j];
24036 0 : ae_v_subd(&x->ptr.pp_double[i2+i][j2+j+1], 1, &a->ptr.pp_double[i1+j][j1+j+1], 1, ae_v_len(j2+j+1,j2+n-1), vr);
24037 : }
24038 : }
24039 : }
24040 0 : return;
24041 : }
24042 0 : if( optype==1 )
24043 : {
24044 :
24045 : /*
24046 : * X*A^(-T)
24047 : */
24048 0 : for(i=0; i<=m-1; i++)
24049 : {
24050 0 : for(j=n-1; j>=0; j--)
24051 : {
24052 0 : vr = (double)(0);
24053 0 : vd = (double)(1);
24054 0 : if( j<n-1 )
24055 : {
24056 0 : vr = ae_v_dotproduct(&x->ptr.pp_double[i2+i][j2+j+1], 1, &a->ptr.pp_double[i1+j][j1+j+1], 1, ae_v_len(j2+j+1,j2+n-1));
24057 : }
24058 0 : if( !isunit )
24059 : {
24060 0 : vd = a->ptr.pp_double[i1+j][j1+j];
24061 : }
24062 0 : x->ptr.pp_double[i2+i][j2+j] = (x->ptr.pp_double[i2+i][j2+j]-vr)/vd;
24063 : }
24064 : }
24065 0 : return;
24066 : }
24067 : }
24068 : else
24069 : {
24070 :
24071 : /*
24072 : * Lower triangular matrix
24073 : */
24074 0 : if( optype==0 )
24075 : {
24076 :
24077 : /*
24078 : * X*A^(-1)
24079 : */
24080 0 : for(i=0; i<=m-1; i++)
24081 : {
24082 0 : for(j=n-1; j>=0; j--)
24083 : {
24084 0 : if( isunit )
24085 : {
24086 0 : vd = (double)(1);
24087 : }
24088 : else
24089 : {
24090 0 : vd = a->ptr.pp_double[i1+j][j1+j];
24091 : }
24092 0 : x->ptr.pp_double[i2+i][j2+j] = x->ptr.pp_double[i2+i][j2+j]/vd;
24093 0 : if( j>0 )
24094 : {
24095 0 : vr = x->ptr.pp_double[i2+i][j2+j];
24096 0 : ae_v_subd(&x->ptr.pp_double[i2+i][j2], 1, &a->ptr.pp_double[i1+j][j1], 1, ae_v_len(j2,j2+j-1), vr);
24097 : }
24098 : }
24099 : }
24100 0 : return;
24101 : }
24102 0 : if( optype==1 )
24103 : {
24104 :
24105 : /*
24106 : * X*A^(-T)
24107 : */
24108 0 : for(i=0; i<=m-1; i++)
24109 : {
24110 0 : for(j=0; j<=n-1; j++)
24111 : {
24112 0 : vr = (double)(0);
24113 0 : vd = (double)(1);
24114 0 : if( j>0 )
24115 : {
24116 0 : vr = ae_v_dotproduct(&x->ptr.pp_double[i2+i][j2], 1, &a->ptr.pp_double[i1+j][j1], 1, ae_v_len(j2,j2+j-1));
24117 : }
24118 0 : if( !isunit )
24119 : {
24120 0 : vd = a->ptr.pp_double[i1+j][j1+j];
24121 : }
24122 0 : x->ptr.pp_double[i2+i][j2+j] = (x->ptr.pp_double[i2+i][j2+j]-vr)/vd;
24123 : }
24124 : }
24125 0 : return;
24126 : }
24127 : }
24128 : }
24129 :
24130 :
24131 : /*************************************************************************
24132 : Level 2 subroutine
24133 : *************************************************************************/
24134 0 : static void ablas_rmatrixlefttrsm2(ae_int_t m,
24135 : ae_int_t n,
24136 : /* Real */ ae_matrix* a,
24137 : ae_int_t i1,
24138 : ae_int_t j1,
24139 : ae_bool isupper,
24140 : ae_bool isunit,
24141 : ae_int_t optype,
24142 : /* Real */ ae_matrix* x,
24143 : ae_int_t i2,
24144 : ae_int_t j2,
24145 : ae_state *_state)
24146 : {
24147 : ae_int_t i;
24148 : ae_int_t j;
24149 : double vr;
24150 : double vd;
24151 :
24152 :
24153 :
24154 : /*
24155 : * Special case
24156 : */
24157 0 : if( n==0||m==0 )
24158 : {
24159 0 : return;
24160 : }
24161 :
24162 : /*
24163 : * Try fast code
24164 : */
24165 0 : if( rmatrixlefttrsmf(m, n, a, i1, j1, isupper, isunit, optype, x, i2, j2, _state) )
24166 : {
24167 0 : return;
24168 : }
24169 :
24170 : /*
24171 : * General case
24172 : */
24173 0 : if( isupper )
24174 : {
24175 :
24176 : /*
24177 : * Upper triangular matrix
24178 : */
24179 0 : if( optype==0 )
24180 : {
24181 :
24182 : /*
24183 : * A^(-1)*X
24184 : */
24185 0 : for(i=m-1; i>=0; i--)
24186 : {
24187 0 : for(j=i+1; j<=m-1; j++)
24188 : {
24189 0 : vr = a->ptr.pp_double[i1+i][j1+j];
24190 0 : ae_v_subd(&x->ptr.pp_double[i2+i][j2], 1, &x->ptr.pp_double[i2+j][j2], 1, ae_v_len(j2,j2+n-1), vr);
24191 : }
24192 0 : if( !isunit )
24193 : {
24194 0 : vd = 1/a->ptr.pp_double[i1+i][j1+i];
24195 0 : ae_v_muld(&x->ptr.pp_double[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd);
24196 : }
24197 : }
24198 0 : return;
24199 : }
24200 0 : if( optype==1 )
24201 : {
24202 :
24203 : /*
24204 : * A^(-T)*X
24205 : */
24206 0 : for(i=0; i<=m-1; i++)
24207 : {
24208 0 : if( isunit )
24209 : {
24210 0 : vd = (double)(1);
24211 : }
24212 : else
24213 : {
24214 0 : vd = 1/a->ptr.pp_double[i1+i][j1+i];
24215 : }
24216 0 : ae_v_muld(&x->ptr.pp_double[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd);
24217 0 : for(j=i+1; j<=m-1; j++)
24218 : {
24219 0 : vr = a->ptr.pp_double[i1+i][j1+j];
24220 0 : ae_v_subd(&x->ptr.pp_double[i2+j][j2], 1, &x->ptr.pp_double[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vr);
24221 : }
24222 : }
24223 0 : return;
24224 : }
24225 : }
24226 : else
24227 : {
24228 :
24229 : /*
24230 : * Lower triangular matrix
24231 : */
24232 0 : if( optype==0 )
24233 : {
24234 :
24235 : /*
24236 : * A^(-1)*X
24237 : */
24238 0 : for(i=0; i<=m-1; i++)
24239 : {
24240 0 : for(j=0; j<=i-1; j++)
24241 : {
24242 0 : vr = a->ptr.pp_double[i1+i][j1+j];
24243 0 : ae_v_subd(&x->ptr.pp_double[i2+i][j2], 1, &x->ptr.pp_double[i2+j][j2], 1, ae_v_len(j2,j2+n-1), vr);
24244 : }
24245 0 : if( isunit )
24246 : {
24247 0 : vd = (double)(1);
24248 : }
24249 : else
24250 : {
24251 0 : vd = 1/a->ptr.pp_double[i1+j][j1+j];
24252 : }
24253 0 : ae_v_muld(&x->ptr.pp_double[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd);
24254 : }
24255 0 : return;
24256 : }
24257 0 : if( optype==1 )
24258 : {
24259 :
24260 : /*
24261 : * A^(-T)*X
24262 : */
24263 0 : for(i=m-1; i>=0; i--)
24264 : {
24265 0 : if( isunit )
24266 : {
24267 0 : vd = (double)(1);
24268 : }
24269 : else
24270 : {
24271 0 : vd = 1/a->ptr.pp_double[i1+i][j1+i];
24272 : }
24273 0 : ae_v_muld(&x->ptr.pp_double[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vd);
24274 0 : for(j=i-1; j>=0; j--)
24275 : {
24276 0 : vr = a->ptr.pp_double[i1+i][j1+j];
24277 0 : ae_v_subd(&x->ptr.pp_double[i2+j][j2], 1, &x->ptr.pp_double[i2+i][j2], 1, ae_v_len(j2,j2+n-1), vr);
24278 : }
24279 : }
24280 0 : return;
24281 : }
24282 : }
24283 : }
24284 :
24285 :
24286 : /*************************************************************************
24287 : Level 2 subroutine
24288 : *************************************************************************/
24289 0 : static void ablas_cmatrixherk2(ae_int_t n,
24290 : ae_int_t k,
24291 : double alpha,
24292 : /* Complex */ ae_matrix* a,
24293 : ae_int_t ia,
24294 : ae_int_t ja,
24295 : ae_int_t optypea,
24296 : double beta,
24297 : /* Complex */ ae_matrix* c,
24298 : ae_int_t ic,
24299 : ae_int_t jc,
24300 : ae_bool isupper,
24301 : ae_state *_state)
24302 : {
24303 : ae_int_t i;
24304 : ae_int_t j;
24305 : ae_int_t j1;
24306 : ae_int_t j2;
24307 : ae_complex v;
24308 :
24309 :
24310 :
24311 : /*
24312 : * Fast exit (nothing to be done)
24313 : */
24314 0 : if( (ae_fp_eq(alpha,(double)(0))||k==0)&&ae_fp_eq(beta,(double)(1)) )
24315 : {
24316 0 : return;
24317 : }
24318 :
24319 : /*
24320 : * Try to call fast SYRK
24321 : */
24322 0 : if( cmatrixherkf(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state) )
24323 : {
24324 0 : return;
24325 : }
24326 :
24327 : /*
24328 : * SYRK
24329 : */
24330 0 : if( optypea==0 )
24331 : {
24332 :
24333 : /*
24334 : * C=alpha*A*A^H+beta*C
24335 : */
24336 0 : for(i=0; i<=n-1; i++)
24337 : {
24338 0 : if( isupper )
24339 : {
24340 0 : j1 = i;
24341 0 : j2 = n-1;
24342 : }
24343 : else
24344 : {
24345 0 : j1 = 0;
24346 0 : j2 = i;
24347 : }
24348 0 : for(j=j1; j<=j2; j++)
24349 : {
24350 0 : if( ae_fp_neq(alpha,(double)(0))&&k>0 )
24351 : {
24352 0 : v = ae_v_cdotproduct(&a->ptr.pp_complex[ia+i][ja], 1, "N", &a->ptr.pp_complex[ia+j][ja], 1, "Conj", ae_v_len(ja,ja+k-1));
24353 : }
24354 : else
24355 : {
24356 0 : v = ae_complex_from_i(0);
24357 : }
24358 0 : if( ae_fp_eq(beta,(double)(0)) )
24359 : {
24360 0 : c->ptr.pp_complex[ic+i][jc+j] = ae_c_mul_d(v,alpha);
24361 : }
24362 : else
24363 : {
24364 0 : c->ptr.pp_complex[ic+i][jc+j] = ae_c_add(ae_c_mul_d(c->ptr.pp_complex[ic+i][jc+j],beta),ae_c_mul_d(v,alpha));
24365 : }
24366 : }
24367 : }
24368 0 : return;
24369 : }
24370 : else
24371 : {
24372 :
24373 : /*
24374 : * C=alpha*A^H*A+beta*C
24375 : */
24376 0 : for(i=0; i<=n-1; i++)
24377 : {
24378 0 : if( isupper )
24379 : {
24380 0 : j1 = i;
24381 0 : j2 = n-1;
24382 : }
24383 : else
24384 : {
24385 0 : j1 = 0;
24386 0 : j2 = i;
24387 : }
24388 0 : if( ae_fp_eq(beta,(double)(0)) )
24389 : {
24390 0 : for(j=j1; j<=j2; j++)
24391 : {
24392 0 : c->ptr.pp_complex[ic+i][jc+j] = ae_complex_from_i(0);
24393 : }
24394 : }
24395 : else
24396 : {
24397 0 : ae_v_cmuld(&c->ptr.pp_complex[ic+i][jc+j1], 1, ae_v_len(jc+j1,jc+j2), beta);
24398 : }
24399 : }
24400 0 : if( ae_fp_neq(alpha,(double)(0))&&k>0 )
24401 : {
24402 0 : for(i=0; i<=k-1; i++)
24403 : {
24404 0 : for(j=0; j<=n-1; j++)
24405 : {
24406 0 : if( isupper )
24407 : {
24408 0 : j1 = j;
24409 0 : j2 = n-1;
24410 : }
24411 : else
24412 : {
24413 0 : j1 = 0;
24414 0 : j2 = j;
24415 : }
24416 0 : v = ae_c_mul_d(ae_c_conj(a->ptr.pp_complex[ia+i][ja+j], _state),alpha);
24417 0 : ae_v_caddc(&c->ptr.pp_complex[ic+j][jc+j1], 1, &a->ptr.pp_complex[ia+i][ja+j1], 1, "N", ae_v_len(jc+j1,jc+j2), v);
24418 : }
24419 : }
24420 : }
24421 0 : return;
24422 : }
24423 : }
24424 :
24425 :
24426 : /*************************************************************************
24427 : Level 2 subrotuine
24428 : *************************************************************************/
24429 0 : static void ablas_rmatrixsyrk2(ae_int_t n,
24430 : ae_int_t k,
24431 : double alpha,
24432 : /* Real */ ae_matrix* a,
24433 : ae_int_t ia,
24434 : ae_int_t ja,
24435 : ae_int_t optypea,
24436 : double beta,
24437 : /* Real */ ae_matrix* c,
24438 : ae_int_t ic,
24439 : ae_int_t jc,
24440 : ae_bool isupper,
24441 : ae_state *_state)
24442 : {
24443 : ae_int_t i;
24444 : ae_int_t j;
24445 : ae_int_t j1;
24446 : ae_int_t j2;
24447 : double v;
24448 :
24449 :
24450 :
24451 : /*
24452 : * Fast exit (nothing to be done)
24453 : */
24454 0 : if( (ae_fp_eq(alpha,(double)(0))||k==0)&&ae_fp_eq(beta,(double)(1)) )
24455 : {
24456 0 : return;
24457 : }
24458 :
24459 : /*
24460 : * Try to call fast SYRK
24461 : */
24462 0 : if( rmatrixsyrkf(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper, _state) )
24463 : {
24464 0 : return;
24465 : }
24466 :
24467 : /*
24468 : * SYRK
24469 : */
24470 0 : if( optypea==0 )
24471 : {
24472 :
24473 : /*
24474 : * C=alpha*A*A^H+beta*C
24475 : */
24476 0 : for(i=0; i<=n-1; i++)
24477 : {
24478 0 : if( isupper )
24479 : {
24480 0 : j1 = i;
24481 0 : j2 = n-1;
24482 : }
24483 : else
24484 : {
24485 0 : j1 = 0;
24486 0 : j2 = i;
24487 : }
24488 0 : for(j=j1; j<=j2; j++)
24489 : {
24490 0 : if( ae_fp_neq(alpha,(double)(0))&&k>0 )
24491 : {
24492 0 : v = ae_v_dotproduct(&a->ptr.pp_double[ia+i][ja], 1, &a->ptr.pp_double[ia+j][ja], 1, ae_v_len(ja,ja+k-1));
24493 : }
24494 : else
24495 : {
24496 0 : v = (double)(0);
24497 : }
24498 0 : if( ae_fp_eq(beta,(double)(0)) )
24499 : {
24500 0 : c->ptr.pp_double[ic+i][jc+j] = alpha*v;
24501 : }
24502 : else
24503 : {
24504 0 : c->ptr.pp_double[ic+i][jc+j] = beta*c->ptr.pp_double[ic+i][jc+j]+alpha*v;
24505 : }
24506 : }
24507 : }
24508 0 : return;
24509 : }
24510 : else
24511 : {
24512 :
24513 : /*
24514 : * C=alpha*A^H*A+beta*C
24515 : */
24516 0 : for(i=0; i<=n-1; i++)
24517 : {
24518 0 : if( isupper )
24519 : {
24520 0 : j1 = i;
24521 0 : j2 = n-1;
24522 : }
24523 : else
24524 : {
24525 0 : j1 = 0;
24526 0 : j2 = i;
24527 : }
24528 0 : if( ae_fp_eq(beta,(double)(0)) )
24529 : {
24530 0 : for(j=j1; j<=j2; j++)
24531 : {
24532 0 : c->ptr.pp_double[ic+i][jc+j] = (double)(0);
24533 : }
24534 : }
24535 : else
24536 : {
24537 0 : ae_v_muld(&c->ptr.pp_double[ic+i][jc+j1], 1, ae_v_len(jc+j1,jc+j2), beta);
24538 : }
24539 : }
24540 0 : if( ae_fp_neq(alpha,(double)(0))&&k>0 )
24541 : {
24542 0 : for(i=0; i<=k-1; i++)
24543 : {
24544 0 : for(j=0; j<=n-1; j++)
24545 : {
24546 0 : if( isupper )
24547 : {
24548 0 : j1 = j;
24549 0 : j2 = n-1;
24550 : }
24551 : else
24552 : {
24553 0 : j1 = 0;
24554 0 : j2 = j;
24555 : }
24556 0 : v = alpha*a->ptr.pp_double[ia+i][ja+j];
24557 0 : ae_v_addd(&c->ptr.pp_double[ic+j][jc+j1], 1, &a->ptr.pp_double[ia+i][ja+j1], 1, ae_v_len(jc+j1,jc+j2), v);
24558 : }
24559 : }
24560 : }
24561 0 : return;
24562 : }
24563 : }
24564 :
24565 :
24566 : /*************************************************************************
24567 : This subroutine is an actual implementation of CMatrixGEMM. It does not
24568 : perform some integrity checks performed in the driver function, and it
24569 : does not activate multithreading framework (driver decides whether to
24570 : activate workers or not).
24571 :
24572 : -- ALGLIB routine --
24573 : 10.01.2019
24574 : Bochkanov Sergey
24575 : *************************************************************************/
24576 0 : static void ablas_cmatrixgemmrec(ae_int_t m,
24577 : ae_int_t n,
24578 : ae_int_t k,
24579 : ae_complex alpha,
24580 : /* Complex */ ae_matrix* a,
24581 : ae_int_t ia,
24582 : ae_int_t ja,
24583 : ae_int_t optypea,
24584 : /* Complex */ ae_matrix* b,
24585 : ae_int_t ib,
24586 : ae_int_t jb,
24587 : ae_int_t optypeb,
24588 : ae_complex beta,
24589 : /* Complex */ ae_matrix* c,
24590 : ae_int_t ic,
24591 : ae_int_t jc,
24592 : ae_state *_state)
24593 : {
24594 : ae_int_t s1;
24595 : ae_int_t s2;
24596 : ae_int_t tsa;
24597 : ae_int_t tsb;
24598 : ae_int_t tscur;
24599 :
24600 :
24601 :
24602 : /*
24603 : * Tile hierarchy: B -> A -> A/2
24604 : */
24605 0 : tsa = matrixtilesizea(_state)/2;
24606 0 : tsb = matrixtilesizeb(_state);
24607 0 : tscur = tsb;
24608 0 : if( imax3(m, n, k, _state)<=tsb )
24609 : {
24610 0 : tscur = tsa;
24611 : }
24612 0 : ae_assert(tscur>=1, "CMatrixGEMMRec: integrity check failed", _state);
24613 :
24614 : /*
24615 : * Use MKL or ALGLIB basecase code
24616 : */
24617 0 : if( imax3(m, n, k, _state)<=tsb )
24618 : {
24619 0 : if( cmatrixgemmmkl(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state) )
24620 : {
24621 0 : return;
24622 : }
24623 : }
24624 0 : if( imax3(m, n, k, _state)<=tsa )
24625 : {
24626 0 : cmatrixgemmk(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24627 0 : return;
24628 : }
24629 :
24630 : /*
24631 : * Recursive algorithm: parallel splitting on M/N
24632 : */
24633 0 : if( m>=n&&m>=k )
24634 : {
24635 :
24636 : /*
24637 : * A*B = (A1 A2)^T*B
24638 : */
24639 0 : tiledsplit(m, tscur, &s1, &s2, _state);
24640 0 : ablas_cmatrixgemmrec(s1, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24641 0 : if( optypea==0 )
24642 : {
24643 0 : ablas_cmatrixgemmrec(s2, n, k, alpha, a, ia+s1, ja, optypea, b, ib, jb, optypeb, beta, c, ic+s1, jc, _state);
24644 : }
24645 : else
24646 : {
24647 0 : ablas_cmatrixgemmrec(s2, n, k, alpha, a, ia, ja+s1, optypea, b, ib, jb, optypeb, beta, c, ic+s1, jc, _state);
24648 : }
24649 0 : return;
24650 : }
24651 0 : if( n>=m&&n>=k )
24652 : {
24653 :
24654 : /*
24655 : * A*B = A*(B1 B2)
24656 : */
24657 0 : tiledsplit(n, tscur, &s1, &s2, _state);
24658 0 : if( optypeb==0 )
24659 : {
24660 0 : ablas_cmatrixgemmrec(m, s1, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24661 0 : ablas_cmatrixgemmrec(m, s2, k, alpha, a, ia, ja, optypea, b, ib, jb+s1, optypeb, beta, c, ic, jc+s1, _state);
24662 : }
24663 : else
24664 : {
24665 0 : ablas_cmatrixgemmrec(m, s1, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24666 0 : ablas_cmatrixgemmrec(m, s2, k, alpha, a, ia, ja, optypea, b, ib+s1, jb, optypeb, beta, c, ic, jc+s1, _state);
24667 : }
24668 0 : return;
24669 : }
24670 :
24671 : /*
24672 : * Recursive algorithm: serial splitting on K
24673 : */
24674 :
24675 : /*
24676 : * A*B = (A1 A2)*(B1 B2)^T
24677 : */
24678 0 : tiledsplit(k, tscur, &s1, &s2, _state);
24679 0 : if( optypea==0&&optypeb==0 )
24680 : {
24681 0 : ablas_cmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24682 0 : ablas_cmatrixgemmrec(m, n, s2, alpha, a, ia, ja+s1, optypea, b, ib+s1, jb, optypeb, ae_complex_from_d(1.0), c, ic, jc, _state);
24683 : }
24684 0 : if( optypea==0&&optypeb!=0 )
24685 : {
24686 0 : ablas_cmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24687 0 : ablas_cmatrixgemmrec(m, n, s2, alpha, a, ia, ja+s1, optypea, b, ib, jb+s1, optypeb, ae_complex_from_d(1.0), c, ic, jc, _state);
24688 : }
24689 0 : if( optypea!=0&&optypeb==0 )
24690 : {
24691 0 : ablas_cmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24692 0 : ablas_cmatrixgemmrec(m, n, s2, alpha, a, ia+s1, ja, optypea, b, ib+s1, jb, optypeb, ae_complex_from_d(1.0), c, ic, jc, _state);
24693 : }
24694 0 : if( optypea!=0&&optypeb!=0 )
24695 : {
24696 0 : ablas_cmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24697 0 : ablas_cmatrixgemmrec(m, n, s2, alpha, a, ia+s1, ja, optypea, b, ib, jb+s1, optypeb, ae_complex_from_d(1.0), c, ic, jc, _state);
24698 : }
24699 : }
24700 :
24701 :
24702 : /*************************************************************************
24703 : Serial stub for GPL edition.
24704 : *************************************************************************/
24705 0 : ae_bool _trypexec_ablas_cmatrixgemmrec(ae_int_t m,
24706 : ae_int_t n,
24707 : ae_int_t k,
24708 : ae_complex alpha,
24709 : /* Complex */ ae_matrix* a,
24710 : ae_int_t ia,
24711 : ae_int_t ja,
24712 : ae_int_t optypea,
24713 : /* Complex */ ae_matrix* b,
24714 : ae_int_t ib,
24715 : ae_int_t jb,
24716 : ae_int_t optypeb,
24717 : ae_complex beta,
24718 : /* Complex */ ae_matrix* c,
24719 : ae_int_t ic,
24720 : ae_int_t jc,
24721 : ae_state *_state)
24722 : {
24723 0 : return ae_false;
24724 : }
24725 :
24726 :
24727 : /*************************************************************************
24728 : This subroutine is an actual implementation of RMatrixGEMM. It does not
24729 : perform some integrity checks performed in the driver function, and it
24730 : does not activate multithreading framework (driver decides whether to
24731 : activate workers or not).
24732 :
24733 : -- ALGLIB routine --
24734 : 10.01.2019
24735 : Bochkanov Sergey
24736 : *************************************************************************/
24737 0 : static void ablas_rmatrixgemmrec(ae_int_t m,
24738 : ae_int_t n,
24739 : ae_int_t k,
24740 : double alpha,
24741 : /* Real */ ae_matrix* a,
24742 : ae_int_t ia,
24743 : ae_int_t ja,
24744 : ae_int_t optypea,
24745 : /* Real */ ae_matrix* b,
24746 : ae_int_t ib,
24747 : ae_int_t jb,
24748 : ae_int_t optypeb,
24749 : double beta,
24750 : /* Real */ ae_matrix* c,
24751 : ae_int_t ic,
24752 : ae_int_t jc,
24753 : ae_state *_state)
24754 : {
24755 : ae_int_t s1;
24756 : ae_int_t s2;
24757 : ae_int_t tsa;
24758 : ae_int_t tsb;
24759 : ae_int_t tscur;
24760 :
24761 :
24762 0 : tsa = matrixtilesizea(_state);
24763 0 : tsb = matrixtilesizeb(_state);
24764 0 : tscur = tsb;
24765 0 : if( imax3(m, n, k, _state)<=tsb )
24766 : {
24767 0 : tscur = tsa;
24768 : }
24769 0 : ae_assert(tscur>=1, "RMatrixGEMMRec: integrity check failed", _state);
24770 :
24771 : /*
24772 : * Use MKL or ALGLIB basecase code
24773 : */
24774 0 : if( (m<=tsb&&n<=tsb)&&k<=tsb )
24775 : {
24776 0 : if( rmatrixgemmmkl(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state) )
24777 : {
24778 0 : return;
24779 : }
24780 : }
24781 0 : if( (m<=tsa&&n<=tsa)&&k<=tsa )
24782 : {
24783 0 : rmatrixgemmk(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24784 0 : return;
24785 : }
24786 :
24787 : /*
24788 : * Recursive algorithm: split on M or N
24789 : */
24790 0 : if( m>=n&&m>=k )
24791 : {
24792 :
24793 : /*
24794 : * A*B = (A1 A2)^T*B
24795 : */
24796 0 : tiledsplit(m, tscur, &s1, &s2, _state);
24797 0 : if( optypea==0 )
24798 : {
24799 0 : ablas_rmatrixgemmrec(s2, n, k, alpha, a, ia+s1, ja, optypea, b, ib, jb, optypeb, beta, c, ic+s1, jc, _state);
24800 0 : ablas_rmatrixgemmrec(s1, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24801 : }
24802 : else
24803 : {
24804 0 : ablas_rmatrixgemmrec(s2, n, k, alpha, a, ia, ja+s1, optypea, b, ib, jb, optypeb, beta, c, ic+s1, jc, _state);
24805 0 : ablas_rmatrixgemmrec(s1, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24806 : }
24807 0 : return;
24808 : }
24809 0 : if( n>=m&&n>=k )
24810 : {
24811 :
24812 : /*
24813 : * A*B = A*(B1 B2)
24814 : */
24815 0 : tiledsplit(n, tscur, &s1, &s2, _state);
24816 0 : if( optypeb==0 )
24817 : {
24818 0 : ablas_rmatrixgemmrec(m, s2, k, alpha, a, ia, ja, optypea, b, ib, jb+s1, optypeb, beta, c, ic, jc+s1, _state);
24819 0 : ablas_rmatrixgemmrec(m, s1, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24820 : }
24821 : else
24822 : {
24823 0 : ablas_rmatrixgemmrec(m, s2, k, alpha, a, ia, ja, optypea, b, ib+s1, jb, optypeb, beta, c, ic, jc+s1, _state);
24824 0 : ablas_rmatrixgemmrec(m, s1, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24825 : }
24826 0 : return;
24827 : }
24828 :
24829 : /*
24830 : * Recursive algorithm: split on K
24831 : */
24832 :
24833 : /*
24834 : * A*B = (A1 A2)*(B1 B2)^T
24835 : */
24836 0 : tiledsplit(k, tscur, &s1, &s2, _state);
24837 0 : if( optypea==0&&optypeb==0 )
24838 : {
24839 0 : ablas_rmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24840 0 : ablas_rmatrixgemmrec(m, n, s2, alpha, a, ia, ja+s1, optypea, b, ib+s1, jb, optypeb, 1.0, c, ic, jc, _state);
24841 : }
24842 0 : if( optypea==0&&optypeb!=0 )
24843 : {
24844 0 : ablas_rmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24845 0 : ablas_rmatrixgemmrec(m, n, s2, alpha, a, ia, ja+s1, optypea, b, ib, jb+s1, optypeb, 1.0, c, ic, jc, _state);
24846 : }
24847 0 : if( optypea!=0&&optypeb==0 )
24848 : {
24849 0 : ablas_rmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24850 0 : ablas_rmatrixgemmrec(m, n, s2, alpha, a, ia+s1, ja, optypea, b, ib+s1, jb, optypeb, 1.0, c, ic, jc, _state);
24851 : }
24852 0 : if( optypea!=0&&optypeb!=0 )
24853 : {
24854 0 : ablas_rmatrixgemmrec(m, n, s1, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc, _state);
24855 0 : ablas_rmatrixgemmrec(m, n, s2, alpha, a, ia+s1, ja, optypea, b, ib, jb+s1, optypeb, 1.0, c, ic, jc, _state);
24856 : }
24857 : }
24858 :
24859 :
24860 : /*************************************************************************
24861 : Serial stub for GPL edition.
24862 : *************************************************************************/
24863 0 : ae_bool _trypexec_ablas_rmatrixgemmrec(ae_int_t m,
24864 : ae_int_t n,
24865 : ae_int_t k,
24866 : double alpha,
24867 : /* Real */ ae_matrix* a,
24868 : ae_int_t ia,
24869 : ae_int_t ja,
24870 : ae_int_t optypea,
24871 : /* Real */ ae_matrix* b,
24872 : ae_int_t ib,
24873 : ae_int_t jb,
24874 : ae_int_t optypeb,
24875 : double beta,
24876 : /* Real */ ae_matrix* c,
24877 : ae_int_t ic,
24878 : ae_int_t jc,
24879 : ae_state *_state)
24880 : {
24881 0 : return ae_false;
24882 : }
24883 :
24884 :
24885 : #endif
24886 : #if defined(AE_COMPILE_DLU) || !defined(AE_PARTIAL_BUILD)
24887 :
24888 :
24889 : /*************************************************************************
24890 : Recurrent complex LU subroutine.
24891 : Never call it directly.
24892 :
24893 : -- ALGLIB routine --
24894 : 04.01.2010
24895 : Bochkanov Sergey
24896 : *************************************************************************/
24897 0 : void cmatrixluprec(/* Complex */ ae_matrix* a,
24898 : ae_int_t offs,
24899 : ae_int_t m,
24900 : ae_int_t n,
24901 : /* Integer */ ae_vector* pivots,
24902 : /* Complex */ ae_vector* tmp,
24903 : ae_state *_state)
24904 : {
24905 : ae_int_t i;
24906 : ae_int_t m1;
24907 : ae_int_t m2;
24908 :
24909 :
24910 0 : if( ae_minint(m, n, _state)<=ablascomplexblocksize(a, _state) )
24911 : {
24912 0 : dlu_cmatrixlup2(a, offs, m, n, pivots, tmp, _state);
24913 0 : return;
24914 : }
24915 0 : if( m>n )
24916 : {
24917 0 : cmatrixluprec(a, offs, n, n, pivots, tmp, _state);
24918 0 : for(i=0; i<=n-1; i++)
24919 : {
24920 0 : ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+n][offs+i], a->stride, "N", ae_v_len(0,m-n-1));
24921 0 : ae_v_cmove(&a->ptr.pp_complex[offs+n][offs+i], a->stride, &a->ptr.pp_complex[offs+n][pivots->ptr.p_int[offs+i]], a->stride, "N", ae_v_len(offs+n,offs+m-1));
24922 0 : ae_v_cmove(&a->ptr.pp_complex[offs+n][pivots->ptr.p_int[offs+i]], a->stride, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs+n,offs+m-1));
24923 : }
24924 0 : cmatrixrighttrsm(m-n, n, a, offs, offs, ae_true, ae_true, 0, a, offs+n, offs, _state);
24925 0 : return;
24926 : }
24927 0 : ablascomplexsplitlength(a, m, &m1, &m2, _state);
24928 0 : cmatrixluprec(a, offs, m1, n, pivots, tmp, _state);
24929 0 : if( m2>0 )
24930 : {
24931 0 : for(i=0; i<=m1-1; i++)
24932 : {
24933 0 : if( offs+i!=pivots->ptr.p_int[offs+i] )
24934 : {
24935 0 : ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+m1][offs+i], a->stride, "N", ae_v_len(0,m2-1));
24936 0 : ae_v_cmove(&a->ptr.pp_complex[offs+m1][offs+i], a->stride, &a->ptr.pp_complex[offs+m1][pivots->ptr.p_int[offs+i]], a->stride, "N", ae_v_len(offs+m1,offs+m-1));
24937 0 : ae_v_cmove(&a->ptr.pp_complex[offs+m1][pivots->ptr.p_int[offs+i]], a->stride, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs+m1,offs+m-1));
24938 : }
24939 : }
24940 0 : cmatrixrighttrsm(m2, m1, a, offs, offs, ae_true, ae_true, 0, a, offs+m1, offs, _state);
24941 0 : cmatrixgemm(m-m1, n-m1, m1, ae_complex_from_d(-1.0), a, offs+m1, offs, 0, a, offs, offs+m1, 0, ae_complex_from_d(1.0), a, offs+m1, offs+m1, _state);
24942 0 : cmatrixluprec(a, offs+m1, m-m1, n-m1, pivots, tmp, _state);
24943 0 : for(i=0; i<=m2-1; i++)
24944 : {
24945 0 : if( offs+m1+i!=pivots->ptr.p_int[offs+m1+i] )
24946 : {
24947 0 : ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs][offs+m1+i], a->stride, "N", ae_v_len(0,m1-1));
24948 0 : ae_v_cmove(&a->ptr.pp_complex[offs][offs+m1+i], a->stride, &a->ptr.pp_complex[offs][pivots->ptr.p_int[offs+m1+i]], a->stride, "N", ae_v_len(offs,offs+m1-1));
24949 0 : ae_v_cmove(&a->ptr.pp_complex[offs][pivots->ptr.p_int[offs+m1+i]], a->stride, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs,offs+m1-1));
24950 : }
24951 : }
24952 : }
24953 : }
24954 :
24955 :
24956 : /*************************************************************************
24957 : Recurrent real LU subroutine.
24958 : Never call it directly.
24959 :
24960 : -- ALGLIB routine --
24961 : 04.01.2010
24962 : Bochkanov Sergey
24963 : *************************************************************************/
24964 0 : void rmatrixluprec(/* Real */ ae_matrix* a,
24965 : ae_int_t offs,
24966 : ae_int_t m,
24967 : ae_int_t n,
24968 : /* Integer */ ae_vector* pivots,
24969 : /* Real */ ae_vector* tmp,
24970 : ae_state *_state)
24971 : {
24972 : ae_int_t i;
24973 : ae_int_t m1;
24974 : ae_int_t m2;
24975 :
24976 :
24977 0 : if( ae_minint(m, n, _state)<=ablasblocksize(a, _state) )
24978 : {
24979 0 : dlu_rmatrixlup2(a, offs, m, n, pivots, tmp, _state);
24980 0 : return;
24981 : }
24982 0 : if( m>n )
24983 : {
24984 0 : rmatrixluprec(a, offs, n, n, pivots, tmp, _state);
24985 0 : for(i=0; i<=n-1; i++)
24986 : {
24987 0 : if( offs+i!=pivots->ptr.p_int[offs+i] )
24988 : {
24989 0 : ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+n][offs+i], a->stride, ae_v_len(0,m-n-1));
24990 0 : ae_v_move(&a->ptr.pp_double[offs+n][offs+i], a->stride, &a->ptr.pp_double[offs+n][pivots->ptr.p_int[offs+i]], a->stride, ae_v_len(offs+n,offs+m-1));
24991 0 : ae_v_move(&a->ptr.pp_double[offs+n][pivots->ptr.p_int[offs+i]], a->stride, &tmp->ptr.p_double[0], 1, ae_v_len(offs+n,offs+m-1));
24992 : }
24993 : }
24994 0 : rmatrixrighttrsm(m-n, n, a, offs, offs, ae_true, ae_true, 0, a, offs+n, offs, _state);
24995 0 : return;
24996 : }
24997 0 : ablassplitlength(a, m, &m1, &m2, _state);
24998 0 : rmatrixluprec(a, offs, m1, n, pivots, tmp, _state);
24999 0 : if( m2>0 )
25000 : {
25001 0 : for(i=0; i<=m1-1; i++)
25002 : {
25003 0 : if( offs+i!=pivots->ptr.p_int[offs+i] )
25004 : {
25005 0 : ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+m1][offs+i], a->stride, ae_v_len(0,m2-1));
25006 0 : ae_v_move(&a->ptr.pp_double[offs+m1][offs+i], a->stride, &a->ptr.pp_double[offs+m1][pivots->ptr.p_int[offs+i]], a->stride, ae_v_len(offs+m1,offs+m-1));
25007 0 : ae_v_move(&a->ptr.pp_double[offs+m1][pivots->ptr.p_int[offs+i]], a->stride, &tmp->ptr.p_double[0], 1, ae_v_len(offs+m1,offs+m-1));
25008 : }
25009 : }
25010 0 : rmatrixrighttrsm(m2, m1, a, offs, offs, ae_true, ae_true, 0, a, offs+m1, offs, _state);
25011 0 : rmatrixgemm(m-m1, n-m1, m1, -1.0, a, offs+m1, offs, 0, a, offs, offs+m1, 0, 1.0, a, offs+m1, offs+m1, _state);
25012 0 : rmatrixluprec(a, offs+m1, m-m1, n-m1, pivots, tmp, _state);
25013 0 : for(i=0; i<=m2-1; i++)
25014 : {
25015 0 : if( offs+m1+i!=pivots->ptr.p_int[offs+m1+i] )
25016 : {
25017 0 : ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs][offs+m1+i], a->stride, ae_v_len(0,m1-1));
25018 0 : ae_v_move(&a->ptr.pp_double[offs][offs+m1+i], a->stride, &a->ptr.pp_double[offs][pivots->ptr.p_int[offs+m1+i]], a->stride, ae_v_len(offs,offs+m1-1));
25019 0 : ae_v_move(&a->ptr.pp_double[offs][pivots->ptr.p_int[offs+m1+i]], a->stride, &tmp->ptr.p_double[0], 1, ae_v_len(offs,offs+m1-1));
25020 : }
25021 : }
25022 : }
25023 : }
25024 :
25025 :
25026 : /*************************************************************************
25027 : Recurrent complex LU subroutine.
25028 : Never call it directly.
25029 :
25030 : -- ALGLIB routine --
25031 : 04.01.2010
25032 : Bochkanov Sergey
25033 : *************************************************************************/
25034 0 : void cmatrixplurec(/* Complex */ ae_matrix* a,
25035 : ae_int_t offs,
25036 : ae_int_t m,
25037 : ae_int_t n,
25038 : /* Integer */ ae_vector* pivots,
25039 : /* Complex */ ae_vector* tmp,
25040 : ae_state *_state)
25041 : {
25042 : ae_int_t i;
25043 : ae_int_t n1;
25044 : ae_int_t n2;
25045 : ae_int_t tsa;
25046 : ae_int_t tsb;
25047 :
25048 :
25049 0 : tsa = matrixtilesizea(_state)/2;
25050 0 : tsb = matrixtilesizeb(_state);
25051 0 : if( n<=tsa )
25052 : {
25053 0 : dlu_cmatrixplu2(a, offs, m, n, pivots, tmp, _state);
25054 0 : return;
25055 : }
25056 0 : if( n>m )
25057 : {
25058 0 : cmatrixplurec(a, offs, m, m, pivots, tmp, _state);
25059 0 : for(i=0; i<=m-1; i++)
25060 : {
25061 0 : ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+i][offs+m], 1, "N", ae_v_len(0,n-m-1));
25062 0 : ae_v_cmove(&a->ptr.pp_complex[offs+i][offs+m], 1, &a->ptr.pp_complex[pivots->ptr.p_int[offs+i]][offs+m], 1, "N", ae_v_len(offs+m,offs+n-1));
25063 0 : ae_v_cmove(&a->ptr.pp_complex[pivots->ptr.p_int[offs+i]][offs+m], 1, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs+m,offs+n-1));
25064 : }
25065 0 : cmatrixlefttrsm(m, n-m, a, offs, offs, ae_false, ae_true, 0, a, offs, offs+m, _state);
25066 0 : return;
25067 : }
25068 0 : if( n>tsb )
25069 : {
25070 0 : n1 = tsb;
25071 0 : n2 = n-n1;
25072 : }
25073 : else
25074 : {
25075 0 : tiledsplit(n, tsa, &n1, &n2, _state);
25076 : }
25077 0 : cmatrixplurec(a, offs, m, n1, pivots, tmp, _state);
25078 0 : if( n2>0 )
25079 : {
25080 0 : for(i=0; i<=n1-1; i++)
25081 : {
25082 0 : if( offs+i!=pivots->ptr.p_int[offs+i] )
25083 : {
25084 0 : ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+i][offs+n1], 1, "N", ae_v_len(0,n2-1));
25085 0 : ae_v_cmove(&a->ptr.pp_complex[offs+i][offs+n1], 1, &a->ptr.pp_complex[pivots->ptr.p_int[offs+i]][offs+n1], 1, "N", ae_v_len(offs+n1,offs+n-1));
25086 0 : ae_v_cmove(&a->ptr.pp_complex[pivots->ptr.p_int[offs+i]][offs+n1], 1, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs+n1,offs+n-1));
25087 : }
25088 : }
25089 0 : cmatrixlefttrsm(n1, n2, a, offs, offs, ae_false, ae_true, 0, a, offs, offs+n1, _state);
25090 0 : cmatrixgemm(m-n1, n-n1, n1, ae_complex_from_d(-1.0), a, offs+n1, offs, 0, a, offs, offs+n1, 0, ae_complex_from_d(1.0), a, offs+n1, offs+n1, _state);
25091 0 : cmatrixplurec(a, offs+n1, m-n1, n-n1, pivots, tmp, _state);
25092 0 : for(i=0; i<=n2-1; i++)
25093 : {
25094 0 : if( offs+n1+i!=pivots->ptr.p_int[offs+n1+i] )
25095 : {
25096 0 : ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+n1+i][offs], 1, "N", ae_v_len(0,n1-1));
25097 0 : ae_v_cmove(&a->ptr.pp_complex[offs+n1+i][offs], 1, &a->ptr.pp_complex[pivots->ptr.p_int[offs+n1+i]][offs], 1, "N", ae_v_len(offs,offs+n1-1));
25098 0 : ae_v_cmove(&a->ptr.pp_complex[pivots->ptr.p_int[offs+n1+i]][offs], 1, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs,offs+n1-1));
25099 : }
25100 : }
25101 : }
25102 : }
25103 :
25104 :
25105 : /*************************************************************************
25106 : Recurrent real LU subroutine.
25107 : Never call it directly.
25108 :
25109 : -- ALGLIB routine --
25110 : 04.01.2010
25111 : Bochkanov Sergey
25112 : *************************************************************************/
25113 0 : void rmatrixplurec(/* Real */ ae_matrix* a,
25114 : ae_int_t offs,
25115 : ae_int_t m,
25116 : ae_int_t n,
25117 : /* Integer */ ae_vector* pivots,
25118 : /* Real */ ae_vector* tmp,
25119 : ae_state *_state)
25120 : {
25121 : ae_int_t i;
25122 : ae_int_t n1;
25123 : ae_int_t n2;
25124 : ae_int_t tsa;
25125 : ae_int_t tsb;
25126 :
25127 :
25128 0 : tsa = matrixtilesizea(_state);
25129 0 : tsb = matrixtilesizeb(_state);
25130 0 : if( n<=tsb )
25131 : {
25132 0 : if( rmatrixplumkl(a, offs, m, n, pivots, _state) )
25133 : {
25134 0 : return;
25135 : }
25136 : }
25137 0 : if( n<=tsa )
25138 : {
25139 0 : dlu_rmatrixplu2(a, offs, m, n, pivots, tmp, _state);
25140 0 : return;
25141 : }
25142 0 : if( n>m )
25143 : {
25144 0 : rmatrixplurec(a, offs, m, m, pivots, tmp, _state);
25145 0 : for(i=0; i<=m-1; i++)
25146 : {
25147 0 : ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+i][offs+m], 1, ae_v_len(0,n-m-1));
25148 0 : ae_v_move(&a->ptr.pp_double[offs+i][offs+m], 1, &a->ptr.pp_double[pivots->ptr.p_int[offs+i]][offs+m], 1, ae_v_len(offs+m,offs+n-1));
25149 0 : ae_v_move(&a->ptr.pp_double[pivots->ptr.p_int[offs+i]][offs+m], 1, &tmp->ptr.p_double[0], 1, ae_v_len(offs+m,offs+n-1));
25150 : }
25151 0 : rmatrixlefttrsm(m, n-m, a, offs, offs, ae_false, ae_true, 0, a, offs, offs+m, _state);
25152 0 : return;
25153 : }
25154 0 : if( n>tsb )
25155 : {
25156 0 : n1 = tsb;
25157 0 : n2 = n-n1;
25158 : }
25159 : else
25160 : {
25161 0 : tiledsplit(n, tsa, &n1, &n2, _state);
25162 : }
25163 0 : rmatrixplurec(a, offs, m, n1, pivots, tmp, _state);
25164 0 : if( n2>0 )
25165 : {
25166 0 : for(i=0; i<=n1-1; i++)
25167 : {
25168 0 : if( offs+i!=pivots->ptr.p_int[offs+i] )
25169 : {
25170 0 : ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+i][offs+n1], 1, ae_v_len(0,n2-1));
25171 0 : ae_v_move(&a->ptr.pp_double[offs+i][offs+n1], 1, &a->ptr.pp_double[pivots->ptr.p_int[offs+i]][offs+n1], 1, ae_v_len(offs+n1,offs+n-1));
25172 0 : ae_v_move(&a->ptr.pp_double[pivots->ptr.p_int[offs+i]][offs+n1], 1, &tmp->ptr.p_double[0], 1, ae_v_len(offs+n1,offs+n-1));
25173 : }
25174 : }
25175 0 : rmatrixlefttrsm(n1, n2, a, offs, offs, ae_false, ae_true, 0, a, offs, offs+n1, _state);
25176 0 : rmatrixgemm(m-n1, n-n1, n1, -1.0, a, offs+n1, offs, 0, a, offs, offs+n1, 0, 1.0, a, offs+n1, offs+n1, _state);
25177 0 : rmatrixplurec(a, offs+n1, m-n1, n-n1, pivots, tmp, _state);
25178 0 : for(i=0; i<=n2-1; i++)
25179 : {
25180 0 : if( offs+n1+i!=pivots->ptr.p_int[offs+n1+i] )
25181 : {
25182 0 : ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+n1+i][offs], 1, ae_v_len(0,n1-1));
25183 0 : ae_v_move(&a->ptr.pp_double[offs+n1+i][offs], 1, &a->ptr.pp_double[pivots->ptr.p_int[offs+n1+i]][offs], 1, ae_v_len(offs,offs+n1-1));
25184 0 : ae_v_move(&a->ptr.pp_double[pivots->ptr.p_int[offs+n1+i]][offs], 1, &tmp->ptr.p_double[0], 1, ae_v_len(offs,offs+n1-1));
25185 : }
25186 : }
25187 : }
25188 : }
25189 :
25190 :
25191 : /*************************************************************************
25192 : Complex LUP kernel
25193 :
25194 : -- ALGLIB routine --
25195 : 10.01.2010
25196 : Bochkanov Sergey
25197 : *************************************************************************/
25198 0 : static void dlu_cmatrixlup2(/* Complex */ ae_matrix* a,
25199 : ae_int_t offs,
25200 : ae_int_t m,
25201 : ae_int_t n,
25202 : /* Integer */ ae_vector* pivots,
25203 : /* Complex */ ae_vector* tmp,
25204 : ae_state *_state)
25205 : {
25206 : ae_int_t i;
25207 : ae_int_t j;
25208 : ae_int_t jp;
25209 : ae_complex s;
25210 :
25211 :
25212 0 : if( m==0||n==0 )
25213 : {
25214 0 : return;
25215 : }
25216 0 : for(j=0; j<=ae_minint(m-1, n-1, _state); j++)
25217 : {
25218 0 : jp = j;
25219 0 : for(i=j+1; i<=n-1; i++)
25220 : {
25221 0 : if( ae_fp_greater(ae_c_abs(a->ptr.pp_complex[offs+j][offs+i], _state),ae_c_abs(a->ptr.pp_complex[offs+j][offs+jp], _state)) )
25222 : {
25223 0 : jp = i;
25224 : }
25225 : }
25226 0 : pivots->ptr.p_int[offs+j] = offs+jp;
25227 0 : if( jp!=j )
25228 : {
25229 0 : ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs][offs+j], a->stride, "N", ae_v_len(0,m-1));
25230 0 : ae_v_cmove(&a->ptr.pp_complex[offs][offs+j], a->stride, &a->ptr.pp_complex[offs][offs+jp], a->stride, "N", ae_v_len(offs,offs+m-1));
25231 0 : ae_v_cmove(&a->ptr.pp_complex[offs][offs+jp], a->stride, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs,offs+m-1));
25232 : }
25233 0 : if( ae_c_neq_d(a->ptr.pp_complex[offs+j][offs+j],(double)(0))&&j+1<=n-1 )
25234 : {
25235 0 : s = ae_c_d_div(1,a->ptr.pp_complex[offs+j][offs+j]);
25236 0 : ae_v_cmulc(&a->ptr.pp_complex[offs+j][offs+j+1], 1, ae_v_len(offs+j+1,offs+n-1), s);
25237 : }
25238 0 : if( j<ae_minint(m-1, n-1, _state) )
25239 : {
25240 0 : ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+j+1][offs+j], a->stride, "N", ae_v_len(0,m-j-2));
25241 0 : ae_v_cmoveneg(&tmp->ptr.p_complex[m], 1, &a->ptr.pp_complex[offs+j][offs+j+1], 1, "N", ae_v_len(m,m+n-j-2));
25242 0 : cmatrixrank1(m-j-1, n-j-1, a, offs+j+1, offs+j+1, tmp, 0, tmp, m, _state);
25243 : }
25244 : }
25245 : }
25246 :
25247 :
25248 : /*************************************************************************
25249 : Real LUP kernel
25250 :
25251 : -- ALGLIB routine --
25252 : 10.01.2010
25253 : Bochkanov Sergey
25254 : *************************************************************************/
25255 0 : static void dlu_rmatrixlup2(/* Real */ ae_matrix* a,
25256 : ae_int_t offs,
25257 : ae_int_t m,
25258 : ae_int_t n,
25259 : /* Integer */ ae_vector* pivots,
25260 : /* Real */ ae_vector* tmp,
25261 : ae_state *_state)
25262 : {
25263 : ae_int_t i;
25264 : ae_int_t j;
25265 : ae_int_t jp;
25266 : double s;
25267 :
25268 :
25269 0 : if( m==0||n==0 )
25270 : {
25271 0 : return;
25272 : }
25273 0 : for(j=0; j<=ae_minint(m-1, n-1, _state); j++)
25274 : {
25275 0 : jp = j;
25276 0 : for(i=j+1; i<=n-1; i++)
25277 : {
25278 0 : if( ae_fp_greater(ae_fabs(a->ptr.pp_double[offs+j][offs+i], _state),ae_fabs(a->ptr.pp_double[offs+j][offs+jp], _state)) )
25279 : {
25280 0 : jp = i;
25281 : }
25282 : }
25283 0 : pivots->ptr.p_int[offs+j] = offs+jp;
25284 0 : if( jp!=j )
25285 : {
25286 0 : ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs][offs+j], a->stride, ae_v_len(0,m-1));
25287 0 : ae_v_move(&a->ptr.pp_double[offs][offs+j], a->stride, &a->ptr.pp_double[offs][offs+jp], a->stride, ae_v_len(offs,offs+m-1));
25288 0 : ae_v_move(&a->ptr.pp_double[offs][offs+jp], a->stride, &tmp->ptr.p_double[0], 1, ae_v_len(offs,offs+m-1));
25289 : }
25290 0 : if( ae_fp_neq(a->ptr.pp_double[offs+j][offs+j],(double)(0))&&j+1<=n-1 )
25291 : {
25292 0 : s = 1/a->ptr.pp_double[offs+j][offs+j];
25293 0 : ae_v_muld(&a->ptr.pp_double[offs+j][offs+j+1], 1, ae_v_len(offs+j+1,offs+n-1), s);
25294 : }
25295 0 : if( j<ae_minint(m-1, n-1, _state) )
25296 : {
25297 0 : ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+j+1][offs+j], a->stride, ae_v_len(0,m-j-2));
25298 0 : ae_v_moveneg(&tmp->ptr.p_double[m], 1, &a->ptr.pp_double[offs+j][offs+j+1], 1, ae_v_len(m,m+n-j-2));
25299 0 : rmatrixrank1(m-j-1, n-j-1, a, offs+j+1, offs+j+1, tmp, 0, tmp, m, _state);
25300 : }
25301 : }
25302 : }
25303 :
25304 :
25305 : /*************************************************************************
25306 : Complex PLU kernel
25307 :
25308 : -- LAPACK routine (version 3.0) --
25309 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
25310 : Courant Institute, Argonne National Lab, and Rice University
25311 : June 30, 1992
25312 : *************************************************************************/
25313 0 : static void dlu_cmatrixplu2(/* Complex */ ae_matrix* a,
25314 : ae_int_t offs,
25315 : ae_int_t m,
25316 : ae_int_t n,
25317 : /* Integer */ ae_vector* pivots,
25318 : /* Complex */ ae_vector* tmp,
25319 : ae_state *_state)
25320 : {
25321 : ae_int_t i;
25322 : ae_int_t j;
25323 : ae_int_t jp;
25324 : ae_complex s;
25325 :
25326 :
25327 0 : if( m==0||n==0 )
25328 : {
25329 0 : return;
25330 : }
25331 0 : for(j=0; j<=ae_minint(m-1, n-1, _state); j++)
25332 : {
25333 0 : jp = j;
25334 0 : for(i=j+1; i<=m-1; i++)
25335 : {
25336 0 : if( ae_fp_greater(ae_c_abs(a->ptr.pp_complex[offs+i][offs+j], _state),ae_c_abs(a->ptr.pp_complex[offs+jp][offs+j], _state)) )
25337 : {
25338 0 : jp = i;
25339 : }
25340 : }
25341 0 : pivots->ptr.p_int[offs+j] = offs+jp;
25342 0 : if( ae_c_neq_d(a->ptr.pp_complex[offs+jp][offs+j],(double)(0)) )
25343 : {
25344 0 : if( jp!=j )
25345 : {
25346 0 : for(i=0; i<=n-1; i++)
25347 : {
25348 0 : s = a->ptr.pp_complex[offs+j][offs+i];
25349 0 : a->ptr.pp_complex[offs+j][offs+i] = a->ptr.pp_complex[offs+jp][offs+i];
25350 0 : a->ptr.pp_complex[offs+jp][offs+i] = s;
25351 : }
25352 : }
25353 0 : if( j+1<=m-1 )
25354 : {
25355 0 : s = ae_c_d_div(1,a->ptr.pp_complex[offs+j][offs+j]);
25356 0 : ae_v_cmulc(&a->ptr.pp_complex[offs+j+1][offs+j], a->stride, ae_v_len(offs+j+1,offs+m-1), s);
25357 : }
25358 : }
25359 0 : if( j<ae_minint(m, n, _state)-1 )
25360 : {
25361 0 : ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+j+1][offs+j], a->stride, "N", ae_v_len(0,m-j-2));
25362 0 : ae_v_cmoveneg(&tmp->ptr.p_complex[m], 1, &a->ptr.pp_complex[offs+j][offs+j+1], 1, "N", ae_v_len(m,m+n-j-2));
25363 0 : cmatrixrank1(m-j-1, n-j-1, a, offs+j+1, offs+j+1, tmp, 0, tmp, m, _state);
25364 : }
25365 : }
25366 : }
25367 :
25368 :
25369 : /*************************************************************************
25370 : Real PLU kernel
25371 :
25372 : -- LAPACK routine (version 3.0) --
25373 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
25374 : Courant Institute, Argonne National Lab, and Rice University
25375 : June 30, 1992
25376 : *************************************************************************/
25377 0 : static void dlu_rmatrixplu2(/* Real */ ae_matrix* a,
25378 : ae_int_t offs,
25379 : ae_int_t m,
25380 : ae_int_t n,
25381 : /* Integer */ ae_vector* pivots,
25382 : /* Real */ ae_vector* tmp,
25383 : ae_state *_state)
25384 : {
25385 : ae_int_t i;
25386 : ae_int_t j;
25387 : ae_int_t jp;
25388 : double s;
25389 :
25390 :
25391 0 : if( m==0||n==0 )
25392 : {
25393 0 : return;
25394 : }
25395 0 : for(j=0; j<=ae_minint(m-1, n-1, _state); j++)
25396 : {
25397 0 : jp = j;
25398 0 : for(i=j+1; i<=m-1; i++)
25399 : {
25400 0 : if( ae_fp_greater(ae_fabs(a->ptr.pp_double[offs+i][offs+j], _state),ae_fabs(a->ptr.pp_double[offs+jp][offs+j], _state)) )
25401 : {
25402 0 : jp = i;
25403 : }
25404 : }
25405 0 : pivots->ptr.p_int[offs+j] = offs+jp;
25406 0 : if( ae_fp_neq(a->ptr.pp_double[offs+jp][offs+j],(double)(0)) )
25407 : {
25408 0 : if( jp!=j )
25409 : {
25410 0 : for(i=0; i<=n-1; i++)
25411 : {
25412 0 : s = a->ptr.pp_double[offs+j][offs+i];
25413 0 : a->ptr.pp_double[offs+j][offs+i] = a->ptr.pp_double[offs+jp][offs+i];
25414 0 : a->ptr.pp_double[offs+jp][offs+i] = s;
25415 : }
25416 : }
25417 0 : if( j+1<=m-1 )
25418 : {
25419 0 : s = 1/a->ptr.pp_double[offs+j][offs+j];
25420 0 : ae_v_muld(&a->ptr.pp_double[offs+j+1][offs+j], a->stride, ae_v_len(offs+j+1,offs+m-1), s);
25421 : }
25422 : }
25423 0 : if( j<ae_minint(m, n, _state)-1 )
25424 : {
25425 0 : ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+j+1][offs+j], a->stride, ae_v_len(0,m-j-2));
25426 0 : ae_v_moveneg(&tmp->ptr.p_double[m], 1, &a->ptr.pp_double[offs+j][offs+j+1], 1, ae_v_len(m,m+n-j-2));
25427 0 : rmatrixrank1(m-j-1, n-j-1, a, offs+j+1, offs+j+1, tmp, 0, tmp, m, _state);
25428 : }
25429 : }
25430 : }
25431 :
25432 :
25433 : #endif
25434 : #if defined(AE_COMPILE_SPTRF) || !defined(AE_PARTIAL_BUILD)
25435 :
25436 :
25437 : /*************************************************************************
25438 : Sparse LU for square NxN CRS matrix with both row and column permutations.
25439 :
25440 : Represents A as Pr*L*U*Pc, where:
25441 : * Pr is a product of row permutations Pr=Pr(0)*Pr(1)*...*Pr(n-2)*Pr(n-1)
25442 : * Pc is a product of col permutations Pc=Pc(n-1)*Pc(n-2)*...*Pc(1)*Pc(0)
25443 : * L is lower unitriangular
25444 : * U is upper triangular
25445 :
25446 : INPUT PARAMETERS:
25447 : A - sparse square matrix in CRS format
25448 : PivotType - pivot type:
25449 : * 0 - for best pivoting available
25450 : * 1 - row-only pivoting
25451 : * 2 - row and column greedy pivoting algorithm (most
25452 : sparse pivot column is selected from the trailing
25453 : matrix at each step)
25454 : Buf - temporary buffer, previously allocated memory is
25455 : reused as much as possible
25456 :
25457 : OUTPUT PARAMETERS:
25458 : A - LU decomposition of A
25459 : PR - array[N], row pivots
25460 : PC - array[N], column pivots
25461 : Buf - following fields of Buf are set:
25462 : * Buf.RowPermRawIdx[] - contains row permutation, with
25463 : RawIdx[I]=J meaning that J-th row of the original
25464 : input matrix was moved to Ith position of the output
25465 : factorization
25466 :
25467 : This function always succeeds i.e. it ALWAYS returns valid factorization,
25468 : but for your convenience it also returns boolean value which helps to
25469 : detect symbolically degenerate matrix:
25470 : * function returns TRUE if the matrix was factorized AND symbolically
25471 : non-degenerate
25472 : * function returns FALSE if the matrix was factorized but U has strictly
25473 : zero elements at the diagonal (the factorization is returned anyway).
25474 :
25475 : -- ALGLIB routine --
25476 : 15.01.2019
25477 : Bochkanov Sergey
25478 : *************************************************************************/
25479 0 : ae_bool sptrflu(sparsematrix* a,
25480 : ae_int_t pivottype,
25481 : /* Integer */ ae_vector* pr,
25482 : /* Integer */ ae_vector* pc,
25483 : sluv2buffer* buf,
25484 : ae_state *_state)
25485 : {
25486 : ae_int_t n;
25487 : ae_int_t k;
25488 : ae_int_t i;
25489 : ae_int_t j;
25490 : ae_int_t jp;
25491 : ae_int_t i0;
25492 : ae_int_t i1;
25493 : ae_int_t ibest;
25494 : ae_int_t jbest;
25495 : double v;
25496 : double v0;
25497 : ae_int_t nz0;
25498 : ae_int_t nz1;
25499 : double uu;
25500 : ae_int_t offs;
25501 : ae_int_t tmpndense;
25502 : ae_bool densificationsupported;
25503 : ae_int_t densifyabove;
25504 : ae_bool result;
25505 :
25506 :
25507 0 : ae_assert(sparseiscrs(a, _state), "SparseLU: A is not stored in CRS format", _state);
25508 0 : ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SparseLU: non-square A", _state);
25509 0 : ae_assert((pivottype==0||pivottype==1)||pivottype==2, "SparseLU: unexpected pivot type", _state);
25510 0 : result = ae_true;
25511 0 : n = sparsegetnrows(a, _state);
25512 0 : if( pivottype==0 )
25513 : {
25514 0 : pivottype = 2;
25515 : }
25516 0 : densificationsupported = pivottype==2;
25517 :
25518 : /*
25519 : *
25520 : */
25521 0 : buf->n = n;
25522 0 : ivectorsetlengthatleast(&buf->rowpermrawidx, n, _state);
25523 0 : for(i=0; i<=n-1; i++)
25524 : {
25525 0 : buf->rowpermrawidx.ptr.p_int[i] = i;
25526 : }
25527 :
25528 : /*
25529 : * Allocate storage for sparse L and U factors
25530 : *
25531 : * NOTE: SparseMatrix structure for these factors is only
25532 : * partially initialized; we use it just as a temporary
25533 : * storage and do not intend to use facilities of the
25534 : * 'sparse' subpackage to work with these objects.
25535 : */
25536 0 : buf->sparsel.matrixtype = 1;
25537 0 : buf->sparsel.m = n;
25538 0 : buf->sparsel.n = n;
25539 0 : ivectorsetlengthatleast(&buf->sparsel.ridx, n+1, _state);
25540 0 : buf->sparsel.ridx.ptr.p_int[0] = 0;
25541 0 : buf->sparseut.matrixtype = 1;
25542 0 : buf->sparseut.m = n;
25543 0 : buf->sparseut.n = n;
25544 0 : ivectorsetlengthatleast(&buf->sparseut.ridx, n+1, _state);
25545 0 : buf->sparseut.ridx.ptr.p_int[0] = 0;
25546 :
25547 : /*
25548 : * Allocate unprocessed yet part of the matrix,
25549 : * two submatrices:
25550 : * * BU, upper J rows of columns [J,N), upper submatrix
25551 : * * BL, left J cols of rows [J,N), left submatrix
25552 : * * B1, (N-J)*(N-J) square submatrix
25553 : */
25554 0 : sptrf_sluv2list1init(n, &buf->bleft, _state);
25555 0 : sptrf_sluv2list1init(n, &buf->bupper, _state);
25556 0 : ivectorsetlengthatleast(pr, n, _state);
25557 0 : ivectorsetlengthatleast(pc, n, _state);
25558 0 : ivectorsetlengthatleast(&buf->v0i, n, _state);
25559 0 : ivectorsetlengthatleast(&buf->v1i, n, _state);
25560 0 : rvectorsetlengthatleast(&buf->v0r, n, _state);
25561 0 : rvectorsetlengthatleast(&buf->v1r, n, _state);
25562 0 : sptrf_sparsetrailinit(a, &buf->strail, _state);
25563 :
25564 : /*
25565 : * Prepare dense trail, initial densification
25566 : */
25567 0 : sptrf_densetrailinit(&buf->dtrail, n, _state);
25568 0 : densifyabove = ae_round(sptrf_densebnd*n, _state)+1;
25569 0 : if( densificationsupported )
25570 : {
25571 0 : for(i=0; i<=n-1; i++)
25572 : {
25573 0 : if( buf->strail.nzc.ptr.p_int[i]>densifyabove )
25574 : {
25575 0 : sptrf_sparsetraildensify(&buf->strail, i, &buf->bupper, &buf->dtrail, _state);
25576 : }
25577 : }
25578 : }
25579 :
25580 : /*
25581 : * Process sparse part
25582 : */
25583 0 : for(k=0; k<=n-1; k++)
25584 : {
25585 :
25586 : /*
25587 : * Find pivot column and pivot row
25588 : */
25589 0 : if( !sptrf_sparsetrailfindpivot(&buf->strail, pivottype, &ibest, &jbest, _state) )
25590 : {
25591 :
25592 : /*
25593 : * Only densified columns are left, break sparse iteration
25594 : */
25595 0 : ae_assert(buf->dtrail.ndense+k==n, "SPTRF: integrity check failed (35741)", _state);
25596 0 : break;
25597 : }
25598 0 : pc->ptr.p_int[k] = jbest;
25599 0 : pr->ptr.p_int[k] = ibest;
25600 0 : j = buf->rowpermrawidx.ptr.p_int[k];
25601 0 : buf->rowpermrawidx.ptr.p_int[k] = buf->rowpermrawidx.ptr.p_int[ibest];
25602 0 : buf->rowpermrawidx.ptr.p_int[ibest] = j;
25603 :
25604 : /*
25605 : * Apply pivoting to BL and BU
25606 : */
25607 0 : sptrf_sluv2list1swap(&buf->bleft, k, ibest, _state);
25608 0 : sptrf_sluv2list1swap(&buf->bupper, k, jbest, _state);
25609 :
25610 : /*
25611 : * Apply pivoting to sparse trail, pivot out
25612 : */
25613 0 : sptrf_sparsetrailpivotout(&buf->strail, ibest, jbest, &uu, &buf->v0i, &buf->v0r, &nz0, &buf->v1i, &buf->v1r, &nz1, _state);
25614 0 : result = result&&uu!=0;
25615 :
25616 : /*
25617 : * Pivot dense trail
25618 : */
25619 0 : tmpndense = buf->dtrail.ndense;
25620 0 : for(i=0; i<=tmpndense-1; i++)
25621 : {
25622 0 : v = buf->dtrail.d.ptr.pp_double[k][i];
25623 0 : buf->dtrail.d.ptr.pp_double[k][i] = buf->dtrail.d.ptr.pp_double[ibest][i];
25624 0 : buf->dtrail.d.ptr.pp_double[ibest][i] = v;
25625 : }
25626 :
25627 : /*
25628 : * Output to LU matrix
25629 : */
25630 0 : sptrf_sluv2list1appendsequencetomatrix(&buf->bupper, k, ae_true, uu, n, &buf->sparseut, k, _state);
25631 0 : sptrf_sluv2list1appendsequencetomatrix(&buf->bleft, k, ae_false, 0.0, n, &buf->sparsel, k, _state);
25632 :
25633 : /*
25634 : * Extract K-th col/row of B1, generate K-th col/row of BL/BU, update NZC
25635 : */
25636 0 : sptrf_sluv2list1pushsparsevector(&buf->bleft, &buf->v0i, &buf->v0r, nz0, _state);
25637 0 : sptrf_sluv2list1pushsparsevector(&buf->bupper, &buf->v1i, &buf->v1r, nz1, _state);
25638 :
25639 : /*
25640 : * Update the rest of the matrix
25641 : */
25642 0 : if( nz0*(nz1+buf->dtrail.ndense)>0 )
25643 : {
25644 :
25645 : /*
25646 : * Update dense trail
25647 : *
25648 : * NOTE: this update MUST be performed before we update sparse trail,
25649 : * because sparse update may move columns to dense storage after
25650 : * update is performed on them. Thus, we have to avoid applying
25651 : * same update twice.
25652 : */
25653 0 : if( buf->dtrail.ndense>0 )
25654 : {
25655 0 : tmpndense = buf->dtrail.ndense;
25656 0 : for(i=0; i<=nz0-1; i++)
25657 : {
25658 0 : i0 = buf->v0i.ptr.p_int[i];
25659 0 : v0 = buf->v0r.ptr.p_double[i];
25660 0 : for(j=0; j<=tmpndense-1; j++)
25661 : {
25662 0 : buf->dtrail.d.ptr.pp_double[i0][j] = buf->dtrail.d.ptr.pp_double[i0][j]-v0*buf->dtrail.d.ptr.pp_double[k][j];
25663 : }
25664 : }
25665 : }
25666 :
25667 : /*
25668 : * Update sparse trail
25669 : */
25670 0 : sptrf_sparsetrailupdate(&buf->strail, &buf->v0i, &buf->v0r, nz0, &buf->v1i, &buf->v1r, nz1, &buf->bupper, &buf->dtrail, densificationsupported, _state);
25671 : }
25672 : }
25673 :
25674 : /*
25675 : * Process densified trail
25676 : */
25677 0 : if( buf->dtrail.ndense>0 )
25678 : {
25679 0 : tmpndense = buf->dtrail.ndense;
25680 :
25681 : /*
25682 : * Generate column pivots to bring actual order of columns in the
25683 : * working part of the matrix to one used for dense storage
25684 : */
25685 0 : for(i=n-tmpndense; i<=n-1; i++)
25686 : {
25687 0 : k = buf->dtrail.did.ptr.p_int[i-(n-tmpndense)];
25688 0 : jp = -1;
25689 0 : for(j=i; j<=n-1; j++)
25690 : {
25691 0 : if( buf->strail.colid.ptr.p_int[j]==k )
25692 : {
25693 0 : jp = j;
25694 0 : break;
25695 : }
25696 : }
25697 0 : ae_assert(jp>=0, "SPTRF: integrity check failed during reordering", _state);
25698 0 : k = buf->strail.colid.ptr.p_int[i];
25699 0 : buf->strail.colid.ptr.p_int[i] = buf->strail.colid.ptr.p_int[jp];
25700 0 : buf->strail.colid.ptr.p_int[jp] = k;
25701 0 : pc->ptr.p_int[i] = jp;
25702 : }
25703 :
25704 : /*
25705 : * Perform dense LU decomposition on dense trail
25706 : */
25707 0 : rmatrixsetlengthatleast(&buf->dbuf, buf->dtrail.ndense, buf->dtrail.ndense, _state);
25708 0 : for(i=0; i<=tmpndense-1; i++)
25709 : {
25710 0 : for(j=0; j<=tmpndense-1; j++)
25711 : {
25712 0 : buf->dbuf.ptr.pp_double[i][j] = buf->dtrail.d.ptr.pp_double[i+(n-tmpndense)][j];
25713 : }
25714 : }
25715 0 : rvectorsetlengthatleast(&buf->tmp0, 2*n, _state);
25716 0 : ivectorsetlengthatleast(&buf->tmpp, n, _state);
25717 0 : rmatrixplurec(&buf->dbuf, 0, tmpndense, tmpndense, &buf->tmpp, &buf->tmp0, _state);
25718 :
25719 : /*
25720 : * Convert indexes of rows pivots, swap elements of BLeft
25721 : */
25722 0 : for(i=0; i<=tmpndense-1; i++)
25723 : {
25724 0 : pr->ptr.p_int[i+(n-tmpndense)] = buf->tmpp.ptr.p_int[i]+(n-tmpndense);
25725 0 : sptrf_sluv2list1swap(&buf->bleft, i+(n-tmpndense), pr->ptr.p_int[i+(n-tmpndense)], _state);
25726 0 : j = buf->rowpermrawidx.ptr.p_int[i+(n-tmpndense)];
25727 0 : buf->rowpermrawidx.ptr.p_int[i+(n-tmpndense)] = buf->rowpermrawidx.ptr.p_int[pr->ptr.p_int[i+(n-tmpndense)]];
25728 0 : buf->rowpermrawidx.ptr.p_int[pr->ptr.p_int[i+(n-tmpndense)]] = j;
25729 : }
25730 :
25731 : /*
25732 : * Convert U-factor
25733 : */
25734 0 : ivectorgrowto(&buf->sparseut.idx, buf->sparseut.ridx.ptr.p_int[n-tmpndense]+n*tmpndense, _state);
25735 0 : rvectorgrowto(&buf->sparseut.vals, buf->sparseut.ridx.ptr.p_int[n-tmpndense]+n*tmpndense, _state);
25736 0 : for(j=0; j<=tmpndense-1; j++)
25737 : {
25738 0 : offs = buf->sparseut.ridx.ptr.p_int[j+(n-tmpndense)];
25739 0 : k = n-tmpndense;
25740 :
25741 : /*
25742 : * Convert leading N-NDense columns
25743 : */
25744 0 : for(i=0; i<=k-1; i++)
25745 : {
25746 0 : v = buf->dtrail.d.ptr.pp_double[i][j];
25747 0 : if( v!=0 )
25748 : {
25749 0 : buf->sparseut.idx.ptr.p_int[offs] = i;
25750 0 : buf->sparseut.vals.ptr.p_double[offs] = v;
25751 0 : offs = offs+1;
25752 : }
25753 : }
25754 :
25755 : /*
25756 : * Convert upper diagonal elements
25757 : */
25758 0 : for(i=0; i<=j-1; i++)
25759 : {
25760 0 : v = buf->dbuf.ptr.pp_double[i][j];
25761 0 : if( v!=0 )
25762 : {
25763 0 : buf->sparseut.idx.ptr.p_int[offs] = i+(n-tmpndense);
25764 0 : buf->sparseut.vals.ptr.p_double[offs] = v;
25765 0 : offs = offs+1;
25766 : }
25767 : }
25768 :
25769 : /*
25770 : * Convert diagonal element (always stored)
25771 : */
25772 0 : v = buf->dbuf.ptr.pp_double[j][j];
25773 0 : buf->sparseut.idx.ptr.p_int[offs] = j+(n-tmpndense);
25774 0 : buf->sparseut.vals.ptr.p_double[offs] = v;
25775 0 : offs = offs+1;
25776 0 : result = result&&v!=0;
25777 :
25778 : /*
25779 : * Column is done
25780 : */
25781 0 : buf->sparseut.ridx.ptr.p_int[j+(n-tmpndense)+1] = offs;
25782 : }
25783 :
25784 : /*
25785 : * Convert L-factor
25786 : */
25787 0 : ivectorgrowto(&buf->sparsel.idx, buf->sparsel.ridx.ptr.p_int[n-tmpndense]+n*tmpndense, _state);
25788 0 : rvectorgrowto(&buf->sparsel.vals, buf->sparsel.ridx.ptr.p_int[n-tmpndense]+n*tmpndense, _state);
25789 0 : for(i=0; i<=tmpndense-1; i++)
25790 : {
25791 0 : sptrf_sluv2list1appendsequencetomatrix(&buf->bleft, i+(n-tmpndense), ae_false, 0.0, n, &buf->sparsel, i+(n-tmpndense), _state);
25792 0 : offs = buf->sparsel.ridx.ptr.p_int[i+(n-tmpndense)+1];
25793 0 : for(j=0; j<=i-1; j++)
25794 : {
25795 0 : v = buf->dbuf.ptr.pp_double[i][j];
25796 0 : if( v!=0 )
25797 : {
25798 0 : buf->sparsel.idx.ptr.p_int[offs] = j+(n-tmpndense);
25799 0 : buf->sparsel.vals.ptr.p_double[offs] = v;
25800 0 : offs = offs+1;
25801 : }
25802 : }
25803 0 : buf->sparsel.ridx.ptr.p_int[i+(n-tmpndense)+1] = offs;
25804 : }
25805 : }
25806 :
25807 : /*
25808 : * Allocate output
25809 : */
25810 0 : ivectorsetlengthatleast(&buf->tmpi, n, _state);
25811 0 : for(i=0; i<=n-1; i++)
25812 : {
25813 0 : buf->tmpi.ptr.p_int[i] = buf->sparsel.ridx.ptr.p_int[i+1]-buf->sparsel.ridx.ptr.p_int[i];
25814 : }
25815 0 : for(i=0; i<=n-1; i++)
25816 : {
25817 0 : i0 = buf->sparseut.ridx.ptr.p_int[i];
25818 0 : i1 = buf->sparseut.ridx.ptr.p_int[i+1]-1;
25819 0 : for(j=i0; j<=i1; j++)
25820 : {
25821 0 : k = buf->sparseut.idx.ptr.p_int[j];
25822 0 : buf->tmpi.ptr.p_int[k] = buf->tmpi.ptr.p_int[k]+1;
25823 : }
25824 : }
25825 0 : a->matrixtype = 1;
25826 0 : a->ninitialized = buf->sparsel.ridx.ptr.p_int[n]+buf->sparseut.ridx.ptr.p_int[n];
25827 0 : a->m = n;
25828 0 : a->n = n;
25829 0 : ivectorsetlengthatleast(&a->ridx, n+1, _state);
25830 0 : ivectorsetlengthatleast(&a->idx, a->ninitialized, _state);
25831 0 : rvectorsetlengthatleast(&a->vals, a->ninitialized, _state);
25832 0 : a->ridx.ptr.p_int[0] = 0;
25833 0 : for(i=0; i<=n-1; i++)
25834 : {
25835 0 : a->ridx.ptr.p_int[i+1] = a->ridx.ptr.p_int[i]+buf->tmpi.ptr.p_int[i];
25836 : }
25837 0 : for(i=0; i<=n-1; i++)
25838 : {
25839 0 : i0 = buf->sparsel.ridx.ptr.p_int[i];
25840 0 : i1 = buf->sparsel.ridx.ptr.p_int[i+1]-1;
25841 0 : jp = a->ridx.ptr.p_int[i];
25842 0 : for(j=i0; j<=i1; j++)
25843 : {
25844 0 : a->idx.ptr.p_int[jp+(j-i0)] = buf->sparsel.idx.ptr.p_int[j];
25845 0 : a->vals.ptr.p_double[jp+(j-i0)] = buf->sparsel.vals.ptr.p_double[j];
25846 : }
25847 0 : buf->tmpi.ptr.p_int[i] = buf->sparsel.ridx.ptr.p_int[i+1]-buf->sparsel.ridx.ptr.p_int[i];
25848 : }
25849 0 : ivectorsetlengthatleast(&a->didx, n, _state);
25850 0 : ivectorsetlengthatleast(&a->uidx, n, _state);
25851 0 : for(i=0; i<=n-1; i++)
25852 : {
25853 0 : a->didx.ptr.p_int[i] = a->ridx.ptr.p_int[i]+buf->tmpi.ptr.p_int[i];
25854 0 : a->uidx.ptr.p_int[i] = a->didx.ptr.p_int[i]+1;
25855 0 : buf->tmpi.ptr.p_int[i] = a->didx.ptr.p_int[i];
25856 : }
25857 0 : for(i=0; i<=n-1; i++)
25858 : {
25859 0 : i0 = buf->sparseut.ridx.ptr.p_int[i];
25860 0 : i1 = buf->sparseut.ridx.ptr.p_int[i+1]-1;
25861 0 : for(j=i0; j<=i1; j++)
25862 : {
25863 0 : k = buf->sparseut.idx.ptr.p_int[j];
25864 0 : offs = buf->tmpi.ptr.p_int[k];
25865 0 : a->idx.ptr.p_int[offs] = i;
25866 0 : a->vals.ptr.p_double[offs] = buf->sparseut.vals.ptr.p_double[j];
25867 0 : buf->tmpi.ptr.p_int[k] = offs+1;
25868 : }
25869 : }
25870 0 : return result;
25871 : }
25872 :
25873 :
25874 : /*************************************************************************
25875 : This function initialized rectangular submatrix structure.
25876 :
25877 : After initialization this structure stores matrix[N,0], which contains N
25878 : rows (sequences), stored as single-linked lists.
25879 :
25880 : -- ALGLIB routine --
25881 : 15.01.2019
25882 : Bochkanov Sergey
25883 : *************************************************************************/
25884 0 : static void sptrf_sluv2list1init(ae_int_t n,
25885 : sluv2list1matrix* a,
25886 : ae_state *_state)
25887 : {
25888 : ae_int_t i;
25889 :
25890 :
25891 0 : ae_assert(n>=1, "SLUV2List1Init: N<1", _state);
25892 0 : a->nfixed = n;
25893 0 : a->ndynamic = 0;
25894 0 : a->nallocated = n;
25895 0 : a->nused = 0;
25896 0 : ivectorgrowto(&a->idxfirst, n, _state);
25897 0 : ivectorgrowto(&a->strgidx, 2*a->nallocated, _state);
25898 0 : rvectorgrowto(&a->strgval, a->nallocated, _state);
25899 0 : for(i=0; i<=n-1; i++)
25900 : {
25901 0 : a->idxfirst.ptr.p_int[i] = -1;
25902 : }
25903 0 : }
25904 :
25905 :
25906 : /*************************************************************************
25907 : This function swaps sequences #I and #J stored by the structure
25908 :
25909 : -- ALGLIB routine --
25910 : 15.01.2019
25911 : Bochkanov Sergey
25912 : *************************************************************************/
25913 0 : static void sptrf_sluv2list1swap(sluv2list1matrix* a,
25914 : ae_int_t i,
25915 : ae_int_t j,
25916 : ae_state *_state)
25917 : {
25918 : ae_int_t k;
25919 :
25920 :
25921 0 : k = a->idxfirst.ptr.p_int[i];
25922 0 : a->idxfirst.ptr.p_int[i] = a->idxfirst.ptr.p_int[j];
25923 0 : a->idxfirst.ptr.p_int[j] = k;
25924 0 : }
25925 :
25926 :
25927 : /*************************************************************************
25928 : This function drops sequence #I from the structure
25929 :
25930 : -- ALGLIB routine --
25931 : 15.01.2019
25932 : Bochkanov Sergey
25933 : *************************************************************************/
25934 0 : static void sptrf_sluv2list1dropsequence(sluv2list1matrix* a,
25935 : ae_int_t i,
25936 : ae_state *_state)
25937 : {
25938 :
25939 :
25940 0 : a->idxfirst.ptr.p_int[i] = -1;
25941 0 : }
25942 :
25943 :
25944 : /*************************************************************************
25945 : This function appends sequence from the structure to the sparse matrix.
25946 :
25947 : It is assumed that S is a lower triangular matrix, and A stores strictly
25948 : lower triangular elements (no diagonal ones!). You can explicitly control
25949 : whether you want to add diagonal elements or not.
25950 :
25951 : Output matrix is assumed to be stored in CRS format and to be partially
25952 : initialized (up to, but not including, Dst-th row). DIdx and UIdx are NOT
25953 : updated by this function as well as NInitialized.
25954 :
25955 : INPUT PARAMETERS:
25956 : A - rectangular matrix structure
25957 : Src - sequence (row or column) index in the structure
25958 : HasDiagonal - whether we want to add diagonal element
25959 : D - diagonal element, if HasDiagonal=True
25960 : NZMAX - maximum estimated number of non-zeros in the row,
25961 : this function will preallocate storage in the output
25962 : matrix.
25963 : S - destination matrix in CRS format, partially initialized
25964 : Dst - destination row index
25965 :
25966 :
25967 : -- ALGLIB routine --
25968 : 15.01.2019
25969 : Bochkanov Sergey
25970 : *************************************************************************/
25971 0 : static void sptrf_sluv2list1appendsequencetomatrix(sluv2list1matrix* a,
25972 : ae_int_t src,
25973 : ae_bool hasdiagonal,
25974 : double d,
25975 : ae_int_t nzmax,
25976 : sparsematrix* s,
25977 : ae_int_t dst,
25978 : ae_state *_state)
25979 : {
25980 : ae_int_t i;
25981 : ae_int_t i0;
25982 : ae_int_t i1;
25983 : ae_int_t jp;
25984 : ae_int_t nnz;
25985 :
25986 :
25987 0 : i0 = s->ridx.ptr.p_int[dst];
25988 0 : ivectorgrowto(&s->idx, i0+nzmax, _state);
25989 0 : rvectorgrowto(&s->vals, i0+nzmax, _state);
25990 0 : if( hasdiagonal )
25991 : {
25992 0 : i1 = i0+nzmax-1;
25993 0 : s->idx.ptr.p_int[i1] = dst;
25994 0 : s->vals.ptr.p_double[i1] = d;
25995 0 : nnz = 1;
25996 : }
25997 : else
25998 : {
25999 0 : i1 = i0+nzmax;
26000 0 : nnz = 0;
26001 : }
26002 0 : jp = a->idxfirst.ptr.p_int[src];
26003 0 : while(jp>=0)
26004 : {
26005 0 : i1 = i1-1;
26006 0 : s->idx.ptr.p_int[i1] = a->strgidx.ptr.p_int[2*jp+1];
26007 0 : s->vals.ptr.p_double[i1] = a->strgval.ptr.p_double[jp];
26008 0 : nnz = nnz+1;
26009 0 : jp = a->strgidx.ptr.p_int[2*jp+0];
26010 : }
26011 0 : for(i=0; i<=nnz-1; i++)
26012 : {
26013 0 : s->idx.ptr.p_int[i0+i] = s->idx.ptr.p_int[i1+i];
26014 0 : s->vals.ptr.p_double[i0+i] = s->vals.ptr.p_double[i1+i];
26015 : }
26016 0 : s->ridx.ptr.p_int[dst+1] = s->ridx.ptr.p_int[dst]+nnz;
26017 0 : }
26018 :
26019 :
26020 : /*************************************************************************
26021 : This function appends sparse column to the matrix, increasing its size
26022 : from [N,K] to [N,K+1]
26023 :
26024 : -- ALGLIB routine --
26025 : 15.01.2019
26026 : Bochkanov Sergey
26027 : *************************************************************************/
26028 0 : static void sptrf_sluv2list1pushsparsevector(sluv2list1matrix* a,
26029 : /* Integer */ ae_vector* si,
26030 : /* Real */ ae_vector* sv,
26031 : ae_int_t nz,
26032 : ae_state *_state)
26033 : {
26034 : ae_int_t idx;
26035 : ae_int_t i;
26036 : ae_int_t k;
26037 : ae_int_t nused;
26038 : double v;
26039 :
26040 :
26041 :
26042 : /*
26043 : * Fetch matrix size, increase
26044 : */
26045 0 : k = a->ndynamic;
26046 0 : ae_assert(k<a->nfixed, "Assertion failed", _state);
26047 0 : a->ndynamic = k+1;
26048 :
26049 : /*
26050 : * Allocate new storage if needed
26051 : */
26052 0 : nused = a->nused;
26053 0 : a->nallocated = ae_maxint(a->nallocated, nused+nz, _state);
26054 0 : ivectorgrowto(&a->strgidx, 2*a->nallocated, _state);
26055 0 : rvectorgrowto(&a->strgval, a->nallocated, _state);
26056 :
26057 : /*
26058 : * Append to list
26059 : */
26060 0 : for(idx=0; idx<=nz-1; idx++)
26061 : {
26062 0 : i = si->ptr.p_int[idx];
26063 0 : v = sv->ptr.p_double[idx];
26064 0 : a->strgidx.ptr.p_int[2*nused+0] = a->idxfirst.ptr.p_int[i];
26065 0 : a->strgidx.ptr.p_int[2*nused+1] = k;
26066 0 : a->strgval.ptr.p_double[nused] = v;
26067 0 : a->idxfirst.ptr.p_int[i] = nused;
26068 0 : nused = nused+1;
26069 : }
26070 0 : a->nused = nused;
26071 0 : }
26072 :
26073 :
26074 : /*************************************************************************
26075 : This function initializes dense trail, by default it is matrix[N,0]
26076 :
26077 : -- ALGLIB routine --
26078 : 15.01.2019
26079 : Bochkanov Sergey
26080 : *************************************************************************/
26081 0 : static void sptrf_densetrailinit(sluv2densetrail* d,
26082 : ae_int_t n,
26083 : ae_state *_state)
26084 : {
26085 : ae_int_t excessivesize;
26086 :
26087 :
26088 :
26089 : /*
26090 : * Note: excessive rows are allocated to accomodate for situation when
26091 : * this buffer is used to solve successive problems with increasing
26092 : * sizes.
26093 : */
26094 0 : excessivesize = ae_maxint(ae_round(1.333*n, _state), n, _state);
26095 0 : d->n = n;
26096 0 : d->ndense = 0;
26097 0 : ivectorsetlengthatleast(&d->did, n, _state);
26098 0 : if( d->d.rows<=excessivesize )
26099 : {
26100 0 : rmatrixsetlengthatleast(&d->d, n, 1, _state);
26101 : }
26102 : else
26103 : {
26104 0 : ae_matrix_set_length(&d->d, excessivesize, 1, _state);
26105 : }
26106 0 : }
26107 :
26108 :
26109 : /*************************************************************************
26110 : This function appends column with id=ID to the dense trail (column IDs are
26111 : integer numbers in [0,N) which can be used to track column permutations).
26112 :
26113 : -- ALGLIB routine --
26114 : 15.01.2019
26115 : Bochkanov Sergey
26116 : *************************************************************************/
26117 0 : static void sptrf_densetrailappendcolumn(sluv2densetrail* d,
26118 : /* Real */ ae_vector* x,
26119 : ae_int_t id,
26120 : ae_state *_state)
26121 : {
26122 : ae_int_t n;
26123 : ae_int_t i;
26124 : ae_int_t targetidx;
26125 :
26126 :
26127 0 : n = d->n;
26128 :
26129 : /*
26130 : * Reallocate storage
26131 : */
26132 0 : rmatrixgrowcolsto(&d->d, d->ndense+1, n, _state);
26133 :
26134 : /*
26135 : * Copy to dense storage:
26136 : * * BUpper
26137 : * * BTrail
26138 : * Remove from sparse storage
26139 : */
26140 0 : targetidx = d->ndense;
26141 0 : for(i=0; i<=n-1; i++)
26142 : {
26143 0 : d->d.ptr.pp_double[i][targetidx] = x->ptr.p_double[i];
26144 : }
26145 0 : d->did.ptr.p_int[targetidx] = id;
26146 0 : d->ndense = targetidx+1;
26147 0 : }
26148 :
26149 :
26150 : /*************************************************************************
26151 : This function initializes sparse trail from the sparse matrix. By default,
26152 : sparse trail spans columns and rows in [0,N) range. Subsequent pivoting
26153 : out of rows/columns changes its range to [K,N), [K+1,N) and so on.
26154 :
26155 : -- ALGLIB routine --
26156 : 15.01.2019
26157 : Bochkanov Sergey
26158 : *************************************************************************/
26159 0 : static void sptrf_sparsetrailinit(sparsematrix* s,
26160 : sluv2sparsetrail* a,
26161 : ae_state *_state)
26162 : {
26163 : ae_int_t i;
26164 : ae_int_t j;
26165 : ae_int_t n;
26166 : ae_int_t j0;
26167 : ae_int_t j1;
26168 : ae_int_t jj;
26169 : ae_int_t p;
26170 : ae_int_t slsused;
26171 :
26172 :
26173 0 : ae_assert(s->m==s->n, "SparseTrailInit: M<>N", _state);
26174 0 : ae_assert(s->matrixtype==1, "SparseTrailInit: non-CRS input", _state);
26175 0 : n = s->n;
26176 0 : a->n = s->n;
26177 0 : a->k = 0;
26178 0 : ivectorsetlengthatleast(&a->nzc, n, _state);
26179 0 : ivectorsetlengthatleast(&a->colid, n, _state);
26180 0 : rvectorsetlengthatleast(&a->tmp0, n, _state);
26181 0 : for(i=0; i<=n-1; i++)
26182 : {
26183 0 : a->colid.ptr.p_int[i] = i;
26184 : }
26185 0 : bvectorsetlengthatleast(&a->isdensified, n, _state);
26186 0 : for(i=0; i<=n-1; i++)
26187 : {
26188 0 : a->isdensified.ptr.p_bool[i] = ae_false;
26189 : }
26190 :
26191 : /*
26192 : * Working set of columns
26193 : */
26194 0 : a->maxwrkcnt = iboundval(ae_round(1+(double)n/(double)3, _state), 1, ae_minint(n, 50, _state), _state);
26195 0 : a->wrkcnt = 0;
26196 0 : ivectorsetlengthatleast(&a->wrkset, a->maxwrkcnt, _state);
26197 :
26198 : /*
26199 : * Sparse linked storage (SLS). Store CRS matrix to SLS format,
26200 : * row by row, starting from the last one.
26201 : */
26202 0 : ivectorsetlengthatleast(&a->slscolptr, n, _state);
26203 0 : ivectorsetlengthatleast(&a->slsrowptr, n, _state);
26204 0 : ivectorsetlengthatleast(&a->slsidx, s->ridx.ptr.p_int[n]*sptrf_slswidth, _state);
26205 0 : rvectorsetlengthatleast(&a->slsval, s->ridx.ptr.p_int[n], _state);
26206 0 : for(i=0; i<=n-1; i++)
26207 : {
26208 0 : a->nzc.ptr.p_int[i] = 0;
26209 : }
26210 0 : for(i=0; i<=n-1; i++)
26211 : {
26212 0 : a->slscolptr.ptr.p_int[i] = -1;
26213 0 : a->slsrowptr.ptr.p_int[i] = -1;
26214 : }
26215 0 : slsused = 0;
26216 0 : for(i=n-1; i>=0; i--)
26217 : {
26218 0 : j0 = s->ridx.ptr.p_int[i];
26219 0 : j1 = s->ridx.ptr.p_int[i+1]-1;
26220 0 : for(jj=j1; jj>=j0; jj--)
26221 : {
26222 0 : j = s->idx.ptr.p_int[jj];
26223 :
26224 : /*
26225 : * Update non-zero counts for columns
26226 : */
26227 0 : a->nzc.ptr.p_int[j] = a->nzc.ptr.p_int[j]+1;
26228 :
26229 : /*
26230 : * Insert into column list
26231 : */
26232 0 : p = a->slscolptr.ptr.p_int[j];
26233 0 : if( p>=0 )
26234 : {
26235 0 : a->slsidx.ptr.p_int[p*sptrf_slswidth+0] = slsused;
26236 : }
26237 0 : a->slsidx.ptr.p_int[slsused*sptrf_slswidth+0] = -1;
26238 0 : a->slsidx.ptr.p_int[slsused*sptrf_slswidth+1] = p;
26239 0 : a->slscolptr.ptr.p_int[j] = slsused;
26240 :
26241 : /*
26242 : * Insert into row list
26243 : */
26244 0 : p = a->slsrowptr.ptr.p_int[i];
26245 0 : if( p>=0 )
26246 : {
26247 0 : a->slsidx.ptr.p_int[p*sptrf_slswidth+2] = slsused;
26248 : }
26249 0 : a->slsidx.ptr.p_int[slsused*sptrf_slswidth+2] = -1;
26250 0 : a->slsidx.ptr.p_int[slsused*sptrf_slswidth+3] = p;
26251 0 : a->slsrowptr.ptr.p_int[i] = slsused;
26252 :
26253 : /*
26254 : * Store index and value
26255 : */
26256 0 : a->slsidx.ptr.p_int[slsused*sptrf_slswidth+4] = i;
26257 0 : a->slsidx.ptr.p_int[slsused*sptrf_slswidth+5] = j;
26258 0 : a->slsval.ptr.p_double[slsused] = s->vals.ptr.p_double[jj];
26259 0 : slsused = slsused+1;
26260 : }
26261 : }
26262 0 : a->slsused = slsused;
26263 0 : }
26264 :
26265 :
26266 : /*************************************************************************
26267 : This function searches for a appropriate pivot column/row.
26268 :
26269 : If there exists non-densified column, it returns indexes of pivot column
26270 : and row, with most sparse column selected for column pivoting, and largest
26271 : element selected for row pivoting. Function result is True.
26272 :
26273 : PivotType=1 means that no column pivoting is performed
26274 : PivotType=2 means that both column and row pivoting are supported
26275 :
26276 : If all columns were densified, False is returned.
26277 :
26278 : -- ALGLIB routine --
26279 : 15.01.2019
26280 : Bochkanov Sergey
26281 : *************************************************************************/
26282 0 : static ae_bool sptrf_sparsetrailfindpivot(sluv2sparsetrail* a,
26283 : ae_int_t pivottype,
26284 : ae_int_t* ipiv,
26285 : ae_int_t* jpiv,
26286 : ae_state *_state)
26287 : {
26288 : ae_int_t n;
26289 : ae_int_t k;
26290 : ae_int_t j;
26291 : ae_int_t jp;
26292 : ae_int_t entry;
26293 : ae_int_t nz;
26294 : ae_int_t maxwrknz;
26295 : ae_int_t nnzbest;
26296 : double s;
26297 : double bbest;
26298 : ae_int_t wrk0;
26299 : ae_int_t wrk1;
26300 : ae_bool result;
26301 :
26302 0 : *ipiv = 0;
26303 0 : *jpiv = 0;
26304 :
26305 0 : n = a->n;
26306 0 : k = a->k;
26307 0 : nnzbest = n+1;
26308 0 : *jpiv = -1;
26309 0 : *ipiv = -1;
26310 0 : result = ae_true;
26311 :
26312 : /*
26313 : * Select pivot column
26314 : */
26315 0 : if( pivottype==1 )
26316 : {
26317 :
26318 : /*
26319 : * No column pivoting
26320 : */
26321 0 : ae_assert(!a->isdensified.ptr.p_bool[k], "SparseTrailFindPivot: integrity check failed", _state);
26322 0 : *jpiv = k;
26323 : }
26324 : else
26325 : {
26326 :
26327 : /*
26328 : * Find pivot column
26329 : */
26330 : for(;;)
26331 : {
26332 :
26333 : /*
26334 : * Scan working set (if non-empty) for good columns
26335 : */
26336 0 : maxwrknz = a->maxwrknz;
26337 0 : for(j=0; j<=a->wrkcnt-1; j++)
26338 : {
26339 0 : jp = a->wrkset.ptr.p_int[j];
26340 0 : if( jp<k )
26341 : {
26342 0 : continue;
26343 : }
26344 0 : if( a->isdensified.ptr.p_bool[jp] )
26345 : {
26346 0 : continue;
26347 : }
26348 0 : nz = a->nzc.ptr.p_int[jp];
26349 0 : if( nz>maxwrknz )
26350 : {
26351 0 : continue;
26352 : }
26353 0 : if( *jpiv<0||nz<nnzbest )
26354 : {
26355 0 : nnzbest = nz;
26356 0 : *jpiv = jp;
26357 : }
26358 : }
26359 0 : if( *jpiv>=0 )
26360 : {
26361 0 : break;
26362 : }
26363 :
26364 : /*
26365 : * Well, nothing found. Recompute working set:
26366 : * * determine most sparse unprocessed yet column
26367 : * * gather all columns with density in [Wrk0,Wrk1) range,
26368 : * increase range, repeat, until working set is full
26369 : */
26370 0 : a->wrkcnt = 0;
26371 0 : a->maxwrknz = 0;
26372 0 : wrk0 = n+1;
26373 0 : for(jp=k; jp<=n-1; jp++)
26374 : {
26375 0 : if( !a->isdensified.ptr.p_bool[jp]&&a->nzc.ptr.p_int[jp]<wrk0 )
26376 : {
26377 0 : wrk0 = a->nzc.ptr.p_int[jp];
26378 : }
26379 : }
26380 0 : if( wrk0>n )
26381 : {
26382 :
26383 : /*
26384 : * Only densified columns are present, exit.
26385 : */
26386 0 : result = ae_false;
26387 0 : return result;
26388 : }
26389 0 : wrk1 = wrk0+1;
26390 0 : while(a->wrkcnt<a->maxwrkcnt&&wrk0<=n)
26391 : {
26392 :
26393 : /*
26394 : * Find columns with non-zero count in [Wrk0,Wrk1) range
26395 : */
26396 0 : for(jp=k; jp<=n-1; jp++)
26397 : {
26398 0 : if( a->wrkcnt==a->maxwrkcnt )
26399 : {
26400 0 : break;
26401 : }
26402 0 : if( a->isdensified.ptr.p_bool[jp] )
26403 : {
26404 0 : continue;
26405 : }
26406 0 : if( a->nzc.ptr.p_int[jp]>=wrk0&&a->nzc.ptr.p_int[jp]<wrk1 )
26407 : {
26408 0 : a->wrkset.ptr.p_int[a->wrkcnt] = jp;
26409 0 : a->wrkcnt = a->wrkcnt+1;
26410 0 : a->maxwrknz = ae_maxint(a->maxwrknz, a->nzc.ptr.p_int[jp], _state);
26411 : }
26412 : }
26413 :
26414 : /*
26415 : * Advance scan range
26416 : */
26417 0 : jp = ae_round(1.41*(wrk1-wrk0), _state)+1;
26418 0 : wrk0 = wrk1;
26419 0 : wrk1 = wrk0+jp;
26420 : }
26421 : }
26422 : }
26423 :
26424 : /*
26425 : * Select pivot row
26426 : */
26427 0 : bbest = (double)(0);
26428 0 : entry = a->slscolptr.ptr.p_int[*jpiv];
26429 0 : while(entry>=0)
26430 : {
26431 0 : s = ae_fabs(a->slsval.ptr.p_double[entry], _state);
26432 0 : if( *ipiv<0||ae_fp_greater(s,bbest) )
26433 : {
26434 0 : bbest = s;
26435 0 : *ipiv = a->slsidx.ptr.p_int[entry*sptrf_slswidth+4];
26436 : }
26437 0 : entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1];
26438 : }
26439 0 : if( *ipiv<0 )
26440 : {
26441 0 : *ipiv = k;
26442 : }
26443 0 : return result;
26444 : }
26445 :
26446 :
26447 : /*************************************************************************
26448 : This function pivots out specified row and column.
26449 :
26450 : Sparse trail range changes from [K,N) to [K+1,N).
26451 :
26452 : V0I, V0R, V1I, V1R must be preallocated arrays[N].
26453 :
26454 : Following data are returned:
26455 : * UU - diagonal element (pivoted out), can be zero
26456 : * V0I, V0R, NZ0 - sparse column pivoted out to the left (after permutation
26457 : is applied to its elements) and divided by UU.
26458 : V0I is array[NZ0] which stores row indexes in [K+1,N) range, V0R stores
26459 : values.
26460 : * V1I, V1R, NZ1 - sparse row pivoted out to the top.
26461 :
26462 : -- ALGLIB routine --
26463 : 15.01.2019
26464 : Bochkanov Sergey
26465 : *************************************************************************/
26466 0 : static void sptrf_sparsetrailpivotout(sluv2sparsetrail* a,
26467 : ae_int_t ipiv,
26468 : ae_int_t jpiv,
26469 : double* uu,
26470 : /* Integer */ ae_vector* v0i,
26471 : /* Real */ ae_vector* v0r,
26472 : ae_int_t* nz0,
26473 : /* Integer */ ae_vector* v1i,
26474 : /* Real */ ae_vector* v1r,
26475 : ae_int_t* nz1,
26476 : ae_state *_state)
26477 : {
26478 : ae_int_t n;
26479 : ae_int_t k;
26480 : ae_int_t i;
26481 : ae_int_t j;
26482 : ae_int_t entry;
26483 : double v;
26484 : double s;
26485 : ae_bool vb;
26486 : ae_int_t pos0k;
26487 : ae_int_t pos0piv;
26488 : ae_int_t pprev;
26489 : ae_int_t pnext;
26490 : ae_int_t pnextnext;
26491 :
26492 0 : *uu = 0;
26493 0 : *nz0 = 0;
26494 0 : *nz1 = 0;
26495 :
26496 0 : n = a->n;
26497 0 : k = a->k;
26498 0 : ae_assert(k<n, "SparseTrailPivotOut: integrity check failed", _state);
26499 :
26500 : /*
26501 : * Pivot out column JPiv from the sparse linked storage:
26502 : * * remove column JPiv from the matrix
26503 : * * update column K:
26504 : * * change element indexes after it is permuted to JPiv
26505 : * * resort rows affected by move K->JPiv
26506 : *
26507 : * NOTE: this code leaves V0I/V0R/NZ0 in the unfinalized state,
26508 : * i.e. these arrays do not account for pivoting performed
26509 : * on rows. They will be post-processed later.
26510 : */
26511 0 : *nz0 = 0;
26512 0 : pos0k = -1;
26513 0 : pos0piv = -1;
26514 0 : entry = a->slscolptr.ptr.p_int[jpiv];
26515 0 : while(entry>=0)
26516 : {
26517 :
26518 : /*
26519 : * Offload element
26520 : */
26521 0 : i = a->slsidx.ptr.p_int[entry*sptrf_slswidth+4];
26522 0 : v0i->ptr.p_int[*nz0] = i;
26523 0 : v0r->ptr.p_double[*nz0] = a->slsval.ptr.p_double[entry];
26524 0 : if( i==k )
26525 : {
26526 0 : pos0k = *nz0;
26527 : }
26528 0 : if( i==ipiv )
26529 : {
26530 0 : pos0piv = *nz0;
26531 : }
26532 0 : *nz0 = *nz0+1;
26533 :
26534 : /*
26535 : * Remove element from the row list
26536 : */
26537 0 : pprev = a->slsidx.ptr.p_int[entry*sptrf_slswidth+2];
26538 0 : pnext = a->slsidx.ptr.p_int[entry*sptrf_slswidth+3];
26539 0 : if( pprev>=0 )
26540 : {
26541 0 : a->slsidx.ptr.p_int[pprev*sptrf_slswidth+3] = pnext;
26542 : }
26543 : else
26544 : {
26545 0 : a->slsrowptr.ptr.p_int[i] = pnext;
26546 : }
26547 0 : if( pnext>=0 )
26548 : {
26549 0 : a->slsidx.ptr.p_int[pnext*sptrf_slswidth+2] = pprev;
26550 : }
26551 :
26552 : /*
26553 : * Select next entry
26554 : */
26555 0 : entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1];
26556 : }
26557 0 : entry = a->slscolptr.ptr.p_int[k];
26558 0 : a->slscolptr.ptr.p_int[jpiv] = entry;
26559 0 : while(entry>=0)
26560 : {
26561 :
26562 : /*
26563 : * Change column index
26564 : */
26565 0 : a->slsidx.ptr.p_int[entry*sptrf_slswidth+5] = jpiv;
26566 :
26567 : /*
26568 : * Next entry
26569 : */
26570 0 : entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1];
26571 : }
26572 :
26573 : /*
26574 : * Post-process V0, account for pivoting.
26575 : * Compute diagonal element UU.
26576 : */
26577 0 : *uu = (double)(0);
26578 0 : if( pos0k>=0||pos0piv>=0 )
26579 : {
26580 :
26581 : /*
26582 : * Apply permutation to rows of pivoted out column, specific
26583 : * implementation depends on the sparsity at locations #Pos0K
26584 : * and #Pos0Piv of the V0 array.
26585 : */
26586 0 : if( pos0k>=0&&pos0piv>=0 )
26587 : {
26588 :
26589 : /*
26590 : * Obtain diagonal element
26591 : */
26592 0 : *uu = v0r->ptr.p_double[pos0piv];
26593 0 : if( *uu!=0 )
26594 : {
26595 0 : s = 1/(*uu);
26596 : }
26597 : else
26598 : {
26599 0 : s = (double)(1);
26600 : }
26601 :
26602 : /*
26603 : * Move pivoted out element, shift array by one in order
26604 : * to remove heading diagonal element (not needed here
26605 : * anymore).
26606 : */
26607 0 : v0r->ptr.p_double[pos0piv] = v0r->ptr.p_double[pos0k];
26608 0 : for(i=0; i<=*nz0-2; i++)
26609 : {
26610 0 : v0i->ptr.p_int[i] = v0i->ptr.p_int[i+1];
26611 0 : v0r->ptr.p_double[i] = v0r->ptr.p_double[i+1]*s;
26612 : }
26613 0 : *nz0 = *nz0-1;
26614 : }
26615 0 : if( pos0k>=0&&pos0piv<0 )
26616 : {
26617 :
26618 : /*
26619 : * Diagonal element is zero
26620 : */
26621 0 : *uu = (double)(0);
26622 :
26623 : /*
26624 : * Pivot out element, reorder array
26625 : */
26626 0 : v0i->ptr.p_int[pos0k] = ipiv;
26627 0 : for(i=pos0k; i<=*nz0-2; i++)
26628 : {
26629 0 : if( v0i->ptr.p_int[i]<v0i->ptr.p_int[i+1] )
26630 : {
26631 0 : break;
26632 : }
26633 0 : j = v0i->ptr.p_int[i];
26634 0 : v0i->ptr.p_int[i] = v0i->ptr.p_int[i+1];
26635 0 : v0i->ptr.p_int[i+1] = j;
26636 0 : v = v0r->ptr.p_double[i];
26637 0 : v0r->ptr.p_double[i] = v0r->ptr.p_double[i+1];
26638 0 : v0r->ptr.p_double[i+1] = v;
26639 : }
26640 : }
26641 0 : if( pos0k<0&&pos0piv>=0 )
26642 : {
26643 :
26644 : /*
26645 : * Get diagonal element
26646 : */
26647 0 : *uu = v0r->ptr.p_double[pos0piv];
26648 0 : if( *uu!=0 )
26649 : {
26650 0 : s = 1/(*uu);
26651 : }
26652 : else
26653 : {
26654 0 : s = (double)(1);
26655 : }
26656 :
26657 : /*
26658 : * Shift array past the pivoted in element by one
26659 : * in order to remove pivot
26660 : */
26661 0 : for(i=0; i<=pos0piv-1; i++)
26662 : {
26663 0 : v0r->ptr.p_double[i] = v0r->ptr.p_double[i]*s;
26664 : }
26665 0 : for(i=pos0piv; i<=*nz0-2; i++)
26666 : {
26667 0 : v0i->ptr.p_int[i] = v0i->ptr.p_int[i+1];
26668 0 : v0r->ptr.p_double[i] = v0r->ptr.p_double[i+1]*s;
26669 : }
26670 0 : *nz0 = *nz0-1;
26671 : }
26672 : }
26673 :
26674 : /*
26675 : * Pivot out row IPiv from the sparse linked storage:
26676 : * * remove row IPiv from the matrix
26677 : * * reindex elements of row K after it is permuted to IPiv
26678 : * * apply permutation to the cols of the pivoted out row,
26679 : * resort columns
26680 : */
26681 0 : *nz1 = 0;
26682 0 : entry = a->slsrowptr.ptr.p_int[ipiv];
26683 0 : while(entry>=0)
26684 : {
26685 :
26686 : /*
26687 : * Offload element
26688 : */
26689 0 : j = a->slsidx.ptr.p_int[entry*sptrf_slswidth+5];
26690 0 : v1i->ptr.p_int[*nz1] = j;
26691 0 : v1r->ptr.p_double[*nz1] = a->slsval.ptr.p_double[entry];
26692 0 : *nz1 = *nz1+1;
26693 :
26694 : /*
26695 : * Remove element from the column list
26696 : */
26697 0 : pprev = a->slsidx.ptr.p_int[entry*sptrf_slswidth+0];
26698 0 : pnext = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1];
26699 0 : if( pprev>=0 )
26700 : {
26701 0 : a->slsidx.ptr.p_int[pprev*sptrf_slswidth+1] = pnext;
26702 : }
26703 : else
26704 : {
26705 0 : a->slscolptr.ptr.p_int[j] = pnext;
26706 : }
26707 0 : if( pnext>=0 )
26708 : {
26709 0 : a->slsidx.ptr.p_int[pnext*sptrf_slswidth+0] = pprev;
26710 : }
26711 :
26712 : /*
26713 : * Select next entry
26714 : */
26715 0 : entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+3];
26716 : }
26717 0 : a->slsrowptr.ptr.p_int[ipiv] = a->slsrowptr.ptr.p_int[k];
26718 0 : entry = a->slsrowptr.ptr.p_int[ipiv];
26719 0 : while(entry>=0)
26720 : {
26721 :
26722 : /*
26723 : * Change row index
26724 : */
26725 0 : a->slsidx.ptr.p_int[entry*sptrf_slswidth+4] = ipiv;
26726 :
26727 : /*
26728 : * Resort column affected by row pivoting
26729 : */
26730 0 : j = a->slsidx.ptr.p_int[entry*sptrf_slswidth+5];
26731 0 : pprev = a->slsidx.ptr.p_int[entry*sptrf_slswidth+0];
26732 0 : pnext = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1];
26733 0 : while(pnext>=0&&a->slsidx.ptr.p_int[pnext*sptrf_slswidth+4]<ipiv)
26734 : {
26735 0 : pnextnext = a->slsidx.ptr.p_int[pnext*sptrf_slswidth+1];
26736 :
26737 : /*
26738 : * prev->next
26739 : */
26740 0 : if( pprev>=0 )
26741 : {
26742 0 : a->slsidx.ptr.p_int[pprev*sptrf_slswidth+1] = pnext;
26743 : }
26744 : else
26745 : {
26746 0 : a->slscolptr.ptr.p_int[j] = pnext;
26747 : }
26748 :
26749 : /*
26750 : * entry->prev, entry->next
26751 : */
26752 0 : a->slsidx.ptr.p_int[entry*sptrf_slswidth+0] = pnext;
26753 0 : a->slsidx.ptr.p_int[entry*sptrf_slswidth+1] = pnextnext;
26754 :
26755 : /*
26756 : * next->prev, next->next
26757 : */
26758 0 : a->slsidx.ptr.p_int[pnext*sptrf_slswidth+0] = pprev;
26759 0 : a->slsidx.ptr.p_int[pnext*sptrf_slswidth+1] = entry;
26760 :
26761 : /*
26762 : * nextnext->prev
26763 : */
26764 0 : if( pnextnext>=0 )
26765 : {
26766 0 : a->slsidx.ptr.p_int[pnextnext*sptrf_slswidth+0] = entry;
26767 : }
26768 :
26769 : /*
26770 : * PPrev, Item, PNext
26771 : */
26772 0 : pprev = pnext;
26773 0 : pnext = pnextnext;
26774 : }
26775 :
26776 : /*
26777 : * Next entry
26778 : */
26779 0 : entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+3];
26780 : }
26781 :
26782 : /*
26783 : * Reorder other structures
26784 : */
26785 0 : i = a->nzc.ptr.p_int[k];
26786 0 : a->nzc.ptr.p_int[k] = a->nzc.ptr.p_int[jpiv];
26787 0 : a->nzc.ptr.p_int[jpiv] = i;
26788 0 : i = a->colid.ptr.p_int[k];
26789 0 : a->colid.ptr.p_int[k] = a->colid.ptr.p_int[jpiv];
26790 0 : a->colid.ptr.p_int[jpiv] = i;
26791 0 : vb = a->isdensified.ptr.p_bool[k];
26792 0 : a->isdensified.ptr.p_bool[k] = a->isdensified.ptr.p_bool[jpiv];
26793 0 : a->isdensified.ptr.p_bool[jpiv] = vb;
26794 :
26795 : /*
26796 : * Handle removal of col/row #K
26797 : */
26798 0 : for(i=0; i<=*nz1-1; i++)
26799 : {
26800 0 : j = v1i->ptr.p_int[i];
26801 0 : a->nzc.ptr.p_int[j] = a->nzc.ptr.p_int[j]-1;
26802 : }
26803 0 : a->k = a->k+1;
26804 0 : }
26805 :
26806 :
26807 : /*************************************************************************
26808 : This function densifies I1-th column of the sparse trail.
26809 :
26810 : PARAMETERS:
26811 : A - sparse trail
26812 : I1 - column index
26813 : BUpper - upper rectangular submatrix, updated during densification
26814 : of the columns (densified columns are removed)
26815 : DTrail - dense trail, receives densified columns from sparse
26816 : trail and BUpper
26817 :
26818 : -- ALGLIB routine --
26819 : 15.01.2019
26820 : Bochkanov Sergey
26821 : *************************************************************************/
26822 0 : static void sptrf_sparsetraildensify(sluv2sparsetrail* a,
26823 : ae_int_t i1,
26824 : sluv2list1matrix* bupper,
26825 : sluv2densetrail* dtrail,
26826 : ae_state *_state)
26827 : {
26828 : ae_int_t n;
26829 : ae_int_t k;
26830 : ae_int_t i;
26831 : ae_int_t jp;
26832 : ae_int_t entry;
26833 : ae_int_t pprev;
26834 : ae_int_t pnext;
26835 :
26836 :
26837 0 : n = a->n;
26838 0 : k = a->k;
26839 0 : ae_assert(k<n, "SparseTrailDensify: integrity check failed", _state);
26840 0 : ae_assert(k<=i1, "SparseTrailDensify: integrity check failed", _state);
26841 0 : ae_assert(!a->isdensified.ptr.p_bool[i1], "SparseTrailDensify: integrity check failed", _state);
26842 :
26843 : /*
26844 : * Offload items [0,K) of densified column from BUpper
26845 : */
26846 0 : for(i=0; i<=n-1; i++)
26847 : {
26848 0 : a->tmp0.ptr.p_double[i] = (double)(0);
26849 : }
26850 0 : jp = bupper->idxfirst.ptr.p_int[i1];
26851 0 : while(jp>=0)
26852 : {
26853 0 : a->tmp0.ptr.p_double[bupper->strgidx.ptr.p_int[2*jp+1]] = bupper->strgval.ptr.p_double[jp];
26854 0 : jp = bupper->strgidx.ptr.p_int[2*jp+0];
26855 : }
26856 0 : sptrf_sluv2list1dropsequence(bupper, i1, _state);
26857 :
26858 : /*
26859 : * Offload items [K,N) of densified column from BLeft
26860 : */
26861 0 : entry = a->slscolptr.ptr.p_int[i1];
26862 0 : while(entry>=0)
26863 : {
26864 :
26865 : /*
26866 : * Offload element
26867 : */
26868 0 : i = a->slsidx.ptr.p_int[entry*sptrf_slswidth+4];
26869 0 : a->tmp0.ptr.p_double[i] = a->slsval.ptr.p_double[entry];
26870 :
26871 : /*
26872 : * Remove element from the row list
26873 : */
26874 0 : pprev = a->slsidx.ptr.p_int[entry*sptrf_slswidth+2];
26875 0 : pnext = a->slsidx.ptr.p_int[entry*sptrf_slswidth+3];
26876 0 : if( pprev>=0 )
26877 : {
26878 0 : a->slsidx.ptr.p_int[pprev*sptrf_slswidth+3] = pnext;
26879 : }
26880 : else
26881 : {
26882 0 : a->slsrowptr.ptr.p_int[i] = pnext;
26883 : }
26884 0 : if( pnext>=0 )
26885 : {
26886 0 : a->slsidx.ptr.p_int[pnext*sptrf_slswidth+2] = pprev;
26887 : }
26888 :
26889 : /*
26890 : * Select next entry
26891 : */
26892 0 : entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1];
26893 : }
26894 :
26895 : /*
26896 : * Densify
26897 : */
26898 0 : a->nzc.ptr.p_int[i1] = 0;
26899 0 : a->isdensified.ptr.p_bool[i1] = ae_true;
26900 0 : a->slscolptr.ptr.p_int[i1] = -1;
26901 0 : sptrf_densetrailappendcolumn(dtrail, &a->tmp0, a->colid.ptr.p_int[i1], _state);
26902 0 : }
26903 :
26904 :
26905 : /*************************************************************************
26906 : This function appends rank-1 update to the sparse trail. Dense trail is
26907 : not updated here, but we may move some columns to dense trail during
26908 : update (i.e. densify them). Thus, you have to update dense trail BEFORE
26909 : you start updating sparse one (otherwise, recently densified columns will
26910 : be updated twice).
26911 :
26912 : PARAMETERS:
26913 : A - sparse trail
26914 : V0I, V0R - update column returned by SparseTrailPivotOut (MUST be
26915 : array[N] independently of the NZ0).
26916 : NZ0 - non-zero count for update column
26917 : V1I, V1R - update row returned by SparseTrailPivotOut
26918 : NZ1 - non-zero count for update row
26919 : BUpper - upper rectangular submatrix, updated during densification
26920 : of the columns (densified columns are removed)
26921 : DTrail - dense trail, receives densified columns from sparse
26922 : trail and BUpper
26923 : DensificationSupported- if False, no densification is performed
26924 :
26925 : -- ALGLIB routine --
26926 : 15.01.2019
26927 : Bochkanov Sergey
26928 : *************************************************************************/
26929 0 : static void sptrf_sparsetrailupdate(sluv2sparsetrail* a,
26930 : /* Integer */ ae_vector* v0i,
26931 : /* Real */ ae_vector* v0r,
26932 : ae_int_t nz0,
26933 : /* Integer */ ae_vector* v1i,
26934 : /* Real */ ae_vector* v1r,
26935 : ae_int_t nz1,
26936 : sluv2list1matrix* bupper,
26937 : sluv2densetrail* dtrail,
26938 : ae_bool densificationsupported,
26939 : ae_state *_state)
26940 : {
26941 : ae_int_t n;
26942 : ae_int_t k;
26943 : ae_int_t i;
26944 : ae_int_t j;
26945 : ae_int_t i0;
26946 : ae_int_t i1;
26947 : double v1;
26948 : ae_int_t densifyabove;
26949 : ae_int_t nnz;
26950 : ae_int_t entry;
26951 : ae_int_t newentry;
26952 : ae_int_t pprev;
26953 : ae_int_t pnext;
26954 : ae_int_t p;
26955 : ae_int_t nexti;
26956 : ae_int_t newoffs;
26957 :
26958 :
26959 0 : n = a->n;
26960 0 : k = a->k;
26961 0 : ae_assert(k<n, "SparseTrailPivotOut: integrity check failed", _state);
26962 0 : densifyabove = ae_round(sptrf_densebnd*(n-k), _state)+1;
26963 0 : ae_assert(v0i->cnt>=nz0+1, "SparseTrailUpdate: integrity check failed", _state);
26964 0 : ae_assert(v0r->cnt>=nz0+1, "SparseTrailUpdate: integrity check failed", _state);
26965 0 : v0i->ptr.p_int[nz0] = -1;
26966 0 : v0r->ptr.p_double[nz0] = (double)(0);
26967 :
26968 : /*
26969 : * Update sparse representation
26970 : */
26971 0 : ivectorgrowto(&a->slsidx, (a->slsused+nz0*nz1)*sptrf_slswidth, _state);
26972 0 : rvectorgrowto(&a->slsval, a->slsused+nz0*nz1, _state);
26973 0 : for(j=0; j<=nz1-1; j++)
26974 : {
26975 0 : if( nz0==0 )
26976 : {
26977 0 : continue;
26978 : }
26979 0 : i1 = v1i->ptr.p_int[j];
26980 0 : v1 = v1r->ptr.p_double[j];
26981 :
26982 : /*
26983 : * Update column #I1
26984 : */
26985 0 : nnz = a->nzc.ptr.p_int[i1];
26986 0 : i = 0;
26987 0 : i0 = v0i->ptr.p_int[i];
26988 0 : entry = a->slscolptr.ptr.p_int[i1];
26989 0 : pprev = -1;
26990 0 : while(i<nz0)
26991 : {
26992 :
26993 : /*
26994 : * Handle possible fill-in happening BEFORE already existing
26995 : * entry of the column list (or simply fill-in, if no entry
26996 : * is present).
26997 : */
26998 0 : pnext = entry;
26999 0 : if( entry>=0 )
27000 : {
27001 0 : nexti = a->slsidx.ptr.p_int[entry*sptrf_slswidth+4];
27002 : }
27003 : else
27004 : {
27005 0 : nexti = n+1;
27006 : }
27007 0 : while(i<nz0)
27008 : {
27009 0 : if( i0>=nexti )
27010 : {
27011 0 : break;
27012 : }
27013 :
27014 : /*
27015 : * Allocate new entry, store column/row/value
27016 : */
27017 0 : newentry = a->slsused;
27018 0 : a->slsused = newentry+1;
27019 0 : nnz = nnz+1;
27020 0 : newoffs = newentry*sptrf_slswidth;
27021 0 : a->slsidx.ptr.p_int[newoffs+4] = i0;
27022 0 : a->slsidx.ptr.p_int[newoffs+5] = i1;
27023 0 : a->slsval.ptr.p_double[newentry] = -v1*v0r->ptr.p_double[i];
27024 :
27025 : /*
27026 : * Insert entry into column list
27027 : */
27028 0 : a->slsidx.ptr.p_int[newoffs+0] = pprev;
27029 0 : a->slsidx.ptr.p_int[newoffs+1] = pnext;
27030 0 : if( pprev>=0 )
27031 : {
27032 0 : a->slsidx.ptr.p_int[pprev*sptrf_slswidth+1] = newentry;
27033 : }
27034 : else
27035 : {
27036 0 : a->slscolptr.ptr.p_int[i1] = newentry;
27037 : }
27038 0 : if( entry>=0 )
27039 : {
27040 0 : a->slsidx.ptr.p_int[entry*sptrf_slswidth+0] = newentry;
27041 : }
27042 :
27043 : /*
27044 : * Insert entry into row list
27045 : */
27046 0 : p = a->slsrowptr.ptr.p_int[i0];
27047 0 : a->slsidx.ptr.p_int[newoffs+2] = -1;
27048 0 : a->slsidx.ptr.p_int[newoffs+3] = p;
27049 0 : if( p>=0 )
27050 : {
27051 0 : a->slsidx.ptr.p_int[p*sptrf_slswidth+2] = newentry;
27052 : }
27053 0 : a->slsrowptr.ptr.p_int[i0] = newentry;
27054 :
27055 : /*
27056 : * Advance pointers
27057 : */
27058 0 : pprev = newentry;
27059 0 : i = i+1;
27060 0 : i0 = v0i->ptr.p_int[i];
27061 : }
27062 0 : if( i>=nz0 )
27063 : {
27064 0 : break;
27065 : }
27066 :
27067 : /*
27068 : * Update already existing entry of the column list, if needed
27069 : */
27070 0 : if( entry>=0 )
27071 : {
27072 0 : if( i0==nexti )
27073 : {
27074 0 : a->slsval.ptr.p_double[entry] = a->slsval.ptr.p_double[entry]-v1*v0r->ptr.p_double[i];
27075 0 : i = i+1;
27076 0 : i0 = v0i->ptr.p_int[i];
27077 : }
27078 0 : pprev = entry;
27079 : }
27080 :
27081 : /*
27082 : * Advance to the next pre-existing entry (if present)
27083 : */
27084 0 : if( entry>=0 )
27085 : {
27086 0 : entry = a->slsidx.ptr.p_int[entry*sptrf_slswidth+1];
27087 : }
27088 : }
27089 0 : a->nzc.ptr.p_int[i1] = nnz;
27090 :
27091 : /*
27092 : * Densify column if needed
27093 : */
27094 0 : if( (densificationsupported&&nnz>densifyabove)&&!a->isdensified.ptr.p_bool[i1] )
27095 : {
27096 0 : sptrf_sparsetraildensify(a, i1, bupper, dtrail, _state);
27097 : }
27098 : }
27099 0 : }
27100 :
27101 :
27102 0 : void _sluv2list1matrix_init(void* _p, ae_state *_state, ae_bool make_automatic)
27103 : {
27104 0 : sluv2list1matrix *p = (sluv2list1matrix*)_p;
27105 0 : ae_touch_ptr((void*)p);
27106 0 : ae_vector_init(&p->idxfirst, 0, DT_INT, _state, make_automatic);
27107 0 : ae_vector_init(&p->strgidx, 0, DT_INT, _state, make_automatic);
27108 0 : ae_vector_init(&p->strgval, 0, DT_REAL, _state, make_automatic);
27109 0 : }
27110 :
27111 :
27112 0 : void _sluv2list1matrix_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
27113 : {
27114 0 : sluv2list1matrix *dst = (sluv2list1matrix*)_dst;
27115 0 : sluv2list1matrix *src = (sluv2list1matrix*)_src;
27116 0 : dst->nfixed = src->nfixed;
27117 0 : dst->ndynamic = src->ndynamic;
27118 0 : ae_vector_init_copy(&dst->idxfirst, &src->idxfirst, _state, make_automatic);
27119 0 : ae_vector_init_copy(&dst->strgidx, &src->strgidx, _state, make_automatic);
27120 0 : ae_vector_init_copy(&dst->strgval, &src->strgval, _state, make_automatic);
27121 0 : dst->nallocated = src->nallocated;
27122 0 : dst->nused = src->nused;
27123 0 : }
27124 :
27125 :
27126 0 : void _sluv2list1matrix_clear(void* _p)
27127 : {
27128 0 : sluv2list1matrix *p = (sluv2list1matrix*)_p;
27129 0 : ae_touch_ptr((void*)p);
27130 0 : ae_vector_clear(&p->idxfirst);
27131 0 : ae_vector_clear(&p->strgidx);
27132 0 : ae_vector_clear(&p->strgval);
27133 0 : }
27134 :
27135 :
27136 0 : void _sluv2list1matrix_destroy(void* _p)
27137 : {
27138 0 : sluv2list1matrix *p = (sluv2list1matrix*)_p;
27139 0 : ae_touch_ptr((void*)p);
27140 0 : ae_vector_destroy(&p->idxfirst);
27141 0 : ae_vector_destroy(&p->strgidx);
27142 0 : ae_vector_destroy(&p->strgval);
27143 0 : }
27144 :
27145 :
27146 0 : void _sluv2sparsetrail_init(void* _p, ae_state *_state, ae_bool make_automatic)
27147 : {
27148 0 : sluv2sparsetrail *p = (sluv2sparsetrail*)_p;
27149 0 : ae_touch_ptr((void*)p);
27150 0 : ae_vector_init(&p->nzc, 0, DT_INT, _state, make_automatic);
27151 0 : ae_vector_init(&p->wrkset, 0, DT_INT, _state, make_automatic);
27152 0 : ae_vector_init(&p->colid, 0, DT_INT, _state, make_automatic);
27153 0 : ae_vector_init(&p->isdensified, 0, DT_BOOL, _state, make_automatic);
27154 0 : ae_vector_init(&p->slscolptr, 0, DT_INT, _state, make_automatic);
27155 0 : ae_vector_init(&p->slsrowptr, 0, DT_INT, _state, make_automatic);
27156 0 : ae_vector_init(&p->slsidx, 0, DT_INT, _state, make_automatic);
27157 0 : ae_vector_init(&p->slsval, 0, DT_REAL, _state, make_automatic);
27158 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
27159 0 : }
27160 :
27161 :
27162 0 : void _sluv2sparsetrail_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
27163 : {
27164 0 : sluv2sparsetrail *dst = (sluv2sparsetrail*)_dst;
27165 0 : sluv2sparsetrail *src = (sluv2sparsetrail*)_src;
27166 0 : dst->n = src->n;
27167 0 : dst->k = src->k;
27168 0 : ae_vector_init_copy(&dst->nzc, &src->nzc, _state, make_automatic);
27169 0 : dst->maxwrkcnt = src->maxwrkcnt;
27170 0 : dst->maxwrknz = src->maxwrknz;
27171 0 : dst->wrkcnt = src->wrkcnt;
27172 0 : ae_vector_init_copy(&dst->wrkset, &src->wrkset, _state, make_automatic);
27173 0 : ae_vector_init_copy(&dst->colid, &src->colid, _state, make_automatic);
27174 0 : ae_vector_init_copy(&dst->isdensified, &src->isdensified, _state, make_automatic);
27175 0 : ae_vector_init_copy(&dst->slscolptr, &src->slscolptr, _state, make_automatic);
27176 0 : ae_vector_init_copy(&dst->slsrowptr, &src->slsrowptr, _state, make_automatic);
27177 0 : ae_vector_init_copy(&dst->slsidx, &src->slsidx, _state, make_automatic);
27178 0 : ae_vector_init_copy(&dst->slsval, &src->slsval, _state, make_automatic);
27179 0 : dst->slsused = src->slsused;
27180 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
27181 0 : }
27182 :
27183 :
27184 0 : void _sluv2sparsetrail_clear(void* _p)
27185 : {
27186 0 : sluv2sparsetrail *p = (sluv2sparsetrail*)_p;
27187 0 : ae_touch_ptr((void*)p);
27188 0 : ae_vector_clear(&p->nzc);
27189 0 : ae_vector_clear(&p->wrkset);
27190 0 : ae_vector_clear(&p->colid);
27191 0 : ae_vector_clear(&p->isdensified);
27192 0 : ae_vector_clear(&p->slscolptr);
27193 0 : ae_vector_clear(&p->slsrowptr);
27194 0 : ae_vector_clear(&p->slsidx);
27195 0 : ae_vector_clear(&p->slsval);
27196 0 : ae_vector_clear(&p->tmp0);
27197 0 : }
27198 :
27199 :
27200 0 : void _sluv2sparsetrail_destroy(void* _p)
27201 : {
27202 0 : sluv2sparsetrail *p = (sluv2sparsetrail*)_p;
27203 0 : ae_touch_ptr((void*)p);
27204 0 : ae_vector_destroy(&p->nzc);
27205 0 : ae_vector_destroy(&p->wrkset);
27206 0 : ae_vector_destroy(&p->colid);
27207 0 : ae_vector_destroy(&p->isdensified);
27208 0 : ae_vector_destroy(&p->slscolptr);
27209 0 : ae_vector_destroy(&p->slsrowptr);
27210 0 : ae_vector_destroy(&p->slsidx);
27211 0 : ae_vector_destroy(&p->slsval);
27212 0 : ae_vector_destroy(&p->tmp0);
27213 0 : }
27214 :
27215 :
27216 0 : void _sluv2densetrail_init(void* _p, ae_state *_state, ae_bool make_automatic)
27217 : {
27218 0 : sluv2densetrail *p = (sluv2densetrail*)_p;
27219 0 : ae_touch_ptr((void*)p);
27220 0 : ae_matrix_init(&p->d, 0, 0, DT_REAL, _state, make_automatic);
27221 0 : ae_vector_init(&p->did, 0, DT_INT, _state, make_automatic);
27222 0 : }
27223 :
27224 :
27225 0 : void _sluv2densetrail_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
27226 : {
27227 0 : sluv2densetrail *dst = (sluv2densetrail*)_dst;
27228 0 : sluv2densetrail *src = (sluv2densetrail*)_src;
27229 0 : dst->n = src->n;
27230 0 : dst->ndense = src->ndense;
27231 0 : ae_matrix_init_copy(&dst->d, &src->d, _state, make_automatic);
27232 0 : ae_vector_init_copy(&dst->did, &src->did, _state, make_automatic);
27233 0 : }
27234 :
27235 :
27236 0 : void _sluv2densetrail_clear(void* _p)
27237 : {
27238 0 : sluv2densetrail *p = (sluv2densetrail*)_p;
27239 0 : ae_touch_ptr((void*)p);
27240 0 : ae_matrix_clear(&p->d);
27241 0 : ae_vector_clear(&p->did);
27242 0 : }
27243 :
27244 :
27245 0 : void _sluv2densetrail_destroy(void* _p)
27246 : {
27247 0 : sluv2densetrail *p = (sluv2densetrail*)_p;
27248 0 : ae_touch_ptr((void*)p);
27249 0 : ae_matrix_destroy(&p->d);
27250 0 : ae_vector_destroy(&p->did);
27251 0 : }
27252 :
27253 :
27254 0 : void _sluv2buffer_init(void* _p, ae_state *_state, ae_bool make_automatic)
27255 : {
27256 0 : sluv2buffer *p = (sluv2buffer*)_p;
27257 0 : ae_touch_ptr((void*)p);
27258 0 : _sparsematrix_init(&p->sparsel, _state, make_automatic);
27259 0 : _sparsematrix_init(&p->sparseut, _state, make_automatic);
27260 0 : _sluv2list1matrix_init(&p->bleft, _state, make_automatic);
27261 0 : _sluv2list1matrix_init(&p->bupper, _state, make_automatic);
27262 0 : _sluv2sparsetrail_init(&p->strail, _state, make_automatic);
27263 0 : _sluv2densetrail_init(&p->dtrail, _state, make_automatic);
27264 0 : ae_vector_init(&p->rowpermrawidx, 0, DT_INT, _state, make_automatic);
27265 0 : ae_matrix_init(&p->dbuf, 0, 0, DT_REAL, _state, make_automatic);
27266 0 : ae_vector_init(&p->v0i, 0, DT_INT, _state, make_automatic);
27267 0 : ae_vector_init(&p->v1i, 0, DT_INT, _state, make_automatic);
27268 0 : ae_vector_init(&p->v0r, 0, DT_REAL, _state, make_automatic);
27269 0 : ae_vector_init(&p->v1r, 0, DT_REAL, _state, make_automatic);
27270 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
27271 0 : ae_vector_init(&p->tmpi, 0, DT_INT, _state, make_automatic);
27272 0 : ae_vector_init(&p->tmpp, 0, DT_INT, _state, make_automatic);
27273 0 : }
27274 :
27275 :
27276 0 : void _sluv2buffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
27277 : {
27278 0 : sluv2buffer *dst = (sluv2buffer*)_dst;
27279 0 : sluv2buffer *src = (sluv2buffer*)_src;
27280 0 : dst->n = src->n;
27281 0 : _sparsematrix_init_copy(&dst->sparsel, &src->sparsel, _state, make_automatic);
27282 0 : _sparsematrix_init_copy(&dst->sparseut, &src->sparseut, _state, make_automatic);
27283 0 : _sluv2list1matrix_init_copy(&dst->bleft, &src->bleft, _state, make_automatic);
27284 0 : _sluv2list1matrix_init_copy(&dst->bupper, &src->bupper, _state, make_automatic);
27285 0 : _sluv2sparsetrail_init_copy(&dst->strail, &src->strail, _state, make_automatic);
27286 0 : _sluv2densetrail_init_copy(&dst->dtrail, &src->dtrail, _state, make_automatic);
27287 0 : ae_vector_init_copy(&dst->rowpermrawidx, &src->rowpermrawidx, _state, make_automatic);
27288 0 : ae_matrix_init_copy(&dst->dbuf, &src->dbuf, _state, make_automatic);
27289 0 : ae_vector_init_copy(&dst->v0i, &src->v0i, _state, make_automatic);
27290 0 : ae_vector_init_copy(&dst->v1i, &src->v1i, _state, make_automatic);
27291 0 : ae_vector_init_copy(&dst->v0r, &src->v0r, _state, make_automatic);
27292 0 : ae_vector_init_copy(&dst->v1r, &src->v1r, _state, make_automatic);
27293 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
27294 0 : ae_vector_init_copy(&dst->tmpi, &src->tmpi, _state, make_automatic);
27295 0 : ae_vector_init_copy(&dst->tmpp, &src->tmpp, _state, make_automatic);
27296 0 : }
27297 :
27298 :
27299 0 : void _sluv2buffer_clear(void* _p)
27300 : {
27301 0 : sluv2buffer *p = (sluv2buffer*)_p;
27302 0 : ae_touch_ptr((void*)p);
27303 0 : _sparsematrix_clear(&p->sparsel);
27304 0 : _sparsematrix_clear(&p->sparseut);
27305 0 : _sluv2list1matrix_clear(&p->bleft);
27306 0 : _sluv2list1matrix_clear(&p->bupper);
27307 0 : _sluv2sparsetrail_clear(&p->strail);
27308 0 : _sluv2densetrail_clear(&p->dtrail);
27309 0 : ae_vector_clear(&p->rowpermrawidx);
27310 0 : ae_matrix_clear(&p->dbuf);
27311 0 : ae_vector_clear(&p->v0i);
27312 0 : ae_vector_clear(&p->v1i);
27313 0 : ae_vector_clear(&p->v0r);
27314 0 : ae_vector_clear(&p->v1r);
27315 0 : ae_vector_clear(&p->tmp0);
27316 0 : ae_vector_clear(&p->tmpi);
27317 0 : ae_vector_clear(&p->tmpp);
27318 0 : }
27319 :
27320 :
27321 0 : void _sluv2buffer_destroy(void* _p)
27322 : {
27323 0 : sluv2buffer *p = (sluv2buffer*)_p;
27324 0 : ae_touch_ptr((void*)p);
27325 0 : _sparsematrix_destroy(&p->sparsel);
27326 0 : _sparsematrix_destroy(&p->sparseut);
27327 0 : _sluv2list1matrix_destroy(&p->bleft);
27328 0 : _sluv2list1matrix_destroy(&p->bupper);
27329 0 : _sluv2sparsetrail_destroy(&p->strail);
27330 0 : _sluv2densetrail_destroy(&p->dtrail);
27331 0 : ae_vector_destroy(&p->rowpermrawidx);
27332 0 : ae_matrix_destroy(&p->dbuf);
27333 0 : ae_vector_destroy(&p->v0i);
27334 0 : ae_vector_destroy(&p->v1i);
27335 0 : ae_vector_destroy(&p->v0r);
27336 0 : ae_vector_destroy(&p->v1r);
27337 0 : ae_vector_destroy(&p->tmp0);
27338 0 : ae_vector_destroy(&p->tmpi);
27339 0 : ae_vector_destroy(&p->tmpp);
27340 0 : }
27341 :
27342 :
27343 : #endif
27344 : #if defined(AE_COMPILE_AMDORDERING) || !defined(AE_PARTIAL_BUILD)
27345 :
27346 :
27347 : /*************************************************************************
27348 : This function generates approximate minimum degree ordering
27349 :
27350 : INPUT PARAMETERS
27351 : A - lower triangular sparse matrix in CRS format
27352 : N - problem size
27353 : Buf - reusable buffer object, does not need special initialization
27354 :
27355 : OUTPUT PARAMETERS
27356 : Perm - array[N], maps original indexes I to permuted indexes
27357 : InvPerm - array[N], maps permuted indexes I to original indexes
27358 :
27359 : NOTE: definite 'DEBUG.SLOW' trace tag will activate extra-slow (roughly
27360 : N^3 ops) integrity checks, in addition to cheap O(1) ones.
27361 :
27362 : -- ALGLIB PROJECT --
27363 : Copyright 05.10.2020 by Bochkanov Sergey.
27364 : *************************************************************************/
27365 0 : void generateamdpermutation(sparsematrix* a,
27366 : ae_int_t n,
27367 : /* Integer */ ae_vector* perm,
27368 : /* Integer */ ae_vector* invperm,
27369 : amdbuffer* buf,
27370 : ae_state *_state)
27371 : {
27372 : ae_int_t i;
27373 : ae_int_t j;
27374 : ae_int_t k;
27375 : ae_int_t p;
27376 : ae_int_t setprealloc;
27377 : ae_int_t inithashbucketsize;
27378 : ae_bool extendeddebug;
27379 : ae_int_t nodesize;
27380 : ae_int_t cnt0;
27381 : ae_int_t cnt1;
27382 :
27383 :
27384 0 : setprealloc = 3;
27385 0 : inithashbucketsize = 16;
27386 0 : extendeddebug = ae_is_trace_enabled("DEBUG.SLOW");
27387 0 : buf->n = n;
27388 0 : buf->checkexactdegrees = extendeddebug;
27389 0 : buf->extendeddebug = extendeddebug;
27390 0 : amdordering_mtxinit(n, &buf->mtxl, _state);
27391 0 : amdordering_knsinitfroma(a, n, &buf->seta, _state);
27392 0 : amdordering_knsinit(n, n, setprealloc, &buf->setsuper, _state);
27393 0 : for(i=0; i<=n-1; i++)
27394 : {
27395 0 : amdordering_knsaddnewelement(&buf->setsuper, i, i, _state);
27396 : }
27397 0 : amdordering_knsinit(n, n, setprealloc, &buf->sete, _state);
27398 0 : amdordering_knsinit(n, n, inithashbucketsize, &buf->hashbuckets, _state);
27399 0 : amdordering_nsinitemptyslow(n, &buf->nonemptybuckets, _state);
27400 0 : ivectorsetlengthatleast(&buf->perm, n, _state);
27401 0 : ivectorsetlengthatleast(&buf->invperm, n, _state);
27402 0 : ivectorsetlengthatleast(&buf->columnswaps, n, _state);
27403 0 : for(i=0; i<=n-1; i++)
27404 : {
27405 0 : buf->perm.ptr.p_int[i] = i;
27406 0 : buf->invperm.ptr.p_int[i] = i;
27407 : }
27408 0 : amdordering_vtxinit(a, n, buf->checkexactdegrees, &buf->vertexdegrees, _state);
27409 0 : bsetallocv(n, ae_true, &buf->issupernode, _state);
27410 0 : bsetallocv(n, ae_false, &buf->iseliminated, _state);
27411 0 : isetallocv(n, -1, &buf->arrwe, _state);
27412 0 : if( extendeddebug )
27413 : {
27414 0 : ae_matrix_set_length(&buf->dbga, n, n, _state);
27415 0 : for(i=0; i<=n-1; i++)
27416 : {
27417 0 : for(j=0; j<=n-1; j++)
27418 : {
27419 0 : if( (j<=i&&sparseexists(a, i, j, _state))||(j>=i&&sparseexists(a, j, i, _state)) )
27420 : {
27421 0 : buf->dbga.ptr.pp_double[i][j] = 0.1/n*(ae_sin(i+0.17, _state)+ae_cos(ae_sqrt(j+0.65, _state), _state));
27422 : }
27423 : else
27424 : {
27425 0 : buf->dbga.ptr.pp_double[i][j] = (double)(0);
27426 : }
27427 : }
27428 : }
27429 0 : for(i=0; i<=n-1; i++)
27430 : {
27431 0 : buf->dbga.ptr.pp_double[i][i] = (double)(1);
27432 : }
27433 : }
27434 0 : ivectorsetlengthatleast(&buf->ls, n, _state);
27435 0 : amdordering_nsinitemptyslow(n, &buf->lp, _state);
27436 0 : amdordering_nsinitemptyslow(n, &buf->plp, _state);
27437 0 : amdordering_nsinitemptyslow(n, &buf->ep, _state);
27438 0 : amdordering_nsinitemptyslow(n, &buf->exactdegreetmp0, _state);
27439 0 : amdordering_nsinitemptyslow(n, &buf->adji, _state);
27440 0 : amdordering_nsinitemptyslow(n, &buf->adjj, _state);
27441 0 : k = 0;
27442 0 : while(k<n)
27443 : {
27444 0 : amdordering_amdselectpivotelement(buf, k, &p, &nodesize, _state);
27445 0 : amdordering_amdcomputelp(buf, p, _state);
27446 0 : amdordering_amdmasselimination(buf, p, k, _state);
27447 0 : amdordering_amddetectsupernodes(buf, _state);
27448 0 : if( extendeddebug )
27449 : {
27450 0 : ae_assert(buf->checkexactdegrees, "AMD: extended debug needs exact degrees", _state);
27451 0 : for(i=k; i<=k+nodesize-1; i++)
27452 : {
27453 0 : if( buf->columnswaps.ptr.p_int[i]!=i )
27454 : {
27455 0 : swaprows(&buf->dbga, i, buf->columnswaps.ptr.p_int[i], n, _state);
27456 0 : swapcols(&buf->dbga, i, buf->columnswaps.ptr.p_int[i], n, _state);
27457 : }
27458 : }
27459 0 : for(i=0; i<=nodesize-1; i++)
27460 : {
27461 0 : rmatrixgemm(n-k-i, n-k-i, k+i, -1.0, &buf->dbga, k+i, 0, 0, &buf->dbga, 0, k+i, 0, 1.0, &buf->dbga, k+i, k+i, _state);
27462 : }
27463 0 : cnt0 = amdordering_nscount(&buf->lp, _state);
27464 0 : cnt1 = 0;
27465 0 : for(i=k+1; i<=n-1; i++)
27466 : {
27467 0 : if( ae_fp_neq(buf->dbga.ptr.pp_double[i][k],(double)(0)) )
27468 : {
27469 0 : inc(&cnt1, _state);
27470 : }
27471 : }
27472 0 : ae_assert(cnt0+nodesize-1==cnt1, "AMD: integrity check 7344 failed", _state);
27473 0 : ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, p, _state)>=amdordering_vtxgetexact(&buf->vertexdegrees, p, _state), "AMD: integrity check for ApproxD failed", _state);
27474 0 : ae_assert(amdordering_vtxgetexact(&buf->vertexdegrees, p, _state)==cnt0, "AMD: integrity check for ExactD failed", _state);
27475 : }
27476 0 : ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, p, _state)>=amdordering_nscount(&buf->lp, _state), "AMD: integrity check 7956 failed", _state);
27477 0 : ae_assert(amdordering_knscountkth(&buf->sete, p, _state)>2||amdordering_vtxgetapprox(&buf->vertexdegrees, p, _state)==amdordering_nscount(&buf->lp, _state), "AMD: integrity check 7295 failed", _state);
27478 0 : amdordering_knsstartenumeration(&buf->sete, p, _state);
27479 0 : while(amdordering_knsenumerate(&buf->sete, &j, _state))
27480 : {
27481 0 : amdordering_mtxclearcolumn(&buf->mtxl, j, _state);
27482 : }
27483 0 : amdordering_knsstartenumeration(&buf->setsuper, p, _state);
27484 0 : while(amdordering_knsenumerate(&buf->setsuper, &j, _state))
27485 : {
27486 0 : buf->iseliminated.ptr.p_bool[j] = ae_true;
27487 0 : amdordering_mtxclearrow(&buf->mtxl, j, _state);
27488 : }
27489 0 : amdordering_knsclearkthreclaim(&buf->seta, p, _state);
27490 0 : amdordering_knsclearkthreclaim(&buf->sete, p, _state);
27491 0 : buf->issupernode.ptr.p_bool[p] = ae_false;
27492 0 : amdordering_vtxremovevertex(&buf->vertexdegrees, p, _state);
27493 0 : k = k+nodesize;
27494 : }
27495 0 : ivectorsetlengthatleast(perm, n, _state);
27496 0 : ivectorsetlengthatleast(invperm, n, _state);
27497 0 : for(i=0; i<=n-1; i++)
27498 : {
27499 0 : perm->ptr.p_int[i] = buf->perm.ptr.p_int[i];
27500 0 : invperm->ptr.p_int[i] = buf->invperm.ptr.p_int[i];
27501 : }
27502 0 : }
27503 :
27504 :
27505 : /*************************************************************************
27506 : Initializes n-set by empty structure.
27507 :
27508 : IMPORTANT: this function need O(N) time for initialization. It is recommended
27509 : to reduce its usage as much as possible, and use nsClear()
27510 : where possible.
27511 :
27512 : INPUT PARAMETERS
27513 : N - possible set size
27514 :
27515 : OUTPUT PARAMETERS
27516 : SA - empty N-set
27517 :
27518 : -- ALGLIB PROJECT --
27519 : Copyright 05.10.2020 by Bochkanov Sergey.
27520 : *************************************************************************/
27521 0 : static void amdordering_nsinitemptyslow(ae_int_t n,
27522 : amdnset* sa,
27523 : ae_state *_state)
27524 : {
27525 :
27526 :
27527 0 : sa->n = n;
27528 0 : sa->nstored = 0;
27529 0 : isetallocv(n, -999999999, &sa->locationof, _state);
27530 0 : isetallocv(n, -999999999, &sa->items, _state);
27531 0 : }
27532 :
27533 :
27534 : /*************************************************************************
27535 : Copies n-set to properly initialized target set. The target set has to be
27536 : properly initialized, and it can be non-empty. If it is non-empty, its
27537 : contents is quickly erased before copying.
27538 :
27539 : The cost of this function is O(max(SrcSize,DstSize))
27540 :
27541 : INPUT PARAMETERS
27542 : SSrc - source N-set
27543 : SDst - destination N-set (has same size as SSrc)
27544 :
27545 : OUTPUT PARAMETERS
27546 : SDst - copy of SSrc
27547 :
27548 : -- ALGLIB PROJECT --
27549 : Copyright 05.10.2020 by Bochkanov Sergey.
27550 : *************************************************************************/
27551 0 : static void amdordering_nscopy(amdnset* ssrc,
27552 : amdnset* sdst,
27553 : ae_state *_state)
27554 : {
27555 : ae_int_t ns;
27556 : ae_int_t i;
27557 : ae_int_t k;
27558 :
27559 :
27560 0 : amdordering_nsclear(sdst, _state);
27561 0 : ns = ssrc->nstored;
27562 0 : for(i=0; i<=ns-1; i++)
27563 : {
27564 0 : k = ssrc->items.ptr.p_int[i];
27565 0 : sdst->items.ptr.p_int[i] = k;
27566 0 : sdst->locationof.ptr.p_int[k] = i;
27567 : }
27568 0 : sdst->nstored = ns;
27569 0 : }
27570 :
27571 :
27572 : /*************************************************************************
27573 : Add K-th element to the set. The element may already exist in the set.
27574 :
27575 : INPUT PARAMETERS
27576 : SA - set
27577 : K - element to add, 0<=K<N.
27578 :
27579 : OUTPUT PARAMETERS
27580 : SA - modified SA
27581 :
27582 : -- ALGLIB PROJECT --
27583 : Copyright 05.10.2020 by Bochkanov Sergey.
27584 : *************************************************************************/
27585 0 : static void amdordering_nsaddelement(amdnset* sa,
27586 : ae_int_t k,
27587 : ae_state *_state)
27588 : {
27589 : ae_int_t ns;
27590 :
27591 :
27592 0 : if( sa->locationof.ptr.p_int[k]>=0 )
27593 : {
27594 0 : return;
27595 : }
27596 0 : ns = sa->nstored;
27597 0 : sa->locationof.ptr.p_int[k] = ns;
27598 0 : sa->items.ptr.p_int[ns] = k;
27599 0 : sa->nstored = ns+1;
27600 : }
27601 :
27602 :
27603 : /*************************************************************************
27604 : Add K-th set from the source kn-set
27605 :
27606 : INPUT PARAMETERS
27607 : SA - set
27608 : Src, K - source kn-set and set index K
27609 :
27610 : OUTPUT PARAMETERS
27611 : SA - modified SA
27612 :
27613 : -- ALGLIB PROJECT --
27614 : Copyright 05.10.2020 by Bochkanov Sergey.
27615 : *************************************************************************/
27616 0 : static void amdordering_nsaddkth(amdnset* sa,
27617 : amdknset* src,
27618 : ae_int_t k,
27619 : ae_state *_state)
27620 : {
27621 : ae_int_t idxbegin;
27622 : ae_int_t idxend;
27623 : ae_int_t j;
27624 : ae_int_t ns;
27625 :
27626 :
27627 0 : idxbegin = src->vbegin.ptr.p_int[k];
27628 0 : idxend = idxbegin+src->vcnt.ptr.p_int[k];
27629 0 : ns = sa->nstored;
27630 0 : while(idxbegin<idxend)
27631 : {
27632 0 : j = src->data.ptr.p_int[idxbegin];
27633 0 : if( sa->locationof.ptr.p_int[j]<0 )
27634 : {
27635 0 : sa->locationof.ptr.p_int[j] = ns;
27636 0 : sa->items.ptr.p_int[ns] = j;
27637 0 : ns = ns+1;
27638 : }
27639 0 : idxbegin = idxbegin+1;
27640 : }
27641 0 : sa->nstored = ns;
27642 0 : }
27643 :
27644 :
27645 : /*************************************************************************
27646 : Subtracts K-th set from the source structure
27647 :
27648 : INPUT PARAMETERS
27649 : SA - set
27650 : Src, K - source kn-set and set index K
27651 :
27652 : OUTPUT PARAMETERS
27653 : SA - modified SA
27654 :
27655 : -- ALGLIB PROJECT --
27656 : Copyright 05.10.2020 by Bochkanov Sergey.
27657 : *************************************************************************/
27658 0 : static void amdordering_nssubtractkth(amdnset* sa,
27659 : amdknset* src,
27660 : ae_int_t k,
27661 : ae_state *_state)
27662 : {
27663 : ae_int_t idxbegin;
27664 : ae_int_t idxend;
27665 : ae_int_t j;
27666 : ae_int_t loc;
27667 : ae_int_t ns;
27668 : ae_int_t item;
27669 :
27670 :
27671 0 : idxbegin = src->vbegin.ptr.p_int[k];
27672 0 : idxend = idxbegin+src->vcnt.ptr.p_int[k];
27673 0 : ns = sa->nstored;
27674 0 : while(idxbegin<idxend)
27675 : {
27676 0 : j = src->data.ptr.p_int[idxbegin];
27677 0 : loc = sa->locationof.ptr.p_int[j];
27678 0 : if( loc>=0 )
27679 : {
27680 0 : item = sa->items.ptr.p_int[ns-1];
27681 0 : sa->items.ptr.p_int[loc] = item;
27682 0 : sa->locationof.ptr.p_int[item] = loc;
27683 0 : sa->locationof.ptr.p_int[j] = -1;
27684 0 : ns = ns-1;
27685 : }
27686 0 : idxbegin = idxbegin+1;
27687 : }
27688 0 : sa->nstored = ns;
27689 0 : }
27690 :
27691 :
27692 : /*************************************************************************
27693 : Clears set
27694 :
27695 : INPUT PARAMETERS
27696 : SA - set to be cleared
27697 :
27698 :
27699 : -- ALGLIB PROJECT --
27700 : Copyright 05.10.2020 by Bochkanov Sergey.
27701 : *************************************************************************/
27702 0 : static void amdordering_nsclear(amdnset* sa, ae_state *_state)
27703 : {
27704 : ae_int_t i;
27705 : ae_int_t ns;
27706 :
27707 :
27708 0 : ns = sa->nstored;
27709 0 : for(i=0; i<=ns-1; i++)
27710 : {
27711 0 : sa->locationof.ptr.p_int[sa->items.ptr.p_int[i]] = -1;
27712 : }
27713 0 : sa->nstored = 0;
27714 0 : }
27715 :
27716 :
27717 : /*************************************************************************
27718 : Counts set elements
27719 :
27720 : INPUT PARAMETERS
27721 : SA - set
27722 :
27723 : RESULT
27724 : number of elements in SA
27725 :
27726 : -- ALGLIB PROJECT --
27727 : Copyright 05.10.2020 by Bochkanov Sergey.
27728 : *************************************************************************/
27729 0 : static ae_int_t amdordering_nscount(amdnset* sa, ae_state *_state)
27730 : {
27731 : ae_int_t result;
27732 :
27733 :
27734 0 : result = sa->nstored;
27735 0 : return result;
27736 : }
27737 :
27738 :
27739 : /*************************************************************************
27740 : Counts set elements not present in the K-th set of the source structure
27741 :
27742 : INPUT PARAMETERS
27743 : SA - set
27744 : Src, K - source kn-set and set index K
27745 :
27746 : RESULT
27747 : number of elements in SA not present in Src[K]
27748 :
27749 : -- ALGLIB PROJECT --
27750 : Copyright 05.10.2020 by Bochkanov Sergey.
27751 : *************************************************************************/
27752 0 : static ae_int_t amdordering_nscountnotkth(amdnset* sa,
27753 : amdknset* src,
27754 : ae_int_t k,
27755 : ae_state *_state)
27756 : {
27757 : ae_int_t idxbegin;
27758 : ae_int_t idxend;
27759 : ae_int_t intersectcnt;
27760 : ae_int_t result;
27761 :
27762 :
27763 0 : idxbegin = src->vbegin.ptr.p_int[k];
27764 0 : idxend = idxbegin+src->vcnt.ptr.p_int[k];
27765 0 : intersectcnt = 0;
27766 0 : while(idxbegin<idxend)
27767 : {
27768 0 : if( sa->locationof.ptr.p_int[src->data.ptr.p_int[idxbegin]]>=0 )
27769 : {
27770 0 : intersectcnt = intersectcnt+1;
27771 : }
27772 0 : idxbegin = idxbegin+1;
27773 : }
27774 0 : result = sa->nstored-intersectcnt;
27775 0 : return result;
27776 : }
27777 :
27778 :
27779 : /*************************************************************************
27780 : Counts set elements also present in the K-th set of the source structure
27781 :
27782 : INPUT PARAMETERS
27783 : SA - set
27784 : Src, K - source kn-set and set index K
27785 :
27786 : RESULT
27787 : number of elements in SA also present in Src[K]
27788 :
27789 : -- ALGLIB PROJECT --
27790 : Copyright 05.10.2020 by Bochkanov Sergey.
27791 : *************************************************************************/
27792 0 : static ae_int_t amdordering_nscountandkth(amdnset* sa,
27793 : amdknset* src,
27794 : ae_int_t k,
27795 : ae_state *_state)
27796 : {
27797 : ae_int_t idxbegin;
27798 : ae_int_t idxend;
27799 : ae_int_t result;
27800 :
27801 :
27802 0 : idxbegin = src->vbegin.ptr.p_int[k];
27803 0 : idxend = idxbegin+src->vcnt.ptr.p_int[k];
27804 0 : result = 0;
27805 0 : while(idxbegin<idxend)
27806 : {
27807 0 : if( sa->locationof.ptr.p_int[src->data.ptr.p_int[idxbegin]]>=0 )
27808 : {
27809 0 : result = result+1;
27810 : }
27811 0 : idxbegin = idxbegin+1;
27812 : }
27813 0 : return result;
27814 : }
27815 :
27816 :
27817 : /*************************************************************************
27818 : Compare two sets, returns True for equal sets
27819 :
27820 : INPUT PARAMETERS
27821 : S0 - set 0
27822 : S1 - set 1, must have same parameter N as set 0
27823 :
27824 : RESULT
27825 : True, if sets are equal
27826 :
27827 : -- ALGLIB PROJECT --
27828 : Copyright 05.10.2020 by Bochkanov Sergey.
27829 : *************************************************************************/
27830 0 : static ae_bool amdordering_nsequal(amdnset* s0,
27831 : amdnset* s1,
27832 : ae_state *_state)
27833 : {
27834 : ae_int_t i;
27835 : ae_int_t ns0;
27836 : ae_int_t ns1;
27837 : ae_bool result;
27838 :
27839 :
27840 0 : result = ae_false;
27841 0 : if( s0->n!=s1->n )
27842 : {
27843 0 : return result;
27844 : }
27845 0 : if( s0->nstored!=s1->nstored )
27846 : {
27847 0 : return result;
27848 : }
27849 0 : ns0 = s0->nstored;
27850 0 : ns1 = s1->nstored;
27851 0 : for(i=0; i<=ns0-1; i++)
27852 : {
27853 0 : if( s1->locationof.ptr.p_int[s0->items.ptr.p_int[i]]<0 )
27854 : {
27855 0 : return result;
27856 : }
27857 : }
27858 0 : for(i=0; i<=ns1-1; i++)
27859 : {
27860 0 : if( s0->locationof.ptr.p_int[s1->items.ptr.p_int[i]]<0 )
27861 : {
27862 0 : return result;
27863 : }
27864 : }
27865 0 : result = ae_true;
27866 0 : return result;
27867 : }
27868 :
27869 :
27870 : /*************************************************************************
27871 : Prepares iteration over set
27872 :
27873 : INPUT PARAMETERS
27874 : SA - set
27875 :
27876 : OUTPUT PARAMETERS
27877 : SA - SA ready for repeated calls of nsEnumerate()
27878 :
27879 : -- ALGLIB PROJECT --
27880 : Copyright 05.10.2020 by Bochkanov Sergey.
27881 : *************************************************************************/
27882 0 : static void amdordering_nsstartenumeration(amdnset* sa, ae_state *_state)
27883 : {
27884 :
27885 :
27886 0 : sa->iteridx = 0;
27887 0 : }
27888 :
27889 :
27890 : /*************************************************************************
27891 : Iterates over the set. Subsequent calls return True and set J to new set
27892 : item until iteration stops and False is returned.
27893 :
27894 : INPUT PARAMETERS
27895 : SA - n-set
27896 :
27897 : OUTPUT PARAMETERS
27898 : J - if:
27899 : * Result=True - index of element in the set
27900 : * Result=False - not set
27901 :
27902 :
27903 : -- ALGLIB PROJECT --
27904 : Copyright 05.10.2020 by Bochkanov Sergey.
27905 : *************************************************************************/
27906 0 : static ae_bool amdordering_nsenumerate(amdnset* sa,
27907 : ae_int_t* i,
27908 : ae_state *_state)
27909 : {
27910 : ae_int_t k;
27911 : ae_bool result;
27912 :
27913 0 : *i = 0;
27914 :
27915 0 : k = sa->iteridx;
27916 0 : if( k>=sa->nstored )
27917 : {
27918 0 : result = ae_false;
27919 0 : return result;
27920 : }
27921 0 : *i = sa->items.ptr.p_int[k];
27922 0 : sa->iteridx = k+1;
27923 0 : result = ae_true;
27924 0 : return result;
27925 : }
27926 :
27927 :
27928 : /*************************************************************************
27929 : Compresses internal storage, reclaiming previously dropped blocks. To be
27930 : used internally by kn-set modification functions.
27931 :
27932 : INPUT PARAMETERS
27933 : SA - kn-set to compress
27934 :
27935 : -- ALGLIB PROJECT --
27936 : Copyright 05.10.2020 by Bochkanov Sergey.
27937 : *************************************************************************/
27938 0 : static void amdordering_knscompressstorage(amdknset* sa, ae_state *_state)
27939 : {
27940 : ae_int_t i;
27941 : ae_int_t blocklen;
27942 : ae_int_t setidx;
27943 : ae_int_t srcoffs;
27944 : ae_int_t dstoffs;
27945 :
27946 :
27947 0 : srcoffs = 0;
27948 0 : dstoffs = 0;
27949 0 : while(srcoffs<sa->dataused)
27950 : {
27951 0 : blocklen = sa->data.ptr.p_int[srcoffs+0];
27952 0 : setidx = sa->data.ptr.p_int[srcoffs+1];
27953 0 : ae_assert(blocklen>=amdordering_knsheadersize, "knsCompressStorage: integrity check 6385 failed", _state);
27954 0 : if( setidx<0 )
27955 : {
27956 0 : srcoffs = srcoffs+blocklen;
27957 0 : continue;
27958 : }
27959 0 : if( srcoffs!=dstoffs )
27960 : {
27961 0 : for(i=0; i<=blocklen-1; i++)
27962 : {
27963 0 : sa->data.ptr.p_int[dstoffs+i] = sa->data.ptr.p_int[srcoffs+i];
27964 : }
27965 0 : sa->vbegin.ptr.p_int[setidx] = dstoffs+amdordering_knsheadersize;
27966 : }
27967 0 : dstoffs = dstoffs+blocklen;
27968 0 : srcoffs = srcoffs+blocklen;
27969 : }
27970 0 : ae_assert(srcoffs==sa->dataused, "knsCompressStorage: integrity check 9464 failed", _state);
27971 0 : sa->dataused = dstoffs;
27972 0 : }
27973 :
27974 :
27975 : /*************************************************************************
27976 : Reallocates internal storage for set #SetIdx, increasing its capacity to
27977 : NewAllocated exactly. This function may invalidate internal pointers for
27978 : ALL sets in the kn-set structure because it may perform storage
27979 : compression in order to reclaim previously freed space.
27980 :
27981 : INPUT PARAMETERS
27982 : SA - kn-set structure
27983 : SetIdx - set to reallocate
27984 : NewAllocated - new size for the set, must be at least equal to already
27985 : allocated
27986 :
27987 : -- ALGLIB PROJECT --
27988 : Copyright 05.10.2020 by Bochkanov Sergey.
27989 : *************************************************************************/
27990 0 : static void amdordering_knsreallocate(amdknset* sa,
27991 : ae_int_t setidx,
27992 : ae_int_t newallocated,
27993 : ae_state *_state)
27994 : {
27995 : ae_int_t oldbegin;
27996 : ae_int_t oldcnt;
27997 : ae_int_t newbegin;
27998 : ae_int_t j;
27999 :
28000 :
28001 0 : if( sa->data.cnt<sa->dataused+amdordering_knsheadersize+newallocated )
28002 : {
28003 0 : amdordering_knscompressstorage(sa, _state);
28004 0 : if( sa->data.cnt<sa->dataused+amdordering_knsheadersize+newallocated )
28005 : {
28006 0 : ivectorgrowto(&sa->data, sa->dataused+amdordering_knsheadersize+newallocated, _state);
28007 : }
28008 : }
28009 0 : oldbegin = sa->vbegin.ptr.p_int[setidx];
28010 0 : oldcnt = sa->vcnt.ptr.p_int[setidx];
28011 0 : newbegin = sa->dataused+amdordering_knsheadersize;
28012 0 : sa->vbegin.ptr.p_int[setidx] = newbegin;
28013 0 : sa->vallocated.ptr.p_int[setidx] = newallocated;
28014 0 : sa->data.ptr.p_int[oldbegin-1] = -1;
28015 0 : sa->data.ptr.p_int[newbegin-2] = amdordering_knsheadersize+newallocated;
28016 0 : sa->data.ptr.p_int[newbegin-1] = setidx;
28017 0 : sa->dataused = sa->dataused+sa->data.ptr.p_int[newbegin-2];
28018 0 : for(j=0; j<=oldcnt-1; j++)
28019 : {
28020 0 : sa->data.ptr.p_int[newbegin+j] = sa->data.ptr.p_int[oldbegin+j];
28021 : }
28022 0 : }
28023 :
28024 :
28025 : /*************************************************************************
28026 : Initialize kn-set
28027 :
28028 : INPUT PARAMETERS
28029 : K - sets count
28030 : N - set size
28031 : kPrealloc - preallocate place per set (can be zero)
28032 :
28033 : OUTPUT PARAMETERS
28034 : SA - K sets of N elements, initially empty
28035 :
28036 : -- ALGLIB PROJECT --
28037 : Copyright 05.10.2020 by Bochkanov Sergey.
28038 : *************************************************************************/
28039 0 : static void amdordering_knsinit(ae_int_t k,
28040 : ae_int_t n,
28041 : ae_int_t kprealloc,
28042 : amdknset* sa,
28043 : ae_state *_state)
28044 : {
28045 : ae_int_t i;
28046 :
28047 :
28048 0 : sa->k = n;
28049 0 : sa->n = n;
28050 0 : isetallocv(n, -1, &sa->flagarray, _state);
28051 0 : isetallocv(n, kprealloc, &sa->vallocated, _state);
28052 0 : ivectorsetlengthatleast(&sa->vbegin, n, _state);
28053 0 : sa->vbegin.ptr.p_int[0] = amdordering_knsheadersize;
28054 0 : for(i=1; i<=n-1; i++)
28055 : {
28056 0 : sa->vbegin.ptr.p_int[i] = sa->vbegin.ptr.p_int[i-1]+sa->vallocated.ptr.p_int[i-1]+amdordering_knsheadersize;
28057 : }
28058 0 : sa->dataused = sa->vbegin.ptr.p_int[n-1]+sa->vallocated.ptr.p_int[n-1];
28059 0 : ivectorsetlengthatleast(&sa->data, sa->dataused, _state);
28060 0 : for(i=0; i<=n-1; i++)
28061 : {
28062 0 : sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]-2] = amdordering_knsheadersize+sa->vallocated.ptr.p_int[i];
28063 0 : sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]-1] = i;
28064 : }
28065 0 : isetallocv(n, 0, &sa->vcnt, _state);
28066 0 : }
28067 :
28068 :
28069 : /*************************************************************************
28070 : Initialize kn-set from lower triangle of symmetric A
28071 :
28072 : INPUT PARAMETERS
28073 : A - lower triangular sparse matrix in CRS format
28074 : N - problem size
28075 :
28076 : OUTPUT PARAMETERS
28077 : SA - N sets of N elements, reproducing both lower and upper
28078 : triangles of A
28079 :
28080 : -- ALGLIB PROJECT --
28081 : Copyright 05.10.2020 by Bochkanov Sergey.
28082 : *************************************************************************/
28083 0 : static void amdordering_knsinitfroma(sparsematrix* a,
28084 : ae_int_t n,
28085 : amdknset* sa,
28086 : ae_state *_state)
28087 : {
28088 : ae_int_t i;
28089 : ae_int_t j;
28090 : ae_int_t jj;
28091 : ae_int_t j0;
28092 : ae_int_t j1;
28093 :
28094 :
28095 0 : sa->k = n;
28096 0 : sa->n = n;
28097 0 : isetallocv(n, -1, &sa->flagarray, _state);
28098 0 : ivectorsetlengthatleast(&sa->vallocated, n, _state);
28099 0 : for(i=0; i<=n-1; i++)
28100 : {
28101 0 : ae_assert(a->didx.ptr.p_int[i]<a->uidx.ptr.p_int[i], "knsInitFromA: integrity check for diagonal of A failed", _state);
28102 0 : j0 = a->ridx.ptr.p_int[i];
28103 0 : j1 = a->didx.ptr.p_int[i]-1;
28104 0 : sa->vallocated.ptr.p_int[i] = 1+(j1-j0+1);
28105 0 : for(jj=j0; jj<=j1; jj++)
28106 : {
28107 0 : j = a->idx.ptr.p_int[jj];
28108 0 : sa->vallocated.ptr.p_int[j] = sa->vallocated.ptr.p_int[j]+1;
28109 : }
28110 : }
28111 0 : ivectorsetlengthatleast(&sa->vbegin, n, _state);
28112 0 : sa->vbegin.ptr.p_int[0] = amdordering_knsheadersize;
28113 0 : for(i=1; i<=n-1; i++)
28114 : {
28115 0 : sa->vbegin.ptr.p_int[i] = sa->vbegin.ptr.p_int[i-1]+sa->vallocated.ptr.p_int[i-1]+amdordering_knsheadersize;
28116 : }
28117 0 : sa->dataused = sa->vbegin.ptr.p_int[n-1]+sa->vallocated.ptr.p_int[n-1];
28118 0 : ivectorsetlengthatleast(&sa->data, sa->dataused, _state);
28119 0 : for(i=0; i<=n-1; i++)
28120 : {
28121 0 : sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]-2] = amdordering_knsheadersize+sa->vallocated.ptr.p_int[i];
28122 0 : sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]-1] = i;
28123 : }
28124 0 : isetallocv(n, 0, &sa->vcnt, _state);
28125 0 : for(i=0; i<=n-1; i++)
28126 : {
28127 0 : sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]+sa->vcnt.ptr.p_int[i]] = i;
28128 0 : sa->vcnt.ptr.p_int[i] = sa->vcnt.ptr.p_int[i]+1;
28129 0 : j0 = a->ridx.ptr.p_int[i];
28130 0 : j1 = a->didx.ptr.p_int[i]-1;
28131 0 : for(jj=j0; jj<=j1; jj++)
28132 : {
28133 0 : j = a->idx.ptr.p_int[jj];
28134 0 : sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]+sa->vcnt.ptr.p_int[i]] = j;
28135 0 : sa->data.ptr.p_int[sa->vbegin.ptr.p_int[j]+sa->vcnt.ptr.p_int[j]] = i;
28136 0 : sa->vcnt.ptr.p_int[i] = sa->vcnt.ptr.p_int[i]+1;
28137 0 : sa->vcnt.ptr.p_int[j] = sa->vcnt.ptr.p_int[j]+1;
28138 : }
28139 : }
28140 0 : }
28141 :
28142 :
28143 : /*************************************************************************
28144 : Prepares iteration over I-th set
28145 :
28146 : INPUT PARAMETERS
28147 : SA - kn-set
28148 : I - set index
28149 :
28150 : OUTPUT PARAMETERS
28151 : SA - SA ready for repeated calls of knsEnumerate()
28152 :
28153 : -- ALGLIB PROJECT --
28154 : Copyright 05.10.2020 by Bochkanov Sergey.
28155 : *************************************************************************/
28156 0 : static void amdordering_knsstartenumeration(amdknset* sa,
28157 : ae_int_t i,
28158 : ae_state *_state)
28159 : {
28160 :
28161 :
28162 0 : sa->iterrow = i;
28163 0 : sa->iteridx = 0;
28164 0 : }
28165 :
28166 :
28167 : /*************************************************************************
28168 : Iterates over I-th set (as specified during recent knsStartEnumeration call).
28169 : Subsequent calls return True and set J to new set item until iteration
28170 : stops and False is returned.
28171 :
28172 : INPUT PARAMETERS
28173 : SA - kn-set
28174 :
28175 : OUTPUT PARAMETERS
28176 : J - if:
28177 : * Result=True - index of element in the set
28178 : * Result=False - not set
28179 :
28180 :
28181 : -- ALGLIB PROJECT --
28182 : Copyright 05.10.2020 by Bochkanov Sergey.
28183 : *************************************************************************/
28184 0 : static ae_bool amdordering_knsenumerate(amdknset* sa,
28185 : ae_int_t* i,
28186 : ae_state *_state)
28187 : {
28188 : ae_bool result;
28189 :
28190 0 : *i = 0;
28191 :
28192 0 : if( sa->iteridx<sa->vcnt.ptr.p_int[sa->iterrow] )
28193 : {
28194 0 : *i = sa->data.ptr.p_int[sa->vbegin.ptr.p_int[sa->iterrow]+sa->iteridx];
28195 0 : sa->iteridx = sa->iteridx+1;
28196 0 : result = ae_true;
28197 : }
28198 : else
28199 : {
28200 0 : result = ae_false;
28201 : }
28202 0 : return result;
28203 : }
28204 :
28205 :
28206 : /*************************************************************************
28207 : Allows direct access to internal storage of kn-set structure - returns
28208 : range of elements SA.Data[idxBegin...idxEnd-1] used to store K-th set
28209 :
28210 : INPUT PARAMETERS
28211 : SA - kn-set
28212 : K - set index
28213 :
28214 : OUTPUT PARAMETERS
28215 : idxBegin,
28216 : idxEnd - half-range [idxBegin,idxEnd) of SA.Data that stores
28217 : K-th set
28218 :
28219 :
28220 : -- ALGLIB PROJECT --
28221 : Copyright 05.10.2020 by Bochkanov Sergey.
28222 : *************************************************************************/
28223 0 : static void amdordering_knsdirectaccess(amdknset* sa,
28224 : ae_int_t k,
28225 : ae_int_t* idxbegin,
28226 : ae_int_t* idxend,
28227 : ae_state *_state)
28228 : {
28229 :
28230 0 : *idxbegin = 0;
28231 0 : *idxend = 0;
28232 :
28233 0 : *idxbegin = sa->vbegin.ptr.p_int[k];
28234 0 : *idxend = *idxbegin+sa->vcnt.ptr.p_int[k];
28235 0 : }
28236 :
28237 :
28238 : /*************************************************************************
28239 : Add K-th element to I-th set. The caller guarantees that the element is
28240 : not present in the target set.
28241 :
28242 : INPUT PARAMETERS
28243 : SA - kn-set
28244 : I - set index
28245 : K - element to add
28246 :
28247 : OUTPUT PARAMETERS
28248 : SA - modified SA
28249 :
28250 : -- ALGLIB PROJECT --
28251 : Copyright 05.10.2020 by Bochkanov Sergey.
28252 : *************************************************************************/
28253 0 : static void amdordering_knsaddnewelement(amdknset* sa,
28254 : ae_int_t i,
28255 : ae_int_t k,
28256 : ae_state *_state)
28257 : {
28258 : ae_int_t cnt;
28259 :
28260 :
28261 0 : cnt = sa->vcnt.ptr.p_int[i];
28262 0 : if( cnt==sa->vallocated.ptr.p_int[i] )
28263 : {
28264 0 : amdordering_knsreallocate(sa, i, 2*sa->vallocated.ptr.p_int[i]+1, _state);
28265 : }
28266 0 : sa->data.ptr.p_int[sa->vbegin.ptr.p_int[i]+cnt] = k;
28267 0 : sa->vcnt.ptr.p_int[i] = cnt+1;
28268 0 : }
28269 :
28270 :
28271 : /*************************************************************************
28272 : Subtracts source n-set from the I-th set of the destination kn-set.
28273 :
28274 : INPUT PARAMETERS
28275 : SA - destination kn-set structure
28276 : I - set index in the structure
28277 : Src - source n-set
28278 :
28279 : OUTPUT PARAMETERS
28280 : SA - I-th set except for elements in Src
28281 :
28282 : -- ALGLIB PROJECT --
28283 : Copyright 05.10.2020 by Bochkanov Sergey.
28284 : *************************************************************************/
28285 0 : static void amdordering_knssubtract1(amdknset* sa,
28286 : ae_int_t i,
28287 : amdnset* src,
28288 : ae_state *_state)
28289 : {
28290 : ae_int_t j;
28291 : ae_int_t idxbegin;
28292 : ae_int_t idxend;
28293 : ae_int_t cnt;
28294 :
28295 :
28296 0 : cnt = sa->vcnt.ptr.p_int[i];
28297 0 : idxbegin = sa->vbegin.ptr.p_int[i];
28298 0 : idxend = idxbegin+cnt;
28299 0 : while(idxbegin<idxend)
28300 : {
28301 0 : j = sa->data.ptr.p_int[idxbegin];
28302 0 : if( src->locationof.ptr.p_int[j]>=0 )
28303 : {
28304 0 : sa->data.ptr.p_int[idxbegin] = sa->data.ptr.p_int[idxend-1];
28305 0 : idxend = idxend-1;
28306 0 : cnt = cnt-1;
28307 : }
28308 : else
28309 : {
28310 0 : idxbegin = idxbegin+1;
28311 : }
28312 : }
28313 0 : sa->vcnt.ptr.p_int[i] = cnt;
28314 0 : }
28315 :
28316 :
28317 : /*************************************************************************
28318 : Adds Kth set of the source kn-set to the I-th destination set. The caller
28319 : guarantees that SA[I] and Src[J] do NOT intersect, i.e. do not have shared
28320 : elements - it allows to use faster algorithms.
28321 :
28322 : INPUT PARAMETERS
28323 : SA - destination kn-set structure
28324 : I - set index in the structure
28325 : Src - source kn-set
28326 : K - set index
28327 :
28328 : OUTPUT PARAMETERS
28329 : SA - I-th set plus for elements in K-th set of Src
28330 :
28331 : -- ALGLIB PROJECT --
28332 : Copyright 05.10.2020 by Bochkanov Sergey.
28333 : *************************************************************************/
28334 0 : static void amdordering_knsaddkthdistinct(amdknset* sa,
28335 : ae_int_t i,
28336 : amdknset* src,
28337 : ae_int_t k,
28338 : ae_state *_state)
28339 : {
28340 : ae_int_t idxdst;
28341 : ae_int_t idxsrcbegin;
28342 : ae_int_t cnt;
28343 : ae_int_t srccnt;
28344 : ae_int_t j;
28345 :
28346 :
28347 0 : cnt = sa->vcnt.ptr.p_int[i];
28348 0 : srccnt = src->vcnt.ptr.p_int[k];
28349 0 : if( cnt+srccnt>sa->vallocated.ptr.p_int[i] )
28350 : {
28351 0 : amdordering_knsreallocate(sa, i, 2*(cnt+srccnt)+1, _state);
28352 : }
28353 0 : idxsrcbegin = src->vbegin.ptr.p_int[k];
28354 0 : idxdst = sa->vbegin.ptr.p_int[i]+cnt;
28355 0 : for(j=0; j<=srccnt-1; j++)
28356 : {
28357 0 : sa->data.ptr.p_int[idxdst] = src->data.ptr.p_int[idxsrcbegin+j];
28358 0 : idxdst = idxdst+1;
28359 : }
28360 0 : sa->vcnt.ptr.p_int[i] = cnt+srccnt;
28361 0 : }
28362 :
28363 :
28364 : /*************************************************************************
28365 : Counts elements of K-th set of S0
28366 :
28367 : INPUT PARAMETERS
28368 : S0 - kn-set structure
28369 : K - set index in the structure S0
28370 :
28371 : RESULT
28372 : K-th set element count
28373 :
28374 : -- ALGLIB PROJECT --
28375 : Copyright 05.10.2020 by Bochkanov Sergey.
28376 : *************************************************************************/
28377 0 : static ae_int_t amdordering_knscountkth(amdknset* s0,
28378 : ae_int_t k,
28379 : ae_state *_state)
28380 : {
28381 : ae_int_t result;
28382 :
28383 :
28384 0 : result = s0->vcnt.ptr.p_int[k];
28385 0 : return result;
28386 : }
28387 :
28388 :
28389 : /*************************************************************************
28390 : Counts elements of I-th set of S0 not present in K-th set of S1
28391 :
28392 : INPUT PARAMETERS
28393 : S0 - kn-set structure
28394 : I - set index in the structure S0
28395 : S1 - kn-set to compare against
28396 : K - set index in the structure S1
28397 :
28398 : RESULT
28399 : count
28400 :
28401 : -- ALGLIB PROJECT --
28402 : Copyright 05.10.2020 by Bochkanov Sergey.
28403 : *************************************************************************/
28404 0 : static ae_int_t amdordering_knscountnotkth(amdknset* s0,
28405 : ae_int_t i,
28406 : amdknset* s1,
28407 : ae_int_t k,
28408 : ae_state *_state)
28409 : {
28410 : ae_int_t idxbegin0;
28411 : ae_int_t idxbegin1;
28412 : ae_int_t cnt0;
28413 : ae_int_t cnt1;
28414 : ae_int_t j;
28415 : ae_int_t result;
28416 :
28417 :
28418 0 : cnt0 = s0->vcnt.ptr.p_int[i];
28419 0 : cnt1 = s1->vcnt.ptr.p_int[k];
28420 0 : idxbegin0 = s0->vbegin.ptr.p_int[i];
28421 0 : idxbegin1 = s1->vbegin.ptr.p_int[k];
28422 0 : for(j=0; j<=cnt1-1; j++)
28423 : {
28424 0 : s0->flagarray.ptr.p_int[s1->data.ptr.p_int[idxbegin1+j]] = 1;
28425 : }
28426 0 : result = 0;
28427 0 : for(j=0; j<=cnt0-1; j++)
28428 : {
28429 0 : if( s0->flagarray.ptr.p_int[s0->data.ptr.p_int[idxbegin0+j]]<0 )
28430 : {
28431 0 : result = result+1;
28432 : }
28433 : }
28434 0 : for(j=0; j<=cnt1-1; j++)
28435 : {
28436 0 : s0->flagarray.ptr.p_int[s1->data.ptr.p_int[idxbegin1+j]] = -1;
28437 : }
28438 0 : return result;
28439 : }
28440 :
28441 :
28442 : /*************************************************************************
28443 : Counts elements of I-th set of S0 that are also present in K-th set of S1
28444 :
28445 : INPUT PARAMETERS
28446 : S0 - kn-set structure
28447 : I - set index in the structure S0
28448 : S1 - kn-set to compare against
28449 : K - set index in the structure S1
28450 :
28451 : RESULT
28452 : count
28453 :
28454 : -- ALGLIB PROJECT --
28455 : Copyright 05.10.2020 by Bochkanov Sergey.
28456 : *************************************************************************/
28457 0 : static ae_int_t amdordering_knscountandkth(amdknset* s0,
28458 : ae_int_t i,
28459 : amdknset* s1,
28460 : ae_int_t k,
28461 : ae_state *_state)
28462 : {
28463 : ae_int_t idxbegin0;
28464 : ae_int_t idxbegin1;
28465 : ae_int_t cnt0;
28466 : ae_int_t cnt1;
28467 : ae_int_t j;
28468 : ae_int_t result;
28469 :
28470 :
28471 0 : cnt0 = s0->vcnt.ptr.p_int[i];
28472 0 : cnt1 = s1->vcnt.ptr.p_int[k];
28473 0 : idxbegin0 = s0->vbegin.ptr.p_int[i];
28474 0 : idxbegin1 = s1->vbegin.ptr.p_int[k];
28475 0 : for(j=0; j<=cnt1-1; j++)
28476 : {
28477 0 : s0->flagarray.ptr.p_int[s1->data.ptr.p_int[idxbegin1+j]] = 1;
28478 : }
28479 0 : result = 0;
28480 0 : for(j=0; j<=cnt0-1; j++)
28481 : {
28482 0 : if( s0->flagarray.ptr.p_int[s0->data.ptr.p_int[idxbegin0+j]]>0 )
28483 : {
28484 0 : result = result+1;
28485 : }
28486 : }
28487 0 : for(j=0; j<=cnt1-1; j++)
28488 : {
28489 0 : s0->flagarray.ptr.p_int[s1->data.ptr.p_int[idxbegin1+j]] = -1;
28490 : }
28491 0 : return result;
28492 : }
28493 :
28494 :
28495 : /*************************************************************************
28496 : Sums elements in I-th set of S0, returns sum.
28497 :
28498 : INPUT PARAMETERS
28499 : S0 - kn-set structure
28500 : I - set index in the structure S0
28501 :
28502 : RESULT
28503 : sum
28504 :
28505 : -- ALGLIB PROJECT --
28506 : Copyright 05.10.2020 by Bochkanov Sergey.
28507 : *************************************************************************/
28508 0 : static ae_int_t amdordering_knssumkth(amdknset* s0,
28509 : ae_int_t i,
28510 : ae_state *_state)
28511 : {
28512 : ae_int_t idxbegin0;
28513 : ae_int_t cnt0;
28514 : ae_int_t j;
28515 : ae_int_t result;
28516 :
28517 :
28518 0 : cnt0 = s0->vcnt.ptr.p_int[i];
28519 0 : idxbegin0 = s0->vbegin.ptr.p_int[i];
28520 0 : result = 0;
28521 0 : for(j=0; j<=cnt0-1; j++)
28522 : {
28523 0 : result = result+s0->data.ptr.p_int[idxbegin0+j];
28524 : }
28525 0 : return result;
28526 : }
28527 :
28528 :
28529 : /*************************************************************************
28530 : Clear k-th kn-set in collection.
28531 :
28532 : Freed memory is NOT reclaimed for future garbage collection.
28533 :
28534 : INPUT PARAMETERS
28535 : SA - kn-set structure
28536 : K - set index
28537 :
28538 : OUTPUT PARAMETERS
28539 : SA - K-th set was cleared
28540 :
28541 : -- ALGLIB PROJECT --
28542 : Copyright 05.10.2020 by Bochkanov Sergey.
28543 : *************************************************************************/
28544 0 : static void amdordering_knsclearkthnoreclaim(amdknset* sa,
28545 : ae_int_t k,
28546 : ae_state *_state)
28547 : {
28548 :
28549 :
28550 0 : sa->vcnt.ptr.p_int[k] = 0;
28551 0 : }
28552 :
28553 :
28554 : /*************************************************************************
28555 : Clear k-th kn-set in collection.
28556 :
28557 : Freed memory is reclaimed for future garbage collection. This function is
28558 : NOT recommended if you intend to add elements to this set in some future,
28559 : because every addition will result in reallocation of previously freed
28560 : memory. Use knsClearKthNoReclaim().
28561 :
28562 : INPUT PARAMETERS
28563 : SA - kn-set structure
28564 : K - set index
28565 :
28566 : OUTPUT PARAMETERS
28567 : SA - K-th set was cleared
28568 :
28569 : -- ALGLIB PROJECT --
28570 : Copyright 05.10.2020 by Bochkanov Sergey.
28571 : *************************************************************************/
28572 0 : static void amdordering_knsclearkthreclaim(amdknset* sa,
28573 : ae_int_t k,
28574 : ae_state *_state)
28575 : {
28576 : ae_int_t idxbegin;
28577 : ae_int_t allocated;
28578 :
28579 :
28580 0 : idxbegin = sa->vbegin.ptr.p_int[k];
28581 0 : allocated = sa->vallocated.ptr.p_int[k];
28582 0 : sa->vcnt.ptr.p_int[k] = 0;
28583 0 : if( allocated>=amdordering_knsheadersize )
28584 : {
28585 0 : sa->data.ptr.p_int[idxbegin-2] = 2;
28586 0 : sa->data.ptr.p_int[idxbegin+0] = allocated;
28587 0 : sa->data.ptr.p_int[idxbegin+1] = -1;
28588 0 : sa->vallocated.ptr.p_int[k] = 0;
28589 : }
28590 0 : }
28591 :
28592 :
28593 : /*************************************************************************
28594 : Initialize linked list matrix
28595 :
28596 : INPUT PARAMETERS
28597 : N - matrix size
28598 :
28599 : OUTPUT PARAMETERS
28600 : A - NxN linked list matrix
28601 :
28602 : -- ALGLIB PROJECT --
28603 : Copyright 05.10.2020 by Bochkanov Sergey.
28604 : *************************************************************************/
28605 0 : static void amdordering_mtxinit(ae_int_t n,
28606 : amdllmatrix* a,
28607 : ae_state *_state)
28608 : {
28609 :
28610 :
28611 0 : a->n = n;
28612 0 : isetallocv(2*n+1, -1, &a->vbegin, _state);
28613 0 : isetallocv(n, 0, &a->vcolcnt, _state);
28614 0 : a->entriesinitialized = 0;
28615 0 : }
28616 :
28617 :
28618 : /*************************************************************************
28619 : Adds column from matrix to n-set
28620 :
28621 : INPUT PARAMETERS
28622 : A - NxN linked list matrix
28623 : J - column index to add
28624 : S - target n-set
28625 :
28626 : OUTPUT PARAMETERS
28627 : S - elements from J-th column are added to S
28628 :
28629 :
28630 : -- ALGLIB PROJECT --
28631 : Copyright 05.10.2020 by Bochkanov Sergey.
28632 : *************************************************************************/
28633 0 : static void amdordering_mtxaddcolumnto(amdllmatrix* a,
28634 : ae_int_t j,
28635 : amdnset* s,
28636 : ae_state *_state)
28637 : {
28638 : ae_int_t n;
28639 : ae_int_t eidx;
28640 :
28641 :
28642 0 : n = a->n;
28643 0 : eidx = a->vbegin.ptr.p_int[n+j];
28644 0 : while(eidx>=0)
28645 : {
28646 0 : amdordering_nsaddelement(s, a->entries.ptr.p_int[eidx*amdordering_llmentrysize+4], _state);
28647 0 : eidx = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+3];
28648 : }
28649 0 : }
28650 :
28651 :
28652 : /*************************************************************************
28653 : Inserts new element into column J, row I. The caller guarantees that the
28654 : element being inserted is NOT already present in the matrix.
28655 :
28656 : INPUT PARAMETERS
28657 : A - NxN linked list matrix
28658 : I - row index
28659 : J - column index
28660 :
28661 : OUTPUT PARAMETERS
28662 : A - element (I,J) added to the list.
28663 :
28664 :
28665 : -- ALGLIB PROJECT --
28666 : Copyright 05.10.2020 by Bochkanov Sergey.
28667 : *************************************************************************/
28668 0 : static void amdordering_mtxinsertnewelement(amdllmatrix* a,
28669 : ae_int_t i,
28670 : ae_int_t j,
28671 : ae_state *_state)
28672 : {
28673 : ae_int_t n;
28674 : ae_int_t k;
28675 : ae_int_t newsize;
28676 : ae_int_t eidx;
28677 : ae_int_t offs;
28678 :
28679 :
28680 0 : n = a->n;
28681 0 : if( a->vbegin.ptr.p_int[2*n]<0 )
28682 : {
28683 0 : newsize = 2*a->entriesinitialized+1;
28684 0 : ivectorresize(&a->entries, newsize*amdordering_llmentrysize, _state);
28685 0 : for(k=a->entriesinitialized; k<=newsize-2; k++)
28686 : {
28687 0 : a->entries.ptr.p_int[k*amdordering_llmentrysize+0] = k+1;
28688 : }
28689 0 : a->entries.ptr.p_int[(newsize-1)*amdordering_llmentrysize+0] = a->vbegin.ptr.p_int[2*n];
28690 0 : a->vbegin.ptr.p_int[2*n] = a->entriesinitialized;
28691 0 : a->entriesinitialized = newsize;
28692 : }
28693 0 : eidx = a->vbegin.ptr.p_int[2*n];
28694 0 : offs = eidx*amdordering_llmentrysize;
28695 0 : a->vbegin.ptr.p_int[2*n] = a->entries.ptr.p_int[offs+0];
28696 0 : a->entries.ptr.p_int[offs+0] = -1;
28697 0 : a->entries.ptr.p_int[offs+1] = a->vbegin.ptr.p_int[i];
28698 0 : if( a->vbegin.ptr.p_int[i]>=0 )
28699 : {
28700 0 : a->entries.ptr.p_int[a->vbegin.ptr.p_int[i]*amdordering_llmentrysize+0] = eidx;
28701 : }
28702 0 : a->entries.ptr.p_int[offs+2] = -1;
28703 0 : a->entries.ptr.p_int[offs+3] = a->vbegin.ptr.p_int[j+n];
28704 0 : if( a->vbegin.ptr.p_int[j+n]>=0 )
28705 : {
28706 0 : a->entries.ptr.p_int[a->vbegin.ptr.p_int[j+n]*amdordering_llmentrysize+2] = eidx;
28707 : }
28708 0 : a->entries.ptr.p_int[offs+4] = i;
28709 0 : a->entries.ptr.p_int[offs+5] = j;
28710 0 : a->vbegin.ptr.p_int[i] = eidx;
28711 0 : a->vbegin.ptr.p_int[j+n] = eidx;
28712 0 : a->vcolcnt.ptr.p_int[j] = a->vcolcnt.ptr.p_int[j]+1;
28713 0 : }
28714 :
28715 :
28716 : /*************************************************************************
28717 : Counts elements in J-th column
28718 :
28719 : INPUT PARAMETERS
28720 : A - NxN linked list matrix
28721 : J - column index
28722 :
28723 : RESULT
28724 : element count
28725 :
28726 :
28727 : -- ALGLIB PROJECT --
28728 : Copyright 05.10.2020 by Bochkanov Sergey.
28729 : *************************************************************************/
28730 0 : static ae_int_t amdordering_mtxcountcolumn(amdllmatrix* a,
28731 : ae_int_t j,
28732 : ae_state *_state)
28733 : {
28734 : ae_int_t result;
28735 :
28736 :
28737 0 : result = a->vcolcnt.ptr.p_int[j];
28738 0 : return result;
28739 : }
28740 :
28741 :
28742 : /*************************************************************************
28743 : Clears K-th column or row
28744 :
28745 : INPUT PARAMETERS
28746 : A - NxN linked list matrix
28747 : K - column/row index to clear
28748 : IsCol - whether we want to clear row or column
28749 :
28750 : OUTPUT PARAMETERS
28751 : A - K-th column or row is empty
28752 :
28753 :
28754 : -- ALGLIB PROJECT --
28755 : Copyright 05.10.2020 by Bochkanov Sergey.
28756 : *************************************************************************/
28757 0 : static void amdordering_mtxclearx(amdllmatrix* a,
28758 : ae_int_t k,
28759 : ae_bool iscol,
28760 : ae_state *_state)
28761 : {
28762 : ae_int_t n;
28763 : ae_int_t eidx;
28764 : ae_int_t enext;
28765 : ae_int_t idxprev;
28766 : ae_int_t idxnext;
28767 : ae_int_t idxr;
28768 : ae_int_t idxc;
28769 :
28770 :
28771 0 : n = a->n;
28772 0 : if( iscol )
28773 : {
28774 0 : eidx = a->vbegin.ptr.p_int[n+k];
28775 : }
28776 : else
28777 : {
28778 0 : eidx = a->vbegin.ptr.p_int[k];
28779 : }
28780 0 : while(eidx>=0)
28781 : {
28782 0 : idxr = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+4];
28783 0 : idxc = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+5];
28784 0 : if( iscol )
28785 : {
28786 0 : enext = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+3];
28787 : }
28788 : else
28789 : {
28790 0 : enext = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+1];
28791 : }
28792 0 : idxprev = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+0];
28793 0 : idxnext = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+1];
28794 0 : if( idxprev>=0 )
28795 : {
28796 0 : a->entries.ptr.p_int[idxprev*amdordering_llmentrysize+1] = idxnext;
28797 : }
28798 : else
28799 : {
28800 0 : a->vbegin.ptr.p_int[idxr] = idxnext;
28801 : }
28802 0 : if( idxnext>=0 )
28803 : {
28804 0 : a->entries.ptr.p_int[idxnext*amdordering_llmentrysize+0] = idxprev;
28805 : }
28806 0 : idxprev = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+2];
28807 0 : idxnext = a->entries.ptr.p_int[eidx*amdordering_llmentrysize+3];
28808 0 : if( idxprev>=0 )
28809 : {
28810 0 : a->entries.ptr.p_int[idxprev*amdordering_llmentrysize+3] = idxnext;
28811 : }
28812 : else
28813 : {
28814 0 : a->vbegin.ptr.p_int[idxc+n] = idxnext;
28815 : }
28816 0 : if( idxnext>=0 )
28817 : {
28818 0 : a->entries.ptr.p_int[idxnext*amdordering_llmentrysize+2] = idxprev;
28819 : }
28820 0 : a->entries.ptr.p_int[eidx*amdordering_llmentrysize+0] = a->vbegin.ptr.p_int[2*n];
28821 0 : a->vbegin.ptr.p_int[2*n] = eidx;
28822 0 : eidx = enext;
28823 0 : if( !iscol )
28824 : {
28825 0 : a->vcolcnt.ptr.p_int[idxc] = a->vcolcnt.ptr.p_int[idxc]-1;
28826 : }
28827 : }
28828 0 : if( iscol )
28829 : {
28830 0 : a->vcolcnt.ptr.p_int[k] = 0;
28831 : }
28832 0 : }
28833 :
28834 :
28835 : /*************************************************************************
28836 : Clears J-th column
28837 :
28838 : INPUT PARAMETERS
28839 : A - NxN linked list matrix
28840 : J - column index to clear
28841 :
28842 : OUTPUT PARAMETERS
28843 : A - J-th column is empty
28844 :
28845 :
28846 : -- ALGLIB PROJECT --
28847 : Copyright 05.10.2020 by Bochkanov Sergey.
28848 : *************************************************************************/
28849 0 : static void amdordering_mtxclearcolumn(amdllmatrix* a,
28850 : ae_int_t j,
28851 : ae_state *_state)
28852 : {
28853 :
28854 :
28855 0 : amdordering_mtxclearx(a, j, ae_true, _state);
28856 0 : }
28857 :
28858 :
28859 : /*************************************************************************
28860 : Clears J-th row
28861 :
28862 : INPUT PARAMETERS
28863 : A - NxN linked list matrix
28864 : J - row index to clear
28865 :
28866 : OUTPUT PARAMETERS
28867 : A - J-th row is empty
28868 :
28869 :
28870 : -- ALGLIB PROJECT --
28871 : Copyright 05.10.2020 by Bochkanov Sergey.
28872 : *************************************************************************/
28873 0 : static void amdordering_mtxclearrow(amdllmatrix* a,
28874 : ae_int_t j,
28875 : ae_state *_state)
28876 : {
28877 :
28878 :
28879 0 : amdordering_mtxclearx(a, j, ae_false, _state);
28880 0 : }
28881 :
28882 :
28883 : /*************************************************************************
28884 : Initialize vertex storage using A to estimate initial degrees
28885 :
28886 : INPUT PARAMETERS
28887 : A - NxN lower triangular sparse CRS matrix
28888 : N - problem size
28889 : CheckExactDegrees-
28890 : whether we want to maintain additional exact degress
28891 : (the search is still done using approximate ones)
28892 :
28893 : OUTPUT PARAMETERS
28894 : S - vertex set
28895 :
28896 :
28897 : -- ALGLIB PROJECT --
28898 : Copyright 05.10.2020 by Bochkanov Sergey.
28899 : *************************************************************************/
28900 0 : static void amdordering_vtxinit(sparsematrix* a,
28901 : ae_int_t n,
28902 : ae_bool checkexactdegrees,
28903 : amdvertexset* s,
28904 : ae_state *_state)
28905 : {
28906 : ae_int_t i;
28907 : ae_int_t j;
28908 : ae_int_t jj;
28909 : ae_int_t j0;
28910 : ae_int_t j1;
28911 :
28912 0 : _amdvertexset_clear(s);
28913 :
28914 0 : s->n = n;
28915 0 : s->checkexactdegrees = checkexactdegrees;
28916 0 : s->smallestdegree = 0;
28917 0 : bsetallocv(n, ae_true, &s->isvertex, _state);
28918 0 : isetallocv(n, 0, &s->approxd, _state);
28919 0 : for(i=0; i<=n-1; i++)
28920 : {
28921 0 : j0 = a->ridx.ptr.p_int[i];
28922 0 : j1 = a->didx.ptr.p_int[i]-1;
28923 0 : s->approxd.ptr.p_int[i] = j1-j0+1;
28924 0 : for(jj=j0; jj<=j1; jj++)
28925 : {
28926 0 : j = a->idx.ptr.p_int[jj];
28927 0 : s->approxd.ptr.p_int[j] = s->approxd.ptr.p_int[j]+1;
28928 : }
28929 : }
28930 0 : if( checkexactdegrees )
28931 : {
28932 0 : icopyallocv(n, &s->approxd, &s->optionalexactd, _state);
28933 : }
28934 0 : isetallocv(n, -1, &s->vbegin, _state);
28935 0 : isetallocv(n, -1, &s->vprev, _state);
28936 0 : isetallocv(n, -1, &s->vnext, _state);
28937 0 : for(i=0; i<=n-1; i++)
28938 : {
28939 0 : j = s->approxd.ptr.p_int[i];
28940 0 : j0 = s->vbegin.ptr.p_int[j];
28941 0 : s->vbegin.ptr.p_int[j] = i;
28942 0 : s->vnext.ptr.p_int[i] = j0;
28943 0 : s->vprev.ptr.p_int[i] = -1;
28944 0 : if( j0>=0 )
28945 : {
28946 0 : s->vprev.ptr.p_int[j0] = i;
28947 : }
28948 : }
28949 0 : }
28950 :
28951 :
28952 : /*************************************************************************
28953 : Removes vertex from the storage
28954 :
28955 : INPUT PARAMETERS
28956 : S - vertex set
28957 : P - vertex to be removed
28958 :
28959 : OUTPUT PARAMETERS
28960 : S - modified
28961 :
28962 :
28963 : -- ALGLIB PROJECT --
28964 : Copyright 05.10.2020 by Bochkanov Sergey.
28965 : *************************************************************************/
28966 0 : static void amdordering_vtxremovevertex(amdvertexset* s,
28967 : ae_int_t p,
28968 : ae_state *_state)
28969 : {
28970 : ae_int_t d;
28971 : ae_int_t idxprev;
28972 : ae_int_t idxnext;
28973 :
28974 :
28975 0 : d = s->approxd.ptr.p_int[p];
28976 0 : idxprev = s->vprev.ptr.p_int[p];
28977 0 : idxnext = s->vnext.ptr.p_int[p];
28978 0 : if( idxprev>=0 )
28979 : {
28980 0 : s->vnext.ptr.p_int[idxprev] = idxnext;
28981 : }
28982 : else
28983 : {
28984 0 : s->vbegin.ptr.p_int[d] = idxnext;
28985 : }
28986 0 : if( idxnext>=0 )
28987 : {
28988 0 : s->vprev.ptr.p_int[idxnext] = idxprev;
28989 : }
28990 0 : s->isvertex.ptr.p_bool[p] = ae_false;
28991 0 : s->approxd.ptr.p_int[p] = -9999999;
28992 0 : if( s->checkexactdegrees )
28993 : {
28994 0 : s->optionalexactd.ptr.p_int[p] = -9999999;
28995 : }
28996 0 : }
28997 :
28998 :
28999 : /*************************************************************************
29000 : Get approximate degree. Result is undefined for removed vertexes.
29001 :
29002 : INPUT PARAMETERS
29003 : S - vertex set
29004 : P - vertex index
29005 :
29006 : RESULT
29007 : vertex degree
29008 :
29009 :
29010 : -- ALGLIB PROJECT --
29011 : Copyright 05.10.2020 by Bochkanov Sergey.
29012 : *************************************************************************/
29013 0 : static ae_int_t amdordering_vtxgetapprox(amdvertexset* s,
29014 : ae_int_t p,
29015 : ae_state *_state)
29016 : {
29017 : ae_int_t result;
29018 :
29019 :
29020 0 : result = s->approxd.ptr.p_int[p];
29021 0 : return result;
29022 : }
29023 :
29024 :
29025 : /*************************************************************************
29026 : Get exact degree (or 0, if not supported). Result is undefined for
29027 : removed vertexes.
29028 :
29029 : INPUT PARAMETERS
29030 : S - vertex set
29031 : P - vertex index
29032 :
29033 : RESULT
29034 : vertex degree
29035 :
29036 :
29037 : -- ALGLIB PROJECT --
29038 : Copyright 05.10.2020 by Bochkanov Sergey.
29039 : *************************************************************************/
29040 0 : static ae_int_t amdordering_vtxgetexact(amdvertexset* s,
29041 : ae_int_t p,
29042 : ae_state *_state)
29043 : {
29044 : ae_int_t result;
29045 :
29046 :
29047 0 : if( s->checkexactdegrees )
29048 : {
29049 0 : result = s->optionalexactd.ptr.p_int[p];
29050 : }
29051 : else
29052 : {
29053 0 : result = 0;
29054 : }
29055 0 : return result;
29056 : }
29057 :
29058 :
29059 : /*************************************************************************
29060 : Returns index of vertex with minimum approximate degree, or -1 when there
29061 : is no vertex.
29062 :
29063 : INPUT PARAMETERS
29064 : S - vertex set
29065 :
29066 : RESULT
29067 : vertex index, or -1
29068 :
29069 :
29070 : -- ALGLIB PROJECT --
29071 : Copyright 05.10.2020 by Bochkanov Sergey.
29072 : *************************************************************************/
29073 0 : static ae_int_t amdordering_vtxgetapproxmindegree(amdvertexset* s,
29074 : ae_state *_state)
29075 : {
29076 : ae_int_t i;
29077 : ae_int_t n;
29078 : ae_int_t result;
29079 :
29080 :
29081 0 : n = s->n;
29082 0 : result = -1;
29083 0 : for(i=s->smallestdegree; i<=n-1; i++)
29084 : {
29085 0 : if( s->vbegin.ptr.p_int[i]>=0 )
29086 : {
29087 0 : s->smallestdegree = i;
29088 0 : result = s->vbegin.ptr.p_int[i];
29089 0 : return result;
29090 : }
29091 : }
29092 0 : return result;
29093 : }
29094 :
29095 :
29096 : /*************************************************************************
29097 : Update approximate degree
29098 :
29099 : INPUT PARAMETERS
29100 : S - vertex set
29101 : P - vertex to be updated
29102 : DNew - new degree
29103 :
29104 : OUTPUT PARAMETERS
29105 : S - modified
29106 :
29107 :
29108 : -- ALGLIB PROJECT --
29109 : Copyright 05.10.2020 by Bochkanov Sergey.
29110 : *************************************************************************/
29111 0 : static void amdordering_vtxupdateapproximatedegree(amdvertexset* s,
29112 : ae_int_t p,
29113 : ae_int_t dnew,
29114 : ae_state *_state)
29115 : {
29116 : ae_int_t dold;
29117 : ae_int_t idxprev;
29118 : ae_int_t idxnext;
29119 : ae_int_t oldbegin;
29120 :
29121 :
29122 0 : dold = s->approxd.ptr.p_int[p];
29123 0 : if( dold==dnew )
29124 : {
29125 0 : return;
29126 : }
29127 0 : idxprev = s->vprev.ptr.p_int[p];
29128 0 : idxnext = s->vnext.ptr.p_int[p];
29129 0 : if( idxprev>=0 )
29130 : {
29131 0 : s->vnext.ptr.p_int[idxprev] = idxnext;
29132 : }
29133 : else
29134 : {
29135 0 : s->vbegin.ptr.p_int[dold] = idxnext;
29136 : }
29137 0 : if( idxnext>=0 )
29138 : {
29139 0 : s->vprev.ptr.p_int[idxnext] = idxprev;
29140 : }
29141 0 : oldbegin = s->vbegin.ptr.p_int[dnew];
29142 0 : s->vbegin.ptr.p_int[dnew] = p;
29143 0 : s->vnext.ptr.p_int[p] = oldbegin;
29144 0 : s->vprev.ptr.p_int[p] = -1;
29145 0 : if( oldbegin>=0 )
29146 : {
29147 0 : s->vprev.ptr.p_int[oldbegin] = p;
29148 : }
29149 0 : s->approxd.ptr.p_int[p] = dnew;
29150 0 : if( dnew<s->smallestdegree )
29151 : {
29152 0 : s->smallestdegree = dnew;
29153 : }
29154 : }
29155 :
29156 :
29157 : /*************************************************************************
29158 : Update optional exact degree. Silently returns if vertex set does not store
29159 : exact degrees.
29160 :
29161 : INPUT PARAMETERS
29162 : S - vertex set
29163 : P - vertex to be updated
29164 : D - new degree
29165 :
29166 : OUTPUT PARAMETERS
29167 : S - modified
29168 :
29169 :
29170 : -- ALGLIB PROJECT --
29171 : Copyright 05.10.2020 by Bochkanov Sergey.
29172 : *************************************************************************/
29173 0 : static void amdordering_vtxupdateexactdegree(amdvertexset* s,
29174 : ae_int_t p,
29175 : ae_int_t d,
29176 : ae_state *_state)
29177 : {
29178 :
29179 :
29180 0 : if( !s->checkexactdegrees )
29181 : {
29182 0 : return;
29183 : }
29184 0 : s->optionalexactd.ptr.p_int[p] = d;
29185 : }
29186 :
29187 :
29188 : /*************************************************************************
29189 : This function selects K-th pivot with minimum approximate degree and
29190 : generates permutation that reorders variable to the K-th position in the
29191 : matrix.
29192 :
29193 : Due to supernodal structure of the matrix more than one pivot variable can
29194 : be selected and moved to the beginning. The actual count of pivots selected
29195 : is returned in NodeSize.
29196 :
29197 : INPUT PARAMETERS
29198 : Buf - properly initialized buffer object
29199 : K - pivot index
29200 :
29201 : OUTPUT PARAMETERS
29202 : Buf.Perm - entries [K,K+NodeSize) are initialized by permutation
29203 : Buf.InvPerm - entries [K,K+NodeSize) are initialized by permutation
29204 : Buf.ColumnSwaps-entries [K,K+NodeSize) are initialized by permutation
29205 : P - pivot supervariable
29206 : NodeSize - supernode size
29207 :
29208 : -- ALGLIB PROJECT --
29209 : Copyright 05.10.2020 by Bochkanov Sergey.
29210 : *************************************************************************/
29211 0 : static void amdordering_amdselectpivotelement(amdbuffer* buf,
29212 : ae_int_t k,
29213 : ae_int_t* p,
29214 : ae_int_t* nodesize,
29215 : ae_state *_state)
29216 : {
29217 : ae_int_t i;
29218 : ae_int_t j;
29219 :
29220 0 : *p = 0;
29221 0 : *nodesize = 0;
29222 :
29223 0 : *p = amdordering_vtxgetapproxmindegree(&buf->vertexdegrees, _state);
29224 0 : ae_assert(*p>=0, "GenerateAMDPermutation: integrity check 3634 failed", _state);
29225 0 : ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, *p, _state)>=0, "integrity check RDFD2 failed", _state);
29226 0 : *nodesize = 0;
29227 0 : amdordering_knsstartenumeration(&buf->setsuper, *p, _state);
29228 0 : while(amdordering_knsenumerate(&buf->setsuper, &j, _state))
29229 : {
29230 0 : i = buf->perm.ptr.p_int[j];
29231 0 : buf->columnswaps.ptr.p_int[k+(*nodesize)] = i;
29232 0 : buf->invperm.ptr.p_int[i] = buf->invperm.ptr.p_int[k+(*nodesize)];
29233 0 : buf->invperm.ptr.p_int[k+(*nodesize)] = j;
29234 0 : buf->perm.ptr.p_int[buf->invperm.ptr.p_int[i]] = i;
29235 0 : buf->perm.ptr.p_int[buf->invperm.ptr.p_int[k+(*nodesize)]] = k+(*nodesize);
29236 0 : inc(nodesize, _state);
29237 : }
29238 0 : ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, *p, _state)>=0&&(!buf->checkexactdegrees||amdordering_vtxgetexact(&buf->vertexdegrees, *p, _state)>=0), "AMD: integrity check RDFD failed", _state);
29239 0 : }
29240 :
29241 :
29242 : /*************************************************************************
29243 : This function computes nonzero pattern of Lp, the column that is added to
29244 : the lower triangular Cholesky factor.
29245 :
29246 : INPUT PARAMETERS
29247 : Buf - properly initialized buffer object
29248 : P - pivot column
29249 :
29250 : OUTPUT PARAMETERS
29251 : Buf.Lp - initialized with Lp
29252 : Buf.PLp - initialized with setSuper[P]+Lp
29253 : Buf.Ep - initialized with setE[P]
29254 : Buf.mtxL - L := L+Lp
29255 : Buf.Ls - first Buf.LSCnt elements contain subset of Lp elements
29256 : that are principal nodes in supervariables.
29257 :
29258 : -- ALGLIB PROJECT --
29259 : Copyright 05.10.2020 by Bochkanov Sergey.
29260 : *************************************************************************/
29261 0 : static void amdordering_amdcomputelp(amdbuffer* buf,
29262 : ae_int_t p,
29263 : ae_state *_state)
29264 : {
29265 : ae_int_t i;
29266 :
29267 :
29268 0 : amdordering_nsclear(&buf->lp, _state);
29269 0 : amdordering_nsaddkth(&buf->lp, &buf->seta, p, _state);
29270 0 : amdordering_knsstartenumeration(&buf->sete, p, _state);
29271 0 : while(amdordering_knsenumerate(&buf->sete, &i, _state))
29272 : {
29273 0 : amdordering_mtxaddcolumnto(&buf->mtxl, i, &buf->lp, _state);
29274 : }
29275 0 : amdordering_nssubtractkth(&buf->lp, &buf->setsuper, p, _state);
29276 0 : buf->lscnt = 0;
29277 0 : amdordering_nsstartenumeration(&buf->lp, _state);
29278 0 : while(amdordering_nsenumerate(&buf->lp, &i, _state))
29279 : {
29280 0 : ae_assert(!buf->iseliminated.ptr.p_bool[i], "AMD: integrity check 0740 failed", _state);
29281 0 : amdordering_mtxinsertnewelement(&buf->mtxl, i, p, _state);
29282 0 : if( buf->issupernode.ptr.p_bool[i] )
29283 : {
29284 0 : buf->ls.ptr.p_int[buf->lscnt] = i;
29285 0 : buf->lscnt = buf->lscnt+1;
29286 : }
29287 : }
29288 0 : amdordering_nscopy(&buf->lp, &buf->plp, _state);
29289 0 : amdordering_nsaddkth(&buf->plp, &buf->setsuper, p, _state);
29290 0 : amdordering_nsclear(&buf->ep, _state);
29291 0 : amdordering_nsaddkth(&buf->ep, &buf->sete, p, _state);
29292 0 : }
29293 :
29294 :
29295 : /*************************************************************************
29296 : Having output of AMDComputeLp() in the Buf object, this function performs
29297 : mass elimination in the quotient graph.
29298 :
29299 : INPUT PARAMETERS
29300 : Buf - properly initialized buffer object
29301 : P - pivot column
29302 : K - number of already eliminated columns (P-th is not counted)
29303 :
29304 : OUTPUT PARAMETERS
29305 : Buf.setA - Lp is eliminated from setA
29306 : Buf.setE - Ep is eliminated from setE, P is added
29307 : approxD - updated
29308 :
29309 : -- ALGLIB PROJECT --
29310 : Copyright 05.10.2020 by Bochkanov Sergey.
29311 : *************************************************************************/
29312 0 : static void amdordering_amdmasselimination(amdbuffer* buf,
29313 : ae_int_t p,
29314 : ae_int_t k,
29315 : ae_state *_state)
29316 : {
29317 : ae_int_t n;
29318 : ae_int_t lidx;
29319 : ae_int_t lpi;
29320 : ae_int_t cntsuperi;
29321 : ae_int_t cntainoti;
29322 : ae_int_t cntlpnoti;
29323 : ae_int_t cc;
29324 : ae_int_t j;
29325 : ae_int_t e;
29326 : ae_int_t we;
29327 : ae_int_t cnttoclean;
29328 : ae_int_t idxbegin;
29329 : ae_int_t idxend;
29330 : ae_int_t jj;
29331 :
29332 :
29333 0 : n = buf->n;
29334 0 : ivectorsetlengthatleast(&buf->tmp0, n, _state);
29335 0 : cnttoclean = 0;
29336 0 : for(lidx=0; lidx<=buf->lscnt-1; lidx++)
29337 : {
29338 0 : lpi = buf->ls.ptr.p_int[lidx];
29339 0 : cntsuperi = amdordering_knscountkth(&buf->setsuper, lpi, _state);
29340 0 : amdordering_knsdirectaccess(&buf->sete, lpi, &idxbegin, &idxend, _state);
29341 0 : for(jj=idxbegin; jj<=idxend-1; jj++)
29342 : {
29343 0 : e = buf->sete.data.ptr.p_int[jj];
29344 0 : we = buf->arrwe.ptr.p_int[e];
29345 0 : if( we<0 )
29346 : {
29347 0 : we = amdordering_mtxcountcolumn(&buf->mtxl, e, _state);
29348 0 : buf->tmp0.ptr.p_int[cnttoclean] = e;
29349 0 : cnttoclean = cnttoclean+1;
29350 : }
29351 0 : buf->arrwe.ptr.p_int[e] = we-cntsuperi;
29352 : }
29353 : }
29354 0 : for(lidx=0; lidx<=buf->lscnt-1; lidx++)
29355 : {
29356 0 : lpi = buf->ls.ptr.p_int[lidx];
29357 0 : amdordering_knssubtract1(&buf->seta, lpi, &buf->plp, _state);
29358 0 : amdordering_knssubtract1(&buf->sete, lpi, &buf->ep, _state);
29359 0 : amdordering_knsaddnewelement(&buf->sete, lpi, p, _state);
29360 0 : if( buf->extendeddebug )
29361 : {
29362 0 : ae_assert(amdordering_knscountnotkth(&buf->seta, lpi, &buf->setsuper, lpi, _state)==amdordering_knscountkth(&buf->seta, lpi, _state), "AMD: integrity check 454F failed", _state);
29363 0 : ae_assert(amdordering_knscountandkth(&buf->seta, lpi, &buf->setsuper, lpi, _state)==0, "AMD: integrity check kl5nv failed", _state);
29364 0 : ae_assert(amdordering_nscountandkth(&buf->lp, &buf->setsuper, lpi, _state)==amdordering_knscountkth(&buf->setsuper, lpi, _state), "AMD: integrity check 8463 failed", _state);
29365 : }
29366 0 : cntainoti = amdordering_knscountkth(&buf->seta, lpi, _state);
29367 0 : cntlpnoti = amdordering_nscount(&buf->lp, _state)-amdordering_knscountkth(&buf->setsuper, lpi, _state);
29368 0 : cc = 0;
29369 0 : amdordering_knsdirectaccess(&buf->sete, lpi, &idxbegin, &idxend, _state);
29370 0 : for(jj=idxbegin; jj<=idxend-1; jj++)
29371 : {
29372 0 : j = buf->sete.data.ptr.p_int[jj];
29373 0 : if( j==p )
29374 : {
29375 0 : continue;
29376 : }
29377 0 : e = buf->arrwe.ptr.p_int[j];
29378 0 : if( e<0 )
29379 : {
29380 0 : e = amdordering_mtxcountcolumn(&buf->mtxl, j, _state);
29381 : }
29382 0 : cc = cc+e;
29383 : }
29384 0 : amdordering_vtxupdateapproximatedegree(&buf->vertexdegrees, lpi, imin3(n-k, amdordering_vtxgetapprox(&buf->vertexdegrees, lpi, _state)+cntlpnoti, cntainoti+cntlpnoti+cc, _state), _state);
29385 0 : if( buf->checkexactdegrees )
29386 : {
29387 0 : amdordering_nsclear(&buf->exactdegreetmp0, _state);
29388 0 : amdordering_knsstartenumeration(&buf->sete, lpi, _state);
29389 0 : while(amdordering_knsenumerate(&buf->sete, &j, _state))
29390 : {
29391 0 : amdordering_mtxaddcolumnto(&buf->mtxl, j, &buf->exactdegreetmp0, _state);
29392 : }
29393 0 : amdordering_vtxupdateexactdegree(&buf->vertexdegrees, lpi, cntainoti+amdordering_nscountnotkth(&buf->exactdegreetmp0, &buf->setsuper, lpi, _state), _state);
29394 0 : ae_assert(amdordering_knscountkth(&buf->sete, lpi, _state)>2||amdordering_vtxgetapprox(&buf->vertexdegrees, lpi, _state)==amdordering_vtxgetexact(&buf->vertexdegrees, lpi, _state), "AMD: integrity check 7206 failed", _state);
29395 0 : ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, lpi, _state)>=amdordering_vtxgetexact(&buf->vertexdegrees, lpi, _state), "AMD: integrity check 8206 failed", _state);
29396 : }
29397 : }
29398 0 : for(j=0; j<=cnttoclean-1; j++)
29399 : {
29400 0 : buf->arrwe.ptr.p_int[buf->tmp0.ptr.p_int[j]] = -1;
29401 : }
29402 0 : }
29403 :
29404 :
29405 : /*************************************************************************
29406 : After mass elimination, but before removal of vertex P, we may perform
29407 : supernode detection. Only variables/supernodes in Lp (P itself is NOT
29408 : included) can be merged into larger supernodes.
29409 :
29410 : INPUT PARAMETERS
29411 : Buf - properly initialized buffer object
29412 :
29413 : OUTPUT PARAMETERS
29414 : Buf - following fields of Buf may be modified:
29415 : * Buf.setSuper
29416 : * Buf.setA
29417 : * Buf.setE
29418 : * Buf.IsSupernode
29419 : * ApproxD and ExactD
29420 :
29421 : -- ALGLIB PROJECT --
29422 : Copyright 05.10.2020 by Bochkanov Sergey.
29423 : *************************************************************************/
29424 0 : static void amdordering_amddetectsupernodes(amdbuffer* buf,
29425 : ae_state *_state)
29426 : {
29427 : ae_int_t n;
29428 : ae_int_t i;
29429 : ae_int_t j;
29430 : ae_int_t cnt;
29431 : ae_int_t lpi;
29432 : ae_int_t lpj;
29433 : ae_int_t nj;
29434 : ae_int_t hashi;
29435 :
29436 :
29437 0 : n = buf->n;
29438 0 : ivectorsetlengthatleast(&buf->sncandidates, n, _state);
29439 0 : if( buf->lscnt<2 )
29440 : {
29441 0 : return;
29442 : }
29443 0 : for(i=0; i<=buf->lscnt-1; i++)
29444 : {
29445 0 : lpi = buf->ls.ptr.p_int[i];
29446 0 : hashi = (amdordering_knssumkth(&buf->seta, lpi, _state)+amdordering_knssumkth(&buf->sete, lpi, _state))%n;
29447 0 : amdordering_nsaddelement(&buf->nonemptybuckets, hashi, _state);
29448 0 : amdordering_knsaddnewelement(&buf->hashbuckets, hashi, lpi, _state);
29449 : }
29450 0 : amdordering_nsstartenumeration(&buf->nonemptybuckets, _state);
29451 0 : while(amdordering_nsenumerate(&buf->nonemptybuckets, &hashi, _state))
29452 : {
29453 0 : if( amdordering_knscountkth(&buf->hashbuckets, hashi, _state)>=2 )
29454 : {
29455 0 : cnt = 0;
29456 0 : amdordering_knsstartenumeration(&buf->hashbuckets, hashi, _state);
29457 0 : while(amdordering_knsenumerate(&buf->hashbuckets, &i, _state))
29458 : {
29459 0 : buf->sncandidates.ptr.p_int[cnt] = i;
29460 0 : cnt = cnt+1;
29461 : }
29462 0 : for(i=cnt-1; i>=0; i--)
29463 : {
29464 0 : for(j=cnt-1; j>=i+1; j--)
29465 : {
29466 0 : if( buf->issupernode.ptr.p_bool[buf->sncandidates.ptr.p_int[i]]&&buf->issupernode.ptr.p_bool[buf->sncandidates.ptr.p_int[j]] )
29467 : {
29468 0 : lpi = buf->sncandidates.ptr.p_int[i];
29469 0 : lpj = buf->sncandidates.ptr.p_int[j];
29470 0 : amdordering_nsclear(&buf->adji, _state);
29471 0 : amdordering_nsclear(&buf->adjj, _state);
29472 0 : amdordering_nsaddkth(&buf->adji, &buf->seta, lpi, _state);
29473 0 : amdordering_nsaddkth(&buf->adjj, &buf->seta, lpj, _state);
29474 0 : amdordering_nsaddkth(&buf->adji, &buf->sete, lpi, _state);
29475 0 : amdordering_nsaddkth(&buf->adjj, &buf->sete, lpj, _state);
29476 0 : amdordering_nsaddelement(&buf->adji, lpi, _state);
29477 0 : amdordering_nsaddelement(&buf->adji, lpj, _state);
29478 0 : amdordering_nsaddelement(&buf->adjj, lpi, _state);
29479 0 : amdordering_nsaddelement(&buf->adjj, lpj, _state);
29480 0 : if( !amdordering_nsequal(&buf->adji, &buf->adjj, _state) )
29481 : {
29482 0 : continue;
29483 : }
29484 0 : if( buf->extendeddebug )
29485 : {
29486 0 : ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, lpi, _state)>=1&&(!buf->checkexactdegrees||amdordering_vtxgetexact(&buf->vertexdegrees, lpi, _state)>=1), "AMD: integrity check &GBFF1 failed", _state);
29487 0 : ae_assert(amdordering_vtxgetapprox(&buf->vertexdegrees, lpj, _state)>=1&&(!buf->checkexactdegrees||amdordering_vtxgetexact(&buf->vertexdegrees, lpj, _state)>=1), "AMD: integrity check &GBFF2 failed", _state);
29488 0 : ae_assert(amdordering_knscountandkth(&buf->setsuper, lpi, &buf->setsuper, lpj, _state)==0, "AMD: integrity check &GBFF3 failed", _state);
29489 : }
29490 0 : nj = amdordering_knscountkth(&buf->setsuper, lpj, _state);
29491 0 : amdordering_knsaddkthdistinct(&buf->setsuper, lpi, &buf->setsuper, lpj, _state);
29492 0 : amdordering_knsclearkthreclaim(&buf->setsuper, lpj, _state);
29493 0 : amdordering_knsclearkthreclaim(&buf->seta, lpj, _state);
29494 0 : amdordering_knsclearkthreclaim(&buf->sete, lpj, _state);
29495 0 : buf->issupernode.ptr.p_bool[lpj] = ae_false;
29496 0 : amdordering_vtxremovevertex(&buf->vertexdegrees, lpj, _state);
29497 0 : amdordering_vtxupdateapproximatedegree(&buf->vertexdegrees, lpi, amdordering_vtxgetapprox(&buf->vertexdegrees, lpi, _state)-nj, _state);
29498 0 : if( buf->checkexactdegrees )
29499 : {
29500 0 : amdordering_vtxupdateexactdegree(&buf->vertexdegrees, lpi, amdordering_vtxgetexact(&buf->vertexdegrees, lpi, _state)-nj, _state);
29501 : }
29502 : }
29503 : }
29504 : }
29505 : }
29506 0 : amdordering_knsclearkthnoreclaim(&buf->hashbuckets, hashi, _state);
29507 : }
29508 0 : amdordering_nsclear(&buf->nonemptybuckets, _state);
29509 : }
29510 :
29511 :
29512 0 : void _amdnset_init(void* _p, ae_state *_state, ae_bool make_automatic)
29513 : {
29514 0 : amdnset *p = (amdnset*)_p;
29515 0 : ae_touch_ptr((void*)p);
29516 0 : ae_vector_init(&p->items, 0, DT_INT, _state, make_automatic);
29517 0 : ae_vector_init(&p->locationof, 0, DT_INT, _state, make_automatic);
29518 0 : }
29519 :
29520 :
29521 0 : void _amdnset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
29522 : {
29523 0 : amdnset *dst = (amdnset*)_dst;
29524 0 : amdnset *src = (amdnset*)_src;
29525 0 : dst->n = src->n;
29526 0 : dst->nstored = src->nstored;
29527 0 : ae_vector_init_copy(&dst->items, &src->items, _state, make_automatic);
29528 0 : ae_vector_init_copy(&dst->locationof, &src->locationof, _state, make_automatic);
29529 0 : dst->iteridx = src->iteridx;
29530 0 : }
29531 :
29532 :
29533 0 : void _amdnset_clear(void* _p)
29534 : {
29535 0 : amdnset *p = (amdnset*)_p;
29536 0 : ae_touch_ptr((void*)p);
29537 0 : ae_vector_clear(&p->items);
29538 0 : ae_vector_clear(&p->locationof);
29539 0 : }
29540 :
29541 :
29542 0 : void _amdnset_destroy(void* _p)
29543 : {
29544 0 : amdnset *p = (amdnset*)_p;
29545 0 : ae_touch_ptr((void*)p);
29546 0 : ae_vector_destroy(&p->items);
29547 0 : ae_vector_destroy(&p->locationof);
29548 0 : }
29549 :
29550 :
29551 0 : void _amdknset_init(void* _p, ae_state *_state, ae_bool make_automatic)
29552 : {
29553 0 : amdknset *p = (amdknset*)_p;
29554 0 : ae_touch_ptr((void*)p);
29555 0 : ae_vector_init(&p->flagarray, 0, DT_INT, _state, make_automatic);
29556 0 : ae_vector_init(&p->vbegin, 0, DT_INT, _state, make_automatic);
29557 0 : ae_vector_init(&p->vallocated, 0, DT_INT, _state, make_automatic);
29558 0 : ae_vector_init(&p->vcnt, 0, DT_INT, _state, make_automatic);
29559 0 : ae_vector_init(&p->data, 0, DT_INT, _state, make_automatic);
29560 0 : }
29561 :
29562 :
29563 0 : void _amdknset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
29564 : {
29565 0 : amdknset *dst = (amdknset*)_dst;
29566 0 : amdknset *src = (amdknset*)_src;
29567 0 : dst->k = src->k;
29568 0 : dst->n = src->n;
29569 0 : ae_vector_init_copy(&dst->flagarray, &src->flagarray, _state, make_automatic);
29570 0 : ae_vector_init_copy(&dst->vbegin, &src->vbegin, _state, make_automatic);
29571 0 : ae_vector_init_copy(&dst->vallocated, &src->vallocated, _state, make_automatic);
29572 0 : ae_vector_init_copy(&dst->vcnt, &src->vcnt, _state, make_automatic);
29573 0 : ae_vector_init_copy(&dst->data, &src->data, _state, make_automatic);
29574 0 : dst->dataused = src->dataused;
29575 0 : dst->iterrow = src->iterrow;
29576 0 : dst->iteridx = src->iteridx;
29577 0 : }
29578 :
29579 :
29580 0 : void _amdknset_clear(void* _p)
29581 : {
29582 0 : amdknset *p = (amdknset*)_p;
29583 0 : ae_touch_ptr((void*)p);
29584 0 : ae_vector_clear(&p->flagarray);
29585 0 : ae_vector_clear(&p->vbegin);
29586 0 : ae_vector_clear(&p->vallocated);
29587 0 : ae_vector_clear(&p->vcnt);
29588 0 : ae_vector_clear(&p->data);
29589 0 : }
29590 :
29591 :
29592 0 : void _amdknset_destroy(void* _p)
29593 : {
29594 0 : amdknset *p = (amdknset*)_p;
29595 0 : ae_touch_ptr((void*)p);
29596 0 : ae_vector_destroy(&p->flagarray);
29597 0 : ae_vector_destroy(&p->vbegin);
29598 0 : ae_vector_destroy(&p->vallocated);
29599 0 : ae_vector_destroy(&p->vcnt);
29600 0 : ae_vector_destroy(&p->data);
29601 0 : }
29602 :
29603 :
29604 0 : void _amdvertexset_init(void* _p, ae_state *_state, ae_bool make_automatic)
29605 : {
29606 0 : amdvertexset *p = (amdvertexset*)_p;
29607 0 : ae_touch_ptr((void*)p);
29608 0 : ae_vector_init(&p->approxd, 0, DT_INT, _state, make_automatic);
29609 0 : ae_vector_init(&p->optionalexactd, 0, DT_INT, _state, make_automatic);
29610 0 : ae_vector_init(&p->isvertex, 0, DT_BOOL, _state, make_automatic);
29611 0 : ae_vector_init(&p->vbegin, 0, DT_INT, _state, make_automatic);
29612 0 : ae_vector_init(&p->vprev, 0, DT_INT, _state, make_automatic);
29613 0 : ae_vector_init(&p->vnext, 0, DT_INT, _state, make_automatic);
29614 0 : }
29615 :
29616 :
29617 0 : void _amdvertexset_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
29618 : {
29619 0 : amdvertexset *dst = (amdvertexset*)_dst;
29620 0 : amdvertexset *src = (amdvertexset*)_src;
29621 0 : dst->n = src->n;
29622 0 : dst->checkexactdegrees = src->checkexactdegrees;
29623 0 : dst->smallestdegree = src->smallestdegree;
29624 0 : ae_vector_init_copy(&dst->approxd, &src->approxd, _state, make_automatic);
29625 0 : ae_vector_init_copy(&dst->optionalexactd, &src->optionalexactd, _state, make_automatic);
29626 0 : ae_vector_init_copy(&dst->isvertex, &src->isvertex, _state, make_automatic);
29627 0 : ae_vector_init_copy(&dst->vbegin, &src->vbegin, _state, make_automatic);
29628 0 : ae_vector_init_copy(&dst->vprev, &src->vprev, _state, make_automatic);
29629 0 : ae_vector_init_copy(&dst->vnext, &src->vnext, _state, make_automatic);
29630 0 : }
29631 :
29632 :
29633 0 : void _amdvertexset_clear(void* _p)
29634 : {
29635 0 : amdvertexset *p = (amdvertexset*)_p;
29636 0 : ae_touch_ptr((void*)p);
29637 0 : ae_vector_clear(&p->approxd);
29638 0 : ae_vector_clear(&p->optionalexactd);
29639 0 : ae_vector_clear(&p->isvertex);
29640 0 : ae_vector_clear(&p->vbegin);
29641 0 : ae_vector_clear(&p->vprev);
29642 0 : ae_vector_clear(&p->vnext);
29643 0 : }
29644 :
29645 :
29646 0 : void _amdvertexset_destroy(void* _p)
29647 : {
29648 0 : amdvertexset *p = (amdvertexset*)_p;
29649 0 : ae_touch_ptr((void*)p);
29650 0 : ae_vector_destroy(&p->approxd);
29651 0 : ae_vector_destroy(&p->optionalexactd);
29652 0 : ae_vector_destroy(&p->isvertex);
29653 0 : ae_vector_destroy(&p->vbegin);
29654 0 : ae_vector_destroy(&p->vprev);
29655 0 : ae_vector_destroy(&p->vnext);
29656 0 : }
29657 :
29658 :
29659 0 : void _amdllmatrix_init(void* _p, ae_state *_state, ae_bool make_automatic)
29660 : {
29661 0 : amdllmatrix *p = (amdllmatrix*)_p;
29662 0 : ae_touch_ptr((void*)p);
29663 0 : ae_vector_init(&p->vbegin, 0, DT_INT, _state, make_automatic);
29664 0 : ae_vector_init(&p->vcolcnt, 0, DT_INT, _state, make_automatic);
29665 0 : ae_vector_init(&p->entries, 0, DT_INT, _state, make_automatic);
29666 0 : }
29667 :
29668 :
29669 0 : void _amdllmatrix_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
29670 : {
29671 0 : amdllmatrix *dst = (amdllmatrix*)_dst;
29672 0 : amdllmatrix *src = (amdllmatrix*)_src;
29673 0 : dst->n = src->n;
29674 0 : ae_vector_init_copy(&dst->vbegin, &src->vbegin, _state, make_automatic);
29675 0 : ae_vector_init_copy(&dst->vcolcnt, &src->vcolcnt, _state, make_automatic);
29676 0 : ae_vector_init_copy(&dst->entries, &src->entries, _state, make_automatic);
29677 0 : dst->entriesinitialized = src->entriesinitialized;
29678 0 : }
29679 :
29680 :
29681 0 : void _amdllmatrix_clear(void* _p)
29682 : {
29683 0 : amdllmatrix *p = (amdllmatrix*)_p;
29684 0 : ae_touch_ptr((void*)p);
29685 0 : ae_vector_clear(&p->vbegin);
29686 0 : ae_vector_clear(&p->vcolcnt);
29687 0 : ae_vector_clear(&p->entries);
29688 0 : }
29689 :
29690 :
29691 0 : void _amdllmatrix_destroy(void* _p)
29692 : {
29693 0 : amdllmatrix *p = (amdllmatrix*)_p;
29694 0 : ae_touch_ptr((void*)p);
29695 0 : ae_vector_destroy(&p->vbegin);
29696 0 : ae_vector_destroy(&p->vcolcnt);
29697 0 : ae_vector_destroy(&p->entries);
29698 0 : }
29699 :
29700 :
29701 0 : void _amdbuffer_init(void* _p, ae_state *_state, ae_bool make_automatic)
29702 : {
29703 0 : amdbuffer *p = (amdbuffer*)_p;
29704 0 : ae_touch_ptr((void*)p);
29705 0 : ae_vector_init(&p->iseliminated, 0, DT_BOOL, _state, make_automatic);
29706 0 : ae_vector_init(&p->issupernode, 0, DT_BOOL, _state, make_automatic);
29707 0 : _amdknset_init(&p->setsuper, _state, make_automatic);
29708 0 : _amdknset_init(&p->seta, _state, make_automatic);
29709 0 : _amdknset_init(&p->sete, _state, make_automatic);
29710 0 : _amdllmatrix_init(&p->mtxl, _state, make_automatic);
29711 0 : _amdvertexset_init(&p->vertexdegrees, _state, make_automatic);
29712 0 : ae_vector_init(&p->perm, 0, DT_INT, _state, make_automatic);
29713 0 : ae_vector_init(&p->invperm, 0, DT_INT, _state, make_automatic);
29714 0 : ae_vector_init(&p->columnswaps, 0, DT_INT, _state, make_automatic);
29715 0 : _amdnset_init(&p->lp, _state, make_automatic);
29716 0 : _amdnset_init(&p->plp, _state, make_automatic);
29717 0 : _amdnset_init(&p->ep, _state, make_automatic);
29718 0 : _amdnset_init(&p->adji, _state, make_automatic);
29719 0 : _amdnset_init(&p->adjj, _state, make_automatic);
29720 0 : ae_vector_init(&p->ls, 0, DT_INT, _state, make_automatic);
29721 0 : _amdnset_init(&p->exactdegreetmp0, _state, make_automatic);
29722 0 : _amdknset_init(&p->hashbuckets, _state, make_automatic);
29723 0 : _amdnset_init(&p->nonemptybuckets, _state, make_automatic);
29724 0 : ae_vector_init(&p->sncandidates, 0, DT_INT, _state, make_automatic);
29725 0 : ae_vector_init(&p->tmp0, 0, DT_INT, _state, make_automatic);
29726 0 : ae_vector_init(&p->arrwe, 0, DT_INT, _state, make_automatic);
29727 0 : ae_matrix_init(&p->dbga, 0, 0, DT_REAL, _state, make_automatic);
29728 0 : }
29729 :
29730 :
29731 0 : void _amdbuffer_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
29732 : {
29733 0 : amdbuffer *dst = (amdbuffer*)_dst;
29734 0 : amdbuffer *src = (amdbuffer*)_src;
29735 0 : dst->n = src->n;
29736 0 : dst->extendeddebug = src->extendeddebug;
29737 0 : dst->checkexactdegrees = src->checkexactdegrees;
29738 0 : ae_vector_init_copy(&dst->iseliminated, &src->iseliminated, _state, make_automatic);
29739 0 : ae_vector_init_copy(&dst->issupernode, &src->issupernode, _state, make_automatic);
29740 0 : _amdknset_init_copy(&dst->setsuper, &src->setsuper, _state, make_automatic);
29741 0 : _amdknset_init_copy(&dst->seta, &src->seta, _state, make_automatic);
29742 0 : _amdknset_init_copy(&dst->sete, &src->sete, _state, make_automatic);
29743 0 : _amdllmatrix_init_copy(&dst->mtxl, &src->mtxl, _state, make_automatic);
29744 0 : _amdvertexset_init_copy(&dst->vertexdegrees, &src->vertexdegrees, _state, make_automatic);
29745 0 : ae_vector_init_copy(&dst->perm, &src->perm, _state, make_automatic);
29746 0 : ae_vector_init_copy(&dst->invperm, &src->invperm, _state, make_automatic);
29747 0 : ae_vector_init_copy(&dst->columnswaps, &src->columnswaps, _state, make_automatic);
29748 0 : _amdnset_init_copy(&dst->lp, &src->lp, _state, make_automatic);
29749 0 : _amdnset_init_copy(&dst->plp, &src->plp, _state, make_automatic);
29750 0 : _amdnset_init_copy(&dst->ep, &src->ep, _state, make_automatic);
29751 0 : _amdnset_init_copy(&dst->adji, &src->adji, _state, make_automatic);
29752 0 : _amdnset_init_copy(&dst->adjj, &src->adjj, _state, make_automatic);
29753 0 : ae_vector_init_copy(&dst->ls, &src->ls, _state, make_automatic);
29754 0 : dst->lscnt = src->lscnt;
29755 0 : _amdnset_init_copy(&dst->exactdegreetmp0, &src->exactdegreetmp0, _state, make_automatic);
29756 0 : _amdknset_init_copy(&dst->hashbuckets, &src->hashbuckets, _state, make_automatic);
29757 0 : _amdnset_init_copy(&dst->nonemptybuckets, &src->nonemptybuckets, _state, make_automatic);
29758 0 : ae_vector_init_copy(&dst->sncandidates, &src->sncandidates, _state, make_automatic);
29759 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
29760 0 : ae_vector_init_copy(&dst->arrwe, &src->arrwe, _state, make_automatic);
29761 0 : ae_matrix_init_copy(&dst->dbga, &src->dbga, _state, make_automatic);
29762 0 : }
29763 :
29764 :
29765 0 : void _amdbuffer_clear(void* _p)
29766 : {
29767 0 : amdbuffer *p = (amdbuffer*)_p;
29768 0 : ae_touch_ptr((void*)p);
29769 0 : ae_vector_clear(&p->iseliminated);
29770 0 : ae_vector_clear(&p->issupernode);
29771 0 : _amdknset_clear(&p->setsuper);
29772 0 : _amdknset_clear(&p->seta);
29773 0 : _amdknset_clear(&p->sete);
29774 0 : _amdllmatrix_clear(&p->mtxl);
29775 0 : _amdvertexset_clear(&p->vertexdegrees);
29776 0 : ae_vector_clear(&p->perm);
29777 0 : ae_vector_clear(&p->invperm);
29778 0 : ae_vector_clear(&p->columnswaps);
29779 0 : _amdnset_clear(&p->lp);
29780 0 : _amdnset_clear(&p->plp);
29781 0 : _amdnset_clear(&p->ep);
29782 0 : _amdnset_clear(&p->adji);
29783 0 : _amdnset_clear(&p->adjj);
29784 0 : ae_vector_clear(&p->ls);
29785 0 : _amdnset_clear(&p->exactdegreetmp0);
29786 0 : _amdknset_clear(&p->hashbuckets);
29787 0 : _amdnset_clear(&p->nonemptybuckets);
29788 0 : ae_vector_clear(&p->sncandidates);
29789 0 : ae_vector_clear(&p->tmp0);
29790 0 : ae_vector_clear(&p->arrwe);
29791 0 : ae_matrix_clear(&p->dbga);
29792 0 : }
29793 :
29794 :
29795 0 : void _amdbuffer_destroy(void* _p)
29796 : {
29797 0 : amdbuffer *p = (amdbuffer*)_p;
29798 0 : ae_touch_ptr((void*)p);
29799 0 : ae_vector_destroy(&p->iseliminated);
29800 0 : ae_vector_destroy(&p->issupernode);
29801 0 : _amdknset_destroy(&p->setsuper);
29802 0 : _amdknset_destroy(&p->seta);
29803 0 : _amdknset_destroy(&p->sete);
29804 0 : _amdllmatrix_destroy(&p->mtxl);
29805 0 : _amdvertexset_destroy(&p->vertexdegrees);
29806 0 : ae_vector_destroy(&p->perm);
29807 0 : ae_vector_destroy(&p->invperm);
29808 0 : ae_vector_destroy(&p->columnswaps);
29809 0 : _amdnset_destroy(&p->lp);
29810 0 : _amdnset_destroy(&p->plp);
29811 0 : _amdnset_destroy(&p->ep);
29812 0 : _amdnset_destroy(&p->adji);
29813 0 : _amdnset_destroy(&p->adjj);
29814 0 : ae_vector_destroy(&p->ls);
29815 0 : _amdnset_destroy(&p->exactdegreetmp0);
29816 0 : _amdknset_destroy(&p->hashbuckets);
29817 0 : _amdnset_destroy(&p->nonemptybuckets);
29818 0 : ae_vector_destroy(&p->sncandidates);
29819 0 : ae_vector_destroy(&p->tmp0);
29820 0 : ae_vector_destroy(&p->arrwe);
29821 0 : ae_matrix_destroy(&p->dbga);
29822 0 : }
29823 :
29824 :
29825 : #endif
29826 : #if defined(AE_COMPILE_SPCHOL) || !defined(AE_PARTIAL_BUILD)
29827 :
29828 :
29829 : /*************************************************************************
29830 : Informational function, useful for debugging
29831 : *************************************************************************/
29832 0 : ae_int_t spsymmgetmaxfastkernel(ae_state *_state)
29833 : {
29834 : ae_int_t result;
29835 :
29836 :
29837 0 : result = spchol_maxfastkernel;
29838 0 : return result;
29839 : }
29840 :
29841 :
29842 : /*************************************************************************
29843 : Symbolic phase of Cholesky decomposition.
29844 :
29845 : Performs preliminary analysis of Cholesky/LDLT factorization. The latter
29846 : is computed with strictly diagonal D (no Bunch-Kauffman pivoting).
29847 :
29848 : The analysis object produced by this function will be used later to guide
29849 : actual decomposition.
29850 :
29851 : Depending on settings specified during factorization, may produce vanilla
29852 : Cholesky or L*D*LT decomposition (with strictly diagonal D), without
29853 : permutation or with permutation P (being either topological ordering or
29854 : sparsity preserving ordering).
29855 :
29856 : Thus, A is represented as either L*LT or L*D*LT or P*L*LT*PT or P*L*D*LT*PT.
29857 :
29858 : NOTE: L*D*LT family of factorization may be used to factorize indefinite
29859 : matrices. However, numerical stability is guaranteed ONLY for a class
29860 : of quasi-definite matrices.
29861 :
29862 : INPUT PARAMETERS:
29863 : A - sparse square matrix in CRS format, with LOWER triangle
29864 : being used to store the matrix.
29865 : FactType - factorization type:
29866 : * 0 for traditional Cholesky
29867 : * 1 for LDLT decomposition with strictly diagonal D
29868 : PermType - permutation type:
29869 : *-2 for column count ordering (NOT RECOMMENDED!)
29870 : *-1 for absence of permutation
29871 : * 0 for best permutation available
29872 : * 1 for supernodal ordering (improves locality and
29873 : performance, but does NOT change fill-in pattern)
29874 : * 2 for supernodal AMD ordering (improves fill-in)
29875 : Analysis - can be uninitialized instance, or previous analysis
29876 : results. Previously allocated memory is reused as much
29877 : as possible.
29878 : Buf - buffer; may be completely uninitialized, or one remained
29879 : from previous calls (including ones with completely
29880 : different matrices). Previously allocated temporary
29881 : space will be reused as much as possible.
29882 :
29883 : OUTPUT PARAMETERS:
29884 : Analysis - symbolic analysis of the matrix structure which will
29885 : be used later to guide numerical factorization. The
29886 : numerical values are stored internally in the structure,
29887 : but you have to run factorization phase explicitly
29888 : with SPSymmAnalyze(). You can also reload another
29889 : matrix with same sparsity pattern with SPSymmReload().
29890 :
29891 : This function fails if and only if the matrix A is symbolically degenerate
29892 : i.e. has diagonal element which is exactly zero. In such case False is
29893 : returned.
29894 :
29895 : NOTE: defining 'SCHOLESKY' trace tag will activate tracing
29896 :
29897 : NOTE: defining 'DEBUG.SLOW' trace tag will activate extra-slow (roughly
29898 : N^3 ops) integrity checks, in addition to cheap O(1) ones.
29899 :
29900 : -- ALGLIB routine --
29901 : 20.09.2020
29902 : Bochkanov Sergey
29903 : *************************************************************************/
29904 0 : ae_bool spsymmanalyze(sparsematrix* a,
29905 : ae_int_t facttype,
29906 : ae_int_t permtype,
29907 : spcholanalysis* analysis,
29908 : ae_state *_state)
29909 : {
29910 : ae_int_t n;
29911 : ae_int_t i;
29912 : ae_bool permready;
29913 : ae_bool result;
29914 :
29915 :
29916 0 : ae_assert(sparseiscrs(a, _state), "SPSymmAnalyze: A is not stored in CRS format", _state);
29917 0 : ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SPSymmAnalyze: non-square A", _state);
29918 0 : ae_assert(facttype==0||facttype==1, "SPSymmAnalyze: unexpected FactType", _state);
29919 0 : ae_assert((((permtype==0||permtype==1)||permtype==2)||permtype==-1)||permtype==-2, "SPSymmAnalyze: unexpected PermType", _state);
29920 0 : if( permtype==0 )
29921 : {
29922 0 : permtype = 2;
29923 : }
29924 0 : result = ae_true;
29925 0 : n = sparsegetnrows(a, _state);
29926 0 : analysis->tasktype = 0;
29927 0 : analysis->n = n;
29928 0 : analysis->unitd = facttype==0;
29929 0 : analysis->permtype = permtype;
29930 0 : analysis->extendeddebug = ae_is_trace_enabled("DEBUG.SLOW");
29931 0 : analysis->dotrace = ae_is_trace_enabled("SCHOLESKY");
29932 0 : analysis->istopologicalordering = permtype==-1||permtype==1;
29933 0 : analysis->applypermutationtooutput = permtype==-1;
29934 0 : analysis->modtype = 0;
29935 0 : analysis->modparam0 = 0.0;
29936 0 : analysis->modparam1 = 0.0;
29937 0 : analysis->modparam2 = 0.0;
29938 0 : analysis->modparam3 = 0.0;
29939 :
29940 : /*
29941 : * Initial trace message
29942 : */
29943 0 : if( analysis->dotrace )
29944 : {
29945 0 : ae_trace("\n\n");
29946 0 : ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n");
29947 0 : ae_trace("// SPARSE CHOLESKY ANALYSIS STARTED //\n");
29948 0 : ae_trace("////////////////////////////////////////////////////////////////////////////////////////////////////\n");
29949 : }
29950 :
29951 : /*
29952 : * Initial integrity check - diagonal MUST be symbolically nonzero
29953 : */
29954 0 : for(i=0; i<=n-1; i++)
29955 : {
29956 0 : if( a->didx.ptr.p_int[i]==a->uidx.ptr.p_int[i] )
29957 : {
29958 0 : if( analysis->dotrace )
29959 : {
29960 0 : ae_trace("> the matrix diagonal is symbolically zero, stopping");
29961 : }
29962 0 : result = ae_false;
29963 0 : return result;
29964 : }
29965 : }
29966 :
29967 : /*
29968 : * Allocate temporaries
29969 : */
29970 0 : ivectorsetlengthatleast(&analysis->tmp0, n+1, _state);
29971 0 : ivectorsetlengthatleast(&analysis->tmp1, n+1, _state);
29972 0 : ivectorsetlengthatleast(&analysis->tmp2, n+1, _state);
29973 0 : ivectorsetlengthatleast(&analysis->tmp3, n+1, _state);
29974 0 : ivectorsetlengthatleast(&analysis->tmp4, n+1, _state);
29975 0 : bvectorsetlengthatleast(&analysis->flagarray, n+1, _state);
29976 :
29977 : /*
29978 : * What type of permutation do we have?
29979 : */
29980 0 : if( analysis->istopologicalordering )
29981 : {
29982 0 : ae_assert(permtype==-1||permtype==1, "SPSymmAnalyze: integrity check failed (ihebd)", _state);
29983 :
29984 : /*
29985 : * Build topologically ordered elimination tree
29986 : */
29987 0 : spchol_buildetree(a, n, &analysis->tmpparent, &analysis->superperm, &analysis->invsuperperm, &analysis->tmp0, &analysis->tmp1, &analysis->tmp2, &analysis->flagarray, _state);
29988 0 : ivectorsetlengthatleast(&analysis->fillinperm, n, _state);
29989 0 : ivectorsetlengthatleast(&analysis->invfillinperm, n, _state);
29990 0 : ivectorsetlengthatleast(&analysis->effectiveperm, n, _state);
29991 0 : ivectorsetlengthatleast(&analysis->inveffectiveperm, n, _state);
29992 0 : for(i=0; i<=n-1; i++)
29993 : {
29994 0 : analysis->fillinperm.ptr.p_int[i] = i;
29995 0 : analysis->invfillinperm.ptr.p_int[i] = i;
29996 0 : analysis->effectiveperm.ptr.p_int[i] = analysis->superperm.ptr.p_int[i];
29997 0 : analysis->inveffectiveperm.ptr.p_int[i] = analysis->invsuperperm.ptr.p_int[i];
29998 : }
29999 :
30000 : /*
30001 : * Reorder input matrix
30002 : */
30003 0 : spchol_topologicalpermutation(a, &analysis->superperm, &analysis->wrkat, _state);
30004 :
30005 : /*
30006 : * Analyze etree, build supernodal structure
30007 : */
30008 0 : spchol_createsupernodalstructure(&analysis->wrkat, &analysis->tmpparent, n, analysis, &analysis->node2supernode, &analysis->tmp0, &analysis->tmp1, &analysis->tmp2, &analysis->tmp3, &analysis->tmp4, &analysis->flagarray, _state);
30009 :
30010 : /*
30011 : * Having fully initialized supernodal structure, analyze dependencies
30012 : */
30013 0 : spchol_analyzesupernodaldependencies(analysis, a, &analysis->node2supernode, n, &analysis->tmp0, &analysis->tmp1, &analysis->flagarray, _state);
30014 : }
30015 : else
30016 : {
30017 :
30018 : /*
30019 : * Generate fill-in reducing permutation
30020 : */
30021 0 : permready = ae_false;
30022 0 : if( permtype==-2 )
30023 : {
30024 0 : spchol_generatedbgpermutation(a, n, &analysis->fillinperm, &analysis->invfillinperm, _state);
30025 0 : permready = ae_true;
30026 : }
30027 0 : if( permtype==2 )
30028 : {
30029 0 : generateamdpermutation(a, n, &analysis->fillinperm, &analysis->invfillinperm, &analysis->amdtmp, _state);
30030 0 : permready = ae_true;
30031 : }
30032 0 : ae_assert(permready, "SPSymmAnalyze: integrity check failed (pp4td)", _state);
30033 :
30034 : /*
30035 : * Apply permutation to the matrix, perform analysis on the initially reordered matrix
30036 : * (we may need one more reordering, now topological one, due to supernodal analysis).
30037 : * Build topologically ordered elimination tree
30038 : */
30039 0 : sparsesymmpermtblbuf(a, ae_false, &analysis->fillinperm, &analysis->tmpa, _state);
30040 0 : spchol_buildetree(&analysis->tmpa, n, &analysis->tmpparent, &analysis->superperm, &analysis->invsuperperm, &analysis->tmp0, &analysis->tmp1, &analysis->tmp2, &analysis->flagarray, _state);
30041 0 : ivectorsetlengthatleast(&analysis->effectiveperm, n, _state);
30042 0 : ivectorsetlengthatleast(&analysis->inveffectiveperm, n, _state);
30043 0 : for(i=0; i<=n-1; i++)
30044 : {
30045 0 : analysis->effectiveperm.ptr.p_int[i] = analysis->superperm.ptr.p_int[analysis->fillinperm.ptr.p_int[i]];
30046 0 : analysis->inveffectiveperm.ptr.p_int[analysis->effectiveperm.ptr.p_int[i]] = i;
30047 : }
30048 :
30049 : /*
30050 : * Reorder input matrix
30051 : */
30052 0 : spchol_topologicalpermutation(&analysis->tmpa, &analysis->superperm, &analysis->wrkat, _state);
30053 :
30054 : /*
30055 : * Analyze etree, build supernodal structure
30056 : */
30057 0 : spchol_createsupernodalstructure(&analysis->wrkat, &analysis->tmpparent, n, analysis, &analysis->node2supernode, &analysis->tmp0, &analysis->tmp1, &analysis->tmp2, &analysis->tmp3, &analysis->tmp4, &analysis->flagarray, _state);
30058 :
30059 : /*
30060 : * Having fully initialized supernodal structure, analyze dependencies
30061 : */
30062 0 : spchol_analyzesupernodaldependencies(analysis, &analysis->tmpa, &analysis->node2supernode, n, &analysis->tmp0, &analysis->tmp1, &analysis->flagarray, _state);
30063 : }
30064 0 : return result;
30065 : }
30066 :
30067 :
30068 : /*************************************************************************
30069 : Sets modified Cholesky type
30070 :
30071 : INPUT PARAMETERS:
30072 : Analysis - symbolic analysis of the matrix structure
30073 : ModStrategy - modification type:
30074 : * 0 for traditional Cholesky/LDLT (Cholesky fails when
30075 : encounters nonpositive pivot, LDLT fails when zero
30076 : pivot is encountered, no stability checks for
30077 : overflows/underflows)
30078 : * 1 for modified Cholesky with additional checks:
30079 : * pivots less than ModParam0 are increased; (similar
30080 : procedure with proper generalization is applied to
30081 : LDLT)
30082 : * if, at some moment, sum of absolute values of
30083 : elements in column J will become greater than
30084 : ModParam1, Cholesky/LDLT will treat it as failure
30085 : and will stop immediately
30086 : * if ModParam0 is zero, no pivot modification is applied
30087 : * if ModParam1 is zero, no overflow check is performed
30088 : P0, P1, P2,P3 - modification parameters #0 #1, #2 and #3.
30089 : Params #2 and #3 are ignored in current version.
30090 :
30091 : OUTPUT PARAMETERS:
30092 : Analysis - symbolic analysis of the matrix structure, new strategy
30093 : (results will be seen with next SPSymmFactorize() call)
30094 :
30095 : -- ALGLIB routine --
30096 : 20.09.2020
30097 : Bochkanov Sergey
30098 : *************************************************************************/
30099 0 : void spsymmsetmodificationstrategy(spcholanalysis* analysis,
30100 : ae_int_t modstrategy,
30101 : double p0,
30102 : double p1,
30103 : double p2,
30104 : double p3,
30105 : ae_state *_state)
30106 : {
30107 :
30108 :
30109 0 : ae_assert(modstrategy==0||modstrategy==1, "SPSymmSetModificationStrategy: unexpected ModStrategy", _state);
30110 0 : ae_assert(ae_isfinite(p0, _state)&&ae_fp_greater_eq(p0,(double)(0)), "SPSymmSetModificationStrategy: bad P0", _state);
30111 0 : ae_assert(ae_isfinite(p1, _state), "SPSymmSetModificationStrategy: bad P1", _state);
30112 0 : ae_assert(ae_isfinite(p2, _state), "SPSymmSetModificationStrategy: bad P2", _state);
30113 0 : ae_assert(ae_isfinite(p3, _state), "SPSymmSetModificationStrategy: bad P3", _state);
30114 0 : analysis->modtype = modstrategy;
30115 0 : analysis->modparam0 = p0;
30116 0 : analysis->modparam1 = p1;
30117 0 : analysis->modparam2 = p2;
30118 0 : analysis->modparam3 = p3;
30119 0 : }
30120 :
30121 :
30122 : /*************************************************************************
30123 : Updates symmetric matrix internally stored in previously initialized
30124 : Analysis object.
30125 :
30126 : You can use this function to perform multiple factorizations with same
30127 : sparsity patterns: perform symbolic analysis once with SPSymmAnalyze(),
30128 : then update internal matrix with SPSymmReload() and call SPSymmFactorize().
30129 :
30130 : INPUT PARAMETERS:
30131 : Analysis - symbolic analysis of the matrix structure
30132 : A - sparse square matrix in CRS format with LOWER triangle
30133 : being used to store the matrix. The matrix MUST have
30134 : sparsity pattern exactly same as one used to
30135 : initialize the Analysis object.
30136 : The algorithm will fail in an unpredictable way if
30137 : something different was passed.
30138 :
30139 : OUTPUT PARAMETERS:
30140 : Analysis - symbolic analysis of the matrix structure which will
30141 : be used later to guide numerical factorization. The
30142 : numerical values are stored internally in the structure,
30143 : but you have to run factorization phase explicitly
30144 : with SPSymmAnalyze(). You can also reload another
30145 : matrix with same sparsity pattern with SPSymmReload().
30146 :
30147 : -- ALGLIB routine --
30148 : 20.09.2020
30149 : Bochkanov Sergey
30150 : *************************************************************************/
30151 0 : void spsymmreload(spcholanalysis* analysis,
30152 : sparsematrix* a,
30153 : ae_state *_state)
30154 : {
30155 :
30156 :
30157 0 : ae_assert(sparseiscrs(a, _state), "SPSymmReload: A is not stored in CRS format", _state);
30158 0 : ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SPSymmReload: non-square A", _state);
30159 0 : if( analysis->istopologicalordering )
30160 : {
30161 :
30162 : /*
30163 : * Topological (fill-in preserving) ordering is used, we can copy
30164 : * A directly into WrkAT using joint permute+transpose
30165 : */
30166 0 : spchol_topologicalpermutation(a, &analysis->effectiveperm, &analysis->wrkat, _state);
30167 : }
30168 : else
30169 : {
30170 :
30171 : /*
30172 : * Non-topological permutation; first we perform generic symmetric
30173 : * permutation, then transpose result
30174 : */
30175 0 : sparsesymmpermtblbuf(a, ae_false, &analysis->effectiveperm, &analysis->tmpa, _state);
30176 0 : sparsecopytransposecrsbuf(&analysis->tmpa, &analysis->wrkat, _state);
30177 : }
30178 0 : }
30179 :
30180 :
30181 : /*************************************************************************
30182 : Sparse Cholesky factorization of SPD matrix stored in CRS format, using
30183 : precomputed analysis of sparsity pattern stored in Analysis object and
30184 : the matrix that is presently loaded into A.
30185 :
30186 : Depending on settings specified during factorization, may produce vanilla
30187 : Cholesky or L*D*LT decomposition (with strictly diagonal D), without
30188 : permutation or with permutation P (being either topological ordering or
30189 : sparsity preserving ordering).
30190 :
30191 : Thus, A is represented as either L*LT or L*D*LT or P*L*LT*PT or P*L*D*LT*PT.
30192 :
30193 : NOTE: L*D*LT family of factorization may be used to factorize indefinite
30194 : matrices. However, numerical stability is guaranteed ONLY for a class
30195 : of quasi-definite matrices.
30196 :
30197 : INPUT PARAMETERS:
30198 : Analysis - prior analysis performed on some sparse matrix, with
30199 : matrix being stored in Analysis. This matrix is
30200 : destroyed during factorization.
30201 : D, P - possibly preallocated buffers
30202 :
30203 : OUTPUT PARAMETERS:
30204 : A - Cholesky decomposition of A stored in CRS format
30205 : in LOWER triangle.
30206 : D - array[N], diagonal factor. If no diagonal factor was
30207 : required during analysis phase, still returned but
30208 : filled with units.
30209 : P - array[N], pivots. Permutation matrix P is a product of
30210 : P(0)*P(1)*...*P(N-1), where P(i) is a permutation of
30211 : row/col I and P[I] (with P[I]>=I).
30212 : If no permutation was requested during analysis phase,
30213 : still returned but filled with unit elements.
30214 :
30215 : The function returns True when factorization resulted in nondegenerate
30216 : matrix. False is returned when factorization fails (Cholesky factorization
30217 : of indefinite matrix) or LDLT factorization has exactly zero elements at
30218 : the diagonal.
30219 :
30220 : In the latter case contents of A, D and P is undefined.
30221 :
30222 : -- ALGLIB routine --
30223 : 20.09.2020
30224 : Bochkanov Sergey
30225 : *************************************************************************/
30226 0 : ae_bool spsymmfactorize(spcholanalysis* analysis,
30227 : sparsematrix* a,
30228 : /* Real */ ae_vector* d,
30229 : /* Integer */ ae_vector* p,
30230 : ae_state *_state)
30231 : {
30232 : ae_int_t i;
30233 : ae_int_t j;
30234 : ae_int_t k;
30235 : ae_int_t ii;
30236 : ae_int_t i0;
30237 : ae_int_t i1;
30238 : ae_int_t n;
30239 : ae_int_t cols0;
30240 : ae_int_t cols1;
30241 : ae_int_t offss;
30242 : ae_int_t sstride;
30243 : ae_int_t blocksize;
30244 : ae_int_t sidx;
30245 : ae_int_t uidx;
30246 : ae_bool result;
30247 :
30248 :
30249 0 : ae_assert(analysis->tasktype==0, "SPCholFactorize: Analysis type does not match current task", _state);
30250 0 : result = ae_true;
30251 0 : n = analysis->n;
30252 :
30253 : /*
30254 : * Prepare structures:
30255 : * * WrkRows[] store pointers to beginnings of the offdiagonal supernode row ranges;
30256 : * at the beginning of the work WrkRows[]=0, but as we advance from the column
30257 : * range [0,A) to [A,B), to [B,C) and so on, we advance WrkRows[] in order to
30258 : * quickly skip parts that are less than A, less than B, less than C and so on.
30259 : */
30260 0 : ivectorsetlengthatleast(&analysis->raw2smap, n, _state);
30261 0 : ivectorsetlengthatleast(&analysis->tmp0, n+1, _state);
30262 0 : bsetallocv(n, ae_false, &analysis->flagarray, _state);
30263 0 : isetallocv(analysis->nsuper, 0, &analysis->wrkrows, _state);
30264 0 : rsetallocv(n, 0.0, &analysis->diagd, _state);
30265 0 : rsetallocv(analysis->rowoffsets.ptr.p_int[analysis->nsuper], 0.0, &analysis->rowstorage, _state);
30266 :
30267 : /*
30268 : * Now we can run actual supernodal Cholesky
30269 : */
30270 0 : for(sidx=0; sidx<=analysis->nsuper-1; sidx++)
30271 : {
30272 0 : cols0 = analysis->supercolrange.ptr.p_int[sidx];
30273 0 : cols1 = analysis->supercolrange.ptr.p_int[sidx+1];
30274 0 : blocksize = cols1-cols0;
30275 0 : offss = analysis->rowoffsets.ptr.p_int[sidx];
30276 0 : sstride = analysis->rowstrides.ptr.p_int[sidx];
30277 :
30278 : /*
30279 : * Prepare mapping of raw (range 0...N-1) indexes into internal (range 0...BlockSize+OffdiagSize-1) ones
30280 : */
30281 0 : if( analysis->extendeddebug )
30282 : {
30283 0 : isetv(n, -1, &analysis->raw2smap, _state);
30284 : }
30285 0 : for(i=cols0; i<=cols1-1; i++)
30286 : {
30287 0 : analysis->raw2smap.ptr.p_int[i] = i-cols0;
30288 : }
30289 0 : for(k=analysis->superrowridx.ptr.p_int[sidx]; k<=analysis->superrowridx.ptr.p_int[sidx+1]-1; k++)
30290 : {
30291 0 : analysis->raw2smap.ptr.p_int[analysis->superrowidx.ptr.p_int[k]] = blocksize+(k-analysis->superrowridx.ptr.p_int[sidx]);
30292 : }
30293 :
30294 : /*
30295 : * Load supernode #SIdx using Raw2SMap to perform quick transformation between global and local indexing.
30296 : */
30297 0 : for(j=cols0; j<=cols1-1; j++)
30298 : {
30299 0 : i0 = analysis->wrkat.ridx.ptr.p_int[j];
30300 0 : i1 = analysis->wrkat.ridx.ptr.p_int[j+1]-1;
30301 0 : for(ii=i0; ii<=i1; ii++)
30302 : {
30303 0 : analysis->rowstorage.ptr.p_double[offss+analysis->raw2smap.ptr.p_int[analysis->wrkat.idx.ptr.p_int[ii]]*sstride+(j-cols0)] = analysis->wrkat.vals.ptr.p_double[ii];
30304 : }
30305 : }
30306 :
30307 : /*
30308 : * Update current supernode with nonzeros from the current row
30309 : */
30310 0 : for(ii=analysis->ladjplusr.ptr.p_int[sidx]; ii<=analysis->ladjplusr.ptr.p_int[sidx+1]-1; ii++)
30311 : {
30312 0 : uidx = analysis->ladjplus.ptr.p_int[ii];
30313 0 : analysis->wrkrows.ptr.p_int[uidx] = spchol_updatesupernode(analysis, sidx, cols0, cols1, offss, &analysis->raw2smap, uidx, analysis->wrkrows.ptr.p_int[uidx], &analysis->diagd, analysis->supercolrange.ptr.p_int[uidx], _state);
30314 : }
30315 :
30316 : /*
30317 : * Factorize current supernode
30318 : */
30319 0 : if( !spchol_factorizesupernode(analysis, sidx, _state) )
30320 : {
30321 0 : result = ae_false;
30322 0 : return result;
30323 : }
30324 : }
30325 :
30326 : /*
30327 : * Convert from supernodal storage to SparseMatrix format
30328 : */
30329 0 : spchol_extractmatrix(analysis, &analysis->rowoffsets, &analysis->rowstrides, &analysis->rowstorage, &analysis->diagd, n, a, d, p, &analysis->tmp0, _state);
30330 0 : return result;
30331 : }
30332 :
30333 :
30334 : /*************************************************************************
30335 : This function generates test reodering used for debug purposes only
30336 :
30337 : INPUT PARAMETERS
30338 : A - lower triangular sparse matrix in CRS format
30339 : N - problem size
30340 :
30341 : OUTPUT PARAMETERS
30342 : Perm - array[N], maps original indexes I to permuted indexes
30343 : InvPerm - array[N], maps permuted indexes I to original indexes
30344 :
30345 : -- ALGLIB PROJECT --
30346 : Copyright 05.10.2020 by Bochkanov Sergey.
30347 : *************************************************************************/
30348 0 : static void spchol_generatedbgpermutation(sparsematrix* a,
30349 : ae_int_t n,
30350 : /* Integer */ ae_vector* perm,
30351 : /* Integer */ ae_vector* invperm,
30352 : ae_state *_state)
30353 : {
30354 : ae_int_t i;
30355 :
30356 :
30357 0 : ivectorsetlengthatleast(perm, n, _state);
30358 0 : ivectorsetlengthatleast(invperm, n, _state);
30359 0 : for(i=0; i<=n-1; i++)
30360 : {
30361 0 : perm->ptr.p_int[i] = n-1-i;
30362 0 : invperm->ptr.p_int[i] = n-1-i;
30363 : }
30364 0 : }
30365 :
30366 :
30367 : /*************************************************************************
30368 : This function builds elimination tree and reorders it according to the
30369 : topological post-ordering.
30370 :
30371 : INPUT PARAMETERS
30372 : A - lower triangular sparse matrix in CRS format
30373 : N - problem size
30374 :
30375 : tRawParentOfRawNode,
30376 : tRawParentOfReorderedNode,
30377 : tTmp,
30378 : tFlagArray - preallocated temporary arrays, length at least N+1, no
30379 : meaningful output is provided in these variables
30380 :
30381 : OUTPUT PARAMETERS
30382 : Parent - array[N], Parent[I] contains index of parent of I-th
30383 : column (after topological reordering). -1 is used to
30384 : denote column with no parents.
30385 : SupernodalPermutation
30386 : - array[N], maps original indexes I to permuted indexes
30387 : InvSupernodalPermutation
30388 : - array[N], maps permuted indexes I to original indexes
30389 :
30390 : -- ALGLIB PROJECT --
30391 : Copyright 05.10.2020 by Bochkanov Sergey.
30392 : *************************************************************************/
30393 0 : static void spchol_buildetree(sparsematrix* a,
30394 : ae_int_t n,
30395 : /* Integer */ ae_vector* parent,
30396 : /* Integer */ ae_vector* supernodalpermutation,
30397 : /* Integer */ ae_vector* invsupernodalpermutation,
30398 : /* Integer */ ae_vector* trawparentofrawnode,
30399 : /* Integer */ ae_vector* trawparentofreorderednode,
30400 : /* Integer */ ae_vector* ttmp,
30401 : /* Boolean */ ae_vector* tflagarray,
30402 : ae_state *_state)
30403 : {
30404 : ae_int_t i;
30405 : ae_int_t j;
30406 : ae_int_t k;
30407 : ae_int_t sidx;
30408 : ae_int_t parentk;
30409 : ae_int_t unprocessedchildrencnt;
30410 : ae_int_t j0;
30411 : ae_int_t j1;
30412 : ae_int_t jj;
30413 :
30414 :
30415 0 : ae_assert(trawparentofrawnode->cnt>=n+1, "BuildETree: input buffer tRawParentOfRawNode is too short", _state);
30416 0 : ae_assert(ttmp->cnt>=n+1, "BuildETree: input buffer tTmp is too short", _state);
30417 0 : ae_assert(trawparentofreorderednode->cnt>=n+1, "BuildETree: input buffer tRawParentOfReorderedNode is too short", _state);
30418 0 : ae_assert(tflagarray->cnt>=n+1, "BuildETree: input buffer tFlagArray is too short", _state);
30419 :
30420 : /*
30421 : * Avoid spurious compiler warnings
30422 : */
30423 0 : unprocessedchildrencnt = 0;
30424 :
30425 : /*
30426 : * Build elimination tree with original column order using path compression:
30427 : * tTmp[] array stores indexes of some ancestor of the vertex.
30428 : */
30429 0 : for(i=0; i<=n-1; i++)
30430 : {
30431 0 : trawparentofrawnode->ptr.p_int[i] = -1;
30432 0 : ttmp->ptr.p_int[i] = i;
30433 0 : j0 = a->ridx.ptr.p_int[i];
30434 0 : j1 = a->didx.ptr.p_int[i]-1;
30435 0 : for(jj=j0; jj<=j1; jj++)
30436 : {
30437 0 : j = a->idx.ptr.p_int[jj];
30438 0 : k = ttmp->ptr.p_int[j];
30439 0 : ttmp->ptr.p_int[j] = i;
30440 0 : parentk = trawparentofrawnode->ptr.p_int[k];
30441 0 : while(parentk>=0)
30442 : {
30443 0 : ttmp->ptr.p_int[k] = i;
30444 0 : k = parentk;
30445 0 : parentk = trawparentofrawnode->ptr.p_int[k];
30446 : }
30447 0 : if( k!=i )
30448 : {
30449 0 : trawparentofrawnode->ptr.p_int[k] = i;
30450 : }
30451 : }
30452 : }
30453 :
30454 : /*
30455 : * Compute topological ordering of the elimination tree, produce:
30456 : * * direct and inverse permutations
30457 : * * reordered etree stored in Parent[]
30458 : */
30459 0 : isetallocv(n, -1, invsupernodalpermutation, _state);
30460 0 : isetallocv(n, -1, supernodalpermutation, _state);
30461 0 : isetallocv(n, -1, parent, _state);
30462 0 : isetv(n, -1, trawparentofreorderednode, _state);
30463 0 : isetv(n, 0, ttmp, _state);
30464 0 : for(i=0; i<=n-1; i++)
30465 : {
30466 0 : k = trawparentofrawnode->ptr.p_int[i];
30467 0 : if( k>=0 )
30468 : {
30469 0 : ttmp->ptr.p_int[k] = ttmp->ptr.p_int[k]+1;
30470 : }
30471 : }
30472 0 : bsetv(n, ae_true, tflagarray, _state);
30473 0 : sidx = 0;
30474 0 : for(i=0; i<=n-1; i++)
30475 : {
30476 0 : if( tflagarray->ptr.p_bool[i] )
30477 : {
30478 :
30479 : /*
30480 : * Move column I to position SIdx, decrease unprocessed children count
30481 : */
30482 0 : supernodalpermutation->ptr.p_int[i] = sidx;
30483 0 : invsupernodalpermutation->ptr.p_int[sidx] = i;
30484 0 : tflagarray->ptr.p_bool[i] = ae_false;
30485 0 : k = trawparentofrawnode->ptr.p_int[i];
30486 0 : trawparentofreorderednode->ptr.p_int[sidx] = k;
30487 0 : if( k>=0 )
30488 : {
30489 0 : unprocessedchildrencnt = ttmp->ptr.p_int[k]-1;
30490 0 : ttmp->ptr.p_int[k] = unprocessedchildrencnt;
30491 : }
30492 0 : sidx = sidx+1;
30493 :
30494 : /*
30495 : * Add parents (as long as parent has no unprocessed children)
30496 : */
30497 0 : while(k>=0&&unprocessedchildrencnt==0)
30498 : {
30499 0 : supernodalpermutation->ptr.p_int[k] = sidx;
30500 0 : invsupernodalpermutation->ptr.p_int[sidx] = k;
30501 0 : tflagarray->ptr.p_bool[k] = ae_false;
30502 0 : k = trawparentofrawnode->ptr.p_int[k];
30503 0 : trawparentofreorderednode->ptr.p_int[sidx] = k;
30504 0 : if( k>=0 )
30505 : {
30506 0 : unprocessedchildrencnt = ttmp->ptr.p_int[k]-1;
30507 0 : ttmp->ptr.p_int[k] = unprocessedchildrencnt;
30508 : }
30509 0 : sidx = sidx+1;
30510 : }
30511 : }
30512 : }
30513 0 : for(i=0; i<=n-1; i++)
30514 : {
30515 0 : k = trawparentofreorderednode->ptr.p_int[i];
30516 0 : if( k>=0 )
30517 : {
30518 0 : parent->ptr.p_int[i] = supernodalpermutation->ptr.p_int[k];
30519 : }
30520 : }
30521 0 : }
30522 :
30523 :
30524 : /*************************************************************************
30525 : This function analyzes postordered elimination tree and creates supernodal
30526 : structure in Analysis object.
30527 :
30528 : INPUT PARAMETERS
30529 : AT - upper triangular CRS matrix, transpose and reordering
30530 : of the original input matrix A
30531 : Parent - array[N], supernodal etree
30532 : N - problem size
30533 :
30534 : tChildrenR,
30535 : tChildrenI,
30536 : tParentNodeOfSupernode,
30537 : tNode2Supernode,
30538 : tTmp0,
30539 : tFlagArray - temporary arrays, length at least N+1, simply provide
30540 : preallocated place.
30541 :
30542 : OUTPUT PARAMETERS
30543 : Analysis - following fields are initialized:
30544 : * Analysis.NSuper
30545 : * Analysis.SuperColRange
30546 : * Analysis.SuperRowRIdx
30547 : * Analysis.SuperRowIdx
30548 : * Analysis.ParentSupernode
30549 : * Analysis.OutRowCounts
30550 : other fields are ignored and not changed.
30551 : Node2Supernode- array[N] that maps node indexes to supernode indexes
30552 :
30553 : -- ALGLIB PROJECT --
30554 : Copyright 05.10.2020 by Bochkanov Sergey.
30555 : *************************************************************************/
30556 0 : static void spchol_createsupernodalstructure(sparsematrix* at,
30557 : /* Integer */ ae_vector* parent,
30558 : ae_int_t n,
30559 : spcholanalysis* analysis,
30560 : /* Integer */ ae_vector* node2supernode,
30561 : /* Integer */ ae_vector* tchildrenr,
30562 : /* Integer */ ae_vector* tchildreni,
30563 : /* Integer */ ae_vector* tparentnodeofsupernode,
30564 : /* Integer */ ae_vector* tfakenonzeros,
30565 : /* Integer */ ae_vector* ttmp0,
30566 : /* Boolean */ ae_vector* tflagarray,
30567 : ae_state *_state)
30568 : {
30569 : ae_int_t nsuper;
30570 : ae_int_t i;
30571 : ae_int_t j;
30572 : ae_int_t k;
30573 : ae_int_t sidx;
30574 : ae_int_t i0;
30575 : ae_int_t ii;
30576 : ae_int_t columnidx;
30577 : ae_int_t nodeidx;
30578 : ae_int_t rfirst;
30579 : ae_int_t rlast;
30580 : ae_int_t cols0;
30581 : ae_int_t cols1;
30582 : ae_int_t blocksize;
30583 : ae_bool createsupernode;
30584 : ae_int_t colcount;
30585 : ae_int_t offdiagcnt;
30586 : ae_int_t childcolcount;
30587 : ae_int_t childoffdiagcnt;
30588 : ae_int_t fakezerosinnewsupernode;
30589 : double mergeinefficiency;
30590 : ae_bool hastheonlychild;
30591 :
30592 :
30593 0 : ae_assert(ttmp0->cnt>=n+1, "CreateSupernodalStructure: input buffer tTmp0 is too short", _state);
30594 0 : ae_assert(tchildrenr->cnt>=n+1, "CreateSupernodalStructure: input buffer ChildrenR is too short", _state);
30595 0 : ae_assert(tchildreni->cnt>=n+1, "CreateSupernodalStructure: input buffer ChildrenI is too short", _state);
30596 0 : ae_assert(tparentnodeofsupernode->cnt>=n+1, "CreateSupernodalStructure: input buffer tParentNodeOfSupernode is too short", _state);
30597 0 : ae_assert(tfakenonzeros->cnt>=n+1, "CreateSupernodalStructure: input buffer tFakeNonzeros is too short", _state);
30598 0 : ae_assert(tflagarray->cnt>=n+1, "CreateSupernodalStructure: input buffer tFlagArray is too short", _state);
30599 :
30600 : /*
30601 : * Trace
30602 : */
30603 0 : if( analysis->dotrace )
30604 : {
30605 0 : ae_trace("=== GENERATING SUPERNODAL STRUCTURE ================================================================\n");
30606 : }
30607 :
30608 : /*
30609 : * Convert etree from per-column parent array to per-column children list
30610 : */
30611 0 : isetv(n, 0, ttmp0, _state);
30612 0 : for(i=0; i<=n-1; i++)
30613 : {
30614 0 : nodeidx = parent->ptr.p_int[i];
30615 0 : if( nodeidx>=0 )
30616 : {
30617 0 : ttmp0->ptr.p_int[nodeidx] = ttmp0->ptr.p_int[nodeidx]+1;
30618 : }
30619 : }
30620 0 : tchildrenr->ptr.p_int[0] = 0;
30621 0 : for(i=0; i<=n-1; i++)
30622 : {
30623 0 : tchildrenr->ptr.p_int[i+1] = tchildrenr->ptr.p_int[i]+ttmp0->ptr.p_int[i];
30624 : }
30625 0 : isetv(n, 0, ttmp0, _state);
30626 0 : for(i=0; i<=n-1; i++)
30627 : {
30628 0 : k = parent->ptr.p_int[i];
30629 0 : if( k>=0 )
30630 : {
30631 0 : tchildreni->ptr.p_int[tchildrenr->ptr.p_int[k]+ttmp0->ptr.p_int[k]] = i;
30632 0 : ttmp0->ptr.p_int[k] = ttmp0->ptr.p_int[k]+1;
30633 : }
30634 : }
30635 :
30636 : /*
30637 : * Analyze supernodal structure:
30638 : * * determine children count for each node
30639 : * * combine chains of children into supernodes
30640 : * * generate direct and inverse supernodal (topological) permutations
30641 : * * generate column structure of supernodes (after supernodal permutation)
30642 : */
30643 0 : isetallocv(n, -1, node2supernode, _state);
30644 0 : ivectorsetlengthatleast(&analysis->supercolrange, n+1, _state);
30645 0 : ivectorsetlengthatleast(&analysis->superrowridx, n+1, _state);
30646 0 : isetv(n, n+1, tparentnodeofsupernode, _state);
30647 0 : bsetv(n, ae_true, tflagarray, _state);
30648 0 : nsuper = 0;
30649 0 : analysis->supercolrange.ptr.p_int[0] = 0;
30650 0 : analysis->superrowridx.ptr.p_int[0] = 0;
30651 0 : while(analysis->supercolrange.ptr.p_int[nsuper]<n)
30652 : {
30653 0 : columnidx = analysis->supercolrange.ptr.p_int[nsuper];
30654 :
30655 : /*
30656 : * Compute nonzero pattern of the column, create temporary standalone node
30657 : * for possible supernodal merge. Newly created node has just one column
30658 : * and no fake nonzeros.
30659 : */
30660 0 : rfirst = analysis->superrowridx.ptr.p_int[nsuper];
30661 0 : rlast = spchol_computenonzeropattern(at, columnidx, n, &analysis->superrowridx, &analysis->superrowidx, nsuper, tchildrenr, tchildreni, node2supernode, tflagarray, ttmp0, _state);
30662 0 : analysis->supercolrange.ptr.p_int[nsuper+1] = columnidx+1;
30663 0 : analysis->superrowridx.ptr.p_int[nsuper+1] = rlast;
30664 0 : node2supernode->ptr.p_int[columnidx] = nsuper;
30665 0 : tparentnodeofsupernode->ptr.p_int[nsuper] = parent->ptr.p_int[columnidx];
30666 0 : tfakenonzeros->ptr.p_int[nsuper] = 0;
30667 0 : offdiagcnt = rlast-rfirst;
30668 0 : colcount = 1;
30669 0 : nsuper = nsuper+1;
30670 0 : if( analysis->dotrace )
30671 : {
30672 0 : ae_trace("> incoming column %0d\n",
30673 : (int)(columnidx));
30674 0 : ae_trace("offdiagnnz = %0d\n",
30675 0 : (int)(rlast-rfirst));
30676 0 : ae_trace("children = [ ");
30677 0 : for(i=tchildrenr->ptr.p_int[columnidx]; i<=tchildrenr->ptr.p_int[columnidx+1]-1; i++)
30678 : {
30679 0 : ae_trace("S%0d ",
30680 0 : (int)(node2supernode->ptr.p_int[tchildreni->ptr.p_int[i]]));
30681 : }
30682 0 : ae_trace("]\n");
30683 : }
30684 :
30685 : /*
30686 : * Decide whether to merge column with previous supernode or not
30687 : */
30688 0 : childcolcount = 0;
30689 0 : childoffdiagcnt = 0;
30690 0 : mergeinefficiency = 0.0;
30691 0 : fakezerosinnewsupernode = 0;
30692 0 : createsupernode = ae_false;
30693 0 : hastheonlychild = ae_false;
30694 0 : if( nsuper>=2&&tparentnodeofsupernode->ptr.p_int[nsuper-2]==columnidx )
30695 : {
30696 0 : childcolcount = analysis->supercolrange.ptr.p_int[nsuper-1]-analysis->supercolrange.ptr.p_int[nsuper-2];
30697 0 : childoffdiagcnt = analysis->superrowridx.ptr.p_int[nsuper-1]-analysis->superrowridx.ptr.p_int[nsuper-2];
30698 0 : hastheonlychild = tchildrenr->ptr.p_int[columnidx+1]-tchildrenr->ptr.p_int[columnidx]==1;
30699 0 : if( (hastheonlychild||spchol_relaxedsupernodes)&&colcount+childcolcount<=spchol_maxsupernode )
30700 : {
30701 0 : i = colcount+childcolcount;
30702 0 : k = i*(i+1)/2+offdiagcnt*i;
30703 0 : fakezerosinnewsupernode = tfakenonzeros->ptr.p_int[nsuper-2]+tfakenonzeros->ptr.p_int[nsuper-1]+(offdiagcnt-(childoffdiagcnt-1))*childcolcount;
30704 0 : mergeinefficiency = (double)fakezerosinnewsupernode/(double)k;
30705 0 : if( colcount+childcolcount==2&&fakezerosinnewsupernode<=spchol_smallfakestolerance )
30706 : {
30707 0 : createsupernode = ae_true;
30708 : }
30709 0 : if( ae_fp_less_eq(mergeinefficiency,spchol_maxmergeinefficiency) )
30710 : {
30711 0 : createsupernode = ae_true;
30712 : }
30713 : }
30714 : }
30715 :
30716 : /*
30717 : * Create supernode if needed
30718 : */
30719 0 : if( createsupernode )
30720 : {
30721 :
30722 : /*
30723 : * Create supernode from nodes NSuper-2 and NSuper-1.
30724 : * Because these nodes are in the child-parent relation, we can simply
30725 : * copy nonzero pattern from NSuper-1.
30726 : */
30727 0 : ae_assert(tparentnodeofsupernode->ptr.p_int[nsuper-2]==columnidx, "CreateSupernodalStructure: integrity check 9472 failed", _state);
30728 0 : i0 = analysis->superrowridx.ptr.p_int[nsuper-1];
30729 0 : ii = analysis->superrowridx.ptr.p_int[nsuper]-analysis->superrowridx.ptr.p_int[nsuper-1];
30730 0 : rfirst = analysis->superrowridx.ptr.p_int[nsuper-2];
30731 0 : rlast = rfirst+ii;
30732 0 : for(i=0; i<=ii-1; i++)
30733 : {
30734 0 : analysis->superrowidx.ptr.p_int[rfirst+i] = analysis->superrowidx.ptr.p_int[i0+i];
30735 : }
30736 0 : analysis->supercolrange.ptr.p_int[nsuper-1] = columnidx+1;
30737 0 : analysis->superrowridx.ptr.p_int[nsuper-1] = rlast;
30738 0 : node2supernode->ptr.p_int[columnidx] = nsuper-2;
30739 0 : tfakenonzeros->ptr.p_int[nsuper-2] = fakezerosinnewsupernode;
30740 0 : tparentnodeofsupernode->ptr.p_int[nsuper-2] = parent->ptr.p_int[columnidx];
30741 0 : nsuper = nsuper-1;
30742 :
30743 : /*
30744 : * Trace
30745 : */
30746 0 : if( analysis->dotrace )
30747 : {
30748 0 : ae_trace("> merged with supernode S%0d",
30749 0 : (int)(nsuper-1));
30750 0 : if( ae_fp_neq(mergeinefficiency,(double)(0)) )
30751 : {
30752 0 : ae_trace(" (%2.0f%% inefficiency)",
30753 : (double)(mergeinefficiency*100));
30754 : }
30755 0 : ae_trace("\n*\n");
30756 : }
30757 : }
30758 : else
30759 : {
30760 :
30761 : /*
30762 : * Trace
30763 : */
30764 0 : if( analysis->dotrace )
30765 : {
30766 0 : ae_trace("> standalone node S%0d created\n*\n",
30767 0 : (int)(nsuper-1));
30768 : }
30769 : }
30770 : }
30771 0 : analysis->nsuper = nsuper;
30772 0 : ae_assert(analysis->nsuper>=1, "SPSymmAnalyze: integrity check failed (95mgd)", _state);
30773 0 : ae_assert(analysis->supercolrange.ptr.p_int[0]==0, "SPCholFactorize: integrity check failed (f446s)", _state);
30774 0 : ae_assert(analysis->supercolrange.ptr.p_int[nsuper]==n, "SPSymmAnalyze: integrity check failed (04ut4)", _state);
30775 0 : isetallocv(nsuper, -1, &analysis->parentsupernode, _state);
30776 0 : for(sidx=0; sidx<=nsuper-1; sidx++)
30777 : {
30778 0 : nodeidx = tparentnodeofsupernode->ptr.p_int[sidx];
30779 0 : if( nodeidx>=0 )
30780 : {
30781 0 : nodeidx = node2supernode->ptr.p_int[nodeidx];
30782 0 : analysis->parentsupernode.ptr.p_int[sidx] = nodeidx;
30783 : }
30784 : }
30785 :
30786 : /*
30787 : * Allocate supernodal storage
30788 : */
30789 0 : ivectorsetlengthatleast(&analysis->rowoffsets, analysis->nsuper+1, _state);
30790 0 : ivectorsetlengthatleast(&analysis->rowstrides, analysis->nsuper, _state);
30791 0 : analysis->rowoffsets.ptr.p_int[0] = 0;
30792 0 : for(i=0; i<=analysis->nsuper-1; i++)
30793 : {
30794 0 : blocksize = analysis->supercolrange.ptr.p_int[i+1]-analysis->supercolrange.ptr.p_int[i];
30795 0 : analysis->rowstrides.ptr.p_int[i] = spchol_recommendedstridefor(blocksize, _state);
30796 0 : analysis->rowoffsets.ptr.p_int[i+1] = analysis->rowoffsets.ptr.p_int[i];
30797 0 : analysis->rowoffsets.ptr.p_int[i+1] = analysis->rowoffsets.ptr.p_int[i+1]+analysis->rowstrides.ptr.p_int[i]*blocksize;
30798 0 : analysis->rowoffsets.ptr.p_int[i+1] = analysis->rowoffsets.ptr.p_int[i+1]+analysis->rowstrides.ptr.p_int[i]*(analysis->superrowridx.ptr.p_int[i+1]-analysis->superrowridx.ptr.p_int[i]);
30799 0 : analysis->rowoffsets.ptr.p_int[i+1] = spchol_alignpositioninarray(analysis->rowoffsets.ptr.p_int[i+1], _state);
30800 : }
30801 :
30802 : /*
30803 : * Analyze output structure
30804 : */
30805 0 : isetallocv(n, 0, &analysis->outrowcounts, _state);
30806 0 : for(sidx=0; sidx<=nsuper-1; sidx++)
30807 : {
30808 0 : cols0 = analysis->supercolrange.ptr.p_int[sidx];
30809 0 : cols1 = analysis->supercolrange.ptr.p_int[sidx+1];
30810 0 : rfirst = analysis->superrowridx.ptr.p_int[sidx];
30811 0 : rlast = analysis->superrowridx.ptr.p_int[sidx+1];
30812 0 : blocksize = cols1-cols0;
30813 0 : for(j=cols0; j<=cols1-1; j++)
30814 : {
30815 0 : analysis->outrowcounts.ptr.p_int[j] = analysis->outrowcounts.ptr.p_int[j]+(j-cols0+1);
30816 : }
30817 0 : for(ii=rfirst; ii<=rlast-1; ii++)
30818 : {
30819 0 : i0 = analysis->superrowidx.ptr.p_int[ii];
30820 0 : analysis->outrowcounts.ptr.p_int[i0] = analysis->outrowcounts.ptr.p_int[i0]+blocksize;
30821 : }
30822 : }
30823 0 : }
30824 :
30825 :
30826 : /*************************************************************************
30827 : This function analyzes supernodal structure and precomputes dependency
30828 : matrix LAdj+
30829 :
30830 : INPUT PARAMETERS
30831 : Analysis - analysis object with completely initialized supernodal
30832 : structure
30833 : RawA - original (before reordering) input matrix
30834 : Node2Supernode- mapping from node to supernode indexes
30835 : N - problem size
30836 :
30837 : tTmp0,
30838 : tTmp1,
30839 : tFlagArray - temporary arrays, length at least N+1, simply provide
30840 : preallocated place.
30841 :
30842 : OUTPUT PARAMETERS
30843 : Analysis - following fields are initialized:
30844 : * Analysis.LAdjPlus
30845 : * Analysis.LAdjPlusR
30846 : Node2Supernode- array[N] that maps node indexes to supernode indexes
30847 :
30848 : -- ALGLIB PROJECT --
30849 : Copyright 05.10.2020 by Bochkanov Sergey.
30850 : *************************************************************************/
30851 0 : static void spchol_analyzesupernodaldependencies(spcholanalysis* analysis,
30852 : sparsematrix* rawa,
30853 : /* Integer */ ae_vector* node2supernode,
30854 : ae_int_t n,
30855 : /* Integer */ ae_vector* ttmp0,
30856 : /* Integer */ ae_vector* ttmp1,
30857 : /* Boolean */ ae_vector* tflagarray,
30858 : ae_state *_state)
30859 : {
30860 : ae_int_t i;
30861 : ae_int_t j;
30862 : ae_int_t rowidx;
30863 : ae_int_t j0;
30864 : ae_int_t j1;
30865 : ae_int_t jj;
30866 : ae_int_t rfirst;
30867 : ae_int_t rlast;
30868 : ae_int_t sidx;
30869 : ae_int_t uidx;
30870 : ae_int_t dbgrank1nodes;
30871 : ae_int_t dbgrank2nodes;
30872 : ae_int_t dbgrank3nodes;
30873 : ae_int_t dbgrank4nodes;
30874 : ae_int_t dbgbignodes;
30875 : double dbgtotalflop;
30876 : double dbgnoscatterflop;
30877 : double dbgnorowscatterflop;
30878 : double dbgnocolscatterflop;
30879 : double dbgcholeskyflop;
30880 : double dbgcholesky4flop;
30881 : double dbgrank1flop;
30882 : double dbgrank4plusflop;
30883 : double dbg444flop;
30884 : double dbgxx4flop;
30885 : double uflop;
30886 : ae_int_t wrkrow;
30887 : ae_int_t offdiagrow;
30888 : ae_int_t lastrow;
30889 : ae_int_t uwidth;
30890 : ae_int_t uheight;
30891 : ae_int_t urank;
30892 : ae_int_t theight;
30893 : ae_int_t twidth;
30894 :
30895 :
30896 0 : ae_assert(ttmp0->cnt>=n+1, "AnalyzeSupernodalDependencies: input buffer tTmp0 is too short", _state);
30897 0 : ae_assert(ttmp1->cnt>=n+1, "AnalyzeSupernodalDependencies: input buffer tTmp1 is too short", _state);
30898 0 : ae_assert(tflagarray->cnt>=n+1, "AnalyzeSupernodalDependencies: input buffer tTmp0 is too short", _state);
30899 0 : ae_assert(sparseiscrs(rawa, _state), "AnalyzeSupernodalDependencies: RawA must be CRS matrix", _state);
30900 :
30901 : /*
30902 : * Determine LAdjPlus - supernodes feeding updates to the SIdx-th one.
30903 : *
30904 : * Without supernodes we have: K-th row of L (also denoted as ladj+(K))
30905 : * includes original nonzeros from A (also denoted as ladj(K)) as well
30906 : * as all elements on paths in elimination tree from ladj(K) to K.
30907 : *
30908 : * With supernodes: same principle applied.
30909 : */
30910 0 : isetallocv(analysis->nsuper+1, 0, &analysis->ladjplusr, _state);
30911 0 : bsetv(n, ae_true, tflagarray, _state);
30912 0 : analysis->ladjplusr.ptr.p_int[0] = 0;
30913 0 : for(sidx=0; sidx<=analysis->nsuper-1; sidx++)
30914 : {
30915 :
30916 : /*
30917 : * Generate list of nodes feeding updates to SIdx-th one
30918 : */
30919 0 : ivectorgrowto(&analysis->ladjplus, analysis->ladjplusr.ptr.p_int[sidx]+analysis->nsuper, _state);
30920 0 : rfirst = analysis->ladjplusr.ptr.p_int[sidx];
30921 0 : rlast = rfirst;
30922 0 : for(rowidx=analysis->supercolrange.ptr.p_int[sidx]; rowidx<=analysis->supercolrange.ptr.p_int[sidx+1]-1; rowidx++)
30923 : {
30924 0 : i = analysis->invsuperperm.ptr.p_int[rowidx];
30925 0 : j0 = rawa->ridx.ptr.p_int[i];
30926 0 : j1 = rawa->uidx.ptr.p_int[i]-1;
30927 0 : for(jj=j0; jj<=j1; jj++)
30928 : {
30929 0 : j = node2supernode->ptr.p_int[analysis->superperm.ptr.p_int[rawa->idx.ptr.p_int[jj]]];
30930 0 : if( j<sidx&&tflagarray->ptr.p_bool[j] )
30931 : {
30932 0 : analysis->ladjplus.ptr.p_int[rlast] = j;
30933 0 : tflagarray->ptr.p_bool[j] = ae_false;
30934 0 : rlast = rlast+1;
30935 0 : j = analysis->parentsupernode.ptr.p_int[j];
30936 0 : while((j>=0&&j<sidx)&&tflagarray->ptr.p_bool[j])
30937 : {
30938 0 : analysis->ladjplus.ptr.p_int[rlast] = j;
30939 0 : tflagarray->ptr.p_bool[j] = ae_false;
30940 0 : rlast = rlast+1;
30941 0 : j = analysis->parentsupernode.ptr.p_int[j];
30942 : }
30943 : }
30944 : }
30945 : }
30946 0 : for(i=rfirst; i<=rlast-1; i++)
30947 : {
30948 0 : tflagarray->ptr.p_bool[analysis->ladjplus.ptr.p_int[i]] = ae_true;
30949 : }
30950 0 : analysis->ladjplusr.ptr.p_int[sidx+1] = rlast;
30951 : }
30952 :
30953 : /*
30954 : * Analyze statistics for trace output
30955 : */
30956 0 : if( analysis->dotrace )
30957 : {
30958 0 : ae_trace("=== ANALYZING SUPERNODAL DEPENDENCIES ==============================================================\n");
30959 0 : dbgrank1nodes = 0;
30960 0 : dbgrank2nodes = 0;
30961 0 : dbgrank3nodes = 0;
30962 0 : dbgrank4nodes = 0;
30963 0 : dbgbignodes = 0;
30964 0 : dbgtotalflop = (double)(0);
30965 0 : dbgnoscatterflop = (double)(0);
30966 0 : dbgnorowscatterflop = (double)(0);
30967 0 : dbgnocolscatterflop = (double)(0);
30968 0 : dbgrank1flop = (double)(0);
30969 0 : dbgrank4plusflop = (double)(0);
30970 0 : dbg444flop = (double)(0);
30971 0 : dbgxx4flop = (double)(0);
30972 0 : dbgcholeskyflop = (double)(0);
30973 0 : dbgcholesky4flop = (double)(0);
30974 0 : isetv(analysis->nsuper, 0, ttmp0, _state);
30975 0 : for(sidx=0; sidx<=analysis->nsuper-1; sidx++)
30976 : {
30977 :
30978 : /*
30979 : * Node sizes
30980 : */
30981 0 : if( analysis->supercolrange.ptr.p_int[sidx+1]-analysis->supercolrange.ptr.p_int[sidx]==1 )
30982 : {
30983 0 : inc(&dbgrank1nodes, _state);
30984 : }
30985 0 : if( analysis->supercolrange.ptr.p_int[sidx+1]-analysis->supercolrange.ptr.p_int[sidx]==2 )
30986 : {
30987 0 : inc(&dbgrank2nodes, _state);
30988 : }
30989 0 : if( analysis->supercolrange.ptr.p_int[sidx+1]-analysis->supercolrange.ptr.p_int[sidx]==3 )
30990 : {
30991 0 : inc(&dbgrank3nodes, _state);
30992 : }
30993 0 : if( analysis->supercolrange.ptr.p_int[sidx+1]-analysis->supercolrange.ptr.p_int[sidx]==4 )
30994 : {
30995 0 : inc(&dbgrank4nodes, _state);
30996 : }
30997 0 : if( analysis->supercolrange.ptr.p_int[sidx+1]-analysis->supercolrange.ptr.p_int[sidx]>4 )
30998 : {
30999 0 : inc(&dbgbignodes, _state);
31000 : }
31001 :
31002 : /*
31003 : * FLOP counts
31004 : */
31005 0 : twidth = analysis->supercolrange.ptr.p_int[sidx+1]-analysis->supercolrange.ptr.p_int[sidx];
31006 0 : theight = twidth+(analysis->superrowridx.ptr.p_int[sidx+1]-analysis->superrowridx.ptr.p_int[sidx]);
31007 0 : for(i=analysis->ladjplusr.ptr.p_int[sidx]; i<=analysis->ladjplusr.ptr.p_int[sidx+1]-1; i++)
31008 : {
31009 0 : uidx = analysis->ladjplus.ptr.p_int[i];
31010 :
31011 : /*
31012 : * Determine update width, height, rank
31013 : */
31014 0 : wrkrow = ttmp0->ptr.p_int[uidx];
31015 0 : offdiagrow = wrkrow;
31016 0 : lastrow = analysis->superrowridx.ptr.p_int[uidx+1]-analysis->superrowridx.ptr.p_int[uidx];
31017 0 : while(offdiagrow<lastrow&&analysis->superrowidx.ptr.p_int[analysis->superrowridx.ptr.p_int[uidx]+offdiagrow]<analysis->supercolrange.ptr.p_int[sidx+1])
31018 : {
31019 0 : offdiagrow = offdiagrow+1;
31020 : }
31021 0 : uwidth = offdiagrow-wrkrow;
31022 0 : uheight = lastrow-wrkrow;
31023 0 : urank = analysis->supercolrange.ptr.p_int[uidx+1]-analysis->supercolrange.ptr.p_int[uidx];
31024 0 : ttmp0->ptr.p_int[uidx] = offdiagrow;
31025 :
31026 : /*
31027 : * Compute update FLOP cost
31028 : */
31029 0 : uflop = rmul3((double)(uwidth), (double)(uheight), (double)(urank), _state);
31030 0 : dbgtotalflop = dbgtotalflop+uflop;
31031 0 : if( uheight==theight&&uwidth==twidth )
31032 : {
31033 0 : dbgnoscatterflop = dbgnoscatterflop+uflop;
31034 : }
31035 0 : if( uheight==theight )
31036 : {
31037 0 : dbgnorowscatterflop = dbgnorowscatterflop+uflop;
31038 : }
31039 0 : if( uwidth==twidth )
31040 : {
31041 0 : dbgnocolscatterflop = dbgnocolscatterflop+uflop;
31042 : }
31043 0 : if( urank==1 )
31044 : {
31045 0 : dbgrank1flop = dbgrank1flop+uflop;
31046 : }
31047 0 : if( urank>=4 )
31048 : {
31049 0 : dbgrank4plusflop = dbgrank4plusflop+uflop;
31050 : }
31051 0 : if( (urank==4&&uwidth==4)&&twidth==4 )
31052 : {
31053 0 : dbg444flop = dbg444flop+uflop;
31054 : }
31055 0 : if( twidth==4 )
31056 : {
31057 0 : dbgxx4flop = dbgxx4flop+uflop;
31058 : }
31059 : }
31060 0 : uflop = (double)(0);
31061 0 : for(i=0; i<=twidth-1; i++)
31062 : {
31063 0 : uflop = uflop+(theight-i)*i+(theight-i);
31064 : }
31065 0 : dbgtotalflop = dbgtotalflop+uflop;
31066 0 : dbgcholeskyflop = dbgcholeskyflop+uflop;
31067 0 : if( twidth==4 )
31068 : {
31069 0 : dbgcholesky4flop = dbgcholesky4flop+uflop;
31070 : }
31071 : }
31072 :
31073 : /*
31074 : * Output
31075 : */
31076 0 : ae_trace("> node size statistics:\n");
31077 0 : ae_trace("rank1 = %6d\n",
31078 : (int)(dbgrank1nodes));
31079 0 : ae_trace("rank2 = %6d\n",
31080 : (int)(dbgrank2nodes));
31081 0 : ae_trace("rank3 = %6d\n",
31082 : (int)(dbgrank3nodes));
31083 0 : ae_trace("rank4 = %6d\n",
31084 : (int)(dbgrank4nodes));
31085 0 : ae_trace("big nodes = %6d\n",
31086 : (int)(dbgbignodes));
31087 0 : ae_trace("> Total FLOP count (fused multiply-adds):\n");
31088 0 : ae_trace("total = %8.2f MFLOP\n",
31089 : (double)(1.0E-6*dbgtotalflop));
31090 0 : ae_trace("> FLOP counts for updates:\n");
31091 0 : ae_trace("no-sctr = %8.2f MFLOP (no row scatter, no col scatter, best case)\n",
31092 : (double)(1.0E-6*dbgnoscatterflop));
31093 0 : ae_trace("M4*44->N4 = %8.2f MFLOP (no col scatter, big blocks, good case)\n",
31094 : (double)(1.0E-6*dbg444flop));
31095 0 : ae_trace("no-row-sctr = %8.2f MFLOP (no row scatter, good case for col-wise storage)\n",
31096 : (double)(1.0E-6*dbgnorowscatterflop));
31097 0 : ae_trace("no-col-sctr = %8.2f MFLOP (no col scatter, good case for row-wise storage)\n",
31098 : (double)(1.0E-6*dbgnocolscatterflop));
31099 0 : ae_trace("XX*XX->N4 = %8.2f MFLOP\n",
31100 : (double)(1.0E-6*dbgxx4flop));
31101 0 : ae_trace("rank1 = %8.2f MFLOP\n",
31102 : (double)(1.0E-6*dbgrank1flop));
31103 0 : ae_trace("rank4+ = %8.2f MFLOP\n",
31104 : (double)(1.0E-6*dbgrank4plusflop));
31105 0 : ae_trace("> FLOP counts for Cholesky:\n");
31106 0 : ae_trace("cholesky = %8.2f MFLOP\n",
31107 : (double)(1.0E-6*dbgcholeskyflop));
31108 0 : ae_trace("cholesky4 = %8.2f MFLOP\n",
31109 : (double)(1.0E-6*dbgcholesky4flop));
31110 : }
31111 0 : }
31112 :
31113 :
31114 : /*************************************************************************
31115 : This function extracts computed matrix from the supernodal storage.
31116 : Depending on settings, a supernodal permutation can be applied to the matrix.
31117 :
31118 : INPUT PARAMETERS
31119 : Analysis - analysis object with completely initialized supernodal
31120 : structure
31121 : Offsets - offsets for supernodal storage
31122 : Strides - row strides for supernodal storage
31123 : RowStorage - supernodal storage
31124 : DiagD - diagonal factor
31125 : N - problem size
31126 :
31127 : TmpP - preallocated temporary array[N+1]
31128 :
31129 : OUTPUT PARAMETERS
31130 : A - sparse matrix in CRS format:
31131 : * for PermType=0, sparse matrix in the original ordering
31132 : (i.e. the matrix is reordered prior to output that
31133 : may require considerable amount of operations due to
31134 : permutation being applied)
31135 : * for PermType=1, sparse matrix in the topological
31136 : ordering. The least overhead for output.
31137 : D - array[N], diagonal
31138 : P - output permutation in product form
31139 :
31140 : -- ALGLIB PROJECT --
31141 : Copyright 05.10.2020 by Bochkanov Sergey.
31142 : *************************************************************************/
31143 0 : static void spchol_extractmatrix(spcholanalysis* analysis,
31144 : /* Integer */ ae_vector* offsets,
31145 : /* Integer */ ae_vector* strides,
31146 : /* Real */ ae_vector* rowstorage,
31147 : /* Real */ ae_vector* diagd,
31148 : ae_int_t n,
31149 : sparsematrix* a,
31150 : /* Real */ ae_vector* d,
31151 : /* Integer */ ae_vector* p,
31152 : /* Integer */ ae_vector* tmpp,
31153 : ae_state *_state)
31154 : {
31155 : ae_int_t i;
31156 : ae_int_t j;
31157 : ae_int_t k;
31158 : ae_int_t sidx;
31159 : ae_int_t i0;
31160 : ae_int_t ii;
31161 : ae_int_t rfirst;
31162 : ae_int_t rlast;
31163 : ae_int_t cols0;
31164 : ae_int_t cols1;
31165 : ae_int_t blocksize;
31166 : ae_int_t rowstride;
31167 : ae_int_t offdiagsize;
31168 : ae_int_t offssdiag;
31169 :
31170 :
31171 0 : ae_assert(tmpp->cnt>=n+1, "ExtractMatrix: preallocated temporary TmpP is too short", _state);
31172 :
31173 : /*
31174 : * Basic initialization
31175 : */
31176 0 : a->matrixtype = 1;
31177 0 : a->n = n;
31178 0 : a->m = n;
31179 :
31180 : /*
31181 : * Various permutation types
31182 : */
31183 0 : if( analysis->applypermutationtooutput )
31184 : {
31185 0 : ae_assert(analysis->istopologicalordering, "ExtractMatrix: critical integrity check failed (attempt to merge in nontopological permutation)", _state);
31186 :
31187 : /*
31188 : * Output matrix is topologically permuted, so we return A=L*L' instead of A=P*L*L'*P'.
31189 : * Somewhat inefficient because we have to apply permutation to L returned by supernodal code.
31190 : */
31191 0 : ivectorsetlengthatleast(&a->ridx, n+1, _state);
31192 0 : ivectorsetlengthatleast(&a->didx, n, _state);
31193 0 : a->ridx.ptr.p_int[0] = 0;
31194 0 : for(i=0; i<=n-1; i++)
31195 : {
31196 0 : a->ridx.ptr.p_int[i+1] = a->ridx.ptr.p_int[i]+analysis->outrowcounts.ptr.p_int[analysis->effectiveperm.ptr.p_int[i]];
31197 : }
31198 0 : for(i=0; i<=n-1; i++)
31199 : {
31200 0 : a->didx.ptr.p_int[i] = a->ridx.ptr.p_int[i];
31201 : }
31202 0 : a->ninitialized = a->ridx.ptr.p_int[n];
31203 0 : rvectorsetlengthatleast(&a->vals, a->ninitialized, _state);
31204 0 : ivectorsetlengthatleast(&a->idx, a->ninitialized, _state);
31205 0 : for(sidx=0; sidx<=analysis->nsuper-1; sidx++)
31206 : {
31207 0 : cols0 = analysis->supercolrange.ptr.p_int[sidx];
31208 0 : cols1 = analysis->supercolrange.ptr.p_int[sidx+1];
31209 0 : rfirst = analysis->superrowridx.ptr.p_int[sidx];
31210 0 : rlast = analysis->superrowridx.ptr.p_int[sidx+1];
31211 0 : blocksize = cols1-cols0;
31212 0 : offdiagsize = rlast-rfirst;
31213 0 : rowstride = strides->ptr.p_int[sidx];
31214 0 : offssdiag = offsets->ptr.p_int[sidx];
31215 0 : for(i=0; i<=blocksize-1; i++)
31216 : {
31217 0 : i0 = analysis->inveffectiveperm.ptr.p_int[cols0+i];
31218 0 : ii = a->didx.ptr.p_int[i0];
31219 0 : for(j=0; j<=i; j++)
31220 : {
31221 0 : a->idx.ptr.p_int[ii] = analysis->inveffectiveperm.ptr.p_int[cols0+j];
31222 0 : a->vals.ptr.p_double[ii] = rowstorage->ptr.p_double[offssdiag+i*rowstride+j];
31223 0 : ii = ii+1;
31224 : }
31225 0 : a->didx.ptr.p_int[i0] = ii;
31226 : }
31227 0 : for(k=0; k<=offdiagsize-1; k++)
31228 : {
31229 0 : i0 = analysis->inveffectiveperm.ptr.p_int[analysis->superrowidx.ptr.p_int[k+rfirst]];
31230 0 : ii = a->didx.ptr.p_int[i0];
31231 0 : for(j=0; j<=blocksize-1; j++)
31232 : {
31233 0 : a->idx.ptr.p_int[ii] = analysis->inveffectiveperm.ptr.p_int[cols0+j];
31234 0 : a->vals.ptr.p_double[ii] = rowstorage->ptr.p_double[offssdiag+(blocksize+k)*rowstride+j];
31235 0 : ii = ii+1;
31236 : }
31237 0 : a->didx.ptr.p_int[i0] = ii;
31238 : }
31239 : }
31240 0 : for(i=0; i<=n-1; i++)
31241 : {
31242 0 : ae_assert(a->didx.ptr.p_int[i]==a->ridx.ptr.p_int[i+1], "ExtractMatrix: integrity check failed (9473t)", _state);
31243 0 : tagsortmiddleir(&a->idx, &a->vals, a->ridx.ptr.p_int[i], a->ridx.ptr.p_int[i+1]-a->ridx.ptr.p_int[i], _state);
31244 0 : ae_assert(a->idx.ptr.p_int[a->ridx.ptr.p_int[i+1]-1]==i, "ExtractMatrix: integrity check failed (e4tfd)", _state);
31245 : }
31246 0 : sparseinitduidx(a, _state);
31247 :
31248 : /*
31249 : * Prepare D[] and P[]
31250 : */
31251 0 : rvectorsetlengthatleast(d, n, _state);
31252 0 : ivectorsetlengthatleast(p, n, _state);
31253 0 : for(i=0; i<=n-1; i++)
31254 : {
31255 0 : d->ptr.p_double[i] = diagd->ptr.p_double[analysis->effectiveperm.ptr.p_int[i]];
31256 0 : p->ptr.p_int[i] = i;
31257 : }
31258 : }
31259 : else
31260 : {
31261 :
31262 : /*
31263 : * The permutation is NOT applied to L prior to extraction,
31264 : * we return both L and P: A=P*L*L'*P'.
31265 : */
31266 0 : ivectorsetlengthatleast(&a->ridx, n+1, _state);
31267 0 : ivectorsetlengthatleast(&a->didx, n, _state);
31268 0 : a->ridx.ptr.p_int[0] = 0;
31269 0 : for(i=0; i<=n-1; i++)
31270 : {
31271 0 : a->ridx.ptr.p_int[i+1] = a->ridx.ptr.p_int[i]+analysis->outrowcounts.ptr.p_int[i];
31272 : }
31273 0 : for(i=0; i<=n-1; i++)
31274 : {
31275 0 : a->didx.ptr.p_int[i] = a->ridx.ptr.p_int[i];
31276 : }
31277 0 : a->ninitialized = a->ridx.ptr.p_int[n];
31278 0 : rvectorsetlengthatleast(&a->vals, a->ninitialized, _state);
31279 0 : ivectorsetlengthatleast(&a->idx, a->ninitialized, _state);
31280 0 : for(sidx=0; sidx<=analysis->nsuper-1; sidx++)
31281 : {
31282 0 : cols0 = analysis->supercolrange.ptr.p_int[sidx];
31283 0 : cols1 = analysis->supercolrange.ptr.p_int[sidx+1];
31284 0 : rfirst = analysis->superrowridx.ptr.p_int[sidx];
31285 0 : rlast = analysis->superrowridx.ptr.p_int[sidx+1];
31286 0 : blocksize = cols1-cols0;
31287 0 : offdiagsize = rlast-rfirst;
31288 0 : rowstride = strides->ptr.p_int[sidx];
31289 0 : offssdiag = offsets->ptr.p_int[sidx];
31290 0 : for(i=0; i<=blocksize-1; i++)
31291 : {
31292 0 : i0 = cols0+i;
31293 0 : ii = a->didx.ptr.p_int[i0];
31294 0 : for(j=0; j<=i; j++)
31295 : {
31296 0 : a->idx.ptr.p_int[ii] = cols0+j;
31297 0 : a->vals.ptr.p_double[ii] = rowstorage->ptr.p_double[offssdiag+i*rowstride+j];
31298 0 : ii = ii+1;
31299 : }
31300 0 : a->didx.ptr.p_int[i0] = ii;
31301 : }
31302 0 : for(k=0; k<=offdiagsize-1; k++)
31303 : {
31304 0 : i0 = analysis->superrowidx.ptr.p_int[k+rfirst];
31305 0 : ii = a->didx.ptr.p_int[i0];
31306 0 : for(j=0; j<=blocksize-1; j++)
31307 : {
31308 0 : a->idx.ptr.p_int[ii] = cols0+j;
31309 0 : a->vals.ptr.p_double[ii] = rowstorage->ptr.p_double[offssdiag+(blocksize+k)*rowstride+j];
31310 0 : ii = ii+1;
31311 : }
31312 0 : a->didx.ptr.p_int[i0] = ii;
31313 : }
31314 : }
31315 0 : for(i=0; i<=n-1; i++)
31316 : {
31317 0 : ae_assert(a->didx.ptr.p_int[i]==a->ridx.ptr.p_int[i+1], "ExtractMatrix: integrity check failed (34e43)", _state);
31318 0 : ae_assert(a->idx.ptr.p_int[a->ridx.ptr.p_int[i+1]-1]==i, "ExtractMatrix: integrity check failed (k4df5)", _state);
31319 : }
31320 0 : sparseinitduidx(a, _state);
31321 :
31322 : /*
31323 : * Extract diagonal
31324 : */
31325 0 : rvectorsetlengthatleast(d, n, _state);
31326 0 : for(i=0; i<=n-1; i++)
31327 : {
31328 0 : d->ptr.p_double[i] = diagd->ptr.p_double[i];
31329 : }
31330 :
31331 : /*
31332 : * Convert permutation table into product form
31333 : */
31334 0 : ivectorsetlengthatleast(p, n, _state);
31335 0 : for(i=0; i<=n-1; i++)
31336 : {
31337 0 : p->ptr.p_int[i] = i;
31338 0 : tmpp->ptr.p_int[i] = i;
31339 : }
31340 0 : for(i=0; i<=n-1; i++)
31341 : {
31342 :
31343 : /*
31344 : * We need to move element K to position I.
31345 : * J is where K actually stored
31346 : */
31347 0 : k = analysis->inveffectiveperm.ptr.p_int[i];
31348 0 : j = tmpp->ptr.p_int[k];
31349 :
31350 : /*
31351 : * Swap elements of P[I:N-1] that is used to store current locations of elements in different way
31352 : */
31353 0 : i0 = p->ptr.p_int[i];
31354 0 : p->ptr.p_int[i] = p->ptr.p_int[j];
31355 0 : p->ptr.p_int[j] = i0;
31356 :
31357 : /*
31358 : * record pivoting of positions I and J
31359 : */
31360 0 : p->ptr.p_int[i] = j;
31361 0 : tmpp->ptr.p_int[i0] = j;
31362 : }
31363 : }
31364 0 : }
31365 :
31366 :
31367 : /*************************************************************************
31368 : This function is a specialized version of SparseSymmPermTbl() that takes
31369 : into account specifics of topological reorderings (improves performance)
31370 : and additionally transposes its output.
31371 :
31372 : INPUT PARAMETERS
31373 : A - sparse lower triangular matrix in CRS format.
31374 : P - array[N] which stores permutation table; P[I]=J means
31375 : that I-th row/column of matrix A is moved to J-th
31376 : position. For performance reasons we do NOT check that
31377 : P[] is a correct permutation (that there is no
31378 : repetitions, just that all its elements are in [0,N)
31379 : range.
31380 : B - sparse matrix object that will hold output.
31381 : Previously allocated memory will be reused as much as
31382 : possible.
31383 :
31384 : OUTPUT PARAMETERS
31385 : B - permuted and transposed upper triangular matrix in the
31386 : special internal CRS-like matrix format (MatrixType=-10082).
31387 :
31388 : -- ALGLIB PROJECT --
31389 : Copyright 05.10.2020 by Bochkanov Sergey.
31390 : *************************************************************************/
31391 0 : static void spchol_topologicalpermutation(sparsematrix* a,
31392 : /* Integer */ ae_vector* p,
31393 : sparsematrix* b,
31394 : ae_state *_state)
31395 : {
31396 : ae_int_t i;
31397 : ae_int_t j;
31398 : ae_int_t jj;
31399 : ae_int_t j0;
31400 : ae_int_t j1;
31401 : ae_int_t k;
31402 : ae_int_t k0;
31403 : ae_int_t n;
31404 : ae_bool bflag;
31405 :
31406 :
31407 0 : ae_assert(a->matrixtype==1, "TopologicalPermutation: incorrect matrix type (convert your matrix to CRS)", _state);
31408 0 : ae_assert(p->cnt>=a->n, "TopologicalPermutation: Length(P)<N", _state);
31409 0 : ae_assert(a->m==a->n, "TopologicalPermutation: matrix is non-square", _state);
31410 0 : ae_assert(a->ninitialized==a->ridx.ptr.p_int[a->n], "TopologicalPermutation: integrity check failed", _state);
31411 0 : bflag = ae_true;
31412 0 : n = a->n;
31413 0 : for(i=0; i<=n-1; i++)
31414 : {
31415 0 : j = p->ptr.p_int[i];
31416 0 : bflag = (bflag&&j>=0)&&j<n;
31417 : }
31418 0 : ae_assert(bflag, "TopologicalPermutation: P[] contains values outside of [0,N) range", _state);
31419 :
31420 : /*
31421 : * Prepare output
31422 : */
31423 0 : b->matrixtype = -10082;
31424 0 : b->n = n;
31425 0 : b->m = n;
31426 0 : ivectorsetlengthatleast(&b->didx, n, _state);
31427 0 : ivectorsetlengthatleast(&b->uidx, n, _state);
31428 :
31429 : /*
31430 : * Determine row sizes (temporary stored in DIdx) and ranges
31431 : */
31432 0 : isetv(n, 0, &b->uidx, _state);
31433 0 : for(i=0; i<=n-1; i++)
31434 : {
31435 0 : j0 = a->ridx.ptr.p_int[i];
31436 0 : j1 = a->uidx.ptr.p_int[i]-1;
31437 0 : for(jj=j0; jj<=j1; jj++)
31438 : {
31439 0 : j = a->idx.ptr.p_int[jj];
31440 0 : b->uidx.ptr.p_int[j] = b->uidx.ptr.p_int[j]+1;
31441 : }
31442 : }
31443 0 : for(i=0; i<=n-1; i++)
31444 : {
31445 0 : b->didx.ptr.p_int[p->ptr.p_int[i]] = b->uidx.ptr.p_int[i];
31446 : }
31447 0 : ivectorsetlengthatleast(&b->ridx, n+1, _state);
31448 0 : b->ridx.ptr.p_int[0] = 0;
31449 0 : for(i=0; i<=n-1; i++)
31450 : {
31451 0 : b->ridx.ptr.p_int[i+1] = b->ridx.ptr.p_int[i]+b->didx.ptr.p_int[i];
31452 0 : b->uidx.ptr.p_int[i] = b->ridx.ptr.p_int[i];
31453 : }
31454 0 : b->ninitialized = b->ridx.ptr.p_int[n];
31455 0 : ivectorsetlengthatleast(&b->idx, b->ninitialized, _state);
31456 0 : rvectorsetlengthatleast(&b->vals, b->ninitialized, _state);
31457 :
31458 : /*
31459 : * Process matrix
31460 : */
31461 0 : for(i=0; i<=n-1; i++)
31462 : {
31463 0 : j0 = a->ridx.ptr.p_int[i];
31464 0 : j1 = a->uidx.ptr.p_int[i]-1;
31465 0 : k = p->ptr.p_int[i];
31466 0 : for(jj=j0; jj<=j1; jj++)
31467 : {
31468 0 : j = p->ptr.p_int[a->idx.ptr.p_int[jj]];
31469 0 : k0 = b->uidx.ptr.p_int[j];
31470 0 : b->idx.ptr.p_int[k0] = k;
31471 0 : b->vals.ptr.p_double[k0] = a->vals.ptr.p_double[jj];
31472 0 : b->uidx.ptr.p_int[j] = k0+1;
31473 : }
31474 : }
31475 0 : }
31476 :
31477 :
31478 : /*************************************************************************
31479 : Determine nonzero pattern of the column.
31480 :
31481 : This function takes as input:
31482 : * A^T - transpose of original input matrix
31483 : * index of column of L being computed
31484 : * SuperRowRIdx[] and SuperRowIdx[] - arrays that store row structure of
31485 : supernodes, and NSuper - supernodes count
31486 : * ChildrenNodesR[], ChildrenNodesI[] - arrays that store children nodes
31487 : for each node
31488 : * Node2Supernode[] - array that maps node indexes to supernodes
31489 : * TrueArray[] - array[N] that has all of its elements set to True (this
31490 : invariant is preserved on output)
31491 : * Tmp0[] - array[N], temporary array
31492 :
31493 : As output, it constructs nonzero pattern (diagonal element not included)
31494 : of the column #ColumnIdx on top of SuperRowIdx[] array, starting at
31495 : location SuperRowIdx[SuperRowRIdx[NSuper]] and till location
31496 : SuperRowIdx[Result-1], where Result is a function result.
31497 :
31498 : The SuperRowIdx[] array is automatically resized as needed.
31499 :
31500 : It is important that this function computes nonzero pattern, but it does
31501 : NOT change other supernodal structures. The caller still has to finalize
31502 : the column (setup supernode ranges, mappings, etc).
31503 :
31504 : -- ALGLIB routine --
31505 : 20.09.2020
31506 : Bochkanov Sergey
31507 : *************************************************************************/
31508 0 : static ae_int_t spchol_computenonzeropattern(sparsematrix* wrkat,
31509 : ae_int_t columnidx,
31510 : ae_int_t n,
31511 : /* Integer */ ae_vector* superrowridx,
31512 : /* Integer */ ae_vector* superrowidx,
31513 : ae_int_t nsuper,
31514 : /* Integer */ ae_vector* childrennodesr,
31515 : /* Integer */ ae_vector* childrennodesi,
31516 : /* Integer */ ae_vector* node2supernode,
31517 : /* Boolean */ ae_vector* truearray,
31518 : /* Integer */ ae_vector* tmp0,
31519 : ae_state *_state)
31520 : {
31521 : ae_int_t i;
31522 : ae_int_t ii;
31523 : ae_int_t jj;
31524 : ae_int_t i0;
31525 : ae_int_t i1;
31526 : ae_int_t j0;
31527 : ae_int_t j1;
31528 : ae_int_t cidx;
31529 : ae_int_t rfirst;
31530 : ae_int_t rlast;
31531 : ae_int_t tfirst;
31532 : ae_int_t tlast;
31533 : ae_int_t supernodalchildrencount;
31534 : ae_int_t result;
31535 :
31536 :
31537 0 : ae_assert(truearray->cnt>=n, "ComputeNonzeroPattern: input temporary is too short", _state);
31538 0 : ae_assert(tmp0->cnt>=n, "ComputeNonzeroPattern: input temporary is too short", _state);
31539 :
31540 : /*
31541 : * Determine supernodal children in Tmp0
31542 : */
31543 0 : supernodalchildrencount = 0;
31544 0 : i0 = childrennodesr->ptr.p_int[columnidx];
31545 0 : i1 = childrennodesr->ptr.p_int[columnidx+1]-1;
31546 0 : for(ii=i0; ii<=i1; ii++)
31547 : {
31548 0 : i = node2supernode->ptr.p_int[childrennodesi->ptr.p_int[ii]];
31549 0 : if( truearray->ptr.p_bool[i] )
31550 : {
31551 0 : tmp0->ptr.p_int[supernodalchildrencount] = i;
31552 0 : truearray->ptr.p_bool[i] = ae_false;
31553 0 : supernodalchildrencount = supernodalchildrencount+1;
31554 : }
31555 : }
31556 0 : for(i=0; i<=supernodalchildrencount-1; i++)
31557 : {
31558 0 : truearray->ptr.p_bool[tmp0->ptr.p_int[i]] = ae_true;
31559 : }
31560 :
31561 : /*
31562 : * Initialized column by nonzero pattern from A
31563 : */
31564 0 : rfirst = superrowridx->ptr.p_int[nsuper];
31565 0 : tfirst = rfirst+n;
31566 0 : igrowv(rfirst+2*n, superrowidx, _state);
31567 0 : i0 = wrkat->ridx.ptr.p_int[columnidx]+1;
31568 0 : i1 = wrkat->ridx.ptr.p_int[columnidx+1];
31569 0 : icopyvx(i1-i0, &wrkat->idx, i0, superrowidx, rfirst, _state);
31570 0 : rlast = rfirst+(i1-i0);
31571 :
31572 : /*
31573 : * For column with small number of children use ordered merge algorithm.
31574 : * For column with many children it is better to perform unsorted merge,
31575 : * and then sort the sequence.
31576 : */
31577 0 : if( supernodalchildrencount<=4 )
31578 : {
31579 :
31580 : /*
31581 : * Ordered merge. The best approach for small number of children,
31582 : * but may have O(N^2) running time when O(N) children are present.
31583 : */
31584 0 : for(cidx=0; cidx<=supernodalchildrencount-1; cidx++)
31585 : {
31586 :
31587 : /*
31588 : * Skip initial elements that do not contribute to subdiagonal nonzero pattern
31589 : */
31590 0 : i0 = superrowridx->ptr.p_int[tmp0->ptr.p_int[cidx]];
31591 0 : i1 = superrowridx->ptr.p_int[tmp0->ptr.p_int[cidx]+1]-1;
31592 0 : while(i0<=i1&&superrowidx->ptr.p_int[i0]<=columnidx)
31593 : {
31594 0 : i0 = i0+1;
31595 : }
31596 0 : j0 = rfirst;
31597 0 : j1 = rlast-1;
31598 :
31599 : /*
31600 : * Handle degenerate cases: empty merge target or empty merge source.
31601 : */
31602 0 : if( j1<j0 )
31603 : {
31604 0 : icopyvx(i1-i0+1, superrowidx, i0, superrowidx, rlast, _state);
31605 0 : rlast = rlast+(i1-i0+1);
31606 0 : continue;
31607 : }
31608 0 : if( i1<i0 )
31609 : {
31610 0 : continue;
31611 : }
31612 :
31613 : /*
31614 : * General case: two non-empty sorted sequences given by [I0,I1] and [J0,J1],
31615 : * have to be merged and stored into [RFirst,RLast).
31616 : */
31617 0 : ii = superrowidx->ptr.p_int[i0];
31618 0 : jj = superrowidx->ptr.p_int[j0];
31619 0 : tlast = tfirst;
31620 : for(;;)
31621 : {
31622 0 : if( ii<jj )
31623 : {
31624 0 : superrowidx->ptr.p_int[tlast] = ii;
31625 0 : tlast = tlast+1;
31626 0 : i0 = i0+1;
31627 0 : if( i0>i1 )
31628 : {
31629 0 : break;
31630 : }
31631 0 : ii = superrowidx->ptr.p_int[i0];
31632 : }
31633 0 : if( jj<ii )
31634 : {
31635 0 : superrowidx->ptr.p_int[tlast] = jj;
31636 0 : tlast = tlast+1;
31637 0 : j0 = j0+1;
31638 0 : if( j0>j1 )
31639 : {
31640 0 : break;
31641 : }
31642 0 : jj = superrowidx->ptr.p_int[j0];
31643 : }
31644 0 : if( jj==ii )
31645 : {
31646 0 : superrowidx->ptr.p_int[tlast] = ii;
31647 0 : tlast = tlast+1;
31648 0 : i0 = i0+1;
31649 0 : j0 = j0+1;
31650 0 : if( i0>i1 )
31651 : {
31652 0 : break;
31653 : }
31654 0 : if( j0>j1 )
31655 : {
31656 0 : break;
31657 : }
31658 0 : ii = superrowidx->ptr.p_int[i0];
31659 0 : jj = superrowidx->ptr.p_int[j0];
31660 : }
31661 : }
31662 0 : for(ii=i0; ii<=i1; ii++)
31663 : {
31664 0 : superrowidx->ptr.p_int[tlast] = superrowidx->ptr.p_int[ii];
31665 0 : tlast = tlast+1;
31666 : }
31667 0 : for(jj=j0; jj<=j1; jj++)
31668 : {
31669 0 : superrowidx->ptr.p_int[tlast] = superrowidx->ptr.p_int[jj];
31670 0 : tlast = tlast+1;
31671 : }
31672 0 : icopyvx(tlast-tfirst, superrowidx, tfirst, superrowidx, rfirst, _state);
31673 0 : rlast = rfirst+(tlast-tfirst);
31674 : }
31675 0 : result = rlast;
31676 : }
31677 : else
31678 : {
31679 :
31680 : /*
31681 : * Unordered merge followed by sort. Guaranteed N*logN worst case.
31682 : */
31683 0 : for(ii=rfirst; ii<=rlast-1; ii++)
31684 : {
31685 0 : truearray->ptr.p_bool[superrowidx->ptr.p_int[ii]] = ae_false;
31686 : }
31687 0 : for(cidx=0; cidx<=supernodalchildrencount-1; cidx++)
31688 : {
31689 :
31690 : /*
31691 : * Skip initial elements that do not contribute to subdiagonal nonzero pattern
31692 : */
31693 0 : i0 = superrowridx->ptr.p_int[tmp0->ptr.p_int[cidx]];
31694 0 : i1 = superrowridx->ptr.p_int[tmp0->ptr.p_int[cidx]+1]-1;
31695 0 : while(i0<=i1&&superrowidx->ptr.p_int[i0]<=columnidx)
31696 : {
31697 0 : i0 = i0+1;
31698 : }
31699 :
31700 : /*
31701 : * Append elements not present in the sequence
31702 : */
31703 0 : for(ii=i0; ii<=i1; ii++)
31704 : {
31705 0 : i = superrowidx->ptr.p_int[ii];
31706 0 : if( truearray->ptr.p_bool[i] )
31707 : {
31708 0 : superrowidx->ptr.p_int[rlast] = i;
31709 0 : rlast = rlast+1;
31710 0 : truearray->ptr.p_bool[i] = ae_false;
31711 : }
31712 : }
31713 : }
31714 0 : for(ii=rfirst; ii<=rlast-1; ii++)
31715 : {
31716 0 : truearray->ptr.p_bool[superrowidx->ptr.p_int[ii]] = ae_true;
31717 : }
31718 0 : tagsortmiddlei(superrowidx, rfirst, rlast-rfirst, _state);
31719 0 : result = rlast;
31720 : }
31721 0 : return result;
31722 : }
31723 :
31724 :
31725 : /*************************************************************************
31726 : Update target supernode with data from one of its children. This operation
31727 : is a supernodal equivalent of the column update in the left-looking
31728 : Cholesky.
31729 :
31730 : The generic update has following form:
31731 :
31732 : S := S - scatter(U*D*Uc')
31733 :
31734 : where
31735 : * S is an tHeight*tWidth rectangular target matrix that is:
31736 : * stored with tStride>=tWidth in RowStorage[OffsS:OffsS+tHeight*tStride-1]
31737 : * lower trapezoidal i.e. its leading tWidth*tWidth submatrix is lower
31738 : triangular. One may update either entire tWidth*tWidth submatrix or
31739 : just its lower part, because upper triangle is not referenced anyway.
31740 : * the height of S is not given because it is not actually needed
31741 : * U is an uHeight*uRank rectangular update matrix tht is:
31742 : * stored with row stride uStride>=uRank in RowStorage[OffsU:OffsU+uHeight*uStride-1].
31743 : * Uc is the leading uWidth*uRank submatrix of U
31744 : * D is uRank*uRank diagonal matrix that is:
31745 : * stored in DiagD[OffsD:OffsD+uRank-1]
31746 : * unit, when Analysis.UnitD=True. In this case it can be ignored, although
31747 : DiagD still contains 1's in all of its entries
31748 : * uHeight<=tHeight, uWidth<=tWidth, so scatter operation is needed to update
31749 : S with smaller update.
31750 : * scatter() is an operation that extends smaller uHeight*uWidth update
31751 : matrix U*Uc' into larger tHeight*tWidth target matrix by adding zero rows
31752 : and columns into U*Uc':
31753 : * I-th row of update modifies Raw2SMap[SuperRowIdx[URBase+I]]-th row of
31754 : the matrix S
31755 : * J-th column of update modifies Raw2SMap[SuperRowIdx[URBase+J]]-th col
31756 : of the matrix S
31757 :
31758 : -- ALGLIB routine --
31759 : 20.09.2020
31760 : Bochkanov Sergey
31761 : *************************************************************************/
31762 0 : static ae_int_t spchol_updatesupernode(spcholanalysis* analysis,
31763 : ae_int_t sidx,
31764 : ae_int_t cols0,
31765 : ae_int_t cols1,
31766 : ae_int_t offss,
31767 : /* Integer */ ae_vector* raw2smap,
31768 : ae_int_t uidx,
31769 : ae_int_t wrkrow,
31770 : /* Real */ ae_vector* diagd,
31771 : ae_int_t offsd,
31772 : ae_state *_state)
31773 : {
31774 : ae_int_t i;
31775 : ae_int_t j;
31776 : ae_int_t k;
31777 : ae_int_t colu0;
31778 : ae_int_t colu1;
31779 : ae_int_t urbase;
31780 : ae_int_t urlast;
31781 : ae_int_t urank;
31782 : ae_int_t uwidth;
31783 : ae_int_t uheight;
31784 : ae_int_t urowstride;
31785 : ae_int_t twidth;
31786 : ae_int_t trowstride;
31787 : ae_int_t targetrow;
31788 : ae_int_t targetcol;
31789 : ae_int_t offsu;
31790 : ae_int_t offdiagrow;
31791 : ae_int_t lastrow;
31792 : ae_int_t offs0;
31793 : ae_int_t offsj;
31794 : ae_int_t offsk;
31795 : double v;
31796 : ae_int_t result;
31797 :
31798 :
31799 0 : twidth = cols1-cols0;
31800 0 : offsu = analysis->rowoffsets.ptr.p_int[uidx];
31801 0 : colu0 = analysis->supercolrange.ptr.p_int[uidx];
31802 0 : colu1 = analysis->supercolrange.ptr.p_int[uidx+1];
31803 0 : urbase = analysis->superrowridx.ptr.p_int[uidx];
31804 0 : urlast = analysis->superrowridx.ptr.p_int[uidx+1];
31805 0 : urank = colu1-colu0;
31806 0 : trowstride = analysis->rowstrides.ptr.p_int[sidx];
31807 0 : urowstride = analysis->rowstrides.ptr.p_int[uidx];
31808 :
31809 : /*
31810 : * Skip leading uRank+WrkRow rows of U because they are not used.
31811 : */
31812 0 : offsu = offsu+(colu1-colu0+wrkrow)*urowstride;
31813 :
31814 : /*
31815 : * Analyze range of rows in supernode LAdjPlus[II] and determine two subranges:
31816 : * * one with indexes stored at SuperRowIdx[WrkRow:OffdiagRow);
31817 : * these indexes are the ones that intersect with range of rows/columns [ColS0,ColS1)
31818 : * occupied by diagonal block of the supernode SIdx
31819 : * * one with indexes stored at SuperRowIdx[OffdiagRow:LastRow);
31820 : * these indexes are ones that intersect with range of rows occupied by
31821 : * offdiagonal block of the supernode SIdx
31822 : */
31823 0 : if( analysis->extendeddebug )
31824 : {
31825 0 : ae_assert(analysis->superrowidx.ptr.p_int[urbase+wrkrow]>=cols0, "SPCholFactorize: integrity check 6378 failed", _state);
31826 0 : ae_assert(analysis->superrowidx.ptr.p_int[urbase+wrkrow]<cols1, "SPCholFactorize: integrity check 6729 failed", _state);
31827 : }
31828 0 : offdiagrow = wrkrow;
31829 0 : lastrow = urlast-urbase;
31830 0 : while(offdiagrow<lastrow&&analysis->superrowidx.ptr.p_int[offdiagrow+urbase]<cols1)
31831 : {
31832 0 : offdiagrow = offdiagrow+1;
31833 : }
31834 0 : uwidth = offdiagrow-wrkrow;
31835 0 : uheight = lastrow-wrkrow;
31836 0 : result = offdiagrow;
31837 0 : if( analysis->extendeddebug )
31838 : {
31839 :
31840 : /*
31841 : * Extended integrity check (if requested)
31842 : */
31843 0 : ae_assert(wrkrow<offdiagrow&&analysis->superrowidx.ptr.p_int[wrkrow+urbase]>=cols0, "SPCholFactorize: integrity check failed (44trg6)", _state);
31844 0 : for(i=wrkrow; i<=lastrow-1; i++)
31845 : {
31846 0 : ae_assert(raw2smap->ptr.p_int[analysis->superrowidx.ptr.p_int[i+urbase]]>=0, "SPCholFactorize: integrity check failed (43t63)", _state);
31847 : }
31848 : }
31849 :
31850 : /*
31851 : * Handle special cases
31852 : */
31853 0 : if( trowstride==4 )
31854 : {
31855 :
31856 : /*
31857 : * Target is stride-4 column, try several kernels that may work with tWidth=3 and tWidth=4
31858 : */
31859 0 : if( ((uwidth==4&&twidth==4)&&urank==4)&&urowstride==4 )
31860 : {
31861 0 : if( spchol_updatekernel4444(&analysis->rowstorage, offss, offsu, uheight, &analysis->diagd, colu0, raw2smap, &analysis->superrowidx, urbase+wrkrow, _state) )
31862 : {
31863 0 : return result;
31864 : }
31865 : }
31866 0 : if( spchol_updatekernelabc4(&analysis->rowstorage, offss, twidth, offsu, uheight, urank, urowstride, uwidth, &analysis->diagd, colu0, raw2smap, &analysis->superrowidx, urbase+wrkrow, _state) )
31867 : {
31868 0 : return result;
31869 : }
31870 : }
31871 0 : if( urank==1&&urowstride==1 )
31872 : {
31873 0 : if( spchol_updatekernelrank1(&analysis->rowstorage, offss, twidth, trowstride, offsu, uheight, uwidth, &analysis->diagd, colu0, raw2smap, &analysis->superrowidx, urbase+wrkrow, _state) )
31874 : {
31875 0 : return result;
31876 : }
31877 : }
31878 0 : if( urank==2&&urowstride==2 )
31879 : {
31880 0 : if( spchol_updatekernelrank2(&analysis->rowstorage, offss, twidth, trowstride, offsu, uheight, uwidth, &analysis->diagd, colu0, raw2smap, &analysis->superrowidx, urbase+wrkrow, _state) )
31881 : {
31882 0 : return result;
31883 : }
31884 : }
31885 :
31886 : /*
31887 : * Handle general update, rerefence code
31888 : */
31889 0 : ivectorsetlengthatleast(&analysis->u2smap, uheight, _state);
31890 0 : for(i=0; i<=uheight-1; i++)
31891 : {
31892 0 : analysis->u2smap.ptr.p_int[i] = raw2smap->ptr.p_int[analysis->superrowidx.ptr.p_int[urbase+wrkrow+i]];
31893 : }
31894 0 : if( analysis->unitd )
31895 : {
31896 :
31897 : /*
31898 : * Unit D, vanilla Cholesky
31899 : */
31900 0 : for(k=0; k<=uheight-1; k++)
31901 : {
31902 0 : targetrow = offss+analysis->u2smap.ptr.p_int[k]*trowstride;
31903 0 : for(j=0; j<=uwidth-1; j++)
31904 : {
31905 0 : targetcol = analysis->u2smap.ptr.p_int[j];
31906 0 : offsj = offsu+j*urowstride;
31907 0 : offsk = offsu+k*urowstride;
31908 0 : offs0 = targetrow+targetcol;
31909 0 : v = analysis->rowstorage.ptr.p_double[offs0];
31910 0 : for(i=0; i<=urank-1; i++)
31911 : {
31912 0 : v = v-analysis->rowstorage.ptr.p_double[offsj+i]*analysis->rowstorage.ptr.p_double[offsk+i];
31913 : }
31914 0 : analysis->rowstorage.ptr.p_double[offs0] = v;
31915 : }
31916 : }
31917 : }
31918 : else
31919 : {
31920 :
31921 : /*
31922 : * Non-unit D, LDLT decomposition
31923 : */
31924 0 : for(k=0; k<=uheight-1; k++)
31925 : {
31926 0 : targetrow = offss+analysis->u2smap.ptr.p_int[k]*trowstride;
31927 0 : for(j=0; j<=uwidth-1; j++)
31928 : {
31929 0 : targetcol = analysis->u2smap.ptr.p_int[j];
31930 0 : offsj = offsu+j*urowstride;
31931 0 : offsk = offsu+k*urowstride;
31932 0 : offs0 = targetrow+targetcol;
31933 0 : v = analysis->rowstorage.ptr.p_double[offs0];
31934 0 : for(i=0; i<=urank-1; i++)
31935 : {
31936 0 : v = v-analysis->rowstorage.ptr.p_double[offsj+i]*diagd->ptr.p_double[offsd+i]*analysis->rowstorage.ptr.p_double[offsk+i];
31937 : }
31938 0 : analysis->rowstorage.ptr.p_double[offs0] = v;
31939 : }
31940 : }
31941 : }
31942 0 : return result;
31943 : }
31944 :
31945 :
31946 : /*************************************************************************
31947 : Factorizes target supernode, returns True on success, False on failure.
31948 :
31949 : -- ALGLIB routine --
31950 : 20.09.2020
31951 : Bochkanov Sergey
31952 : *************************************************************************/
31953 0 : static ae_bool spchol_factorizesupernode(spcholanalysis* analysis,
31954 : ae_int_t sidx,
31955 : ae_state *_state)
31956 : {
31957 : ae_int_t i;
31958 : ae_int_t j;
31959 : ae_int_t k;
31960 : ae_int_t cols0;
31961 : ae_int_t cols1;
31962 : ae_int_t offss;
31963 : ae_int_t blocksize;
31964 : ae_int_t offdiagsize;
31965 : ae_int_t sstride;
31966 : double v;
31967 : double vs;
31968 : double possignvraw;
31969 : ae_bool controlpivot;
31970 : ae_bool controloverflow;
31971 : ae_bool result;
31972 :
31973 :
31974 0 : cols0 = analysis->supercolrange.ptr.p_int[sidx];
31975 0 : cols1 = analysis->supercolrange.ptr.p_int[sidx+1];
31976 0 : offss = analysis->rowoffsets.ptr.p_int[sidx];
31977 0 : blocksize = cols1-cols0;
31978 0 : offdiagsize = analysis->superrowridx.ptr.p_int[sidx+1]-analysis->superrowridx.ptr.p_int[sidx];
31979 0 : sstride = analysis->rowstrides.ptr.p_int[sidx];
31980 0 : controlpivot = analysis->modtype==1&&ae_fp_greater(analysis->modparam0,(double)(0));
31981 0 : controloverflow = analysis->modtype==1&&ae_fp_greater(analysis->modparam1,(double)(0));
31982 0 : if( analysis->unitd )
31983 : {
31984 :
31985 : /*
31986 : * Classic Cholesky
31987 : */
31988 0 : for(j=0; j<=blocksize-1; j++)
31989 : {
31990 :
31991 : /*
31992 : * Compute J-th column
31993 : */
31994 0 : vs = (double)(0);
31995 0 : for(k=j; k<=blocksize+offdiagsize-1; k++)
31996 : {
31997 0 : v = analysis->rowstorage.ptr.p_double[offss+k*sstride+j];
31998 0 : for(i=0; i<=j-1; i++)
31999 : {
32000 0 : v = v-analysis->rowstorage.ptr.p_double[offss+k*sstride+i]*analysis->rowstorage.ptr.p_double[offss+j*sstride+i];
32001 : }
32002 0 : analysis->rowstorage.ptr.p_double[offss+k*sstride+j] = v;
32003 0 : vs = vs+ae_fabs(v, _state);
32004 : }
32005 0 : if( controloverflow&&ae_fp_greater(vs,analysis->modparam1) )
32006 : {
32007 :
32008 : /*
32009 : * Possible failure due to accumulation of numerical errors
32010 : */
32011 0 : result = ae_false;
32012 0 : return result;
32013 : }
32014 :
32015 : /*
32016 : * Handle pivot element
32017 : */
32018 0 : v = analysis->rowstorage.ptr.p_double[offss+j*sstride+j];
32019 0 : if( controlpivot&&ae_fp_less_eq(v,analysis->modparam0) )
32020 : {
32021 :
32022 : /*
32023 : * Basic modified Cholesky
32024 : */
32025 0 : v = ae_sqrt(analysis->modparam0, _state);
32026 0 : analysis->diagd.ptr.p_double[cols0+j] = 1.0;
32027 0 : analysis->rowstorage.ptr.p_double[offss+j*sstride+j] = v;
32028 0 : v = 1/v;
32029 0 : for(k=j+1; k<=blocksize+offdiagsize-1; k++)
32030 : {
32031 0 : analysis->rowstorage.ptr.p_double[offss+k*sstride+j] = v*analysis->rowstorage.ptr.p_double[offss+k*sstride+j];
32032 : }
32033 : }
32034 : else
32035 : {
32036 :
32037 : /*
32038 : * Default case
32039 : */
32040 0 : if( ae_fp_less_eq(v,(double)(0)) )
32041 : {
32042 0 : result = ae_false;
32043 0 : return result;
32044 : }
32045 0 : analysis->diagd.ptr.p_double[cols0+j] = 1.0;
32046 0 : v = 1/ae_sqrt(v, _state);
32047 0 : for(k=j; k<=blocksize+offdiagsize-1; k++)
32048 : {
32049 0 : analysis->rowstorage.ptr.p_double[offss+k*sstride+j] = v*analysis->rowstorage.ptr.p_double[offss+k*sstride+j];
32050 : }
32051 : }
32052 : }
32053 : }
32054 : else
32055 : {
32056 :
32057 : /*
32058 : * LDLT with diagonal D
32059 : */
32060 0 : for(j=0; j<=blocksize-1; j++)
32061 : {
32062 :
32063 : /*
32064 : * Compute J-th column
32065 : */
32066 0 : vs = (double)(0);
32067 0 : for(k=j; k<=blocksize+offdiagsize-1; k++)
32068 : {
32069 0 : v = analysis->rowstorage.ptr.p_double[offss+k*sstride+j];
32070 0 : for(i=0; i<=j-1; i++)
32071 : {
32072 0 : v = v-analysis->rowstorage.ptr.p_double[offss+k*sstride+i]*analysis->diagd.ptr.p_double[cols0+i]*analysis->rowstorage.ptr.p_double[offss+j*sstride+i];
32073 : }
32074 0 : analysis->rowstorage.ptr.p_double[offss+k*sstride+j] = v;
32075 0 : vs = vs+ae_fabs(v, _state);
32076 : }
32077 0 : if( controloverflow&&ae_fp_greater(vs,analysis->modparam1) )
32078 : {
32079 :
32080 : /*
32081 : * Possible failure due to accumulation of numerical errors
32082 : */
32083 0 : result = ae_false;
32084 0 : return result;
32085 : }
32086 :
32087 : /*
32088 : * Handle pivot element
32089 : */
32090 0 : ae_assert(analysis->wrkat.idx.ptr.p_int[analysis->wrkat.ridx.ptr.p_int[cols0+j]]==cols0+j, "FactorizeSupernode: integrity check failed", _state);
32091 0 : possignvraw = possign(analysis->wrkat.vals.ptr.p_double[analysis->wrkat.ridx.ptr.p_int[cols0+j]], _state);
32092 0 : v = analysis->rowstorage.ptr.p_double[offss+j*sstride+j];
32093 0 : if( controlpivot&&ae_fp_less_eq(v/possignvraw,analysis->modparam0) )
32094 : {
32095 :
32096 : /*
32097 : * Basic modified LDLT
32098 : */
32099 0 : v = possignvraw*analysis->modparam0;
32100 0 : analysis->diagd.ptr.p_double[cols0+j] = v;
32101 0 : analysis->rowstorage.ptr.p_double[offss+j*sstride+j] = 1.0;
32102 0 : v = 1/v;
32103 0 : for(k=j+1; k<=blocksize+offdiagsize-1; k++)
32104 : {
32105 0 : analysis->rowstorage.ptr.p_double[offss+k*sstride+j] = v*analysis->rowstorage.ptr.p_double[offss+k*sstride+j];
32106 : }
32107 : }
32108 : else
32109 : {
32110 :
32111 : /*
32112 : * Unmodified LDLT
32113 : */
32114 0 : if( ae_fp_eq(v,(double)(0)) )
32115 : {
32116 0 : result = ae_false;
32117 0 : return result;
32118 : }
32119 0 : analysis->diagd.ptr.p_double[cols0+j] = v;
32120 0 : v = 1/v;
32121 0 : for(k=j; k<=blocksize+offdiagsize-1; k++)
32122 : {
32123 0 : analysis->rowstorage.ptr.p_double[offss+k*sstride+j] = v*analysis->rowstorage.ptr.p_double[offss+k*sstride+j];
32124 : }
32125 : }
32126 : }
32127 : }
32128 0 : result = ae_true;
32129 0 : return result;
32130 : }
32131 :
32132 :
32133 : /*************************************************************************
32134 : This function returns recommended stride for given row size
32135 :
32136 : -- ALGLIB routine --
32137 : 20.10.2020
32138 : Bochkanov Sergey
32139 : *************************************************************************/
32140 0 : static ae_int_t spchol_recommendedstridefor(ae_int_t rowsize,
32141 : ae_state *_state)
32142 : {
32143 : ae_int_t result;
32144 :
32145 :
32146 0 : result = rowsize;
32147 0 : if( rowsize==3 )
32148 : {
32149 0 : result = 4;
32150 : }
32151 0 : return result;
32152 : }
32153 :
32154 :
32155 : /*************************************************************************
32156 : This function aligns position in array in order to better accommodate to
32157 : SIMD specifics.
32158 :
32159 : NOTE: this function aligns position measured in double precision numbers,
32160 : not in bits or bytes. If you want to have 256-bit aligned position,
32161 : round Offs to nearest multiple of 4 that is not less than Offs.
32162 :
32163 : -- ALGLIB routine --
32164 : 20.10.2020
32165 : Bochkanov Sergey
32166 : *************************************************************************/
32167 0 : static ae_int_t spchol_alignpositioninarray(ae_int_t offs,
32168 : ae_state *_state)
32169 : {
32170 : ae_int_t result;
32171 :
32172 :
32173 0 : result = offs;
32174 0 : if( offs%4!=0 )
32175 : {
32176 0 : result = result+(4-offs%4);
32177 : }
32178 0 : return result;
32179 : }
32180 :
32181 :
32182 : /*************************************************************************
32183 : Fast kernels for small supernodal updates: special 4x4x4x4 function.
32184 :
32185 : ! See comments on UpdateSupernode() for information on generic supernodal
32186 : ! updates, including notation used below.
32187 :
32188 : The generic update has following form:
32189 :
32190 : S := S - scatter(U*D*Uc')
32191 :
32192 : This specialized function performs 4x4x4x4 update, i.e.:
32193 : * S is a tHeight*4 matrix
32194 : * U is a uHeight*4 matrix
32195 : * Uc' is a 4*4 matrix
32196 : * scatter() scatters rows of U*Uc', but does not scatter columns (they are
32197 : densely packed).
32198 :
32199 : Return value:
32200 : * True if update was applied
32201 : * False if kernel refused to perform an update.
32202 :
32203 : -- ALGLIB routine --
32204 : 20.09.2020
32205 : Bochkanov Sergey
32206 : *************************************************************************/
32207 0 : static ae_bool spchol_updatekernel4444(/* Real */ ae_vector* rowstorage,
32208 : ae_int_t offss,
32209 : ae_int_t offsu,
32210 : ae_int_t uheight,
32211 : /* Real */ ae_vector* diagd,
32212 : ae_int_t offsd,
32213 : /* Integer */ ae_vector* raw2smap,
32214 : /* Integer */ ae_vector* superrowidx,
32215 : ae_int_t urbase,
32216 : ae_state *_state)
32217 : {
32218 : ae_int_t k;
32219 : ae_int_t targetrow;
32220 : ae_int_t offsk;
32221 : double d0;
32222 : double d1;
32223 : double d2;
32224 : double d3;
32225 : double u00;
32226 : double u01;
32227 : double u02;
32228 : double u03;
32229 : double u10;
32230 : double u11;
32231 : double u12;
32232 : double u13;
32233 : double u20;
32234 : double u21;
32235 : double u22;
32236 : double u23;
32237 : double u30;
32238 : double u31;
32239 : double u32;
32240 : double u33;
32241 : double uk0;
32242 : double uk1;
32243 : double uk2;
32244 : double uk3;
32245 : ae_bool result;
32246 :
32247 :
32248 0 : d0 = diagd->ptr.p_double[offsd+0];
32249 0 : d1 = diagd->ptr.p_double[offsd+1];
32250 0 : d2 = diagd->ptr.p_double[offsd+2];
32251 0 : d3 = diagd->ptr.p_double[offsd+3];
32252 0 : u00 = d0*rowstorage->ptr.p_double[offsu+0*4+0];
32253 0 : u01 = d1*rowstorage->ptr.p_double[offsu+0*4+1];
32254 0 : u02 = d2*rowstorage->ptr.p_double[offsu+0*4+2];
32255 0 : u03 = d3*rowstorage->ptr.p_double[offsu+0*4+3];
32256 0 : u10 = d0*rowstorage->ptr.p_double[offsu+1*4+0];
32257 0 : u11 = d1*rowstorage->ptr.p_double[offsu+1*4+1];
32258 0 : u12 = d2*rowstorage->ptr.p_double[offsu+1*4+2];
32259 0 : u13 = d3*rowstorage->ptr.p_double[offsu+1*4+3];
32260 0 : u20 = d0*rowstorage->ptr.p_double[offsu+2*4+0];
32261 0 : u21 = d1*rowstorage->ptr.p_double[offsu+2*4+1];
32262 0 : u22 = d2*rowstorage->ptr.p_double[offsu+2*4+2];
32263 0 : u23 = d3*rowstorage->ptr.p_double[offsu+2*4+3];
32264 0 : u30 = d0*rowstorage->ptr.p_double[offsu+3*4+0];
32265 0 : u31 = d1*rowstorage->ptr.p_double[offsu+3*4+1];
32266 0 : u32 = d2*rowstorage->ptr.p_double[offsu+3*4+2];
32267 0 : u33 = d3*rowstorage->ptr.p_double[offsu+3*4+3];
32268 0 : for(k=0; k<=uheight-1; k++)
32269 : {
32270 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*4;
32271 0 : offsk = offsu+k*4;
32272 0 : uk0 = rowstorage->ptr.p_double[offsk+0];
32273 0 : uk1 = rowstorage->ptr.p_double[offsk+1];
32274 0 : uk2 = rowstorage->ptr.p_double[offsk+2];
32275 0 : uk3 = rowstorage->ptr.p_double[offsk+3];
32276 0 : rowstorage->ptr.p_double[targetrow+0] = rowstorage->ptr.p_double[targetrow+0]-u00*uk0-u01*uk1-u02*uk2-u03*uk3;
32277 0 : rowstorage->ptr.p_double[targetrow+1] = rowstorage->ptr.p_double[targetrow+1]-u10*uk0-u11*uk1-u12*uk2-u13*uk3;
32278 0 : rowstorage->ptr.p_double[targetrow+2] = rowstorage->ptr.p_double[targetrow+2]-u20*uk0-u21*uk1-u22*uk2-u23*uk3;
32279 0 : rowstorage->ptr.p_double[targetrow+3] = rowstorage->ptr.p_double[targetrow+3]-u30*uk0-u31*uk1-u32*uk2-u33*uk3;
32280 : }
32281 0 : result = ae_true;
32282 0 : return result;
32283 : }
32284 :
32285 :
32286 : /*************************************************************************
32287 : Fast kernels for small supernodal updates: special 4x4x4x4 function.
32288 :
32289 : ! See comments on UpdateSupernode() for information on generic supernodal
32290 : ! updates, including notation used below.
32291 :
32292 : The generic update has following form:
32293 :
32294 : S := S - scatter(U*D*Uc')
32295 :
32296 : This specialized function performs AxBxCx4 update, i.e.:
32297 : * S is a tHeight*A matrix with row stride equal to 4 (usually it means that
32298 : it has 3 or 4 columns)
32299 : * U is a uHeight*B matrix
32300 : * Uc' is a B*C matrix, with C<=A
32301 : * scatter() scatters rows and columns of U*Uc'
32302 :
32303 : Return value:
32304 : * True if update was applied
32305 : * False if kernel refused to perform an update (quick exit for unsupported
32306 : combinations of input sizes)
32307 :
32308 : -- ALGLIB routine --
32309 : 20.09.2020
32310 : Bochkanov Sergey
32311 : *************************************************************************/
32312 0 : static ae_bool spchol_updatekernelabc4(/* Real */ ae_vector* rowstorage,
32313 : ae_int_t offss,
32314 : ae_int_t twidth,
32315 : ae_int_t offsu,
32316 : ae_int_t uheight,
32317 : ae_int_t urank,
32318 : ae_int_t urowstride,
32319 : ae_int_t uwidth,
32320 : /* Real */ ae_vector* diagd,
32321 : ae_int_t offsd,
32322 : /* Integer */ ae_vector* raw2smap,
32323 : /* Integer */ ae_vector* superrowidx,
32324 : ae_int_t urbase,
32325 : ae_state *_state)
32326 : {
32327 : ae_int_t k;
32328 : ae_int_t targetrow;
32329 : ae_int_t targetcol;
32330 : ae_int_t offsk;
32331 : double d0;
32332 : double d1;
32333 : double d2;
32334 : double d3;
32335 : double u00;
32336 : double u01;
32337 : double u02;
32338 : double u03;
32339 : double u10;
32340 : double u11;
32341 : double u12;
32342 : double u13;
32343 : double u20;
32344 : double u21;
32345 : double u22;
32346 : double u23;
32347 : double u30;
32348 : double u31;
32349 : double u32;
32350 : double u33;
32351 : double uk0;
32352 : double uk1;
32353 : double uk2;
32354 : double uk3;
32355 : ae_int_t srccol0;
32356 : ae_int_t srccol1;
32357 : ae_int_t srccol2;
32358 : ae_int_t srccol3;
32359 : ae_bool result;
32360 :
32361 :
32362 :
32363 : /*
32364 : * Filter out unsupported combinations (ones that are too sparse for the non-SIMD code)
32365 : */
32366 0 : result = ae_false;
32367 0 : if( twidth<3||twidth>4 )
32368 : {
32369 0 : return result;
32370 : }
32371 0 : if( uwidth<3||uwidth>4 )
32372 : {
32373 0 : return result;
32374 : }
32375 0 : if( urank>4 )
32376 : {
32377 0 : return result;
32378 : }
32379 :
32380 : /*
32381 : * Determine source columns for target columns, -1 if target column
32382 : * is not updated.
32383 : */
32384 0 : srccol0 = -1;
32385 0 : srccol1 = -1;
32386 0 : srccol2 = -1;
32387 0 : srccol3 = -1;
32388 0 : for(k=0; k<=uwidth-1; k++)
32389 : {
32390 0 : targetcol = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]];
32391 0 : if( targetcol==0 )
32392 : {
32393 0 : srccol0 = k;
32394 : }
32395 0 : if( targetcol==1 )
32396 : {
32397 0 : srccol1 = k;
32398 : }
32399 0 : if( targetcol==2 )
32400 : {
32401 0 : srccol2 = k;
32402 : }
32403 0 : if( targetcol==3 )
32404 : {
32405 0 : srccol3 = k;
32406 : }
32407 : }
32408 :
32409 : /*
32410 : * Load update matrix into aligned/rearranged 4x4 storage
32411 : */
32412 0 : d0 = (double)(0);
32413 0 : d1 = (double)(0);
32414 0 : d2 = (double)(0);
32415 0 : d3 = (double)(0);
32416 0 : u00 = (double)(0);
32417 0 : u01 = (double)(0);
32418 0 : u02 = (double)(0);
32419 0 : u03 = (double)(0);
32420 0 : u10 = (double)(0);
32421 0 : u11 = (double)(0);
32422 0 : u12 = (double)(0);
32423 0 : u13 = (double)(0);
32424 0 : u20 = (double)(0);
32425 0 : u21 = (double)(0);
32426 0 : u22 = (double)(0);
32427 0 : u23 = (double)(0);
32428 0 : u30 = (double)(0);
32429 0 : u31 = (double)(0);
32430 0 : u32 = (double)(0);
32431 0 : u33 = (double)(0);
32432 0 : if( urank>=1 )
32433 : {
32434 0 : d0 = diagd->ptr.p_double[offsd+0];
32435 : }
32436 0 : if( urank>=2 )
32437 : {
32438 0 : d1 = diagd->ptr.p_double[offsd+1];
32439 : }
32440 0 : if( urank>=3 )
32441 : {
32442 0 : d2 = diagd->ptr.p_double[offsd+2];
32443 : }
32444 0 : if( urank>=4 )
32445 : {
32446 0 : d3 = diagd->ptr.p_double[offsd+3];
32447 : }
32448 0 : if( srccol0>=0 )
32449 : {
32450 0 : if( urank>=1 )
32451 : {
32452 0 : u00 = d0*rowstorage->ptr.p_double[offsu+srccol0*urowstride+0];
32453 : }
32454 0 : if( urank>=2 )
32455 : {
32456 0 : u01 = d1*rowstorage->ptr.p_double[offsu+srccol0*urowstride+1];
32457 : }
32458 0 : if( urank>=3 )
32459 : {
32460 0 : u02 = d2*rowstorage->ptr.p_double[offsu+srccol0*urowstride+2];
32461 : }
32462 0 : if( urank>=4 )
32463 : {
32464 0 : u03 = d3*rowstorage->ptr.p_double[offsu+srccol0*urowstride+3];
32465 : }
32466 : }
32467 0 : if( srccol1>=0 )
32468 : {
32469 0 : if( urank>=1 )
32470 : {
32471 0 : u10 = d0*rowstorage->ptr.p_double[offsu+srccol1*urowstride+0];
32472 : }
32473 0 : if( urank>=2 )
32474 : {
32475 0 : u11 = d1*rowstorage->ptr.p_double[offsu+srccol1*urowstride+1];
32476 : }
32477 0 : if( urank>=3 )
32478 : {
32479 0 : u12 = d2*rowstorage->ptr.p_double[offsu+srccol1*urowstride+2];
32480 : }
32481 0 : if( urank>=4 )
32482 : {
32483 0 : u13 = d3*rowstorage->ptr.p_double[offsu+srccol1*urowstride+3];
32484 : }
32485 : }
32486 0 : if( srccol2>=0 )
32487 : {
32488 0 : if( urank>=1 )
32489 : {
32490 0 : u20 = d0*rowstorage->ptr.p_double[offsu+srccol2*urowstride+0];
32491 : }
32492 0 : if( urank>=2 )
32493 : {
32494 0 : u21 = d1*rowstorage->ptr.p_double[offsu+srccol2*urowstride+1];
32495 : }
32496 0 : if( urank>=3 )
32497 : {
32498 0 : u22 = d2*rowstorage->ptr.p_double[offsu+srccol2*urowstride+2];
32499 : }
32500 0 : if( urank>=4 )
32501 : {
32502 0 : u23 = d3*rowstorage->ptr.p_double[offsu+srccol2*urowstride+3];
32503 : }
32504 : }
32505 0 : if( srccol3>=0 )
32506 : {
32507 0 : if( urank>=1 )
32508 : {
32509 0 : u30 = d0*rowstorage->ptr.p_double[offsu+srccol3*urowstride+0];
32510 : }
32511 0 : if( urank>=2 )
32512 : {
32513 0 : u31 = d1*rowstorage->ptr.p_double[offsu+srccol3*urowstride+1];
32514 : }
32515 0 : if( urank>=3 )
32516 : {
32517 0 : u32 = d2*rowstorage->ptr.p_double[offsu+srccol3*urowstride+2];
32518 : }
32519 0 : if( urank>=4 )
32520 : {
32521 0 : u33 = d3*rowstorage->ptr.p_double[offsu+srccol3*urowstride+3];
32522 : }
32523 : }
32524 :
32525 : /*
32526 : * Run update
32527 : */
32528 0 : if( urank==1 )
32529 : {
32530 0 : for(k=0; k<=uheight-1; k++)
32531 : {
32532 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*4;
32533 0 : offsk = offsu+k*urowstride;
32534 0 : uk0 = rowstorage->ptr.p_double[offsk+0];
32535 0 : rowstorage->ptr.p_double[targetrow+0] = rowstorage->ptr.p_double[targetrow+0]-u00*uk0;
32536 0 : rowstorage->ptr.p_double[targetrow+1] = rowstorage->ptr.p_double[targetrow+1]-u10*uk0;
32537 0 : rowstorage->ptr.p_double[targetrow+2] = rowstorage->ptr.p_double[targetrow+2]-u20*uk0;
32538 0 : rowstorage->ptr.p_double[targetrow+3] = rowstorage->ptr.p_double[targetrow+3]-u30*uk0;
32539 : }
32540 : }
32541 0 : if( urank==2 )
32542 : {
32543 0 : for(k=0; k<=uheight-1; k++)
32544 : {
32545 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*4;
32546 0 : offsk = offsu+k*urowstride;
32547 0 : uk0 = rowstorage->ptr.p_double[offsk+0];
32548 0 : uk1 = rowstorage->ptr.p_double[offsk+1];
32549 0 : rowstorage->ptr.p_double[targetrow+0] = rowstorage->ptr.p_double[targetrow+0]-u00*uk0-u01*uk1;
32550 0 : rowstorage->ptr.p_double[targetrow+1] = rowstorage->ptr.p_double[targetrow+1]-u10*uk0-u11*uk1;
32551 0 : rowstorage->ptr.p_double[targetrow+2] = rowstorage->ptr.p_double[targetrow+2]-u20*uk0-u21*uk1;
32552 0 : rowstorage->ptr.p_double[targetrow+3] = rowstorage->ptr.p_double[targetrow+3]-u30*uk0-u31*uk1;
32553 : }
32554 : }
32555 0 : if( urank==3 )
32556 : {
32557 0 : for(k=0; k<=uheight-1; k++)
32558 : {
32559 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*4;
32560 0 : offsk = offsu+k*urowstride;
32561 0 : uk0 = rowstorage->ptr.p_double[offsk+0];
32562 0 : uk1 = rowstorage->ptr.p_double[offsk+1];
32563 0 : uk2 = rowstorage->ptr.p_double[offsk+2];
32564 0 : rowstorage->ptr.p_double[targetrow+0] = rowstorage->ptr.p_double[targetrow+0]-u00*uk0-u01*uk1-u02*uk2;
32565 0 : rowstorage->ptr.p_double[targetrow+1] = rowstorage->ptr.p_double[targetrow+1]-u10*uk0-u11*uk1-u12*uk2;
32566 0 : rowstorage->ptr.p_double[targetrow+2] = rowstorage->ptr.p_double[targetrow+2]-u20*uk0-u21*uk1-u22*uk2;
32567 0 : rowstorage->ptr.p_double[targetrow+3] = rowstorage->ptr.p_double[targetrow+3]-u30*uk0-u31*uk1-u32*uk2;
32568 : }
32569 : }
32570 0 : if( urank==4 )
32571 : {
32572 0 : for(k=0; k<=uheight-1; k++)
32573 : {
32574 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*4;
32575 0 : offsk = offsu+k*urowstride;
32576 0 : uk0 = rowstorage->ptr.p_double[offsk+0];
32577 0 : uk1 = rowstorage->ptr.p_double[offsk+1];
32578 0 : uk2 = rowstorage->ptr.p_double[offsk+2];
32579 0 : uk3 = rowstorage->ptr.p_double[offsk+3];
32580 0 : rowstorage->ptr.p_double[targetrow+0] = rowstorage->ptr.p_double[targetrow+0]-u00*uk0-u01*uk1-u02*uk2-u03*uk3;
32581 0 : rowstorage->ptr.p_double[targetrow+1] = rowstorage->ptr.p_double[targetrow+1]-u10*uk0-u11*uk1-u12*uk2-u13*uk3;
32582 0 : rowstorage->ptr.p_double[targetrow+2] = rowstorage->ptr.p_double[targetrow+2]-u20*uk0-u21*uk1-u22*uk2-u23*uk3;
32583 0 : rowstorage->ptr.p_double[targetrow+3] = rowstorage->ptr.p_double[targetrow+3]-u30*uk0-u31*uk1-u32*uk2-u33*uk3;
32584 : }
32585 : }
32586 0 : result = ae_true;
32587 0 : return result;
32588 : }
32589 :
32590 :
32591 : /*************************************************************************
32592 : Fast kernels for small supernodal updates: special rank-1 function.
32593 :
32594 : ! See comments on UpdateSupernode() for information on generic supernodal
32595 : ! updates, including notation used below.
32596 :
32597 : The generic update has following form:
32598 :
32599 : S := S - scatter(U*D*Uc')
32600 :
32601 : This specialized function performs rank-1 update, i.e.:
32602 : * S is a tHeight*A matrix, with A<=4
32603 : * U is a uHeight*1 matrix with unit stride
32604 : * Uc' is a 1*B matrix, with B<=A
32605 : * scatter() scatters rows and columns of U*Uc'
32606 :
32607 : Return value:
32608 : * True if update was applied
32609 : * False if kernel refused to perform an update (quick exit for unsupported
32610 : combinations of input sizes)
32611 :
32612 : -- ALGLIB routine --
32613 : 20.09.2020
32614 : Bochkanov Sergey
32615 : *************************************************************************/
32616 0 : static ae_bool spchol_updatekernelrank1(/* Real */ ae_vector* rowstorage,
32617 : ae_int_t offss,
32618 : ae_int_t twidth,
32619 : ae_int_t trowstride,
32620 : ae_int_t offsu,
32621 : ae_int_t uheight,
32622 : ae_int_t uwidth,
32623 : /* Real */ ae_vector* diagd,
32624 : ae_int_t offsd,
32625 : /* Integer */ ae_vector* raw2smap,
32626 : /* Integer */ ae_vector* superrowidx,
32627 : ae_int_t urbase,
32628 : ae_state *_state)
32629 : {
32630 : ae_int_t k;
32631 : ae_int_t targetrow;
32632 : double d0;
32633 : double u00;
32634 : double u10;
32635 : double u20;
32636 : double u30;
32637 : double uk;
32638 : ae_int_t col0;
32639 : ae_int_t col1;
32640 : ae_int_t col2;
32641 : ae_int_t col3;
32642 : ae_bool result;
32643 :
32644 :
32645 :
32646 : /*
32647 : * Filter out unsupported combinations (ones that are too sparse for the non-SIMD code)
32648 : */
32649 0 : result = ae_false;
32650 0 : if( twidth>4 )
32651 : {
32652 0 : return result;
32653 : }
32654 0 : if( uwidth>4 )
32655 : {
32656 0 : return result;
32657 : }
32658 :
32659 : /*
32660 : * Determine target columns, load update matrix
32661 : */
32662 0 : d0 = diagd->ptr.p_double[offsd];
32663 0 : col0 = 0;
32664 0 : col1 = 0;
32665 0 : col2 = 0;
32666 0 : col3 = 0;
32667 0 : u00 = (double)(0);
32668 0 : u10 = (double)(0);
32669 0 : u20 = (double)(0);
32670 0 : u30 = (double)(0);
32671 0 : if( uwidth>=1 )
32672 : {
32673 0 : col0 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+0]];
32674 0 : u00 = d0*rowstorage->ptr.p_double[offsu+0];
32675 : }
32676 0 : if( uwidth>=2 )
32677 : {
32678 0 : col1 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+1]];
32679 0 : u10 = d0*rowstorage->ptr.p_double[offsu+1];
32680 : }
32681 0 : if( uwidth>=3 )
32682 : {
32683 0 : col2 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+2]];
32684 0 : u20 = d0*rowstorage->ptr.p_double[offsu+2];
32685 : }
32686 0 : if( uwidth>=4 )
32687 : {
32688 0 : col3 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+3]];
32689 0 : u30 = d0*rowstorage->ptr.p_double[offsu+3];
32690 : }
32691 :
32692 : /*
32693 : * Run update
32694 : */
32695 0 : if( uwidth==1 )
32696 : {
32697 0 : for(k=0; k<=uheight-1; k++)
32698 : {
32699 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride;
32700 0 : uk = rowstorage->ptr.p_double[offsu+k];
32701 0 : rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk;
32702 : }
32703 : }
32704 0 : if( uwidth==2 )
32705 : {
32706 0 : for(k=0; k<=uheight-1; k++)
32707 : {
32708 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride;
32709 0 : uk = rowstorage->ptr.p_double[offsu+k];
32710 0 : rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk;
32711 0 : rowstorage->ptr.p_double[targetrow+col1] = rowstorage->ptr.p_double[targetrow+col1]-u10*uk;
32712 : }
32713 : }
32714 0 : if( uwidth==3 )
32715 : {
32716 0 : for(k=0; k<=uheight-1; k++)
32717 : {
32718 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride;
32719 0 : uk = rowstorage->ptr.p_double[offsu+k];
32720 0 : rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk;
32721 0 : rowstorage->ptr.p_double[targetrow+col1] = rowstorage->ptr.p_double[targetrow+col1]-u10*uk;
32722 0 : rowstorage->ptr.p_double[targetrow+col2] = rowstorage->ptr.p_double[targetrow+col2]-u20*uk;
32723 : }
32724 : }
32725 0 : if( uwidth==4 )
32726 : {
32727 0 : for(k=0; k<=uheight-1; k++)
32728 : {
32729 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride;
32730 0 : uk = rowstorage->ptr.p_double[offsu+k];
32731 0 : rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk;
32732 0 : rowstorage->ptr.p_double[targetrow+col1] = rowstorage->ptr.p_double[targetrow+col1]-u10*uk;
32733 0 : rowstorage->ptr.p_double[targetrow+col2] = rowstorage->ptr.p_double[targetrow+col2]-u20*uk;
32734 0 : rowstorage->ptr.p_double[targetrow+col3] = rowstorage->ptr.p_double[targetrow+col3]-u30*uk;
32735 : }
32736 : }
32737 0 : result = ae_true;
32738 0 : return result;
32739 : }
32740 :
32741 :
32742 : /*************************************************************************
32743 : Fast kernels for small supernodal updates: special rank-2 function.
32744 :
32745 : ! See comments on UpdateSupernode() for information on generic supernodal
32746 : ! updates, including notation used below.
32747 :
32748 : The generic update has following form:
32749 :
32750 : S := S - scatter(U*D*Uc')
32751 :
32752 : This specialized function performs rank-2 update, i.e.:
32753 : * S is a tHeight*A matrix, with A<=4
32754 : * U is a uHeight*2 matrix with row stride equal to 2
32755 : * Uc' is a 2*B matrix, with B<=A
32756 : * scatter() scatters rows and columns of U*Uc
32757 :
32758 : Return value:
32759 : * True if update was applied
32760 : * False if kernel refused to perform an update (quick exit for unsupported
32761 : combinations of input sizes)
32762 :
32763 : -- ALGLIB routine --
32764 : 20.09.2020
32765 : Bochkanov Sergey
32766 : *************************************************************************/
32767 0 : static ae_bool spchol_updatekernelrank2(/* Real */ ae_vector* rowstorage,
32768 : ae_int_t offss,
32769 : ae_int_t twidth,
32770 : ae_int_t trowstride,
32771 : ae_int_t offsu,
32772 : ae_int_t uheight,
32773 : ae_int_t uwidth,
32774 : /* Real */ ae_vector* diagd,
32775 : ae_int_t offsd,
32776 : /* Integer */ ae_vector* raw2smap,
32777 : /* Integer */ ae_vector* superrowidx,
32778 : ae_int_t urbase,
32779 : ae_state *_state)
32780 : {
32781 : ae_int_t k;
32782 : ae_int_t targetrow;
32783 : double d0;
32784 : double d1;
32785 : double u00;
32786 : double u10;
32787 : double u20;
32788 : double u30;
32789 : double u01;
32790 : double u11;
32791 : double u21;
32792 : double u31;
32793 : double uk0;
32794 : double uk1;
32795 : ae_int_t col0;
32796 : ae_int_t col1;
32797 : ae_int_t col2;
32798 : ae_int_t col3;
32799 : ae_bool result;
32800 :
32801 :
32802 :
32803 : /*
32804 : * Filter out unsupported combinations (ones that are too sparse for the non-SIMD code)
32805 : */
32806 0 : result = ae_false;
32807 0 : if( twidth>4 )
32808 : {
32809 0 : return result;
32810 : }
32811 0 : if( uwidth>4 )
32812 : {
32813 0 : return result;
32814 : }
32815 :
32816 : /*
32817 : * Determine target columns, load update matrix
32818 : */
32819 0 : d0 = diagd->ptr.p_double[offsd];
32820 0 : d1 = diagd->ptr.p_double[offsd+1];
32821 0 : col0 = 0;
32822 0 : col1 = 0;
32823 0 : col2 = 0;
32824 0 : col3 = 0;
32825 0 : u00 = (double)(0);
32826 0 : u01 = (double)(0);
32827 0 : u10 = (double)(0);
32828 0 : u11 = (double)(0);
32829 0 : u20 = (double)(0);
32830 0 : u21 = (double)(0);
32831 0 : u30 = (double)(0);
32832 0 : u31 = (double)(0);
32833 0 : if( uwidth>=1 )
32834 : {
32835 0 : col0 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+0]];
32836 0 : u00 = d0*rowstorage->ptr.p_double[offsu+0];
32837 0 : u01 = d1*rowstorage->ptr.p_double[offsu+1];
32838 : }
32839 0 : if( uwidth>=2 )
32840 : {
32841 0 : col1 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+1]];
32842 0 : u10 = d0*rowstorage->ptr.p_double[offsu+1*2+0];
32843 0 : u11 = d1*rowstorage->ptr.p_double[offsu+1*2+1];
32844 : }
32845 0 : if( uwidth>=3 )
32846 : {
32847 0 : col2 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+2]];
32848 0 : u20 = d0*rowstorage->ptr.p_double[offsu+2*2+0];
32849 0 : u21 = d1*rowstorage->ptr.p_double[offsu+2*2+1];
32850 : }
32851 0 : if( uwidth>=4 )
32852 : {
32853 0 : col3 = raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+3]];
32854 0 : u30 = d0*rowstorage->ptr.p_double[offsu+3*2+0];
32855 0 : u31 = d1*rowstorage->ptr.p_double[offsu+3*2+1];
32856 : }
32857 :
32858 : /*
32859 : * Run update
32860 : */
32861 0 : if( uwidth==1 )
32862 : {
32863 0 : for(k=0; k<=uheight-1; k++)
32864 : {
32865 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride;
32866 0 : uk0 = rowstorage->ptr.p_double[offsu+2*k+0];
32867 0 : uk1 = rowstorage->ptr.p_double[offsu+2*k+1];
32868 0 : rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk0-u01*uk1;
32869 : }
32870 : }
32871 0 : if( uwidth==2 )
32872 : {
32873 0 : for(k=0; k<=uheight-1; k++)
32874 : {
32875 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride;
32876 0 : uk0 = rowstorage->ptr.p_double[offsu+2*k+0];
32877 0 : uk1 = rowstorage->ptr.p_double[offsu+2*k+1];
32878 0 : rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk0-u01*uk1;
32879 0 : rowstorage->ptr.p_double[targetrow+col1] = rowstorage->ptr.p_double[targetrow+col1]-u10*uk0-u11*uk1;
32880 : }
32881 : }
32882 0 : if( uwidth==3 )
32883 : {
32884 0 : for(k=0; k<=uheight-1; k++)
32885 : {
32886 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride;
32887 0 : uk0 = rowstorage->ptr.p_double[offsu+2*k+0];
32888 0 : uk1 = rowstorage->ptr.p_double[offsu+2*k+1];
32889 0 : rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk0-u01*uk1;
32890 0 : rowstorage->ptr.p_double[targetrow+col1] = rowstorage->ptr.p_double[targetrow+col1]-u10*uk0-u11*uk1;
32891 0 : rowstorage->ptr.p_double[targetrow+col2] = rowstorage->ptr.p_double[targetrow+col2]-u20*uk0-u21*uk1;
32892 : }
32893 : }
32894 0 : if( uwidth==4 )
32895 : {
32896 0 : for(k=0; k<=uheight-1; k++)
32897 : {
32898 0 : targetrow = offss+raw2smap->ptr.p_int[superrowidx->ptr.p_int[urbase+k]]*trowstride;
32899 0 : uk0 = rowstorage->ptr.p_double[offsu+2*k+0];
32900 0 : uk1 = rowstorage->ptr.p_double[offsu+2*k+1];
32901 0 : rowstorage->ptr.p_double[targetrow+col0] = rowstorage->ptr.p_double[targetrow+col0]-u00*uk0-u01*uk1;
32902 0 : rowstorage->ptr.p_double[targetrow+col1] = rowstorage->ptr.p_double[targetrow+col1]-u10*uk0-u11*uk1;
32903 0 : rowstorage->ptr.p_double[targetrow+col2] = rowstorage->ptr.p_double[targetrow+col2]-u20*uk0-u21*uk1;
32904 0 : rowstorage->ptr.p_double[targetrow+col3] = rowstorage->ptr.p_double[targetrow+col3]-u30*uk0-u31*uk1;
32905 : }
32906 : }
32907 0 : result = ae_true;
32908 0 : return result;
32909 : }
32910 :
32911 :
32912 0 : void _spcholanalysis_init(void* _p, ae_state *_state, ae_bool make_automatic)
32913 : {
32914 0 : spcholanalysis *p = (spcholanalysis*)_p;
32915 0 : ae_touch_ptr((void*)p);
32916 0 : ae_vector_init(&p->parentsupernode, 0, DT_INT, _state, make_automatic);
32917 0 : ae_vector_init(&p->supercolrange, 0, DT_INT, _state, make_automatic);
32918 0 : ae_vector_init(&p->superrowridx, 0, DT_INT, _state, make_automatic);
32919 0 : ae_vector_init(&p->superrowidx, 0, DT_INT, _state, make_automatic);
32920 0 : ae_vector_init(&p->fillinperm, 0, DT_INT, _state, make_automatic);
32921 0 : ae_vector_init(&p->invfillinperm, 0, DT_INT, _state, make_automatic);
32922 0 : ae_vector_init(&p->superperm, 0, DT_INT, _state, make_automatic);
32923 0 : ae_vector_init(&p->invsuperperm, 0, DT_INT, _state, make_automatic);
32924 0 : ae_vector_init(&p->effectiveperm, 0, DT_INT, _state, make_automatic);
32925 0 : ae_vector_init(&p->inveffectiveperm, 0, DT_INT, _state, make_automatic);
32926 0 : ae_vector_init(&p->ladjplusr, 0, DT_INT, _state, make_automatic);
32927 0 : ae_vector_init(&p->ladjplus, 0, DT_INT, _state, make_automatic);
32928 0 : ae_vector_init(&p->outrowcounts, 0, DT_INT, _state, make_automatic);
32929 0 : _sparsematrix_init(&p->wrkat, _state, make_automatic);
32930 0 : ae_vector_init(&p->rowstorage, 0, DT_REAL, _state, make_automatic);
32931 0 : ae_vector_init(&p->rowstrides, 0, DT_INT, _state, make_automatic);
32932 0 : ae_vector_init(&p->rowoffsets, 0, DT_INT, _state, make_automatic);
32933 0 : ae_vector_init(&p->diagd, 0, DT_REAL, _state, make_automatic);
32934 0 : ae_vector_init(&p->wrkrows, 0, DT_INT, _state, make_automatic);
32935 0 : ae_vector_init(&p->flagarray, 0, DT_BOOL, _state, make_automatic);
32936 0 : ae_vector_init(&p->tmpparent, 0, DT_INT, _state, make_automatic);
32937 0 : ae_vector_init(&p->node2supernode, 0, DT_INT, _state, make_automatic);
32938 0 : ae_vector_init(&p->u2smap, 0, DT_INT, _state, make_automatic);
32939 0 : ae_vector_init(&p->raw2smap, 0, DT_INT, _state, make_automatic);
32940 0 : _amdbuffer_init(&p->amdtmp, _state, make_automatic);
32941 0 : ae_vector_init(&p->tmp0, 0, DT_INT, _state, make_automatic);
32942 0 : ae_vector_init(&p->tmp1, 0, DT_INT, _state, make_automatic);
32943 0 : ae_vector_init(&p->tmp2, 0, DT_INT, _state, make_automatic);
32944 0 : ae_vector_init(&p->tmp3, 0, DT_INT, _state, make_automatic);
32945 0 : ae_vector_init(&p->tmp4, 0, DT_INT, _state, make_automatic);
32946 0 : _sparsematrix_init(&p->tmpa, _state, make_automatic);
32947 0 : }
32948 :
32949 :
32950 0 : void _spcholanalysis_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
32951 : {
32952 0 : spcholanalysis *dst = (spcholanalysis*)_dst;
32953 0 : spcholanalysis *src = (spcholanalysis*)_src;
32954 0 : dst->tasktype = src->tasktype;
32955 0 : dst->n = src->n;
32956 0 : dst->permtype = src->permtype;
32957 0 : dst->unitd = src->unitd;
32958 0 : dst->modtype = src->modtype;
32959 0 : dst->modparam0 = src->modparam0;
32960 0 : dst->modparam1 = src->modparam1;
32961 0 : dst->modparam2 = src->modparam2;
32962 0 : dst->modparam3 = src->modparam3;
32963 0 : dst->extendeddebug = src->extendeddebug;
32964 0 : dst->dotrace = src->dotrace;
32965 0 : dst->nsuper = src->nsuper;
32966 0 : ae_vector_init_copy(&dst->parentsupernode, &src->parentsupernode, _state, make_automatic);
32967 0 : ae_vector_init_copy(&dst->supercolrange, &src->supercolrange, _state, make_automatic);
32968 0 : ae_vector_init_copy(&dst->superrowridx, &src->superrowridx, _state, make_automatic);
32969 0 : ae_vector_init_copy(&dst->superrowidx, &src->superrowidx, _state, make_automatic);
32970 0 : ae_vector_init_copy(&dst->fillinperm, &src->fillinperm, _state, make_automatic);
32971 0 : ae_vector_init_copy(&dst->invfillinperm, &src->invfillinperm, _state, make_automatic);
32972 0 : ae_vector_init_copy(&dst->superperm, &src->superperm, _state, make_automatic);
32973 0 : ae_vector_init_copy(&dst->invsuperperm, &src->invsuperperm, _state, make_automatic);
32974 0 : ae_vector_init_copy(&dst->effectiveperm, &src->effectiveperm, _state, make_automatic);
32975 0 : ae_vector_init_copy(&dst->inveffectiveperm, &src->inveffectiveperm, _state, make_automatic);
32976 0 : dst->istopologicalordering = src->istopologicalordering;
32977 0 : dst->applypermutationtooutput = src->applypermutationtooutput;
32978 0 : ae_vector_init_copy(&dst->ladjplusr, &src->ladjplusr, _state, make_automatic);
32979 0 : ae_vector_init_copy(&dst->ladjplus, &src->ladjplus, _state, make_automatic);
32980 0 : ae_vector_init_copy(&dst->outrowcounts, &src->outrowcounts, _state, make_automatic);
32981 0 : _sparsematrix_init_copy(&dst->wrkat, &src->wrkat, _state, make_automatic);
32982 0 : ae_vector_init_copy(&dst->rowstorage, &src->rowstorage, _state, make_automatic);
32983 0 : ae_vector_init_copy(&dst->rowstrides, &src->rowstrides, _state, make_automatic);
32984 0 : ae_vector_init_copy(&dst->rowoffsets, &src->rowoffsets, _state, make_automatic);
32985 0 : ae_vector_init_copy(&dst->diagd, &src->diagd, _state, make_automatic);
32986 0 : ae_vector_init_copy(&dst->wrkrows, &src->wrkrows, _state, make_automatic);
32987 0 : ae_vector_init_copy(&dst->flagarray, &src->flagarray, _state, make_automatic);
32988 0 : ae_vector_init_copy(&dst->tmpparent, &src->tmpparent, _state, make_automatic);
32989 0 : ae_vector_init_copy(&dst->node2supernode, &src->node2supernode, _state, make_automatic);
32990 0 : ae_vector_init_copy(&dst->u2smap, &src->u2smap, _state, make_automatic);
32991 0 : ae_vector_init_copy(&dst->raw2smap, &src->raw2smap, _state, make_automatic);
32992 0 : _amdbuffer_init_copy(&dst->amdtmp, &src->amdtmp, _state, make_automatic);
32993 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
32994 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
32995 0 : ae_vector_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic);
32996 0 : ae_vector_init_copy(&dst->tmp3, &src->tmp3, _state, make_automatic);
32997 0 : ae_vector_init_copy(&dst->tmp4, &src->tmp4, _state, make_automatic);
32998 0 : _sparsematrix_init_copy(&dst->tmpa, &src->tmpa, _state, make_automatic);
32999 0 : }
33000 :
33001 :
33002 0 : void _spcholanalysis_clear(void* _p)
33003 : {
33004 0 : spcholanalysis *p = (spcholanalysis*)_p;
33005 0 : ae_touch_ptr((void*)p);
33006 0 : ae_vector_clear(&p->parentsupernode);
33007 0 : ae_vector_clear(&p->supercolrange);
33008 0 : ae_vector_clear(&p->superrowridx);
33009 0 : ae_vector_clear(&p->superrowidx);
33010 0 : ae_vector_clear(&p->fillinperm);
33011 0 : ae_vector_clear(&p->invfillinperm);
33012 0 : ae_vector_clear(&p->superperm);
33013 0 : ae_vector_clear(&p->invsuperperm);
33014 0 : ae_vector_clear(&p->effectiveperm);
33015 0 : ae_vector_clear(&p->inveffectiveperm);
33016 0 : ae_vector_clear(&p->ladjplusr);
33017 0 : ae_vector_clear(&p->ladjplus);
33018 0 : ae_vector_clear(&p->outrowcounts);
33019 0 : _sparsematrix_clear(&p->wrkat);
33020 0 : ae_vector_clear(&p->rowstorage);
33021 0 : ae_vector_clear(&p->rowstrides);
33022 0 : ae_vector_clear(&p->rowoffsets);
33023 0 : ae_vector_clear(&p->diagd);
33024 0 : ae_vector_clear(&p->wrkrows);
33025 0 : ae_vector_clear(&p->flagarray);
33026 0 : ae_vector_clear(&p->tmpparent);
33027 0 : ae_vector_clear(&p->node2supernode);
33028 0 : ae_vector_clear(&p->u2smap);
33029 0 : ae_vector_clear(&p->raw2smap);
33030 0 : _amdbuffer_clear(&p->amdtmp);
33031 0 : ae_vector_clear(&p->tmp0);
33032 0 : ae_vector_clear(&p->tmp1);
33033 0 : ae_vector_clear(&p->tmp2);
33034 0 : ae_vector_clear(&p->tmp3);
33035 0 : ae_vector_clear(&p->tmp4);
33036 0 : _sparsematrix_clear(&p->tmpa);
33037 0 : }
33038 :
33039 :
33040 0 : void _spcholanalysis_destroy(void* _p)
33041 : {
33042 0 : spcholanalysis *p = (spcholanalysis*)_p;
33043 0 : ae_touch_ptr((void*)p);
33044 0 : ae_vector_destroy(&p->parentsupernode);
33045 0 : ae_vector_destroy(&p->supercolrange);
33046 0 : ae_vector_destroy(&p->superrowridx);
33047 0 : ae_vector_destroy(&p->superrowidx);
33048 0 : ae_vector_destroy(&p->fillinperm);
33049 0 : ae_vector_destroy(&p->invfillinperm);
33050 0 : ae_vector_destroy(&p->superperm);
33051 0 : ae_vector_destroy(&p->invsuperperm);
33052 0 : ae_vector_destroy(&p->effectiveperm);
33053 0 : ae_vector_destroy(&p->inveffectiveperm);
33054 0 : ae_vector_destroy(&p->ladjplusr);
33055 0 : ae_vector_destroy(&p->ladjplus);
33056 0 : ae_vector_destroy(&p->outrowcounts);
33057 0 : _sparsematrix_destroy(&p->wrkat);
33058 0 : ae_vector_destroy(&p->rowstorage);
33059 0 : ae_vector_destroy(&p->rowstrides);
33060 0 : ae_vector_destroy(&p->rowoffsets);
33061 0 : ae_vector_destroy(&p->diagd);
33062 0 : ae_vector_destroy(&p->wrkrows);
33063 0 : ae_vector_destroy(&p->flagarray);
33064 0 : ae_vector_destroy(&p->tmpparent);
33065 0 : ae_vector_destroy(&p->node2supernode);
33066 0 : ae_vector_destroy(&p->u2smap);
33067 0 : ae_vector_destroy(&p->raw2smap);
33068 0 : _amdbuffer_destroy(&p->amdtmp);
33069 0 : ae_vector_destroy(&p->tmp0);
33070 0 : ae_vector_destroy(&p->tmp1);
33071 0 : ae_vector_destroy(&p->tmp2);
33072 0 : ae_vector_destroy(&p->tmp3);
33073 0 : ae_vector_destroy(&p->tmp4);
33074 0 : _sparsematrix_destroy(&p->tmpa);
33075 0 : }
33076 :
33077 :
33078 : #endif
33079 : #if defined(AE_COMPILE_MATGEN) || !defined(AE_PARTIAL_BUILD)
33080 :
33081 :
33082 : /*************************************************************************
33083 : Generation of a random uniformly distributed (Haar) orthogonal matrix
33084 :
33085 : INPUT PARAMETERS:
33086 : N - matrix size, N>=1
33087 :
33088 : OUTPUT PARAMETERS:
33089 : A - orthogonal NxN matrix, array[0..N-1,0..N-1]
33090 :
33091 : NOTE: this function uses algorithm described in Stewart, G. W. (1980),
33092 : "The Efficient Generation of Random Orthogonal Matrices with an
33093 : Application to Condition Estimators".
33094 :
33095 : Speaking short, to generate an (N+1)x(N+1) orthogonal matrix, it:
33096 : * takes an NxN one
33097 : * takes uniformly distributed unit vector of dimension N+1.
33098 : * constructs a Householder reflection from the vector, then applies
33099 : it to the smaller matrix (embedded in the larger size with a 1 at
33100 : the bottom right corner).
33101 :
33102 : -- ALGLIB routine --
33103 : 04.12.2009
33104 : Bochkanov Sergey
33105 : *************************************************************************/
33106 0 : void rmatrixrndorthogonal(ae_int_t n,
33107 : /* Real */ ae_matrix* a,
33108 : ae_state *_state)
33109 : {
33110 : ae_int_t i;
33111 : ae_int_t j;
33112 :
33113 0 : ae_matrix_clear(a);
33114 :
33115 0 : ae_assert(n>=1, "RMatrixRndOrthogonal: N<1!", _state);
33116 0 : ae_matrix_set_length(a, n, n, _state);
33117 0 : for(i=0; i<=n-1; i++)
33118 : {
33119 0 : for(j=0; j<=n-1; j++)
33120 : {
33121 0 : if( i==j )
33122 : {
33123 0 : a->ptr.pp_double[i][j] = (double)(1);
33124 : }
33125 : else
33126 : {
33127 0 : a->ptr.pp_double[i][j] = (double)(0);
33128 : }
33129 : }
33130 : }
33131 0 : rmatrixrndorthogonalfromtheright(a, n, n, _state);
33132 0 : }
33133 :
33134 :
33135 : /*************************************************************************
33136 : Generation of random NxN matrix with given condition number and norm2(A)=1
33137 :
33138 : INPUT PARAMETERS:
33139 : N - matrix size
33140 : C - condition number (in 2-norm)
33141 :
33142 : OUTPUT PARAMETERS:
33143 : A - random matrix with norm2(A)=1 and cond(A)=C
33144 :
33145 : -- ALGLIB routine --
33146 : 04.12.2009
33147 : Bochkanov Sergey
33148 : *************************************************************************/
33149 0 : void rmatrixrndcond(ae_int_t n,
33150 : double c,
33151 : /* Real */ ae_matrix* a,
33152 : ae_state *_state)
33153 : {
33154 : ae_frame _frame_block;
33155 : ae_int_t i;
33156 : ae_int_t j;
33157 : double l1;
33158 : double l2;
33159 : hqrndstate rs;
33160 :
33161 0 : ae_frame_make(_state, &_frame_block);
33162 0 : memset(&rs, 0, sizeof(rs));
33163 0 : ae_matrix_clear(a);
33164 0 : _hqrndstate_init(&rs, _state, ae_true);
33165 :
33166 0 : ae_assert(n>=1&&ae_fp_greater_eq(c,(double)(1)), "RMatrixRndCond: N<1 or C<1!", _state);
33167 0 : ae_matrix_set_length(a, n, n, _state);
33168 0 : if( n==1 )
33169 : {
33170 :
33171 : /*
33172 : * special case
33173 : */
33174 0 : a->ptr.pp_double[0][0] = (double)(2*ae_randominteger(2, _state)-1);
33175 0 : ae_frame_leave(_state);
33176 0 : return;
33177 : }
33178 0 : hqrndrandomize(&rs, _state);
33179 0 : l1 = (double)(0);
33180 0 : l2 = ae_log(1/c, _state);
33181 0 : for(i=0; i<=n-1; i++)
33182 : {
33183 0 : for(j=0; j<=n-1; j++)
33184 : {
33185 0 : a->ptr.pp_double[i][j] = (double)(0);
33186 : }
33187 : }
33188 0 : a->ptr.pp_double[0][0] = ae_exp(l1, _state);
33189 0 : for(i=1; i<=n-2; i++)
33190 : {
33191 0 : a->ptr.pp_double[i][i] = ae_exp(hqrnduniformr(&rs, _state)*(l2-l1)+l1, _state);
33192 : }
33193 0 : a->ptr.pp_double[n-1][n-1] = ae_exp(l2, _state);
33194 0 : rmatrixrndorthogonalfromtheleft(a, n, n, _state);
33195 0 : rmatrixrndorthogonalfromtheright(a, n, n, _state);
33196 0 : ae_frame_leave(_state);
33197 : }
33198 :
33199 :
33200 : /*************************************************************************
33201 : Generation of a random Haar distributed orthogonal complex matrix
33202 :
33203 : INPUT PARAMETERS:
33204 : N - matrix size, N>=1
33205 :
33206 : OUTPUT PARAMETERS:
33207 : A - orthogonal NxN matrix, array[0..N-1,0..N-1]
33208 :
33209 : NOTE: this function uses algorithm described in Stewart, G. W. (1980),
33210 : "The Efficient Generation of Random Orthogonal Matrices with an
33211 : Application to Condition Estimators".
33212 :
33213 : Speaking short, to generate an (N+1)x(N+1) orthogonal matrix, it:
33214 : * takes an NxN one
33215 : * takes uniformly distributed unit vector of dimension N+1.
33216 : * constructs a Householder reflection from the vector, then applies
33217 : it to the smaller matrix (embedded in the larger size with a 1 at
33218 : the bottom right corner).
33219 :
33220 : -- ALGLIB routine --
33221 : 04.12.2009
33222 : Bochkanov Sergey
33223 : *************************************************************************/
33224 0 : void cmatrixrndorthogonal(ae_int_t n,
33225 : /* Complex */ ae_matrix* a,
33226 : ae_state *_state)
33227 : {
33228 : ae_int_t i;
33229 : ae_int_t j;
33230 :
33231 0 : ae_matrix_clear(a);
33232 :
33233 0 : ae_assert(n>=1, "CMatrixRndOrthogonal: N<1!", _state);
33234 0 : ae_matrix_set_length(a, n, n, _state);
33235 0 : for(i=0; i<=n-1; i++)
33236 : {
33237 0 : for(j=0; j<=n-1; j++)
33238 : {
33239 0 : if( i==j )
33240 : {
33241 0 : a->ptr.pp_complex[i][j] = ae_complex_from_i(1);
33242 : }
33243 : else
33244 : {
33245 0 : a->ptr.pp_complex[i][j] = ae_complex_from_i(0);
33246 : }
33247 : }
33248 : }
33249 0 : cmatrixrndorthogonalfromtheright(a, n, n, _state);
33250 0 : }
33251 :
33252 :
33253 : /*************************************************************************
33254 : Generation of random NxN complex matrix with given condition number C and
33255 : norm2(A)=1
33256 :
33257 : INPUT PARAMETERS:
33258 : N - matrix size
33259 : C - condition number (in 2-norm)
33260 :
33261 : OUTPUT PARAMETERS:
33262 : A - random matrix with norm2(A)=1 and cond(A)=C
33263 :
33264 : -- ALGLIB routine --
33265 : 04.12.2009
33266 : Bochkanov Sergey
33267 : *************************************************************************/
33268 0 : void cmatrixrndcond(ae_int_t n,
33269 : double c,
33270 : /* Complex */ ae_matrix* a,
33271 : ae_state *_state)
33272 : {
33273 : ae_frame _frame_block;
33274 : ae_int_t i;
33275 : ae_int_t j;
33276 : double l1;
33277 : double l2;
33278 : hqrndstate state;
33279 : ae_complex v;
33280 :
33281 0 : ae_frame_make(_state, &_frame_block);
33282 0 : memset(&state, 0, sizeof(state));
33283 0 : ae_matrix_clear(a);
33284 0 : _hqrndstate_init(&state, _state, ae_true);
33285 :
33286 0 : ae_assert(n>=1&&ae_fp_greater_eq(c,(double)(1)), "CMatrixRndCond: N<1 or C<1!", _state);
33287 0 : ae_matrix_set_length(a, n, n, _state);
33288 0 : if( n==1 )
33289 : {
33290 :
33291 : /*
33292 : * special case
33293 : */
33294 0 : hqrndrandomize(&state, _state);
33295 0 : hqrndunit2(&state, &v.x, &v.y, _state);
33296 0 : a->ptr.pp_complex[0][0] = v;
33297 0 : ae_frame_leave(_state);
33298 0 : return;
33299 : }
33300 0 : hqrndrandomize(&state, _state);
33301 0 : l1 = (double)(0);
33302 0 : l2 = ae_log(1/c, _state);
33303 0 : for(i=0; i<=n-1; i++)
33304 : {
33305 0 : for(j=0; j<=n-1; j++)
33306 : {
33307 0 : a->ptr.pp_complex[i][j] = ae_complex_from_i(0);
33308 : }
33309 : }
33310 0 : a->ptr.pp_complex[0][0] = ae_complex_from_d(ae_exp(l1, _state));
33311 0 : for(i=1; i<=n-2; i++)
33312 : {
33313 0 : a->ptr.pp_complex[i][i] = ae_complex_from_d(ae_exp(hqrnduniformr(&state, _state)*(l2-l1)+l1, _state));
33314 : }
33315 0 : a->ptr.pp_complex[n-1][n-1] = ae_complex_from_d(ae_exp(l2, _state));
33316 0 : cmatrixrndorthogonalfromtheleft(a, n, n, _state);
33317 0 : cmatrixrndorthogonalfromtheright(a, n, n, _state);
33318 0 : ae_frame_leave(_state);
33319 : }
33320 :
33321 :
33322 : /*************************************************************************
33323 : Generation of random NxN symmetric matrix with given condition number and
33324 : norm2(A)=1
33325 :
33326 : INPUT PARAMETERS:
33327 : N - matrix size
33328 : C - condition number (in 2-norm)
33329 :
33330 : OUTPUT PARAMETERS:
33331 : A - random matrix with norm2(A)=1 and cond(A)=C
33332 :
33333 : -- ALGLIB routine --
33334 : 04.12.2009
33335 : Bochkanov Sergey
33336 : *************************************************************************/
33337 0 : void smatrixrndcond(ae_int_t n,
33338 : double c,
33339 : /* Real */ ae_matrix* a,
33340 : ae_state *_state)
33341 : {
33342 : ae_frame _frame_block;
33343 : ae_int_t i;
33344 : ae_int_t j;
33345 : double l1;
33346 : double l2;
33347 : hqrndstate rs;
33348 :
33349 0 : ae_frame_make(_state, &_frame_block);
33350 0 : memset(&rs, 0, sizeof(rs));
33351 0 : ae_matrix_clear(a);
33352 0 : _hqrndstate_init(&rs, _state, ae_true);
33353 :
33354 0 : ae_assert(n>=1&&ae_fp_greater_eq(c,(double)(1)), "SMatrixRndCond: N<1 or C<1!", _state);
33355 0 : ae_matrix_set_length(a, n, n, _state);
33356 0 : if( n==1 )
33357 : {
33358 :
33359 : /*
33360 : * special case
33361 : */
33362 0 : a->ptr.pp_double[0][0] = (double)(2*ae_randominteger(2, _state)-1);
33363 0 : ae_frame_leave(_state);
33364 0 : return;
33365 : }
33366 :
33367 : /*
33368 : * Prepare matrix
33369 : */
33370 0 : hqrndrandomize(&rs, _state);
33371 0 : l1 = (double)(0);
33372 0 : l2 = ae_log(1/c, _state);
33373 0 : for(i=0; i<=n-1; i++)
33374 : {
33375 0 : for(j=0; j<=n-1; j++)
33376 : {
33377 0 : a->ptr.pp_double[i][j] = (double)(0);
33378 : }
33379 : }
33380 0 : a->ptr.pp_double[0][0] = ae_exp(l1, _state);
33381 0 : for(i=1; i<=n-2; i++)
33382 : {
33383 0 : a->ptr.pp_double[i][i] = (2*hqrnduniformi(&rs, 2, _state)-1)*ae_exp(hqrnduniformr(&rs, _state)*(l2-l1)+l1, _state);
33384 : }
33385 0 : a->ptr.pp_double[n-1][n-1] = ae_exp(l2, _state);
33386 :
33387 : /*
33388 : * Multiply
33389 : */
33390 0 : smatrixrndmultiply(a, n, _state);
33391 0 : ae_frame_leave(_state);
33392 : }
33393 :
33394 :
33395 : /*************************************************************************
33396 : Generation of random NxN symmetric positive definite matrix with given
33397 : condition number and norm2(A)=1
33398 :
33399 : INPUT PARAMETERS:
33400 : N - matrix size
33401 : C - condition number (in 2-norm)
33402 :
33403 : OUTPUT PARAMETERS:
33404 : A - random SPD matrix with norm2(A)=1 and cond(A)=C
33405 :
33406 : -- ALGLIB routine --
33407 : 04.12.2009
33408 : Bochkanov Sergey
33409 : *************************************************************************/
33410 0 : void spdmatrixrndcond(ae_int_t n,
33411 : double c,
33412 : /* Real */ ae_matrix* a,
33413 : ae_state *_state)
33414 : {
33415 : ae_frame _frame_block;
33416 : ae_int_t i;
33417 : ae_int_t j;
33418 : double l1;
33419 : double l2;
33420 : hqrndstate rs;
33421 :
33422 0 : ae_frame_make(_state, &_frame_block);
33423 0 : memset(&rs, 0, sizeof(rs));
33424 0 : ae_matrix_clear(a);
33425 0 : _hqrndstate_init(&rs, _state, ae_true);
33426 :
33427 :
33428 : /*
33429 : * Special cases
33430 : */
33431 0 : if( n<=0||ae_fp_less(c,(double)(1)) )
33432 : {
33433 0 : ae_frame_leave(_state);
33434 0 : return;
33435 : }
33436 0 : ae_matrix_set_length(a, n, n, _state);
33437 0 : if( n==1 )
33438 : {
33439 0 : a->ptr.pp_double[0][0] = (double)(1);
33440 0 : ae_frame_leave(_state);
33441 0 : return;
33442 : }
33443 :
33444 : /*
33445 : * Prepare matrix
33446 : */
33447 0 : hqrndrandomize(&rs, _state);
33448 0 : l1 = (double)(0);
33449 0 : l2 = ae_log(1/c, _state);
33450 0 : for(i=0; i<=n-1; i++)
33451 : {
33452 0 : for(j=0; j<=n-1; j++)
33453 : {
33454 0 : a->ptr.pp_double[i][j] = (double)(0);
33455 : }
33456 : }
33457 0 : a->ptr.pp_double[0][0] = ae_exp(l1, _state);
33458 0 : for(i=1; i<=n-2; i++)
33459 : {
33460 0 : a->ptr.pp_double[i][i] = ae_exp(hqrnduniformr(&rs, _state)*(l2-l1)+l1, _state);
33461 : }
33462 0 : a->ptr.pp_double[n-1][n-1] = ae_exp(l2, _state);
33463 :
33464 : /*
33465 : * Multiply
33466 : */
33467 0 : smatrixrndmultiply(a, n, _state);
33468 0 : ae_frame_leave(_state);
33469 : }
33470 :
33471 :
33472 : /*************************************************************************
33473 : Generation of random NxN Hermitian matrix with given condition number and
33474 : norm2(A)=1
33475 :
33476 : INPUT PARAMETERS:
33477 : N - matrix size
33478 : C - condition number (in 2-norm)
33479 :
33480 : OUTPUT PARAMETERS:
33481 : A - random matrix with norm2(A)=1 and cond(A)=C
33482 :
33483 : -- ALGLIB routine --
33484 : 04.12.2009
33485 : Bochkanov Sergey
33486 : *************************************************************************/
33487 0 : void hmatrixrndcond(ae_int_t n,
33488 : double c,
33489 : /* Complex */ ae_matrix* a,
33490 : ae_state *_state)
33491 : {
33492 : ae_frame _frame_block;
33493 : ae_int_t i;
33494 : ae_int_t j;
33495 : double l1;
33496 : double l2;
33497 : hqrndstate rs;
33498 :
33499 0 : ae_frame_make(_state, &_frame_block);
33500 0 : memset(&rs, 0, sizeof(rs));
33501 0 : ae_matrix_clear(a);
33502 0 : _hqrndstate_init(&rs, _state, ae_true);
33503 :
33504 0 : ae_assert(n>=1&&ae_fp_greater_eq(c,(double)(1)), "HMatrixRndCond: N<1 or C<1!", _state);
33505 0 : ae_matrix_set_length(a, n, n, _state);
33506 0 : if( n==1 )
33507 : {
33508 :
33509 : /*
33510 : * special case
33511 : */
33512 0 : a->ptr.pp_complex[0][0] = ae_complex_from_i(2*ae_randominteger(2, _state)-1);
33513 0 : ae_frame_leave(_state);
33514 0 : return;
33515 : }
33516 :
33517 : /*
33518 : * Prepare matrix
33519 : */
33520 0 : hqrndrandomize(&rs, _state);
33521 0 : l1 = (double)(0);
33522 0 : l2 = ae_log(1/c, _state);
33523 0 : for(i=0; i<=n-1; i++)
33524 : {
33525 0 : for(j=0; j<=n-1; j++)
33526 : {
33527 0 : a->ptr.pp_complex[i][j] = ae_complex_from_i(0);
33528 : }
33529 : }
33530 0 : a->ptr.pp_complex[0][0] = ae_complex_from_d(ae_exp(l1, _state));
33531 0 : for(i=1; i<=n-2; i++)
33532 : {
33533 0 : a->ptr.pp_complex[i][i] = ae_complex_from_d((2*hqrnduniformi(&rs, 2, _state)-1)*ae_exp(hqrnduniformr(&rs, _state)*(l2-l1)+l1, _state));
33534 : }
33535 0 : a->ptr.pp_complex[n-1][n-1] = ae_complex_from_d(ae_exp(l2, _state));
33536 :
33537 : /*
33538 : * Multiply
33539 : */
33540 0 : hmatrixrndmultiply(a, n, _state);
33541 :
33542 : /*
33543 : * post-process to ensure that matrix diagonal is real
33544 : */
33545 0 : for(i=0; i<=n-1; i++)
33546 : {
33547 0 : a->ptr.pp_complex[i][i].y = (double)(0);
33548 : }
33549 0 : ae_frame_leave(_state);
33550 : }
33551 :
33552 :
33553 : /*************************************************************************
33554 : Generation of random NxN Hermitian positive definite matrix with given
33555 : condition number and norm2(A)=1
33556 :
33557 : INPUT PARAMETERS:
33558 : N - matrix size
33559 : C - condition number (in 2-norm)
33560 :
33561 : OUTPUT PARAMETERS:
33562 : A - random HPD matrix with norm2(A)=1 and cond(A)=C
33563 :
33564 : -- ALGLIB routine --
33565 : 04.12.2009
33566 : Bochkanov Sergey
33567 : *************************************************************************/
33568 0 : void hpdmatrixrndcond(ae_int_t n,
33569 : double c,
33570 : /* Complex */ ae_matrix* a,
33571 : ae_state *_state)
33572 : {
33573 : ae_frame _frame_block;
33574 : ae_int_t i;
33575 : ae_int_t j;
33576 : double l1;
33577 : double l2;
33578 : hqrndstate rs;
33579 :
33580 0 : ae_frame_make(_state, &_frame_block);
33581 0 : memset(&rs, 0, sizeof(rs));
33582 0 : ae_matrix_clear(a);
33583 0 : _hqrndstate_init(&rs, _state, ae_true);
33584 :
33585 :
33586 : /*
33587 : * Special cases
33588 : */
33589 0 : if( n<=0||ae_fp_less(c,(double)(1)) )
33590 : {
33591 0 : ae_frame_leave(_state);
33592 0 : return;
33593 : }
33594 0 : ae_matrix_set_length(a, n, n, _state);
33595 0 : if( n==1 )
33596 : {
33597 0 : a->ptr.pp_complex[0][0] = ae_complex_from_i(1);
33598 0 : ae_frame_leave(_state);
33599 0 : return;
33600 : }
33601 :
33602 : /*
33603 : * Prepare matrix
33604 : */
33605 0 : hqrndrandomize(&rs, _state);
33606 0 : l1 = (double)(0);
33607 0 : l2 = ae_log(1/c, _state);
33608 0 : for(i=0; i<=n-1; i++)
33609 : {
33610 0 : for(j=0; j<=n-1; j++)
33611 : {
33612 0 : a->ptr.pp_complex[i][j] = ae_complex_from_i(0);
33613 : }
33614 : }
33615 0 : a->ptr.pp_complex[0][0] = ae_complex_from_d(ae_exp(l1, _state));
33616 0 : for(i=1; i<=n-2; i++)
33617 : {
33618 0 : a->ptr.pp_complex[i][i] = ae_complex_from_d(ae_exp(hqrnduniformr(&rs, _state)*(l2-l1)+l1, _state));
33619 : }
33620 0 : a->ptr.pp_complex[n-1][n-1] = ae_complex_from_d(ae_exp(l2, _state));
33621 :
33622 : /*
33623 : * Multiply
33624 : */
33625 0 : hmatrixrndmultiply(a, n, _state);
33626 :
33627 : /*
33628 : * post-process to ensure that matrix diagonal is real
33629 : */
33630 0 : for(i=0; i<=n-1; i++)
33631 : {
33632 0 : a->ptr.pp_complex[i][i].y = (double)(0);
33633 : }
33634 0 : ae_frame_leave(_state);
33635 : }
33636 :
33637 :
33638 : /*************************************************************************
33639 : Multiplication of MxN matrix by NxN random Haar distributed orthogonal matrix
33640 :
33641 : INPUT PARAMETERS:
33642 : A - matrix, array[0..M-1, 0..N-1]
33643 : M, N- matrix size
33644 :
33645 : OUTPUT PARAMETERS:
33646 : A - A*Q, where Q is random NxN orthogonal matrix
33647 :
33648 : -- ALGLIB routine --
33649 : 04.12.2009
33650 : Bochkanov Sergey
33651 : *************************************************************************/
33652 0 : void rmatrixrndorthogonalfromtheright(/* Real */ ae_matrix* a,
33653 : ae_int_t m,
33654 : ae_int_t n,
33655 : ae_state *_state)
33656 : {
33657 : ae_frame _frame_block;
33658 : double tau;
33659 : double lambdav;
33660 : ae_int_t s;
33661 : ae_int_t i;
33662 : double u1;
33663 : double u2;
33664 : ae_vector w;
33665 : ae_vector v;
33666 : hqrndstate state;
33667 :
33668 0 : ae_frame_make(_state, &_frame_block);
33669 0 : memset(&w, 0, sizeof(w));
33670 0 : memset(&v, 0, sizeof(v));
33671 0 : memset(&state, 0, sizeof(state));
33672 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
33673 0 : ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
33674 0 : _hqrndstate_init(&state, _state, ae_true);
33675 :
33676 0 : ae_assert(n>=1&&m>=1, "RMatrixRndOrthogonalFromTheRight: N<1 or M<1!", _state);
33677 0 : if( n==1 )
33678 : {
33679 :
33680 : /*
33681 : * Special case
33682 : */
33683 0 : tau = (double)(2*ae_randominteger(2, _state)-1);
33684 0 : for(i=0; i<=m-1; i++)
33685 : {
33686 0 : a->ptr.pp_double[i][0] = a->ptr.pp_double[i][0]*tau;
33687 : }
33688 0 : ae_frame_leave(_state);
33689 0 : return;
33690 : }
33691 :
33692 : /*
33693 : * General case.
33694 : * First pass.
33695 : */
33696 0 : ae_vector_set_length(&w, m, _state);
33697 0 : ae_vector_set_length(&v, n+1, _state);
33698 0 : hqrndrandomize(&state, _state);
33699 0 : for(s=2; s<=n; s++)
33700 : {
33701 :
33702 : /*
33703 : * Prepare random normal v
33704 : */
33705 0 : do
33706 : {
33707 0 : i = 1;
33708 0 : while(i<=s)
33709 : {
33710 0 : hqrndnormal2(&state, &u1, &u2, _state);
33711 0 : v.ptr.p_double[i] = u1;
33712 0 : if( i+1<=s )
33713 : {
33714 0 : v.ptr.p_double[i+1] = u2;
33715 : }
33716 0 : i = i+2;
33717 : }
33718 0 : lambdav = ae_v_dotproduct(&v.ptr.p_double[1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,s));
33719 : }
33720 0 : while(ae_fp_eq(lambdav,(double)(0)));
33721 :
33722 : /*
33723 : * Prepare and apply reflection
33724 : */
33725 0 : generatereflection(&v, s, &tau, _state);
33726 0 : v.ptr.p_double[1] = (double)(1);
33727 0 : applyreflectionfromtheright(a, tau, &v, 0, m-1, n-s, n-1, &w, _state);
33728 : }
33729 :
33730 : /*
33731 : * Second pass.
33732 : */
33733 0 : for(i=0; i<=n-1; i++)
33734 : {
33735 0 : tau = (double)(2*hqrnduniformi(&state, 2, _state)-1);
33736 0 : ae_v_muld(&a->ptr.pp_double[0][i], a->stride, ae_v_len(0,m-1), tau);
33737 : }
33738 0 : ae_frame_leave(_state);
33739 : }
33740 :
33741 :
33742 : /*************************************************************************
33743 : Multiplication of MxN matrix by MxM random Haar distributed orthogonal matrix
33744 :
33745 : INPUT PARAMETERS:
33746 : A - matrix, array[0..M-1, 0..N-1]
33747 : M, N- matrix size
33748 :
33749 : OUTPUT PARAMETERS:
33750 : A - Q*A, where Q is random MxM orthogonal matrix
33751 :
33752 : -- ALGLIB routine --
33753 : 04.12.2009
33754 : Bochkanov Sergey
33755 : *************************************************************************/
33756 0 : void rmatrixrndorthogonalfromtheleft(/* Real */ ae_matrix* a,
33757 : ae_int_t m,
33758 : ae_int_t n,
33759 : ae_state *_state)
33760 : {
33761 : ae_frame _frame_block;
33762 : double tau;
33763 : double lambdav;
33764 : ae_int_t s;
33765 : ae_int_t i;
33766 : ae_int_t j;
33767 : double u1;
33768 : double u2;
33769 : ae_vector w;
33770 : ae_vector v;
33771 : hqrndstate state;
33772 :
33773 0 : ae_frame_make(_state, &_frame_block);
33774 0 : memset(&w, 0, sizeof(w));
33775 0 : memset(&v, 0, sizeof(v));
33776 0 : memset(&state, 0, sizeof(state));
33777 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
33778 0 : ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
33779 0 : _hqrndstate_init(&state, _state, ae_true);
33780 :
33781 0 : ae_assert(n>=1&&m>=1, "RMatrixRndOrthogonalFromTheRight: N<1 or M<1!", _state);
33782 0 : if( m==1 )
33783 : {
33784 :
33785 : /*
33786 : * special case
33787 : */
33788 0 : tau = (double)(2*ae_randominteger(2, _state)-1);
33789 0 : for(j=0; j<=n-1; j++)
33790 : {
33791 0 : a->ptr.pp_double[0][j] = a->ptr.pp_double[0][j]*tau;
33792 : }
33793 0 : ae_frame_leave(_state);
33794 0 : return;
33795 : }
33796 :
33797 : /*
33798 : * General case.
33799 : * First pass.
33800 : */
33801 0 : ae_vector_set_length(&w, n, _state);
33802 0 : ae_vector_set_length(&v, m+1, _state);
33803 0 : hqrndrandomize(&state, _state);
33804 0 : for(s=2; s<=m; s++)
33805 : {
33806 :
33807 : /*
33808 : * Prepare random normal v
33809 : */
33810 0 : do
33811 : {
33812 0 : i = 1;
33813 0 : while(i<=s)
33814 : {
33815 0 : hqrndnormal2(&state, &u1, &u2, _state);
33816 0 : v.ptr.p_double[i] = u1;
33817 0 : if( i+1<=s )
33818 : {
33819 0 : v.ptr.p_double[i+1] = u2;
33820 : }
33821 0 : i = i+2;
33822 : }
33823 0 : lambdav = ae_v_dotproduct(&v.ptr.p_double[1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,s));
33824 : }
33825 0 : while(ae_fp_eq(lambdav,(double)(0)));
33826 :
33827 : /*
33828 : * Prepare and apply reflection
33829 : */
33830 0 : generatereflection(&v, s, &tau, _state);
33831 0 : v.ptr.p_double[1] = (double)(1);
33832 0 : applyreflectionfromtheleft(a, tau, &v, m-s, m-1, 0, n-1, &w, _state);
33833 : }
33834 :
33835 : /*
33836 : * Second pass.
33837 : */
33838 0 : for(i=0; i<=m-1; i++)
33839 : {
33840 0 : tau = (double)(2*hqrnduniformi(&state, 2, _state)-1);
33841 0 : ae_v_muld(&a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), tau);
33842 : }
33843 0 : ae_frame_leave(_state);
33844 : }
33845 :
33846 :
33847 : /*************************************************************************
33848 : Multiplication of MxN complex matrix by NxN random Haar distributed
33849 : complex orthogonal matrix
33850 :
33851 : INPUT PARAMETERS:
33852 : A - matrix, array[0..M-1, 0..N-1]
33853 : M, N- matrix size
33854 :
33855 : OUTPUT PARAMETERS:
33856 : A - A*Q, where Q is random NxN orthogonal matrix
33857 :
33858 : -- ALGLIB routine --
33859 : 04.12.2009
33860 : Bochkanov Sergey
33861 : *************************************************************************/
33862 0 : void cmatrixrndorthogonalfromtheright(/* Complex */ ae_matrix* a,
33863 : ae_int_t m,
33864 : ae_int_t n,
33865 : ae_state *_state)
33866 : {
33867 : ae_frame _frame_block;
33868 : ae_complex lambdav;
33869 : ae_complex tau;
33870 : ae_int_t s;
33871 : ae_int_t i;
33872 : ae_vector w;
33873 : ae_vector v;
33874 : hqrndstate state;
33875 :
33876 0 : ae_frame_make(_state, &_frame_block);
33877 0 : memset(&w, 0, sizeof(w));
33878 0 : memset(&v, 0, sizeof(v));
33879 0 : memset(&state, 0, sizeof(state));
33880 0 : ae_vector_init(&w, 0, DT_COMPLEX, _state, ae_true);
33881 0 : ae_vector_init(&v, 0, DT_COMPLEX, _state, ae_true);
33882 0 : _hqrndstate_init(&state, _state, ae_true);
33883 :
33884 0 : ae_assert(n>=1&&m>=1, "CMatrixRndOrthogonalFromTheRight: N<1 or M<1!", _state);
33885 0 : if( n==1 )
33886 : {
33887 :
33888 : /*
33889 : * Special case
33890 : */
33891 0 : hqrndrandomize(&state, _state);
33892 0 : hqrndunit2(&state, &tau.x, &tau.y, _state);
33893 0 : for(i=0; i<=m-1; i++)
33894 : {
33895 0 : a->ptr.pp_complex[i][0] = ae_c_mul(a->ptr.pp_complex[i][0],tau);
33896 : }
33897 0 : ae_frame_leave(_state);
33898 0 : return;
33899 : }
33900 :
33901 : /*
33902 : * General case.
33903 : * First pass.
33904 : */
33905 0 : ae_vector_set_length(&w, m, _state);
33906 0 : ae_vector_set_length(&v, n+1, _state);
33907 0 : hqrndrandomize(&state, _state);
33908 0 : for(s=2; s<=n; s++)
33909 : {
33910 :
33911 : /*
33912 : * Prepare random normal v
33913 : */
33914 0 : do
33915 : {
33916 0 : for(i=1; i<=s; i++)
33917 : {
33918 0 : hqrndnormal2(&state, &tau.x, &tau.y, _state);
33919 0 : v.ptr.p_complex[i] = tau;
33920 : }
33921 0 : lambdav = ae_v_cdotproduct(&v.ptr.p_complex[1], 1, "N", &v.ptr.p_complex[1], 1, "Conj", ae_v_len(1,s));
33922 : }
33923 0 : while(ae_c_eq_d(lambdav,(double)(0)));
33924 :
33925 : /*
33926 : * Prepare and apply reflection
33927 : */
33928 0 : complexgeneratereflection(&v, s, &tau, _state);
33929 0 : v.ptr.p_complex[1] = ae_complex_from_i(1);
33930 0 : complexapplyreflectionfromtheright(a, tau, &v, 0, m-1, n-s, n-1, &w, _state);
33931 : }
33932 :
33933 : /*
33934 : * Second pass.
33935 : */
33936 0 : for(i=0; i<=n-1; i++)
33937 : {
33938 0 : hqrndunit2(&state, &tau.x, &tau.y, _state);
33939 0 : ae_v_cmulc(&a->ptr.pp_complex[0][i], a->stride, ae_v_len(0,m-1), tau);
33940 : }
33941 0 : ae_frame_leave(_state);
33942 : }
33943 :
33944 :
33945 : /*************************************************************************
33946 : Multiplication of MxN complex matrix by MxM random Haar distributed
33947 : complex orthogonal matrix
33948 :
33949 : INPUT PARAMETERS:
33950 : A - matrix, array[0..M-1, 0..N-1]
33951 : M, N- matrix size
33952 :
33953 : OUTPUT PARAMETERS:
33954 : A - Q*A, where Q is random MxM orthogonal matrix
33955 :
33956 : -- ALGLIB routine --
33957 : 04.12.2009
33958 : Bochkanov Sergey
33959 : *************************************************************************/
33960 0 : void cmatrixrndorthogonalfromtheleft(/* Complex */ ae_matrix* a,
33961 : ae_int_t m,
33962 : ae_int_t n,
33963 : ae_state *_state)
33964 : {
33965 : ae_frame _frame_block;
33966 : ae_complex tau;
33967 : ae_complex lambdav;
33968 : ae_int_t s;
33969 : ae_int_t i;
33970 : ae_int_t j;
33971 : ae_vector w;
33972 : ae_vector v;
33973 : hqrndstate state;
33974 :
33975 0 : ae_frame_make(_state, &_frame_block);
33976 0 : memset(&w, 0, sizeof(w));
33977 0 : memset(&v, 0, sizeof(v));
33978 0 : memset(&state, 0, sizeof(state));
33979 0 : ae_vector_init(&w, 0, DT_COMPLEX, _state, ae_true);
33980 0 : ae_vector_init(&v, 0, DT_COMPLEX, _state, ae_true);
33981 0 : _hqrndstate_init(&state, _state, ae_true);
33982 :
33983 0 : ae_assert(n>=1&&m>=1, "CMatrixRndOrthogonalFromTheRight: N<1 or M<1!", _state);
33984 0 : if( m==1 )
33985 : {
33986 :
33987 : /*
33988 : * special case
33989 : */
33990 0 : hqrndrandomize(&state, _state);
33991 0 : hqrndunit2(&state, &tau.x, &tau.y, _state);
33992 0 : for(j=0; j<=n-1; j++)
33993 : {
33994 0 : a->ptr.pp_complex[0][j] = ae_c_mul(a->ptr.pp_complex[0][j],tau);
33995 : }
33996 0 : ae_frame_leave(_state);
33997 0 : return;
33998 : }
33999 :
34000 : /*
34001 : * General case.
34002 : * First pass.
34003 : */
34004 0 : ae_vector_set_length(&w, n, _state);
34005 0 : ae_vector_set_length(&v, m+1, _state);
34006 0 : hqrndrandomize(&state, _state);
34007 0 : for(s=2; s<=m; s++)
34008 : {
34009 :
34010 : /*
34011 : * Prepare random normal v
34012 : */
34013 0 : do
34014 : {
34015 0 : for(i=1; i<=s; i++)
34016 : {
34017 0 : hqrndnormal2(&state, &tau.x, &tau.y, _state);
34018 0 : v.ptr.p_complex[i] = tau;
34019 : }
34020 0 : lambdav = ae_v_cdotproduct(&v.ptr.p_complex[1], 1, "N", &v.ptr.p_complex[1], 1, "Conj", ae_v_len(1,s));
34021 : }
34022 0 : while(ae_c_eq_d(lambdav,(double)(0)));
34023 :
34024 : /*
34025 : * Prepare and apply reflection
34026 : */
34027 0 : complexgeneratereflection(&v, s, &tau, _state);
34028 0 : v.ptr.p_complex[1] = ae_complex_from_i(1);
34029 0 : complexapplyreflectionfromtheleft(a, tau, &v, m-s, m-1, 0, n-1, &w, _state);
34030 : }
34031 :
34032 : /*
34033 : * Second pass.
34034 : */
34035 0 : for(i=0; i<=m-1; i++)
34036 : {
34037 0 : hqrndunit2(&state, &tau.x, &tau.y, _state);
34038 0 : ae_v_cmulc(&a->ptr.pp_complex[i][0], 1, ae_v_len(0,n-1), tau);
34039 : }
34040 0 : ae_frame_leave(_state);
34041 : }
34042 :
34043 :
34044 : /*************************************************************************
34045 : Symmetric multiplication of NxN matrix by random Haar distributed
34046 : orthogonal matrix
34047 :
34048 : INPUT PARAMETERS:
34049 : A - matrix, array[0..N-1, 0..N-1]
34050 : N - matrix size
34051 :
34052 : OUTPUT PARAMETERS:
34053 : A - Q'*A*Q, where Q is random NxN orthogonal matrix
34054 :
34055 : -- ALGLIB routine --
34056 : 04.12.2009
34057 : Bochkanov Sergey
34058 : *************************************************************************/
34059 0 : void smatrixrndmultiply(/* Real */ ae_matrix* a,
34060 : ae_int_t n,
34061 : ae_state *_state)
34062 : {
34063 : ae_frame _frame_block;
34064 : double tau;
34065 : double lambdav;
34066 : ae_int_t s;
34067 : ae_int_t i;
34068 : double u1;
34069 : double u2;
34070 : ae_vector w;
34071 : ae_vector v;
34072 : hqrndstate state;
34073 :
34074 0 : ae_frame_make(_state, &_frame_block);
34075 0 : memset(&w, 0, sizeof(w));
34076 0 : memset(&v, 0, sizeof(v));
34077 0 : memset(&state, 0, sizeof(state));
34078 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
34079 0 : ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
34080 0 : _hqrndstate_init(&state, _state, ae_true);
34081 :
34082 :
34083 : /*
34084 : * General case.
34085 : */
34086 0 : ae_vector_set_length(&w, n, _state);
34087 0 : ae_vector_set_length(&v, n+1, _state);
34088 0 : hqrndrandomize(&state, _state);
34089 0 : for(s=2; s<=n; s++)
34090 : {
34091 :
34092 : /*
34093 : * Prepare random normal v
34094 : */
34095 0 : do
34096 : {
34097 0 : i = 1;
34098 0 : while(i<=s)
34099 : {
34100 0 : hqrndnormal2(&state, &u1, &u2, _state);
34101 0 : v.ptr.p_double[i] = u1;
34102 0 : if( i+1<=s )
34103 : {
34104 0 : v.ptr.p_double[i+1] = u2;
34105 : }
34106 0 : i = i+2;
34107 : }
34108 0 : lambdav = ae_v_dotproduct(&v.ptr.p_double[1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,s));
34109 : }
34110 0 : while(ae_fp_eq(lambdav,(double)(0)));
34111 :
34112 : /*
34113 : * Prepare and apply reflection
34114 : */
34115 0 : generatereflection(&v, s, &tau, _state);
34116 0 : v.ptr.p_double[1] = (double)(1);
34117 0 : applyreflectionfromtheright(a, tau, &v, 0, n-1, n-s, n-1, &w, _state);
34118 0 : applyreflectionfromtheleft(a, tau, &v, n-s, n-1, 0, n-1, &w, _state);
34119 : }
34120 :
34121 : /*
34122 : * Second pass.
34123 : */
34124 0 : for(i=0; i<=n-1; i++)
34125 : {
34126 0 : tau = (double)(2*hqrnduniformi(&state, 2, _state)-1);
34127 0 : ae_v_muld(&a->ptr.pp_double[0][i], a->stride, ae_v_len(0,n-1), tau);
34128 0 : ae_v_muld(&a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), tau);
34129 : }
34130 :
34131 : /*
34132 : * Copy upper triangle to lower
34133 : */
34134 0 : for(i=0; i<=n-2; i++)
34135 : {
34136 0 : ae_v_move(&a->ptr.pp_double[i+1][i], a->stride, &a->ptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1));
34137 : }
34138 0 : ae_frame_leave(_state);
34139 0 : }
34140 :
34141 :
34142 : /*************************************************************************
34143 : Hermitian multiplication of NxN matrix by random Haar distributed
34144 : complex orthogonal matrix
34145 :
34146 : INPUT PARAMETERS:
34147 : A - matrix, array[0..N-1, 0..N-1]
34148 : N - matrix size
34149 :
34150 : OUTPUT PARAMETERS:
34151 : A - Q^H*A*Q, where Q is random NxN orthogonal matrix
34152 :
34153 : -- ALGLIB routine --
34154 : 04.12.2009
34155 : Bochkanov Sergey
34156 : *************************************************************************/
34157 0 : void hmatrixrndmultiply(/* Complex */ ae_matrix* a,
34158 : ae_int_t n,
34159 : ae_state *_state)
34160 : {
34161 : ae_frame _frame_block;
34162 : ae_complex tau;
34163 : ae_complex lambdav;
34164 : ae_int_t s;
34165 : ae_int_t i;
34166 : ae_vector w;
34167 : ae_vector v;
34168 : hqrndstate state;
34169 :
34170 0 : ae_frame_make(_state, &_frame_block);
34171 0 : memset(&w, 0, sizeof(w));
34172 0 : memset(&v, 0, sizeof(v));
34173 0 : memset(&state, 0, sizeof(state));
34174 0 : ae_vector_init(&w, 0, DT_COMPLEX, _state, ae_true);
34175 0 : ae_vector_init(&v, 0, DT_COMPLEX, _state, ae_true);
34176 0 : _hqrndstate_init(&state, _state, ae_true);
34177 :
34178 :
34179 : /*
34180 : * General case.
34181 : */
34182 0 : ae_vector_set_length(&w, n, _state);
34183 0 : ae_vector_set_length(&v, n+1, _state);
34184 0 : hqrndrandomize(&state, _state);
34185 0 : for(s=2; s<=n; s++)
34186 : {
34187 :
34188 : /*
34189 : * Prepare random normal v
34190 : */
34191 0 : do
34192 : {
34193 0 : for(i=1; i<=s; i++)
34194 : {
34195 0 : hqrndnormal2(&state, &tau.x, &tau.y, _state);
34196 0 : v.ptr.p_complex[i] = tau;
34197 : }
34198 0 : lambdav = ae_v_cdotproduct(&v.ptr.p_complex[1], 1, "N", &v.ptr.p_complex[1], 1, "Conj", ae_v_len(1,s));
34199 : }
34200 0 : while(ae_c_eq_d(lambdav,(double)(0)));
34201 :
34202 : /*
34203 : * Prepare and apply reflection
34204 : */
34205 0 : complexgeneratereflection(&v, s, &tau, _state);
34206 0 : v.ptr.p_complex[1] = ae_complex_from_i(1);
34207 0 : complexapplyreflectionfromtheright(a, tau, &v, 0, n-1, n-s, n-1, &w, _state);
34208 0 : complexapplyreflectionfromtheleft(a, ae_c_conj(tau, _state), &v, n-s, n-1, 0, n-1, &w, _state);
34209 : }
34210 :
34211 : /*
34212 : * Second pass.
34213 : */
34214 0 : for(i=0; i<=n-1; i++)
34215 : {
34216 0 : hqrndunit2(&state, &tau.x, &tau.y, _state);
34217 0 : ae_v_cmulc(&a->ptr.pp_complex[0][i], a->stride, ae_v_len(0,n-1), tau);
34218 0 : tau = ae_c_conj(tau, _state);
34219 0 : ae_v_cmulc(&a->ptr.pp_complex[i][0], 1, ae_v_len(0,n-1), tau);
34220 : }
34221 :
34222 : /*
34223 : * Change all values from lower triangle by complex-conjugate values
34224 : * from upper one
34225 : */
34226 0 : for(i=0; i<=n-2; i++)
34227 : {
34228 0 : ae_v_cmove(&a->ptr.pp_complex[i+1][i], a->stride, &a->ptr.pp_complex[i][i+1], 1, "N", ae_v_len(i+1,n-1));
34229 : }
34230 0 : for(s=0; s<=n-2; s++)
34231 : {
34232 0 : for(i=s+1; i<=n-1; i++)
34233 : {
34234 0 : a->ptr.pp_complex[i][s].y = -a->ptr.pp_complex[i][s].y;
34235 : }
34236 : }
34237 0 : ae_frame_leave(_state);
34238 0 : }
34239 :
34240 :
34241 : #endif
34242 : #if defined(AE_COMPILE_TRFAC) || !defined(AE_PARTIAL_BUILD)
34243 :
34244 :
34245 : /*************************************************************************
34246 : LU decomposition of a general real matrix with row pivoting
34247 :
34248 : A is represented as A = P*L*U, where:
34249 : * L is lower unitriangular matrix
34250 : * U is upper triangular matrix
34251 : * P = P0*P1*...*PK, K=min(M,N)-1,
34252 : Pi - permutation matrix for I and Pivots[I]
34253 :
34254 : ! COMMERCIAL EDITION OF ALGLIB:
34255 : !
34256 : ! Commercial Edition of ALGLIB includes following important improvements
34257 : ! of this function:
34258 : ! * high-performance native backend with same C# interface (C# version)
34259 : ! * multithreading support (C++ and C# versions)
34260 : ! * hardware vendor (Intel) implementations of linear algebra primitives
34261 : ! (C++ and C# versions, x86/x64 platform)
34262 : !
34263 : ! We recommend you to read 'Working with commercial version' section of
34264 : ! ALGLIB Reference Manual in order to find out how to use performance-
34265 : ! related features provided by commercial edition of ALGLIB.
34266 :
34267 : INPUT PARAMETERS:
34268 : A - array[0..M-1, 0..N-1].
34269 : M - number of rows in matrix A.
34270 : N - number of columns in matrix A.
34271 :
34272 :
34273 : OUTPUT PARAMETERS:
34274 : A - matrices L and U in compact form:
34275 : * L is stored under main diagonal
34276 : * U is stored on and above main diagonal
34277 : Pivots - permutation matrix in compact form.
34278 : array[0..Min(M-1,N-1)].
34279 :
34280 : -- ALGLIB routine --
34281 : 10.01.2010
34282 : Bochkanov Sergey
34283 : *************************************************************************/
34284 0 : void rmatrixlu(/* Real */ ae_matrix* a,
34285 : ae_int_t m,
34286 : ae_int_t n,
34287 : /* Integer */ ae_vector* pivots,
34288 : ae_state *_state)
34289 : {
34290 :
34291 0 : ae_vector_clear(pivots);
34292 :
34293 0 : ae_assert(m>0, "RMatrixLU: incorrect M!", _state);
34294 0 : ae_assert(n>0, "RMatrixLU: incorrect N!", _state);
34295 0 : rmatrixplu(a, m, n, pivots, _state);
34296 0 : }
34297 :
34298 :
34299 : /*************************************************************************
34300 : LU decomposition of a general complex matrix with row pivoting
34301 :
34302 : A is represented as A = P*L*U, where:
34303 : * L is lower unitriangular matrix
34304 : * U is upper triangular matrix
34305 : * P = P0*P1*...*PK, K=min(M,N)-1,
34306 : Pi - permutation matrix for I and Pivots[I]
34307 :
34308 : ! COMMERCIAL EDITION OF ALGLIB:
34309 : !
34310 : ! Commercial Edition of ALGLIB includes following important improvements
34311 : ! of this function:
34312 : ! * high-performance native backend with same C# interface (C# version)
34313 : ! * multithreading support (C++ and C# versions)
34314 : ! * hardware vendor (Intel) implementations of linear algebra primitives
34315 : ! (C++ and C# versions, x86/x64 platform)
34316 : !
34317 : ! We recommend you to read 'Working with commercial version' section of
34318 : ! ALGLIB Reference Manual in order to find out how to use performance-
34319 : ! related features provided by commercial edition of ALGLIB.
34320 :
34321 : INPUT PARAMETERS:
34322 : A - array[0..M-1, 0..N-1].
34323 : M - number of rows in matrix A.
34324 : N - number of columns in matrix A.
34325 :
34326 :
34327 : OUTPUT PARAMETERS:
34328 : A - matrices L and U in compact form:
34329 : * L is stored under main diagonal
34330 : * U is stored on and above main diagonal
34331 : Pivots - permutation matrix in compact form.
34332 : array[0..Min(M-1,N-1)].
34333 :
34334 : -- ALGLIB routine --
34335 : 10.01.2010
34336 : Bochkanov Sergey
34337 : *************************************************************************/
34338 0 : void cmatrixlu(/* Complex */ ae_matrix* a,
34339 : ae_int_t m,
34340 : ae_int_t n,
34341 : /* Integer */ ae_vector* pivots,
34342 : ae_state *_state)
34343 : {
34344 :
34345 0 : ae_vector_clear(pivots);
34346 :
34347 0 : ae_assert(m>0, "CMatrixLU: incorrect M!", _state);
34348 0 : ae_assert(n>0, "CMatrixLU: incorrect N!", _state);
34349 0 : cmatrixplu(a, m, n, pivots, _state);
34350 0 : }
34351 :
34352 :
34353 : /*************************************************************************
34354 : Cache-oblivious Cholesky decomposition
34355 :
34356 : The algorithm computes Cholesky decomposition of a Hermitian positive-
34357 : definite matrix. The result of an algorithm is a representation of A as
34358 : A=U'*U or A=L*L' (here X' denotes conj(X^T)).
34359 :
34360 : ! COMMERCIAL EDITION OF ALGLIB:
34361 : !
34362 : ! Commercial Edition of ALGLIB includes following important improvements
34363 : ! of this function:
34364 : ! * high-performance native backend with same C# interface (C# version)
34365 : ! * multithreading support (C++ and C# versions)
34366 : ! * hardware vendor (Intel) implementations of linear algebra primitives
34367 : ! (C++ and C# versions, x86/x64 platform)
34368 : !
34369 : ! We recommend you to read 'Working with commercial version' section of
34370 : ! ALGLIB Reference Manual in order to find out how to use performance-
34371 : ! related features provided by commercial edition of ALGLIB.
34372 :
34373 : INPUT PARAMETERS:
34374 : A - upper or lower triangle of a factorized matrix.
34375 : array with elements [0..N-1, 0..N-1].
34376 : N - size of matrix A.
34377 : IsUpper - if IsUpper=True, then A contains an upper triangle of
34378 : a symmetric matrix, otherwise A contains a lower one.
34379 :
34380 : OUTPUT PARAMETERS:
34381 : A - the result of factorization. If IsUpper=True, then
34382 : the upper triangle contains matrix U, so that A = U'*U,
34383 : and the elements below the main diagonal are not modified.
34384 : Similarly, if IsUpper = False.
34385 :
34386 : RESULT:
34387 : If the matrix is positive-definite, the function returns True.
34388 : Otherwise, the function returns False. Contents of A is not determined
34389 : in such case.
34390 :
34391 : -- ALGLIB routine --
34392 : 15.12.2009-22.01.2018
34393 : Bochkanov Sergey
34394 : *************************************************************************/
34395 0 : ae_bool hpdmatrixcholesky(/* Complex */ ae_matrix* a,
34396 : ae_int_t n,
34397 : ae_bool isupper,
34398 : ae_state *_state)
34399 : {
34400 : ae_frame _frame_block;
34401 : ae_vector tmp;
34402 : ae_bool result;
34403 :
34404 0 : ae_frame_make(_state, &_frame_block);
34405 0 : memset(&tmp, 0, sizeof(tmp));
34406 0 : ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true);
34407 :
34408 0 : if( n<1 )
34409 : {
34410 0 : result = ae_false;
34411 0 : ae_frame_leave(_state);
34412 0 : return result;
34413 : }
34414 0 : result = trfac_hpdmatrixcholeskyrec(a, 0, n, isupper, &tmp, _state);
34415 0 : ae_frame_leave(_state);
34416 0 : return result;
34417 : }
34418 :
34419 :
34420 : /*************************************************************************
34421 : Cache-oblivious Cholesky decomposition
34422 :
34423 : The algorithm computes Cholesky decomposition of a symmetric positive-
34424 : definite matrix. The result of an algorithm is a representation of A as
34425 : A=U^T*U or A=L*L^T
34426 :
34427 : ! COMMERCIAL EDITION OF ALGLIB:
34428 : !
34429 : ! Commercial Edition of ALGLIB includes following important improvements
34430 : ! of this function:
34431 : ! * high-performance native backend with same C# interface (C# version)
34432 : ! * multithreading support (C++ and C# versions)
34433 : ! * hardware vendor (Intel) implementations of linear algebra primitives
34434 : ! (C++ and C# versions, x86/x64 platform)
34435 : !
34436 : ! We recommend you to read 'Working with commercial version' section of
34437 : ! ALGLIB Reference Manual in order to find out how to use performance-
34438 : ! related features provided by commercial edition of ALGLIB.
34439 :
34440 : INPUT PARAMETERS:
34441 : A - upper or lower triangle of a factorized matrix.
34442 : array with elements [0..N-1, 0..N-1].
34443 : N - size of matrix A.
34444 : IsUpper - if IsUpper=True, then A contains an upper triangle of
34445 : a symmetric matrix, otherwise A contains a lower one.
34446 :
34447 : OUTPUT PARAMETERS:
34448 : A - the result of factorization. If IsUpper=True, then
34449 : the upper triangle contains matrix U, so that A = U^T*U,
34450 : and the elements below the main diagonal are not modified.
34451 : Similarly, if IsUpper = False.
34452 :
34453 : RESULT:
34454 : If the matrix is positive-definite, the function returns True.
34455 : Otherwise, the function returns False. Contents of A is not determined
34456 : in such case.
34457 :
34458 : -- ALGLIB routine --
34459 : 15.12.2009
34460 : Bochkanov Sergey
34461 : *************************************************************************/
34462 0 : ae_bool spdmatrixcholesky(/* Real */ ae_matrix* a,
34463 : ae_int_t n,
34464 : ae_bool isupper,
34465 : ae_state *_state)
34466 : {
34467 : ae_frame _frame_block;
34468 : ae_vector tmp;
34469 : ae_bool result;
34470 :
34471 0 : ae_frame_make(_state, &_frame_block);
34472 0 : memset(&tmp, 0, sizeof(tmp));
34473 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
34474 :
34475 0 : if( n<1 )
34476 : {
34477 0 : result = ae_false;
34478 0 : ae_frame_leave(_state);
34479 0 : return result;
34480 : }
34481 0 : result = spdmatrixcholeskyrec(a, 0, n, isupper, &tmp, _state);
34482 0 : ae_frame_leave(_state);
34483 0 : return result;
34484 : }
34485 :
34486 :
34487 : /*************************************************************************
34488 : Update of Cholesky decomposition: rank-1 update to original A. "Buffered"
34489 : version which uses preallocated buffer which is saved between subsequent
34490 : function calls.
34491 :
34492 : This function uses internally allocated buffer which is not saved between
34493 : subsequent calls. So, if you perform a lot of subsequent updates,
34494 : we recommend you to use "buffered" version of this function:
34495 : SPDMatrixCholeskyUpdateAdd1Buf().
34496 :
34497 : INPUT PARAMETERS:
34498 : A - upper or lower Cholesky factor.
34499 : array with elements [0..N-1, 0..N-1].
34500 : Exception is thrown if array size is too small.
34501 : N - size of matrix A, N>0
34502 : IsUpper - if IsUpper=True, then A contains upper Cholesky factor;
34503 : otherwise A contains a lower one.
34504 : U - array[N], rank-1 update to A: A_mod = A + u*u'
34505 : Exception is thrown if array size is too small.
34506 : BufR - possibly preallocated buffer; automatically resized if
34507 : needed. It is recommended to reuse this buffer if you
34508 : perform a lot of subsequent decompositions.
34509 :
34510 : OUTPUT PARAMETERS:
34511 : A - updated factorization. If IsUpper=True, then the upper
34512 : triangle contains matrix U, and the elements below the main
34513 : diagonal are not modified. Similarly, if IsUpper = False.
34514 :
34515 : NOTE: this function always succeeds, so it does not return completion code
34516 :
34517 : NOTE: this function checks sizes of input arrays, but it does NOT checks
34518 : for presence of infinities or NAN's.
34519 :
34520 : -- ALGLIB --
34521 : 03.02.2014
34522 : Sergey Bochkanov
34523 : *************************************************************************/
34524 0 : void spdmatrixcholeskyupdateadd1(/* Real */ ae_matrix* a,
34525 : ae_int_t n,
34526 : ae_bool isupper,
34527 : /* Real */ ae_vector* u,
34528 : ae_state *_state)
34529 : {
34530 : ae_frame _frame_block;
34531 : ae_vector bufr;
34532 :
34533 0 : ae_frame_make(_state, &_frame_block);
34534 0 : memset(&bufr, 0, sizeof(bufr));
34535 0 : ae_vector_init(&bufr, 0, DT_REAL, _state, ae_true);
34536 :
34537 0 : ae_assert(n>0, "SPDMatrixCholeskyUpdateAdd1: N<=0", _state);
34538 0 : ae_assert(a->rows>=n, "SPDMatrixCholeskyUpdateAdd1: Rows(A)<N", _state);
34539 0 : ae_assert(a->cols>=n, "SPDMatrixCholeskyUpdateAdd1: Cols(A)<N", _state);
34540 0 : ae_assert(u->cnt>=n, "SPDMatrixCholeskyUpdateAdd1: Length(U)<N", _state);
34541 0 : spdmatrixcholeskyupdateadd1buf(a, n, isupper, u, &bufr, _state);
34542 0 : ae_frame_leave(_state);
34543 0 : }
34544 :
34545 :
34546 : /*************************************************************************
34547 : Update of Cholesky decomposition: "fixing" some variables.
34548 :
34549 : This function uses internally allocated buffer which is not saved between
34550 : subsequent calls. So, if you perform a lot of subsequent updates,
34551 : we recommend you to use "buffered" version of this function:
34552 : SPDMatrixCholeskyUpdateFixBuf().
34553 :
34554 : "FIXING" EXPLAINED:
34555 :
34556 : Suppose we have N*N positive definite matrix A. "Fixing" some variable
34557 : means filling corresponding row/column of A by zeros, and setting
34558 : diagonal element to 1.
34559 :
34560 : For example, if we fix 2nd variable in 4*4 matrix A, it becomes Af:
34561 :
34562 : ( A00 A01 A02 A03 ) ( Af00 0 Af02 Af03 )
34563 : ( A10 A11 A12 A13 ) ( 0 1 0 0 )
34564 : ( A20 A21 A22 A23 ) => ( Af20 0 Af22 Af23 )
34565 : ( A30 A31 A32 A33 ) ( Af30 0 Af32 Af33 )
34566 :
34567 : If we have Cholesky decomposition of A, it must be recalculated after
34568 : variables were fixed. However, it is possible to use efficient
34569 : algorithm, which needs O(K*N^2) time to "fix" K variables, given
34570 : Cholesky decomposition of original, "unfixed" A.
34571 :
34572 : INPUT PARAMETERS:
34573 : A - upper or lower Cholesky factor.
34574 : array with elements [0..N-1, 0..N-1].
34575 : Exception is thrown if array size is too small.
34576 : N - size of matrix A, N>0
34577 : IsUpper - if IsUpper=True, then A contains upper Cholesky factor;
34578 : otherwise A contains a lower one.
34579 : Fix - array[N], I-th element is True if I-th variable must be
34580 : fixed. Exception is thrown if array size is too small.
34581 : BufR - possibly preallocated buffer; automatically resized if
34582 : needed. It is recommended to reuse this buffer if you
34583 : perform a lot of subsequent decompositions.
34584 :
34585 : OUTPUT PARAMETERS:
34586 : A - updated factorization. If IsUpper=True, then the upper
34587 : triangle contains matrix U, and the elements below the main
34588 : diagonal are not modified. Similarly, if IsUpper = False.
34589 :
34590 : NOTE: this function always succeeds, so it does not return completion code
34591 :
34592 : NOTE: this function checks sizes of input arrays, but it does NOT checks
34593 : for presence of infinities or NAN's.
34594 :
34595 : NOTE: this function is efficient only for moderate amount of updated
34596 : variables - say, 0.1*N or 0.3*N. For larger amount of variables it
34597 : will still work, but you may get better performance with
34598 : straightforward Cholesky.
34599 :
34600 : -- ALGLIB --
34601 : 03.02.2014
34602 : Sergey Bochkanov
34603 : *************************************************************************/
34604 0 : void spdmatrixcholeskyupdatefix(/* Real */ ae_matrix* a,
34605 : ae_int_t n,
34606 : ae_bool isupper,
34607 : /* Boolean */ ae_vector* fix,
34608 : ae_state *_state)
34609 : {
34610 : ae_frame _frame_block;
34611 : ae_vector bufr;
34612 :
34613 0 : ae_frame_make(_state, &_frame_block);
34614 0 : memset(&bufr, 0, sizeof(bufr));
34615 0 : ae_vector_init(&bufr, 0, DT_REAL, _state, ae_true);
34616 :
34617 0 : ae_assert(n>0, "SPDMatrixCholeskyUpdateFix: N<=0", _state);
34618 0 : ae_assert(a->rows>=n, "SPDMatrixCholeskyUpdateFix: Rows(A)<N", _state);
34619 0 : ae_assert(a->cols>=n, "SPDMatrixCholeskyUpdateFix: Cols(A)<N", _state);
34620 0 : ae_assert(fix->cnt>=n, "SPDMatrixCholeskyUpdateFix: Length(Fix)<N", _state);
34621 0 : spdmatrixcholeskyupdatefixbuf(a, n, isupper, fix, &bufr, _state);
34622 0 : ae_frame_leave(_state);
34623 0 : }
34624 :
34625 :
34626 : /*************************************************************************
34627 : Update of Cholesky decomposition: rank-1 update to original A. "Buffered"
34628 : version which uses preallocated buffer which is saved between subsequent
34629 : function calls.
34630 :
34631 : See comments for SPDMatrixCholeskyUpdateAdd1() for more information.
34632 :
34633 : INPUT PARAMETERS:
34634 : A - upper or lower Cholesky factor.
34635 : array with elements [0..N-1, 0..N-1].
34636 : Exception is thrown if array size is too small.
34637 : N - size of matrix A, N>0
34638 : IsUpper - if IsUpper=True, then A contains upper Cholesky factor;
34639 : otherwise A contains a lower one.
34640 : U - array[N], rank-1 update to A: A_mod = A + u*u'
34641 : Exception is thrown if array size is too small.
34642 : BufR - possibly preallocated buffer; automatically resized if
34643 : needed. It is recommended to reuse this buffer if you
34644 : perform a lot of subsequent decompositions.
34645 :
34646 : OUTPUT PARAMETERS:
34647 : A - updated factorization. If IsUpper=True, then the upper
34648 : triangle contains matrix U, and the elements below the main
34649 : diagonal are not modified. Similarly, if IsUpper = False.
34650 :
34651 : -- ALGLIB --
34652 : 03.02.2014
34653 : Sergey Bochkanov
34654 : *************************************************************************/
34655 0 : void spdmatrixcholeskyupdateadd1buf(/* Real */ ae_matrix* a,
34656 : ae_int_t n,
34657 : ae_bool isupper,
34658 : /* Real */ ae_vector* u,
34659 : /* Real */ ae_vector* bufr,
34660 : ae_state *_state)
34661 : {
34662 : ae_int_t i;
34663 : ae_int_t j;
34664 : ae_int_t nz;
34665 : double cs;
34666 : double sn;
34667 : double v;
34668 : double vv;
34669 :
34670 :
34671 0 : ae_assert(n>0, "SPDMatrixCholeskyUpdateAdd1Buf: N<=0", _state);
34672 0 : ae_assert(a->rows>=n, "SPDMatrixCholeskyUpdateAdd1Buf: Rows(A)<N", _state);
34673 0 : ae_assert(a->cols>=n, "SPDMatrixCholeskyUpdateAdd1Buf: Cols(A)<N", _state);
34674 0 : ae_assert(u->cnt>=n, "SPDMatrixCholeskyUpdateAdd1Buf: Length(U)<N", _state);
34675 :
34676 : /*
34677 : * Find index of first non-zero entry in U
34678 : */
34679 0 : nz = n;
34680 0 : for(i=0; i<=n-1; i++)
34681 : {
34682 0 : if( ae_fp_neq(u->ptr.p_double[i],(double)(0)) )
34683 : {
34684 0 : nz = i;
34685 0 : break;
34686 : }
34687 : }
34688 0 : if( nz==n )
34689 : {
34690 :
34691 : /*
34692 : * Nothing to update
34693 : */
34694 0 : return;
34695 : }
34696 :
34697 : /*
34698 : * If working with upper triangular matrix
34699 : */
34700 0 : if( isupper )
34701 : {
34702 :
34703 : /*
34704 : * Perform a sequence of updates which fix variables one by one.
34705 : * This approach is different from one which is used when we work
34706 : * with lower triangular matrix.
34707 : */
34708 0 : rvectorsetlengthatleast(bufr, n, _state);
34709 0 : for(j=nz; j<=n-1; j++)
34710 : {
34711 0 : bufr->ptr.p_double[j] = u->ptr.p_double[j];
34712 : }
34713 0 : for(i=nz; i<=n-1; i++)
34714 : {
34715 0 : if( ae_fp_neq(bufr->ptr.p_double[i],(double)(0)) )
34716 : {
34717 0 : generaterotation(a->ptr.pp_double[i][i], bufr->ptr.p_double[i], &cs, &sn, &v, _state);
34718 0 : a->ptr.pp_double[i][i] = v;
34719 0 : bufr->ptr.p_double[i] = 0.0;
34720 0 : for(j=i+1; j<=n-1; j++)
34721 : {
34722 0 : v = a->ptr.pp_double[i][j];
34723 0 : vv = bufr->ptr.p_double[j];
34724 0 : a->ptr.pp_double[i][j] = cs*v+sn*vv;
34725 0 : bufr->ptr.p_double[j] = -sn*v+cs*vv;
34726 : }
34727 : }
34728 : }
34729 : }
34730 : else
34731 : {
34732 :
34733 : /*
34734 : * Calculate rows of modified Cholesky factor, row-by-row
34735 : * (updates performed during variable fixing are applied
34736 : * simultaneously to each row)
34737 : */
34738 0 : rvectorsetlengthatleast(bufr, 3*n, _state);
34739 0 : for(j=nz; j<=n-1; j++)
34740 : {
34741 0 : bufr->ptr.p_double[j] = u->ptr.p_double[j];
34742 : }
34743 0 : for(i=nz; i<=n-1; i++)
34744 : {
34745 :
34746 : /*
34747 : * Update all previous updates [Idx+1...I-1] to I-th row
34748 : */
34749 0 : vv = bufr->ptr.p_double[i];
34750 0 : for(j=nz; j<=i-1; j++)
34751 : {
34752 0 : cs = bufr->ptr.p_double[n+2*j+0];
34753 0 : sn = bufr->ptr.p_double[n+2*j+1];
34754 0 : v = a->ptr.pp_double[i][j];
34755 0 : a->ptr.pp_double[i][j] = cs*v+sn*vv;
34756 0 : vv = -sn*v+cs*vv;
34757 : }
34758 :
34759 : /*
34760 : * generate rotation applied to I-th element of update vector
34761 : */
34762 0 : generaterotation(a->ptr.pp_double[i][i], vv, &cs, &sn, &v, _state);
34763 0 : a->ptr.pp_double[i][i] = v;
34764 0 : bufr->ptr.p_double[n+2*i+0] = cs;
34765 0 : bufr->ptr.p_double[n+2*i+1] = sn;
34766 : }
34767 : }
34768 : }
34769 :
34770 :
34771 : /*************************************************************************
34772 : Update of Cholesky decomposition: "fixing" some variables. "Buffered"
34773 : version which uses preallocated buffer which is saved between subsequent
34774 : function calls.
34775 :
34776 : See comments for SPDMatrixCholeskyUpdateFix() for more information.
34777 :
34778 : INPUT PARAMETERS:
34779 : A - upper or lower Cholesky factor.
34780 : array with elements [0..N-1, 0..N-1].
34781 : Exception is thrown if array size is too small.
34782 : N - size of matrix A, N>0
34783 : IsUpper - if IsUpper=True, then A contains upper Cholesky factor;
34784 : otherwise A contains a lower one.
34785 : Fix - array[N], I-th element is True if I-th variable must be
34786 : fixed. Exception is thrown if array size is too small.
34787 : BufR - possibly preallocated buffer; automatically resized if
34788 : needed. It is recommended to reuse this buffer if you
34789 : perform a lot of subsequent decompositions.
34790 :
34791 : OUTPUT PARAMETERS:
34792 : A - updated factorization. If IsUpper=True, then the upper
34793 : triangle contains matrix U, and the elements below the main
34794 : diagonal are not modified. Similarly, if IsUpper = False.
34795 :
34796 : -- ALGLIB --
34797 : 03.02.2014
34798 : Sergey Bochkanov
34799 : *************************************************************************/
34800 0 : void spdmatrixcholeskyupdatefixbuf(/* Real */ ae_matrix* a,
34801 : ae_int_t n,
34802 : ae_bool isupper,
34803 : /* Boolean */ ae_vector* fix,
34804 : /* Real */ ae_vector* bufr,
34805 : ae_state *_state)
34806 : {
34807 : ae_int_t i;
34808 : ae_int_t j;
34809 : ae_int_t k;
34810 : ae_int_t nfix;
34811 : ae_int_t idx;
34812 : double cs;
34813 : double sn;
34814 : double v;
34815 : double vv;
34816 :
34817 :
34818 0 : ae_assert(n>0, "SPDMatrixCholeskyUpdateFixBuf: N<=0", _state);
34819 0 : ae_assert(a->rows>=n, "SPDMatrixCholeskyUpdateFixBuf: Rows(A)<N", _state);
34820 0 : ae_assert(a->cols>=n, "SPDMatrixCholeskyUpdateFixBuf: Cols(A)<N", _state);
34821 0 : ae_assert(fix->cnt>=n, "SPDMatrixCholeskyUpdateFixBuf: Length(Fix)<N", _state);
34822 :
34823 : /*
34824 : * Count number of variables to fix.
34825 : * Quick exit if NFix=0 or NFix=N
34826 : */
34827 0 : nfix = 0;
34828 0 : for(i=0; i<=n-1; i++)
34829 : {
34830 0 : if( fix->ptr.p_bool[i] )
34831 : {
34832 0 : inc(&nfix, _state);
34833 : }
34834 : }
34835 0 : if( nfix==0 )
34836 : {
34837 :
34838 : /*
34839 : * Nothing to fix
34840 : */
34841 0 : return;
34842 : }
34843 0 : if( nfix==n )
34844 : {
34845 :
34846 : /*
34847 : * All variables are fixed.
34848 : * Set A to identity and exit.
34849 : */
34850 0 : if( isupper )
34851 : {
34852 0 : for(i=0; i<=n-1; i++)
34853 : {
34854 0 : a->ptr.pp_double[i][i] = (double)(1);
34855 0 : for(j=i+1; j<=n-1; j++)
34856 : {
34857 0 : a->ptr.pp_double[i][j] = (double)(0);
34858 : }
34859 : }
34860 : }
34861 : else
34862 : {
34863 0 : for(i=0; i<=n-1; i++)
34864 : {
34865 0 : for(j=0; j<=i-1; j++)
34866 : {
34867 0 : a->ptr.pp_double[i][j] = (double)(0);
34868 : }
34869 0 : a->ptr.pp_double[i][i] = (double)(1);
34870 : }
34871 : }
34872 0 : return;
34873 : }
34874 :
34875 : /*
34876 : * If working with upper triangular matrix
34877 : */
34878 0 : if( isupper )
34879 : {
34880 :
34881 : /*
34882 : * Perform a sequence of updates which fix variables one by one.
34883 : * This approach is different from one which is used when we work
34884 : * with lower triangular matrix.
34885 : */
34886 0 : rvectorsetlengthatleast(bufr, n, _state);
34887 0 : for(k=0; k<=n-1; k++)
34888 : {
34889 0 : if( fix->ptr.p_bool[k] )
34890 : {
34891 0 : idx = k;
34892 :
34893 : /*
34894 : * Quick exit if it is last variable
34895 : */
34896 0 : if( idx==n-1 )
34897 : {
34898 0 : for(i=0; i<=idx-1; i++)
34899 : {
34900 0 : a->ptr.pp_double[i][idx] = 0.0;
34901 : }
34902 0 : a->ptr.pp_double[idx][idx] = 1.0;
34903 0 : continue;
34904 : }
34905 :
34906 : /*
34907 : * We have Cholesky decomposition of quadratic term in A,
34908 : * with upper triangle being stored as given below:
34909 : *
34910 : * ( U00 u01 U02 )
34911 : * U = ( u11 u12 )
34912 : * ( U22 )
34913 : *
34914 : * Here u11 is diagonal element corresponding to variable K. We
34915 : * want to fix this variable, and we do so by modifying U as follows:
34916 : *
34917 : * ( U00 0 U02 )
34918 : * U_mod = ( 1 0 )
34919 : * ( U_m )
34920 : *
34921 : * with U_m = CHOLESKY [ (U22^T)*U22 + (u12^T)*u12 ]
34922 : *
34923 : * Of course, we can calculate U_m by calculating (U22^T)*U22 explicitly,
34924 : * modifying it and performing Cholesky decomposition of modified matrix.
34925 : * However, we can treat it as follows:
34926 : * * we already have CHOLESKY[(U22^T)*U22], which is equal to U22
34927 : * * we have rank-1 update (u12^T)*u12 applied to (U22^T)*U22
34928 : * * thus, we can calculate updated Cholesky with O(N^2) algorithm
34929 : * instead of O(N^3) one
34930 : */
34931 0 : for(j=idx+1; j<=n-1; j++)
34932 : {
34933 0 : bufr->ptr.p_double[j] = a->ptr.pp_double[idx][j];
34934 : }
34935 0 : for(i=0; i<=idx-1; i++)
34936 : {
34937 0 : a->ptr.pp_double[i][idx] = 0.0;
34938 : }
34939 0 : a->ptr.pp_double[idx][idx] = 1.0;
34940 0 : for(i=idx+1; i<=n-1; i++)
34941 : {
34942 0 : a->ptr.pp_double[idx][i] = 0.0;
34943 : }
34944 0 : for(i=idx+1; i<=n-1; i++)
34945 : {
34946 0 : if( ae_fp_neq(bufr->ptr.p_double[i],(double)(0)) )
34947 : {
34948 0 : generaterotation(a->ptr.pp_double[i][i], bufr->ptr.p_double[i], &cs, &sn, &v, _state);
34949 0 : a->ptr.pp_double[i][i] = v;
34950 0 : bufr->ptr.p_double[i] = 0.0;
34951 0 : for(j=i+1; j<=n-1; j++)
34952 : {
34953 0 : v = a->ptr.pp_double[i][j];
34954 0 : vv = bufr->ptr.p_double[j];
34955 0 : a->ptr.pp_double[i][j] = cs*v+sn*vv;
34956 0 : bufr->ptr.p_double[j] = -sn*v+cs*vv;
34957 : }
34958 : }
34959 : }
34960 : }
34961 : }
34962 : }
34963 : else
34964 : {
34965 :
34966 : /*
34967 : * Calculate rows of modified Cholesky factor, row-by-row
34968 : * (updates performed during variable fixing are applied
34969 : * simultaneously to each row)
34970 : */
34971 0 : rvectorsetlengthatleast(bufr, 3*n, _state);
34972 0 : for(k=0; k<=n-1; k++)
34973 : {
34974 0 : if( fix->ptr.p_bool[k] )
34975 : {
34976 0 : idx = k;
34977 :
34978 : /*
34979 : * Quick exit if it is last variable
34980 : */
34981 0 : if( idx==n-1 )
34982 : {
34983 0 : for(i=0; i<=idx-1; i++)
34984 : {
34985 0 : a->ptr.pp_double[idx][i] = 0.0;
34986 : }
34987 0 : a->ptr.pp_double[idx][idx] = 1.0;
34988 0 : continue;
34989 : }
34990 :
34991 : /*
34992 : * store column to buffer and clear row/column of A
34993 : */
34994 0 : for(j=idx+1; j<=n-1; j++)
34995 : {
34996 0 : bufr->ptr.p_double[j] = a->ptr.pp_double[j][idx];
34997 : }
34998 0 : for(i=0; i<=idx-1; i++)
34999 : {
35000 0 : a->ptr.pp_double[idx][i] = 0.0;
35001 : }
35002 0 : a->ptr.pp_double[idx][idx] = 1.0;
35003 0 : for(i=idx+1; i<=n-1; i++)
35004 : {
35005 0 : a->ptr.pp_double[i][idx] = 0.0;
35006 : }
35007 :
35008 : /*
35009 : * Apply update to rows of A
35010 : */
35011 0 : for(i=idx+1; i<=n-1; i++)
35012 : {
35013 :
35014 : /*
35015 : * Update all previous updates [Idx+1...I-1] to I-th row
35016 : */
35017 0 : vv = bufr->ptr.p_double[i];
35018 0 : for(j=idx+1; j<=i-1; j++)
35019 : {
35020 0 : cs = bufr->ptr.p_double[n+2*j+0];
35021 0 : sn = bufr->ptr.p_double[n+2*j+1];
35022 0 : v = a->ptr.pp_double[i][j];
35023 0 : a->ptr.pp_double[i][j] = cs*v+sn*vv;
35024 0 : vv = -sn*v+cs*vv;
35025 : }
35026 :
35027 : /*
35028 : * generate rotation applied to I-th element of update vector
35029 : */
35030 0 : generaterotation(a->ptr.pp_double[i][i], vv, &cs, &sn, &v, _state);
35031 0 : a->ptr.pp_double[i][i] = v;
35032 0 : bufr->ptr.p_double[n+2*i+0] = cs;
35033 0 : bufr->ptr.p_double[n+2*i+1] = sn;
35034 : }
35035 : }
35036 : }
35037 : }
35038 : }
35039 :
35040 :
35041 : /*************************************************************************
35042 : Sparse LU decomposition with column pivoting for sparsity and row pivoting
35043 : for stability. Input must be square sparse matrix stored in CRS format.
35044 :
35045 : The algorithm computes LU decomposition of a general square matrix
35046 : (rectangular ones are not supported). The result of an algorithm is a
35047 : representation of A as A = P*L*U*Q, where:
35048 : * L is lower unitriangular matrix
35049 : * U is upper triangular matrix
35050 : * P = P0*P1*...*PK, K=N-1, Pi - permutation matrix for I and P[I]
35051 : * Q = QK*...*Q1*Q0, K=N-1, Qi - permutation matrix for I and Q[I]
35052 :
35053 : This function pivots columns for higher sparsity, and then pivots rows for
35054 : stability (larger element at the diagonal).
35055 :
35056 : INPUT PARAMETERS:
35057 : A - sparse NxN matrix in CRS format. An exception is generated
35058 : if matrix is non-CRS or non-square.
35059 : PivotType- pivoting strategy:
35060 : * 0 for best pivoting available (2 in current version)
35061 : * 1 for row-only pivoting (NOT RECOMMENDED)
35062 : * 2 for complete pivoting which produces most sparse outputs
35063 :
35064 : OUTPUT PARAMETERS:
35065 : A - the result of factorization, matrices L and U stored in
35066 : compact form using CRS sparse storage format:
35067 : * lower unitriangular L is stored strictly under main diagonal
35068 : * upper triangilar U is stored ON and ABOVE main diagonal
35069 : P - row permutation matrix in compact form, array[N]
35070 : Q - col permutation matrix in compact form, array[N]
35071 :
35072 : This function always succeeds, i.e. it ALWAYS returns valid factorization,
35073 : but for your convenience it also returns boolean value which helps to
35074 : detect symbolically degenerate matrices:
35075 : * function returns TRUE, if the matrix was factorized AND symbolically
35076 : non-degenerate
35077 : * function returns FALSE, if the matrix was factorized but U has strictly
35078 : zero elements at the diagonal (the factorization is returned anyway).
35079 :
35080 :
35081 : -- ALGLIB routine --
35082 : 03.09.2018
35083 : Bochkanov Sergey
35084 : *************************************************************************/
35085 0 : ae_bool sparselu(sparsematrix* a,
35086 : ae_int_t pivottype,
35087 : /* Integer */ ae_vector* p,
35088 : /* Integer */ ae_vector* q,
35089 : ae_state *_state)
35090 : {
35091 : ae_frame _frame_block;
35092 : sluv2buffer buf2;
35093 : ae_bool result;
35094 :
35095 0 : ae_frame_make(_state, &_frame_block);
35096 0 : memset(&buf2, 0, sizeof(buf2));
35097 0 : ae_vector_clear(p);
35098 0 : ae_vector_clear(q);
35099 0 : _sluv2buffer_init(&buf2, _state, ae_true);
35100 :
35101 0 : ae_assert((pivottype==0||pivottype==1)||pivottype==2, "SparseLU: unexpected pivot type", _state);
35102 0 : ae_assert(sparseiscrs(a, _state), "SparseLU: A is not stored in CRS format", _state);
35103 0 : ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SparseLU: non-square A", _state);
35104 0 : result = sptrflu(a, pivottype, p, q, &buf2, _state);
35105 0 : ae_frame_leave(_state);
35106 0 : return result;
35107 : }
35108 :
35109 :
35110 : /*************************************************************************
35111 : Sparse Cholesky decomposition for skyline matrixm using in-place algorithm
35112 : without allocating additional storage.
35113 :
35114 : The algorithm computes Cholesky decomposition of a symmetric positive-
35115 : definite sparse matrix. The result of an algorithm is a representation of
35116 : A as A=U^T*U or A=L*L^T
35117 :
35118 : This function allows to perform very efficient decomposition of low-profile
35119 : matrices (average bandwidth is ~5-10 elements). For larger matrices it is
35120 : recommended to use supernodal Cholesky decomposition: SparseCholeskyP() or
35121 : SparseCholeskyAnalyze()/SparseCholeskyFactorize().
35122 :
35123 : INPUT PARAMETERS:
35124 : A - sparse matrix in skyline storage (SKS) format.
35125 : N - size of matrix A (can be smaller than actual size of A)
35126 : IsUpper - if IsUpper=True, then factorization is performed on upper
35127 : triangle. Another triangle is ignored (it may contant some
35128 : data, but it is not changed).
35129 :
35130 :
35131 : OUTPUT PARAMETERS:
35132 : A - the result of factorization, stored in SKS. If IsUpper=True,
35133 : then the upper triangle contains matrix U, such that
35134 : A = U^T*U. Lower triangle is not changed.
35135 : Similarly, if IsUpper = False. In this case L is returned,
35136 : and we have A = L*(L^T).
35137 : Note that THIS function does not perform permutation of
35138 : rows to reduce bandwidth.
35139 :
35140 : RESULT:
35141 : If the matrix is positive-definite, the function returns True.
35142 : Otherwise, the function returns False. Contents of A is not determined
35143 : in such case.
35144 :
35145 : NOTE: for performance reasons this function does NOT check that input
35146 : matrix includes only finite values. It is your responsibility to
35147 : make sure that there are no infinite or NAN values in the matrix.
35148 :
35149 : -- ALGLIB routine --
35150 : 16.01.2014
35151 : Bochkanov Sergey
35152 : *************************************************************************/
35153 0 : ae_bool sparsecholeskyskyline(sparsematrix* a,
35154 : ae_int_t n,
35155 : ae_bool isupper,
35156 : ae_state *_state)
35157 : {
35158 : ae_int_t i;
35159 : ae_int_t j;
35160 : ae_int_t k;
35161 : ae_int_t jnz;
35162 : ae_int_t jnza;
35163 : ae_int_t jnzl;
35164 : double v;
35165 : double vv;
35166 : double a12;
35167 : ae_int_t nready;
35168 : ae_int_t nadd;
35169 : ae_int_t banda;
35170 : ae_int_t offsa;
35171 : ae_int_t offsl;
35172 : ae_bool result;
35173 :
35174 :
35175 0 : ae_assert(n>=0, "SparseCholeskySkyline: N<0", _state);
35176 0 : ae_assert(sparsegetnrows(a, _state)>=n, "SparseCholeskySkyline: rows(A)<N", _state);
35177 0 : ae_assert(sparsegetncols(a, _state)>=n, "SparseCholeskySkyline: cols(A)<N", _state);
35178 0 : ae_assert(sparseissks(a, _state), "SparseCholeskySkyline: A is not stored in SKS format", _state);
35179 0 : result = ae_false;
35180 :
35181 : /*
35182 : * transpose if needed
35183 : */
35184 0 : if( isupper )
35185 : {
35186 0 : sparsetransposesks(a, _state);
35187 : }
35188 :
35189 : /*
35190 : * Perform Cholesky decomposition:
35191 : * * we assume than leading NReady*NReady submatrix is done
35192 : * * having Cholesky decomposition of NReady*NReady submatrix we
35193 : * obtain decomposition of larger (NReady+NAdd)*(NReady+NAdd) one.
35194 : *
35195 : * Here is algorithm. At the start we have
35196 : *
35197 : * ( | )
35198 : * ( L | )
35199 : * S = ( | )
35200 : * (----------)
35201 : * ( A | B )
35202 : *
35203 : * with L being already computed Cholesky factor, A and B being
35204 : * unprocessed parts of the matrix. Of course, L/A/B are stored
35205 : * in SKS format.
35206 : *
35207 : * Then, we calculate A1:=(inv(L)*A')' and replace A with A1.
35208 : * Then, we calculate B1:=B-A1*A1' and replace B with B1
35209 : *
35210 : * Finally, we calculate small NAdd*NAdd Cholesky of B1 with
35211 : * dense solver. Now, L/A1/B1 are Cholesky decomposition of the
35212 : * larger (NReady+NAdd)*(NReady+NAdd) matrix.
35213 : */
35214 0 : nready = 0;
35215 0 : nadd = 1;
35216 0 : while(nready<n)
35217 : {
35218 0 : ae_assert(nadd==1, "SkylineCholesky: internal error", _state);
35219 :
35220 : /*
35221 : * Calculate A1:=(inv(L)*A')'
35222 : *
35223 : * Elements are calculated row by row (example below is given
35224 : * for NAdd=1):
35225 : * * first, we solve L[0,0]*A1[0]=A[0]
35226 : * * then, we solve L[1,0]*A1[0]+L[1,1]*A1[1]=A[1]
35227 : * * then, we move to next row and so on
35228 : * * during calculation of A1 we update A12 - squared norm of A1
35229 : *
35230 : * We extensively use sparsity of both A/A1 and L:
35231 : * * first, equations from 0 to BANDWIDTH(A1)-1 are completely zero
35232 : * * second, for I>=BANDWIDTH(A1), I-th equation is reduced from
35233 : * L[I,0]*A1[0] + L[I,1]*A1[1] + ... + L[I,I]*A1[I] = A[I]
35234 : * to
35235 : * L[I,JNZ]*A1[JNZ] + ... + L[I,I]*A1[I] = A[I]
35236 : * where JNZ = max(NReady-BANDWIDTH(A1),I-BANDWIDTH(L[i]))
35237 : * (JNZ is an index of the firts column where both A and L become
35238 : * nonzero).
35239 : *
35240 : * NOTE: we rely on details of SparseMatrix internal storage format.
35241 : * This is allowed by SparseMatrix specification.
35242 : */
35243 0 : a12 = 0.0;
35244 0 : if( a->didx.ptr.p_int[nready]>0 )
35245 : {
35246 0 : banda = a->didx.ptr.p_int[nready];
35247 0 : for(i=nready-banda; i<=nready-1; i++)
35248 : {
35249 :
35250 : /*
35251 : * Elements of A1[0:I-1] were computed:
35252 : * * A1[0:NReady-BandA-1] are zero (sparse)
35253 : * * A1[NReady-BandA:I-1] replaced corresponding elements of A
35254 : *
35255 : * Now it is time to get I-th one.
35256 : *
35257 : * First, we calculate:
35258 : * * JNZA - index of the first column where A become nonzero
35259 : * * JNZL - index of the first column where L become nonzero
35260 : * * JNZ - index of the first column where both A and L become nonzero
35261 : * * OffsA - offset of A[JNZ] in A.Vals
35262 : * * OffsL - offset of L[I,JNZ] in A.Vals
35263 : *
35264 : * Then, we solve SUM(A1[j]*L[I,j],j=JNZ..I-1) + A1[I]*L[I,I] = A[I],
35265 : * with A1[JNZ..I-1] already known, and A1[I] unknown.
35266 : */
35267 0 : jnza = nready-banda;
35268 0 : jnzl = i-a->didx.ptr.p_int[i];
35269 0 : jnz = ae_maxint(jnza, jnzl, _state);
35270 0 : offsa = a->ridx.ptr.p_int[nready]+(jnz-jnza);
35271 0 : offsl = a->ridx.ptr.p_int[i]+(jnz-jnzl);
35272 0 : v = 0.0;
35273 0 : k = i-1-jnz;
35274 0 : for(j=0; j<=k; j++)
35275 : {
35276 0 : v = v+a->vals.ptr.p_double[offsa+j]*a->vals.ptr.p_double[offsl+j];
35277 : }
35278 0 : vv = (a->vals.ptr.p_double[offsa+k+1]-v)/a->vals.ptr.p_double[offsl+k+1];
35279 0 : a->vals.ptr.p_double[offsa+k+1] = vv;
35280 0 : a12 = a12+vv*vv;
35281 : }
35282 : }
35283 :
35284 : /*
35285 : * Calculate CHOLESKY(B-A1*A1')
35286 : */
35287 0 : offsa = a->ridx.ptr.p_int[nready]+a->didx.ptr.p_int[nready];
35288 0 : v = a->vals.ptr.p_double[offsa];
35289 0 : if( ae_fp_less_eq(v,a12) )
35290 : {
35291 0 : result = ae_false;
35292 0 : return result;
35293 : }
35294 0 : a->vals.ptr.p_double[offsa] = ae_sqrt(v-a12, _state);
35295 :
35296 : /*
35297 : * Increase size of the updated matrix
35298 : */
35299 0 : inc(&nready, _state);
35300 : }
35301 :
35302 : /*
35303 : * transpose if needed
35304 : */
35305 0 : if( isupper )
35306 : {
35307 0 : sparsetransposesks(a, _state);
35308 : }
35309 0 : result = ae_true;
35310 0 : return result;
35311 : }
35312 :
35313 :
35314 : /*************************************************************************
35315 : Sparse Cholesky decomposition for a matrix stored in any sparse storage,
35316 : without rows/cols permutation.
35317 :
35318 : This function is the most convenient (less parameters to specify), although
35319 : less efficient, version of sparse Cholesky.
35320 :
35321 : Internally it:
35322 : * calls SparseCholeskyAnalyze() function to perform symbolic analysis
35323 : phase with no permutation being configured.
35324 : * calls SparseCholeskyFactorize() function to perform numerical phase of
35325 : the factorization
35326 :
35327 : Following alternatives may result in better performance:
35328 : * using SparseCholeskyP(), which selects best pivoting available, which
35329 : almost always results in improved sparsity and cache locality
35330 : * using SparseCholeskyAnalyze() and SparseCholeskyFactorize() functions
35331 : directly, which may improve performance of repetitive factorizations
35332 : with same sparsity patterns.
35333 :
35334 : The latter also allows one to perform LDLT factorization of indefinite
35335 : matrix (one with strictly diagonal D, which is known to be stable only
35336 : in few special cases, like quasi-definite matrices).
35337 :
35338 : INPUT PARAMETERS:
35339 : A - a square NxN sparse matrix, stored in any storage format.
35340 : IsUpper - if IsUpper=True, then factorization is performed on upper
35341 : triangle. Another triangle is ignored on input, dropped
35342 : on output. Similarly, if IsUpper=False, the lower triangle
35343 : is processed.
35344 :
35345 : OUTPUT PARAMETERS:
35346 : A - the result of factorization, stored in CRS format:
35347 : * if IsUpper=True, then the upper triangle contains matrix
35348 : U such that A = U^T*U and the lower triangle is empty.
35349 : * similarly, if IsUpper=False, then lower triangular L is
35350 : returned and we have A = L*(L^T).
35351 : Note that THIS function does not perform permutation of
35352 : the rows to reduce fill-in.
35353 :
35354 : RESULT:
35355 : If the matrix is positive-definite, the function returns True.
35356 : Otherwise, the function returns False. Contents of A is undefined
35357 : in such case.
35358 :
35359 : NOTE: for performance reasons this function does NOT check that input
35360 : matrix includes only finite values. It is your responsibility to
35361 : make sure that there are no infinite or NAN values in the matrix.
35362 :
35363 : -- ALGLIB routine --
35364 : 16.09.2020
35365 : Bochkanov Sergey
35366 : *************************************************************************/
35367 0 : ae_bool sparsecholesky(sparsematrix* a, ae_bool isupper, ae_state *_state)
35368 : {
35369 : ae_frame _frame_block;
35370 : sparsedecompositionanalysis analysis;
35371 : ae_int_t facttype;
35372 : ae_int_t permtype;
35373 : ae_vector dummyd;
35374 : ae_vector dummyp;
35375 : ae_bool result;
35376 :
35377 0 : ae_frame_make(_state, &_frame_block);
35378 0 : memset(&analysis, 0, sizeof(analysis));
35379 0 : memset(&dummyd, 0, sizeof(dummyd));
35380 0 : memset(&dummyp, 0, sizeof(dummyp));
35381 0 : _sparsedecompositionanalysis_init(&analysis, _state, ae_true);
35382 0 : ae_vector_init(&dummyd, 0, DT_REAL, _state, ae_true);
35383 0 : ae_vector_init(&dummyp, 0, DT_INT, _state, ae_true);
35384 :
35385 0 : ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SparseCholesky: A is not square", _state);
35386 :
35387 : /*
35388 : * Quick exit
35389 : */
35390 0 : if( sparsegetnrows(a, _state)==0 )
35391 : {
35392 0 : result = ae_true;
35393 0 : ae_frame_leave(_state);
35394 0 : return result;
35395 : }
35396 :
35397 : /*
35398 : * Choose factorization and permutation: vanilla Cholesky and no permutation
35399 : */
35400 0 : facttype = 0;
35401 0 : permtype = -1;
35402 :
35403 : /*
35404 : * Easy case - CRS matrix in lower triangle, no conversion or transposition is needed
35405 : */
35406 0 : if( sparseiscrs(a, _state)&&!isupper )
35407 : {
35408 0 : result = spsymmanalyze(a, facttype, permtype, &analysis.analysis, _state);
35409 0 : if( !result )
35410 : {
35411 0 : ae_frame_leave(_state);
35412 0 : return result;
35413 : }
35414 0 : result = spsymmfactorize(&analysis.analysis, a, &dummyd, &dummyp, _state);
35415 0 : ae_frame_leave(_state);
35416 0 : return result;
35417 : }
35418 :
35419 : /*
35420 : * A bit more complex - we need conversion and/or transposition
35421 : */
35422 0 : if( isupper )
35423 : {
35424 0 : sparsecopytocrsbuf(a, &analysis.wrkat, _state);
35425 0 : sparsecopytransposecrsbuf(&analysis.wrkat, &analysis.wrka, _state);
35426 : }
35427 : else
35428 : {
35429 0 : sparsecopytocrsbuf(a, &analysis.wrka, _state);
35430 : }
35431 0 : result = spsymmanalyze(&analysis.wrka, facttype, permtype, &analysis.analysis, _state);
35432 0 : if( !result )
35433 : {
35434 0 : ae_frame_leave(_state);
35435 0 : return result;
35436 : }
35437 0 : result = spsymmfactorize(&analysis.analysis, &analysis.wrka, &dummyd, &dummyp, _state);
35438 0 : if( !result )
35439 : {
35440 0 : ae_frame_leave(_state);
35441 0 : return result;
35442 : }
35443 0 : if( isupper )
35444 : {
35445 0 : sparsecopytransposecrsbuf(&analysis.wrka, a, _state);
35446 : }
35447 : else
35448 : {
35449 0 : sparsecopybuf(&analysis.wrka, a, _state);
35450 : }
35451 0 : ae_frame_leave(_state);
35452 0 : return result;
35453 : }
35454 :
35455 :
35456 : /*************************************************************************
35457 : Sparse Cholesky decomposition for a matrix stored in any sparse storage
35458 : format, with performance-enhancing permutation of rows/cols.
35459 :
35460 : Present version is configured to perform supernodal permutation which
35461 : sparsity reducing ordering.
35462 :
35463 : This function is a wrapper around generic sparse decomposition functions
35464 : that internally:
35465 : * calls SparseCholeskyAnalyze() function to perform symbolic analysis
35466 : phase with best available permutation being configured.
35467 : * calls SparseCholeskyFactorize() function to perform numerical phase of
35468 : the factorization.
35469 :
35470 : NOTE: using SparseCholeskyAnalyze() and SparseCholeskyFactorize() directly
35471 : may improve performance of repetitive factorizations with same
35472 : sparsity patterns. It also allows one to perform LDLT factorization
35473 : of indefinite matrix - a factorization with strictly diagonal D,
35474 : which is known to be stable only in few special cases, like quasi-
35475 : definite matrices.
35476 :
35477 : INPUT PARAMETERS:
35478 : A - a square NxN sparse matrix, stored in any storage format.
35479 : IsUpper - if IsUpper=True, then factorization is performed on upper
35480 : triangle. Another triangle is ignored on input, dropped
35481 : on output. Similarly, if IsUpper=False, the lower triangle
35482 : is processed.
35483 :
35484 : OUTPUT PARAMETERS:
35485 : A - the result of factorization, stored in CRS format:
35486 : * if IsUpper=True, then the upper triangle contains matrix
35487 : U such that A = U^T*U and the lower triangle is empty.
35488 : * similarly, if IsUpper=False, then lower triangular L is
35489 : returned and we have A = L*(L^T).
35490 : P - a row/column permutation, a product of P0*P1*...*Pk, k=N-1,
35491 : with Pi being permutation of rows/cols I and P[I]
35492 :
35493 : RESULT:
35494 : If the matrix is positive-definite, the function returns True.
35495 : Otherwise, the function returns False. Contents of A is undefined
35496 : in such case.
35497 :
35498 : NOTE: for performance reasons this function does NOT check that input
35499 : matrix includes only finite values. It is your responsibility to
35500 : make sure that there are no infinite or NAN values in the matrix.
35501 :
35502 : -- ALGLIB routine --
35503 : 16.09.2020
35504 : Bochkanov Sergey
35505 : *************************************************************************/
35506 0 : ae_bool sparsecholeskyp(sparsematrix* a,
35507 : ae_bool isupper,
35508 : /* Integer */ ae_vector* p,
35509 : ae_state *_state)
35510 : {
35511 : ae_frame _frame_block;
35512 : sparsedecompositionanalysis analysis;
35513 : ae_vector dummyd;
35514 : ae_int_t facttype;
35515 : ae_int_t permtype;
35516 : ae_bool result;
35517 :
35518 0 : ae_frame_make(_state, &_frame_block);
35519 0 : memset(&analysis, 0, sizeof(analysis));
35520 0 : memset(&dummyd, 0, sizeof(dummyd));
35521 0 : ae_vector_clear(p);
35522 0 : _sparsedecompositionanalysis_init(&analysis, _state, ae_true);
35523 0 : ae_vector_init(&dummyd, 0, DT_REAL, _state, ae_true);
35524 :
35525 0 : ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SparseCholeskyP: A is not square", _state);
35526 :
35527 : /*
35528 : * Quick exit
35529 : */
35530 0 : if( sparsegetnrows(a, _state)==0 )
35531 : {
35532 0 : result = ae_true;
35533 0 : ae_frame_leave(_state);
35534 0 : return result;
35535 : }
35536 :
35537 : /*
35538 : * Choose factorization and permutation: vanilla Cholesky and best permutation available
35539 : */
35540 0 : facttype = 0;
35541 0 : permtype = 0;
35542 :
35543 : /*
35544 : * Easy case - CRS matrix in lower triangle, no conversion or transposition is needed
35545 : */
35546 0 : if( sparseiscrs(a, _state)&&!isupper )
35547 : {
35548 0 : result = spsymmanalyze(a, facttype, permtype, &analysis.analysis, _state);
35549 0 : if( !result )
35550 : {
35551 0 : ae_frame_leave(_state);
35552 0 : return result;
35553 : }
35554 0 : result = spsymmfactorize(&analysis.analysis, a, &dummyd, p, _state);
35555 0 : ae_frame_leave(_state);
35556 0 : return result;
35557 : }
35558 :
35559 : /*
35560 : * A bit more complex - we need conversion and/or transposition
35561 : */
35562 0 : if( isupper )
35563 : {
35564 0 : sparsecopytocrsbuf(a, &analysis.wrkat, _state);
35565 0 : sparsecopytransposecrsbuf(&analysis.wrkat, &analysis.wrka, _state);
35566 : }
35567 : else
35568 : {
35569 0 : sparsecopytocrsbuf(a, &analysis.wrka, _state);
35570 : }
35571 0 : result = spsymmanalyze(&analysis.wrka, facttype, permtype, &analysis.analysis, _state);
35572 0 : if( !result )
35573 : {
35574 0 : ae_frame_leave(_state);
35575 0 : return result;
35576 : }
35577 0 : result = spsymmfactorize(&analysis.analysis, &analysis.wrka, &dummyd, p, _state);
35578 0 : if( !result )
35579 : {
35580 0 : ae_frame_leave(_state);
35581 0 : return result;
35582 : }
35583 0 : if( isupper )
35584 : {
35585 0 : sparsecopytransposecrsbuf(&analysis.wrka, a, _state);
35586 : }
35587 : else
35588 : {
35589 0 : sparsecopybuf(&analysis.wrka, a, _state);
35590 : }
35591 0 : ae_frame_leave(_state);
35592 0 : return result;
35593 : }
35594 :
35595 :
35596 : /*************************************************************************
35597 : Sparse Cholesky/LDLT decomposition: symbolic analysis phase.
35598 :
35599 : This function is a part of the 'expert' sparse Cholesky API:
35600 : * SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads
35601 : matrix to be factorized into internal storage
35602 : * SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT
35603 : with lower bounds on pivot magnitudes and additional overflow safeguards
35604 : * SparseCholeskyFactorize(), that performs numeric factorization using
35605 : precomputed symbolic analysis and internally stored matrix - and outputs
35606 : result
35607 : * SparseCholeskyReload(), that reloads one more matrix with same sparsity
35608 : pattern into internal storage so one may reuse previously allocated
35609 : temporaries and previously performed symbolic analysis
35610 :
35611 : This specific function performs preliminary analysis of the Cholesky/LDLT
35612 : factorization. It allows to choose different permutation types and to
35613 : choose between classic Cholesky and indefinite LDLT factorization (the
35614 : latter is computed with strictly diagonal D, i.e. without Bunch-Kauffman
35615 : pivoting).
35616 :
35617 : NOTE: L*D*LT family of factorization may be used to factorize indefinite
35618 : matrices. However, numerical stability is guaranteed ONLY for a class
35619 : of quasi-definite matrices.
35620 :
35621 : NOTE: all internal processing is performed with lower triangular matrices
35622 : stored in CRS format. Any other storage formats and/or upper
35623 : triangular storage means that one format conversion and/or one
35624 : transposition will be performed internally for the analysis and
35625 : factorization phases. Thus, highest performance is achieved when
35626 : input is a lower triangular CRS matrix.
35627 :
35628 : INPUT PARAMETERS:
35629 : A - sparse square matrix in any sparse storage format.
35630 : IsUpper - whether upper or lower triangle is decomposed (the
35631 : other one is ignored).
35632 : FactType - factorization type:
35633 : * 0 for traditional Cholesky of SPD matrix
35634 : * 1 for LDLT decomposition with strictly diagonal D,
35635 : which may have non-positive entries.
35636 : PermType - permutation type:
35637 : *-1 for absence of permutation
35638 : * 0 for best fill-in reducing permutation available
35639 : * 1 for supernodal ordering (improves locality and
35640 : performance, does NOT change fill-in factor)
35641 : * 2 for AMD (approximate minimum degree) ordering
35642 :
35643 : OUTPUT PARAMETERS:
35644 : Analysis - contains:
35645 : * symbolic analysis of the matrix structure which will
35646 : be used later to guide numerical factorization.
35647 : * specific numeric values loaded into internal memory
35648 : waiting for the factorization to be performed
35649 :
35650 : This function fails if and only if the matrix A is symbolically degenerate
35651 : i.e. has diagonal element which is exactly zero. In such case False is
35652 : returned, contents of Analysis object is undefined.
35653 :
35654 : -- ALGLIB routine --
35655 : 20.09.2020
35656 : Bochkanov Sergey
35657 : *************************************************************************/
35658 0 : ae_bool sparsecholeskyanalyze(sparsematrix* a,
35659 : ae_bool isupper,
35660 : ae_int_t facttype,
35661 : ae_int_t permtype,
35662 : sparsedecompositionanalysis* analysis,
35663 : ae_state *_state)
35664 : {
35665 : ae_bool result;
35666 :
35667 0 : _sparsedecompositionanalysis_clear(analysis);
35668 :
35669 0 : ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SparseCholeskyAnalyze: A is not square", _state);
35670 0 : ae_assert(facttype==0||facttype==1, "SparseCholeskyAnalyze: unexpected FactType", _state);
35671 0 : ae_assert((((permtype==0||permtype==1)||permtype==2)||permtype==-1)||permtype==-2, "SparseCholeskyAnalyze: unexpected PermType", _state);
35672 0 : analysis->n = sparsegetnrows(a, _state);
35673 0 : analysis->facttype = facttype;
35674 0 : analysis->permtype = permtype;
35675 0 : if( !sparseiscrs(a, _state) )
35676 : {
35677 :
35678 : /*
35679 : * The matrix is stored in non-CRS format. First, we have to convert
35680 : * it to CRS. Then we may need to transpose it in order to get lower
35681 : * triangular one (as supported by SPSymmAnalyze).
35682 : */
35683 0 : sparsecopytocrs(a, &analysis->crsa, _state);
35684 0 : if( isupper )
35685 : {
35686 0 : sparsecopytransposecrsbuf(&analysis->crsa, &analysis->crsat, _state);
35687 0 : result = spsymmanalyze(&analysis->crsat, facttype, permtype, &analysis->analysis, _state);
35688 : }
35689 : else
35690 : {
35691 0 : result = spsymmanalyze(&analysis->crsa, facttype, permtype, &analysis->analysis, _state);
35692 : }
35693 : }
35694 : else
35695 : {
35696 :
35697 : /*
35698 : * The matrix is stored in CRS format. However we may need to
35699 : * transpose it in order to get lower triangular one (as supported
35700 : * by SPSymmAnalyze).
35701 : */
35702 0 : if( isupper )
35703 : {
35704 0 : sparsecopytransposecrsbuf(a, &analysis->crsat, _state);
35705 0 : result = spsymmanalyze(&analysis->crsat, facttype, permtype, &analysis->analysis, _state);
35706 : }
35707 : else
35708 : {
35709 0 : result = spsymmanalyze(a, facttype, permtype, &analysis->analysis, _state);
35710 : }
35711 : }
35712 0 : return result;
35713 : }
35714 :
35715 :
35716 : /*************************************************************************
35717 : Allows to control stability-improving modification strategy for sparse
35718 : Cholesky/LDLT decompositions. Modified Cholesky is more robust than its
35719 : unmodified counterpart.
35720 :
35721 : This function is a part of the 'expert' sparse Cholesky API:
35722 : * SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads
35723 : matrix to be factorized into internal storage
35724 : * SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT
35725 : with lower bounds on pivot magnitudes and additional overflow safeguards
35726 : * SparseCholeskyFactorize(), that performs numeric factorization using
35727 : precomputed symbolic analysis and internally stored matrix - and outputs
35728 : result
35729 : * SparseCholeskyReload(), that reloads one more matrix with same sparsity
35730 : pattern into internal storage so one may reuse previously allocated
35731 : temporaries and previously performed symbolic analysis
35732 :
35733 : INPUT PARAMETERS:
35734 : Analysis - symbolic analysis of the matrix structure
35735 : ModStrategy - modification type:
35736 : * 0 for traditional Cholesky/LDLT (Cholesky fails when
35737 : encounters nonpositive pivot, LDLT fails when zero
35738 : pivot is encountered, no stability checks for
35739 : overflows/underflows)
35740 : * 1 for modified Cholesky with additional checks:
35741 : * pivots less than ModParam0 are increased; (similar
35742 : sign-preserving procedure is applied during LDLT)
35743 : * if, at some moment, sum of absolute values of
35744 : elements in column J will become greater than
35745 : ModParam1, Cholesky/LDLT will treat it as failure
35746 : and will stop immediately
35747 : P0, P1, P2,P3 - modification parameters #0 #1, #2 and #3.
35748 : Params #2 and #3 are ignored in current version.
35749 :
35750 : OUTPUT PARAMETERS:
35751 : Analysis - symbolic analysis of the matrix structure, new strategy
35752 : Results will be seen with next SparseCholeskyFactorize()
35753 : call.
35754 :
35755 : -- ALGLIB routine --
35756 : 20.09.2020
35757 : Bochkanov Sergey
35758 : *************************************************************************/
35759 0 : void sparsecholeskysetmodtype(sparsedecompositionanalysis* analysis,
35760 : ae_int_t modstrategy,
35761 : double p0,
35762 : double p1,
35763 : double p2,
35764 : double p3,
35765 : ae_state *_state)
35766 : {
35767 :
35768 :
35769 0 : spsymmsetmodificationstrategy(&analysis->analysis, modstrategy, p0, p1, p2, p3, _state);
35770 0 : }
35771 :
35772 :
35773 : /*************************************************************************
35774 : Sparse Cholesky decomposition: numerical analysis phase.
35775 :
35776 : This function is a part of the 'expert' sparse Cholesky API:
35777 : * SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads
35778 : matrix to be factorized into internal storage
35779 : * SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT
35780 : with lower bounds on pivot magnitudes and additional overflow safeguards
35781 : * SparseCholeskyFactorize(), that performs numeric factorization using
35782 : precomputed symbolic analysis and internally stored matrix - and outputs
35783 : result
35784 : * SparseCholeskyReload(), that reloads one more matrix with same sparsity
35785 : pattern into internal storage so one may reuse previously allocated
35786 : temporaries and previously performed symbolic analysis
35787 :
35788 : Depending on settings specified during SparseCholeskyAnalyze() call it may
35789 : produce classic Cholesky or L*D*LT decomposition (with strictly diagonal
35790 : D), without permutation or with performance-enhancing permutation P.
35791 :
35792 : NOTE: all internal processing is performed with lower triangular matrices
35793 : stored in CRS format. Any other storage formats and/or upper
35794 : triangular storage means that one format conversion and/or one
35795 : transposition will be performed internally for the analysis and
35796 : factorization phases. Thus, highest performance is achieved when
35797 : input is a lower triangular CRS matrix, and lower triangular output
35798 : is requested.
35799 :
35800 : NOTE: L*D*LT family of factorization may be used to factorize indefinite
35801 : matrices. However, numerical stability is guaranteed ONLY for a class
35802 : of quasi-definite matrices.
35803 :
35804 : INPUT PARAMETERS:
35805 : Analysis - prior analysis with internally stored matrix which will
35806 : be factorized
35807 : NeedUpper - whether upper triangular or lower triangular output is
35808 : needed
35809 :
35810 : OUTPUT PARAMETERS:
35811 : A - Cholesky decomposition of A stored in lower triangular
35812 : CRS format, i.e. A=L*L' (or upper triangular CRS, with
35813 : A=U'*U, depending on NeedUpper parameter).
35814 : D - array[N], diagonal factor. If no diagonal factor was
35815 : required during analysis phase, still returned but
35816 : filled with 1's
35817 : P - array[N], pivots. Permutation matrix P is a product of
35818 : P(0)*P(1)*...*P(N-1), where P(i) is a permutation of
35819 : row/col I and P[I] (with P[I]>=I).
35820 : If no permutation was requested during analysis phase,
35821 : still returned but filled with identity permutation.
35822 :
35823 : The function returns True when factorization resulted in nondegenerate
35824 : matrix. False is returned when factorization fails (Cholesky factorization
35825 : of indefinite matrix) or LDLT factorization has exactly zero elements at
35826 : the diagonal. In the latter case contents of A, D and P is undefined.
35827 :
35828 : The analysis object is not changed during the factorization. Subsequent
35829 : calls to SparseCholeskyFactorize() will result in same factorization being
35830 : performed one more time.
35831 :
35832 : -- ALGLIB routine --
35833 : 20.09.2020
35834 : Bochkanov Sergey
35835 : *************************************************************************/
35836 0 : ae_bool sparsecholeskyfactorize(sparsedecompositionanalysis* analysis,
35837 : ae_bool needupper,
35838 : sparsematrix* a,
35839 : /* Real */ ae_vector* d,
35840 : /* Integer */ ae_vector* p,
35841 : ae_state *_state)
35842 : {
35843 : ae_bool result;
35844 :
35845 0 : _sparsematrix_clear(a);
35846 0 : ae_vector_clear(d);
35847 0 : ae_vector_clear(p);
35848 :
35849 0 : if( needupper )
35850 : {
35851 0 : result = spsymmfactorize(&analysis->analysis, &analysis->wrka, d, p, _state);
35852 0 : if( !result )
35853 : {
35854 0 : return result;
35855 : }
35856 0 : sparsecopytransposecrsbuf(&analysis->wrka, a, _state);
35857 : }
35858 : else
35859 : {
35860 0 : result = spsymmfactorize(&analysis->analysis, a, d, p, _state);
35861 : }
35862 0 : return result;
35863 : }
35864 :
35865 :
35866 : /*************************************************************************
35867 : Sparse Cholesky decomposition: update internally stored matrix with
35868 : another one with exactly same sparsity pattern.
35869 :
35870 : This function is a part of the 'expert' sparse Cholesky API:
35871 : * SparseCholeskyAnalyze(), that performs symbolic analysis phase and loads
35872 : matrix to be factorized into internal storage
35873 : * SparseCholeskySetModType(), that allows to use modified Cholesky/LDLT
35874 : with lower bounds on pivot magnitudes and additional overflow safeguards
35875 : * SparseCholeskyFactorize(), that performs numeric factorization using
35876 : precomputed symbolic analysis and internally stored matrix - and outputs
35877 : result
35878 : * SparseCholeskyReload(), that reloads one more matrix with same sparsity
35879 : pattern into internal storage so one may reuse previously allocated
35880 : temporaries and previously performed symbolic analysis
35881 :
35882 : This specific function replaces internally stored numerical values with
35883 : ones from another sparse matrix (but having exactly same sparsity pattern
35884 : as one that was used for initial SparseCholeskyAnalyze() call).
35885 :
35886 : NOTE: all internal processing is performed with lower triangular matrices
35887 : stored in CRS format. Any other storage formats and/or upper
35888 : triangular storage means that one format conversion and/or one
35889 : transposition will be performed internally for the analysis and
35890 : factorization phases. Thus, highest performance is achieved when
35891 : input is a lower triangular CRS matrix.
35892 :
35893 : INPUT PARAMETERS:
35894 : Analysis - analysis object
35895 : A - sparse square matrix in any sparse storage format. It
35896 : MUST have exactly same sparsity pattern as that of the
35897 : matrix that was passed to SparseCholeskyAnalyze().
35898 : Any difference (missing elements or additional elements)
35899 : may result in unpredictable and undefined behavior -
35900 : an algorithm may fail due to memory access violation.
35901 : IsUpper - whether upper or lower triangle is decomposed (the
35902 : other one is ignored).
35903 :
35904 : OUTPUT PARAMETERS:
35905 : Analysis - contains:
35906 : * symbolic analysis of the matrix structure which will
35907 : be used later to guide numerical factorization.
35908 : * specific numeric values loaded into internal memory
35909 : waiting for the factorization to be performed
35910 :
35911 : -- ALGLIB routine --
35912 : 20.09.2020
35913 : Bochkanov Sergey
35914 : *************************************************************************/
35915 0 : void sparsecholeskyreload(sparsedecompositionanalysis* analysis,
35916 : sparsematrix* a,
35917 : ae_bool isupper,
35918 : ae_state *_state)
35919 : {
35920 :
35921 :
35922 0 : ae_assert(sparsegetnrows(a, _state)==sparsegetncols(a, _state), "SparseCholeskyReload: A is not square", _state);
35923 0 : ae_assert(sparsegetnrows(a, _state)==analysis->n, "SparseCholeskyReload: size of A does not match that stored in Analysis", _state);
35924 0 : if( !sparseiscrs(a, _state) )
35925 : {
35926 :
35927 : /*
35928 : * The matrix is stored in non-CRS format. First, we have to convert
35929 : * it to CRS. Then we may need to transpose it in order to get lower
35930 : * triangular one (as supported by SPSymmAnalyze).
35931 : */
35932 0 : sparsecopytocrs(a, &analysis->crsa, _state);
35933 0 : if( isupper )
35934 : {
35935 0 : sparsecopytransposecrsbuf(&analysis->crsa, &analysis->crsat, _state);
35936 0 : spsymmreload(&analysis->analysis, &analysis->crsat, _state);
35937 : }
35938 : else
35939 : {
35940 0 : spsymmreload(&analysis->analysis, &analysis->crsa, _state);
35941 : }
35942 : }
35943 : else
35944 : {
35945 :
35946 : /*
35947 : * The matrix is stored in CRS format. However we may need to
35948 : * transpose it in order to get lower triangular one (as supported
35949 : * by SPSymmAnalyze).
35950 : */
35951 0 : if( isupper )
35952 : {
35953 0 : sparsecopytransposecrsbuf(a, &analysis->crsat, _state);
35954 0 : spsymmreload(&analysis->analysis, &analysis->crsat, _state);
35955 : }
35956 : else
35957 : {
35958 0 : spsymmreload(&analysis->analysis, a, _state);
35959 : }
35960 : }
35961 0 : }
35962 :
35963 :
35964 0 : void rmatrixlup(/* Real */ ae_matrix* a,
35965 : ae_int_t m,
35966 : ae_int_t n,
35967 : /* Integer */ ae_vector* pivots,
35968 : ae_state *_state)
35969 : {
35970 : ae_frame _frame_block;
35971 : ae_vector tmp;
35972 : ae_int_t i;
35973 : ae_int_t j;
35974 : double mx;
35975 : double v;
35976 :
35977 0 : ae_frame_make(_state, &_frame_block);
35978 0 : memset(&tmp, 0, sizeof(tmp));
35979 0 : ae_vector_clear(pivots);
35980 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
35981 :
35982 :
35983 : /*
35984 : * Internal LU decomposition subroutine.
35985 : * Never call it directly.
35986 : */
35987 0 : ae_assert(m>0, "RMatrixLUP: incorrect M!", _state);
35988 0 : ae_assert(n>0, "RMatrixLUP: incorrect N!", _state);
35989 :
35990 : /*
35991 : * Scale matrix to avoid overflows,
35992 : * decompose it, then scale back.
35993 : */
35994 0 : mx = (double)(0);
35995 0 : for(i=0; i<=m-1; i++)
35996 : {
35997 0 : for(j=0; j<=n-1; j++)
35998 : {
35999 0 : mx = ae_maxreal(mx, ae_fabs(a->ptr.pp_double[i][j], _state), _state);
36000 : }
36001 : }
36002 0 : if( ae_fp_neq(mx,(double)(0)) )
36003 : {
36004 0 : v = 1/mx;
36005 0 : for(i=0; i<=m-1; i++)
36006 : {
36007 0 : ae_v_muld(&a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
36008 : }
36009 : }
36010 0 : ae_vector_set_length(pivots, ae_minint(m, n, _state), _state);
36011 0 : ae_vector_set_length(&tmp, 2*ae_maxint(m, n, _state), _state);
36012 0 : rmatrixluprec(a, 0, m, n, pivots, &tmp, _state);
36013 0 : if( ae_fp_neq(mx,(double)(0)) )
36014 : {
36015 0 : v = mx;
36016 0 : for(i=0; i<=m-1; i++)
36017 : {
36018 0 : ae_v_muld(&a->ptr.pp_double[i][0], 1, ae_v_len(0,ae_minint(i, n-1, _state)), v);
36019 : }
36020 : }
36021 0 : ae_frame_leave(_state);
36022 0 : }
36023 :
36024 :
36025 0 : void cmatrixlup(/* Complex */ ae_matrix* a,
36026 : ae_int_t m,
36027 : ae_int_t n,
36028 : /* Integer */ ae_vector* pivots,
36029 : ae_state *_state)
36030 : {
36031 : ae_frame _frame_block;
36032 : ae_vector tmp;
36033 : ae_int_t i;
36034 : ae_int_t j;
36035 : double mx;
36036 : double v;
36037 :
36038 0 : ae_frame_make(_state, &_frame_block);
36039 0 : memset(&tmp, 0, sizeof(tmp));
36040 0 : ae_vector_clear(pivots);
36041 0 : ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true);
36042 :
36043 :
36044 : /*
36045 : * Internal LU decomposition subroutine.
36046 : * Never call it directly.
36047 : */
36048 0 : ae_assert(m>0, "CMatrixLUP: incorrect M!", _state);
36049 0 : ae_assert(n>0, "CMatrixLUP: incorrect N!", _state);
36050 :
36051 : /*
36052 : * Scale matrix to avoid overflows,
36053 : * decompose it, then scale back.
36054 : */
36055 0 : mx = (double)(0);
36056 0 : for(i=0; i<=m-1; i++)
36057 : {
36058 0 : for(j=0; j<=n-1; j++)
36059 : {
36060 0 : mx = ae_maxreal(mx, ae_c_abs(a->ptr.pp_complex[i][j], _state), _state);
36061 : }
36062 : }
36063 0 : if( ae_fp_neq(mx,(double)(0)) )
36064 : {
36065 0 : v = 1/mx;
36066 0 : for(i=0; i<=m-1; i++)
36067 : {
36068 0 : ae_v_cmuld(&a->ptr.pp_complex[i][0], 1, ae_v_len(0,n-1), v);
36069 : }
36070 : }
36071 0 : ae_vector_set_length(pivots, ae_minint(m, n, _state), _state);
36072 0 : ae_vector_set_length(&tmp, 2*ae_maxint(m, n, _state), _state);
36073 0 : cmatrixluprec(a, 0, m, n, pivots, &tmp, _state);
36074 0 : if( ae_fp_neq(mx,(double)(0)) )
36075 : {
36076 0 : v = mx;
36077 0 : for(i=0; i<=m-1; i++)
36078 : {
36079 0 : ae_v_cmuld(&a->ptr.pp_complex[i][0], 1, ae_v_len(0,ae_minint(i, n-1, _state)), v);
36080 : }
36081 : }
36082 0 : ae_frame_leave(_state);
36083 0 : }
36084 :
36085 :
36086 0 : void rmatrixplu(/* Real */ ae_matrix* a,
36087 : ae_int_t m,
36088 : ae_int_t n,
36089 : /* Integer */ ae_vector* pivots,
36090 : ae_state *_state)
36091 : {
36092 : ae_frame _frame_block;
36093 : ae_vector tmp;
36094 : ae_int_t i;
36095 : ae_int_t j;
36096 : double mx;
36097 : double v;
36098 :
36099 0 : ae_frame_make(_state, &_frame_block);
36100 0 : memset(&tmp, 0, sizeof(tmp));
36101 0 : ae_vector_clear(pivots);
36102 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
36103 :
36104 :
36105 : /*
36106 : * Internal LU decomposition subroutine.
36107 : * Never call it directly.
36108 : */
36109 0 : ae_assert(m>0, "RMatrixPLU: incorrect M!", _state);
36110 0 : ae_assert(n>0, "RMatrixPLU: incorrect N!", _state);
36111 0 : ae_vector_set_length(&tmp, 2*ae_maxint(m, n, _state), _state);
36112 0 : ae_vector_set_length(pivots, ae_minint(m, n, _state), _state);
36113 :
36114 : /*
36115 : * Scale matrix to avoid overflows,
36116 : * decompose it, then scale back.
36117 : */
36118 0 : mx = (double)(0);
36119 0 : for(i=0; i<=m-1; i++)
36120 : {
36121 0 : for(j=0; j<=n-1; j++)
36122 : {
36123 0 : mx = ae_maxreal(mx, ae_fabs(a->ptr.pp_double[i][j], _state), _state);
36124 : }
36125 : }
36126 0 : if( ae_fp_neq(mx,(double)(0)) )
36127 : {
36128 0 : v = 1/mx;
36129 0 : for(i=0; i<=m-1; i++)
36130 : {
36131 0 : ae_v_muld(&a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
36132 : }
36133 : }
36134 0 : rmatrixplurec(a, 0, m, n, pivots, &tmp, _state);
36135 0 : if( ae_fp_neq(mx,(double)(0)) )
36136 : {
36137 0 : v = mx;
36138 0 : for(i=0; i<=ae_minint(m, n, _state)-1; i++)
36139 : {
36140 0 : ae_v_muld(&a->ptr.pp_double[i][i], 1, ae_v_len(i,n-1), v);
36141 : }
36142 : }
36143 0 : ae_frame_leave(_state);
36144 0 : }
36145 :
36146 :
36147 0 : void cmatrixplu(/* Complex */ ae_matrix* a,
36148 : ae_int_t m,
36149 : ae_int_t n,
36150 : /* Integer */ ae_vector* pivots,
36151 : ae_state *_state)
36152 : {
36153 : ae_frame _frame_block;
36154 : ae_vector tmp;
36155 : ae_int_t i;
36156 : ae_int_t j;
36157 : double mx;
36158 : ae_complex v;
36159 :
36160 0 : ae_frame_make(_state, &_frame_block);
36161 0 : memset(&tmp, 0, sizeof(tmp));
36162 0 : ae_vector_clear(pivots);
36163 0 : ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true);
36164 :
36165 :
36166 : /*
36167 : * Internal LU decomposition subroutine.
36168 : * Never call it directly.
36169 : */
36170 0 : ae_assert(m>0, "CMatrixPLU: incorrect M!", _state);
36171 0 : ae_assert(n>0, "CMatrixPLU: incorrect N!", _state);
36172 0 : ae_vector_set_length(&tmp, 2*ae_maxint(m, n, _state), _state);
36173 0 : ae_vector_set_length(pivots, ae_minint(m, n, _state), _state);
36174 :
36175 : /*
36176 : * Scale matrix to avoid overflows,
36177 : * decompose it, then scale back.
36178 : */
36179 0 : mx = (double)(0);
36180 0 : for(i=0; i<=m-1; i++)
36181 : {
36182 0 : for(j=0; j<=n-1; j++)
36183 : {
36184 0 : mx = ae_maxreal(mx, ae_c_abs(a->ptr.pp_complex[i][j], _state), _state);
36185 : }
36186 : }
36187 0 : if( ae_fp_neq(mx,(double)(0)) )
36188 : {
36189 0 : v = ae_complex_from_d(1/mx);
36190 0 : for(i=0; i<=m-1; i++)
36191 : {
36192 0 : ae_v_cmulc(&a->ptr.pp_complex[i][0], 1, ae_v_len(0,n-1), v);
36193 : }
36194 : }
36195 0 : cmatrixplurec(a, 0, m, n, pivots, &tmp, _state);
36196 0 : if( ae_fp_neq(mx,(double)(0)) )
36197 : {
36198 0 : v = ae_complex_from_d(mx);
36199 0 : for(i=0; i<=ae_minint(m, n, _state)-1; i++)
36200 : {
36201 0 : ae_v_cmulc(&a->ptr.pp_complex[i][i], 1, ae_v_len(i,n-1), v);
36202 : }
36203 : }
36204 0 : ae_frame_leave(_state);
36205 0 : }
36206 :
36207 :
36208 : /*************************************************************************
36209 : Advanced interface for SPDMatrixCholesky, performs no temporary allocations.
36210 :
36211 : INPUT PARAMETERS:
36212 : A - matrix given by upper or lower triangle
36213 : Offs - offset of diagonal block to decompose
36214 : N - diagonal block size
36215 : IsUpper - what half is given
36216 : Tmp - temporary array; allocated by function, if its size is too
36217 : small; can be reused on subsequent calls.
36218 :
36219 : OUTPUT PARAMETERS:
36220 : A - upper (or lower) triangle contains Cholesky decomposition
36221 :
36222 : RESULT:
36223 : True, on success
36224 : False, on failure
36225 :
36226 : -- ALGLIB routine --
36227 : 15.12.2009
36228 : Bochkanov Sergey
36229 : *************************************************************************/
36230 0 : ae_bool spdmatrixcholeskyrec(/* Real */ ae_matrix* a,
36231 : ae_int_t offs,
36232 : ae_int_t n,
36233 : ae_bool isupper,
36234 : /* Real */ ae_vector* tmp,
36235 : ae_state *_state)
36236 : {
36237 : ae_int_t n1;
36238 : ae_int_t n2;
36239 : ae_int_t tsa;
36240 : ae_int_t tsb;
36241 : ae_bool result;
36242 :
36243 :
36244 0 : tsa = matrixtilesizea(_state);
36245 0 : tsb = matrixtilesizeb(_state);
36246 :
36247 : /*
36248 : * Allocate temporaries
36249 : */
36250 0 : if( tmp->cnt<2*n )
36251 : {
36252 0 : ae_vector_set_length(tmp, 2*n, _state);
36253 : }
36254 :
36255 : /*
36256 : * Basecases
36257 : */
36258 0 : if( n<1 )
36259 : {
36260 0 : result = ae_false;
36261 0 : return result;
36262 : }
36263 0 : if( n==1 )
36264 : {
36265 0 : if( ae_fp_greater(a->ptr.pp_double[offs][offs],(double)(0)) )
36266 : {
36267 0 : a->ptr.pp_double[offs][offs] = ae_sqrt(a->ptr.pp_double[offs][offs], _state);
36268 0 : result = ae_true;
36269 : }
36270 : else
36271 : {
36272 0 : result = ae_false;
36273 : }
36274 0 : return result;
36275 : }
36276 0 : if( n<=tsb )
36277 : {
36278 0 : if( spdmatrixcholeskymkl(a, offs, n, isupper, &result, _state) )
36279 : {
36280 0 : return result;
36281 : }
36282 : }
36283 0 : if( n<=tsa )
36284 : {
36285 0 : result = trfac_spdmatrixcholesky2(a, offs, n, isupper, tmp, _state);
36286 0 : return result;
36287 : }
36288 :
36289 : /*
36290 : * Split task into smaller ones
36291 : */
36292 0 : if( n>tsb )
36293 : {
36294 :
36295 : /*
36296 : * Split leading B-sized block from the beginning (block-matrix approach)
36297 : */
36298 0 : n1 = tsb;
36299 0 : n2 = n-n1;
36300 : }
36301 : else
36302 : {
36303 :
36304 : /*
36305 : * Smaller than B-size, perform cache-oblivious split
36306 : */
36307 0 : tiledsplit(n, tsa, &n1, &n2, _state);
36308 : }
36309 0 : result = spdmatrixcholeskyrec(a, offs, n1, isupper, tmp, _state);
36310 0 : if( !result )
36311 : {
36312 0 : return result;
36313 : }
36314 0 : if( n2>0 )
36315 : {
36316 0 : if( isupper )
36317 : {
36318 0 : rmatrixlefttrsm(n1, n2, a, offs, offs, isupper, ae_false, 1, a, offs, offs+n1, _state);
36319 0 : rmatrixsyrk(n2, n1, -1.0, a, offs, offs+n1, 1, 1.0, a, offs+n1, offs+n1, isupper, _state);
36320 : }
36321 : else
36322 : {
36323 0 : rmatrixrighttrsm(n2, n1, a, offs, offs, isupper, ae_false, 1, a, offs+n1, offs, _state);
36324 0 : rmatrixsyrk(n2, n1, -1.0, a, offs+n1, offs, 0, 1.0, a, offs+n1, offs+n1, isupper, _state);
36325 : }
36326 0 : result = spdmatrixcholeskyrec(a, offs+n1, n2, isupper, tmp, _state);
36327 0 : if( !result )
36328 : {
36329 0 : return result;
36330 : }
36331 : }
36332 0 : return result;
36333 : }
36334 :
36335 :
36336 : /*************************************************************************
36337 : Recursive computational subroutine for HPDMatrixCholesky
36338 :
36339 : -- ALGLIB routine --
36340 : 15.12.2009
36341 : Bochkanov Sergey
36342 : *************************************************************************/
36343 0 : static ae_bool trfac_hpdmatrixcholeskyrec(/* Complex */ ae_matrix* a,
36344 : ae_int_t offs,
36345 : ae_int_t n,
36346 : ae_bool isupper,
36347 : /* Complex */ ae_vector* tmp,
36348 : ae_state *_state)
36349 : {
36350 : ae_int_t n1;
36351 : ae_int_t n2;
36352 : ae_int_t tsa;
36353 : ae_int_t tsb;
36354 : ae_bool result;
36355 :
36356 :
36357 0 : tsa = matrixtilesizea(_state)/2;
36358 0 : tsb = matrixtilesizeb(_state);
36359 :
36360 : /*
36361 : * check N
36362 : */
36363 0 : if( n<1 )
36364 : {
36365 0 : result = ae_false;
36366 0 : return result;
36367 : }
36368 :
36369 : /*
36370 : * Prepare buffer
36371 : */
36372 0 : if( tmp->cnt<2*n )
36373 : {
36374 0 : ae_vector_set_length(tmp, 2*n, _state);
36375 : }
36376 :
36377 : /*
36378 : * Basecases
36379 : *
36380 : * NOTE: we do not use MKL for basecases because their price is only
36381 : * minor part of overall running time for N>256.
36382 : */
36383 0 : if( n==1 )
36384 : {
36385 0 : if( ae_fp_greater(a->ptr.pp_complex[offs][offs].x,(double)(0)) )
36386 : {
36387 0 : a->ptr.pp_complex[offs][offs] = ae_complex_from_d(ae_sqrt(a->ptr.pp_complex[offs][offs].x, _state));
36388 0 : result = ae_true;
36389 : }
36390 : else
36391 : {
36392 0 : result = ae_false;
36393 : }
36394 0 : return result;
36395 : }
36396 0 : if( n<=tsa )
36397 : {
36398 0 : result = trfac_hpdmatrixcholesky2(a, offs, n, isupper, tmp, _state);
36399 0 : return result;
36400 : }
36401 :
36402 : /*
36403 : * Split task into smaller ones
36404 : */
36405 0 : if( n>tsb )
36406 : {
36407 :
36408 : /*
36409 : * Split leading B-sized block from the beginning (block-matrix approach)
36410 : */
36411 0 : n1 = tsb;
36412 0 : n2 = n-n1;
36413 : }
36414 : else
36415 : {
36416 :
36417 : /*
36418 : * Smaller than B-size, perform cache-oblivious split
36419 : */
36420 0 : tiledsplit(n, tsa, &n1, &n2, _state);
36421 : }
36422 0 : result = trfac_hpdmatrixcholeskyrec(a, offs, n1, isupper, tmp, _state);
36423 0 : if( !result )
36424 : {
36425 0 : return result;
36426 : }
36427 0 : if( n2>0 )
36428 : {
36429 0 : if( isupper )
36430 : {
36431 0 : cmatrixlefttrsm(n1, n2, a, offs, offs, isupper, ae_false, 2, a, offs, offs+n1, _state);
36432 0 : cmatrixherk(n2, n1, -1.0, a, offs, offs+n1, 2, 1.0, a, offs+n1, offs+n1, isupper, _state);
36433 : }
36434 : else
36435 : {
36436 0 : cmatrixrighttrsm(n2, n1, a, offs, offs, isupper, ae_false, 2, a, offs+n1, offs, _state);
36437 0 : cmatrixherk(n2, n1, -1.0, a, offs+n1, offs, 0, 1.0, a, offs+n1, offs+n1, isupper, _state);
36438 : }
36439 0 : result = trfac_hpdmatrixcholeskyrec(a, offs+n1, n2, isupper, tmp, _state);
36440 0 : if( !result )
36441 : {
36442 0 : return result;
36443 : }
36444 : }
36445 0 : return result;
36446 : }
36447 :
36448 :
36449 : /*************************************************************************
36450 : Level-2 Hermitian Cholesky subroutine.
36451 :
36452 : -- LAPACK routine (version 3.0) --
36453 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
36454 : Courant Institute, Argonne National Lab, and Rice University
36455 : February 29, 1992
36456 : *************************************************************************/
36457 0 : static ae_bool trfac_hpdmatrixcholesky2(/* Complex */ ae_matrix* aaa,
36458 : ae_int_t offs,
36459 : ae_int_t n,
36460 : ae_bool isupper,
36461 : /* Complex */ ae_vector* tmp,
36462 : ae_state *_state)
36463 : {
36464 : ae_int_t i;
36465 : ae_int_t j;
36466 : double ajj;
36467 : ae_complex v;
36468 : double r;
36469 : ae_bool result;
36470 :
36471 :
36472 0 : result = ae_true;
36473 0 : if( n<0 )
36474 : {
36475 0 : result = ae_false;
36476 0 : return result;
36477 : }
36478 :
36479 : /*
36480 : * Quick return if possible
36481 : */
36482 0 : if( n==0 )
36483 : {
36484 0 : return result;
36485 : }
36486 0 : if( isupper )
36487 : {
36488 :
36489 : /*
36490 : * Compute the Cholesky factorization A = U'*U.
36491 : */
36492 0 : for(j=0; j<=n-1; j++)
36493 : {
36494 :
36495 : /*
36496 : * Compute U(J,J) and test for non-positive-definiteness.
36497 : */
36498 0 : v = ae_v_cdotproduct(&aaa->ptr.pp_complex[offs][offs+j], aaa->stride, "Conj", &aaa->ptr.pp_complex[offs][offs+j], aaa->stride, "N", ae_v_len(offs,offs+j-1));
36499 0 : ajj = ae_c_sub(aaa->ptr.pp_complex[offs+j][offs+j],v).x;
36500 0 : if( ae_fp_less_eq(ajj,(double)(0)) )
36501 : {
36502 0 : aaa->ptr.pp_complex[offs+j][offs+j] = ae_complex_from_d(ajj);
36503 0 : result = ae_false;
36504 0 : return result;
36505 : }
36506 0 : ajj = ae_sqrt(ajj, _state);
36507 0 : aaa->ptr.pp_complex[offs+j][offs+j] = ae_complex_from_d(ajj);
36508 :
36509 : /*
36510 : * Compute elements J+1:N-1 of row J.
36511 : */
36512 0 : if( j<n-1 )
36513 : {
36514 0 : if( j>0 )
36515 : {
36516 0 : ae_v_cmoveneg(&tmp->ptr.p_complex[0], 1, &aaa->ptr.pp_complex[offs][offs+j], aaa->stride, "Conj", ae_v_len(0,j-1));
36517 0 : cmatrixmv(n-j-1, j, aaa, offs, offs+j+1, 1, tmp, 0, tmp, n, _state);
36518 0 : ae_v_cadd(&aaa->ptr.pp_complex[offs+j][offs+j+1], 1, &tmp->ptr.p_complex[n], 1, "N", ae_v_len(offs+j+1,offs+n-1));
36519 : }
36520 0 : r = 1/ajj;
36521 0 : ae_v_cmuld(&aaa->ptr.pp_complex[offs+j][offs+j+1], 1, ae_v_len(offs+j+1,offs+n-1), r);
36522 : }
36523 : }
36524 : }
36525 : else
36526 : {
36527 :
36528 : /*
36529 : * Compute the Cholesky factorization A = L*L'.
36530 : */
36531 0 : for(j=0; j<=n-1; j++)
36532 : {
36533 :
36534 : /*
36535 : * Compute L(J+1,J+1) and test for non-positive-definiteness.
36536 : */
36537 0 : v = ae_v_cdotproduct(&aaa->ptr.pp_complex[offs+j][offs], 1, "Conj", &aaa->ptr.pp_complex[offs+j][offs], 1, "N", ae_v_len(offs,offs+j-1));
36538 0 : ajj = ae_c_sub(aaa->ptr.pp_complex[offs+j][offs+j],v).x;
36539 0 : if( ae_fp_less_eq(ajj,(double)(0)) )
36540 : {
36541 0 : aaa->ptr.pp_complex[offs+j][offs+j] = ae_complex_from_d(ajj);
36542 0 : result = ae_false;
36543 0 : return result;
36544 : }
36545 0 : ajj = ae_sqrt(ajj, _state);
36546 0 : aaa->ptr.pp_complex[offs+j][offs+j] = ae_complex_from_d(ajj);
36547 :
36548 : /*
36549 : * Compute elements J+1:N of column J.
36550 : */
36551 0 : if( j<n-1 )
36552 : {
36553 0 : r = 1/ajj;
36554 0 : if( j>0 )
36555 : {
36556 0 : ae_v_cmove(&tmp->ptr.p_complex[0], 1, &aaa->ptr.pp_complex[offs+j][offs], 1, "Conj", ae_v_len(0,j-1));
36557 0 : cmatrixmv(n-j-1, j, aaa, offs+j+1, offs, 0, tmp, 0, tmp, n, _state);
36558 0 : for(i=0; i<=n-j-2; i++)
36559 : {
36560 0 : aaa->ptr.pp_complex[offs+j+1+i][offs+j] = ae_c_mul_d(ae_c_sub(aaa->ptr.pp_complex[offs+j+1+i][offs+j],tmp->ptr.p_complex[n+i]),r);
36561 : }
36562 : }
36563 : else
36564 : {
36565 0 : for(i=0; i<=n-j-2; i++)
36566 : {
36567 0 : aaa->ptr.pp_complex[offs+j+1+i][offs+j] = ae_c_mul_d(aaa->ptr.pp_complex[offs+j+1+i][offs+j],r);
36568 : }
36569 : }
36570 : }
36571 : }
36572 : }
36573 0 : return result;
36574 : }
36575 :
36576 :
36577 : /*************************************************************************
36578 : Level-2 Cholesky subroutine
36579 :
36580 : -- LAPACK routine (version 3.0) --
36581 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
36582 : Courant Institute, Argonne National Lab, and Rice University
36583 : February 29, 1992
36584 : *************************************************************************/
36585 0 : static ae_bool trfac_spdmatrixcholesky2(/* Real */ ae_matrix* aaa,
36586 : ae_int_t offs,
36587 : ae_int_t n,
36588 : ae_bool isupper,
36589 : /* Real */ ae_vector* tmp,
36590 : ae_state *_state)
36591 : {
36592 : ae_int_t i;
36593 : ae_int_t j;
36594 : double ajj;
36595 : double v;
36596 : double r;
36597 : ae_bool result;
36598 :
36599 :
36600 0 : result = ae_true;
36601 0 : if( n<0 )
36602 : {
36603 0 : result = ae_false;
36604 0 : return result;
36605 : }
36606 :
36607 : /*
36608 : * Quick return if possible
36609 : */
36610 0 : if( n==0 )
36611 : {
36612 0 : return result;
36613 : }
36614 0 : if( isupper )
36615 : {
36616 :
36617 : /*
36618 : * Compute the Cholesky factorization A = U'*U.
36619 : */
36620 0 : for(j=0; j<=n-1; j++)
36621 : {
36622 :
36623 : /*
36624 : * Compute U(J,J) and test for non-positive-definiteness.
36625 : */
36626 0 : v = ae_v_dotproduct(&aaa->ptr.pp_double[offs][offs+j], aaa->stride, &aaa->ptr.pp_double[offs][offs+j], aaa->stride, ae_v_len(offs,offs+j-1));
36627 0 : ajj = aaa->ptr.pp_double[offs+j][offs+j]-v;
36628 0 : if( ae_fp_less_eq(ajj,(double)(0)) )
36629 : {
36630 0 : aaa->ptr.pp_double[offs+j][offs+j] = ajj;
36631 0 : result = ae_false;
36632 0 : return result;
36633 : }
36634 0 : ajj = ae_sqrt(ajj, _state);
36635 0 : aaa->ptr.pp_double[offs+j][offs+j] = ajj;
36636 :
36637 : /*
36638 : * Compute elements J+1:N-1 of row J.
36639 : */
36640 0 : if( j<n-1 )
36641 : {
36642 0 : if( j>0 )
36643 : {
36644 0 : ae_v_moveneg(&tmp->ptr.p_double[0], 1, &aaa->ptr.pp_double[offs][offs+j], aaa->stride, ae_v_len(0,j-1));
36645 0 : rmatrixmv(n-j-1, j, aaa, offs, offs+j+1, 1, tmp, 0, tmp, n, _state);
36646 0 : ae_v_add(&aaa->ptr.pp_double[offs+j][offs+j+1], 1, &tmp->ptr.p_double[n], 1, ae_v_len(offs+j+1,offs+n-1));
36647 : }
36648 0 : r = 1/ajj;
36649 0 : ae_v_muld(&aaa->ptr.pp_double[offs+j][offs+j+1], 1, ae_v_len(offs+j+1,offs+n-1), r);
36650 : }
36651 : }
36652 : }
36653 : else
36654 : {
36655 :
36656 : /*
36657 : * Compute the Cholesky factorization A = L*L'.
36658 : */
36659 0 : for(j=0; j<=n-1; j++)
36660 : {
36661 :
36662 : /*
36663 : * Compute L(J+1,J+1) and test for non-positive-definiteness.
36664 : */
36665 0 : v = ae_v_dotproduct(&aaa->ptr.pp_double[offs+j][offs], 1, &aaa->ptr.pp_double[offs+j][offs], 1, ae_v_len(offs,offs+j-1));
36666 0 : ajj = aaa->ptr.pp_double[offs+j][offs+j]-v;
36667 0 : if( ae_fp_less_eq(ajj,(double)(0)) )
36668 : {
36669 0 : aaa->ptr.pp_double[offs+j][offs+j] = ajj;
36670 0 : result = ae_false;
36671 0 : return result;
36672 : }
36673 0 : ajj = ae_sqrt(ajj, _state);
36674 0 : aaa->ptr.pp_double[offs+j][offs+j] = ajj;
36675 :
36676 : /*
36677 : * Compute elements J+1:N of column J.
36678 : */
36679 0 : if( j<n-1 )
36680 : {
36681 0 : r = 1/ajj;
36682 0 : if( j>0 )
36683 : {
36684 0 : ae_v_move(&tmp->ptr.p_double[0], 1, &aaa->ptr.pp_double[offs+j][offs], 1, ae_v_len(0,j-1));
36685 0 : rmatrixmv(n-j-1, j, aaa, offs+j+1, offs, 0, tmp, 0, tmp, n, _state);
36686 0 : for(i=0; i<=n-j-2; i++)
36687 : {
36688 0 : aaa->ptr.pp_double[offs+j+1+i][offs+j] = (aaa->ptr.pp_double[offs+j+1+i][offs+j]-tmp->ptr.p_double[n+i])*r;
36689 : }
36690 : }
36691 : else
36692 : {
36693 0 : for(i=0; i<=n-j-2; i++)
36694 : {
36695 0 : aaa->ptr.pp_double[offs+j+1+i][offs+j] = aaa->ptr.pp_double[offs+j+1+i][offs+j]*r;
36696 : }
36697 : }
36698 : }
36699 : }
36700 : }
36701 0 : return result;
36702 : }
36703 :
36704 :
36705 0 : void _sparsedecompositionanalysis_init(void* _p, ae_state *_state, ae_bool make_automatic)
36706 : {
36707 0 : sparsedecompositionanalysis *p = (sparsedecompositionanalysis*)_p;
36708 0 : ae_touch_ptr((void*)p);
36709 0 : _spcholanalysis_init(&p->analysis, _state, make_automatic);
36710 0 : _sparsematrix_init(&p->wrka, _state, make_automatic);
36711 0 : _sparsematrix_init(&p->wrkat, _state, make_automatic);
36712 0 : _sparsematrix_init(&p->crsa, _state, make_automatic);
36713 0 : _sparsematrix_init(&p->crsat, _state, make_automatic);
36714 0 : }
36715 :
36716 :
36717 0 : void _sparsedecompositionanalysis_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
36718 : {
36719 0 : sparsedecompositionanalysis *dst = (sparsedecompositionanalysis*)_dst;
36720 0 : sparsedecompositionanalysis *src = (sparsedecompositionanalysis*)_src;
36721 0 : dst->n = src->n;
36722 0 : dst->facttype = src->facttype;
36723 0 : dst->permtype = src->permtype;
36724 0 : _spcholanalysis_init_copy(&dst->analysis, &src->analysis, _state, make_automatic);
36725 0 : _sparsematrix_init_copy(&dst->wrka, &src->wrka, _state, make_automatic);
36726 0 : _sparsematrix_init_copy(&dst->wrkat, &src->wrkat, _state, make_automatic);
36727 0 : _sparsematrix_init_copy(&dst->crsa, &src->crsa, _state, make_automatic);
36728 0 : _sparsematrix_init_copy(&dst->crsat, &src->crsat, _state, make_automatic);
36729 0 : }
36730 :
36731 :
36732 0 : void _sparsedecompositionanalysis_clear(void* _p)
36733 : {
36734 0 : sparsedecompositionanalysis *p = (sparsedecompositionanalysis*)_p;
36735 0 : ae_touch_ptr((void*)p);
36736 0 : _spcholanalysis_clear(&p->analysis);
36737 0 : _sparsematrix_clear(&p->wrka);
36738 0 : _sparsematrix_clear(&p->wrkat);
36739 0 : _sparsematrix_clear(&p->crsa);
36740 0 : _sparsematrix_clear(&p->crsat);
36741 0 : }
36742 :
36743 :
36744 0 : void _sparsedecompositionanalysis_destroy(void* _p)
36745 : {
36746 0 : sparsedecompositionanalysis *p = (sparsedecompositionanalysis*)_p;
36747 0 : ae_touch_ptr((void*)p);
36748 0 : _spcholanalysis_destroy(&p->analysis);
36749 0 : _sparsematrix_destroy(&p->wrka);
36750 0 : _sparsematrix_destroy(&p->wrkat);
36751 0 : _sparsematrix_destroy(&p->crsa);
36752 0 : _sparsematrix_destroy(&p->crsat);
36753 0 : }
36754 :
36755 :
36756 : #endif
36757 : #if defined(AE_COMPILE_RCOND) || !defined(AE_PARTIAL_BUILD)
36758 :
36759 :
36760 : /*************************************************************************
36761 : Estimate of a matrix condition number (1-norm)
36762 :
36763 : The algorithm calculates a lower bound of the condition number. In this case,
36764 : the algorithm does not return a lower bound of the condition number, but an
36765 : inverse number (to avoid an overflow in case of a singular matrix).
36766 :
36767 : Input parameters:
36768 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
36769 : N - size of matrix A.
36770 :
36771 : Result: 1/LowerBound(cond(A))
36772 :
36773 : NOTE:
36774 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
36775 : 0.0 is returned in such cases.
36776 : *************************************************************************/
36777 0 : double rmatrixrcond1(/* Real */ ae_matrix* a,
36778 : ae_int_t n,
36779 : ae_state *_state)
36780 : {
36781 : ae_frame _frame_block;
36782 : ae_matrix _a;
36783 : ae_int_t i;
36784 : ae_int_t j;
36785 : double v;
36786 : double nrm;
36787 : ae_vector pivots;
36788 : ae_vector t;
36789 : double result;
36790 :
36791 0 : ae_frame_make(_state, &_frame_block);
36792 0 : memset(&_a, 0, sizeof(_a));
36793 0 : memset(&pivots, 0, sizeof(pivots));
36794 0 : memset(&t, 0, sizeof(t));
36795 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
36796 0 : a = &_a;
36797 0 : ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
36798 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
36799 :
36800 0 : ae_assert(n>=1, "RMatrixRCond1: N<1!", _state);
36801 0 : ae_vector_set_length(&t, n, _state);
36802 0 : for(i=0; i<=n-1; i++)
36803 : {
36804 0 : t.ptr.p_double[i] = (double)(0);
36805 : }
36806 0 : for(i=0; i<=n-1; i++)
36807 : {
36808 0 : for(j=0; j<=n-1; j++)
36809 : {
36810 0 : t.ptr.p_double[j] = t.ptr.p_double[j]+ae_fabs(a->ptr.pp_double[i][j], _state);
36811 : }
36812 : }
36813 0 : nrm = (double)(0);
36814 0 : for(i=0; i<=n-1; i++)
36815 : {
36816 0 : nrm = ae_maxreal(nrm, t.ptr.p_double[i], _state);
36817 : }
36818 0 : rmatrixlu(a, n, n, &pivots, _state);
36819 0 : rcond_rmatrixrcondluinternal(a, n, ae_true, ae_true, nrm, &v, _state);
36820 0 : result = v;
36821 0 : ae_frame_leave(_state);
36822 0 : return result;
36823 : }
36824 :
36825 :
36826 : /*************************************************************************
36827 : Estimate of a matrix condition number (infinity-norm).
36828 :
36829 : The algorithm calculates a lower bound of the condition number. In this case,
36830 : the algorithm does not return a lower bound of the condition number, but an
36831 : inverse number (to avoid an overflow in case of a singular matrix).
36832 :
36833 : Input parameters:
36834 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
36835 : N - size of matrix A.
36836 :
36837 : Result: 1/LowerBound(cond(A))
36838 :
36839 : NOTE:
36840 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
36841 : 0.0 is returned in such cases.
36842 : *************************************************************************/
36843 0 : double rmatrixrcondinf(/* Real */ ae_matrix* a,
36844 : ae_int_t n,
36845 : ae_state *_state)
36846 : {
36847 : ae_frame _frame_block;
36848 : ae_matrix _a;
36849 : ae_int_t i;
36850 : ae_int_t j;
36851 : double v;
36852 : double nrm;
36853 : ae_vector pivots;
36854 : double result;
36855 :
36856 0 : ae_frame_make(_state, &_frame_block);
36857 0 : memset(&_a, 0, sizeof(_a));
36858 0 : memset(&pivots, 0, sizeof(pivots));
36859 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
36860 0 : a = &_a;
36861 0 : ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
36862 :
36863 0 : ae_assert(n>=1, "RMatrixRCondInf: N<1!", _state);
36864 0 : nrm = (double)(0);
36865 0 : for(i=0; i<=n-1; i++)
36866 : {
36867 0 : v = (double)(0);
36868 0 : for(j=0; j<=n-1; j++)
36869 : {
36870 0 : v = v+ae_fabs(a->ptr.pp_double[i][j], _state);
36871 : }
36872 0 : nrm = ae_maxreal(nrm, v, _state);
36873 : }
36874 0 : rmatrixlu(a, n, n, &pivots, _state);
36875 0 : rcond_rmatrixrcondluinternal(a, n, ae_false, ae_true, nrm, &v, _state);
36876 0 : result = v;
36877 0 : ae_frame_leave(_state);
36878 0 : return result;
36879 : }
36880 :
36881 :
36882 : /*************************************************************************
36883 : Condition number estimate of a symmetric positive definite matrix.
36884 :
36885 : The algorithm calculates a lower bound of the condition number. In this case,
36886 : the algorithm does not return a lower bound of the condition number, but an
36887 : inverse number (to avoid an overflow in case of a singular matrix).
36888 :
36889 : It should be noted that 1-norm and inf-norm of condition numbers of symmetric
36890 : matrices are equal, so the algorithm doesn't take into account the
36891 : differences between these types of norms.
36892 :
36893 : Input parameters:
36894 : A - symmetric positive definite matrix which is given by its
36895 : upper or lower triangle depending on the value of
36896 : IsUpper. Array with elements [0..N-1, 0..N-1].
36897 : N - size of matrix A.
36898 : IsUpper - storage format.
36899 :
36900 : Result:
36901 : 1/LowerBound(cond(A)), if matrix A is positive definite,
36902 : -1, if matrix A is not positive definite, and its condition number
36903 : could not be found by this algorithm.
36904 :
36905 : NOTE:
36906 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
36907 : 0.0 is returned in such cases.
36908 : *************************************************************************/
36909 0 : double spdmatrixrcond(/* Real */ ae_matrix* a,
36910 : ae_int_t n,
36911 : ae_bool isupper,
36912 : ae_state *_state)
36913 : {
36914 : ae_frame _frame_block;
36915 : ae_matrix _a;
36916 : ae_int_t i;
36917 : ae_int_t j;
36918 : ae_int_t j1;
36919 : ae_int_t j2;
36920 : double v;
36921 : double nrm;
36922 : ae_vector t;
36923 : double result;
36924 :
36925 0 : ae_frame_make(_state, &_frame_block);
36926 0 : memset(&_a, 0, sizeof(_a));
36927 0 : memset(&t, 0, sizeof(t));
36928 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
36929 0 : a = &_a;
36930 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
36931 :
36932 0 : ae_vector_set_length(&t, n, _state);
36933 0 : for(i=0; i<=n-1; i++)
36934 : {
36935 0 : t.ptr.p_double[i] = (double)(0);
36936 : }
36937 0 : for(i=0; i<=n-1; i++)
36938 : {
36939 0 : if( isupper )
36940 : {
36941 0 : j1 = i;
36942 0 : j2 = n-1;
36943 : }
36944 : else
36945 : {
36946 0 : j1 = 0;
36947 0 : j2 = i;
36948 : }
36949 0 : for(j=j1; j<=j2; j++)
36950 : {
36951 0 : if( i==j )
36952 : {
36953 0 : t.ptr.p_double[i] = t.ptr.p_double[i]+ae_fabs(a->ptr.pp_double[i][i], _state);
36954 : }
36955 : else
36956 : {
36957 0 : t.ptr.p_double[i] = t.ptr.p_double[i]+ae_fabs(a->ptr.pp_double[i][j], _state);
36958 0 : t.ptr.p_double[j] = t.ptr.p_double[j]+ae_fabs(a->ptr.pp_double[i][j], _state);
36959 : }
36960 : }
36961 : }
36962 0 : nrm = (double)(0);
36963 0 : for(i=0; i<=n-1; i++)
36964 : {
36965 0 : nrm = ae_maxreal(nrm, t.ptr.p_double[i], _state);
36966 : }
36967 0 : if( spdmatrixcholesky(a, n, isupper, _state) )
36968 : {
36969 0 : rcond_spdmatrixrcondcholeskyinternal(a, n, isupper, ae_true, nrm, &v, _state);
36970 0 : result = v;
36971 : }
36972 : else
36973 : {
36974 0 : result = (double)(-1);
36975 : }
36976 0 : ae_frame_leave(_state);
36977 0 : return result;
36978 : }
36979 :
36980 :
36981 : /*************************************************************************
36982 : Triangular matrix: estimate of a condition number (1-norm)
36983 :
36984 : The algorithm calculates a lower bound of the condition number. In this case,
36985 : the algorithm does not return a lower bound of the condition number, but an
36986 : inverse number (to avoid an overflow in case of a singular matrix).
36987 :
36988 : Input parameters:
36989 : A - matrix. Array[0..N-1, 0..N-1].
36990 : N - size of A.
36991 : IsUpper - True, if the matrix is upper triangular.
36992 : IsUnit - True, if the matrix has a unit diagonal.
36993 :
36994 : Result: 1/LowerBound(cond(A))
36995 :
36996 : NOTE:
36997 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
36998 : 0.0 is returned in such cases.
36999 : *************************************************************************/
37000 0 : double rmatrixtrrcond1(/* Real */ ae_matrix* a,
37001 : ae_int_t n,
37002 : ae_bool isupper,
37003 : ae_bool isunit,
37004 : ae_state *_state)
37005 : {
37006 : ae_frame _frame_block;
37007 : ae_int_t i;
37008 : ae_int_t j;
37009 : double v;
37010 : double nrm;
37011 : ae_vector pivots;
37012 : ae_vector t;
37013 : ae_int_t j1;
37014 : ae_int_t j2;
37015 : double result;
37016 :
37017 0 : ae_frame_make(_state, &_frame_block);
37018 0 : memset(&pivots, 0, sizeof(pivots));
37019 0 : memset(&t, 0, sizeof(t));
37020 0 : ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
37021 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
37022 :
37023 0 : ae_assert(n>=1, "RMatrixTRRCond1: N<1!", _state);
37024 0 : ae_vector_set_length(&t, n, _state);
37025 0 : for(i=0; i<=n-1; i++)
37026 : {
37027 0 : t.ptr.p_double[i] = (double)(0);
37028 : }
37029 0 : for(i=0; i<=n-1; i++)
37030 : {
37031 0 : if( isupper )
37032 : {
37033 0 : j1 = i+1;
37034 0 : j2 = n-1;
37035 : }
37036 : else
37037 : {
37038 0 : j1 = 0;
37039 0 : j2 = i-1;
37040 : }
37041 0 : for(j=j1; j<=j2; j++)
37042 : {
37043 0 : t.ptr.p_double[j] = t.ptr.p_double[j]+ae_fabs(a->ptr.pp_double[i][j], _state);
37044 : }
37045 0 : if( isunit )
37046 : {
37047 0 : t.ptr.p_double[i] = t.ptr.p_double[i]+1;
37048 : }
37049 : else
37050 : {
37051 0 : t.ptr.p_double[i] = t.ptr.p_double[i]+ae_fabs(a->ptr.pp_double[i][i], _state);
37052 : }
37053 : }
37054 0 : nrm = (double)(0);
37055 0 : for(i=0; i<=n-1; i++)
37056 : {
37057 0 : nrm = ae_maxreal(nrm, t.ptr.p_double[i], _state);
37058 : }
37059 0 : rcond_rmatrixrcondtrinternal(a, n, isupper, isunit, ae_true, nrm, &v, _state);
37060 0 : result = v;
37061 0 : ae_frame_leave(_state);
37062 0 : return result;
37063 : }
37064 :
37065 :
37066 : /*************************************************************************
37067 : Triangular matrix: estimate of a matrix condition number (infinity-norm).
37068 :
37069 : The algorithm calculates a lower bound of the condition number. In this case,
37070 : the algorithm does not return a lower bound of the condition number, but an
37071 : inverse number (to avoid an overflow in case of a singular matrix).
37072 :
37073 : Input parameters:
37074 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
37075 : N - size of matrix A.
37076 : IsUpper - True, if the matrix is upper triangular.
37077 : IsUnit - True, if the matrix has a unit diagonal.
37078 :
37079 : Result: 1/LowerBound(cond(A))
37080 :
37081 : NOTE:
37082 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
37083 : 0.0 is returned in such cases.
37084 : *************************************************************************/
37085 0 : double rmatrixtrrcondinf(/* Real */ ae_matrix* a,
37086 : ae_int_t n,
37087 : ae_bool isupper,
37088 : ae_bool isunit,
37089 : ae_state *_state)
37090 : {
37091 : ae_frame _frame_block;
37092 : ae_int_t i;
37093 : ae_int_t j;
37094 : double v;
37095 : double nrm;
37096 : ae_vector pivots;
37097 : ae_int_t j1;
37098 : ae_int_t j2;
37099 : double result;
37100 :
37101 0 : ae_frame_make(_state, &_frame_block);
37102 0 : memset(&pivots, 0, sizeof(pivots));
37103 0 : ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
37104 :
37105 0 : ae_assert(n>=1, "RMatrixTRRCondInf: N<1!", _state);
37106 0 : nrm = (double)(0);
37107 0 : for(i=0; i<=n-1; i++)
37108 : {
37109 0 : if( isupper )
37110 : {
37111 0 : j1 = i+1;
37112 0 : j2 = n-1;
37113 : }
37114 : else
37115 : {
37116 0 : j1 = 0;
37117 0 : j2 = i-1;
37118 : }
37119 0 : v = (double)(0);
37120 0 : for(j=j1; j<=j2; j++)
37121 : {
37122 0 : v = v+ae_fabs(a->ptr.pp_double[i][j], _state);
37123 : }
37124 0 : if( isunit )
37125 : {
37126 0 : v = v+1;
37127 : }
37128 : else
37129 : {
37130 0 : v = v+ae_fabs(a->ptr.pp_double[i][i], _state);
37131 : }
37132 0 : nrm = ae_maxreal(nrm, v, _state);
37133 : }
37134 0 : rcond_rmatrixrcondtrinternal(a, n, isupper, isunit, ae_false, nrm, &v, _state);
37135 0 : result = v;
37136 0 : ae_frame_leave(_state);
37137 0 : return result;
37138 : }
37139 :
37140 :
37141 : /*************************************************************************
37142 : Condition number estimate of a Hermitian positive definite matrix.
37143 :
37144 : The algorithm calculates a lower bound of the condition number. In this case,
37145 : the algorithm does not return a lower bound of the condition number, but an
37146 : inverse number (to avoid an overflow in case of a singular matrix).
37147 :
37148 : It should be noted that 1-norm and inf-norm of condition numbers of symmetric
37149 : matrices are equal, so the algorithm doesn't take into account the
37150 : differences between these types of norms.
37151 :
37152 : Input parameters:
37153 : A - Hermitian positive definite matrix which is given by its
37154 : upper or lower triangle depending on the value of
37155 : IsUpper. Array with elements [0..N-1, 0..N-1].
37156 : N - size of matrix A.
37157 : IsUpper - storage format.
37158 :
37159 : Result:
37160 : 1/LowerBound(cond(A)), if matrix A is positive definite,
37161 : -1, if matrix A is not positive definite, and its condition number
37162 : could not be found by this algorithm.
37163 :
37164 : NOTE:
37165 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
37166 : 0.0 is returned in such cases.
37167 : *************************************************************************/
37168 0 : double hpdmatrixrcond(/* Complex */ ae_matrix* a,
37169 : ae_int_t n,
37170 : ae_bool isupper,
37171 : ae_state *_state)
37172 : {
37173 : ae_frame _frame_block;
37174 : ae_matrix _a;
37175 : ae_int_t i;
37176 : ae_int_t j;
37177 : ae_int_t j1;
37178 : ae_int_t j2;
37179 : double v;
37180 : double nrm;
37181 : ae_vector t;
37182 : double result;
37183 :
37184 0 : ae_frame_make(_state, &_frame_block);
37185 0 : memset(&_a, 0, sizeof(_a));
37186 0 : memset(&t, 0, sizeof(t));
37187 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
37188 0 : a = &_a;
37189 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
37190 :
37191 0 : ae_vector_set_length(&t, n, _state);
37192 0 : for(i=0; i<=n-1; i++)
37193 : {
37194 0 : t.ptr.p_double[i] = (double)(0);
37195 : }
37196 0 : for(i=0; i<=n-1; i++)
37197 : {
37198 0 : if( isupper )
37199 : {
37200 0 : j1 = i;
37201 0 : j2 = n-1;
37202 : }
37203 : else
37204 : {
37205 0 : j1 = 0;
37206 0 : j2 = i;
37207 : }
37208 0 : for(j=j1; j<=j2; j++)
37209 : {
37210 0 : if( i==j )
37211 : {
37212 0 : t.ptr.p_double[i] = t.ptr.p_double[i]+ae_c_abs(a->ptr.pp_complex[i][i], _state);
37213 : }
37214 : else
37215 : {
37216 0 : t.ptr.p_double[i] = t.ptr.p_double[i]+ae_c_abs(a->ptr.pp_complex[i][j], _state);
37217 0 : t.ptr.p_double[j] = t.ptr.p_double[j]+ae_c_abs(a->ptr.pp_complex[i][j], _state);
37218 : }
37219 : }
37220 : }
37221 0 : nrm = (double)(0);
37222 0 : for(i=0; i<=n-1; i++)
37223 : {
37224 0 : nrm = ae_maxreal(nrm, t.ptr.p_double[i], _state);
37225 : }
37226 0 : if( hpdmatrixcholesky(a, n, isupper, _state) )
37227 : {
37228 0 : rcond_hpdmatrixrcondcholeskyinternal(a, n, isupper, ae_true, nrm, &v, _state);
37229 0 : result = v;
37230 : }
37231 : else
37232 : {
37233 0 : result = (double)(-1);
37234 : }
37235 0 : ae_frame_leave(_state);
37236 0 : return result;
37237 : }
37238 :
37239 :
37240 : /*************************************************************************
37241 : Estimate of a matrix condition number (1-norm)
37242 :
37243 : The algorithm calculates a lower bound of the condition number. In this case,
37244 : the algorithm does not return a lower bound of the condition number, but an
37245 : inverse number (to avoid an overflow in case of a singular matrix).
37246 :
37247 : Input parameters:
37248 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
37249 : N - size of matrix A.
37250 :
37251 : Result: 1/LowerBound(cond(A))
37252 :
37253 : NOTE:
37254 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
37255 : 0.0 is returned in such cases.
37256 : *************************************************************************/
37257 0 : double cmatrixrcond1(/* Complex */ ae_matrix* a,
37258 : ae_int_t n,
37259 : ae_state *_state)
37260 : {
37261 : ae_frame _frame_block;
37262 : ae_matrix _a;
37263 : ae_int_t i;
37264 : ae_int_t j;
37265 : double v;
37266 : double nrm;
37267 : ae_vector pivots;
37268 : ae_vector t;
37269 : double result;
37270 :
37271 0 : ae_frame_make(_state, &_frame_block);
37272 0 : memset(&_a, 0, sizeof(_a));
37273 0 : memset(&pivots, 0, sizeof(pivots));
37274 0 : memset(&t, 0, sizeof(t));
37275 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
37276 0 : a = &_a;
37277 0 : ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
37278 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
37279 :
37280 0 : ae_assert(n>=1, "CMatrixRCond1: N<1!", _state);
37281 0 : ae_vector_set_length(&t, n, _state);
37282 0 : for(i=0; i<=n-1; i++)
37283 : {
37284 0 : t.ptr.p_double[i] = (double)(0);
37285 : }
37286 0 : for(i=0; i<=n-1; i++)
37287 : {
37288 0 : for(j=0; j<=n-1; j++)
37289 : {
37290 0 : t.ptr.p_double[j] = t.ptr.p_double[j]+ae_c_abs(a->ptr.pp_complex[i][j], _state);
37291 : }
37292 : }
37293 0 : nrm = (double)(0);
37294 0 : for(i=0; i<=n-1; i++)
37295 : {
37296 0 : nrm = ae_maxreal(nrm, t.ptr.p_double[i], _state);
37297 : }
37298 0 : cmatrixlu(a, n, n, &pivots, _state);
37299 0 : rcond_cmatrixrcondluinternal(a, n, ae_true, ae_true, nrm, &v, _state);
37300 0 : result = v;
37301 0 : ae_frame_leave(_state);
37302 0 : return result;
37303 : }
37304 :
37305 :
37306 : /*************************************************************************
37307 : Estimate of a matrix condition number (infinity-norm).
37308 :
37309 : The algorithm calculates a lower bound of the condition number. In this case,
37310 : the algorithm does not return a lower bound of the condition number, but an
37311 : inverse number (to avoid an overflow in case of a singular matrix).
37312 :
37313 : Input parameters:
37314 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
37315 : N - size of matrix A.
37316 :
37317 : Result: 1/LowerBound(cond(A))
37318 :
37319 : NOTE:
37320 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
37321 : 0.0 is returned in such cases.
37322 : *************************************************************************/
37323 0 : double cmatrixrcondinf(/* Complex */ ae_matrix* a,
37324 : ae_int_t n,
37325 : ae_state *_state)
37326 : {
37327 : ae_frame _frame_block;
37328 : ae_matrix _a;
37329 : ae_int_t i;
37330 : ae_int_t j;
37331 : double v;
37332 : double nrm;
37333 : ae_vector pivots;
37334 : double result;
37335 :
37336 0 : ae_frame_make(_state, &_frame_block);
37337 0 : memset(&_a, 0, sizeof(_a));
37338 0 : memset(&pivots, 0, sizeof(pivots));
37339 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
37340 0 : a = &_a;
37341 0 : ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
37342 :
37343 0 : ae_assert(n>=1, "CMatrixRCondInf: N<1!", _state);
37344 0 : nrm = (double)(0);
37345 0 : for(i=0; i<=n-1; i++)
37346 : {
37347 0 : v = (double)(0);
37348 0 : for(j=0; j<=n-1; j++)
37349 : {
37350 0 : v = v+ae_c_abs(a->ptr.pp_complex[i][j], _state);
37351 : }
37352 0 : nrm = ae_maxreal(nrm, v, _state);
37353 : }
37354 0 : cmatrixlu(a, n, n, &pivots, _state);
37355 0 : rcond_cmatrixrcondluinternal(a, n, ae_false, ae_true, nrm, &v, _state);
37356 0 : result = v;
37357 0 : ae_frame_leave(_state);
37358 0 : return result;
37359 : }
37360 :
37361 :
37362 : /*************************************************************************
37363 : Estimate of the condition number of a matrix given by its LU decomposition (1-norm)
37364 :
37365 : The algorithm calculates a lower bound of the condition number. In this case,
37366 : the algorithm does not return a lower bound of the condition number, but an
37367 : inverse number (to avoid an overflow in case of a singular matrix).
37368 :
37369 : Input parameters:
37370 : LUA - LU decomposition of a matrix in compact form. Output of
37371 : the RMatrixLU subroutine.
37372 : N - size of matrix A.
37373 :
37374 : Result: 1/LowerBound(cond(A))
37375 :
37376 : NOTE:
37377 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
37378 : 0.0 is returned in such cases.
37379 : *************************************************************************/
37380 0 : double rmatrixlurcond1(/* Real */ ae_matrix* lua,
37381 : ae_int_t n,
37382 : ae_state *_state)
37383 : {
37384 : double v;
37385 : double result;
37386 :
37387 :
37388 0 : rcond_rmatrixrcondluinternal(lua, n, ae_true, ae_false, (double)(0), &v, _state);
37389 0 : result = v;
37390 0 : return result;
37391 : }
37392 :
37393 :
37394 : /*************************************************************************
37395 : Estimate of the condition number of a matrix given by its LU decomposition
37396 : (infinity norm).
37397 :
37398 : The algorithm calculates a lower bound of the condition number. In this case,
37399 : the algorithm does not return a lower bound of the condition number, but an
37400 : inverse number (to avoid an overflow in case of a singular matrix).
37401 :
37402 : Input parameters:
37403 : LUA - LU decomposition of a matrix in compact form. Output of
37404 : the RMatrixLU subroutine.
37405 : N - size of matrix A.
37406 :
37407 : Result: 1/LowerBound(cond(A))
37408 :
37409 : NOTE:
37410 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
37411 : 0.0 is returned in such cases.
37412 : *************************************************************************/
37413 0 : double rmatrixlurcondinf(/* Real */ ae_matrix* lua,
37414 : ae_int_t n,
37415 : ae_state *_state)
37416 : {
37417 : double v;
37418 : double result;
37419 :
37420 :
37421 0 : rcond_rmatrixrcondluinternal(lua, n, ae_false, ae_false, (double)(0), &v, _state);
37422 0 : result = v;
37423 0 : return result;
37424 : }
37425 :
37426 :
37427 : /*************************************************************************
37428 : Condition number estimate of a symmetric positive definite matrix given by
37429 : Cholesky decomposition.
37430 :
37431 : The algorithm calculates a lower bound of the condition number. In this
37432 : case, the algorithm does not return a lower bound of the condition number,
37433 : but an inverse number (to avoid an overflow in case of a singular matrix).
37434 :
37435 : It should be noted that 1-norm and inf-norm condition numbers of symmetric
37436 : matrices are equal, so the algorithm doesn't take into account the
37437 : differences between these types of norms.
37438 :
37439 : Input parameters:
37440 : CD - Cholesky decomposition of matrix A,
37441 : output of SMatrixCholesky subroutine.
37442 : N - size of matrix A.
37443 :
37444 : Result: 1/LowerBound(cond(A))
37445 :
37446 : NOTE:
37447 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
37448 : 0.0 is returned in such cases.
37449 : *************************************************************************/
37450 0 : double spdmatrixcholeskyrcond(/* Real */ ae_matrix* a,
37451 : ae_int_t n,
37452 : ae_bool isupper,
37453 : ae_state *_state)
37454 : {
37455 : double v;
37456 : double result;
37457 :
37458 :
37459 0 : rcond_spdmatrixrcondcholeskyinternal(a, n, isupper, ae_false, (double)(0), &v, _state);
37460 0 : result = v;
37461 0 : return result;
37462 : }
37463 :
37464 :
37465 : /*************************************************************************
37466 : Condition number estimate of a Hermitian positive definite matrix given by
37467 : Cholesky decomposition.
37468 :
37469 : The algorithm calculates a lower bound of the condition number. In this
37470 : case, the algorithm does not return a lower bound of the condition number,
37471 : but an inverse number (to avoid an overflow in case of a singular matrix).
37472 :
37473 : It should be noted that 1-norm and inf-norm condition numbers of symmetric
37474 : matrices are equal, so the algorithm doesn't take into account the
37475 : differences between these types of norms.
37476 :
37477 : Input parameters:
37478 : CD - Cholesky decomposition of matrix A,
37479 : output of SMatrixCholesky subroutine.
37480 : N - size of matrix A.
37481 :
37482 : Result: 1/LowerBound(cond(A))
37483 :
37484 : NOTE:
37485 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
37486 : 0.0 is returned in such cases.
37487 : *************************************************************************/
37488 0 : double hpdmatrixcholeskyrcond(/* Complex */ ae_matrix* a,
37489 : ae_int_t n,
37490 : ae_bool isupper,
37491 : ae_state *_state)
37492 : {
37493 : double v;
37494 : double result;
37495 :
37496 :
37497 0 : rcond_hpdmatrixrcondcholeskyinternal(a, n, isupper, ae_false, (double)(0), &v, _state);
37498 0 : result = v;
37499 0 : return result;
37500 : }
37501 :
37502 :
37503 : /*************************************************************************
37504 : Estimate of the condition number of a matrix given by its LU decomposition (1-norm)
37505 :
37506 : The algorithm calculates a lower bound of the condition number. In this case,
37507 : the algorithm does not return a lower bound of the condition number, but an
37508 : inverse number (to avoid an overflow in case of a singular matrix).
37509 :
37510 : Input parameters:
37511 : LUA - LU decomposition of a matrix in compact form. Output of
37512 : the CMatrixLU subroutine.
37513 : N - size of matrix A.
37514 :
37515 : Result: 1/LowerBound(cond(A))
37516 :
37517 : NOTE:
37518 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
37519 : 0.0 is returned in such cases.
37520 : *************************************************************************/
37521 0 : double cmatrixlurcond1(/* Complex */ ae_matrix* lua,
37522 : ae_int_t n,
37523 : ae_state *_state)
37524 : {
37525 : double v;
37526 : double result;
37527 :
37528 :
37529 0 : ae_assert(n>=1, "CMatrixLURCond1: N<1!", _state);
37530 0 : rcond_cmatrixrcondluinternal(lua, n, ae_true, ae_false, 0.0, &v, _state);
37531 0 : result = v;
37532 0 : return result;
37533 : }
37534 :
37535 :
37536 : /*************************************************************************
37537 : Estimate of the condition number of a matrix given by its LU decomposition
37538 : (infinity norm).
37539 :
37540 : The algorithm calculates a lower bound of the condition number. In this case,
37541 : the algorithm does not return a lower bound of the condition number, but an
37542 : inverse number (to avoid an overflow in case of a singular matrix).
37543 :
37544 : Input parameters:
37545 : LUA - LU decomposition of a matrix in compact form. Output of
37546 : the CMatrixLU subroutine.
37547 : N - size of matrix A.
37548 :
37549 : Result: 1/LowerBound(cond(A))
37550 :
37551 : NOTE:
37552 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
37553 : 0.0 is returned in such cases.
37554 : *************************************************************************/
37555 0 : double cmatrixlurcondinf(/* Complex */ ae_matrix* lua,
37556 : ae_int_t n,
37557 : ae_state *_state)
37558 : {
37559 : double v;
37560 : double result;
37561 :
37562 :
37563 0 : ae_assert(n>=1, "CMatrixLURCondInf: N<1!", _state);
37564 0 : rcond_cmatrixrcondluinternal(lua, n, ae_false, ae_false, 0.0, &v, _state);
37565 0 : result = v;
37566 0 : return result;
37567 : }
37568 :
37569 :
37570 : /*************************************************************************
37571 : Triangular matrix: estimate of a condition number (1-norm)
37572 :
37573 : The algorithm calculates a lower bound of the condition number. In this case,
37574 : the algorithm does not return a lower bound of the condition number, but an
37575 : inverse number (to avoid an overflow in case of a singular matrix).
37576 :
37577 : Input parameters:
37578 : A - matrix. Array[0..N-1, 0..N-1].
37579 : N - size of A.
37580 : IsUpper - True, if the matrix is upper triangular.
37581 : IsUnit - True, if the matrix has a unit diagonal.
37582 :
37583 : Result: 1/LowerBound(cond(A))
37584 :
37585 : NOTE:
37586 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
37587 : 0.0 is returned in such cases.
37588 : *************************************************************************/
37589 0 : double cmatrixtrrcond1(/* Complex */ ae_matrix* a,
37590 : ae_int_t n,
37591 : ae_bool isupper,
37592 : ae_bool isunit,
37593 : ae_state *_state)
37594 : {
37595 : ae_frame _frame_block;
37596 : ae_int_t i;
37597 : ae_int_t j;
37598 : double v;
37599 : double nrm;
37600 : ae_vector pivots;
37601 : ae_vector t;
37602 : ae_int_t j1;
37603 : ae_int_t j2;
37604 : double result;
37605 :
37606 0 : ae_frame_make(_state, &_frame_block);
37607 0 : memset(&pivots, 0, sizeof(pivots));
37608 0 : memset(&t, 0, sizeof(t));
37609 0 : ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
37610 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
37611 :
37612 0 : ae_assert(n>=1, "RMatrixTRRCond1: N<1!", _state);
37613 0 : ae_vector_set_length(&t, n, _state);
37614 0 : for(i=0; i<=n-1; i++)
37615 : {
37616 0 : t.ptr.p_double[i] = (double)(0);
37617 : }
37618 0 : for(i=0; i<=n-1; i++)
37619 : {
37620 0 : if( isupper )
37621 : {
37622 0 : j1 = i+1;
37623 0 : j2 = n-1;
37624 : }
37625 : else
37626 : {
37627 0 : j1 = 0;
37628 0 : j2 = i-1;
37629 : }
37630 0 : for(j=j1; j<=j2; j++)
37631 : {
37632 0 : t.ptr.p_double[j] = t.ptr.p_double[j]+ae_c_abs(a->ptr.pp_complex[i][j], _state);
37633 : }
37634 0 : if( isunit )
37635 : {
37636 0 : t.ptr.p_double[i] = t.ptr.p_double[i]+1;
37637 : }
37638 : else
37639 : {
37640 0 : t.ptr.p_double[i] = t.ptr.p_double[i]+ae_c_abs(a->ptr.pp_complex[i][i], _state);
37641 : }
37642 : }
37643 0 : nrm = (double)(0);
37644 0 : for(i=0; i<=n-1; i++)
37645 : {
37646 0 : nrm = ae_maxreal(nrm, t.ptr.p_double[i], _state);
37647 : }
37648 0 : rcond_cmatrixrcondtrinternal(a, n, isupper, isunit, ae_true, nrm, &v, _state);
37649 0 : result = v;
37650 0 : ae_frame_leave(_state);
37651 0 : return result;
37652 : }
37653 :
37654 :
37655 : /*************************************************************************
37656 : Triangular matrix: estimate of a matrix condition number (infinity-norm).
37657 :
37658 : The algorithm calculates a lower bound of the condition number. In this case,
37659 : the algorithm does not return a lower bound of the condition number, but an
37660 : inverse number (to avoid an overflow in case of a singular matrix).
37661 :
37662 : Input parameters:
37663 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
37664 : N - size of matrix A.
37665 : IsUpper - True, if the matrix is upper triangular.
37666 : IsUnit - True, if the matrix has a unit diagonal.
37667 :
37668 : Result: 1/LowerBound(cond(A))
37669 :
37670 : NOTE:
37671 : if k(A) is very large, then matrix is assumed degenerate, k(A)=INF,
37672 : 0.0 is returned in such cases.
37673 : *************************************************************************/
37674 0 : double cmatrixtrrcondinf(/* Complex */ ae_matrix* a,
37675 : ae_int_t n,
37676 : ae_bool isupper,
37677 : ae_bool isunit,
37678 : ae_state *_state)
37679 : {
37680 : ae_frame _frame_block;
37681 : ae_int_t i;
37682 : ae_int_t j;
37683 : double v;
37684 : double nrm;
37685 : ae_vector pivots;
37686 : ae_int_t j1;
37687 : ae_int_t j2;
37688 : double result;
37689 :
37690 0 : ae_frame_make(_state, &_frame_block);
37691 0 : memset(&pivots, 0, sizeof(pivots));
37692 0 : ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
37693 :
37694 0 : ae_assert(n>=1, "RMatrixTRRCondInf: N<1!", _state);
37695 0 : nrm = (double)(0);
37696 0 : for(i=0; i<=n-1; i++)
37697 : {
37698 0 : if( isupper )
37699 : {
37700 0 : j1 = i+1;
37701 0 : j2 = n-1;
37702 : }
37703 : else
37704 : {
37705 0 : j1 = 0;
37706 0 : j2 = i-1;
37707 : }
37708 0 : v = (double)(0);
37709 0 : for(j=j1; j<=j2; j++)
37710 : {
37711 0 : v = v+ae_c_abs(a->ptr.pp_complex[i][j], _state);
37712 : }
37713 0 : if( isunit )
37714 : {
37715 0 : v = v+1;
37716 : }
37717 : else
37718 : {
37719 0 : v = v+ae_c_abs(a->ptr.pp_complex[i][i], _state);
37720 : }
37721 0 : nrm = ae_maxreal(nrm, v, _state);
37722 : }
37723 0 : rcond_cmatrixrcondtrinternal(a, n, isupper, isunit, ae_false, nrm, &v, _state);
37724 0 : result = v;
37725 0 : ae_frame_leave(_state);
37726 0 : return result;
37727 : }
37728 :
37729 :
37730 : /*************************************************************************
37731 : Threshold for rcond: matrices with condition number beyond this threshold
37732 : are considered singular.
37733 :
37734 : Threshold must be far enough from underflow, at least Sqr(Threshold) must
37735 : be greater than underflow.
37736 : *************************************************************************/
37737 0 : double rcondthreshold(ae_state *_state)
37738 : {
37739 : double result;
37740 :
37741 :
37742 0 : result = ae_sqrt(ae_sqrt(ae_minrealnumber, _state), _state);
37743 0 : return result;
37744 : }
37745 :
37746 :
37747 : /*************************************************************************
37748 : Internal subroutine for condition number estimation
37749 :
37750 : -- LAPACK routine (version 3.0) --
37751 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
37752 : Courant Institute, Argonne National Lab, and Rice University
37753 : February 29, 1992
37754 : *************************************************************************/
37755 0 : static void rcond_rmatrixrcondtrinternal(/* Real */ ae_matrix* a,
37756 : ae_int_t n,
37757 : ae_bool isupper,
37758 : ae_bool isunit,
37759 : ae_bool onenorm,
37760 : double anorm,
37761 : double* rc,
37762 : ae_state *_state)
37763 : {
37764 : ae_frame _frame_block;
37765 : ae_vector ex;
37766 : ae_vector ev;
37767 : ae_vector iwork;
37768 : ae_vector tmp;
37769 : ae_int_t i;
37770 : ae_int_t j;
37771 : ae_int_t kase;
37772 : ae_int_t kase1;
37773 : ae_int_t j1;
37774 : ae_int_t j2;
37775 : double ainvnm;
37776 : double maxgrowth;
37777 : double s;
37778 :
37779 0 : ae_frame_make(_state, &_frame_block);
37780 0 : memset(&ex, 0, sizeof(ex));
37781 0 : memset(&ev, 0, sizeof(ev));
37782 0 : memset(&iwork, 0, sizeof(iwork));
37783 0 : memset(&tmp, 0, sizeof(tmp));
37784 0 : *rc = 0;
37785 0 : ae_vector_init(&ex, 0, DT_REAL, _state, ae_true);
37786 0 : ae_vector_init(&ev, 0, DT_REAL, _state, ae_true);
37787 0 : ae_vector_init(&iwork, 0, DT_INT, _state, ae_true);
37788 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
37789 :
37790 :
37791 : /*
37792 : * RC=0 if something happens
37793 : */
37794 0 : *rc = (double)(0);
37795 :
37796 : /*
37797 : * init
37798 : */
37799 0 : if( onenorm )
37800 : {
37801 0 : kase1 = 1;
37802 : }
37803 : else
37804 : {
37805 0 : kase1 = 2;
37806 : }
37807 0 : ae_vector_set_length(&iwork, n+1, _state);
37808 0 : ae_vector_set_length(&tmp, n, _state);
37809 :
37810 : /*
37811 : * prepare parameters for triangular solver
37812 : */
37813 0 : maxgrowth = 1/rcondthreshold(_state);
37814 0 : s = (double)(0);
37815 0 : for(i=0; i<=n-1; i++)
37816 : {
37817 0 : if( isupper )
37818 : {
37819 0 : j1 = i+1;
37820 0 : j2 = n-1;
37821 : }
37822 : else
37823 : {
37824 0 : j1 = 0;
37825 0 : j2 = i-1;
37826 : }
37827 0 : for(j=j1; j<=j2; j++)
37828 : {
37829 0 : s = ae_maxreal(s, ae_fabs(a->ptr.pp_double[i][j], _state), _state);
37830 : }
37831 0 : if( isunit )
37832 : {
37833 0 : s = ae_maxreal(s, (double)(1), _state);
37834 : }
37835 : else
37836 : {
37837 0 : s = ae_maxreal(s, ae_fabs(a->ptr.pp_double[i][i], _state), _state);
37838 : }
37839 : }
37840 0 : if( ae_fp_eq(s,(double)(0)) )
37841 : {
37842 0 : s = (double)(1);
37843 : }
37844 0 : s = 1/s;
37845 :
37846 : /*
37847 : * Scale according to S
37848 : */
37849 0 : anorm = anorm*s;
37850 :
37851 : /*
37852 : * Quick return if possible
37853 : * We assume that ANORM<>0 after this block
37854 : */
37855 0 : if( ae_fp_eq(anorm,(double)(0)) )
37856 : {
37857 0 : ae_frame_leave(_state);
37858 0 : return;
37859 : }
37860 0 : if( n==1 )
37861 : {
37862 0 : *rc = (double)(1);
37863 0 : ae_frame_leave(_state);
37864 0 : return;
37865 : }
37866 :
37867 : /*
37868 : * Estimate the norm of inv(A).
37869 : */
37870 0 : ainvnm = (double)(0);
37871 0 : kase = 0;
37872 : for(;;)
37873 : {
37874 0 : rcond_rmatrixestimatenorm(n, &ev, &ex, &iwork, &ainvnm, &kase, _state);
37875 0 : if( kase==0 )
37876 : {
37877 0 : break;
37878 : }
37879 :
37880 : /*
37881 : * from 1-based array to 0-based
37882 : */
37883 0 : for(i=0; i<=n-1; i++)
37884 : {
37885 0 : ex.ptr.p_double[i] = ex.ptr.p_double[i+1];
37886 : }
37887 :
37888 : /*
37889 : * multiply by inv(A) or inv(A')
37890 : */
37891 0 : if( kase==kase1 )
37892 : {
37893 :
37894 : /*
37895 : * multiply by inv(A)
37896 : */
37897 0 : if( !rmatrixscaledtrsafesolve(a, s, n, &ex, isupper, 0, isunit, maxgrowth, _state) )
37898 : {
37899 0 : ae_frame_leave(_state);
37900 0 : return;
37901 : }
37902 : }
37903 : else
37904 : {
37905 :
37906 : /*
37907 : * multiply by inv(A')
37908 : */
37909 0 : if( !rmatrixscaledtrsafesolve(a, s, n, &ex, isupper, 1, isunit, maxgrowth, _state) )
37910 : {
37911 0 : ae_frame_leave(_state);
37912 0 : return;
37913 : }
37914 : }
37915 :
37916 : /*
37917 : * from 0-based array to 1-based
37918 : */
37919 0 : for(i=n-1; i>=0; i--)
37920 : {
37921 0 : ex.ptr.p_double[i+1] = ex.ptr.p_double[i];
37922 : }
37923 : }
37924 :
37925 : /*
37926 : * Compute the estimate of the reciprocal condition number.
37927 : */
37928 0 : if( ae_fp_neq(ainvnm,(double)(0)) )
37929 : {
37930 0 : *rc = 1/ainvnm;
37931 0 : *rc = *rc/anorm;
37932 0 : if( ae_fp_less(*rc,rcondthreshold(_state)) )
37933 : {
37934 0 : *rc = (double)(0);
37935 : }
37936 : }
37937 0 : ae_frame_leave(_state);
37938 : }
37939 :
37940 :
37941 : /*************************************************************************
37942 : Condition number estimation
37943 :
37944 : -- LAPACK routine (version 3.0) --
37945 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
37946 : Courant Institute, Argonne National Lab, and Rice University
37947 : March 31, 1993
37948 : *************************************************************************/
37949 0 : static void rcond_cmatrixrcondtrinternal(/* Complex */ ae_matrix* a,
37950 : ae_int_t n,
37951 : ae_bool isupper,
37952 : ae_bool isunit,
37953 : ae_bool onenorm,
37954 : double anorm,
37955 : double* rc,
37956 : ae_state *_state)
37957 : {
37958 : ae_frame _frame_block;
37959 : ae_vector ex;
37960 : ae_vector cwork2;
37961 : ae_vector cwork3;
37962 : ae_vector cwork4;
37963 : ae_vector isave;
37964 : ae_vector rsave;
37965 : ae_int_t kase;
37966 : ae_int_t kase1;
37967 : double ainvnm;
37968 : ae_int_t i;
37969 : ae_int_t j;
37970 : ae_int_t j1;
37971 : ae_int_t j2;
37972 : double s;
37973 : double maxgrowth;
37974 :
37975 0 : ae_frame_make(_state, &_frame_block);
37976 0 : memset(&ex, 0, sizeof(ex));
37977 0 : memset(&cwork2, 0, sizeof(cwork2));
37978 0 : memset(&cwork3, 0, sizeof(cwork3));
37979 0 : memset(&cwork4, 0, sizeof(cwork4));
37980 0 : memset(&isave, 0, sizeof(isave));
37981 0 : memset(&rsave, 0, sizeof(rsave));
37982 0 : *rc = 0;
37983 0 : ae_vector_init(&ex, 0, DT_COMPLEX, _state, ae_true);
37984 0 : ae_vector_init(&cwork2, 0, DT_COMPLEX, _state, ae_true);
37985 0 : ae_vector_init(&cwork3, 0, DT_COMPLEX, _state, ae_true);
37986 0 : ae_vector_init(&cwork4, 0, DT_COMPLEX, _state, ae_true);
37987 0 : ae_vector_init(&isave, 0, DT_INT, _state, ae_true);
37988 0 : ae_vector_init(&rsave, 0, DT_REAL, _state, ae_true);
37989 :
37990 :
37991 : /*
37992 : * RC=0 if something happens
37993 : */
37994 0 : *rc = (double)(0);
37995 :
37996 : /*
37997 : * init
37998 : */
37999 0 : if( n<=0 )
38000 : {
38001 0 : ae_frame_leave(_state);
38002 0 : return;
38003 : }
38004 0 : if( n==0 )
38005 : {
38006 0 : *rc = (double)(1);
38007 0 : ae_frame_leave(_state);
38008 0 : return;
38009 : }
38010 0 : ae_vector_set_length(&cwork2, n+1, _state);
38011 :
38012 : /*
38013 : * prepare parameters for triangular solver
38014 : */
38015 0 : maxgrowth = 1/rcondthreshold(_state);
38016 0 : s = (double)(0);
38017 0 : for(i=0; i<=n-1; i++)
38018 : {
38019 0 : if( isupper )
38020 : {
38021 0 : j1 = i+1;
38022 0 : j2 = n-1;
38023 : }
38024 : else
38025 : {
38026 0 : j1 = 0;
38027 0 : j2 = i-1;
38028 : }
38029 0 : for(j=j1; j<=j2; j++)
38030 : {
38031 0 : s = ae_maxreal(s, ae_c_abs(a->ptr.pp_complex[i][j], _state), _state);
38032 : }
38033 0 : if( isunit )
38034 : {
38035 0 : s = ae_maxreal(s, (double)(1), _state);
38036 : }
38037 : else
38038 : {
38039 0 : s = ae_maxreal(s, ae_c_abs(a->ptr.pp_complex[i][i], _state), _state);
38040 : }
38041 : }
38042 0 : if( ae_fp_eq(s,(double)(0)) )
38043 : {
38044 0 : s = (double)(1);
38045 : }
38046 0 : s = 1/s;
38047 :
38048 : /*
38049 : * Scale according to S
38050 : */
38051 0 : anorm = anorm*s;
38052 :
38053 : /*
38054 : * Quick return if possible
38055 : */
38056 0 : if( ae_fp_eq(anorm,(double)(0)) )
38057 : {
38058 0 : ae_frame_leave(_state);
38059 0 : return;
38060 : }
38061 :
38062 : /*
38063 : * Estimate the norm of inv(A).
38064 : */
38065 0 : ainvnm = (double)(0);
38066 0 : if( onenorm )
38067 : {
38068 0 : kase1 = 1;
38069 : }
38070 : else
38071 : {
38072 0 : kase1 = 2;
38073 : }
38074 0 : kase = 0;
38075 : for(;;)
38076 : {
38077 0 : rcond_cmatrixestimatenorm(n, &cwork4, &ex, &ainvnm, &kase, &isave, &rsave, _state);
38078 0 : if( kase==0 )
38079 : {
38080 0 : break;
38081 : }
38082 :
38083 : /*
38084 : * From 1-based to 0-based
38085 : */
38086 0 : for(i=0; i<=n-1; i++)
38087 : {
38088 0 : ex.ptr.p_complex[i] = ex.ptr.p_complex[i+1];
38089 : }
38090 :
38091 : /*
38092 : * multiply by inv(A) or inv(A')
38093 : */
38094 0 : if( kase==kase1 )
38095 : {
38096 :
38097 : /*
38098 : * multiply by inv(A)
38099 : */
38100 0 : if( !cmatrixscaledtrsafesolve(a, s, n, &ex, isupper, 0, isunit, maxgrowth, _state) )
38101 : {
38102 0 : ae_frame_leave(_state);
38103 0 : return;
38104 : }
38105 : }
38106 : else
38107 : {
38108 :
38109 : /*
38110 : * multiply by inv(A')
38111 : */
38112 0 : if( !cmatrixscaledtrsafesolve(a, s, n, &ex, isupper, 2, isunit, maxgrowth, _state) )
38113 : {
38114 0 : ae_frame_leave(_state);
38115 0 : return;
38116 : }
38117 : }
38118 :
38119 : /*
38120 : * from 0-based to 1-based
38121 : */
38122 0 : for(i=n-1; i>=0; i--)
38123 : {
38124 0 : ex.ptr.p_complex[i+1] = ex.ptr.p_complex[i];
38125 : }
38126 : }
38127 :
38128 : /*
38129 : * Compute the estimate of the reciprocal condition number.
38130 : */
38131 0 : if( ae_fp_neq(ainvnm,(double)(0)) )
38132 : {
38133 0 : *rc = 1/ainvnm;
38134 0 : *rc = *rc/anorm;
38135 0 : if( ae_fp_less(*rc,rcondthreshold(_state)) )
38136 : {
38137 0 : *rc = (double)(0);
38138 : }
38139 : }
38140 0 : ae_frame_leave(_state);
38141 : }
38142 :
38143 :
38144 : /*************************************************************************
38145 : Internal subroutine for condition number estimation
38146 :
38147 : -- LAPACK routine (version 3.0) --
38148 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
38149 : Courant Institute, Argonne National Lab, and Rice University
38150 : February 29, 1992
38151 : *************************************************************************/
38152 0 : static void rcond_spdmatrixrcondcholeskyinternal(/* Real */ ae_matrix* cha,
38153 : ae_int_t n,
38154 : ae_bool isupper,
38155 : ae_bool isnormprovided,
38156 : double anorm,
38157 : double* rc,
38158 : ae_state *_state)
38159 : {
38160 : ae_frame _frame_block;
38161 : ae_int_t i;
38162 : ae_int_t j;
38163 : ae_int_t kase;
38164 : double ainvnm;
38165 : ae_vector ex;
38166 : ae_vector ev;
38167 : ae_vector tmp;
38168 : ae_vector iwork;
38169 : double sa;
38170 : double v;
38171 : double maxgrowth;
38172 :
38173 0 : ae_frame_make(_state, &_frame_block);
38174 0 : memset(&ex, 0, sizeof(ex));
38175 0 : memset(&ev, 0, sizeof(ev));
38176 0 : memset(&tmp, 0, sizeof(tmp));
38177 0 : memset(&iwork, 0, sizeof(iwork));
38178 0 : *rc = 0;
38179 0 : ae_vector_init(&ex, 0, DT_REAL, _state, ae_true);
38180 0 : ae_vector_init(&ev, 0, DT_REAL, _state, ae_true);
38181 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
38182 0 : ae_vector_init(&iwork, 0, DT_INT, _state, ae_true);
38183 :
38184 0 : ae_assert(n>=1, "Assertion failed", _state);
38185 0 : ae_vector_set_length(&tmp, n, _state);
38186 :
38187 : /*
38188 : * RC=0 if something happens
38189 : */
38190 0 : *rc = (double)(0);
38191 :
38192 : /*
38193 : * prepare parameters for triangular solver
38194 : */
38195 0 : maxgrowth = 1/rcondthreshold(_state);
38196 0 : sa = (double)(0);
38197 0 : if( isupper )
38198 : {
38199 0 : for(i=0; i<=n-1; i++)
38200 : {
38201 0 : for(j=i; j<=n-1; j++)
38202 : {
38203 0 : sa = ae_maxreal(sa, ae_c_abs(ae_complex_from_d(cha->ptr.pp_double[i][j]), _state), _state);
38204 : }
38205 : }
38206 : }
38207 : else
38208 : {
38209 0 : for(i=0; i<=n-1; i++)
38210 : {
38211 0 : for(j=0; j<=i; j++)
38212 : {
38213 0 : sa = ae_maxreal(sa, ae_c_abs(ae_complex_from_d(cha->ptr.pp_double[i][j]), _state), _state);
38214 : }
38215 : }
38216 : }
38217 0 : if( ae_fp_eq(sa,(double)(0)) )
38218 : {
38219 0 : sa = (double)(1);
38220 : }
38221 0 : sa = 1/sa;
38222 :
38223 : /*
38224 : * Estimate the norm of A.
38225 : */
38226 0 : if( !isnormprovided )
38227 : {
38228 0 : kase = 0;
38229 0 : anorm = (double)(0);
38230 : for(;;)
38231 : {
38232 0 : rcond_rmatrixestimatenorm(n, &ev, &ex, &iwork, &anorm, &kase, _state);
38233 0 : if( kase==0 )
38234 : {
38235 0 : break;
38236 : }
38237 0 : if( isupper )
38238 : {
38239 :
38240 : /*
38241 : * Multiply by U
38242 : */
38243 0 : for(i=1; i<=n; i++)
38244 : {
38245 0 : v = ae_v_dotproduct(&cha->ptr.pp_double[i-1][i-1], 1, &ex.ptr.p_double[i], 1, ae_v_len(i-1,n-1));
38246 0 : ex.ptr.p_double[i] = v;
38247 : }
38248 0 : ae_v_muld(&ex.ptr.p_double[1], 1, ae_v_len(1,n), sa);
38249 :
38250 : /*
38251 : * Multiply by U'
38252 : */
38253 0 : for(i=0; i<=n-1; i++)
38254 : {
38255 0 : tmp.ptr.p_double[i] = (double)(0);
38256 : }
38257 0 : for(i=0; i<=n-1; i++)
38258 : {
38259 0 : v = ex.ptr.p_double[i+1];
38260 0 : ae_v_addd(&tmp.ptr.p_double[i], 1, &cha->ptr.pp_double[i][i], 1, ae_v_len(i,n-1), v);
38261 : }
38262 0 : ae_v_move(&ex.ptr.p_double[1], 1, &tmp.ptr.p_double[0], 1, ae_v_len(1,n));
38263 0 : ae_v_muld(&ex.ptr.p_double[1], 1, ae_v_len(1,n), sa);
38264 : }
38265 : else
38266 : {
38267 :
38268 : /*
38269 : * Multiply by L'
38270 : */
38271 0 : for(i=0; i<=n-1; i++)
38272 : {
38273 0 : tmp.ptr.p_double[i] = (double)(0);
38274 : }
38275 0 : for(i=0; i<=n-1; i++)
38276 : {
38277 0 : v = ex.ptr.p_double[i+1];
38278 0 : ae_v_addd(&tmp.ptr.p_double[0], 1, &cha->ptr.pp_double[i][0], 1, ae_v_len(0,i), v);
38279 : }
38280 0 : ae_v_move(&ex.ptr.p_double[1], 1, &tmp.ptr.p_double[0], 1, ae_v_len(1,n));
38281 0 : ae_v_muld(&ex.ptr.p_double[1], 1, ae_v_len(1,n), sa);
38282 :
38283 : /*
38284 : * Multiply by L
38285 : */
38286 0 : for(i=n; i>=1; i--)
38287 : {
38288 0 : v = ae_v_dotproduct(&cha->ptr.pp_double[i-1][0], 1, &ex.ptr.p_double[1], 1, ae_v_len(0,i-1));
38289 0 : ex.ptr.p_double[i] = v;
38290 : }
38291 0 : ae_v_muld(&ex.ptr.p_double[1], 1, ae_v_len(1,n), sa);
38292 : }
38293 : }
38294 : }
38295 :
38296 : /*
38297 : * Quick return if possible
38298 : */
38299 0 : if( ae_fp_eq(anorm,(double)(0)) )
38300 : {
38301 0 : ae_frame_leave(_state);
38302 0 : return;
38303 : }
38304 0 : if( n==1 )
38305 : {
38306 0 : *rc = (double)(1);
38307 0 : ae_frame_leave(_state);
38308 0 : return;
38309 : }
38310 :
38311 : /*
38312 : * Estimate the 1-norm of inv(A).
38313 : */
38314 0 : kase = 0;
38315 : for(;;)
38316 : {
38317 0 : rcond_rmatrixestimatenorm(n, &ev, &ex, &iwork, &ainvnm, &kase, _state);
38318 0 : if( kase==0 )
38319 : {
38320 0 : break;
38321 : }
38322 0 : for(i=0; i<=n-1; i++)
38323 : {
38324 0 : ex.ptr.p_double[i] = ex.ptr.p_double[i+1];
38325 : }
38326 0 : if( isupper )
38327 : {
38328 :
38329 : /*
38330 : * Multiply by inv(U').
38331 : */
38332 0 : if( !rmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 1, ae_false, maxgrowth, _state) )
38333 : {
38334 0 : ae_frame_leave(_state);
38335 0 : return;
38336 : }
38337 :
38338 : /*
38339 : * Multiply by inv(U).
38340 : */
38341 0 : if( !rmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 0, ae_false, maxgrowth, _state) )
38342 : {
38343 0 : ae_frame_leave(_state);
38344 0 : return;
38345 : }
38346 : }
38347 : else
38348 : {
38349 :
38350 : /*
38351 : * Multiply by inv(L).
38352 : */
38353 0 : if( !rmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 0, ae_false, maxgrowth, _state) )
38354 : {
38355 0 : ae_frame_leave(_state);
38356 0 : return;
38357 : }
38358 :
38359 : /*
38360 : * Multiply by inv(L').
38361 : */
38362 0 : if( !rmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 1, ae_false, maxgrowth, _state) )
38363 : {
38364 0 : ae_frame_leave(_state);
38365 0 : return;
38366 : }
38367 : }
38368 0 : for(i=n-1; i>=0; i--)
38369 : {
38370 0 : ex.ptr.p_double[i+1] = ex.ptr.p_double[i];
38371 : }
38372 : }
38373 :
38374 : /*
38375 : * Compute the estimate of the reciprocal condition number.
38376 : */
38377 0 : if( ae_fp_neq(ainvnm,(double)(0)) )
38378 : {
38379 0 : v = 1/ainvnm;
38380 0 : *rc = v/anorm;
38381 0 : if( ae_fp_less(*rc,rcondthreshold(_state)) )
38382 : {
38383 0 : *rc = (double)(0);
38384 : }
38385 : }
38386 0 : ae_frame_leave(_state);
38387 : }
38388 :
38389 :
38390 : /*************************************************************************
38391 : Internal subroutine for condition number estimation
38392 :
38393 : -- LAPACK routine (version 3.0) --
38394 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
38395 : Courant Institute, Argonne National Lab, and Rice University
38396 : February 29, 1992
38397 : *************************************************************************/
38398 0 : static void rcond_hpdmatrixrcondcholeskyinternal(/* Complex */ ae_matrix* cha,
38399 : ae_int_t n,
38400 : ae_bool isupper,
38401 : ae_bool isnormprovided,
38402 : double anorm,
38403 : double* rc,
38404 : ae_state *_state)
38405 : {
38406 : ae_frame _frame_block;
38407 : ae_vector isave;
38408 : ae_vector rsave;
38409 : ae_vector ex;
38410 : ae_vector ev;
38411 : ae_vector tmp;
38412 : ae_int_t kase;
38413 : double ainvnm;
38414 : ae_complex v;
38415 : ae_int_t i;
38416 : ae_int_t j;
38417 : double sa;
38418 : double maxgrowth;
38419 :
38420 0 : ae_frame_make(_state, &_frame_block);
38421 0 : memset(&isave, 0, sizeof(isave));
38422 0 : memset(&rsave, 0, sizeof(rsave));
38423 0 : memset(&ex, 0, sizeof(ex));
38424 0 : memset(&ev, 0, sizeof(ev));
38425 0 : memset(&tmp, 0, sizeof(tmp));
38426 0 : *rc = 0;
38427 0 : ae_vector_init(&isave, 0, DT_INT, _state, ae_true);
38428 0 : ae_vector_init(&rsave, 0, DT_REAL, _state, ae_true);
38429 0 : ae_vector_init(&ex, 0, DT_COMPLEX, _state, ae_true);
38430 0 : ae_vector_init(&ev, 0, DT_COMPLEX, _state, ae_true);
38431 0 : ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true);
38432 :
38433 0 : ae_assert(n>=1, "Assertion failed", _state);
38434 0 : ae_vector_set_length(&tmp, n, _state);
38435 :
38436 : /*
38437 : * RC=0 if something happens
38438 : */
38439 0 : *rc = (double)(0);
38440 :
38441 : /*
38442 : * prepare parameters for triangular solver
38443 : */
38444 0 : maxgrowth = 1/rcondthreshold(_state);
38445 0 : sa = (double)(0);
38446 0 : if( isupper )
38447 : {
38448 0 : for(i=0; i<=n-1; i++)
38449 : {
38450 0 : for(j=i; j<=n-1; j++)
38451 : {
38452 0 : sa = ae_maxreal(sa, ae_c_abs(cha->ptr.pp_complex[i][j], _state), _state);
38453 : }
38454 : }
38455 : }
38456 : else
38457 : {
38458 0 : for(i=0; i<=n-1; i++)
38459 : {
38460 0 : for(j=0; j<=i; j++)
38461 : {
38462 0 : sa = ae_maxreal(sa, ae_c_abs(cha->ptr.pp_complex[i][j], _state), _state);
38463 : }
38464 : }
38465 : }
38466 0 : if( ae_fp_eq(sa,(double)(0)) )
38467 : {
38468 0 : sa = (double)(1);
38469 : }
38470 0 : sa = 1/sa;
38471 :
38472 : /*
38473 : * Estimate the norm of A
38474 : */
38475 0 : if( !isnormprovided )
38476 : {
38477 0 : anorm = (double)(0);
38478 0 : kase = 0;
38479 : for(;;)
38480 : {
38481 0 : rcond_cmatrixestimatenorm(n, &ev, &ex, &anorm, &kase, &isave, &rsave, _state);
38482 0 : if( kase==0 )
38483 : {
38484 0 : break;
38485 : }
38486 0 : if( isupper )
38487 : {
38488 :
38489 : /*
38490 : * Multiply by U
38491 : */
38492 0 : for(i=1; i<=n; i++)
38493 : {
38494 0 : v = ae_v_cdotproduct(&cha->ptr.pp_complex[i-1][i-1], 1, "N", &ex.ptr.p_complex[i], 1, "N", ae_v_len(i-1,n-1));
38495 0 : ex.ptr.p_complex[i] = v;
38496 : }
38497 0 : ae_v_cmuld(&ex.ptr.p_complex[1], 1, ae_v_len(1,n), sa);
38498 :
38499 : /*
38500 : * Multiply by U'
38501 : */
38502 0 : for(i=0; i<=n-1; i++)
38503 : {
38504 0 : tmp.ptr.p_complex[i] = ae_complex_from_i(0);
38505 : }
38506 0 : for(i=0; i<=n-1; i++)
38507 : {
38508 0 : v = ex.ptr.p_complex[i+1];
38509 0 : ae_v_caddc(&tmp.ptr.p_complex[i], 1, &cha->ptr.pp_complex[i][i], 1, "Conj", ae_v_len(i,n-1), v);
38510 : }
38511 0 : ae_v_cmove(&ex.ptr.p_complex[1], 1, &tmp.ptr.p_complex[0], 1, "N", ae_v_len(1,n));
38512 0 : ae_v_cmuld(&ex.ptr.p_complex[1], 1, ae_v_len(1,n), sa);
38513 : }
38514 : else
38515 : {
38516 :
38517 : /*
38518 : * Multiply by L'
38519 : */
38520 0 : for(i=0; i<=n-1; i++)
38521 : {
38522 0 : tmp.ptr.p_complex[i] = ae_complex_from_i(0);
38523 : }
38524 0 : for(i=0; i<=n-1; i++)
38525 : {
38526 0 : v = ex.ptr.p_complex[i+1];
38527 0 : ae_v_caddc(&tmp.ptr.p_complex[0], 1, &cha->ptr.pp_complex[i][0], 1, "Conj", ae_v_len(0,i), v);
38528 : }
38529 0 : ae_v_cmove(&ex.ptr.p_complex[1], 1, &tmp.ptr.p_complex[0], 1, "N", ae_v_len(1,n));
38530 0 : ae_v_cmuld(&ex.ptr.p_complex[1], 1, ae_v_len(1,n), sa);
38531 :
38532 : /*
38533 : * Multiply by L
38534 : */
38535 0 : for(i=n; i>=1; i--)
38536 : {
38537 0 : v = ae_v_cdotproduct(&cha->ptr.pp_complex[i-1][0], 1, "N", &ex.ptr.p_complex[1], 1, "N", ae_v_len(0,i-1));
38538 0 : ex.ptr.p_complex[i] = v;
38539 : }
38540 0 : ae_v_cmuld(&ex.ptr.p_complex[1], 1, ae_v_len(1,n), sa);
38541 : }
38542 : }
38543 : }
38544 :
38545 : /*
38546 : * Quick return if possible
38547 : * After this block we assume that ANORM<>0
38548 : */
38549 0 : if( ae_fp_eq(anorm,(double)(0)) )
38550 : {
38551 0 : ae_frame_leave(_state);
38552 0 : return;
38553 : }
38554 0 : if( n==1 )
38555 : {
38556 0 : *rc = (double)(1);
38557 0 : ae_frame_leave(_state);
38558 0 : return;
38559 : }
38560 :
38561 : /*
38562 : * Estimate the norm of inv(A).
38563 : */
38564 0 : ainvnm = (double)(0);
38565 0 : kase = 0;
38566 : for(;;)
38567 : {
38568 0 : rcond_cmatrixestimatenorm(n, &ev, &ex, &ainvnm, &kase, &isave, &rsave, _state);
38569 0 : if( kase==0 )
38570 : {
38571 0 : break;
38572 : }
38573 0 : for(i=0; i<=n-1; i++)
38574 : {
38575 0 : ex.ptr.p_complex[i] = ex.ptr.p_complex[i+1];
38576 : }
38577 0 : if( isupper )
38578 : {
38579 :
38580 : /*
38581 : * Multiply by inv(U').
38582 : */
38583 0 : if( !cmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 2, ae_false, maxgrowth, _state) )
38584 : {
38585 0 : ae_frame_leave(_state);
38586 0 : return;
38587 : }
38588 :
38589 : /*
38590 : * Multiply by inv(U).
38591 : */
38592 0 : if( !cmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 0, ae_false, maxgrowth, _state) )
38593 : {
38594 0 : ae_frame_leave(_state);
38595 0 : return;
38596 : }
38597 : }
38598 : else
38599 : {
38600 :
38601 : /*
38602 : * Multiply by inv(L).
38603 : */
38604 0 : if( !cmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 0, ae_false, maxgrowth, _state) )
38605 : {
38606 0 : ae_frame_leave(_state);
38607 0 : return;
38608 : }
38609 :
38610 : /*
38611 : * Multiply by inv(L').
38612 : */
38613 0 : if( !cmatrixscaledtrsafesolve(cha, sa, n, &ex, isupper, 2, ae_false, maxgrowth, _state) )
38614 : {
38615 0 : ae_frame_leave(_state);
38616 0 : return;
38617 : }
38618 : }
38619 0 : for(i=n-1; i>=0; i--)
38620 : {
38621 0 : ex.ptr.p_complex[i+1] = ex.ptr.p_complex[i];
38622 : }
38623 : }
38624 :
38625 : /*
38626 : * Compute the estimate of the reciprocal condition number.
38627 : */
38628 0 : if( ae_fp_neq(ainvnm,(double)(0)) )
38629 : {
38630 0 : *rc = 1/ainvnm;
38631 0 : *rc = *rc/anorm;
38632 0 : if( ae_fp_less(*rc,rcondthreshold(_state)) )
38633 : {
38634 0 : *rc = (double)(0);
38635 : }
38636 : }
38637 0 : ae_frame_leave(_state);
38638 : }
38639 :
38640 :
38641 : /*************************************************************************
38642 : Internal subroutine for condition number estimation
38643 :
38644 : -- LAPACK routine (version 3.0) --
38645 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
38646 : Courant Institute, Argonne National Lab, and Rice University
38647 : February 29, 1992
38648 : *************************************************************************/
38649 0 : static void rcond_rmatrixrcondluinternal(/* Real */ ae_matrix* lua,
38650 : ae_int_t n,
38651 : ae_bool onenorm,
38652 : ae_bool isanormprovided,
38653 : double anorm,
38654 : double* rc,
38655 : ae_state *_state)
38656 : {
38657 : ae_frame _frame_block;
38658 : ae_vector ex;
38659 : ae_vector ev;
38660 : ae_vector iwork;
38661 : ae_vector tmp;
38662 : double v;
38663 : ae_int_t i;
38664 : ae_int_t j;
38665 : ae_int_t kase;
38666 : ae_int_t kase1;
38667 : double ainvnm;
38668 : double maxgrowth;
38669 : double su;
38670 : double sl;
38671 : ae_bool mupper;
38672 : ae_bool munit;
38673 :
38674 0 : ae_frame_make(_state, &_frame_block);
38675 0 : memset(&ex, 0, sizeof(ex));
38676 0 : memset(&ev, 0, sizeof(ev));
38677 0 : memset(&iwork, 0, sizeof(iwork));
38678 0 : memset(&tmp, 0, sizeof(tmp));
38679 0 : *rc = 0;
38680 0 : ae_vector_init(&ex, 0, DT_REAL, _state, ae_true);
38681 0 : ae_vector_init(&ev, 0, DT_REAL, _state, ae_true);
38682 0 : ae_vector_init(&iwork, 0, DT_INT, _state, ae_true);
38683 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
38684 :
38685 :
38686 : /*
38687 : * RC=0 if something happens
38688 : */
38689 0 : *rc = (double)(0);
38690 :
38691 : /*
38692 : * init
38693 : */
38694 0 : if( onenorm )
38695 : {
38696 0 : kase1 = 1;
38697 : }
38698 : else
38699 : {
38700 0 : kase1 = 2;
38701 : }
38702 0 : mupper = ae_true;
38703 0 : munit = ae_true;
38704 0 : ae_vector_set_length(&iwork, n+1, _state);
38705 0 : ae_vector_set_length(&tmp, n, _state);
38706 :
38707 : /*
38708 : * prepare parameters for triangular solver
38709 : */
38710 0 : maxgrowth = 1/rcondthreshold(_state);
38711 0 : su = (double)(0);
38712 0 : sl = (double)(1);
38713 0 : for(i=0; i<=n-1; i++)
38714 : {
38715 0 : for(j=0; j<=i-1; j++)
38716 : {
38717 0 : sl = ae_maxreal(sl, ae_fabs(lua->ptr.pp_double[i][j], _state), _state);
38718 : }
38719 0 : for(j=i; j<=n-1; j++)
38720 : {
38721 0 : su = ae_maxreal(su, ae_fabs(lua->ptr.pp_double[i][j], _state), _state);
38722 : }
38723 : }
38724 0 : if( ae_fp_eq(su,(double)(0)) )
38725 : {
38726 0 : su = (double)(1);
38727 : }
38728 0 : su = 1/su;
38729 0 : sl = 1/sl;
38730 :
38731 : /*
38732 : * Estimate the norm of A.
38733 : */
38734 0 : if( !isanormprovided )
38735 : {
38736 0 : kase = 0;
38737 0 : anorm = (double)(0);
38738 : for(;;)
38739 : {
38740 0 : rcond_rmatrixestimatenorm(n, &ev, &ex, &iwork, &anorm, &kase, _state);
38741 0 : if( kase==0 )
38742 : {
38743 0 : break;
38744 : }
38745 0 : if( kase==kase1 )
38746 : {
38747 :
38748 : /*
38749 : * Multiply by U
38750 : */
38751 0 : for(i=1; i<=n; i++)
38752 : {
38753 0 : v = ae_v_dotproduct(&lua->ptr.pp_double[i-1][i-1], 1, &ex.ptr.p_double[i], 1, ae_v_len(i-1,n-1));
38754 0 : ex.ptr.p_double[i] = v;
38755 : }
38756 :
38757 : /*
38758 : * Multiply by L
38759 : */
38760 0 : for(i=n; i>=1; i--)
38761 : {
38762 0 : if( i>1 )
38763 : {
38764 0 : v = ae_v_dotproduct(&lua->ptr.pp_double[i-1][0], 1, &ex.ptr.p_double[1], 1, ae_v_len(0,i-2));
38765 : }
38766 : else
38767 : {
38768 0 : v = (double)(0);
38769 : }
38770 0 : ex.ptr.p_double[i] = ex.ptr.p_double[i]+v;
38771 : }
38772 : }
38773 : else
38774 : {
38775 :
38776 : /*
38777 : * Multiply by L'
38778 : */
38779 0 : for(i=0; i<=n-1; i++)
38780 : {
38781 0 : tmp.ptr.p_double[i] = (double)(0);
38782 : }
38783 0 : for(i=0; i<=n-1; i++)
38784 : {
38785 0 : v = ex.ptr.p_double[i+1];
38786 0 : if( i>=1 )
38787 : {
38788 0 : ae_v_addd(&tmp.ptr.p_double[0], 1, &lua->ptr.pp_double[i][0], 1, ae_v_len(0,i-1), v);
38789 : }
38790 0 : tmp.ptr.p_double[i] = tmp.ptr.p_double[i]+v;
38791 : }
38792 0 : ae_v_move(&ex.ptr.p_double[1], 1, &tmp.ptr.p_double[0], 1, ae_v_len(1,n));
38793 :
38794 : /*
38795 : * Multiply by U'
38796 : */
38797 0 : for(i=0; i<=n-1; i++)
38798 : {
38799 0 : tmp.ptr.p_double[i] = (double)(0);
38800 : }
38801 0 : for(i=0; i<=n-1; i++)
38802 : {
38803 0 : v = ex.ptr.p_double[i+1];
38804 0 : ae_v_addd(&tmp.ptr.p_double[i], 1, &lua->ptr.pp_double[i][i], 1, ae_v_len(i,n-1), v);
38805 : }
38806 0 : ae_v_move(&ex.ptr.p_double[1], 1, &tmp.ptr.p_double[0], 1, ae_v_len(1,n));
38807 : }
38808 : }
38809 : }
38810 :
38811 : /*
38812 : * Scale according to SU/SL
38813 : */
38814 0 : anorm = anorm*su*sl;
38815 :
38816 : /*
38817 : * Quick return if possible
38818 : * We assume that ANORM<>0 after this block
38819 : */
38820 0 : if( ae_fp_eq(anorm,(double)(0)) )
38821 : {
38822 0 : ae_frame_leave(_state);
38823 0 : return;
38824 : }
38825 0 : if( n==1 )
38826 : {
38827 0 : *rc = (double)(1);
38828 0 : ae_frame_leave(_state);
38829 0 : return;
38830 : }
38831 :
38832 : /*
38833 : * Estimate the norm of inv(A).
38834 : */
38835 0 : ainvnm = (double)(0);
38836 0 : kase = 0;
38837 : for(;;)
38838 : {
38839 0 : rcond_rmatrixestimatenorm(n, &ev, &ex, &iwork, &ainvnm, &kase, _state);
38840 0 : if( kase==0 )
38841 : {
38842 0 : break;
38843 : }
38844 :
38845 : /*
38846 : * from 1-based array to 0-based
38847 : */
38848 0 : for(i=0; i<=n-1; i++)
38849 : {
38850 0 : ex.ptr.p_double[i] = ex.ptr.p_double[i+1];
38851 : }
38852 :
38853 : /*
38854 : * multiply by inv(A) or inv(A')
38855 : */
38856 0 : if( kase==kase1 )
38857 : {
38858 :
38859 : /*
38860 : * Multiply by inv(L).
38861 : */
38862 0 : if( !rmatrixscaledtrsafesolve(lua, sl, n, &ex, !mupper, 0, munit, maxgrowth, _state) )
38863 : {
38864 0 : ae_frame_leave(_state);
38865 0 : return;
38866 : }
38867 :
38868 : /*
38869 : * Multiply by inv(U).
38870 : */
38871 0 : if( !rmatrixscaledtrsafesolve(lua, su, n, &ex, mupper, 0, !munit, maxgrowth, _state) )
38872 : {
38873 0 : ae_frame_leave(_state);
38874 0 : return;
38875 : }
38876 : }
38877 : else
38878 : {
38879 :
38880 : /*
38881 : * Multiply by inv(U').
38882 : */
38883 0 : if( !rmatrixscaledtrsafesolve(lua, su, n, &ex, mupper, 1, !munit, maxgrowth, _state) )
38884 : {
38885 0 : ae_frame_leave(_state);
38886 0 : return;
38887 : }
38888 :
38889 : /*
38890 : * Multiply by inv(L').
38891 : */
38892 0 : if( !rmatrixscaledtrsafesolve(lua, sl, n, &ex, !mupper, 1, munit, maxgrowth, _state) )
38893 : {
38894 0 : ae_frame_leave(_state);
38895 0 : return;
38896 : }
38897 : }
38898 :
38899 : /*
38900 : * from 0-based array to 1-based
38901 : */
38902 0 : for(i=n-1; i>=0; i--)
38903 : {
38904 0 : ex.ptr.p_double[i+1] = ex.ptr.p_double[i];
38905 : }
38906 : }
38907 :
38908 : /*
38909 : * Compute the estimate of the reciprocal condition number.
38910 : */
38911 0 : if( ae_fp_neq(ainvnm,(double)(0)) )
38912 : {
38913 0 : *rc = 1/ainvnm;
38914 0 : *rc = *rc/anorm;
38915 0 : if( ae_fp_less(*rc,rcondthreshold(_state)) )
38916 : {
38917 0 : *rc = (double)(0);
38918 : }
38919 : }
38920 0 : ae_frame_leave(_state);
38921 : }
38922 :
38923 :
38924 : /*************************************************************************
38925 : Condition number estimation
38926 :
38927 : -- LAPACK routine (version 3.0) --
38928 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
38929 : Courant Institute, Argonne National Lab, and Rice University
38930 : March 31, 1993
38931 : *************************************************************************/
38932 0 : static void rcond_cmatrixrcondluinternal(/* Complex */ ae_matrix* lua,
38933 : ae_int_t n,
38934 : ae_bool onenorm,
38935 : ae_bool isanormprovided,
38936 : double anorm,
38937 : double* rc,
38938 : ae_state *_state)
38939 : {
38940 : ae_frame _frame_block;
38941 : ae_vector ex;
38942 : ae_vector cwork2;
38943 : ae_vector cwork3;
38944 : ae_vector cwork4;
38945 : ae_vector isave;
38946 : ae_vector rsave;
38947 : ae_int_t kase;
38948 : ae_int_t kase1;
38949 : double ainvnm;
38950 : ae_complex v;
38951 : ae_int_t i;
38952 : ae_int_t j;
38953 : double su;
38954 : double sl;
38955 : double maxgrowth;
38956 :
38957 0 : ae_frame_make(_state, &_frame_block);
38958 0 : memset(&ex, 0, sizeof(ex));
38959 0 : memset(&cwork2, 0, sizeof(cwork2));
38960 0 : memset(&cwork3, 0, sizeof(cwork3));
38961 0 : memset(&cwork4, 0, sizeof(cwork4));
38962 0 : memset(&isave, 0, sizeof(isave));
38963 0 : memset(&rsave, 0, sizeof(rsave));
38964 0 : *rc = 0;
38965 0 : ae_vector_init(&ex, 0, DT_COMPLEX, _state, ae_true);
38966 0 : ae_vector_init(&cwork2, 0, DT_COMPLEX, _state, ae_true);
38967 0 : ae_vector_init(&cwork3, 0, DT_COMPLEX, _state, ae_true);
38968 0 : ae_vector_init(&cwork4, 0, DT_COMPLEX, _state, ae_true);
38969 0 : ae_vector_init(&isave, 0, DT_INT, _state, ae_true);
38970 0 : ae_vector_init(&rsave, 0, DT_REAL, _state, ae_true);
38971 :
38972 0 : if( n<=0 )
38973 : {
38974 0 : ae_frame_leave(_state);
38975 0 : return;
38976 : }
38977 0 : ae_vector_set_length(&cwork2, n+1, _state);
38978 0 : *rc = (double)(0);
38979 0 : if( n==0 )
38980 : {
38981 0 : *rc = (double)(1);
38982 0 : ae_frame_leave(_state);
38983 0 : return;
38984 : }
38985 :
38986 : /*
38987 : * prepare parameters for triangular solver
38988 : */
38989 0 : maxgrowth = 1/rcondthreshold(_state);
38990 0 : su = (double)(0);
38991 0 : sl = (double)(1);
38992 0 : for(i=0; i<=n-1; i++)
38993 : {
38994 0 : for(j=0; j<=i-1; j++)
38995 : {
38996 0 : sl = ae_maxreal(sl, ae_c_abs(lua->ptr.pp_complex[i][j], _state), _state);
38997 : }
38998 0 : for(j=i; j<=n-1; j++)
38999 : {
39000 0 : su = ae_maxreal(su, ae_c_abs(lua->ptr.pp_complex[i][j], _state), _state);
39001 : }
39002 : }
39003 0 : if( ae_fp_eq(su,(double)(0)) )
39004 : {
39005 0 : su = (double)(1);
39006 : }
39007 0 : su = 1/su;
39008 0 : sl = 1/sl;
39009 :
39010 : /*
39011 : * Estimate the norm of SU*SL*A.
39012 : */
39013 0 : if( !isanormprovided )
39014 : {
39015 0 : anorm = (double)(0);
39016 0 : if( onenorm )
39017 : {
39018 0 : kase1 = 1;
39019 : }
39020 : else
39021 : {
39022 0 : kase1 = 2;
39023 : }
39024 0 : kase = 0;
39025 0 : do
39026 : {
39027 0 : rcond_cmatrixestimatenorm(n, &cwork4, &ex, &anorm, &kase, &isave, &rsave, _state);
39028 0 : if( kase!=0 )
39029 : {
39030 0 : if( kase==kase1 )
39031 : {
39032 :
39033 : /*
39034 : * Multiply by U
39035 : */
39036 0 : for(i=1; i<=n; i++)
39037 : {
39038 0 : v = ae_v_cdotproduct(&lua->ptr.pp_complex[i-1][i-1], 1, "N", &ex.ptr.p_complex[i], 1, "N", ae_v_len(i-1,n-1));
39039 0 : ex.ptr.p_complex[i] = v;
39040 : }
39041 :
39042 : /*
39043 : * Multiply by L
39044 : */
39045 0 : for(i=n; i>=1; i--)
39046 : {
39047 0 : v = ae_complex_from_i(0);
39048 0 : if( i>1 )
39049 : {
39050 0 : v = ae_v_cdotproduct(&lua->ptr.pp_complex[i-1][0], 1, "N", &ex.ptr.p_complex[1], 1, "N", ae_v_len(0,i-2));
39051 : }
39052 0 : ex.ptr.p_complex[i] = ae_c_add(v,ex.ptr.p_complex[i]);
39053 : }
39054 : }
39055 : else
39056 : {
39057 :
39058 : /*
39059 : * Multiply by L'
39060 : */
39061 0 : for(i=1; i<=n; i++)
39062 : {
39063 0 : cwork2.ptr.p_complex[i] = ae_complex_from_i(0);
39064 : }
39065 0 : for(i=1; i<=n; i++)
39066 : {
39067 0 : v = ex.ptr.p_complex[i];
39068 0 : if( i>1 )
39069 : {
39070 0 : ae_v_caddc(&cwork2.ptr.p_complex[1], 1, &lua->ptr.pp_complex[i-1][0], 1, "Conj", ae_v_len(1,i-1), v);
39071 : }
39072 0 : cwork2.ptr.p_complex[i] = ae_c_add(cwork2.ptr.p_complex[i],v);
39073 : }
39074 :
39075 : /*
39076 : * Multiply by U'
39077 : */
39078 0 : for(i=1; i<=n; i++)
39079 : {
39080 0 : ex.ptr.p_complex[i] = ae_complex_from_i(0);
39081 : }
39082 0 : for(i=1; i<=n; i++)
39083 : {
39084 0 : v = cwork2.ptr.p_complex[i];
39085 0 : ae_v_caddc(&ex.ptr.p_complex[i], 1, &lua->ptr.pp_complex[i-1][i-1], 1, "Conj", ae_v_len(i,n), v);
39086 : }
39087 : }
39088 : }
39089 : }
39090 0 : while(kase!=0);
39091 : }
39092 :
39093 : /*
39094 : * Scale according to SU/SL
39095 : */
39096 0 : anorm = anorm*su*sl;
39097 :
39098 : /*
39099 : * Quick return if possible
39100 : */
39101 0 : if( ae_fp_eq(anorm,(double)(0)) )
39102 : {
39103 0 : ae_frame_leave(_state);
39104 0 : return;
39105 : }
39106 :
39107 : /*
39108 : * Estimate the norm of inv(A).
39109 : */
39110 0 : ainvnm = (double)(0);
39111 0 : if( onenorm )
39112 : {
39113 0 : kase1 = 1;
39114 : }
39115 : else
39116 : {
39117 0 : kase1 = 2;
39118 : }
39119 0 : kase = 0;
39120 : for(;;)
39121 : {
39122 0 : rcond_cmatrixestimatenorm(n, &cwork4, &ex, &ainvnm, &kase, &isave, &rsave, _state);
39123 0 : if( kase==0 )
39124 : {
39125 0 : break;
39126 : }
39127 :
39128 : /*
39129 : * From 1-based to 0-based
39130 : */
39131 0 : for(i=0; i<=n-1; i++)
39132 : {
39133 0 : ex.ptr.p_complex[i] = ex.ptr.p_complex[i+1];
39134 : }
39135 :
39136 : /*
39137 : * multiply by inv(A) or inv(A')
39138 : */
39139 0 : if( kase==kase1 )
39140 : {
39141 :
39142 : /*
39143 : * Multiply by inv(L).
39144 : */
39145 0 : if( !cmatrixscaledtrsafesolve(lua, sl, n, &ex, ae_false, 0, ae_true, maxgrowth, _state) )
39146 : {
39147 0 : *rc = (double)(0);
39148 0 : ae_frame_leave(_state);
39149 0 : return;
39150 : }
39151 :
39152 : /*
39153 : * Multiply by inv(U).
39154 : */
39155 0 : if( !cmatrixscaledtrsafesolve(lua, su, n, &ex, ae_true, 0, ae_false, maxgrowth, _state) )
39156 : {
39157 0 : *rc = (double)(0);
39158 0 : ae_frame_leave(_state);
39159 0 : return;
39160 : }
39161 : }
39162 : else
39163 : {
39164 :
39165 : /*
39166 : * Multiply by inv(U').
39167 : */
39168 0 : if( !cmatrixscaledtrsafesolve(lua, su, n, &ex, ae_true, 2, ae_false, maxgrowth, _state) )
39169 : {
39170 0 : *rc = (double)(0);
39171 0 : ae_frame_leave(_state);
39172 0 : return;
39173 : }
39174 :
39175 : /*
39176 : * Multiply by inv(L').
39177 : */
39178 0 : if( !cmatrixscaledtrsafesolve(lua, sl, n, &ex, ae_false, 2, ae_true, maxgrowth, _state) )
39179 : {
39180 0 : *rc = (double)(0);
39181 0 : ae_frame_leave(_state);
39182 0 : return;
39183 : }
39184 : }
39185 :
39186 : /*
39187 : * from 0-based to 1-based
39188 : */
39189 0 : for(i=n-1; i>=0; i--)
39190 : {
39191 0 : ex.ptr.p_complex[i+1] = ex.ptr.p_complex[i];
39192 : }
39193 : }
39194 :
39195 : /*
39196 : * Compute the estimate of the reciprocal condition number.
39197 : */
39198 0 : if( ae_fp_neq(ainvnm,(double)(0)) )
39199 : {
39200 0 : *rc = 1/ainvnm;
39201 0 : *rc = *rc/anorm;
39202 0 : if( ae_fp_less(*rc,rcondthreshold(_state)) )
39203 : {
39204 0 : *rc = (double)(0);
39205 : }
39206 : }
39207 0 : ae_frame_leave(_state);
39208 : }
39209 :
39210 :
39211 : /*************************************************************************
39212 : Internal subroutine for matrix norm estimation
39213 :
39214 : -- LAPACK auxiliary routine (version 3.0) --
39215 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
39216 : Courant Institute, Argonne National Lab, and Rice University
39217 : February 29, 1992
39218 : *************************************************************************/
39219 0 : static void rcond_rmatrixestimatenorm(ae_int_t n,
39220 : /* Real */ ae_vector* v,
39221 : /* Real */ ae_vector* x,
39222 : /* Integer */ ae_vector* isgn,
39223 : double* est,
39224 : ae_int_t* kase,
39225 : ae_state *_state)
39226 : {
39227 : ae_int_t itmax;
39228 : ae_int_t i;
39229 : double t;
39230 : ae_bool flg;
39231 : ae_int_t positer;
39232 : ae_int_t posj;
39233 : ae_int_t posjlast;
39234 : ae_int_t posjump;
39235 : ae_int_t posaltsgn;
39236 : ae_int_t posestold;
39237 : ae_int_t postemp;
39238 :
39239 :
39240 0 : itmax = 5;
39241 0 : posaltsgn = n+1;
39242 0 : posestold = n+2;
39243 0 : postemp = n+3;
39244 0 : positer = n+1;
39245 0 : posj = n+2;
39246 0 : posjlast = n+3;
39247 0 : posjump = n+4;
39248 0 : if( *kase==0 )
39249 : {
39250 0 : ae_vector_set_length(v, n+4, _state);
39251 0 : ae_vector_set_length(x, n+1, _state);
39252 0 : ae_vector_set_length(isgn, n+5, _state);
39253 0 : t = (double)1/(double)n;
39254 0 : for(i=1; i<=n; i++)
39255 : {
39256 0 : x->ptr.p_double[i] = t;
39257 : }
39258 0 : *kase = 1;
39259 0 : isgn->ptr.p_int[posjump] = 1;
39260 0 : return;
39261 : }
39262 :
39263 : /*
39264 : * ................ ENTRY (JUMP = 1)
39265 : * FIRST ITERATION. X HAS BEEN OVERWRITTEN BY A*X.
39266 : */
39267 0 : if( isgn->ptr.p_int[posjump]==1 )
39268 : {
39269 0 : if( n==1 )
39270 : {
39271 0 : v->ptr.p_double[1] = x->ptr.p_double[1];
39272 0 : *est = ae_fabs(v->ptr.p_double[1], _state);
39273 0 : *kase = 0;
39274 0 : return;
39275 : }
39276 0 : *est = (double)(0);
39277 0 : for(i=1; i<=n; i++)
39278 : {
39279 0 : *est = *est+ae_fabs(x->ptr.p_double[i], _state);
39280 : }
39281 0 : for(i=1; i<=n; i++)
39282 : {
39283 0 : if( ae_fp_greater_eq(x->ptr.p_double[i],(double)(0)) )
39284 : {
39285 0 : x->ptr.p_double[i] = (double)(1);
39286 : }
39287 : else
39288 : {
39289 0 : x->ptr.p_double[i] = (double)(-1);
39290 : }
39291 0 : isgn->ptr.p_int[i] = ae_sign(x->ptr.p_double[i], _state);
39292 : }
39293 0 : *kase = 2;
39294 0 : isgn->ptr.p_int[posjump] = 2;
39295 0 : return;
39296 : }
39297 :
39298 : /*
39299 : * ................ ENTRY (JUMP = 2)
39300 : * FIRST ITERATION. X HAS BEEN OVERWRITTEN BY TRANDPOSE(A)*X.
39301 : */
39302 0 : if( isgn->ptr.p_int[posjump]==2 )
39303 : {
39304 0 : isgn->ptr.p_int[posj] = 1;
39305 0 : for(i=2; i<=n; i++)
39306 : {
39307 0 : if( ae_fp_greater(ae_fabs(x->ptr.p_double[i], _state),ae_fabs(x->ptr.p_double[isgn->ptr.p_int[posj]], _state)) )
39308 : {
39309 0 : isgn->ptr.p_int[posj] = i;
39310 : }
39311 : }
39312 0 : isgn->ptr.p_int[positer] = 2;
39313 :
39314 : /*
39315 : * MAIN LOOP - ITERATIONS 2,3,...,ITMAX.
39316 : */
39317 0 : for(i=1; i<=n; i++)
39318 : {
39319 0 : x->ptr.p_double[i] = (double)(0);
39320 : }
39321 0 : x->ptr.p_double[isgn->ptr.p_int[posj]] = (double)(1);
39322 0 : *kase = 1;
39323 0 : isgn->ptr.p_int[posjump] = 3;
39324 0 : return;
39325 : }
39326 :
39327 : /*
39328 : * ................ ENTRY (JUMP = 3)
39329 : * X HAS BEEN OVERWRITTEN BY A*X.
39330 : */
39331 0 : if( isgn->ptr.p_int[posjump]==3 )
39332 : {
39333 0 : ae_v_move(&v->ptr.p_double[1], 1, &x->ptr.p_double[1], 1, ae_v_len(1,n));
39334 0 : v->ptr.p_double[posestold] = *est;
39335 0 : *est = (double)(0);
39336 0 : for(i=1; i<=n; i++)
39337 : {
39338 0 : *est = *est+ae_fabs(v->ptr.p_double[i], _state);
39339 : }
39340 0 : flg = ae_false;
39341 0 : for(i=1; i<=n; i++)
39342 : {
39343 0 : if( (ae_fp_greater_eq(x->ptr.p_double[i],(double)(0))&&isgn->ptr.p_int[i]<0)||(ae_fp_less(x->ptr.p_double[i],(double)(0))&&isgn->ptr.p_int[i]>=0) )
39344 : {
39345 0 : flg = ae_true;
39346 : }
39347 : }
39348 :
39349 : /*
39350 : * REPEATED SIGN VECTOR DETECTED, HENCE ALGORITHM HAS CONVERGED.
39351 : * OR MAY BE CYCLING.
39352 : */
39353 0 : if( !flg||ae_fp_less_eq(*est,v->ptr.p_double[posestold]) )
39354 : {
39355 0 : v->ptr.p_double[posaltsgn] = (double)(1);
39356 0 : for(i=1; i<=n; i++)
39357 : {
39358 0 : x->ptr.p_double[i] = v->ptr.p_double[posaltsgn]*(1+(double)(i-1)/(double)(n-1));
39359 0 : v->ptr.p_double[posaltsgn] = -v->ptr.p_double[posaltsgn];
39360 : }
39361 0 : *kase = 1;
39362 0 : isgn->ptr.p_int[posjump] = 5;
39363 0 : return;
39364 : }
39365 0 : for(i=1; i<=n; i++)
39366 : {
39367 0 : if( ae_fp_greater_eq(x->ptr.p_double[i],(double)(0)) )
39368 : {
39369 0 : x->ptr.p_double[i] = (double)(1);
39370 0 : isgn->ptr.p_int[i] = 1;
39371 : }
39372 : else
39373 : {
39374 0 : x->ptr.p_double[i] = (double)(-1);
39375 0 : isgn->ptr.p_int[i] = -1;
39376 : }
39377 : }
39378 0 : *kase = 2;
39379 0 : isgn->ptr.p_int[posjump] = 4;
39380 0 : return;
39381 : }
39382 :
39383 : /*
39384 : * ................ ENTRY (JUMP = 4)
39385 : * X HAS BEEN OVERWRITTEN BY TRANDPOSE(A)*X.
39386 : */
39387 0 : if( isgn->ptr.p_int[posjump]==4 )
39388 : {
39389 0 : isgn->ptr.p_int[posjlast] = isgn->ptr.p_int[posj];
39390 0 : isgn->ptr.p_int[posj] = 1;
39391 0 : for(i=2; i<=n; i++)
39392 : {
39393 0 : if( ae_fp_greater(ae_fabs(x->ptr.p_double[i], _state),ae_fabs(x->ptr.p_double[isgn->ptr.p_int[posj]], _state)) )
39394 : {
39395 0 : isgn->ptr.p_int[posj] = i;
39396 : }
39397 : }
39398 0 : if( ae_fp_neq(x->ptr.p_double[isgn->ptr.p_int[posjlast]],ae_fabs(x->ptr.p_double[isgn->ptr.p_int[posj]], _state))&&isgn->ptr.p_int[positer]<itmax )
39399 : {
39400 0 : isgn->ptr.p_int[positer] = isgn->ptr.p_int[positer]+1;
39401 0 : for(i=1; i<=n; i++)
39402 : {
39403 0 : x->ptr.p_double[i] = (double)(0);
39404 : }
39405 0 : x->ptr.p_double[isgn->ptr.p_int[posj]] = (double)(1);
39406 0 : *kase = 1;
39407 0 : isgn->ptr.p_int[posjump] = 3;
39408 0 : return;
39409 : }
39410 :
39411 : /*
39412 : * ITERATION COMPLETE. FINAL STAGE.
39413 : */
39414 0 : v->ptr.p_double[posaltsgn] = (double)(1);
39415 0 : for(i=1; i<=n; i++)
39416 : {
39417 0 : x->ptr.p_double[i] = v->ptr.p_double[posaltsgn]*(1+(double)(i-1)/(double)(n-1));
39418 0 : v->ptr.p_double[posaltsgn] = -v->ptr.p_double[posaltsgn];
39419 : }
39420 0 : *kase = 1;
39421 0 : isgn->ptr.p_int[posjump] = 5;
39422 0 : return;
39423 : }
39424 :
39425 : /*
39426 : * ................ ENTRY (JUMP = 5)
39427 : * X HAS BEEN OVERWRITTEN BY A*X.
39428 : */
39429 0 : if( isgn->ptr.p_int[posjump]==5 )
39430 : {
39431 0 : v->ptr.p_double[postemp] = (double)(0);
39432 0 : for(i=1; i<=n; i++)
39433 : {
39434 0 : v->ptr.p_double[postemp] = v->ptr.p_double[postemp]+ae_fabs(x->ptr.p_double[i], _state);
39435 : }
39436 0 : v->ptr.p_double[postemp] = 2*v->ptr.p_double[postemp]/(3*n);
39437 0 : if( ae_fp_greater(v->ptr.p_double[postemp],*est) )
39438 : {
39439 0 : ae_v_move(&v->ptr.p_double[1], 1, &x->ptr.p_double[1], 1, ae_v_len(1,n));
39440 0 : *est = v->ptr.p_double[postemp];
39441 : }
39442 0 : *kase = 0;
39443 0 : return;
39444 : }
39445 : }
39446 :
39447 :
39448 0 : static void rcond_cmatrixestimatenorm(ae_int_t n,
39449 : /* Complex */ ae_vector* v,
39450 : /* Complex */ ae_vector* x,
39451 : double* est,
39452 : ae_int_t* kase,
39453 : /* Integer */ ae_vector* isave,
39454 : /* Real */ ae_vector* rsave,
39455 : ae_state *_state)
39456 : {
39457 : ae_int_t itmax;
39458 : ae_int_t i;
39459 : ae_int_t iter;
39460 : ae_int_t j;
39461 : ae_int_t jlast;
39462 : ae_int_t jump;
39463 : double absxi;
39464 : double altsgn;
39465 : double estold;
39466 : double safmin;
39467 : double temp;
39468 :
39469 :
39470 :
39471 : /*
39472 : *Executable Statements ..
39473 : */
39474 0 : itmax = 5;
39475 0 : safmin = ae_minrealnumber;
39476 0 : if( *kase==0 )
39477 : {
39478 0 : ae_vector_set_length(v, n+1, _state);
39479 0 : ae_vector_set_length(x, n+1, _state);
39480 0 : ae_vector_set_length(isave, 5, _state);
39481 0 : ae_vector_set_length(rsave, 4, _state);
39482 0 : for(i=1; i<=n; i++)
39483 : {
39484 0 : x->ptr.p_complex[i] = ae_complex_from_d((double)1/(double)n);
39485 : }
39486 0 : *kase = 1;
39487 0 : jump = 1;
39488 0 : rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state);
39489 0 : return;
39490 : }
39491 0 : rcond_internalcomplexrcondloadall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state);
39492 :
39493 : /*
39494 : * ENTRY (JUMP = 1)
39495 : * FIRST ITERATION. X HAS BEEN OVERWRITTEN BY A*X.
39496 : */
39497 0 : if( jump==1 )
39498 : {
39499 0 : if( n==1 )
39500 : {
39501 0 : v->ptr.p_complex[1] = x->ptr.p_complex[1];
39502 0 : *est = ae_c_abs(v->ptr.p_complex[1], _state);
39503 0 : *kase = 0;
39504 0 : rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state);
39505 0 : return;
39506 : }
39507 0 : *est = rcond_internalcomplexrcondscsum1(x, n, _state);
39508 0 : for(i=1; i<=n; i++)
39509 : {
39510 0 : absxi = ae_c_abs(x->ptr.p_complex[i], _state);
39511 0 : if( ae_fp_greater(absxi,safmin) )
39512 : {
39513 0 : x->ptr.p_complex[i] = ae_c_div_d(x->ptr.p_complex[i],absxi);
39514 : }
39515 : else
39516 : {
39517 0 : x->ptr.p_complex[i] = ae_complex_from_i(1);
39518 : }
39519 : }
39520 0 : *kase = 2;
39521 0 : jump = 2;
39522 0 : rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state);
39523 0 : return;
39524 : }
39525 :
39526 : /*
39527 : * ENTRY (JUMP = 2)
39528 : * FIRST ITERATION. X HAS BEEN OVERWRITTEN BY CTRANS(A)*X.
39529 : */
39530 0 : if( jump==2 )
39531 : {
39532 0 : j = rcond_internalcomplexrcondicmax1(x, n, _state);
39533 0 : iter = 2;
39534 :
39535 : /*
39536 : * MAIN LOOP - ITERATIONS 2,3,...,ITMAX.
39537 : */
39538 0 : for(i=1; i<=n; i++)
39539 : {
39540 0 : x->ptr.p_complex[i] = ae_complex_from_i(0);
39541 : }
39542 0 : x->ptr.p_complex[j] = ae_complex_from_i(1);
39543 0 : *kase = 1;
39544 0 : jump = 3;
39545 0 : rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state);
39546 0 : return;
39547 : }
39548 :
39549 : /*
39550 : * ENTRY (JUMP = 3)
39551 : * X HAS BEEN OVERWRITTEN BY A*X.
39552 : */
39553 0 : if( jump==3 )
39554 : {
39555 0 : ae_v_cmove(&v->ptr.p_complex[1], 1, &x->ptr.p_complex[1], 1, "N", ae_v_len(1,n));
39556 0 : estold = *est;
39557 0 : *est = rcond_internalcomplexrcondscsum1(v, n, _state);
39558 :
39559 : /*
39560 : * TEST FOR CYCLING.
39561 : */
39562 0 : if( ae_fp_less_eq(*est,estold) )
39563 : {
39564 :
39565 : /*
39566 : * ITERATION COMPLETE. FINAL STAGE.
39567 : */
39568 0 : altsgn = (double)(1);
39569 0 : for(i=1; i<=n; i++)
39570 : {
39571 0 : x->ptr.p_complex[i] = ae_complex_from_d(altsgn*(1+(double)(i-1)/(double)(n-1)));
39572 0 : altsgn = -altsgn;
39573 : }
39574 0 : *kase = 1;
39575 0 : jump = 5;
39576 0 : rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state);
39577 0 : return;
39578 : }
39579 0 : for(i=1; i<=n; i++)
39580 : {
39581 0 : absxi = ae_c_abs(x->ptr.p_complex[i], _state);
39582 0 : if( ae_fp_greater(absxi,safmin) )
39583 : {
39584 0 : x->ptr.p_complex[i] = ae_c_div_d(x->ptr.p_complex[i],absxi);
39585 : }
39586 : else
39587 : {
39588 0 : x->ptr.p_complex[i] = ae_complex_from_i(1);
39589 : }
39590 : }
39591 0 : *kase = 2;
39592 0 : jump = 4;
39593 0 : rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state);
39594 0 : return;
39595 : }
39596 :
39597 : /*
39598 : * ENTRY (JUMP = 4)
39599 : * X HAS BEEN OVERWRITTEN BY CTRANS(A)*X.
39600 : */
39601 0 : if( jump==4 )
39602 : {
39603 0 : jlast = j;
39604 0 : j = rcond_internalcomplexrcondicmax1(x, n, _state);
39605 0 : if( ae_fp_neq(ae_c_abs(x->ptr.p_complex[jlast], _state),ae_c_abs(x->ptr.p_complex[j], _state))&&iter<itmax )
39606 : {
39607 0 : iter = iter+1;
39608 :
39609 : /*
39610 : * MAIN LOOP - ITERATIONS 2,3,...,ITMAX.
39611 : */
39612 0 : for(i=1; i<=n; i++)
39613 : {
39614 0 : x->ptr.p_complex[i] = ae_complex_from_i(0);
39615 : }
39616 0 : x->ptr.p_complex[j] = ae_complex_from_i(1);
39617 0 : *kase = 1;
39618 0 : jump = 3;
39619 0 : rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state);
39620 0 : return;
39621 : }
39622 :
39623 : /*
39624 : * ITERATION COMPLETE. FINAL STAGE.
39625 : */
39626 0 : altsgn = (double)(1);
39627 0 : for(i=1; i<=n; i++)
39628 : {
39629 0 : x->ptr.p_complex[i] = ae_complex_from_d(altsgn*(1+(double)(i-1)/(double)(n-1)));
39630 0 : altsgn = -altsgn;
39631 : }
39632 0 : *kase = 1;
39633 0 : jump = 5;
39634 0 : rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state);
39635 0 : return;
39636 : }
39637 :
39638 : /*
39639 : * ENTRY (JUMP = 5)
39640 : * X HAS BEEN OVERWRITTEN BY A*X.
39641 : */
39642 0 : if( jump==5 )
39643 : {
39644 0 : temp = 2*(rcond_internalcomplexrcondscsum1(x, n, _state)/(3*n));
39645 0 : if( ae_fp_greater(temp,*est) )
39646 : {
39647 0 : ae_v_cmove(&v->ptr.p_complex[1], 1, &x->ptr.p_complex[1], 1, "N", ae_v_len(1,n));
39648 0 : *est = temp;
39649 : }
39650 0 : *kase = 0;
39651 0 : rcond_internalcomplexrcondsaveall(isave, rsave, &i, &iter, &j, &jlast, &jump, &absxi, &altsgn, &estold, &temp, _state);
39652 0 : return;
39653 : }
39654 : }
39655 :
39656 :
39657 0 : static double rcond_internalcomplexrcondscsum1(/* Complex */ ae_vector* x,
39658 : ae_int_t n,
39659 : ae_state *_state)
39660 : {
39661 : ae_int_t i;
39662 : double result;
39663 :
39664 :
39665 0 : result = (double)(0);
39666 0 : for(i=1; i<=n; i++)
39667 : {
39668 0 : result = result+ae_c_abs(x->ptr.p_complex[i], _state);
39669 : }
39670 0 : return result;
39671 : }
39672 :
39673 :
39674 0 : static ae_int_t rcond_internalcomplexrcondicmax1(/* Complex */ ae_vector* x,
39675 : ae_int_t n,
39676 : ae_state *_state)
39677 : {
39678 : ae_int_t i;
39679 : double m;
39680 : ae_int_t result;
39681 :
39682 :
39683 0 : result = 1;
39684 0 : m = ae_c_abs(x->ptr.p_complex[1], _state);
39685 0 : for(i=2; i<=n; i++)
39686 : {
39687 0 : if( ae_fp_greater(ae_c_abs(x->ptr.p_complex[i], _state),m) )
39688 : {
39689 0 : result = i;
39690 0 : m = ae_c_abs(x->ptr.p_complex[i], _state);
39691 : }
39692 : }
39693 0 : return result;
39694 : }
39695 :
39696 :
39697 0 : static void rcond_internalcomplexrcondsaveall(/* Integer */ ae_vector* isave,
39698 : /* Real */ ae_vector* rsave,
39699 : ae_int_t* i,
39700 : ae_int_t* iter,
39701 : ae_int_t* j,
39702 : ae_int_t* jlast,
39703 : ae_int_t* jump,
39704 : double* absxi,
39705 : double* altsgn,
39706 : double* estold,
39707 : double* temp,
39708 : ae_state *_state)
39709 : {
39710 :
39711 :
39712 0 : isave->ptr.p_int[0] = *i;
39713 0 : isave->ptr.p_int[1] = *iter;
39714 0 : isave->ptr.p_int[2] = *j;
39715 0 : isave->ptr.p_int[3] = *jlast;
39716 0 : isave->ptr.p_int[4] = *jump;
39717 0 : rsave->ptr.p_double[0] = *absxi;
39718 0 : rsave->ptr.p_double[1] = *altsgn;
39719 0 : rsave->ptr.p_double[2] = *estold;
39720 0 : rsave->ptr.p_double[3] = *temp;
39721 0 : }
39722 :
39723 :
39724 0 : static void rcond_internalcomplexrcondloadall(/* Integer */ ae_vector* isave,
39725 : /* Real */ ae_vector* rsave,
39726 : ae_int_t* i,
39727 : ae_int_t* iter,
39728 : ae_int_t* j,
39729 : ae_int_t* jlast,
39730 : ae_int_t* jump,
39731 : double* absxi,
39732 : double* altsgn,
39733 : double* estold,
39734 : double* temp,
39735 : ae_state *_state)
39736 : {
39737 :
39738 :
39739 0 : *i = isave->ptr.p_int[0];
39740 0 : *iter = isave->ptr.p_int[1];
39741 0 : *j = isave->ptr.p_int[2];
39742 0 : *jlast = isave->ptr.p_int[3];
39743 0 : *jump = isave->ptr.p_int[4];
39744 0 : *absxi = rsave->ptr.p_double[0];
39745 0 : *altsgn = rsave->ptr.p_double[1];
39746 0 : *estold = rsave->ptr.p_double[2];
39747 0 : *temp = rsave->ptr.p_double[3];
39748 0 : }
39749 :
39750 :
39751 : #endif
39752 : #if defined(AE_COMPILE_MATINV) || !defined(AE_PARTIAL_BUILD)
39753 :
39754 :
39755 : /*************************************************************************
39756 : Inversion of a matrix given by its LU decomposition.
39757 :
39758 : ! COMMERCIAL EDITION OF ALGLIB:
39759 : !
39760 : ! Commercial Edition of ALGLIB includes following important improvements
39761 : ! of this function:
39762 : ! * high-performance native backend with same C# interface (C# version)
39763 : ! * multithreading support (C++ and C# versions)
39764 : ! * hardware vendor (Intel) implementations of linear algebra primitives
39765 : ! (C++ and C# versions, x86/x64 platform)
39766 : !
39767 : ! We recommend you to read 'Working with commercial version' section of
39768 : ! ALGLIB Reference Manual in order to find out how to use performance-
39769 : ! related features provided by commercial edition of ALGLIB.
39770 :
39771 : INPUT PARAMETERS:
39772 : A - LU decomposition of the matrix
39773 : (output of RMatrixLU subroutine).
39774 : Pivots - table of permutations
39775 : (the output of RMatrixLU subroutine).
39776 : N - size of matrix A (optional) :
39777 : * if given, only principal NxN submatrix is processed and
39778 : overwritten. other elements are unchanged.
39779 : * if not given, size is automatically determined from
39780 : matrix size (A must be square matrix)
39781 :
39782 : OUTPUT PARAMETERS:
39783 : Info - return code:
39784 : * -3 A is singular, or VERY close to singular.
39785 : it is filled by zeros in such cases.
39786 : * 1 task is solved (but matrix A may be ill-conditioned,
39787 : check R1/RInf parameters for condition numbers).
39788 : Rep - solver report, see below for more info
39789 : A - inverse of matrix A.
39790 : Array whose indexes range within [0..N-1, 0..N-1].
39791 :
39792 : SOLVER REPORT
39793 :
39794 : Subroutine sets following fields of the Rep structure:
39795 : * R1 reciprocal of condition number: 1/cond(A), 1-norm.
39796 : * RInf reciprocal of condition number: 1/cond(A), inf-norm.
39797 :
39798 : -- ALGLIB routine --
39799 : 05.02.2010
39800 : Bochkanov Sergey
39801 : *************************************************************************/
39802 0 : void rmatrixluinverse(/* Real */ ae_matrix* a,
39803 : /* Integer */ ae_vector* pivots,
39804 : ae_int_t n,
39805 : ae_int_t* info,
39806 : matinvreport* rep,
39807 : ae_state *_state)
39808 : {
39809 : ae_frame _frame_block;
39810 : ae_vector work;
39811 : ae_int_t i;
39812 : ae_int_t j;
39813 : ae_int_t k;
39814 : double v;
39815 : sinteger sinfo;
39816 :
39817 0 : ae_frame_make(_state, &_frame_block);
39818 0 : memset(&work, 0, sizeof(work));
39819 0 : memset(&sinfo, 0, sizeof(sinfo));
39820 0 : *info = 0;
39821 0 : _matinvreport_clear(rep);
39822 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
39823 0 : _sinteger_init(&sinfo, _state, ae_true);
39824 :
39825 0 : ae_assert(n>0, "RMatrixLUInverse: N<=0!", _state);
39826 0 : ae_assert(a->cols>=n, "RMatrixLUInverse: cols(A)<N!", _state);
39827 0 : ae_assert(a->rows>=n, "RMatrixLUInverse: rows(A)<N!", _state);
39828 0 : ae_assert(pivots->cnt>=n, "RMatrixLUInverse: len(Pivots)<N!", _state);
39829 0 : ae_assert(apservisfinitematrix(a, n, n, _state), "RMatrixLUInverse: A contains infinite or NaN values!", _state);
39830 0 : *info = 1;
39831 0 : for(i=0; i<=n-1; i++)
39832 : {
39833 0 : if( pivots->ptr.p_int[i]>n-1||pivots->ptr.p_int[i]<i )
39834 : {
39835 0 : *info = -1;
39836 : }
39837 : }
39838 0 : ae_assert(*info>0, "RMatrixLUInverse: incorrect Pivots array!", _state);
39839 :
39840 : /*
39841 : * calculate condition numbers
39842 : */
39843 0 : rep->r1 = rmatrixlurcond1(a, n, _state);
39844 0 : rep->rinf = rmatrixlurcondinf(a, n, _state);
39845 0 : if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) )
39846 : {
39847 0 : for(i=0; i<=n-1; i++)
39848 : {
39849 0 : for(j=0; j<=n-1; j++)
39850 : {
39851 0 : a->ptr.pp_double[i][j] = (double)(0);
39852 : }
39853 : }
39854 0 : rep->r1 = (double)(0);
39855 0 : rep->rinf = (double)(0);
39856 0 : *info = -3;
39857 0 : ae_frame_leave(_state);
39858 0 : return;
39859 : }
39860 :
39861 : /*
39862 : * Call cache-oblivious code
39863 : */
39864 0 : ae_vector_set_length(&work, n, _state);
39865 0 : sinfo.val = 1;
39866 0 : matinv_rmatrixluinverserec(a, 0, n, &work, &sinfo, rep, _state);
39867 0 : *info = sinfo.val;
39868 :
39869 : /*
39870 : * apply permutations
39871 : */
39872 0 : for(i=0; i<=n-1; i++)
39873 : {
39874 0 : for(j=n-2; j>=0; j--)
39875 : {
39876 0 : k = pivots->ptr.p_int[j];
39877 0 : v = a->ptr.pp_double[i][j];
39878 0 : a->ptr.pp_double[i][j] = a->ptr.pp_double[i][k];
39879 0 : a->ptr.pp_double[i][k] = v;
39880 : }
39881 : }
39882 0 : ae_frame_leave(_state);
39883 : }
39884 :
39885 :
39886 : /*************************************************************************
39887 : Inversion of a general matrix.
39888 :
39889 : ! COMMERCIAL EDITION OF ALGLIB:
39890 : !
39891 : ! Commercial Edition of ALGLIB includes following important improvements
39892 : ! of this function:
39893 : ! * high-performance native backend with same C# interface (C# version)
39894 : ! * multithreading support (C++ and C# versions)
39895 : ! * hardware vendor (Intel) implementations of linear algebra primitives
39896 : ! (C++ and C# versions, x86/x64 platform)
39897 : !
39898 : ! We recommend you to read 'Working with commercial version' section of
39899 : ! ALGLIB Reference Manual in order to find out how to use performance-
39900 : ! related features provided by commercial edition of ALGLIB.
39901 :
39902 : Input parameters:
39903 : A - matrix.
39904 : N - size of matrix A (optional) :
39905 : * if given, only principal NxN submatrix is processed and
39906 : overwritten. other elements are unchanged.
39907 : * if not given, size is automatically determined from
39908 : matrix size (A must be square matrix)
39909 :
39910 : Output parameters:
39911 : Info - return code, same as in RMatrixLUInverse
39912 : Rep - solver report, same as in RMatrixLUInverse
39913 : A - inverse of matrix A, same as in RMatrixLUInverse
39914 :
39915 : Result:
39916 : True, if the matrix is not singular.
39917 : False, if the matrix is singular.
39918 :
39919 : -- ALGLIB --
39920 : Copyright 2005-2010 by Bochkanov Sergey
39921 : *************************************************************************/
39922 0 : void rmatrixinverse(/* Real */ ae_matrix* a,
39923 : ae_int_t n,
39924 : ae_int_t* info,
39925 : matinvreport* rep,
39926 : ae_state *_state)
39927 : {
39928 : ae_frame _frame_block;
39929 : ae_vector pivots;
39930 :
39931 0 : ae_frame_make(_state, &_frame_block);
39932 0 : memset(&pivots, 0, sizeof(pivots));
39933 0 : *info = 0;
39934 0 : _matinvreport_clear(rep);
39935 0 : ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
39936 :
39937 0 : ae_assert(n>0, "RMatrixInverse: N<=0!", _state);
39938 0 : ae_assert(a->cols>=n, "RMatrixInverse: cols(A)<N!", _state);
39939 0 : ae_assert(a->rows>=n, "RMatrixInverse: rows(A)<N!", _state);
39940 0 : ae_assert(apservisfinitematrix(a, n, n, _state), "RMatrixInverse: A contains infinite or NaN values!", _state);
39941 0 : rmatrixlu(a, n, n, &pivots, _state);
39942 0 : rmatrixluinverse(a, &pivots, n, info, rep, _state);
39943 0 : ae_frame_leave(_state);
39944 0 : }
39945 :
39946 :
39947 : /*************************************************************************
39948 : Inversion of a matrix given by its LU decomposition.
39949 :
39950 : ! COMMERCIAL EDITION OF ALGLIB:
39951 : !
39952 : ! Commercial Edition of ALGLIB includes following important improvements
39953 : ! of this function:
39954 : ! * high-performance native backend with same C# interface (C# version)
39955 : ! * multithreading support (C++ and C# versions)
39956 : ! * hardware vendor (Intel) implementations of linear algebra primitives
39957 : ! (C++ and C# versions, x86/x64 platform)
39958 : !
39959 : ! We recommend you to read 'Working with commercial version' section of
39960 : ! ALGLIB Reference Manual in order to find out how to use performance-
39961 : ! related features provided by commercial edition of ALGLIB.
39962 :
39963 : INPUT PARAMETERS:
39964 : A - LU decomposition of the matrix
39965 : (output of CMatrixLU subroutine).
39966 : Pivots - table of permutations
39967 : (the output of CMatrixLU subroutine).
39968 : N - size of matrix A (optional) :
39969 : * if given, only principal NxN submatrix is processed and
39970 : overwritten. other elements are unchanged.
39971 : * if not given, size is automatically determined from
39972 : matrix size (A must be square matrix)
39973 :
39974 : OUTPUT PARAMETERS:
39975 : Info - return code, same as in RMatrixLUInverse
39976 : Rep - solver report, same as in RMatrixLUInverse
39977 : A - inverse of matrix A, same as in RMatrixLUInverse
39978 :
39979 : -- ALGLIB routine --
39980 : 05.02.2010
39981 : Bochkanov Sergey
39982 : *************************************************************************/
39983 0 : void cmatrixluinverse(/* Complex */ ae_matrix* a,
39984 : /* Integer */ ae_vector* pivots,
39985 : ae_int_t n,
39986 : ae_int_t* info,
39987 : matinvreport* rep,
39988 : ae_state *_state)
39989 : {
39990 : ae_frame _frame_block;
39991 : ae_vector work;
39992 : ae_int_t i;
39993 : ae_int_t j;
39994 : ae_int_t k;
39995 : ae_complex v;
39996 : sinteger sinfo;
39997 :
39998 0 : ae_frame_make(_state, &_frame_block);
39999 0 : memset(&work, 0, sizeof(work));
40000 0 : memset(&sinfo, 0, sizeof(sinfo));
40001 0 : *info = 0;
40002 0 : _matinvreport_clear(rep);
40003 0 : ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true);
40004 0 : _sinteger_init(&sinfo, _state, ae_true);
40005 :
40006 0 : ae_assert(n>0, "CMatrixLUInverse: N<=0!", _state);
40007 0 : ae_assert(a->cols>=n, "CMatrixLUInverse: cols(A)<N!", _state);
40008 0 : ae_assert(a->rows>=n, "CMatrixLUInverse: rows(A)<N!", _state);
40009 0 : ae_assert(pivots->cnt>=n, "CMatrixLUInverse: len(Pivots)<N!", _state);
40010 0 : ae_assert(apservisfinitecmatrix(a, n, n, _state), "CMatrixLUInverse: A contains infinite or NaN values!", _state);
40011 0 : *info = 1;
40012 0 : for(i=0; i<=n-1; i++)
40013 : {
40014 0 : if( pivots->ptr.p_int[i]>n-1||pivots->ptr.p_int[i]<i )
40015 : {
40016 0 : *info = -1;
40017 : }
40018 : }
40019 0 : ae_assert(*info>0, "CMatrixLUInverse: incorrect Pivots array!", _state);
40020 :
40021 : /*
40022 : * calculate condition numbers
40023 : */
40024 0 : rep->r1 = cmatrixlurcond1(a, n, _state);
40025 0 : rep->rinf = cmatrixlurcondinf(a, n, _state);
40026 0 : if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) )
40027 : {
40028 0 : for(i=0; i<=n-1; i++)
40029 : {
40030 0 : for(j=0; j<=n-1; j++)
40031 : {
40032 0 : a->ptr.pp_complex[i][j] = ae_complex_from_i(0);
40033 : }
40034 : }
40035 0 : rep->r1 = (double)(0);
40036 0 : rep->rinf = (double)(0);
40037 0 : *info = -3;
40038 0 : ae_frame_leave(_state);
40039 0 : return;
40040 : }
40041 :
40042 : /*
40043 : * Call cache-oblivious code
40044 : */
40045 0 : ae_vector_set_length(&work, n, _state);
40046 0 : sinfo.val = 1;
40047 0 : matinv_cmatrixluinverserec(a, 0, n, &work, &sinfo, rep, _state);
40048 0 : *info = sinfo.val;
40049 :
40050 : /*
40051 : * apply permutations
40052 : */
40053 0 : for(i=0; i<=n-1; i++)
40054 : {
40055 0 : for(j=n-2; j>=0; j--)
40056 : {
40057 0 : k = pivots->ptr.p_int[j];
40058 0 : v = a->ptr.pp_complex[i][j];
40059 0 : a->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][k];
40060 0 : a->ptr.pp_complex[i][k] = v;
40061 : }
40062 : }
40063 0 : ae_frame_leave(_state);
40064 : }
40065 :
40066 :
40067 : /*************************************************************************
40068 : Inversion of a general matrix.
40069 :
40070 : ! COMMERCIAL EDITION OF ALGLIB:
40071 : !
40072 : ! Commercial Edition of ALGLIB includes following important improvements
40073 : ! of this function:
40074 : ! * high-performance native backend with same C# interface (C# version)
40075 : ! * multithreading support (C++ and C# versions)
40076 : ! * hardware vendor (Intel) implementations of linear algebra primitives
40077 : ! (C++ and C# versions, x86/x64 platform)
40078 : !
40079 : ! We recommend you to read 'Working with commercial version' section of
40080 : ! ALGLIB Reference Manual in order to find out how to use performance-
40081 : ! related features provided by commercial edition of ALGLIB.
40082 :
40083 : Input parameters:
40084 : A - matrix
40085 : N - size of matrix A (optional) :
40086 : * if given, only principal NxN submatrix is processed and
40087 : overwritten. other elements are unchanged.
40088 : * if not given, size is automatically determined from
40089 : matrix size (A must be square matrix)
40090 :
40091 : Output parameters:
40092 : Info - return code, same as in RMatrixLUInverse
40093 : Rep - solver report, same as in RMatrixLUInverse
40094 : A - inverse of matrix A, same as in RMatrixLUInverse
40095 :
40096 : -- ALGLIB --
40097 : Copyright 2005 by Bochkanov Sergey
40098 : *************************************************************************/
40099 0 : void cmatrixinverse(/* Complex */ ae_matrix* a,
40100 : ae_int_t n,
40101 : ae_int_t* info,
40102 : matinvreport* rep,
40103 : ae_state *_state)
40104 : {
40105 : ae_frame _frame_block;
40106 : ae_vector pivots;
40107 :
40108 0 : ae_frame_make(_state, &_frame_block);
40109 0 : memset(&pivots, 0, sizeof(pivots));
40110 0 : *info = 0;
40111 0 : _matinvreport_clear(rep);
40112 0 : ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
40113 :
40114 0 : ae_assert(n>0, "CRMatrixInverse: N<=0!", _state);
40115 0 : ae_assert(a->cols>=n, "CRMatrixInverse: cols(A)<N!", _state);
40116 0 : ae_assert(a->rows>=n, "CRMatrixInverse: rows(A)<N!", _state);
40117 0 : ae_assert(apservisfinitecmatrix(a, n, n, _state), "CMatrixInverse: A contains infinite or NaN values!", _state);
40118 0 : cmatrixlu(a, n, n, &pivots, _state);
40119 0 : cmatrixluinverse(a, &pivots, n, info, rep, _state);
40120 0 : ae_frame_leave(_state);
40121 0 : }
40122 :
40123 :
40124 : /*************************************************************************
40125 : Inversion of a symmetric positive definite matrix which is given
40126 : by Cholesky decomposition.
40127 :
40128 : ! COMMERCIAL EDITION OF ALGLIB:
40129 : !
40130 : ! Commercial Edition of ALGLIB includes following important improvements
40131 : ! of this function:
40132 : ! * high-performance native backend with same C# interface (C# version)
40133 : ! * multithreading support (C++ and C# versions)
40134 : ! * hardware vendor (Intel) implementations of linear algebra primitives
40135 : ! (C++ and C# versions, x86/x64 platform)
40136 : !
40137 : ! We recommend you to read 'Working with commercial version' section of
40138 : ! ALGLIB Reference Manual in order to find out how to use performance-
40139 : ! related features provided by commercial edition of ALGLIB.
40140 :
40141 : Input parameters:
40142 : A - Cholesky decomposition of the matrix to be inverted:
40143 : A=U'*U or A = L*L'.
40144 : Output of SPDMatrixCholesky subroutine.
40145 : N - size of matrix A (optional) :
40146 : * if given, only principal NxN submatrix is processed and
40147 : overwritten. other elements are unchanged.
40148 : * if not given, size is automatically determined from
40149 : matrix size (A must be square matrix)
40150 : IsUpper - storage type (optional):
40151 : * if True, symmetric matrix A is given by its upper
40152 : triangle, and the lower triangle isn't used/changed by
40153 : function
40154 : * if False, symmetric matrix A is given by its lower
40155 : triangle, and the upper triangle isn't used/changed by
40156 : function
40157 : * if not given, lower half is used.
40158 :
40159 : Output parameters:
40160 : Info - return code, same as in RMatrixLUInverse
40161 : Rep - solver report, same as in RMatrixLUInverse
40162 : A - inverse of matrix A, same as in RMatrixLUInverse
40163 :
40164 : -- ALGLIB routine --
40165 : 10.02.2010
40166 : Bochkanov Sergey
40167 : *************************************************************************/
40168 0 : void spdmatrixcholeskyinverse(/* Real */ ae_matrix* a,
40169 : ae_int_t n,
40170 : ae_bool isupper,
40171 : ae_int_t* info,
40172 : matinvreport* rep,
40173 : ae_state *_state)
40174 : {
40175 : ae_frame _frame_block;
40176 : ae_int_t i;
40177 : ae_int_t j;
40178 : ae_vector tmp;
40179 : matinvreport rep2;
40180 : ae_bool f;
40181 :
40182 0 : ae_frame_make(_state, &_frame_block);
40183 0 : memset(&tmp, 0, sizeof(tmp));
40184 0 : memset(&rep2, 0, sizeof(rep2));
40185 0 : *info = 0;
40186 0 : _matinvreport_clear(rep);
40187 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
40188 0 : _matinvreport_init(&rep2, _state, ae_true);
40189 :
40190 0 : ae_assert(n>0, "SPDMatrixCholeskyInverse: N<=0!", _state);
40191 0 : ae_assert(a->cols>=n, "SPDMatrixCholeskyInverse: cols(A)<N!", _state);
40192 0 : ae_assert(a->rows>=n, "SPDMatrixCholeskyInverse: rows(A)<N!", _state);
40193 0 : *info = 1;
40194 0 : f = ae_true;
40195 0 : for(i=0; i<=n-1; i++)
40196 : {
40197 0 : f = f&&ae_isfinite(a->ptr.pp_double[i][i], _state);
40198 : }
40199 0 : ae_assert(f, "SPDMatrixCholeskyInverse: A contains infinite or NaN values!", _state);
40200 :
40201 : /*
40202 : * calculate condition numbers
40203 : */
40204 0 : rep->r1 = spdmatrixcholeskyrcond(a, n, isupper, _state);
40205 0 : rep->rinf = rep->r1;
40206 0 : if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) )
40207 : {
40208 0 : if( isupper )
40209 : {
40210 0 : for(i=0; i<=n-1; i++)
40211 : {
40212 0 : for(j=i; j<=n-1; j++)
40213 : {
40214 0 : a->ptr.pp_double[i][j] = (double)(0);
40215 : }
40216 : }
40217 : }
40218 : else
40219 : {
40220 0 : for(i=0; i<=n-1; i++)
40221 : {
40222 0 : for(j=0; j<=i; j++)
40223 : {
40224 0 : a->ptr.pp_double[i][j] = (double)(0);
40225 : }
40226 : }
40227 : }
40228 0 : rep->r1 = (double)(0);
40229 0 : rep->rinf = (double)(0);
40230 0 : *info = -3;
40231 0 : ae_frame_leave(_state);
40232 0 : return;
40233 : }
40234 :
40235 : /*
40236 : * Inverse
40237 : */
40238 0 : ae_vector_set_length(&tmp, n, _state);
40239 0 : spdmatrixcholeskyinverserec(a, 0, n, isupper, &tmp, _state);
40240 0 : ae_frame_leave(_state);
40241 : }
40242 :
40243 :
40244 : /*************************************************************************
40245 : Inversion of a symmetric positive definite matrix.
40246 :
40247 : Given an upper or lower triangle of a symmetric positive definite matrix,
40248 : the algorithm generates matrix A^-1 and saves the upper or lower triangle
40249 : depending on the input.
40250 :
40251 : ! COMMERCIAL EDITION OF ALGLIB:
40252 : !
40253 : ! Commercial Edition of ALGLIB includes following important improvements
40254 : ! of this function:
40255 : ! * high-performance native backend with same C# interface (C# version)
40256 : ! * multithreading support (C++ and C# versions)
40257 : ! * hardware vendor (Intel) implementations of linear algebra primitives
40258 : ! (C++ and C# versions, x86/x64 platform)
40259 : !
40260 : ! We recommend you to read 'Working with commercial version' section of
40261 : ! ALGLIB Reference Manual in order to find out how to use performance-
40262 : ! related features provided by commercial edition of ALGLIB.
40263 :
40264 : Input parameters:
40265 : A - matrix to be inverted (upper or lower triangle).
40266 : Array with elements [0..N-1,0..N-1].
40267 : N - size of matrix A (optional) :
40268 : * if given, only principal NxN submatrix is processed and
40269 : overwritten. other elements are unchanged.
40270 : * if not given, size is automatically determined from
40271 : matrix size (A must be square matrix)
40272 : IsUpper - storage type (optional):
40273 : * if True, symmetric matrix A is given by its upper
40274 : triangle, and the lower triangle isn't used/changed by
40275 : function
40276 : * if False, symmetric matrix A is given by its lower
40277 : triangle, and the upper triangle isn't used/changed by
40278 : function
40279 : * if not given, both lower and upper triangles must be
40280 : filled.
40281 :
40282 : Output parameters:
40283 : Info - return code, same as in RMatrixLUInverse
40284 : Rep - solver report, same as in RMatrixLUInverse
40285 : A - inverse of matrix A, same as in RMatrixLUInverse
40286 :
40287 : -- ALGLIB routine --
40288 : 10.02.2010
40289 : Bochkanov Sergey
40290 : *************************************************************************/
40291 0 : void spdmatrixinverse(/* Real */ ae_matrix* a,
40292 : ae_int_t n,
40293 : ae_bool isupper,
40294 : ae_int_t* info,
40295 : matinvreport* rep,
40296 : ae_state *_state)
40297 : {
40298 :
40299 0 : *info = 0;
40300 0 : _matinvreport_clear(rep);
40301 :
40302 0 : ae_assert(n>0, "SPDMatrixInverse: N<=0!", _state);
40303 0 : ae_assert(a->cols>=n, "SPDMatrixInverse: cols(A)<N!", _state);
40304 0 : ae_assert(a->rows>=n, "SPDMatrixInverse: rows(A)<N!", _state);
40305 0 : ae_assert(isfinitertrmatrix(a, n, isupper, _state), "SPDMatrixInverse: A contains infinite or NaN values!", _state);
40306 0 : *info = 1;
40307 0 : if( spdmatrixcholesky(a, n, isupper, _state) )
40308 : {
40309 0 : spdmatrixcholeskyinverse(a, n, isupper, info, rep, _state);
40310 : }
40311 : else
40312 : {
40313 0 : *info = -3;
40314 : }
40315 0 : }
40316 :
40317 :
40318 : /*************************************************************************
40319 : Inversion of a Hermitian positive definite matrix which is given
40320 : by Cholesky decomposition.
40321 :
40322 : ! COMMERCIAL EDITION OF ALGLIB:
40323 : !
40324 : ! Commercial Edition of ALGLIB includes following important improvements
40325 : ! of this function:
40326 : ! * high-performance native backend with same C# interface (C# version)
40327 : ! * multithreading support (C++ and C# versions)
40328 : ! * hardware vendor (Intel) implementations of linear algebra primitives
40329 : ! (C++ and C# versions, x86/x64 platform)
40330 : !
40331 : ! We recommend you to read 'Working with commercial version' section of
40332 : ! ALGLIB Reference Manual in order to find out how to use performance-
40333 : ! related features provided by commercial edition of ALGLIB.
40334 :
40335 : Input parameters:
40336 : A - Cholesky decomposition of the matrix to be inverted:
40337 : A=U'*U or A = L*L'.
40338 : Output of HPDMatrixCholesky subroutine.
40339 : N - size of matrix A (optional) :
40340 : * if given, only principal NxN submatrix is processed and
40341 : overwritten. other elements are unchanged.
40342 : * if not given, size is automatically determined from
40343 : matrix size (A must be square matrix)
40344 : IsUpper - storage type (optional):
40345 : * if True, symmetric matrix A is given by its upper
40346 : triangle, and the lower triangle isn't used/changed by
40347 : function
40348 : * if False, symmetric matrix A is given by its lower
40349 : triangle, and the upper triangle isn't used/changed by
40350 : function
40351 : * if not given, lower half is used.
40352 :
40353 : Output parameters:
40354 : Info - return code, same as in RMatrixLUInverse
40355 : Rep - solver report, same as in RMatrixLUInverse
40356 : A - inverse of matrix A, same as in RMatrixLUInverse
40357 :
40358 : -- ALGLIB routine --
40359 : 10.02.2010
40360 : Bochkanov Sergey
40361 : *************************************************************************/
40362 0 : void hpdmatrixcholeskyinverse(/* Complex */ ae_matrix* a,
40363 : ae_int_t n,
40364 : ae_bool isupper,
40365 : ae_int_t* info,
40366 : matinvreport* rep,
40367 : ae_state *_state)
40368 : {
40369 : ae_frame _frame_block;
40370 : ae_int_t i;
40371 : ae_int_t j;
40372 : matinvreport rep2;
40373 : ae_vector tmp;
40374 : ae_bool f;
40375 :
40376 0 : ae_frame_make(_state, &_frame_block);
40377 0 : memset(&rep2, 0, sizeof(rep2));
40378 0 : memset(&tmp, 0, sizeof(tmp));
40379 0 : *info = 0;
40380 0 : _matinvreport_clear(rep);
40381 0 : _matinvreport_init(&rep2, _state, ae_true);
40382 0 : ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true);
40383 :
40384 0 : ae_assert(n>0, "HPDMatrixCholeskyInverse: N<=0!", _state);
40385 0 : ae_assert(a->cols>=n, "HPDMatrixCholeskyInverse: cols(A)<N!", _state);
40386 0 : ae_assert(a->rows>=n, "HPDMatrixCholeskyInverse: rows(A)<N!", _state);
40387 0 : f = ae_true;
40388 0 : for(i=0; i<=n-1; i++)
40389 : {
40390 0 : f = (f&&ae_isfinite(a->ptr.pp_complex[i][i].x, _state))&&ae_isfinite(a->ptr.pp_complex[i][i].y, _state);
40391 : }
40392 0 : ae_assert(f, "HPDMatrixCholeskyInverse: A contains infinite or NaN values!", _state);
40393 0 : *info = 1;
40394 :
40395 : /*
40396 : * calculate condition numbers
40397 : */
40398 0 : rep->r1 = hpdmatrixcholeskyrcond(a, n, isupper, _state);
40399 0 : rep->rinf = rep->r1;
40400 0 : if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) )
40401 : {
40402 0 : if( isupper )
40403 : {
40404 0 : for(i=0; i<=n-1; i++)
40405 : {
40406 0 : for(j=i; j<=n-1; j++)
40407 : {
40408 0 : a->ptr.pp_complex[i][j] = ae_complex_from_i(0);
40409 : }
40410 : }
40411 : }
40412 : else
40413 : {
40414 0 : for(i=0; i<=n-1; i++)
40415 : {
40416 0 : for(j=0; j<=i; j++)
40417 : {
40418 0 : a->ptr.pp_complex[i][j] = ae_complex_from_i(0);
40419 : }
40420 : }
40421 : }
40422 0 : rep->r1 = (double)(0);
40423 0 : rep->rinf = (double)(0);
40424 0 : *info = -3;
40425 0 : ae_frame_leave(_state);
40426 0 : return;
40427 : }
40428 :
40429 : /*
40430 : * Inverse
40431 : */
40432 0 : ae_vector_set_length(&tmp, n, _state);
40433 0 : matinv_hpdmatrixcholeskyinverserec(a, 0, n, isupper, &tmp, _state);
40434 0 : ae_frame_leave(_state);
40435 : }
40436 :
40437 :
40438 : /*************************************************************************
40439 : Inversion of a Hermitian positive definite matrix.
40440 :
40441 : Given an upper or lower triangle of a Hermitian positive definite matrix,
40442 : the algorithm generates matrix A^-1 and saves the upper or lower triangle
40443 : depending on the input.
40444 :
40445 : ! COMMERCIAL EDITION OF ALGLIB:
40446 : !
40447 : ! Commercial Edition of ALGLIB includes following important improvements
40448 : ! of this function:
40449 : ! * high-performance native backend with same C# interface (C# version)
40450 : ! * multithreading support (C++ and C# versions)
40451 : ! * hardware vendor (Intel) implementations of linear algebra primitives
40452 : ! (C++ and C# versions, x86/x64 platform)
40453 : !
40454 : ! We recommend you to read 'Working with commercial version' section of
40455 : ! ALGLIB Reference Manual in order to find out how to use performance-
40456 : ! related features provided by commercial edition of ALGLIB.
40457 :
40458 : Input parameters:
40459 : A - matrix to be inverted (upper or lower triangle).
40460 : Array with elements [0..N-1,0..N-1].
40461 : N - size of matrix A (optional) :
40462 : * if given, only principal NxN submatrix is processed and
40463 : overwritten. other elements are unchanged.
40464 : * if not given, size is automatically determined from
40465 : matrix size (A must be square matrix)
40466 : IsUpper - storage type (optional):
40467 : * if True, symmetric matrix A is given by its upper
40468 : triangle, and the lower triangle isn't used/changed by
40469 : function
40470 : * if False, symmetric matrix A is given by its lower
40471 : triangle, and the upper triangle isn't used/changed by
40472 : function
40473 : * if not given, both lower and upper triangles must be
40474 : filled.
40475 :
40476 : Output parameters:
40477 : Info - return code, same as in RMatrixLUInverse
40478 : Rep - solver report, same as in RMatrixLUInverse
40479 : A - inverse of matrix A, same as in RMatrixLUInverse
40480 :
40481 : -- ALGLIB routine --
40482 : 10.02.2010
40483 : Bochkanov Sergey
40484 : *************************************************************************/
40485 0 : void hpdmatrixinverse(/* Complex */ ae_matrix* a,
40486 : ae_int_t n,
40487 : ae_bool isupper,
40488 : ae_int_t* info,
40489 : matinvreport* rep,
40490 : ae_state *_state)
40491 : {
40492 :
40493 0 : *info = 0;
40494 0 : _matinvreport_clear(rep);
40495 :
40496 0 : ae_assert(n>0, "HPDMatrixInverse: N<=0!", _state);
40497 0 : ae_assert(a->cols>=n, "HPDMatrixInverse: cols(A)<N!", _state);
40498 0 : ae_assert(a->rows>=n, "HPDMatrixInverse: rows(A)<N!", _state);
40499 0 : ae_assert(apservisfinitectrmatrix(a, n, isupper, _state), "HPDMatrixInverse: A contains infinite or NaN values!", _state);
40500 0 : *info = 1;
40501 0 : if( hpdmatrixcholesky(a, n, isupper, _state) )
40502 : {
40503 0 : hpdmatrixcholeskyinverse(a, n, isupper, info, rep, _state);
40504 : }
40505 : else
40506 : {
40507 0 : *info = -3;
40508 : }
40509 0 : }
40510 :
40511 :
40512 : /*************************************************************************
40513 : Triangular matrix inverse (real)
40514 :
40515 : The subroutine inverts the following types of matrices:
40516 : * upper triangular
40517 : * upper triangular with unit diagonal
40518 : * lower triangular
40519 : * lower triangular with unit diagonal
40520 :
40521 : In case of an upper (lower) triangular matrix, the inverse matrix will
40522 : also be upper (lower) triangular, and after the end of the algorithm, the
40523 : inverse matrix replaces the source matrix. The elements below (above) the
40524 : main diagonal are not changed by the algorithm.
40525 :
40526 : If the matrix has a unit diagonal, the inverse matrix also has a unit
40527 : diagonal, and the diagonal elements are not passed to the algorithm.
40528 :
40529 : ! COMMERCIAL EDITION OF ALGLIB:
40530 : !
40531 : ! Commercial Edition of ALGLIB includes following important improvements
40532 : ! of this function:
40533 : ! * high-performance native backend with same C# interface (C# version)
40534 : ! * multithreading support (C++ and C# versions)
40535 : ! * hardware vendor (Intel) implementations of linear algebra primitives
40536 : ! (C++ and C# versions, x86/x64 platform)
40537 : !
40538 : ! We recommend you to read 'Working with commercial version' section of
40539 : ! ALGLIB Reference Manual in order to find out how to use performance-
40540 : ! related features provided by commercial edition of ALGLIB.
40541 :
40542 : Input parameters:
40543 : A - matrix, array[0..N-1, 0..N-1].
40544 : N - size of matrix A (optional) :
40545 : * if given, only principal NxN submatrix is processed and
40546 : overwritten. other elements are unchanged.
40547 : * if not given, size is automatically determined from
40548 : matrix size (A must be square matrix)
40549 : IsUpper - True, if the matrix is upper triangular.
40550 : IsUnit - diagonal type (optional):
40551 : * if True, matrix has unit diagonal (a[i,i] are NOT used)
40552 : * if False, matrix diagonal is arbitrary
40553 : * if not given, False is assumed
40554 :
40555 : Output parameters:
40556 : Info - same as for RMatrixLUInverse
40557 : Rep - same as for RMatrixLUInverse
40558 : A - same as for RMatrixLUInverse.
40559 :
40560 : -- ALGLIB --
40561 : Copyright 05.02.2010 by Bochkanov Sergey
40562 : *************************************************************************/
40563 0 : void rmatrixtrinverse(/* Real */ ae_matrix* a,
40564 : ae_int_t n,
40565 : ae_bool isupper,
40566 : ae_bool isunit,
40567 : ae_int_t* info,
40568 : matinvreport* rep,
40569 : ae_state *_state)
40570 : {
40571 : ae_frame _frame_block;
40572 : ae_int_t i;
40573 : ae_int_t j;
40574 : ae_vector tmp;
40575 : sinteger sinfo;
40576 :
40577 0 : ae_frame_make(_state, &_frame_block);
40578 0 : memset(&tmp, 0, sizeof(tmp));
40579 0 : memset(&sinfo, 0, sizeof(sinfo));
40580 0 : *info = 0;
40581 0 : _matinvreport_clear(rep);
40582 0 : ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
40583 0 : _sinteger_init(&sinfo, _state, ae_true);
40584 :
40585 0 : ae_assert(n>0, "RMatrixTRInverse: N<=0!", _state);
40586 0 : ae_assert(a->cols>=n, "RMatrixTRInverse: cols(A)<N!", _state);
40587 0 : ae_assert(a->rows>=n, "RMatrixTRInverse: rows(A)<N!", _state);
40588 0 : ae_assert(isfinitertrmatrix(a, n, isupper, _state), "RMatrixTRInverse: A contains infinite or NaN values!", _state);
40589 :
40590 : /*
40591 : * calculate condition numbers
40592 : */
40593 0 : rep->r1 = rmatrixtrrcond1(a, n, isupper, isunit, _state);
40594 0 : rep->rinf = rmatrixtrrcondinf(a, n, isupper, isunit, _state);
40595 0 : if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) )
40596 : {
40597 0 : for(i=0; i<=n-1; i++)
40598 : {
40599 0 : for(j=0; j<=n-1; j++)
40600 : {
40601 0 : a->ptr.pp_double[i][j] = (double)(0);
40602 : }
40603 : }
40604 0 : rep->r1 = (double)(0);
40605 0 : rep->rinf = (double)(0);
40606 0 : *info = -3;
40607 0 : ae_frame_leave(_state);
40608 0 : return;
40609 : }
40610 :
40611 : /*
40612 : * Invert
40613 : */
40614 0 : ae_vector_set_length(&tmp, n, _state);
40615 0 : sinfo.val = 1;
40616 0 : matinv_rmatrixtrinverserec(a, 0, n, isupper, isunit, &tmp, &sinfo, _state);
40617 0 : *info = sinfo.val;
40618 0 : ae_frame_leave(_state);
40619 : }
40620 :
40621 :
40622 : /*************************************************************************
40623 : Triangular matrix inverse (complex)
40624 :
40625 : The subroutine inverts the following types of matrices:
40626 : * upper triangular
40627 : * upper triangular with unit diagonal
40628 : * lower triangular
40629 : * lower triangular with unit diagonal
40630 :
40631 : In case of an upper (lower) triangular matrix, the inverse matrix will
40632 : also be upper (lower) triangular, and after the end of the algorithm, the
40633 : inverse matrix replaces the source matrix. The elements below (above) the
40634 : main diagonal are not changed by the algorithm.
40635 :
40636 : If the matrix has a unit diagonal, the inverse matrix also has a unit
40637 : diagonal, and the diagonal elements are not passed to the algorithm.
40638 :
40639 : ! COMMERCIAL EDITION OF ALGLIB:
40640 : !
40641 : ! Commercial Edition of ALGLIB includes following important improvements
40642 : ! of this function:
40643 : ! * high-performance native backend with same C# interface (C# version)
40644 : ! * multithreading support (C++ and C# versions)
40645 : ! * hardware vendor (Intel) implementations of linear algebra primitives
40646 : ! (C++ and C# versions, x86/x64 platform)
40647 : !
40648 : ! We recommend you to read 'Working with commercial version' section of
40649 : ! ALGLIB Reference Manual in order to find out how to use performance-
40650 : ! related features provided by commercial edition of ALGLIB.
40651 :
40652 : Input parameters:
40653 : A - matrix, array[0..N-1, 0..N-1].
40654 : N - size of matrix A (optional) :
40655 : * if given, only principal NxN submatrix is processed and
40656 : overwritten. other elements are unchanged.
40657 : * if not given, size is automatically determined from
40658 : matrix size (A must be square matrix)
40659 : IsUpper - True, if the matrix is upper triangular.
40660 : IsUnit - diagonal type (optional):
40661 : * if True, matrix has unit diagonal (a[i,i] are NOT used)
40662 : * if False, matrix diagonal is arbitrary
40663 : * if not given, False is assumed
40664 :
40665 : Output parameters:
40666 : Info - same as for RMatrixLUInverse
40667 : Rep - same as for RMatrixLUInverse
40668 : A - same as for RMatrixLUInverse.
40669 :
40670 : -- ALGLIB --
40671 : Copyright 05.02.2010 by Bochkanov Sergey
40672 : *************************************************************************/
40673 0 : void cmatrixtrinverse(/* Complex */ ae_matrix* a,
40674 : ae_int_t n,
40675 : ae_bool isupper,
40676 : ae_bool isunit,
40677 : ae_int_t* info,
40678 : matinvreport* rep,
40679 : ae_state *_state)
40680 : {
40681 : ae_frame _frame_block;
40682 : ae_int_t i;
40683 : ae_int_t j;
40684 : ae_vector tmp;
40685 : sinteger sinfo;
40686 :
40687 0 : ae_frame_make(_state, &_frame_block);
40688 0 : memset(&tmp, 0, sizeof(tmp));
40689 0 : memset(&sinfo, 0, sizeof(sinfo));
40690 0 : *info = 0;
40691 0 : _matinvreport_clear(rep);
40692 0 : ae_vector_init(&tmp, 0, DT_COMPLEX, _state, ae_true);
40693 0 : _sinteger_init(&sinfo, _state, ae_true);
40694 :
40695 0 : ae_assert(n>0, "CMatrixTRInverse: N<=0!", _state);
40696 0 : ae_assert(a->cols>=n, "CMatrixTRInverse: cols(A)<N!", _state);
40697 0 : ae_assert(a->rows>=n, "CMatrixTRInverse: rows(A)<N!", _state);
40698 0 : ae_assert(apservisfinitectrmatrix(a, n, isupper, _state), "CMatrixTRInverse: A contains infinite or NaN values!", _state);
40699 :
40700 : /*
40701 : * calculate condition numbers
40702 : */
40703 0 : rep->r1 = cmatrixtrrcond1(a, n, isupper, isunit, _state);
40704 0 : rep->rinf = cmatrixtrrcondinf(a, n, isupper, isunit, _state);
40705 0 : if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) )
40706 : {
40707 0 : for(i=0; i<=n-1; i++)
40708 : {
40709 0 : for(j=0; j<=n-1; j++)
40710 : {
40711 0 : a->ptr.pp_complex[i][j] = ae_complex_from_i(0);
40712 : }
40713 : }
40714 0 : rep->r1 = (double)(0);
40715 0 : rep->rinf = (double)(0);
40716 0 : *info = -3;
40717 0 : ae_frame_leave(_state);
40718 0 : return;
40719 : }
40720 :
40721 : /*
40722 : * Invert
40723 : */
40724 0 : ae_vector_set_length(&tmp, n, _state);
40725 0 : sinfo.val = 1;
40726 0 : matinv_cmatrixtrinverserec(a, 0, n, isupper, isunit, &tmp, &sinfo, _state);
40727 0 : *info = sinfo.val;
40728 0 : ae_frame_leave(_state);
40729 : }
40730 :
40731 :
40732 : /*************************************************************************
40733 : Recursive subroutine for SPD inversion.
40734 :
40735 : NOTE: this function expects that matris is strictly positive-definite.
40736 :
40737 : -- ALGLIB routine --
40738 : 10.02.2010
40739 : Bochkanov Sergey
40740 : *************************************************************************/
40741 0 : void spdmatrixcholeskyinverserec(/* Real */ ae_matrix* a,
40742 : ae_int_t offs,
40743 : ae_int_t n,
40744 : ae_bool isupper,
40745 : /* Real */ ae_vector* tmp,
40746 : ae_state *_state)
40747 : {
40748 : ae_frame _frame_block;
40749 : ae_int_t i;
40750 : ae_int_t j;
40751 : double v;
40752 : ae_int_t n1;
40753 : ae_int_t n2;
40754 : sinteger sinfo2;
40755 : ae_int_t tsa;
40756 : ae_int_t tsb;
40757 : ae_int_t tscur;
40758 :
40759 0 : ae_frame_make(_state, &_frame_block);
40760 0 : memset(&sinfo2, 0, sizeof(sinfo2));
40761 0 : _sinteger_init(&sinfo2, _state, ae_true);
40762 :
40763 0 : if( n<1 )
40764 : {
40765 0 : ae_frame_leave(_state);
40766 0 : return;
40767 : }
40768 0 : tsa = matrixtilesizea(_state);
40769 0 : tsb = matrixtilesizeb(_state);
40770 0 : tscur = tsb;
40771 0 : if( n<=tsb )
40772 : {
40773 0 : tscur = tsa;
40774 : }
40775 :
40776 : /*
40777 : * Base case
40778 : */
40779 0 : if( n<=tsa )
40780 : {
40781 0 : sinfo2.val = 1;
40782 0 : matinv_rmatrixtrinverserec(a, offs, n, isupper, ae_false, tmp, &sinfo2, _state);
40783 0 : ae_assert(sinfo2.val>0, "SPDMatrixCholeskyInverseRec: integrity check failed", _state);
40784 0 : if( isupper )
40785 : {
40786 :
40787 : /*
40788 : * Compute the product U * U'.
40789 : * NOTE: we never assume that diagonal of U is real
40790 : */
40791 0 : for(i=0; i<=n-1; i++)
40792 : {
40793 0 : if( i==0 )
40794 : {
40795 :
40796 : /*
40797 : * 1x1 matrix
40798 : */
40799 0 : a->ptr.pp_double[offs+i][offs+i] = ae_sqr(a->ptr.pp_double[offs+i][offs+i], _state);
40800 : }
40801 : else
40802 : {
40803 :
40804 : /*
40805 : * (I+1)x(I+1) matrix,
40806 : *
40807 : * ( A11 A12 ) ( A11^H ) ( A11*A11^H+A12*A12^H A12*A22^H )
40808 : * ( ) * ( ) = ( )
40809 : * ( A22 ) ( A12^H A22^H ) ( A22*A12^H A22*A22^H )
40810 : *
40811 : * A11 is IxI, A22 is 1x1.
40812 : */
40813 0 : ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs][offs+i], a->stride, ae_v_len(0,i-1));
40814 0 : for(j=0; j<=i-1; j++)
40815 : {
40816 0 : v = a->ptr.pp_double[offs+j][offs+i];
40817 0 : ae_v_addd(&a->ptr.pp_double[offs+j][offs+j], 1, &tmp->ptr.p_double[j], 1, ae_v_len(offs+j,offs+i-1), v);
40818 : }
40819 0 : v = a->ptr.pp_double[offs+i][offs+i];
40820 0 : ae_v_muld(&a->ptr.pp_double[offs][offs+i], a->stride, ae_v_len(offs,offs+i-1), v);
40821 0 : a->ptr.pp_double[offs+i][offs+i] = ae_sqr(a->ptr.pp_double[offs+i][offs+i], _state);
40822 : }
40823 : }
40824 : }
40825 : else
40826 : {
40827 :
40828 : /*
40829 : * Compute the product L' * L
40830 : * NOTE: we never assume that diagonal of L is real
40831 : */
40832 0 : for(i=0; i<=n-1; i++)
40833 : {
40834 0 : if( i==0 )
40835 : {
40836 :
40837 : /*
40838 : * 1x1 matrix
40839 : */
40840 0 : a->ptr.pp_double[offs+i][offs+i] = ae_sqr(a->ptr.pp_double[offs+i][offs+i], _state);
40841 : }
40842 : else
40843 : {
40844 :
40845 : /*
40846 : * (I+1)x(I+1) matrix,
40847 : *
40848 : * ( A11^H A21^H ) ( A11 ) ( A11^H*A11+A21^H*A21 A21^H*A22 )
40849 : * ( ) * ( ) = ( )
40850 : * ( A22^H ) ( A21 A22 ) ( A22^H*A21 A22^H*A22 )
40851 : *
40852 : * A11 is IxI, A22 is 1x1.
40853 : */
40854 0 : ae_v_move(&tmp->ptr.p_double[0], 1, &a->ptr.pp_double[offs+i][offs], 1, ae_v_len(0,i-1));
40855 0 : for(j=0; j<=i-1; j++)
40856 : {
40857 0 : v = a->ptr.pp_double[offs+i][offs+j];
40858 0 : ae_v_addd(&a->ptr.pp_double[offs+j][offs], 1, &tmp->ptr.p_double[0], 1, ae_v_len(offs,offs+j), v);
40859 : }
40860 0 : v = a->ptr.pp_double[offs+i][offs+i];
40861 0 : ae_v_muld(&a->ptr.pp_double[offs+i][offs], 1, ae_v_len(offs,offs+i-1), v);
40862 0 : a->ptr.pp_double[offs+i][offs+i] = ae_sqr(a->ptr.pp_double[offs+i][offs+i], _state);
40863 : }
40864 : }
40865 : }
40866 0 : ae_frame_leave(_state);
40867 0 : return;
40868 : }
40869 :
40870 : /*
40871 : * Recursive code: triangular factor inversion merged with
40872 : * UU' or L'L multiplication
40873 : */
40874 0 : tiledsplit(n, tscur, &n1, &n2, _state);
40875 :
40876 : /*
40877 : * form off-diagonal block of trangular inverse
40878 : */
40879 0 : if( isupper )
40880 : {
40881 0 : for(i=0; i<=n1-1; i++)
40882 : {
40883 0 : ae_v_muld(&a->ptr.pp_double[offs+i][offs+n1], 1, ae_v_len(offs+n1,offs+n-1), -1);
40884 : }
40885 0 : rmatrixlefttrsm(n1, n2, a, offs, offs, isupper, ae_false, 0, a, offs, offs+n1, _state);
40886 0 : rmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, isupper, ae_false, 0, a, offs, offs+n1, _state);
40887 : }
40888 : else
40889 : {
40890 0 : for(i=0; i<=n2-1; i++)
40891 : {
40892 0 : ae_v_muld(&a->ptr.pp_double[offs+n1+i][offs], 1, ae_v_len(offs,offs+n1-1), -1);
40893 : }
40894 0 : rmatrixrighttrsm(n2, n1, a, offs, offs, isupper, ae_false, 0, a, offs+n1, offs, _state);
40895 0 : rmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, isupper, ae_false, 0, a, offs+n1, offs, _state);
40896 : }
40897 :
40898 : /*
40899 : * invert first diagonal block
40900 : */
40901 0 : spdmatrixcholeskyinverserec(a, offs, n1, isupper, tmp, _state);
40902 :
40903 : /*
40904 : * update first diagonal block with off-diagonal block,
40905 : * update off-diagonal block
40906 : */
40907 0 : if( isupper )
40908 : {
40909 0 : rmatrixsyrk(n1, n2, 1.0, a, offs, offs+n1, 0, 1.0, a, offs, offs, isupper, _state);
40910 0 : rmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, isupper, ae_false, 1, a, offs, offs+n1, _state);
40911 : }
40912 : else
40913 : {
40914 0 : rmatrixsyrk(n1, n2, 1.0, a, offs+n1, offs, 1, 1.0, a, offs, offs, isupper, _state);
40915 0 : rmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, isupper, ae_false, 1, a, offs+n1, offs, _state);
40916 : }
40917 :
40918 : /*
40919 : * invert second diagonal block
40920 : */
40921 0 : spdmatrixcholeskyinverserec(a, offs+n1, n2, isupper, tmp, _state);
40922 0 : ae_frame_leave(_state);
40923 : }
40924 :
40925 :
40926 : /*************************************************************************
40927 : Serial stub for GPL edition.
40928 : *************************************************************************/
40929 0 : ae_bool _trypexec_spdmatrixcholeskyinverserec(/* Real */ ae_matrix* a,
40930 : ae_int_t offs,
40931 : ae_int_t n,
40932 : ae_bool isupper,
40933 : /* Real */ ae_vector* tmp,
40934 : ae_state *_state)
40935 : {
40936 0 : return ae_false;
40937 : }
40938 :
40939 :
40940 : /*************************************************************************
40941 : Triangular matrix inversion, recursive subroutine
40942 :
40943 : NOTE: this function sets Info on failure, leaves it unchanged on success.
40944 :
40945 : NOTE: only Tmp[Offs:Offs+N-1] is modified, other entries of the temporary array are not modified
40946 :
40947 : -- ALGLIB --
40948 : 05.02.2010, Bochkanov Sergey.
40949 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
40950 : Courant Institute, Argonne National Lab, and Rice University
40951 : February 29, 1992.
40952 : *************************************************************************/
40953 0 : static void matinv_rmatrixtrinverserec(/* Real */ ae_matrix* a,
40954 : ae_int_t offs,
40955 : ae_int_t n,
40956 : ae_bool isupper,
40957 : ae_bool isunit,
40958 : /* Real */ ae_vector* tmp,
40959 : sinteger* info,
40960 : ae_state *_state)
40961 : {
40962 : ae_int_t n1;
40963 : ae_int_t n2;
40964 : ae_int_t mn;
40965 : ae_int_t i;
40966 : ae_int_t j;
40967 : double v;
40968 : double ajj;
40969 : ae_int_t tsa;
40970 : ae_int_t tsb;
40971 : ae_int_t tscur;
40972 :
40973 :
40974 0 : if( n<1 )
40975 : {
40976 0 : info->val = -1;
40977 0 : return;
40978 : }
40979 0 : tsa = matrixtilesizea(_state);
40980 0 : tsb = matrixtilesizeb(_state);
40981 0 : tscur = tsb;
40982 0 : if( n<=tsb )
40983 : {
40984 0 : tscur = tsa;
40985 : }
40986 :
40987 : /*
40988 : * Try to activate parallelism
40989 : */
40990 0 : if( n>=2*tsb&&ae_fp_greater_eq(rmul3((double)(n), (double)(n), (double)(n), _state)*((double)1/(double)3),smpactivationlevel(_state)) )
40991 : {
40992 0 : if( _trypexec_matinv_rmatrixtrinverserec(a,offs,n,isupper,isunit,tmp,info, _state) )
40993 : {
40994 0 : return;
40995 : }
40996 : }
40997 :
40998 : /*
40999 : * Base case
41000 : */
41001 0 : if( n<=tsa )
41002 : {
41003 0 : if( isupper )
41004 : {
41005 :
41006 : /*
41007 : * Compute inverse of upper triangular matrix.
41008 : */
41009 0 : for(j=0; j<=n-1; j++)
41010 : {
41011 0 : if( !isunit )
41012 : {
41013 0 : if( ae_fp_eq(a->ptr.pp_double[offs+j][offs+j],(double)(0)) )
41014 : {
41015 0 : info->val = -3;
41016 0 : return;
41017 : }
41018 0 : a->ptr.pp_double[offs+j][offs+j] = 1/a->ptr.pp_double[offs+j][offs+j];
41019 0 : ajj = -a->ptr.pp_double[offs+j][offs+j];
41020 : }
41021 : else
41022 : {
41023 0 : ajj = (double)(-1);
41024 : }
41025 :
41026 : /*
41027 : * Compute elements 1:j-1 of j-th column.
41028 : */
41029 0 : if( j>0 )
41030 : {
41031 0 : ae_v_move(&tmp->ptr.p_double[offs+0], 1, &a->ptr.pp_double[offs+0][offs+j], a->stride, ae_v_len(offs+0,offs+j-1));
41032 0 : for(i=0; i<=j-1; i++)
41033 : {
41034 0 : if( i<j-1 )
41035 : {
41036 0 : v = ae_v_dotproduct(&a->ptr.pp_double[offs+i][offs+i+1], 1, &tmp->ptr.p_double[offs+i+1], 1, ae_v_len(offs+i+1,offs+j-1));
41037 : }
41038 : else
41039 : {
41040 0 : v = (double)(0);
41041 : }
41042 0 : if( !isunit )
41043 : {
41044 0 : a->ptr.pp_double[offs+i][offs+j] = v+a->ptr.pp_double[offs+i][offs+i]*tmp->ptr.p_double[offs+i];
41045 : }
41046 : else
41047 : {
41048 0 : a->ptr.pp_double[offs+i][offs+j] = v+tmp->ptr.p_double[offs+i];
41049 : }
41050 : }
41051 0 : ae_v_muld(&a->ptr.pp_double[offs+0][offs+j], a->stride, ae_v_len(offs+0,offs+j-1), ajj);
41052 : }
41053 : }
41054 : }
41055 : else
41056 : {
41057 :
41058 : /*
41059 : * Compute inverse of lower triangular matrix.
41060 : */
41061 0 : for(j=n-1; j>=0; j--)
41062 : {
41063 0 : if( !isunit )
41064 : {
41065 0 : if( ae_fp_eq(a->ptr.pp_double[offs+j][offs+j],(double)(0)) )
41066 : {
41067 0 : info->val = -3;
41068 0 : return;
41069 : }
41070 0 : a->ptr.pp_double[offs+j][offs+j] = 1/a->ptr.pp_double[offs+j][offs+j];
41071 0 : ajj = -a->ptr.pp_double[offs+j][offs+j];
41072 : }
41073 : else
41074 : {
41075 0 : ajj = (double)(-1);
41076 : }
41077 0 : if( j<n-1 )
41078 : {
41079 :
41080 : /*
41081 : * Compute elements j+1:n of j-th column.
41082 : */
41083 0 : ae_v_move(&tmp->ptr.p_double[offs+j+1], 1, &a->ptr.pp_double[offs+j+1][offs+j], a->stride, ae_v_len(offs+j+1,offs+n-1));
41084 0 : for(i=j+1; i<=n-1; i++)
41085 : {
41086 0 : if( i>j+1 )
41087 : {
41088 0 : v = ae_v_dotproduct(&a->ptr.pp_double[offs+i][offs+j+1], 1, &tmp->ptr.p_double[offs+j+1], 1, ae_v_len(offs+j+1,offs+i-1));
41089 : }
41090 : else
41091 : {
41092 0 : v = (double)(0);
41093 : }
41094 0 : if( !isunit )
41095 : {
41096 0 : a->ptr.pp_double[offs+i][offs+j] = v+a->ptr.pp_double[offs+i][offs+i]*tmp->ptr.p_double[offs+i];
41097 : }
41098 : else
41099 : {
41100 0 : a->ptr.pp_double[offs+i][offs+j] = v+tmp->ptr.p_double[offs+i];
41101 : }
41102 : }
41103 0 : ae_v_muld(&a->ptr.pp_double[offs+j+1][offs+j], a->stride, ae_v_len(offs+j+1,offs+n-1), ajj);
41104 : }
41105 : }
41106 : }
41107 0 : return;
41108 : }
41109 :
41110 : /*
41111 : * Recursive case
41112 : */
41113 0 : tiledsplit(n, tscur, &n1, &n2, _state);
41114 0 : mn = imin2(n1, n2, _state);
41115 0 : touchint(&mn, _state);
41116 0 : if( n2>0 )
41117 : {
41118 0 : if( isupper )
41119 : {
41120 0 : for(i=0; i<=n1-1; i++)
41121 : {
41122 0 : ae_v_muld(&a->ptr.pp_double[offs+i][offs+n1], 1, ae_v_len(offs+n1,offs+n-1), -1);
41123 : }
41124 0 : rmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, isupper, isunit, 0, a, offs, offs+n1, _state);
41125 0 : matinv_rmatrixtrinverserec(a, offs+n1, n2, isupper, isunit, tmp, info, _state);
41126 0 : rmatrixlefttrsm(n1, n2, a, offs, offs, isupper, isunit, 0, a, offs, offs+n1, _state);
41127 : }
41128 : else
41129 : {
41130 0 : for(i=0; i<=n2-1; i++)
41131 : {
41132 0 : ae_v_muld(&a->ptr.pp_double[offs+n1+i][offs], 1, ae_v_len(offs,offs+n1-1), -1);
41133 : }
41134 0 : rmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, isupper, isunit, 0, a, offs+n1, offs, _state);
41135 0 : matinv_rmatrixtrinverserec(a, offs+n1, n2, isupper, isunit, tmp, info, _state);
41136 0 : rmatrixrighttrsm(n2, n1, a, offs, offs, isupper, isunit, 0, a, offs+n1, offs, _state);
41137 : }
41138 : }
41139 0 : matinv_rmatrixtrinverserec(a, offs, n1, isupper, isunit, tmp, info, _state);
41140 : }
41141 :
41142 :
41143 : /*************************************************************************
41144 : Serial stub for GPL edition.
41145 : *************************************************************************/
41146 0 : ae_bool _trypexec_matinv_rmatrixtrinverserec(/* Real */ ae_matrix* a,
41147 : ae_int_t offs,
41148 : ae_int_t n,
41149 : ae_bool isupper,
41150 : ae_bool isunit,
41151 : /* Real */ ae_vector* tmp,
41152 : sinteger* info,
41153 : ae_state *_state)
41154 : {
41155 0 : return ae_false;
41156 : }
41157 :
41158 :
41159 : /*************************************************************************
41160 : Triangular matrix inversion, recursive subroutine.
41161 :
41162 : Info is modified on failure, left unchanged on success.
41163 :
41164 : -- ALGLIB --
41165 : 05.02.2010, Bochkanov Sergey.
41166 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
41167 : Courant Institute, Argonne National Lab, and Rice University
41168 : February 29, 1992.
41169 : *************************************************************************/
41170 0 : static void matinv_cmatrixtrinverserec(/* Complex */ ae_matrix* a,
41171 : ae_int_t offs,
41172 : ae_int_t n,
41173 : ae_bool isupper,
41174 : ae_bool isunit,
41175 : /* Complex */ ae_vector* tmp,
41176 : sinteger* info,
41177 : ae_state *_state)
41178 : {
41179 : ae_int_t n1;
41180 : ae_int_t n2;
41181 : ae_int_t i;
41182 : ae_int_t j;
41183 : ae_complex v;
41184 : ae_complex ajj;
41185 : ae_int_t tsa;
41186 : ae_int_t tsb;
41187 : ae_int_t tscur;
41188 : ae_int_t mn;
41189 :
41190 :
41191 0 : if( n<1 )
41192 : {
41193 0 : info->val = -1;
41194 0 : return;
41195 : }
41196 0 : tsa = matrixtilesizea(_state)/2;
41197 0 : tsb = matrixtilesizeb(_state);
41198 0 : tscur = tsb;
41199 0 : if( n<=tsb )
41200 : {
41201 0 : tscur = tsa;
41202 : }
41203 :
41204 : /*
41205 : * Try to activate parallelism
41206 : */
41207 0 : if( n>=2*tsb&&ae_fp_greater_eq(rmul3((double)(n), (double)(n), (double)(n), _state)*((double)4/(double)3),smpactivationlevel(_state)) )
41208 : {
41209 0 : if( _trypexec_matinv_cmatrixtrinverserec(a,offs,n,isupper,isunit,tmp,info, _state) )
41210 : {
41211 0 : return;
41212 : }
41213 : }
41214 :
41215 : /*
41216 : * Base case
41217 : */
41218 0 : if( n<=tsa )
41219 : {
41220 0 : if( isupper )
41221 : {
41222 :
41223 : /*
41224 : * Compute inverse of upper triangular matrix.
41225 : */
41226 0 : for(j=0; j<=n-1; j++)
41227 : {
41228 0 : if( !isunit )
41229 : {
41230 0 : if( ae_c_eq_d(a->ptr.pp_complex[offs+j][offs+j],(double)(0)) )
41231 : {
41232 0 : info->val = -3;
41233 0 : return;
41234 : }
41235 0 : a->ptr.pp_complex[offs+j][offs+j] = ae_c_d_div(1,a->ptr.pp_complex[offs+j][offs+j]);
41236 0 : ajj = ae_c_neg(a->ptr.pp_complex[offs+j][offs+j]);
41237 : }
41238 : else
41239 : {
41240 0 : ajj = ae_complex_from_i(-1);
41241 : }
41242 :
41243 : /*
41244 : * Compute elements 1:j-1 of j-th column.
41245 : */
41246 0 : if( j>0 )
41247 : {
41248 0 : ae_v_cmove(&tmp->ptr.p_complex[offs+0], 1, &a->ptr.pp_complex[offs+0][offs+j], a->stride, "N", ae_v_len(offs+0,offs+j-1));
41249 0 : for(i=0; i<=j-1; i++)
41250 : {
41251 0 : if( i<j-1 )
41252 : {
41253 0 : v = ae_v_cdotproduct(&a->ptr.pp_complex[offs+i][offs+i+1], 1, "N", &tmp->ptr.p_complex[offs+i+1], 1, "N", ae_v_len(offs+i+1,offs+j-1));
41254 : }
41255 : else
41256 : {
41257 0 : v = ae_complex_from_i(0);
41258 : }
41259 0 : if( !isunit )
41260 : {
41261 0 : a->ptr.pp_complex[offs+i][offs+j] = ae_c_add(v,ae_c_mul(a->ptr.pp_complex[offs+i][offs+i],tmp->ptr.p_complex[offs+i]));
41262 : }
41263 : else
41264 : {
41265 0 : a->ptr.pp_complex[offs+i][offs+j] = ae_c_add(v,tmp->ptr.p_complex[offs+i]);
41266 : }
41267 : }
41268 0 : ae_v_cmulc(&a->ptr.pp_complex[offs+0][offs+j], a->stride, ae_v_len(offs+0,offs+j-1), ajj);
41269 : }
41270 : }
41271 : }
41272 : else
41273 : {
41274 :
41275 : /*
41276 : * Compute inverse of lower triangular matrix.
41277 : */
41278 0 : for(j=n-1; j>=0; j--)
41279 : {
41280 0 : if( !isunit )
41281 : {
41282 0 : if( ae_c_eq_d(a->ptr.pp_complex[offs+j][offs+j],(double)(0)) )
41283 : {
41284 0 : info->val = -3;
41285 0 : return;
41286 : }
41287 0 : a->ptr.pp_complex[offs+j][offs+j] = ae_c_d_div(1,a->ptr.pp_complex[offs+j][offs+j]);
41288 0 : ajj = ae_c_neg(a->ptr.pp_complex[offs+j][offs+j]);
41289 : }
41290 : else
41291 : {
41292 0 : ajj = ae_complex_from_i(-1);
41293 : }
41294 0 : if( j<n-1 )
41295 : {
41296 :
41297 : /*
41298 : * Compute elements j+1:n of j-th column.
41299 : */
41300 0 : ae_v_cmove(&tmp->ptr.p_complex[offs+j+1], 1, &a->ptr.pp_complex[offs+j+1][offs+j], a->stride, "N", ae_v_len(offs+j+1,offs+n-1));
41301 0 : for(i=j+1; i<=n-1; i++)
41302 : {
41303 0 : if( i>j+1 )
41304 : {
41305 0 : v = ae_v_cdotproduct(&a->ptr.pp_complex[offs+i][offs+j+1], 1, "N", &tmp->ptr.p_complex[offs+j+1], 1, "N", ae_v_len(offs+j+1,offs+i-1));
41306 : }
41307 : else
41308 : {
41309 0 : v = ae_complex_from_i(0);
41310 : }
41311 0 : if( !isunit )
41312 : {
41313 0 : a->ptr.pp_complex[offs+i][offs+j] = ae_c_add(v,ae_c_mul(a->ptr.pp_complex[offs+i][offs+i],tmp->ptr.p_complex[offs+i]));
41314 : }
41315 : else
41316 : {
41317 0 : a->ptr.pp_complex[offs+i][offs+j] = ae_c_add(v,tmp->ptr.p_complex[offs+i]);
41318 : }
41319 : }
41320 0 : ae_v_cmulc(&a->ptr.pp_complex[offs+j+1][offs+j], a->stride, ae_v_len(offs+j+1,offs+n-1), ajj);
41321 : }
41322 : }
41323 : }
41324 0 : return;
41325 : }
41326 :
41327 : /*
41328 : * Recursive case
41329 : */
41330 0 : tiledsplit(n, tscur, &n1, &n2, _state);
41331 0 : mn = imin2(n1, n2, _state);
41332 0 : touchint(&mn, _state);
41333 0 : if( n2>0 )
41334 : {
41335 0 : if( isupper )
41336 : {
41337 0 : for(i=0; i<=n1-1; i++)
41338 : {
41339 0 : ae_v_cmuld(&a->ptr.pp_complex[offs+i][offs+n1], 1, ae_v_len(offs+n1,offs+n-1), -1);
41340 : }
41341 0 : cmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, isupper, isunit, 0, a, offs, offs+n1, _state);
41342 0 : matinv_cmatrixtrinverserec(a, offs+n1, n2, isupper, isunit, tmp, info, _state);
41343 0 : cmatrixlefttrsm(n1, n2, a, offs, offs, isupper, isunit, 0, a, offs, offs+n1, _state);
41344 : }
41345 : else
41346 : {
41347 0 : for(i=0; i<=n2-1; i++)
41348 : {
41349 0 : ae_v_cmuld(&a->ptr.pp_complex[offs+n1+i][offs], 1, ae_v_len(offs,offs+n1-1), -1);
41350 : }
41351 0 : cmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, isupper, isunit, 0, a, offs+n1, offs, _state);
41352 0 : matinv_cmatrixtrinverserec(a, offs+n1, n2, isupper, isunit, tmp, info, _state);
41353 0 : cmatrixrighttrsm(n2, n1, a, offs, offs, isupper, isunit, 0, a, offs+n1, offs, _state);
41354 : }
41355 : }
41356 0 : matinv_cmatrixtrinverserec(a, offs, n1, isupper, isunit, tmp, info, _state);
41357 : }
41358 :
41359 :
41360 : /*************************************************************************
41361 : Serial stub for GPL edition.
41362 : *************************************************************************/
41363 0 : ae_bool _trypexec_matinv_cmatrixtrinverserec(/* Complex */ ae_matrix* a,
41364 : ae_int_t offs,
41365 : ae_int_t n,
41366 : ae_bool isupper,
41367 : ae_bool isunit,
41368 : /* Complex */ ae_vector* tmp,
41369 : sinteger* info,
41370 : ae_state *_state)
41371 : {
41372 0 : return ae_false;
41373 : }
41374 :
41375 :
41376 0 : static void matinv_rmatrixluinverserec(/* Real */ ae_matrix* a,
41377 : ae_int_t offs,
41378 : ae_int_t n,
41379 : /* Real */ ae_vector* work,
41380 : sinteger* info,
41381 : matinvreport* rep,
41382 : ae_state *_state)
41383 : {
41384 : ae_int_t i;
41385 : ae_int_t j;
41386 : double v;
41387 : ae_int_t n1;
41388 : ae_int_t n2;
41389 : ae_int_t tsa;
41390 : ae_int_t tsb;
41391 : ae_int_t tscur;
41392 : ae_int_t mn;
41393 :
41394 :
41395 0 : if( n<1 )
41396 : {
41397 0 : info->val = -1;
41398 0 : return;
41399 : }
41400 0 : tsa = matrixtilesizea(_state);
41401 0 : tsb = matrixtilesizeb(_state);
41402 0 : tscur = tsb;
41403 0 : if( n<=tsb )
41404 : {
41405 0 : tscur = tsa;
41406 : }
41407 :
41408 : /*
41409 : * Try parallelism
41410 : */
41411 0 : if( n>=2*tsb&&ae_fp_greater_eq((double)8/(double)6*rmul3((double)(n), (double)(n), (double)(n), _state),smpactivationlevel(_state)) )
41412 : {
41413 0 : if( _trypexec_matinv_rmatrixluinverserec(a,offs,n,work,info,rep, _state) )
41414 : {
41415 0 : return;
41416 : }
41417 : }
41418 :
41419 : /*
41420 : * Base case
41421 : */
41422 0 : if( n<=tsa )
41423 : {
41424 :
41425 : /*
41426 : * Form inv(U)
41427 : */
41428 0 : matinv_rmatrixtrinverserec(a, offs, n, ae_true, ae_false, work, info, _state);
41429 0 : if( info->val<=0 )
41430 : {
41431 0 : return;
41432 : }
41433 :
41434 : /*
41435 : * Solve the equation inv(A)*L = inv(U) for inv(A).
41436 : */
41437 0 : for(j=n-1; j>=0; j--)
41438 : {
41439 :
41440 : /*
41441 : * Copy current column of L to WORK and replace with zeros.
41442 : */
41443 0 : for(i=j+1; i<=n-1; i++)
41444 : {
41445 0 : work->ptr.p_double[i] = a->ptr.pp_double[offs+i][offs+j];
41446 0 : a->ptr.pp_double[offs+i][offs+j] = (double)(0);
41447 : }
41448 :
41449 : /*
41450 : * Compute current column of inv(A).
41451 : */
41452 0 : if( j<n-1 )
41453 : {
41454 0 : for(i=0; i<=n-1; i++)
41455 : {
41456 0 : v = ae_v_dotproduct(&a->ptr.pp_double[offs+i][offs+j+1], 1, &work->ptr.p_double[j+1], 1, ae_v_len(offs+j+1,offs+n-1));
41457 0 : a->ptr.pp_double[offs+i][offs+j] = a->ptr.pp_double[offs+i][offs+j]-v;
41458 : }
41459 : }
41460 : }
41461 0 : return;
41462 : }
41463 :
41464 : /*
41465 : * Recursive code:
41466 : *
41467 : * ( L1 ) ( U1 U12 )
41468 : * A = ( ) * ( )
41469 : * ( L12 L2 ) ( U2 )
41470 : *
41471 : * ( W X )
41472 : * A^-1 = ( )
41473 : * ( Y Z )
41474 : *
41475 : * In-place calculation can be done as follows:
41476 : * * X := inv(U1)*U12*inv(U2)
41477 : * * Y := inv(L2)*L12*inv(L1)
41478 : * * W := inv(L1*U1)+X*Y
41479 : * * X := -X*inv(L2)
41480 : * * Y := -inv(U2)*Y
41481 : * * Z := inv(L2*U2)
41482 : *
41483 : * Reordering w.r.t. interdependencies gives us:
41484 : *
41485 : * * X := inv(U1)*U12 \ suitable for parallel execution
41486 : * * Y := L12*inv(L1) /
41487 : *
41488 : * * X := X*inv(U2) \
41489 : * * Y := inv(L2)*Y | suitable for parallel execution
41490 : * * W := inv(L1*U1) /
41491 : *
41492 : * * W := W+X*Y
41493 : *
41494 : * * X := -X*inv(L2) \ suitable for parallel execution
41495 : * * Y := -inv(U2)*Y /
41496 : *
41497 : * * Z := inv(L2*U2)
41498 : */
41499 0 : tiledsplit(n, tscur, &n1, &n2, _state);
41500 0 : mn = imin2(n1, n2, _state);
41501 0 : touchint(&mn, _state);
41502 0 : ae_assert(n2>0, "LUInverseRec: internal error!", _state);
41503 :
41504 : /*
41505 : * X := inv(U1)*U12
41506 : * Y := L12*inv(L1)
41507 : */
41508 0 : rmatrixlefttrsm(n1, n2, a, offs, offs, ae_true, ae_false, 0, a, offs, offs+n1, _state);
41509 0 : rmatrixrighttrsm(n2, n1, a, offs, offs, ae_false, ae_true, 0, a, offs+n1, offs, _state);
41510 :
41511 : /*
41512 : * X := X*inv(U2)
41513 : * Y := inv(L2)*Y
41514 : * W := inv(L1*U1)
41515 : */
41516 0 : rmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, ae_true, ae_false, 0, a, offs, offs+n1, _state);
41517 0 : rmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, ae_false, ae_true, 0, a, offs+n1, offs, _state);
41518 0 : matinv_rmatrixluinverserec(a, offs, n1, work, info, rep, _state);
41519 0 : if( info->val<=0 )
41520 : {
41521 0 : return;
41522 : }
41523 :
41524 : /*
41525 : * W := W+X*Y
41526 : */
41527 0 : rmatrixgemm(n1, n1, n2, 1.0, a, offs, offs+n1, 0, a, offs+n1, offs, 0, 1.0, a, offs, offs, _state);
41528 :
41529 : /*
41530 : * X := -X*inv(L2)
41531 : * Y := -inv(U2)*Y
41532 : */
41533 0 : rmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, ae_false, ae_true, 0, a, offs, offs+n1, _state);
41534 0 : rmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, ae_true, ae_false, 0, a, offs+n1, offs, _state);
41535 0 : for(i=0; i<=n1-1; i++)
41536 : {
41537 0 : ae_v_muld(&a->ptr.pp_double[offs+i][offs+n1], 1, ae_v_len(offs+n1,offs+n-1), -1);
41538 : }
41539 0 : for(i=0; i<=n2-1; i++)
41540 : {
41541 0 : ae_v_muld(&a->ptr.pp_double[offs+n1+i][offs], 1, ae_v_len(offs,offs+n1-1), -1);
41542 : }
41543 :
41544 : /*
41545 : * Z := inv(L2*U2)
41546 : */
41547 0 : matinv_rmatrixluinverserec(a, offs+n1, n2, work, info, rep, _state);
41548 : }
41549 :
41550 :
41551 : /*************************************************************************
41552 : Serial stub for GPL edition.
41553 : *************************************************************************/
41554 0 : ae_bool _trypexec_matinv_rmatrixluinverserec(/* Real */ ae_matrix* a,
41555 : ae_int_t offs,
41556 : ae_int_t n,
41557 : /* Real */ ae_vector* work,
41558 : sinteger* info,
41559 : matinvreport* rep,
41560 : ae_state *_state)
41561 : {
41562 0 : return ae_false;
41563 : }
41564 :
41565 :
41566 0 : static void matinv_cmatrixluinverserec(/* Complex */ ae_matrix* a,
41567 : ae_int_t offs,
41568 : ae_int_t n,
41569 : /* Complex */ ae_vector* work,
41570 : sinteger* ssinfo,
41571 : matinvreport* rep,
41572 : ae_state *_state)
41573 : {
41574 : ae_int_t i;
41575 : ae_int_t j;
41576 : ae_complex v;
41577 : ae_int_t n1;
41578 : ae_int_t n2;
41579 : ae_int_t mn;
41580 : ae_int_t tsa;
41581 : ae_int_t tsb;
41582 : ae_int_t tscur;
41583 :
41584 :
41585 0 : if( n<1 )
41586 : {
41587 0 : ssinfo->val = -1;
41588 0 : return;
41589 : }
41590 0 : tsa = matrixtilesizea(_state)/2;
41591 0 : tsb = matrixtilesizeb(_state);
41592 0 : tscur = tsb;
41593 0 : if( n<=tsb )
41594 : {
41595 0 : tscur = tsa;
41596 : }
41597 :
41598 : /*
41599 : * Try parallelism
41600 : */
41601 0 : if( n>=2*tsb&&ae_fp_greater_eq((double)32/(double)6*rmul3((double)(n), (double)(n), (double)(n), _state),smpactivationlevel(_state)) )
41602 : {
41603 0 : if( _trypexec_matinv_cmatrixluinverserec(a,offs,n,work,ssinfo,rep, _state) )
41604 : {
41605 0 : return;
41606 : }
41607 : }
41608 :
41609 : /*
41610 : * Base case
41611 : */
41612 0 : if( n<=tsa )
41613 : {
41614 :
41615 : /*
41616 : * Form inv(U)
41617 : */
41618 0 : matinv_cmatrixtrinverserec(a, offs, n, ae_true, ae_false, work, ssinfo, _state);
41619 0 : if( ssinfo->val<=0 )
41620 : {
41621 0 : return;
41622 : }
41623 :
41624 : /*
41625 : * Solve the equation inv(A)*L = inv(U) for inv(A).
41626 : */
41627 0 : for(j=n-1; j>=0; j--)
41628 : {
41629 :
41630 : /*
41631 : * Copy current column of L to WORK and replace with zeros.
41632 : */
41633 0 : for(i=j+1; i<=n-1; i++)
41634 : {
41635 0 : work->ptr.p_complex[i] = a->ptr.pp_complex[offs+i][offs+j];
41636 0 : a->ptr.pp_complex[offs+i][offs+j] = ae_complex_from_i(0);
41637 : }
41638 :
41639 : /*
41640 : * Compute current column of inv(A).
41641 : */
41642 0 : if( j<n-1 )
41643 : {
41644 0 : for(i=0; i<=n-1; i++)
41645 : {
41646 0 : v = ae_v_cdotproduct(&a->ptr.pp_complex[offs+i][offs+j+1], 1, "N", &work->ptr.p_complex[j+1], 1, "N", ae_v_len(offs+j+1,offs+n-1));
41647 0 : a->ptr.pp_complex[offs+i][offs+j] = ae_c_sub(a->ptr.pp_complex[offs+i][offs+j],v);
41648 : }
41649 : }
41650 : }
41651 0 : return;
41652 : }
41653 :
41654 : /*
41655 : * Recursive code:
41656 : *
41657 : * ( L1 ) ( U1 U12 )
41658 : * A = ( ) * ( )
41659 : * ( L12 L2 ) ( U2 )
41660 : *
41661 : * ( W X )
41662 : * A^-1 = ( )
41663 : * ( Y Z )
41664 : *
41665 : * In-place calculation can be done as follows:
41666 : * * X := inv(U1)*U12*inv(U2)
41667 : * * Y := inv(L2)*L12*inv(L1)
41668 : * * W := inv(L1*U1)+X*Y
41669 : * * X := -X*inv(L2)
41670 : * * Y := -inv(U2)*Y
41671 : * * Z := inv(L2*U2)
41672 : *
41673 : * Reordering w.r.t. interdependencies gives us:
41674 : *
41675 : * * X := inv(U1)*U12 \ suitable for parallel execution
41676 : * * Y := L12*inv(L1) /
41677 : *
41678 : * * X := X*inv(U2) \
41679 : * * Y := inv(L2)*Y | suitable for parallel execution
41680 : * * W := inv(L1*U1) /
41681 : *
41682 : * * W := W+X*Y
41683 : *
41684 : * * X := -X*inv(L2) \ suitable for parallel execution
41685 : * * Y := -inv(U2)*Y /
41686 : *
41687 : * * Z := inv(L2*U2)
41688 : */
41689 0 : tiledsplit(n, tscur, &n1, &n2, _state);
41690 0 : mn = imin2(n1, n2, _state);
41691 0 : touchint(&mn, _state);
41692 0 : ae_assert(n2>0, "LUInverseRec: internal error!", _state);
41693 :
41694 : /*
41695 : * X := inv(U1)*U12
41696 : * Y := L12*inv(L1)
41697 : */
41698 0 : cmatrixlefttrsm(n1, n2, a, offs, offs, ae_true, ae_false, 0, a, offs, offs+n1, _state);
41699 0 : cmatrixrighttrsm(n2, n1, a, offs, offs, ae_false, ae_true, 0, a, offs+n1, offs, _state);
41700 :
41701 : /*
41702 : * X := X*inv(U2)
41703 : * Y := inv(L2)*Y
41704 : * W := inv(L1*U1)
41705 : */
41706 0 : cmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, ae_true, ae_false, 0, a, offs, offs+n1, _state);
41707 0 : cmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, ae_false, ae_true, 0, a, offs+n1, offs, _state);
41708 0 : matinv_cmatrixluinverserec(a, offs, n1, work, ssinfo, rep, _state);
41709 0 : if( ssinfo->val<=0 )
41710 : {
41711 0 : return;
41712 : }
41713 :
41714 : /*
41715 : * W := W+X*Y
41716 : */
41717 0 : cmatrixgemm(n1, n1, n2, ae_complex_from_d(1.0), a, offs, offs+n1, 0, a, offs+n1, offs, 0, ae_complex_from_d(1.0), a, offs, offs, _state);
41718 :
41719 : /*
41720 : * X := -X*inv(L2)
41721 : * Y := -inv(U2)*Y
41722 : */
41723 0 : cmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, ae_false, ae_true, 0, a, offs, offs+n1, _state);
41724 0 : cmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, ae_true, ae_false, 0, a, offs+n1, offs, _state);
41725 0 : for(i=0; i<=n1-1; i++)
41726 : {
41727 0 : ae_v_cmuld(&a->ptr.pp_complex[offs+i][offs+n1], 1, ae_v_len(offs+n1,offs+n-1), -1);
41728 : }
41729 0 : for(i=0; i<=n2-1; i++)
41730 : {
41731 0 : ae_v_cmuld(&a->ptr.pp_complex[offs+n1+i][offs], 1, ae_v_len(offs,offs+n1-1), -1);
41732 : }
41733 :
41734 : /*
41735 : * Z := inv(L2*U2)
41736 : */
41737 0 : matinv_cmatrixluinverserec(a, offs+n1, n2, work, ssinfo, rep, _state);
41738 : }
41739 :
41740 :
41741 : /*************************************************************************
41742 : Serial stub for GPL edition.
41743 : *************************************************************************/
41744 0 : ae_bool _trypexec_matinv_cmatrixluinverserec(/* Complex */ ae_matrix* a,
41745 : ae_int_t offs,
41746 : ae_int_t n,
41747 : /* Complex */ ae_vector* work,
41748 : sinteger* ssinfo,
41749 : matinvreport* rep,
41750 : ae_state *_state)
41751 : {
41752 0 : return ae_false;
41753 : }
41754 :
41755 :
41756 : /*************************************************************************
41757 : Recursive subroutine for HPD inversion.
41758 :
41759 : -- ALGLIB routine --
41760 : 10.02.2010
41761 : Bochkanov Sergey
41762 : *************************************************************************/
41763 0 : static void matinv_hpdmatrixcholeskyinverserec(/* Complex */ ae_matrix* a,
41764 : ae_int_t offs,
41765 : ae_int_t n,
41766 : ae_bool isupper,
41767 : /* Complex */ ae_vector* tmp,
41768 : ae_state *_state)
41769 : {
41770 : ae_frame _frame_block;
41771 : ae_int_t i;
41772 : ae_int_t j;
41773 : ae_complex v;
41774 : ae_int_t n1;
41775 : ae_int_t n2;
41776 : sinteger sinfo;
41777 : ae_int_t tsa;
41778 : ae_int_t tsb;
41779 : ae_int_t tscur;
41780 :
41781 0 : ae_frame_make(_state, &_frame_block);
41782 0 : memset(&sinfo, 0, sizeof(sinfo));
41783 0 : _sinteger_init(&sinfo, _state, ae_true);
41784 :
41785 0 : if( n<1 )
41786 : {
41787 0 : ae_frame_leave(_state);
41788 0 : return;
41789 : }
41790 0 : tsa = matrixtilesizea(_state)/2;
41791 0 : tsb = matrixtilesizeb(_state);
41792 0 : tscur = tsb;
41793 0 : if( n<=tsb )
41794 : {
41795 0 : tscur = tsa;
41796 : }
41797 :
41798 : /*
41799 : * Base case
41800 : */
41801 0 : if( n<=tsa )
41802 : {
41803 0 : sinfo.val = 1;
41804 0 : matinv_cmatrixtrinverserec(a, offs, n, isupper, ae_false, tmp, &sinfo, _state);
41805 0 : ae_assert(sinfo.val>0, "HPDMatrixCholeskyInverseRec: integrity check failed", _state);
41806 0 : if( isupper )
41807 : {
41808 :
41809 : /*
41810 : * Compute the product U * U'.
41811 : * NOTE: we never assume that diagonal of U is real
41812 : */
41813 0 : for(i=0; i<=n-1; i++)
41814 : {
41815 0 : if( i==0 )
41816 : {
41817 :
41818 : /*
41819 : * 1x1 matrix
41820 : */
41821 0 : a->ptr.pp_complex[offs+i][offs+i] = ae_complex_from_d(ae_sqr(a->ptr.pp_complex[offs+i][offs+i].x, _state)+ae_sqr(a->ptr.pp_complex[offs+i][offs+i].y, _state));
41822 : }
41823 : else
41824 : {
41825 :
41826 : /*
41827 : * (I+1)x(I+1) matrix,
41828 : *
41829 : * ( A11 A12 ) ( A11^H ) ( A11*A11^H+A12*A12^H A12*A22^H )
41830 : * ( ) * ( ) = ( )
41831 : * ( A22 ) ( A12^H A22^H ) ( A22*A12^H A22*A22^H )
41832 : *
41833 : * A11 is IxI, A22 is 1x1.
41834 : */
41835 0 : ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs][offs+i], a->stride, "Conj", ae_v_len(0,i-1));
41836 0 : for(j=0; j<=i-1; j++)
41837 : {
41838 0 : v = a->ptr.pp_complex[offs+j][offs+i];
41839 0 : ae_v_caddc(&a->ptr.pp_complex[offs+j][offs+j], 1, &tmp->ptr.p_complex[j], 1, "N", ae_v_len(offs+j,offs+i-1), v);
41840 : }
41841 0 : v = ae_c_conj(a->ptr.pp_complex[offs+i][offs+i], _state);
41842 0 : ae_v_cmulc(&a->ptr.pp_complex[offs][offs+i], a->stride, ae_v_len(offs,offs+i-1), v);
41843 0 : a->ptr.pp_complex[offs+i][offs+i] = ae_complex_from_d(ae_sqr(a->ptr.pp_complex[offs+i][offs+i].x, _state)+ae_sqr(a->ptr.pp_complex[offs+i][offs+i].y, _state));
41844 : }
41845 : }
41846 : }
41847 : else
41848 : {
41849 :
41850 : /*
41851 : * Compute the product L' * L
41852 : * NOTE: we never assume that diagonal of L is real
41853 : */
41854 0 : for(i=0; i<=n-1; i++)
41855 : {
41856 0 : if( i==0 )
41857 : {
41858 :
41859 : /*
41860 : * 1x1 matrix
41861 : */
41862 0 : a->ptr.pp_complex[offs+i][offs+i] = ae_complex_from_d(ae_sqr(a->ptr.pp_complex[offs+i][offs+i].x, _state)+ae_sqr(a->ptr.pp_complex[offs+i][offs+i].y, _state));
41863 : }
41864 : else
41865 : {
41866 :
41867 : /*
41868 : * (I+1)x(I+1) matrix,
41869 : *
41870 : * ( A11^H A21^H ) ( A11 ) ( A11^H*A11+A21^H*A21 A21^H*A22 )
41871 : * ( ) * ( ) = ( )
41872 : * ( A22^H ) ( A21 A22 ) ( A22^H*A21 A22^H*A22 )
41873 : *
41874 : * A11 is IxI, A22 is 1x1.
41875 : */
41876 0 : ae_v_cmove(&tmp->ptr.p_complex[0], 1, &a->ptr.pp_complex[offs+i][offs], 1, "N", ae_v_len(0,i-1));
41877 0 : for(j=0; j<=i-1; j++)
41878 : {
41879 0 : v = ae_c_conj(a->ptr.pp_complex[offs+i][offs+j], _state);
41880 0 : ae_v_caddc(&a->ptr.pp_complex[offs+j][offs], 1, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(offs,offs+j), v);
41881 : }
41882 0 : v = ae_c_conj(a->ptr.pp_complex[offs+i][offs+i], _state);
41883 0 : ae_v_cmulc(&a->ptr.pp_complex[offs+i][offs], 1, ae_v_len(offs,offs+i-1), v);
41884 0 : a->ptr.pp_complex[offs+i][offs+i] = ae_complex_from_d(ae_sqr(a->ptr.pp_complex[offs+i][offs+i].x, _state)+ae_sqr(a->ptr.pp_complex[offs+i][offs+i].y, _state));
41885 : }
41886 : }
41887 : }
41888 0 : ae_frame_leave(_state);
41889 0 : return;
41890 : }
41891 :
41892 : /*
41893 : * Recursive code: triangular factor inversion merged with
41894 : * UU' or L'L multiplication
41895 : */
41896 0 : tiledsplit(n, tscur, &n1, &n2, _state);
41897 :
41898 : /*
41899 : * form off-diagonal block of trangular inverse
41900 : */
41901 0 : if( isupper )
41902 : {
41903 0 : for(i=0; i<=n1-1; i++)
41904 : {
41905 0 : ae_v_cmuld(&a->ptr.pp_complex[offs+i][offs+n1], 1, ae_v_len(offs+n1,offs+n-1), -1);
41906 : }
41907 0 : cmatrixlefttrsm(n1, n2, a, offs, offs, isupper, ae_false, 0, a, offs, offs+n1, _state);
41908 0 : cmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, isupper, ae_false, 0, a, offs, offs+n1, _state);
41909 : }
41910 : else
41911 : {
41912 0 : for(i=0; i<=n2-1; i++)
41913 : {
41914 0 : ae_v_cmuld(&a->ptr.pp_complex[offs+n1+i][offs], 1, ae_v_len(offs,offs+n1-1), -1);
41915 : }
41916 0 : cmatrixrighttrsm(n2, n1, a, offs, offs, isupper, ae_false, 0, a, offs+n1, offs, _state);
41917 0 : cmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, isupper, ae_false, 0, a, offs+n1, offs, _state);
41918 : }
41919 :
41920 : /*
41921 : * invert first diagonal block
41922 : */
41923 0 : matinv_hpdmatrixcholeskyinverserec(a, offs, n1, isupper, tmp, _state);
41924 :
41925 : /*
41926 : * update first diagonal block with off-diagonal block,
41927 : * update off-diagonal block
41928 : */
41929 0 : if( isupper )
41930 : {
41931 0 : cmatrixherk(n1, n2, 1.0, a, offs, offs+n1, 0, 1.0, a, offs, offs, isupper, _state);
41932 0 : cmatrixrighttrsm(n1, n2, a, offs+n1, offs+n1, isupper, ae_false, 2, a, offs, offs+n1, _state);
41933 : }
41934 : else
41935 : {
41936 0 : cmatrixherk(n1, n2, 1.0, a, offs+n1, offs, 2, 1.0, a, offs, offs, isupper, _state);
41937 0 : cmatrixlefttrsm(n2, n1, a, offs+n1, offs+n1, isupper, ae_false, 2, a, offs+n1, offs, _state);
41938 : }
41939 :
41940 : /*
41941 : * invert second diagonal block
41942 : */
41943 0 : matinv_hpdmatrixcholeskyinverserec(a, offs+n1, n2, isupper, tmp, _state);
41944 0 : ae_frame_leave(_state);
41945 : }
41946 :
41947 :
41948 0 : void _matinvreport_init(void* _p, ae_state *_state, ae_bool make_automatic)
41949 : {
41950 0 : matinvreport *p = (matinvreport*)_p;
41951 0 : ae_touch_ptr((void*)p);
41952 0 : }
41953 :
41954 :
41955 0 : void _matinvreport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
41956 : {
41957 0 : matinvreport *dst = (matinvreport*)_dst;
41958 0 : matinvreport *src = (matinvreport*)_src;
41959 0 : dst->r1 = src->r1;
41960 0 : dst->rinf = src->rinf;
41961 0 : }
41962 :
41963 :
41964 0 : void _matinvreport_clear(void* _p)
41965 : {
41966 0 : matinvreport *p = (matinvreport*)_p;
41967 0 : ae_touch_ptr((void*)p);
41968 0 : }
41969 :
41970 :
41971 0 : void _matinvreport_destroy(void* _p)
41972 : {
41973 0 : matinvreport *p = (matinvreport*)_p;
41974 0 : ae_touch_ptr((void*)p);
41975 0 : }
41976 :
41977 :
41978 : #endif
41979 : #if defined(AE_COMPILE_ORTFAC) || !defined(AE_PARTIAL_BUILD)
41980 :
41981 :
41982 : /*************************************************************************
41983 : QR decomposition of a rectangular matrix of size MxN
41984 :
41985 : ! COMMERCIAL EDITION OF ALGLIB:
41986 : !
41987 : ! Commercial Edition of ALGLIB includes following important improvements
41988 : ! of this function:
41989 : ! * high-performance native backend with same C# interface (C# version)
41990 : ! * multithreading support (C++ and C# versions)
41991 : ! * hardware vendor (Intel) implementations of linear algebra primitives
41992 : ! (C++ and C# versions, x86/x64 platform)
41993 : !
41994 : ! We recommend you to read 'Working with commercial version' section of
41995 : ! ALGLIB Reference Manual in order to find out how to use performance-
41996 : ! related features provided by commercial edition of ALGLIB.
41997 :
41998 : Input parameters:
41999 : A - matrix A whose indexes range within [0..M-1, 0..N-1].
42000 : M - number of rows in matrix A.
42001 : N - number of columns in matrix A.
42002 :
42003 : Output parameters:
42004 : A - matrices Q and R in compact form (see below).
42005 : Tau - array of scalar factors which are used to form
42006 : matrix Q. Array whose index ranges within [0.. Min(M-1,N-1)].
42007 :
42008 : Matrix A is represented as A = QR, where Q is an orthogonal matrix of size
42009 : MxM, R - upper triangular (or upper trapezoid) matrix of size M x N.
42010 :
42011 : The elements of matrix R are located on and above the main diagonal of
42012 : matrix A. The elements which are located in Tau array and below the main
42013 : diagonal of matrix A are used to form matrix Q as follows:
42014 :
42015 : Matrix Q is represented as a product of elementary reflections
42016 :
42017 : Q = H(0)*H(2)*...*H(k-1),
42018 :
42019 : where k = min(m,n), and each H(i) is in the form
42020 :
42021 : H(i) = 1 - tau * v * (v^T)
42022 :
42023 : where tau is a scalar stored in Tau[I]; v - real vector,
42024 : so that v(0:i-1) = 0, v(i) = 1, v(i+1:m-1) stored in A(i+1:m-1,i).
42025 :
42026 : -- ALGLIB routine --
42027 : 17.02.2010
42028 : Bochkanov Sergey
42029 : *************************************************************************/
42030 0 : void rmatrixqr(/* Real */ ae_matrix* a,
42031 : ae_int_t m,
42032 : ae_int_t n,
42033 : /* Real */ ae_vector* tau,
42034 : ae_state *_state)
42035 : {
42036 : ae_frame _frame_block;
42037 : ae_vector work;
42038 : ae_vector t;
42039 : ae_vector taubuf;
42040 : ae_int_t minmn;
42041 : ae_matrix tmpa;
42042 : ae_matrix tmpt;
42043 : ae_matrix tmpr;
42044 : ae_int_t blockstart;
42045 : ae_int_t blocksize;
42046 : ae_int_t rowscount;
42047 : ae_int_t i;
42048 : ae_int_t ts;
42049 :
42050 0 : ae_frame_make(_state, &_frame_block);
42051 0 : memset(&work, 0, sizeof(work));
42052 0 : memset(&t, 0, sizeof(t));
42053 0 : memset(&taubuf, 0, sizeof(taubuf));
42054 0 : memset(&tmpa, 0, sizeof(tmpa));
42055 0 : memset(&tmpt, 0, sizeof(tmpt));
42056 0 : memset(&tmpr, 0, sizeof(tmpr));
42057 0 : ae_vector_clear(tau);
42058 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
42059 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
42060 0 : ae_vector_init(&taubuf, 0, DT_REAL, _state, ae_true);
42061 0 : ae_matrix_init(&tmpa, 0, 0, DT_REAL, _state, ae_true);
42062 0 : ae_matrix_init(&tmpt, 0, 0, DT_REAL, _state, ae_true);
42063 0 : ae_matrix_init(&tmpr, 0, 0, DT_REAL, _state, ae_true);
42064 :
42065 0 : if( m<=0||n<=0 )
42066 : {
42067 0 : ae_frame_leave(_state);
42068 0 : return;
42069 : }
42070 0 : minmn = ae_minint(m, n, _state);
42071 0 : ts = matrixtilesizeb(_state);
42072 0 : ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state);
42073 0 : ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state);
42074 0 : ae_vector_set_length(tau, minmn, _state);
42075 0 : ae_vector_set_length(&taubuf, minmn, _state);
42076 0 : ae_matrix_set_length(&tmpa, m, ts, _state);
42077 0 : ae_matrix_set_length(&tmpt, ts, 2*ts, _state);
42078 0 : ae_matrix_set_length(&tmpr, 2*ts, n, _state);
42079 :
42080 : /*
42081 : * Blocked code
42082 : */
42083 0 : blockstart = 0;
42084 0 : while(blockstart!=minmn)
42085 : {
42086 :
42087 : /*
42088 : * Determine block size
42089 : */
42090 0 : blocksize = minmn-blockstart;
42091 0 : if( blocksize>ts )
42092 : {
42093 0 : blocksize = ts;
42094 : }
42095 0 : rowscount = m-blockstart;
42096 :
42097 : /*
42098 : * QR decomposition of submatrix.
42099 : * Matrix is copied to temporary storage to solve
42100 : * some TLB issues arising from non-contiguous memory
42101 : * access pattern.
42102 : */
42103 0 : rmatrixcopy(rowscount, blocksize, a, blockstart, blockstart, &tmpa, 0, 0, _state);
42104 0 : rmatrixqrbasecase(&tmpa, rowscount, blocksize, &work, &t, &taubuf, _state);
42105 0 : rmatrixcopy(rowscount, blocksize, &tmpa, 0, 0, a, blockstart, blockstart, _state);
42106 0 : ae_v_move(&tau->ptr.p_double[blockstart], 1, &taubuf.ptr.p_double[0], 1, ae_v_len(blockstart,blockstart+blocksize-1));
42107 :
42108 : /*
42109 : * Update the rest, choose between:
42110 : * a) Level 2 algorithm (when the rest of the matrix is small enough)
42111 : * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY
42112 : * representation for products of Householder transformations',
42113 : * by R. Schreiber and C. Van Loan.
42114 : */
42115 0 : if( blockstart+blocksize<=n-1 )
42116 : {
42117 0 : if( n-blockstart-blocksize>=2*ts||rowscount>=4*ts )
42118 : {
42119 :
42120 : /*
42121 : * Prepare block reflector
42122 : */
42123 0 : ortfac_rmatrixblockreflector(&tmpa, &taubuf, ae_true, rowscount, blocksize, &tmpt, &work, _state);
42124 :
42125 : /*
42126 : * Multiply the rest of A by Q'.
42127 : *
42128 : * Q = E + Y*T*Y' = E + TmpA*TmpT*TmpA'
42129 : * Q' = E + Y*T'*Y' = E + TmpA*TmpT'*TmpA'
42130 : */
42131 0 : rmatrixgemm(blocksize, n-blockstart-blocksize, rowscount, 1.0, &tmpa, 0, 0, 1, a, blockstart, blockstart+blocksize, 0, 0.0, &tmpr, 0, 0, _state);
42132 0 : rmatrixgemm(blocksize, n-blockstart-blocksize, blocksize, 1.0, &tmpt, 0, 0, 1, &tmpr, 0, 0, 0, 0.0, &tmpr, blocksize, 0, _state);
42133 0 : rmatrixgemm(rowscount, n-blockstart-blocksize, blocksize, 1.0, &tmpa, 0, 0, 0, &tmpr, blocksize, 0, 0, 1.0, a, blockstart, blockstart+blocksize, _state);
42134 : }
42135 : else
42136 : {
42137 :
42138 : /*
42139 : * Level 2 algorithm
42140 : */
42141 0 : for(i=0; i<=blocksize-1; i++)
42142 : {
42143 0 : ae_v_move(&t.ptr.p_double[1], 1, &tmpa.ptr.pp_double[i][i], tmpa.stride, ae_v_len(1,rowscount-i));
42144 0 : t.ptr.p_double[1] = (double)(1);
42145 0 : applyreflectionfromtheleft(a, taubuf.ptr.p_double[i], &t, blockstart+i, m-1, blockstart+blocksize, n-1, &work, _state);
42146 : }
42147 : }
42148 : }
42149 :
42150 : /*
42151 : * Advance
42152 : */
42153 0 : blockstart = blockstart+blocksize;
42154 : }
42155 0 : ae_frame_leave(_state);
42156 : }
42157 :
42158 :
42159 : /*************************************************************************
42160 : LQ decomposition of a rectangular matrix of size MxN
42161 :
42162 : ! COMMERCIAL EDITION OF ALGLIB:
42163 : !
42164 : ! Commercial Edition of ALGLIB includes following important improvements
42165 : ! of this function:
42166 : ! * high-performance native backend with same C# interface (C# version)
42167 : ! * multithreading support (C++ and C# versions)
42168 : ! * hardware vendor (Intel) implementations of linear algebra primitives
42169 : ! (C++ and C# versions, x86/x64 platform)
42170 : !
42171 : ! We recommend you to read 'Working with commercial version' section of
42172 : ! ALGLIB Reference Manual in order to find out how to use performance-
42173 : ! related features provided by commercial edition of ALGLIB.
42174 :
42175 : Input parameters:
42176 : A - matrix A whose indexes range within [0..M-1, 0..N-1].
42177 : M - number of rows in matrix A.
42178 : N - number of columns in matrix A.
42179 :
42180 : Output parameters:
42181 : A - matrices L and Q in compact form (see below)
42182 : Tau - array of scalar factors which are used to form
42183 : matrix Q. Array whose index ranges within [0..Min(M,N)-1].
42184 :
42185 : Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size
42186 : MxM, L - lower triangular (or lower trapezoid) matrix of size M x N.
42187 :
42188 : The elements of matrix L are located on and below the main diagonal of
42189 : matrix A. The elements which are located in Tau array and above the main
42190 : diagonal of matrix A are used to form matrix Q as follows:
42191 :
42192 : Matrix Q is represented as a product of elementary reflections
42193 :
42194 : Q = H(k-1)*H(k-2)*...*H(1)*H(0),
42195 :
42196 : where k = min(m,n), and each H(i) is of the form
42197 :
42198 : H(i) = 1 - tau * v * (v^T)
42199 :
42200 : where tau is a scalar stored in Tau[I]; v - real vector, so that v(0:i-1)=0,
42201 : v(i) = 1, v(i+1:n-1) stored in A(i,i+1:n-1).
42202 :
42203 : -- ALGLIB routine --
42204 : 17.02.2010
42205 : Bochkanov Sergey
42206 : *************************************************************************/
42207 0 : void rmatrixlq(/* Real */ ae_matrix* a,
42208 : ae_int_t m,
42209 : ae_int_t n,
42210 : /* Real */ ae_vector* tau,
42211 : ae_state *_state)
42212 : {
42213 : ae_frame _frame_block;
42214 : ae_vector work;
42215 : ae_vector t;
42216 : ae_vector taubuf;
42217 : ae_int_t minmn;
42218 : ae_matrix tmpa;
42219 : ae_matrix tmpt;
42220 : ae_matrix tmpr;
42221 : ae_int_t blockstart;
42222 : ae_int_t blocksize;
42223 : ae_int_t columnscount;
42224 : ae_int_t i;
42225 : ae_int_t ts;
42226 :
42227 0 : ae_frame_make(_state, &_frame_block);
42228 0 : memset(&work, 0, sizeof(work));
42229 0 : memset(&t, 0, sizeof(t));
42230 0 : memset(&taubuf, 0, sizeof(taubuf));
42231 0 : memset(&tmpa, 0, sizeof(tmpa));
42232 0 : memset(&tmpt, 0, sizeof(tmpt));
42233 0 : memset(&tmpr, 0, sizeof(tmpr));
42234 0 : ae_vector_clear(tau);
42235 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
42236 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
42237 0 : ae_vector_init(&taubuf, 0, DT_REAL, _state, ae_true);
42238 0 : ae_matrix_init(&tmpa, 0, 0, DT_REAL, _state, ae_true);
42239 0 : ae_matrix_init(&tmpt, 0, 0, DT_REAL, _state, ae_true);
42240 0 : ae_matrix_init(&tmpr, 0, 0, DT_REAL, _state, ae_true);
42241 :
42242 0 : if( m<=0||n<=0 )
42243 : {
42244 0 : ae_frame_leave(_state);
42245 0 : return;
42246 : }
42247 0 : minmn = ae_minint(m, n, _state);
42248 0 : ts = matrixtilesizeb(_state);
42249 0 : ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state);
42250 0 : ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state);
42251 0 : ae_vector_set_length(tau, minmn, _state);
42252 0 : ae_vector_set_length(&taubuf, minmn, _state);
42253 0 : ae_matrix_set_length(&tmpa, ts, n, _state);
42254 0 : ae_matrix_set_length(&tmpt, ts, 2*ts, _state);
42255 0 : ae_matrix_set_length(&tmpr, m, 2*ts, _state);
42256 :
42257 : /*
42258 : * Blocked code
42259 : */
42260 0 : blockstart = 0;
42261 0 : while(blockstart!=minmn)
42262 : {
42263 :
42264 : /*
42265 : * Determine block size
42266 : */
42267 0 : blocksize = minmn-blockstart;
42268 0 : if( blocksize>ts )
42269 : {
42270 0 : blocksize = ts;
42271 : }
42272 0 : columnscount = n-blockstart;
42273 :
42274 : /*
42275 : * LQ decomposition of submatrix.
42276 : * Matrix is copied to temporary storage to solve
42277 : * some TLB issues arising from non-contiguous memory
42278 : * access pattern.
42279 : */
42280 0 : rmatrixcopy(blocksize, columnscount, a, blockstart, blockstart, &tmpa, 0, 0, _state);
42281 0 : rmatrixlqbasecase(&tmpa, blocksize, columnscount, &work, &t, &taubuf, _state);
42282 0 : rmatrixcopy(blocksize, columnscount, &tmpa, 0, 0, a, blockstart, blockstart, _state);
42283 0 : ae_v_move(&tau->ptr.p_double[blockstart], 1, &taubuf.ptr.p_double[0], 1, ae_v_len(blockstart,blockstart+blocksize-1));
42284 :
42285 : /*
42286 : * Update the rest, choose between:
42287 : * a) Level 2 algorithm (when the rest of the matrix is small enough)
42288 : * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY
42289 : * representation for products of Householder transformations',
42290 : * by R. Schreiber and C. Van Loan.
42291 : */
42292 0 : if( blockstart+blocksize<=m-1 )
42293 : {
42294 0 : if( m-blockstart-blocksize>=2*ts )
42295 : {
42296 :
42297 : /*
42298 : * Prepare block reflector
42299 : */
42300 0 : ortfac_rmatrixblockreflector(&tmpa, &taubuf, ae_false, columnscount, blocksize, &tmpt, &work, _state);
42301 :
42302 : /*
42303 : * Multiply the rest of A by Q.
42304 : *
42305 : * Q = E + Y*T*Y' = E + TmpA'*TmpT*TmpA
42306 : */
42307 0 : rmatrixgemm(m-blockstart-blocksize, blocksize, columnscount, 1.0, a, blockstart+blocksize, blockstart, 0, &tmpa, 0, 0, 1, 0.0, &tmpr, 0, 0, _state);
42308 0 : rmatrixgemm(m-blockstart-blocksize, blocksize, blocksize, 1.0, &tmpr, 0, 0, 0, &tmpt, 0, 0, 0, 0.0, &tmpr, 0, blocksize, _state);
42309 0 : rmatrixgemm(m-blockstart-blocksize, columnscount, blocksize, 1.0, &tmpr, 0, blocksize, 0, &tmpa, 0, 0, 0, 1.0, a, blockstart+blocksize, blockstart, _state);
42310 : }
42311 : else
42312 : {
42313 :
42314 : /*
42315 : * Level 2 algorithm
42316 : */
42317 0 : for(i=0; i<=blocksize-1; i++)
42318 : {
42319 0 : ae_v_move(&t.ptr.p_double[1], 1, &tmpa.ptr.pp_double[i][i], 1, ae_v_len(1,columnscount-i));
42320 0 : t.ptr.p_double[1] = (double)(1);
42321 0 : applyreflectionfromtheright(a, taubuf.ptr.p_double[i], &t, blockstart+blocksize, m-1, blockstart+i, n-1, &work, _state);
42322 : }
42323 : }
42324 : }
42325 :
42326 : /*
42327 : * Advance
42328 : */
42329 0 : blockstart = blockstart+blocksize;
42330 : }
42331 0 : ae_frame_leave(_state);
42332 : }
42333 :
42334 :
42335 : /*************************************************************************
42336 : QR decomposition of a rectangular complex matrix of size MxN
42337 :
42338 : ! COMMERCIAL EDITION OF ALGLIB:
42339 : !
42340 : ! Commercial Edition of ALGLIB includes following important improvements
42341 : ! of this function:
42342 : ! * high-performance native backend with same C# interface (C# version)
42343 : ! * multithreading support (C++ and C# versions)
42344 : ! * hardware vendor (Intel) implementations of linear algebra primitives
42345 : ! (C++ and C# versions, x86/x64 platform)
42346 : !
42347 : ! We recommend you to read 'Working with commercial version' section of
42348 : ! ALGLIB Reference Manual in order to find out how to use performance-
42349 : ! related features provided by commercial edition of ALGLIB.
42350 :
42351 : Input parameters:
42352 : A - matrix A whose indexes range within [0..M-1, 0..N-1]
42353 : M - number of rows in matrix A.
42354 : N - number of columns in matrix A.
42355 :
42356 : Output parameters:
42357 : A - matrices Q and R in compact form
42358 : Tau - array of scalar factors which are used to form matrix Q. Array
42359 : whose indexes range within [0.. Min(M,N)-1]
42360 :
42361 : Matrix A is represented as A = QR, where Q is an orthogonal matrix of size
42362 : MxM, R - upper triangular (or upper trapezoid) matrix of size MxN.
42363 :
42364 : -- LAPACK routine (version 3.0) --
42365 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
42366 : Courant Institute, Argonne National Lab, and Rice University
42367 : September 30, 1994
42368 : *************************************************************************/
42369 0 : void cmatrixqr(/* Complex */ ae_matrix* a,
42370 : ae_int_t m,
42371 : ae_int_t n,
42372 : /* Complex */ ae_vector* tau,
42373 : ae_state *_state)
42374 : {
42375 : ae_frame _frame_block;
42376 : ae_vector work;
42377 : ae_vector t;
42378 : ae_vector taubuf;
42379 : ae_int_t minmn;
42380 : ae_matrix tmpa;
42381 : ae_matrix tmpt;
42382 : ae_matrix tmpr;
42383 : ae_int_t blockstart;
42384 : ae_int_t blocksize;
42385 : ae_int_t rowscount;
42386 : ae_int_t i;
42387 : ae_int_t ts;
42388 :
42389 0 : ae_frame_make(_state, &_frame_block);
42390 0 : memset(&work, 0, sizeof(work));
42391 0 : memset(&t, 0, sizeof(t));
42392 0 : memset(&taubuf, 0, sizeof(taubuf));
42393 0 : memset(&tmpa, 0, sizeof(tmpa));
42394 0 : memset(&tmpt, 0, sizeof(tmpt));
42395 0 : memset(&tmpr, 0, sizeof(tmpr));
42396 0 : ae_vector_clear(tau);
42397 0 : ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true);
42398 0 : ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true);
42399 0 : ae_vector_init(&taubuf, 0, DT_COMPLEX, _state, ae_true);
42400 0 : ae_matrix_init(&tmpa, 0, 0, DT_COMPLEX, _state, ae_true);
42401 0 : ae_matrix_init(&tmpt, 0, 0, DT_COMPLEX, _state, ae_true);
42402 0 : ae_matrix_init(&tmpr, 0, 0, DT_COMPLEX, _state, ae_true);
42403 :
42404 0 : if( m<=0||n<=0 )
42405 : {
42406 0 : ae_frame_leave(_state);
42407 0 : return;
42408 : }
42409 0 : ts = matrixtilesizeb(_state)/2;
42410 0 : minmn = ae_minint(m, n, _state);
42411 0 : ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state);
42412 0 : ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state);
42413 0 : ae_vector_set_length(tau, minmn, _state);
42414 0 : ae_vector_set_length(&taubuf, minmn, _state);
42415 0 : ae_matrix_set_length(&tmpa, m, ts, _state);
42416 0 : ae_matrix_set_length(&tmpt, ts, ts, _state);
42417 0 : ae_matrix_set_length(&tmpr, 2*ts, n, _state);
42418 :
42419 : /*
42420 : * Blocked code
42421 : */
42422 0 : blockstart = 0;
42423 0 : while(blockstart!=minmn)
42424 : {
42425 :
42426 : /*
42427 : * Determine block size
42428 : */
42429 0 : blocksize = minmn-blockstart;
42430 0 : if( blocksize>ts )
42431 : {
42432 0 : blocksize = ts;
42433 : }
42434 0 : rowscount = m-blockstart;
42435 :
42436 : /*
42437 : * QR decomposition of submatrix.
42438 : * Matrix is copied to temporary storage to solve
42439 : * some TLB issues arising from non-contiguous memory
42440 : * access pattern.
42441 : */
42442 0 : cmatrixcopy(rowscount, blocksize, a, blockstart, blockstart, &tmpa, 0, 0, _state);
42443 0 : ortfac_cmatrixqrbasecase(&tmpa, rowscount, blocksize, &work, &t, &taubuf, _state);
42444 0 : cmatrixcopy(rowscount, blocksize, &tmpa, 0, 0, a, blockstart, blockstart, _state);
42445 0 : ae_v_cmove(&tau->ptr.p_complex[blockstart], 1, &taubuf.ptr.p_complex[0], 1, "N", ae_v_len(blockstart,blockstart+blocksize-1));
42446 :
42447 : /*
42448 : * Update the rest, choose between:
42449 : * a) Level 2 algorithm (when the rest of the matrix is small enough)
42450 : * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY
42451 : * representation for products of Householder transformations',
42452 : * by R. Schreiber and C. Van Loan.
42453 : */
42454 0 : if( blockstart+blocksize<=n-1 )
42455 : {
42456 0 : if( n-blockstart-blocksize>=2*ts )
42457 : {
42458 :
42459 : /*
42460 : * Prepare block reflector
42461 : */
42462 0 : ortfac_cmatrixblockreflector(&tmpa, &taubuf, ae_true, rowscount, blocksize, &tmpt, &work, _state);
42463 :
42464 : /*
42465 : * Multiply the rest of A by Q'.
42466 : *
42467 : * Q = E + Y*T*Y' = E + TmpA*TmpT*TmpA'
42468 : * Q' = E + Y*T'*Y' = E + TmpA*TmpT'*TmpA'
42469 : */
42470 0 : cmatrixgemm(blocksize, n-blockstart-blocksize, rowscount, ae_complex_from_d(1.0), &tmpa, 0, 0, 2, a, blockstart, blockstart+blocksize, 0, ae_complex_from_d(0.0), &tmpr, 0, 0, _state);
42471 0 : cmatrixgemm(blocksize, n-blockstart-blocksize, blocksize, ae_complex_from_d(1.0), &tmpt, 0, 0, 2, &tmpr, 0, 0, 0, ae_complex_from_d(0.0), &tmpr, blocksize, 0, _state);
42472 0 : cmatrixgemm(rowscount, n-blockstart-blocksize, blocksize, ae_complex_from_d(1.0), &tmpa, 0, 0, 0, &tmpr, blocksize, 0, 0, ae_complex_from_d(1.0), a, blockstart, blockstart+blocksize, _state);
42473 : }
42474 : else
42475 : {
42476 :
42477 : /*
42478 : * Level 2 algorithm
42479 : */
42480 0 : for(i=0; i<=blocksize-1; i++)
42481 : {
42482 0 : ae_v_cmove(&t.ptr.p_complex[1], 1, &tmpa.ptr.pp_complex[i][i], tmpa.stride, "N", ae_v_len(1,rowscount-i));
42483 0 : t.ptr.p_complex[1] = ae_complex_from_i(1);
42484 0 : complexapplyreflectionfromtheleft(a, ae_c_conj(taubuf.ptr.p_complex[i], _state), &t, blockstart+i, m-1, blockstart+blocksize, n-1, &work, _state);
42485 : }
42486 : }
42487 : }
42488 :
42489 : /*
42490 : * Advance
42491 : */
42492 0 : blockstart = blockstart+blocksize;
42493 : }
42494 0 : ae_frame_leave(_state);
42495 : }
42496 :
42497 :
42498 : /*************************************************************************
42499 : LQ decomposition of a rectangular complex matrix of size MxN
42500 :
42501 : ! COMMERCIAL EDITION OF ALGLIB:
42502 : !
42503 : ! Commercial Edition of ALGLIB includes following important improvements
42504 : ! of this function:
42505 : ! * high-performance native backend with same C# interface (C# version)
42506 : ! * multithreading support (C++ and C# versions)
42507 : ! * hardware vendor (Intel) implementations of linear algebra primitives
42508 : ! (C++ and C# versions, x86/x64 platform)
42509 : !
42510 : ! We recommend you to read 'Working with commercial version' section of
42511 : ! ALGLIB Reference Manual in order to find out how to use performance-
42512 : ! related features provided by commercial edition of ALGLIB.
42513 :
42514 : Input parameters:
42515 : A - matrix A whose indexes range within [0..M-1, 0..N-1]
42516 : M - number of rows in matrix A.
42517 : N - number of columns in matrix A.
42518 :
42519 : Output parameters:
42520 : A - matrices Q and L in compact form
42521 : Tau - array of scalar factors which are used to form matrix Q. Array
42522 : whose indexes range within [0.. Min(M,N)-1]
42523 :
42524 : Matrix A is represented as A = LQ, where Q is an orthogonal matrix of size
42525 : MxM, L - lower triangular (or lower trapezoid) matrix of size MxN.
42526 :
42527 : -- LAPACK routine (version 3.0) --
42528 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
42529 : Courant Institute, Argonne National Lab, and Rice University
42530 : September 30, 1994
42531 : *************************************************************************/
42532 0 : void cmatrixlq(/* Complex */ ae_matrix* a,
42533 : ae_int_t m,
42534 : ae_int_t n,
42535 : /* Complex */ ae_vector* tau,
42536 : ae_state *_state)
42537 : {
42538 : ae_frame _frame_block;
42539 : ae_vector work;
42540 : ae_vector t;
42541 : ae_vector taubuf;
42542 : ae_int_t minmn;
42543 : ae_matrix tmpa;
42544 : ae_matrix tmpt;
42545 : ae_matrix tmpr;
42546 : ae_int_t blockstart;
42547 : ae_int_t blocksize;
42548 : ae_int_t columnscount;
42549 : ae_int_t i;
42550 : ae_int_t ts;
42551 :
42552 0 : ae_frame_make(_state, &_frame_block);
42553 0 : memset(&work, 0, sizeof(work));
42554 0 : memset(&t, 0, sizeof(t));
42555 0 : memset(&taubuf, 0, sizeof(taubuf));
42556 0 : memset(&tmpa, 0, sizeof(tmpa));
42557 0 : memset(&tmpt, 0, sizeof(tmpt));
42558 0 : memset(&tmpr, 0, sizeof(tmpr));
42559 0 : ae_vector_clear(tau);
42560 0 : ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true);
42561 0 : ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true);
42562 0 : ae_vector_init(&taubuf, 0, DT_COMPLEX, _state, ae_true);
42563 0 : ae_matrix_init(&tmpa, 0, 0, DT_COMPLEX, _state, ae_true);
42564 0 : ae_matrix_init(&tmpt, 0, 0, DT_COMPLEX, _state, ae_true);
42565 0 : ae_matrix_init(&tmpr, 0, 0, DT_COMPLEX, _state, ae_true);
42566 :
42567 0 : if( m<=0||n<=0 )
42568 : {
42569 0 : ae_frame_leave(_state);
42570 0 : return;
42571 : }
42572 0 : ts = matrixtilesizeb(_state)/2;
42573 0 : minmn = ae_minint(m, n, _state);
42574 0 : ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state);
42575 0 : ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state);
42576 0 : ae_vector_set_length(tau, minmn, _state);
42577 0 : ae_vector_set_length(&taubuf, minmn, _state);
42578 0 : ae_matrix_set_length(&tmpa, ts, n, _state);
42579 0 : ae_matrix_set_length(&tmpt, ts, ts, _state);
42580 0 : ae_matrix_set_length(&tmpr, m, 2*ts, _state);
42581 :
42582 : /*
42583 : * Blocked code
42584 : */
42585 0 : blockstart = 0;
42586 0 : while(blockstart!=minmn)
42587 : {
42588 :
42589 : /*
42590 : * Determine block size
42591 : */
42592 0 : blocksize = minmn-blockstart;
42593 0 : if( blocksize>ts )
42594 : {
42595 0 : blocksize = ts;
42596 : }
42597 0 : columnscount = n-blockstart;
42598 :
42599 : /*
42600 : * LQ decomposition of submatrix.
42601 : * Matrix is copied to temporary storage to solve
42602 : * some TLB issues arising from non-contiguous memory
42603 : * access pattern.
42604 : */
42605 0 : cmatrixcopy(blocksize, columnscount, a, blockstart, blockstart, &tmpa, 0, 0, _state);
42606 0 : ortfac_cmatrixlqbasecase(&tmpa, blocksize, columnscount, &work, &t, &taubuf, _state);
42607 0 : cmatrixcopy(blocksize, columnscount, &tmpa, 0, 0, a, blockstart, blockstart, _state);
42608 0 : ae_v_cmove(&tau->ptr.p_complex[blockstart], 1, &taubuf.ptr.p_complex[0], 1, "N", ae_v_len(blockstart,blockstart+blocksize-1));
42609 :
42610 : /*
42611 : * Update the rest, choose between:
42612 : * a) Level 2 algorithm (when the rest of the matrix is small enough)
42613 : * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY
42614 : * representation for products of Householder transformations',
42615 : * by R. Schreiber and C. Van Loan.
42616 : */
42617 0 : if( blockstart+blocksize<=m-1 )
42618 : {
42619 0 : if( m-blockstart-blocksize>=2*ts )
42620 : {
42621 :
42622 : /*
42623 : * Prepare block reflector
42624 : */
42625 0 : ortfac_cmatrixblockreflector(&tmpa, &taubuf, ae_false, columnscount, blocksize, &tmpt, &work, _state);
42626 :
42627 : /*
42628 : * Multiply the rest of A by Q.
42629 : *
42630 : * Q = E + Y*T*Y' = E + TmpA'*TmpT*TmpA
42631 : */
42632 0 : cmatrixgemm(m-blockstart-blocksize, blocksize, columnscount, ae_complex_from_d(1.0), a, blockstart+blocksize, blockstart, 0, &tmpa, 0, 0, 2, ae_complex_from_d(0.0), &tmpr, 0, 0, _state);
42633 0 : cmatrixgemm(m-blockstart-blocksize, blocksize, blocksize, ae_complex_from_d(1.0), &tmpr, 0, 0, 0, &tmpt, 0, 0, 0, ae_complex_from_d(0.0), &tmpr, 0, blocksize, _state);
42634 0 : cmatrixgemm(m-blockstart-blocksize, columnscount, blocksize, ae_complex_from_d(1.0), &tmpr, 0, blocksize, 0, &tmpa, 0, 0, 0, ae_complex_from_d(1.0), a, blockstart+blocksize, blockstart, _state);
42635 : }
42636 : else
42637 : {
42638 :
42639 : /*
42640 : * Level 2 algorithm
42641 : */
42642 0 : for(i=0; i<=blocksize-1; i++)
42643 : {
42644 0 : ae_v_cmove(&t.ptr.p_complex[1], 1, &tmpa.ptr.pp_complex[i][i], 1, "Conj", ae_v_len(1,columnscount-i));
42645 0 : t.ptr.p_complex[1] = ae_complex_from_i(1);
42646 0 : complexapplyreflectionfromtheright(a, taubuf.ptr.p_complex[i], &t, blockstart+blocksize, m-1, blockstart+i, n-1, &work, _state);
42647 : }
42648 : }
42649 : }
42650 :
42651 : /*
42652 : * Advance
42653 : */
42654 0 : blockstart = blockstart+blocksize;
42655 : }
42656 0 : ae_frame_leave(_state);
42657 : }
42658 :
42659 :
42660 : /*************************************************************************
42661 : Partial unpacking of matrix Q from the QR decomposition of a matrix A
42662 :
42663 : ! COMMERCIAL EDITION OF ALGLIB:
42664 : !
42665 : ! Commercial Edition of ALGLIB includes following important improvements
42666 : ! of this function:
42667 : ! * high-performance native backend with same C# interface (C# version)
42668 : ! * multithreading support (C++ and C# versions)
42669 : ! * hardware vendor (Intel) implementations of linear algebra primitives
42670 : ! (C++ and C# versions, x86/x64 platform)
42671 : !
42672 : ! We recommend you to read 'Working with commercial version' section of
42673 : ! ALGLIB Reference Manual in order to find out how to use performance-
42674 : ! related features provided by commercial edition of ALGLIB.
42675 :
42676 : Input parameters:
42677 : A - matrices Q and R in compact form.
42678 : Output of RMatrixQR subroutine.
42679 : M - number of rows in given matrix A. M>=0.
42680 : N - number of columns in given matrix A. N>=0.
42681 : Tau - scalar factors which are used to form Q.
42682 : Output of the RMatrixQR subroutine.
42683 : QColumns - required number of columns of matrix Q. M>=QColumns>=0.
42684 :
42685 : Output parameters:
42686 : Q - first QColumns columns of matrix Q.
42687 : Array whose indexes range within [0..M-1, 0..QColumns-1].
42688 : If QColumns=0, the array remains unchanged.
42689 :
42690 : -- ALGLIB routine --
42691 : 17.02.2010
42692 : Bochkanov Sergey
42693 : *************************************************************************/
42694 0 : void rmatrixqrunpackq(/* Real */ ae_matrix* a,
42695 : ae_int_t m,
42696 : ae_int_t n,
42697 : /* Real */ ae_vector* tau,
42698 : ae_int_t qcolumns,
42699 : /* Real */ ae_matrix* q,
42700 : ae_state *_state)
42701 : {
42702 : ae_frame _frame_block;
42703 : ae_vector work;
42704 : ae_vector t;
42705 : ae_vector taubuf;
42706 : ae_int_t minmn;
42707 : ae_int_t refcnt;
42708 : ae_matrix tmpa;
42709 : ae_matrix tmpt;
42710 : ae_matrix tmpr;
42711 : ae_int_t blockstart;
42712 : ae_int_t blocksize;
42713 : ae_int_t rowscount;
42714 : ae_int_t i;
42715 : ae_int_t j;
42716 : ae_int_t ts;
42717 :
42718 0 : ae_frame_make(_state, &_frame_block);
42719 0 : memset(&work, 0, sizeof(work));
42720 0 : memset(&t, 0, sizeof(t));
42721 0 : memset(&taubuf, 0, sizeof(taubuf));
42722 0 : memset(&tmpa, 0, sizeof(tmpa));
42723 0 : memset(&tmpt, 0, sizeof(tmpt));
42724 0 : memset(&tmpr, 0, sizeof(tmpr));
42725 0 : ae_matrix_clear(q);
42726 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
42727 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
42728 0 : ae_vector_init(&taubuf, 0, DT_REAL, _state, ae_true);
42729 0 : ae_matrix_init(&tmpa, 0, 0, DT_REAL, _state, ae_true);
42730 0 : ae_matrix_init(&tmpt, 0, 0, DT_REAL, _state, ae_true);
42731 0 : ae_matrix_init(&tmpr, 0, 0, DT_REAL, _state, ae_true);
42732 :
42733 0 : ae_assert(qcolumns<=m, "UnpackQFromQR: QColumns>M!", _state);
42734 0 : if( (m<=0||n<=0)||qcolumns<=0 )
42735 : {
42736 0 : ae_frame_leave(_state);
42737 0 : return;
42738 : }
42739 :
42740 : /*
42741 : * init
42742 : */
42743 0 : ts = matrixtilesizeb(_state);
42744 0 : minmn = ae_minint(m, n, _state);
42745 0 : refcnt = ae_minint(minmn, qcolumns, _state);
42746 0 : ae_matrix_set_length(q, m, qcolumns, _state);
42747 0 : for(i=0; i<=m-1; i++)
42748 : {
42749 0 : for(j=0; j<=qcolumns-1; j++)
42750 : {
42751 0 : if( i==j )
42752 : {
42753 0 : q->ptr.pp_double[i][j] = (double)(1);
42754 : }
42755 : else
42756 : {
42757 0 : q->ptr.pp_double[i][j] = (double)(0);
42758 : }
42759 : }
42760 : }
42761 0 : ae_vector_set_length(&work, ae_maxint(m, qcolumns, _state)+1, _state);
42762 0 : ae_vector_set_length(&t, ae_maxint(m, qcolumns, _state)+1, _state);
42763 0 : ae_vector_set_length(&taubuf, minmn, _state);
42764 0 : ae_matrix_set_length(&tmpa, m, ts, _state);
42765 0 : ae_matrix_set_length(&tmpt, ts, 2*ts, _state);
42766 0 : ae_matrix_set_length(&tmpr, 2*ts, qcolumns, _state);
42767 :
42768 : /*
42769 : * Blocked code
42770 : */
42771 0 : blockstart = ts*(refcnt/ts);
42772 0 : blocksize = refcnt-blockstart;
42773 0 : while(blockstart>=0)
42774 : {
42775 0 : rowscount = m-blockstart;
42776 0 : if( blocksize>0 )
42777 : {
42778 :
42779 : /*
42780 : * Copy current block
42781 : */
42782 0 : rmatrixcopy(rowscount, blocksize, a, blockstart, blockstart, &tmpa, 0, 0, _state);
42783 0 : ae_v_move(&taubuf.ptr.p_double[0], 1, &tau->ptr.p_double[blockstart], 1, ae_v_len(0,blocksize-1));
42784 :
42785 : /*
42786 : * Update, choose between:
42787 : * a) Level 2 algorithm (when the rest of the matrix is small enough)
42788 : * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY
42789 : * representation for products of Householder transformations',
42790 : * by R. Schreiber and C. Van Loan.
42791 : */
42792 0 : if( qcolumns>=2*ts )
42793 : {
42794 :
42795 : /*
42796 : * Prepare block reflector
42797 : */
42798 0 : ortfac_rmatrixblockreflector(&tmpa, &taubuf, ae_true, rowscount, blocksize, &tmpt, &work, _state);
42799 :
42800 : /*
42801 : * Multiply matrix by Q.
42802 : *
42803 : * Q = E + Y*T*Y' = E + TmpA*TmpT*TmpA'
42804 : */
42805 0 : rmatrixgemm(blocksize, qcolumns, rowscount, 1.0, &tmpa, 0, 0, 1, q, blockstart, 0, 0, 0.0, &tmpr, 0, 0, _state);
42806 0 : rmatrixgemm(blocksize, qcolumns, blocksize, 1.0, &tmpt, 0, 0, 0, &tmpr, 0, 0, 0, 0.0, &tmpr, blocksize, 0, _state);
42807 0 : rmatrixgemm(rowscount, qcolumns, blocksize, 1.0, &tmpa, 0, 0, 0, &tmpr, blocksize, 0, 0, 1.0, q, blockstart, 0, _state);
42808 : }
42809 : else
42810 : {
42811 :
42812 : /*
42813 : * Level 2 algorithm
42814 : */
42815 0 : for(i=blocksize-1; i>=0; i--)
42816 : {
42817 0 : ae_v_move(&t.ptr.p_double[1], 1, &tmpa.ptr.pp_double[i][i], tmpa.stride, ae_v_len(1,rowscount-i));
42818 0 : t.ptr.p_double[1] = (double)(1);
42819 0 : applyreflectionfromtheleft(q, taubuf.ptr.p_double[i], &t, blockstart+i, m-1, 0, qcolumns-1, &work, _state);
42820 : }
42821 : }
42822 : }
42823 :
42824 : /*
42825 : * Advance
42826 : */
42827 0 : blockstart = blockstart-ts;
42828 0 : blocksize = ts;
42829 : }
42830 0 : ae_frame_leave(_state);
42831 : }
42832 :
42833 :
42834 : /*************************************************************************
42835 : Unpacking of matrix R from the QR decomposition of a matrix A
42836 :
42837 : Input parameters:
42838 : A - matrices Q and R in compact form.
42839 : Output of RMatrixQR subroutine.
42840 : M - number of rows in given matrix A. M>=0.
42841 : N - number of columns in given matrix A. N>=0.
42842 :
42843 : Output parameters:
42844 : R - matrix R, array[0..M-1, 0..N-1].
42845 :
42846 : -- ALGLIB routine --
42847 : 17.02.2010
42848 : Bochkanov Sergey
42849 : *************************************************************************/
42850 0 : void rmatrixqrunpackr(/* Real */ ae_matrix* a,
42851 : ae_int_t m,
42852 : ae_int_t n,
42853 : /* Real */ ae_matrix* r,
42854 : ae_state *_state)
42855 : {
42856 : ae_int_t i;
42857 : ae_int_t k;
42858 :
42859 0 : ae_matrix_clear(r);
42860 :
42861 0 : if( m<=0||n<=0 )
42862 : {
42863 0 : return;
42864 : }
42865 0 : k = ae_minint(m, n, _state);
42866 0 : ae_matrix_set_length(r, m, n, _state);
42867 0 : for(i=0; i<=n-1; i++)
42868 : {
42869 0 : r->ptr.pp_double[0][i] = (double)(0);
42870 : }
42871 0 : for(i=1; i<=m-1; i++)
42872 : {
42873 0 : ae_v_move(&r->ptr.pp_double[i][0], 1, &r->ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
42874 : }
42875 0 : for(i=0; i<=k-1; i++)
42876 : {
42877 0 : ae_v_move(&r->ptr.pp_double[i][i], 1, &a->ptr.pp_double[i][i], 1, ae_v_len(i,n-1));
42878 : }
42879 : }
42880 :
42881 :
42882 : /*************************************************************************
42883 : Partial unpacking of matrix Q from the LQ decomposition of a matrix A
42884 :
42885 : ! COMMERCIAL EDITION OF ALGLIB:
42886 : !
42887 : ! Commercial Edition of ALGLIB includes following important improvements
42888 : ! of this function:
42889 : ! * high-performance native backend with same C# interface (C# version)
42890 : ! * multithreading support (C++ and C# versions)
42891 : ! * hardware vendor (Intel) implementations of linear algebra primitives
42892 : ! (C++ and C# versions, x86/x64 platform)
42893 : !
42894 : ! We recommend you to read 'Working with commercial version' section of
42895 : ! ALGLIB Reference Manual in order to find out how to use performance-
42896 : ! related features provided by commercial edition of ALGLIB.
42897 :
42898 : Input parameters:
42899 : A - matrices L and Q in compact form.
42900 : Output of RMatrixLQ subroutine.
42901 : M - number of rows in given matrix A. M>=0.
42902 : N - number of columns in given matrix A. N>=0.
42903 : Tau - scalar factors which are used to form Q.
42904 : Output of the RMatrixLQ subroutine.
42905 : QRows - required number of rows in matrix Q. N>=QRows>=0.
42906 :
42907 : Output parameters:
42908 : Q - first QRows rows of matrix Q. Array whose indexes range
42909 : within [0..QRows-1, 0..N-1]. If QRows=0, the array remains
42910 : unchanged.
42911 :
42912 : -- ALGLIB routine --
42913 : 17.02.2010
42914 : Bochkanov Sergey
42915 : *************************************************************************/
42916 0 : void rmatrixlqunpackq(/* Real */ ae_matrix* a,
42917 : ae_int_t m,
42918 : ae_int_t n,
42919 : /* Real */ ae_vector* tau,
42920 : ae_int_t qrows,
42921 : /* Real */ ae_matrix* q,
42922 : ae_state *_state)
42923 : {
42924 : ae_frame _frame_block;
42925 : ae_vector work;
42926 : ae_vector t;
42927 : ae_vector taubuf;
42928 : ae_int_t minmn;
42929 : ae_int_t refcnt;
42930 : ae_matrix tmpa;
42931 : ae_matrix tmpt;
42932 : ae_matrix tmpr;
42933 : ae_int_t blockstart;
42934 : ae_int_t blocksize;
42935 : ae_int_t columnscount;
42936 : ae_int_t i;
42937 : ae_int_t j;
42938 : ae_int_t ts;
42939 :
42940 0 : ae_frame_make(_state, &_frame_block);
42941 0 : memset(&work, 0, sizeof(work));
42942 0 : memset(&t, 0, sizeof(t));
42943 0 : memset(&taubuf, 0, sizeof(taubuf));
42944 0 : memset(&tmpa, 0, sizeof(tmpa));
42945 0 : memset(&tmpt, 0, sizeof(tmpt));
42946 0 : memset(&tmpr, 0, sizeof(tmpr));
42947 0 : ae_matrix_clear(q);
42948 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
42949 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
42950 0 : ae_vector_init(&taubuf, 0, DT_REAL, _state, ae_true);
42951 0 : ae_matrix_init(&tmpa, 0, 0, DT_REAL, _state, ae_true);
42952 0 : ae_matrix_init(&tmpt, 0, 0, DT_REAL, _state, ae_true);
42953 0 : ae_matrix_init(&tmpr, 0, 0, DT_REAL, _state, ae_true);
42954 :
42955 0 : ae_assert(qrows<=n, "RMatrixLQUnpackQ: QRows>N!", _state);
42956 0 : if( (m<=0||n<=0)||qrows<=0 )
42957 : {
42958 0 : ae_frame_leave(_state);
42959 0 : return;
42960 : }
42961 :
42962 : /*
42963 : * init
42964 : */
42965 0 : ts = matrixtilesizeb(_state);
42966 0 : minmn = ae_minint(m, n, _state);
42967 0 : refcnt = ae_minint(minmn, qrows, _state);
42968 0 : ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state);
42969 0 : ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state);
42970 0 : ae_vector_set_length(&taubuf, minmn, _state);
42971 0 : ae_matrix_set_length(&tmpa, ts, n, _state);
42972 0 : ae_matrix_set_length(&tmpt, ts, 2*ts, _state);
42973 0 : ae_matrix_set_length(&tmpr, qrows, 2*ts, _state);
42974 0 : ae_matrix_set_length(q, qrows, n, _state);
42975 0 : for(i=0; i<=qrows-1; i++)
42976 : {
42977 0 : for(j=0; j<=n-1; j++)
42978 : {
42979 0 : if( i==j )
42980 : {
42981 0 : q->ptr.pp_double[i][j] = (double)(1);
42982 : }
42983 : else
42984 : {
42985 0 : q->ptr.pp_double[i][j] = (double)(0);
42986 : }
42987 : }
42988 : }
42989 :
42990 : /*
42991 : * Blocked code
42992 : */
42993 0 : blockstart = ts*(refcnt/ts);
42994 0 : blocksize = refcnt-blockstart;
42995 0 : while(blockstart>=0)
42996 : {
42997 0 : columnscount = n-blockstart;
42998 0 : if( blocksize>0 )
42999 : {
43000 :
43001 : /*
43002 : * Copy submatrix
43003 : */
43004 0 : rmatrixcopy(blocksize, columnscount, a, blockstart, blockstart, &tmpa, 0, 0, _state);
43005 0 : ae_v_move(&taubuf.ptr.p_double[0], 1, &tau->ptr.p_double[blockstart], 1, ae_v_len(0,blocksize-1));
43006 :
43007 : /*
43008 : * Update matrix, choose between:
43009 : * a) Level 2 algorithm (when the rest of the matrix is small enough)
43010 : * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY
43011 : * representation for products of Householder transformations',
43012 : * by R. Schreiber and C. Van Loan.
43013 : */
43014 0 : if( qrows>=2*ts )
43015 : {
43016 :
43017 : /*
43018 : * Prepare block reflector
43019 : */
43020 0 : ortfac_rmatrixblockreflector(&tmpa, &taubuf, ae_false, columnscount, blocksize, &tmpt, &work, _state);
43021 :
43022 : /*
43023 : * Multiply the rest of A by Q'.
43024 : *
43025 : * Q' = E + Y*T'*Y' = E + TmpA'*TmpT'*TmpA
43026 : */
43027 0 : rmatrixgemm(qrows, blocksize, columnscount, 1.0, q, 0, blockstart, 0, &tmpa, 0, 0, 1, 0.0, &tmpr, 0, 0, _state);
43028 0 : rmatrixgemm(qrows, blocksize, blocksize, 1.0, &tmpr, 0, 0, 0, &tmpt, 0, 0, 1, 0.0, &tmpr, 0, blocksize, _state);
43029 0 : rmatrixgemm(qrows, columnscount, blocksize, 1.0, &tmpr, 0, blocksize, 0, &tmpa, 0, 0, 0, 1.0, q, 0, blockstart, _state);
43030 : }
43031 : else
43032 : {
43033 :
43034 : /*
43035 : * Level 2 algorithm
43036 : */
43037 0 : for(i=blocksize-1; i>=0; i--)
43038 : {
43039 0 : ae_v_move(&t.ptr.p_double[1], 1, &tmpa.ptr.pp_double[i][i], 1, ae_v_len(1,columnscount-i));
43040 0 : t.ptr.p_double[1] = (double)(1);
43041 0 : applyreflectionfromtheright(q, taubuf.ptr.p_double[i], &t, 0, qrows-1, blockstart+i, n-1, &work, _state);
43042 : }
43043 : }
43044 : }
43045 :
43046 : /*
43047 : * Advance
43048 : */
43049 0 : blockstart = blockstart-ts;
43050 0 : blocksize = ts;
43051 : }
43052 0 : ae_frame_leave(_state);
43053 : }
43054 :
43055 :
43056 : /*************************************************************************
43057 : Unpacking of matrix L from the LQ decomposition of a matrix A
43058 :
43059 : Input parameters:
43060 : A - matrices Q and L in compact form.
43061 : Output of RMatrixLQ subroutine.
43062 : M - number of rows in given matrix A. M>=0.
43063 : N - number of columns in given matrix A. N>=0.
43064 :
43065 : Output parameters:
43066 : L - matrix L, array[0..M-1, 0..N-1].
43067 :
43068 : -- ALGLIB routine --
43069 : 17.02.2010
43070 : Bochkanov Sergey
43071 : *************************************************************************/
43072 0 : void rmatrixlqunpackl(/* Real */ ae_matrix* a,
43073 : ae_int_t m,
43074 : ae_int_t n,
43075 : /* Real */ ae_matrix* l,
43076 : ae_state *_state)
43077 : {
43078 : ae_int_t i;
43079 : ae_int_t k;
43080 :
43081 0 : ae_matrix_clear(l);
43082 :
43083 0 : if( m<=0||n<=0 )
43084 : {
43085 0 : return;
43086 : }
43087 0 : ae_matrix_set_length(l, m, n, _state);
43088 0 : for(i=0; i<=n-1; i++)
43089 : {
43090 0 : l->ptr.pp_double[0][i] = (double)(0);
43091 : }
43092 0 : for(i=1; i<=m-1; i++)
43093 : {
43094 0 : ae_v_move(&l->ptr.pp_double[i][0], 1, &l->ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
43095 : }
43096 0 : for(i=0; i<=m-1; i++)
43097 : {
43098 0 : k = ae_minint(i, n-1, _state);
43099 0 : ae_v_move(&l->ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,k));
43100 : }
43101 : }
43102 :
43103 :
43104 : /*************************************************************************
43105 : Partial unpacking of matrix Q from QR decomposition of a complex matrix A.
43106 :
43107 : ! COMMERCIAL EDITION OF ALGLIB:
43108 : !
43109 : ! Commercial Edition of ALGLIB includes following important improvements
43110 : ! of this function:
43111 : ! * high-performance native backend with same C# interface (C# version)
43112 : ! * multithreading support (C++ and C# versions)
43113 : ! * hardware vendor (Intel) implementations of linear algebra primitives
43114 : ! (C++ and C# versions, x86/x64 platform)
43115 : !
43116 : ! We recommend you to read 'Working with commercial version' section of
43117 : ! ALGLIB Reference Manual in order to find out how to use performance-
43118 : ! related features provided by commercial edition of ALGLIB.
43119 :
43120 : Input parameters:
43121 : A - matrices Q and R in compact form.
43122 : Output of CMatrixQR subroutine .
43123 : M - number of rows in matrix A. M>=0.
43124 : N - number of columns in matrix A. N>=0.
43125 : Tau - scalar factors which are used to form Q.
43126 : Output of CMatrixQR subroutine .
43127 : QColumns - required number of columns in matrix Q. M>=QColumns>=0.
43128 :
43129 : Output parameters:
43130 : Q - first QColumns columns of matrix Q.
43131 : Array whose index ranges within [0..M-1, 0..QColumns-1].
43132 : If QColumns=0, array isn't changed.
43133 :
43134 : -- ALGLIB routine --
43135 : 17.02.2010
43136 : Bochkanov Sergey
43137 : *************************************************************************/
43138 0 : void cmatrixqrunpackq(/* Complex */ ae_matrix* a,
43139 : ae_int_t m,
43140 : ae_int_t n,
43141 : /* Complex */ ae_vector* tau,
43142 : ae_int_t qcolumns,
43143 : /* Complex */ ae_matrix* q,
43144 : ae_state *_state)
43145 : {
43146 : ae_frame _frame_block;
43147 : ae_vector work;
43148 : ae_vector t;
43149 : ae_vector taubuf;
43150 : ae_int_t minmn;
43151 : ae_int_t refcnt;
43152 : ae_matrix tmpa;
43153 : ae_matrix tmpt;
43154 : ae_matrix tmpr;
43155 : ae_int_t blockstart;
43156 : ae_int_t blocksize;
43157 : ae_int_t rowscount;
43158 : ae_int_t i;
43159 : ae_int_t j;
43160 : ae_int_t ts;
43161 :
43162 0 : ae_frame_make(_state, &_frame_block);
43163 0 : memset(&work, 0, sizeof(work));
43164 0 : memset(&t, 0, sizeof(t));
43165 0 : memset(&taubuf, 0, sizeof(taubuf));
43166 0 : memset(&tmpa, 0, sizeof(tmpa));
43167 0 : memset(&tmpt, 0, sizeof(tmpt));
43168 0 : memset(&tmpr, 0, sizeof(tmpr));
43169 0 : ae_matrix_clear(q);
43170 0 : ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true);
43171 0 : ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true);
43172 0 : ae_vector_init(&taubuf, 0, DT_COMPLEX, _state, ae_true);
43173 0 : ae_matrix_init(&tmpa, 0, 0, DT_COMPLEX, _state, ae_true);
43174 0 : ae_matrix_init(&tmpt, 0, 0, DT_COMPLEX, _state, ae_true);
43175 0 : ae_matrix_init(&tmpr, 0, 0, DT_COMPLEX, _state, ae_true);
43176 :
43177 0 : ae_assert(qcolumns<=m, "UnpackQFromQR: QColumns>M!", _state);
43178 0 : if( m<=0||n<=0 )
43179 : {
43180 0 : ae_frame_leave(_state);
43181 0 : return;
43182 : }
43183 :
43184 : /*
43185 : * init
43186 : */
43187 0 : ts = matrixtilesizeb(_state)/2;
43188 0 : minmn = ae_minint(m, n, _state);
43189 0 : refcnt = ae_minint(minmn, qcolumns, _state);
43190 0 : ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state);
43191 0 : ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state);
43192 0 : ae_vector_set_length(&taubuf, minmn, _state);
43193 0 : ae_matrix_set_length(&tmpa, m, ts, _state);
43194 0 : ae_matrix_set_length(&tmpt, ts, ts, _state);
43195 0 : ae_matrix_set_length(&tmpr, 2*ts, qcolumns, _state);
43196 0 : ae_matrix_set_length(q, m, qcolumns, _state);
43197 0 : for(i=0; i<=m-1; i++)
43198 : {
43199 0 : for(j=0; j<=qcolumns-1; j++)
43200 : {
43201 0 : if( i==j )
43202 : {
43203 0 : q->ptr.pp_complex[i][j] = ae_complex_from_i(1);
43204 : }
43205 : else
43206 : {
43207 0 : q->ptr.pp_complex[i][j] = ae_complex_from_i(0);
43208 : }
43209 : }
43210 : }
43211 :
43212 : /*
43213 : * Blocked code
43214 : */
43215 0 : blockstart = ts*(refcnt/ts);
43216 0 : blocksize = refcnt-blockstart;
43217 0 : while(blockstart>=0)
43218 : {
43219 0 : rowscount = m-blockstart;
43220 0 : if( blocksize>0 )
43221 : {
43222 :
43223 : /*
43224 : * QR decomposition of submatrix.
43225 : * Matrix is copied to temporary storage to solve
43226 : * some TLB issues arising from non-contiguous memory
43227 : * access pattern.
43228 : */
43229 0 : cmatrixcopy(rowscount, blocksize, a, blockstart, blockstart, &tmpa, 0, 0, _state);
43230 0 : ae_v_cmove(&taubuf.ptr.p_complex[0], 1, &tau->ptr.p_complex[blockstart], 1, "N", ae_v_len(0,blocksize-1));
43231 :
43232 : /*
43233 : * Update matrix, choose between:
43234 : * a) Level 2 algorithm (when the rest of the matrix is small enough)
43235 : * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY
43236 : * representation for products of Householder transformations',
43237 : * by R. Schreiber and C. Van Loan.
43238 : */
43239 0 : if( qcolumns>=2*ts )
43240 : {
43241 :
43242 : /*
43243 : * Prepare block reflector
43244 : */
43245 0 : ortfac_cmatrixblockreflector(&tmpa, &taubuf, ae_true, rowscount, blocksize, &tmpt, &work, _state);
43246 :
43247 : /*
43248 : * Multiply the rest of A by Q.
43249 : *
43250 : * Q = E + Y*T*Y' = E + TmpA*TmpT*TmpA'
43251 : */
43252 0 : cmatrixgemm(blocksize, qcolumns, rowscount, ae_complex_from_d(1.0), &tmpa, 0, 0, 2, q, blockstart, 0, 0, ae_complex_from_d(0.0), &tmpr, 0, 0, _state);
43253 0 : cmatrixgemm(blocksize, qcolumns, blocksize, ae_complex_from_d(1.0), &tmpt, 0, 0, 0, &tmpr, 0, 0, 0, ae_complex_from_d(0.0), &tmpr, blocksize, 0, _state);
43254 0 : cmatrixgemm(rowscount, qcolumns, blocksize, ae_complex_from_d(1.0), &tmpa, 0, 0, 0, &tmpr, blocksize, 0, 0, ae_complex_from_d(1.0), q, blockstart, 0, _state);
43255 : }
43256 : else
43257 : {
43258 :
43259 : /*
43260 : * Level 2 algorithm
43261 : */
43262 0 : for(i=blocksize-1; i>=0; i--)
43263 : {
43264 0 : ae_v_cmove(&t.ptr.p_complex[1], 1, &tmpa.ptr.pp_complex[i][i], tmpa.stride, "N", ae_v_len(1,rowscount-i));
43265 0 : t.ptr.p_complex[1] = ae_complex_from_i(1);
43266 0 : complexapplyreflectionfromtheleft(q, taubuf.ptr.p_complex[i], &t, blockstart+i, m-1, 0, qcolumns-1, &work, _state);
43267 : }
43268 : }
43269 : }
43270 :
43271 : /*
43272 : * Advance
43273 : */
43274 0 : blockstart = blockstart-ts;
43275 0 : blocksize = ts;
43276 : }
43277 0 : ae_frame_leave(_state);
43278 : }
43279 :
43280 :
43281 : /*************************************************************************
43282 : Unpacking of matrix R from the QR decomposition of a matrix A
43283 :
43284 : Input parameters:
43285 : A - matrices Q and R in compact form.
43286 : Output of CMatrixQR subroutine.
43287 : M - number of rows in given matrix A. M>=0.
43288 : N - number of columns in given matrix A. N>=0.
43289 :
43290 : Output parameters:
43291 : R - matrix R, array[0..M-1, 0..N-1].
43292 :
43293 : -- ALGLIB routine --
43294 : 17.02.2010
43295 : Bochkanov Sergey
43296 : *************************************************************************/
43297 0 : void cmatrixqrunpackr(/* Complex */ ae_matrix* a,
43298 : ae_int_t m,
43299 : ae_int_t n,
43300 : /* Complex */ ae_matrix* r,
43301 : ae_state *_state)
43302 : {
43303 : ae_int_t i;
43304 : ae_int_t k;
43305 :
43306 0 : ae_matrix_clear(r);
43307 :
43308 0 : if( m<=0||n<=0 )
43309 : {
43310 0 : return;
43311 : }
43312 0 : k = ae_minint(m, n, _state);
43313 0 : ae_matrix_set_length(r, m, n, _state);
43314 0 : for(i=0; i<=n-1; i++)
43315 : {
43316 0 : r->ptr.pp_complex[0][i] = ae_complex_from_i(0);
43317 : }
43318 0 : for(i=1; i<=m-1; i++)
43319 : {
43320 0 : ae_v_cmove(&r->ptr.pp_complex[i][0], 1, &r->ptr.pp_complex[0][0], 1, "N", ae_v_len(0,n-1));
43321 : }
43322 0 : for(i=0; i<=k-1; i++)
43323 : {
43324 0 : ae_v_cmove(&r->ptr.pp_complex[i][i], 1, &a->ptr.pp_complex[i][i], 1, "N", ae_v_len(i,n-1));
43325 : }
43326 : }
43327 :
43328 :
43329 : /*************************************************************************
43330 : Partial unpacking of matrix Q from LQ decomposition of a complex matrix A.
43331 :
43332 : ! COMMERCIAL EDITION OF ALGLIB:
43333 : !
43334 : ! Commercial Edition of ALGLIB includes following important improvements
43335 : ! of this function:
43336 : ! * high-performance native backend with same C# interface (C# version)
43337 : ! * multithreading support (C++ and C# versions)
43338 : ! * hardware vendor (Intel) implementations of linear algebra primitives
43339 : ! (C++ and C# versions, x86/x64 platform)
43340 : !
43341 : ! We recommend you to read 'Working with commercial version' section of
43342 : ! ALGLIB Reference Manual in order to find out how to use performance-
43343 : ! related features provided by commercial edition of ALGLIB.
43344 :
43345 : Input parameters:
43346 : A - matrices Q and R in compact form.
43347 : Output of CMatrixLQ subroutine .
43348 : M - number of rows in matrix A. M>=0.
43349 : N - number of columns in matrix A. N>=0.
43350 : Tau - scalar factors which are used to form Q.
43351 : Output of CMatrixLQ subroutine .
43352 : QRows - required number of rows in matrix Q. N>=QColumns>=0.
43353 :
43354 : Output parameters:
43355 : Q - first QRows rows of matrix Q.
43356 : Array whose index ranges within [0..QRows-1, 0..N-1].
43357 : If QRows=0, array isn't changed.
43358 :
43359 : -- ALGLIB routine --
43360 : 17.02.2010
43361 : Bochkanov Sergey
43362 : *************************************************************************/
43363 0 : void cmatrixlqunpackq(/* Complex */ ae_matrix* a,
43364 : ae_int_t m,
43365 : ae_int_t n,
43366 : /* Complex */ ae_vector* tau,
43367 : ae_int_t qrows,
43368 : /* Complex */ ae_matrix* q,
43369 : ae_state *_state)
43370 : {
43371 : ae_frame _frame_block;
43372 : ae_vector work;
43373 : ae_vector t;
43374 : ae_vector taubuf;
43375 : ae_int_t minmn;
43376 : ae_int_t refcnt;
43377 : ae_matrix tmpa;
43378 : ae_matrix tmpt;
43379 : ae_matrix tmpr;
43380 : ae_int_t blockstart;
43381 : ae_int_t blocksize;
43382 : ae_int_t columnscount;
43383 : ae_int_t i;
43384 : ae_int_t j;
43385 : ae_int_t ts;
43386 :
43387 0 : ae_frame_make(_state, &_frame_block);
43388 0 : memset(&work, 0, sizeof(work));
43389 0 : memset(&t, 0, sizeof(t));
43390 0 : memset(&taubuf, 0, sizeof(taubuf));
43391 0 : memset(&tmpa, 0, sizeof(tmpa));
43392 0 : memset(&tmpt, 0, sizeof(tmpt));
43393 0 : memset(&tmpr, 0, sizeof(tmpr));
43394 0 : ae_matrix_clear(q);
43395 0 : ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true);
43396 0 : ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true);
43397 0 : ae_vector_init(&taubuf, 0, DT_COMPLEX, _state, ae_true);
43398 0 : ae_matrix_init(&tmpa, 0, 0, DT_COMPLEX, _state, ae_true);
43399 0 : ae_matrix_init(&tmpt, 0, 0, DT_COMPLEX, _state, ae_true);
43400 0 : ae_matrix_init(&tmpr, 0, 0, DT_COMPLEX, _state, ae_true);
43401 :
43402 0 : if( m<=0||n<=0 )
43403 : {
43404 0 : ae_frame_leave(_state);
43405 0 : return;
43406 : }
43407 :
43408 : /*
43409 : * Init
43410 : */
43411 0 : ts = matrixtilesizeb(_state)/2;
43412 0 : minmn = ae_minint(m, n, _state);
43413 0 : refcnt = ae_minint(minmn, qrows, _state);
43414 0 : ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state);
43415 0 : ae_vector_set_length(&t, ae_maxint(m, n, _state)+1, _state);
43416 0 : ae_vector_set_length(&taubuf, minmn, _state);
43417 0 : ae_matrix_set_length(&tmpa, ts, n, _state);
43418 0 : ae_matrix_set_length(&tmpt, ts, ts, _state);
43419 0 : ae_matrix_set_length(&tmpr, qrows, 2*ts, _state);
43420 0 : ae_matrix_set_length(q, qrows, n, _state);
43421 0 : for(i=0; i<=qrows-1; i++)
43422 : {
43423 0 : for(j=0; j<=n-1; j++)
43424 : {
43425 0 : if( i==j )
43426 : {
43427 0 : q->ptr.pp_complex[i][j] = ae_complex_from_i(1);
43428 : }
43429 : else
43430 : {
43431 0 : q->ptr.pp_complex[i][j] = ae_complex_from_i(0);
43432 : }
43433 : }
43434 : }
43435 :
43436 : /*
43437 : * Blocked code
43438 : */
43439 0 : blockstart = ts*(refcnt/ts);
43440 0 : blocksize = refcnt-blockstart;
43441 0 : while(blockstart>=0)
43442 : {
43443 0 : columnscount = n-blockstart;
43444 0 : if( blocksize>0 )
43445 : {
43446 :
43447 : /*
43448 : * LQ decomposition of submatrix.
43449 : * Matrix is copied to temporary storage to solve
43450 : * some TLB issues arising from non-contiguous memory
43451 : * access pattern.
43452 : */
43453 0 : cmatrixcopy(blocksize, columnscount, a, blockstart, blockstart, &tmpa, 0, 0, _state);
43454 0 : ae_v_cmove(&taubuf.ptr.p_complex[0], 1, &tau->ptr.p_complex[blockstart], 1, "N", ae_v_len(0,blocksize-1));
43455 :
43456 : /*
43457 : * Update matrix, choose between:
43458 : * a) Level 2 algorithm (when the rest of the matrix is small enough)
43459 : * b) blocked algorithm, see algorithm 5 from 'A storage efficient WY
43460 : * representation for products of Householder transformations',
43461 : * by R. Schreiber and C. Van Loan.
43462 : */
43463 0 : if( qrows>=2*ts )
43464 : {
43465 :
43466 : /*
43467 : * Prepare block reflector
43468 : */
43469 0 : ortfac_cmatrixblockreflector(&tmpa, &taubuf, ae_false, columnscount, blocksize, &tmpt, &work, _state);
43470 :
43471 : /*
43472 : * Multiply the rest of A by Q'.
43473 : *
43474 : * Q' = E + Y*T'*Y' = E + TmpA'*TmpT'*TmpA
43475 : */
43476 0 : cmatrixgemm(qrows, blocksize, columnscount, ae_complex_from_d(1.0), q, 0, blockstart, 0, &tmpa, 0, 0, 2, ae_complex_from_d(0.0), &tmpr, 0, 0, _state);
43477 0 : cmatrixgemm(qrows, blocksize, blocksize, ae_complex_from_d(1.0), &tmpr, 0, 0, 0, &tmpt, 0, 0, 2, ae_complex_from_d(0.0), &tmpr, 0, blocksize, _state);
43478 0 : cmatrixgemm(qrows, columnscount, blocksize, ae_complex_from_d(1.0), &tmpr, 0, blocksize, 0, &tmpa, 0, 0, 0, ae_complex_from_d(1.0), q, 0, blockstart, _state);
43479 : }
43480 : else
43481 : {
43482 :
43483 : /*
43484 : * Level 2 algorithm
43485 : */
43486 0 : for(i=blocksize-1; i>=0; i--)
43487 : {
43488 0 : ae_v_cmove(&t.ptr.p_complex[1], 1, &tmpa.ptr.pp_complex[i][i], 1, "Conj", ae_v_len(1,columnscount-i));
43489 0 : t.ptr.p_complex[1] = ae_complex_from_i(1);
43490 0 : complexapplyreflectionfromtheright(q, ae_c_conj(taubuf.ptr.p_complex[i], _state), &t, 0, qrows-1, blockstart+i, n-1, &work, _state);
43491 : }
43492 : }
43493 : }
43494 :
43495 : /*
43496 : * Advance
43497 : */
43498 0 : blockstart = blockstart-ts;
43499 0 : blocksize = ts;
43500 : }
43501 0 : ae_frame_leave(_state);
43502 : }
43503 :
43504 :
43505 : /*************************************************************************
43506 : Unpacking of matrix L from the LQ decomposition of a matrix A
43507 :
43508 : Input parameters:
43509 : A - matrices Q and L in compact form.
43510 : Output of CMatrixLQ subroutine.
43511 : M - number of rows in given matrix A. M>=0.
43512 : N - number of columns in given matrix A. N>=0.
43513 :
43514 : Output parameters:
43515 : L - matrix L, array[0..M-1, 0..N-1].
43516 :
43517 : -- ALGLIB routine --
43518 : 17.02.2010
43519 : Bochkanov Sergey
43520 : *************************************************************************/
43521 0 : void cmatrixlqunpackl(/* Complex */ ae_matrix* a,
43522 : ae_int_t m,
43523 : ae_int_t n,
43524 : /* Complex */ ae_matrix* l,
43525 : ae_state *_state)
43526 : {
43527 : ae_int_t i;
43528 : ae_int_t k;
43529 :
43530 0 : ae_matrix_clear(l);
43531 :
43532 0 : if( m<=0||n<=0 )
43533 : {
43534 0 : return;
43535 : }
43536 0 : ae_matrix_set_length(l, m, n, _state);
43537 0 : for(i=0; i<=n-1; i++)
43538 : {
43539 0 : l->ptr.pp_complex[0][i] = ae_complex_from_i(0);
43540 : }
43541 0 : for(i=1; i<=m-1; i++)
43542 : {
43543 0 : ae_v_cmove(&l->ptr.pp_complex[i][0], 1, &l->ptr.pp_complex[0][0], 1, "N", ae_v_len(0,n-1));
43544 : }
43545 0 : for(i=0; i<=m-1; i++)
43546 : {
43547 0 : k = ae_minint(i, n-1, _state);
43548 0 : ae_v_cmove(&l->ptr.pp_complex[i][0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,k));
43549 : }
43550 : }
43551 :
43552 :
43553 : /*************************************************************************
43554 : Base case for real QR
43555 :
43556 : -- LAPACK routine (version 3.0) --
43557 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
43558 : Courant Institute, Argonne National Lab, and Rice University
43559 : September 30, 1994.
43560 : Sergey Bochkanov, ALGLIB project, translation from FORTRAN to
43561 : pseudocode, 2007-2010.
43562 : *************************************************************************/
43563 0 : void rmatrixqrbasecase(/* Real */ ae_matrix* a,
43564 : ae_int_t m,
43565 : ae_int_t n,
43566 : /* Real */ ae_vector* work,
43567 : /* Real */ ae_vector* t,
43568 : /* Real */ ae_vector* tau,
43569 : ae_state *_state)
43570 : {
43571 : ae_int_t i;
43572 : ae_int_t k;
43573 : ae_int_t minmn;
43574 : double tmp;
43575 :
43576 :
43577 0 : minmn = ae_minint(m, n, _state);
43578 :
43579 : /*
43580 : * Test the input arguments
43581 : */
43582 0 : k = minmn;
43583 0 : for(i=0; i<=k-1; i++)
43584 : {
43585 :
43586 : /*
43587 : * Generate elementary reflector H(i) to annihilate A(i+1:m,i)
43588 : */
43589 0 : ae_v_move(&t->ptr.p_double[1], 1, &a->ptr.pp_double[i][i], a->stride, ae_v_len(1,m-i));
43590 0 : generatereflection(t, m-i, &tmp, _state);
43591 0 : tau->ptr.p_double[i] = tmp;
43592 0 : ae_v_move(&a->ptr.pp_double[i][i], a->stride, &t->ptr.p_double[1], 1, ae_v_len(i,m-1));
43593 0 : t->ptr.p_double[1] = (double)(1);
43594 0 : if( i<n )
43595 : {
43596 :
43597 : /*
43598 : * Apply H(i) to A(i:m-1,i+1:n-1) from the left
43599 : */
43600 0 : applyreflectionfromtheleft(a, tau->ptr.p_double[i], t, i, m-1, i+1, n-1, work, _state);
43601 : }
43602 : }
43603 0 : }
43604 :
43605 :
43606 : /*************************************************************************
43607 : Base case for real LQ
43608 :
43609 : -- LAPACK routine (version 3.0) --
43610 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
43611 : Courant Institute, Argonne National Lab, and Rice University
43612 : September 30, 1994.
43613 : Sergey Bochkanov, ALGLIB project, translation from FORTRAN to
43614 : pseudocode, 2007-2010.
43615 : *************************************************************************/
43616 0 : void rmatrixlqbasecase(/* Real */ ae_matrix* a,
43617 : ae_int_t m,
43618 : ae_int_t n,
43619 : /* Real */ ae_vector* work,
43620 : /* Real */ ae_vector* t,
43621 : /* Real */ ae_vector* tau,
43622 : ae_state *_state)
43623 : {
43624 : ae_int_t i;
43625 : ae_int_t k;
43626 : double tmp;
43627 :
43628 :
43629 0 : k = ae_minint(m, n, _state);
43630 0 : for(i=0; i<=k-1; i++)
43631 : {
43632 :
43633 : /*
43634 : * Generate elementary reflector H(i) to annihilate A(i,i+1:n-1)
43635 : */
43636 0 : ae_v_move(&t->ptr.p_double[1], 1, &a->ptr.pp_double[i][i], 1, ae_v_len(1,n-i));
43637 0 : generatereflection(t, n-i, &tmp, _state);
43638 0 : tau->ptr.p_double[i] = tmp;
43639 0 : ae_v_move(&a->ptr.pp_double[i][i], 1, &t->ptr.p_double[1], 1, ae_v_len(i,n-1));
43640 0 : t->ptr.p_double[1] = (double)(1);
43641 0 : if( i<n )
43642 : {
43643 :
43644 : /*
43645 : * Apply H(i) to A(i+1:m,i:n) from the right
43646 : */
43647 0 : applyreflectionfromtheright(a, tau->ptr.p_double[i], t, i+1, m-1, i, n-1, work, _state);
43648 : }
43649 : }
43650 0 : }
43651 :
43652 :
43653 : /*************************************************************************
43654 : Reduction of a rectangular matrix to bidiagonal form
43655 :
43656 : The algorithm reduces the rectangular matrix A to bidiagonal form by
43657 : orthogonal transformations P and Q: A = Q*B*(P^T).
43658 :
43659 : ! COMMERCIAL EDITION OF ALGLIB:
43660 : !
43661 : ! Commercial Edition of ALGLIB includes following important improvements
43662 : ! of this function:
43663 : ! * high-performance native backend with same C# interface (C# version)
43664 : ! * hardware vendor (Intel) implementations of linear algebra primitives
43665 : ! (C++ and C# versions, x86/x64 platform)
43666 : !
43667 : ! We recommend you to read 'Working with commercial version' section of
43668 : ! ALGLIB Reference Manual in order to find out how to use performance-
43669 : ! related features provided by commercial edition of ALGLIB.
43670 :
43671 : Input parameters:
43672 : A - source matrix. array[0..M-1, 0..N-1]
43673 : M - number of rows in matrix A.
43674 : N - number of columns in matrix A.
43675 :
43676 : Output parameters:
43677 : A - matrices Q, B, P in compact form (see below).
43678 : TauQ - scalar factors which are used to form matrix Q.
43679 : TauP - scalar factors which are used to form matrix P.
43680 :
43681 : The main diagonal and one of the secondary diagonals of matrix A are
43682 : replaced with bidiagonal matrix B. Other elements contain elementary
43683 : reflections which form MxM matrix Q and NxN matrix P, respectively.
43684 :
43685 : If M>=N, B is the upper bidiagonal MxN matrix and is stored in the
43686 : corresponding elements of matrix A. Matrix Q is represented as a
43687 : product of elementary reflections Q = H(0)*H(1)*...*H(n-1), where
43688 : H(i) = 1-tau*v*v'. Here tau is a scalar which is stored in TauQ[i], and
43689 : vector v has the following structure: v(0:i-1)=0, v(i)=1, v(i+1:m-1) is
43690 : stored in elements A(i+1:m-1,i). Matrix P is as follows: P =
43691 : G(0)*G(1)*...*G(n-2), where G(i) = 1 - tau*u*u'. Tau is stored in TauP[i],
43692 : u(0:i)=0, u(i+1)=1, u(i+2:n-1) is stored in elements A(i,i+2:n-1).
43693 :
43694 : If M<N, B is the lower bidiagonal MxN matrix and is stored in the
43695 : corresponding elements of matrix A. Q = H(0)*H(1)*...*H(m-2), where
43696 : H(i) = 1 - tau*v*v', tau is stored in TauQ, v(0:i)=0, v(i+1)=1, v(i+2:m-1)
43697 : is stored in elements A(i+2:m-1,i). P = G(0)*G(1)*...*G(m-1),
43698 : G(i) = 1-tau*u*u', tau is stored in TauP, u(0:i-1)=0, u(i)=1, u(i+1:n-1)
43699 : is stored in A(i,i+1:n-1).
43700 :
43701 : EXAMPLE:
43702 :
43703 : m=6, n=5 (m > n): m=5, n=6 (m < n):
43704 :
43705 : ( d e u1 u1 u1 ) ( d u1 u1 u1 u1 u1 )
43706 : ( v1 d e u2 u2 ) ( e d u2 u2 u2 u2 )
43707 : ( v1 v2 d e u3 ) ( v1 e d u3 u3 u3 )
43708 : ( v1 v2 v3 d e ) ( v1 v2 e d u4 u4 )
43709 : ( v1 v2 v3 v4 d ) ( v1 v2 v3 e d u5 )
43710 : ( v1 v2 v3 v4 v5 )
43711 :
43712 : Here vi and ui are vectors which form H(i) and G(i), and d and e -
43713 : are the diagonal and off-diagonal elements of matrix B.
43714 :
43715 : -- LAPACK routine (version 3.0) --
43716 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
43717 : Courant Institute, Argonne National Lab, and Rice University
43718 : September 30, 1994.
43719 : Sergey Bochkanov, ALGLIB project, translation from FORTRAN to
43720 : pseudocode, 2007-2010.
43721 : *************************************************************************/
43722 0 : void rmatrixbd(/* Real */ ae_matrix* a,
43723 : ae_int_t m,
43724 : ae_int_t n,
43725 : /* Real */ ae_vector* tauq,
43726 : /* Real */ ae_vector* taup,
43727 : ae_state *_state)
43728 : {
43729 : ae_frame _frame_block;
43730 : ae_vector work;
43731 : ae_vector t;
43732 : ae_int_t maxmn;
43733 : ae_int_t i;
43734 : double ltau;
43735 :
43736 0 : ae_frame_make(_state, &_frame_block);
43737 0 : memset(&work, 0, sizeof(work));
43738 0 : memset(&t, 0, sizeof(t));
43739 0 : ae_vector_clear(tauq);
43740 0 : ae_vector_clear(taup);
43741 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
43742 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
43743 :
43744 :
43745 : /*
43746 : * Prepare
43747 : */
43748 0 : if( n<=0||m<=0 )
43749 : {
43750 0 : ae_frame_leave(_state);
43751 0 : return;
43752 : }
43753 0 : maxmn = ae_maxint(m, n, _state);
43754 0 : ae_vector_set_length(&work, maxmn+1, _state);
43755 0 : ae_vector_set_length(&t, maxmn+1, _state);
43756 0 : if( m>=n )
43757 : {
43758 0 : ae_vector_set_length(tauq, n, _state);
43759 0 : ae_vector_set_length(taup, n, _state);
43760 0 : for(i=0; i<=n-1; i++)
43761 : {
43762 0 : tauq->ptr.p_double[i] = 0.0;
43763 0 : taup->ptr.p_double[i] = 0.0;
43764 : }
43765 : }
43766 : else
43767 : {
43768 0 : ae_vector_set_length(tauq, m, _state);
43769 0 : ae_vector_set_length(taup, m, _state);
43770 0 : for(i=0; i<=m-1; i++)
43771 : {
43772 0 : tauq->ptr.p_double[i] = 0.0;
43773 0 : taup->ptr.p_double[i] = 0.0;
43774 : }
43775 : }
43776 :
43777 : /*
43778 : * Try to use MKL code
43779 : *
43780 : * NOTE: buffers Work[] and T[] are used for temporary storage of diagonals;
43781 : * because they are present in A[], we do not use them.
43782 : */
43783 0 : if( rmatrixbdmkl(a, m, n, &work, &t, tauq, taup, _state) )
43784 : {
43785 0 : ae_frame_leave(_state);
43786 0 : return;
43787 : }
43788 :
43789 : /*
43790 : * ALGLIB code
43791 : */
43792 0 : if( m>=n )
43793 : {
43794 :
43795 : /*
43796 : * Reduce to upper bidiagonal form
43797 : */
43798 0 : for(i=0; i<=n-1; i++)
43799 : {
43800 :
43801 : /*
43802 : * Generate elementary reflector H(i) to annihilate A(i+1:m-1,i)
43803 : */
43804 0 : ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i][i], a->stride, ae_v_len(1,m-i));
43805 0 : generatereflection(&t, m-i, <au, _state);
43806 0 : tauq->ptr.p_double[i] = ltau;
43807 0 : ae_v_move(&a->ptr.pp_double[i][i], a->stride, &t.ptr.p_double[1], 1, ae_v_len(i,m-1));
43808 0 : t.ptr.p_double[1] = (double)(1);
43809 :
43810 : /*
43811 : * Apply H(i) to A(i:m-1,i+1:n-1) from the left
43812 : */
43813 0 : applyreflectionfromtheleft(a, ltau, &t, i, m-1, i+1, n-1, &work, _state);
43814 0 : if( i<n-1 )
43815 : {
43816 :
43817 : /*
43818 : * Generate elementary reflector G(i) to annihilate
43819 : * A(i,i+2:n-1)
43820 : */
43821 0 : ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i][i+1], 1, ae_v_len(1,n-i-1));
43822 0 : generatereflection(&t, n-1-i, <au, _state);
43823 0 : taup->ptr.p_double[i] = ltau;
43824 0 : ae_v_move(&a->ptr.pp_double[i][i+1], 1, &t.ptr.p_double[1], 1, ae_v_len(i+1,n-1));
43825 0 : t.ptr.p_double[1] = (double)(1);
43826 :
43827 : /*
43828 : * Apply G(i) to A(i+1:m-1,i+1:n-1) from the right
43829 : */
43830 0 : applyreflectionfromtheright(a, ltau, &t, i+1, m-1, i+1, n-1, &work, _state);
43831 : }
43832 : else
43833 : {
43834 0 : taup->ptr.p_double[i] = (double)(0);
43835 : }
43836 : }
43837 : }
43838 : else
43839 : {
43840 :
43841 : /*
43842 : * Reduce to lower bidiagonal form
43843 : */
43844 0 : for(i=0; i<=m-1; i++)
43845 : {
43846 :
43847 : /*
43848 : * Generate elementary reflector G(i) to annihilate A(i,i+1:n-1)
43849 : */
43850 0 : ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i][i], 1, ae_v_len(1,n-i));
43851 0 : generatereflection(&t, n-i, <au, _state);
43852 0 : taup->ptr.p_double[i] = ltau;
43853 0 : ae_v_move(&a->ptr.pp_double[i][i], 1, &t.ptr.p_double[1], 1, ae_v_len(i,n-1));
43854 0 : t.ptr.p_double[1] = (double)(1);
43855 :
43856 : /*
43857 : * Apply G(i) to A(i+1:m-1,i:n-1) from the right
43858 : */
43859 0 : applyreflectionfromtheright(a, ltau, &t, i+1, m-1, i, n-1, &work, _state);
43860 0 : if( i<m-1 )
43861 : {
43862 :
43863 : /*
43864 : * Generate elementary reflector H(i) to annihilate
43865 : * A(i+2:m-1,i)
43866 : */
43867 0 : ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,m-1-i));
43868 0 : generatereflection(&t, m-1-i, <au, _state);
43869 0 : tauq->ptr.p_double[i] = ltau;
43870 0 : ae_v_move(&a->ptr.pp_double[i+1][i], a->stride, &t.ptr.p_double[1], 1, ae_v_len(i+1,m-1));
43871 0 : t.ptr.p_double[1] = (double)(1);
43872 :
43873 : /*
43874 : * Apply H(i) to A(i+1:m-1,i+1:n-1) from the left
43875 : */
43876 0 : applyreflectionfromtheleft(a, ltau, &t, i+1, m-1, i+1, n-1, &work, _state);
43877 : }
43878 : else
43879 : {
43880 0 : tauq->ptr.p_double[i] = (double)(0);
43881 : }
43882 : }
43883 : }
43884 0 : ae_frame_leave(_state);
43885 : }
43886 :
43887 :
43888 : /*************************************************************************
43889 : Unpacking matrix Q which reduces a matrix to bidiagonal form.
43890 :
43891 : ! COMMERCIAL EDITION OF ALGLIB:
43892 : !
43893 : ! Commercial Edition of ALGLIB includes following important improvements
43894 : ! of this function:
43895 : ! * high-performance native backend with same C# interface (C# version)
43896 : ! * hardware vendor (Intel) implementations of linear algebra primitives
43897 : ! (C++ and C# versions, x86/x64 platform)
43898 : !
43899 : ! We recommend you to read 'Working with commercial version' section of
43900 : ! ALGLIB Reference Manual in order to find out how to use performance-
43901 : ! related features provided by commercial edition of ALGLIB.
43902 :
43903 : Input parameters:
43904 : QP - matrices Q and P in compact form.
43905 : Output of ToBidiagonal subroutine.
43906 : M - number of rows in matrix A.
43907 : N - number of columns in matrix A.
43908 : TAUQ - scalar factors which are used to form Q.
43909 : Output of ToBidiagonal subroutine.
43910 : QColumns - required number of columns in matrix Q.
43911 : M>=QColumns>=0.
43912 :
43913 : Output parameters:
43914 : Q - first QColumns columns of matrix Q.
43915 : Array[0..M-1, 0..QColumns-1]
43916 : If QColumns=0, the array is not modified.
43917 :
43918 : -- ALGLIB --
43919 : 2005-2010
43920 : Bochkanov Sergey
43921 : *************************************************************************/
43922 0 : void rmatrixbdunpackq(/* Real */ ae_matrix* qp,
43923 : ae_int_t m,
43924 : ae_int_t n,
43925 : /* Real */ ae_vector* tauq,
43926 : ae_int_t qcolumns,
43927 : /* Real */ ae_matrix* q,
43928 : ae_state *_state)
43929 : {
43930 : ae_int_t i;
43931 : ae_int_t j;
43932 :
43933 0 : ae_matrix_clear(q);
43934 :
43935 0 : ae_assert(qcolumns<=m, "RMatrixBDUnpackQ: QColumns>M!", _state);
43936 0 : ae_assert(qcolumns>=0, "RMatrixBDUnpackQ: QColumns<0!", _state);
43937 0 : if( (m==0||n==0)||qcolumns==0 )
43938 : {
43939 0 : return;
43940 : }
43941 :
43942 : /*
43943 : * prepare Q
43944 : */
43945 0 : ae_matrix_set_length(q, m, qcolumns, _state);
43946 0 : for(i=0; i<=m-1; i++)
43947 : {
43948 0 : for(j=0; j<=qcolumns-1; j++)
43949 : {
43950 0 : if( i==j )
43951 : {
43952 0 : q->ptr.pp_double[i][j] = (double)(1);
43953 : }
43954 : else
43955 : {
43956 0 : q->ptr.pp_double[i][j] = (double)(0);
43957 : }
43958 : }
43959 : }
43960 :
43961 : /*
43962 : * Calculate
43963 : */
43964 0 : rmatrixbdmultiplybyq(qp, m, n, tauq, q, m, qcolumns, ae_false, ae_false, _state);
43965 : }
43966 :
43967 :
43968 : /*************************************************************************
43969 : Multiplication by matrix Q which reduces matrix A to bidiagonal form.
43970 :
43971 : The algorithm allows pre- or post-multiply by Q or Q'.
43972 :
43973 : ! COMMERCIAL EDITION OF ALGLIB:
43974 : !
43975 : ! Commercial Edition of ALGLIB includes following important improvements
43976 : ! of this function:
43977 : ! * high-performance native backend with same C# interface (C# version)
43978 : ! * hardware vendor (Intel) implementations of linear algebra primitives
43979 : ! (C++ and C# versions, x86/x64 platform)
43980 : !
43981 : ! We recommend you to read 'Working with commercial version' section of
43982 : ! ALGLIB Reference Manual in order to find out how to use performance-
43983 : ! related features provided by commercial edition of ALGLIB.
43984 :
43985 : Input parameters:
43986 : QP - matrices Q and P in compact form.
43987 : Output of ToBidiagonal subroutine.
43988 : M - number of rows in matrix A.
43989 : N - number of columns in matrix A.
43990 : TAUQ - scalar factors which are used to form Q.
43991 : Output of ToBidiagonal subroutine.
43992 : Z - multiplied matrix.
43993 : array[0..ZRows-1,0..ZColumns-1]
43994 : ZRows - number of rows in matrix Z. If FromTheRight=False,
43995 : ZRows=M, otherwise ZRows can be arbitrary.
43996 : ZColumns - number of columns in matrix Z. If FromTheRight=True,
43997 : ZColumns=M, otherwise ZColumns can be arbitrary.
43998 : FromTheRight - pre- or post-multiply.
43999 : DoTranspose - multiply by Q or Q'.
44000 :
44001 : Output parameters:
44002 : Z - product of Z and Q.
44003 : Array[0..ZRows-1,0..ZColumns-1]
44004 : If ZRows=0 or ZColumns=0, the array is not modified.
44005 :
44006 : -- ALGLIB --
44007 : 2005-2010
44008 : Bochkanov Sergey
44009 : *************************************************************************/
44010 0 : void rmatrixbdmultiplybyq(/* Real */ ae_matrix* qp,
44011 : ae_int_t m,
44012 : ae_int_t n,
44013 : /* Real */ ae_vector* tauq,
44014 : /* Real */ ae_matrix* z,
44015 : ae_int_t zrows,
44016 : ae_int_t zcolumns,
44017 : ae_bool fromtheright,
44018 : ae_bool dotranspose,
44019 : ae_state *_state)
44020 : {
44021 : ae_frame _frame_block;
44022 : ae_int_t i;
44023 : ae_int_t i1;
44024 : ae_int_t i2;
44025 : ae_int_t istep;
44026 : ae_vector v;
44027 : ae_vector work;
44028 : ae_vector dummy;
44029 : ae_int_t mx;
44030 :
44031 0 : ae_frame_make(_state, &_frame_block);
44032 0 : memset(&v, 0, sizeof(v));
44033 0 : memset(&work, 0, sizeof(work));
44034 0 : memset(&dummy, 0, sizeof(dummy));
44035 0 : ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
44036 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
44037 0 : ae_vector_init(&dummy, 0, DT_REAL, _state, ae_true);
44038 :
44039 0 : if( ((m<=0||n<=0)||zrows<=0)||zcolumns<=0 )
44040 : {
44041 0 : ae_frame_leave(_state);
44042 0 : return;
44043 : }
44044 0 : ae_assert((fromtheright&&zcolumns==m)||(!fromtheright&&zrows==m), "RMatrixBDMultiplyByQ: incorrect Z size!", _state);
44045 :
44046 : /*
44047 : * Try to use MKL code
44048 : */
44049 0 : if( rmatrixbdmultiplybymkl(qp, m, n, tauq, &dummy, z, zrows, zcolumns, ae_true, fromtheright, dotranspose, _state) )
44050 : {
44051 0 : ae_frame_leave(_state);
44052 0 : return;
44053 : }
44054 :
44055 : /*
44056 : * init
44057 : */
44058 0 : mx = ae_maxint(m, n, _state);
44059 0 : mx = ae_maxint(mx, zrows, _state);
44060 0 : mx = ae_maxint(mx, zcolumns, _state);
44061 0 : ae_vector_set_length(&v, mx+1, _state);
44062 0 : ae_vector_set_length(&work, mx+1, _state);
44063 0 : if( m>=n )
44064 : {
44065 :
44066 : /*
44067 : * setup
44068 : */
44069 0 : if( fromtheright )
44070 : {
44071 0 : i1 = 0;
44072 0 : i2 = n-1;
44073 0 : istep = 1;
44074 : }
44075 : else
44076 : {
44077 0 : i1 = n-1;
44078 0 : i2 = 0;
44079 0 : istep = -1;
44080 : }
44081 0 : if( dotranspose )
44082 : {
44083 0 : i = i1;
44084 0 : i1 = i2;
44085 0 : i2 = i;
44086 0 : istep = -istep;
44087 : }
44088 :
44089 : /*
44090 : * Process
44091 : */
44092 0 : i = i1;
44093 0 : do
44094 : {
44095 0 : ae_v_move(&v.ptr.p_double[1], 1, &qp->ptr.pp_double[i][i], qp->stride, ae_v_len(1,m-i));
44096 0 : v.ptr.p_double[1] = (double)(1);
44097 0 : if( fromtheright )
44098 : {
44099 0 : applyreflectionfromtheright(z, tauq->ptr.p_double[i], &v, 0, zrows-1, i, m-1, &work, _state);
44100 : }
44101 : else
44102 : {
44103 0 : applyreflectionfromtheleft(z, tauq->ptr.p_double[i], &v, i, m-1, 0, zcolumns-1, &work, _state);
44104 : }
44105 0 : i = i+istep;
44106 : }
44107 0 : while(i!=i2+istep);
44108 : }
44109 : else
44110 : {
44111 :
44112 : /*
44113 : * setup
44114 : */
44115 0 : if( fromtheright )
44116 : {
44117 0 : i1 = 0;
44118 0 : i2 = m-2;
44119 0 : istep = 1;
44120 : }
44121 : else
44122 : {
44123 0 : i1 = m-2;
44124 0 : i2 = 0;
44125 0 : istep = -1;
44126 : }
44127 0 : if( dotranspose )
44128 : {
44129 0 : i = i1;
44130 0 : i1 = i2;
44131 0 : i2 = i;
44132 0 : istep = -istep;
44133 : }
44134 :
44135 : /*
44136 : * Process
44137 : */
44138 0 : if( m-1>0 )
44139 : {
44140 0 : i = i1;
44141 0 : do
44142 : {
44143 0 : ae_v_move(&v.ptr.p_double[1], 1, &qp->ptr.pp_double[i+1][i], qp->stride, ae_v_len(1,m-i-1));
44144 0 : v.ptr.p_double[1] = (double)(1);
44145 0 : if( fromtheright )
44146 : {
44147 0 : applyreflectionfromtheright(z, tauq->ptr.p_double[i], &v, 0, zrows-1, i+1, m-1, &work, _state);
44148 : }
44149 : else
44150 : {
44151 0 : applyreflectionfromtheleft(z, tauq->ptr.p_double[i], &v, i+1, m-1, 0, zcolumns-1, &work, _state);
44152 : }
44153 0 : i = i+istep;
44154 : }
44155 0 : while(i!=i2+istep);
44156 : }
44157 : }
44158 0 : ae_frame_leave(_state);
44159 : }
44160 :
44161 :
44162 : /*************************************************************************
44163 : Unpacking matrix P which reduces matrix A to bidiagonal form.
44164 : The subroutine returns transposed matrix P.
44165 :
44166 : Input parameters:
44167 : QP - matrices Q and P in compact form.
44168 : Output of ToBidiagonal subroutine.
44169 : M - number of rows in matrix A.
44170 : N - number of columns in matrix A.
44171 : TAUP - scalar factors which are used to form P.
44172 : Output of ToBidiagonal subroutine.
44173 : PTRows - required number of rows of matrix P^T. N >= PTRows >= 0.
44174 :
44175 : Output parameters:
44176 : PT - first PTRows columns of matrix P^T
44177 : Array[0..PTRows-1, 0..N-1]
44178 : If PTRows=0, the array is not modified.
44179 :
44180 : -- ALGLIB --
44181 : 2005-2010
44182 : Bochkanov Sergey
44183 : *************************************************************************/
44184 0 : void rmatrixbdunpackpt(/* Real */ ae_matrix* qp,
44185 : ae_int_t m,
44186 : ae_int_t n,
44187 : /* Real */ ae_vector* taup,
44188 : ae_int_t ptrows,
44189 : /* Real */ ae_matrix* pt,
44190 : ae_state *_state)
44191 : {
44192 : ae_int_t i;
44193 : ae_int_t j;
44194 :
44195 0 : ae_matrix_clear(pt);
44196 :
44197 0 : ae_assert(ptrows<=n, "RMatrixBDUnpackPT: PTRows>N!", _state);
44198 0 : ae_assert(ptrows>=0, "RMatrixBDUnpackPT: PTRows<0!", _state);
44199 0 : if( (m==0||n==0)||ptrows==0 )
44200 : {
44201 0 : return;
44202 : }
44203 :
44204 : /*
44205 : * prepare PT
44206 : */
44207 0 : ae_matrix_set_length(pt, ptrows, n, _state);
44208 0 : for(i=0; i<=ptrows-1; i++)
44209 : {
44210 0 : for(j=0; j<=n-1; j++)
44211 : {
44212 0 : if( i==j )
44213 : {
44214 0 : pt->ptr.pp_double[i][j] = (double)(1);
44215 : }
44216 : else
44217 : {
44218 0 : pt->ptr.pp_double[i][j] = (double)(0);
44219 : }
44220 : }
44221 : }
44222 :
44223 : /*
44224 : * Calculate
44225 : */
44226 0 : rmatrixbdmultiplybyp(qp, m, n, taup, pt, ptrows, n, ae_true, ae_true, _state);
44227 : }
44228 :
44229 :
44230 : /*************************************************************************
44231 : Multiplication by matrix P which reduces matrix A to bidiagonal form.
44232 :
44233 : The algorithm allows pre- or post-multiply by P or P'.
44234 :
44235 : Input parameters:
44236 : QP - matrices Q and P in compact form.
44237 : Output of RMatrixBD subroutine.
44238 : M - number of rows in matrix A.
44239 : N - number of columns in matrix A.
44240 : TAUP - scalar factors which are used to form P.
44241 : Output of RMatrixBD subroutine.
44242 : Z - multiplied matrix.
44243 : Array whose indexes range within [0..ZRows-1,0..ZColumns-1].
44244 : ZRows - number of rows in matrix Z. If FromTheRight=False,
44245 : ZRows=N, otherwise ZRows can be arbitrary.
44246 : ZColumns - number of columns in matrix Z. If FromTheRight=True,
44247 : ZColumns=N, otherwise ZColumns can be arbitrary.
44248 : FromTheRight - pre- or post-multiply.
44249 : DoTranspose - multiply by P or P'.
44250 :
44251 : Output parameters:
44252 : Z - product of Z and P.
44253 : Array whose indexes range within [0..ZRows-1,0..ZColumns-1].
44254 : If ZRows=0 or ZColumns=0, the array is not modified.
44255 :
44256 : -- ALGLIB --
44257 : 2005-2010
44258 : Bochkanov Sergey
44259 : *************************************************************************/
44260 0 : void rmatrixbdmultiplybyp(/* Real */ ae_matrix* qp,
44261 : ae_int_t m,
44262 : ae_int_t n,
44263 : /* Real */ ae_vector* taup,
44264 : /* Real */ ae_matrix* z,
44265 : ae_int_t zrows,
44266 : ae_int_t zcolumns,
44267 : ae_bool fromtheright,
44268 : ae_bool dotranspose,
44269 : ae_state *_state)
44270 : {
44271 : ae_frame _frame_block;
44272 : ae_int_t i;
44273 : ae_vector v;
44274 : ae_vector work;
44275 : ae_vector dummy;
44276 : ae_int_t mx;
44277 : ae_int_t i1;
44278 : ae_int_t i2;
44279 : ae_int_t istep;
44280 :
44281 0 : ae_frame_make(_state, &_frame_block);
44282 0 : memset(&v, 0, sizeof(v));
44283 0 : memset(&work, 0, sizeof(work));
44284 0 : memset(&dummy, 0, sizeof(dummy));
44285 0 : ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
44286 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
44287 0 : ae_vector_init(&dummy, 0, DT_REAL, _state, ae_true);
44288 :
44289 0 : if( ((m<=0||n<=0)||zrows<=0)||zcolumns<=0 )
44290 : {
44291 0 : ae_frame_leave(_state);
44292 0 : return;
44293 : }
44294 0 : ae_assert((fromtheright&&zcolumns==n)||(!fromtheright&&zrows==n), "RMatrixBDMultiplyByP: incorrect Z size!", _state);
44295 :
44296 : /*
44297 : * init
44298 : */
44299 0 : mx = ae_maxint(m, n, _state);
44300 0 : mx = ae_maxint(mx, zrows, _state);
44301 0 : mx = ae_maxint(mx, zcolumns, _state);
44302 0 : ae_vector_set_length(&v, mx+1, _state);
44303 0 : ae_vector_set_length(&work, mx+1, _state);
44304 0 : if( m>=n )
44305 : {
44306 :
44307 : /*
44308 : * setup
44309 : */
44310 0 : if( fromtheright )
44311 : {
44312 0 : i1 = n-2;
44313 0 : i2 = 0;
44314 0 : istep = -1;
44315 : }
44316 : else
44317 : {
44318 0 : i1 = 0;
44319 0 : i2 = n-2;
44320 0 : istep = 1;
44321 : }
44322 0 : if( !dotranspose )
44323 : {
44324 0 : i = i1;
44325 0 : i1 = i2;
44326 0 : i2 = i;
44327 0 : istep = -istep;
44328 : }
44329 :
44330 : /*
44331 : * Process
44332 : */
44333 0 : if( n-1>0 )
44334 : {
44335 0 : i = i1;
44336 0 : do
44337 : {
44338 0 : ae_v_move(&v.ptr.p_double[1], 1, &qp->ptr.pp_double[i][i+1], 1, ae_v_len(1,n-1-i));
44339 0 : v.ptr.p_double[1] = (double)(1);
44340 0 : if( fromtheright )
44341 : {
44342 0 : applyreflectionfromtheright(z, taup->ptr.p_double[i], &v, 0, zrows-1, i+1, n-1, &work, _state);
44343 : }
44344 : else
44345 : {
44346 0 : applyreflectionfromtheleft(z, taup->ptr.p_double[i], &v, i+1, n-1, 0, zcolumns-1, &work, _state);
44347 : }
44348 0 : i = i+istep;
44349 : }
44350 0 : while(i!=i2+istep);
44351 : }
44352 : }
44353 : else
44354 : {
44355 :
44356 : /*
44357 : * setup
44358 : */
44359 0 : if( fromtheright )
44360 : {
44361 0 : i1 = m-1;
44362 0 : i2 = 0;
44363 0 : istep = -1;
44364 : }
44365 : else
44366 : {
44367 0 : i1 = 0;
44368 0 : i2 = m-1;
44369 0 : istep = 1;
44370 : }
44371 0 : if( !dotranspose )
44372 : {
44373 0 : i = i1;
44374 0 : i1 = i2;
44375 0 : i2 = i;
44376 0 : istep = -istep;
44377 : }
44378 :
44379 : /*
44380 : * Process
44381 : */
44382 0 : i = i1;
44383 0 : do
44384 : {
44385 0 : ae_v_move(&v.ptr.p_double[1], 1, &qp->ptr.pp_double[i][i], 1, ae_v_len(1,n-i));
44386 0 : v.ptr.p_double[1] = (double)(1);
44387 0 : if( fromtheright )
44388 : {
44389 0 : applyreflectionfromtheright(z, taup->ptr.p_double[i], &v, 0, zrows-1, i, n-1, &work, _state);
44390 : }
44391 : else
44392 : {
44393 0 : applyreflectionfromtheleft(z, taup->ptr.p_double[i], &v, i, n-1, 0, zcolumns-1, &work, _state);
44394 : }
44395 0 : i = i+istep;
44396 : }
44397 0 : while(i!=i2+istep);
44398 : }
44399 0 : ae_frame_leave(_state);
44400 : }
44401 :
44402 :
44403 : /*************************************************************************
44404 : Unpacking of the main and secondary diagonals of bidiagonal decomposition
44405 : of matrix A.
44406 :
44407 : Input parameters:
44408 : B - output of RMatrixBD subroutine.
44409 : M - number of rows in matrix B.
44410 : N - number of columns in matrix B.
44411 :
44412 : Output parameters:
44413 : IsUpper - True, if the matrix is upper bidiagonal.
44414 : otherwise IsUpper is False.
44415 : D - the main diagonal.
44416 : Array whose index ranges within [0..Min(M,N)-1].
44417 : E - the secondary diagonal (upper or lower, depending on
44418 : the value of IsUpper).
44419 : Array index ranges within [0..Min(M,N)-1], the last
44420 : element is not used.
44421 :
44422 : -- ALGLIB --
44423 : 2005-2010
44424 : Bochkanov Sergey
44425 : *************************************************************************/
44426 0 : void rmatrixbdunpackdiagonals(/* Real */ ae_matrix* b,
44427 : ae_int_t m,
44428 : ae_int_t n,
44429 : ae_bool* isupper,
44430 : /* Real */ ae_vector* d,
44431 : /* Real */ ae_vector* e,
44432 : ae_state *_state)
44433 : {
44434 : ae_int_t i;
44435 :
44436 0 : *isupper = ae_false;
44437 0 : ae_vector_clear(d);
44438 0 : ae_vector_clear(e);
44439 :
44440 0 : *isupper = m>=n;
44441 0 : if( m<=0||n<=0 )
44442 : {
44443 0 : return;
44444 : }
44445 0 : if( *isupper )
44446 : {
44447 0 : ae_vector_set_length(d, n, _state);
44448 0 : ae_vector_set_length(e, n, _state);
44449 0 : for(i=0; i<=n-2; i++)
44450 : {
44451 0 : d->ptr.p_double[i] = b->ptr.pp_double[i][i];
44452 0 : e->ptr.p_double[i] = b->ptr.pp_double[i][i+1];
44453 : }
44454 0 : d->ptr.p_double[n-1] = b->ptr.pp_double[n-1][n-1];
44455 : }
44456 : else
44457 : {
44458 0 : ae_vector_set_length(d, m, _state);
44459 0 : ae_vector_set_length(e, m, _state);
44460 0 : for(i=0; i<=m-2; i++)
44461 : {
44462 0 : d->ptr.p_double[i] = b->ptr.pp_double[i][i];
44463 0 : e->ptr.p_double[i] = b->ptr.pp_double[i+1][i];
44464 : }
44465 0 : d->ptr.p_double[m-1] = b->ptr.pp_double[m-1][m-1];
44466 : }
44467 : }
44468 :
44469 :
44470 : /*************************************************************************
44471 : Reduction of a square matrix to upper Hessenberg form: Q'*A*Q = H,
44472 : where Q is an orthogonal matrix, H - Hessenberg matrix.
44473 :
44474 : ! COMMERCIAL EDITION OF ALGLIB:
44475 : !
44476 : ! Commercial Edition of ALGLIB includes following important improvements
44477 : ! of this function:
44478 : ! * high-performance native backend with same C# interface (C# version)
44479 : ! * hardware vendor (Intel) implementations of linear algebra primitives
44480 : ! (C++ and C# versions, x86/x64 platform)
44481 : !
44482 : ! We recommend you to read 'Working with commercial version' section of
44483 : ! ALGLIB Reference Manual in order to find out how to use performance-
44484 : ! related features provided by commercial edition of ALGLIB.
44485 :
44486 : Input parameters:
44487 : A - matrix A with elements [0..N-1, 0..N-1]
44488 : N - size of matrix A.
44489 :
44490 : Output parameters:
44491 : A - matrices Q and P in compact form (see below).
44492 : Tau - array of scalar factors which are used to form matrix Q.
44493 : Array whose index ranges within [0..N-2]
44494 :
44495 : Matrix H is located on the main diagonal, on the lower secondary diagonal
44496 : and above the main diagonal of matrix A. The elements which are used to
44497 : form matrix Q are situated in array Tau and below the lower secondary
44498 : diagonal of matrix A as follows:
44499 :
44500 : Matrix Q is represented as a product of elementary reflections
44501 :
44502 : Q = H(0)*H(2)*...*H(n-2),
44503 :
44504 : where each H(i) is given by
44505 :
44506 : H(i) = 1 - tau * v * (v^T)
44507 :
44508 : where tau is a scalar stored in Tau[I]; v - is a real vector,
44509 : so that v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) stored in A(i+2:n-1,i).
44510 :
44511 : -- LAPACK routine (version 3.0) --
44512 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
44513 : Courant Institute, Argonne National Lab, and Rice University
44514 : October 31, 1992
44515 : *************************************************************************/
44516 0 : void rmatrixhessenberg(/* Real */ ae_matrix* a,
44517 : ae_int_t n,
44518 : /* Real */ ae_vector* tau,
44519 : ae_state *_state)
44520 : {
44521 : ae_frame _frame_block;
44522 : ae_int_t i;
44523 : double v;
44524 : ae_vector t;
44525 : ae_vector work;
44526 :
44527 0 : ae_frame_make(_state, &_frame_block);
44528 0 : memset(&t, 0, sizeof(t));
44529 0 : memset(&work, 0, sizeof(work));
44530 0 : ae_vector_clear(tau);
44531 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
44532 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
44533 :
44534 0 : ae_assert(n>=0, "RMatrixHessenberg: incorrect N!", _state);
44535 :
44536 : /*
44537 : * Quick return if possible
44538 : */
44539 0 : if( n<=1 )
44540 : {
44541 0 : ae_frame_leave(_state);
44542 0 : return;
44543 : }
44544 :
44545 : /*
44546 : * Allocate place
44547 : */
44548 0 : ae_vector_set_length(tau, n-2+1, _state);
44549 0 : ae_vector_set_length(&t, n+1, _state);
44550 0 : ae_vector_set_length(&work, n-1+1, _state);
44551 :
44552 : /*
44553 : * MKL version
44554 : */
44555 0 : if( rmatrixhessenbergmkl(a, n, tau, _state) )
44556 : {
44557 0 : ae_frame_leave(_state);
44558 0 : return;
44559 : }
44560 :
44561 : /*
44562 : * ALGLIB version
44563 : */
44564 0 : for(i=0; i<=n-2; i++)
44565 : {
44566 :
44567 : /*
44568 : * Compute elementary reflector H(i) to annihilate A(i+2:ihi,i)
44569 : */
44570 0 : ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,n-i-1));
44571 0 : generatereflection(&t, n-i-1, &v, _state);
44572 0 : ae_v_move(&a->ptr.pp_double[i+1][i], a->stride, &t.ptr.p_double[1], 1, ae_v_len(i+1,n-1));
44573 0 : tau->ptr.p_double[i] = v;
44574 0 : t.ptr.p_double[1] = (double)(1);
44575 :
44576 : /*
44577 : * Apply H(i) to A(1:ihi,i+1:ihi) from the right
44578 : */
44579 0 : applyreflectionfromtheright(a, v, &t, 0, n-1, i+1, n-1, &work, _state);
44580 :
44581 : /*
44582 : * Apply H(i) to A(i+1:ihi,i+1:n) from the left
44583 : */
44584 0 : applyreflectionfromtheleft(a, v, &t, i+1, n-1, i+1, n-1, &work, _state);
44585 : }
44586 0 : ae_frame_leave(_state);
44587 : }
44588 :
44589 :
44590 : /*************************************************************************
44591 : Unpacking matrix Q which reduces matrix A to upper Hessenberg form
44592 :
44593 : ! COMMERCIAL EDITION OF ALGLIB:
44594 : !
44595 : ! Commercial Edition of ALGLIB includes following important improvements
44596 : ! of this function:
44597 : ! * high-performance native backend with same C# interface (C# version)
44598 : ! * hardware vendor (Intel) implementations of linear algebra primitives
44599 : ! (C++ and C# versions, x86/x64 platform)
44600 : !
44601 : ! We recommend you to read 'Working with commercial version' section of
44602 : ! ALGLIB Reference Manual in order to find out how to use performance-
44603 : ! related features provided by commercial edition of ALGLIB.
44604 :
44605 : Input parameters:
44606 : A - output of RMatrixHessenberg subroutine.
44607 : N - size of matrix A.
44608 : Tau - scalar factors which are used to form Q.
44609 : Output of RMatrixHessenberg subroutine.
44610 :
44611 : Output parameters:
44612 : Q - matrix Q.
44613 : Array whose indexes range within [0..N-1, 0..N-1].
44614 :
44615 : -- ALGLIB --
44616 : 2005-2010
44617 : Bochkanov Sergey
44618 : *************************************************************************/
44619 0 : void rmatrixhessenbergunpackq(/* Real */ ae_matrix* a,
44620 : ae_int_t n,
44621 : /* Real */ ae_vector* tau,
44622 : /* Real */ ae_matrix* q,
44623 : ae_state *_state)
44624 : {
44625 : ae_frame _frame_block;
44626 : ae_int_t i;
44627 : ae_int_t j;
44628 : ae_vector v;
44629 : ae_vector work;
44630 :
44631 0 : ae_frame_make(_state, &_frame_block);
44632 0 : memset(&v, 0, sizeof(v));
44633 0 : memset(&work, 0, sizeof(work));
44634 0 : ae_matrix_clear(q);
44635 0 : ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
44636 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
44637 :
44638 0 : if( n==0 )
44639 : {
44640 0 : ae_frame_leave(_state);
44641 0 : return;
44642 : }
44643 :
44644 : /*
44645 : * init
44646 : */
44647 0 : ae_matrix_set_length(q, n-1+1, n-1+1, _state);
44648 0 : ae_vector_set_length(&v, n-1+1, _state);
44649 0 : ae_vector_set_length(&work, n-1+1, _state);
44650 0 : for(i=0; i<=n-1; i++)
44651 : {
44652 0 : for(j=0; j<=n-1; j++)
44653 : {
44654 0 : if( i==j )
44655 : {
44656 0 : q->ptr.pp_double[i][j] = (double)(1);
44657 : }
44658 : else
44659 : {
44660 0 : q->ptr.pp_double[i][j] = (double)(0);
44661 : }
44662 : }
44663 : }
44664 :
44665 : /*
44666 : * MKL version
44667 : */
44668 0 : if( rmatrixhessenbergunpackqmkl(a, n, tau, q, _state) )
44669 : {
44670 0 : ae_frame_leave(_state);
44671 0 : return;
44672 : }
44673 :
44674 : /*
44675 : * ALGLIB version: unpack Q
44676 : */
44677 0 : for(i=0; i<=n-2; i++)
44678 : {
44679 :
44680 : /*
44681 : * Apply H(i)
44682 : */
44683 0 : ae_v_move(&v.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,n-i-1));
44684 0 : v.ptr.p_double[1] = (double)(1);
44685 0 : applyreflectionfromtheright(q, tau->ptr.p_double[i], &v, 0, n-1, i+1, n-1, &work, _state);
44686 : }
44687 0 : ae_frame_leave(_state);
44688 : }
44689 :
44690 :
44691 : /*************************************************************************
44692 : Unpacking matrix H (the result of matrix A reduction to upper Hessenberg form)
44693 :
44694 : Input parameters:
44695 : A - output of RMatrixHessenberg subroutine.
44696 : N - size of matrix A.
44697 :
44698 : Output parameters:
44699 : H - matrix H. Array whose indexes range within [0..N-1, 0..N-1].
44700 :
44701 : -- ALGLIB --
44702 : 2005-2010
44703 : Bochkanov Sergey
44704 : *************************************************************************/
44705 0 : void rmatrixhessenbergunpackh(/* Real */ ae_matrix* a,
44706 : ae_int_t n,
44707 : /* Real */ ae_matrix* h,
44708 : ae_state *_state)
44709 : {
44710 : ae_frame _frame_block;
44711 : ae_int_t i;
44712 : ae_int_t j;
44713 : ae_vector v;
44714 : ae_vector work;
44715 :
44716 0 : ae_frame_make(_state, &_frame_block);
44717 0 : memset(&v, 0, sizeof(v));
44718 0 : memset(&work, 0, sizeof(work));
44719 0 : ae_matrix_clear(h);
44720 0 : ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
44721 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
44722 :
44723 0 : if( n==0 )
44724 : {
44725 0 : ae_frame_leave(_state);
44726 0 : return;
44727 : }
44728 0 : ae_matrix_set_length(h, n-1+1, n-1+1, _state);
44729 0 : for(i=0; i<=n-1; i++)
44730 : {
44731 0 : for(j=0; j<=i-2; j++)
44732 : {
44733 0 : h->ptr.pp_double[i][j] = (double)(0);
44734 : }
44735 0 : j = ae_maxint(0, i-1, _state);
44736 0 : ae_v_move(&h->ptr.pp_double[i][j], 1, &a->ptr.pp_double[i][j], 1, ae_v_len(j,n-1));
44737 : }
44738 0 : ae_frame_leave(_state);
44739 : }
44740 :
44741 :
44742 : /*************************************************************************
44743 : Reduction of a symmetric matrix which is given by its higher or lower
44744 : triangular part to a tridiagonal matrix using orthogonal similarity
44745 : transformation: Q'*A*Q=T.
44746 :
44747 : ! COMMERCIAL EDITION OF ALGLIB:
44748 : !
44749 : ! Commercial Edition of ALGLIB includes following important improvements
44750 : ! of this function:
44751 : ! * high-performance native backend with same C# interface (C# version)
44752 : ! * hardware vendor (Intel) implementations of linear algebra primitives
44753 : ! (C++ and C# versions, x86/x64 platform)
44754 : !
44755 : ! We recommend you to read 'Working with commercial version' section of
44756 : ! ALGLIB Reference Manual in order to find out how to use performance-
44757 : ! related features provided by commercial edition of ALGLIB.
44758 :
44759 : Input parameters:
44760 : A - matrix to be transformed
44761 : array with elements [0..N-1, 0..N-1].
44762 : N - size of matrix A.
44763 : IsUpper - storage format. If IsUpper = True, then matrix A is given
44764 : by its upper triangle, and the lower triangle is not used
44765 : and not modified by the algorithm, and vice versa
44766 : if IsUpper = False.
44767 :
44768 : Output parameters:
44769 : A - matrices T and Q in compact form (see lower)
44770 : Tau - array of factors which are forming matrices H(i)
44771 : array with elements [0..N-2].
44772 : D - main diagonal of symmetric matrix T.
44773 : array with elements [0..N-1].
44774 : E - secondary diagonal of symmetric matrix T.
44775 : array with elements [0..N-2].
44776 :
44777 :
44778 : If IsUpper=True, the matrix Q is represented as a product of elementary
44779 : reflectors
44780 :
44781 : Q = H(n-2) . . . H(2) H(0).
44782 :
44783 : Each H(i) has the form
44784 :
44785 : H(i) = I - tau * v * v'
44786 :
44787 : where tau is a real scalar, and v is a real vector with
44788 : v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in
44789 : A(0:i-1,i+1), and tau in TAU(i).
44790 :
44791 : If IsUpper=False, the matrix Q is represented as a product of elementary
44792 : reflectors
44793 :
44794 : Q = H(0) H(2) . . . H(n-2).
44795 :
44796 : Each H(i) has the form
44797 :
44798 : H(i) = I - tau * v * v'
44799 :
44800 : where tau is a real scalar, and v is a real vector with
44801 : v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i),
44802 : and tau in TAU(i).
44803 :
44804 : The contents of A on exit are illustrated by the following examples
44805 : with n = 5:
44806 :
44807 : if UPLO = 'U': if UPLO = 'L':
44808 :
44809 : ( d e v1 v2 v3 ) ( d )
44810 : ( d e v2 v3 ) ( e d )
44811 : ( d e v3 ) ( v0 e d )
44812 : ( d e ) ( v0 v1 e d )
44813 : ( d ) ( v0 v1 v2 e d )
44814 :
44815 : where d and e denote diagonal and off-diagonal elements of T, and vi
44816 : denotes an element of the vector defining H(i).
44817 :
44818 : -- LAPACK routine (version 3.0) --
44819 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
44820 : Courant Institute, Argonne National Lab, and Rice University
44821 : October 31, 1992
44822 : *************************************************************************/
44823 0 : void smatrixtd(/* Real */ ae_matrix* a,
44824 : ae_int_t n,
44825 : ae_bool isupper,
44826 : /* Real */ ae_vector* tau,
44827 : /* Real */ ae_vector* d,
44828 : /* Real */ ae_vector* e,
44829 : ae_state *_state)
44830 : {
44831 : ae_frame _frame_block;
44832 : ae_int_t i;
44833 : double alpha;
44834 : double taui;
44835 : double v;
44836 : ae_vector t;
44837 : ae_vector t2;
44838 : ae_vector t3;
44839 :
44840 0 : ae_frame_make(_state, &_frame_block);
44841 0 : memset(&t, 0, sizeof(t));
44842 0 : memset(&t2, 0, sizeof(t2));
44843 0 : memset(&t3, 0, sizeof(t3));
44844 0 : ae_vector_clear(tau);
44845 0 : ae_vector_clear(d);
44846 0 : ae_vector_clear(e);
44847 0 : ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
44848 0 : ae_vector_init(&t2, 0, DT_REAL, _state, ae_true);
44849 0 : ae_vector_init(&t3, 0, DT_REAL, _state, ae_true);
44850 :
44851 0 : if( n<=0 )
44852 : {
44853 0 : ae_frame_leave(_state);
44854 0 : return;
44855 : }
44856 0 : ae_vector_set_length(&t, n+1, _state);
44857 0 : ae_vector_set_length(&t2, n+1, _state);
44858 0 : ae_vector_set_length(&t3, n+1, _state);
44859 0 : if( n>1 )
44860 : {
44861 0 : ae_vector_set_length(tau, n-2+1, _state);
44862 : }
44863 0 : ae_vector_set_length(d, n-1+1, _state);
44864 0 : if( n>1 )
44865 : {
44866 0 : ae_vector_set_length(e, n-2+1, _state);
44867 : }
44868 :
44869 : /*
44870 : * Try to use MKL
44871 : */
44872 0 : if( smatrixtdmkl(a, n, isupper, tau, d, e, _state) )
44873 : {
44874 0 : ae_frame_leave(_state);
44875 0 : return;
44876 : }
44877 :
44878 : /*
44879 : * ALGLIB version
44880 : */
44881 0 : if( isupper )
44882 : {
44883 :
44884 : /*
44885 : * Reduce the upper triangle of A
44886 : */
44887 0 : for(i=n-2; i>=0; i--)
44888 : {
44889 :
44890 : /*
44891 : * Generate elementary reflector H() = E - tau * v * v'
44892 : */
44893 0 : if( i>=1 )
44894 : {
44895 0 : ae_v_move(&t.ptr.p_double[2], 1, &a->ptr.pp_double[0][i+1], a->stride, ae_v_len(2,i+1));
44896 : }
44897 0 : t.ptr.p_double[1] = a->ptr.pp_double[i][i+1];
44898 0 : generatereflection(&t, i+1, &taui, _state);
44899 0 : if( i>=1 )
44900 : {
44901 0 : ae_v_move(&a->ptr.pp_double[0][i+1], a->stride, &t.ptr.p_double[2], 1, ae_v_len(0,i-1));
44902 : }
44903 0 : a->ptr.pp_double[i][i+1] = t.ptr.p_double[1];
44904 0 : e->ptr.p_double[i] = a->ptr.pp_double[i][i+1];
44905 0 : if( ae_fp_neq(taui,(double)(0)) )
44906 : {
44907 :
44908 : /*
44909 : * Apply H from both sides to A
44910 : */
44911 0 : a->ptr.pp_double[i][i+1] = (double)(1);
44912 :
44913 : /*
44914 : * Compute x := tau * A * v storing x in TAU
44915 : */
44916 0 : ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[0][i+1], a->stride, ae_v_len(1,i+1));
44917 0 : symmetricmatrixvectormultiply(a, isupper, 0, i, &t, taui, &t3, _state);
44918 0 : ae_v_move(&tau->ptr.p_double[0], 1, &t3.ptr.p_double[1], 1, ae_v_len(0,i));
44919 :
44920 : /*
44921 : * Compute w := x - 1/2 * tau * (x'*v) * v
44922 : */
44923 0 : v = ae_v_dotproduct(&tau->ptr.p_double[0], 1, &a->ptr.pp_double[0][i+1], a->stride, ae_v_len(0,i));
44924 0 : alpha = -0.5*taui*v;
44925 0 : ae_v_addd(&tau->ptr.p_double[0], 1, &a->ptr.pp_double[0][i+1], a->stride, ae_v_len(0,i), alpha);
44926 :
44927 : /*
44928 : * Apply the transformation as a rank-2 update:
44929 : * A := A - v * w' - w * v'
44930 : */
44931 0 : ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[0][i+1], a->stride, ae_v_len(1,i+1));
44932 0 : ae_v_move(&t3.ptr.p_double[1], 1, &tau->ptr.p_double[0], 1, ae_v_len(1,i+1));
44933 0 : symmetricrank2update(a, isupper, 0, i, &t, &t3, &t2, (double)(-1), _state);
44934 0 : a->ptr.pp_double[i][i+1] = e->ptr.p_double[i];
44935 : }
44936 0 : d->ptr.p_double[i+1] = a->ptr.pp_double[i+1][i+1];
44937 0 : tau->ptr.p_double[i] = taui;
44938 : }
44939 0 : d->ptr.p_double[0] = a->ptr.pp_double[0][0];
44940 : }
44941 : else
44942 : {
44943 :
44944 : /*
44945 : * Reduce the lower triangle of A
44946 : */
44947 0 : for(i=0; i<=n-2; i++)
44948 : {
44949 :
44950 : /*
44951 : * Generate elementary reflector H = E - tau * v * v'
44952 : */
44953 0 : ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,n-i-1));
44954 0 : generatereflection(&t, n-i-1, &taui, _state);
44955 0 : ae_v_move(&a->ptr.pp_double[i+1][i], a->stride, &t.ptr.p_double[1], 1, ae_v_len(i+1,n-1));
44956 0 : e->ptr.p_double[i] = a->ptr.pp_double[i+1][i];
44957 0 : if( ae_fp_neq(taui,(double)(0)) )
44958 : {
44959 :
44960 : /*
44961 : * Apply H from both sides to A
44962 : */
44963 0 : a->ptr.pp_double[i+1][i] = (double)(1);
44964 :
44965 : /*
44966 : * Compute x := tau * A * v storing y in TAU
44967 : */
44968 0 : ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,n-i-1));
44969 0 : symmetricmatrixvectormultiply(a, isupper, i+1, n-1, &t, taui, &t2, _state);
44970 0 : ae_v_move(&tau->ptr.p_double[i], 1, &t2.ptr.p_double[1], 1, ae_v_len(i,n-2));
44971 :
44972 : /*
44973 : * Compute w := x - 1/2 * tau * (x'*v) * v
44974 : */
44975 0 : v = ae_v_dotproduct(&tau->ptr.p_double[i], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(i,n-2));
44976 0 : alpha = -0.5*taui*v;
44977 0 : ae_v_addd(&tau->ptr.p_double[i], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(i,n-2), alpha);
44978 :
44979 : /*
44980 : * Apply the transformation as a rank-2 update:
44981 : * A := A - v * w' - w * v'
44982 : *
44983 : */
44984 0 : ae_v_move(&t.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,n-i-1));
44985 0 : ae_v_move(&t2.ptr.p_double[1], 1, &tau->ptr.p_double[i], 1, ae_v_len(1,n-i-1));
44986 0 : symmetricrank2update(a, isupper, i+1, n-1, &t, &t2, &t3, (double)(-1), _state);
44987 0 : a->ptr.pp_double[i+1][i] = e->ptr.p_double[i];
44988 : }
44989 0 : d->ptr.p_double[i] = a->ptr.pp_double[i][i];
44990 0 : tau->ptr.p_double[i] = taui;
44991 : }
44992 0 : d->ptr.p_double[n-1] = a->ptr.pp_double[n-1][n-1];
44993 : }
44994 0 : ae_frame_leave(_state);
44995 : }
44996 :
44997 :
44998 : /*************************************************************************
44999 : Unpacking matrix Q which reduces symmetric matrix to a tridiagonal
45000 : form.
45001 :
45002 : ! COMMERCIAL EDITION OF ALGLIB:
45003 : !
45004 : ! Commercial Edition of ALGLIB includes following important improvements
45005 : ! of this function:
45006 : ! * high-performance native backend with same C# interface (C# version)
45007 : ! * hardware vendor (Intel) implementations of linear algebra primitives
45008 : ! (C++ and C# versions, x86/x64 platform)
45009 : !
45010 : ! We recommend you to read 'Working with commercial version' section of
45011 : ! ALGLIB Reference Manual in order to find out how to use performance-
45012 : ! related features provided by commercial edition of ALGLIB.
45013 :
45014 : Input parameters:
45015 : A - the result of a SMatrixTD subroutine
45016 : N - size of matrix A.
45017 : IsUpper - storage format (a parameter of SMatrixTD subroutine)
45018 : Tau - the result of a SMatrixTD subroutine
45019 :
45020 : Output parameters:
45021 : Q - transformation matrix.
45022 : array with elements [0..N-1, 0..N-1].
45023 :
45024 : -- ALGLIB --
45025 : Copyright 2005-2010 by Bochkanov Sergey
45026 : *************************************************************************/
45027 0 : void smatrixtdunpackq(/* Real */ ae_matrix* a,
45028 : ae_int_t n,
45029 : ae_bool isupper,
45030 : /* Real */ ae_vector* tau,
45031 : /* Real */ ae_matrix* q,
45032 : ae_state *_state)
45033 : {
45034 : ae_frame _frame_block;
45035 : ae_int_t i;
45036 : ae_int_t j;
45037 : ae_vector v;
45038 : ae_vector work;
45039 :
45040 0 : ae_frame_make(_state, &_frame_block);
45041 0 : memset(&v, 0, sizeof(v));
45042 0 : memset(&work, 0, sizeof(work));
45043 0 : ae_matrix_clear(q);
45044 0 : ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
45045 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
45046 :
45047 0 : if( n==0 )
45048 : {
45049 0 : ae_frame_leave(_state);
45050 0 : return;
45051 : }
45052 :
45053 : /*
45054 : * init
45055 : */
45056 0 : ae_matrix_set_length(q, n-1+1, n-1+1, _state);
45057 0 : ae_vector_set_length(&v, n+1, _state);
45058 0 : ae_vector_set_length(&work, n-1+1, _state);
45059 0 : for(i=0; i<=n-1; i++)
45060 : {
45061 0 : for(j=0; j<=n-1; j++)
45062 : {
45063 0 : if( i==j )
45064 : {
45065 0 : q->ptr.pp_double[i][j] = (double)(1);
45066 : }
45067 : else
45068 : {
45069 0 : q->ptr.pp_double[i][j] = (double)(0);
45070 : }
45071 : }
45072 : }
45073 :
45074 : /*
45075 : * MKL version
45076 : */
45077 0 : if( smatrixtdunpackqmkl(a, n, isupper, tau, q, _state) )
45078 : {
45079 0 : ae_frame_leave(_state);
45080 0 : return;
45081 : }
45082 :
45083 : /*
45084 : * ALGLIB version: unpack Q
45085 : */
45086 0 : if( isupper )
45087 : {
45088 0 : for(i=0; i<=n-2; i++)
45089 : {
45090 :
45091 : /*
45092 : * Apply H(i)
45093 : */
45094 0 : ae_v_move(&v.ptr.p_double[1], 1, &a->ptr.pp_double[0][i+1], a->stride, ae_v_len(1,i+1));
45095 0 : v.ptr.p_double[i+1] = (double)(1);
45096 0 : applyreflectionfromtheleft(q, tau->ptr.p_double[i], &v, 0, i, 0, n-1, &work, _state);
45097 : }
45098 : }
45099 : else
45100 : {
45101 0 : for(i=n-2; i>=0; i--)
45102 : {
45103 :
45104 : /*
45105 : * Apply H(i)
45106 : */
45107 0 : ae_v_move(&v.ptr.p_double[1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(1,n-i-1));
45108 0 : v.ptr.p_double[1] = (double)(1);
45109 0 : applyreflectionfromtheleft(q, tau->ptr.p_double[i], &v, i+1, n-1, 0, n-1, &work, _state);
45110 : }
45111 : }
45112 0 : ae_frame_leave(_state);
45113 : }
45114 :
45115 :
45116 : /*************************************************************************
45117 : Reduction of a Hermitian matrix which is given by its higher or lower
45118 : triangular part to a real tridiagonal matrix using unitary similarity
45119 : transformation: Q'*A*Q = T.
45120 :
45121 : ! COMMERCIAL EDITION OF ALGLIB:
45122 : !
45123 : ! Commercial Edition of ALGLIB includes following important improvements
45124 : ! of this function:
45125 : ! * high-performance native backend with same C# interface (C# version)
45126 : ! * hardware vendor (Intel) implementations of linear algebra primitives
45127 : ! (C++ and C# versions, x86/x64 platform)
45128 : !
45129 : ! We recommend you to read 'Working with commercial version' section of
45130 : ! ALGLIB Reference Manual in order to find out how to use performance-
45131 : ! related features provided by commercial edition of ALGLIB.
45132 :
45133 : Input parameters:
45134 : A - matrix to be transformed
45135 : array with elements [0..N-1, 0..N-1].
45136 : N - size of matrix A.
45137 : IsUpper - storage format. If IsUpper = True, then matrix A is given
45138 : by its upper triangle, and the lower triangle is not used
45139 : and not modified by the algorithm, and vice versa
45140 : if IsUpper = False.
45141 :
45142 : Output parameters:
45143 : A - matrices T and Q in compact form (see lower)
45144 : Tau - array of factors which are forming matrices H(i)
45145 : array with elements [0..N-2].
45146 : D - main diagonal of real symmetric matrix T.
45147 : array with elements [0..N-1].
45148 : E - secondary diagonal of real symmetric matrix T.
45149 : array with elements [0..N-2].
45150 :
45151 :
45152 : If IsUpper=True, the matrix Q is represented as a product of elementary
45153 : reflectors
45154 :
45155 : Q = H(n-2) . . . H(2) H(0).
45156 :
45157 : Each H(i) has the form
45158 :
45159 : H(i) = I - tau * v * v'
45160 :
45161 : where tau is a complex scalar, and v is a complex vector with
45162 : v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in
45163 : A(0:i-1,i+1), and tau in TAU(i).
45164 :
45165 : If IsUpper=False, the matrix Q is represented as a product of elementary
45166 : reflectors
45167 :
45168 : Q = H(0) H(2) . . . H(n-2).
45169 :
45170 : Each H(i) has the form
45171 :
45172 : H(i) = I - tau * v * v'
45173 :
45174 : where tau is a complex scalar, and v is a complex vector with
45175 : v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i),
45176 : and tau in TAU(i).
45177 :
45178 : The contents of A on exit are illustrated by the following examples
45179 : with n = 5:
45180 :
45181 : if UPLO = 'U': if UPLO = 'L':
45182 :
45183 : ( d e v1 v2 v3 ) ( d )
45184 : ( d e v2 v3 ) ( e d )
45185 : ( d e v3 ) ( v0 e d )
45186 : ( d e ) ( v0 v1 e d )
45187 : ( d ) ( v0 v1 v2 e d )
45188 :
45189 : where d and e denote diagonal and off-diagonal elements of T, and vi
45190 : denotes an element of the vector defining H(i).
45191 :
45192 : -- LAPACK routine (version 3.0) --
45193 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
45194 : Courant Institute, Argonne National Lab, and Rice University
45195 : October 31, 1992
45196 : *************************************************************************/
45197 0 : void hmatrixtd(/* Complex */ ae_matrix* a,
45198 : ae_int_t n,
45199 : ae_bool isupper,
45200 : /* Complex */ ae_vector* tau,
45201 : /* Real */ ae_vector* d,
45202 : /* Real */ ae_vector* e,
45203 : ae_state *_state)
45204 : {
45205 : ae_frame _frame_block;
45206 : ae_int_t i;
45207 : ae_complex alpha;
45208 : ae_complex taui;
45209 : ae_complex v;
45210 : ae_vector t;
45211 : ae_vector t2;
45212 : ae_vector t3;
45213 :
45214 0 : ae_frame_make(_state, &_frame_block);
45215 0 : memset(&t, 0, sizeof(t));
45216 0 : memset(&t2, 0, sizeof(t2));
45217 0 : memset(&t3, 0, sizeof(t3));
45218 0 : ae_vector_clear(tau);
45219 0 : ae_vector_clear(d);
45220 0 : ae_vector_clear(e);
45221 0 : ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true);
45222 0 : ae_vector_init(&t2, 0, DT_COMPLEX, _state, ae_true);
45223 0 : ae_vector_init(&t3, 0, DT_COMPLEX, _state, ae_true);
45224 :
45225 :
45226 : /*
45227 : * Init and test
45228 : */
45229 0 : if( n<=0 )
45230 : {
45231 0 : ae_frame_leave(_state);
45232 0 : return;
45233 : }
45234 0 : for(i=0; i<=n-1; i++)
45235 : {
45236 0 : ae_assert(ae_fp_eq(a->ptr.pp_complex[i][i].y,(double)(0)), "Assertion failed", _state);
45237 : }
45238 0 : if( n>1 )
45239 : {
45240 0 : ae_vector_set_length(tau, n-2+1, _state);
45241 0 : ae_vector_set_length(e, n-2+1, _state);
45242 : }
45243 0 : ae_vector_set_length(d, n-1+1, _state);
45244 0 : ae_vector_set_length(&t, n-1+1, _state);
45245 0 : ae_vector_set_length(&t2, n-1+1, _state);
45246 0 : ae_vector_set_length(&t3, n-1+1, _state);
45247 :
45248 : /*
45249 : * MKL version
45250 : */
45251 0 : if( hmatrixtdmkl(a, n, isupper, tau, d, e, _state) )
45252 : {
45253 0 : ae_frame_leave(_state);
45254 0 : return;
45255 : }
45256 :
45257 : /*
45258 : * ALGLIB version
45259 : */
45260 0 : if( isupper )
45261 : {
45262 :
45263 : /*
45264 : * Reduce the upper triangle of A
45265 : */
45266 0 : a->ptr.pp_complex[n-1][n-1] = ae_complex_from_d(a->ptr.pp_complex[n-1][n-1].x);
45267 0 : for(i=n-2; i>=0; i--)
45268 : {
45269 :
45270 : /*
45271 : * Generate elementary reflector H = I+1 - tau * v * v'
45272 : */
45273 0 : alpha = a->ptr.pp_complex[i][i+1];
45274 0 : t.ptr.p_complex[1] = alpha;
45275 0 : if( i>=1 )
45276 : {
45277 0 : ae_v_cmove(&t.ptr.p_complex[2], 1, &a->ptr.pp_complex[0][i+1], a->stride, "N", ae_v_len(2,i+1));
45278 : }
45279 0 : complexgeneratereflection(&t, i+1, &taui, _state);
45280 0 : if( i>=1 )
45281 : {
45282 0 : ae_v_cmove(&a->ptr.pp_complex[0][i+1], a->stride, &t.ptr.p_complex[2], 1, "N", ae_v_len(0,i-1));
45283 : }
45284 0 : alpha = t.ptr.p_complex[1];
45285 0 : e->ptr.p_double[i] = alpha.x;
45286 0 : if( ae_c_neq_d(taui,(double)(0)) )
45287 : {
45288 :
45289 : /*
45290 : * Apply H(I+1) from both sides to A
45291 : */
45292 0 : a->ptr.pp_complex[i][i+1] = ae_complex_from_i(1);
45293 :
45294 : /*
45295 : * Compute x := tau * A * v storing x in TAU
45296 : */
45297 0 : ae_v_cmove(&t.ptr.p_complex[1], 1, &a->ptr.pp_complex[0][i+1], a->stride, "N", ae_v_len(1,i+1));
45298 0 : hermitianmatrixvectormultiply(a, isupper, 0, i, &t, taui, &t2, _state);
45299 0 : ae_v_cmove(&tau->ptr.p_complex[0], 1, &t2.ptr.p_complex[1], 1, "N", ae_v_len(0,i));
45300 :
45301 : /*
45302 : * Compute w := x - 1/2 * tau * (x'*v) * v
45303 : */
45304 0 : v = ae_v_cdotproduct(&tau->ptr.p_complex[0], 1, "Conj", &a->ptr.pp_complex[0][i+1], a->stride, "N", ae_v_len(0,i));
45305 0 : alpha = ae_c_neg(ae_c_mul(ae_c_mul_d(taui,0.5),v));
45306 0 : ae_v_caddc(&tau->ptr.p_complex[0], 1, &a->ptr.pp_complex[0][i+1], a->stride, "N", ae_v_len(0,i), alpha);
45307 :
45308 : /*
45309 : * Apply the transformation as a rank-2 update:
45310 : * A := A - v * w' - w * v'
45311 : */
45312 0 : ae_v_cmove(&t.ptr.p_complex[1], 1, &a->ptr.pp_complex[0][i+1], a->stride, "N", ae_v_len(1,i+1));
45313 0 : ae_v_cmove(&t3.ptr.p_complex[1], 1, &tau->ptr.p_complex[0], 1, "N", ae_v_len(1,i+1));
45314 0 : hermitianrank2update(a, isupper, 0, i, &t, &t3, &t2, ae_complex_from_i(-1), _state);
45315 : }
45316 : else
45317 : {
45318 0 : a->ptr.pp_complex[i][i] = ae_complex_from_d(a->ptr.pp_complex[i][i].x);
45319 : }
45320 0 : a->ptr.pp_complex[i][i+1] = ae_complex_from_d(e->ptr.p_double[i]);
45321 0 : d->ptr.p_double[i+1] = a->ptr.pp_complex[i+1][i+1].x;
45322 0 : tau->ptr.p_complex[i] = taui;
45323 : }
45324 0 : d->ptr.p_double[0] = a->ptr.pp_complex[0][0].x;
45325 : }
45326 : else
45327 : {
45328 :
45329 : /*
45330 : * Reduce the lower triangle of A
45331 : */
45332 0 : a->ptr.pp_complex[0][0] = ae_complex_from_d(a->ptr.pp_complex[0][0].x);
45333 0 : for(i=0; i<=n-2; i++)
45334 : {
45335 :
45336 : /*
45337 : * Generate elementary reflector H = I - tau * v * v'
45338 : */
45339 0 : ae_v_cmove(&t.ptr.p_complex[1], 1, &a->ptr.pp_complex[i+1][i], a->stride, "N", ae_v_len(1,n-i-1));
45340 0 : complexgeneratereflection(&t, n-i-1, &taui, _state);
45341 0 : ae_v_cmove(&a->ptr.pp_complex[i+1][i], a->stride, &t.ptr.p_complex[1], 1, "N", ae_v_len(i+1,n-1));
45342 0 : e->ptr.p_double[i] = a->ptr.pp_complex[i+1][i].x;
45343 0 : if( ae_c_neq_d(taui,(double)(0)) )
45344 : {
45345 :
45346 : /*
45347 : * Apply H(i) from both sides to A(i+1:n,i+1:n)
45348 : */
45349 0 : a->ptr.pp_complex[i+1][i] = ae_complex_from_i(1);
45350 :
45351 : /*
45352 : * Compute x := tau * A * v storing y in TAU
45353 : */
45354 0 : ae_v_cmove(&t.ptr.p_complex[1], 1, &a->ptr.pp_complex[i+1][i], a->stride, "N", ae_v_len(1,n-i-1));
45355 0 : hermitianmatrixvectormultiply(a, isupper, i+1, n-1, &t, taui, &t2, _state);
45356 0 : ae_v_cmove(&tau->ptr.p_complex[i], 1, &t2.ptr.p_complex[1], 1, "N", ae_v_len(i,n-2));
45357 :
45358 : /*
45359 : * Compute w := x - 1/2 * tau * (x'*v) * v
45360 : */
45361 0 : v = ae_v_cdotproduct(&tau->ptr.p_complex[i], 1, "Conj", &a->ptr.pp_complex[i+1][i], a->stride, "N", ae_v_len(i,n-2));
45362 0 : alpha = ae_c_neg(ae_c_mul(ae_c_mul_d(taui,0.5),v));
45363 0 : ae_v_caddc(&tau->ptr.p_complex[i], 1, &a->ptr.pp_complex[i+1][i], a->stride, "N", ae_v_len(i,n-2), alpha);
45364 :
45365 : /*
45366 : * Apply the transformation as a rank-2 update:
45367 : * A := A - v * w' - w * v'
45368 : */
45369 0 : ae_v_cmove(&t.ptr.p_complex[1], 1, &a->ptr.pp_complex[i+1][i], a->stride, "N", ae_v_len(1,n-i-1));
45370 0 : ae_v_cmove(&t2.ptr.p_complex[1], 1, &tau->ptr.p_complex[i], 1, "N", ae_v_len(1,n-i-1));
45371 0 : hermitianrank2update(a, isupper, i+1, n-1, &t, &t2, &t3, ae_complex_from_i(-1), _state);
45372 : }
45373 : else
45374 : {
45375 0 : a->ptr.pp_complex[i+1][i+1] = ae_complex_from_d(a->ptr.pp_complex[i+1][i+1].x);
45376 : }
45377 0 : a->ptr.pp_complex[i+1][i] = ae_complex_from_d(e->ptr.p_double[i]);
45378 0 : d->ptr.p_double[i] = a->ptr.pp_complex[i][i].x;
45379 0 : tau->ptr.p_complex[i] = taui;
45380 : }
45381 0 : d->ptr.p_double[n-1] = a->ptr.pp_complex[n-1][n-1].x;
45382 : }
45383 0 : ae_frame_leave(_state);
45384 : }
45385 :
45386 :
45387 : /*************************************************************************
45388 : Unpacking matrix Q which reduces a Hermitian matrix to a real tridiagonal
45389 : form.
45390 :
45391 : ! COMMERCIAL EDITION OF ALGLIB:
45392 : !
45393 : ! Commercial Edition of ALGLIB includes following important improvements
45394 : ! of this function:
45395 : ! * high-performance native backend with same C# interface (C# version)
45396 : ! * hardware vendor (Intel) implementations of linear algebra primitives
45397 : ! (C++ and C# versions, x86/x64 platform)
45398 : !
45399 : ! We recommend you to read 'Working with commercial version' section of
45400 : ! ALGLIB Reference Manual in order to find out how to use performance-
45401 : ! related features provided by commercial edition of ALGLIB.
45402 :
45403 : Input parameters:
45404 : A - the result of a HMatrixTD subroutine
45405 : N - size of matrix A.
45406 : IsUpper - storage format (a parameter of HMatrixTD subroutine)
45407 : Tau - the result of a HMatrixTD subroutine
45408 :
45409 : Output parameters:
45410 : Q - transformation matrix.
45411 : array with elements [0..N-1, 0..N-1].
45412 :
45413 : -- ALGLIB --
45414 : Copyright 2005-2010 by Bochkanov Sergey
45415 : *************************************************************************/
45416 0 : void hmatrixtdunpackq(/* Complex */ ae_matrix* a,
45417 : ae_int_t n,
45418 : ae_bool isupper,
45419 : /* Complex */ ae_vector* tau,
45420 : /* Complex */ ae_matrix* q,
45421 : ae_state *_state)
45422 : {
45423 : ae_frame _frame_block;
45424 : ae_int_t i;
45425 : ae_int_t j;
45426 : ae_vector v;
45427 : ae_vector work;
45428 :
45429 0 : ae_frame_make(_state, &_frame_block);
45430 0 : memset(&v, 0, sizeof(v));
45431 0 : memset(&work, 0, sizeof(work));
45432 0 : ae_matrix_clear(q);
45433 0 : ae_vector_init(&v, 0, DT_COMPLEX, _state, ae_true);
45434 0 : ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true);
45435 :
45436 0 : if( n==0 )
45437 : {
45438 0 : ae_frame_leave(_state);
45439 0 : return;
45440 : }
45441 :
45442 : /*
45443 : * init
45444 : */
45445 0 : ae_matrix_set_length(q, n-1+1, n-1+1, _state);
45446 0 : ae_vector_set_length(&v, n+1, _state);
45447 0 : ae_vector_set_length(&work, n-1+1, _state);
45448 :
45449 : /*
45450 : * MKL version
45451 : */
45452 0 : if( hmatrixtdunpackqmkl(a, n, isupper, tau, q, _state) )
45453 : {
45454 0 : ae_frame_leave(_state);
45455 0 : return;
45456 : }
45457 :
45458 : /*
45459 : * ALGLIB version
45460 : */
45461 0 : for(i=0; i<=n-1; i++)
45462 : {
45463 0 : for(j=0; j<=n-1; j++)
45464 : {
45465 0 : if( i==j )
45466 : {
45467 0 : q->ptr.pp_complex[i][j] = ae_complex_from_i(1);
45468 : }
45469 : else
45470 : {
45471 0 : q->ptr.pp_complex[i][j] = ae_complex_from_i(0);
45472 : }
45473 : }
45474 : }
45475 0 : if( isupper )
45476 : {
45477 0 : for(i=0; i<=n-2; i++)
45478 : {
45479 :
45480 : /*
45481 : * Apply H(i)
45482 : */
45483 0 : ae_v_cmove(&v.ptr.p_complex[1], 1, &a->ptr.pp_complex[0][i+1], a->stride, "N", ae_v_len(1,i+1));
45484 0 : v.ptr.p_complex[i+1] = ae_complex_from_i(1);
45485 0 : complexapplyreflectionfromtheleft(q, tau->ptr.p_complex[i], &v, 0, i, 0, n-1, &work, _state);
45486 : }
45487 : }
45488 : else
45489 : {
45490 0 : for(i=n-2; i>=0; i--)
45491 : {
45492 :
45493 : /*
45494 : * Apply H(i)
45495 : */
45496 0 : ae_v_cmove(&v.ptr.p_complex[1], 1, &a->ptr.pp_complex[i+1][i], a->stride, "N", ae_v_len(1,n-i-1));
45497 0 : v.ptr.p_complex[1] = ae_complex_from_i(1);
45498 0 : complexapplyreflectionfromtheleft(q, tau->ptr.p_complex[i], &v, i+1, n-1, 0, n-1, &work, _state);
45499 : }
45500 : }
45501 0 : ae_frame_leave(_state);
45502 : }
45503 :
45504 :
45505 : /*************************************************************************
45506 : Base case for complex QR
45507 :
45508 : -- LAPACK routine (version 3.0) --
45509 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
45510 : Courant Institute, Argonne National Lab, and Rice University
45511 : September 30, 1994.
45512 : Sergey Bochkanov, ALGLIB project, translation from FORTRAN to
45513 : pseudocode, 2007-2010.
45514 : *************************************************************************/
45515 0 : static void ortfac_cmatrixqrbasecase(/* Complex */ ae_matrix* a,
45516 : ae_int_t m,
45517 : ae_int_t n,
45518 : /* Complex */ ae_vector* work,
45519 : /* Complex */ ae_vector* t,
45520 : /* Complex */ ae_vector* tau,
45521 : ae_state *_state)
45522 : {
45523 : ae_int_t i;
45524 : ae_int_t k;
45525 : ae_int_t mmi;
45526 : ae_int_t minmn;
45527 : ae_complex tmp;
45528 :
45529 :
45530 0 : minmn = ae_minint(m, n, _state);
45531 0 : if( minmn<=0 )
45532 : {
45533 0 : return;
45534 : }
45535 :
45536 : /*
45537 : * Test the input arguments
45538 : */
45539 0 : k = ae_minint(m, n, _state);
45540 0 : for(i=0; i<=k-1; i++)
45541 : {
45542 :
45543 : /*
45544 : * Generate elementary reflector H(i) to annihilate A(i+1:m,i)
45545 : */
45546 0 : mmi = m-i;
45547 0 : ae_v_cmove(&t->ptr.p_complex[1], 1, &a->ptr.pp_complex[i][i], a->stride, "N", ae_v_len(1,mmi));
45548 0 : complexgeneratereflection(t, mmi, &tmp, _state);
45549 0 : tau->ptr.p_complex[i] = tmp;
45550 0 : ae_v_cmove(&a->ptr.pp_complex[i][i], a->stride, &t->ptr.p_complex[1], 1, "N", ae_v_len(i,m-1));
45551 0 : t->ptr.p_complex[1] = ae_complex_from_i(1);
45552 0 : if( i<n-1 )
45553 : {
45554 :
45555 : /*
45556 : * Apply H'(i) to A(i:m,i+1:n) from the left
45557 : */
45558 0 : complexapplyreflectionfromtheleft(a, ae_c_conj(tau->ptr.p_complex[i], _state), t, i, m-1, i+1, n-1, work, _state);
45559 : }
45560 : }
45561 : }
45562 :
45563 :
45564 : /*************************************************************************
45565 : Base case for complex LQ
45566 :
45567 : -- LAPACK routine (version 3.0) --
45568 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
45569 : Courant Institute, Argonne National Lab, and Rice University
45570 : September 30, 1994.
45571 : Sergey Bochkanov, ALGLIB project, translation from FORTRAN to
45572 : pseudocode, 2007-2010.
45573 : *************************************************************************/
45574 0 : static void ortfac_cmatrixlqbasecase(/* Complex */ ae_matrix* a,
45575 : ae_int_t m,
45576 : ae_int_t n,
45577 : /* Complex */ ae_vector* work,
45578 : /* Complex */ ae_vector* t,
45579 : /* Complex */ ae_vector* tau,
45580 : ae_state *_state)
45581 : {
45582 : ae_int_t i;
45583 : ae_int_t minmn;
45584 : ae_complex tmp;
45585 :
45586 :
45587 0 : minmn = ae_minint(m, n, _state);
45588 0 : if( minmn<=0 )
45589 : {
45590 0 : return;
45591 : }
45592 :
45593 : /*
45594 : * Test the input arguments
45595 : */
45596 0 : for(i=0; i<=minmn-1; i++)
45597 : {
45598 :
45599 : /*
45600 : * Generate elementary reflector H(i)
45601 : *
45602 : * NOTE: ComplexGenerateReflection() generates left reflector,
45603 : * i.e. H which reduces x by applyiong from the left, but we
45604 : * need RIGHT reflector. So we replace H=E-tau*v*v' by H^H,
45605 : * which changes v to conj(v).
45606 : */
45607 0 : ae_v_cmove(&t->ptr.p_complex[1], 1, &a->ptr.pp_complex[i][i], 1, "Conj", ae_v_len(1,n-i));
45608 0 : complexgeneratereflection(t, n-i, &tmp, _state);
45609 0 : tau->ptr.p_complex[i] = tmp;
45610 0 : ae_v_cmove(&a->ptr.pp_complex[i][i], 1, &t->ptr.p_complex[1], 1, "Conj", ae_v_len(i,n-1));
45611 0 : t->ptr.p_complex[1] = ae_complex_from_i(1);
45612 0 : if( i<m-1 )
45613 : {
45614 :
45615 : /*
45616 : * Apply H'(i)
45617 : */
45618 0 : complexapplyreflectionfromtheright(a, tau->ptr.p_complex[i], t, i+1, m-1, i, n-1, work, _state);
45619 : }
45620 : }
45621 : }
45622 :
45623 :
45624 : /*************************************************************************
45625 : Generate block reflector:
45626 : * fill unused parts of reflectors matrix by zeros
45627 : * fill diagonal of reflectors matrix by ones
45628 : * generate triangular factor T
45629 :
45630 : PARAMETERS:
45631 : A - either LengthA*BlockSize (if ColumnwiseA) or
45632 : BlockSize*LengthA (if not ColumnwiseA) matrix of
45633 : elementary reflectors.
45634 : Modified on exit.
45635 : Tau - scalar factors
45636 : ColumnwiseA - reflectors are stored in rows or in columns
45637 : LengthA - length of largest reflector
45638 : BlockSize - number of reflectors
45639 : T - array[BlockSize,2*BlockSize]. Left BlockSize*BlockSize
45640 : submatrix stores triangular factor on exit.
45641 : WORK - array[BlockSize]
45642 :
45643 : -- ALGLIB routine --
45644 : 17.02.2010
45645 : Bochkanov Sergey
45646 : *************************************************************************/
45647 0 : static void ortfac_rmatrixblockreflector(/* Real */ ae_matrix* a,
45648 : /* Real */ ae_vector* tau,
45649 : ae_bool columnwisea,
45650 : ae_int_t lengtha,
45651 : ae_int_t blocksize,
45652 : /* Real */ ae_matrix* t,
45653 : /* Real */ ae_vector* work,
45654 : ae_state *_state)
45655 : {
45656 : ae_int_t i;
45657 : ae_int_t j;
45658 : ae_int_t k;
45659 : double v;
45660 :
45661 :
45662 :
45663 : /*
45664 : * fill beginning of new column with zeros,
45665 : * load 1.0 in the first non-zero element
45666 : */
45667 0 : for(k=0; k<=blocksize-1; k++)
45668 : {
45669 0 : if( columnwisea )
45670 : {
45671 0 : for(i=0; i<=k-1; i++)
45672 : {
45673 0 : a->ptr.pp_double[i][k] = (double)(0);
45674 : }
45675 : }
45676 : else
45677 : {
45678 0 : for(i=0; i<=k-1; i++)
45679 : {
45680 0 : a->ptr.pp_double[k][i] = (double)(0);
45681 : }
45682 : }
45683 0 : a->ptr.pp_double[k][k] = (double)(1);
45684 : }
45685 :
45686 : /*
45687 : * Calculate Gram matrix of A
45688 : */
45689 0 : for(i=0; i<=blocksize-1; i++)
45690 : {
45691 0 : for(j=0; j<=blocksize-1; j++)
45692 : {
45693 0 : t->ptr.pp_double[i][blocksize+j] = (double)(0);
45694 : }
45695 : }
45696 0 : for(k=0; k<=lengtha-1; k++)
45697 : {
45698 0 : for(j=1; j<=blocksize-1; j++)
45699 : {
45700 0 : if( columnwisea )
45701 : {
45702 0 : v = a->ptr.pp_double[k][j];
45703 0 : if( ae_fp_neq(v,(double)(0)) )
45704 : {
45705 0 : ae_v_addd(&t->ptr.pp_double[j][blocksize], 1, &a->ptr.pp_double[k][0], 1, ae_v_len(blocksize,blocksize+j-1), v);
45706 : }
45707 : }
45708 : else
45709 : {
45710 0 : v = a->ptr.pp_double[j][k];
45711 0 : if( ae_fp_neq(v,(double)(0)) )
45712 : {
45713 0 : ae_v_addd(&t->ptr.pp_double[j][blocksize], 1, &a->ptr.pp_double[0][k], a->stride, ae_v_len(blocksize,blocksize+j-1), v);
45714 : }
45715 : }
45716 : }
45717 : }
45718 :
45719 : /*
45720 : * Prepare Y (stored in TmpA) and T (stored in TmpT)
45721 : */
45722 0 : for(k=0; k<=blocksize-1; k++)
45723 : {
45724 :
45725 : /*
45726 : * fill non-zero part of T, use pre-calculated Gram matrix
45727 : */
45728 0 : ae_v_move(&work->ptr.p_double[0], 1, &t->ptr.pp_double[k][blocksize], 1, ae_v_len(0,k-1));
45729 0 : for(i=0; i<=k-1; i++)
45730 : {
45731 0 : v = ae_v_dotproduct(&t->ptr.pp_double[i][i], 1, &work->ptr.p_double[i], 1, ae_v_len(i,k-1));
45732 0 : t->ptr.pp_double[i][k] = -tau->ptr.p_double[k]*v;
45733 : }
45734 0 : t->ptr.pp_double[k][k] = -tau->ptr.p_double[k];
45735 :
45736 : /*
45737 : * Rest of T is filled by zeros
45738 : */
45739 0 : for(i=k+1; i<=blocksize-1; i++)
45740 : {
45741 0 : t->ptr.pp_double[i][k] = (double)(0);
45742 : }
45743 : }
45744 0 : }
45745 :
45746 :
45747 : /*************************************************************************
45748 : Generate block reflector (complex):
45749 : * fill unused parts of reflectors matrix by zeros
45750 : * fill diagonal of reflectors matrix by ones
45751 : * generate triangular factor T
45752 :
45753 :
45754 : -- ALGLIB routine --
45755 : 17.02.2010
45756 : Bochkanov Sergey
45757 : *************************************************************************/
45758 0 : static void ortfac_cmatrixblockreflector(/* Complex */ ae_matrix* a,
45759 : /* Complex */ ae_vector* tau,
45760 : ae_bool columnwisea,
45761 : ae_int_t lengtha,
45762 : ae_int_t blocksize,
45763 : /* Complex */ ae_matrix* t,
45764 : /* Complex */ ae_vector* work,
45765 : ae_state *_state)
45766 : {
45767 : ae_int_t i;
45768 : ae_int_t k;
45769 : ae_complex v;
45770 :
45771 :
45772 :
45773 : /*
45774 : * Prepare Y (stored in TmpA) and T (stored in TmpT)
45775 : */
45776 0 : for(k=0; k<=blocksize-1; k++)
45777 : {
45778 :
45779 : /*
45780 : * fill beginning of new column with zeros,
45781 : * load 1.0 in the first non-zero element
45782 : */
45783 0 : if( columnwisea )
45784 : {
45785 0 : for(i=0; i<=k-1; i++)
45786 : {
45787 0 : a->ptr.pp_complex[i][k] = ae_complex_from_i(0);
45788 : }
45789 : }
45790 : else
45791 : {
45792 0 : for(i=0; i<=k-1; i++)
45793 : {
45794 0 : a->ptr.pp_complex[k][i] = ae_complex_from_i(0);
45795 : }
45796 : }
45797 0 : a->ptr.pp_complex[k][k] = ae_complex_from_i(1);
45798 :
45799 : /*
45800 : * fill non-zero part of T,
45801 : */
45802 0 : for(i=0; i<=k-1; i++)
45803 : {
45804 0 : if( columnwisea )
45805 : {
45806 0 : v = ae_v_cdotproduct(&a->ptr.pp_complex[k][i], a->stride, "Conj", &a->ptr.pp_complex[k][k], a->stride, "N", ae_v_len(k,lengtha-1));
45807 : }
45808 : else
45809 : {
45810 0 : v = ae_v_cdotproduct(&a->ptr.pp_complex[i][k], 1, "N", &a->ptr.pp_complex[k][k], 1, "Conj", ae_v_len(k,lengtha-1));
45811 : }
45812 0 : work->ptr.p_complex[i] = v;
45813 : }
45814 0 : for(i=0; i<=k-1; i++)
45815 : {
45816 0 : v = ae_v_cdotproduct(&t->ptr.pp_complex[i][i], 1, "N", &work->ptr.p_complex[i], 1, "N", ae_v_len(i,k-1));
45817 0 : t->ptr.pp_complex[i][k] = ae_c_neg(ae_c_mul(tau->ptr.p_complex[k],v));
45818 : }
45819 0 : t->ptr.pp_complex[k][k] = ae_c_neg(tau->ptr.p_complex[k]);
45820 :
45821 : /*
45822 : * Rest of T is filled by zeros
45823 : */
45824 0 : for(i=k+1; i<=blocksize-1; i++)
45825 : {
45826 0 : t->ptr.pp_complex[i][k] = ae_complex_from_i(0);
45827 : }
45828 : }
45829 0 : }
45830 :
45831 :
45832 : #endif
45833 : #if defined(AE_COMPILE_FBLS) || !defined(AE_PARTIAL_BUILD)
45834 :
45835 :
45836 : /*************************************************************************
45837 : Basic Cholesky solver for ScaleA*Cholesky(A)'*x = y.
45838 :
45839 : This subroutine assumes that:
45840 : * A*ScaleA is well scaled
45841 : * A is well-conditioned, so no zero divisions or overflow may occur
45842 :
45843 : INPUT PARAMETERS:
45844 : CHA - Cholesky decomposition of A
45845 : SqrtScaleA- square root of scale factor ScaleA
45846 : N - matrix size, N>=0.
45847 : IsUpper - storage type
45848 : XB - right part
45849 : Tmp - buffer; function automatically allocates it, if it is too
45850 : small. It can be reused if function is called several
45851 : times.
45852 :
45853 : OUTPUT PARAMETERS:
45854 : XB - solution
45855 :
45856 : NOTE 1: no assertion or tests are done during algorithm operation
45857 : NOTE 2: N=0 will force algorithm to silently return
45858 :
45859 : -- ALGLIB --
45860 : Copyright 13.10.2010 by Bochkanov Sergey
45861 : *************************************************************************/
45862 0 : void fblscholeskysolve(/* Real */ ae_matrix* cha,
45863 : double sqrtscalea,
45864 : ae_int_t n,
45865 : ae_bool isupper,
45866 : /* Real */ ae_vector* xb,
45867 : /* Real */ ae_vector* tmp,
45868 : ae_state *_state)
45869 : {
45870 : double v;
45871 :
45872 :
45873 0 : if( n<=0 )
45874 : {
45875 0 : return;
45876 : }
45877 0 : if( tmp->cnt<n )
45878 : {
45879 0 : ae_vector_set_length(tmp, n, _state);
45880 : }
45881 :
45882 : /*
45883 : * Scale right part
45884 : */
45885 0 : v = 1/ae_sqr(sqrtscalea, _state);
45886 0 : ae_v_muld(&xb->ptr.p_double[0], 1, ae_v_len(0,n-1), v);
45887 :
45888 : /*
45889 : * Solve A = L*L' or A=U'*U
45890 : */
45891 0 : if( isupper )
45892 : {
45893 :
45894 : /*
45895 : * Solve U'*y=b first.
45896 : */
45897 0 : rmatrixtrsv(n, cha, 0, 0, ae_true, ae_false, 1, xb, 0, _state);
45898 :
45899 : /*
45900 : * Solve U*x=y then.
45901 : */
45902 0 : rmatrixtrsv(n, cha, 0, 0, ae_true, ae_false, 0, xb, 0, _state);
45903 : }
45904 : else
45905 : {
45906 :
45907 : /*
45908 : * Solve L*y=b first
45909 : */
45910 0 : rmatrixtrsv(n, cha, 0, 0, ae_false, ae_false, 0, xb, 0, _state);
45911 :
45912 : /*
45913 : * Solve L'*x=y then.
45914 : */
45915 0 : rmatrixtrsv(n, cha, 0, 0, ae_false, ae_false, 1, xb, 0, _state);
45916 : }
45917 : }
45918 :
45919 :
45920 : /*************************************************************************
45921 : Fast basic linear solver: linear SPD CG
45922 :
45923 : Solves (A^T*A + alpha*I)*x = b where:
45924 : * A is MxN matrix
45925 : * alpha>0 is a scalar
45926 : * I is NxN identity matrix
45927 : * b is Nx1 vector
45928 : * X is Nx1 unknown vector.
45929 :
45930 : N iterations of linear conjugate gradient are used to solve problem.
45931 :
45932 : INPUT PARAMETERS:
45933 : A - array[M,N], matrix
45934 : M - number of rows
45935 : N - number of unknowns
45936 : B - array[N], right part
45937 : X - initial approxumation, array[N]
45938 : Buf - buffer; function automatically allocates it, if it is too
45939 : small. It can be reused if function is called several times
45940 : with same M and N.
45941 :
45942 : OUTPUT PARAMETERS:
45943 : X - improved solution
45944 :
45945 : NOTES:
45946 : * solver checks quality of improved solution. If (because of problem
45947 : condition number, numerical noise, etc.) new solution is WORSE than
45948 : original approximation, then original approximation is returned.
45949 : * solver assumes that both A, B, Alpha are well scaled (i.e. they are
45950 : less than sqrt(overflow) and greater than sqrt(underflow)).
45951 :
45952 : -- ALGLIB --
45953 : Copyright 20.08.2009 by Bochkanov Sergey
45954 : *************************************************************************/
45955 0 : void fblssolvecgx(/* Real */ ae_matrix* a,
45956 : ae_int_t m,
45957 : ae_int_t n,
45958 : double alpha,
45959 : /* Real */ ae_vector* b,
45960 : /* Real */ ae_vector* x,
45961 : /* Real */ ae_vector* buf,
45962 : ae_state *_state)
45963 : {
45964 : ae_int_t k;
45965 : ae_int_t offsrk;
45966 : ae_int_t offsrk1;
45967 : ae_int_t offsxk;
45968 : ae_int_t offsxk1;
45969 : ae_int_t offspk;
45970 : ae_int_t offspk1;
45971 : ae_int_t offstmp1;
45972 : ae_int_t offstmp2;
45973 : ae_int_t bs;
45974 : double e1;
45975 : double e2;
45976 : double rk2;
45977 : double rk12;
45978 : double pap;
45979 : double s;
45980 : double betak;
45981 : double v1;
45982 : double v2;
45983 :
45984 :
45985 :
45986 : /*
45987 : * Test for special case: B=0
45988 : */
45989 0 : v1 = ae_v_dotproduct(&b->ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1));
45990 0 : if( ae_fp_eq(v1,(double)(0)) )
45991 : {
45992 0 : for(k=0; k<=n-1; k++)
45993 : {
45994 0 : x->ptr.p_double[k] = (double)(0);
45995 : }
45996 0 : return;
45997 : }
45998 :
45999 : /*
46000 : * Offsets inside Buf for:
46001 : * * R[K], R[K+1]
46002 : * * X[K], X[K+1]
46003 : * * P[K], P[K+1]
46004 : * * Tmp1 - array[M], Tmp2 - array[N]
46005 : */
46006 0 : offsrk = 0;
46007 0 : offsrk1 = offsrk+n;
46008 0 : offsxk = offsrk1+n;
46009 0 : offsxk1 = offsxk+n;
46010 0 : offspk = offsxk1+n;
46011 0 : offspk1 = offspk+n;
46012 0 : offstmp1 = offspk1+n;
46013 0 : offstmp2 = offstmp1+m;
46014 0 : bs = offstmp2+n;
46015 0 : if( buf->cnt<bs )
46016 : {
46017 0 : ae_vector_set_length(buf, bs, _state);
46018 : }
46019 :
46020 : /*
46021 : * x(0) = x
46022 : */
46023 0 : ae_v_move(&buf->ptr.p_double[offsxk], 1, &x->ptr.p_double[0], 1, ae_v_len(offsxk,offsxk+n-1));
46024 :
46025 : /*
46026 : * r(0) = b-A*x(0)
46027 : * RK2 = r(0)'*r(0)
46028 : */
46029 0 : rmatrixmv(m, n, a, 0, 0, 0, buf, offsxk, buf, offstmp1, _state);
46030 0 : rmatrixmv(n, m, a, 0, 0, 1, buf, offstmp1, buf, offstmp2, _state);
46031 0 : ae_v_addd(&buf->ptr.p_double[offstmp2], 1, &buf->ptr.p_double[offsxk], 1, ae_v_len(offstmp2,offstmp2+n-1), alpha);
46032 0 : ae_v_move(&buf->ptr.p_double[offsrk], 1, &b->ptr.p_double[0], 1, ae_v_len(offsrk,offsrk+n-1));
46033 0 : ae_v_sub(&buf->ptr.p_double[offsrk], 1, &buf->ptr.p_double[offstmp2], 1, ae_v_len(offsrk,offsrk+n-1));
46034 0 : rk2 = ae_v_dotproduct(&buf->ptr.p_double[offsrk], 1, &buf->ptr.p_double[offsrk], 1, ae_v_len(offsrk,offsrk+n-1));
46035 0 : ae_v_move(&buf->ptr.p_double[offspk], 1, &buf->ptr.p_double[offsrk], 1, ae_v_len(offspk,offspk+n-1));
46036 0 : e1 = ae_sqrt(rk2, _state);
46037 :
46038 : /*
46039 : * Cycle
46040 : */
46041 0 : for(k=0; k<=n-1; k++)
46042 : {
46043 :
46044 : /*
46045 : * Calculate A*p(k) - store in Buf[OffsTmp2:OffsTmp2+N-1]
46046 : * and p(k)'*A*p(k) - store in PAP
46047 : *
46048 : * If PAP=0, break (iteration is over)
46049 : */
46050 0 : rmatrixmv(m, n, a, 0, 0, 0, buf, offspk, buf, offstmp1, _state);
46051 0 : v1 = ae_v_dotproduct(&buf->ptr.p_double[offstmp1], 1, &buf->ptr.p_double[offstmp1], 1, ae_v_len(offstmp1,offstmp1+m-1));
46052 0 : v2 = ae_v_dotproduct(&buf->ptr.p_double[offspk], 1, &buf->ptr.p_double[offspk], 1, ae_v_len(offspk,offspk+n-1));
46053 0 : pap = v1+alpha*v2;
46054 0 : rmatrixmv(n, m, a, 0, 0, 1, buf, offstmp1, buf, offstmp2, _state);
46055 0 : ae_v_addd(&buf->ptr.p_double[offstmp2], 1, &buf->ptr.p_double[offspk], 1, ae_v_len(offstmp2,offstmp2+n-1), alpha);
46056 0 : if( ae_fp_eq(pap,(double)(0)) )
46057 : {
46058 0 : break;
46059 : }
46060 :
46061 : /*
46062 : * S = (r(k)'*r(k))/(p(k)'*A*p(k))
46063 : */
46064 0 : s = rk2/pap;
46065 :
46066 : /*
46067 : * x(k+1) = x(k) + S*p(k)
46068 : */
46069 0 : ae_v_move(&buf->ptr.p_double[offsxk1], 1, &buf->ptr.p_double[offsxk], 1, ae_v_len(offsxk1,offsxk1+n-1));
46070 0 : ae_v_addd(&buf->ptr.p_double[offsxk1], 1, &buf->ptr.p_double[offspk], 1, ae_v_len(offsxk1,offsxk1+n-1), s);
46071 :
46072 : /*
46073 : * r(k+1) = r(k) - S*A*p(k)
46074 : * RK12 = r(k+1)'*r(k+1)
46075 : *
46076 : * Break if r(k+1) small enough (when compared to r(k))
46077 : */
46078 0 : ae_v_move(&buf->ptr.p_double[offsrk1], 1, &buf->ptr.p_double[offsrk], 1, ae_v_len(offsrk1,offsrk1+n-1));
46079 0 : ae_v_subd(&buf->ptr.p_double[offsrk1], 1, &buf->ptr.p_double[offstmp2], 1, ae_v_len(offsrk1,offsrk1+n-1), s);
46080 0 : rk12 = ae_v_dotproduct(&buf->ptr.p_double[offsrk1], 1, &buf->ptr.p_double[offsrk1], 1, ae_v_len(offsrk1,offsrk1+n-1));
46081 0 : if( ae_fp_less_eq(ae_sqrt(rk12, _state),100*ae_machineepsilon*ae_sqrt(rk2, _state)) )
46082 : {
46083 :
46084 : /*
46085 : * X(k) = x(k+1) before exit -
46086 : * - because we expect to find solution at x(k)
46087 : */
46088 0 : ae_v_move(&buf->ptr.p_double[offsxk], 1, &buf->ptr.p_double[offsxk1], 1, ae_v_len(offsxk,offsxk+n-1));
46089 0 : break;
46090 : }
46091 :
46092 : /*
46093 : * BetaK = RK12/RK2
46094 : * p(k+1) = r(k+1)+betak*p(k)
46095 : */
46096 0 : betak = rk12/rk2;
46097 0 : ae_v_move(&buf->ptr.p_double[offspk1], 1, &buf->ptr.p_double[offsrk1], 1, ae_v_len(offspk1,offspk1+n-1));
46098 0 : ae_v_addd(&buf->ptr.p_double[offspk1], 1, &buf->ptr.p_double[offspk], 1, ae_v_len(offspk1,offspk1+n-1), betak);
46099 :
46100 : /*
46101 : * r(k) := r(k+1)
46102 : * x(k) := x(k+1)
46103 : * p(k) := p(k+1)
46104 : */
46105 0 : ae_v_move(&buf->ptr.p_double[offsrk], 1, &buf->ptr.p_double[offsrk1], 1, ae_v_len(offsrk,offsrk+n-1));
46106 0 : ae_v_move(&buf->ptr.p_double[offsxk], 1, &buf->ptr.p_double[offsxk1], 1, ae_v_len(offsxk,offsxk+n-1));
46107 0 : ae_v_move(&buf->ptr.p_double[offspk], 1, &buf->ptr.p_double[offspk1], 1, ae_v_len(offspk,offspk+n-1));
46108 0 : rk2 = rk12;
46109 : }
46110 :
46111 : /*
46112 : * Calculate E2
46113 : */
46114 0 : rmatrixmv(m, n, a, 0, 0, 0, buf, offsxk, buf, offstmp1, _state);
46115 0 : rmatrixmv(n, m, a, 0, 0, 1, buf, offstmp1, buf, offstmp2, _state);
46116 0 : ae_v_addd(&buf->ptr.p_double[offstmp2], 1, &buf->ptr.p_double[offsxk], 1, ae_v_len(offstmp2,offstmp2+n-1), alpha);
46117 0 : ae_v_move(&buf->ptr.p_double[offsrk], 1, &b->ptr.p_double[0], 1, ae_v_len(offsrk,offsrk+n-1));
46118 0 : ae_v_sub(&buf->ptr.p_double[offsrk], 1, &buf->ptr.p_double[offstmp2], 1, ae_v_len(offsrk,offsrk+n-1));
46119 0 : v1 = ae_v_dotproduct(&buf->ptr.p_double[offsrk], 1, &buf->ptr.p_double[offsrk], 1, ae_v_len(offsrk,offsrk+n-1));
46120 0 : e2 = ae_sqrt(v1, _state);
46121 :
46122 : /*
46123 : * Output result (if it was improved)
46124 : */
46125 0 : if( ae_fp_less(e2,e1) )
46126 : {
46127 0 : ae_v_move(&x->ptr.p_double[0], 1, &buf->ptr.p_double[offsxk], 1, ae_v_len(0,n-1));
46128 : }
46129 : }
46130 :
46131 :
46132 : /*************************************************************************
46133 : Construction of linear conjugate gradient solver.
46134 :
46135 : State parameter passed using "shared" semantics (i.e. previous state is NOT
46136 : erased). When it is already initialized, we can reause prevously allocated
46137 : memory.
46138 :
46139 : INPUT PARAMETERS:
46140 : X - initial solution
46141 : B - right part
46142 : N - system size
46143 : State - structure; may be preallocated, if we want to reuse memory
46144 :
46145 : OUTPUT PARAMETERS:
46146 : State - structure which is used by FBLSCGIteration() to store
46147 : algorithm state between subsequent calls.
46148 :
46149 : NOTE: no error checking is done; caller must check all parameters, prevent
46150 : overflows, and so on.
46151 :
46152 : -- ALGLIB --
46153 : Copyright 22.10.2009 by Bochkanov Sergey
46154 : *************************************************************************/
46155 0 : void fblscgcreate(/* Real */ ae_vector* x,
46156 : /* Real */ ae_vector* b,
46157 : ae_int_t n,
46158 : fblslincgstate* state,
46159 : ae_state *_state)
46160 : {
46161 :
46162 :
46163 0 : if( state->b.cnt<n )
46164 : {
46165 0 : ae_vector_set_length(&state->b, n, _state);
46166 : }
46167 0 : if( state->rk.cnt<n )
46168 : {
46169 0 : ae_vector_set_length(&state->rk, n, _state);
46170 : }
46171 0 : if( state->rk1.cnt<n )
46172 : {
46173 0 : ae_vector_set_length(&state->rk1, n, _state);
46174 : }
46175 0 : if( state->xk.cnt<n )
46176 : {
46177 0 : ae_vector_set_length(&state->xk, n, _state);
46178 : }
46179 0 : if( state->xk1.cnt<n )
46180 : {
46181 0 : ae_vector_set_length(&state->xk1, n, _state);
46182 : }
46183 0 : if( state->pk.cnt<n )
46184 : {
46185 0 : ae_vector_set_length(&state->pk, n, _state);
46186 : }
46187 0 : if( state->pk1.cnt<n )
46188 : {
46189 0 : ae_vector_set_length(&state->pk1, n, _state);
46190 : }
46191 0 : if( state->tmp2.cnt<n )
46192 : {
46193 0 : ae_vector_set_length(&state->tmp2, n, _state);
46194 : }
46195 0 : if( state->x.cnt<n )
46196 : {
46197 0 : ae_vector_set_length(&state->x, n, _state);
46198 : }
46199 0 : if( state->ax.cnt<n )
46200 : {
46201 0 : ae_vector_set_length(&state->ax, n, _state);
46202 : }
46203 0 : state->n = n;
46204 0 : ae_v_move(&state->xk.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
46205 0 : ae_v_move(&state->b.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,n-1));
46206 0 : ae_vector_set_length(&state->rstate.ia, 1+1, _state);
46207 0 : ae_vector_set_length(&state->rstate.ra, 6+1, _state);
46208 0 : state->rstate.stage = -1;
46209 0 : }
46210 :
46211 :
46212 : /*************************************************************************
46213 : Linear CG solver, function relying on reverse communication to calculate
46214 : matrix-vector products.
46215 :
46216 : See comments for FBLSLinCGState structure for more info.
46217 :
46218 : -- ALGLIB --
46219 : Copyright 22.10.2009 by Bochkanov Sergey
46220 : *************************************************************************/
46221 0 : ae_bool fblscgiteration(fblslincgstate* state, ae_state *_state)
46222 : {
46223 : ae_int_t n;
46224 : ae_int_t k;
46225 : double rk2;
46226 : double rk12;
46227 : double pap;
46228 : double s;
46229 : double betak;
46230 : double v1;
46231 : double v2;
46232 : ae_bool result;
46233 :
46234 :
46235 :
46236 : /*
46237 : * Reverse communication preparations
46238 : * I know it looks ugly, but it works the same way
46239 : * anywhere from C++ to Python.
46240 : *
46241 : * This code initializes locals by:
46242 : * * random values determined during code
46243 : * generation - on first subroutine call
46244 : * * values from previous call - on subsequent calls
46245 : */
46246 0 : if( state->rstate.stage>=0 )
46247 : {
46248 0 : n = state->rstate.ia.ptr.p_int[0];
46249 0 : k = state->rstate.ia.ptr.p_int[1];
46250 0 : rk2 = state->rstate.ra.ptr.p_double[0];
46251 0 : rk12 = state->rstate.ra.ptr.p_double[1];
46252 0 : pap = state->rstate.ra.ptr.p_double[2];
46253 0 : s = state->rstate.ra.ptr.p_double[3];
46254 0 : betak = state->rstate.ra.ptr.p_double[4];
46255 0 : v1 = state->rstate.ra.ptr.p_double[5];
46256 0 : v2 = state->rstate.ra.ptr.p_double[6];
46257 : }
46258 : else
46259 : {
46260 0 : n = 359;
46261 0 : k = -58;
46262 0 : rk2 = -919;
46263 0 : rk12 = -909;
46264 0 : pap = 81;
46265 0 : s = 255;
46266 0 : betak = 74;
46267 0 : v1 = -788;
46268 0 : v2 = 809;
46269 : }
46270 0 : if( state->rstate.stage==0 )
46271 : {
46272 0 : goto lbl_0;
46273 : }
46274 0 : if( state->rstate.stage==1 )
46275 : {
46276 0 : goto lbl_1;
46277 : }
46278 0 : if( state->rstate.stage==2 )
46279 : {
46280 0 : goto lbl_2;
46281 : }
46282 :
46283 : /*
46284 : * Routine body
46285 : */
46286 :
46287 : /*
46288 : * prepare locals
46289 : */
46290 0 : n = state->n;
46291 :
46292 : /*
46293 : * Test for special case: B=0
46294 : */
46295 0 : v1 = ae_v_dotproduct(&state->b.ptr.p_double[0], 1, &state->b.ptr.p_double[0], 1, ae_v_len(0,n-1));
46296 0 : if( ae_fp_eq(v1,(double)(0)) )
46297 : {
46298 0 : for(k=0; k<=n-1; k++)
46299 : {
46300 0 : state->xk.ptr.p_double[k] = (double)(0);
46301 : }
46302 0 : result = ae_false;
46303 0 : return result;
46304 : }
46305 :
46306 : /*
46307 : * r(0) = b-A*x(0)
46308 : * RK2 = r(0)'*r(0)
46309 : */
46310 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
46311 0 : state->rstate.stage = 0;
46312 0 : goto lbl_rcomm;
46313 0 : lbl_0:
46314 0 : ae_v_move(&state->rk.ptr.p_double[0], 1, &state->b.ptr.p_double[0], 1, ae_v_len(0,n-1));
46315 0 : ae_v_sub(&state->rk.ptr.p_double[0], 1, &state->ax.ptr.p_double[0], 1, ae_v_len(0,n-1));
46316 0 : rk2 = ae_v_dotproduct(&state->rk.ptr.p_double[0], 1, &state->rk.ptr.p_double[0], 1, ae_v_len(0,n-1));
46317 0 : ae_v_move(&state->pk.ptr.p_double[0], 1, &state->rk.ptr.p_double[0], 1, ae_v_len(0,n-1));
46318 0 : state->e1 = ae_sqrt(rk2, _state);
46319 :
46320 : /*
46321 : * Cycle
46322 : */
46323 0 : k = 0;
46324 0 : lbl_3:
46325 0 : if( k>n-1 )
46326 : {
46327 0 : goto lbl_5;
46328 : }
46329 :
46330 : /*
46331 : * Calculate A*p(k) - store in State.Tmp2
46332 : * and p(k)'*A*p(k) - store in PAP
46333 : *
46334 : * If PAP=0, break (iteration is over)
46335 : */
46336 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->pk.ptr.p_double[0], 1, ae_v_len(0,n-1));
46337 0 : state->rstate.stage = 1;
46338 0 : goto lbl_rcomm;
46339 0 : lbl_1:
46340 0 : ae_v_move(&state->tmp2.ptr.p_double[0], 1, &state->ax.ptr.p_double[0], 1, ae_v_len(0,n-1));
46341 0 : pap = state->xax;
46342 0 : if( !ae_isfinite(pap, _state) )
46343 : {
46344 0 : goto lbl_5;
46345 : }
46346 0 : if( ae_fp_less_eq(pap,(double)(0)) )
46347 : {
46348 0 : goto lbl_5;
46349 : }
46350 :
46351 : /*
46352 : * S = (r(k)'*r(k))/(p(k)'*A*p(k))
46353 : */
46354 0 : s = rk2/pap;
46355 :
46356 : /*
46357 : * x(k+1) = x(k) + S*p(k)
46358 : */
46359 0 : ae_v_move(&state->xk1.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
46360 0 : ae_v_addd(&state->xk1.ptr.p_double[0], 1, &state->pk.ptr.p_double[0], 1, ae_v_len(0,n-1), s);
46361 :
46362 : /*
46363 : * r(k+1) = r(k) - S*A*p(k)
46364 : * RK12 = r(k+1)'*r(k+1)
46365 : *
46366 : * Break if r(k+1) small enough (when compared to r(k))
46367 : */
46368 0 : ae_v_move(&state->rk1.ptr.p_double[0], 1, &state->rk.ptr.p_double[0], 1, ae_v_len(0,n-1));
46369 0 : ae_v_subd(&state->rk1.ptr.p_double[0], 1, &state->tmp2.ptr.p_double[0], 1, ae_v_len(0,n-1), s);
46370 0 : rk12 = ae_v_dotproduct(&state->rk1.ptr.p_double[0], 1, &state->rk1.ptr.p_double[0], 1, ae_v_len(0,n-1));
46371 0 : if( ae_fp_less_eq(ae_sqrt(rk12, _state),100*ae_machineepsilon*state->e1) )
46372 : {
46373 :
46374 : /*
46375 : * X(k) = x(k+1) before exit -
46376 : * - because we expect to find solution at x(k)
46377 : */
46378 0 : ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xk1.ptr.p_double[0], 1, ae_v_len(0,n-1));
46379 0 : goto lbl_5;
46380 : }
46381 :
46382 : /*
46383 : * BetaK = RK12/RK2
46384 : * p(k+1) = r(k+1)+betak*p(k)
46385 : *
46386 : * NOTE: we expect that BetaK won't overflow because of
46387 : * "Sqrt(RK12)<=100*MachineEpsilon*E1" test above.
46388 : */
46389 0 : betak = rk12/rk2;
46390 0 : ae_v_move(&state->pk1.ptr.p_double[0], 1, &state->rk1.ptr.p_double[0], 1, ae_v_len(0,n-1));
46391 0 : ae_v_addd(&state->pk1.ptr.p_double[0], 1, &state->pk.ptr.p_double[0], 1, ae_v_len(0,n-1), betak);
46392 :
46393 : /*
46394 : * r(k) := r(k+1)
46395 : * x(k) := x(k+1)
46396 : * p(k) := p(k+1)
46397 : */
46398 0 : ae_v_move(&state->rk.ptr.p_double[0], 1, &state->rk1.ptr.p_double[0], 1, ae_v_len(0,n-1));
46399 0 : ae_v_move(&state->xk.ptr.p_double[0], 1, &state->xk1.ptr.p_double[0], 1, ae_v_len(0,n-1));
46400 0 : ae_v_move(&state->pk.ptr.p_double[0], 1, &state->pk1.ptr.p_double[0], 1, ae_v_len(0,n-1));
46401 0 : rk2 = rk12;
46402 0 : k = k+1;
46403 0 : goto lbl_3;
46404 0 : lbl_5:
46405 :
46406 : /*
46407 : * Calculate E2
46408 : */
46409 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->xk.ptr.p_double[0], 1, ae_v_len(0,n-1));
46410 0 : state->rstate.stage = 2;
46411 0 : goto lbl_rcomm;
46412 0 : lbl_2:
46413 0 : ae_v_move(&state->rk.ptr.p_double[0], 1, &state->b.ptr.p_double[0], 1, ae_v_len(0,n-1));
46414 0 : ae_v_sub(&state->rk.ptr.p_double[0], 1, &state->ax.ptr.p_double[0], 1, ae_v_len(0,n-1));
46415 0 : v1 = ae_v_dotproduct(&state->rk.ptr.p_double[0], 1, &state->rk.ptr.p_double[0], 1, ae_v_len(0,n-1));
46416 0 : state->e2 = ae_sqrt(v1, _state);
46417 0 : result = ae_false;
46418 0 : return result;
46419 :
46420 : /*
46421 : * Saving state
46422 : */
46423 0 : lbl_rcomm:
46424 0 : result = ae_true;
46425 0 : state->rstate.ia.ptr.p_int[0] = n;
46426 0 : state->rstate.ia.ptr.p_int[1] = k;
46427 0 : state->rstate.ra.ptr.p_double[0] = rk2;
46428 0 : state->rstate.ra.ptr.p_double[1] = rk12;
46429 0 : state->rstate.ra.ptr.p_double[2] = pap;
46430 0 : state->rstate.ra.ptr.p_double[3] = s;
46431 0 : state->rstate.ra.ptr.p_double[4] = betak;
46432 0 : state->rstate.ra.ptr.p_double[5] = v1;
46433 0 : state->rstate.ra.ptr.p_double[6] = v2;
46434 0 : return result;
46435 : }
46436 :
46437 :
46438 : /*************************************************************************
46439 : Construction of GMRES(k) solver.
46440 :
46441 : State parameter passed using "shared" semantics (i.e. previous state is NOT
46442 : erased). When it is already initialized, we can reause prevously allocated
46443 : memory.
46444 :
46445 : After (but not before!) initialization you can tweak following fields (they
46446 : are initialized by default values, but you can change it):
46447 : * State.EpsOrt - stop if norm of new candidate for orthogonalization is below EpsOrt
46448 : * State.EpsRes - stop of residual decreased below EpsRes*|B|
46449 : * State.EpsRed - stop if relative reduction of residual |R(k+1)|/|R(k)|>EpsRed
46450 :
46451 : INPUT PARAMETERS:
46452 : B - right part
46453 : N - system size
46454 : K - iterations count, K>=1
46455 : State - structure; may be preallocated, if we want to reuse memory
46456 :
46457 : OUTPUT PARAMETERS:
46458 : State - structure which is used by FBLSGMRESIteration() to store
46459 : algorithm state between subsequent calls.
46460 :
46461 : NOTE: no error checking is done; caller must check all parameters, prevent
46462 : overflows, and so on.
46463 :
46464 : -- ALGLIB --
46465 : Copyright 18.11.2020 by Bochkanov Sergey
46466 : *************************************************************************/
46467 0 : void fblsgmrescreate(/* Real */ ae_vector* b,
46468 : ae_int_t n,
46469 : ae_int_t k,
46470 : fblsgmresstate* state,
46471 : ae_state *_state)
46472 : {
46473 :
46474 :
46475 0 : ae_assert((n>0&&k>0)&&k<=n, "FBLSGMRESCreate: incorrect params", _state);
46476 0 : state->n = n;
46477 0 : state->itscnt = k;
46478 0 : state->epsort = (1000+ae_sqrt((double)(n), _state))*ae_machineepsilon;
46479 0 : state->epsres = (1000+ae_sqrt((double)(n), _state))*ae_machineepsilon;
46480 0 : state->epsred = 1.0;
46481 0 : state->epsdiag = (10000+n)*ae_machineepsilon;
46482 0 : state->itsperformed = 0;
46483 0 : state->retcode = 0;
46484 0 : rcopyallocv(n, b, &state->b, _state);
46485 0 : rallocv(n, &state->x, _state);
46486 0 : rallocv(n, &state->ax, _state);
46487 0 : ae_vector_set_length(&state->rstate.ia, 4+1, _state);
46488 0 : ae_vector_set_length(&state->rstate.ra, 10+1, _state);
46489 0 : state->rstate.stage = -1;
46490 0 : }
46491 :
46492 :
46493 : /*************************************************************************
46494 : Linear CG solver, function relying on reverse communication to calculate
46495 : matrix-vector products.
46496 :
46497 : See comments for FBLSLinCGState structure for more info.
46498 :
46499 : -- ALGLIB --
46500 : Copyright 22.10.2009 by Bochkanov Sergey
46501 : *************************************************************************/
46502 0 : ae_bool fblsgmresiteration(fblsgmresstate* state, ae_state *_state)
46503 : {
46504 : ae_int_t n;
46505 : ae_int_t itidx;
46506 : ae_int_t kdim;
46507 : double rmax;
46508 : double rmindiag;
46509 : double cs;
46510 : double sn;
46511 : double v;
46512 : double vv;
46513 : double anrm;
46514 : double qnrm;
46515 : double bnrm;
46516 : double resnrm;
46517 : double prevresnrm;
46518 : ae_int_t i;
46519 : ae_int_t j;
46520 : ae_bool result;
46521 :
46522 :
46523 :
46524 : /*
46525 : * Reverse communication preparations
46526 : * I know it looks ugly, but it works the same way
46527 : * anywhere from C++ to Python.
46528 : *
46529 : * This code initializes locals by:
46530 : * * random values determined during code
46531 : * generation - on first subroutine call
46532 : * * values from previous call - on subsequent calls
46533 : */
46534 0 : if( state->rstate.stage>=0 )
46535 : {
46536 0 : n = state->rstate.ia.ptr.p_int[0];
46537 0 : itidx = state->rstate.ia.ptr.p_int[1];
46538 0 : kdim = state->rstate.ia.ptr.p_int[2];
46539 0 : i = state->rstate.ia.ptr.p_int[3];
46540 0 : j = state->rstate.ia.ptr.p_int[4];
46541 0 : rmax = state->rstate.ra.ptr.p_double[0];
46542 0 : rmindiag = state->rstate.ra.ptr.p_double[1];
46543 0 : cs = state->rstate.ra.ptr.p_double[2];
46544 0 : sn = state->rstate.ra.ptr.p_double[3];
46545 0 : v = state->rstate.ra.ptr.p_double[4];
46546 0 : vv = state->rstate.ra.ptr.p_double[5];
46547 0 : anrm = state->rstate.ra.ptr.p_double[6];
46548 0 : qnrm = state->rstate.ra.ptr.p_double[7];
46549 0 : bnrm = state->rstate.ra.ptr.p_double[8];
46550 0 : resnrm = state->rstate.ra.ptr.p_double[9];
46551 0 : prevresnrm = state->rstate.ra.ptr.p_double[10];
46552 : }
46553 : else
46554 : {
46555 0 : n = 205;
46556 0 : itidx = -838;
46557 0 : kdim = 939;
46558 0 : i = -526;
46559 0 : j = 763;
46560 0 : rmax = -541;
46561 0 : rmindiag = -698;
46562 0 : cs = -900;
46563 0 : sn = -318;
46564 0 : v = -940;
46565 0 : vv = 1016;
46566 0 : anrm = -229;
46567 0 : qnrm = -536;
46568 0 : bnrm = 487;
46569 0 : resnrm = -115;
46570 0 : prevresnrm = 886;
46571 : }
46572 0 : if( state->rstate.stage==0 )
46573 : {
46574 0 : goto lbl_0;
46575 : }
46576 :
46577 : /*
46578 : * Routine body
46579 : */
46580 0 : n = state->n;
46581 0 : state->retcode = 1;
46582 :
46583 : /*
46584 : * Set up Q0
46585 : */
46586 0 : rsetallocv(n, 0.0, &state->xs, _state);
46587 0 : bnrm = ae_sqrt(rdotv2(n, &state->b, _state), _state);
46588 0 : if( ae_fp_eq(bnrm,(double)(0)) )
46589 : {
46590 0 : result = ae_false;
46591 0 : return result;
46592 : }
46593 0 : rallocm(state->itscnt+1, n, &state->qi, _state);
46594 0 : rallocm(state->itscnt, n, &state->aqi, _state);
46595 0 : rcopymulvr(n, 1/bnrm, &state->b, &state->qi, 0, _state);
46596 0 : rsetallocm(state->itscnt+1, state->itscnt, 0.0, &state->h, _state);
46597 0 : rsetallocm(state->itscnt+1, state->itscnt, 0.0, &state->hr, _state);
46598 0 : rsetallocm(state->itscnt+1, state->itscnt+1, 0.0, &state->hq, _state);
46599 0 : for(i=0; i<=state->itscnt; i++)
46600 : {
46601 0 : state->hq.ptr.pp_double[i][i] = (double)(1);
46602 : }
46603 0 : rsetallocv(state->itscnt+1, 0.0, &state->hqb, _state);
46604 0 : state->hqb.ptr.p_double[0] = bnrm;
46605 :
46606 : /*
46607 : * Perform iteration
46608 : */
46609 0 : resnrm = bnrm;
46610 0 : kdim = 0;
46611 0 : rmax = (double)(0);
46612 0 : rmindiag = 1.0E99;
46613 0 : rsetallocv(state->itscnt, 0.0, &state->ys, _state);
46614 0 : rallocv(ae_maxint(n, state->itscnt+2, _state), &state->tmp0, _state);
46615 0 : rallocv(ae_maxint(n, state->itscnt+2, _state), &state->tmp1, _state);
46616 0 : itidx = 0;
46617 0 : lbl_1:
46618 0 : if( itidx>state->itscnt-1 )
46619 : {
46620 0 : goto lbl_3;
46621 : }
46622 0 : prevresnrm = resnrm;
46623 :
46624 : /*
46625 : * Compute A*Qi[ItIdx], then compute Qi[ItIdx+1]
46626 : */
46627 0 : rcopyrv(n, &state->qi, itidx, &state->x, _state);
46628 0 : state->rstate.stage = 0;
46629 0 : goto lbl_rcomm;
46630 0 : lbl_0:
46631 0 : rcopyvr(n, &state->ax, &state->aqi, itidx, _state);
46632 0 : anrm = ae_sqrt(rdotv2(n, &state->ax, _state), _state);
46633 0 : if( ae_fp_eq(anrm,(double)(0)) )
46634 : {
46635 0 : state->retcode = 2;
46636 0 : goto lbl_3;
46637 : }
46638 0 : rowwisegramschmidt(&state->qi, itidx+1, n, &state->ax, &state->tmp0, ae_true, _state);
46639 0 : rowwisegramschmidt(&state->qi, itidx+1, n, &state->ax, &state->tmp1, ae_true, _state);
46640 0 : raddvc(itidx+1, 1.0, &state->tmp0, &state->h, itidx, _state);
46641 0 : raddvc(itidx+1, 1.0, &state->tmp1, &state->h, itidx, _state);
46642 0 : qnrm = ae_sqrt(rdotv2(n, &state->ax, _state), _state);
46643 0 : state->h.ptr.pp_double[itidx+1][itidx] = qnrm;
46644 0 : rmulv(n, 1/coalesce(qnrm, (double)(1), _state), &state->ax, _state);
46645 0 : rcopyvr(n, &state->ax, &state->qi, itidx+1, _state);
46646 :
46647 : /*
46648 : * We have QR decomposition of H from the previous iteration:
46649 : * * (ItIdx+1)*(ItIdx+1) orthogonal HQ embedded into larger (ItIdx+2)*(ItIdx+2) identity matrix
46650 : * * (ItIdx+1)*ItIdx triangular HR embedded into larger (ItIdx+2)*(ItIdx+1) zero matrix
46651 : *
46652 : * We just have to update QR decomposition after one more column is added to H:
46653 : * * multiply this column by HQ to obtain (ItIdx+2)-dimensional vector X
46654 : * * generate rotation to nullify last element of X to obtain (ItIdx+1)-dimensional vector Y
46655 : * that is copied into (ItIdx+1)-th column of HR
46656 : * * apply same rotation to HQ
46657 : * * apply same rotation to HQB - current right-hand side
46658 : */
46659 0 : rcopycv(itidx+2, &state->h, itidx, &state->tmp0, _state);
46660 0 : rmatrixgemv(itidx+2, itidx+2, 1.0, &state->hq, 0, 0, 0, &state->tmp0, 0, 0.0, &state->tmp1, 0, _state);
46661 0 : generaterotation(state->tmp1.ptr.p_double[itidx], state->tmp1.ptr.p_double[itidx+1], &cs, &sn, &v, _state);
46662 0 : state->tmp1.ptr.p_double[itidx] = v;
46663 0 : state->tmp1.ptr.p_double[itidx+1] = (double)(0);
46664 0 : rmax = ae_maxreal(rmax, rmaxabsv(itidx+2, &state->tmp1, _state), _state);
46665 0 : rmindiag = ae_minreal(rmindiag, ae_fabs(v, _state), _state);
46666 0 : if( ae_fp_less_eq(rmindiag,rmax*state->epsdiag) )
46667 : {
46668 0 : state->retcode = 3;
46669 0 : goto lbl_3;
46670 : }
46671 0 : rcopyvc(itidx+2, &state->tmp1, &state->hr, itidx, _state);
46672 0 : for(j=0; j<=itidx+1; j++)
46673 : {
46674 0 : v = state->hq.ptr.pp_double[itidx+0][j];
46675 0 : vv = state->hq.ptr.pp_double[itidx+1][j];
46676 0 : state->hq.ptr.pp_double[itidx+0][j] = cs*v+sn*vv;
46677 0 : state->hq.ptr.pp_double[itidx+1][j] = -sn*v+cs*vv;
46678 : }
46679 0 : v = state->hqb.ptr.p_double[itidx+0];
46680 0 : vv = state->hqb.ptr.p_double[itidx+1];
46681 0 : state->hqb.ptr.p_double[itidx+0] = cs*v+sn*vv;
46682 0 : state->hqb.ptr.p_double[itidx+1] = -sn*v+cs*vv;
46683 0 : resnrm = ae_fabs(state->hqb.ptr.p_double[itidx+1], _state);
46684 :
46685 : /*
46686 : * Previous attempt to extend R was successful (no small diagonal elements).
46687 : * Increase Krylov subspace dimensionality.
46688 : */
46689 0 : kdim = kdim+1;
46690 :
46691 : /*
46692 : * Iteration is over.
46693 : * Terminate if:
46694 : * * last Qi was nearly zero after orthogonalization.
46695 : * * sufficient decrease of residual
46696 : * * stagnation of residual
46697 : */
46698 0 : state->itsperformed = state->itsperformed+1;
46699 0 : if( ae_fp_less_eq(qnrm,state->epsort*anrm)||ae_fp_eq(qnrm,(double)(0)) )
46700 : {
46701 0 : state->retcode = 4;
46702 0 : goto lbl_3;
46703 : }
46704 0 : if( ae_fp_less_eq(resnrm,state->epsres*bnrm) )
46705 : {
46706 0 : state->retcode = 5;
46707 0 : goto lbl_3;
46708 : }
46709 0 : if( ae_fp_greater(resnrm/prevresnrm,state->epsred) )
46710 : {
46711 0 : state->retcode = 6;
46712 0 : goto lbl_3;
46713 : }
46714 0 : itidx = itidx+1;
46715 0 : goto lbl_1;
46716 0 : lbl_3:
46717 :
46718 : /*
46719 : * Post-solve
46720 : */
46721 0 : if( kdim>0 )
46722 : {
46723 0 : rcopyv(kdim, &state->hqb, &state->ys, _state);
46724 0 : rmatrixtrsv(kdim, &state->hr, 0, 0, ae_true, ae_false, 0, &state->ys, 0, _state);
46725 0 : rmatrixmv(n, kdim, &state->qi, 0, 0, 1, &state->ys, 0, &state->xs, 0, _state);
46726 : }
46727 0 : result = ae_false;
46728 0 : return result;
46729 :
46730 : /*
46731 : * Saving state
46732 : */
46733 0 : lbl_rcomm:
46734 0 : result = ae_true;
46735 0 : state->rstate.ia.ptr.p_int[0] = n;
46736 0 : state->rstate.ia.ptr.p_int[1] = itidx;
46737 0 : state->rstate.ia.ptr.p_int[2] = kdim;
46738 0 : state->rstate.ia.ptr.p_int[3] = i;
46739 0 : state->rstate.ia.ptr.p_int[4] = j;
46740 0 : state->rstate.ra.ptr.p_double[0] = rmax;
46741 0 : state->rstate.ra.ptr.p_double[1] = rmindiag;
46742 0 : state->rstate.ra.ptr.p_double[2] = cs;
46743 0 : state->rstate.ra.ptr.p_double[3] = sn;
46744 0 : state->rstate.ra.ptr.p_double[4] = v;
46745 0 : state->rstate.ra.ptr.p_double[5] = vv;
46746 0 : state->rstate.ra.ptr.p_double[6] = anrm;
46747 0 : state->rstate.ra.ptr.p_double[7] = qnrm;
46748 0 : state->rstate.ra.ptr.p_double[8] = bnrm;
46749 0 : state->rstate.ra.ptr.p_double[9] = resnrm;
46750 0 : state->rstate.ra.ptr.p_double[10] = prevresnrm;
46751 0 : return result;
46752 : }
46753 :
46754 :
46755 : /*************************************************************************
46756 : Fast least squares solver, solves well conditioned system without
46757 : performing any checks for degeneracy, and using user-provided buffers
46758 : (which are automatically reallocated if too small).
46759 :
46760 : This function is intended for solution of moderately sized systems. It
46761 : uses factorization algorithms based on Level 2 BLAS operations, thus it
46762 : won't work efficiently on large scale systems.
46763 :
46764 : INPUT PARAMETERS:
46765 : A - array[M,N], system matrix.
46766 : Contents of A is destroyed during solution.
46767 : B - array[M], right part
46768 : M - number of equations
46769 : N - number of variables, N<=M
46770 : Tmp0, Tmp1, Tmp2-
46771 : buffers; function automatically allocates them, if they are
46772 : too small. They can be reused if function is called
46773 : several times.
46774 :
46775 : OUTPUT PARAMETERS:
46776 : B - solution (first N components, next M-N are zero)
46777 :
46778 : -- ALGLIB --
46779 : Copyright 20.01.2012 by Bochkanov Sergey
46780 : *************************************************************************/
46781 0 : void fblssolvels(/* Real */ ae_matrix* a,
46782 : /* Real */ ae_vector* b,
46783 : ae_int_t m,
46784 : ae_int_t n,
46785 : /* Real */ ae_vector* tmp0,
46786 : /* Real */ ae_vector* tmp1,
46787 : /* Real */ ae_vector* tmp2,
46788 : ae_state *_state)
46789 : {
46790 : ae_int_t i;
46791 : ae_int_t k;
46792 : double v;
46793 :
46794 :
46795 0 : ae_assert(n>0, "FBLSSolveLS: N<=0", _state);
46796 0 : ae_assert(m>=n, "FBLSSolveLS: M<N", _state);
46797 0 : ae_assert(a->rows>=m, "FBLSSolveLS: Rows(A)<M", _state);
46798 0 : ae_assert(a->cols>=n, "FBLSSolveLS: Cols(A)<N", _state);
46799 0 : ae_assert(b->cnt>=m, "FBLSSolveLS: Length(B)<M", _state);
46800 :
46801 : /*
46802 : * Allocate temporaries
46803 : */
46804 0 : rvectorsetlengthatleast(tmp0, ae_maxint(m, n, _state)+1, _state);
46805 0 : rvectorsetlengthatleast(tmp1, ae_maxint(m, n, _state)+1, _state);
46806 0 : rvectorsetlengthatleast(tmp2, ae_minint(m, n, _state), _state);
46807 :
46808 : /*
46809 : * Call basecase QR
46810 : */
46811 0 : rmatrixqrbasecase(a, m, n, tmp0, tmp1, tmp2, _state);
46812 :
46813 : /*
46814 : * Multiply B by Q'
46815 : */
46816 0 : for(k=0; k<=n-1; k++)
46817 : {
46818 0 : for(i=0; i<=k-1; i++)
46819 : {
46820 0 : tmp0->ptr.p_double[i] = (double)(0);
46821 : }
46822 0 : ae_v_move(&tmp0->ptr.p_double[k], 1, &a->ptr.pp_double[k][k], a->stride, ae_v_len(k,m-1));
46823 0 : tmp0->ptr.p_double[k] = (double)(1);
46824 0 : v = ae_v_dotproduct(&tmp0->ptr.p_double[k], 1, &b->ptr.p_double[k], 1, ae_v_len(k,m-1));
46825 0 : v = v*tmp2->ptr.p_double[k];
46826 0 : ae_v_subd(&b->ptr.p_double[k], 1, &tmp0->ptr.p_double[k], 1, ae_v_len(k,m-1), v);
46827 : }
46828 :
46829 : /*
46830 : * Solve triangular system
46831 : */
46832 0 : b->ptr.p_double[n-1] = b->ptr.p_double[n-1]/a->ptr.pp_double[n-1][n-1];
46833 0 : for(i=n-2; i>=0; i--)
46834 : {
46835 0 : v = ae_v_dotproduct(&a->ptr.pp_double[i][i+1], 1, &b->ptr.p_double[i+1], 1, ae_v_len(i+1,n-1));
46836 0 : b->ptr.p_double[i] = (b->ptr.p_double[i]-v)/a->ptr.pp_double[i][i];
46837 : }
46838 0 : for(i=n; i<=m-1; i++)
46839 : {
46840 0 : b->ptr.p_double[i] = 0.0;
46841 : }
46842 0 : }
46843 :
46844 :
46845 0 : void _fblslincgstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
46846 : {
46847 0 : fblslincgstate *p = (fblslincgstate*)_p;
46848 0 : ae_touch_ptr((void*)p);
46849 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
46850 0 : ae_vector_init(&p->ax, 0, DT_REAL, _state, make_automatic);
46851 0 : ae_vector_init(&p->rk, 0, DT_REAL, _state, make_automatic);
46852 0 : ae_vector_init(&p->rk1, 0, DT_REAL, _state, make_automatic);
46853 0 : ae_vector_init(&p->xk, 0, DT_REAL, _state, make_automatic);
46854 0 : ae_vector_init(&p->xk1, 0, DT_REAL, _state, make_automatic);
46855 0 : ae_vector_init(&p->pk, 0, DT_REAL, _state, make_automatic);
46856 0 : ae_vector_init(&p->pk1, 0, DT_REAL, _state, make_automatic);
46857 0 : ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic);
46858 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
46859 0 : ae_vector_init(&p->tmp2, 0, DT_REAL, _state, make_automatic);
46860 0 : }
46861 :
46862 :
46863 0 : void _fblslincgstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
46864 : {
46865 0 : fblslincgstate *dst = (fblslincgstate*)_dst;
46866 0 : fblslincgstate *src = (fblslincgstate*)_src;
46867 0 : dst->e1 = src->e1;
46868 0 : dst->e2 = src->e2;
46869 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
46870 0 : ae_vector_init_copy(&dst->ax, &src->ax, _state, make_automatic);
46871 0 : dst->xax = src->xax;
46872 0 : dst->n = src->n;
46873 0 : ae_vector_init_copy(&dst->rk, &src->rk, _state, make_automatic);
46874 0 : ae_vector_init_copy(&dst->rk1, &src->rk1, _state, make_automatic);
46875 0 : ae_vector_init_copy(&dst->xk, &src->xk, _state, make_automatic);
46876 0 : ae_vector_init_copy(&dst->xk1, &src->xk1, _state, make_automatic);
46877 0 : ae_vector_init_copy(&dst->pk, &src->pk, _state, make_automatic);
46878 0 : ae_vector_init_copy(&dst->pk1, &src->pk1, _state, make_automatic);
46879 0 : ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic);
46880 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
46881 0 : ae_vector_init_copy(&dst->tmp2, &src->tmp2, _state, make_automatic);
46882 0 : }
46883 :
46884 :
46885 0 : void _fblslincgstate_clear(void* _p)
46886 : {
46887 0 : fblslincgstate *p = (fblslincgstate*)_p;
46888 0 : ae_touch_ptr((void*)p);
46889 0 : ae_vector_clear(&p->x);
46890 0 : ae_vector_clear(&p->ax);
46891 0 : ae_vector_clear(&p->rk);
46892 0 : ae_vector_clear(&p->rk1);
46893 0 : ae_vector_clear(&p->xk);
46894 0 : ae_vector_clear(&p->xk1);
46895 0 : ae_vector_clear(&p->pk);
46896 0 : ae_vector_clear(&p->pk1);
46897 0 : ae_vector_clear(&p->b);
46898 0 : _rcommstate_clear(&p->rstate);
46899 0 : ae_vector_clear(&p->tmp2);
46900 0 : }
46901 :
46902 :
46903 0 : void _fblslincgstate_destroy(void* _p)
46904 : {
46905 0 : fblslincgstate *p = (fblslincgstate*)_p;
46906 0 : ae_touch_ptr((void*)p);
46907 0 : ae_vector_destroy(&p->x);
46908 0 : ae_vector_destroy(&p->ax);
46909 0 : ae_vector_destroy(&p->rk);
46910 0 : ae_vector_destroy(&p->rk1);
46911 0 : ae_vector_destroy(&p->xk);
46912 0 : ae_vector_destroy(&p->xk1);
46913 0 : ae_vector_destroy(&p->pk);
46914 0 : ae_vector_destroy(&p->pk1);
46915 0 : ae_vector_destroy(&p->b);
46916 0 : _rcommstate_destroy(&p->rstate);
46917 0 : ae_vector_destroy(&p->tmp2);
46918 0 : }
46919 :
46920 :
46921 0 : void _fblsgmresstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
46922 : {
46923 0 : fblsgmresstate *p = (fblsgmresstate*)_p;
46924 0 : ae_touch_ptr((void*)p);
46925 0 : ae_vector_init(&p->b, 0, DT_REAL, _state, make_automatic);
46926 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
46927 0 : ae_vector_init(&p->ax, 0, DT_REAL, _state, make_automatic);
46928 0 : ae_vector_init(&p->xs, 0, DT_REAL, _state, make_automatic);
46929 0 : ae_matrix_init(&p->qi, 0, 0, DT_REAL, _state, make_automatic);
46930 0 : ae_matrix_init(&p->aqi, 0, 0, DT_REAL, _state, make_automatic);
46931 0 : ae_matrix_init(&p->h, 0, 0, DT_REAL, _state, make_automatic);
46932 0 : ae_matrix_init(&p->hq, 0, 0, DT_REAL, _state, make_automatic);
46933 0 : ae_matrix_init(&p->hr, 0, 0, DT_REAL, _state, make_automatic);
46934 0 : ae_vector_init(&p->hqb, 0, DT_REAL, _state, make_automatic);
46935 0 : ae_vector_init(&p->ys, 0, DT_REAL, _state, make_automatic);
46936 0 : ae_vector_init(&p->tmp0, 0, DT_REAL, _state, make_automatic);
46937 0 : ae_vector_init(&p->tmp1, 0, DT_REAL, _state, make_automatic);
46938 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
46939 0 : }
46940 :
46941 :
46942 0 : void _fblsgmresstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
46943 : {
46944 0 : fblsgmresstate *dst = (fblsgmresstate*)_dst;
46945 0 : fblsgmresstate *src = (fblsgmresstate*)_src;
46946 0 : ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic);
46947 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
46948 0 : ae_vector_init_copy(&dst->ax, &src->ax, _state, make_automatic);
46949 0 : ae_vector_init_copy(&dst->xs, &src->xs, _state, make_automatic);
46950 0 : ae_matrix_init_copy(&dst->qi, &src->qi, _state, make_automatic);
46951 0 : ae_matrix_init_copy(&dst->aqi, &src->aqi, _state, make_automatic);
46952 0 : ae_matrix_init_copy(&dst->h, &src->h, _state, make_automatic);
46953 0 : ae_matrix_init_copy(&dst->hq, &src->hq, _state, make_automatic);
46954 0 : ae_matrix_init_copy(&dst->hr, &src->hr, _state, make_automatic);
46955 0 : ae_vector_init_copy(&dst->hqb, &src->hqb, _state, make_automatic);
46956 0 : ae_vector_init_copy(&dst->ys, &src->ys, _state, make_automatic);
46957 0 : ae_vector_init_copy(&dst->tmp0, &src->tmp0, _state, make_automatic);
46958 0 : ae_vector_init_copy(&dst->tmp1, &src->tmp1, _state, make_automatic);
46959 0 : dst->n = src->n;
46960 0 : dst->itscnt = src->itscnt;
46961 0 : dst->epsort = src->epsort;
46962 0 : dst->epsres = src->epsres;
46963 0 : dst->epsred = src->epsred;
46964 0 : dst->epsdiag = src->epsdiag;
46965 0 : dst->itsperformed = src->itsperformed;
46966 0 : dst->retcode = src->retcode;
46967 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
46968 0 : }
46969 :
46970 :
46971 0 : void _fblsgmresstate_clear(void* _p)
46972 : {
46973 0 : fblsgmresstate *p = (fblsgmresstate*)_p;
46974 0 : ae_touch_ptr((void*)p);
46975 0 : ae_vector_clear(&p->b);
46976 0 : ae_vector_clear(&p->x);
46977 0 : ae_vector_clear(&p->ax);
46978 0 : ae_vector_clear(&p->xs);
46979 0 : ae_matrix_clear(&p->qi);
46980 0 : ae_matrix_clear(&p->aqi);
46981 0 : ae_matrix_clear(&p->h);
46982 0 : ae_matrix_clear(&p->hq);
46983 0 : ae_matrix_clear(&p->hr);
46984 0 : ae_vector_clear(&p->hqb);
46985 0 : ae_vector_clear(&p->ys);
46986 0 : ae_vector_clear(&p->tmp0);
46987 0 : ae_vector_clear(&p->tmp1);
46988 0 : _rcommstate_clear(&p->rstate);
46989 0 : }
46990 :
46991 :
46992 0 : void _fblsgmresstate_destroy(void* _p)
46993 : {
46994 0 : fblsgmresstate *p = (fblsgmresstate*)_p;
46995 0 : ae_touch_ptr((void*)p);
46996 0 : ae_vector_destroy(&p->b);
46997 0 : ae_vector_destroy(&p->x);
46998 0 : ae_vector_destroy(&p->ax);
46999 0 : ae_vector_destroy(&p->xs);
47000 0 : ae_matrix_destroy(&p->qi);
47001 0 : ae_matrix_destroy(&p->aqi);
47002 0 : ae_matrix_destroy(&p->h);
47003 0 : ae_matrix_destroy(&p->hq);
47004 0 : ae_matrix_destroy(&p->hr);
47005 0 : ae_vector_destroy(&p->hqb);
47006 0 : ae_vector_destroy(&p->ys);
47007 0 : ae_vector_destroy(&p->tmp0);
47008 0 : ae_vector_destroy(&p->tmp1);
47009 0 : _rcommstate_destroy(&p->rstate);
47010 0 : }
47011 :
47012 :
47013 : #endif
47014 : #if defined(AE_COMPILE_BDSVD) || !defined(AE_PARTIAL_BUILD)
47015 :
47016 :
47017 : /*************************************************************************
47018 : Singular value decomposition of a bidiagonal matrix (extended algorithm)
47019 :
47020 : COMMERCIAL EDITION OF ALGLIB:
47021 :
47022 : ! Commercial version of ALGLIB includes one important improvement of
47023 : ! this function, which can be used from C++ and C#:
47024 : ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB)
47025 : !
47026 : ! Intel MKL gives approximately constant (with respect to number of
47027 : ! worker threads) acceleration factor which depends on CPU being used,
47028 : ! problem size and "baseline" ALGLIB edition which is used for
47029 : ! comparison.
47030 : !
47031 : ! Generally, commercial ALGLIB is several times faster than open-source
47032 : ! generic C edition, and many times faster than open-source C# edition.
47033 : !
47034 : ! Multithreaded acceleration is NOT supported for this function.
47035 : !
47036 : ! We recommend you to read 'Working with commercial version' section of
47037 : ! ALGLIB Reference Manual in order to find out how to use performance-
47038 : ! related features provided by commercial edition of ALGLIB.
47039 :
47040 : The algorithm performs the singular value decomposition of a bidiagonal
47041 : matrix B (upper or lower) representing it as B = Q*S*P^T, where Q and P -
47042 : orthogonal matrices, S - diagonal matrix with non-negative elements on the
47043 : main diagonal, in descending order.
47044 :
47045 : The algorithm finds singular values. In addition, the algorithm can
47046 : calculate matrices Q and P (more precisely, not the matrices, but their
47047 : product with given matrices U and VT - U*Q and (P^T)*VT)). Of course,
47048 : matrices U and VT can be of any type, including identity. Furthermore, the
47049 : algorithm can calculate Q'*C (this product is calculated more effectively
47050 : than U*Q, because this calculation operates with rows instead of matrix
47051 : columns).
47052 :
47053 : The feature of the algorithm is its ability to find all singular values
47054 : including those which are arbitrarily close to 0 with relative accuracy
47055 : close to machine precision. If the parameter IsFractionalAccuracyRequired
47056 : is set to True, all singular values will have high relative accuracy close
47057 : to machine precision. If the parameter is set to False, only the biggest
47058 : singular value will have relative accuracy close to machine precision.
47059 : The absolute error of other singular values is equal to the absolute error
47060 : of the biggest singular value.
47061 :
47062 : Input parameters:
47063 : D - main diagonal of matrix B.
47064 : Array whose index ranges within [0..N-1].
47065 : E - superdiagonal (or subdiagonal) of matrix B.
47066 : Array whose index ranges within [0..N-2].
47067 : N - size of matrix B.
47068 : IsUpper - True, if the matrix is upper bidiagonal.
47069 : IsFractionalAccuracyRequired -
47070 : THIS PARAMETER IS IGNORED SINCE ALGLIB 3.5.0
47071 : SINGULAR VALUES ARE ALWAYS SEARCHED WITH HIGH ACCURACY.
47072 : U - matrix to be multiplied by Q.
47073 : Array whose indexes range within [0..NRU-1, 0..N-1].
47074 : The matrix can be bigger, in that case only the submatrix
47075 : [0..NRU-1, 0..N-1] will be multiplied by Q.
47076 : NRU - number of rows in matrix U.
47077 : C - matrix to be multiplied by Q'.
47078 : Array whose indexes range within [0..N-1, 0..NCC-1].
47079 : The matrix can be bigger, in that case only the submatrix
47080 : [0..N-1, 0..NCC-1] will be multiplied by Q'.
47081 : NCC - number of columns in matrix C.
47082 : VT - matrix to be multiplied by P^T.
47083 : Array whose indexes range within [0..N-1, 0..NCVT-1].
47084 : The matrix can be bigger, in that case only the submatrix
47085 : [0..N-1, 0..NCVT-1] will be multiplied by P^T.
47086 : NCVT - number of columns in matrix VT.
47087 :
47088 : Output parameters:
47089 : D - singular values of matrix B in descending order.
47090 : U - if NRU>0, contains matrix U*Q.
47091 : VT - if NCVT>0, contains matrix (P^T)*VT.
47092 : C - if NCC>0, contains matrix Q'*C.
47093 :
47094 : Result:
47095 : True, if the algorithm has converged.
47096 : False, if the algorithm hasn't converged (rare case).
47097 :
47098 : NOTE: multiplication U*Q is performed by means of transposition to internal
47099 : buffer, multiplication and backward transposition. It helps to avoid
47100 : costly columnwise operations and speed-up algorithm.
47101 :
47102 : Additional information:
47103 : The type of convergence is controlled by the internal parameter TOL.
47104 : If the parameter is greater than 0, the singular values will have
47105 : relative accuracy TOL. If TOL<0, the singular values will have
47106 : absolute accuracy ABS(TOL)*norm(B).
47107 : By default, |TOL| falls within the range of 10*Epsilon and 100*Epsilon,
47108 : where Epsilon is the machine precision. It is not recommended to use
47109 : TOL less than 10*Epsilon since this will considerably slow down the
47110 : algorithm and may not lead to error decreasing.
47111 :
47112 : History:
47113 : * 31 March, 2007.
47114 : changed MAXITR from 6 to 12.
47115 :
47116 : -- LAPACK routine (version 3.0) --
47117 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
47118 : Courant Institute, Argonne National Lab, and Rice University
47119 : October 31, 1999.
47120 : *************************************************************************/
47121 0 : ae_bool rmatrixbdsvd(/* Real */ ae_vector* d,
47122 : /* Real */ ae_vector* e,
47123 : ae_int_t n,
47124 : ae_bool isupper,
47125 : ae_bool isfractionalaccuracyrequired,
47126 : /* Real */ ae_matrix* u,
47127 : ae_int_t nru,
47128 : /* Real */ ae_matrix* c,
47129 : ae_int_t ncc,
47130 : /* Real */ ae_matrix* vt,
47131 : ae_int_t ncvt,
47132 : ae_state *_state)
47133 : {
47134 : ae_frame _frame_block;
47135 : ae_vector _e;
47136 : ae_int_t i;
47137 : ae_vector en;
47138 : ae_vector d1;
47139 : ae_vector e1;
47140 : ae_bool result;
47141 :
47142 0 : ae_frame_make(_state, &_frame_block);
47143 0 : memset(&_e, 0, sizeof(_e));
47144 0 : memset(&en, 0, sizeof(en));
47145 0 : memset(&d1, 0, sizeof(d1));
47146 0 : memset(&e1, 0, sizeof(e1));
47147 0 : ae_vector_init_copy(&_e, e, _state, ae_true);
47148 0 : e = &_e;
47149 0 : ae_vector_init(&en, 0, DT_REAL, _state, ae_true);
47150 0 : ae_vector_init(&d1, 0, DT_REAL, _state, ae_true);
47151 0 : ae_vector_init(&e1, 0, DT_REAL, _state, ae_true);
47152 :
47153 0 : result = ae_false;
47154 :
47155 : /*
47156 : * Try to use MKL
47157 : */
47158 0 : ae_vector_set_length(&en, n, _state);
47159 0 : for(i=0; i<=n-2; i++)
47160 : {
47161 0 : en.ptr.p_double[i] = e->ptr.p_double[i];
47162 : }
47163 0 : en.ptr.p_double[n-1] = 0.0;
47164 0 : if( rmatrixbdsvdmkl(d, &en, n, isupper, u, nru, c, ncc, vt, ncvt, &result, _state) )
47165 : {
47166 0 : ae_frame_leave(_state);
47167 0 : return result;
47168 : }
47169 :
47170 : /*
47171 : * Use ALGLIB code
47172 : */
47173 0 : ae_vector_set_length(&d1, n+1, _state);
47174 0 : ae_v_move(&d1.ptr.p_double[1], 1, &d->ptr.p_double[0], 1, ae_v_len(1,n));
47175 0 : if( n>1 )
47176 : {
47177 0 : ae_vector_set_length(&e1, n-1+1, _state);
47178 0 : ae_v_move(&e1.ptr.p_double[1], 1, &e->ptr.p_double[0], 1, ae_v_len(1,n-1));
47179 : }
47180 0 : result = bdsvd_bidiagonalsvddecompositioninternal(&d1, &e1, n, isupper, isfractionalaccuracyrequired, u, 0, nru, c, 0, ncc, vt, 0, ncvt, _state);
47181 0 : ae_v_move(&d->ptr.p_double[0], 1, &d1.ptr.p_double[1], 1, ae_v_len(0,n-1));
47182 0 : ae_frame_leave(_state);
47183 0 : return result;
47184 : }
47185 :
47186 :
47187 0 : ae_bool bidiagonalsvddecomposition(/* Real */ ae_vector* d,
47188 : /* Real */ ae_vector* e,
47189 : ae_int_t n,
47190 : ae_bool isupper,
47191 : ae_bool isfractionalaccuracyrequired,
47192 : /* Real */ ae_matrix* u,
47193 : ae_int_t nru,
47194 : /* Real */ ae_matrix* c,
47195 : ae_int_t ncc,
47196 : /* Real */ ae_matrix* vt,
47197 : ae_int_t ncvt,
47198 : ae_state *_state)
47199 : {
47200 : ae_frame _frame_block;
47201 : ae_vector _e;
47202 : ae_bool result;
47203 :
47204 0 : ae_frame_make(_state, &_frame_block);
47205 0 : memset(&_e, 0, sizeof(_e));
47206 0 : ae_vector_init_copy(&_e, e, _state, ae_true);
47207 0 : e = &_e;
47208 :
47209 0 : result = bdsvd_bidiagonalsvddecompositioninternal(d, e, n, isupper, isfractionalaccuracyrequired, u, 1, nru, c, 1, ncc, vt, 1, ncvt, _state);
47210 0 : ae_frame_leave(_state);
47211 0 : return result;
47212 : }
47213 :
47214 :
47215 : /*************************************************************************
47216 : Internal working subroutine for bidiagonal decomposition
47217 : *************************************************************************/
47218 0 : static ae_bool bdsvd_bidiagonalsvddecompositioninternal(/* Real */ ae_vector* d,
47219 : /* Real */ ae_vector* e,
47220 : ae_int_t n,
47221 : ae_bool isupper,
47222 : ae_bool isfractionalaccuracyrequired,
47223 : /* Real */ ae_matrix* uu,
47224 : ae_int_t ustart,
47225 : ae_int_t nru,
47226 : /* Real */ ae_matrix* c,
47227 : ae_int_t cstart,
47228 : ae_int_t ncc,
47229 : /* Real */ ae_matrix* vt,
47230 : ae_int_t vstart,
47231 : ae_int_t ncvt,
47232 : ae_state *_state)
47233 : {
47234 : ae_frame _frame_block;
47235 : ae_vector _e;
47236 : ae_int_t i;
47237 : ae_int_t idir;
47238 : ae_int_t isub;
47239 : ae_int_t iter;
47240 : ae_int_t j;
47241 : ae_int_t ll;
47242 : ae_int_t lll;
47243 : ae_int_t m;
47244 : ae_int_t maxit;
47245 : ae_int_t oldll;
47246 : ae_int_t oldm;
47247 : double abse;
47248 : double abss;
47249 : double cosl;
47250 : double cosr;
47251 : double cs;
47252 : double eps;
47253 : double f;
47254 : double g;
47255 : double h;
47256 : double mu;
47257 : double oldcs;
47258 : double oldsn;
47259 : double r;
47260 : double shift;
47261 : double sigmn;
47262 : double sigmx;
47263 : double sinl;
47264 : double sinr;
47265 : double sll;
47266 : double smax;
47267 : double smin;
47268 : double sminl;
47269 : double sminoa;
47270 : double sn;
47271 : double thresh;
47272 : double tol;
47273 : double tolmul;
47274 : double unfl;
47275 : ae_vector work0;
47276 : ae_vector work1;
47277 : ae_vector work2;
47278 : ae_vector work3;
47279 : ae_int_t maxitr;
47280 : ae_bool matrixsplitflag;
47281 : ae_bool iterflag;
47282 : ae_vector utemp;
47283 : ae_vector vttemp;
47284 : ae_vector ctemp;
47285 : ae_vector etemp;
47286 : ae_matrix ut;
47287 : ae_bool fwddir;
47288 : double tmp;
47289 : ae_int_t mm1;
47290 : ae_int_t mm0;
47291 : ae_bool bchangedir;
47292 : ae_int_t uend;
47293 : ae_int_t cend;
47294 : ae_int_t vend;
47295 : ae_bool result;
47296 :
47297 0 : ae_frame_make(_state, &_frame_block);
47298 0 : memset(&_e, 0, sizeof(_e));
47299 0 : memset(&work0, 0, sizeof(work0));
47300 0 : memset(&work1, 0, sizeof(work1));
47301 0 : memset(&work2, 0, sizeof(work2));
47302 0 : memset(&work3, 0, sizeof(work3));
47303 0 : memset(&utemp, 0, sizeof(utemp));
47304 0 : memset(&vttemp, 0, sizeof(vttemp));
47305 0 : memset(&ctemp, 0, sizeof(ctemp));
47306 0 : memset(&etemp, 0, sizeof(etemp));
47307 0 : memset(&ut, 0, sizeof(ut));
47308 0 : ae_vector_init_copy(&_e, e, _state, ae_true);
47309 0 : e = &_e;
47310 0 : ae_vector_init(&work0, 0, DT_REAL, _state, ae_true);
47311 0 : ae_vector_init(&work1, 0, DT_REAL, _state, ae_true);
47312 0 : ae_vector_init(&work2, 0, DT_REAL, _state, ae_true);
47313 0 : ae_vector_init(&work3, 0, DT_REAL, _state, ae_true);
47314 0 : ae_vector_init(&utemp, 0, DT_REAL, _state, ae_true);
47315 0 : ae_vector_init(&vttemp, 0, DT_REAL, _state, ae_true);
47316 0 : ae_vector_init(&ctemp, 0, DT_REAL, _state, ae_true);
47317 0 : ae_vector_init(&etemp, 0, DT_REAL, _state, ae_true);
47318 0 : ae_matrix_init(&ut, 0, 0, DT_REAL, _state, ae_true);
47319 :
47320 0 : result = ae_true;
47321 0 : if( n==0 )
47322 : {
47323 0 : ae_frame_leave(_state);
47324 0 : return result;
47325 : }
47326 0 : if( n==1 )
47327 : {
47328 0 : if( ae_fp_less(d->ptr.p_double[1],(double)(0)) )
47329 : {
47330 0 : d->ptr.p_double[1] = -d->ptr.p_double[1];
47331 0 : if( ncvt>0 )
47332 : {
47333 0 : ae_v_muld(&vt->ptr.pp_double[vstart][vstart], 1, ae_v_len(vstart,vstart+ncvt-1), -1);
47334 : }
47335 : }
47336 0 : ae_frame_leave(_state);
47337 0 : return result;
47338 : }
47339 :
47340 : /*
47341 : * these initializers are not really necessary,
47342 : * but without them compiler complains about uninitialized locals
47343 : */
47344 0 : ll = 0;
47345 0 : oldsn = (double)(0);
47346 :
47347 : /*
47348 : * init
47349 : */
47350 0 : ae_vector_set_length(&work0, n-1+1, _state);
47351 0 : ae_vector_set_length(&work1, n-1+1, _state);
47352 0 : ae_vector_set_length(&work2, n-1+1, _state);
47353 0 : ae_vector_set_length(&work3, n-1+1, _state);
47354 0 : uend = ustart+ae_maxint(nru-1, 0, _state);
47355 0 : vend = vstart+ae_maxint(ncvt-1, 0, _state);
47356 0 : cend = cstart+ae_maxint(ncc-1, 0, _state);
47357 0 : ae_vector_set_length(&utemp, uend+1, _state);
47358 0 : ae_vector_set_length(&vttemp, vend+1, _state);
47359 0 : ae_vector_set_length(&ctemp, cend+1, _state);
47360 0 : maxitr = 12;
47361 0 : fwddir = ae_true;
47362 0 : if( nru>0 )
47363 : {
47364 0 : ae_matrix_set_length(&ut, ustart+n, ustart+nru, _state);
47365 0 : rmatrixtranspose(nru, n, uu, ustart, ustart, &ut, ustart, ustart, _state);
47366 : }
47367 :
47368 : /*
47369 : * resize E from N-1 to N
47370 : */
47371 0 : ae_vector_set_length(&etemp, n+1, _state);
47372 0 : for(i=1; i<=n-1; i++)
47373 : {
47374 0 : etemp.ptr.p_double[i] = e->ptr.p_double[i];
47375 : }
47376 0 : ae_vector_set_length(e, n+1, _state);
47377 0 : for(i=1; i<=n-1; i++)
47378 : {
47379 0 : e->ptr.p_double[i] = etemp.ptr.p_double[i];
47380 : }
47381 0 : e->ptr.p_double[n] = (double)(0);
47382 0 : idir = 0;
47383 :
47384 : /*
47385 : * Get machine constants
47386 : */
47387 0 : eps = ae_machineepsilon;
47388 0 : unfl = ae_minrealnumber;
47389 :
47390 : /*
47391 : * If matrix lower bidiagonal, rotate to be upper bidiagonal
47392 : * by applying Givens rotations on the left
47393 : */
47394 0 : if( !isupper )
47395 : {
47396 0 : for(i=1; i<=n-1; i++)
47397 : {
47398 0 : generaterotation(d->ptr.p_double[i], e->ptr.p_double[i], &cs, &sn, &r, _state);
47399 0 : d->ptr.p_double[i] = r;
47400 0 : e->ptr.p_double[i] = sn*d->ptr.p_double[i+1];
47401 0 : d->ptr.p_double[i+1] = cs*d->ptr.p_double[i+1];
47402 0 : work0.ptr.p_double[i] = cs;
47403 0 : work1.ptr.p_double[i] = sn;
47404 : }
47405 :
47406 : /*
47407 : * Update singular vectors if desired
47408 : */
47409 0 : if( nru>0 )
47410 : {
47411 0 : applyrotationsfromtheleft(fwddir, 1+ustart-1, n+ustart-1, ustart, uend, &work0, &work1, &ut, &utemp, _state);
47412 : }
47413 0 : if( ncc>0 )
47414 : {
47415 0 : applyrotationsfromtheleft(fwddir, 1+cstart-1, n+cstart-1, cstart, cend, &work0, &work1, c, &ctemp, _state);
47416 : }
47417 : }
47418 :
47419 : /*
47420 : * Compute singular values to relative accuracy TOL
47421 : * (By setting TOL to be negative, algorithm will compute
47422 : * singular values to absolute accuracy ABS(TOL)*norm(input matrix))
47423 : */
47424 0 : tolmul = ae_maxreal((double)(10), ae_minreal((double)(100), ae_pow(eps, -0.125, _state), _state), _state);
47425 0 : tol = tolmul*eps;
47426 :
47427 : /*
47428 : * Compute approximate maximum, minimum singular values
47429 : */
47430 0 : smax = (double)(0);
47431 0 : for(i=1; i<=n; i++)
47432 : {
47433 0 : smax = ae_maxreal(smax, ae_fabs(d->ptr.p_double[i], _state), _state);
47434 : }
47435 0 : for(i=1; i<=n-1; i++)
47436 : {
47437 0 : smax = ae_maxreal(smax, ae_fabs(e->ptr.p_double[i], _state), _state);
47438 : }
47439 0 : sminl = (double)(0);
47440 0 : if( ae_fp_greater_eq(tol,(double)(0)) )
47441 : {
47442 :
47443 : /*
47444 : * Relative accuracy desired
47445 : */
47446 0 : sminoa = ae_fabs(d->ptr.p_double[1], _state);
47447 0 : if( ae_fp_neq(sminoa,(double)(0)) )
47448 : {
47449 0 : mu = sminoa;
47450 0 : for(i=2; i<=n; i++)
47451 : {
47452 0 : mu = ae_fabs(d->ptr.p_double[i], _state)*(mu/(mu+ae_fabs(e->ptr.p_double[i-1], _state)));
47453 0 : sminoa = ae_minreal(sminoa, mu, _state);
47454 0 : if( ae_fp_eq(sminoa,(double)(0)) )
47455 : {
47456 0 : break;
47457 : }
47458 : }
47459 : }
47460 0 : sminoa = sminoa/ae_sqrt((double)(n), _state);
47461 0 : thresh = ae_maxreal(tol*sminoa, maxitr*n*n*unfl, _state);
47462 : }
47463 : else
47464 : {
47465 :
47466 : /*
47467 : * Absolute accuracy desired
47468 : */
47469 0 : thresh = ae_maxreal(ae_fabs(tol, _state)*smax, maxitr*n*n*unfl, _state);
47470 : }
47471 :
47472 : /*
47473 : * Prepare for main iteration loop for the singular values
47474 : * (MAXIT is the maximum number of passes through the inner
47475 : * loop permitted before nonconvergence signalled.)
47476 : */
47477 0 : maxit = maxitr*n*n;
47478 0 : iter = 0;
47479 0 : oldll = -1;
47480 0 : oldm = -1;
47481 :
47482 : /*
47483 : * M points to last element of unconverged part of matrix
47484 : */
47485 0 : m = n;
47486 :
47487 : /*
47488 : * Begin main iteration loop
47489 : */
47490 : for(;;)
47491 : {
47492 :
47493 : /*
47494 : * Check for convergence or exceeding iteration count
47495 : */
47496 0 : if( m<=1 )
47497 : {
47498 0 : break;
47499 : }
47500 0 : if( iter>maxit )
47501 : {
47502 0 : result = ae_false;
47503 0 : ae_frame_leave(_state);
47504 0 : return result;
47505 : }
47506 :
47507 : /*
47508 : * Find diagonal block of matrix to work on
47509 : */
47510 0 : if( ae_fp_less(tol,(double)(0))&&ae_fp_less_eq(ae_fabs(d->ptr.p_double[m], _state),thresh) )
47511 : {
47512 0 : d->ptr.p_double[m] = (double)(0);
47513 : }
47514 0 : smax = ae_fabs(d->ptr.p_double[m], _state);
47515 0 : smin = smax;
47516 0 : matrixsplitflag = ae_false;
47517 0 : for(lll=1; lll<=m-1; lll++)
47518 : {
47519 0 : ll = m-lll;
47520 0 : abss = ae_fabs(d->ptr.p_double[ll], _state);
47521 0 : abse = ae_fabs(e->ptr.p_double[ll], _state);
47522 0 : if( ae_fp_less(tol,(double)(0))&&ae_fp_less_eq(abss,thresh) )
47523 : {
47524 0 : d->ptr.p_double[ll] = (double)(0);
47525 : }
47526 0 : if( ae_fp_less_eq(abse,thresh) )
47527 : {
47528 0 : matrixsplitflag = ae_true;
47529 0 : break;
47530 : }
47531 0 : smin = ae_minreal(smin, abss, _state);
47532 0 : smax = ae_maxreal(smax, ae_maxreal(abss, abse, _state), _state);
47533 : }
47534 0 : if( !matrixsplitflag )
47535 : {
47536 0 : ll = 0;
47537 : }
47538 : else
47539 : {
47540 :
47541 : /*
47542 : * Matrix splits since E(LL) = 0
47543 : */
47544 0 : e->ptr.p_double[ll] = (double)(0);
47545 0 : if( ll==m-1 )
47546 : {
47547 :
47548 : /*
47549 : * Convergence of bottom singular value, return to top of loop
47550 : */
47551 0 : m = m-1;
47552 0 : continue;
47553 : }
47554 : }
47555 0 : ll = ll+1;
47556 :
47557 : /*
47558 : * E(LL) through E(M-1) are nonzero, E(LL-1) is zero
47559 : */
47560 0 : if( ll==m-1 )
47561 : {
47562 :
47563 : /*
47564 : * 2 by 2 block, handle separately
47565 : */
47566 0 : bdsvd_svdv2x2(d->ptr.p_double[m-1], e->ptr.p_double[m-1], d->ptr.p_double[m], &sigmn, &sigmx, &sinr, &cosr, &sinl, &cosl, _state);
47567 0 : d->ptr.p_double[m-1] = sigmx;
47568 0 : e->ptr.p_double[m-1] = (double)(0);
47569 0 : d->ptr.p_double[m] = sigmn;
47570 :
47571 : /*
47572 : * Compute singular vectors, if desired
47573 : */
47574 0 : if( ncvt>0 )
47575 : {
47576 0 : mm0 = m+(vstart-1);
47577 0 : mm1 = m-1+(vstart-1);
47578 0 : ae_v_moved(&vttemp.ptr.p_double[vstart], 1, &vt->ptr.pp_double[mm1][vstart], 1, ae_v_len(vstart,vend), cosr);
47579 0 : ae_v_addd(&vttemp.ptr.p_double[vstart], 1, &vt->ptr.pp_double[mm0][vstart], 1, ae_v_len(vstart,vend), sinr);
47580 0 : ae_v_muld(&vt->ptr.pp_double[mm0][vstart], 1, ae_v_len(vstart,vend), cosr);
47581 0 : ae_v_subd(&vt->ptr.pp_double[mm0][vstart], 1, &vt->ptr.pp_double[mm1][vstart], 1, ae_v_len(vstart,vend), sinr);
47582 0 : ae_v_move(&vt->ptr.pp_double[mm1][vstart], 1, &vttemp.ptr.p_double[vstart], 1, ae_v_len(vstart,vend));
47583 : }
47584 0 : if( nru>0 )
47585 : {
47586 0 : mm0 = m+ustart-1;
47587 0 : mm1 = m-1+ustart-1;
47588 0 : ae_v_moved(&utemp.ptr.p_double[ustart], 1, &ut.ptr.pp_double[mm1][ustart], 1, ae_v_len(ustart,uend), cosl);
47589 0 : ae_v_addd(&utemp.ptr.p_double[ustart], 1, &ut.ptr.pp_double[mm0][ustart], 1, ae_v_len(ustart,uend), sinl);
47590 0 : ae_v_muld(&ut.ptr.pp_double[mm0][ustart], 1, ae_v_len(ustart,uend), cosl);
47591 0 : ae_v_subd(&ut.ptr.pp_double[mm0][ustart], 1, &ut.ptr.pp_double[mm1][ustart], 1, ae_v_len(ustart,uend), sinl);
47592 0 : ae_v_move(&ut.ptr.pp_double[mm1][ustart], 1, &utemp.ptr.p_double[ustart], 1, ae_v_len(ustart,uend));
47593 : }
47594 0 : if( ncc>0 )
47595 : {
47596 0 : mm0 = m+cstart-1;
47597 0 : mm1 = m-1+cstart-1;
47598 0 : ae_v_moved(&ctemp.ptr.p_double[cstart], 1, &c->ptr.pp_double[mm1][cstart], 1, ae_v_len(cstart,cend), cosl);
47599 0 : ae_v_addd(&ctemp.ptr.p_double[cstart], 1, &c->ptr.pp_double[mm0][cstart], 1, ae_v_len(cstart,cend), sinl);
47600 0 : ae_v_muld(&c->ptr.pp_double[mm0][cstart], 1, ae_v_len(cstart,cend), cosl);
47601 0 : ae_v_subd(&c->ptr.pp_double[mm0][cstart], 1, &c->ptr.pp_double[mm1][cstart], 1, ae_v_len(cstart,cend), sinl);
47602 0 : ae_v_move(&c->ptr.pp_double[mm1][cstart], 1, &ctemp.ptr.p_double[cstart], 1, ae_v_len(cstart,cend));
47603 : }
47604 0 : m = m-2;
47605 0 : continue;
47606 : }
47607 :
47608 : /*
47609 : * If working on new submatrix, choose shift direction
47610 : * (from larger end diagonal element towards smaller)
47611 : *
47612 : * Previously was
47613 : * "if (LL>OLDM) or (M<OLDLL) then"
47614 : * fixed thanks to Michael Rolle < m@rolle.name >
47615 : * Very strange that LAPACK still contains it.
47616 : */
47617 0 : bchangedir = ae_false;
47618 0 : if( idir==1&&ae_fp_less(ae_fabs(d->ptr.p_double[ll], _state),1.0E-3*ae_fabs(d->ptr.p_double[m], _state)) )
47619 : {
47620 0 : bchangedir = ae_true;
47621 : }
47622 0 : if( idir==2&&ae_fp_less(ae_fabs(d->ptr.p_double[m], _state),1.0E-3*ae_fabs(d->ptr.p_double[ll], _state)) )
47623 : {
47624 0 : bchangedir = ae_true;
47625 : }
47626 0 : if( (ll!=oldll||m!=oldm)||bchangedir )
47627 : {
47628 0 : if( ae_fp_greater_eq(ae_fabs(d->ptr.p_double[ll], _state),ae_fabs(d->ptr.p_double[m], _state)) )
47629 : {
47630 :
47631 : /*
47632 : * Chase bulge from top (big end) to bottom (small end)
47633 : */
47634 0 : idir = 1;
47635 : }
47636 : else
47637 : {
47638 :
47639 : /*
47640 : * Chase bulge from bottom (big end) to top (small end)
47641 : */
47642 0 : idir = 2;
47643 : }
47644 : }
47645 :
47646 : /*
47647 : * Apply convergence tests
47648 : */
47649 0 : if( idir==1 )
47650 : {
47651 :
47652 : /*
47653 : * Run convergence test in forward direction
47654 : * First apply standard test to bottom of matrix
47655 : */
47656 0 : if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[m-1], _state),ae_fabs(tol, _state)*ae_fabs(d->ptr.p_double[m], _state))||(ae_fp_less(tol,(double)(0))&&ae_fp_less_eq(ae_fabs(e->ptr.p_double[m-1], _state),thresh)) )
47657 : {
47658 0 : e->ptr.p_double[m-1] = (double)(0);
47659 0 : continue;
47660 : }
47661 0 : if( ae_fp_greater_eq(tol,(double)(0)) )
47662 : {
47663 :
47664 : /*
47665 : * If relative accuracy desired,
47666 : * apply convergence criterion forward
47667 : */
47668 0 : mu = ae_fabs(d->ptr.p_double[ll], _state);
47669 0 : sminl = mu;
47670 0 : iterflag = ae_false;
47671 0 : for(lll=ll; lll<=m-1; lll++)
47672 : {
47673 0 : if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[lll], _state),tol*mu) )
47674 : {
47675 0 : e->ptr.p_double[lll] = (double)(0);
47676 0 : iterflag = ae_true;
47677 0 : break;
47678 : }
47679 0 : mu = ae_fabs(d->ptr.p_double[lll+1], _state)*(mu/(mu+ae_fabs(e->ptr.p_double[lll], _state)));
47680 0 : sminl = ae_minreal(sminl, mu, _state);
47681 : }
47682 0 : if( iterflag )
47683 : {
47684 0 : continue;
47685 : }
47686 : }
47687 : }
47688 : else
47689 : {
47690 :
47691 : /*
47692 : * Run convergence test in backward direction
47693 : * First apply standard test to top of matrix
47694 : */
47695 0 : if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[ll], _state),ae_fabs(tol, _state)*ae_fabs(d->ptr.p_double[ll], _state))||(ae_fp_less(tol,(double)(0))&&ae_fp_less_eq(ae_fabs(e->ptr.p_double[ll], _state),thresh)) )
47696 : {
47697 0 : e->ptr.p_double[ll] = (double)(0);
47698 0 : continue;
47699 : }
47700 0 : if( ae_fp_greater_eq(tol,(double)(0)) )
47701 : {
47702 :
47703 : /*
47704 : * If relative accuracy desired,
47705 : * apply convergence criterion backward
47706 : */
47707 0 : mu = ae_fabs(d->ptr.p_double[m], _state);
47708 0 : sminl = mu;
47709 0 : iterflag = ae_false;
47710 0 : for(lll=m-1; lll>=ll; lll--)
47711 : {
47712 0 : if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[lll], _state),tol*mu) )
47713 : {
47714 0 : e->ptr.p_double[lll] = (double)(0);
47715 0 : iterflag = ae_true;
47716 0 : break;
47717 : }
47718 0 : mu = ae_fabs(d->ptr.p_double[lll], _state)*(mu/(mu+ae_fabs(e->ptr.p_double[lll], _state)));
47719 0 : sminl = ae_minreal(sminl, mu, _state);
47720 : }
47721 0 : if( iterflag )
47722 : {
47723 0 : continue;
47724 : }
47725 : }
47726 : }
47727 0 : oldll = ll;
47728 0 : oldm = m;
47729 :
47730 : /*
47731 : * Compute shift. First, test if shifting would ruin relative
47732 : * accuracy, and if so set the shift to zero.
47733 : */
47734 0 : if( ae_fp_greater_eq(tol,(double)(0))&&ae_fp_less_eq(n*tol*(sminl/smax),ae_maxreal(eps, 0.01*tol, _state)) )
47735 : {
47736 :
47737 : /*
47738 : * Use a zero shift to avoid loss of relative accuracy
47739 : */
47740 0 : shift = (double)(0);
47741 : }
47742 : else
47743 : {
47744 :
47745 : /*
47746 : * Compute the shift from 2-by-2 block at end of matrix
47747 : */
47748 0 : if( idir==1 )
47749 : {
47750 0 : sll = ae_fabs(d->ptr.p_double[ll], _state);
47751 0 : bdsvd_svd2x2(d->ptr.p_double[m-1], e->ptr.p_double[m-1], d->ptr.p_double[m], &shift, &r, _state);
47752 : }
47753 : else
47754 : {
47755 0 : sll = ae_fabs(d->ptr.p_double[m], _state);
47756 0 : bdsvd_svd2x2(d->ptr.p_double[ll], e->ptr.p_double[ll], d->ptr.p_double[ll+1], &shift, &r, _state);
47757 : }
47758 :
47759 : /*
47760 : * Test if shift negligible, and if so set to zero
47761 : */
47762 0 : if( ae_fp_greater(sll,(double)(0)) )
47763 : {
47764 0 : if( ae_fp_less(ae_sqr(shift/sll, _state),eps) )
47765 : {
47766 0 : shift = (double)(0);
47767 : }
47768 : }
47769 : }
47770 :
47771 : /*
47772 : * Increment iteration count
47773 : */
47774 0 : iter = iter+m-ll;
47775 :
47776 : /*
47777 : * If SHIFT = 0, do simplified QR iteration
47778 : */
47779 0 : if( ae_fp_eq(shift,(double)(0)) )
47780 : {
47781 0 : if( idir==1 )
47782 : {
47783 :
47784 : /*
47785 : * Chase bulge from top to bottom
47786 : * Save cosines and sines for later singular vector updates
47787 : */
47788 0 : cs = (double)(1);
47789 0 : oldcs = (double)(1);
47790 0 : for(i=ll; i<=m-1; i++)
47791 : {
47792 0 : generaterotation(d->ptr.p_double[i]*cs, e->ptr.p_double[i], &cs, &sn, &r, _state);
47793 0 : if( i>ll )
47794 : {
47795 0 : e->ptr.p_double[i-1] = oldsn*r;
47796 : }
47797 0 : generaterotation(oldcs*r, d->ptr.p_double[i+1]*sn, &oldcs, &oldsn, &tmp, _state);
47798 0 : d->ptr.p_double[i] = tmp;
47799 0 : work0.ptr.p_double[i-ll+1] = cs;
47800 0 : work1.ptr.p_double[i-ll+1] = sn;
47801 0 : work2.ptr.p_double[i-ll+1] = oldcs;
47802 0 : work3.ptr.p_double[i-ll+1] = oldsn;
47803 : }
47804 0 : h = d->ptr.p_double[m]*cs;
47805 0 : d->ptr.p_double[m] = h*oldcs;
47806 0 : e->ptr.p_double[m-1] = h*oldsn;
47807 :
47808 : /*
47809 : * Update singular vectors
47810 : */
47811 0 : if( ncvt>0 )
47812 : {
47813 0 : applyrotationsfromtheleft(fwddir, ll+vstart-1, m+vstart-1, vstart, vend, &work0, &work1, vt, &vttemp, _state);
47814 : }
47815 0 : if( nru>0 )
47816 : {
47817 0 : applyrotationsfromtheleft(fwddir, ll+ustart-1, m+ustart-1, ustart, uend, &work2, &work3, &ut, &utemp, _state);
47818 : }
47819 0 : if( ncc>0 )
47820 : {
47821 0 : applyrotationsfromtheleft(fwddir, ll+cstart-1, m+cstart-1, cstart, cend, &work2, &work3, c, &ctemp, _state);
47822 : }
47823 :
47824 : /*
47825 : * Test convergence
47826 : */
47827 0 : if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[m-1], _state),thresh) )
47828 : {
47829 0 : e->ptr.p_double[m-1] = (double)(0);
47830 : }
47831 : }
47832 : else
47833 : {
47834 :
47835 : /*
47836 : * Chase bulge from bottom to top
47837 : * Save cosines and sines for later singular vector updates
47838 : */
47839 0 : cs = (double)(1);
47840 0 : oldcs = (double)(1);
47841 0 : for(i=m; i>=ll+1; i--)
47842 : {
47843 0 : generaterotation(d->ptr.p_double[i]*cs, e->ptr.p_double[i-1], &cs, &sn, &r, _state);
47844 0 : if( i<m )
47845 : {
47846 0 : e->ptr.p_double[i] = oldsn*r;
47847 : }
47848 0 : generaterotation(oldcs*r, d->ptr.p_double[i-1]*sn, &oldcs, &oldsn, &tmp, _state);
47849 0 : d->ptr.p_double[i] = tmp;
47850 0 : work0.ptr.p_double[i-ll] = cs;
47851 0 : work1.ptr.p_double[i-ll] = -sn;
47852 0 : work2.ptr.p_double[i-ll] = oldcs;
47853 0 : work3.ptr.p_double[i-ll] = -oldsn;
47854 : }
47855 0 : h = d->ptr.p_double[ll]*cs;
47856 0 : d->ptr.p_double[ll] = h*oldcs;
47857 0 : e->ptr.p_double[ll] = h*oldsn;
47858 :
47859 : /*
47860 : * Update singular vectors
47861 : */
47862 0 : if( ncvt>0 )
47863 : {
47864 0 : applyrotationsfromtheleft(!fwddir, ll+vstart-1, m+vstart-1, vstart, vend, &work2, &work3, vt, &vttemp, _state);
47865 : }
47866 0 : if( nru>0 )
47867 : {
47868 0 : applyrotationsfromtheleft(!fwddir, ll+ustart-1, m+ustart-1, ustart, uend, &work0, &work1, &ut, &utemp, _state);
47869 : }
47870 0 : if( ncc>0 )
47871 : {
47872 0 : applyrotationsfromtheleft(!fwddir, ll+cstart-1, m+cstart-1, cstart, cend, &work0, &work1, c, &ctemp, _state);
47873 : }
47874 :
47875 : /*
47876 : * Test convergence
47877 : */
47878 0 : if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[ll], _state),thresh) )
47879 : {
47880 0 : e->ptr.p_double[ll] = (double)(0);
47881 : }
47882 : }
47883 : }
47884 : else
47885 : {
47886 :
47887 : /*
47888 : * Use nonzero shift
47889 : */
47890 0 : if( idir==1 )
47891 : {
47892 :
47893 : /*
47894 : * Chase bulge from top to bottom
47895 : * Save cosines and sines for later singular vector updates
47896 : */
47897 0 : f = (ae_fabs(d->ptr.p_double[ll], _state)-shift)*(bdsvd_extsignbdsqr((double)(1), d->ptr.p_double[ll], _state)+shift/d->ptr.p_double[ll]);
47898 0 : g = e->ptr.p_double[ll];
47899 0 : for(i=ll; i<=m-1; i++)
47900 : {
47901 0 : generaterotation(f, g, &cosr, &sinr, &r, _state);
47902 0 : if( i>ll )
47903 : {
47904 0 : e->ptr.p_double[i-1] = r;
47905 : }
47906 0 : f = cosr*d->ptr.p_double[i]+sinr*e->ptr.p_double[i];
47907 0 : e->ptr.p_double[i] = cosr*e->ptr.p_double[i]-sinr*d->ptr.p_double[i];
47908 0 : g = sinr*d->ptr.p_double[i+1];
47909 0 : d->ptr.p_double[i+1] = cosr*d->ptr.p_double[i+1];
47910 0 : generaterotation(f, g, &cosl, &sinl, &r, _state);
47911 0 : d->ptr.p_double[i] = r;
47912 0 : f = cosl*e->ptr.p_double[i]+sinl*d->ptr.p_double[i+1];
47913 0 : d->ptr.p_double[i+1] = cosl*d->ptr.p_double[i+1]-sinl*e->ptr.p_double[i];
47914 0 : if( i<m-1 )
47915 : {
47916 0 : g = sinl*e->ptr.p_double[i+1];
47917 0 : e->ptr.p_double[i+1] = cosl*e->ptr.p_double[i+1];
47918 : }
47919 0 : work0.ptr.p_double[i-ll+1] = cosr;
47920 0 : work1.ptr.p_double[i-ll+1] = sinr;
47921 0 : work2.ptr.p_double[i-ll+1] = cosl;
47922 0 : work3.ptr.p_double[i-ll+1] = sinl;
47923 : }
47924 0 : e->ptr.p_double[m-1] = f;
47925 :
47926 : /*
47927 : * Update singular vectors
47928 : */
47929 0 : if( ncvt>0 )
47930 : {
47931 0 : applyrotationsfromtheleft(fwddir, ll+vstart-1, m+vstart-1, vstart, vend, &work0, &work1, vt, &vttemp, _state);
47932 : }
47933 0 : if( nru>0 )
47934 : {
47935 0 : applyrotationsfromtheleft(fwddir, ll+ustart-1, m+ustart-1, ustart, uend, &work2, &work3, &ut, &utemp, _state);
47936 : }
47937 0 : if( ncc>0 )
47938 : {
47939 0 : applyrotationsfromtheleft(fwddir, ll+cstart-1, m+cstart-1, cstart, cend, &work2, &work3, c, &ctemp, _state);
47940 : }
47941 :
47942 : /*
47943 : * Test convergence
47944 : */
47945 0 : if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[m-1], _state),thresh) )
47946 : {
47947 0 : e->ptr.p_double[m-1] = (double)(0);
47948 : }
47949 : }
47950 : else
47951 : {
47952 :
47953 : /*
47954 : * Chase bulge from bottom to top
47955 : * Save cosines and sines for later singular vector updates
47956 : */
47957 0 : f = (ae_fabs(d->ptr.p_double[m], _state)-shift)*(bdsvd_extsignbdsqr((double)(1), d->ptr.p_double[m], _state)+shift/d->ptr.p_double[m]);
47958 0 : g = e->ptr.p_double[m-1];
47959 0 : for(i=m; i>=ll+1; i--)
47960 : {
47961 0 : generaterotation(f, g, &cosr, &sinr, &r, _state);
47962 0 : if( i<m )
47963 : {
47964 0 : e->ptr.p_double[i] = r;
47965 : }
47966 0 : f = cosr*d->ptr.p_double[i]+sinr*e->ptr.p_double[i-1];
47967 0 : e->ptr.p_double[i-1] = cosr*e->ptr.p_double[i-1]-sinr*d->ptr.p_double[i];
47968 0 : g = sinr*d->ptr.p_double[i-1];
47969 0 : d->ptr.p_double[i-1] = cosr*d->ptr.p_double[i-1];
47970 0 : generaterotation(f, g, &cosl, &sinl, &r, _state);
47971 0 : d->ptr.p_double[i] = r;
47972 0 : f = cosl*e->ptr.p_double[i-1]+sinl*d->ptr.p_double[i-1];
47973 0 : d->ptr.p_double[i-1] = cosl*d->ptr.p_double[i-1]-sinl*e->ptr.p_double[i-1];
47974 0 : if( i>ll+1 )
47975 : {
47976 0 : g = sinl*e->ptr.p_double[i-2];
47977 0 : e->ptr.p_double[i-2] = cosl*e->ptr.p_double[i-2];
47978 : }
47979 0 : work0.ptr.p_double[i-ll] = cosr;
47980 0 : work1.ptr.p_double[i-ll] = -sinr;
47981 0 : work2.ptr.p_double[i-ll] = cosl;
47982 0 : work3.ptr.p_double[i-ll] = -sinl;
47983 : }
47984 0 : e->ptr.p_double[ll] = f;
47985 :
47986 : /*
47987 : * Test convergence
47988 : */
47989 0 : if( ae_fp_less_eq(ae_fabs(e->ptr.p_double[ll], _state),thresh) )
47990 : {
47991 0 : e->ptr.p_double[ll] = (double)(0);
47992 : }
47993 :
47994 : /*
47995 : * Update singular vectors if desired
47996 : */
47997 0 : if( ncvt>0 )
47998 : {
47999 0 : applyrotationsfromtheleft(!fwddir, ll+vstart-1, m+vstart-1, vstart, vend, &work2, &work3, vt, &vttemp, _state);
48000 : }
48001 0 : if( nru>0 )
48002 : {
48003 0 : applyrotationsfromtheleft(!fwddir, ll+ustart-1, m+ustart-1, ustart, uend, &work0, &work1, &ut, &utemp, _state);
48004 : }
48005 0 : if( ncc>0 )
48006 : {
48007 0 : applyrotationsfromtheleft(!fwddir, ll+cstart-1, m+cstart-1, cstart, cend, &work0, &work1, c, &ctemp, _state);
48008 : }
48009 : }
48010 : }
48011 :
48012 : /*
48013 : * QR iteration finished, go back and check convergence
48014 : */
48015 0 : continue;
48016 : }
48017 :
48018 : /*
48019 : * All singular values converged, so make them positive
48020 : */
48021 0 : for(i=1; i<=n; i++)
48022 : {
48023 0 : if( ae_fp_less(d->ptr.p_double[i],(double)(0)) )
48024 : {
48025 0 : d->ptr.p_double[i] = -d->ptr.p_double[i];
48026 :
48027 : /*
48028 : * Change sign of singular vectors, if desired
48029 : */
48030 0 : if( ncvt>0 )
48031 : {
48032 0 : ae_v_muld(&vt->ptr.pp_double[i+vstart-1][vstart], 1, ae_v_len(vstart,vend), -1);
48033 : }
48034 : }
48035 : }
48036 :
48037 : /*
48038 : * Sort the singular values into decreasing order (insertion sort on
48039 : * singular values, but only one transposition per singular vector)
48040 : */
48041 0 : for(i=1; i<=n-1; i++)
48042 : {
48043 :
48044 : /*
48045 : * Scan for smallest D(I)
48046 : */
48047 0 : isub = 1;
48048 0 : smin = d->ptr.p_double[1];
48049 0 : for(j=2; j<=n+1-i; j++)
48050 : {
48051 0 : if( ae_fp_less_eq(d->ptr.p_double[j],smin) )
48052 : {
48053 0 : isub = j;
48054 0 : smin = d->ptr.p_double[j];
48055 : }
48056 : }
48057 0 : if( isub!=n+1-i )
48058 : {
48059 :
48060 : /*
48061 : * Swap singular values and vectors
48062 : */
48063 0 : d->ptr.p_double[isub] = d->ptr.p_double[n+1-i];
48064 0 : d->ptr.p_double[n+1-i] = smin;
48065 0 : if( ncvt>0 )
48066 : {
48067 0 : j = n+1-i;
48068 0 : ae_v_move(&vttemp.ptr.p_double[vstart], 1, &vt->ptr.pp_double[isub+vstart-1][vstart], 1, ae_v_len(vstart,vend));
48069 0 : ae_v_move(&vt->ptr.pp_double[isub+vstart-1][vstart], 1, &vt->ptr.pp_double[j+vstart-1][vstart], 1, ae_v_len(vstart,vend));
48070 0 : ae_v_move(&vt->ptr.pp_double[j+vstart-1][vstart], 1, &vttemp.ptr.p_double[vstart], 1, ae_v_len(vstart,vend));
48071 : }
48072 0 : if( nru>0 )
48073 : {
48074 0 : j = n+1-i;
48075 0 : ae_v_move(&utemp.ptr.p_double[ustart], 1, &ut.ptr.pp_double[isub+ustart-1][ustart], 1, ae_v_len(ustart,uend));
48076 0 : ae_v_move(&ut.ptr.pp_double[isub+ustart-1][ustart], 1, &ut.ptr.pp_double[j+ustart-1][ustart], 1, ae_v_len(ustart,uend));
48077 0 : ae_v_move(&ut.ptr.pp_double[j+ustart-1][ustart], 1, &utemp.ptr.p_double[ustart], 1, ae_v_len(ustart,uend));
48078 : }
48079 0 : if( ncc>0 )
48080 : {
48081 0 : j = n+1-i;
48082 0 : ae_v_move(&ctemp.ptr.p_double[cstart], 1, &c->ptr.pp_double[isub+cstart-1][cstart], 1, ae_v_len(cstart,cend));
48083 0 : ae_v_move(&c->ptr.pp_double[isub+cstart-1][cstart], 1, &c->ptr.pp_double[j+cstart-1][cstart], 1, ae_v_len(cstart,cend));
48084 0 : ae_v_move(&c->ptr.pp_double[j+cstart-1][cstart], 1, &ctemp.ptr.p_double[cstart], 1, ae_v_len(cstart,cend));
48085 : }
48086 : }
48087 : }
48088 :
48089 : /*
48090 : * Copy U back from temporary storage
48091 : */
48092 0 : if( nru>0 )
48093 : {
48094 0 : rmatrixtranspose(n, nru, &ut, ustart, ustart, uu, ustart, ustart, _state);
48095 : }
48096 0 : ae_frame_leave(_state);
48097 0 : return result;
48098 : }
48099 :
48100 :
48101 0 : static double bdsvd_extsignbdsqr(double a, double b, ae_state *_state)
48102 : {
48103 : double result;
48104 :
48105 :
48106 0 : if( ae_fp_greater_eq(b,(double)(0)) )
48107 : {
48108 0 : result = ae_fabs(a, _state);
48109 : }
48110 : else
48111 : {
48112 0 : result = -ae_fabs(a, _state);
48113 : }
48114 0 : return result;
48115 : }
48116 :
48117 :
48118 0 : static void bdsvd_svd2x2(double f,
48119 : double g,
48120 : double h,
48121 : double* ssmin,
48122 : double* ssmax,
48123 : ae_state *_state)
48124 : {
48125 : double aas;
48126 : double at;
48127 : double au;
48128 : double c;
48129 : double fa;
48130 : double fhmn;
48131 : double fhmx;
48132 : double ga;
48133 : double ha;
48134 :
48135 0 : *ssmin = 0;
48136 0 : *ssmax = 0;
48137 :
48138 0 : fa = ae_fabs(f, _state);
48139 0 : ga = ae_fabs(g, _state);
48140 0 : ha = ae_fabs(h, _state);
48141 0 : fhmn = ae_minreal(fa, ha, _state);
48142 0 : fhmx = ae_maxreal(fa, ha, _state);
48143 0 : if( ae_fp_eq(fhmn,(double)(0)) )
48144 : {
48145 0 : *ssmin = (double)(0);
48146 0 : if( ae_fp_eq(fhmx,(double)(0)) )
48147 : {
48148 0 : *ssmax = ga;
48149 : }
48150 : else
48151 : {
48152 0 : *ssmax = ae_maxreal(fhmx, ga, _state)*ae_sqrt(1+ae_sqr(ae_minreal(fhmx, ga, _state)/ae_maxreal(fhmx, ga, _state), _state), _state);
48153 : }
48154 : }
48155 : else
48156 : {
48157 0 : if( ae_fp_less(ga,fhmx) )
48158 : {
48159 0 : aas = 1+fhmn/fhmx;
48160 0 : at = (fhmx-fhmn)/fhmx;
48161 0 : au = ae_sqr(ga/fhmx, _state);
48162 0 : c = 2/(ae_sqrt(aas*aas+au, _state)+ae_sqrt(at*at+au, _state));
48163 0 : *ssmin = fhmn*c;
48164 0 : *ssmax = fhmx/c;
48165 : }
48166 : else
48167 : {
48168 0 : au = fhmx/ga;
48169 0 : if( ae_fp_eq(au,(double)(0)) )
48170 : {
48171 :
48172 : /*
48173 : * Avoid possible harmful underflow if exponent range
48174 : * asymmetric (true SSMIN may not underflow even if
48175 : * AU underflows)
48176 : */
48177 0 : *ssmin = fhmn*fhmx/ga;
48178 0 : *ssmax = ga;
48179 : }
48180 : else
48181 : {
48182 0 : aas = 1+fhmn/fhmx;
48183 0 : at = (fhmx-fhmn)/fhmx;
48184 0 : c = 1/(ae_sqrt(1+ae_sqr(aas*au, _state), _state)+ae_sqrt(1+ae_sqr(at*au, _state), _state));
48185 0 : *ssmin = fhmn*c*au;
48186 0 : *ssmin = *ssmin+(*ssmin);
48187 0 : *ssmax = ga/(c+c);
48188 : }
48189 : }
48190 : }
48191 0 : }
48192 :
48193 :
48194 0 : static void bdsvd_svdv2x2(double f,
48195 : double g,
48196 : double h,
48197 : double* ssmin,
48198 : double* ssmax,
48199 : double* snr,
48200 : double* csr,
48201 : double* snl,
48202 : double* csl,
48203 : ae_state *_state)
48204 : {
48205 : ae_bool gasmal;
48206 : ae_bool swp;
48207 : ae_int_t pmax;
48208 : double a;
48209 : double clt;
48210 : double crt;
48211 : double d;
48212 : double fa;
48213 : double ft;
48214 : double ga;
48215 : double gt;
48216 : double ha;
48217 : double ht;
48218 : double l;
48219 : double m;
48220 : double mm;
48221 : double r;
48222 : double s;
48223 : double slt;
48224 : double srt;
48225 : double t;
48226 : double temp;
48227 : double tsign;
48228 : double tt;
48229 : double v;
48230 :
48231 0 : *ssmin = 0;
48232 0 : *ssmax = 0;
48233 0 : *snr = 0;
48234 0 : *csr = 0;
48235 0 : *snl = 0;
48236 0 : *csl = 0;
48237 :
48238 0 : ft = f;
48239 0 : fa = ae_fabs(ft, _state);
48240 0 : ht = h;
48241 0 : ha = ae_fabs(h, _state);
48242 :
48243 : /*
48244 : * these initializers are not really necessary,
48245 : * but without them compiler complains about uninitialized locals
48246 : */
48247 0 : clt = (double)(0);
48248 0 : crt = (double)(0);
48249 0 : slt = (double)(0);
48250 0 : srt = (double)(0);
48251 0 : tsign = (double)(0);
48252 :
48253 : /*
48254 : * PMAX points to the maximum absolute element of matrix
48255 : * PMAX = 1 if F largest in absolute values
48256 : * PMAX = 2 if G largest in absolute values
48257 : * PMAX = 3 if H largest in absolute values
48258 : */
48259 0 : pmax = 1;
48260 0 : swp = ae_fp_greater(ha,fa);
48261 0 : if( swp )
48262 : {
48263 :
48264 : /*
48265 : * Now FA .ge. HA
48266 : */
48267 0 : pmax = 3;
48268 0 : temp = ft;
48269 0 : ft = ht;
48270 0 : ht = temp;
48271 0 : temp = fa;
48272 0 : fa = ha;
48273 0 : ha = temp;
48274 : }
48275 0 : gt = g;
48276 0 : ga = ae_fabs(gt, _state);
48277 0 : if( ae_fp_eq(ga,(double)(0)) )
48278 : {
48279 :
48280 : /*
48281 : * Diagonal matrix
48282 : */
48283 0 : *ssmin = ha;
48284 0 : *ssmax = fa;
48285 0 : clt = (double)(1);
48286 0 : crt = (double)(1);
48287 0 : slt = (double)(0);
48288 0 : srt = (double)(0);
48289 : }
48290 : else
48291 : {
48292 0 : gasmal = ae_true;
48293 0 : if( ae_fp_greater(ga,fa) )
48294 : {
48295 0 : pmax = 2;
48296 0 : if( ae_fp_less(fa/ga,ae_machineepsilon) )
48297 : {
48298 :
48299 : /*
48300 : * Case of very large GA
48301 : */
48302 0 : gasmal = ae_false;
48303 0 : *ssmax = ga;
48304 0 : if( ae_fp_greater(ha,(double)(1)) )
48305 : {
48306 0 : v = ga/ha;
48307 0 : *ssmin = fa/v;
48308 : }
48309 : else
48310 : {
48311 0 : v = fa/ga;
48312 0 : *ssmin = v*ha;
48313 : }
48314 0 : clt = (double)(1);
48315 0 : slt = ht/gt;
48316 0 : srt = (double)(1);
48317 0 : crt = ft/gt;
48318 : }
48319 : }
48320 0 : if( gasmal )
48321 : {
48322 :
48323 : /*
48324 : * Normal case
48325 : */
48326 0 : d = fa-ha;
48327 0 : if( ae_fp_eq(d,fa) )
48328 : {
48329 0 : l = (double)(1);
48330 : }
48331 : else
48332 : {
48333 0 : l = d/fa;
48334 : }
48335 0 : m = gt/ft;
48336 0 : t = 2-l;
48337 0 : mm = m*m;
48338 0 : tt = t*t;
48339 0 : s = ae_sqrt(tt+mm, _state);
48340 0 : if( ae_fp_eq(l,(double)(0)) )
48341 : {
48342 0 : r = ae_fabs(m, _state);
48343 : }
48344 : else
48345 : {
48346 0 : r = ae_sqrt(l*l+mm, _state);
48347 : }
48348 0 : a = 0.5*(s+r);
48349 0 : *ssmin = ha/a;
48350 0 : *ssmax = fa*a;
48351 0 : if( ae_fp_eq(mm,(double)(0)) )
48352 : {
48353 :
48354 : /*
48355 : * Note that M is very tiny
48356 : */
48357 0 : if( ae_fp_eq(l,(double)(0)) )
48358 : {
48359 0 : t = bdsvd_extsignbdsqr((double)(2), ft, _state)*bdsvd_extsignbdsqr((double)(1), gt, _state);
48360 : }
48361 : else
48362 : {
48363 0 : t = gt/bdsvd_extsignbdsqr(d, ft, _state)+m/t;
48364 : }
48365 : }
48366 : else
48367 : {
48368 0 : t = (m/(s+t)+m/(r+l))*(1+a);
48369 : }
48370 0 : l = ae_sqrt(t*t+4, _state);
48371 0 : crt = 2/l;
48372 0 : srt = t/l;
48373 0 : clt = (crt+srt*m)/a;
48374 0 : v = ht/ft;
48375 0 : slt = v*srt/a;
48376 : }
48377 : }
48378 0 : if( swp )
48379 : {
48380 0 : *csl = srt;
48381 0 : *snl = crt;
48382 0 : *csr = slt;
48383 0 : *snr = clt;
48384 : }
48385 : else
48386 : {
48387 0 : *csl = clt;
48388 0 : *snl = slt;
48389 0 : *csr = crt;
48390 0 : *snr = srt;
48391 : }
48392 :
48393 : /*
48394 : * Correct signs of SSMAX and SSMIN
48395 : */
48396 0 : if( pmax==1 )
48397 : {
48398 0 : tsign = bdsvd_extsignbdsqr((double)(1), *csr, _state)*bdsvd_extsignbdsqr((double)(1), *csl, _state)*bdsvd_extsignbdsqr((double)(1), f, _state);
48399 : }
48400 0 : if( pmax==2 )
48401 : {
48402 0 : tsign = bdsvd_extsignbdsqr((double)(1), *snr, _state)*bdsvd_extsignbdsqr((double)(1), *csl, _state)*bdsvd_extsignbdsqr((double)(1), g, _state);
48403 : }
48404 0 : if( pmax==3 )
48405 : {
48406 0 : tsign = bdsvd_extsignbdsqr((double)(1), *snr, _state)*bdsvd_extsignbdsqr((double)(1), *snl, _state)*bdsvd_extsignbdsqr((double)(1), h, _state);
48407 : }
48408 0 : *ssmax = bdsvd_extsignbdsqr(*ssmax, tsign, _state);
48409 0 : *ssmin = bdsvd_extsignbdsqr(*ssmin, tsign*bdsvd_extsignbdsqr((double)(1), f, _state)*bdsvd_extsignbdsqr((double)(1), h, _state), _state);
48410 0 : }
48411 :
48412 :
48413 : #endif
48414 : #if defined(AE_COMPILE_SVD) || !defined(AE_PARTIAL_BUILD)
48415 :
48416 :
48417 : /*************************************************************************
48418 : Singular value decomposition of a rectangular matrix.
48419 :
48420 : ! COMMERCIAL EDITION OF ALGLIB:
48421 : !
48422 : ! Commercial Edition of ALGLIB includes following important improvements
48423 : ! of this function:
48424 : ! * high-performance native backend with same C# interface (C# version)
48425 : ! * hardware vendor (Intel) implementations of linear algebra primitives
48426 : ! (C++ and C# versions, x86/x64 platform)
48427 : !
48428 : ! We recommend you to read 'Working with commercial version' section of
48429 : ! ALGLIB Reference Manual in order to find out how to use performance-
48430 : ! related features provided by commercial edition of ALGLIB.
48431 :
48432 : The algorithm calculates the singular value decomposition of a matrix of
48433 : size MxN: A = U * S * V^T
48434 :
48435 : The algorithm finds the singular values and, optionally, matrices U and V^T.
48436 : The algorithm can find both first min(M,N) columns of matrix U and rows of
48437 : matrix V^T (singular vectors), and matrices U and V^T wholly (of sizes MxM
48438 : and NxN respectively).
48439 :
48440 : Take into account that the subroutine does not return matrix V but V^T.
48441 :
48442 : Input parameters:
48443 : A - matrix to be decomposed.
48444 : Array whose indexes range within [0..M-1, 0..N-1].
48445 : M - number of rows in matrix A.
48446 : N - number of columns in matrix A.
48447 : UNeeded - 0, 1 or 2. See the description of the parameter U.
48448 : VTNeeded - 0, 1 or 2. See the description of the parameter VT.
48449 : AdditionalMemory -
48450 : If the parameter:
48451 : * equals 0, the algorithm doesn't use additional
48452 : memory (lower requirements, lower performance).
48453 : * equals 1, the algorithm uses additional
48454 : memory of size min(M,N)*min(M,N) of real numbers.
48455 : It often speeds up the algorithm.
48456 : * equals 2, the algorithm uses additional
48457 : memory of size M*min(M,N) of real numbers.
48458 : It allows to get a maximum performance.
48459 : The recommended value of the parameter is 2.
48460 :
48461 : Output parameters:
48462 : W - contains singular values in descending order.
48463 : U - if UNeeded=0, U isn't changed, the left singular vectors
48464 : are not calculated.
48465 : if Uneeded=1, U contains left singular vectors (first
48466 : min(M,N) columns of matrix U). Array whose indexes range
48467 : within [0..M-1, 0..Min(M,N)-1].
48468 : if UNeeded=2, U contains matrix U wholly. Array whose
48469 : indexes range within [0..M-1, 0..M-1].
48470 : VT - if VTNeeded=0, VT isn't changed, the right singular vectors
48471 : are not calculated.
48472 : if VTNeeded=1, VT contains right singular vectors (first
48473 : min(M,N) rows of matrix V^T). Array whose indexes range
48474 : within [0..min(M,N)-1, 0..N-1].
48475 : if VTNeeded=2, VT contains matrix V^T wholly. Array whose
48476 : indexes range within [0..N-1, 0..N-1].
48477 :
48478 : -- ALGLIB --
48479 : Copyright 2005 by Bochkanov Sergey
48480 : *************************************************************************/
48481 0 : ae_bool rmatrixsvd(/* Real */ ae_matrix* a,
48482 : ae_int_t m,
48483 : ae_int_t n,
48484 : ae_int_t uneeded,
48485 : ae_int_t vtneeded,
48486 : ae_int_t additionalmemory,
48487 : /* Real */ ae_vector* w,
48488 : /* Real */ ae_matrix* u,
48489 : /* Real */ ae_matrix* vt,
48490 : ae_state *_state)
48491 : {
48492 : ae_frame _frame_block;
48493 : ae_matrix _a;
48494 : ae_vector tauq;
48495 : ae_vector taup;
48496 : ae_vector tau;
48497 : ae_vector e;
48498 : ae_vector work;
48499 : ae_matrix t2;
48500 : ae_bool isupper;
48501 : ae_int_t minmn;
48502 : ae_int_t ncu;
48503 : ae_int_t nrvt;
48504 : ae_int_t nru;
48505 : ae_int_t ncvt;
48506 : ae_int_t i;
48507 : ae_int_t j;
48508 : ae_bool result;
48509 :
48510 0 : ae_frame_make(_state, &_frame_block);
48511 0 : memset(&_a, 0, sizeof(_a));
48512 0 : memset(&tauq, 0, sizeof(tauq));
48513 0 : memset(&taup, 0, sizeof(taup));
48514 0 : memset(&tau, 0, sizeof(tau));
48515 0 : memset(&e, 0, sizeof(e));
48516 0 : memset(&work, 0, sizeof(work));
48517 0 : memset(&t2, 0, sizeof(t2));
48518 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
48519 0 : a = &_a;
48520 0 : ae_vector_clear(w);
48521 0 : ae_matrix_clear(u);
48522 0 : ae_matrix_clear(vt);
48523 0 : ae_vector_init(&tauq, 0, DT_REAL, _state, ae_true);
48524 0 : ae_vector_init(&taup, 0, DT_REAL, _state, ae_true);
48525 0 : ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
48526 0 : ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
48527 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
48528 0 : ae_matrix_init(&t2, 0, 0, DT_REAL, _state, ae_true);
48529 :
48530 0 : result = ae_true;
48531 0 : if( m==0||n==0 )
48532 : {
48533 0 : ae_frame_leave(_state);
48534 0 : return result;
48535 : }
48536 0 : ae_assert(uneeded>=0&&uneeded<=2, "SVDDecomposition: wrong parameters!", _state);
48537 0 : ae_assert(vtneeded>=0&&vtneeded<=2, "SVDDecomposition: wrong parameters!", _state);
48538 0 : ae_assert(additionalmemory>=0&&additionalmemory<=2, "SVDDecomposition: wrong parameters!", _state);
48539 :
48540 : /*
48541 : * initialize
48542 : */
48543 0 : minmn = ae_minint(m, n, _state);
48544 0 : ae_vector_set_length(w, minmn+1, _state);
48545 0 : ncu = 0;
48546 0 : nru = 0;
48547 0 : if( uneeded==1 )
48548 : {
48549 0 : nru = m;
48550 0 : ncu = minmn;
48551 0 : ae_matrix_set_length(u, nru-1+1, ncu-1+1, _state);
48552 : }
48553 0 : if( uneeded==2 )
48554 : {
48555 0 : nru = m;
48556 0 : ncu = m;
48557 0 : ae_matrix_set_length(u, nru-1+1, ncu-1+1, _state);
48558 : }
48559 0 : nrvt = 0;
48560 0 : ncvt = 0;
48561 0 : if( vtneeded==1 )
48562 : {
48563 0 : nrvt = minmn;
48564 0 : ncvt = n;
48565 0 : ae_matrix_set_length(vt, nrvt-1+1, ncvt-1+1, _state);
48566 : }
48567 0 : if( vtneeded==2 )
48568 : {
48569 0 : nrvt = n;
48570 0 : ncvt = n;
48571 0 : ae_matrix_set_length(vt, nrvt-1+1, ncvt-1+1, _state);
48572 : }
48573 :
48574 : /*
48575 : * M much larger than N
48576 : * Use bidiagonal reduction with QR-decomposition
48577 : */
48578 0 : if( ae_fp_greater((double)(m),1.6*n) )
48579 : {
48580 0 : if( uneeded==0 )
48581 : {
48582 :
48583 : /*
48584 : * No left singular vectors to be computed
48585 : */
48586 0 : rmatrixqr(a, m, n, &tau, _state);
48587 0 : for(i=0; i<=n-1; i++)
48588 : {
48589 0 : for(j=0; j<=i-1; j++)
48590 : {
48591 0 : a->ptr.pp_double[i][j] = (double)(0);
48592 : }
48593 : }
48594 0 : rmatrixbd(a, n, n, &tauq, &taup, _state);
48595 0 : rmatrixbdunpackpt(a, n, n, &taup, nrvt, vt, _state);
48596 0 : rmatrixbdunpackdiagonals(a, n, n, &isupper, w, &e, _state);
48597 0 : result = rmatrixbdsvd(w, &e, n, isupper, ae_false, u, 0, a, 0, vt, ncvt, _state);
48598 0 : ae_frame_leave(_state);
48599 0 : return result;
48600 : }
48601 : else
48602 : {
48603 :
48604 : /*
48605 : * Left singular vectors (may be full matrix U) to be computed
48606 : */
48607 0 : rmatrixqr(a, m, n, &tau, _state);
48608 0 : rmatrixqrunpackq(a, m, n, &tau, ncu, u, _state);
48609 0 : for(i=0; i<=n-1; i++)
48610 : {
48611 0 : for(j=0; j<=i-1; j++)
48612 : {
48613 0 : a->ptr.pp_double[i][j] = (double)(0);
48614 : }
48615 : }
48616 0 : rmatrixbd(a, n, n, &tauq, &taup, _state);
48617 0 : rmatrixbdunpackpt(a, n, n, &taup, nrvt, vt, _state);
48618 0 : rmatrixbdunpackdiagonals(a, n, n, &isupper, w, &e, _state);
48619 0 : if( additionalmemory<1 )
48620 : {
48621 :
48622 : /*
48623 : * No additional memory can be used
48624 : */
48625 0 : rmatrixbdmultiplybyq(a, n, n, &tauq, u, m, n, ae_true, ae_false, _state);
48626 0 : result = rmatrixbdsvd(w, &e, n, isupper, ae_false, u, m, a, 0, vt, ncvt, _state);
48627 : }
48628 : else
48629 : {
48630 :
48631 : /*
48632 : * Large U. Transforming intermediate matrix T2
48633 : */
48634 0 : ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state);
48635 0 : rmatrixbdunpackq(a, n, n, &tauq, n, &t2, _state);
48636 0 : copymatrix(u, 0, m-1, 0, n-1, a, 0, m-1, 0, n-1, _state);
48637 0 : inplacetranspose(&t2, 0, n-1, 0, n-1, &work, _state);
48638 0 : result = rmatrixbdsvd(w, &e, n, isupper, ae_false, u, 0, &t2, n, vt, ncvt, _state);
48639 0 : rmatrixgemm(m, n, n, 1.0, a, 0, 0, 0, &t2, 0, 0, 1, 0.0, u, 0, 0, _state);
48640 : }
48641 0 : ae_frame_leave(_state);
48642 0 : return result;
48643 : }
48644 : }
48645 :
48646 : /*
48647 : * N much larger than M
48648 : * Use bidiagonal reduction with LQ-decomposition
48649 : */
48650 0 : if( ae_fp_greater((double)(n),1.6*m) )
48651 : {
48652 0 : if( vtneeded==0 )
48653 : {
48654 :
48655 : /*
48656 : * No right singular vectors to be computed
48657 : */
48658 0 : rmatrixlq(a, m, n, &tau, _state);
48659 0 : for(i=0; i<=m-1; i++)
48660 : {
48661 0 : for(j=i+1; j<=m-1; j++)
48662 : {
48663 0 : a->ptr.pp_double[i][j] = (double)(0);
48664 : }
48665 : }
48666 0 : rmatrixbd(a, m, m, &tauq, &taup, _state);
48667 0 : rmatrixbdunpackq(a, m, m, &tauq, ncu, u, _state);
48668 0 : rmatrixbdunpackdiagonals(a, m, m, &isupper, w, &e, _state);
48669 0 : ae_vector_set_length(&work, m+1, _state);
48670 0 : inplacetranspose(u, 0, nru-1, 0, ncu-1, &work, _state);
48671 0 : result = rmatrixbdsvd(w, &e, m, isupper, ae_false, a, 0, u, nru, vt, 0, _state);
48672 0 : inplacetranspose(u, 0, nru-1, 0, ncu-1, &work, _state);
48673 0 : ae_frame_leave(_state);
48674 0 : return result;
48675 : }
48676 : else
48677 : {
48678 :
48679 : /*
48680 : * Right singular vectors (may be full matrix VT) to be computed
48681 : */
48682 0 : rmatrixlq(a, m, n, &tau, _state);
48683 0 : rmatrixlqunpackq(a, m, n, &tau, nrvt, vt, _state);
48684 0 : for(i=0; i<=m-1; i++)
48685 : {
48686 0 : for(j=i+1; j<=m-1; j++)
48687 : {
48688 0 : a->ptr.pp_double[i][j] = (double)(0);
48689 : }
48690 : }
48691 0 : rmatrixbd(a, m, m, &tauq, &taup, _state);
48692 0 : rmatrixbdunpackq(a, m, m, &tauq, ncu, u, _state);
48693 0 : rmatrixbdunpackdiagonals(a, m, m, &isupper, w, &e, _state);
48694 0 : ae_vector_set_length(&work, ae_maxint(m, n, _state)+1, _state);
48695 0 : inplacetranspose(u, 0, nru-1, 0, ncu-1, &work, _state);
48696 0 : if( additionalmemory<1 )
48697 : {
48698 :
48699 : /*
48700 : * No additional memory available
48701 : */
48702 0 : rmatrixbdmultiplybyp(a, m, m, &taup, vt, m, n, ae_false, ae_true, _state);
48703 0 : result = rmatrixbdsvd(w, &e, m, isupper, ae_false, a, 0, u, nru, vt, n, _state);
48704 : }
48705 : else
48706 : {
48707 :
48708 : /*
48709 : * Large VT. Transforming intermediate matrix T2
48710 : */
48711 0 : rmatrixbdunpackpt(a, m, m, &taup, m, &t2, _state);
48712 0 : result = rmatrixbdsvd(w, &e, m, isupper, ae_false, a, 0, u, nru, &t2, m, _state);
48713 0 : copymatrix(vt, 0, m-1, 0, n-1, a, 0, m-1, 0, n-1, _state);
48714 0 : rmatrixgemm(m, n, m, 1.0, &t2, 0, 0, 0, a, 0, 0, 0, 0.0, vt, 0, 0, _state);
48715 : }
48716 0 : inplacetranspose(u, 0, nru-1, 0, ncu-1, &work, _state);
48717 0 : ae_frame_leave(_state);
48718 0 : return result;
48719 : }
48720 : }
48721 :
48722 : /*
48723 : * M<=N
48724 : * We can use inplace transposition of U to get rid of columnwise operations
48725 : */
48726 0 : if( m<=n )
48727 : {
48728 0 : rmatrixbd(a, m, n, &tauq, &taup, _state);
48729 0 : rmatrixbdunpackq(a, m, n, &tauq, ncu, u, _state);
48730 0 : rmatrixbdunpackpt(a, m, n, &taup, nrvt, vt, _state);
48731 0 : rmatrixbdunpackdiagonals(a, m, n, &isupper, w, &e, _state);
48732 0 : ae_vector_set_length(&work, m+1, _state);
48733 0 : inplacetranspose(u, 0, nru-1, 0, ncu-1, &work, _state);
48734 0 : result = rmatrixbdsvd(w, &e, minmn, isupper, ae_false, a, 0, u, nru, vt, ncvt, _state);
48735 0 : inplacetranspose(u, 0, nru-1, 0, ncu-1, &work, _state);
48736 0 : ae_frame_leave(_state);
48737 0 : return result;
48738 : }
48739 :
48740 : /*
48741 : * Simple bidiagonal reduction
48742 : */
48743 0 : rmatrixbd(a, m, n, &tauq, &taup, _state);
48744 0 : rmatrixbdunpackq(a, m, n, &tauq, ncu, u, _state);
48745 0 : rmatrixbdunpackpt(a, m, n, &taup, nrvt, vt, _state);
48746 0 : rmatrixbdunpackdiagonals(a, m, n, &isupper, w, &e, _state);
48747 0 : if( additionalmemory<2||uneeded==0 )
48748 : {
48749 :
48750 : /*
48751 : * We cant use additional memory or there is no need in such operations
48752 : */
48753 0 : result = rmatrixbdsvd(w, &e, minmn, isupper, ae_false, u, nru, a, 0, vt, ncvt, _state);
48754 : }
48755 : else
48756 : {
48757 :
48758 : /*
48759 : * We can use additional memory
48760 : */
48761 0 : ae_matrix_set_length(&t2, minmn-1+1, m-1+1, _state);
48762 0 : copyandtranspose(u, 0, m-1, 0, minmn-1, &t2, 0, minmn-1, 0, m-1, _state);
48763 0 : result = rmatrixbdsvd(w, &e, minmn, isupper, ae_false, u, 0, &t2, m, vt, ncvt, _state);
48764 0 : copyandtranspose(&t2, 0, minmn-1, 0, m-1, u, 0, m-1, 0, minmn-1, _state);
48765 : }
48766 0 : ae_frame_leave(_state);
48767 0 : return result;
48768 : }
48769 :
48770 :
48771 : #endif
48772 : #if defined(AE_COMPILE_NORMESTIMATOR) || !defined(AE_PARTIAL_BUILD)
48773 :
48774 :
48775 : /*************************************************************************
48776 : This procedure initializes matrix norm estimator.
48777 :
48778 : USAGE:
48779 : 1. User initializes algorithm state with NormEstimatorCreate() call
48780 : 2. User calls NormEstimatorEstimateSparse() (or NormEstimatorIteration())
48781 : 3. User calls NormEstimatorResults() to get solution.
48782 :
48783 : INPUT PARAMETERS:
48784 : M - number of rows in the matrix being estimated, M>0
48785 : N - number of columns in the matrix being estimated, N>0
48786 : NStart - number of random starting vectors
48787 : recommended value - at least 5.
48788 : NIts - number of iterations to do with best starting vector
48789 : recommended value - at least 5.
48790 :
48791 : OUTPUT PARAMETERS:
48792 : State - structure which stores algorithm state
48793 :
48794 :
48795 : NOTE: this algorithm is effectively deterministic, i.e. it always returns
48796 : same result when repeatedly called for the same matrix. In fact, algorithm
48797 : uses randomized starting vectors, but internal random numbers generator
48798 : always generates same sequence of the random values (it is a feature, not
48799 : bug).
48800 :
48801 : Algorithm can be made non-deterministic with NormEstimatorSetSeed(0) call.
48802 :
48803 : -- ALGLIB --
48804 : Copyright 06.12.2011 by Bochkanov Sergey
48805 : *************************************************************************/
48806 0 : void normestimatorcreate(ae_int_t m,
48807 : ae_int_t n,
48808 : ae_int_t nstart,
48809 : ae_int_t nits,
48810 : normestimatorstate* state,
48811 : ae_state *_state)
48812 : {
48813 :
48814 0 : _normestimatorstate_clear(state);
48815 :
48816 0 : ae_assert(m>0, "NormEstimatorCreate: M<=0", _state);
48817 0 : ae_assert(n>0, "NormEstimatorCreate: N<=0", _state);
48818 0 : ae_assert(nstart>0, "NormEstimatorCreate: NStart<=0", _state);
48819 0 : ae_assert(nits>0, "NormEstimatorCreate: NIts<=0", _state);
48820 0 : state->m = m;
48821 0 : state->n = n;
48822 0 : state->nstart = nstart;
48823 0 : state->nits = nits;
48824 0 : state->seedval = 11;
48825 0 : hqrndrandomize(&state->r, _state);
48826 0 : ae_vector_set_length(&state->x0, state->n, _state);
48827 0 : ae_vector_set_length(&state->t, state->m, _state);
48828 0 : ae_vector_set_length(&state->x1, state->n, _state);
48829 0 : ae_vector_set_length(&state->xbest, state->n, _state);
48830 0 : ae_vector_set_length(&state->x, ae_maxint(state->n, state->m, _state), _state);
48831 0 : ae_vector_set_length(&state->mv, state->m, _state);
48832 0 : ae_vector_set_length(&state->mtv, state->n, _state);
48833 0 : ae_vector_set_length(&state->rstate.ia, 3+1, _state);
48834 0 : ae_vector_set_length(&state->rstate.ra, 2+1, _state);
48835 0 : state->rstate.stage = -1;
48836 0 : }
48837 :
48838 :
48839 : /*************************************************************************
48840 : This function changes seed value used by algorithm. In some cases we need
48841 : deterministic processing, i.e. subsequent calls must return equal results,
48842 : in other cases we need non-deterministic algorithm which returns different
48843 : results for the same matrix on every pass.
48844 :
48845 : Setting zero seed will lead to non-deterministic algorithm, while non-zero
48846 : value will make our algorithm deterministic.
48847 :
48848 : INPUT PARAMETERS:
48849 : State - norm estimator state, must be initialized with a call
48850 : to NormEstimatorCreate()
48851 : SeedVal - seed value, >=0. Zero value = non-deterministic algo.
48852 :
48853 : -- ALGLIB --
48854 : Copyright 06.12.2011 by Bochkanov Sergey
48855 : *************************************************************************/
48856 0 : void normestimatorsetseed(normestimatorstate* state,
48857 : ae_int_t seedval,
48858 : ae_state *_state)
48859 : {
48860 :
48861 :
48862 0 : ae_assert(seedval>=0, "NormEstimatorSetSeed: SeedVal<0", _state);
48863 0 : state->seedval = seedval;
48864 0 : }
48865 :
48866 :
48867 : /*************************************************************************
48868 :
48869 : -- ALGLIB --
48870 : Copyright 06.12.2011 by Bochkanov Sergey
48871 : *************************************************************************/
48872 0 : ae_bool normestimatoriteration(normestimatorstate* state,
48873 : ae_state *_state)
48874 : {
48875 : ae_int_t n;
48876 : ae_int_t m;
48877 : ae_int_t i;
48878 : ae_int_t itcnt;
48879 : double v;
48880 : double growth;
48881 : double bestgrowth;
48882 : ae_bool result;
48883 :
48884 :
48885 :
48886 : /*
48887 : * Reverse communication preparations
48888 : * I know it looks ugly, but it works the same way
48889 : * anywhere from C++ to Python.
48890 : *
48891 : * This code initializes locals by:
48892 : * * random values determined during code
48893 : * generation - on first subroutine call
48894 : * * values from previous call - on subsequent calls
48895 : */
48896 0 : if( state->rstate.stage>=0 )
48897 : {
48898 0 : n = state->rstate.ia.ptr.p_int[0];
48899 0 : m = state->rstate.ia.ptr.p_int[1];
48900 0 : i = state->rstate.ia.ptr.p_int[2];
48901 0 : itcnt = state->rstate.ia.ptr.p_int[3];
48902 0 : v = state->rstate.ra.ptr.p_double[0];
48903 0 : growth = state->rstate.ra.ptr.p_double[1];
48904 0 : bestgrowth = state->rstate.ra.ptr.p_double[2];
48905 : }
48906 : else
48907 : {
48908 0 : n = 359;
48909 0 : m = -58;
48910 0 : i = -919;
48911 0 : itcnt = -909;
48912 0 : v = 81;
48913 0 : growth = 255;
48914 0 : bestgrowth = 74;
48915 : }
48916 0 : if( state->rstate.stage==0 )
48917 : {
48918 0 : goto lbl_0;
48919 : }
48920 0 : if( state->rstate.stage==1 )
48921 : {
48922 0 : goto lbl_1;
48923 : }
48924 0 : if( state->rstate.stage==2 )
48925 : {
48926 0 : goto lbl_2;
48927 : }
48928 0 : if( state->rstate.stage==3 )
48929 : {
48930 0 : goto lbl_3;
48931 : }
48932 :
48933 : /*
48934 : * Routine body
48935 : */
48936 0 : n = state->n;
48937 0 : m = state->m;
48938 0 : if( state->seedval>0 )
48939 : {
48940 0 : hqrndseed(state->seedval, state->seedval+2, &state->r, _state);
48941 : }
48942 0 : bestgrowth = (double)(0);
48943 0 : state->xbest.ptr.p_double[0] = (double)(1);
48944 0 : for(i=1; i<=n-1; i++)
48945 : {
48946 0 : state->xbest.ptr.p_double[i] = (double)(0);
48947 : }
48948 0 : itcnt = 0;
48949 0 : lbl_4:
48950 0 : if( itcnt>state->nstart-1 )
48951 : {
48952 0 : goto lbl_6;
48953 : }
48954 0 : do
48955 : {
48956 0 : v = (double)(0);
48957 0 : for(i=0; i<=n-1; i++)
48958 : {
48959 0 : state->x0.ptr.p_double[i] = hqrndnormal(&state->r, _state);
48960 0 : v = v+ae_sqr(state->x0.ptr.p_double[i], _state);
48961 : }
48962 : }
48963 0 : while(ae_fp_eq(v,(double)(0)));
48964 0 : v = 1/ae_sqrt(v, _state);
48965 0 : ae_v_muld(&state->x0.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
48966 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
48967 0 : state->needmv = ae_true;
48968 0 : state->needmtv = ae_false;
48969 0 : state->rstate.stage = 0;
48970 0 : goto lbl_rcomm;
48971 0 : lbl_0:
48972 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->mv.ptr.p_double[0], 1, ae_v_len(0,m-1));
48973 0 : state->needmv = ae_false;
48974 0 : state->needmtv = ae_true;
48975 0 : state->rstate.stage = 1;
48976 0 : goto lbl_rcomm;
48977 0 : lbl_1:
48978 0 : ae_v_move(&state->x1.ptr.p_double[0], 1, &state->mtv.ptr.p_double[0], 1, ae_v_len(0,n-1));
48979 0 : v = (double)(0);
48980 0 : for(i=0; i<=n-1; i++)
48981 : {
48982 0 : v = v+ae_sqr(state->x1.ptr.p_double[i], _state);
48983 : }
48984 0 : growth = ae_sqrt(ae_sqrt(v, _state), _state);
48985 0 : if( ae_fp_greater(growth,bestgrowth) )
48986 : {
48987 0 : v = 1/ae_sqrt(v, _state);
48988 0 : ae_v_moved(&state->xbest.ptr.p_double[0], 1, &state->x1.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
48989 0 : bestgrowth = growth;
48990 : }
48991 0 : itcnt = itcnt+1;
48992 0 : goto lbl_4;
48993 0 : lbl_6:
48994 0 : ae_v_move(&state->x0.ptr.p_double[0], 1, &state->xbest.ptr.p_double[0], 1, ae_v_len(0,n-1));
48995 0 : itcnt = 0;
48996 0 : lbl_7:
48997 0 : if( itcnt>state->nits-1 )
48998 : {
48999 0 : goto lbl_9;
49000 : }
49001 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
49002 0 : state->needmv = ae_true;
49003 0 : state->needmtv = ae_false;
49004 0 : state->rstate.stage = 2;
49005 0 : goto lbl_rcomm;
49006 0 : lbl_2:
49007 0 : ae_v_move(&state->x.ptr.p_double[0], 1, &state->mv.ptr.p_double[0], 1, ae_v_len(0,m-1));
49008 0 : state->needmv = ae_false;
49009 0 : state->needmtv = ae_true;
49010 0 : state->rstate.stage = 3;
49011 0 : goto lbl_rcomm;
49012 0 : lbl_3:
49013 0 : ae_v_move(&state->x1.ptr.p_double[0], 1, &state->mtv.ptr.p_double[0], 1, ae_v_len(0,n-1));
49014 0 : v = (double)(0);
49015 0 : for(i=0; i<=n-1; i++)
49016 : {
49017 0 : v = v+ae_sqr(state->x1.ptr.p_double[i], _state);
49018 : }
49019 0 : state->repnorm = ae_sqrt(ae_sqrt(v, _state), _state);
49020 0 : if( ae_fp_neq(v,(double)(0)) )
49021 : {
49022 0 : v = 1/ae_sqrt(v, _state);
49023 0 : ae_v_moved(&state->x0.ptr.p_double[0], 1, &state->x1.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
49024 : }
49025 0 : itcnt = itcnt+1;
49026 0 : goto lbl_7;
49027 0 : lbl_9:
49028 0 : result = ae_false;
49029 0 : return result;
49030 :
49031 : /*
49032 : * Saving state
49033 : */
49034 0 : lbl_rcomm:
49035 0 : result = ae_true;
49036 0 : state->rstate.ia.ptr.p_int[0] = n;
49037 0 : state->rstate.ia.ptr.p_int[1] = m;
49038 0 : state->rstate.ia.ptr.p_int[2] = i;
49039 0 : state->rstate.ia.ptr.p_int[3] = itcnt;
49040 0 : state->rstate.ra.ptr.p_double[0] = v;
49041 0 : state->rstate.ra.ptr.p_double[1] = growth;
49042 0 : state->rstate.ra.ptr.p_double[2] = bestgrowth;
49043 0 : return result;
49044 : }
49045 :
49046 :
49047 : /*************************************************************************
49048 : This function estimates norm of the sparse M*N matrix A.
49049 :
49050 : INPUT PARAMETERS:
49051 : State - norm estimator state, must be initialized with a call
49052 : to NormEstimatorCreate()
49053 : A - sparse M*N matrix, must be converted to CRS format
49054 : prior to calling this function.
49055 :
49056 : After this function is over you can call NormEstimatorResults() to get
49057 : estimate of the norm(A).
49058 :
49059 : -- ALGLIB --
49060 : Copyright 06.12.2011 by Bochkanov Sergey
49061 : *************************************************************************/
49062 0 : void normestimatorestimatesparse(normestimatorstate* state,
49063 : sparsematrix* a,
49064 : ae_state *_state)
49065 : {
49066 :
49067 :
49068 0 : normestimatorrestart(state, _state);
49069 0 : while(normestimatoriteration(state, _state))
49070 : {
49071 0 : if( state->needmv )
49072 : {
49073 0 : sparsemv(a, &state->x, &state->mv, _state);
49074 0 : continue;
49075 : }
49076 0 : if( state->needmtv )
49077 : {
49078 0 : sparsemtv(a, &state->x, &state->mtv, _state);
49079 0 : continue;
49080 : }
49081 : }
49082 0 : }
49083 :
49084 :
49085 : /*************************************************************************
49086 : Matrix norm estimation results
49087 :
49088 : INPUT PARAMETERS:
49089 : State - algorithm state
49090 :
49091 : OUTPUT PARAMETERS:
49092 : Nrm - estimate of the matrix norm, Nrm>=0
49093 :
49094 : -- ALGLIB --
49095 : Copyright 06.12.2011 by Bochkanov Sergey
49096 : *************************************************************************/
49097 0 : void normestimatorresults(normestimatorstate* state,
49098 : double* nrm,
49099 : ae_state *_state)
49100 : {
49101 :
49102 0 : *nrm = 0;
49103 :
49104 0 : *nrm = state->repnorm;
49105 0 : }
49106 :
49107 :
49108 : /*************************************************************************
49109 : This function restarts estimator and prepares it for the next estimation
49110 : round.
49111 :
49112 : INPUT PARAMETERS:
49113 : State - algorithm state
49114 : -- ALGLIB --
49115 : Copyright 06.12.2011 by Bochkanov Sergey
49116 : *************************************************************************/
49117 0 : void normestimatorrestart(normestimatorstate* state, ae_state *_state)
49118 : {
49119 :
49120 :
49121 0 : ae_vector_set_length(&state->rstate.ia, 3+1, _state);
49122 0 : ae_vector_set_length(&state->rstate.ra, 2+1, _state);
49123 0 : state->rstate.stage = -1;
49124 0 : }
49125 :
49126 :
49127 0 : void _normestimatorstate_init(void* _p, ae_state *_state, ae_bool make_automatic)
49128 : {
49129 0 : normestimatorstate *p = (normestimatorstate*)_p;
49130 0 : ae_touch_ptr((void*)p);
49131 0 : ae_vector_init(&p->x0, 0, DT_REAL, _state, make_automatic);
49132 0 : ae_vector_init(&p->x1, 0, DT_REAL, _state, make_automatic);
49133 0 : ae_vector_init(&p->t, 0, DT_REAL, _state, make_automatic);
49134 0 : ae_vector_init(&p->xbest, 0, DT_REAL, _state, make_automatic);
49135 0 : _hqrndstate_init(&p->r, _state, make_automatic);
49136 0 : ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic);
49137 0 : ae_vector_init(&p->mv, 0, DT_REAL, _state, make_automatic);
49138 0 : ae_vector_init(&p->mtv, 0, DT_REAL, _state, make_automatic);
49139 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
49140 0 : }
49141 :
49142 :
49143 0 : void _normestimatorstate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
49144 : {
49145 0 : normestimatorstate *dst = (normestimatorstate*)_dst;
49146 0 : normestimatorstate *src = (normestimatorstate*)_src;
49147 0 : dst->n = src->n;
49148 0 : dst->m = src->m;
49149 0 : dst->nstart = src->nstart;
49150 0 : dst->nits = src->nits;
49151 0 : dst->seedval = src->seedval;
49152 0 : ae_vector_init_copy(&dst->x0, &src->x0, _state, make_automatic);
49153 0 : ae_vector_init_copy(&dst->x1, &src->x1, _state, make_automatic);
49154 0 : ae_vector_init_copy(&dst->t, &src->t, _state, make_automatic);
49155 0 : ae_vector_init_copy(&dst->xbest, &src->xbest, _state, make_automatic);
49156 0 : _hqrndstate_init_copy(&dst->r, &src->r, _state, make_automatic);
49157 0 : ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic);
49158 0 : ae_vector_init_copy(&dst->mv, &src->mv, _state, make_automatic);
49159 0 : ae_vector_init_copy(&dst->mtv, &src->mtv, _state, make_automatic);
49160 0 : dst->needmv = src->needmv;
49161 0 : dst->needmtv = src->needmtv;
49162 0 : dst->repnorm = src->repnorm;
49163 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
49164 0 : }
49165 :
49166 :
49167 0 : void _normestimatorstate_clear(void* _p)
49168 : {
49169 0 : normestimatorstate *p = (normestimatorstate*)_p;
49170 0 : ae_touch_ptr((void*)p);
49171 0 : ae_vector_clear(&p->x0);
49172 0 : ae_vector_clear(&p->x1);
49173 0 : ae_vector_clear(&p->t);
49174 0 : ae_vector_clear(&p->xbest);
49175 0 : _hqrndstate_clear(&p->r);
49176 0 : ae_vector_clear(&p->x);
49177 0 : ae_vector_clear(&p->mv);
49178 0 : ae_vector_clear(&p->mtv);
49179 0 : _rcommstate_clear(&p->rstate);
49180 0 : }
49181 :
49182 :
49183 0 : void _normestimatorstate_destroy(void* _p)
49184 : {
49185 0 : normestimatorstate *p = (normestimatorstate*)_p;
49186 0 : ae_touch_ptr((void*)p);
49187 0 : ae_vector_destroy(&p->x0);
49188 0 : ae_vector_destroy(&p->x1);
49189 0 : ae_vector_destroy(&p->t);
49190 0 : ae_vector_destroy(&p->xbest);
49191 0 : _hqrndstate_destroy(&p->r);
49192 0 : ae_vector_destroy(&p->x);
49193 0 : ae_vector_destroy(&p->mv);
49194 0 : ae_vector_destroy(&p->mtv);
49195 0 : _rcommstate_destroy(&p->rstate);
49196 0 : }
49197 :
49198 :
49199 : #endif
49200 : #if defined(AE_COMPILE_HSSCHUR) || !defined(AE_PARTIAL_BUILD)
49201 :
49202 :
49203 0 : void rmatrixinternalschurdecomposition(/* Real */ ae_matrix* h,
49204 : ae_int_t n,
49205 : ae_int_t tneeded,
49206 : ae_int_t zneeded,
49207 : /* Real */ ae_vector* wr,
49208 : /* Real */ ae_vector* wi,
49209 : /* Real */ ae_matrix* z,
49210 : ae_int_t* info,
49211 : ae_state *_state)
49212 : {
49213 : ae_frame _frame_block;
49214 : ae_int_t i;
49215 : ae_int_t j;
49216 : ae_matrix h1;
49217 : ae_matrix z1;
49218 : ae_vector wr1;
49219 : ae_vector wi1;
49220 :
49221 0 : ae_frame_make(_state, &_frame_block);
49222 0 : memset(&h1, 0, sizeof(h1));
49223 0 : memset(&z1, 0, sizeof(z1));
49224 0 : memset(&wr1, 0, sizeof(wr1));
49225 0 : memset(&wi1, 0, sizeof(wi1));
49226 0 : ae_vector_clear(wr);
49227 0 : ae_vector_clear(wi);
49228 0 : *info = 0;
49229 0 : ae_matrix_init(&h1, 0, 0, DT_REAL, _state, ae_true);
49230 0 : ae_matrix_init(&z1, 0, 0, DT_REAL, _state, ae_true);
49231 0 : ae_vector_init(&wr1, 0, DT_REAL, _state, ae_true);
49232 0 : ae_vector_init(&wi1, 0, DT_REAL, _state, ae_true);
49233 :
49234 :
49235 : /*
49236 : * Allocate space
49237 : */
49238 0 : ae_vector_set_length(wr, n, _state);
49239 0 : ae_vector_set_length(wi, n, _state);
49240 0 : if( zneeded==2 )
49241 : {
49242 0 : rmatrixsetlengthatleast(z, n, n, _state);
49243 : }
49244 :
49245 : /*
49246 : * MKL version
49247 : */
49248 0 : if( rmatrixinternalschurdecompositionmkl(h, n, tneeded, zneeded, wr, wi, z, info, _state) )
49249 : {
49250 0 : ae_frame_leave(_state);
49251 0 : return;
49252 : }
49253 :
49254 : /*
49255 : * ALGLIB version
49256 : */
49257 0 : ae_matrix_set_length(&h1, n+1, n+1, _state);
49258 0 : for(i=0; i<=n-1; i++)
49259 : {
49260 0 : for(j=0; j<=n-1; j++)
49261 : {
49262 0 : h1.ptr.pp_double[1+i][1+j] = h->ptr.pp_double[i][j];
49263 : }
49264 : }
49265 0 : if( zneeded==1 )
49266 : {
49267 0 : ae_matrix_set_length(&z1, n+1, n+1, _state);
49268 0 : for(i=0; i<=n-1; i++)
49269 : {
49270 0 : for(j=0; j<=n-1; j++)
49271 : {
49272 0 : z1.ptr.pp_double[1+i][1+j] = z->ptr.pp_double[i][j];
49273 : }
49274 : }
49275 : }
49276 0 : internalschurdecomposition(&h1, n, tneeded, zneeded, &wr1, &wi1, &z1, info, _state);
49277 0 : for(i=0; i<=n-1; i++)
49278 : {
49279 0 : wr->ptr.p_double[i] = wr1.ptr.p_double[i+1];
49280 0 : wi->ptr.p_double[i] = wi1.ptr.p_double[i+1];
49281 : }
49282 0 : if( tneeded!=0 )
49283 : {
49284 0 : for(i=0; i<=n-1; i++)
49285 : {
49286 0 : for(j=0; j<=n-1; j++)
49287 : {
49288 0 : h->ptr.pp_double[i][j] = h1.ptr.pp_double[1+i][1+j];
49289 : }
49290 : }
49291 : }
49292 0 : if( zneeded!=0 )
49293 : {
49294 0 : rmatrixsetlengthatleast(z, n, n, _state);
49295 0 : for(i=0; i<=n-1; i++)
49296 : {
49297 0 : for(j=0; j<=n-1; j++)
49298 : {
49299 0 : z->ptr.pp_double[i][j] = z1.ptr.pp_double[1+i][1+j];
49300 : }
49301 : }
49302 : }
49303 0 : ae_frame_leave(_state);
49304 : }
49305 :
49306 :
49307 : /*************************************************************************
49308 : Subroutine performing the Schur decomposition of a matrix in upper
49309 : Hessenberg form using the QR algorithm with multiple shifts.
49310 :
49311 : The source matrix H is represented as S'*H*S = T, where H - matrix in
49312 : upper Hessenberg form, S - orthogonal matrix (Schur vectors), T - upper
49313 : quasi-triangular matrix (with blocks of sizes 1x1 and 2x2 on the main
49314 : diagonal).
49315 :
49316 : Input parameters:
49317 : H - matrix to be decomposed.
49318 : Array whose indexes range within [1..N, 1..N].
49319 : N - size of H, N>=0.
49320 :
49321 :
49322 : Output parameters:
49323 : H - contains the matrix T.
49324 : Array whose indexes range within [1..N, 1..N].
49325 : All elements below the blocks on the main diagonal are equal
49326 : to 0.
49327 : S - contains Schur vectors.
49328 : Array whose indexes range within [1..N, 1..N].
49329 :
49330 : Note 1:
49331 : The block structure of matrix T could be easily recognized: since all
49332 : the elements below the blocks are zeros, the elements a[i+1,i] which
49333 : are equal to 0 show the block border.
49334 :
49335 : Note 2:
49336 : the algorithm performance depends on the value of the internal
49337 : parameter NS of InternalSchurDecomposition subroutine which defines
49338 : the number of shifts in the QR algorithm (analog of the block width
49339 : in block matrix algorithms in linear algebra). If you require maximum
49340 : performance on your machine, it is recommended to adjust this
49341 : parameter manually.
49342 :
49343 : Result:
49344 : True, if the algorithm has converged and the parameters H and S contain
49345 : the result.
49346 : False, if the algorithm has not converged.
49347 :
49348 : Algorithm implemented on the basis of subroutine DHSEQR (LAPACK 3.0 library).
49349 : *************************************************************************/
49350 0 : ae_bool upperhessenbergschurdecomposition(/* Real */ ae_matrix* h,
49351 : ae_int_t n,
49352 : /* Real */ ae_matrix* s,
49353 : ae_state *_state)
49354 : {
49355 : ae_frame _frame_block;
49356 : ae_vector wi;
49357 : ae_vector wr;
49358 : ae_int_t info;
49359 : ae_bool result;
49360 :
49361 0 : ae_frame_make(_state, &_frame_block);
49362 0 : memset(&wi, 0, sizeof(wi));
49363 0 : memset(&wr, 0, sizeof(wr));
49364 0 : ae_matrix_clear(s);
49365 0 : ae_vector_init(&wi, 0, DT_REAL, _state, ae_true);
49366 0 : ae_vector_init(&wr, 0, DT_REAL, _state, ae_true);
49367 :
49368 0 : internalschurdecomposition(h, n, 1, 2, &wr, &wi, s, &info, _state);
49369 0 : result = info==0;
49370 0 : ae_frame_leave(_state);
49371 0 : return result;
49372 : }
49373 :
49374 :
49375 0 : void internalschurdecomposition(/* Real */ ae_matrix* h,
49376 : ae_int_t n,
49377 : ae_int_t tneeded,
49378 : ae_int_t zneeded,
49379 : /* Real */ ae_vector* wr,
49380 : /* Real */ ae_vector* wi,
49381 : /* Real */ ae_matrix* z,
49382 : ae_int_t* info,
49383 : ae_state *_state)
49384 : {
49385 : ae_frame _frame_block;
49386 : ae_vector work;
49387 : ae_int_t i;
49388 : ae_int_t i1;
49389 : ae_int_t i2;
49390 : ae_int_t ierr;
49391 : ae_int_t ii;
49392 : ae_int_t itemp;
49393 : ae_int_t itn;
49394 : ae_int_t its;
49395 : ae_int_t j;
49396 : ae_int_t k;
49397 : ae_int_t l;
49398 : ae_int_t maxb;
49399 : ae_int_t nr;
49400 : ae_int_t ns;
49401 : ae_int_t nv;
49402 : double absw;
49403 : double smlnum;
49404 : double tau;
49405 : double temp;
49406 : double tst1;
49407 : double ulp;
49408 : double unfl;
49409 : ae_matrix s;
49410 : ae_vector v;
49411 : ae_vector vv;
49412 : ae_vector workc1;
49413 : ae_vector works1;
49414 : ae_vector workv3;
49415 : ae_vector tmpwr;
49416 : ae_vector tmpwi;
49417 : ae_bool initz;
49418 : ae_bool wantt;
49419 : ae_bool wantz;
49420 : double cnst;
49421 : ae_bool failflag;
49422 : ae_int_t p1;
49423 : ae_int_t p2;
49424 : double vt;
49425 :
49426 0 : ae_frame_make(_state, &_frame_block);
49427 0 : memset(&work, 0, sizeof(work));
49428 0 : memset(&s, 0, sizeof(s));
49429 0 : memset(&v, 0, sizeof(v));
49430 0 : memset(&vv, 0, sizeof(vv));
49431 0 : memset(&workc1, 0, sizeof(workc1));
49432 0 : memset(&works1, 0, sizeof(works1));
49433 0 : memset(&workv3, 0, sizeof(workv3));
49434 0 : memset(&tmpwr, 0, sizeof(tmpwr));
49435 0 : memset(&tmpwi, 0, sizeof(tmpwi));
49436 0 : ae_vector_clear(wr);
49437 0 : ae_vector_clear(wi);
49438 0 : *info = 0;
49439 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
49440 0 : ae_matrix_init(&s, 0, 0, DT_REAL, _state, ae_true);
49441 0 : ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
49442 0 : ae_vector_init(&vv, 0, DT_REAL, _state, ae_true);
49443 0 : ae_vector_init(&workc1, 0, DT_REAL, _state, ae_true);
49444 0 : ae_vector_init(&works1, 0, DT_REAL, _state, ae_true);
49445 0 : ae_vector_init(&workv3, 0, DT_REAL, _state, ae_true);
49446 0 : ae_vector_init(&tmpwr, 0, DT_REAL, _state, ae_true);
49447 0 : ae_vector_init(&tmpwi, 0, DT_REAL, _state, ae_true);
49448 :
49449 :
49450 : /*
49451 : * Set the order of the multi-shift QR algorithm to be used.
49452 : * If you want to tune algorithm, change this values
49453 : */
49454 0 : ns = 12;
49455 0 : maxb = 50;
49456 :
49457 : /*
49458 : * Now 2 < NS <= MAXB < NH.
49459 : */
49460 0 : maxb = ae_maxint(3, maxb, _state);
49461 0 : ns = ae_minint(maxb, ns, _state);
49462 :
49463 : /*
49464 : * Initialize
49465 : */
49466 0 : cnst = 1.5;
49467 0 : ae_vector_set_length(&work, ae_maxint(n, 1, _state)+1, _state);
49468 0 : ae_matrix_set_length(&s, ns+1, ns+1, _state);
49469 0 : ae_vector_set_length(&v, ns+1+1, _state);
49470 0 : ae_vector_set_length(&vv, ns+1+1, _state);
49471 0 : ae_vector_set_length(wr, ae_maxint(n, 1, _state)+1, _state);
49472 0 : ae_vector_set_length(wi, ae_maxint(n, 1, _state)+1, _state);
49473 0 : ae_vector_set_length(&workc1, 1+1, _state);
49474 0 : ae_vector_set_length(&works1, 1+1, _state);
49475 0 : ae_vector_set_length(&workv3, 3+1, _state);
49476 0 : ae_vector_set_length(&tmpwr, ae_maxint(n, 1, _state)+1, _state);
49477 0 : ae_vector_set_length(&tmpwi, ae_maxint(n, 1, _state)+1, _state);
49478 0 : ae_assert(n>=0, "InternalSchurDecomposition: incorrect N!", _state);
49479 0 : ae_assert(tneeded==0||tneeded==1, "InternalSchurDecomposition: incorrect TNeeded!", _state);
49480 0 : ae_assert((zneeded==0||zneeded==1)||zneeded==2, "InternalSchurDecomposition: incorrect ZNeeded!", _state);
49481 0 : wantt = tneeded==1;
49482 0 : initz = zneeded==2;
49483 0 : wantz = zneeded!=0;
49484 0 : *info = 0;
49485 :
49486 : /*
49487 : * Initialize Z, if necessary
49488 : */
49489 0 : if( initz )
49490 : {
49491 0 : rmatrixsetlengthatleast(z, n+1, n+1, _state);
49492 0 : for(i=1; i<=n; i++)
49493 : {
49494 0 : for(j=1; j<=n; j++)
49495 : {
49496 0 : if( i==j )
49497 : {
49498 0 : z->ptr.pp_double[i][j] = (double)(1);
49499 : }
49500 : else
49501 : {
49502 0 : z->ptr.pp_double[i][j] = (double)(0);
49503 : }
49504 : }
49505 : }
49506 : }
49507 :
49508 : /*
49509 : * Quick return if possible
49510 : */
49511 0 : if( n==0 )
49512 : {
49513 0 : ae_frame_leave(_state);
49514 0 : return;
49515 : }
49516 0 : if( n==1 )
49517 : {
49518 0 : wr->ptr.p_double[1] = h->ptr.pp_double[1][1];
49519 0 : wi->ptr.p_double[1] = (double)(0);
49520 0 : ae_frame_leave(_state);
49521 0 : return;
49522 : }
49523 :
49524 : /*
49525 : * Set rows and columns 1 to N to zero below the first
49526 : * subdiagonal.
49527 : */
49528 0 : for(j=1; j<=n-2; j++)
49529 : {
49530 0 : for(i=j+2; i<=n; i++)
49531 : {
49532 0 : h->ptr.pp_double[i][j] = (double)(0);
49533 : }
49534 : }
49535 :
49536 : /*
49537 : * Test if N is sufficiently small
49538 : */
49539 0 : if( (ns<=2||ns>n)||maxb>=n )
49540 : {
49541 :
49542 : /*
49543 : * Use the standard double-shift algorithm
49544 : */
49545 0 : hsschur_internalauxschur(wantt, wantz, n, 1, n, h, wr, wi, 1, n, z, &work, &workv3, &workc1, &works1, info, _state);
49546 :
49547 : /*
49548 : * fill entries under diagonal blocks of T with zeros
49549 : */
49550 0 : if( wantt )
49551 : {
49552 0 : j = 1;
49553 0 : while(j<=n)
49554 : {
49555 0 : if( ae_fp_eq(wi->ptr.p_double[j],(double)(0)) )
49556 : {
49557 0 : for(i=j+1; i<=n; i++)
49558 : {
49559 0 : h->ptr.pp_double[i][j] = (double)(0);
49560 : }
49561 0 : j = j+1;
49562 : }
49563 : else
49564 : {
49565 0 : for(i=j+2; i<=n; i++)
49566 : {
49567 0 : h->ptr.pp_double[i][j] = (double)(0);
49568 0 : h->ptr.pp_double[i][j+1] = (double)(0);
49569 : }
49570 0 : j = j+2;
49571 : }
49572 : }
49573 : }
49574 0 : ae_frame_leave(_state);
49575 0 : return;
49576 : }
49577 0 : unfl = ae_minrealnumber;
49578 0 : ulp = 2*ae_machineepsilon;
49579 0 : smlnum = unfl*(n/ulp);
49580 :
49581 : /*
49582 : * I1 and I2 are the indices of the first row and last column of H
49583 : * to which transformations must be applied. If eigenvalues only are
49584 : * being computed, I1 and I2 are set inside the main loop.
49585 : */
49586 0 : i1 = 1;
49587 0 : i2 = n;
49588 :
49589 : /*
49590 : * ITN is the total number of multiple-shift QR iterations allowed.
49591 : */
49592 0 : itn = 30*n;
49593 :
49594 : /*
49595 : * The main loop begins here. I is the loop index and decreases from
49596 : * IHI to ILO in steps of at most MAXB. Each iteration of the loop
49597 : * works with the active submatrix in rows and columns L to I.
49598 : * Eigenvalues I+1 to IHI have already converged. Either L = ILO or
49599 : * H(L,L-1) is negligible so that the matrix splits.
49600 : */
49601 0 : i = n;
49602 : for(;;)
49603 : {
49604 0 : l = 1;
49605 0 : if( i<1 )
49606 : {
49607 :
49608 : /*
49609 : * fill entries under diagonal blocks of T with zeros
49610 : */
49611 0 : if( wantt )
49612 : {
49613 0 : j = 1;
49614 0 : while(j<=n)
49615 : {
49616 0 : if( ae_fp_eq(wi->ptr.p_double[j],(double)(0)) )
49617 : {
49618 0 : for(i=j+1; i<=n; i++)
49619 : {
49620 0 : h->ptr.pp_double[i][j] = (double)(0);
49621 : }
49622 0 : j = j+1;
49623 : }
49624 : else
49625 : {
49626 0 : for(i=j+2; i<=n; i++)
49627 : {
49628 0 : h->ptr.pp_double[i][j] = (double)(0);
49629 0 : h->ptr.pp_double[i][j+1] = (double)(0);
49630 : }
49631 0 : j = j+2;
49632 : }
49633 : }
49634 : }
49635 :
49636 : /*
49637 : * Exit
49638 : */
49639 0 : ae_frame_leave(_state);
49640 0 : return;
49641 : }
49642 :
49643 : /*
49644 : * Perform multiple-shift QR iterations on rows and columns ILO to I
49645 : * until a submatrix of order at most MAXB splits off at the bottom
49646 : * because a subdiagonal element has become negligible.
49647 : */
49648 0 : failflag = ae_true;
49649 0 : for(its=0; its<=itn; its++)
49650 : {
49651 :
49652 : /*
49653 : * Look for a single small subdiagonal element.
49654 : */
49655 0 : for(k=i; k>=l+1; k--)
49656 : {
49657 0 : tst1 = ae_fabs(h->ptr.pp_double[k-1][k-1], _state)+ae_fabs(h->ptr.pp_double[k][k], _state);
49658 0 : if( ae_fp_eq(tst1,(double)(0)) )
49659 : {
49660 0 : tst1 = upperhessenberg1norm(h, l, i, l, i, &work, _state);
49661 : }
49662 0 : if( ae_fp_less_eq(ae_fabs(h->ptr.pp_double[k][k-1], _state),ae_maxreal(ulp*tst1, smlnum, _state)) )
49663 : {
49664 0 : break;
49665 : }
49666 : }
49667 0 : l = k;
49668 0 : if( l>1 )
49669 : {
49670 :
49671 : /*
49672 : * H(L,L-1) is negligible.
49673 : */
49674 0 : h->ptr.pp_double[l][l-1] = (double)(0);
49675 : }
49676 :
49677 : /*
49678 : * Exit from loop if a submatrix of order <= MAXB has split off.
49679 : */
49680 0 : if( l>=i-maxb+1 )
49681 : {
49682 0 : failflag = ae_false;
49683 0 : break;
49684 : }
49685 :
49686 : /*
49687 : * Now the active submatrix is in rows and columns L to I. If
49688 : * eigenvalues only are being computed, only the active submatrix
49689 : * need be transformed.
49690 : */
49691 0 : if( its==20||its==30 )
49692 : {
49693 :
49694 : /*
49695 : * Exceptional shifts.
49696 : */
49697 0 : for(ii=i-ns+1; ii<=i; ii++)
49698 : {
49699 0 : wr->ptr.p_double[ii] = cnst*(ae_fabs(h->ptr.pp_double[ii][ii-1], _state)+ae_fabs(h->ptr.pp_double[ii][ii], _state));
49700 0 : wi->ptr.p_double[ii] = (double)(0);
49701 : }
49702 : }
49703 : else
49704 : {
49705 :
49706 : /*
49707 : * Use eigenvalues of trailing submatrix of order NS as shifts.
49708 : */
49709 0 : copymatrix(h, i-ns+1, i, i-ns+1, i, &s, 1, ns, 1, ns, _state);
49710 0 : hsschur_internalauxschur(ae_false, ae_false, ns, 1, ns, &s, &tmpwr, &tmpwi, 1, ns, z, &work, &workv3, &workc1, &works1, &ierr, _state);
49711 0 : for(p1=1; p1<=ns; p1++)
49712 : {
49713 0 : wr->ptr.p_double[i-ns+p1] = tmpwr.ptr.p_double[p1];
49714 0 : wi->ptr.p_double[i-ns+p1] = tmpwi.ptr.p_double[p1];
49715 : }
49716 0 : if( ierr>0 )
49717 : {
49718 :
49719 : /*
49720 : * If DLAHQR failed to compute all NS eigenvalues, use the
49721 : * unconverged diagonal elements as the remaining shifts.
49722 : */
49723 0 : for(ii=1; ii<=ierr; ii++)
49724 : {
49725 0 : wr->ptr.p_double[i-ns+ii] = s.ptr.pp_double[ii][ii];
49726 0 : wi->ptr.p_double[i-ns+ii] = (double)(0);
49727 : }
49728 : }
49729 : }
49730 :
49731 : /*
49732 : * Form the first column of (G-w(1)) (G-w(2)) . . . (G-w(ns))
49733 : * where G is the Hessenberg submatrix H(L:I,L:I) and w is
49734 : * the vector of shifts (stored in WR and WI). The result is
49735 : * stored in the local array V.
49736 : */
49737 0 : v.ptr.p_double[1] = (double)(1);
49738 0 : for(ii=2; ii<=ns+1; ii++)
49739 : {
49740 0 : v.ptr.p_double[ii] = (double)(0);
49741 : }
49742 0 : nv = 1;
49743 0 : for(j=i-ns+1; j<=i; j++)
49744 : {
49745 0 : if( ae_fp_greater_eq(wi->ptr.p_double[j],(double)(0)) )
49746 : {
49747 0 : if( ae_fp_eq(wi->ptr.p_double[j],(double)(0)) )
49748 : {
49749 :
49750 : /*
49751 : * real shift
49752 : */
49753 0 : p1 = nv+1;
49754 0 : ae_v_move(&vv.ptr.p_double[1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,p1));
49755 0 : matrixvectormultiply(h, l, l+nv, l, l+nv-1, ae_false, &vv, 1, nv, 1.0, &v, 1, nv+1, -wr->ptr.p_double[j], _state);
49756 0 : nv = nv+1;
49757 : }
49758 : else
49759 : {
49760 0 : if( ae_fp_greater(wi->ptr.p_double[j],(double)(0)) )
49761 : {
49762 :
49763 : /*
49764 : * complex conjugate pair of shifts
49765 : */
49766 0 : p1 = nv+1;
49767 0 : ae_v_move(&vv.ptr.p_double[1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,p1));
49768 0 : matrixvectormultiply(h, l, l+nv, l, l+nv-1, ae_false, &v, 1, nv, 1.0, &vv, 1, nv+1, -2*wr->ptr.p_double[j], _state);
49769 0 : itemp = vectoridxabsmax(&vv, 1, nv+1, _state);
49770 0 : temp = 1/ae_maxreal(ae_fabs(vv.ptr.p_double[itemp], _state), smlnum, _state);
49771 0 : p1 = nv+1;
49772 0 : ae_v_muld(&vv.ptr.p_double[1], 1, ae_v_len(1,p1), temp);
49773 0 : absw = pythag2(wr->ptr.p_double[j], wi->ptr.p_double[j], _state);
49774 0 : temp = temp*absw*absw;
49775 0 : matrixvectormultiply(h, l, l+nv+1, l, l+nv, ae_false, &vv, 1, nv+1, 1.0, &v, 1, nv+2, temp, _state);
49776 0 : nv = nv+2;
49777 : }
49778 : }
49779 :
49780 : /*
49781 : * Scale V(1:NV) so that max(abs(V(i))) = 1. If V is zero,
49782 : * reset it to the unit vector.
49783 : */
49784 0 : itemp = vectoridxabsmax(&v, 1, nv, _state);
49785 0 : temp = ae_fabs(v.ptr.p_double[itemp], _state);
49786 0 : if( ae_fp_eq(temp,(double)(0)) )
49787 : {
49788 0 : v.ptr.p_double[1] = (double)(1);
49789 0 : for(ii=2; ii<=nv; ii++)
49790 : {
49791 0 : v.ptr.p_double[ii] = (double)(0);
49792 : }
49793 : }
49794 : else
49795 : {
49796 0 : temp = ae_maxreal(temp, smlnum, _state);
49797 0 : vt = 1/temp;
49798 0 : ae_v_muld(&v.ptr.p_double[1], 1, ae_v_len(1,nv), vt);
49799 : }
49800 : }
49801 : }
49802 :
49803 : /*
49804 : * Multiple-shift QR step
49805 : */
49806 0 : for(k=l; k<=i-1; k++)
49807 : {
49808 :
49809 : /*
49810 : * The first iteration of this loop determines a reflection G
49811 : * from the vector V and applies it from left and right to H,
49812 : * thus creating a nonzero bulge below the subdiagonal.
49813 : *
49814 : * Each subsequent iteration determines a reflection G to
49815 : * restore the Hessenberg form in the (K-1)th column, and thus
49816 : * chases the bulge one step toward the bottom of the active
49817 : * submatrix. NR is the order of G.
49818 : */
49819 0 : nr = ae_minint(ns+1, i-k+1, _state);
49820 0 : if( k>l )
49821 : {
49822 0 : p1 = k-1;
49823 0 : p2 = k+nr-1;
49824 0 : ae_v_move(&v.ptr.p_double[1], 1, &h->ptr.pp_double[k][p1], h->stride, ae_v_len(1,nr));
49825 0 : touchint(&p2, _state);
49826 : }
49827 0 : generatereflection(&v, nr, &tau, _state);
49828 0 : if( k>l )
49829 : {
49830 0 : h->ptr.pp_double[k][k-1] = v.ptr.p_double[1];
49831 0 : for(ii=k+1; ii<=i; ii++)
49832 : {
49833 0 : h->ptr.pp_double[ii][k-1] = (double)(0);
49834 : }
49835 : }
49836 0 : v.ptr.p_double[1] = (double)(1);
49837 :
49838 : /*
49839 : * Apply G from the left to transform the rows of the matrix in
49840 : * columns K to I2.
49841 : */
49842 0 : applyreflectionfromtheleft(h, tau, &v, k, k+nr-1, k, i2, &work, _state);
49843 :
49844 : /*
49845 : * Apply G from the right to transform the columns of the
49846 : * matrix in rows I1 to min(K+NR,I).
49847 : */
49848 0 : applyreflectionfromtheright(h, tau, &v, i1, ae_minint(k+nr, i, _state), k, k+nr-1, &work, _state);
49849 0 : if( wantz )
49850 : {
49851 :
49852 : /*
49853 : * Accumulate transformations in the matrix Z
49854 : */
49855 0 : applyreflectionfromtheright(z, tau, &v, 1, n, k, k+nr-1, &work, _state);
49856 : }
49857 : }
49858 : }
49859 :
49860 : /*
49861 : * Failure to converge in remaining number of iterations
49862 : */
49863 0 : if( failflag )
49864 : {
49865 0 : *info = i;
49866 0 : ae_frame_leave(_state);
49867 0 : return;
49868 : }
49869 :
49870 : /*
49871 : * A submatrix of order <= MAXB in rows and columns L to I has split
49872 : * off. Use the double-shift QR algorithm to handle it.
49873 : */
49874 0 : hsschur_internalauxschur(wantt, wantz, n, l, i, h, wr, wi, 1, n, z, &work, &workv3, &workc1, &works1, info, _state);
49875 0 : if( *info>0 )
49876 : {
49877 0 : ae_frame_leave(_state);
49878 0 : return;
49879 : }
49880 :
49881 : /*
49882 : * Decrement number of remaining iterations, and return to start of
49883 : * the main loop with a new value of I.
49884 : */
49885 0 : itn = itn-its;
49886 0 : i = l-1;
49887 :
49888 : /*
49889 : * Block below is never executed; it is necessary just to avoid
49890 : * "unreachable code" warning about automatically generated code.
49891 : *
49892 : * We just need a way to transfer control to the end of the function,
49893 : * even a fake way which is never actually traversed.
49894 : */
49895 0 : if( alwaysfalse(_state) )
49896 : {
49897 0 : ae_assert(ae_false, "Assertion failed", _state);
49898 0 : break;
49899 : }
49900 : }
49901 0 : ae_frame_leave(_state);
49902 : }
49903 :
49904 :
49905 : /*************************************************************************
49906 : Translation of DLAHQR from LAPACK.
49907 : *************************************************************************/
49908 0 : static void hsschur_internalauxschur(ae_bool wantt,
49909 : ae_bool wantz,
49910 : ae_int_t n,
49911 : ae_int_t ilo,
49912 : ae_int_t ihi,
49913 : /* Real */ ae_matrix* h,
49914 : /* Real */ ae_vector* wr,
49915 : /* Real */ ae_vector* wi,
49916 : ae_int_t iloz,
49917 : ae_int_t ihiz,
49918 : /* Real */ ae_matrix* z,
49919 : /* Real */ ae_vector* work,
49920 : /* Real */ ae_vector* workv3,
49921 : /* Real */ ae_vector* workc1,
49922 : /* Real */ ae_vector* works1,
49923 : ae_int_t* info,
49924 : ae_state *_state)
49925 : {
49926 : double safmin;
49927 : double tst;
49928 : double ab;
49929 : double ba;
49930 : double aa;
49931 : double bb;
49932 : double rt1r;
49933 : double rt1i;
49934 : double rt2r;
49935 : double rt2i;
49936 : double tr;
49937 : double det;
49938 : double rtdisc;
49939 : double h21s;
49940 : ae_int_t i;
49941 : ae_int_t i1;
49942 : ae_int_t i2;
49943 : ae_int_t itmax;
49944 : ae_int_t its;
49945 : ae_int_t j;
49946 : ae_int_t k;
49947 : ae_int_t l;
49948 : ae_int_t m;
49949 : ae_int_t nh;
49950 : ae_int_t nr;
49951 : ae_int_t nz;
49952 : double cs;
49953 : double h11;
49954 : double h12;
49955 : double h21;
49956 : double h22;
49957 : double s;
49958 : double smlnum;
49959 : double sn;
49960 : double sum;
49961 : double t1;
49962 : double t2;
49963 : double t3;
49964 : double v2;
49965 : double v3;
49966 : ae_bool failflag;
49967 : double dat1;
49968 : double dat2;
49969 : ae_int_t p1;
49970 : double him1im1;
49971 : double him1i;
49972 : double hiim1;
49973 : double hii;
49974 : double wrim1;
49975 : double wri;
49976 : double wiim1;
49977 : double wii;
49978 : double ulp;
49979 :
49980 0 : *info = 0;
49981 :
49982 0 : *info = 0;
49983 0 : dat1 = 0.75;
49984 0 : dat2 = -0.4375;
49985 :
49986 : /*
49987 : * Quick return if possible
49988 : */
49989 0 : if( n==0 )
49990 : {
49991 0 : return;
49992 : }
49993 0 : if( ilo==ihi )
49994 : {
49995 0 : wr->ptr.p_double[ilo] = h->ptr.pp_double[ilo][ilo];
49996 0 : wi->ptr.p_double[ilo] = (double)(0);
49997 0 : return;
49998 : }
49999 :
50000 : /*
50001 : * ==== clear out the trash ====
50002 : */
50003 0 : for(j=ilo; j<=ihi-3; j++)
50004 : {
50005 0 : h->ptr.pp_double[j+2][j] = (double)(0);
50006 0 : h->ptr.pp_double[j+3][j] = (double)(0);
50007 : }
50008 0 : if( ilo<=ihi-2 )
50009 : {
50010 0 : h->ptr.pp_double[ihi][ihi-2] = (double)(0);
50011 : }
50012 0 : nh = ihi-ilo+1;
50013 0 : nz = ihiz-iloz+1;
50014 :
50015 : /*
50016 : * Set machine-dependent constants for the stopping criterion.
50017 : */
50018 0 : safmin = ae_minrealnumber;
50019 0 : ulp = ae_machineepsilon;
50020 0 : smlnum = safmin*(nh/ulp);
50021 :
50022 : /*
50023 : * I1 and I2 are the indices of the first row and last column of H
50024 : * to which transformations must be applied. If eigenvalues only are
50025 : * being computed, I1 and I2 are set inside the main loop.
50026 : *
50027 : * Setting them to large negative value helps to debug possible errors
50028 : * due to uninitialized variables; also it helps to avoid compiler
50029 : * warnings.
50030 : */
50031 0 : i1 = -99999;
50032 0 : i2 = -99999;
50033 0 : if( wantt )
50034 : {
50035 0 : i1 = 1;
50036 0 : i2 = n;
50037 : }
50038 :
50039 : /*
50040 : * ITMAX is the total number of QR iterations allowed.
50041 : */
50042 0 : itmax = 30*ae_maxint(10, nh, _state);
50043 :
50044 : /*
50045 : * The main loop begins here. I is the loop index and decreases from
50046 : * IHI to ILO in steps of 1 or 2. Each iteration of the loop works
50047 : * with the active submatrix in rows and columns L to I.
50048 : * Eigenvalues I+1 to IHI have already converged. Either L = ILO or
50049 : * H(L,L-1) is negligible so that the matrix splits.
50050 : */
50051 0 : i = ihi;
50052 : for(;;)
50053 : {
50054 0 : l = ilo;
50055 0 : if( i<ilo )
50056 : {
50057 0 : return;
50058 : }
50059 :
50060 : /*
50061 : * Perform QR iterations on rows and columns ILO to I until a
50062 : * submatrix of order 1 or 2 splits off at the bottom because a
50063 : * subdiagonal element has become negligible.
50064 : */
50065 0 : failflag = ae_true;
50066 0 : for(its=0; its<=itmax; its++)
50067 : {
50068 :
50069 : /*
50070 : * Look for a single small subdiagonal element.
50071 : */
50072 0 : for(k=i; k>=l+1; k--)
50073 : {
50074 0 : if( ae_fp_less_eq(ae_fabs(h->ptr.pp_double[k][k-1], _state),smlnum) )
50075 : {
50076 0 : break;
50077 : }
50078 0 : tst = ae_fabs(h->ptr.pp_double[k-1][k-1], _state)+ae_fabs(h->ptr.pp_double[k][k], _state);
50079 0 : if( ae_fp_eq(tst,(double)(0)) )
50080 : {
50081 0 : if( k-2>=ilo )
50082 : {
50083 0 : tst = tst+ae_fabs(h->ptr.pp_double[k-1][k-2], _state);
50084 : }
50085 0 : if( k+1<=ihi )
50086 : {
50087 0 : tst = tst+ae_fabs(h->ptr.pp_double[k+1][k], _state);
50088 : }
50089 : }
50090 :
50091 : /*
50092 : * ==== The following is a conservative small subdiagonal
50093 : * . deflation criterion due to Ahues & Tisseur (LAWN 122,
50094 : * . 1997). It has better mathematical foundation and
50095 : * . improves accuracy in some cases. ====
50096 : */
50097 0 : if( ae_fp_less_eq(ae_fabs(h->ptr.pp_double[k][k-1], _state),ulp*tst) )
50098 : {
50099 0 : ab = ae_maxreal(ae_fabs(h->ptr.pp_double[k][k-1], _state), ae_fabs(h->ptr.pp_double[k-1][k], _state), _state);
50100 0 : ba = ae_minreal(ae_fabs(h->ptr.pp_double[k][k-1], _state), ae_fabs(h->ptr.pp_double[k-1][k], _state), _state);
50101 0 : aa = ae_maxreal(ae_fabs(h->ptr.pp_double[k][k], _state), ae_fabs(h->ptr.pp_double[k-1][k-1]-h->ptr.pp_double[k][k], _state), _state);
50102 0 : bb = ae_minreal(ae_fabs(h->ptr.pp_double[k][k], _state), ae_fabs(h->ptr.pp_double[k-1][k-1]-h->ptr.pp_double[k][k], _state), _state);
50103 0 : s = aa+ab;
50104 0 : if( ae_fp_less_eq(ba*(ab/s),ae_maxreal(smlnum, ulp*(bb*(aa/s)), _state)) )
50105 : {
50106 0 : break;
50107 : }
50108 : }
50109 : }
50110 0 : l = k;
50111 0 : if( l>ilo )
50112 : {
50113 :
50114 : /*
50115 : * H(L,L-1) is negligible
50116 : */
50117 0 : h->ptr.pp_double[l][l-1] = (double)(0);
50118 : }
50119 :
50120 : /*
50121 : * Exit from loop if a submatrix of order 1 or 2 has split off.
50122 : */
50123 0 : if( l>=i-1 )
50124 : {
50125 0 : failflag = ae_false;
50126 0 : break;
50127 : }
50128 :
50129 : /*
50130 : * Now the active submatrix is in rows and columns L to I. If
50131 : * eigenvalues only are being computed, only the active submatrix
50132 : * need be transformed.
50133 : */
50134 0 : if( !wantt )
50135 : {
50136 0 : i1 = l;
50137 0 : i2 = i;
50138 : }
50139 :
50140 : /*
50141 : * Shifts
50142 : */
50143 0 : if( its==10 )
50144 : {
50145 :
50146 : /*
50147 : * Exceptional shift.
50148 : */
50149 0 : s = ae_fabs(h->ptr.pp_double[l+1][l], _state)+ae_fabs(h->ptr.pp_double[l+2][l+1], _state);
50150 0 : h11 = dat1*s+h->ptr.pp_double[l][l];
50151 0 : h12 = dat2*s;
50152 0 : h21 = s;
50153 0 : h22 = h11;
50154 : }
50155 : else
50156 : {
50157 0 : if( its==20 )
50158 : {
50159 :
50160 : /*
50161 : * Exceptional shift.
50162 : */
50163 0 : s = ae_fabs(h->ptr.pp_double[i][i-1], _state)+ae_fabs(h->ptr.pp_double[i-1][i-2], _state);
50164 0 : h11 = dat1*s+h->ptr.pp_double[i][i];
50165 0 : h12 = dat2*s;
50166 0 : h21 = s;
50167 0 : h22 = h11;
50168 : }
50169 : else
50170 : {
50171 :
50172 : /*
50173 : * Prepare to use Francis' double shift
50174 : * (i.e. 2nd degree generalized Rayleigh quotient)
50175 : */
50176 0 : h11 = h->ptr.pp_double[i-1][i-1];
50177 0 : h21 = h->ptr.pp_double[i][i-1];
50178 0 : h12 = h->ptr.pp_double[i-1][i];
50179 0 : h22 = h->ptr.pp_double[i][i];
50180 : }
50181 : }
50182 0 : s = ae_fabs(h11, _state)+ae_fabs(h12, _state)+ae_fabs(h21, _state)+ae_fabs(h22, _state);
50183 0 : if( ae_fp_eq(s,(double)(0)) )
50184 : {
50185 0 : rt1r = (double)(0);
50186 0 : rt1i = (double)(0);
50187 0 : rt2r = (double)(0);
50188 0 : rt2i = (double)(0);
50189 : }
50190 : else
50191 : {
50192 0 : h11 = h11/s;
50193 0 : h21 = h21/s;
50194 0 : h12 = h12/s;
50195 0 : h22 = h22/s;
50196 0 : tr = (h11+h22)/2;
50197 0 : det = (h11-tr)*(h22-tr)-h12*h21;
50198 0 : rtdisc = ae_sqrt(ae_fabs(det, _state), _state);
50199 0 : if( ae_fp_greater_eq(det,(double)(0)) )
50200 : {
50201 :
50202 : /*
50203 : * ==== complex conjugate shifts ====
50204 : */
50205 0 : rt1r = tr*s;
50206 0 : rt2r = rt1r;
50207 0 : rt1i = rtdisc*s;
50208 0 : rt2i = -rt1i;
50209 : }
50210 : else
50211 : {
50212 :
50213 : /*
50214 : * ==== real shifts (use only one of them) ====
50215 : */
50216 0 : rt1r = tr+rtdisc;
50217 0 : rt2r = tr-rtdisc;
50218 0 : if( ae_fp_less_eq(ae_fabs(rt1r-h22, _state),ae_fabs(rt2r-h22, _state)) )
50219 : {
50220 0 : rt1r = rt1r*s;
50221 0 : rt2r = rt1r;
50222 : }
50223 : else
50224 : {
50225 0 : rt2r = rt2r*s;
50226 0 : rt1r = rt2r;
50227 : }
50228 0 : rt1i = (double)(0);
50229 0 : rt2i = (double)(0);
50230 : }
50231 : }
50232 :
50233 : /*
50234 : * Look for two consecutive small subdiagonal elements.
50235 : */
50236 0 : for(m=i-2; m>=l; m--)
50237 : {
50238 :
50239 : /*
50240 : * Determine the effect of starting the double-shift QR
50241 : * iteration at row M, and see if this would make H(M,M-1)
50242 : * negligible. (The following uses scaling to avoid
50243 : * overflows and most underflows.)
50244 : */
50245 0 : h21s = h->ptr.pp_double[m+1][m];
50246 0 : s = ae_fabs(h->ptr.pp_double[m][m]-rt2r, _state)+ae_fabs(rt2i, _state)+ae_fabs(h21s, _state);
50247 0 : h21s = h->ptr.pp_double[m+1][m]/s;
50248 0 : workv3->ptr.p_double[1] = h21s*h->ptr.pp_double[m][m+1]+(h->ptr.pp_double[m][m]-rt1r)*((h->ptr.pp_double[m][m]-rt2r)/s)-rt1i*(rt2i/s);
50249 0 : workv3->ptr.p_double[2] = h21s*(h->ptr.pp_double[m][m]+h->ptr.pp_double[m+1][m+1]-rt1r-rt2r);
50250 0 : workv3->ptr.p_double[3] = h21s*h->ptr.pp_double[m+2][m+1];
50251 0 : s = ae_fabs(workv3->ptr.p_double[1], _state)+ae_fabs(workv3->ptr.p_double[2], _state)+ae_fabs(workv3->ptr.p_double[3], _state);
50252 0 : workv3->ptr.p_double[1] = workv3->ptr.p_double[1]/s;
50253 0 : workv3->ptr.p_double[2] = workv3->ptr.p_double[2]/s;
50254 0 : workv3->ptr.p_double[3] = workv3->ptr.p_double[3]/s;
50255 0 : if( m==l )
50256 : {
50257 0 : break;
50258 : }
50259 0 : if( ae_fp_less_eq(ae_fabs(h->ptr.pp_double[m][m-1], _state)*(ae_fabs(workv3->ptr.p_double[2], _state)+ae_fabs(workv3->ptr.p_double[3], _state)),ulp*ae_fabs(workv3->ptr.p_double[1], _state)*(ae_fabs(h->ptr.pp_double[m-1][m-1], _state)+ae_fabs(h->ptr.pp_double[m][m], _state)+ae_fabs(h->ptr.pp_double[m+1][m+1], _state))) )
50260 : {
50261 0 : break;
50262 : }
50263 : }
50264 :
50265 : /*
50266 : * Double-shift QR step
50267 : */
50268 0 : for(k=m; k<=i-1; k++)
50269 : {
50270 :
50271 : /*
50272 : * The first iteration of this loop determines a reflection G
50273 : * from the vector V and applies it from left and right to H,
50274 : * thus creating a nonzero bulge below the subdiagonal.
50275 : *
50276 : * Each subsequent iteration determines a reflection G to
50277 : * restore the Hessenberg form in the (K-1)th column, and thus
50278 : * chases the bulge one step toward the bottom of the active
50279 : * submatrix. NR is the order of G.
50280 : */
50281 0 : nr = ae_minint(3, i-k+1, _state);
50282 0 : if( k>m )
50283 : {
50284 0 : for(p1=1; p1<=nr; p1++)
50285 : {
50286 0 : workv3->ptr.p_double[p1] = h->ptr.pp_double[k+p1-1][k-1];
50287 : }
50288 : }
50289 0 : generatereflection(workv3, nr, &t1, _state);
50290 0 : if( k>m )
50291 : {
50292 0 : h->ptr.pp_double[k][k-1] = workv3->ptr.p_double[1];
50293 0 : h->ptr.pp_double[k+1][k-1] = (double)(0);
50294 0 : if( k<i-1 )
50295 : {
50296 0 : h->ptr.pp_double[k+2][k-1] = (double)(0);
50297 : }
50298 : }
50299 : else
50300 : {
50301 0 : if( m>l )
50302 : {
50303 :
50304 : /*
50305 : * ==== Use the following instead of
50306 : * H( K, K-1 ) = -H( K, K-1 ) to
50307 : * avoid a bug when v(2) and v(3)
50308 : * underflow. ====
50309 : */
50310 0 : h->ptr.pp_double[k][k-1] = h->ptr.pp_double[k][k-1]*(1-t1);
50311 : }
50312 : }
50313 0 : v2 = workv3->ptr.p_double[2];
50314 0 : t2 = t1*v2;
50315 0 : if( nr==3 )
50316 : {
50317 0 : v3 = workv3->ptr.p_double[3];
50318 0 : t3 = t1*v3;
50319 :
50320 : /*
50321 : * Apply G from the left to transform the rows of the matrix
50322 : * in columns K to I2.
50323 : */
50324 0 : for(j=k; j<=i2; j++)
50325 : {
50326 0 : sum = h->ptr.pp_double[k][j]+v2*h->ptr.pp_double[k+1][j]+v3*h->ptr.pp_double[k+2][j];
50327 0 : h->ptr.pp_double[k][j] = h->ptr.pp_double[k][j]-sum*t1;
50328 0 : h->ptr.pp_double[k+1][j] = h->ptr.pp_double[k+1][j]-sum*t2;
50329 0 : h->ptr.pp_double[k+2][j] = h->ptr.pp_double[k+2][j]-sum*t3;
50330 : }
50331 :
50332 : /*
50333 : * Apply G from the right to transform the columns of the
50334 : * matrix in rows I1 to min(K+3,I).
50335 : */
50336 0 : for(j=i1; j<=ae_minint(k+3, i, _state); j++)
50337 : {
50338 0 : sum = h->ptr.pp_double[j][k]+v2*h->ptr.pp_double[j][k+1]+v3*h->ptr.pp_double[j][k+2];
50339 0 : h->ptr.pp_double[j][k] = h->ptr.pp_double[j][k]-sum*t1;
50340 0 : h->ptr.pp_double[j][k+1] = h->ptr.pp_double[j][k+1]-sum*t2;
50341 0 : h->ptr.pp_double[j][k+2] = h->ptr.pp_double[j][k+2]-sum*t3;
50342 : }
50343 0 : if( wantz )
50344 : {
50345 :
50346 : /*
50347 : * Accumulate transformations in the matrix Z
50348 : */
50349 0 : for(j=iloz; j<=ihiz; j++)
50350 : {
50351 0 : sum = z->ptr.pp_double[j][k]+v2*z->ptr.pp_double[j][k+1]+v3*z->ptr.pp_double[j][k+2];
50352 0 : z->ptr.pp_double[j][k] = z->ptr.pp_double[j][k]-sum*t1;
50353 0 : z->ptr.pp_double[j][k+1] = z->ptr.pp_double[j][k+1]-sum*t2;
50354 0 : z->ptr.pp_double[j][k+2] = z->ptr.pp_double[j][k+2]-sum*t3;
50355 : }
50356 : }
50357 : }
50358 : else
50359 : {
50360 0 : if( nr==2 )
50361 : {
50362 :
50363 : /*
50364 : * Apply G from the left to transform the rows of the matrix
50365 : * in columns K to I2.
50366 : */
50367 0 : for(j=k; j<=i2; j++)
50368 : {
50369 0 : sum = h->ptr.pp_double[k][j]+v2*h->ptr.pp_double[k+1][j];
50370 0 : h->ptr.pp_double[k][j] = h->ptr.pp_double[k][j]-sum*t1;
50371 0 : h->ptr.pp_double[k+1][j] = h->ptr.pp_double[k+1][j]-sum*t2;
50372 : }
50373 :
50374 : /*
50375 : * Apply G from the right to transform the columns of the
50376 : * matrix in rows I1 to min(K+3,I).
50377 : */
50378 0 : for(j=i1; j<=i; j++)
50379 : {
50380 0 : sum = h->ptr.pp_double[j][k]+v2*h->ptr.pp_double[j][k+1];
50381 0 : h->ptr.pp_double[j][k] = h->ptr.pp_double[j][k]-sum*t1;
50382 0 : h->ptr.pp_double[j][k+1] = h->ptr.pp_double[j][k+1]-sum*t2;
50383 : }
50384 0 : if( wantz )
50385 : {
50386 :
50387 : /*
50388 : * Accumulate transformations in the matrix Z
50389 : */
50390 0 : for(j=iloz; j<=ihiz; j++)
50391 : {
50392 0 : sum = z->ptr.pp_double[j][k]+v2*z->ptr.pp_double[j][k+1];
50393 0 : z->ptr.pp_double[j][k] = z->ptr.pp_double[j][k]-sum*t1;
50394 0 : z->ptr.pp_double[j][k+1] = z->ptr.pp_double[j][k+1]-sum*t2;
50395 : }
50396 : }
50397 : }
50398 : }
50399 : }
50400 : }
50401 :
50402 : /*
50403 : * Failure to converge in remaining number of iterations
50404 : */
50405 0 : if( failflag )
50406 : {
50407 0 : *info = i;
50408 0 : return;
50409 : }
50410 :
50411 : /*
50412 : * Convergence
50413 : */
50414 0 : if( l==i )
50415 : {
50416 :
50417 : /*
50418 : * H(I,I-1) is negligible: one eigenvalue has converged.
50419 : */
50420 0 : wr->ptr.p_double[i] = h->ptr.pp_double[i][i];
50421 0 : wi->ptr.p_double[i] = (double)(0);
50422 : }
50423 : else
50424 : {
50425 0 : if( l==i-1 )
50426 : {
50427 :
50428 : /*
50429 : * H(I-1,I-2) is negligible: a pair of eigenvalues have converged.
50430 : *
50431 : * Transform the 2-by-2 submatrix to standard Schur form,
50432 : * and compute and store the eigenvalues.
50433 : */
50434 0 : him1im1 = h->ptr.pp_double[i-1][i-1];
50435 0 : him1i = h->ptr.pp_double[i-1][i];
50436 0 : hiim1 = h->ptr.pp_double[i][i-1];
50437 0 : hii = h->ptr.pp_double[i][i];
50438 0 : hsschur_aux2x2schur(&him1im1, &him1i, &hiim1, &hii, &wrim1, &wiim1, &wri, &wii, &cs, &sn, _state);
50439 0 : wr->ptr.p_double[i-1] = wrim1;
50440 0 : wi->ptr.p_double[i-1] = wiim1;
50441 0 : wr->ptr.p_double[i] = wri;
50442 0 : wi->ptr.p_double[i] = wii;
50443 0 : h->ptr.pp_double[i-1][i-1] = him1im1;
50444 0 : h->ptr.pp_double[i-1][i] = him1i;
50445 0 : h->ptr.pp_double[i][i-1] = hiim1;
50446 0 : h->ptr.pp_double[i][i] = hii;
50447 0 : if( wantt )
50448 : {
50449 :
50450 : /*
50451 : * Apply the transformation to the rest of H.
50452 : */
50453 0 : if( i2>i )
50454 : {
50455 0 : workc1->ptr.p_double[1] = cs;
50456 0 : works1->ptr.p_double[1] = sn;
50457 0 : applyrotationsfromtheleft(ae_true, i-1, i, i+1, i2, workc1, works1, h, work, _state);
50458 : }
50459 0 : workc1->ptr.p_double[1] = cs;
50460 0 : works1->ptr.p_double[1] = sn;
50461 0 : applyrotationsfromtheright(ae_true, i1, i-2, i-1, i, workc1, works1, h, work, _state);
50462 : }
50463 0 : if( wantz )
50464 : {
50465 :
50466 : /*
50467 : * Apply the transformation to Z.
50468 : */
50469 0 : workc1->ptr.p_double[1] = cs;
50470 0 : works1->ptr.p_double[1] = sn;
50471 0 : applyrotationsfromtheright(ae_true, iloz, iloz+nz-1, i-1, i, workc1, works1, z, work, _state);
50472 : }
50473 : }
50474 : }
50475 :
50476 : /*
50477 : * return to start of the main loop with new value of I.
50478 : */
50479 0 : i = l-1;
50480 : }
50481 : }
50482 :
50483 :
50484 0 : static void hsschur_aux2x2schur(double* a,
50485 : double* b,
50486 : double* c,
50487 : double* d,
50488 : double* rt1r,
50489 : double* rt1i,
50490 : double* rt2r,
50491 : double* rt2i,
50492 : double* cs,
50493 : double* sn,
50494 : ae_state *_state)
50495 : {
50496 : double multpl;
50497 : double aa;
50498 : double bb;
50499 : double bcmax;
50500 : double bcmis;
50501 : double cc;
50502 : double cs1;
50503 : double dd;
50504 : double eps;
50505 : double p;
50506 : double sab;
50507 : double sac;
50508 : double scl;
50509 : double sigma;
50510 : double sn1;
50511 : double tau;
50512 : double temp;
50513 : double z;
50514 :
50515 0 : *rt1r = 0;
50516 0 : *rt1i = 0;
50517 0 : *rt2r = 0;
50518 0 : *rt2i = 0;
50519 0 : *cs = 0;
50520 0 : *sn = 0;
50521 :
50522 0 : multpl = 4.0;
50523 0 : eps = ae_machineepsilon;
50524 0 : if( ae_fp_eq(*c,(double)(0)) )
50525 : {
50526 0 : *cs = (double)(1);
50527 0 : *sn = (double)(0);
50528 : }
50529 : else
50530 : {
50531 0 : if( ae_fp_eq(*b,(double)(0)) )
50532 : {
50533 :
50534 : /*
50535 : * Swap rows and columns
50536 : */
50537 0 : *cs = (double)(0);
50538 0 : *sn = (double)(1);
50539 0 : temp = *d;
50540 0 : *d = *a;
50541 0 : *a = temp;
50542 0 : *b = -*c;
50543 0 : *c = (double)(0);
50544 : }
50545 : else
50546 : {
50547 0 : if( ae_fp_eq(*a-(*d),(double)(0))&&hsschur_extschursigntoone(*b, _state)!=hsschur_extschursigntoone(*c, _state) )
50548 : {
50549 0 : *cs = (double)(1);
50550 0 : *sn = (double)(0);
50551 : }
50552 : else
50553 : {
50554 0 : temp = *a-(*d);
50555 0 : p = 0.5*temp;
50556 0 : bcmax = ae_maxreal(ae_fabs(*b, _state), ae_fabs(*c, _state), _state);
50557 0 : bcmis = ae_minreal(ae_fabs(*b, _state), ae_fabs(*c, _state), _state)*hsschur_extschursigntoone(*b, _state)*hsschur_extschursigntoone(*c, _state);
50558 0 : scl = ae_maxreal(ae_fabs(p, _state), bcmax, _state);
50559 0 : z = p/scl*p+bcmax/scl*bcmis;
50560 :
50561 : /*
50562 : * If Z is of the order of the machine accuracy, postpone the
50563 : * decision on the nature of eigenvalues
50564 : */
50565 0 : if( ae_fp_greater_eq(z,multpl*eps) )
50566 : {
50567 :
50568 : /*
50569 : * Real eigenvalues. Compute A and D.
50570 : */
50571 0 : z = p+hsschur_extschursign(ae_sqrt(scl, _state)*ae_sqrt(z, _state), p, _state);
50572 0 : *a = *d+z;
50573 0 : *d = *d-bcmax/z*bcmis;
50574 :
50575 : /*
50576 : * Compute B and the rotation matrix
50577 : */
50578 0 : tau = pythag2(*c, z, _state);
50579 0 : *cs = z/tau;
50580 0 : *sn = *c/tau;
50581 0 : *b = *b-(*c);
50582 0 : *c = (double)(0);
50583 : }
50584 : else
50585 : {
50586 :
50587 : /*
50588 : * Complex eigenvalues, or real (almost) equal eigenvalues.
50589 : * Make diagonal elements equal.
50590 : */
50591 0 : sigma = *b+(*c);
50592 0 : tau = pythag2(sigma, temp, _state);
50593 0 : *cs = ae_sqrt(0.5*(1+ae_fabs(sigma, _state)/tau), _state);
50594 0 : *sn = -p/(tau*(*cs))*hsschur_extschursign((double)(1), sigma, _state);
50595 :
50596 : /*
50597 : * Compute [ AA BB ] = [ A B ] [ CS -SN ]
50598 : * [ CC DD ] [ C D ] [ SN CS ]
50599 : */
50600 0 : aa = *a*(*cs)+*b*(*sn);
50601 0 : bb = -*a*(*sn)+*b*(*cs);
50602 0 : cc = *c*(*cs)+*d*(*sn);
50603 0 : dd = -*c*(*sn)+*d*(*cs);
50604 :
50605 : /*
50606 : * Compute [ A B ] = [ CS SN ] [ AA BB ]
50607 : * [ C D ] [-SN CS ] [ CC DD ]
50608 : */
50609 0 : *a = aa*(*cs)+cc*(*sn);
50610 0 : *b = bb*(*cs)+dd*(*sn);
50611 0 : *c = -aa*(*sn)+cc*(*cs);
50612 0 : *d = -bb*(*sn)+dd*(*cs);
50613 0 : temp = 0.5*(*a+(*d));
50614 0 : *a = temp;
50615 0 : *d = temp;
50616 0 : if( ae_fp_neq(*c,(double)(0)) )
50617 : {
50618 0 : if( ae_fp_neq(*b,(double)(0)) )
50619 : {
50620 0 : if( hsschur_extschursigntoone(*b, _state)==hsschur_extschursigntoone(*c, _state) )
50621 : {
50622 :
50623 : /*
50624 : * Real eigenvalues: reduce to upper triangular form
50625 : */
50626 0 : sab = ae_sqrt(ae_fabs(*b, _state), _state);
50627 0 : sac = ae_sqrt(ae_fabs(*c, _state), _state);
50628 0 : p = hsschur_extschursign(sab*sac, *c, _state);
50629 0 : tau = 1/ae_sqrt(ae_fabs(*b+(*c), _state), _state);
50630 0 : *a = temp+p;
50631 0 : *d = temp-p;
50632 0 : *b = *b-(*c);
50633 0 : *c = (double)(0);
50634 0 : cs1 = sab*tau;
50635 0 : sn1 = sac*tau;
50636 0 : temp = *cs*cs1-*sn*sn1;
50637 0 : *sn = *cs*sn1+*sn*cs1;
50638 0 : *cs = temp;
50639 : }
50640 : }
50641 : else
50642 : {
50643 0 : *b = -*c;
50644 0 : *c = (double)(0);
50645 0 : temp = *cs;
50646 0 : *cs = -*sn;
50647 0 : *sn = temp;
50648 : }
50649 : }
50650 : }
50651 : }
50652 : }
50653 : }
50654 :
50655 : /*
50656 : * Store eigenvalues in (RT1R,RT1I) and (RT2R,RT2I).
50657 : */
50658 0 : *rt1r = *a;
50659 0 : *rt2r = *d;
50660 0 : if( ae_fp_eq(*c,(double)(0)) )
50661 : {
50662 0 : *rt1i = (double)(0);
50663 0 : *rt2i = (double)(0);
50664 : }
50665 : else
50666 : {
50667 0 : *rt1i = ae_sqrt(ae_fabs(*b, _state), _state)*ae_sqrt(ae_fabs(*c, _state), _state);
50668 0 : *rt2i = -*rt1i;
50669 : }
50670 0 : }
50671 :
50672 :
50673 0 : static double hsschur_extschursign(double a, double b, ae_state *_state)
50674 : {
50675 : double result;
50676 :
50677 :
50678 0 : if( ae_fp_greater_eq(b,(double)(0)) )
50679 : {
50680 0 : result = ae_fabs(a, _state);
50681 : }
50682 : else
50683 : {
50684 0 : result = -ae_fabs(a, _state);
50685 : }
50686 0 : return result;
50687 : }
50688 :
50689 :
50690 0 : static ae_int_t hsschur_extschursigntoone(double b, ae_state *_state)
50691 : {
50692 : ae_int_t result;
50693 :
50694 :
50695 0 : if( ae_fp_greater_eq(b,(double)(0)) )
50696 : {
50697 0 : result = 1;
50698 : }
50699 : else
50700 : {
50701 0 : result = -1;
50702 : }
50703 0 : return result;
50704 : }
50705 :
50706 :
50707 : #endif
50708 : #if defined(AE_COMPILE_EVD) || !defined(AE_PARTIAL_BUILD)
50709 :
50710 :
50711 : /*************************************************************************
50712 : This function initializes subspace iteration solver. This solver is used
50713 : to solve symmetric real eigenproblems where just a few (top K) eigenvalues
50714 : and corresponding eigenvectors is required.
50715 :
50716 : This solver can be significantly faster than complete EVD decomposition
50717 : in the following case:
50718 : * when only just a small fraction of top eigenpairs of dense matrix is
50719 : required. When K approaches N, this solver is slower than complete dense
50720 : EVD
50721 : * when problem matrix is sparse (and/or is not known explicitly, i.e. only
50722 : matrix-matrix product can be performed)
50723 :
50724 : USAGE (explicit dense/sparse matrix):
50725 : 1. User initializes algorithm state with eigsubspacecreate() call
50726 : 2. [optional] User tunes solver parameters by calling eigsubspacesetcond()
50727 : or other functions
50728 : 3. User calls eigsubspacesolvedense() or eigsubspacesolvesparse() methods,
50729 : which take algorithm state and 2D array or alglib.sparsematrix object.
50730 :
50731 : USAGE (out-of-core mode):
50732 : 1. User initializes algorithm state with eigsubspacecreate() call
50733 : 2. [optional] User tunes solver parameters by calling eigsubspacesetcond()
50734 : or other functions
50735 : 3. User activates out-of-core mode of the solver and repeatedly calls
50736 : communication functions in a loop like below:
50737 : > alglib.eigsubspaceoocstart(state)
50738 : > while alglib.eigsubspaceooccontinue(state) do
50739 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
50740 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
50741 : > [calculate Y=A*X, with X=R^NxM]
50742 : > alglib.eigsubspaceoocsendresult(state, in Y)
50743 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
50744 :
50745 : INPUT PARAMETERS:
50746 : N - problem dimensionality, N>0
50747 : K - number of top eigenvector to calculate, 0<K<=N.
50748 :
50749 : OUTPUT PARAMETERS:
50750 : State - structure which stores algorithm state
50751 :
50752 : NOTE: if you solve many similar EVD problems you may find it useful to
50753 : reuse previous subspace as warm-start point for new EVD problem. It
50754 : can be done with eigsubspacesetwarmstart() function.
50755 :
50756 : -- ALGLIB --
50757 : Copyright 16.01.2017 by Bochkanov Sergey
50758 : *************************************************************************/
50759 0 : void eigsubspacecreate(ae_int_t n,
50760 : ae_int_t k,
50761 : eigsubspacestate* state,
50762 : ae_state *_state)
50763 : {
50764 :
50765 0 : _eigsubspacestate_clear(state);
50766 :
50767 0 : ae_assert(n>0, "EigSubspaceCreate: N<=0", _state);
50768 0 : ae_assert(k>0, "EigSubspaceCreate: K<=0", _state);
50769 0 : ae_assert(k<=n, "EigSubspaceCreate: K>N", _state);
50770 0 : eigsubspacecreatebuf(n, k, state, _state);
50771 0 : }
50772 :
50773 :
50774 : /*************************************************************************
50775 : Buffered version of constructor which aims to reuse previously allocated
50776 : memory as much as possible.
50777 :
50778 : -- ALGLIB --
50779 : Copyright 16.01.2017 by Bochkanov Sergey
50780 : *************************************************************************/
50781 0 : void eigsubspacecreatebuf(ae_int_t n,
50782 : ae_int_t k,
50783 : eigsubspacestate* state,
50784 : ae_state *_state)
50785 : {
50786 :
50787 :
50788 0 : ae_assert(n>0, "EigSubspaceCreate: N<=0", _state);
50789 0 : ae_assert(k>0, "EigSubspaceCreate: K<=0", _state);
50790 0 : ae_assert(k<=n, "EigSubspaceCreate: K>N", _state);
50791 :
50792 : /*
50793 : * Initialize algorithm parameters
50794 : */
50795 0 : state->running = ae_false;
50796 0 : state->n = n;
50797 0 : state->k = k;
50798 0 : state->nwork = ae_minint(ae_maxint(2*k, 8, _state), n, _state);
50799 0 : state->eigenvectorsneeded = 1;
50800 0 : state->usewarmstart = ae_false;
50801 0 : state->firstcall = ae_true;
50802 0 : eigsubspacesetcond(state, 0.0, 0, _state);
50803 :
50804 : /*
50805 : * Allocate temporaries
50806 : */
50807 0 : rmatrixsetlengthatleast(&state->x, state->n, state->nwork, _state);
50808 0 : rmatrixsetlengthatleast(&state->ax, state->n, state->nwork, _state);
50809 0 : }
50810 :
50811 :
50812 : /*************************************************************************
50813 : This function sets stopping critera for the solver:
50814 : * error in eigenvector/value allowed by solver
50815 : * maximum number of iterations to perform
50816 :
50817 : INPUT PARAMETERS:
50818 : State - solver structure
50819 : Eps - eps>=0, with non-zero value used to tell solver that
50820 : it can stop after all eigenvalues converged with
50821 : error roughly proportional to eps*MAX(LAMBDA_MAX),
50822 : where LAMBDA_MAX is a maximum eigenvalue.
50823 : Zero value means that no check for precision is
50824 : performed.
50825 : MaxIts - maxits>=0, with non-zero value used to tell solver
50826 : that it can stop after maxits steps (no matter how
50827 : precise current estimate is)
50828 :
50829 : NOTE: passing eps=0 and maxits=0 results in automatic selection of
50830 : moderate eps as stopping criteria (1.0E-6 in current implementation,
50831 : but it may change without notice).
50832 :
50833 : NOTE: very small values of eps are possible (say, 1.0E-12), although the
50834 : larger problem you solve (N and/or K), the harder it is to find
50835 : precise eigenvectors because rounding errors tend to accumulate.
50836 :
50837 : NOTE: passing non-zero eps results in some performance penalty, roughly
50838 : equal to 2N*(2K)^2 FLOPs per iteration. These additional computations
50839 : are required in order to estimate current error in eigenvalues via
50840 : Rayleigh-Ritz process.
50841 : Most of this additional time is spent in construction of ~2Kx2K
50842 : symmetric subproblem whose eigenvalues are checked with exact
50843 : eigensolver.
50844 : This additional time is negligible if you search for eigenvalues of
50845 : the large dense matrix, but may become noticeable on highly sparse
50846 : EVD problems, where cost of matrix-matrix product is low.
50847 : If you set eps to exactly zero, Rayleigh-Ritz phase is completely
50848 : turned off.
50849 :
50850 : -- ALGLIB --
50851 : Copyright 16.01.2017 by Bochkanov Sergey
50852 : *************************************************************************/
50853 0 : void eigsubspacesetcond(eigsubspacestate* state,
50854 : double eps,
50855 : ae_int_t maxits,
50856 : ae_state *_state)
50857 : {
50858 :
50859 :
50860 0 : ae_assert(!state->running, "EigSubspaceSetCond: solver is already running", _state);
50861 0 : ae_assert(ae_isfinite(eps, _state)&&ae_fp_greater_eq(eps,(double)(0)), "EigSubspaceSetCond: Eps<0 or NAN/INF", _state);
50862 0 : ae_assert(maxits>=0, "EigSubspaceSetCond: MaxIts<0", _state);
50863 0 : if( ae_fp_eq(eps,(double)(0))&&maxits==0 )
50864 : {
50865 0 : eps = 1.0E-6;
50866 : }
50867 0 : state->eps = eps;
50868 0 : state->maxits = maxits;
50869 0 : }
50870 :
50871 :
50872 : /*************************************************************************
50873 : This function sets warm-start mode of the solver: next call to the solver
50874 : will reuse previous subspace as warm-start point. It can significantly
50875 : speed-up convergence when you solve many similar eigenproblems.
50876 :
50877 : INPUT PARAMETERS:
50878 : State - solver structure
50879 : UseWarmStart- either True or False
50880 :
50881 : -- ALGLIB --
50882 : Copyright 12.11.2017 by Bochkanov Sergey
50883 : *************************************************************************/
50884 0 : void eigsubspacesetwarmstart(eigsubspacestate* state,
50885 : ae_bool usewarmstart,
50886 : ae_state *_state)
50887 : {
50888 :
50889 :
50890 0 : ae_assert(!state->running, "EigSubspaceSetWarmStart: solver is already running", _state);
50891 0 : state->usewarmstart = usewarmstart;
50892 0 : }
50893 :
50894 :
50895 : /*************************************************************************
50896 : This function initiates out-of-core mode of subspace eigensolver. It
50897 : should be used in conjunction with other out-of-core-related functions of
50898 : this subspackage in a loop like below:
50899 :
50900 : > alglib.eigsubspaceoocstart(state)
50901 : > while alglib.eigsubspaceooccontinue(state) do
50902 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
50903 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
50904 : > [calculate Y=A*X, with X=R^NxM]
50905 : > alglib.eigsubspaceoocsendresult(state, in Y)
50906 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
50907 :
50908 : INPUT PARAMETERS:
50909 : State - solver object
50910 : MType - matrix type:
50911 : * 0 for real symmetric matrix (solver assumes that
50912 : matrix being processed is symmetric; symmetric
50913 : direct eigensolver is used for smaller subproblems
50914 : arising during solution of larger "full" task)
50915 : Future versions of ALGLIB may introduce support for
50916 : other matrix types; for now, only symmetric
50917 : eigenproblems are supported.
50918 :
50919 :
50920 : -- ALGLIB --
50921 : Copyright 16.01.2017 by Bochkanov Sergey
50922 : *************************************************************************/
50923 0 : void eigsubspaceoocstart(eigsubspacestate* state,
50924 : ae_int_t mtype,
50925 : ae_state *_state)
50926 : {
50927 :
50928 :
50929 0 : ae_assert(!state->running, "EigSubspaceStart: solver is already running", _state);
50930 0 : ae_assert(mtype==0, "EigSubspaceStart: incorrect mtype parameter", _state);
50931 0 : ae_vector_set_length(&state->rstate.ia, 7+1, _state);
50932 0 : ae_vector_set_length(&state->rstate.ra, 1+1, _state);
50933 0 : state->rstate.stage = -1;
50934 0 : evd_clearrfields(state, _state);
50935 0 : state->running = ae_true;
50936 0 : state->matrixtype = mtype;
50937 0 : }
50938 :
50939 :
50940 : /*************************************************************************
50941 : This function performs subspace iteration in the out-of-core mode. It
50942 : should be used in conjunction with other out-of-core-related functions of
50943 : this subspackage in a loop like below:
50944 :
50945 : > alglib.eigsubspaceoocstart(state)
50946 : > while alglib.eigsubspaceooccontinue(state) do
50947 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
50948 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
50949 : > [calculate Y=A*X, with X=R^NxM]
50950 : > alglib.eigsubspaceoocsendresult(state, in Y)
50951 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
50952 :
50953 :
50954 : -- ALGLIB --
50955 : Copyright 16.01.2017 by Bochkanov Sergey
50956 : *************************************************************************/
50957 0 : ae_bool eigsubspaceooccontinue(eigsubspacestate* state, ae_state *_state)
50958 : {
50959 : ae_bool result;
50960 :
50961 :
50962 0 : ae_assert(state->running, "EigSubspaceContinue: solver is not running", _state);
50963 0 : result = eigsubspaceiteration(state, _state);
50964 0 : state->running = result;
50965 0 : return result;
50966 : }
50967 :
50968 :
50969 : /*************************************************************************
50970 : This function is used to retrieve information about out-of-core request
50971 : sent by solver to user code: request type (current version of the solver
50972 : sends only requests for matrix-matrix products) and request size (size of
50973 : the matrices being multiplied).
50974 :
50975 : This function returns just request metrics; in order to get contents of
50976 : the matrices being multiplied, use eigsubspaceoocgetrequestdata().
50977 :
50978 : It should be used in conjunction with other out-of-core-related functions
50979 : of this subspackage in a loop like below:
50980 :
50981 : > alglib.eigsubspaceoocstart(state)
50982 : > while alglib.eigsubspaceooccontinue(state) do
50983 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
50984 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
50985 : > [calculate Y=A*X, with X=R^NxM]
50986 : > alglib.eigsubspaceoocsendresult(state, in Y)
50987 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
50988 :
50989 : INPUT PARAMETERS:
50990 : State - solver running in out-of-core mode
50991 :
50992 : OUTPUT PARAMETERS:
50993 : RequestType - type of the request to process:
50994 : * 0 - for matrix-matrix product A*X, with A being
50995 : NxN matrix whose eigenvalues/vectors are needed,
50996 : and X being NxREQUESTSIZE one which is returned
50997 : by the eigsubspaceoocgetrequestdata().
50998 : RequestSize - size of the X matrix (number of columns), usually
50999 : it is several times larger than number of vectors
51000 : K requested by user.
51001 :
51002 :
51003 : -- ALGLIB --
51004 : Copyright 16.01.2017 by Bochkanov Sergey
51005 : *************************************************************************/
51006 0 : void eigsubspaceoocgetrequestinfo(eigsubspacestate* state,
51007 : ae_int_t* requesttype,
51008 : ae_int_t* requestsize,
51009 : ae_state *_state)
51010 : {
51011 :
51012 0 : *requesttype = 0;
51013 0 : *requestsize = 0;
51014 :
51015 0 : ae_assert(state->running, "EigSubspaceOOCGetRequestInfo: solver is not running", _state);
51016 0 : *requesttype = state->requesttype;
51017 0 : *requestsize = state->requestsize;
51018 0 : }
51019 :
51020 :
51021 : /*************************************************************************
51022 : This function is used to retrieve information about out-of-core request
51023 : sent by solver to user code: matrix X (array[N,RequestSize) which have to
51024 : be multiplied by out-of-core matrix A in a product A*X.
51025 :
51026 : This function returns just request data; in order to get size of the data
51027 : prior to processing requestm, use eigsubspaceoocgetrequestinfo().
51028 :
51029 : It should be used in conjunction with other out-of-core-related functions
51030 : of this subspackage in a loop like below:
51031 :
51032 : > alglib.eigsubspaceoocstart(state)
51033 : > while alglib.eigsubspaceooccontinue(state) do
51034 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
51035 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
51036 : > [calculate Y=A*X, with X=R^NxM]
51037 : > alglib.eigsubspaceoocsendresult(state, in Y)
51038 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
51039 :
51040 : INPUT PARAMETERS:
51041 : State - solver running in out-of-core mode
51042 : X - possibly preallocated storage; reallocated if
51043 : needed, left unchanged, if large enough to store
51044 : request data.
51045 :
51046 : OUTPUT PARAMETERS:
51047 : X - array[N,RequestSize] or larger, leading rectangle
51048 : is filled with dense matrix X.
51049 :
51050 :
51051 : -- ALGLIB --
51052 : Copyright 16.01.2017 by Bochkanov Sergey
51053 : *************************************************************************/
51054 0 : void eigsubspaceoocgetrequestdata(eigsubspacestate* state,
51055 : /* Real */ ae_matrix* x,
51056 : ae_state *_state)
51057 : {
51058 : ae_int_t i;
51059 : ae_int_t j;
51060 :
51061 :
51062 0 : ae_assert(state->running, "EigSubspaceOOCGetRequestInfo: solver is not running", _state);
51063 0 : rmatrixsetlengthatleast(x, state->n, state->requestsize, _state);
51064 0 : for(i=0; i<=state->n-1; i++)
51065 : {
51066 0 : for(j=0; j<=state->requestsize-1; j++)
51067 : {
51068 0 : x->ptr.pp_double[i][j] = state->x.ptr.pp_double[i][j];
51069 : }
51070 : }
51071 0 : }
51072 :
51073 :
51074 : /*************************************************************************
51075 : This function is used to send user reply to out-of-core request sent by
51076 : solver. Usually it is product A*X for returned by solver matrix X.
51077 :
51078 : It should be used in conjunction with other out-of-core-related functions
51079 : of this subspackage in a loop like below:
51080 :
51081 : > alglib.eigsubspaceoocstart(state)
51082 : > while alglib.eigsubspaceooccontinue(state) do
51083 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
51084 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
51085 : > [calculate Y=A*X, with X=R^NxM]
51086 : > alglib.eigsubspaceoocsendresult(state, in Y)
51087 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
51088 :
51089 : INPUT PARAMETERS:
51090 : State - solver running in out-of-core mode
51091 : AX - array[N,RequestSize] or larger, leading rectangle
51092 : is filled with product A*X.
51093 :
51094 :
51095 : -- ALGLIB --
51096 : Copyright 16.01.2017 by Bochkanov Sergey
51097 : *************************************************************************/
51098 0 : void eigsubspaceoocsendresult(eigsubspacestate* state,
51099 : /* Real */ ae_matrix* ax,
51100 : ae_state *_state)
51101 : {
51102 : ae_int_t i;
51103 : ae_int_t j;
51104 :
51105 :
51106 0 : ae_assert(state->running, "EigSubspaceOOCGetRequestInfo: solver is not running", _state);
51107 0 : for(i=0; i<=state->n-1; i++)
51108 : {
51109 0 : for(j=0; j<=state->requestsize-1; j++)
51110 : {
51111 0 : state->ax.ptr.pp_double[i][j] = ax->ptr.pp_double[i][j];
51112 : }
51113 : }
51114 0 : }
51115 :
51116 :
51117 : /*************************************************************************
51118 : This function finalizes out-of-core mode of subspace eigensolver. It
51119 : should be used in conjunction with other out-of-core-related functions of
51120 : this subspackage in a loop like below:
51121 :
51122 : > alglib.eigsubspaceoocstart(state)
51123 : > while alglib.eigsubspaceooccontinue(state) do
51124 : > alglib.eigsubspaceoocgetrequestinfo(state, out RequestType, out M)
51125 : > alglib.eigsubspaceoocgetrequestdata(state, out X)
51126 : > [calculate Y=A*X, with X=R^NxM]
51127 : > alglib.eigsubspaceoocsendresult(state, in Y)
51128 : > alglib.eigsubspaceoocstop(state, out W, out Z, out Report)
51129 :
51130 : INPUT PARAMETERS:
51131 : State - solver state
51132 :
51133 : OUTPUT PARAMETERS:
51134 : W - array[K], depending on solver settings:
51135 : * top K eigenvalues ordered by descending - if
51136 : eigenvectors are returned in Z
51137 : * zeros - if invariant subspace is returned in Z
51138 : Z - array[N,K], depending on solver settings either:
51139 : * matrix of eigenvectors found
51140 : * orthogonal basis of K-dimensional invariant subspace
51141 : Rep - report with additional parameters
51142 :
51143 : -- ALGLIB --
51144 : Copyright 16.01.2017 by Bochkanov Sergey
51145 : *************************************************************************/
51146 0 : void eigsubspaceoocstop(eigsubspacestate* state,
51147 : /* Real */ ae_vector* w,
51148 : /* Real */ ae_matrix* z,
51149 : eigsubspacereport* rep,
51150 : ae_state *_state)
51151 : {
51152 : ae_int_t n;
51153 : ae_int_t k;
51154 : ae_int_t i;
51155 : ae_int_t j;
51156 :
51157 0 : ae_vector_clear(w);
51158 0 : ae_matrix_clear(z);
51159 0 : _eigsubspacereport_clear(rep);
51160 :
51161 0 : ae_assert(!state->running, "EigSubspaceStop: solver is still running", _state);
51162 0 : n = state->n;
51163 0 : k = state->k;
51164 0 : ae_vector_set_length(w, k, _state);
51165 0 : ae_matrix_set_length(z, n, k, _state);
51166 0 : for(i=0; i<=k-1; i++)
51167 : {
51168 0 : w->ptr.p_double[i] = state->rw.ptr.p_double[i];
51169 : }
51170 0 : for(i=0; i<=n-1; i++)
51171 : {
51172 0 : for(j=0; j<=k-1; j++)
51173 : {
51174 0 : z->ptr.pp_double[i][j] = state->rq.ptr.pp_double[i][j];
51175 : }
51176 : }
51177 0 : rep->iterationscount = state->repiterationscount;
51178 0 : }
51179 :
51180 :
51181 : /*************************************************************************
51182 : This function runs eigensolver for dense NxN symmetric matrix A, given by
51183 : upper or lower triangle.
51184 :
51185 : This function can not process nonsymmetric matrices.
51186 :
51187 : ! COMMERCIAL EDITION OF ALGLIB:
51188 : !
51189 : ! Commercial Edition of ALGLIB includes following important improvements
51190 : ! of this function:
51191 : ! * high-performance native backend with same C# interface (C# version)
51192 : ! * multithreading support (C++ and C# versions)
51193 : ! * hardware vendor (Intel) implementations of linear algebra primitives
51194 : ! (C++ and C# versions, x86/x64 platform)
51195 : !
51196 : ! We recommend you to read 'Working with commercial version' section of
51197 : ! ALGLIB Reference Manual in order to find out how to use performance-
51198 : ! related features provided by commercial edition of ALGLIB.
51199 :
51200 : INPUT PARAMETERS:
51201 : State - solver state
51202 : A - array[N,N], symmetric NxN matrix given by one of its
51203 : triangles
51204 : IsUpper - whether upper or lower triangle of A is given (the
51205 : other one is not referenced at all).
51206 :
51207 : OUTPUT PARAMETERS:
51208 : W - array[K], top K eigenvalues ordered by descending
51209 : of their absolute values
51210 : Z - array[N,K], matrix of eigenvectors found
51211 : Rep - report with additional parameters
51212 :
51213 : NOTE: internally this function allocates a copy of NxN dense A. You should
51214 : take it into account when working with very large matrices occupying
51215 : almost all RAM.
51216 :
51217 : -- ALGLIB --
51218 : Copyright 16.01.2017 by Bochkanov Sergey
51219 : *************************************************************************/
51220 0 : void eigsubspacesolvedenses(eigsubspacestate* state,
51221 : /* Real */ ae_matrix* a,
51222 : ae_bool isupper,
51223 : /* Real */ ae_vector* w,
51224 : /* Real */ ae_matrix* z,
51225 : eigsubspacereport* rep,
51226 : ae_state *_state)
51227 : {
51228 : ae_frame _frame_block;
51229 : ae_int_t n;
51230 : ae_int_t m;
51231 : ae_int_t i;
51232 : ae_int_t j;
51233 : ae_int_t k;
51234 : double v;
51235 : ae_matrix acopy;
51236 :
51237 0 : ae_frame_make(_state, &_frame_block);
51238 0 : memset(&acopy, 0, sizeof(acopy));
51239 0 : ae_vector_clear(w);
51240 0 : ae_matrix_clear(z);
51241 0 : _eigsubspacereport_clear(rep);
51242 0 : ae_matrix_init(&acopy, 0, 0, DT_REAL, _state, ae_true);
51243 :
51244 0 : ae_assert(!state->running, "EigSubspaceSolveDenseS: solver is still running", _state);
51245 0 : n = state->n;
51246 :
51247 : /*
51248 : * Allocate copy of A, copy one triangle to another
51249 : */
51250 0 : ae_matrix_set_length(&acopy, n, n, _state);
51251 0 : for(i=0; i<=n-1; i++)
51252 : {
51253 0 : for(j=i; j<=n-1; j++)
51254 : {
51255 0 : if( isupper )
51256 : {
51257 0 : v = a->ptr.pp_double[i][j];
51258 : }
51259 : else
51260 : {
51261 0 : v = a->ptr.pp_double[j][i];
51262 : }
51263 0 : acopy.ptr.pp_double[i][j] = v;
51264 0 : acopy.ptr.pp_double[j][i] = v;
51265 : }
51266 : }
51267 :
51268 : /*
51269 : * Start iterations
51270 : */
51271 0 : state->matrixtype = 0;
51272 0 : ae_vector_set_length(&state->rstate.ia, 7+1, _state);
51273 0 : ae_vector_set_length(&state->rstate.ra, 1+1, _state);
51274 0 : state->rstate.stage = -1;
51275 0 : evd_clearrfields(state, _state);
51276 0 : while(eigsubspaceiteration(state, _state))
51277 : {
51278 :
51279 : /*
51280 : * Calculate A*X with RMatrixGEMM
51281 : */
51282 0 : ae_assert(state->requesttype==0, "EigSubspaceSolveDense: integrity check failed", _state);
51283 0 : ae_assert(state->requestsize>0, "EigSubspaceSolveDense: integrity check failed", _state);
51284 0 : m = state->requestsize;
51285 0 : rmatrixgemm(n, m, n, 1.0, &acopy, 0, 0, 0, &state->x, 0, 0, 0, 0.0, &state->ax, 0, 0, _state);
51286 : }
51287 0 : k = state->k;
51288 0 : ae_vector_set_length(w, k, _state);
51289 0 : ae_matrix_set_length(z, n, k, _state);
51290 0 : for(i=0; i<=k-1; i++)
51291 : {
51292 0 : w->ptr.p_double[i] = state->rw.ptr.p_double[i];
51293 : }
51294 0 : for(i=0; i<=n-1; i++)
51295 : {
51296 0 : for(j=0; j<=k-1; j++)
51297 : {
51298 0 : z->ptr.pp_double[i][j] = state->rq.ptr.pp_double[i][j];
51299 : }
51300 : }
51301 0 : rep->iterationscount = state->repiterationscount;
51302 0 : ae_frame_leave(_state);
51303 0 : }
51304 :
51305 :
51306 : /*************************************************************************
51307 : This function runs eigensolver for dense NxN symmetric matrix A, given by
51308 : upper or lower triangle.
51309 :
51310 : This function can not process nonsymmetric matrices.
51311 :
51312 : INPUT PARAMETERS:
51313 : State - solver state
51314 : A - NxN symmetric matrix given by one of its triangles
51315 : IsUpper - whether upper or lower triangle of A is given (the
51316 : other one is not referenced at all).
51317 :
51318 : OUTPUT PARAMETERS:
51319 : W - array[K], top K eigenvalues ordered by descending
51320 : of their absolute values
51321 : Z - array[N,K], matrix of eigenvectors found
51322 : Rep - report with additional parameters
51323 :
51324 : -- ALGLIB --
51325 : Copyright 16.01.2017 by Bochkanov Sergey
51326 : *************************************************************************/
51327 0 : void eigsubspacesolvesparses(eigsubspacestate* state,
51328 : sparsematrix* a,
51329 : ae_bool isupper,
51330 : /* Real */ ae_vector* w,
51331 : /* Real */ ae_matrix* z,
51332 : eigsubspacereport* rep,
51333 : ae_state *_state)
51334 : {
51335 : ae_int_t n;
51336 : ae_int_t i;
51337 : ae_int_t j;
51338 : ae_int_t k;
51339 :
51340 0 : ae_vector_clear(w);
51341 0 : ae_matrix_clear(z);
51342 0 : _eigsubspacereport_clear(rep);
51343 :
51344 0 : ae_assert(!state->running, "EigSubspaceSolveSparseS: solver is still running", _state);
51345 0 : n = state->n;
51346 0 : state->matrixtype = 0;
51347 0 : ae_vector_set_length(&state->rstate.ia, 7+1, _state);
51348 0 : ae_vector_set_length(&state->rstate.ra, 1+1, _state);
51349 0 : state->rstate.stage = -1;
51350 0 : evd_clearrfields(state, _state);
51351 0 : while(eigsubspaceiteration(state, _state))
51352 : {
51353 0 : ae_assert(state->requesttype==0, "EigSubspaceSolveDense: integrity check failed", _state);
51354 0 : ae_assert(state->requestsize>0, "EigSubspaceSolveDense: integrity check failed", _state);
51355 0 : sparsesmm(a, isupper, &state->x, state->requestsize, &state->ax, _state);
51356 : }
51357 0 : k = state->k;
51358 0 : ae_vector_set_length(w, k, _state);
51359 0 : ae_matrix_set_length(z, n, k, _state);
51360 0 : for(i=0; i<=k-1; i++)
51361 : {
51362 0 : w->ptr.p_double[i] = state->rw.ptr.p_double[i];
51363 : }
51364 0 : for(i=0; i<=n-1; i++)
51365 : {
51366 0 : for(j=0; j<=k-1; j++)
51367 : {
51368 0 : z->ptr.pp_double[i][j] = state->rq.ptr.pp_double[i][j];
51369 : }
51370 : }
51371 0 : rep->iterationscount = state->repiterationscount;
51372 0 : }
51373 :
51374 :
51375 : /*************************************************************************
51376 : Internal r-comm function.
51377 :
51378 : -- ALGLIB --
51379 : Copyright 16.01.2017 by Bochkanov Sergey
51380 : *************************************************************************/
51381 0 : ae_bool eigsubspaceiteration(eigsubspacestate* state, ae_state *_state)
51382 : {
51383 : ae_int_t n;
51384 : ae_int_t nwork;
51385 : ae_int_t k;
51386 : ae_int_t cnt;
51387 : ae_int_t i;
51388 : ae_int_t i1;
51389 : ae_int_t j;
51390 : double vv;
51391 : double v;
51392 : ae_int_t convcnt;
51393 : ae_bool result;
51394 :
51395 :
51396 :
51397 : /*
51398 : * Reverse communication preparations
51399 : * I know it looks ugly, but it works the same way
51400 : * anywhere from C++ to Python.
51401 : *
51402 : * This code initializes locals by:
51403 : * * random values determined during code
51404 : * generation - on first subroutine call
51405 : * * values from previous call - on subsequent calls
51406 : */
51407 0 : if( state->rstate.stage>=0 )
51408 : {
51409 0 : n = state->rstate.ia.ptr.p_int[0];
51410 0 : nwork = state->rstate.ia.ptr.p_int[1];
51411 0 : k = state->rstate.ia.ptr.p_int[2];
51412 0 : cnt = state->rstate.ia.ptr.p_int[3];
51413 0 : i = state->rstate.ia.ptr.p_int[4];
51414 0 : i1 = state->rstate.ia.ptr.p_int[5];
51415 0 : j = state->rstate.ia.ptr.p_int[6];
51416 0 : convcnt = state->rstate.ia.ptr.p_int[7];
51417 0 : vv = state->rstate.ra.ptr.p_double[0];
51418 0 : v = state->rstate.ra.ptr.p_double[1];
51419 : }
51420 : else
51421 : {
51422 0 : n = 359;
51423 0 : nwork = -58;
51424 0 : k = -919;
51425 0 : cnt = -909;
51426 0 : i = 81;
51427 0 : i1 = 255;
51428 0 : j = 74;
51429 0 : convcnt = -788;
51430 0 : vv = 809;
51431 0 : v = 205;
51432 : }
51433 0 : if( state->rstate.stage==0 )
51434 : {
51435 0 : goto lbl_0;
51436 : }
51437 :
51438 : /*
51439 : * Routine body
51440 : */
51441 0 : n = state->n;
51442 0 : k = state->k;
51443 0 : nwork = state->nwork;
51444 :
51445 : /*
51446 : * Initialize RNG. Deterministic initialization (with fixed
51447 : * seed) is required because we need deterministic behavior
51448 : * of the entire solver.
51449 : */
51450 0 : hqrndseed(453, 463664, &state->rs, _state);
51451 :
51452 : /*
51453 : * Prepare iteration
51454 : * Initialize QNew with random orthogonal matrix (or reuse its previous value).
51455 : */
51456 0 : state->repiterationscount = 0;
51457 0 : rmatrixsetlengthatleast(&state->qcur, nwork, n, _state);
51458 0 : rmatrixsetlengthatleast(&state->qnew, nwork, n, _state);
51459 0 : rmatrixsetlengthatleast(&state->znew, nwork, n, _state);
51460 0 : rvectorsetlengthatleast(&state->wcur, nwork, _state);
51461 0 : rvectorsetlengthatleast(&state->wprev, nwork, _state);
51462 0 : rvectorsetlengthatleast(&state->wrank, nwork, _state);
51463 0 : rmatrixsetlengthatleast(&state->x, n, nwork, _state);
51464 0 : rmatrixsetlengthatleast(&state->ax, n, nwork, _state);
51465 0 : rmatrixsetlengthatleast(&state->rq, n, k, _state);
51466 0 : rvectorsetlengthatleast(&state->rw, k, _state);
51467 0 : rmatrixsetlengthatleast(&state->rz, nwork, k, _state);
51468 0 : rmatrixsetlengthatleast(&state->r, nwork, nwork, _state);
51469 0 : for(i=0; i<=nwork-1; i++)
51470 : {
51471 0 : state->wprev.ptr.p_double[i] = -1.0;
51472 : }
51473 0 : if( !state->usewarmstart||state->firstcall )
51474 : {
51475 :
51476 : /*
51477 : * Use Q0 (either no warm start request, or warm start was
51478 : * requested by user - but it is first call).
51479 : *
51480 : */
51481 0 : if( state->firstcall )
51482 : {
51483 :
51484 : /*
51485 : * First call, generate Q0
51486 : */
51487 0 : for(i=0; i<=nwork-1; i++)
51488 : {
51489 0 : for(j=0; j<=n-1; j++)
51490 : {
51491 0 : state->znew.ptr.pp_double[i][j] = hqrnduniformr(&state->rs, _state)-0.5;
51492 : }
51493 : }
51494 0 : rmatrixlq(&state->znew, nwork, n, &state->tau, _state);
51495 0 : rmatrixlqunpackq(&state->znew, nwork, n, &state->tau, nwork, &state->q0, _state);
51496 0 : state->firstcall = ae_false;
51497 : }
51498 0 : rmatrixcopy(nwork, n, &state->q0, 0, 0, &state->qnew, 0, 0, _state);
51499 : }
51500 :
51501 : /*
51502 : * Start iteration
51503 : */
51504 0 : state->repiterationscount = 0;
51505 0 : convcnt = 0;
51506 0 : lbl_1:
51507 0 : if( !((state->maxits==0||state->repiterationscount<state->maxits)&&convcnt<evd_stepswithintol) )
51508 : {
51509 0 : goto lbl_2;
51510 : }
51511 :
51512 : /*
51513 : * Update QCur := QNew
51514 : *
51515 : * Calculate A*Q'
51516 : */
51517 0 : rmatrixcopy(nwork, n, &state->qnew, 0, 0, &state->qcur, 0, 0, _state);
51518 0 : rmatrixtranspose(nwork, n, &state->qcur, 0, 0, &state->x, 0, 0, _state);
51519 0 : evd_clearrfields(state, _state);
51520 0 : state->requesttype = 0;
51521 0 : state->requestsize = nwork;
51522 0 : state->rstate.stage = 0;
51523 0 : goto lbl_rcomm;
51524 0 : lbl_0:
51525 :
51526 : /*
51527 : * Perform Rayleigh-Ritz step to estimate convergence of diagonal eigenvalues
51528 : */
51529 0 : if( ae_fp_greater(state->eps,(double)(0)) )
51530 : {
51531 0 : ae_assert(state->matrixtype==0, "integrity check failed", _state);
51532 0 : rmatrixsetlengthatleast(&state->r, nwork, nwork, _state);
51533 0 : rmatrixgemm(nwork, nwork, n, 1.0, &state->qcur, 0, 0, 0, &state->ax, 0, 0, 0, 0.0, &state->r, 0, 0, _state);
51534 0 : if( !smatrixevd(&state->r, nwork, 0, ae_true, &state->wcur, &state->dummy, _state) )
51535 : {
51536 0 : ae_assert(ae_false, "EigSubspace: direct eigensolver failed to converge", _state);
51537 : }
51538 0 : for(j=0; j<=nwork-1; j++)
51539 : {
51540 0 : state->wrank.ptr.p_double[j] = ae_fabs(state->wcur.ptr.p_double[j], _state);
51541 : }
51542 0 : rankxuntied(&state->wrank, nwork, &state->buf, _state);
51543 0 : v = (double)(0);
51544 0 : vv = (double)(0);
51545 0 : for(j=0; j<=nwork-1; j++)
51546 : {
51547 0 : if( ae_fp_greater_eq(state->wrank.ptr.p_double[j],(double)(nwork-k)) )
51548 : {
51549 0 : v = ae_maxreal(v, ae_fabs(state->wcur.ptr.p_double[j]-state->wprev.ptr.p_double[j], _state), _state);
51550 0 : vv = ae_maxreal(vv, ae_fabs(state->wcur.ptr.p_double[j], _state), _state);
51551 : }
51552 : }
51553 0 : if( ae_fp_eq(vv,(double)(0)) )
51554 : {
51555 0 : vv = (double)(1);
51556 : }
51557 0 : if( ae_fp_less_eq(v,state->eps*vv) )
51558 : {
51559 0 : inc(&convcnt, _state);
51560 : }
51561 : else
51562 : {
51563 0 : convcnt = 0;
51564 : }
51565 0 : for(j=0; j<=nwork-1; j++)
51566 : {
51567 0 : state->wprev.ptr.p_double[j] = state->wcur.ptr.p_double[j];
51568 : }
51569 : }
51570 :
51571 : /*
51572 : * QR renormalization and update of QNew
51573 : */
51574 0 : rmatrixtranspose(n, nwork, &state->ax, 0, 0, &state->znew, 0, 0, _state);
51575 0 : rmatrixlq(&state->znew, nwork, n, &state->tau, _state);
51576 0 : rmatrixlqunpackq(&state->znew, nwork, n, &state->tau, nwork, &state->qnew, _state);
51577 :
51578 : /*
51579 : * Update iteration index
51580 : */
51581 0 : state->repiterationscount = state->repiterationscount+1;
51582 0 : goto lbl_1;
51583 0 : lbl_2:
51584 :
51585 : /*
51586 : * Perform Rayleigh-Ritz step: find true eigenpairs in NWork-dimensional
51587 : * subspace.
51588 : */
51589 0 : ae_assert(state->matrixtype==0, "integrity check failed", _state);
51590 0 : ae_assert(state->eigenvectorsneeded==1, "Assertion failed", _state);
51591 0 : rmatrixgemm(nwork, nwork, n, 1.0, &state->qcur, 0, 0, 0, &state->ax, 0, 0, 0, 0.0, &state->r, 0, 0, _state);
51592 0 : if( !smatrixevd(&state->r, nwork, 1, ae_true, &state->tw, &state->tz, _state) )
51593 : {
51594 0 : ae_assert(ae_false, "EigSubspace: direct eigensolver failed to converge", _state);
51595 : }
51596 :
51597 : /*
51598 : * Reorder eigenpairs according to their absolute magnitude, select
51599 : * K top ones. This reordering algorithm is very inefficient and has
51600 : * O(NWork*K) running time, but it is still faster than other parts
51601 : * of the solver, so we may use it.
51602 : *
51603 : * Then, we transform RZ to RQ (full N-dimensional representation).
51604 : * After this part is done, RW and RQ contain solution.
51605 : */
51606 0 : for(j=0; j<=nwork-1; j++)
51607 : {
51608 0 : state->wrank.ptr.p_double[j] = ae_fabs(state->tw.ptr.p_double[j], _state);
51609 : }
51610 0 : rankxuntied(&state->wrank, nwork, &state->buf, _state);
51611 0 : cnt = 0;
51612 0 : for(i=nwork-1; i>=nwork-k; i--)
51613 : {
51614 0 : for(i1=0; i1<=nwork-1; i1++)
51615 : {
51616 0 : if( ae_fp_eq(state->wrank.ptr.p_double[i1],(double)(i)) )
51617 : {
51618 0 : ae_assert(cnt<k, "EigSubspace: integrity check failed", _state);
51619 0 : state->rw.ptr.p_double[cnt] = state->tw.ptr.p_double[i1];
51620 0 : for(j=0; j<=nwork-1; j++)
51621 : {
51622 0 : state->rz.ptr.pp_double[j][cnt] = state->tz.ptr.pp_double[j][i1];
51623 : }
51624 0 : cnt = cnt+1;
51625 : }
51626 : }
51627 : }
51628 0 : ae_assert(cnt==k, "EigSubspace: integrity check failed", _state);
51629 0 : rmatrixgemm(n, k, nwork, 1.0, &state->qcur, 0, 0, 1, &state->rz, 0, 0, 0, 0.0, &state->rq, 0, 0, _state);
51630 0 : result = ae_false;
51631 0 : return result;
51632 :
51633 : /*
51634 : * Saving state
51635 : */
51636 0 : lbl_rcomm:
51637 0 : result = ae_true;
51638 0 : state->rstate.ia.ptr.p_int[0] = n;
51639 0 : state->rstate.ia.ptr.p_int[1] = nwork;
51640 0 : state->rstate.ia.ptr.p_int[2] = k;
51641 0 : state->rstate.ia.ptr.p_int[3] = cnt;
51642 0 : state->rstate.ia.ptr.p_int[4] = i;
51643 0 : state->rstate.ia.ptr.p_int[5] = i1;
51644 0 : state->rstate.ia.ptr.p_int[6] = j;
51645 0 : state->rstate.ia.ptr.p_int[7] = convcnt;
51646 0 : state->rstate.ra.ptr.p_double[0] = vv;
51647 0 : state->rstate.ra.ptr.p_double[1] = v;
51648 0 : return result;
51649 : }
51650 :
51651 :
51652 : /*************************************************************************
51653 : Finding the eigenvalues and eigenvectors of a symmetric matrix
51654 :
51655 : The algorithm finds eigen pairs of a symmetric matrix by reducing it to
51656 : tridiagonal form and using the QL/QR algorithm.
51657 :
51658 : ! COMMERCIAL EDITION OF ALGLIB:
51659 : !
51660 : ! Commercial Edition of ALGLIB includes following important improvements
51661 : ! of this function:
51662 : ! * high-performance native backend with same C# interface (C# version)
51663 : ! * hardware vendor (Intel) implementations of linear algebra primitives
51664 : ! (C++ and C# versions, x86/x64 platform)
51665 : !
51666 : ! We recommend you to read 'Working with commercial version' section of
51667 : ! ALGLIB Reference Manual in order to find out how to use performance-
51668 : ! related features provided by commercial edition of ALGLIB.
51669 :
51670 : Input parameters:
51671 : A - symmetric matrix which is given by its upper or lower
51672 : triangular part.
51673 : Array whose indexes range within [0..N-1, 0..N-1].
51674 : N - size of matrix A.
51675 : ZNeeded - flag controlling whether the eigenvectors are needed or not.
51676 : If ZNeeded is equal to:
51677 : * 0, the eigenvectors are not returned;
51678 : * 1, the eigenvectors are returned.
51679 : IsUpper - storage format.
51680 :
51681 : Output parameters:
51682 : D - eigenvalues in ascending order.
51683 : Array whose index ranges within [0..N-1].
51684 : Z - if ZNeeded is equal to:
51685 : * 0, Z hasn't changed;
51686 : * 1, Z contains the eigenvectors.
51687 : Array whose indexes range within [0..N-1, 0..N-1].
51688 : The eigenvectors are stored in the matrix columns.
51689 :
51690 : Result:
51691 : True, if the algorithm has converged.
51692 : False, if the algorithm hasn't converged (rare case).
51693 :
51694 : -- ALGLIB --
51695 : Copyright 2005-2008 by Bochkanov Sergey
51696 : *************************************************************************/
51697 0 : ae_bool smatrixevd(/* Real */ ae_matrix* a,
51698 : ae_int_t n,
51699 : ae_int_t zneeded,
51700 : ae_bool isupper,
51701 : /* Real */ ae_vector* d,
51702 : /* Real */ ae_matrix* z,
51703 : ae_state *_state)
51704 : {
51705 : ae_frame _frame_block;
51706 : ae_matrix _a;
51707 : ae_vector tau;
51708 : ae_vector e;
51709 : ae_bool result;
51710 :
51711 0 : ae_frame_make(_state, &_frame_block);
51712 0 : memset(&_a, 0, sizeof(_a));
51713 0 : memset(&tau, 0, sizeof(tau));
51714 0 : memset(&e, 0, sizeof(e));
51715 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
51716 0 : a = &_a;
51717 0 : ae_vector_clear(d);
51718 0 : ae_matrix_clear(z);
51719 0 : ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
51720 0 : ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
51721 :
51722 0 : ae_assert(zneeded==0||zneeded==1, "SMatrixEVD: incorrect ZNeeded", _state);
51723 0 : smatrixtd(a, n, isupper, &tau, d, &e, _state);
51724 0 : if( zneeded==1 )
51725 : {
51726 0 : smatrixtdunpackq(a, n, isupper, &tau, z, _state);
51727 : }
51728 0 : result = smatrixtdevd(d, &e, n, zneeded, z, _state);
51729 0 : ae_frame_leave(_state);
51730 0 : return result;
51731 : }
51732 :
51733 :
51734 : /*************************************************************************
51735 : Subroutine for finding the eigenvalues (and eigenvectors) of a symmetric
51736 : matrix in a given half open interval (A, B] by using a bisection and
51737 : inverse iteration
51738 :
51739 : ! COMMERCIAL EDITION OF ALGLIB:
51740 : !
51741 : ! Commercial Edition of ALGLIB includes following important improvements
51742 : ! of this function:
51743 : ! * high-performance native backend with same C# interface (C# version)
51744 : ! * hardware vendor (Intel) implementations of linear algebra primitives
51745 : ! (C++ and C# versions, x86/x64 platform)
51746 : !
51747 : ! We recommend you to read 'Working with commercial version' section of
51748 : ! ALGLIB Reference Manual in order to find out how to use performance-
51749 : ! related features provided by commercial edition of ALGLIB.
51750 :
51751 : Input parameters:
51752 : A - symmetric matrix which is given by its upper or lower
51753 : triangular part. Array [0..N-1, 0..N-1].
51754 : N - size of matrix A.
51755 : ZNeeded - flag controlling whether the eigenvectors are needed or not.
51756 : If ZNeeded is equal to:
51757 : * 0, the eigenvectors are not returned;
51758 : * 1, the eigenvectors are returned.
51759 : IsUpperA - storage format of matrix A.
51760 : B1, B2 - half open interval (B1, B2] to search eigenvalues in.
51761 :
51762 : Output parameters:
51763 : M - number of eigenvalues found in a given half-interval (M>=0).
51764 : W - array of the eigenvalues found.
51765 : Array whose index ranges within [0..M-1].
51766 : Z - if ZNeeded is equal to:
51767 : * 0, Z hasn't changed;
51768 : * 1, Z contains eigenvectors.
51769 : Array whose indexes range within [0..N-1, 0..M-1].
51770 : The eigenvectors are stored in the matrix columns.
51771 :
51772 : Result:
51773 : True, if successful. M contains the number of eigenvalues in the given
51774 : half-interval (could be equal to 0), W contains the eigenvalues,
51775 : Z contains the eigenvectors (if needed).
51776 :
51777 : False, if the bisection method subroutine wasn't able to find the
51778 : eigenvalues in the given interval or if the inverse iteration subroutine
51779 : wasn't able to find all the corresponding eigenvectors.
51780 : In that case, the eigenvalues and eigenvectors are not returned,
51781 : M is equal to 0.
51782 :
51783 : -- ALGLIB --
51784 : Copyright 07.01.2006 by Bochkanov Sergey
51785 : *************************************************************************/
51786 0 : ae_bool smatrixevdr(/* Real */ ae_matrix* a,
51787 : ae_int_t n,
51788 : ae_int_t zneeded,
51789 : ae_bool isupper,
51790 : double b1,
51791 : double b2,
51792 : ae_int_t* m,
51793 : /* Real */ ae_vector* w,
51794 : /* Real */ ae_matrix* z,
51795 : ae_state *_state)
51796 : {
51797 : ae_frame _frame_block;
51798 : ae_matrix _a;
51799 : ae_vector tau;
51800 : ae_vector e;
51801 : ae_bool result;
51802 :
51803 0 : ae_frame_make(_state, &_frame_block);
51804 0 : memset(&_a, 0, sizeof(_a));
51805 0 : memset(&tau, 0, sizeof(tau));
51806 0 : memset(&e, 0, sizeof(e));
51807 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
51808 0 : a = &_a;
51809 0 : *m = 0;
51810 0 : ae_vector_clear(w);
51811 0 : ae_matrix_clear(z);
51812 0 : ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
51813 0 : ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
51814 :
51815 0 : ae_assert(zneeded==0||zneeded==1, "SMatrixTDEVDR: incorrect ZNeeded", _state);
51816 0 : smatrixtd(a, n, isupper, &tau, w, &e, _state);
51817 0 : if( zneeded==1 )
51818 : {
51819 0 : smatrixtdunpackq(a, n, isupper, &tau, z, _state);
51820 : }
51821 0 : result = smatrixtdevdr(w, &e, n, zneeded, b1, b2, m, z, _state);
51822 0 : ae_frame_leave(_state);
51823 0 : return result;
51824 : }
51825 :
51826 :
51827 : /*************************************************************************
51828 : Subroutine for finding the eigenvalues and eigenvectors of a symmetric
51829 : matrix with given indexes by using bisection and inverse iteration methods.
51830 :
51831 : Input parameters:
51832 : A - symmetric matrix which is given by its upper or lower
51833 : triangular part. Array whose indexes range within [0..N-1, 0..N-1].
51834 : N - size of matrix A.
51835 : ZNeeded - flag controlling whether the eigenvectors are needed or not.
51836 : If ZNeeded is equal to:
51837 : * 0, the eigenvectors are not returned;
51838 : * 1, the eigenvectors are returned.
51839 : IsUpperA - storage format of matrix A.
51840 : I1, I2 - index interval for searching (from I1 to I2).
51841 : 0 <= I1 <= I2 <= N-1.
51842 :
51843 : Output parameters:
51844 : W - array of the eigenvalues found.
51845 : Array whose index ranges within [0..I2-I1].
51846 : Z - if ZNeeded is equal to:
51847 : * 0, Z hasn't changed;
51848 : * 1, Z contains eigenvectors.
51849 : Array whose indexes range within [0..N-1, 0..I2-I1].
51850 : In that case, the eigenvectors are stored in the matrix columns.
51851 :
51852 : Result:
51853 : True, if successful. W contains the eigenvalues, Z contains the
51854 : eigenvectors (if needed).
51855 :
51856 : False, if the bisection method subroutine wasn't able to find the
51857 : eigenvalues in the given interval or if the inverse iteration subroutine
51858 : wasn't able to find all the corresponding eigenvectors.
51859 : In that case, the eigenvalues and eigenvectors are not returned.
51860 :
51861 : -- ALGLIB --
51862 : Copyright 07.01.2006 by Bochkanov Sergey
51863 : *************************************************************************/
51864 0 : ae_bool smatrixevdi(/* Real */ ae_matrix* a,
51865 : ae_int_t n,
51866 : ae_int_t zneeded,
51867 : ae_bool isupper,
51868 : ae_int_t i1,
51869 : ae_int_t i2,
51870 : /* Real */ ae_vector* w,
51871 : /* Real */ ae_matrix* z,
51872 : ae_state *_state)
51873 : {
51874 : ae_frame _frame_block;
51875 : ae_matrix _a;
51876 : ae_vector tau;
51877 : ae_vector e;
51878 : ae_bool result;
51879 :
51880 0 : ae_frame_make(_state, &_frame_block);
51881 0 : memset(&_a, 0, sizeof(_a));
51882 0 : memset(&tau, 0, sizeof(tau));
51883 0 : memset(&e, 0, sizeof(e));
51884 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
51885 0 : a = &_a;
51886 0 : ae_vector_clear(w);
51887 0 : ae_matrix_clear(z);
51888 0 : ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
51889 0 : ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
51890 :
51891 0 : ae_assert(zneeded==0||zneeded==1, "SMatrixEVDI: incorrect ZNeeded", _state);
51892 0 : smatrixtd(a, n, isupper, &tau, w, &e, _state);
51893 0 : if( zneeded==1 )
51894 : {
51895 0 : smatrixtdunpackq(a, n, isupper, &tau, z, _state);
51896 : }
51897 0 : result = smatrixtdevdi(w, &e, n, zneeded, i1, i2, z, _state);
51898 0 : ae_frame_leave(_state);
51899 0 : return result;
51900 : }
51901 :
51902 :
51903 : /*************************************************************************
51904 : Finding the eigenvalues and eigenvectors of a Hermitian matrix
51905 :
51906 : The algorithm finds eigen pairs of a Hermitian matrix by reducing it to
51907 : real tridiagonal form and using the QL/QR algorithm.
51908 :
51909 : ! COMMERCIAL EDITION OF ALGLIB:
51910 : !
51911 : ! Commercial Edition of ALGLIB includes following important improvements
51912 : ! of this function:
51913 : ! * high-performance native backend with same C# interface (C# version)
51914 : ! * hardware vendor (Intel) implementations of linear algebra primitives
51915 : ! (C++ and C# versions, x86/x64 platform)
51916 : !
51917 : ! We recommend you to read 'Working with commercial version' section of
51918 : ! ALGLIB Reference Manual in order to find out how to use performance-
51919 : ! related features provided by commercial edition of ALGLIB.
51920 :
51921 : Input parameters:
51922 : A - Hermitian matrix which is given by its upper or lower
51923 : triangular part.
51924 : Array whose indexes range within [0..N-1, 0..N-1].
51925 : N - size of matrix A.
51926 : IsUpper - storage format.
51927 : ZNeeded - flag controlling whether the eigenvectors are needed or
51928 : not. If ZNeeded is equal to:
51929 : * 0, the eigenvectors are not returned;
51930 : * 1, the eigenvectors are returned.
51931 :
51932 : Output parameters:
51933 : D - eigenvalues in ascending order.
51934 : Array whose index ranges within [0..N-1].
51935 : Z - if ZNeeded is equal to:
51936 : * 0, Z hasn't changed;
51937 : * 1, Z contains the eigenvectors.
51938 : Array whose indexes range within [0..N-1, 0..N-1].
51939 : The eigenvectors are stored in the matrix columns.
51940 :
51941 : Result:
51942 : True, if the algorithm has converged.
51943 : False, if the algorithm hasn't converged (rare case).
51944 :
51945 : Note:
51946 : eigenvectors of Hermitian matrix are defined up to multiplication by
51947 : a complex number L, such that |L|=1.
51948 :
51949 : -- ALGLIB --
51950 : Copyright 2005, 23 March 2007 by Bochkanov Sergey
51951 : *************************************************************************/
51952 0 : ae_bool hmatrixevd(/* Complex */ ae_matrix* a,
51953 : ae_int_t n,
51954 : ae_int_t zneeded,
51955 : ae_bool isupper,
51956 : /* Real */ ae_vector* d,
51957 : /* Complex */ ae_matrix* z,
51958 : ae_state *_state)
51959 : {
51960 : ae_frame _frame_block;
51961 : ae_matrix _a;
51962 : ae_vector tau;
51963 : ae_vector e;
51964 : ae_matrix t;
51965 : ae_matrix qz;
51966 : ae_matrix q;
51967 : ae_int_t i;
51968 : ae_int_t j;
51969 : ae_bool result;
51970 :
51971 0 : ae_frame_make(_state, &_frame_block);
51972 0 : memset(&_a, 0, sizeof(_a));
51973 0 : memset(&tau, 0, sizeof(tau));
51974 0 : memset(&e, 0, sizeof(e));
51975 0 : memset(&t, 0, sizeof(t));
51976 0 : memset(&qz, 0, sizeof(qz));
51977 0 : memset(&q, 0, sizeof(q));
51978 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
51979 0 : a = &_a;
51980 0 : ae_vector_clear(d);
51981 0 : ae_matrix_clear(z);
51982 0 : ae_vector_init(&tau, 0, DT_COMPLEX, _state, ae_true);
51983 0 : ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
51984 0 : ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true);
51985 0 : ae_matrix_init(&qz, 0, 0, DT_REAL, _state, ae_true);
51986 0 : ae_matrix_init(&q, 0, 0, DT_COMPLEX, _state, ae_true);
51987 :
51988 0 : ae_assert(zneeded==0||zneeded==1, "HermitianEVD: incorrect ZNeeded", _state);
51989 :
51990 : /*
51991 : * Reduce to tridiagonal form
51992 : */
51993 0 : hmatrixtd(a, n, isupper, &tau, d, &e, _state);
51994 0 : if( zneeded==1 )
51995 : {
51996 0 : hmatrixtdunpackq(a, n, isupper, &tau, &q, _state);
51997 0 : zneeded = 2;
51998 : }
51999 :
52000 : /*
52001 : * TDEVD
52002 : */
52003 0 : result = smatrixtdevd(d, &e, n, zneeded, &t, _state);
52004 :
52005 : /*
52006 : * Eigenvectors are needed
52007 : * Calculate Z = Q*T = Re(Q)*T + i*Im(Q)*T
52008 : */
52009 0 : if( result&&zneeded!=0 )
52010 : {
52011 0 : ae_matrix_set_length(z, n, n, _state);
52012 0 : ae_matrix_set_length(&qz, n, 2*n, _state);
52013 :
52014 : /*
52015 : * Calculate Re(Q)*T
52016 : */
52017 0 : for(i=0; i<=n-1; i++)
52018 : {
52019 0 : for(j=0; j<=n-1; j++)
52020 : {
52021 0 : qz.ptr.pp_double[i][j] = q.ptr.pp_complex[i][j].x;
52022 : }
52023 : }
52024 0 : rmatrixgemm(n, n, n, 1.0, &qz, 0, 0, 0, &t, 0, 0, 0, 0.0, &qz, 0, n, _state);
52025 0 : for(i=0; i<=n-1; i++)
52026 : {
52027 0 : for(j=0; j<=n-1; j++)
52028 : {
52029 0 : z->ptr.pp_complex[i][j].x = qz.ptr.pp_double[i][n+j];
52030 : }
52031 : }
52032 :
52033 : /*
52034 : * Calculate Im(Q)*T
52035 : */
52036 0 : for(i=0; i<=n-1; i++)
52037 : {
52038 0 : for(j=0; j<=n-1; j++)
52039 : {
52040 0 : qz.ptr.pp_double[i][j] = q.ptr.pp_complex[i][j].y;
52041 : }
52042 : }
52043 0 : rmatrixgemm(n, n, n, 1.0, &qz, 0, 0, 0, &t, 0, 0, 0, 0.0, &qz, 0, n, _state);
52044 0 : for(i=0; i<=n-1; i++)
52045 : {
52046 0 : for(j=0; j<=n-1; j++)
52047 : {
52048 0 : z->ptr.pp_complex[i][j].y = qz.ptr.pp_double[i][n+j];
52049 : }
52050 : }
52051 : }
52052 0 : ae_frame_leave(_state);
52053 0 : return result;
52054 : }
52055 :
52056 :
52057 : /*************************************************************************
52058 : Subroutine for finding the eigenvalues (and eigenvectors) of a Hermitian
52059 : matrix in a given half-interval (A, B] by using a bisection and inverse
52060 : iteration
52061 :
52062 : Input parameters:
52063 : A - Hermitian matrix which is given by its upper or lower
52064 : triangular part. Array whose indexes range within
52065 : [0..N-1, 0..N-1].
52066 : N - size of matrix A.
52067 : ZNeeded - flag controlling whether the eigenvectors are needed or
52068 : not. If ZNeeded is equal to:
52069 : * 0, the eigenvectors are not returned;
52070 : * 1, the eigenvectors are returned.
52071 : IsUpperA - storage format of matrix A.
52072 : B1, B2 - half-interval (B1, B2] to search eigenvalues in.
52073 :
52074 : Output parameters:
52075 : M - number of eigenvalues found in a given half-interval, M>=0
52076 : W - array of the eigenvalues found.
52077 : Array whose index ranges within [0..M-1].
52078 : Z - if ZNeeded is equal to:
52079 : * 0, Z hasn't changed;
52080 : * 1, Z contains eigenvectors.
52081 : Array whose indexes range within [0..N-1, 0..M-1].
52082 : The eigenvectors are stored in the matrix columns.
52083 :
52084 : Result:
52085 : True, if successful. M contains the number of eigenvalues in the given
52086 : half-interval (could be equal to 0), W contains the eigenvalues,
52087 : Z contains the eigenvectors (if needed).
52088 :
52089 : False, if the bisection method subroutine wasn't able to find the
52090 : eigenvalues in the given interval or if the inverse iteration
52091 : subroutine wasn't able to find all the corresponding eigenvectors.
52092 : In that case, the eigenvalues and eigenvectors are not returned, M is
52093 : equal to 0.
52094 :
52095 : Note:
52096 : eigen vectors of Hermitian matrix are defined up to multiplication by
52097 : a complex number L, such as |L|=1.
52098 :
52099 : -- ALGLIB --
52100 : Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey.
52101 : *************************************************************************/
52102 0 : ae_bool hmatrixevdr(/* Complex */ ae_matrix* a,
52103 : ae_int_t n,
52104 : ae_int_t zneeded,
52105 : ae_bool isupper,
52106 : double b1,
52107 : double b2,
52108 : ae_int_t* m,
52109 : /* Real */ ae_vector* w,
52110 : /* Complex */ ae_matrix* z,
52111 : ae_state *_state)
52112 : {
52113 : ae_frame _frame_block;
52114 : ae_matrix _a;
52115 : ae_matrix q;
52116 : ae_matrix t;
52117 : ae_vector tau;
52118 : ae_vector e;
52119 : ae_vector work;
52120 : ae_int_t i;
52121 : ae_int_t k;
52122 : double v;
52123 : ae_bool result;
52124 :
52125 0 : ae_frame_make(_state, &_frame_block);
52126 0 : memset(&_a, 0, sizeof(_a));
52127 0 : memset(&q, 0, sizeof(q));
52128 0 : memset(&t, 0, sizeof(t));
52129 0 : memset(&tau, 0, sizeof(tau));
52130 0 : memset(&e, 0, sizeof(e));
52131 0 : memset(&work, 0, sizeof(work));
52132 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
52133 0 : a = &_a;
52134 0 : *m = 0;
52135 0 : ae_vector_clear(w);
52136 0 : ae_matrix_clear(z);
52137 0 : ae_matrix_init(&q, 0, 0, DT_COMPLEX, _state, ae_true);
52138 0 : ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true);
52139 0 : ae_vector_init(&tau, 0, DT_COMPLEX, _state, ae_true);
52140 0 : ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
52141 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
52142 :
52143 0 : ae_assert(zneeded==0||zneeded==1, "HermitianEigenValuesAndVectorsInInterval: incorrect ZNeeded", _state);
52144 :
52145 : /*
52146 : * Reduce to tridiagonal form
52147 : */
52148 0 : hmatrixtd(a, n, isupper, &tau, w, &e, _state);
52149 0 : if( zneeded==1 )
52150 : {
52151 0 : hmatrixtdunpackq(a, n, isupper, &tau, &q, _state);
52152 0 : zneeded = 2;
52153 : }
52154 :
52155 : /*
52156 : * Bisection and inverse iteration
52157 : */
52158 0 : result = smatrixtdevdr(w, &e, n, zneeded, b1, b2, m, &t, _state);
52159 :
52160 : /*
52161 : * Eigenvectors are needed
52162 : * Calculate Z = Q*T = Re(Q)*T + i*Im(Q)*T
52163 : */
52164 0 : if( (result&&zneeded!=0)&&*m!=0 )
52165 : {
52166 0 : ae_vector_set_length(&work, *m-1+1, _state);
52167 0 : ae_matrix_set_length(z, n-1+1, *m-1+1, _state);
52168 0 : for(i=0; i<=n-1; i++)
52169 : {
52170 :
52171 : /*
52172 : * Calculate real part
52173 : */
52174 0 : for(k=0; k<=*m-1; k++)
52175 : {
52176 0 : work.ptr.p_double[k] = (double)(0);
52177 : }
52178 0 : for(k=0; k<=n-1; k++)
52179 : {
52180 0 : v = q.ptr.pp_complex[i][k].x;
52181 0 : ae_v_addd(&work.ptr.p_double[0], 1, &t.ptr.pp_double[k][0], 1, ae_v_len(0,*m-1), v);
52182 : }
52183 0 : for(k=0; k<=*m-1; k++)
52184 : {
52185 0 : z->ptr.pp_complex[i][k].x = work.ptr.p_double[k];
52186 : }
52187 :
52188 : /*
52189 : * Calculate imaginary part
52190 : */
52191 0 : for(k=0; k<=*m-1; k++)
52192 : {
52193 0 : work.ptr.p_double[k] = (double)(0);
52194 : }
52195 0 : for(k=0; k<=n-1; k++)
52196 : {
52197 0 : v = q.ptr.pp_complex[i][k].y;
52198 0 : ae_v_addd(&work.ptr.p_double[0], 1, &t.ptr.pp_double[k][0], 1, ae_v_len(0,*m-1), v);
52199 : }
52200 0 : for(k=0; k<=*m-1; k++)
52201 : {
52202 0 : z->ptr.pp_complex[i][k].y = work.ptr.p_double[k];
52203 : }
52204 : }
52205 : }
52206 0 : ae_frame_leave(_state);
52207 0 : return result;
52208 : }
52209 :
52210 :
52211 : /*************************************************************************
52212 : Subroutine for finding the eigenvalues and eigenvectors of a Hermitian
52213 : matrix with given indexes by using bisection and inverse iteration methods
52214 :
52215 : Input parameters:
52216 : A - Hermitian matrix which is given by its upper or lower
52217 : triangular part.
52218 : Array whose indexes range within [0..N-1, 0..N-1].
52219 : N - size of matrix A.
52220 : ZNeeded - flag controlling whether the eigenvectors are needed or
52221 : not. If ZNeeded is equal to:
52222 : * 0, the eigenvectors are not returned;
52223 : * 1, the eigenvectors are returned.
52224 : IsUpperA - storage format of matrix A.
52225 : I1, I2 - index interval for searching (from I1 to I2).
52226 : 0 <= I1 <= I2 <= N-1.
52227 :
52228 : Output parameters:
52229 : W - array of the eigenvalues found.
52230 : Array whose index ranges within [0..I2-I1].
52231 : Z - if ZNeeded is equal to:
52232 : * 0, Z hasn't changed;
52233 : * 1, Z contains eigenvectors.
52234 : Array whose indexes range within [0..N-1, 0..I2-I1].
52235 : In that case, the eigenvectors are stored in the matrix
52236 : columns.
52237 :
52238 : Result:
52239 : True, if successful. W contains the eigenvalues, Z contains the
52240 : eigenvectors (if needed).
52241 :
52242 : False, if the bisection method subroutine wasn't able to find the
52243 : eigenvalues in the given interval or if the inverse iteration
52244 : subroutine wasn't able to find all the corresponding eigenvectors.
52245 : In that case, the eigenvalues and eigenvectors are not returned.
52246 :
52247 : Note:
52248 : eigen vectors of Hermitian matrix are defined up to multiplication by
52249 : a complex number L, such as |L|=1.
52250 :
52251 : -- ALGLIB --
52252 : Copyright 07.01.2006, 24.03.2007 by Bochkanov Sergey.
52253 : *************************************************************************/
52254 0 : ae_bool hmatrixevdi(/* Complex */ ae_matrix* a,
52255 : ae_int_t n,
52256 : ae_int_t zneeded,
52257 : ae_bool isupper,
52258 : ae_int_t i1,
52259 : ae_int_t i2,
52260 : /* Real */ ae_vector* w,
52261 : /* Complex */ ae_matrix* z,
52262 : ae_state *_state)
52263 : {
52264 : ae_frame _frame_block;
52265 : ae_matrix _a;
52266 : ae_matrix q;
52267 : ae_matrix t;
52268 : ae_vector tau;
52269 : ae_vector e;
52270 : ae_vector work;
52271 : ae_int_t i;
52272 : ae_int_t k;
52273 : double v;
52274 : ae_int_t m;
52275 : ae_bool result;
52276 :
52277 0 : ae_frame_make(_state, &_frame_block);
52278 0 : memset(&_a, 0, sizeof(_a));
52279 0 : memset(&q, 0, sizeof(q));
52280 0 : memset(&t, 0, sizeof(t));
52281 0 : memset(&tau, 0, sizeof(tau));
52282 0 : memset(&e, 0, sizeof(e));
52283 0 : memset(&work, 0, sizeof(work));
52284 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
52285 0 : a = &_a;
52286 0 : ae_vector_clear(w);
52287 0 : ae_matrix_clear(z);
52288 0 : ae_matrix_init(&q, 0, 0, DT_COMPLEX, _state, ae_true);
52289 0 : ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true);
52290 0 : ae_vector_init(&tau, 0, DT_COMPLEX, _state, ae_true);
52291 0 : ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
52292 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
52293 :
52294 0 : ae_assert(zneeded==0||zneeded==1, "HermitianEigenValuesAndVectorsByIndexes: incorrect ZNeeded", _state);
52295 :
52296 : /*
52297 : * Reduce to tridiagonal form
52298 : */
52299 0 : hmatrixtd(a, n, isupper, &tau, w, &e, _state);
52300 0 : if( zneeded==1 )
52301 : {
52302 0 : hmatrixtdunpackq(a, n, isupper, &tau, &q, _state);
52303 0 : zneeded = 2;
52304 : }
52305 :
52306 : /*
52307 : * Bisection and inverse iteration
52308 : */
52309 0 : result = smatrixtdevdi(w, &e, n, zneeded, i1, i2, &t, _state);
52310 :
52311 : /*
52312 : * Eigenvectors are needed
52313 : * Calculate Z = Q*T = Re(Q)*T + i*Im(Q)*T
52314 : */
52315 0 : m = i2-i1+1;
52316 0 : if( result&&zneeded!=0 )
52317 : {
52318 0 : ae_vector_set_length(&work, m-1+1, _state);
52319 0 : ae_matrix_set_length(z, n-1+1, m-1+1, _state);
52320 0 : for(i=0; i<=n-1; i++)
52321 : {
52322 :
52323 : /*
52324 : * Calculate real part
52325 : */
52326 0 : for(k=0; k<=m-1; k++)
52327 : {
52328 0 : work.ptr.p_double[k] = (double)(0);
52329 : }
52330 0 : for(k=0; k<=n-1; k++)
52331 : {
52332 0 : v = q.ptr.pp_complex[i][k].x;
52333 0 : ae_v_addd(&work.ptr.p_double[0], 1, &t.ptr.pp_double[k][0], 1, ae_v_len(0,m-1), v);
52334 : }
52335 0 : for(k=0; k<=m-1; k++)
52336 : {
52337 0 : z->ptr.pp_complex[i][k].x = work.ptr.p_double[k];
52338 : }
52339 :
52340 : /*
52341 : * Calculate imaginary part
52342 : */
52343 0 : for(k=0; k<=m-1; k++)
52344 : {
52345 0 : work.ptr.p_double[k] = (double)(0);
52346 : }
52347 0 : for(k=0; k<=n-1; k++)
52348 : {
52349 0 : v = q.ptr.pp_complex[i][k].y;
52350 0 : ae_v_addd(&work.ptr.p_double[0], 1, &t.ptr.pp_double[k][0], 1, ae_v_len(0,m-1), v);
52351 : }
52352 0 : for(k=0; k<=m-1; k++)
52353 : {
52354 0 : z->ptr.pp_complex[i][k].y = work.ptr.p_double[k];
52355 : }
52356 : }
52357 : }
52358 0 : ae_frame_leave(_state);
52359 0 : return result;
52360 : }
52361 :
52362 :
52363 : /*************************************************************************
52364 : Finding the eigenvalues and eigenvectors of a tridiagonal symmetric matrix
52365 :
52366 : The algorithm finds the eigen pairs of a tridiagonal symmetric matrix by
52367 : using an QL/QR algorithm with implicit shifts.
52368 :
52369 : ! COMMERCIAL EDITION OF ALGLIB:
52370 : !
52371 : ! Commercial Edition of ALGLIB includes following important improvements
52372 : ! of this function:
52373 : ! * high-performance native backend with same C# interface (C# version)
52374 : ! * hardware vendor (Intel) implementations of linear algebra primitives
52375 : ! (C++ and C# versions, x86/x64 platform)
52376 : !
52377 : ! We recommend you to read 'Working with commercial version' section of
52378 : ! ALGLIB Reference Manual in order to find out how to use performance-
52379 : ! related features provided by commercial edition of ALGLIB.
52380 :
52381 : Input parameters:
52382 : D - the main diagonal of a tridiagonal matrix.
52383 : Array whose index ranges within [0..N-1].
52384 : E - the secondary diagonal of a tridiagonal matrix.
52385 : Array whose index ranges within [0..N-2].
52386 : N - size of matrix A.
52387 : ZNeeded - flag controlling whether the eigenvectors are needed or not.
52388 : If ZNeeded is equal to:
52389 : * 0, the eigenvectors are not needed;
52390 : * 1, the eigenvectors of a tridiagonal matrix
52391 : are multiplied by the square matrix Z. It is used if the
52392 : tridiagonal matrix is obtained by the similarity
52393 : transformation of a symmetric matrix;
52394 : * 2, the eigenvectors of a tridiagonal matrix replace the
52395 : square matrix Z;
52396 : * 3, matrix Z contains the first row of the eigenvectors
52397 : matrix.
52398 : Z - if ZNeeded=1, Z contains the square matrix by which the
52399 : eigenvectors are multiplied.
52400 : Array whose indexes range within [0..N-1, 0..N-1].
52401 :
52402 : Output parameters:
52403 : D - eigenvalues in ascending order.
52404 : Array whose index ranges within [0..N-1].
52405 : Z - if ZNeeded is equal to:
52406 : * 0, Z hasn't changed;
52407 : * 1, Z contains the product of a given matrix (from the left)
52408 : and the eigenvectors matrix (from the right);
52409 : * 2, Z contains the eigenvectors.
52410 : * 3, Z contains the first row of the eigenvectors matrix.
52411 : If ZNeeded<3, Z is the array whose indexes range within [0..N-1, 0..N-1].
52412 : In that case, the eigenvectors are stored in the matrix columns.
52413 : If ZNeeded=3, Z is the array whose indexes range within [0..0, 0..N-1].
52414 :
52415 : Result:
52416 : True, if the algorithm has converged.
52417 : False, if the algorithm hasn't converged.
52418 :
52419 : -- LAPACK routine (version 3.0) --
52420 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
52421 : Courant Institute, Argonne National Lab, and Rice University
52422 : September 30, 1994
52423 : *************************************************************************/
52424 0 : ae_bool smatrixtdevd(/* Real */ ae_vector* d,
52425 : /* Real */ ae_vector* e,
52426 : ae_int_t n,
52427 : ae_int_t zneeded,
52428 : /* Real */ ae_matrix* z,
52429 : ae_state *_state)
52430 : {
52431 : ae_frame _frame_block;
52432 : ae_vector _e;
52433 : ae_vector d1;
52434 : ae_vector e1;
52435 : ae_vector ex;
52436 : ae_matrix z1;
52437 : ae_int_t i;
52438 : ae_int_t j;
52439 : ae_bool result;
52440 :
52441 0 : ae_frame_make(_state, &_frame_block);
52442 0 : memset(&_e, 0, sizeof(_e));
52443 0 : memset(&d1, 0, sizeof(d1));
52444 0 : memset(&e1, 0, sizeof(e1));
52445 0 : memset(&ex, 0, sizeof(ex));
52446 0 : memset(&z1, 0, sizeof(z1));
52447 0 : ae_vector_init_copy(&_e, e, _state, ae_true);
52448 0 : e = &_e;
52449 0 : ae_vector_init(&d1, 0, DT_REAL, _state, ae_true);
52450 0 : ae_vector_init(&e1, 0, DT_REAL, _state, ae_true);
52451 0 : ae_vector_init(&ex, 0, DT_REAL, _state, ae_true);
52452 0 : ae_matrix_init(&z1, 0, 0, DT_REAL, _state, ae_true);
52453 :
52454 0 : ae_assert(n>=1, "SMatrixTDEVD: N<=0", _state);
52455 0 : ae_assert(zneeded>=0&&zneeded<=3, "SMatrixTDEVD: incorrect ZNeeded", _state);
52456 0 : result = ae_false;
52457 :
52458 : /*
52459 : * Preprocess Z: make ZNeeded equal to 0, 1 or 3.
52460 : * Ensure that memory for Z is allocated.
52461 : */
52462 0 : if( zneeded==2 )
52463 : {
52464 :
52465 : /*
52466 : * Load identity to Z
52467 : */
52468 0 : rmatrixsetlengthatleast(z, n, n, _state);
52469 0 : for(i=0; i<=n-1; i++)
52470 : {
52471 0 : for(j=0; j<=n-1; j++)
52472 : {
52473 0 : z->ptr.pp_double[i][j] = 0.0;
52474 : }
52475 0 : z->ptr.pp_double[i][i] = 1.0;
52476 : }
52477 0 : zneeded = 1;
52478 : }
52479 0 : if( zneeded==3 )
52480 : {
52481 :
52482 : /*
52483 : * Allocate memory
52484 : */
52485 0 : rmatrixsetlengthatleast(z, 1, n, _state);
52486 : }
52487 :
52488 : /*
52489 : * Try to solve problem with MKL
52490 : */
52491 0 : ae_vector_set_length(&ex, n, _state);
52492 0 : for(i=0; i<=n-2; i++)
52493 : {
52494 0 : ex.ptr.p_double[i] = e->ptr.p_double[i];
52495 : }
52496 0 : if( smatrixtdevdmkl(d, &ex, n, zneeded, z, &result, _state) )
52497 : {
52498 0 : ae_frame_leave(_state);
52499 0 : return result;
52500 : }
52501 :
52502 : /*
52503 : * Prepare 1-based task
52504 : */
52505 0 : ae_vector_set_length(&d1, n+1, _state);
52506 0 : ae_vector_set_length(&e1, n+1, _state);
52507 0 : ae_v_move(&d1.ptr.p_double[1], 1, &d->ptr.p_double[0], 1, ae_v_len(1,n));
52508 0 : if( n>1 )
52509 : {
52510 0 : ae_v_move(&e1.ptr.p_double[1], 1, &e->ptr.p_double[0], 1, ae_v_len(1,n-1));
52511 : }
52512 0 : if( zneeded==1 )
52513 : {
52514 0 : ae_matrix_set_length(&z1, n+1, n+1, _state);
52515 0 : for(i=1; i<=n; i++)
52516 : {
52517 0 : ae_v_move(&z1.ptr.pp_double[i][1], 1, &z->ptr.pp_double[i-1][0], 1, ae_v_len(1,n));
52518 : }
52519 : }
52520 :
52521 : /*
52522 : * Solve 1-based task
52523 : */
52524 0 : result = evd_tridiagonalevd(&d1, &e1, n, zneeded, &z1, _state);
52525 0 : if( !result )
52526 : {
52527 0 : ae_frame_leave(_state);
52528 0 : return result;
52529 : }
52530 :
52531 : /*
52532 : * Convert back to 0-based result
52533 : */
52534 0 : ae_v_move(&d->ptr.p_double[0], 1, &d1.ptr.p_double[1], 1, ae_v_len(0,n-1));
52535 0 : if( zneeded!=0 )
52536 : {
52537 0 : if( zneeded==1 )
52538 : {
52539 0 : for(i=1; i<=n; i++)
52540 : {
52541 0 : ae_v_move(&z->ptr.pp_double[i-1][0], 1, &z1.ptr.pp_double[i][1], 1, ae_v_len(0,n-1));
52542 : }
52543 0 : ae_frame_leave(_state);
52544 0 : return result;
52545 : }
52546 0 : if( zneeded==2 )
52547 : {
52548 0 : ae_matrix_set_length(z, n-1+1, n-1+1, _state);
52549 0 : for(i=1; i<=n; i++)
52550 : {
52551 0 : ae_v_move(&z->ptr.pp_double[i-1][0], 1, &z1.ptr.pp_double[i][1], 1, ae_v_len(0,n-1));
52552 : }
52553 0 : ae_frame_leave(_state);
52554 0 : return result;
52555 : }
52556 0 : if( zneeded==3 )
52557 : {
52558 0 : ae_matrix_set_length(z, 0+1, n-1+1, _state);
52559 0 : ae_v_move(&z->ptr.pp_double[0][0], 1, &z1.ptr.pp_double[1][1], 1, ae_v_len(0,n-1));
52560 0 : ae_frame_leave(_state);
52561 0 : return result;
52562 : }
52563 0 : ae_assert(ae_false, "SMatrixTDEVD: Incorrect ZNeeded!", _state);
52564 : }
52565 0 : ae_frame_leave(_state);
52566 0 : return result;
52567 : }
52568 :
52569 :
52570 : /*************************************************************************
52571 : Subroutine for finding the tridiagonal matrix eigenvalues/vectors in a
52572 : given half-interval (A, B] by using bisection and inverse iteration.
52573 :
52574 : Input parameters:
52575 : D - the main diagonal of a tridiagonal matrix.
52576 : Array whose index ranges within [0..N-1].
52577 : E - the secondary diagonal of a tridiagonal matrix.
52578 : Array whose index ranges within [0..N-2].
52579 : N - size of matrix, N>=0.
52580 : ZNeeded - flag controlling whether the eigenvectors are needed or not.
52581 : If ZNeeded is equal to:
52582 : * 0, the eigenvectors are not needed;
52583 : * 1, the eigenvectors of a tridiagonal matrix are multiplied
52584 : by the square matrix Z. It is used if the tridiagonal
52585 : matrix is obtained by the similarity transformation
52586 : of a symmetric matrix.
52587 : * 2, the eigenvectors of a tridiagonal matrix replace matrix Z.
52588 : A, B - half-interval (A, B] to search eigenvalues in.
52589 : Z - if ZNeeded is equal to:
52590 : * 0, Z isn't used and remains unchanged;
52591 : * 1, Z contains the square matrix (array whose indexes range
52592 : within [0..N-1, 0..N-1]) which reduces the given symmetric
52593 : matrix to tridiagonal form;
52594 : * 2, Z isn't used (but changed on the exit).
52595 :
52596 : Output parameters:
52597 : D - array of the eigenvalues found.
52598 : Array whose index ranges within [0..M-1].
52599 : M - number of eigenvalues found in the given half-interval (M>=0).
52600 : Z - if ZNeeded is equal to:
52601 : * 0, doesn't contain any information;
52602 : * 1, contains the product of a given NxN matrix Z (from the
52603 : left) and NxM matrix of the eigenvectors found (from the
52604 : right). Array whose indexes range within [0..N-1, 0..M-1].
52605 : * 2, contains the matrix of the eigenvectors found.
52606 : Array whose indexes range within [0..N-1, 0..M-1].
52607 :
52608 : Result:
52609 :
52610 : True, if successful. In that case, M contains the number of eigenvalues
52611 : in the given half-interval (could be equal to 0), D contains the eigenvalues,
52612 : Z contains the eigenvectors (if needed).
52613 : It should be noted that the subroutine changes the size of arrays D and Z.
52614 :
52615 : False, if the bisection method subroutine wasn't able to find the
52616 : eigenvalues in the given interval or if the inverse iteration subroutine
52617 : wasn't able to find all the corresponding eigenvectors. In that case,
52618 : the eigenvalues and eigenvectors are not returned, M is equal to 0.
52619 :
52620 : -- ALGLIB --
52621 : Copyright 31.03.2008 by Bochkanov Sergey
52622 : *************************************************************************/
52623 0 : ae_bool smatrixtdevdr(/* Real */ ae_vector* d,
52624 : /* Real */ ae_vector* e,
52625 : ae_int_t n,
52626 : ae_int_t zneeded,
52627 : double a,
52628 : double b,
52629 : ae_int_t* m,
52630 : /* Real */ ae_matrix* z,
52631 : ae_state *_state)
52632 : {
52633 : ae_frame _frame_block;
52634 : ae_int_t errorcode;
52635 : ae_int_t nsplit;
52636 : ae_int_t i;
52637 : ae_int_t j;
52638 : ae_int_t k;
52639 : ae_int_t cr;
52640 : ae_vector iblock;
52641 : ae_vector isplit;
52642 : ae_vector ifail;
52643 : ae_vector d1;
52644 : ae_vector e1;
52645 : ae_vector w;
52646 : ae_matrix z2;
52647 : ae_matrix z3;
52648 : double v;
52649 : ae_bool result;
52650 :
52651 0 : ae_frame_make(_state, &_frame_block);
52652 0 : memset(&iblock, 0, sizeof(iblock));
52653 0 : memset(&isplit, 0, sizeof(isplit));
52654 0 : memset(&ifail, 0, sizeof(ifail));
52655 0 : memset(&d1, 0, sizeof(d1));
52656 0 : memset(&e1, 0, sizeof(e1));
52657 0 : memset(&w, 0, sizeof(w));
52658 0 : memset(&z2, 0, sizeof(z2));
52659 0 : memset(&z3, 0, sizeof(z3));
52660 0 : *m = 0;
52661 0 : ae_vector_init(&iblock, 0, DT_INT, _state, ae_true);
52662 0 : ae_vector_init(&isplit, 0, DT_INT, _state, ae_true);
52663 0 : ae_vector_init(&ifail, 0, DT_INT, _state, ae_true);
52664 0 : ae_vector_init(&d1, 0, DT_REAL, _state, ae_true);
52665 0 : ae_vector_init(&e1, 0, DT_REAL, _state, ae_true);
52666 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
52667 0 : ae_matrix_init(&z2, 0, 0, DT_REAL, _state, ae_true);
52668 0 : ae_matrix_init(&z3, 0, 0, DT_REAL, _state, ae_true);
52669 :
52670 0 : ae_assert(zneeded>=0&&zneeded<=2, "SMatrixTDEVDR: incorrect ZNeeded!", _state);
52671 :
52672 : /*
52673 : * Special cases
52674 : */
52675 0 : if( ae_fp_less_eq(b,a) )
52676 : {
52677 0 : *m = 0;
52678 0 : result = ae_true;
52679 0 : ae_frame_leave(_state);
52680 0 : return result;
52681 : }
52682 0 : if( n<=0 )
52683 : {
52684 0 : *m = 0;
52685 0 : result = ae_true;
52686 0 : ae_frame_leave(_state);
52687 0 : return result;
52688 : }
52689 :
52690 : /*
52691 : * Copy D,E to D1, E1
52692 : */
52693 0 : ae_vector_set_length(&d1, n+1, _state);
52694 0 : ae_v_move(&d1.ptr.p_double[1], 1, &d->ptr.p_double[0], 1, ae_v_len(1,n));
52695 0 : if( n>1 )
52696 : {
52697 0 : ae_vector_set_length(&e1, n-1+1, _state);
52698 0 : ae_v_move(&e1.ptr.p_double[1], 1, &e->ptr.p_double[0], 1, ae_v_len(1,n-1));
52699 : }
52700 :
52701 : /*
52702 : * No eigen vectors
52703 : */
52704 0 : if( zneeded==0 )
52705 : {
52706 0 : result = evd_internalbisectioneigenvalues(&d1, &e1, n, 2, 1, a, b, 0, 0, (double)(-1), &w, m, &nsplit, &iblock, &isplit, &errorcode, _state);
52707 0 : if( !result||*m==0 )
52708 : {
52709 0 : *m = 0;
52710 0 : ae_frame_leave(_state);
52711 0 : return result;
52712 : }
52713 0 : ae_vector_set_length(d, *m-1+1, _state);
52714 0 : ae_v_move(&d->ptr.p_double[0], 1, &w.ptr.p_double[1], 1, ae_v_len(0,*m-1));
52715 0 : ae_frame_leave(_state);
52716 0 : return result;
52717 : }
52718 :
52719 : /*
52720 : * Eigen vectors are multiplied by Z
52721 : */
52722 0 : if( zneeded==1 )
52723 : {
52724 :
52725 : /*
52726 : * Find eigen pairs
52727 : */
52728 0 : result = evd_internalbisectioneigenvalues(&d1, &e1, n, 2, 2, a, b, 0, 0, (double)(-1), &w, m, &nsplit, &iblock, &isplit, &errorcode, _state);
52729 0 : if( !result||*m==0 )
52730 : {
52731 0 : *m = 0;
52732 0 : ae_frame_leave(_state);
52733 0 : return result;
52734 : }
52735 0 : evd_internaldstein(n, &d1, &e1, *m, &w, &iblock, &isplit, &z2, &ifail, &cr, _state);
52736 0 : if( cr!=0 )
52737 : {
52738 0 : *m = 0;
52739 0 : result = ae_false;
52740 0 : ae_frame_leave(_state);
52741 0 : return result;
52742 : }
52743 :
52744 : /*
52745 : * Sort eigen values and vectors
52746 : */
52747 0 : for(i=1; i<=*m; i++)
52748 : {
52749 0 : k = i;
52750 0 : for(j=i; j<=*m; j++)
52751 : {
52752 0 : if( ae_fp_less(w.ptr.p_double[j],w.ptr.p_double[k]) )
52753 : {
52754 0 : k = j;
52755 : }
52756 : }
52757 0 : v = w.ptr.p_double[i];
52758 0 : w.ptr.p_double[i] = w.ptr.p_double[k];
52759 0 : w.ptr.p_double[k] = v;
52760 0 : for(j=1; j<=n; j++)
52761 : {
52762 0 : v = z2.ptr.pp_double[j][i];
52763 0 : z2.ptr.pp_double[j][i] = z2.ptr.pp_double[j][k];
52764 0 : z2.ptr.pp_double[j][k] = v;
52765 : }
52766 : }
52767 :
52768 : /*
52769 : * Transform Z2 and overwrite Z
52770 : */
52771 0 : ae_matrix_set_length(&z3, *m+1, n+1, _state);
52772 0 : for(i=1; i<=*m; i++)
52773 : {
52774 0 : ae_v_move(&z3.ptr.pp_double[i][1], 1, &z2.ptr.pp_double[1][i], z2.stride, ae_v_len(1,n));
52775 : }
52776 0 : for(i=1; i<=n; i++)
52777 : {
52778 0 : for(j=1; j<=*m; j++)
52779 : {
52780 0 : v = ae_v_dotproduct(&z->ptr.pp_double[i-1][0], 1, &z3.ptr.pp_double[j][1], 1, ae_v_len(0,n-1));
52781 0 : z2.ptr.pp_double[i][j] = v;
52782 : }
52783 : }
52784 0 : ae_matrix_set_length(z, n-1+1, *m-1+1, _state);
52785 0 : for(i=1; i<=*m; i++)
52786 : {
52787 0 : ae_v_move(&z->ptr.pp_double[0][i-1], z->stride, &z2.ptr.pp_double[1][i], z2.stride, ae_v_len(0,n-1));
52788 : }
52789 :
52790 : /*
52791 : * Store W
52792 : */
52793 0 : ae_vector_set_length(d, *m-1+1, _state);
52794 0 : for(i=1; i<=*m; i++)
52795 : {
52796 0 : d->ptr.p_double[i-1] = w.ptr.p_double[i];
52797 : }
52798 0 : ae_frame_leave(_state);
52799 0 : return result;
52800 : }
52801 :
52802 : /*
52803 : * Eigen vectors are stored in Z
52804 : */
52805 0 : if( zneeded==2 )
52806 : {
52807 :
52808 : /*
52809 : * Find eigen pairs
52810 : */
52811 0 : result = evd_internalbisectioneigenvalues(&d1, &e1, n, 2, 2, a, b, 0, 0, (double)(-1), &w, m, &nsplit, &iblock, &isplit, &errorcode, _state);
52812 0 : if( !result||*m==0 )
52813 : {
52814 0 : *m = 0;
52815 0 : ae_frame_leave(_state);
52816 0 : return result;
52817 : }
52818 0 : evd_internaldstein(n, &d1, &e1, *m, &w, &iblock, &isplit, &z2, &ifail, &cr, _state);
52819 0 : if( cr!=0 )
52820 : {
52821 0 : *m = 0;
52822 0 : result = ae_false;
52823 0 : ae_frame_leave(_state);
52824 0 : return result;
52825 : }
52826 :
52827 : /*
52828 : * Sort eigen values and vectors
52829 : */
52830 0 : for(i=1; i<=*m; i++)
52831 : {
52832 0 : k = i;
52833 0 : for(j=i; j<=*m; j++)
52834 : {
52835 0 : if( ae_fp_less(w.ptr.p_double[j],w.ptr.p_double[k]) )
52836 : {
52837 0 : k = j;
52838 : }
52839 : }
52840 0 : v = w.ptr.p_double[i];
52841 0 : w.ptr.p_double[i] = w.ptr.p_double[k];
52842 0 : w.ptr.p_double[k] = v;
52843 0 : for(j=1; j<=n; j++)
52844 : {
52845 0 : v = z2.ptr.pp_double[j][i];
52846 0 : z2.ptr.pp_double[j][i] = z2.ptr.pp_double[j][k];
52847 0 : z2.ptr.pp_double[j][k] = v;
52848 : }
52849 : }
52850 :
52851 : /*
52852 : * Store W
52853 : */
52854 0 : ae_vector_set_length(d, *m-1+1, _state);
52855 0 : for(i=1; i<=*m; i++)
52856 : {
52857 0 : d->ptr.p_double[i-1] = w.ptr.p_double[i];
52858 : }
52859 0 : ae_matrix_set_length(z, n-1+1, *m-1+1, _state);
52860 0 : for(i=1; i<=*m; i++)
52861 : {
52862 0 : ae_v_move(&z->ptr.pp_double[0][i-1], z->stride, &z2.ptr.pp_double[1][i], z2.stride, ae_v_len(0,n-1));
52863 : }
52864 0 : ae_frame_leave(_state);
52865 0 : return result;
52866 : }
52867 0 : result = ae_false;
52868 0 : ae_frame_leave(_state);
52869 0 : return result;
52870 : }
52871 :
52872 :
52873 : /*************************************************************************
52874 : Subroutine for finding tridiagonal matrix eigenvalues/vectors with given
52875 : indexes (in ascending order) by using the bisection and inverse iteraion.
52876 :
52877 : Input parameters:
52878 : D - the main diagonal of a tridiagonal matrix.
52879 : Array whose index ranges within [0..N-1].
52880 : E - the secondary diagonal of a tridiagonal matrix.
52881 : Array whose index ranges within [0..N-2].
52882 : N - size of matrix. N>=0.
52883 : ZNeeded - flag controlling whether the eigenvectors are needed or not.
52884 : If ZNeeded is equal to:
52885 : * 0, the eigenvectors are not needed;
52886 : * 1, the eigenvectors of a tridiagonal matrix are multiplied
52887 : by the square matrix Z. It is used if the
52888 : tridiagonal matrix is obtained by the similarity transformation
52889 : of a symmetric matrix.
52890 : * 2, the eigenvectors of a tridiagonal matrix replace
52891 : matrix Z.
52892 : I1, I2 - index interval for searching (from I1 to I2).
52893 : 0 <= I1 <= I2 <= N-1.
52894 : Z - if ZNeeded is equal to:
52895 : * 0, Z isn't used and remains unchanged;
52896 : * 1, Z contains the square matrix (array whose indexes range within [0..N-1, 0..N-1])
52897 : which reduces the given symmetric matrix to tridiagonal form;
52898 : * 2, Z isn't used (but changed on the exit).
52899 :
52900 : Output parameters:
52901 : D - array of the eigenvalues found.
52902 : Array whose index ranges within [0..I2-I1].
52903 : Z - if ZNeeded is equal to:
52904 : * 0, doesn't contain any information;
52905 : * 1, contains the product of a given NxN matrix Z (from the left) and
52906 : Nx(I2-I1) matrix of the eigenvectors found (from the right).
52907 : Array whose indexes range within [0..N-1, 0..I2-I1].
52908 : * 2, contains the matrix of the eigenvalues found.
52909 : Array whose indexes range within [0..N-1, 0..I2-I1].
52910 :
52911 :
52912 : Result:
52913 :
52914 : True, if successful. In that case, D contains the eigenvalues,
52915 : Z contains the eigenvectors (if needed).
52916 : It should be noted that the subroutine changes the size of arrays D and Z.
52917 :
52918 : False, if the bisection method subroutine wasn't able to find the eigenvalues
52919 : in the given interval or if the inverse iteration subroutine wasn't able
52920 : to find all the corresponding eigenvectors. In that case, the eigenvalues
52921 : and eigenvectors are not returned.
52922 :
52923 : -- ALGLIB --
52924 : Copyright 25.12.2005 by Bochkanov Sergey
52925 : *************************************************************************/
52926 0 : ae_bool smatrixtdevdi(/* Real */ ae_vector* d,
52927 : /* Real */ ae_vector* e,
52928 : ae_int_t n,
52929 : ae_int_t zneeded,
52930 : ae_int_t i1,
52931 : ae_int_t i2,
52932 : /* Real */ ae_matrix* z,
52933 : ae_state *_state)
52934 : {
52935 : ae_frame _frame_block;
52936 : ae_int_t errorcode;
52937 : ae_int_t nsplit;
52938 : ae_int_t i;
52939 : ae_int_t j;
52940 : ae_int_t k;
52941 : ae_int_t m;
52942 : ae_int_t cr;
52943 : ae_vector iblock;
52944 : ae_vector isplit;
52945 : ae_vector ifail;
52946 : ae_vector w;
52947 : ae_vector d1;
52948 : ae_vector e1;
52949 : ae_matrix z2;
52950 : ae_matrix z3;
52951 : double v;
52952 : ae_bool result;
52953 :
52954 0 : ae_frame_make(_state, &_frame_block);
52955 0 : memset(&iblock, 0, sizeof(iblock));
52956 0 : memset(&isplit, 0, sizeof(isplit));
52957 0 : memset(&ifail, 0, sizeof(ifail));
52958 0 : memset(&w, 0, sizeof(w));
52959 0 : memset(&d1, 0, sizeof(d1));
52960 0 : memset(&e1, 0, sizeof(e1));
52961 0 : memset(&z2, 0, sizeof(z2));
52962 0 : memset(&z3, 0, sizeof(z3));
52963 0 : ae_vector_init(&iblock, 0, DT_INT, _state, ae_true);
52964 0 : ae_vector_init(&isplit, 0, DT_INT, _state, ae_true);
52965 0 : ae_vector_init(&ifail, 0, DT_INT, _state, ae_true);
52966 0 : ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
52967 0 : ae_vector_init(&d1, 0, DT_REAL, _state, ae_true);
52968 0 : ae_vector_init(&e1, 0, DT_REAL, _state, ae_true);
52969 0 : ae_matrix_init(&z2, 0, 0, DT_REAL, _state, ae_true);
52970 0 : ae_matrix_init(&z3, 0, 0, DT_REAL, _state, ae_true);
52971 :
52972 0 : ae_assert((0<=i1&&i1<=i2)&&i2<n, "SMatrixTDEVDI: incorrect I1/I2!", _state);
52973 :
52974 : /*
52975 : * Copy D,E to D1, E1
52976 : */
52977 0 : ae_vector_set_length(&d1, n+1, _state);
52978 0 : ae_v_move(&d1.ptr.p_double[1], 1, &d->ptr.p_double[0], 1, ae_v_len(1,n));
52979 0 : if( n>1 )
52980 : {
52981 0 : ae_vector_set_length(&e1, n-1+1, _state);
52982 0 : ae_v_move(&e1.ptr.p_double[1], 1, &e->ptr.p_double[0], 1, ae_v_len(1,n-1));
52983 : }
52984 :
52985 : /*
52986 : * No eigen vectors
52987 : */
52988 0 : if( zneeded==0 )
52989 : {
52990 0 : result = evd_internalbisectioneigenvalues(&d1, &e1, n, 3, 1, (double)(0), (double)(0), i1+1, i2+1, (double)(-1), &w, &m, &nsplit, &iblock, &isplit, &errorcode, _state);
52991 0 : if( !result )
52992 : {
52993 0 : ae_frame_leave(_state);
52994 0 : return result;
52995 : }
52996 0 : if( m!=i2-i1+1 )
52997 : {
52998 0 : result = ae_false;
52999 0 : ae_frame_leave(_state);
53000 0 : return result;
53001 : }
53002 0 : ae_vector_set_length(d, m-1+1, _state);
53003 0 : for(i=1; i<=m; i++)
53004 : {
53005 0 : d->ptr.p_double[i-1] = w.ptr.p_double[i];
53006 : }
53007 0 : ae_frame_leave(_state);
53008 0 : return result;
53009 : }
53010 :
53011 : /*
53012 : * Eigen vectors are multiplied by Z
53013 : */
53014 0 : if( zneeded==1 )
53015 : {
53016 :
53017 : /*
53018 : * Find eigen pairs
53019 : */
53020 0 : result = evd_internalbisectioneigenvalues(&d1, &e1, n, 3, 2, (double)(0), (double)(0), i1+1, i2+1, (double)(-1), &w, &m, &nsplit, &iblock, &isplit, &errorcode, _state);
53021 0 : if( !result )
53022 : {
53023 0 : ae_frame_leave(_state);
53024 0 : return result;
53025 : }
53026 0 : if( m!=i2-i1+1 )
53027 : {
53028 0 : result = ae_false;
53029 0 : ae_frame_leave(_state);
53030 0 : return result;
53031 : }
53032 0 : evd_internaldstein(n, &d1, &e1, m, &w, &iblock, &isplit, &z2, &ifail, &cr, _state);
53033 0 : if( cr!=0 )
53034 : {
53035 0 : result = ae_false;
53036 0 : ae_frame_leave(_state);
53037 0 : return result;
53038 : }
53039 :
53040 : /*
53041 : * Sort eigen values and vectors
53042 : */
53043 0 : for(i=1; i<=m; i++)
53044 : {
53045 0 : k = i;
53046 0 : for(j=i; j<=m; j++)
53047 : {
53048 0 : if( ae_fp_less(w.ptr.p_double[j],w.ptr.p_double[k]) )
53049 : {
53050 0 : k = j;
53051 : }
53052 : }
53053 0 : v = w.ptr.p_double[i];
53054 0 : w.ptr.p_double[i] = w.ptr.p_double[k];
53055 0 : w.ptr.p_double[k] = v;
53056 0 : for(j=1; j<=n; j++)
53057 : {
53058 0 : v = z2.ptr.pp_double[j][i];
53059 0 : z2.ptr.pp_double[j][i] = z2.ptr.pp_double[j][k];
53060 0 : z2.ptr.pp_double[j][k] = v;
53061 : }
53062 : }
53063 :
53064 : /*
53065 : * Transform Z2 and overwrite Z
53066 : */
53067 0 : ae_matrix_set_length(&z3, m+1, n+1, _state);
53068 0 : for(i=1; i<=m; i++)
53069 : {
53070 0 : ae_v_move(&z3.ptr.pp_double[i][1], 1, &z2.ptr.pp_double[1][i], z2.stride, ae_v_len(1,n));
53071 : }
53072 0 : for(i=1; i<=n; i++)
53073 : {
53074 0 : for(j=1; j<=m; j++)
53075 : {
53076 0 : v = ae_v_dotproduct(&z->ptr.pp_double[i-1][0], 1, &z3.ptr.pp_double[j][1], 1, ae_v_len(0,n-1));
53077 0 : z2.ptr.pp_double[i][j] = v;
53078 : }
53079 : }
53080 0 : ae_matrix_set_length(z, n-1+1, m-1+1, _state);
53081 0 : for(i=1; i<=m; i++)
53082 : {
53083 0 : ae_v_move(&z->ptr.pp_double[0][i-1], z->stride, &z2.ptr.pp_double[1][i], z2.stride, ae_v_len(0,n-1));
53084 : }
53085 :
53086 : /*
53087 : * Store W
53088 : */
53089 0 : ae_vector_set_length(d, m-1+1, _state);
53090 0 : for(i=1; i<=m; i++)
53091 : {
53092 0 : d->ptr.p_double[i-1] = w.ptr.p_double[i];
53093 : }
53094 0 : ae_frame_leave(_state);
53095 0 : return result;
53096 : }
53097 :
53098 : /*
53099 : * Eigen vectors are stored in Z
53100 : */
53101 0 : if( zneeded==2 )
53102 : {
53103 :
53104 : /*
53105 : * Find eigen pairs
53106 : */
53107 0 : result = evd_internalbisectioneigenvalues(&d1, &e1, n, 3, 2, (double)(0), (double)(0), i1+1, i2+1, (double)(-1), &w, &m, &nsplit, &iblock, &isplit, &errorcode, _state);
53108 0 : if( !result )
53109 : {
53110 0 : ae_frame_leave(_state);
53111 0 : return result;
53112 : }
53113 0 : if( m!=i2-i1+1 )
53114 : {
53115 0 : result = ae_false;
53116 0 : ae_frame_leave(_state);
53117 0 : return result;
53118 : }
53119 0 : evd_internaldstein(n, &d1, &e1, m, &w, &iblock, &isplit, &z2, &ifail, &cr, _state);
53120 0 : if( cr!=0 )
53121 : {
53122 0 : result = ae_false;
53123 0 : ae_frame_leave(_state);
53124 0 : return result;
53125 : }
53126 :
53127 : /*
53128 : * Sort eigen values and vectors
53129 : */
53130 0 : for(i=1; i<=m; i++)
53131 : {
53132 0 : k = i;
53133 0 : for(j=i; j<=m; j++)
53134 : {
53135 0 : if( ae_fp_less(w.ptr.p_double[j],w.ptr.p_double[k]) )
53136 : {
53137 0 : k = j;
53138 : }
53139 : }
53140 0 : v = w.ptr.p_double[i];
53141 0 : w.ptr.p_double[i] = w.ptr.p_double[k];
53142 0 : w.ptr.p_double[k] = v;
53143 0 : for(j=1; j<=n; j++)
53144 : {
53145 0 : v = z2.ptr.pp_double[j][i];
53146 0 : z2.ptr.pp_double[j][i] = z2.ptr.pp_double[j][k];
53147 0 : z2.ptr.pp_double[j][k] = v;
53148 : }
53149 : }
53150 :
53151 : /*
53152 : * Store Z
53153 : */
53154 0 : ae_matrix_set_length(z, n-1+1, m-1+1, _state);
53155 0 : for(i=1; i<=m; i++)
53156 : {
53157 0 : ae_v_move(&z->ptr.pp_double[0][i-1], z->stride, &z2.ptr.pp_double[1][i], z2.stride, ae_v_len(0,n-1));
53158 : }
53159 :
53160 : /*
53161 : * Store W
53162 : */
53163 0 : ae_vector_set_length(d, m-1+1, _state);
53164 0 : for(i=1; i<=m; i++)
53165 : {
53166 0 : d->ptr.p_double[i-1] = w.ptr.p_double[i];
53167 : }
53168 0 : ae_frame_leave(_state);
53169 0 : return result;
53170 : }
53171 0 : result = ae_false;
53172 0 : ae_frame_leave(_state);
53173 0 : return result;
53174 : }
53175 :
53176 :
53177 : /*************************************************************************
53178 : Finding eigenvalues and eigenvectors of a general (unsymmetric) matrix
53179 :
53180 : ! COMMERCIAL EDITION OF ALGLIB:
53181 : !
53182 : ! Commercial Edition of ALGLIB includes following important improvements
53183 : ! of this function:
53184 : ! * high-performance native backend with same C# interface (C# version)
53185 : ! * hardware vendor (Intel) implementations of linear algebra primitives
53186 : ! (C++ and C# versions, x86/x64 platform)
53187 : !
53188 : ! We recommend you to read 'Working with commercial version' section of
53189 : ! ALGLIB Reference Manual in order to find out how to use performance-
53190 : ! related features provided by commercial edition of ALGLIB.
53191 :
53192 : The algorithm finds eigenvalues and eigenvectors of a general matrix by
53193 : using the QR algorithm with multiple shifts. The algorithm can find
53194 : eigenvalues and both left and right eigenvectors.
53195 :
53196 : The right eigenvector is a vector x such that A*x = w*x, and the left
53197 : eigenvector is a vector y such that y'*A = w*y' (here y' implies a complex
53198 : conjugate transposition of vector y).
53199 :
53200 : Input parameters:
53201 : A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
53202 : N - size of matrix A.
53203 : VNeeded - flag controlling whether eigenvectors are needed or not.
53204 : If VNeeded is equal to:
53205 : * 0, eigenvectors are not returned;
53206 : * 1, right eigenvectors are returned;
53207 : * 2, left eigenvectors are returned;
53208 : * 3, both left and right eigenvectors are returned.
53209 :
53210 : Output parameters:
53211 : WR - real parts of eigenvalues.
53212 : Array whose index ranges within [0..N-1].
53213 : WR - imaginary parts of eigenvalues.
53214 : Array whose index ranges within [0..N-1].
53215 : VL, VR - arrays of left and right eigenvectors (if they are needed).
53216 : If WI[i]=0, the respective eigenvalue is a real number,
53217 : and it corresponds to the column number I of matrices VL/VR.
53218 : If WI[i]>0, we have a pair of complex conjugate numbers with
53219 : positive and negative imaginary parts:
53220 : the first eigenvalue WR[i] + sqrt(-1)*WI[i];
53221 : the second eigenvalue WR[i+1] + sqrt(-1)*WI[i+1];
53222 : WI[i]>0
53223 : WI[i+1] = -WI[i] < 0
53224 : In that case, the eigenvector corresponding to the first
53225 : eigenvalue is located in i and i+1 columns of matrices
53226 : VL/VR (the column number i contains the real part, and the
53227 : column number i+1 contains the imaginary part), and the vector
53228 : corresponding to the second eigenvalue is a complex conjugate to
53229 : the first vector.
53230 : Arrays whose indexes range within [0..N-1, 0..N-1].
53231 :
53232 : Result:
53233 : True, if the algorithm has converged.
53234 : False, if the algorithm has not converged.
53235 :
53236 : Note 1:
53237 : Some users may ask the following question: what if WI[N-1]>0?
53238 : WI[N] must contain an eigenvalue which is complex conjugate to the
53239 : N-th eigenvalue, but the array has only size N?
53240 : The answer is as follows: such a situation cannot occur because the
53241 : algorithm finds a pairs of eigenvalues, therefore, if WI[i]>0, I is
53242 : strictly less than N-1.
53243 :
53244 : Note 2:
53245 : The algorithm performance depends on the value of the internal parameter
53246 : NS of the InternalSchurDecomposition subroutine which defines the number
53247 : of shifts in the QR algorithm (similarly to the block width in block-matrix
53248 : algorithms of linear algebra). If you require maximum performance
53249 : on your machine, it is recommended to adjust this parameter manually.
53250 :
53251 :
53252 : See also the InternalTREVC subroutine.
53253 :
53254 : The algorithm is based on the LAPACK 3.0 library.
53255 : *************************************************************************/
53256 0 : ae_bool rmatrixevd(/* Real */ ae_matrix* a,
53257 : ae_int_t n,
53258 : ae_int_t vneeded,
53259 : /* Real */ ae_vector* wr,
53260 : /* Real */ ae_vector* wi,
53261 : /* Real */ ae_matrix* vl,
53262 : /* Real */ ae_matrix* vr,
53263 : ae_state *_state)
53264 : {
53265 : ae_frame _frame_block;
53266 : ae_matrix _a;
53267 : ae_matrix a1;
53268 : ae_matrix vl1;
53269 : ae_matrix vr1;
53270 : ae_matrix s1;
53271 : ae_matrix s;
53272 : ae_matrix dummy;
53273 : ae_vector wr1;
53274 : ae_vector wi1;
53275 : ae_vector tau;
53276 : ae_int_t i;
53277 : ae_int_t info;
53278 : ae_vector sel1;
53279 : ae_int_t m1;
53280 : ae_bool result;
53281 :
53282 0 : ae_frame_make(_state, &_frame_block);
53283 0 : memset(&_a, 0, sizeof(_a));
53284 0 : memset(&a1, 0, sizeof(a1));
53285 0 : memset(&vl1, 0, sizeof(vl1));
53286 0 : memset(&vr1, 0, sizeof(vr1));
53287 0 : memset(&s1, 0, sizeof(s1));
53288 0 : memset(&s, 0, sizeof(s));
53289 0 : memset(&dummy, 0, sizeof(dummy));
53290 0 : memset(&wr1, 0, sizeof(wr1));
53291 0 : memset(&wi1, 0, sizeof(wi1));
53292 0 : memset(&tau, 0, sizeof(tau));
53293 0 : memset(&sel1, 0, sizeof(sel1));
53294 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
53295 0 : a = &_a;
53296 0 : ae_vector_clear(wr);
53297 0 : ae_vector_clear(wi);
53298 0 : ae_matrix_clear(vl);
53299 0 : ae_matrix_clear(vr);
53300 0 : ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true);
53301 0 : ae_matrix_init(&vl1, 0, 0, DT_REAL, _state, ae_true);
53302 0 : ae_matrix_init(&vr1, 0, 0, DT_REAL, _state, ae_true);
53303 0 : ae_matrix_init(&s1, 0, 0, DT_REAL, _state, ae_true);
53304 0 : ae_matrix_init(&s, 0, 0, DT_REAL, _state, ae_true);
53305 0 : ae_matrix_init(&dummy, 0, 0, DT_REAL, _state, ae_true);
53306 0 : ae_vector_init(&wr1, 0, DT_REAL, _state, ae_true);
53307 0 : ae_vector_init(&wi1, 0, DT_REAL, _state, ae_true);
53308 0 : ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
53309 0 : ae_vector_init(&sel1, 0, DT_BOOL, _state, ae_true);
53310 :
53311 0 : ae_assert(vneeded>=0&&vneeded<=3, "RMatrixEVD: incorrect VNeeded!", _state);
53312 0 : if( vneeded==0 )
53313 : {
53314 :
53315 : /*
53316 : * Eigen values only
53317 : */
53318 0 : rmatrixhessenberg(a, n, &tau, _state);
53319 0 : rmatrixinternalschurdecomposition(a, n, 0, 0, wr, wi, &dummy, &info, _state);
53320 0 : result = info==0;
53321 0 : ae_frame_leave(_state);
53322 0 : return result;
53323 : }
53324 :
53325 : /*
53326 : * Eigen values and vectors
53327 : */
53328 0 : rmatrixhessenberg(a, n, &tau, _state);
53329 0 : rmatrixhessenbergunpackq(a, n, &tau, &s, _state);
53330 0 : rmatrixinternalschurdecomposition(a, n, 1, 1, wr, wi, &s, &info, _state);
53331 0 : result = info==0;
53332 0 : if( !result )
53333 : {
53334 0 : ae_frame_leave(_state);
53335 0 : return result;
53336 : }
53337 0 : if( vneeded==1||vneeded==3 )
53338 : {
53339 0 : ae_matrix_set_length(vr, n, n, _state);
53340 0 : for(i=0; i<=n-1; i++)
53341 : {
53342 0 : ae_v_move(&vr->ptr.pp_double[i][0], 1, &s.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
53343 : }
53344 : }
53345 0 : if( vneeded==2||vneeded==3 )
53346 : {
53347 0 : ae_matrix_set_length(vl, n, n, _state);
53348 0 : for(i=0; i<=n-1; i++)
53349 : {
53350 0 : ae_v_move(&vl->ptr.pp_double[i][0], 1, &s.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
53351 : }
53352 : }
53353 0 : evd_rmatrixinternaltrevc(a, n, vneeded, 1, &sel1, vl, vr, &m1, &info, _state);
53354 0 : result = info==0;
53355 0 : ae_frame_leave(_state);
53356 0 : return result;
53357 : }
53358 :
53359 :
53360 : /*************************************************************************
53361 : Clears request fileds (to be sure that we don't forgot to clear something)
53362 : *************************************************************************/
53363 0 : static void evd_clearrfields(eigsubspacestate* state, ae_state *_state)
53364 : {
53365 :
53366 :
53367 0 : state->requesttype = -1;
53368 0 : state->requestsize = -1;
53369 0 : }
53370 :
53371 :
53372 0 : static ae_bool evd_tridiagonalevd(/* Real */ ae_vector* d,
53373 : /* Real */ ae_vector* e,
53374 : ae_int_t n,
53375 : ae_int_t zneeded,
53376 : /* Real */ ae_matrix* z,
53377 : ae_state *_state)
53378 : {
53379 : ae_frame _frame_block;
53380 : ae_vector _e;
53381 : ae_int_t maxit;
53382 : ae_int_t i;
53383 : ae_int_t ii;
53384 : ae_int_t iscale;
53385 : ae_int_t j;
53386 : ae_int_t jtot;
53387 : ae_int_t k;
53388 : ae_int_t t;
53389 : ae_int_t l;
53390 : ae_int_t l1;
53391 : ae_int_t lend;
53392 : ae_int_t lendm1;
53393 : ae_int_t lendp1;
53394 : ae_int_t lendsv;
53395 : ae_int_t lm1;
53396 : ae_int_t lsv;
53397 : ae_int_t m;
53398 : ae_int_t mm1;
53399 : ae_int_t nm1;
53400 : ae_int_t nmaxit;
53401 : ae_int_t tmpint;
53402 : double anorm;
53403 : double b;
53404 : double c;
53405 : double eps;
53406 : double eps2;
53407 : double f;
53408 : double g;
53409 : double p;
53410 : double r;
53411 : double rt1;
53412 : double rt2;
53413 : double s;
53414 : double safmax;
53415 : double safmin;
53416 : double ssfmax;
53417 : double ssfmin;
53418 : double tst;
53419 : double tmp;
53420 : ae_vector work1;
53421 : ae_vector work2;
53422 : ae_vector workc;
53423 : ae_vector works;
53424 : ae_vector wtemp;
53425 : ae_bool gotoflag;
53426 : ae_int_t zrows;
53427 : ae_bool wastranspose;
53428 : ae_bool result;
53429 :
53430 0 : ae_frame_make(_state, &_frame_block);
53431 0 : memset(&_e, 0, sizeof(_e));
53432 0 : memset(&work1, 0, sizeof(work1));
53433 0 : memset(&work2, 0, sizeof(work2));
53434 0 : memset(&workc, 0, sizeof(workc));
53435 0 : memset(&works, 0, sizeof(works));
53436 0 : memset(&wtemp, 0, sizeof(wtemp));
53437 0 : ae_vector_init_copy(&_e, e, _state, ae_true);
53438 0 : e = &_e;
53439 0 : ae_vector_init(&work1, 0, DT_REAL, _state, ae_true);
53440 0 : ae_vector_init(&work2, 0, DT_REAL, _state, ae_true);
53441 0 : ae_vector_init(&workc, 0, DT_REAL, _state, ae_true);
53442 0 : ae_vector_init(&works, 0, DT_REAL, _state, ae_true);
53443 0 : ae_vector_init(&wtemp, 0, DT_REAL, _state, ae_true);
53444 :
53445 0 : ae_assert(zneeded>=0&&zneeded<=3, "TridiagonalEVD: Incorrent ZNeeded", _state);
53446 :
53447 : /*
53448 : * Quick return if possible
53449 : */
53450 0 : if( zneeded<0||zneeded>3 )
53451 : {
53452 0 : result = ae_false;
53453 0 : ae_frame_leave(_state);
53454 0 : return result;
53455 : }
53456 0 : result = ae_true;
53457 0 : if( n==0 )
53458 : {
53459 0 : ae_frame_leave(_state);
53460 0 : return result;
53461 : }
53462 0 : if( n==1 )
53463 : {
53464 0 : if( zneeded==2||zneeded==3 )
53465 : {
53466 0 : ae_matrix_set_length(z, 1+1, 1+1, _state);
53467 0 : z->ptr.pp_double[1][1] = (double)(1);
53468 : }
53469 0 : ae_frame_leave(_state);
53470 0 : return result;
53471 : }
53472 0 : maxit = 30;
53473 :
53474 : /*
53475 : * Initialize arrays
53476 : */
53477 0 : ae_vector_set_length(&wtemp, n+1, _state);
53478 0 : ae_vector_set_length(&work1, n-1+1, _state);
53479 0 : ae_vector_set_length(&work2, n-1+1, _state);
53480 0 : ae_vector_set_length(&workc, n+1, _state);
53481 0 : ae_vector_set_length(&works, n+1, _state);
53482 :
53483 : /*
53484 : * Determine the unit roundoff and over/underflow thresholds.
53485 : */
53486 0 : eps = ae_machineepsilon;
53487 0 : eps2 = ae_sqr(eps, _state);
53488 0 : safmin = ae_minrealnumber;
53489 0 : safmax = ae_maxrealnumber;
53490 0 : ssfmax = ae_sqrt(safmax, _state)/3;
53491 0 : ssfmin = ae_sqrt(safmin, _state)/eps2;
53492 :
53493 : /*
53494 : * Prepare Z
53495 : *
53496 : * Here we are using transposition to get rid of column operations
53497 : *
53498 : */
53499 0 : wastranspose = ae_false;
53500 0 : zrows = 0;
53501 0 : if( zneeded==1 )
53502 : {
53503 0 : zrows = n;
53504 : }
53505 0 : if( zneeded==2 )
53506 : {
53507 0 : zrows = n;
53508 : }
53509 0 : if( zneeded==3 )
53510 : {
53511 0 : zrows = 1;
53512 : }
53513 0 : if( zneeded==1 )
53514 : {
53515 0 : wastranspose = ae_true;
53516 0 : inplacetranspose(z, 1, n, 1, n, &wtemp, _state);
53517 : }
53518 0 : if( zneeded==2 )
53519 : {
53520 0 : wastranspose = ae_true;
53521 0 : ae_matrix_set_length(z, n+1, n+1, _state);
53522 0 : for(i=1; i<=n; i++)
53523 : {
53524 0 : for(j=1; j<=n; j++)
53525 : {
53526 0 : if( i==j )
53527 : {
53528 0 : z->ptr.pp_double[i][j] = (double)(1);
53529 : }
53530 : else
53531 : {
53532 0 : z->ptr.pp_double[i][j] = (double)(0);
53533 : }
53534 : }
53535 : }
53536 : }
53537 0 : if( zneeded==3 )
53538 : {
53539 0 : wastranspose = ae_false;
53540 0 : ae_matrix_set_length(z, 1+1, n+1, _state);
53541 0 : for(j=1; j<=n; j++)
53542 : {
53543 0 : if( j==1 )
53544 : {
53545 0 : z->ptr.pp_double[1][j] = (double)(1);
53546 : }
53547 : else
53548 : {
53549 0 : z->ptr.pp_double[1][j] = (double)(0);
53550 : }
53551 : }
53552 : }
53553 0 : nmaxit = n*maxit;
53554 0 : jtot = 0;
53555 :
53556 : /*
53557 : * Determine where the matrix splits and choose QL or QR iteration
53558 : * for each block, according to whether top or bottom diagonal
53559 : * element is smaller.
53560 : */
53561 0 : l1 = 1;
53562 0 : nm1 = n-1;
53563 : for(;;)
53564 : {
53565 0 : if( l1>n )
53566 : {
53567 0 : break;
53568 : }
53569 0 : if( l1>1 )
53570 : {
53571 0 : e->ptr.p_double[l1-1] = (double)(0);
53572 : }
53573 0 : gotoflag = ae_false;
53574 0 : m = l1;
53575 0 : if( l1<=nm1 )
53576 : {
53577 0 : for(m=l1; m<=nm1; m++)
53578 : {
53579 0 : tst = ae_fabs(e->ptr.p_double[m], _state);
53580 0 : if( ae_fp_eq(tst,(double)(0)) )
53581 : {
53582 0 : gotoflag = ae_true;
53583 0 : break;
53584 : }
53585 0 : if( ae_fp_less_eq(tst,ae_sqrt(ae_fabs(d->ptr.p_double[m], _state), _state)*ae_sqrt(ae_fabs(d->ptr.p_double[m+1], _state), _state)*eps) )
53586 : {
53587 0 : e->ptr.p_double[m] = (double)(0);
53588 0 : gotoflag = ae_true;
53589 0 : break;
53590 : }
53591 : }
53592 : }
53593 0 : if( !gotoflag )
53594 : {
53595 0 : m = n;
53596 : }
53597 :
53598 : /*
53599 : * label 30:
53600 : */
53601 0 : l = l1;
53602 0 : lsv = l;
53603 0 : lend = m;
53604 0 : lendsv = lend;
53605 0 : l1 = m+1;
53606 0 : if( lend==l )
53607 : {
53608 0 : continue;
53609 : }
53610 :
53611 : /*
53612 : * Scale submatrix in rows and columns L to LEND
53613 : */
53614 0 : if( l==lend )
53615 : {
53616 0 : anorm = ae_fabs(d->ptr.p_double[l], _state);
53617 : }
53618 : else
53619 : {
53620 0 : anorm = ae_maxreal(ae_fabs(d->ptr.p_double[l], _state)+ae_fabs(e->ptr.p_double[l], _state), ae_fabs(e->ptr.p_double[lend-1], _state)+ae_fabs(d->ptr.p_double[lend], _state), _state);
53621 0 : for(i=l+1; i<=lend-1; i++)
53622 : {
53623 0 : anorm = ae_maxreal(anorm, ae_fabs(d->ptr.p_double[i], _state)+ae_fabs(e->ptr.p_double[i], _state)+ae_fabs(e->ptr.p_double[i-1], _state), _state);
53624 : }
53625 : }
53626 0 : iscale = 0;
53627 0 : if( ae_fp_eq(anorm,(double)(0)) )
53628 : {
53629 0 : continue;
53630 : }
53631 0 : if( ae_fp_greater(anorm,ssfmax) )
53632 : {
53633 0 : iscale = 1;
53634 0 : tmp = ssfmax/anorm;
53635 0 : tmpint = lend-1;
53636 0 : ae_v_muld(&d->ptr.p_double[l], 1, ae_v_len(l,lend), tmp);
53637 0 : ae_v_muld(&e->ptr.p_double[l], 1, ae_v_len(l,tmpint), tmp);
53638 : }
53639 0 : if( ae_fp_less(anorm,ssfmin) )
53640 : {
53641 0 : iscale = 2;
53642 0 : tmp = ssfmin/anorm;
53643 0 : tmpint = lend-1;
53644 0 : ae_v_muld(&d->ptr.p_double[l], 1, ae_v_len(l,lend), tmp);
53645 0 : ae_v_muld(&e->ptr.p_double[l], 1, ae_v_len(l,tmpint), tmp);
53646 : }
53647 :
53648 : /*
53649 : * Choose between QL and QR iteration
53650 : */
53651 0 : if( ae_fp_less(ae_fabs(d->ptr.p_double[lend], _state),ae_fabs(d->ptr.p_double[l], _state)) )
53652 : {
53653 0 : lend = lsv;
53654 0 : l = lendsv;
53655 : }
53656 0 : if( lend>l )
53657 : {
53658 :
53659 : /*
53660 : * QL Iteration
53661 : *
53662 : * Look for small subdiagonal element.
53663 : */
53664 : for(;;)
53665 : {
53666 0 : gotoflag = ae_false;
53667 0 : if( l!=lend )
53668 : {
53669 0 : lendm1 = lend-1;
53670 0 : for(m=l; m<=lendm1; m++)
53671 : {
53672 0 : tst = ae_sqr(ae_fabs(e->ptr.p_double[m], _state), _state);
53673 0 : if( ae_fp_less_eq(tst,eps2*ae_fabs(d->ptr.p_double[m], _state)*ae_fabs(d->ptr.p_double[m+1], _state)+safmin) )
53674 : {
53675 0 : gotoflag = ae_true;
53676 0 : break;
53677 : }
53678 : }
53679 : }
53680 0 : if( !gotoflag )
53681 : {
53682 0 : m = lend;
53683 : }
53684 0 : if( m<lend )
53685 : {
53686 0 : e->ptr.p_double[m] = (double)(0);
53687 : }
53688 0 : p = d->ptr.p_double[l];
53689 0 : if( m!=l )
53690 : {
53691 :
53692 : /*
53693 : * If remaining matrix is 2-by-2, use DLAE2 or SLAEV2
53694 : * to compute its eigensystem.
53695 : */
53696 0 : if( m==l+1 )
53697 : {
53698 0 : if( zneeded>0 )
53699 : {
53700 0 : evd_tdevdev2(d->ptr.p_double[l], e->ptr.p_double[l], d->ptr.p_double[l+1], &rt1, &rt2, &c, &s, _state);
53701 0 : work1.ptr.p_double[l] = c;
53702 0 : work2.ptr.p_double[l] = s;
53703 0 : workc.ptr.p_double[1] = work1.ptr.p_double[l];
53704 0 : works.ptr.p_double[1] = work2.ptr.p_double[l];
53705 0 : if( !wastranspose )
53706 : {
53707 0 : applyrotationsfromtheright(ae_false, 1, zrows, l, l+1, &workc, &works, z, &wtemp, _state);
53708 : }
53709 : else
53710 : {
53711 0 : applyrotationsfromtheleft(ae_false, l, l+1, 1, zrows, &workc, &works, z, &wtemp, _state);
53712 : }
53713 : }
53714 : else
53715 : {
53716 0 : evd_tdevde2(d->ptr.p_double[l], e->ptr.p_double[l], d->ptr.p_double[l+1], &rt1, &rt2, _state);
53717 : }
53718 0 : d->ptr.p_double[l] = rt1;
53719 0 : d->ptr.p_double[l+1] = rt2;
53720 0 : e->ptr.p_double[l] = (double)(0);
53721 0 : l = l+2;
53722 0 : if( l<=lend )
53723 : {
53724 0 : continue;
53725 : }
53726 :
53727 : /*
53728 : * GOTO 140
53729 : */
53730 0 : break;
53731 : }
53732 0 : if( jtot==nmaxit )
53733 : {
53734 :
53735 : /*
53736 : * GOTO 140
53737 : */
53738 0 : break;
53739 : }
53740 0 : jtot = jtot+1;
53741 :
53742 : /*
53743 : * Form shift.
53744 : */
53745 0 : g = (d->ptr.p_double[l+1]-p)/(2*e->ptr.p_double[l]);
53746 0 : r = evd_tdevdpythag(g, (double)(1), _state);
53747 0 : g = d->ptr.p_double[m]-p+e->ptr.p_double[l]/(g+evd_tdevdextsign(r, g, _state));
53748 0 : s = (double)(1);
53749 0 : c = (double)(1);
53750 0 : p = (double)(0);
53751 :
53752 : /*
53753 : * Inner loop
53754 : */
53755 0 : mm1 = m-1;
53756 0 : for(i=mm1; i>=l; i--)
53757 : {
53758 0 : f = s*e->ptr.p_double[i];
53759 0 : b = c*e->ptr.p_double[i];
53760 0 : generaterotation(g, f, &c, &s, &r, _state);
53761 0 : if( i!=m-1 )
53762 : {
53763 0 : e->ptr.p_double[i+1] = r;
53764 : }
53765 0 : g = d->ptr.p_double[i+1]-p;
53766 0 : r = (d->ptr.p_double[i]-g)*s+2*c*b;
53767 0 : p = s*r;
53768 0 : d->ptr.p_double[i+1] = g+p;
53769 0 : g = c*r-b;
53770 :
53771 : /*
53772 : * If eigenvectors are desired, then save rotations.
53773 : */
53774 0 : if( zneeded>0 )
53775 : {
53776 0 : work1.ptr.p_double[i] = c;
53777 0 : work2.ptr.p_double[i] = -s;
53778 : }
53779 : }
53780 :
53781 : /*
53782 : * If eigenvectors are desired, then apply saved rotations.
53783 : */
53784 0 : if( zneeded>0 )
53785 : {
53786 0 : for(i=l; i<=m-1; i++)
53787 : {
53788 0 : workc.ptr.p_double[i-l+1] = work1.ptr.p_double[i];
53789 0 : works.ptr.p_double[i-l+1] = work2.ptr.p_double[i];
53790 : }
53791 0 : if( !wastranspose )
53792 : {
53793 0 : applyrotationsfromtheright(ae_false, 1, zrows, l, m, &workc, &works, z, &wtemp, _state);
53794 : }
53795 : else
53796 : {
53797 0 : applyrotationsfromtheleft(ae_false, l, m, 1, zrows, &workc, &works, z, &wtemp, _state);
53798 : }
53799 : }
53800 0 : d->ptr.p_double[l] = d->ptr.p_double[l]-p;
53801 0 : e->ptr.p_double[l] = g;
53802 0 : continue;
53803 : }
53804 :
53805 : /*
53806 : * Eigenvalue found.
53807 : */
53808 0 : d->ptr.p_double[l] = p;
53809 0 : l = l+1;
53810 0 : if( l<=lend )
53811 : {
53812 0 : continue;
53813 : }
53814 0 : break;
53815 : }
53816 : }
53817 : else
53818 : {
53819 :
53820 : /*
53821 : * QR Iteration
53822 : *
53823 : * Look for small superdiagonal element.
53824 : */
53825 : for(;;)
53826 : {
53827 0 : gotoflag = ae_false;
53828 0 : if( l!=lend )
53829 : {
53830 0 : lendp1 = lend+1;
53831 0 : for(m=l; m>=lendp1; m--)
53832 : {
53833 0 : tst = ae_sqr(ae_fabs(e->ptr.p_double[m-1], _state), _state);
53834 0 : if( ae_fp_less_eq(tst,eps2*ae_fabs(d->ptr.p_double[m], _state)*ae_fabs(d->ptr.p_double[m-1], _state)+safmin) )
53835 : {
53836 0 : gotoflag = ae_true;
53837 0 : break;
53838 : }
53839 : }
53840 : }
53841 0 : if( !gotoflag )
53842 : {
53843 0 : m = lend;
53844 : }
53845 0 : if( m>lend )
53846 : {
53847 0 : e->ptr.p_double[m-1] = (double)(0);
53848 : }
53849 0 : p = d->ptr.p_double[l];
53850 0 : if( m!=l )
53851 : {
53852 :
53853 : /*
53854 : * If remaining matrix is 2-by-2, use DLAE2 or SLAEV2
53855 : * to compute its eigensystem.
53856 : */
53857 0 : if( m==l-1 )
53858 : {
53859 0 : if( zneeded>0 )
53860 : {
53861 0 : evd_tdevdev2(d->ptr.p_double[l-1], e->ptr.p_double[l-1], d->ptr.p_double[l], &rt1, &rt2, &c, &s, _state);
53862 0 : work1.ptr.p_double[m] = c;
53863 0 : work2.ptr.p_double[m] = s;
53864 0 : workc.ptr.p_double[1] = c;
53865 0 : works.ptr.p_double[1] = s;
53866 0 : if( !wastranspose )
53867 : {
53868 0 : applyrotationsfromtheright(ae_true, 1, zrows, l-1, l, &workc, &works, z, &wtemp, _state);
53869 : }
53870 : else
53871 : {
53872 0 : applyrotationsfromtheleft(ae_true, l-1, l, 1, zrows, &workc, &works, z, &wtemp, _state);
53873 : }
53874 : }
53875 : else
53876 : {
53877 0 : evd_tdevde2(d->ptr.p_double[l-1], e->ptr.p_double[l-1], d->ptr.p_double[l], &rt1, &rt2, _state);
53878 : }
53879 0 : d->ptr.p_double[l-1] = rt1;
53880 0 : d->ptr.p_double[l] = rt2;
53881 0 : e->ptr.p_double[l-1] = (double)(0);
53882 0 : l = l-2;
53883 0 : if( l>=lend )
53884 : {
53885 0 : continue;
53886 : }
53887 0 : break;
53888 : }
53889 0 : if( jtot==nmaxit )
53890 : {
53891 0 : break;
53892 : }
53893 0 : jtot = jtot+1;
53894 :
53895 : /*
53896 : * Form shift.
53897 : */
53898 0 : g = (d->ptr.p_double[l-1]-p)/(2*e->ptr.p_double[l-1]);
53899 0 : r = evd_tdevdpythag(g, (double)(1), _state);
53900 0 : g = d->ptr.p_double[m]-p+e->ptr.p_double[l-1]/(g+evd_tdevdextsign(r, g, _state));
53901 0 : s = (double)(1);
53902 0 : c = (double)(1);
53903 0 : p = (double)(0);
53904 :
53905 : /*
53906 : * Inner loop
53907 : */
53908 0 : lm1 = l-1;
53909 0 : for(i=m; i<=lm1; i++)
53910 : {
53911 0 : f = s*e->ptr.p_double[i];
53912 0 : b = c*e->ptr.p_double[i];
53913 0 : generaterotation(g, f, &c, &s, &r, _state);
53914 0 : if( i!=m )
53915 : {
53916 0 : e->ptr.p_double[i-1] = r;
53917 : }
53918 0 : g = d->ptr.p_double[i]-p;
53919 0 : r = (d->ptr.p_double[i+1]-g)*s+2*c*b;
53920 0 : p = s*r;
53921 0 : d->ptr.p_double[i] = g+p;
53922 0 : g = c*r-b;
53923 :
53924 : /*
53925 : * If eigenvectors are desired, then save rotations.
53926 : */
53927 0 : if( zneeded>0 )
53928 : {
53929 0 : work1.ptr.p_double[i] = c;
53930 0 : work2.ptr.p_double[i] = s;
53931 : }
53932 : }
53933 :
53934 : /*
53935 : * If eigenvectors are desired, then apply saved rotations.
53936 : */
53937 0 : if( zneeded>0 )
53938 : {
53939 0 : for(i=m; i<=l-1; i++)
53940 : {
53941 0 : workc.ptr.p_double[i-m+1] = work1.ptr.p_double[i];
53942 0 : works.ptr.p_double[i-m+1] = work2.ptr.p_double[i];
53943 : }
53944 0 : if( !wastranspose )
53945 : {
53946 0 : applyrotationsfromtheright(ae_true, 1, zrows, m, l, &workc, &works, z, &wtemp, _state);
53947 : }
53948 : else
53949 : {
53950 0 : applyrotationsfromtheleft(ae_true, m, l, 1, zrows, &workc, &works, z, &wtemp, _state);
53951 : }
53952 : }
53953 0 : d->ptr.p_double[l] = d->ptr.p_double[l]-p;
53954 0 : e->ptr.p_double[lm1] = g;
53955 0 : continue;
53956 : }
53957 :
53958 : /*
53959 : * Eigenvalue found.
53960 : */
53961 0 : d->ptr.p_double[l] = p;
53962 0 : l = l-1;
53963 0 : if( l>=lend )
53964 : {
53965 0 : continue;
53966 : }
53967 0 : break;
53968 : }
53969 : }
53970 :
53971 : /*
53972 : * Undo scaling if necessary
53973 : */
53974 0 : if( iscale==1 )
53975 : {
53976 0 : tmp = anorm/ssfmax;
53977 0 : tmpint = lendsv-1;
53978 0 : ae_v_muld(&d->ptr.p_double[lsv], 1, ae_v_len(lsv,lendsv), tmp);
53979 0 : ae_v_muld(&e->ptr.p_double[lsv], 1, ae_v_len(lsv,tmpint), tmp);
53980 : }
53981 0 : if( iscale==2 )
53982 : {
53983 0 : tmp = anorm/ssfmin;
53984 0 : tmpint = lendsv-1;
53985 0 : ae_v_muld(&d->ptr.p_double[lsv], 1, ae_v_len(lsv,lendsv), tmp);
53986 0 : ae_v_muld(&e->ptr.p_double[lsv], 1, ae_v_len(lsv,tmpint), tmp);
53987 : }
53988 :
53989 : /*
53990 : * Check for no convergence to an eigenvalue after a total
53991 : * of N*MAXIT iterations.
53992 : */
53993 0 : if( jtot>=nmaxit )
53994 : {
53995 0 : result = ae_false;
53996 0 : if( wastranspose )
53997 : {
53998 0 : inplacetranspose(z, 1, n, 1, n, &wtemp, _state);
53999 : }
54000 0 : ae_frame_leave(_state);
54001 0 : return result;
54002 : }
54003 : }
54004 :
54005 : /*
54006 : * Order eigenvalues and eigenvectors.
54007 : */
54008 0 : if( zneeded==0 )
54009 : {
54010 :
54011 : /*
54012 : * Sort
54013 : */
54014 0 : if( n==1 )
54015 : {
54016 0 : ae_frame_leave(_state);
54017 0 : return result;
54018 : }
54019 0 : if( n==2 )
54020 : {
54021 0 : if( ae_fp_greater(d->ptr.p_double[1],d->ptr.p_double[2]) )
54022 : {
54023 0 : tmp = d->ptr.p_double[1];
54024 0 : d->ptr.p_double[1] = d->ptr.p_double[2];
54025 0 : d->ptr.p_double[2] = tmp;
54026 : }
54027 0 : ae_frame_leave(_state);
54028 0 : return result;
54029 : }
54030 0 : i = 2;
54031 0 : do
54032 : {
54033 0 : t = i;
54034 0 : while(t!=1)
54035 : {
54036 0 : k = t/2;
54037 0 : if( ae_fp_greater_eq(d->ptr.p_double[k],d->ptr.p_double[t]) )
54038 : {
54039 0 : t = 1;
54040 : }
54041 : else
54042 : {
54043 0 : tmp = d->ptr.p_double[k];
54044 0 : d->ptr.p_double[k] = d->ptr.p_double[t];
54045 0 : d->ptr.p_double[t] = tmp;
54046 0 : t = k;
54047 : }
54048 : }
54049 0 : i = i+1;
54050 : }
54051 0 : while(i<=n);
54052 0 : i = n-1;
54053 0 : do
54054 : {
54055 0 : tmp = d->ptr.p_double[i+1];
54056 0 : d->ptr.p_double[i+1] = d->ptr.p_double[1];
54057 0 : d->ptr.p_double[1] = tmp;
54058 0 : t = 1;
54059 0 : while(t!=0)
54060 : {
54061 0 : k = 2*t;
54062 0 : if( k>i )
54063 : {
54064 0 : t = 0;
54065 : }
54066 : else
54067 : {
54068 0 : if( k<i )
54069 : {
54070 0 : if( ae_fp_greater(d->ptr.p_double[k+1],d->ptr.p_double[k]) )
54071 : {
54072 0 : k = k+1;
54073 : }
54074 : }
54075 0 : if( ae_fp_greater_eq(d->ptr.p_double[t],d->ptr.p_double[k]) )
54076 : {
54077 0 : t = 0;
54078 : }
54079 : else
54080 : {
54081 0 : tmp = d->ptr.p_double[k];
54082 0 : d->ptr.p_double[k] = d->ptr.p_double[t];
54083 0 : d->ptr.p_double[t] = tmp;
54084 0 : t = k;
54085 : }
54086 : }
54087 : }
54088 0 : i = i-1;
54089 : }
54090 0 : while(i>=1);
54091 : }
54092 : else
54093 : {
54094 :
54095 : /*
54096 : * Use Selection Sort to minimize swaps of eigenvectors
54097 : */
54098 0 : for(ii=2; ii<=n; ii++)
54099 : {
54100 0 : i = ii-1;
54101 0 : k = i;
54102 0 : p = d->ptr.p_double[i];
54103 0 : for(j=ii; j<=n; j++)
54104 : {
54105 0 : if( ae_fp_less(d->ptr.p_double[j],p) )
54106 : {
54107 0 : k = j;
54108 0 : p = d->ptr.p_double[j];
54109 : }
54110 : }
54111 0 : if( k!=i )
54112 : {
54113 0 : d->ptr.p_double[k] = d->ptr.p_double[i];
54114 0 : d->ptr.p_double[i] = p;
54115 0 : if( wastranspose )
54116 : {
54117 0 : ae_v_move(&wtemp.ptr.p_double[1], 1, &z->ptr.pp_double[i][1], 1, ae_v_len(1,n));
54118 0 : ae_v_move(&z->ptr.pp_double[i][1], 1, &z->ptr.pp_double[k][1], 1, ae_v_len(1,n));
54119 0 : ae_v_move(&z->ptr.pp_double[k][1], 1, &wtemp.ptr.p_double[1], 1, ae_v_len(1,n));
54120 : }
54121 : else
54122 : {
54123 0 : ae_v_move(&wtemp.ptr.p_double[1], 1, &z->ptr.pp_double[1][i], z->stride, ae_v_len(1,zrows));
54124 0 : ae_v_move(&z->ptr.pp_double[1][i], z->stride, &z->ptr.pp_double[1][k], z->stride, ae_v_len(1,zrows));
54125 0 : ae_v_move(&z->ptr.pp_double[1][k], z->stride, &wtemp.ptr.p_double[1], 1, ae_v_len(1,zrows));
54126 : }
54127 : }
54128 : }
54129 0 : if( wastranspose )
54130 : {
54131 0 : inplacetranspose(z, 1, n, 1, n, &wtemp, _state);
54132 : }
54133 : }
54134 0 : ae_frame_leave(_state);
54135 0 : return result;
54136 : }
54137 :
54138 :
54139 : /*************************************************************************
54140 : DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix
54141 : [ A B ]
54142 : [ B C ].
54143 : On return, RT1 is the eigenvalue of larger absolute value, and RT2
54144 : is the eigenvalue of smaller absolute value.
54145 :
54146 : -- LAPACK auxiliary routine (version 3.0) --
54147 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
54148 : Courant Institute, Argonne National Lab, and Rice University
54149 : October 31, 1992
54150 : *************************************************************************/
54151 0 : static void evd_tdevde2(double a,
54152 : double b,
54153 : double c,
54154 : double* rt1,
54155 : double* rt2,
54156 : ae_state *_state)
54157 : {
54158 : double ab;
54159 : double acmn;
54160 : double acmx;
54161 : double adf;
54162 : double df;
54163 : double rt;
54164 : double sm;
54165 : double tb;
54166 :
54167 0 : *rt1 = 0;
54168 0 : *rt2 = 0;
54169 :
54170 0 : sm = a+c;
54171 0 : df = a-c;
54172 0 : adf = ae_fabs(df, _state);
54173 0 : tb = b+b;
54174 0 : ab = ae_fabs(tb, _state);
54175 0 : if( ae_fp_greater(ae_fabs(a, _state),ae_fabs(c, _state)) )
54176 : {
54177 0 : acmx = a;
54178 0 : acmn = c;
54179 : }
54180 : else
54181 : {
54182 0 : acmx = c;
54183 0 : acmn = a;
54184 : }
54185 0 : if( ae_fp_greater(adf,ab) )
54186 : {
54187 0 : rt = adf*ae_sqrt(1+ae_sqr(ab/adf, _state), _state);
54188 : }
54189 : else
54190 : {
54191 0 : if( ae_fp_less(adf,ab) )
54192 : {
54193 0 : rt = ab*ae_sqrt(1+ae_sqr(adf/ab, _state), _state);
54194 : }
54195 : else
54196 : {
54197 :
54198 : /*
54199 : * Includes case AB=ADF=0
54200 : */
54201 0 : rt = ab*ae_sqrt((double)(2), _state);
54202 : }
54203 : }
54204 0 : if( ae_fp_less(sm,(double)(0)) )
54205 : {
54206 0 : *rt1 = 0.5*(sm-rt);
54207 :
54208 : /*
54209 : * Order of execution important.
54210 : * To get fully accurate smaller eigenvalue,
54211 : * next line needs to be executed in higher precision.
54212 : */
54213 0 : *rt2 = acmx/(*rt1)*acmn-b/(*rt1)*b;
54214 : }
54215 : else
54216 : {
54217 0 : if( ae_fp_greater(sm,(double)(0)) )
54218 : {
54219 0 : *rt1 = 0.5*(sm+rt);
54220 :
54221 : /*
54222 : * Order of execution important.
54223 : * To get fully accurate smaller eigenvalue,
54224 : * next line needs to be executed in higher precision.
54225 : */
54226 0 : *rt2 = acmx/(*rt1)*acmn-b/(*rt1)*b;
54227 : }
54228 : else
54229 : {
54230 :
54231 : /*
54232 : * Includes case RT1 = RT2 = 0
54233 : */
54234 0 : *rt1 = 0.5*rt;
54235 0 : *rt2 = -0.5*rt;
54236 : }
54237 : }
54238 0 : }
54239 :
54240 :
54241 : /*************************************************************************
54242 : DLAEV2 computes the eigendecomposition of a 2-by-2 symmetric matrix
54243 :
54244 : [ A B ]
54245 : [ B C ].
54246 :
54247 : On return, RT1 is the eigenvalue of larger absolute value, RT2 is the
54248 : eigenvalue of smaller absolute value, and (CS1,SN1) is the unit right
54249 : eigenvector for RT1, giving the decomposition
54250 :
54251 : [ CS1 SN1 ] [ A B ] [ CS1 -SN1 ] = [ RT1 0 ]
54252 : [-SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ].
54253 :
54254 :
54255 : -- LAPACK auxiliary routine (version 3.0) --
54256 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
54257 : Courant Institute, Argonne National Lab, and Rice University
54258 : October 31, 1992
54259 : *************************************************************************/
54260 0 : static void evd_tdevdev2(double a,
54261 : double b,
54262 : double c,
54263 : double* rt1,
54264 : double* rt2,
54265 : double* cs1,
54266 : double* sn1,
54267 : ae_state *_state)
54268 : {
54269 : ae_int_t sgn1;
54270 : ae_int_t sgn2;
54271 : double ab;
54272 : double acmn;
54273 : double acmx;
54274 : double acs;
54275 : double adf;
54276 : double cs;
54277 : double ct;
54278 : double df;
54279 : double rt;
54280 : double sm;
54281 : double tb;
54282 : double tn;
54283 :
54284 0 : *rt1 = 0;
54285 0 : *rt2 = 0;
54286 0 : *cs1 = 0;
54287 0 : *sn1 = 0;
54288 :
54289 :
54290 : /*
54291 : * Compute the eigenvalues
54292 : */
54293 0 : sm = a+c;
54294 0 : df = a-c;
54295 0 : adf = ae_fabs(df, _state);
54296 0 : tb = b+b;
54297 0 : ab = ae_fabs(tb, _state);
54298 0 : if( ae_fp_greater(ae_fabs(a, _state),ae_fabs(c, _state)) )
54299 : {
54300 0 : acmx = a;
54301 0 : acmn = c;
54302 : }
54303 : else
54304 : {
54305 0 : acmx = c;
54306 0 : acmn = a;
54307 : }
54308 0 : if( ae_fp_greater(adf,ab) )
54309 : {
54310 0 : rt = adf*ae_sqrt(1+ae_sqr(ab/adf, _state), _state);
54311 : }
54312 : else
54313 : {
54314 0 : if( ae_fp_less(adf,ab) )
54315 : {
54316 0 : rt = ab*ae_sqrt(1+ae_sqr(adf/ab, _state), _state);
54317 : }
54318 : else
54319 : {
54320 :
54321 : /*
54322 : * Includes case AB=ADF=0
54323 : */
54324 0 : rt = ab*ae_sqrt((double)(2), _state);
54325 : }
54326 : }
54327 0 : if( ae_fp_less(sm,(double)(0)) )
54328 : {
54329 0 : *rt1 = 0.5*(sm-rt);
54330 0 : sgn1 = -1;
54331 :
54332 : /*
54333 : * Order of execution important.
54334 : * To get fully accurate smaller eigenvalue,
54335 : * next line needs to be executed in higher precision.
54336 : */
54337 0 : *rt2 = acmx/(*rt1)*acmn-b/(*rt1)*b;
54338 : }
54339 : else
54340 : {
54341 0 : if( ae_fp_greater(sm,(double)(0)) )
54342 : {
54343 0 : *rt1 = 0.5*(sm+rt);
54344 0 : sgn1 = 1;
54345 :
54346 : /*
54347 : * Order of execution important.
54348 : * To get fully accurate smaller eigenvalue,
54349 : * next line needs to be executed in higher precision.
54350 : */
54351 0 : *rt2 = acmx/(*rt1)*acmn-b/(*rt1)*b;
54352 : }
54353 : else
54354 : {
54355 :
54356 : /*
54357 : * Includes case RT1 = RT2 = 0
54358 : */
54359 0 : *rt1 = 0.5*rt;
54360 0 : *rt2 = -0.5*rt;
54361 0 : sgn1 = 1;
54362 : }
54363 : }
54364 :
54365 : /*
54366 : * Compute the eigenvector
54367 : */
54368 0 : if( ae_fp_greater_eq(df,(double)(0)) )
54369 : {
54370 0 : cs = df+rt;
54371 0 : sgn2 = 1;
54372 : }
54373 : else
54374 : {
54375 0 : cs = df-rt;
54376 0 : sgn2 = -1;
54377 : }
54378 0 : acs = ae_fabs(cs, _state);
54379 0 : if( ae_fp_greater(acs,ab) )
54380 : {
54381 0 : ct = -tb/cs;
54382 0 : *sn1 = 1/ae_sqrt(1+ct*ct, _state);
54383 0 : *cs1 = ct*(*sn1);
54384 : }
54385 : else
54386 : {
54387 0 : if( ae_fp_eq(ab,(double)(0)) )
54388 : {
54389 0 : *cs1 = (double)(1);
54390 0 : *sn1 = (double)(0);
54391 : }
54392 : else
54393 : {
54394 0 : tn = -cs/tb;
54395 0 : *cs1 = 1/ae_sqrt(1+tn*tn, _state);
54396 0 : *sn1 = tn*(*cs1);
54397 : }
54398 : }
54399 0 : if( sgn1==sgn2 )
54400 : {
54401 0 : tn = *cs1;
54402 0 : *cs1 = -*sn1;
54403 0 : *sn1 = tn;
54404 : }
54405 0 : }
54406 :
54407 :
54408 : /*************************************************************************
54409 : Internal routine
54410 : *************************************************************************/
54411 0 : static double evd_tdevdpythag(double a, double b, ae_state *_state)
54412 : {
54413 : double result;
54414 :
54415 :
54416 0 : if( ae_fp_less(ae_fabs(a, _state),ae_fabs(b, _state)) )
54417 : {
54418 0 : result = ae_fabs(b, _state)*ae_sqrt(1+ae_sqr(a/b, _state), _state);
54419 : }
54420 : else
54421 : {
54422 0 : result = ae_fabs(a, _state)*ae_sqrt(1+ae_sqr(b/a, _state), _state);
54423 : }
54424 0 : return result;
54425 : }
54426 :
54427 :
54428 : /*************************************************************************
54429 : Internal routine
54430 : *************************************************************************/
54431 0 : static double evd_tdevdextsign(double a, double b, ae_state *_state)
54432 : {
54433 : double result;
54434 :
54435 :
54436 0 : if( ae_fp_greater_eq(b,(double)(0)) )
54437 : {
54438 0 : result = ae_fabs(a, _state);
54439 : }
54440 : else
54441 : {
54442 0 : result = -ae_fabs(a, _state);
54443 : }
54444 0 : return result;
54445 : }
54446 :
54447 :
54448 0 : static ae_bool evd_internalbisectioneigenvalues(/* Real */ ae_vector* d,
54449 : /* Real */ ae_vector* e,
54450 : ae_int_t n,
54451 : ae_int_t irange,
54452 : ae_int_t iorder,
54453 : double vl,
54454 : double vu,
54455 : ae_int_t il,
54456 : ae_int_t iu,
54457 : double abstol,
54458 : /* Real */ ae_vector* w,
54459 : ae_int_t* m,
54460 : ae_int_t* nsplit,
54461 : /* Integer */ ae_vector* iblock,
54462 : /* Integer */ ae_vector* isplit,
54463 : ae_int_t* errorcode,
54464 : ae_state *_state)
54465 : {
54466 : ae_frame _frame_block;
54467 : ae_vector _d;
54468 : ae_vector _e;
54469 : double fudge;
54470 : double relfac;
54471 : ae_bool ncnvrg;
54472 : ae_bool toofew;
54473 : ae_int_t ib;
54474 : ae_int_t ibegin;
54475 : ae_int_t idiscl;
54476 : ae_int_t idiscu;
54477 : ae_int_t ie;
54478 : ae_int_t iend;
54479 : ae_int_t iinfo;
54480 : ae_int_t im;
54481 : ae_int_t iin;
54482 : ae_int_t ioff;
54483 : ae_int_t iout;
54484 : ae_int_t itmax;
54485 : ae_int_t iw;
54486 : ae_int_t iwoff;
54487 : ae_int_t j;
54488 : ae_int_t itmp1;
54489 : ae_int_t jb;
54490 : ae_int_t jdisc;
54491 : ae_int_t je;
54492 : ae_int_t nwl;
54493 : ae_int_t nwu;
54494 : double atoli;
54495 : double bnorm;
54496 : double gl;
54497 : double gu;
54498 : double pivmin;
54499 : double rtoli;
54500 : double safemn;
54501 : double tmp1;
54502 : double tmp2;
54503 : double tnorm;
54504 : double ulp;
54505 : double wkill;
54506 : double wl;
54507 : double wlu;
54508 : double wu;
54509 : double wul;
54510 : double scalefactor;
54511 : double t;
54512 : ae_vector idumma;
54513 : ae_vector work;
54514 : ae_vector iwork;
54515 : ae_vector ia1s2;
54516 : ae_vector ra1s2;
54517 : ae_matrix ra1s2x2;
54518 : ae_matrix ia1s2x2;
54519 : ae_vector ra1siin;
54520 : ae_vector ra2siin;
54521 : ae_vector ra3siin;
54522 : ae_vector ra4siin;
54523 : ae_matrix ra1siinx2;
54524 : ae_matrix ia1siinx2;
54525 : ae_vector iworkspace;
54526 : ae_vector rworkspace;
54527 : ae_int_t tmpi;
54528 : ae_bool result;
54529 :
54530 0 : ae_frame_make(_state, &_frame_block);
54531 0 : memset(&_d, 0, sizeof(_d));
54532 0 : memset(&_e, 0, sizeof(_e));
54533 0 : memset(&idumma, 0, sizeof(idumma));
54534 0 : memset(&work, 0, sizeof(work));
54535 0 : memset(&iwork, 0, sizeof(iwork));
54536 0 : memset(&ia1s2, 0, sizeof(ia1s2));
54537 0 : memset(&ra1s2, 0, sizeof(ra1s2));
54538 0 : memset(&ra1s2x2, 0, sizeof(ra1s2x2));
54539 0 : memset(&ia1s2x2, 0, sizeof(ia1s2x2));
54540 0 : memset(&ra1siin, 0, sizeof(ra1siin));
54541 0 : memset(&ra2siin, 0, sizeof(ra2siin));
54542 0 : memset(&ra3siin, 0, sizeof(ra3siin));
54543 0 : memset(&ra4siin, 0, sizeof(ra4siin));
54544 0 : memset(&ra1siinx2, 0, sizeof(ra1siinx2));
54545 0 : memset(&ia1siinx2, 0, sizeof(ia1siinx2));
54546 0 : memset(&iworkspace, 0, sizeof(iworkspace));
54547 0 : memset(&rworkspace, 0, sizeof(rworkspace));
54548 0 : ae_vector_init_copy(&_d, d, _state, ae_true);
54549 0 : d = &_d;
54550 0 : ae_vector_init_copy(&_e, e, _state, ae_true);
54551 0 : e = &_e;
54552 0 : ae_vector_clear(w);
54553 0 : *m = 0;
54554 0 : *nsplit = 0;
54555 0 : ae_vector_clear(iblock);
54556 0 : ae_vector_clear(isplit);
54557 0 : *errorcode = 0;
54558 0 : ae_vector_init(&idumma, 0, DT_INT, _state, ae_true);
54559 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
54560 0 : ae_vector_init(&iwork, 0, DT_INT, _state, ae_true);
54561 0 : ae_vector_init(&ia1s2, 0, DT_INT, _state, ae_true);
54562 0 : ae_vector_init(&ra1s2, 0, DT_REAL, _state, ae_true);
54563 0 : ae_matrix_init(&ra1s2x2, 0, 0, DT_REAL, _state, ae_true);
54564 0 : ae_matrix_init(&ia1s2x2, 0, 0, DT_INT, _state, ae_true);
54565 0 : ae_vector_init(&ra1siin, 0, DT_REAL, _state, ae_true);
54566 0 : ae_vector_init(&ra2siin, 0, DT_REAL, _state, ae_true);
54567 0 : ae_vector_init(&ra3siin, 0, DT_REAL, _state, ae_true);
54568 0 : ae_vector_init(&ra4siin, 0, DT_REAL, _state, ae_true);
54569 0 : ae_matrix_init(&ra1siinx2, 0, 0, DT_REAL, _state, ae_true);
54570 0 : ae_matrix_init(&ia1siinx2, 0, 0, DT_INT, _state, ae_true);
54571 0 : ae_vector_init(&iworkspace, 0, DT_INT, _state, ae_true);
54572 0 : ae_vector_init(&rworkspace, 0, DT_REAL, _state, ae_true);
54573 :
54574 :
54575 : /*
54576 : * Quick return if possible
54577 : */
54578 0 : *m = 0;
54579 0 : if( n==0 )
54580 : {
54581 0 : result = ae_true;
54582 0 : ae_frame_leave(_state);
54583 0 : return result;
54584 : }
54585 :
54586 : /*
54587 : * Get machine constants
54588 : * NB is the minimum vector length for vector bisection, or 0
54589 : * if only scalar is to be done.
54590 : */
54591 0 : fudge = (double)(2);
54592 0 : relfac = (double)(2);
54593 0 : safemn = ae_minrealnumber;
54594 0 : ulp = 2*ae_machineepsilon;
54595 0 : rtoli = ulp*relfac;
54596 0 : ae_vector_set_length(&idumma, 1+1, _state);
54597 0 : ae_vector_set_length(&work, 4*n+1, _state);
54598 0 : ae_vector_set_length(&iwork, 3*n+1, _state);
54599 0 : ae_vector_set_length(w, n+1, _state);
54600 0 : ae_vector_set_length(iblock, n+1, _state);
54601 0 : ae_vector_set_length(isplit, n+1, _state);
54602 0 : ae_vector_set_length(&ia1s2, 2+1, _state);
54603 0 : ae_vector_set_length(&ra1s2, 2+1, _state);
54604 0 : ae_matrix_set_length(&ra1s2x2, 2+1, 2+1, _state);
54605 0 : ae_matrix_set_length(&ia1s2x2, 2+1, 2+1, _state);
54606 0 : ae_vector_set_length(&ra1siin, n+1, _state);
54607 0 : ae_vector_set_length(&ra2siin, n+1, _state);
54608 0 : ae_vector_set_length(&ra3siin, n+1, _state);
54609 0 : ae_vector_set_length(&ra4siin, n+1, _state);
54610 0 : ae_matrix_set_length(&ra1siinx2, n+1, 2+1, _state);
54611 0 : ae_matrix_set_length(&ia1siinx2, n+1, 2+1, _state);
54612 0 : ae_vector_set_length(&iworkspace, n+1, _state);
54613 0 : ae_vector_set_length(&rworkspace, n+1, _state);
54614 :
54615 : /*
54616 : * these initializers are not really necessary,
54617 : * but without them compiler complains about uninitialized locals
54618 : */
54619 0 : wlu = (double)(0);
54620 0 : wul = (double)(0);
54621 :
54622 : /*
54623 : * Check for Errors
54624 : */
54625 0 : result = ae_false;
54626 0 : *errorcode = 0;
54627 0 : if( irange<=0||irange>=4 )
54628 : {
54629 0 : *errorcode = -4;
54630 : }
54631 0 : if( iorder<=0||iorder>=3 )
54632 : {
54633 0 : *errorcode = -5;
54634 : }
54635 0 : if( n<0 )
54636 : {
54637 0 : *errorcode = -3;
54638 : }
54639 0 : if( irange==2&&ae_fp_greater_eq(vl,vu) )
54640 : {
54641 0 : *errorcode = -6;
54642 : }
54643 0 : if( irange==3&&(il<1||il>ae_maxint(1, n, _state)) )
54644 : {
54645 0 : *errorcode = -8;
54646 : }
54647 0 : if( irange==3&&(iu<ae_minint(n, il, _state)||iu>n) )
54648 : {
54649 0 : *errorcode = -9;
54650 : }
54651 0 : if( *errorcode!=0 )
54652 : {
54653 0 : ae_frame_leave(_state);
54654 0 : return result;
54655 : }
54656 :
54657 : /*
54658 : * Initialize error flags
54659 : */
54660 0 : ncnvrg = ae_false;
54661 0 : toofew = ae_false;
54662 :
54663 : /*
54664 : * Simplifications:
54665 : */
54666 0 : if( (irange==3&&il==1)&&iu==n )
54667 : {
54668 0 : irange = 1;
54669 : }
54670 :
54671 : /*
54672 : * Special Case when N=1
54673 : */
54674 0 : if( n==1 )
54675 : {
54676 0 : *nsplit = 1;
54677 0 : isplit->ptr.p_int[1] = 1;
54678 0 : if( irange==2&&(ae_fp_greater_eq(vl,d->ptr.p_double[1])||ae_fp_less(vu,d->ptr.p_double[1])) )
54679 : {
54680 0 : *m = 0;
54681 : }
54682 : else
54683 : {
54684 0 : w->ptr.p_double[1] = d->ptr.p_double[1];
54685 0 : iblock->ptr.p_int[1] = 1;
54686 0 : *m = 1;
54687 : }
54688 0 : result = ae_true;
54689 0 : ae_frame_leave(_state);
54690 0 : return result;
54691 : }
54692 :
54693 : /*
54694 : * Scaling
54695 : */
54696 0 : t = ae_fabs(d->ptr.p_double[n], _state);
54697 0 : for(j=1; j<=n-1; j++)
54698 : {
54699 0 : t = ae_maxreal(t, ae_fabs(d->ptr.p_double[j], _state), _state);
54700 0 : t = ae_maxreal(t, ae_fabs(e->ptr.p_double[j], _state), _state);
54701 : }
54702 0 : scalefactor = (double)(1);
54703 0 : if( ae_fp_neq(t,(double)(0)) )
54704 : {
54705 0 : if( ae_fp_greater(t,ae_sqrt(ae_sqrt(ae_minrealnumber, _state), _state)*ae_sqrt(ae_maxrealnumber, _state)) )
54706 : {
54707 0 : scalefactor = t;
54708 : }
54709 0 : if( ae_fp_less(t,ae_sqrt(ae_sqrt(ae_maxrealnumber, _state), _state)*ae_sqrt(ae_minrealnumber, _state)) )
54710 : {
54711 0 : scalefactor = t;
54712 : }
54713 0 : for(j=1; j<=n-1; j++)
54714 : {
54715 0 : d->ptr.p_double[j] = d->ptr.p_double[j]/scalefactor;
54716 0 : e->ptr.p_double[j] = e->ptr.p_double[j]/scalefactor;
54717 : }
54718 0 : d->ptr.p_double[n] = d->ptr.p_double[n]/scalefactor;
54719 : }
54720 :
54721 : /*
54722 : * Compute Splitting Points
54723 : */
54724 0 : *nsplit = 1;
54725 0 : work.ptr.p_double[n] = (double)(0);
54726 0 : pivmin = (double)(1);
54727 0 : for(j=2; j<=n; j++)
54728 : {
54729 0 : tmp1 = ae_sqr(e->ptr.p_double[j-1], _state);
54730 0 : if( ae_fp_greater(ae_fabs(d->ptr.p_double[j]*d->ptr.p_double[j-1], _state)*ae_sqr(ulp, _state)+safemn,tmp1) )
54731 : {
54732 0 : isplit->ptr.p_int[*nsplit] = j-1;
54733 0 : *nsplit = *nsplit+1;
54734 0 : work.ptr.p_double[j-1] = (double)(0);
54735 : }
54736 : else
54737 : {
54738 0 : work.ptr.p_double[j-1] = tmp1;
54739 0 : pivmin = ae_maxreal(pivmin, tmp1, _state);
54740 : }
54741 : }
54742 0 : isplit->ptr.p_int[*nsplit] = n;
54743 0 : pivmin = pivmin*safemn;
54744 :
54745 : /*
54746 : * Compute Interval and ATOLI
54747 : */
54748 0 : if( irange==3 )
54749 : {
54750 :
54751 : /*
54752 : * RANGE='I': Compute the interval containing eigenvalues
54753 : * IL through IU.
54754 : *
54755 : * Compute Gershgorin interval for entire (split) matrix
54756 : * and use it as the initial interval
54757 : */
54758 0 : gu = d->ptr.p_double[1];
54759 0 : gl = d->ptr.p_double[1];
54760 0 : tmp1 = (double)(0);
54761 0 : for(j=1; j<=n-1; j++)
54762 : {
54763 0 : tmp2 = ae_sqrt(work.ptr.p_double[j], _state);
54764 0 : gu = ae_maxreal(gu, d->ptr.p_double[j]+tmp1+tmp2, _state);
54765 0 : gl = ae_minreal(gl, d->ptr.p_double[j]-tmp1-tmp2, _state);
54766 0 : tmp1 = tmp2;
54767 : }
54768 0 : gu = ae_maxreal(gu, d->ptr.p_double[n]+tmp1, _state);
54769 0 : gl = ae_minreal(gl, d->ptr.p_double[n]-tmp1, _state);
54770 0 : tnorm = ae_maxreal(ae_fabs(gl, _state), ae_fabs(gu, _state), _state);
54771 0 : gl = gl-fudge*tnorm*ulp*n-fudge*2*pivmin;
54772 0 : gu = gu+fudge*tnorm*ulp*n+fudge*pivmin;
54773 :
54774 : /*
54775 : * Compute Iteration parameters
54776 : */
54777 0 : itmax = ae_iceil((ae_log(tnorm+pivmin, _state)-ae_log(pivmin, _state))/ae_log((double)(2), _state), _state)+2;
54778 0 : if( ae_fp_less_eq(abstol,(double)(0)) )
54779 : {
54780 0 : atoli = ulp*tnorm;
54781 : }
54782 : else
54783 : {
54784 0 : atoli = abstol;
54785 : }
54786 0 : work.ptr.p_double[n+1] = gl;
54787 0 : work.ptr.p_double[n+2] = gl;
54788 0 : work.ptr.p_double[n+3] = gu;
54789 0 : work.ptr.p_double[n+4] = gu;
54790 0 : work.ptr.p_double[n+5] = gl;
54791 0 : work.ptr.p_double[n+6] = gu;
54792 0 : iwork.ptr.p_int[1] = -1;
54793 0 : iwork.ptr.p_int[2] = -1;
54794 0 : iwork.ptr.p_int[3] = n+1;
54795 0 : iwork.ptr.p_int[4] = n+1;
54796 0 : iwork.ptr.p_int[5] = il-1;
54797 0 : iwork.ptr.p_int[6] = iu;
54798 :
54799 : /*
54800 : * Calling DLAEBZ
54801 : *
54802 : * DLAEBZ( 3, ITMAX, N, 2, 2, NB, ATOLI, RTOLI, PIVMIN, D, E,
54803 : * WORK, IWORK( 5 ), WORK( N+1 ), WORK( N+5 ), IOUT,
54804 : * IWORK, W, IBLOCK, IINFO )
54805 : */
54806 0 : ia1s2.ptr.p_int[1] = iwork.ptr.p_int[5];
54807 0 : ia1s2.ptr.p_int[2] = iwork.ptr.p_int[6];
54808 0 : ra1s2.ptr.p_double[1] = work.ptr.p_double[n+5];
54809 0 : ra1s2.ptr.p_double[2] = work.ptr.p_double[n+6];
54810 0 : ra1s2x2.ptr.pp_double[1][1] = work.ptr.p_double[n+1];
54811 0 : ra1s2x2.ptr.pp_double[2][1] = work.ptr.p_double[n+2];
54812 0 : ra1s2x2.ptr.pp_double[1][2] = work.ptr.p_double[n+3];
54813 0 : ra1s2x2.ptr.pp_double[2][2] = work.ptr.p_double[n+4];
54814 0 : ia1s2x2.ptr.pp_int[1][1] = iwork.ptr.p_int[1];
54815 0 : ia1s2x2.ptr.pp_int[2][1] = iwork.ptr.p_int[2];
54816 0 : ia1s2x2.ptr.pp_int[1][2] = iwork.ptr.p_int[3];
54817 0 : ia1s2x2.ptr.pp_int[2][2] = iwork.ptr.p_int[4];
54818 0 : evd_internaldlaebz(3, itmax, n, 2, 2, atoli, rtoli, pivmin, d, e, &work, &ia1s2, &ra1s2x2, &ra1s2, &iout, &ia1s2x2, w, iblock, &iinfo, _state);
54819 0 : iwork.ptr.p_int[5] = ia1s2.ptr.p_int[1];
54820 0 : iwork.ptr.p_int[6] = ia1s2.ptr.p_int[2];
54821 0 : work.ptr.p_double[n+5] = ra1s2.ptr.p_double[1];
54822 0 : work.ptr.p_double[n+6] = ra1s2.ptr.p_double[2];
54823 0 : work.ptr.p_double[n+1] = ra1s2x2.ptr.pp_double[1][1];
54824 0 : work.ptr.p_double[n+2] = ra1s2x2.ptr.pp_double[2][1];
54825 0 : work.ptr.p_double[n+3] = ra1s2x2.ptr.pp_double[1][2];
54826 0 : work.ptr.p_double[n+4] = ra1s2x2.ptr.pp_double[2][2];
54827 0 : iwork.ptr.p_int[1] = ia1s2x2.ptr.pp_int[1][1];
54828 0 : iwork.ptr.p_int[2] = ia1s2x2.ptr.pp_int[2][1];
54829 0 : iwork.ptr.p_int[3] = ia1s2x2.ptr.pp_int[1][2];
54830 0 : iwork.ptr.p_int[4] = ia1s2x2.ptr.pp_int[2][2];
54831 0 : if( iwork.ptr.p_int[6]==iu )
54832 : {
54833 0 : wl = work.ptr.p_double[n+1];
54834 0 : wlu = work.ptr.p_double[n+3];
54835 0 : nwl = iwork.ptr.p_int[1];
54836 0 : wu = work.ptr.p_double[n+4];
54837 0 : wul = work.ptr.p_double[n+2];
54838 0 : nwu = iwork.ptr.p_int[4];
54839 : }
54840 : else
54841 : {
54842 0 : wl = work.ptr.p_double[n+2];
54843 0 : wlu = work.ptr.p_double[n+4];
54844 0 : nwl = iwork.ptr.p_int[2];
54845 0 : wu = work.ptr.p_double[n+3];
54846 0 : wul = work.ptr.p_double[n+1];
54847 0 : nwu = iwork.ptr.p_int[3];
54848 : }
54849 0 : if( ((nwl<0||nwl>=n)||nwu<1)||nwu>n )
54850 : {
54851 0 : *errorcode = 4;
54852 0 : result = ae_false;
54853 0 : ae_frame_leave(_state);
54854 0 : return result;
54855 : }
54856 : }
54857 : else
54858 : {
54859 :
54860 : /*
54861 : * RANGE='A' or 'V' -- Set ATOLI
54862 : */
54863 0 : tnorm = ae_maxreal(ae_fabs(d->ptr.p_double[1], _state)+ae_fabs(e->ptr.p_double[1], _state), ae_fabs(d->ptr.p_double[n], _state)+ae_fabs(e->ptr.p_double[n-1], _state), _state);
54864 0 : for(j=2; j<=n-1; j++)
54865 : {
54866 0 : tnorm = ae_maxreal(tnorm, ae_fabs(d->ptr.p_double[j], _state)+ae_fabs(e->ptr.p_double[j-1], _state)+ae_fabs(e->ptr.p_double[j], _state), _state);
54867 : }
54868 0 : if( ae_fp_less_eq(abstol,(double)(0)) )
54869 : {
54870 0 : atoli = ulp*tnorm;
54871 : }
54872 : else
54873 : {
54874 0 : atoli = abstol;
54875 : }
54876 0 : if( irange==2 )
54877 : {
54878 0 : wl = vl;
54879 0 : wu = vu;
54880 : }
54881 : else
54882 : {
54883 0 : wl = (double)(0);
54884 0 : wu = (double)(0);
54885 : }
54886 : }
54887 :
54888 : /*
54889 : * Find Eigenvalues -- Loop Over Blocks and recompute NWL and NWU.
54890 : * NWL accumulates the number of eigenvalues .le. WL,
54891 : * NWU accumulates the number of eigenvalues .le. WU
54892 : */
54893 0 : *m = 0;
54894 0 : iend = 0;
54895 0 : *errorcode = 0;
54896 0 : nwl = 0;
54897 0 : nwu = 0;
54898 0 : for(jb=1; jb<=*nsplit; jb++)
54899 : {
54900 0 : ioff = iend;
54901 0 : ibegin = ioff+1;
54902 0 : iend = isplit->ptr.p_int[jb];
54903 0 : iin = iend-ioff;
54904 0 : if( iin==1 )
54905 : {
54906 :
54907 : /*
54908 : * Special Case -- IIN=1
54909 : */
54910 0 : if( irange==1||ae_fp_greater_eq(wl,d->ptr.p_double[ibegin]-pivmin) )
54911 : {
54912 0 : nwl = nwl+1;
54913 : }
54914 0 : if( irange==1||ae_fp_greater_eq(wu,d->ptr.p_double[ibegin]-pivmin) )
54915 : {
54916 0 : nwu = nwu+1;
54917 : }
54918 0 : if( irange==1||(ae_fp_less(wl,d->ptr.p_double[ibegin]-pivmin)&&ae_fp_greater_eq(wu,d->ptr.p_double[ibegin]-pivmin)) )
54919 : {
54920 0 : *m = *m+1;
54921 0 : w->ptr.p_double[*m] = d->ptr.p_double[ibegin];
54922 0 : iblock->ptr.p_int[*m] = jb;
54923 : }
54924 : }
54925 : else
54926 : {
54927 :
54928 : /*
54929 : * General Case -- IIN > 1
54930 : *
54931 : * Compute Gershgorin Interval
54932 : * and use it as the initial interval
54933 : */
54934 0 : gu = d->ptr.p_double[ibegin];
54935 0 : gl = d->ptr.p_double[ibegin];
54936 0 : tmp1 = (double)(0);
54937 0 : for(j=ibegin; j<=iend-1; j++)
54938 : {
54939 0 : tmp2 = ae_fabs(e->ptr.p_double[j], _state);
54940 0 : gu = ae_maxreal(gu, d->ptr.p_double[j]+tmp1+tmp2, _state);
54941 0 : gl = ae_minreal(gl, d->ptr.p_double[j]-tmp1-tmp2, _state);
54942 0 : tmp1 = tmp2;
54943 : }
54944 0 : gu = ae_maxreal(gu, d->ptr.p_double[iend]+tmp1, _state);
54945 0 : gl = ae_minreal(gl, d->ptr.p_double[iend]-tmp1, _state);
54946 0 : bnorm = ae_maxreal(ae_fabs(gl, _state), ae_fabs(gu, _state), _state);
54947 0 : gl = gl-fudge*bnorm*ulp*iin-fudge*pivmin;
54948 0 : gu = gu+fudge*bnorm*ulp*iin+fudge*pivmin;
54949 :
54950 : /*
54951 : * Compute ATOLI for the current submatrix
54952 : */
54953 0 : if( ae_fp_less_eq(abstol,(double)(0)) )
54954 : {
54955 0 : atoli = ulp*ae_maxreal(ae_fabs(gl, _state), ae_fabs(gu, _state), _state);
54956 : }
54957 : else
54958 : {
54959 0 : atoli = abstol;
54960 : }
54961 0 : if( irange>1 )
54962 : {
54963 0 : if( ae_fp_less(gu,wl) )
54964 : {
54965 0 : nwl = nwl+iin;
54966 0 : nwu = nwu+iin;
54967 0 : continue;
54968 : }
54969 0 : gl = ae_maxreal(gl, wl, _state);
54970 0 : gu = ae_minreal(gu, wu, _state);
54971 0 : if( ae_fp_greater_eq(gl,gu) )
54972 : {
54973 0 : continue;
54974 : }
54975 : }
54976 :
54977 : /*
54978 : * Set Up Initial Interval
54979 : */
54980 0 : work.ptr.p_double[n+1] = gl;
54981 0 : work.ptr.p_double[n+iin+1] = gu;
54982 :
54983 : /*
54984 : * Calling DLAEBZ
54985 : *
54986 : * CALL DLAEBZ( 1, 0, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
54987 : * D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),
54988 : * IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IM,
54989 : * IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
54990 : */
54991 0 : for(tmpi=1; tmpi<=iin; tmpi++)
54992 : {
54993 0 : ra1siin.ptr.p_double[tmpi] = d->ptr.p_double[ibegin-1+tmpi];
54994 0 : if( ibegin-1+tmpi<n )
54995 : {
54996 0 : ra2siin.ptr.p_double[tmpi] = e->ptr.p_double[ibegin-1+tmpi];
54997 : }
54998 0 : ra3siin.ptr.p_double[tmpi] = work.ptr.p_double[ibegin-1+tmpi];
54999 0 : ra1siinx2.ptr.pp_double[tmpi][1] = work.ptr.p_double[n+tmpi];
55000 0 : ra1siinx2.ptr.pp_double[tmpi][2] = work.ptr.p_double[n+tmpi+iin];
55001 0 : ra4siin.ptr.p_double[tmpi] = work.ptr.p_double[n+2*iin+tmpi];
55002 0 : rworkspace.ptr.p_double[tmpi] = w->ptr.p_double[*m+tmpi];
55003 0 : iworkspace.ptr.p_int[tmpi] = iblock->ptr.p_int[*m+tmpi];
55004 0 : ia1siinx2.ptr.pp_int[tmpi][1] = iwork.ptr.p_int[tmpi];
55005 0 : ia1siinx2.ptr.pp_int[tmpi][2] = iwork.ptr.p_int[tmpi+iin];
55006 : }
55007 0 : evd_internaldlaebz(1, 0, iin, iin, 1, atoli, rtoli, pivmin, &ra1siin, &ra2siin, &ra3siin, &idumma, &ra1siinx2, &ra4siin, &im, &ia1siinx2, &rworkspace, &iworkspace, &iinfo, _state);
55008 0 : for(tmpi=1; tmpi<=iin; tmpi++)
55009 : {
55010 0 : work.ptr.p_double[n+tmpi] = ra1siinx2.ptr.pp_double[tmpi][1];
55011 0 : work.ptr.p_double[n+tmpi+iin] = ra1siinx2.ptr.pp_double[tmpi][2];
55012 0 : work.ptr.p_double[n+2*iin+tmpi] = ra4siin.ptr.p_double[tmpi];
55013 0 : w->ptr.p_double[*m+tmpi] = rworkspace.ptr.p_double[tmpi];
55014 0 : iblock->ptr.p_int[*m+tmpi] = iworkspace.ptr.p_int[tmpi];
55015 0 : iwork.ptr.p_int[tmpi] = ia1siinx2.ptr.pp_int[tmpi][1];
55016 0 : iwork.ptr.p_int[tmpi+iin] = ia1siinx2.ptr.pp_int[tmpi][2];
55017 : }
55018 0 : nwl = nwl+iwork.ptr.p_int[1];
55019 0 : nwu = nwu+iwork.ptr.p_int[iin+1];
55020 0 : iwoff = *m-iwork.ptr.p_int[1];
55021 :
55022 : /*
55023 : * Compute Eigenvalues
55024 : */
55025 0 : itmax = ae_iceil((ae_log(gu-gl+pivmin, _state)-ae_log(pivmin, _state))/ae_log((double)(2), _state), _state)+2;
55026 :
55027 : /*
55028 : * Calling DLAEBZ
55029 : *
55030 : *CALL DLAEBZ( 2, ITMAX, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
55031 : * D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),
55032 : * IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IOUT,
55033 : * IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
55034 : */
55035 0 : for(tmpi=1; tmpi<=iin; tmpi++)
55036 : {
55037 0 : ra1siin.ptr.p_double[tmpi] = d->ptr.p_double[ibegin-1+tmpi];
55038 0 : if( ibegin-1+tmpi<n )
55039 : {
55040 0 : ra2siin.ptr.p_double[tmpi] = e->ptr.p_double[ibegin-1+tmpi];
55041 : }
55042 0 : ra3siin.ptr.p_double[tmpi] = work.ptr.p_double[ibegin-1+tmpi];
55043 0 : ra1siinx2.ptr.pp_double[tmpi][1] = work.ptr.p_double[n+tmpi];
55044 0 : ra1siinx2.ptr.pp_double[tmpi][2] = work.ptr.p_double[n+tmpi+iin];
55045 0 : ra4siin.ptr.p_double[tmpi] = work.ptr.p_double[n+2*iin+tmpi];
55046 0 : rworkspace.ptr.p_double[tmpi] = w->ptr.p_double[*m+tmpi];
55047 0 : iworkspace.ptr.p_int[tmpi] = iblock->ptr.p_int[*m+tmpi];
55048 0 : ia1siinx2.ptr.pp_int[tmpi][1] = iwork.ptr.p_int[tmpi];
55049 0 : ia1siinx2.ptr.pp_int[tmpi][2] = iwork.ptr.p_int[tmpi+iin];
55050 : }
55051 0 : evd_internaldlaebz(2, itmax, iin, iin, 1, atoli, rtoli, pivmin, &ra1siin, &ra2siin, &ra3siin, &idumma, &ra1siinx2, &ra4siin, &iout, &ia1siinx2, &rworkspace, &iworkspace, &iinfo, _state);
55052 0 : for(tmpi=1; tmpi<=iin; tmpi++)
55053 : {
55054 0 : work.ptr.p_double[n+tmpi] = ra1siinx2.ptr.pp_double[tmpi][1];
55055 0 : work.ptr.p_double[n+tmpi+iin] = ra1siinx2.ptr.pp_double[tmpi][2];
55056 0 : work.ptr.p_double[n+2*iin+tmpi] = ra4siin.ptr.p_double[tmpi];
55057 0 : w->ptr.p_double[*m+tmpi] = rworkspace.ptr.p_double[tmpi];
55058 0 : iblock->ptr.p_int[*m+tmpi] = iworkspace.ptr.p_int[tmpi];
55059 0 : iwork.ptr.p_int[tmpi] = ia1siinx2.ptr.pp_int[tmpi][1];
55060 0 : iwork.ptr.p_int[tmpi+iin] = ia1siinx2.ptr.pp_int[tmpi][2];
55061 : }
55062 :
55063 : /*
55064 : * Copy Eigenvalues Into W and IBLOCK
55065 : * Use -JB for block number for unconverged eigenvalues.
55066 : */
55067 0 : for(j=1; j<=iout; j++)
55068 : {
55069 0 : tmp1 = 0.5*(work.ptr.p_double[j+n]+work.ptr.p_double[j+iin+n]);
55070 :
55071 : /*
55072 : * Flag non-convergence.
55073 : */
55074 0 : if( j>iout-iinfo )
55075 : {
55076 0 : ncnvrg = ae_true;
55077 0 : ib = -jb;
55078 : }
55079 : else
55080 : {
55081 0 : ib = jb;
55082 : }
55083 0 : for(je=iwork.ptr.p_int[j]+1+iwoff; je<=iwork.ptr.p_int[j+iin]+iwoff; je++)
55084 : {
55085 0 : w->ptr.p_double[je] = tmp1;
55086 0 : iblock->ptr.p_int[je] = ib;
55087 : }
55088 : }
55089 0 : *m = *m+im;
55090 : }
55091 : }
55092 :
55093 : /*
55094 : * If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU
55095 : * If NWL+1 < IL or NWU > IU, discard extra eigenvalues.
55096 : */
55097 0 : if( irange==3 )
55098 : {
55099 0 : im = 0;
55100 0 : idiscl = il-1-nwl;
55101 0 : idiscu = nwu-iu;
55102 0 : if( idiscl>0||idiscu>0 )
55103 : {
55104 0 : for(je=1; je<=*m; je++)
55105 : {
55106 0 : if( ae_fp_less_eq(w->ptr.p_double[je],wlu)&&idiscl>0 )
55107 : {
55108 0 : idiscl = idiscl-1;
55109 : }
55110 : else
55111 : {
55112 0 : if( ae_fp_greater_eq(w->ptr.p_double[je],wul)&&idiscu>0 )
55113 : {
55114 0 : idiscu = idiscu-1;
55115 : }
55116 : else
55117 : {
55118 0 : im = im+1;
55119 0 : w->ptr.p_double[im] = w->ptr.p_double[je];
55120 0 : iblock->ptr.p_int[im] = iblock->ptr.p_int[je];
55121 : }
55122 : }
55123 : }
55124 0 : *m = im;
55125 : }
55126 0 : if( idiscl>0||idiscu>0 )
55127 : {
55128 :
55129 : /*
55130 : * Code to deal with effects of bad arithmetic:
55131 : * Some low eigenvalues to be discarded are not in (WL,WLU],
55132 : * or high eigenvalues to be discarded are not in (WUL,WU]
55133 : * so just kill off the smallest IDISCL/largest IDISCU
55134 : * eigenvalues, by simply finding the smallest/largest
55135 : * eigenvalue(s).
55136 : *
55137 : * (If N(w) is monotone non-decreasing, this should never
55138 : * happen.)
55139 : */
55140 0 : if( idiscl>0 )
55141 : {
55142 0 : wkill = wu;
55143 0 : for(jdisc=1; jdisc<=idiscl; jdisc++)
55144 : {
55145 0 : iw = 0;
55146 0 : for(je=1; je<=*m; je++)
55147 : {
55148 0 : if( iblock->ptr.p_int[je]!=0&&(ae_fp_less(w->ptr.p_double[je],wkill)||iw==0) )
55149 : {
55150 0 : iw = je;
55151 0 : wkill = w->ptr.p_double[je];
55152 : }
55153 : }
55154 0 : iblock->ptr.p_int[iw] = 0;
55155 : }
55156 : }
55157 0 : if( idiscu>0 )
55158 : {
55159 0 : wkill = wl;
55160 0 : for(jdisc=1; jdisc<=idiscu; jdisc++)
55161 : {
55162 0 : iw = 0;
55163 0 : for(je=1; je<=*m; je++)
55164 : {
55165 0 : if( iblock->ptr.p_int[je]!=0&&(ae_fp_greater(w->ptr.p_double[je],wkill)||iw==0) )
55166 : {
55167 0 : iw = je;
55168 0 : wkill = w->ptr.p_double[je];
55169 : }
55170 : }
55171 0 : iblock->ptr.p_int[iw] = 0;
55172 : }
55173 : }
55174 0 : im = 0;
55175 0 : for(je=1; je<=*m; je++)
55176 : {
55177 0 : if( iblock->ptr.p_int[je]!=0 )
55178 : {
55179 0 : im = im+1;
55180 0 : w->ptr.p_double[im] = w->ptr.p_double[je];
55181 0 : iblock->ptr.p_int[im] = iblock->ptr.p_int[je];
55182 : }
55183 : }
55184 0 : *m = im;
55185 : }
55186 0 : if( idiscl<0||idiscu<0 )
55187 : {
55188 0 : toofew = ae_true;
55189 : }
55190 : }
55191 :
55192 : /*
55193 : * If ORDER='B', do nothing -- the eigenvalues are already sorted
55194 : * by block.
55195 : * If ORDER='E', sort the eigenvalues from smallest to largest
55196 : */
55197 0 : if( iorder==1&&*nsplit>1 )
55198 : {
55199 0 : for(je=1; je<=*m-1; je++)
55200 : {
55201 0 : ie = 0;
55202 0 : tmp1 = w->ptr.p_double[je];
55203 0 : for(j=je+1; j<=*m; j++)
55204 : {
55205 0 : if( ae_fp_less(w->ptr.p_double[j],tmp1) )
55206 : {
55207 0 : ie = j;
55208 0 : tmp1 = w->ptr.p_double[j];
55209 : }
55210 : }
55211 0 : if( ie!=0 )
55212 : {
55213 0 : itmp1 = iblock->ptr.p_int[ie];
55214 0 : w->ptr.p_double[ie] = w->ptr.p_double[je];
55215 0 : iblock->ptr.p_int[ie] = iblock->ptr.p_int[je];
55216 0 : w->ptr.p_double[je] = tmp1;
55217 0 : iblock->ptr.p_int[je] = itmp1;
55218 : }
55219 : }
55220 : }
55221 0 : for(j=1; j<=*m; j++)
55222 : {
55223 0 : w->ptr.p_double[j] = w->ptr.p_double[j]*scalefactor;
55224 : }
55225 0 : *errorcode = 0;
55226 0 : if( ncnvrg )
55227 : {
55228 0 : *errorcode = *errorcode+1;
55229 : }
55230 0 : if( toofew )
55231 : {
55232 0 : *errorcode = *errorcode+2;
55233 : }
55234 0 : result = *errorcode==0;
55235 0 : ae_frame_leave(_state);
55236 0 : return result;
55237 : }
55238 :
55239 :
55240 0 : static void evd_internaldstein(ae_int_t n,
55241 : /* Real */ ae_vector* d,
55242 : /* Real */ ae_vector* e,
55243 : ae_int_t m,
55244 : /* Real */ ae_vector* w,
55245 : /* Integer */ ae_vector* iblock,
55246 : /* Integer */ ae_vector* isplit,
55247 : /* Real */ ae_matrix* z,
55248 : /* Integer */ ae_vector* ifail,
55249 : ae_int_t* info,
55250 : ae_state *_state)
55251 : {
55252 : ae_frame _frame_block;
55253 : ae_vector _e;
55254 : ae_vector _w;
55255 : ae_int_t maxits;
55256 : ae_int_t extra;
55257 : ae_int_t b1;
55258 : ae_int_t blksiz;
55259 : ae_int_t bn;
55260 : ae_int_t gpind;
55261 : ae_int_t i;
55262 : ae_int_t iinfo;
55263 : ae_int_t its;
55264 : ae_int_t j;
55265 : ae_int_t j1;
55266 : ae_int_t jblk;
55267 : ae_int_t jmax;
55268 : ae_int_t nblk;
55269 : ae_int_t nrmchk;
55270 : double dtpcrt;
55271 : double eps;
55272 : double eps1;
55273 : double nrm;
55274 : double onenrm;
55275 : double ortol;
55276 : double pertol;
55277 : double scl;
55278 : double sep;
55279 : double tol;
55280 : double xj;
55281 : double xjm;
55282 : double ztr;
55283 : ae_vector work1;
55284 : ae_vector work2;
55285 : ae_vector work3;
55286 : ae_vector work4;
55287 : ae_vector work5;
55288 : ae_vector iwork;
55289 : ae_bool tmpcriterion;
55290 : ae_int_t ti;
55291 : ae_int_t i1;
55292 : ae_int_t i2;
55293 : double v;
55294 : hqrndstate rs;
55295 :
55296 0 : ae_frame_make(_state, &_frame_block);
55297 0 : memset(&_e, 0, sizeof(_e));
55298 0 : memset(&_w, 0, sizeof(_w));
55299 0 : memset(&work1, 0, sizeof(work1));
55300 0 : memset(&work2, 0, sizeof(work2));
55301 0 : memset(&work3, 0, sizeof(work3));
55302 0 : memset(&work4, 0, sizeof(work4));
55303 0 : memset(&work5, 0, sizeof(work5));
55304 0 : memset(&iwork, 0, sizeof(iwork));
55305 0 : memset(&rs, 0, sizeof(rs));
55306 0 : ae_vector_init_copy(&_e, e, _state, ae_true);
55307 0 : e = &_e;
55308 0 : ae_vector_init_copy(&_w, w, _state, ae_true);
55309 0 : w = &_w;
55310 0 : ae_matrix_clear(z);
55311 0 : ae_vector_clear(ifail);
55312 0 : *info = 0;
55313 0 : ae_vector_init(&work1, 0, DT_REAL, _state, ae_true);
55314 0 : ae_vector_init(&work2, 0, DT_REAL, _state, ae_true);
55315 0 : ae_vector_init(&work3, 0, DT_REAL, _state, ae_true);
55316 0 : ae_vector_init(&work4, 0, DT_REAL, _state, ae_true);
55317 0 : ae_vector_init(&work5, 0, DT_REAL, _state, ae_true);
55318 0 : ae_vector_init(&iwork, 0, DT_INT, _state, ae_true);
55319 0 : _hqrndstate_init(&rs, _state, ae_true);
55320 :
55321 0 : hqrndseed(346436, 2434, &rs, _state);
55322 0 : maxits = 5;
55323 0 : extra = 2;
55324 0 : ae_vector_set_length(&work1, ae_maxint(n, 1, _state)+1, _state);
55325 0 : ae_vector_set_length(&work2, ae_maxint(n-1, 1, _state)+1, _state);
55326 0 : ae_vector_set_length(&work3, ae_maxint(n, 1, _state)+1, _state);
55327 0 : ae_vector_set_length(&work4, ae_maxint(n, 1, _state)+1, _state);
55328 0 : ae_vector_set_length(&work5, ae_maxint(n, 1, _state)+1, _state);
55329 0 : ae_vector_set_length(&iwork, ae_maxint(n, 1, _state)+1, _state);
55330 0 : ae_vector_set_length(ifail, ae_maxint(m, 1, _state)+1, _state);
55331 0 : ae_matrix_set_length(z, ae_maxint(n, 1, _state)+1, ae_maxint(m, 1, _state)+1, _state);
55332 :
55333 : /*
55334 : * these initializers are not really necessary,
55335 : * but without them compiler complains about uninitialized locals
55336 : */
55337 0 : gpind = 0;
55338 0 : onenrm = (double)(0);
55339 0 : ortol = (double)(0);
55340 0 : dtpcrt = (double)(0);
55341 0 : xjm = (double)(0);
55342 :
55343 : /*
55344 : * Test the input parameters.
55345 : */
55346 0 : *info = 0;
55347 0 : for(i=1; i<=m; i++)
55348 : {
55349 0 : ifail->ptr.p_int[i] = 0;
55350 : }
55351 0 : if( n<0 )
55352 : {
55353 0 : *info = -1;
55354 0 : ae_frame_leave(_state);
55355 0 : return;
55356 : }
55357 0 : if( m<0||m>n )
55358 : {
55359 0 : *info = -4;
55360 0 : ae_frame_leave(_state);
55361 0 : return;
55362 : }
55363 0 : for(j=2; j<=m; j++)
55364 : {
55365 0 : if( iblock->ptr.p_int[j]<iblock->ptr.p_int[j-1] )
55366 : {
55367 0 : *info = -6;
55368 0 : break;
55369 : }
55370 0 : if( iblock->ptr.p_int[j]==iblock->ptr.p_int[j-1]&&ae_fp_less(w->ptr.p_double[j],w->ptr.p_double[j-1]) )
55371 : {
55372 0 : *info = -5;
55373 0 : break;
55374 : }
55375 : }
55376 0 : if( *info!=0 )
55377 : {
55378 0 : ae_frame_leave(_state);
55379 0 : return;
55380 : }
55381 :
55382 : /*
55383 : * Quick return if possible
55384 : */
55385 0 : if( n==0||m==0 )
55386 : {
55387 0 : ae_frame_leave(_state);
55388 0 : return;
55389 : }
55390 0 : if( n==1 )
55391 : {
55392 0 : z->ptr.pp_double[1][1] = (double)(1);
55393 0 : ae_frame_leave(_state);
55394 0 : return;
55395 : }
55396 :
55397 : /*
55398 : * Some preparations
55399 : */
55400 0 : ti = n-1;
55401 0 : ae_v_move(&work1.ptr.p_double[1], 1, &e->ptr.p_double[1], 1, ae_v_len(1,ti));
55402 0 : ae_vector_set_length(e, n+1, _state);
55403 0 : ae_v_move(&e->ptr.p_double[1], 1, &work1.ptr.p_double[1], 1, ae_v_len(1,ti));
55404 0 : ae_v_move(&work1.ptr.p_double[1], 1, &w->ptr.p_double[1], 1, ae_v_len(1,m));
55405 0 : ae_vector_set_length(w, n+1, _state);
55406 0 : ae_v_move(&w->ptr.p_double[1], 1, &work1.ptr.p_double[1], 1, ae_v_len(1,m));
55407 :
55408 : /*
55409 : * Get machine constants.
55410 : */
55411 0 : eps = ae_machineepsilon;
55412 :
55413 : /*
55414 : * Compute eigenvectors of matrix blocks.
55415 : */
55416 0 : j1 = 1;
55417 0 : for(nblk=1; nblk<=iblock->ptr.p_int[m]; nblk++)
55418 : {
55419 :
55420 : /*
55421 : * Find starting and ending indices of block nblk.
55422 : */
55423 0 : if( nblk==1 )
55424 : {
55425 0 : b1 = 1;
55426 : }
55427 : else
55428 : {
55429 0 : b1 = isplit->ptr.p_int[nblk-1]+1;
55430 : }
55431 0 : bn = isplit->ptr.p_int[nblk];
55432 0 : blksiz = bn-b1+1;
55433 0 : if( blksiz!=1 )
55434 : {
55435 :
55436 : /*
55437 : * Compute reorthogonalization criterion and stopping criterion.
55438 : */
55439 0 : gpind = b1;
55440 0 : onenrm = ae_fabs(d->ptr.p_double[b1], _state)+ae_fabs(e->ptr.p_double[b1], _state);
55441 0 : onenrm = ae_maxreal(onenrm, ae_fabs(d->ptr.p_double[bn], _state)+ae_fabs(e->ptr.p_double[bn-1], _state), _state);
55442 0 : for(i=b1+1; i<=bn-1; i++)
55443 : {
55444 0 : onenrm = ae_maxreal(onenrm, ae_fabs(d->ptr.p_double[i], _state)+ae_fabs(e->ptr.p_double[i-1], _state)+ae_fabs(e->ptr.p_double[i], _state), _state);
55445 : }
55446 0 : ortol = 0.001*onenrm;
55447 0 : dtpcrt = ae_sqrt(0.1/blksiz, _state);
55448 : }
55449 :
55450 : /*
55451 : * Loop through eigenvalues of block nblk.
55452 : */
55453 0 : jblk = 0;
55454 0 : for(j=j1; j<=m; j++)
55455 : {
55456 0 : if( iblock->ptr.p_int[j]!=nblk )
55457 : {
55458 0 : j1 = j;
55459 0 : break;
55460 : }
55461 0 : jblk = jblk+1;
55462 0 : xj = w->ptr.p_double[j];
55463 0 : if( blksiz==1 )
55464 : {
55465 :
55466 : /*
55467 : * Skip all the work if the block size is one.
55468 : */
55469 0 : work1.ptr.p_double[1] = (double)(1);
55470 : }
55471 : else
55472 : {
55473 :
55474 : /*
55475 : * If eigenvalues j and j-1 are too close, add a relatively
55476 : * small perturbation.
55477 : */
55478 0 : if( jblk>1 )
55479 : {
55480 0 : eps1 = ae_fabs(eps*xj, _state);
55481 0 : pertol = 10*eps1;
55482 0 : sep = xj-xjm;
55483 0 : if( ae_fp_less(sep,pertol) )
55484 : {
55485 0 : xj = xjm+pertol;
55486 : }
55487 : }
55488 0 : its = 0;
55489 0 : nrmchk = 0;
55490 :
55491 : /*
55492 : * Get random starting vector.
55493 : */
55494 0 : for(ti=1; ti<=blksiz; ti++)
55495 : {
55496 0 : work1.ptr.p_double[ti] = 2*hqrnduniformr(&rs, _state)-1;
55497 : }
55498 :
55499 : /*
55500 : * Copy the matrix T so it won't be destroyed in factorization.
55501 : */
55502 0 : for(ti=1; ti<=blksiz-1; ti++)
55503 : {
55504 0 : work2.ptr.p_double[ti] = e->ptr.p_double[b1+ti-1];
55505 0 : work3.ptr.p_double[ti] = e->ptr.p_double[b1+ti-1];
55506 0 : work4.ptr.p_double[ti] = d->ptr.p_double[b1+ti-1];
55507 : }
55508 0 : work4.ptr.p_double[blksiz] = d->ptr.p_double[b1+blksiz-1];
55509 :
55510 : /*
55511 : * Compute LU factors with partial pivoting ( PT = LU )
55512 : */
55513 0 : tol = (double)(0);
55514 0 : evd_tdininternaldlagtf(blksiz, &work4, xj, &work2, &work3, tol, &work5, &iwork, &iinfo, _state);
55515 :
55516 : /*
55517 : * Update iteration count.
55518 : */
55519 0 : do
55520 : {
55521 0 : its = its+1;
55522 0 : if( its>maxits )
55523 : {
55524 :
55525 : /*
55526 : * If stopping criterion was not satisfied, update info and
55527 : * store eigenvector number in array ifail.
55528 : */
55529 0 : *info = *info+1;
55530 0 : ifail->ptr.p_int[*info] = j;
55531 0 : break;
55532 : }
55533 :
55534 : /*
55535 : * Normalize and scale the righthand side vector Pb.
55536 : */
55537 0 : v = (double)(0);
55538 0 : for(ti=1; ti<=blksiz; ti++)
55539 : {
55540 0 : v = v+ae_fabs(work1.ptr.p_double[ti], _state);
55541 : }
55542 0 : scl = blksiz*onenrm*ae_maxreal(eps, ae_fabs(work4.ptr.p_double[blksiz], _state), _state)/v;
55543 0 : ae_v_muld(&work1.ptr.p_double[1], 1, ae_v_len(1,blksiz), scl);
55544 :
55545 : /*
55546 : * Solve the system LU = Pb.
55547 : */
55548 0 : evd_tdininternaldlagts(blksiz, &work4, &work2, &work3, &work5, &iwork, &work1, &tol, &iinfo, _state);
55549 :
55550 : /*
55551 : * Reorthogonalize by modified Gram-Schmidt if eigenvalues are
55552 : * close enough.
55553 : */
55554 0 : if( jblk!=1 )
55555 : {
55556 0 : if( ae_fp_greater(ae_fabs(xj-xjm, _state),ortol) )
55557 : {
55558 0 : gpind = j;
55559 : }
55560 0 : if( gpind!=j )
55561 : {
55562 0 : for(i=gpind; i<=j-1; i++)
55563 : {
55564 0 : i1 = b1;
55565 0 : i2 = b1+blksiz-1;
55566 0 : ztr = ae_v_dotproduct(&work1.ptr.p_double[1], 1, &z->ptr.pp_double[i1][i], z->stride, ae_v_len(1,blksiz));
55567 0 : ae_v_subd(&work1.ptr.p_double[1], 1, &z->ptr.pp_double[i1][i], z->stride, ae_v_len(1,blksiz), ztr);
55568 0 : touchint(&i2, _state);
55569 : }
55570 : }
55571 : }
55572 :
55573 : /*
55574 : * Check the infinity norm of the iterate.
55575 : */
55576 0 : jmax = vectoridxabsmax(&work1, 1, blksiz, _state);
55577 0 : nrm = ae_fabs(work1.ptr.p_double[jmax], _state);
55578 :
55579 : /*
55580 : * Continue for additional iterations after norm reaches
55581 : * stopping criterion.
55582 : */
55583 0 : tmpcriterion = ae_false;
55584 0 : if( ae_fp_less(nrm,dtpcrt) )
55585 : {
55586 0 : tmpcriterion = ae_true;
55587 : }
55588 : else
55589 : {
55590 0 : nrmchk = nrmchk+1;
55591 0 : if( nrmchk<extra+1 )
55592 : {
55593 0 : tmpcriterion = ae_true;
55594 : }
55595 : }
55596 : }
55597 : while(tmpcriterion);
55598 :
55599 : /*
55600 : * Accept iterate as jth eigenvector.
55601 : */
55602 0 : scl = 1/vectornorm2(&work1, 1, blksiz, _state);
55603 0 : jmax = vectoridxabsmax(&work1, 1, blksiz, _state);
55604 0 : if( ae_fp_less(work1.ptr.p_double[jmax],(double)(0)) )
55605 : {
55606 0 : scl = -scl;
55607 : }
55608 0 : ae_v_muld(&work1.ptr.p_double[1], 1, ae_v_len(1,blksiz), scl);
55609 : }
55610 0 : for(i=1; i<=n; i++)
55611 : {
55612 0 : z->ptr.pp_double[i][j] = (double)(0);
55613 : }
55614 0 : for(i=1; i<=blksiz; i++)
55615 : {
55616 0 : z->ptr.pp_double[b1+i-1][j] = work1.ptr.p_double[i];
55617 : }
55618 :
55619 : /*
55620 : * Save the shift to check eigenvalue spacing at next
55621 : * iteration.
55622 : */
55623 0 : xjm = xj;
55624 : }
55625 : }
55626 0 : ae_frame_leave(_state);
55627 : }
55628 :
55629 :
55630 0 : static void evd_tdininternaldlagtf(ae_int_t n,
55631 : /* Real */ ae_vector* a,
55632 : double lambdav,
55633 : /* Real */ ae_vector* b,
55634 : /* Real */ ae_vector* c,
55635 : double tol,
55636 : /* Real */ ae_vector* d,
55637 : /* Integer */ ae_vector* iin,
55638 : ae_int_t* info,
55639 : ae_state *_state)
55640 : {
55641 : ae_int_t k;
55642 : double eps;
55643 : double mult;
55644 : double piv1;
55645 : double piv2;
55646 : double scale1;
55647 : double scale2;
55648 : double temp;
55649 : double tl;
55650 :
55651 0 : *info = 0;
55652 :
55653 0 : *info = 0;
55654 0 : if( n<0 )
55655 : {
55656 0 : *info = -1;
55657 0 : return;
55658 : }
55659 0 : if( n==0 )
55660 : {
55661 0 : return;
55662 : }
55663 0 : a->ptr.p_double[1] = a->ptr.p_double[1]-lambdav;
55664 0 : iin->ptr.p_int[n] = 0;
55665 0 : if( n==1 )
55666 : {
55667 0 : if( ae_fp_eq(a->ptr.p_double[1],(double)(0)) )
55668 : {
55669 0 : iin->ptr.p_int[1] = 1;
55670 : }
55671 0 : return;
55672 : }
55673 0 : eps = ae_machineepsilon;
55674 0 : tl = ae_maxreal(tol, eps, _state);
55675 0 : scale1 = ae_fabs(a->ptr.p_double[1], _state)+ae_fabs(b->ptr.p_double[1], _state);
55676 0 : for(k=1; k<=n-1; k++)
55677 : {
55678 0 : a->ptr.p_double[k+1] = a->ptr.p_double[k+1]-lambdav;
55679 0 : scale2 = ae_fabs(c->ptr.p_double[k], _state)+ae_fabs(a->ptr.p_double[k+1], _state);
55680 0 : if( k<n-1 )
55681 : {
55682 0 : scale2 = scale2+ae_fabs(b->ptr.p_double[k+1], _state);
55683 : }
55684 0 : if( ae_fp_eq(a->ptr.p_double[k],(double)(0)) )
55685 : {
55686 0 : piv1 = (double)(0);
55687 : }
55688 : else
55689 : {
55690 0 : piv1 = ae_fabs(a->ptr.p_double[k], _state)/scale1;
55691 : }
55692 0 : if( ae_fp_eq(c->ptr.p_double[k],(double)(0)) )
55693 : {
55694 0 : iin->ptr.p_int[k] = 0;
55695 0 : piv2 = (double)(0);
55696 0 : scale1 = scale2;
55697 0 : if( k<n-1 )
55698 : {
55699 0 : d->ptr.p_double[k] = (double)(0);
55700 : }
55701 : }
55702 : else
55703 : {
55704 0 : piv2 = ae_fabs(c->ptr.p_double[k], _state)/scale2;
55705 0 : if( ae_fp_less_eq(piv2,piv1) )
55706 : {
55707 0 : iin->ptr.p_int[k] = 0;
55708 0 : scale1 = scale2;
55709 0 : c->ptr.p_double[k] = c->ptr.p_double[k]/a->ptr.p_double[k];
55710 0 : a->ptr.p_double[k+1] = a->ptr.p_double[k+1]-c->ptr.p_double[k]*b->ptr.p_double[k];
55711 0 : if( k<n-1 )
55712 : {
55713 0 : d->ptr.p_double[k] = (double)(0);
55714 : }
55715 : }
55716 : else
55717 : {
55718 0 : iin->ptr.p_int[k] = 1;
55719 0 : mult = a->ptr.p_double[k]/c->ptr.p_double[k];
55720 0 : a->ptr.p_double[k] = c->ptr.p_double[k];
55721 0 : temp = a->ptr.p_double[k+1];
55722 0 : a->ptr.p_double[k+1] = b->ptr.p_double[k]-mult*temp;
55723 0 : if( k<n-1 )
55724 : {
55725 0 : d->ptr.p_double[k] = b->ptr.p_double[k+1];
55726 0 : b->ptr.p_double[k+1] = -mult*d->ptr.p_double[k];
55727 : }
55728 0 : b->ptr.p_double[k] = temp;
55729 0 : c->ptr.p_double[k] = mult;
55730 : }
55731 : }
55732 0 : if( ae_fp_less_eq(ae_maxreal(piv1, piv2, _state),tl)&&iin->ptr.p_int[n]==0 )
55733 : {
55734 0 : iin->ptr.p_int[n] = k;
55735 : }
55736 : }
55737 0 : if( ae_fp_less_eq(ae_fabs(a->ptr.p_double[n], _state),scale1*tl)&&iin->ptr.p_int[n]==0 )
55738 : {
55739 0 : iin->ptr.p_int[n] = n;
55740 : }
55741 : }
55742 :
55743 :
55744 0 : static void evd_tdininternaldlagts(ae_int_t n,
55745 : /* Real */ ae_vector* a,
55746 : /* Real */ ae_vector* b,
55747 : /* Real */ ae_vector* c,
55748 : /* Real */ ae_vector* d,
55749 : /* Integer */ ae_vector* iin,
55750 : /* Real */ ae_vector* y,
55751 : double* tol,
55752 : ae_int_t* info,
55753 : ae_state *_state)
55754 : {
55755 : ae_int_t k;
55756 : double absak;
55757 : double ak;
55758 : double bignum;
55759 : double eps;
55760 : double pert;
55761 : double sfmin;
55762 : double temp;
55763 :
55764 0 : *info = 0;
55765 :
55766 0 : *info = 0;
55767 0 : if( n<0 )
55768 : {
55769 0 : *info = -1;
55770 0 : return;
55771 : }
55772 0 : if( n==0 )
55773 : {
55774 0 : return;
55775 : }
55776 0 : eps = ae_machineepsilon;
55777 0 : sfmin = ae_minrealnumber;
55778 0 : bignum = 1/sfmin;
55779 0 : if( ae_fp_less_eq(*tol,(double)(0)) )
55780 : {
55781 0 : *tol = ae_fabs(a->ptr.p_double[1], _state);
55782 0 : if( n>1 )
55783 : {
55784 0 : *tol = ae_maxreal(*tol, ae_maxreal(ae_fabs(a->ptr.p_double[2], _state), ae_fabs(b->ptr.p_double[1], _state), _state), _state);
55785 : }
55786 0 : for(k=3; k<=n; k++)
55787 : {
55788 0 : *tol = ae_maxreal(*tol, ae_maxreal(ae_fabs(a->ptr.p_double[k], _state), ae_maxreal(ae_fabs(b->ptr.p_double[k-1], _state), ae_fabs(d->ptr.p_double[k-2], _state), _state), _state), _state);
55789 : }
55790 0 : *tol = *tol*eps;
55791 0 : if( ae_fp_eq(*tol,(double)(0)) )
55792 : {
55793 0 : *tol = eps;
55794 : }
55795 : }
55796 0 : for(k=2; k<=n; k++)
55797 : {
55798 0 : if( iin->ptr.p_int[k-1]==0 )
55799 : {
55800 0 : y->ptr.p_double[k] = y->ptr.p_double[k]-c->ptr.p_double[k-1]*y->ptr.p_double[k-1];
55801 : }
55802 : else
55803 : {
55804 0 : temp = y->ptr.p_double[k-1];
55805 0 : y->ptr.p_double[k-1] = y->ptr.p_double[k];
55806 0 : y->ptr.p_double[k] = temp-c->ptr.p_double[k-1]*y->ptr.p_double[k];
55807 : }
55808 : }
55809 0 : for(k=n; k>=1; k--)
55810 : {
55811 0 : if( k<=n-2 )
55812 : {
55813 0 : temp = y->ptr.p_double[k]-b->ptr.p_double[k]*y->ptr.p_double[k+1]-d->ptr.p_double[k]*y->ptr.p_double[k+2];
55814 : }
55815 : else
55816 : {
55817 0 : if( k==n-1 )
55818 : {
55819 0 : temp = y->ptr.p_double[k]-b->ptr.p_double[k]*y->ptr.p_double[k+1];
55820 : }
55821 : else
55822 : {
55823 0 : temp = y->ptr.p_double[k];
55824 : }
55825 : }
55826 0 : ak = a->ptr.p_double[k];
55827 0 : pert = ae_fabs(*tol, _state);
55828 0 : if( ae_fp_less(ak,(double)(0)) )
55829 : {
55830 0 : pert = -pert;
55831 : }
55832 : for(;;)
55833 : {
55834 0 : absak = ae_fabs(ak, _state);
55835 0 : if( ae_fp_less(absak,(double)(1)) )
55836 : {
55837 0 : if( ae_fp_less(absak,sfmin) )
55838 : {
55839 0 : if( ae_fp_eq(absak,(double)(0))||ae_fp_greater(ae_fabs(temp, _state)*sfmin,absak) )
55840 : {
55841 0 : ak = ak+pert;
55842 0 : pert = 2*pert;
55843 0 : continue;
55844 : }
55845 : else
55846 : {
55847 0 : temp = temp*bignum;
55848 0 : ak = ak*bignum;
55849 : }
55850 : }
55851 : else
55852 : {
55853 0 : if( ae_fp_greater(ae_fabs(temp, _state),absak*bignum) )
55854 : {
55855 0 : ak = ak+pert;
55856 0 : pert = 2*pert;
55857 0 : continue;
55858 : }
55859 : }
55860 : }
55861 0 : break;
55862 : }
55863 0 : y->ptr.p_double[k] = temp/ak;
55864 : }
55865 : }
55866 :
55867 :
55868 0 : static void evd_internaldlaebz(ae_int_t ijob,
55869 : ae_int_t nitmax,
55870 : ae_int_t n,
55871 : ae_int_t mmax,
55872 : ae_int_t minp,
55873 : double abstol,
55874 : double reltol,
55875 : double pivmin,
55876 : /* Real */ ae_vector* d,
55877 : /* Real */ ae_vector* e,
55878 : /* Real */ ae_vector* e2,
55879 : /* Integer */ ae_vector* nval,
55880 : /* Real */ ae_matrix* ab,
55881 : /* Real */ ae_vector* c,
55882 : ae_int_t* mout,
55883 : /* Integer */ ae_matrix* nab,
55884 : /* Real */ ae_vector* work,
55885 : /* Integer */ ae_vector* iwork,
55886 : ae_int_t* info,
55887 : ae_state *_state)
55888 : {
55889 : ae_int_t itmp1;
55890 : ae_int_t itmp2;
55891 : ae_int_t j;
55892 : ae_int_t ji;
55893 : ae_int_t jit;
55894 : ae_int_t jp;
55895 : ae_int_t kf;
55896 : ae_int_t kfnew;
55897 : ae_int_t kl;
55898 : ae_int_t klnew;
55899 : double tmp1;
55900 : double tmp2;
55901 :
55902 0 : *mout = 0;
55903 0 : *info = 0;
55904 :
55905 0 : *info = 0;
55906 0 : if( ijob<1||ijob>3 )
55907 : {
55908 0 : *info = -1;
55909 0 : return;
55910 : }
55911 :
55912 : /*
55913 : * Initialize NAB
55914 : */
55915 0 : if( ijob==1 )
55916 : {
55917 :
55918 : /*
55919 : * Compute the number of eigenvalues in the initial intervals.
55920 : */
55921 0 : *mout = 0;
55922 :
55923 : /*
55924 : *DIR$ NOVECTOR
55925 : */
55926 0 : for(ji=1; ji<=minp; ji++)
55927 : {
55928 0 : for(jp=1; jp<=2; jp++)
55929 : {
55930 0 : tmp1 = d->ptr.p_double[1]-ab->ptr.pp_double[ji][jp];
55931 0 : if( ae_fp_less(ae_fabs(tmp1, _state),pivmin) )
55932 : {
55933 0 : tmp1 = -pivmin;
55934 : }
55935 0 : nab->ptr.pp_int[ji][jp] = 0;
55936 0 : if( ae_fp_less_eq(tmp1,(double)(0)) )
55937 : {
55938 0 : nab->ptr.pp_int[ji][jp] = 1;
55939 : }
55940 0 : for(j=2; j<=n; j++)
55941 : {
55942 0 : tmp1 = d->ptr.p_double[j]-e2->ptr.p_double[j-1]/tmp1-ab->ptr.pp_double[ji][jp];
55943 0 : if( ae_fp_less(ae_fabs(tmp1, _state),pivmin) )
55944 : {
55945 0 : tmp1 = -pivmin;
55946 : }
55947 0 : if( ae_fp_less_eq(tmp1,(double)(0)) )
55948 : {
55949 0 : nab->ptr.pp_int[ji][jp] = nab->ptr.pp_int[ji][jp]+1;
55950 : }
55951 : }
55952 : }
55953 0 : *mout = *mout+nab->ptr.pp_int[ji][2]-nab->ptr.pp_int[ji][1];
55954 : }
55955 0 : return;
55956 : }
55957 :
55958 : /*
55959 : * Initialize for loop
55960 : *
55961 : * KF and KL have the following meaning:
55962 : * Intervals 1,...,KF-1 have converged.
55963 : * Intervals KF,...,KL still need to be refined.
55964 : */
55965 0 : kf = 1;
55966 0 : kl = minp;
55967 :
55968 : /*
55969 : * If IJOB=2, initialize C.
55970 : * If IJOB=3, use the user-supplied starting point.
55971 : */
55972 0 : if( ijob==2 )
55973 : {
55974 0 : for(ji=1; ji<=minp; ji++)
55975 : {
55976 0 : c->ptr.p_double[ji] = 0.5*(ab->ptr.pp_double[ji][1]+ab->ptr.pp_double[ji][2]);
55977 : }
55978 : }
55979 :
55980 : /*
55981 : * Iteration loop
55982 : */
55983 0 : for(jit=1; jit<=nitmax; jit++)
55984 : {
55985 :
55986 : /*
55987 : * Loop over intervals
55988 : *
55989 : *
55990 : * Serial Version of the loop
55991 : */
55992 0 : klnew = kl;
55993 0 : for(ji=kf; ji<=kl; ji++)
55994 : {
55995 :
55996 : /*
55997 : * Compute N(w), the number of eigenvalues less than w
55998 : */
55999 0 : tmp1 = c->ptr.p_double[ji];
56000 0 : tmp2 = d->ptr.p_double[1]-tmp1;
56001 0 : itmp1 = 0;
56002 0 : if( ae_fp_less_eq(tmp2,pivmin) )
56003 : {
56004 0 : itmp1 = 1;
56005 0 : tmp2 = ae_minreal(tmp2, -pivmin, _state);
56006 : }
56007 :
56008 : /*
56009 : * A series of compiler directives to defeat vectorization
56010 : * for the next loop
56011 : *
56012 : **$PL$ CMCHAR=' '
56013 : *CDIR$ NEXTSCALAR
56014 : *C$DIR SCALAR
56015 : *CDIR$ NEXT SCALAR
56016 : *CVD$L NOVECTOR
56017 : *CDEC$ NOVECTOR
56018 : *CVD$ NOVECTOR
56019 : **VDIR NOVECTOR
56020 : **VOCL LOOP,SCALAR
56021 : *CIBM PREFER SCALAR
56022 : **$PL$ CMCHAR='*'
56023 : */
56024 0 : for(j=2; j<=n; j++)
56025 : {
56026 0 : tmp2 = d->ptr.p_double[j]-e2->ptr.p_double[j-1]/tmp2-tmp1;
56027 0 : if( ae_fp_less_eq(tmp2,pivmin) )
56028 : {
56029 0 : itmp1 = itmp1+1;
56030 0 : tmp2 = ae_minreal(tmp2, -pivmin, _state);
56031 : }
56032 : }
56033 0 : if( ijob<=2 )
56034 : {
56035 :
56036 : /*
56037 : * IJOB=2: Choose all intervals containing eigenvalues.
56038 : *
56039 : * Insure that N(w) is monotone
56040 : */
56041 0 : itmp1 = ae_minint(nab->ptr.pp_int[ji][2], ae_maxint(nab->ptr.pp_int[ji][1], itmp1, _state), _state);
56042 :
56043 : /*
56044 : * Update the Queue -- add intervals if both halves
56045 : * contain eigenvalues.
56046 : */
56047 0 : if( itmp1==nab->ptr.pp_int[ji][2] )
56048 : {
56049 :
56050 : /*
56051 : * No eigenvalue in the upper interval:
56052 : * just use the lower interval.
56053 : */
56054 0 : ab->ptr.pp_double[ji][2] = tmp1;
56055 : }
56056 : else
56057 : {
56058 0 : if( itmp1==nab->ptr.pp_int[ji][1] )
56059 : {
56060 :
56061 : /*
56062 : * No eigenvalue in the lower interval:
56063 : * just use the upper interval.
56064 : */
56065 0 : ab->ptr.pp_double[ji][1] = tmp1;
56066 : }
56067 : else
56068 : {
56069 0 : if( klnew<mmax )
56070 : {
56071 :
56072 : /*
56073 : * Eigenvalue in both intervals -- add upper to queue.
56074 : */
56075 0 : klnew = klnew+1;
56076 0 : ab->ptr.pp_double[klnew][2] = ab->ptr.pp_double[ji][2];
56077 0 : nab->ptr.pp_int[klnew][2] = nab->ptr.pp_int[ji][2];
56078 0 : ab->ptr.pp_double[klnew][1] = tmp1;
56079 0 : nab->ptr.pp_int[klnew][1] = itmp1;
56080 0 : ab->ptr.pp_double[ji][2] = tmp1;
56081 0 : nab->ptr.pp_int[ji][2] = itmp1;
56082 : }
56083 : else
56084 : {
56085 0 : *info = mmax+1;
56086 0 : return;
56087 : }
56088 : }
56089 : }
56090 : }
56091 : else
56092 : {
56093 :
56094 : /*
56095 : * IJOB=3: Binary search. Keep only the interval
56096 : * containing w s.t. N(w) = NVAL
56097 : */
56098 0 : if( itmp1<=nval->ptr.p_int[ji] )
56099 : {
56100 0 : ab->ptr.pp_double[ji][1] = tmp1;
56101 0 : nab->ptr.pp_int[ji][1] = itmp1;
56102 : }
56103 0 : if( itmp1>=nval->ptr.p_int[ji] )
56104 : {
56105 0 : ab->ptr.pp_double[ji][2] = tmp1;
56106 0 : nab->ptr.pp_int[ji][2] = itmp1;
56107 : }
56108 : }
56109 : }
56110 0 : kl = klnew;
56111 :
56112 : /*
56113 : * Check for convergence
56114 : */
56115 0 : kfnew = kf;
56116 0 : for(ji=kf; ji<=kl; ji++)
56117 : {
56118 0 : tmp1 = ae_fabs(ab->ptr.pp_double[ji][2]-ab->ptr.pp_double[ji][1], _state);
56119 0 : tmp2 = ae_maxreal(ae_fabs(ab->ptr.pp_double[ji][2], _state), ae_fabs(ab->ptr.pp_double[ji][1], _state), _state);
56120 0 : if( ae_fp_less(tmp1,ae_maxreal(abstol, ae_maxreal(pivmin, reltol*tmp2, _state), _state))||nab->ptr.pp_int[ji][1]>=nab->ptr.pp_int[ji][2] )
56121 : {
56122 :
56123 : /*
56124 : * Converged -- Swap with position KFNEW,
56125 : * then increment KFNEW
56126 : */
56127 0 : if( ji>kfnew )
56128 : {
56129 0 : tmp1 = ab->ptr.pp_double[ji][1];
56130 0 : tmp2 = ab->ptr.pp_double[ji][2];
56131 0 : itmp1 = nab->ptr.pp_int[ji][1];
56132 0 : itmp2 = nab->ptr.pp_int[ji][2];
56133 0 : ab->ptr.pp_double[ji][1] = ab->ptr.pp_double[kfnew][1];
56134 0 : ab->ptr.pp_double[ji][2] = ab->ptr.pp_double[kfnew][2];
56135 0 : nab->ptr.pp_int[ji][1] = nab->ptr.pp_int[kfnew][1];
56136 0 : nab->ptr.pp_int[ji][2] = nab->ptr.pp_int[kfnew][2];
56137 0 : ab->ptr.pp_double[kfnew][1] = tmp1;
56138 0 : ab->ptr.pp_double[kfnew][2] = tmp2;
56139 0 : nab->ptr.pp_int[kfnew][1] = itmp1;
56140 0 : nab->ptr.pp_int[kfnew][2] = itmp2;
56141 0 : if( ijob==3 )
56142 : {
56143 0 : itmp1 = nval->ptr.p_int[ji];
56144 0 : nval->ptr.p_int[ji] = nval->ptr.p_int[kfnew];
56145 0 : nval->ptr.p_int[kfnew] = itmp1;
56146 : }
56147 : }
56148 0 : kfnew = kfnew+1;
56149 : }
56150 : }
56151 0 : kf = kfnew;
56152 :
56153 : /*
56154 : * Choose Midpoints
56155 : */
56156 0 : for(ji=kf; ji<=kl; ji++)
56157 : {
56158 0 : c->ptr.p_double[ji] = 0.5*(ab->ptr.pp_double[ji][1]+ab->ptr.pp_double[ji][2]);
56159 : }
56160 :
56161 : /*
56162 : * If no more intervals to refine, quit.
56163 : */
56164 0 : if( kf>kl )
56165 : {
56166 0 : break;
56167 : }
56168 : }
56169 :
56170 : /*
56171 : * Converged
56172 : */
56173 0 : *info = ae_maxint(kl+1-kf, 0, _state);
56174 0 : *mout = kl;
56175 : }
56176 :
56177 :
56178 : /*************************************************************************
56179 : Internal subroutine
56180 :
56181 : -- LAPACK routine (version 3.0) --
56182 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
56183 : Courant Institute, Argonne National Lab, and Rice University
56184 : June 30, 1999
56185 : *************************************************************************/
56186 0 : static void evd_rmatrixinternaltrevc(/* Real */ ae_matrix* t,
56187 : ae_int_t n,
56188 : ae_int_t side,
56189 : ae_int_t howmny,
56190 : /* Boolean */ ae_vector* vselect,
56191 : /* Real */ ae_matrix* vl,
56192 : /* Real */ ae_matrix* vr,
56193 : ae_int_t* m,
56194 : ae_int_t* info,
56195 : ae_state *_state)
56196 : {
56197 : ae_frame _frame_block;
56198 : ae_vector _vselect;
56199 : ae_int_t i;
56200 : ae_int_t j;
56201 : ae_matrix t1;
56202 : ae_matrix vl1;
56203 : ae_matrix vr1;
56204 : ae_vector vselect1;
56205 :
56206 0 : ae_frame_make(_state, &_frame_block);
56207 0 : memset(&_vselect, 0, sizeof(_vselect));
56208 0 : memset(&t1, 0, sizeof(t1));
56209 0 : memset(&vl1, 0, sizeof(vl1));
56210 0 : memset(&vr1, 0, sizeof(vr1));
56211 0 : memset(&vselect1, 0, sizeof(vselect1));
56212 0 : ae_vector_init_copy(&_vselect, vselect, _state, ae_true);
56213 0 : vselect = &_vselect;
56214 0 : *m = 0;
56215 0 : *info = 0;
56216 0 : ae_matrix_init(&t1, 0, 0, DT_REAL, _state, ae_true);
56217 0 : ae_matrix_init(&vl1, 0, 0, DT_REAL, _state, ae_true);
56218 0 : ae_matrix_init(&vr1, 0, 0, DT_REAL, _state, ae_true);
56219 0 : ae_vector_init(&vselect1, 0, DT_BOOL, _state, ae_true);
56220 :
56221 :
56222 : /*
56223 : * Allocate VL/VR, if needed
56224 : */
56225 0 : if( howmny==2||howmny==3 )
56226 : {
56227 0 : if( side==1||side==3 )
56228 : {
56229 0 : rmatrixsetlengthatleast(vr, n, n, _state);
56230 : }
56231 0 : if( side==2||side==3 )
56232 : {
56233 0 : rmatrixsetlengthatleast(vl, n, n, _state);
56234 : }
56235 : }
56236 :
56237 : /*
56238 : * Try to use MKL kernel
56239 : */
56240 0 : if( rmatrixinternaltrevcmkl(t, n, side, howmny, vl, vr, m, info, _state) )
56241 : {
56242 0 : ae_frame_leave(_state);
56243 0 : return;
56244 : }
56245 :
56246 : /*
56247 : * ALGLIB version
56248 : */
56249 0 : ae_matrix_set_length(&t1, n+1, n+1, _state);
56250 0 : for(i=0; i<=n-1; i++)
56251 : {
56252 0 : for(j=0; j<=n-1; j++)
56253 : {
56254 0 : t1.ptr.pp_double[i+1][j+1] = t->ptr.pp_double[i][j];
56255 : }
56256 : }
56257 0 : if( howmny==3 )
56258 : {
56259 0 : ae_vector_set_length(&vselect1, n+1, _state);
56260 0 : for(i=0; i<=n-1; i++)
56261 : {
56262 0 : vselect1.ptr.p_bool[1+i] = vselect->ptr.p_bool[i];
56263 : }
56264 : }
56265 0 : if( (side==2||side==3)&&howmny==1 )
56266 : {
56267 0 : ae_matrix_set_length(&vl1, n+1, n+1, _state);
56268 0 : for(i=0; i<=n-1; i++)
56269 : {
56270 0 : for(j=0; j<=n-1; j++)
56271 : {
56272 0 : vl1.ptr.pp_double[i+1][j+1] = vl->ptr.pp_double[i][j];
56273 : }
56274 : }
56275 : }
56276 0 : if( (side==1||side==3)&&howmny==1 )
56277 : {
56278 0 : ae_matrix_set_length(&vr1, n+1, n+1, _state);
56279 0 : for(i=0; i<=n-1; i++)
56280 : {
56281 0 : for(j=0; j<=n-1; j++)
56282 : {
56283 0 : vr1.ptr.pp_double[i+1][j+1] = vr->ptr.pp_double[i][j];
56284 : }
56285 : }
56286 : }
56287 0 : evd_internaltrevc(&t1, n, side, howmny, &vselect1, &vl1, &vr1, m, info, _state);
56288 0 : if( side!=1 )
56289 : {
56290 0 : rmatrixsetlengthatleast(vl, n, n, _state);
56291 0 : for(i=0; i<=n-1; i++)
56292 : {
56293 0 : for(j=0; j<=n-1; j++)
56294 : {
56295 0 : vl->ptr.pp_double[i][j] = vl1.ptr.pp_double[i+1][j+1];
56296 : }
56297 : }
56298 : }
56299 0 : if( side!=2 )
56300 : {
56301 0 : rmatrixsetlengthatleast(vr, n, n, _state);
56302 0 : for(i=0; i<=n-1; i++)
56303 : {
56304 0 : for(j=0; j<=n-1; j++)
56305 : {
56306 0 : vr->ptr.pp_double[i][j] = vr1.ptr.pp_double[i+1][j+1];
56307 : }
56308 : }
56309 : }
56310 0 : ae_frame_leave(_state);
56311 : }
56312 :
56313 :
56314 : /*************************************************************************
56315 : Internal subroutine
56316 :
56317 : -- LAPACK routine (version 3.0) --
56318 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
56319 : Courant Institute, Argonne National Lab, and Rice University
56320 : June 30, 1999
56321 : *************************************************************************/
56322 0 : static void evd_internaltrevc(/* Real */ ae_matrix* t,
56323 : ae_int_t n,
56324 : ae_int_t side,
56325 : ae_int_t howmny,
56326 : /* Boolean */ ae_vector* vselect,
56327 : /* Real */ ae_matrix* vl,
56328 : /* Real */ ae_matrix* vr,
56329 : ae_int_t* m,
56330 : ae_int_t* info,
56331 : ae_state *_state)
56332 : {
56333 : ae_frame _frame_block;
56334 : ae_vector _vselect;
56335 : ae_bool allv;
56336 : ae_bool bothv;
56337 : ae_bool leftv;
56338 : ae_bool over;
56339 : ae_bool pair;
56340 : ae_bool rightv;
56341 : ae_bool somev;
56342 : ae_int_t i;
56343 : ae_int_t ierr;
56344 : ae_int_t ii;
56345 : ae_int_t ip;
56346 : ae_int_t iis;
56347 : ae_int_t j;
56348 : ae_int_t j1;
56349 : ae_int_t j2;
56350 : ae_int_t jnxt;
56351 : ae_int_t k;
56352 : ae_int_t ki;
56353 : ae_int_t n2;
56354 : double beta;
56355 : double bignum;
56356 : double emax;
56357 : double rec;
56358 : double remax;
56359 : double scl;
56360 : double smin;
56361 : double smlnum;
56362 : double ulp;
56363 : double unfl;
56364 : double vcrit;
56365 : double vmax;
56366 : double wi;
56367 : double wr;
56368 : double xnorm;
56369 : ae_matrix x;
56370 : ae_vector work;
56371 : ae_vector temp;
56372 : ae_matrix temp11;
56373 : ae_matrix temp22;
56374 : ae_matrix temp11b;
56375 : ae_matrix temp21b;
56376 : ae_matrix temp12b;
56377 : ae_matrix temp22b;
56378 : ae_bool skipflag;
56379 : ae_int_t k1;
56380 : ae_int_t k2;
56381 : ae_int_t k3;
56382 : ae_int_t k4;
56383 : double vt;
56384 : ae_vector rswap4;
56385 : ae_vector zswap4;
56386 : ae_matrix ipivot44;
56387 : ae_vector civ4;
56388 : ae_vector crv4;
56389 :
56390 0 : ae_frame_make(_state, &_frame_block);
56391 0 : memset(&_vselect, 0, sizeof(_vselect));
56392 0 : memset(&x, 0, sizeof(x));
56393 0 : memset(&work, 0, sizeof(work));
56394 0 : memset(&temp, 0, sizeof(temp));
56395 0 : memset(&temp11, 0, sizeof(temp11));
56396 0 : memset(&temp22, 0, sizeof(temp22));
56397 0 : memset(&temp11b, 0, sizeof(temp11b));
56398 0 : memset(&temp21b, 0, sizeof(temp21b));
56399 0 : memset(&temp12b, 0, sizeof(temp12b));
56400 0 : memset(&temp22b, 0, sizeof(temp22b));
56401 0 : memset(&rswap4, 0, sizeof(rswap4));
56402 0 : memset(&zswap4, 0, sizeof(zswap4));
56403 0 : memset(&ipivot44, 0, sizeof(ipivot44));
56404 0 : memset(&civ4, 0, sizeof(civ4));
56405 0 : memset(&crv4, 0, sizeof(crv4));
56406 0 : ae_vector_init_copy(&_vselect, vselect, _state, ae_true);
56407 0 : vselect = &_vselect;
56408 0 : *m = 0;
56409 0 : *info = 0;
56410 0 : ae_matrix_init(&x, 0, 0, DT_REAL, _state, ae_true);
56411 0 : ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
56412 0 : ae_vector_init(&temp, 0, DT_REAL, _state, ae_true);
56413 0 : ae_matrix_init(&temp11, 0, 0, DT_REAL, _state, ae_true);
56414 0 : ae_matrix_init(&temp22, 0, 0, DT_REAL, _state, ae_true);
56415 0 : ae_matrix_init(&temp11b, 0, 0, DT_REAL, _state, ae_true);
56416 0 : ae_matrix_init(&temp21b, 0, 0, DT_REAL, _state, ae_true);
56417 0 : ae_matrix_init(&temp12b, 0, 0, DT_REAL, _state, ae_true);
56418 0 : ae_matrix_init(&temp22b, 0, 0, DT_REAL, _state, ae_true);
56419 0 : ae_vector_init(&rswap4, 0, DT_BOOL, _state, ae_true);
56420 0 : ae_vector_init(&zswap4, 0, DT_BOOL, _state, ae_true);
56421 0 : ae_matrix_init(&ipivot44, 0, 0, DT_INT, _state, ae_true);
56422 0 : ae_vector_init(&civ4, 0, DT_REAL, _state, ae_true);
56423 0 : ae_vector_init(&crv4, 0, DT_REAL, _state, ae_true);
56424 :
56425 0 : ae_matrix_set_length(&x, 2+1, 2+1, _state);
56426 0 : ae_matrix_set_length(&temp11, 1+1, 1+1, _state);
56427 0 : ae_matrix_set_length(&temp11b, 1+1, 1+1, _state);
56428 0 : ae_matrix_set_length(&temp21b, 2+1, 1+1, _state);
56429 0 : ae_matrix_set_length(&temp12b, 1+1, 2+1, _state);
56430 0 : ae_matrix_set_length(&temp22b, 2+1, 2+1, _state);
56431 0 : ae_matrix_set_length(&temp22, 2+1, 2+1, _state);
56432 0 : ae_vector_set_length(&work, 3*n+1, _state);
56433 0 : ae_vector_set_length(&temp, n+1, _state);
56434 0 : ae_vector_set_length(&rswap4, 4+1, _state);
56435 0 : ae_vector_set_length(&zswap4, 4+1, _state);
56436 0 : ae_matrix_set_length(&ipivot44, 4+1, 4+1, _state);
56437 0 : ae_vector_set_length(&civ4, 4+1, _state);
56438 0 : ae_vector_set_length(&crv4, 4+1, _state);
56439 0 : if( howmny!=1 )
56440 : {
56441 0 : if( side==1||side==3 )
56442 : {
56443 0 : ae_matrix_set_length(vr, n+1, n+1, _state);
56444 : }
56445 0 : if( side==2||side==3 )
56446 : {
56447 0 : ae_matrix_set_length(vl, n+1, n+1, _state);
56448 : }
56449 : }
56450 :
56451 : /*
56452 : * Decode and test the input parameters
56453 : */
56454 0 : bothv = side==3;
56455 0 : rightv = side==1||bothv;
56456 0 : leftv = side==2||bothv;
56457 0 : allv = howmny==2;
56458 0 : over = howmny==1;
56459 0 : somev = howmny==3;
56460 0 : *info = 0;
56461 0 : if( n<0 )
56462 : {
56463 0 : *info = -2;
56464 0 : ae_frame_leave(_state);
56465 0 : return;
56466 : }
56467 0 : if( !rightv&&!leftv )
56468 : {
56469 0 : *info = -3;
56470 0 : ae_frame_leave(_state);
56471 0 : return;
56472 : }
56473 0 : if( (!allv&&!over)&&!somev )
56474 : {
56475 0 : *info = -4;
56476 0 : ae_frame_leave(_state);
56477 0 : return;
56478 : }
56479 :
56480 : /*
56481 : * Set M to the number of columns required to store the selected
56482 : * eigenvectors, standardize the array SELECT if necessary, and
56483 : * test MM.
56484 : */
56485 0 : if( somev )
56486 : {
56487 0 : *m = 0;
56488 0 : pair = ae_false;
56489 0 : for(j=1; j<=n; j++)
56490 : {
56491 0 : if( pair )
56492 : {
56493 0 : pair = ae_false;
56494 0 : vselect->ptr.p_bool[j] = ae_false;
56495 : }
56496 : else
56497 : {
56498 0 : if( j<n )
56499 : {
56500 0 : if( ae_fp_eq(t->ptr.pp_double[j+1][j],(double)(0)) )
56501 : {
56502 0 : if( vselect->ptr.p_bool[j] )
56503 : {
56504 0 : *m = *m+1;
56505 : }
56506 : }
56507 : else
56508 : {
56509 0 : pair = ae_true;
56510 0 : if( vselect->ptr.p_bool[j]||vselect->ptr.p_bool[j+1] )
56511 : {
56512 0 : vselect->ptr.p_bool[j] = ae_true;
56513 0 : *m = *m+2;
56514 : }
56515 : }
56516 : }
56517 : else
56518 : {
56519 0 : if( vselect->ptr.p_bool[n] )
56520 : {
56521 0 : *m = *m+1;
56522 : }
56523 : }
56524 : }
56525 : }
56526 : }
56527 : else
56528 : {
56529 0 : *m = n;
56530 : }
56531 :
56532 : /*
56533 : * Quick return if possible.
56534 : */
56535 0 : if( n==0 )
56536 : {
56537 0 : ae_frame_leave(_state);
56538 0 : return;
56539 : }
56540 :
56541 : /*
56542 : * Set the constants to control overflow.
56543 : */
56544 0 : unfl = ae_minrealnumber;
56545 0 : ulp = ae_machineepsilon;
56546 0 : smlnum = unfl*(n/ulp);
56547 0 : bignum = (1-ulp)/smlnum;
56548 :
56549 : /*
56550 : * Compute 1-norm of each column of strictly upper triangular
56551 : * part of T to control overflow in triangular solver.
56552 : */
56553 0 : work.ptr.p_double[1] = (double)(0);
56554 0 : for(j=2; j<=n; j++)
56555 : {
56556 0 : work.ptr.p_double[j] = (double)(0);
56557 0 : for(i=1; i<=j-1; i++)
56558 : {
56559 0 : work.ptr.p_double[j] = work.ptr.p_double[j]+ae_fabs(t->ptr.pp_double[i][j], _state);
56560 : }
56561 : }
56562 :
56563 : /*
56564 : * Index IP is used to specify the real or complex eigenvalue:
56565 : * IP = 0, real eigenvalue,
56566 : * 1, first of conjugate complex pair: (wr,wi)
56567 : * -1, second of conjugate complex pair: (wr,wi)
56568 : */
56569 0 : n2 = 2*n;
56570 0 : if( rightv )
56571 : {
56572 :
56573 : /*
56574 : * Compute right eigenvectors.
56575 : */
56576 0 : ip = 0;
56577 0 : iis = *m;
56578 0 : for(ki=n; ki>=1; ki--)
56579 : {
56580 0 : skipflag = ae_false;
56581 0 : if( ip==1 )
56582 : {
56583 0 : skipflag = ae_true;
56584 : }
56585 : else
56586 : {
56587 0 : if( ki!=1 )
56588 : {
56589 0 : if( ae_fp_neq(t->ptr.pp_double[ki][ki-1],(double)(0)) )
56590 : {
56591 0 : ip = -1;
56592 : }
56593 : }
56594 0 : if( somev )
56595 : {
56596 0 : if( ip==0 )
56597 : {
56598 0 : if( !vselect->ptr.p_bool[ki] )
56599 : {
56600 0 : skipflag = ae_true;
56601 : }
56602 : }
56603 : else
56604 : {
56605 0 : if( !vselect->ptr.p_bool[ki-1] )
56606 : {
56607 0 : skipflag = ae_true;
56608 : }
56609 : }
56610 : }
56611 : }
56612 0 : if( !skipflag )
56613 : {
56614 :
56615 : /*
56616 : * Compute the KI-th eigenvalue (WR,WI).
56617 : */
56618 0 : wr = t->ptr.pp_double[ki][ki];
56619 0 : wi = (double)(0);
56620 0 : if( ip!=0 )
56621 : {
56622 0 : wi = ae_sqrt(ae_fabs(t->ptr.pp_double[ki][ki-1], _state), _state)*ae_sqrt(ae_fabs(t->ptr.pp_double[ki-1][ki], _state), _state);
56623 : }
56624 0 : smin = ae_maxreal(ulp*(ae_fabs(wr, _state)+ae_fabs(wi, _state)), smlnum, _state);
56625 0 : if( ip==0 )
56626 : {
56627 :
56628 : /*
56629 : * Real right eigenvector
56630 : */
56631 0 : work.ptr.p_double[ki+n] = (double)(1);
56632 :
56633 : /*
56634 : * Form right-hand side
56635 : */
56636 0 : for(k=1; k<=ki-1; k++)
56637 : {
56638 0 : work.ptr.p_double[k+n] = -t->ptr.pp_double[k][ki];
56639 : }
56640 :
56641 : /*
56642 : * Solve the upper quasi-triangular system:
56643 : * (T(1:KI-1,1:KI-1) - WR)*X = SCALE*WORK.
56644 : */
56645 0 : jnxt = ki-1;
56646 0 : for(j=ki-1; j>=1; j--)
56647 : {
56648 0 : if( j>jnxt )
56649 : {
56650 0 : continue;
56651 : }
56652 0 : j1 = j;
56653 0 : j2 = j;
56654 0 : jnxt = j-1;
56655 0 : if( j>1 )
56656 : {
56657 0 : if( ae_fp_neq(t->ptr.pp_double[j][j-1],(double)(0)) )
56658 : {
56659 0 : j1 = j-1;
56660 0 : jnxt = j-2;
56661 : }
56662 : }
56663 0 : if( j1==j2 )
56664 : {
56665 :
56666 : /*
56667 : * 1-by-1 diagonal block
56668 : */
56669 0 : temp11.ptr.pp_double[1][1] = t->ptr.pp_double[j][j];
56670 0 : temp11b.ptr.pp_double[1][1] = work.ptr.p_double[j+n];
56671 0 : evd_internalhsevdlaln2(ae_false, 1, 1, smin, (double)(1), &temp11, 1.0, 1.0, &temp11b, wr, 0.0, &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state);
56672 :
56673 : /*
56674 : * Scale X(1,1) to avoid overflow when updating
56675 : * the right-hand side.
56676 : */
56677 0 : if( ae_fp_greater(xnorm,(double)(1)) )
56678 : {
56679 0 : if( ae_fp_greater(work.ptr.p_double[j],bignum/xnorm) )
56680 : {
56681 0 : x.ptr.pp_double[1][1] = x.ptr.pp_double[1][1]/xnorm;
56682 0 : scl = scl/xnorm;
56683 : }
56684 : }
56685 :
56686 : /*
56687 : * Scale if necessary
56688 : */
56689 0 : if( ae_fp_neq(scl,(double)(1)) )
56690 : {
56691 0 : k1 = n+1;
56692 0 : k2 = n+ki;
56693 0 : ae_v_muld(&work.ptr.p_double[k1], 1, ae_v_len(k1,k2), scl);
56694 : }
56695 0 : work.ptr.p_double[j+n] = x.ptr.pp_double[1][1];
56696 :
56697 : /*
56698 : * Update right-hand side
56699 : */
56700 0 : k1 = 1+n;
56701 0 : k2 = j-1+n;
56702 0 : k3 = j-1;
56703 0 : vt = -x.ptr.pp_double[1][1];
56704 0 : ae_v_addd(&work.ptr.p_double[k1], 1, &t->ptr.pp_double[1][j], t->stride, ae_v_len(k1,k2), vt);
56705 : }
56706 : else
56707 : {
56708 :
56709 : /*
56710 : * 2-by-2 diagonal block
56711 : */
56712 0 : temp22.ptr.pp_double[1][1] = t->ptr.pp_double[j-1][j-1];
56713 0 : temp22.ptr.pp_double[1][2] = t->ptr.pp_double[j-1][j];
56714 0 : temp22.ptr.pp_double[2][1] = t->ptr.pp_double[j][j-1];
56715 0 : temp22.ptr.pp_double[2][2] = t->ptr.pp_double[j][j];
56716 0 : temp21b.ptr.pp_double[1][1] = work.ptr.p_double[j-1+n];
56717 0 : temp21b.ptr.pp_double[2][1] = work.ptr.p_double[j+n];
56718 0 : evd_internalhsevdlaln2(ae_false, 2, 1, smin, 1.0, &temp22, 1.0, 1.0, &temp21b, wr, (double)(0), &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state);
56719 :
56720 : /*
56721 : * Scale X(1,1) and X(2,1) to avoid overflow when
56722 : * updating the right-hand side.
56723 : */
56724 0 : if( ae_fp_greater(xnorm,(double)(1)) )
56725 : {
56726 0 : beta = ae_maxreal(work.ptr.p_double[j-1], work.ptr.p_double[j], _state);
56727 0 : if( ae_fp_greater(beta,bignum/xnorm) )
56728 : {
56729 0 : x.ptr.pp_double[1][1] = x.ptr.pp_double[1][1]/xnorm;
56730 0 : x.ptr.pp_double[2][1] = x.ptr.pp_double[2][1]/xnorm;
56731 0 : scl = scl/xnorm;
56732 : }
56733 : }
56734 :
56735 : /*
56736 : * Scale if necessary
56737 : */
56738 0 : if( ae_fp_neq(scl,(double)(1)) )
56739 : {
56740 0 : k1 = 1+n;
56741 0 : k2 = ki+n;
56742 0 : ae_v_muld(&work.ptr.p_double[k1], 1, ae_v_len(k1,k2), scl);
56743 : }
56744 0 : work.ptr.p_double[j-1+n] = x.ptr.pp_double[1][1];
56745 0 : work.ptr.p_double[j+n] = x.ptr.pp_double[2][1];
56746 :
56747 : /*
56748 : * Update right-hand side
56749 : */
56750 0 : k1 = 1+n;
56751 0 : k2 = j-2+n;
56752 0 : k3 = j-2;
56753 0 : k4 = j-1;
56754 0 : vt = -x.ptr.pp_double[1][1];
56755 0 : ae_v_addd(&work.ptr.p_double[k1], 1, &t->ptr.pp_double[1][k4], t->stride, ae_v_len(k1,k2), vt);
56756 0 : vt = -x.ptr.pp_double[2][1];
56757 0 : ae_v_addd(&work.ptr.p_double[k1], 1, &t->ptr.pp_double[1][j], t->stride, ae_v_len(k1,k2), vt);
56758 : }
56759 : }
56760 :
56761 : /*
56762 : * Copy the vector x or Q*x to VR and normalize.
56763 : */
56764 0 : if( !over )
56765 : {
56766 0 : k1 = 1+n;
56767 0 : k2 = ki+n;
56768 0 : ae_v_move(&vr->ptr.pp_double[1][iis], vr->stride, &work.ptr.p_double[k1], 1, ae_v_len(1,ki));
56769 0 : ii = columnidxabsmax(vr, 1, ki, iis, _state);
56770 0 : remax = 1/ae_fabs(vr->ptr.pp_double[ii][iis], _state);
56771 0 : ae_v_muld(&vr->ptr.pp_double[1][iis], vr->stride, ae_v_len(1,ki), remax);
56772 0 : for(k=ki+1; k<=n; k++)
56773 : {
56774 0 : vr->ptr.pp_double[k][iis] = (double)(0);
56775 : }
56776 : }
56777 : else
56778 : {
56779 0 : if( ki>1 )
56780 : {
56781 0 : ae_v_move(&temp.ptr.p_double[1], 1, &vr->ptr.pp_double[1][ki], vr->stride, ae_v_len(1,n));
56782 0 : matrixvectormultiply(vr, 1, n, 1, ki-1, ae_false, &work, 1+n, ki-1+n, 1.0, &temp, 1, n, work.ptr.p_double[ki+n], _state);
56783 0 : ae_v_move(&vr->ptr.pp_double[1][ki], vr->stride, &temp.ptr.p_double[1], 1, ae_v_len(1,n));
56784 : }
56785 0 : ii = columnidxabsmax(vr, 1, n, ki, _state);
56786 0 : remax = 1/ae_fabs(vr->ptr.pp_double[ii][ki], _state);
56787 0 : ae_v_muld(&vr->ptr.pp_double[1][ki], vr->stride, ae_v_len(1,n), remax);
56788 : }
56789 : }
56790 : else
56791 : {
56792 :
56793 : /*
56794 : * Complex right eigenvector.
56795 : *
56796 : * Initial solve
56797 : * [ (T(KI-1,KI-1) T(KI-1,KI) ) - (WR + I* WI)]*X = 0.
56798 : * [ (T(KI,KI-1) T(KI,KI) ) ]
56799 : */
56800 0 : if( ae_fp_greater_eq(ae_fabs(t->ptr.pp_double[ki-1][ki], _state),ae_fabs(t->ptr.pp_double[ki][ki-1], _state)) )
56801 : {
56802 0 : work.ptr.p_double[ki-1+n] = (double)(1);
56803 0 : work.ptr.p_double[ki+n2] = wi/t->ptr.pp_double[ki-1][ki];
56804 : }
56805 : else
56806 : {
56807 0 : work.ptr.p_double[ki-1+n] = -wi/t->ptr.pp_double[ki][ki-1];
56808 0 : work.ptr.p_double[ki+n2] = (double)(1);
56809 : }
56810 0 : work.ptr.p_double[ki+n] = (double)(0);
56811 0 : work.ptr.p_double[ki-1+n2] = (double)(0);
56812 :
56813 : /*
56814 : * Form right-hand side
56815 : */
56816 0 : for(k=1; k<=ki-2; k++)
56817 : {
56818 0 : work.ptr.p_double[k+n] = -work.ptr.p_double[ki-1+n]*t->ptr.pp_double[k][ki-1];
56819 0 : work.ptr.p_double[k+n2] = -work.ptr.p_double[ki+n2]*t->ptr.pp_double[k][ki];
56820 : }
56821 :
56822 : /*
56823 : * Solve upper quasi-triangular system:
56824 : * (T(1:KI-2,1:KI-2) - (WR+i*WI))*X = SCALE*(WORK+i*WORK2)
56825 : */
56826 0 : jnxt = ki-2;
56827 0 : for(j=ki-2; j>=1; j--)
56828 : {
56829 0 : if( j>jnxt )
56830 : {
56831 0 : continue;
56832 : }
56833 0 : j1 = j;
56834 0 : j2 = j;
56835 0 : jnxt = j-1;
56836 0 : if( j>1 )
56837 : {
56838 0 : if( ae_fp_neq(t->ptr.pp_double[j][j-1],(double)(0)) )
56839 : {
56840 0 : j1 = j-1;
56841 0 : jnxt = j-2;
56842 : }
56843 : }
56844 0 : if( j1==j2 )
56845 : {
56846 :
56847 : /*
56848 : * 1-by-1 diagonal block
56849 : */
56850 0 : temp11.ptr.pp_double[1][1] = t->ptr.pp_double[j][j];
56851 0 : temp12b.ptr.pp_double[1][1] = work.ptr.p_double[j+n];
56852 0 : temp12b.ptr.pp_double[1][2] = work.ptr.p_double[j+n+n];
56853 0 : evd_internalhsevdlaln2(ae_false, 1, 2, smin, 1.0, &temp11, 1.0, 1.0, &temp12b, wr, wi, &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state);
56854 :
56855 : /*
56856 : * Scale X(1,1) and X(1,2) to avoid overflow when
56857 : * updating the right-hand side.
56858 : */
56859 0 : if( ae_fp_greater(xnorm,(double)(1)) )
56860 : {
56861 0 : if( ae_fp_greater(work.ptr.p_double[j],bignum/xnorm) )
56862 : {
56863 0 : x.ptr.pp_double[1][1] = x.ptr.pp_double[1][1]/xnorm;
56864 0 : x.ptr.pp_double[1][2] = x.ptr.pp_double[1][2]/xnorm;
56865 0 : scl = scl/xnorm;
56866 : }
56867 : }
56868 :
56869 : /*
56870 : * Scale if necessary
56871 : */
56872 0 : if( ae_fp_neq(scl,(double)(1)) )
56873 : {
56874 0 : k1 = 1+n;
56875 0 : k2 = ki+n;
56876 0 : ae_v_muld(&work.ptr.p_double[k1], 1, ae_v_len(k1,k2), scl);
56877 0 : k1 = 1+n2;
56878 0 : k2 = ki+n2;
56879 0 : ae_v_muld(&work.ptr.p_double[k1], 1, ae_v_len(k1,k2), scl);
56880 : }
56881 0 : work.ptr.p_double[j+n] = x.ptr.pp_double[1][1];
56882 0 : work.ptr.p_double[j+n2] = x.ptr.pp_double[1][2];
56883 :
56884 : /*
56885 : * Update the right-hand side
56886 : */
56887 0 : k1 = 1+n;
56888 0 : k2 = j-1+n;
56889 0 : k3 = 1;
56890 0 : k4 = j-1;
56891 0 : vt = -x.ptr.pp_double[1][1];
56892 0 : ae_v_addd(&work.ptr.p_double[k1], 1, &t->ptr.pp_double[k3][j], t->stride, ae_v_len(k1,k2), vt);
56893 0 : k1 = 1+n2;
56894 0 : k2 = j-1+n2;
56895 0 : k3 = 1;
56896 0 : k4 = j-1;
56897 0 : vt = -x.ptr.pp_double[1][2];
56898 0 : ae_v_addd(&work.ptr.p_double[k1], 1, &t->ptr.pp_double[k3][j], t->stride, ae_v_len(k1,k2), vt);
56899 : }
56900 : else
56901 : {
56902 :
56903 : /*
56904 : * 2-by-2 diagonal block
56905 : */
56906 0 : temp22.ptr.pp_double[1][1] = t->ptr.pp_double[j-1][j-1];
56907 0 : temp22.ptr.pp_double[1][2] = t->ptr.pp_double[j-1][j];
56908 0 : temp22.ptr.pp_double[2][1] = t->ptr.pp_double[j][j-1];
56909 0 : temp22.ptr.pp_double[2][2] = t->ptr.pp_double[j][j];
56910 0 : temp22b.ptr.pp_double[1][1] = work.ptr.p_double[j-1+n];
56911 0 : temp22b.ptr.pp_double[1][2] = work.ptr.p_double[j-1+n+n];
56912 0 : temp22b.ptr.pp_double[2][1] = work.ptr.p_double[j+n];
56913 0 : temp22b.ptr.pp_double[2][2] = work.ptr.p_double[j+n+n];
56914 0 : evd_internalhsevdlaln2(ae_false, 2, 2, smin, 1.0, &temp22, 1.0, 1.0, &temp22b, wr, wi, &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state);
56915 :
56916 : /*
56917 : * Scale X to avoid overflow when updating
56918 : * the right-hand side.
56919 : */
56920 0 : if( ae_fp_greater(xnorm,(double)(1)) )
56921 : {
56922 0 : beta = ae_maxreal(work.ptr.p_double[j-1], work.ptr.p_double[j], _state);
56923 0 : if( ae_fp_greater(beta,bignum/xnorm) )
56924 : {
56925 0 : rec = 1/xnorm;
56926 0 : x.ptr.pp_double[1][1] = x.ptr.pp_double[1][1]*rec;
56927 0 : x.ptr.pp_double[1][2] = x.ptr.pp_double[1][2]*rec;
56928 0 : x.ptr.pp_double[2][1] = x.ptr.pp_double[2][1]*rec;
56929 0 : x.ptr.pp_double[2][2] = x.ptr.pp_double[2][2]*rec;
56930 0 : scl = scl*rec;
56931 : }
56932 : }
56933 :
56934 : /*
56935 : * Scale if necessary
56936 : */
56937 0 : if( ae_fp_neq(scl,(double)(1)) )
56938 : {
56939 0 : ae_v_muld(&work.ptr.p_double[1+n], 1, ae_v_len(1+n,ki+n), scl);
56940 0 : ae_v_muld(&work.ptr.p_double[1+n2], 1, ae_v_len(1+n2,ki+n2), scl);
56941 : }
56942 0 : work.ptr.p_double[j-1+n] = x.ptr.pp_double[1][1];
56943 0 : work.ptr.p_double[j+n] = x.ptr.pp_double[2][1];
56944 0 : work.ptr.p_double[j-1+n2] = x.ptr.pp_double[1][2];
56945 0 : work.ptr.p_double[j+n2] = x.ptr.pp_double[2][2];
56946 :
56947 : /*
56948 : * Update the right-hand side
56949 : */
56950 0 : vt = -x.ptr.pp_double[1][1];
56951 0 : ae_v_addd(&work.ptr.p_double[n+1], 1, &t->ptr.pp_double[1][j-1], t->stride, ae_v_len(n+1,n+j-2), vt);
56952 0 : vt = -x.ptr.pp_double[2][1];
56953 0 : ae_v_addd(&work.ptr.p_double[n+1], 1, &t->ptr.pp_double[1][j], t->stride, ae_v_len(n+1,n+j-2), vt);
56954 0 : vt = -x.ptr.pp_double[1][2];
56955 0 : ae_v_addd(&work.ptr.p_double[n2+1], 1, &t->ptr.pp_double[1][j-1], t->stride, ae_v_len(n2+1,n2+j-2), vt);
56956 0 : vt = -x.ptr.pp_double[2][2];
56957 0 : ae_v_addd(&work.ptr.p_double[n2+1], 1, &t->ptr.pp_double[1][j], t->stride, ae_v_len(n2+1,n2+j-2), vt);
56958 : }
56959 : }
56960 :
56961 : /*
56962 : * Copy the vector x or Q*x to VR and normalize.
56963 : */
56964 0 : if( !over )
56965 : {
56966 0 : ae_v_move(&vr->ptr.pp_double[1][iis-1], vr->stride, &work.ptr.p_double[n+1], 1, ae_v_len(1,ki));
56967 0 : ae_v_move(&vr->ptr.pp_double[1][iis], vr->stride, &work.ptr.p_double[n2+1], 1, ae_v_len(1,ki));
56968 0 : emax = (double)(0);
56969 0 : for(k=1; k<=ki; k++)
56970 : {
56971 0 : emax = ae_maxreal(emax, ae_fabs(vr->ptr.pp_double[k][iis-1], _state)+ae_fabs(vr->ptr.pp_double[k][iis], _state), _state);
56972 : }
56973 0 : remax = 1/emax;
56974 0 : ae_v_muld(&vr->ptr.pp_double[1][iis-1], vr->stride, ae_v_len(1,ki), remax);
56975 0 : ae_v_muld(&vr->ptr.pp_double[1][iis], vr->stride, ae_v_len(1,ki), remax);
56976 0 : for(k=ki+1; k<=n; k++)
56977 : {
56978 0 : vr->ptr.pp_double[k][iis-1] = (double)(0);
56979 0 : vr->ptr.pp_double[k][iis] = (double)(0);
56980 : }
56981 : }
56982 : else
56983 : {
56984 0 : if( ki>2 )
56985 : {
56986 0 : ae_v_move(&temp.ptr.p_double[1], 1, &vr->ptr.pp_double[1][ki-1], vr->stride, ae_v_len(1,n));
56987 0 : matrixvectormultiply(vr, 1, n, 1, ki-2, ae_false, &work, 1+n, ki-2+n, 1.0, &temp, 1, n, work.ptr.p_double[ki-1+n], _state);
56988 0 : ae_v_move(&vr->ptr.pp_double[1][ki-1], vr->stride, &temp.ptr.p_double[1], 1, ae_v_len(1,n));
56989 0 : ae_v_move(&temp.ptr.p_double[1], 1, &vr->ptr.pp_double[1][ki], vr->stride, ae_v_len(1,n));
56990 0 : matrixvectormultiply(vr, 1, n, 1, ki-2, ae_false, &work, 1+n2, ki-2+n2, 1.0, &temp, 1, n, work.ptr.p_double[ki+n2], _state);
56991 0 : ae_v_move(&vr->ptr.pp_double[1][ki], vr->stride, &temp.ptr.p_double[1], 1, ae_v_len(1,n));
56992 : }
56993 : else
56994 : {
56995 0 : vt = work.ptr.p_double[ki-1+n];
56996 0 : ae_v_muld(&vr->ptr.pp_double[1][ki-1], vr->stride, ae_v_len(1,n), vt);
56997 0 : vt = work.ptr.p_double[ki+n2];
56998 0 : ae_v_muld(&vr->ptr.pp_double[1][ki], vr->stride, ae_v_len(1,n), vt);
56999 : }
57000 0 : emax = (double)(0);
57001 0 : for(k=1; k<=n; k++)
57002 : {
57003 0 : emax = ae_maxreal(emax, ae_fabs(vr->ptr.pp_double[k][ki-1], _state)+ae_fabs(vr->ptr.pp_double[k][ki], _state), _state);
57004 : }
57005 0 : remax = 1/emax;
57006 0 : ae_v_muld(&vr->ptr.pp_double[1][ki-1], vr->stride, ae_v_len(1,n), remax);
57007 0 : ae_v_muld(&vr->ptr.pp_double[1][ki], vr->stride, ae_v_len(1,n), remax);
57008 : }
57009 : }
57010 0 : iis = iis-1;
57011 0 : if( ip!=0 )
57012 : {
57013 0 : iis = iis-1;
57014 : }
57015 : }
57016 0 : if( ip==1 )
57017 : {
57018 0 : ip = 0;
57019 : }
57020 0 : if( ip==-1 )
57021 : {
57022 0 : ip = 1;
57023 : }
57024 : }
57025 : }
57026 0 : if( leftv )
57027 : {
57028 :
57029 : /*
57030 : * Compute left eigenvectors.
57031 : */
57032 0 : ip = 0;
57033 0 : iis = 1;
57034 0 : for(ki=1; ki<=n; ki++)
57035 : {
57036 0 : skipflag = ae_false;
57037 0 : if( ip==-1 )
57038 : {
57039 0 : skipflag = ae_true;
57040 : }
57041 : else
57042 : {
57043 0 : if( ki!=n )
57044 : {
57045 0 : if( ae_fp_neq(t->ptr.pp_double[ki+1][ki],(double)(0)) )
57046 : {
57047 0 : ip = 1;
57048 : }
57049 : }
57050 0 : if( somev )
57051 : {
57052 0 : if( !vselect->ptr.p_bool[ki] )
57053 : {
57054 0 : skipflag = ae_true;
57055 : }
57056 : }
57057 : }
57058 0 : if( !skipflag )
57059 : {
57060 :
57061 : /*
57062 : * Compute the KI-th eigenvalue (WR,WI).
57063 : */
57064 0 : wr = t->ptr.pp_double[ki][ki];
57065 0 : wi = (double)(0);
57066 0 : if( ip!=0 )
57067 : {
57068 0 : wi = ae_sqrt(ae_fabs(t->ptr.pp_double[ki][ki+1], _state), _state)*ae_sqrt(ae_fabs(t->ptr.pp_double[ki+1][ki], _state), _state);
57069 : }
57070 0 : smin = ae_maxreal(ulp*(ae_fabs(wr, _state)+ae_fabs(wi, _state)), smlnum, _state);
57071 0 : if( ip==0 )
57072 : {
57073 :
57074 : /*
57075 : * Real left eigenvector.
57076 : */
57077 0 : work.ptr.p_double[ki+n] = (double)(1);
57078 :
57079 : /*
57080 : * Form right-hand side
57081 : */
57082 0 : for(k=ki+1; k<=n; k++)
57083 : {
57084 0 : work.ptr.p_double[k+n] = -t->ptr.pp_double[ki][k];
57085 : }
57086 :
57087 : /*
57088 : * Solve the quasi-triangular system:
57089 : * (T(KI+1:N,KI+1:N) - WR)'*X = SCALE*WORK
57090 : */
57091 0 : vmax = (double)(1);
57092 0 : vcrit = bignum;
57093 0 : jnxt = ki+1;
57094 0 : for(j=ki+1; j<=n; j++)
57095 : {
57096 0 : if( j<jnxt )
57097 : {
57098 0 : continue;
57099 : }
57100 0 : j1 = j;
57101 0 : j2 = j;
57102 0 : jnxt = j+1;
57103 0 : if( j<n )
57104 : {
57105 0 : if( ae_fp_neq(t->ptr.pp_double[j+1][j],(double)(0)) )
57106 : {
57107 0 : j2 = j+1;
57108 0 : jnxt = j+2;
57109 : }
57110 : }
57111 0 : if( j1==j2 )
57112 : {
57113 :
57114 : /*
57115 : * 1-by-1 diagonal block
57116 : *
57117 : * Scale if necessary to avoid overflow when forming
57118 : * the right-hand side.
57119 : */
57120 0 : if( ae_fp_greater(work.ptr.p_double[j],vcrit) )
57121 : {
57122 0 : rec = 1/vmax;
57123 0 : ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), rec);
57124 0 : vmax = (double)(1);
57125 0 : vcrit = bignum;
57126 : }
57127 0 : vt = ae_v_dotproduct(&t->ptr.pp_double[ki+1][j], t->stride, &work.ptr.p_double[ki+1+n], 1, ae_v_len(ki+1,j-1));
57128 0 : work.ptr.p_double[j+n] = work.ptr.p_double[j+n]-vt;
57129 :
57130 : /*
57131 : * Solve (T(J,J)-WR)'*X = WORK
57132 : */
57133 0 : temp11.ptr.pp_double[1][1] = t->ptr.pp_double[j][j];
57134 0 : temp11b.ptr.pp_double[1][1] = work.ptr.p_double[j+n];
57135 0 : evd_internalhsevdlaln2(ae_false, 1, 1, smin, 1.0, &temp11, 1.0, 1.0, &temp11b, wr, (double)(0), &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state);
57136 :
57137 : /*
57138 : * Scale if necessary
57139 : */
57140 0 : if( ae_fp_neq(scl,(double)(1)) )
57141 : {
57142 0 : ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), scl);
57143 : }
57144 0 : work.ptr.p_double[j+n] = x.ptr.pp_double[1][1];
57145 0 : vmax = ae_maxreal(ae_fabs(work.ptr.p_double[j+n], _state), vmax, _state);
57146 0 : vcrit = bignum/vmax;
57147 : }
57148 : else
57149 : {
57150 :
57151 : /*
57152 : * 2-by-2 diagonal block
57153 : *
57154 : * Scale if necessary to avoid overflow when forming
57155 : * the right-hand side.
57156 : */
57157 0 : beta = ae_maxreal(work.ptr.p_double[j], work.ptr.p_double[j+1], _state);
57158 0 : if( ae_fp_greater(beta,vcrit) )
57159 : {
57160 0 : rec = 1/vmax;
57161 0 : ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), rec);
57162 0 : vmax = (double)(1);
57163 0 : vcrit = bignum;
57164 : }
57165 0 : vt = ae_v_dotproduct(&t->ptr.pp_double[ki+1][j], t->stride, &work.ptr.p_double[ki+1+n], 1, ae_v_len(ki+1,j-1));
57166 0 : work.ptr.p_double[j+n] = work.ptr.p_double[j+n]-vt;
57167 0 : vt = ae_v_dotproduct(&t->ptr.pp_double[ki+1][j+1], t->stride, &work.ptr.p_double[ki+1+n], 1, ae_v_len(ki+1,j-1));
57168 0 : work.ptr.p_double[j+1+n] = work.ptr.p_double[j+1+n]-vt;
57169 :
57170 : /*
57171 : * Solve
57172 : * [T(J,J)-WR T(J,J+1) ]'* X = SCALE*( WORK1 )
57173 : * [T(J+1,J) T(J+1,J+1)-WR] ( WORK2 )
57174 : */
57175 0 : temp22.ptr.pp_double[1][1] = t->ptr.pp_double[j][j];
57176 0 : temp22.ptr.pp_double[1][2] = t->ptr.pp_double[j][j+1];
57177 0 : temp22.ptr.pp_double[2][1] = t->ptr.pp_double[j+1][j];
57178 0 : temp22.ptr.pp_double[2][2] = t->ptr.pp_double[j+1][j+1];
57179 0 : temp21b.ptr.pp_double[1][1] = work.ptr.p_double[j+n];
57180 0 : temp21b.ptr.pp_double[2][1] = work.ptr.p_double[j+1+n];
57181 0 : evd_internalhsevdlaln2(ae_true, 2, 1, smin, 1.0, &temp22, 1.0, 1.0, &temp21b, wr, (double)(0), &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state);
57182 :
57183 : /*
57184 : * Scale if necessary
57185 : */
57186 0 : if( ae_fp_neq(scl,(double)(1)) )
57187 : {
57188 0 : ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), scl);
57189 : }
57190 0 : work.ptr.p_double[j+n] = x.ptr.pp_double[1][1];
57191 0 : work.ptr.p_double[j+1+n] = x.ptr.pp_double[2][1];
57192 0 : vmax = ae_maxreal(ae_fabs(work.ptr.p_double[j+n], _state), ae_maxreal(ae_fabs(work.ptr.p_double[j+1+n], _state), vmax, _state), _state);
57193 0 : vcrit = bignum/vmax;
57194 : }
57195 : }
57196 :
57197 : /*
57198 : * Copy the vector x or Q*x to VL and normalize.
57199 : */
57200 0 : if( !over )
57201 : {
57202 0 : ae_v_move(&vl->ptr.pp_double[ki][iis], vl->stride, &work.ptr.p_double[ki+n], 1, ae_v_len(ki,n));
57203 0 : ii = columnidxabsmax(vl, ki, n, iis, _state);
57204 0 : remax = 1/ae_fabs(vl->ptr.pp_double[ii][iis], _state);
57205 0 : ae_v_muld(&vl->ptr.pp_double[ki][iis], vl->stride, ae_v_len(ki,n), remax);
57206 0 : for(k=1; k<=ki-1; k++)
57207 : {
57208 0 : vl->ptr.pp_double[k][iis] = (double)(0);
57209 : }
57210 : }
57211 : else
57212 : {
57213 0 : if( ki<n )
57214 : {
57215 0 : ae_v_move(&temp.ptr.p_double[1], 1, &vl->ptr.pp_double[1][ki], vl->stride, ae_v_len(1,n));
57216 0 : matrixvectormultiply(vl, 1, n, ki+1, n, ae_false, &work, ki+1+n, n+n, 1.0, &temp, 1, n, work.ptr.p_double[ki+n], _state);
57217 0 : ae_v_move(&vl->ptr.pp_double[1][ki], vl->stride, &temp.ptr.p_double[1], 1, ae_v_len(1,n));
57218 : }
57219 0 : ii = columnidxabsmax(vl, 1, n, ki, _state);
57220 0 : remax = 1/ae_fabs(vl->ptr.pp_double[ii][ki], _state);
57221 0 : ae_v_muld(&vl->ptr.pp_double[1][ki], vl->stride, ae_v_len(1,n), remax);
57222 : }
57223 : }
57224 : else
57225 : {
57226 :
57227 : /*
57228 : * Complex left eigenvector.
57229 : *
57230 : * Initial solve:
57231 : * ((T(KI,KI) T(KI,KI+1) )' - (WR - I* WI))*X = 0.
57232 : * ((T(KI+1,KI) T(KI+1,KI+1)) )
57233 : */
57234 0 : if( ae_fp_greater_eq(ae_fabs(t->ptr.pp_double[ki][ki+1], _state),ae_fabs(t->ptr.pp_double[ki+1][ki], _state)) )
57235 : {
57236 0 : work.ptr.p_double[ki+n] = wi/t->ptr.pp_double[ki][ki+1];
57237 0 : work.ptr.p_double[ki+1+n2] = (double)(1);
57238 : }
57239 : else
57240 : {
57241 0 : work.ptr.p_double[ki+n] = (double)(1);
57242 0 : work.ptr.p_double[ki+1+n2] = -wi/t->ptr.pp_double[ki+1][ki];
57243 : }
57244 0 : work.ptr.p_double[ki+1+n] = (double)(0);
57245 0 : work.ptr.p_double[ki+n2] = (double)(0);
57246 :
57247 : /*
57248 : * Form right-hand side
57249 : */
57250 0 : for(k=ki+2; k<=n; k++)
57251 : {
57252 0 : work.ptr.p_double[k+n] = -work.ptr.p_double[ki+n]*t->ptr.pp_double[ki][k];
57253 0 : work.ptr.p_double[k+n2] = -work.ptr.p_double[ki+1+n2]*t->ptr.pp_double[ki+1][k];
57254 : }
57255 :
57256 : /*
57257 : * Solve complex quasi-triangular system:
57258 : * ( T(KI+2,N:KI+2,N) - (WR-i*WI) )*X = WORK1+i*WORK2
57259 : */
57260 0 : vmax = (double)(1);
57261 0 : vcrit = bignum;
57262 0 : jnxt = ki+2;
57263 0 : for(j=ki+2; j<=n; j++)
57264 : {
57265 0 : if( j<jnxt )
57266 : {
57267 0 : continue;
57268 : }
57269 0 : j1 = j;
57270 0 : j2 = j;
57271 0 : jnxt = j+1;
57272 0 : if( j<n )
57273 : {
57274 0 : if( ae_fp_neq(t->ptr.pp_double[j+1][j],(double)(0)) )
57275 : {
57276 0 : j2 = j+1;
57277 0 : jnxt = j+2;
57278 : }
57279 : }
57280 0 : if( j1==j2 )
57281 : {
57282 :
57283 : /*
57284 : * 1-by-1 diagonal block
57285 : *
57286 : * Scale if necessary to avoid overflow when
57287 : * forming the right-hand side elements.
57288 : */
57289 0 : if( ae_fp_greater(work.ptr.p_double[j],vcrit) )
57290 : {
57291 0 : rec = 1/vmax;
57292 0 : ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), rec);
57293 0 : ae_v_muld(&work.ptr.p_double[ki+n2], 1, ae_v_len(ki+n2,n+n2), rec);
57294 0 : vmax = (double)(1);
57295 0 : vcrit = bignum;
57296 : }
57297 0 : vt = ae_v_dotproduct(&t->ptr.pp_double[ki+2][j], t->stride, &work.ptr.p_double[ki+2+n], 1, ae_v_len(ki+2,j-1));
57298 0 : work.ptr.p_double[j+n] = work.ptr.p_double[j+n]-vt;
57299 0 : vt = ae_v_dotproduct(&t->ptr.pp_double[ki+2][j], t->stride, &work.ptr.p_double[ki+2+n2], 1, ae_v_len(ki+2,j-1));
57300 0 : work.ptr.p_double[j+n2] = work.ptr.p_double[j+n2]-vt;
57301 :
57302 : /*
57303 : * Solve (T(J,J)-(WR-i*WI))*(X11+i*X12)= WK+I*WK2
57304 : */
57305 0 : temp11.ptr.pp_double[1][1] = t->ptr.pp_double[j][j];
57306 0 : temp12b.ptr.pp_double[1][1] = work.ptr.p_double[j+n];
57307 0 : temp12b.ptr.pp_double[1][2] = work.ptr.p_double[j+n+n];
57308 0 : evd_internalhsevdlaln2(ae_false, 1, 2, smin, 1.0, &temp11, 1.0, 1.0, &temp12b, wr, -wi, &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state);
57309 :
57310 : /*
57311 : * Scale if necessary
57312 : */
57313 0 : if( ae_fp_neq(scl,(double)(1)) )
57314 : {
57315 0 : ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), scl);
57316 0 : ae_v_muld(&work.ptr.p_double[ki+n2], 1, ae_v_len(ki+n2,n+n2), scl);
57317 : }
57318 0 : work.ptr.p_double[j+n] = x.ptr.pp_double[1][1];
57319 0 : work.ptr.p_double[j+n2] = x.ptr.pp_double[1][2];
57320 0 : vmax = ae_maxreal(ae_fabs(work.ptr.p_double[j+n], _state), ae_maxreal(ae_fabs(work.ptr.p_double[j+n2], _state), vmax, _state), _state);
57321 0 : vcrit = bignum/vmax;
57322 : }
57323 : else
57324 : {
57325 :
57326 : /*
57327 : * 2-by-2 diagonal block
57328 : *
57329 : * Scale if necessary to avoid overflow when forming
57330 : * the right-hand side elements.
57331 : */
57332 0 : beta = ae_maxreal(work.ptr.p_double[j], work.ptr.p_double[j+1], _state);
57333 0 : if( ae_fp_greater(beta,vcrit) )
57334 : {
57335 0 : rec = 1/vmax;
57336 0 : ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), rec);
57337 0 : ae_v_muld(&work.ptr.p_double[ki+n2], 1, ae_v_len(ki+n2,n+n2), rec);
57338 0 : vmax = (double)(1);
57339 0 : vcrit = bignum;
57340 : }
57341 0 : vt = ae_v_dotproduct(&t->ptr.pp_double[ki+2][j], t->stride, &work.ptr.p_double[ki+2+n], 1, ae_v_len(ki+2,j-1));
57342 0 : work.ptr.p_double[j+n] = work.ptr.p_double[j+n]-vt;
57343 0 : vt = ae_v_dotproduct(&t->ptr.pp_double[ki+2][j], t->stride, &work.ptr.p_double[ki+2+n2], 1, ae_v_len(ki+2,j-1));
57344 0 : work.ptr.p_double[j+n2] = work.ptr.p_double[j+n2]-vt;
57345 0 : vt = ae_v_dotproduct(&t->ptr.pp_double[ki+2][j+1], t->stride, &work.ptr.p_double[ki+2+n], 1, ae_v_len(ki+2,j-1));
57346 0 : work.ptr.p_double[j+1+n] = work.ptr.p_double[j+1+n]-vt;
57347 0 : vt = ae_v_dotproduct(&t->ptr.pp_double[ki+2][j+1], t->stride, &work.ptr.p_double[ki+2+n2], 1, ae_v_len(ki+2,j-1));
57348 0 : work.ptr.p_double[j+1+n2] = work.ptr.p_double[j+1+n2]-vt;
57349 :
57350 : /*
57351 : * Solve 2-by-2 complex linear equation
57352 : * ([T(j,j) T(j,j+1) ]'-(wr-i*wi)*I)*X = SCALE*B
57353 : * ([T(j+1,j) T(j+1,j+1)] )
57354 : */
57355 0 : temp22.ptr.pp_double[1][1] = t->ptr.pp_double[j][j];
57356 0 : temp22.ptr.pp_double[1][2] = t->ptr.pp_double[j][j+1];
57357 0 : temp22.ptr.pp_double[2][1] = t->ptr.pp_double[j+1][j];
57358 0 : temp22.ptr.pp_double[2][2] = t->ptr.pp_double[j+1][j+1];
57359 0 : temp22b.ptr.pp_double[1][1] = work.ptr.p_double[j+n];
57360 0 : temp22b.ptr.pp_double[1][2] = work.ptr.p_double[j+n+n];
57361 0 : temp22b.ptr.pp_double[2][1] = work.ptr.p_double[j+1+n];
57362 0 : temp22b.ptr.pp_double[2][2] = work.ptr.p_double[j+1+n+n];
57363 0 : evd_internalhsevdlaln2(ae_true, 2, 2, smin, 1.0, &temp22, 1.0, 1.0, &temp22b, wr, -wi, &rswap4, &zswap4, &ipivot44, &civ4, &crv4, &x, &scl, &xnorm, &ierr, _state);
57364 :
57365 : /*
57366 : * Scale if necessary
57367 : */
57368 0 : if( ae_fp_neq(scl,(double)(1)) )
57369 : {
57370 0 : ae_v_muld(&work.ptr.p_double[ki+n], 1, ae_v_len(ki+n,n+n), scl);
57371 0 : ae_v_muld(&work.ptr.p_double[ki+n2], 1, ae_v_len(ki+n2,n+n2), scl);
57372 : }
57373 0 : work.ptr.p_double[j+n] = x.ptr.pp_double[1][1];
57374 0 : work.ptr.p_double[j+n2] = x.ptr.pp_double[1][2];
57375 0 : work.ptr.p_double[j+1+n] = x.ptr.pp_double[2][1];
57376 0 : work.ptr.p_double[j+1+n2] = x.ptr.pp_double[2][2];
57377 0 : vmax = ae_maxreal(ae_fabs(x.ptr.pp_double[1][1], _state), vmax, _state);
57378 0 : vmax = ae_maxreal(ae_fabs(x.ptr.pp_double[1][2], _state), vmax, _state);
57379 0 : vmax = ae_maxreal(ae_fabs(x.ptr.pp_double[2][1], _state), vmax, _state);
57380 0 : vmax = ae_maxreal(ae_fabs(x.ptr.pp_double[2][2], _state), vmax, _state);
57381 0 : vcrit = bignum/vmax;
57382 : }
57383 : }
57384 :
57385 : /*
57386 : * Copy the vector x or Q*x to VL and normalize.
57387 : */
57388 0 : if( !over )
57389 : {
57390 0 : ae_v_move(&vl->ptr.pp_double[ki][iis], vl->stride, &work.ptr.p_double[ki+n], 1, ae_v_len(ki,n));
57391 0 : ae_v_move(&vl->ptr.pp_double[ki][iis+1], vl->stride, &work.ptr.p_double[ki+n2], 1, ae_v_len(ki,n));
57392 0 : emax = (double)(0);
57393 0 : for(k=ki; k<=n; k++)
57394 : {
57395 0 : emax = ae_maxreal(emax, ae_fabs(vl->ptr.pp_double[k][iis], _state)+ae_fabs(vl->ptr.pp_double[k][iis+1], _state), _state);
57396 : }
57397 0 : remax = 1/emax;
57398 0 : ae_v_muld(&vl->ptr.pp_double[ki][iis], vl->stride, ae_v_len(ki,n), remax);
57399 0 : ae_v_muld(&vl->ptr.pp_double[ki][iis+1], vl->stride, ae_v_len(ki,n), remax);
57400 0 : for(k=1; k<=ki-1; k++)
57401 : {
57402 0 : vl->ptr.pp_double[k][iis] = (double)(0);
57403 0 : vl->ptr.pp_double[k][iis+1] = (double)(0);
57404 : }
57405 : }
57406 : else
57407 : {
57408 0 : if( ki<n-1 )
57409 : {
57410 0 : ae_v_move(&temp.ptr.p_double[1], 1, &vl->ptr.pp_double[1][ki], vl->stride, ae_v_len(1,n));
57411 0 : matrixvectormultiply(vl, 1, n, ki+2, n, ae_false, &work, ki+2+n, n+n, 1.0, &temp, 1, n, work.ptr.p_double[ki+n], _state);
57412 0 : ae_v_move(&vl->ptr.pp_double[1][ki], vl->stride, &temp.ptr.p_double[1], 1, ae_v_len(1,n));
57413 0 : ae_v_move(&temp.ptr.p_double[1], 1, &vl->ptr.pp_double[1][ki+1], vl->stride, ae_v_len(1,n));
57414 0 : matrixvectormultiply(vl, 1, n, ki+2, n, ae_false, &work, ki+2+n2, n+n2, 1.0, &temp, 1, n, work.ptr.p_double[ki+1+n2], _state);
57415 0 : ae_v_move(&vl->ptr.pp_double[1][ki+1], vl->stride, &temp.ptr.p_double[1], 1, ae_v_len(1,n));
57416 : }
57417 : else
57418 : {
57419 0 : vt = work.ptr.p_double[ki+n];
57420 0 : ae_v_muld(&vl->ptr.pp_double[1][ki], vl->stride, ae_v_len(1,n), vt);
57421 0 : vt = work.ptr.p_double[ki+1+n2];
57422 0 : ae_v_muld(&vl->ptr.pp_double[1][ki+1], vl->stride, ae_v_len(1,n), vt);
57423 : }
57424 0 : emax = (double)(0);
57425 0 : for(k=1; k<=n; k++)
57426 : {
57427 0 : emax = ae_maxreal(emax, ae_fabs(vl->ptr.pp_double[k][ki], _state)+ae_fabs(vl->ptr.pp_double[k][ki+1], _state), _state);
57428 : }
57429 0 : remax = 1/emax;
57430 0 : ae_v_muld(&vl->ptr.pp_double[1][ki], vl->stride, ae_v_len(1,n), remax);
57431 0 : ae_v_muld(&vl->ptr.pp_double[1][ki+1], vl->stride, ae_v_len(1,n), remax);
57432 : }
57433 : }
57434 0 : iis = iis+1;
57435 0 : if( ip!=0 )
57436 : {
57437 0 : iis = iis+1;
57438 : }
57439 : }
57440 0 : if( ip==-1 )
57441 : {
57442 0 : ip = 0;
57443 : }
57444 0 : if( ip==1 )
57445 : {
57446 0 : ip = -1;
57447 : }
57448 : }
57449 : }
57450 0 : ae_frame_leave(_state);
57451 : }
57452 :
57453 :
57454 : /*************************************************************************
57455 : DLALN2 solves a system of the form (ca A - w D ) X = s B
57456 : or (ca A' - w D) X = s B with possible scaling ("s") and
57457 : perturbation of A. (A' means A-transpose.)
57458 :
57459 : A is an NA x NA real matrix, ca is a real scalar, D is an NA x NA
57460 : real diagonal matrix, w is a real or complex value, and X and B are
57461 : NA x 1 matrices -- real if w is real, complex if w is complex. NA
57462 : may be 1 or 2.
57463 :
57464 : If w is complex, X and B are represented as NA x 2 matrices,
57465 : the first column of each being the real part and the second
57466 : being the imaginary part.
57467 :
57468 : "s" is a scaling factor (.LE. 1), computed by DLALN2, which is
57469 : so chosen that X can be computed without overflow. X is further
57470 : scaled if necessary to assure that norm(ca A - w D)*norm(X) is less
57471 : than overflow.
57472 :
57473 : If both singular values of (ca A - w D) are less than SMIN,
57474 : SMIN*identity will be used instead of (ca A - w D). If only one
57475 : singular value is less than SMIN, one element of (ca A - w D) will be
57476 : perturbed enough to make the smallest singular value roughly SMIN.
57477 : If both singular values are at least SMIN, (ca A - w D) will not be
57478 : perturbed. In any case, the perturbation will be at most some small
57479 : multiple of max( SMIN, ulp*norm(ca A - w D) ). The singular values
57480 : are computed by infinity-norm approximations, and thus will only be
57481 : correct to a factor of 2 or so.
57482 :
57483 : Note: all input quantities are assumed to be smaller than overflow
57484 : by a reasonable factor. (See BIGNUM.)
57485 :
57486 : -- LAPACK auxiliary routine (version 3.0) --
57487 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
57488 : Courant Institute, Argonne National Lab, and Rice University
57489 : October 31, 1992
57490 : *************************************************************************/
57491 0 : static void evd_internalhsevdlaln2(ae_bool ltrans,
57492 : ae_int_t na,
57493 : ae_int_t nw,
57494 : double smin,
57495 : double ca,
57496 : /* Real */ ae_matrix* a,
57497 : double d1,
57498 : double d2,
57499 : /* Real */ ae_matrix* b,
57500 : double wr,
57501 : double wi,
57502 : /* Boolean */ ae_vector* rswap4,
57503 : /* Boolean */ ae_vector* zswap4,
57504 : /* Integer */ ae_matrix* ipivot44,
57505 : /* Real */ ae_vector* civ4,
57506 : /* Real */ ae_vector* crv4,
57507 : /* Real */ ae_matrix* x,
57508 : double* scl,
57509 : double* xnorm,
57510 : ae_int_t* info,
57511 : ae_state *_state)
57512 : {
57513 : ae_int_t icmax;
57514 : ae_int_t j;
57515 : double bbnd;
57516 : double bi1;
57517 : double bi2;
57518 : double bignum;
57519 : double bnorm;
57520 : double br1;
57521 : double br2;
57522 : double ci21;
57523 : double ci22;
57524 : double cmax;
57525 : double cnorm;
57526 : double cr21;
57527 : double cr22;
57528 : double csi;
57529 : double csr;
57530 : double li21;
57531 : double lr21;
57532 : double smini;
57533 : double smlnum;
57534 : double temp;
57535 : double u22abs;
57536 : double ui11;
57537 : double ui11r;
57538 : double ui12;
57539 : double ui12s;
57540 : double ui22;
57541 : double ur11;
57542 : double ur11r;
57543 : double ur12;
57544 : double ur12s;
57545 : double ur22;
57546 : double xi1;
57547 : double xi2;
57548 : double xr1;
57549 : double xr2;
57550 : double tmp1;
57551 : double tmp2;
57552 :
57553 0 : *scl = 0;
57554 0 : *xnorm = 0;
57555 0 : *info = 0;
57556 :
57557 0 : zswap4->ptr.p_bool[1] = ae_false;
57558 0 : zswap4->ptr.p_bool[2] = ae_false;
57559 0 : zswap4->ptr.p_bool[3] = ae_true;
57560 0 : zswap4->ptr.p_bool[4] = ae_true;
57561 0 : rswap4->ptr.p_bool[1] = ae_false;
57562 0 : rswap4->ptr.p_bool[2] = ae_true;
57563 0 : rswap4->ptr.p_bool[3] = ae_false;
57564 0 : rswap4->ptr.p_bool[4] = ae_true;
57565 0 : ipivot44->ptr.pp_int[1][1] = 1;
57566 0 : ipivot44->ptr.pp_int[2][1] = 2;
57567 0 : ipivot44->ptr.pp_int[3][1] = 3;
57568 0 : ipivot44->ptr.pp_int[4][1] = 4;
57569 0 : ipivot44->ptr.pp_int[1][2] = 2;
57570 0 : ipivot44->ptr.pp_int[2][2] = 1;
57571 0 : ipivot44->ptr.pp_int[3][2] = 4;
57572 0 : ipivot44->ptr.pp_int[4][2] = 3;
57573 0 : ipivot44->ptr.pp_int[1][3] = 3;
57574 0 : ipivot44->ptr.pp_int[2][3] = 4;
57575 0 : ipivot44->ptr.pp_int[3][3] = 1;
57576 0 : ipivot44->ptr.pp_int[4][3] = 2;
57577 0 : ipivot44->ptr.pp_int[1][4] = 4;
57578 0 : ipivot44->ptr.pp_int[2][4] = 3;
57579 0 : ipivot44->ptr.pp_int[3][4] = 2;
57580 0 : ipivot44->ptr.pp_int[4][4] = 1;
57581 0 : smlnum = 2*ae_minrealnumber;
57582 0 : bignum = 1/smlnum;
57583 0 : smini = ae_maxreal(smin, smlnum, _state);
57584 :
57585 : /*
57586 : * Don't check for input errors
57587 : */
57588 0 : *info = 0;
57589 :
57590 : /*
57591 : * Standard Initializations
57592 : */
57593 0 : *scl = (double)(1);
57594 0 : if( na==1 )
57595 : {
57596 :
57597 : /*
57598 : * 1 x 1 (i.e., scalar) system C X = B
57599 : */
57600 0 : if( nw==1 )
57601 : {
57602 :
57603 : /*
57604 : * Real 1x1 system.
57605 : *
57606 : * C = ca A - w D
57607 : */
57608 0 : csr = ca*a->ptr.pp_double[1][1]-wr*d1;
57609 0 : cnorm = ae_fabs(csr, _state);
57610 :
57611 : /*
57612 : * If | C | < SMINI, use C = SMINI
57613 : */
57614 0 : if( ae_fp_less(cnorm,smini) )
57615 : {
57616 0 : csr = smini;
57617 0 : cnorm = smini;
57618 0 : *info = 1;
57619 : }
57620 :
57621 : /*
57622 : * Check scaling for X = B / C
57623 : */
57624 0 : bnorm = ae_fabs(b->ptr.pp_double[1][1], _state);
57625 0 : if( ae_fp_less(cnorm,(double)(1))&&ae_fp_greater(bnorm,(double)(1)) )
57626 : {
57627 0 : if( ae_fp_greater(bnorm,bignum*cnorm) )
57628 : {
57629 0 : *scl = 1/bnorm;
57630 : }
57631 : }
57632 :
57633 : /*
57634 : * Compute X
57635 : */
57636 0 : x->ptr.pp_double[1][1] = b->ptr.pp_double[1][1]*(*scl)/csr;
57637 0 : *xnorm = ae_fabs(x->ptr.pp_double[1][1], _state);
57638 : }
57639 : else
57640 : {
57641 :
57642 : /*
57643 : * Complex 1x1 system (w is complex)
57644 : *
57645 : * C = ca A - w D
57646 : */
57647 0 : csr = ca*a->ptr.pp_double[1][1]-wr*d1;
57648 0 : csi = -wi*d1;
57649 0 : cnorm = ae_fabs(csr, _state)+ae_fabs(csi, _state);
57650 :
57651 : /*
57652 : * If | C | < SMINI, use C = SMINI
57653 : */
57654 0 : if( ae_fp_less(cnorm,smini) )
57655 : {
57656 0 : csr = smini;
57657 0 : csi = (double)(0);
57658 0 : cnorm = smini;
57659 0 : *info = 1;
57660 : }
57661 :
57662 : /*
57663 : * Check scaling for X = B / C
57664 : */
57665 0 : bnorm = ae_fabs(b->ptr.pp_double[1][1], _state)+ae_fabs(b->ptr.pp_double[1][2], _state);
57666 0 : if( ae_fp_less(cnorm,(double)(1))&&ae_fp_greater(bnorm,(double)(1)) )
57667 : {
57668 0 : if( ae_fp_greater(bnorm,bignum*cnorm) )
57669 : {
57670 0 : *scl = 1/bnorm;
57671 : }
57672 : }
57673 :
57674 : /*
57675 : * Compute X
57676 : */
57677 0 : evd_internalhsevdladiv(*scl*b->ptr.pp_double[1][1], *scl*b->ptr.pp_double[1][2], csr, csi, &tmp1, &tmp2, _state);
57678 0 : x->ptr.pp_double[1][1] = tmp1;
57679 0 : x->ptr.pp_double[1][2] = tmp2;
57680 0 : *xnorm = ae_fabs(x->ptr.pp_double[1][1], _state)+ae_fabs(x->ptr.pp_double[1][2], _state);
57681 : }
57682 : }
57683 : else
57684 : {
57685 :
57686 : /*
57687 : * 2x2 System
57688 : *
57689 : * Compute the real part of C = ca A - w D (or ca A' - w D )
57690 : */
57691 0 : crv4->ptr.p_double[1+0] = ca*a->ptr.pp_double[1][1]-wr*d1;
57692 0 : crv4->ptr.p_double[2+2] = ca*a->ptr.pp_double[2][2]-wr*d2;
57693 0 : if( ltrans )
57694 : {
57695 0 : crv4->ptr.p_double[1+2] = ca*a->ptr.pp_double[2][1];
57696 0 : crv4->ptr.p_double[2+0] = ca*a->ptr.pp_double[1][2];
57697 : }
57698 : else
57699 : {
57700 0 : crv4->ptr.p_double[2+0] = ca*a->ptr.pp_double[2][1];
57701 0 : crv4->ptr.p_double[1+2] = ca*a->ptr.pp_double[1][2];
57702 : }
57703 0 : if( nw==1 )
57704 : {
57705 :
57706 : /*
57707 : * Real 2x2 system (w is real)
57708 : *
57709 : * Find the largest element in C
57710 : */
57711 0 : cmax = (double)(0);
57712 0 : icmax = 0;
57713 0 : for(j=1; j<=4; j++)
57714 : {
57715 0 : if( ae_fp_greater(ae_fabs(crv4->ptr.p_double[j], _state),cmax) )
57716 : {
57717 0 : cmax = ae_fabs(crv4->ptr.p_double[j], _state);
57718 0 : icmax = j;
57719 : }
57720 : }
57721 :
57722 : /*
57723 : * If norm(C) < SMINI, use SMINI*identity.
57724 : */
57725 0 : if( ae_fp_less(cmax,smini) )
57726 : {
57727 0 : bnorm = ae_maxreal(ae_fabs(b->ptr.pp_double[1][1], _state), ae_fabs(b->ptr.pp_double[2][1], _state), _state);
57728 0 : if( ae_fp_less(smini,(double)(1))&&ae_fp_greater(bnorm,(double)(1)) )
57729 : {
57730 0 : if( ae_fp_greater(bnorm,bignum*smini) )
57731 : {
57732 0 : *scl = 1/bnorm;
57733 : }
57734 : }
57735 0 : temp = *scl/smini;
57736 0 : x->ptr.pp_double[1][1] = temp*b->ptr.pp_double[1][1];
57737 0 : x->ptr.pp_double[2][1] = temp*b->ptr.pp_double[2][1];
57738 0 : *xnorm = temp*bnorm;
57739 0 : *info = 1;
57740 0 : return;
57741 : }
57742 :
57743 : /*
57744 : * Gaussian elimination with complete pivoting.
57745 : */
57746 0 : ur11 = crv4->ptr.p_double[icmax];
57747 0 : cr21 = crv4->ptr.p_double[ipivot44->ptr.pp_int[2][icmax]];
57748 0 : ur12 = crv4->ptr.p_double[ipivot44->ptr.pp_int[3][icmax]];
57749 0 : cr22 = crv4->ptr.p_double[ipivot44->ptr.pp_int[4][icmax]];
57750 0 : ur11r = 1/ur11;
57751 0 : lr21 = ur11r*cr21;
57752 0 : ur22 = cr22-ur12*lr21;
57753 :
57754 : /*
57755 : * If smaller pivot < SMINI, use SMINI
57756 : */
57757 0 : if( ae_fp_less(ae_fabs(ur22, _state),smini) )
57758 : {
57759 0 : ur22 = smini;
57760 0 : *info = 1;
57761 : }
57762 0 : if( rswap4->ptr.p_bool[icmax] )
57763 : {
57764 0 : br1 = b->ptr.pp_double[2][1];
57765 0 : br2 = b->ptr.pp_double[1][1];
57766 : }
57767 : else
57768 : {
57769 0 : br1 = b->ptr.pp_double[1][1];
57770 0 : br2 = b->ptr.pp_double[2][1];
57771 : }
57772 0 : br2 = br2-lr21*br1;
57773 0 : bbnd = ae_maxreal(ae_fabs(br1*(ur22*ur11r), _state), ae_fabs(br2, _state), _state);
57774 0 : if( ae_fp_greater(bbnd,(double)(1))&&ae_fp_less(ae_fabs(ur22, _state),(double)(1)) )
57775 : {
57776 0 : if( ae_fp_greater_eq(bbnd,bignum*ae_fabs(ur22, _state)) )
57777 : {
57778 0 : *scl = 1/bbnd;
57779 : }
57780 : }
57781 0 : xr2 = br2*(*scl)/ur22;
57782 0 : xr1 = *scl*br1*ur11r-xr2*(ur11r*ur12);
57783 0 : if( zswap4->ptr.p_bool[icmax] )
57784 : {
57785 0 : x->ptr.pp_double[1][1] = xr2;
57786 0 : x->ptr.pp_double[2][1] = xr1;
57787 : }
57788 : else
57789 : {
57790 0 : x->ptr.pp_double[1][1] = xr1;
57791 0 : x->ptr.pp_double[2][1] = xr2;
57792 : }
57793 0 : *xnorm = ae_maxreal(ae_fabs(xr1, _state), ae_fabs(xr2, _state), _state);
57794 :
57795 : /*
57796 : * Further scaling if norm(A) norm(X) > overflow
57797 : */
57798 0 : if( ae_fp_greater(*xnorm,(double)(1))&&ae_fp_greater(cmax,(double)(1)) )
57799 : {
57800 0 : if( ae_fp_greater(*xnorm,bignum/cmax) )
57801 : {
57802 0 : temp = cmax/bignum;
57803 0 : x->ptr.pp_double[1][1] = temp*x->ptr.pp_double[1][1];
57804 0 : x->ptr.pp_double[2][1] = temp*x->ptr.pp_double[2][1];
57805 0 : *xnorm = temp*(*xnorm);
57806 0 : *scl = temp*(*scl);
57807 : }
57808 : }
57809 : }
57810 : else
57811 : {
57812 :
57813 : /*
57814 : * Complex 2x2 system (w is complex)
57815 : *
57816 : * Find the largest element in C
57817 : */
57818 0 : civ4->ptr.p_double[1+0] = -wi*d1;
57819 0 : civ4->ptr.p_double[2+0] = (double)(0);
57820 0 : civ4->ptr.p_double[1+2] = (double)(0);
57821 0 : civ4->ptr.p_double[2+2] = -wi*d2;
57822 0 : cmax = (double)(0);
57823 0 : icmax = 0;
57824 0 : for(j=1; j<=4; j++)
57825 : {
57826 0 : if( ae_fp_greater(ae_fabs(crv4->ptr.p_double[j], _state)+ae_fabs(civ4->ptr.p_double[j], _state),cmax) )
57827 : {
57828 0 : cmax = ae_fabs(crv4->ptr.p_double[j], _state)+ae_fabs(civ4->ptr.p_double[j], _state);
57829 0 : icmax = j;
57830 : }
57831 : }
57832 :
57833 : /*
57834 : * If norm(C) < SMINI, use SMINI*identity.
57835 : */
57836 0 : if( ae_fp_less(cmax,smini) )
57837 : {
57838 0 : bnorm = ae_maxreal(ae_fabs(b->ptr.pp_double[1][1], _state)+ae_fabs(b->ptr.pp_double[1][2], _state), ae_fabs(b->ptr.pp_double[2][1], _state)+ae_fabs(b->ptr.pp_double[2][2], _state), _state);
57839 0 : if( ae_fp_less(smini,(double)(1))&&ae_fp_greater(bnorm,(double)(1)) )
57840 : {
57841 0 : if( ae_fp_greater(bnorm,bignum*smini) )
57842 : {
57843 0 : *scl = 1/bnorm;
57844 : }
57845 : }
57846 0 : temp = *scl/smini;
57847 0 : x->ptr.pp_double[1][1] = temp*b->ptr.pp_double[1][1];
57848 0 : x->ptr.pp_double[2][1] = temp*b->ptr.pp_double[2][1];
57849 0 : x->ptr.pp_double[1][2] = temp*b->ptr.pp_double[1][2];
57850 0 : x->ptr.pp_double[2][2] = temp*b->ptr.pp_double[2][2];
57851 0 : *xnorm = temp*bnorm;
57852 0 : *info = 1;
57853 0 : return;
57854 : }
57855 :
57856 : /*
57857 : * Gaussian elimination with complete pivoting.
57858 : */
57859 0 : ur11 = crv4->ptr.p_double[icmax];
57860 0 : ui11 = civ4->ptr.p_double[icmax];
57861 0 : cr21 = crv4->ptr.p_double[ipivot44->ptr.pp_int[2][icmax]];
57862 0 : ci21 = civ4->ptr.p_double[ipivot44->ptr.pp_int[2][icmax]];
57863 0 : ur12 = crv4->ptr.p_double[ipivot44->ptr.pp_int[3][icmax]];
57864 0 : ui12 = civ4->ptr.p_double[ipivot44->ptr.pp_int[3][icmax]];
57865 0 : cr22 = crv4->ptr.p_double[ipivot44->ptr.pp_int[4][icmax]];
57866 0 : ci22 = civ4->ptr.p_double[ipivot44->ptr.pp_int[4][icmax]];
57867 0 : if( icmax==1||icmax==4 )
57868 : {
57869 :
57870 : /*
57871 : * Code when off-diagonals of pivoted C are real
57872 : */
57873 0 : if( ae_fp_greater(ae_fabs(ur11, _state),ae_fabs(ui11, _state)) )
57874 : {
57875 0 : temp = ui11/ur11;
57876 0 : ur11r = 1/(ur11*(1+ae_sqr(temp, _state)));
57877 0 : ui11r = -temp*ur11r;
57878 : }
57879 : else
57880 : {
57881 0 : temp = ur11/ui11;
57882 0 : ui11r = -1/(ui11*(1+ae_sqr(temp, _state)));
57883 0 : ur11r = -temp*ui11r;
57884 : }
57885 0 : lr21 = cr21*ur11r;
57886 0 : li21 = cr21*ui11r;
57887 0 : ur12s = ur12*ur11r;
57888 0 : ui12s = ur12*ui11r;
57889 0 : ur22 = cr22-ur12*lr21;
57890 0 : ui22 = ci22-ur12*li21;
57891 : }
57892 : else
57893 : {
57894 :
57895 : /*
57896 : * Code when diagonals of pivoted C are real
57897 : */
57898 0 : ur11r = 1/ur11;
57899 0 : ui11r = (double)(0);
57900 0 : lr21 = cr21*ur11r;
57901 0 : li21 = ci21*ur11r;
57902 0 : ur12s = ur12*ur11r;
57903 0 : ui12s = ui12*ur11r;
57904 0 : ur22 = cr22-ur12*lr21+ui12*li21;
57905 0 : ui22 = -ur12*li21-ui12*lr21;
57906 : }
57907 0 : u22abs = ae_fabs(ur22, _state)+ae_fabs(ui22, _state);
57908 :
57909 : /*
57910 : * If smaller pivot < SMINI, use SMINI
57911 : */
57912 0 : if( ae_fp_less(u22abs,smini) )
57913 : {
57914 0 : ur22 = smini;
57915 0 : ui22 = (double)(0);
57916 0 : *info = 1;
57917 : }
57918 0 : if( rswap4->ptr.p_bool[icmax] )
57919 : {
57920 0 : br2 = b->ptr.pp_double[1][1];
57921 0 : br1 = b->ptr.pp_double[2][1];
57922 0 : bi2 = b->ptr.pp_double[1][2];
57923 0 : bi1 = b->ptr.pp_double[2][2];
57924 : }
57925 : else
57926 : {
57927 0 : br1 = b->ptr.pp_double[1][1];
57928 0 : br2 = b->ptr.pp_double[2][1];
57929 0 : bi1 = b->ptr.pp_double[1][2];
57930 0 : bi2 = b->ptr.pp_double[2][2];
57931 : }
57932 0 : br2 = br2-lr21*br1+li21*bi1;
57933 0 : bi2 = bi2-li21*br1-lr21*bi1;
57934 0 : bbnd = ae_maxreal((ae_fabs(br1, _state)+ae_fabs(bi1, _state))*(u22abs*(ae_fabs(ur11r, _state)+ae_fabs(ui11r, _state))), ae_fabs(br2, _state)+ae_fabs(bi2, _state), _state);
57935 0 : if( ae_fp_greater(bbnd,(double)(1))&&ae_fp_less(u22abs,(double)(1)) )
57936 : {
57937 0 : if( ae_fp_greater_eq(bbnd,bignum*u22abs) )
57938 : {
57939 0 : *scl = 1/bbnd;
57940 0 : br1 = *scl*br1;
57941 0 : bi1 = *scl*bi1;
57942 0 : br2 = *scl*br2;
57943 0 : bi2 = *scl*bi2;
57944 : }
57945 : }
57946 0 : evd_internalhsevdladiv(br2, bi2, ur22, ui22, &xr2, &xi2, _state);
57947 0 : xr1 = ur11r*br1-ui11r*bi1-ur12s*xr2+ui12s*xi2;
57948 0 : xi1 = ui11r*br1+ur11r*bi1-ui12s*xr2-ur12s*xi2;
57949 0 : if( zswap4->ptr.p_bool[icmax] )
57950 : {
57951 0 : x->ptr.pp_double[1][1] = xr2;
57952 0 : x->ptr.pp_double[2][1] = xr1;
57953 0 : x->ptr.pp_double[1][2] = xi2;
57954 0 : x->ptr.pp_double[2][2] = xi1;
57955 : }
57956 : else
57957 : {
57958 0 : x->ptr.pp_double[1][1] = xr1;
57959 0 : x->ptr.pp_double[2][1] = xr2;
57960 0 : x->ptr.pp_double[1][2] = xi1;
57961 0 : x->ptr.pp_double[2][2] = xi2;
57962 : }
57963 0 : *xnorm = ae_maxreal(ae_fabs(xr1, _state)+ae_fabs(xi1, _state), ae_fabs(xr2, _state)+ae_fabs(xi2, _state), _state);
57964 :
57965 : /*
57966 : * Further scaling if norm(A) norm(X) > overflow
57967 : */
57968 0 : if( ae_fp_greater(*xnorm,(double)(1))&&ae_fp_greater(cmax,(double)(1)) )
57969 : {
57970 0 : if( ae_fp_greater(*xnorm,bignum/cmax) )
57971 : {
57972 0 : temp = cmax/bignum;
57973 0 : x->ptr.pp_double[1][1] = temp*x->ptr.pp_double[1][1];
57974 0 : x->ptr.pp_double[2][1] = temp*x->ptr.pp_double[2][1];
57975 0 : x->ptr.pp_double[1][2] = temp*x->ptr.pp_double[1][2];
57976 0 : x->ptr.pp_double[2][2] = temp*x->ptr.pp_double[2][2];
57977 0 : *xnorm = temp*(*xnorm);
57978 0 : *scl = temp*(*scl);
57979 : }
57980 : }
57981 : }
57982 : }
57983 : }
57984 :
57985 :
57986 : /*************************************************************************
57987 : performs complex division in real arithmetic
57988 :
57989 : a + i*b
57990 : p + i*q = ---------
57991 : c + i*d
57992 :
57993 : The algorithm is due to Robert L. Smith and can be found
57994 : in D. Knuth, The art of Computer Programming, Vol.2, p.195
57995 :
57996 : -- LAPACK auxiliary routine (version 3.0) --
57997 : Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
57998 : Courant Institute, Argonne National Lab, and Rice University
57999 : October 31, 1992
58000 : *************************************************************************/
58001 0 : static void evd_internalhsevdladiv(double a,
58002 : double b,
58003 : double c,
58004 : double d,
58005 : double* p,
58006 : double* q,
58007 : ae_state *_state)
58008 : {
58009 : double e;
58010 : double f;
58011 :
58012 0 : *p = 0;
58013 0 : *q = 0;
58014 :
58015 0 : if( ae_fp_less(ae_fabs(d, _state),ae_fabs(c, _state)) )
58016 : {
58017 0 : e = d/c;
58018 0 : f = c+d*e;
58019 0 : *p = (a+b*e)/f;
58020 0 : *q = (b-a*e)/f;
58021 : }
58022 : else
58023 : {
58024 0 : e = c/d;
58025 0 : f = d+c*e;
58026 0 : *p = (b+a*e)/f;
58027 0 : *q = (-a+b*e)/f;
58028 : }
58029 0 : }
58030 :
58031 :
58032 0 : void _eigsubspacestate_init(void* _p, ae_state *_state, ae_bool make_automatic)
58033 : {
58034 0 : eigsubspacestate *p = (eigsubspacestate*)_p;
58035 0 : ae_touch_ptr((void*)p);
58036 0 : _hqrndstate_init(&p->rs, _state, make_automatic);
58037 0 : ae_vector_init(&p->tau, 0, DT_REAL, _state, make_automatic);
58038 0 : ae_matrix_init(&p->q0, 0, 0, DT_REAL, _state, make_automatic);
58039 0 : ae_matrix_init(&p->qcur, 0, 0, DT_REAL, _state, make_automatic);
58040 0 : ae_matrix_init(&p->qnew, 0, 0, DT_REAL, _state, make_automatic);
58041 0 : ae_matrix_init(&p->znew, 0, 0, DT_REAL, _state, make_automatic);
58042 0 : ae_matrix_init(&p->r, 0, 0, DT_REAL, _state, make_automatic);
58043 0 : ae_matrix_init(&p->rz, 0, 0, DT_REAL, _state, make_automatic);
58044 0 : ae_matrix_init(&p->tz, 0, 0, DT_REAL, _state, make_automatic);
58045 0 : ae_matrix_init(&p->rq, 0, 0, DT_REAL, _state, make_automatic);
58046 0 : ae_matrix_init(&p->dummy, 0, 0, DT_REAL, _state, make_automatic);
58047 0 : ae_vector_init(&p->rw, 0, DT_REAL, _state, make_automatic);
58048 0 : ae_vector_init(&p->tw, 0, DT_REAL, _state, make_automatic);
58049 0 : ae_vector_init(&p->wcur, 0, DT_REAL, _state, make_automatic);
58050 0 : ae_vector_init(&p->wprev, 0, DT_REAL, _state, make_automatic);
58051 0 : ae_vector_init(&p->wrank, 0, DT_REAL, _state, make_automatic);
58052 0 : _apbuffers_init(&p->buf, _state, make_automatic);
58053 0 : ae_matrix_init(&p->x, 0, 0, DT_REAL, _state, make_automatic);
58054 0 : ae_matrix_init(&p->ax, 0, 0, DT_REAL, _state, make_automatic);
58055 0 : _rcommstate_init(&p->rstate, _state, make_automatic);
58056 0 : }
58057 :
58058 :
58059 0 : void _eigsubspacestate_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
58060 : {
58061 0 : eigsubspacestate *dst = (eigsubspacestate*)_dst;
58062 0 : eigsubspacestate *src = (eigsubspacestate*)_src;
58063 0 : dst->n = src->n;
58064 0 : dst->k = src->k;
58065 0 : dst->nwork = src->nwork;
58066 0 : dst->maxits = src->maxits;
58067 0 : dst->eps = src->eps;
58068 0 : dst->eigenvectorsneeded = src->eigenvectorsneeded;
58069 0 : dst->matrixtype = src->matrixtype;
58070 0 : dst->usewarmstart = src->usewarmstart;
58071 0 : dst->firstcall = src->firstcall;
58072 0 : _hqrndstate_init_copy(&dst->rs, &src->rs, _state, make_automatic);
58073 0 : dst->running = src->running;
58074 0 : ae_vector_init_copy(&dst->tau, &src->tau, _state, make_automatic);
58075 0 : ae_matrix_init_copy(&dst->q0, &src->q0, _state, make_automatic);
58076 0 : ae_matrix_init_copy(&dst->qcur, &src->qcur, _state, make_automatic);
58077 0 : ae_matrix_init_copy(&dst->qnew, &src->qnew, _state, make_automatic);
58078 0 : ae_matrix_init_copy(&dst->znew, &src->znew, _state, make_automatic);
58079 0 : ae_matrix_init_copy(&dst->r, &src->r, _state, make_automatic);
58080 0 : ae_matrix_init_copy(&dst->rz, &src->rz, _state, make_automatic);
58081 0 : ae_matrix_init_copy(&dst->tz, &src->tz, _state, make_automatic);
58082 0 : ae_matrix_init_copy(&dst->rq, &src->rq, _state, make_automatic);
58083 0 : ae_matrix_init_copy(&dst->dummy, &src->dummy, _state, make_automatic);
58084 0 : ae_vector_init_copy(&dst->rw, &src->rw, _state, make_automatic);
58085 0 : ae_vector_init_copy(&dst->tw, &src->tw, _state, make_automatic);
58086 0 : ae_vector_init_copy(&dst->wcur, &src->wcur, _state, make_automatic);
58087 0 : ae_vector_init_copy(&dst->wprev, &src->wprev, _state, make_automatic);
58088 0 : ae_vector_init_copy(&dst->wrank, &src->wrank, _state, make_automatic);
58089 0 : _apbuffers_init_copy(&dst->buf, &src->buf, _state, make_automatic);
58090 0 : ae_matrix_init_copy(&dst->x, &src->x, _state, make_automatic);
58091 0 : ae_matrix_init_copy(&dst->ax, &src->ax, _state, make_automatic);
58092 0 : dst->requesttype = src->requesttype;
58093 0 : dst->requestsize = src->requestsize;
58094 0 : dst->repiterationscount = src->repiterationscount;
58095 0 : _rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic);
58096 0 : }
58097 :
58098 :
58099 0 : void _eigsubspacestate_clear(void* _p)
58100 : {
58101 0 : eigsubspacestate *p = (eigsubspacestate*)_p;
58102 0 : ae_touch_ptr((void*)p);
58103 0 : _hqrndstate_clear(&p->rs);
58104 0 : ae_vector_clear(&p->tau);
58105 0 : ae_matrix_clear(&p->q0);
58106 0 : ae_matrix_clear(&p->qcur);
58107 0 : ae_matrix_clear(&p->qnew);
58108 0 : ae_matrix_clear(&p->znew);
58109 0 : ae_matrix_clear(&p->r);
58110 0 : ae_matrix_clear(&p->rz);
58111 0 : ae_matrix_clear(&p->tz);
58112 0 : ae_matrix_clear(&p->rq);
58113 0 : ae_matrix_clear(&p->dummy);
58114 0 : ae_vector_clear(&p->rw);
58115 0 : ae_vector_clear(&p->tw);
58116 0 : ae_vector_clear(&p->wcur);
58117 0 : ae_vector_clear(&p->wprev);
58118 0 : ae_vector_clear(&p->wrank);
58119 0 : _apbuffers_clear(&p->buf);
58120 0 : ae_matrix_clear(&p->x);
58121 0 : ae_matrix_clear(&p->ax);
58122 0 : _rcommstate_clear(&p->rstate);
58123 0 : }
58124 :
58125 :
58126 0 : void _eigsubspacestate_destroy(void* _p)
58127 : {
58128 0 : eigsubspacestate *p = (eigsubspacestate*)_p;
58129 0 : ae_touch_ptr((void*)p);
58130 0 : _hqrndstate_destroy(&p->rs);
58131 0 : ae_vector_destroy(&p->tau);
58132 0 : ae_matrix_destroy(&p->q0);
58133 0 : ae_matrix_destroy(&p->qcur);
58134 0 : ae_matrix_destroy(&p->qnew);
58135 0 : ae_matrix_destroy(&p->znew);
58136 0 : ae_matrix_destroy(&p->r);
58137 0 : ae_matrix_destroy(&p->rz);
58138 0 : ae_matrix_destroy(&p->tz);
58139 0 : ae_matrix_destroy(&p->rq);
58140 0 : ae_matrix_destroy(&p->dummy);
58141 0 : ae_vector_destroy(&p->rw);
58142 0 : ae_vector_destroy(&p->tw);
58143 0 : ae_vector_destroy(&p->wcur);
58144 0 : ae_vector_destroy(&p->wprev);
58145 0 : ae_vector_destroy(&p->wrank);
58146 0 : _apbuffers_destroy(&p->buf);
58147 0 : ae_matrix_destroy(&p->x);
58148 0 : ae_matrix_destroy(&p->ax);
58149 0 : _rcommstate_destroy(&p->rstate);
58150 0 : }
58151 :
58152 :
58153 0 : void _eigsubspacereport_init(void* _p, ae_state *_state, ae_bool make_automatic)
58154 : {
58155 0 : eigsubspacereport *p = (eigsubspacereport*)_p;
58156 0 : ae_touch_ptr((void*)p);
58157 0 : }
58158 :
58159 :
58160 0 : void _eigsubspacereport_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
58161 : {
58162 0 : eigsubspacereport *dst = (eigsubspacereport*)_dst;
58163 0 : eigsubspacereport *src = (eigsubspacereport*)_src;
58164 0 : dst->iterationscount = src->iterationscount;
58165 0 : }
58166 :
58167 :
58168 0 : void _eigsubspacereport_clear(void* _p)
58169 : {
58170 0 : eigsubspacereport *p = (eigsubspacereport*)_p;
58171 0 : ae_touch_ptr((void*)p);
58172 0 : }
58173 :
58174 :
58175 0 : void _eigsubspacereport_destroy(void* _p)
58176 : {
58177 0 : eigsubspacereport *p = (eigsubspacereport*)_p;
58178 0 : ae_touch_ptr((void*)p);
58179 0 : }
58180 :
58181 :
58182 : #endif
58183 : #if defined(AE_COMPILE_SCHUR) || !defined(AE_PARTIAL_BUILD)
58184 :
58185 :
58186 : /*************************************************************************
58187 : Subroutine performing the Schur decomposition of a general matrix by using
58188 : the QR algorithm with multiple shifts.
58189 :
58190 : COMMERCIAL EDITION OF ALGLIB:
58191 :
58192 : ! Commercial version of ALGLIB includes one important improvement of
58193 : ! this function, which can be used from C++ and C#:
58194 : ! * Intel MKL support (lightweight Intel MKL is shipped with ALGLIB)
58195 : !
58196 : ! Intel MKL gives approximately constant (with respect to number of
58197 : ! worker threads) acceleration factor which depends on CPU being used,
58198 : ! problem size and "baseline" ALGLIB edition which is used for
58199 : ! comparison.
58200 : !
58201 : ! Multithreaded acceleration is NOT supported for this function.
58202 : !
58203 : ! We recommend you to read 'Working with commercial version' section of
58204 : ! ALGLIB Reference Manual in order to find out how to use performance-
58205 : ! related features provided by commercial edition of ALGLIB.
58206 :
58207 : The source matrix A is represented as S'*A*S = T, where S is an orthogonal
58208 : matrix (Schur vectors), T - upper quasi-triangular matrix (with blocks of
58209 : sizes 1x1 and 2x2 on the main diagonal).
58210 :
58211 : Input parameters:
58212 : A - matrix to be decomposed.
58213 : Array whose indexes range within [0..N-1, 0..N-1].
58214 : N - size of A, N>=0.
58215 :
58216 :
58217 : Output parameters:
58218 : A - contains matrix T.
58219 : Array whose indexes range within [0..N-1, 0..N-1].
58220 : S - contains Schur vectors.
58221 : Array whose indexes range within [0..N-1, 0..N-1].
58222 :
58223 : Note 1:
58224 : The block structure of matrix T can be easily recognized: since all
58225 : the elements below the blocks are zeros, the elements a[i+1,i] which
58226 : are equal to 0 show the block border.
58227 :
58228 : Note 2:
58229 : The algorithm performance depends on the value of the internal parameter
58230 : NS of the InternalSchurDecomposition subroutine which defines the number
58231 : of shifts in the QR algorithm (similarly to the block width in block-matrix
58232 : algorithms in linear algebra). If you require maximum performance on
58233 : your machine, it is recommended to adjust this parameter manually.
58234 :
58235 : Result:
58236 : True,
58237 : if the algorithm has converged and parameters A and S contain the result.
58238 : False,
58239 : if the algorithm has not converged.
58240 :
58241 : Algorithm implemented on the basis of the DHSEQR subroutine (LAPACK 3.0 library).
58242 : *************************************************************************/
58243 0 : ae_bool rmatrixschur(/* Real */ ae_matrix* a,
58244 : ae_int_t n,
58245 : /* Real */ ae_matrix* s,
58246 : ae_state *_state)
58247 : {
58248 : ae_frame _frame_block;
58249 : ae_vector tau;
58250 : ae_vector wi;
58251 : ae_vector wr;
58252 : ae_int_t info;
58253 : ae_bool result;
58254 :
58255 0 : ae_frame_make(_state, &_frame_block);
58256 0 : memset(&tau, 0, sizeof(tau));
58257 0 : memset(&wi, 0, sizeof(wi));
58258 0 : memset(&wr, 0, sizeof(wr));
58259 0 : ae_matrix_clear(s);
58260 0 : ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
58261 0 : ae_vector_init(&wi, 0, DT_REAL, _state, ae_true);
58262 0 : ae_vector_init(&wr, 0, DT_REAL, _state, ae_true);
58263 :
58264 :
58265 : /*
58266 : * Upper Hessenberg form of the 0-based matrix
58267 : */
58268 0 : rmatrixhessenberg(a, n, &tau, _state);
58269 0 : rmatrixhessenbergunpackq(a, n, &tau, s, _state);
58270 :
58271 : /*
58272 : * Schur decomposition
58273 : */
58274 0 : rmatrixinternalschurdecomposition(a, n, 1, 1, &wr, &wi, s, &info, _state);
58275 0 : result = info==0;
58276 0 : ae_frame_leave(_state);
58277 0 : return result;
58278 : }
58279 :
58280 :
58281 : #endif
58282 : #if defined(AE_COMPILE_SPDGEVD) || !defined(AE_PARTIAL_BUILD)
58283 :
58284 :
58285 : /*************************************************************************
58286 : Algorithm for solving the following generalized symmetric positive-definite
58287 : eigenproblem:
58288 : A*x = lambda*B*x (1) or
58289 : A*B*x = lambda*x (2) or
58290 : B*A*x = lambda*x (3).
58291 : where A is a symmetric matrix, B - symmetric positive-definite matrix.
58292 : The problem is solved by reducing it to an ordinary symmetric eigenvalue
58293 : problem.
58294 :
58295 : Input parameters:
58296 : A - symmetric matrix which is given by its upper or lower
58297 : triangular part.
58298 : Array whose indexes range within [0..N-1, 0..N-1].
58299 : N - size of matrices A and B.
58300 : IsUpperA - storage format of matrix A.
58301 : B - symmetric positive-definite matrix which is given by
58302 : its upper or lower triangular part.
58303 : Array whose indexes range within [0..N-1, 0..N-1].
58304 : IsUpperB - storage format of matrix B.
58305 : ZNeeded - if ZNeeded is equal to:
58306 : * 0, the eigenvectors are not returned;
58307 : * 1, the eigenvectors are returned.
58308 : ProblemType - if ProblemType is equal to:
58309 : * 1, the following problem is solved: A*x = lambda*B*x;
58310 : * 2, the following problem is solved: A*B*x = lambda*x;
58311 : * 3, the following problem is solved: B*A*x = lambda*x.
58312 :
58313 : Output parameters:
58314 : D - eigenvalues in ascending order.
58315 : Array whose index ranges within [0..N-1].
58316 : Z - if ZNeeded is equal to:
58317 : * 0, Z hasn't changed;
58318 : * 1, Z contains eigenvectors.
58319 : Array whose indexes range within [0..N-1, 0..N-1].
58320 : The eigenvectors are stored in matrix columns. It should
58321 : be noted that the eigenvectors in such problems do not
58322 : form an orthogonal system.
58323 :
58324 : Result:
58325 : True, if the problem was solved successfully.
58326 : False, if the error occurred during the Cholesky decomposition of matrix
58327 : B (the matrix isn't positive-definite) or during the work of the iterative
58328 : algorithm for solving the symmetric eigenproblem.
58329 :
58330 : See also the GeneralizedSymmetricDefiniteEVDReduce subroutine.
58331 :
58332 : -- ALGLIB --
58333 : Copyright 1.28.2006 by Bochkanov Sergey
58334 : *************************************************************************/
58335 0 : ae_bool smatrixgevd(/* Real */ ae_matrix* a,
58336 : ae_int_t n,
58337 : ae_bool isuppera,
58338 : /* Real */ ae_matrix* b,
58339 : ae_bool isupperb,
58340 : ae_int_t zneeded,
58341 : ae_int_t problemtype,
58342 : /* Real */ ae_vector* d,
58343 : /* Real */ ae_matrix* z,
58344 : ae_state *_state)
58345 : {
58346 : ae_frame _frame_block;
58347 : ae_matrix _a;
58348 : ae_matrix r;
58349 : ae_matrix t;
58350 : ae_bool isupperr;
58351 : ae_int_t j1;
58352 : ae_int_t j2;
58353 : ae_int_t j1inc;
58354 : ae_int_t j2inc;
58355 : ae_int_t i;
58356 : ae_int_t j;
58357 : double v;
58358 : ae_bool result;
58359 :
58360 0 : ae_frame_make(_state, &_frame_block);
58361 0 : memset(&_a, 0, sizeof(_a));
58362 0 : memset(&r, 0, sizeof(r));
58363 0 : memset(&t, 0, sizeof(t));
58364 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
58365 0 : a = &_a;
58366 0 : ae_vector_clear(d);
58367 0 : ae_matrix_clear(z);
58368 0 : ae_matrix_init(&r, 0, 0, DT_REAL, _state, ae_true);
58369 0 : ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true);
58370 :
58371 :
58372 : /*
58373 : * Reduce and solve
58374 : */
58375 0 : result = smatrixgevdreduce(a, n, isuppera, b, isupperb, problemtype, &r, &isupperr, _state);
58376 0 : if( !result )
58377 : {
58378 0 : ae_frame_leave(_state);
58379 0 : return result;
58380 : }
58381 0 : result = smatrixevd(a, n, zneeded, isuppera, d, &t, _state);
58382 0 : if( !result )
58383 : {
58384 0 : ae_frame_leave(_state);
58385 0 : return result;
58386 : }
58387 :
58388 : /*
58389 : * Transform eigenvectors if needed
58390 : */
58391 0 : if( zneeded!=0 )
58392 : {
58393 :
58394 : /*
58395 : * fill Z with zeros
58396 : */
58397 0 : ae_matrix_set_length(z, n-1+1, n-1+1, _state);
58398 0 : for(j=0; j<=n-1; j++)
58399 : {
58400 0 : z->ptr.pp_double[0][j] = 0.0;
58401 : }
58402 0 : for(i=1; i<=n-1; i++)
58403 : {
58404 0 : ae_v_move(&z->ptr.pp_double[i][0], 1, &z->ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
58405 : }
58406 :
58407 : /*
58408 : * Setup R properties
58409 : */
58410 0 : if( isupperr )
58411 : {
58412 0 : j1 = 0;
58413 0 : j2 = n-1;
58414 0 : j1inc = 1;
58415 0 : j2inc = 0;
58416 : }
58417 : else
58418 : {
58419 0 : j1 = 0;
58420 0 : j2 = 0;
58421 0 : j1inc = 0;
58422 0 : j2inc = 1;
58423 : }
58424 :
58425 : /*
58426 : * Calculate R*Z
58427 : */
58428 0 : for(i=0; i<=n-1; i++)
58429 : {
58430 0 : for(j=j1; j<=j2; j++)
58431 : {
58432 0 : v = r.ptr.pp_double[i][j];
58433 0 : ae_v_addd(&z->ptr.pp_double[i][0], 1, &t.ptr.pp_double[j][0], 1, ae_v_len(0,n-1), v);
58434 : }
58435 0 : j1 = j1+j1inc;
58436 0 : j2 = j2+j2inc;
58437 : }
58438 : }
58439 0 : ae_frame_leave(_state);
58440 0 : return result;
58441 : }
58442 :
58443 :
58444 : /*************************************************************************
58445 : Algorithm for reduction of the following generalized symmetric positive-
58446 : definite eigenvalue problem:
58447 : A*x = lambda*B*x (1) or
58448 : A*B*x = lambda*x (2) or
58449 : B*A*x = lambda*x (3)
58450 : to the symmetric eigenvalues problem C*y = lambda*y (eigenvalues of this and
58451 : the given problems are the same, and the eigenvectors of the given problem
58452 : could be obtained by multiplying the obtained eigenvectors by the
58453 : transformation matrix x = R*y).
58454 :
58455 : Here A is a symmetric matrix, B - symmetric positive-definite matrix.
58456 :
58457 : Input parameters:
58458 : A - symmetric matrix which is given by its upper or lower
58459 : triangular part.
58460 : Array whose indexes range within [0..N-1, 0..N-1].
58461 : N - size of matrices A and B.
58462 : IsUpperA - storage format of matrix A.
58463 : B - symmetric positive-definite matrix which is given by
58464 : its upper or lower triangular part.
58465 : Array whose indexes range within [0..N-1, 0..N-1].
58466 : IsUpperB - storage format of matrix B.
58467 : ProblemType - if ProblemType is equal to:
58468 : * 1, the following problem is solved: A*x = lambda*B*x;
58469 : * 2, the following problem is solved: A*B*x = lambda*x;
58470 : * 3, the following problem is solved: B*A*x = lambda*x.
58471 :
58472 : Output parameters:
58473 : A - symmetric matrix which is given by its upper or lower
58474 : triangle depending on IsUpperA. Contains matrix C.
58475 : Array whose indexes range within [0..N-1, 0..N-1].
58476 : R - upper triangular or low triangular transformation matrix
58477 : which is used to obtain the eigenvectors of a given problem
58478 : as the product of eigenvectors of C (from the right) and
58479 : matrix R (from the left). If the matrix is upper
58480 : triangular, the elements below the main diagonal
58481 : are equal to 0 (and vice versa). Thus, we can perform
58482 : the multiplication without taking into account the
58483 : internal structure (which is an easier though less
58484 : effective way).
58485 : Array whose indexes range within [0..N-1, 0..N-1].
58486 : IsUpperR - type of matrix R (upper or lower triangular).
58487 :
58488 : Result:
58489 : True, if the problem was reduced successfully.
58490 : False, if the error occurred during the Cholesky decomposition of
58491 : matrix B (the matrix is not positive-definite).
58492 :
58493 : -- ALGLIB --
58494 : Copyright 1.28.2006 by Bochkanov Sergey
58495 : *************************************************************************/
58496 0 : ae_bool smatrixgevdreduce(/* Real */ ae_matrix* a,
58497 : ae_int_t n,
58498 : ae_bool isuppera,
58499 : /* Real */ ae_matrix* b,
58500 : ae_bool isupperb,
58501 : ae_int_t problemtype,
58502 : /* Real */ ae_matrix* r,
58503 : ae_bool* isupperr,
58504 : ae_state *_state)
58505 : {
58506 : ae_frame _frame_block;
58507 : ae_matrix t;
58508 : ae_vector w1;
58509 : ae_vector w2;
58510 : ae_vector w3;
58511 : ae_int_t i;
58512 : ae_int_t j;
58513 : double v;
58514 : matinvreport rep;
58515 : ae_int_t info;
58516 : ae_bool result;
58517 :
58518 0 : ae_frame_make(_state, &_frame_block);
58519 0 : memset(&t, 0, sizeof(t));
58520 0 : memset(&w1, 0, sizeof(w1));
58521 0 : memset(&w2, 0, sizeof(w2));
58522 0 : memset(&w3, 0, sizeof(w3));
58523 0 : memset(&rep, 0, sizeof(rep));
58524 0 : ae_matrix_clear(r);
58525 0 : *isupperr = ae_false;
58526 0 : ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true);
58527 0 : ae_vector_init(&w1, 0, DT_REAL, _state, ae_true);
58528 0 : ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
58529 0 : ae_vector_init(&w3, 0, DT_REAL, _state, ae_true);
58530 0 : _matinvreport_init(&rep, _state, ae_true);
58531 :
58532 0 : ae_assert(n>0, "SMatrixGEVDReduce: N<=0!", _state);
58533 0 : ae_assert((problemtype==1||problemtype==2)||problemtype==3, "SMatrixGEVDReduce: incorrect ProblemType!", _state);
58534 0 : result = ae_true;
58535 :
58536 : /*
58537 : * Problem 1: A*x = lambda*B*x
58538 : *
58539 : * Reducing to:
58540 : * C*y = lambda*y
58541 : * C = L^(-1) * A * L^(-T)
58542 : * x = L^(-T) * y
58543 : */
58544 0 : if( problemtype==1 )
58545 : {
58546 :
58547 : /*
58548 : * Factorize B in T: B = LL'
58549 : */
58550 0 : ae_matrix_set_length(&t, n-1+1, n-1+1, _state);
58551 0 : if( isupperb )
58552 : {
58553 0 : for(i=0; i<=n-1; i++)
58554 : {
58555 0 : ae_v_move(&t.ptr.pp_double[i][i], t.stride, &b->ptr.pp_double[i][i], 1, ae_v_len(i,n-1));
58556 : }
58557 : }
58558 : else
58559 : {
58560 0 : for(i=0; i<=n-1; i++)
58561 : {
58562 0 : ae_v_move(&t.ptr.pp_double[i][0], 1, &b->ptr.pp_double[i][0], 1, ae_v_len(0,i));
58563 : }
58564 : }
58565 0 : if( !spdmatrixcholesky(&t, n, ae_false, _state) )
58566 : {
58567 0 : result = ae_false;
58568 0 : ae_frame_leave(_state);
58569 0 : return result;
58570 : }
58571 :
58572 : /*
58573 : * Invert L in T
58574 : */
58575 0 : rmatrixtrinverse(&t, n, ae_false, ae_false, &info, &rep, _state);
58576 0 : if( info<=0 )
58577 : {
58578 0 : result = ae_false;
58579 0 : ae_frame_leave(_state);
58580 0 : return result;
58581 : }
58582 :
58583 : /*
58584 : * Build L^(-1) * A * L^(-T) in R
58585 : */
58586 0 : ae_vector_set_length(&w1, n+1, _state);
58587 0 : ae_vector_set_length(&w2, n+1, _state);
58588 0 : ae_matrix_set_length(r, n-1+1, n-1+1, _state);
58589 0 : for(j=1; j<=n; j++)
58590 : {
58591 :
58592 : /*
58593 : * Form w2 = A * l'(j) (here l'(j) is j-th column of L^(-T))
58594 : */
58595 0 : ae_v_move(&w1.ptr.p_double[1], 1, &t.ptr.pp_double[j-1][0], 1, ae_v_len(1,j));
58596 0 : symmetricmatrixvectormultiply(a, isuppera, 0, j-1, &w1, 1.0, &w2, _state);
58597 0 : if( isuppera )
58598 : {
58599 0 : matrixvectormultiply(a, 0, j-1, j, n-1, ae_true, &w1, 1, j, 1.0, &w2, j+1, n, 0.0, _state);
58600 : }
58601 : else
58602 : {
58603 0 : matrixvectormultiply(a, j, n-1, 0, j-1, ae_false, &w1, 1, j, 1.0, &w2, j+1, n, 0.0, _state);
58604 : }
58605 :
58606 : /*
58607 : * Form l(i)*w2 (here l(i) is i-th row of L^(-1))
58608 : */
58609 0 : for(i=1; i<=n; i++)
58610 : {
58611 0 : v = ae_v_dotproduct(&t.ptr.pp_double[i-1][0], 1, &w2.ptr.p_double[1], 1, ae_v_len(0,i-1));
58612 0 : r->ptr.pp_double[i-1][j-1] = v;
58613 : }
58614 : }
58615 :
58616 : /*
58617 : * Copy R to A
58618 : */
58619 0 : for(i=0; i<=n-1; i++)
58620 : {
58621 0 : ae_v_move(&a->ptr.pp_double[i][0], 1, &r->ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
58622 : }
58623 :
58624 : /*
58625 : * Copy L^(-1) from T to R and transpose
58626 : */
58627 0 : *isupperr = ae_true;
58628 0 : for(i=0; i<=n-1; i++)
58629 : {
58630 0 : for(j=0; j<=i-1; j++)
58631 : {
58632 0 : r->ptr.pp_double[i][j] = (double)(0);
58633 : }
58634 : }
58635 0 : for(i=0; i<=n-1; i++)
58636 : {
58637 0 : ae_v_move(&r->ptr.pp_double[i][i], 1, &t.ptr.pp_double[i][i], t.stride, ae_v_len(i,n-1));
58638 : }
58639 0 : ae_frame_leave(_state);
58640 0 : return result;
58641 : }
58642 :
58643 : /*
58644 : * Problem 2: A*B*x = lambda*x
58645 : * or
58646 : * problem 3: B*A*x = lambda*x
58647 : *
58648 : * Reducing to:
58649 : * C*y = lambda*y
58650 : * C = U * A * U'
58651 : * B = U'* U
58652 : */
58653 0 : if( problemtype==2||problemtype==3 )
58654 : {
58655 :
58656 : /*
58657 : * Factorize B in T: B = U'*U
58658 : */
58659 0 : ae_matrix_set_length(&t, n-1+1, n-1+1, _state);
58660 0 : if( isupperb )
58661 : {
58662 0 : for(i=0; i<=n-1; i++)
58663 : {
58664 0 : ae_v_move(&t.ptr.pp_double[i][i], 1, &b->ptr.pp_double[i][i], 1, ae_v_len(i,n-1));
58665 : }
58666 : }
58667 : else
58668 : {
58669 0 : for(i=0; i<=n-1; i++)
58670 : {
58671 0 : ae_v_move(&t.ptr.pp_double[i][i], 1, &b->ptr.pp_double[i][i], b->stride, ae_v_len(i,n-1));
58672 : }
58673 : }
58674 0 : if( !spdmatrixcholesky(&t, n, ae_true, _state) )
58675 : {
58676 0 : result = ae_false;
58677 0 : ae_frame_leave(_state);
58678 0 : return result;
58679 : }
58680 :
58681 : /*
58682 : * Build U * A * U' in R
58683 : */
58684 0 : ae_vector_set_length(&w1, n+1, _state);
58685 0 : ae_vector_set_length(&w2, n+1, _state);
58686 0 : ae_vector_set_length(&w3, n+1, _state);
58687 0 : ae_matrix_set_length(r, n-1+1, n-1+1, _state);
58688 0 : for(j=1; j<=n; j++)
58689 : {
58690 :
58691 : /*
58692 : * Form w2 = A * u'(j) (here u'(j) is j-th column of U')
58693 : */
58694 0 : ae_v_move(&w1.ptr.p_double[1], 1, &t.ptr.pp_double[j-1][j-1], 1, ae_v_len(1,n-j+1));
58695 0 : symmetricmatrixvectormultiply(a, isuppera, j-1, n-1, &w1, 1.0, &w3, _state);
58696 0 : ae_v_move(&w2.ptr.p_double[j], 1, &w3.ptr.p_double[1], 1, ae_v_len(j,n));
58697 0 : ae_v_move(&w1.ptr.p_double[j], 1, &t.ptr.pp_double[j-1][j-1], 1, ae_v_len(j,n));
58698 0 : if( isuppera )
58699 : {
58700 0 : matrixvectormultiply(a, 0, j-2, j-1, n-1, ae_false, &w1, j, n, 1.0, &w2, 1, j-1, 0.0, _state);
58701 : }
58702 : else
58703 : {
58704 0 : matrixvectormultiply(a, j-1, n-1, 0, j-2, ae_true, &w1, j, n, 1.0, &w2, 1, j-1, 0.0, _state);
58705 : }
58706 :
58707 : /*
58708 : * Form u(i)*w2 (here u(i) is i-th row of U)
58709 : */
58710 0 : for(i=1; i<=n; i++)
58711 : {
58712 0 : v = ae_v_dotproduct(&t.ptr.pp_double[i-1][i-1], 1, &w2.ptr.p_double[i], 1, ae_v_len(i-1,n-1));
58713 0 : r->ptr.pp_double[i-1][j-1] = v;
58714 : }
58715 : }
58716 :
58717 : /*
58718 : * Copy R to A
58719 : */
58720 0 : for(i=0; i<=n-1; i++)
58721 : {
58722 0 : ae_v_move(&a->ptr.pp_double[i][0], 1, &r->ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
58723 : }
58724 0 : if( problemtype==2 )
58725 : {
58726 :
58727 : /*
58728 : * Invert U in T
58729 : */
58730 0 : rmatrixtrinverse(&t, n, ae_true, ae_false, &info, &rep, _state);
58731 0 : if( info<=0 )
58732 : {
58733 0 : result = ae_false;
58734 0 : ae_frame_leave(_state);
58735 0 : return result;
58736 : }
58737 :
58738 : /*
58739 : * Copy U^-1 from T to R
58740 : */
58741 0 : *isupperr = ae_true;
58742 0 : for(i=0; i<=n-1; i++)
58743 : {
58744 0 : for(j=0; j<=i-1; j++)
58745 : {
58746 0 : r->ptr.pp_double[i][j] = (double)(0);
58747 : }
58748 : }
58749 0 : for(i=0; i<=n-1; i++)
58750 : {
58751 0 : ae_v_move(&r->ptr.pp_double[i][i], 1, &t.ptr.pp_double[i][i], 1, ae_v_len(i,n-1));
58752 : }
58753 : }
58754 : else
58755 : {
58756 :
58757 : /*
58758 : * Copy U from T to R and transpose
58759 : */
58760 0 : *isupperr = ae_false;
58761 0 : for(i=0; i<=n-1; i++)
58762 : {
58763 0 : for(j=i+1; j<=n-1; j++)
58764 : {
58765 0 : r->ptr.pp_double[i][j] = (double)(0);
58766 : }
58767 : }
58768 0 : for(i=0; i<=n-1; i++)
58769 : {
58770 0 : ae_v_move(&r->ptr.pp_double[i][i], r->stride, &t.ptr.pp_double[i][i], 1, ae_v_len(i,n-1));
58771 : }
58772 : }
58773 : }
58774 0 : ae_frame_leave(_state);
58775 0 : return result;
58776 : }
58777 :
58778 :
58779 : #endif
58780 : #if defined(AE_COMPILE_INVERSEUPDATE) || !defined(AE_PARTIAL_BUILD)
58781 :
58782 :
58783 : /*************************************************************************
58784 : Inverse matrix update by the Sherman-Morrison formula
58785 :
58786 : The algorithm updates matrix A^-1 when adding a number to an element
58787 : of matrix A.
58788 :
58789 : Input parameters:
58790 : InvA - inverse of matrix A.
58791 : Array whose indexes range within [0..N-1, 0..N-1].
58792 : N - size of matrix A.
58793 : UpdRow - row where the element to be updated is stored.
58794 : UpdColumn - column where the element to be updated is stored.
58795 : UpdVal - a number to be added to the element.
58796 :
58797 :
58798 : Output parameters:
58799 : InvA - inverse of modified matrix A.
58800 :
58801 : -- ALGLIB --
58802 : Copyright 2005 by Bochkanov Sergey
58803 : *************************************************************************/
58804 0 : void rmatrixinvupdatesimple(/* Real */ ae_matrix* inva,
58805 : ae_int_t n,
58806 : ae_int_t updrow,
58807 : ae_int_t updcolumn,
58808 : double updval,
58809 : ae_state *_state)
58810 : {
58811 : ae_frame _frame_block;
58812 : ae_vector t1;
58813 : ae_vector t2;
58814 : ae_int_t i;
58815 : double lambdav;
58816 : double vt;
58817 :
58818 0 : ae_frame_make(_state, &_frame_block);
58819 0 : memset(&t1, 0, sizeof(t1));
58820 0 : memset(&t2, 0, sizeof(t2));
58821 0 : ae_vector_init(&t1, 0, DT_REAL, _state, ae_true);
58822 0 : ae_vector_init(&t2, 0, DT_REAL, _state, ae_true);
58823 :
58824 0 : ae_assert(updrow>=0&&updrow<n, "RMatrixInvUpdateSimple: incorrect UpdRow!", _state);
58825 0 : ae_assert(updcolumn>=0&&updcolumn<n, "RMatrixInvUpdateSimple: incorrect UpdColumn!", _state);
58826 0 : ae_vector_set_length(&t1, n-1+1, _state);
58827 0 : ae_vector_set_length(&t2, n-1+1, _state);
58828 :
58829 : /*
58830 : * T1 = InvA * U
58831 : */
58832 0 : ae_v_move(&t1.ptr.p_double[0], 1, &inva->ptr.pp_double[0][updrow], inva->stride, ae_v_len(0,n-1));
58833 :
58834 : /*
58835 : * T2 = v*InvA
58836 : */
58837 0 : ae_v_move(&t2.ptr.p_double[0], 1, &inva->ptr.pp_double[updcolumn][0], 1, ae_v_len(0,n-1));
58838 :
58839 : /*
58840 : * Lambda = v * InvA * U
58841 : */
58842 0 : lambdav = updval*inva->ptr.pp_double[updcolumn][updrow];
58843 :
58844 : /*
58845 : * InvA = InvA - correction
58846 : */
58847 0 : for(i=0; i<=n-1; i++)
58848 : {
58849 0 : vt = updval*t1.ptr.p_double[i];
58850 0 : vt = vt/(1+lambdav);
58851 0 : ae_v_subd(&inva->ptr.pp_double[i][0], 1, &t2.ptr.p_double[0], 1, ae_v_len(0,n-1), vt);
58852 : }
58853 0 : ae_frame_leave(_state);
58854 0 : }
58855 :
58856 :
58857 : /*************************************************************************
58858 : Inverse matrix update by the Sherman-Morrison formula
58859 :
58860 : The algorithm updates matrix A^-1 when adding a vector to a row
58861 : of matrix A.
58862 :
58863 : Input parameters:
58864 : InvA - inverse of matrix A.
58865 : Array whose indexes range within [0..N-1, 0..N-1].
58866 : N - size of matrix A.
58867 : UpdRow - the row of A whose vector V was added.
58868 : 0 <= Row <= N-1
58869 : V - the vector to be added to a row.
58870 : Array whose index ranges within [0..N-1].
58871 :
58872 : Output parameters:
58873 : InvA - inverse of modified matrix A.
58874 :
58875 : -- ALGLIB --
58876 : Copyright 2005 by Bochkanov Sergey
58877 : *************************************************************************/
58878 0 : void rmatrixinvupdaterow(/* Real */ ae_matrix* inva,
58879 : ae_int_t n,
58880 : ae_int_t updrow,
58881 : /* Real */ ae_vector* v,
58882 : ae_state *_state)
58883 : {
58884 : ae_frame _frame_block;
58885 : ae_vector t1;
58886 : ae_vector t2;
58887 : ae_int_t i;
58888 : ae_int_t j;
58889 : double lambdav;
58890 : double vt;
58891 :
58892 0 : ae_frame_make(_state, &_frame_block);
58893 0 : memset(&t1, 0, sizeof(t1));
58894 0 : memset(&t2, 0, sizeof(t2));
58895 0 : ae_vector_init(&t1, 0, DT_REAL, _state, ae_true);
58896 0 : ae_vector_init(&t2, 0, DT_REAL, _state, ae_true);
58897 :
58898 0 : ae_vector_set_length(&t1, n-1+1, _state);
58899 0 : ae_vector_set_length(&t2, n-1+1, _state);
58900 :
58901 : /*
58902 : * T1 = InvA * U
58903 : */
58904 0 : ae_v_move(&t1.ptr.p_double[0], 1, &inva->ptr.pp_double[0][updrow], inva->stride, ae_v_len(0,n-1));
58905 :
58906 : /*
58907 : * T2 = v*InvA
58908 : * Lambda = v * InvA * U
58909 : */
58910 0 : for(j=0; j<=n-1; j++)
58911 : {
58912 0 : vt = ae_v_dotproduct(&v->ptr.p_double[0], 1, &inva->ptr.pp_double[0][j], inva->stride, ae_v_len(0,n-1));
58913 0 : t2.ptr.p_double[j] = vt;
58914 : }
58915 0 : lambdav = t2.ptr.p_double[updrow];
58916 :
58917 : /*
58918 : * InvA = InvA - correction
58919 : */
58920 0 : for(i=0; i<=n-1; i++)
58921 : {
58922 0 : vt = t1.ptr.p_double[i]/(1+lambdav);
58923 0 : ae_v_subd(&inva->ptr.pp_double[i][0], 1, &t2.ptr.p_double[0], 1, ae_v_len(0,n-1), vt);
58924 : }
58925 0 : ae_frame_leave(_state);
58926 0 : }
58927 :
58928 :
58929 : /*************************************************************************
58930 : Inverse matrix update by the Sherman-Morrison formula
58931 :
58932 : The algorithm updates matrix A^-1 when adding a vector to a column
58933 : of matrix A.
58934 :
58935 : Input parameters:
58936 : InvA - inverse of matrix A.
58937 : Array whose indexes range within [0..N-1, 0..N-1].
58938 : N - size of matrix A.
58939 : UpdColumn - the column of A whose vector U was added.
58940 : 0 <= UpdColumn <= N-1
58941 : U - the vector to be added to a column.
58942 : Array whose index ranges within [0..N-1].
58943 :
58944 : Output parameters:
58945 : InvA - inverse of modified matrix A.
58946 :
58947 : -- ALGLIB --
58948 : Copyright 2005 by Bochkanov Sergey
58949 : *************************************************************************/
58950 0 : void rmatrixinvupdatecolumn(/* Real */ ae_matrix* inva,
58951 : ae_int_t n,
58952 : ae_int_t updcolumn,
58953 : /* Real */ ae_vector* u,
58954 : ae_state *_state)
58955 : {
58956 : ae_frame _frame_block;
58957 : ae_vector t1;
58958 : ae_vector t2;
58959 : ae_int_t i;
58960 : double lambdav;
58961 : double vt;
58962 :
58963 0 : ae_frame_make(_state, &_frame_block);
58964 0 : memset(&t1, 0, sizeof(t1));
58965 0 : memset(&t2, 0, sizeof(t2));
58966 0 : ae_vector_init(&t1, 0, DT_REAL, _state, ae_true);
58967 0 : ae_vector_init(&t2, 0, DT_REAL, _state, ae_true);
58968 :
58969 0 : ae_vector_set_length(&t1, n-1+1, _state);
58970 0 : ae_vector_set_length(&t2, n-1+1, _state);
58971 :
58972 : /*
58973 : * T1 = InvA * U
58974 : * Lambda = v * InvA * U
58975 : */
58976 0 : for(i=0; i<=n-1; i++)
58977 : {
58978 0 : vt = ae_v_dotproduct(&inva->ptr.pp_double[i][0], 1, &u->ptr.p_double[0], 1, ae_v_len(0,n-1));
58979 0 : t1.ptr.p_double[i] = vt;
58980 : }
58981 0 : lambdav = t1.ptr.p_double[updcolumn];
58982 :
58983 : /*
58984 : * T2 = v*InvA
58985 : */
58986 0 : ae_v_move(&t2.ptr.p_double[0], 1, &inva->ptr.pp_double[updcolumn][0], 1, ae_v_len(0,n-1));
58987 :
58988 : /*
58989 : * InvA = InvA - correction
58990 : */
58991 0 : for(i=0; i<=n-1; i++)
58992 : {
58993 0 : vt = t1.ptr.p_double[i]/(1+lambdav);
58994 0 : ae_v_subd(&inva->ptr.pp_double[i][0], 1, &t2.ptr.p_double[0], 1, ae_v_len(0,n-1), vt);
58995 : }
58996 0 : ae_frame_leave(_state);
58997 0 : }
58998 :
58999 :
59000 : /*************************************************************************
59001 : Inverse matrix update by the Sherman-Morrison formula
59002 :
59003 : The algorithm computes the inverse of matrix A+u*v' by using the given matrix
59004 : A^-1 and the vectors u and v.
59005 :
59006 : Input parameters:
59007 : InvA - inverse of matrix A.
59008 : Array whose indexes range within [0..N-1, 0..N-1].
59009 : N - size of matrix A.
59010 : U - the vector modifying the matrix.
59011 : Array whose index ranges within [0..N-1].
59012 : V - the vector modifying the matrix.
59013 : Array whose index ranges within [0..N-1].
59014 :
59015 : Output parameters:
59016 : InvA - inverse of matrix A + u*v'.
59017 :
59018 : -- ALGLIB --
59019 : Copyright 2005 by Bochkanov Sergey
59020 : *************************************************************************/
59021 0 : void rmatrixinvupdateuv(/* Real */ ae_matrix* inva,
59022 : ae_int_t n,
59023 : /* Real */ ae_vector* u,
59024 : /* Real */ ae_vector* v,
59025 : ae_state *_state)
59026 : {
59027 : ae_frame _frame_block;
59028 : ae_vector t1;
59029 : ae_vector t2;
59030 : ae_int_t i;
59031 : ae_int_t j;
59032 : double lambdav;
59033 : double vt;
59034 :
59035 0 : ae_frame_make(_state, &_frame_block);
59036 0 : memset(&t1, 0, sizeof(t1));
59037 0 : memset(&t2, 0, sizeof(t2));
59038 0 : ae_vector_init(&t1, 0, DT_REAL, _state, ae_true);
59039 0 : ae_vector_init(&t2, 0, DT_REAL, _state, ae_true);
59040 :
59041 0 : ae_vector_set_length(&t1, n-1+1, _state);
59042 0 : ae_vector_set_length(&t2, n-1+1, _state);
59043 :
59044 : /*
59045 : * T1 = InvA * U
59046 : * Lambda = v * T1
59047 : */
59048 0 : for(i=0; i<=n-1; i++)
59049 : {
59050 0 : vt = ae_v_dotproduct(&inva->ptr.pp_double[i][0], 1, &u->ptr.p_double[0], 1, ae_v_len(0,n-1));
59051 0 : t1.ptr.p_double[i] = vt;
59052 : }
59053 0 : lambdav = ae_v_dotproduct(&v->ptr.p_double[0], 1, &t1.ptr.p_double[0], 1, ae_v_len(0,n-1));
59054 :
59055 : /*
59056 : * T2 = v*InvA
59057 : */
59058 0 : for(j=0; j<=n-1; j++)
59059 : {
59060 0 : vt = ae_v_dotproduct(&v->ptr.p_double[0], 1, &inva->ptr.pp_double[0][j], inva->stride, ae_v_len(0,n-1));
59061 0 : t2.ptr.p_double[j] = vt;
59062 : }
59063 :
59064 : /*
59065 : * InvA = InvA - correction
59066 : */
59067 0 : for(i=0; i<=n-1; i++)
59068 : {
59069 0 : vt = t1.ptr.p_double[i]/(1+lambdav);
59070 0 : ae_v_subd(&inva->ptr.pp_double[i][0], 1, &t2.ptr.p_double[0], 1, ae_v_len(0,n-1), vt);
59071 : }
59072 0 : ae_frame_leave(_state);
59073 0 : }
59074 :
59075 :
59076 : #endif
59077 : #if defined(AE_COMPILE_MATDET) || !defined(AE_PARTIAL_BUILD)
59078 :
59079 :
59080 : /*************************************************************************
59081 : Determinant calculation of the matrix given by its LU decomposition.
59082 :
59083 : Input parameters:
59084 : A - LU decomposition of the matrix (output of
59085 : RMatrixLU subroutine).
59086 : Pivots - table of permutations which were made during
59087 : the LU decomposition.
59088 : Output of RMatrixLU subroutine.
59089 : N - (optional) size of matrix A:
59090 : * if given, only principal NxN submatrix is processed and
59091 : overwritten. other elements are unchanged.
59092 : * if not given, automatically determined from matrix size
59093 : (A must be square matrix)
59094 :
59095 : Result: matrix determinant.
59096 :
59097 : -- ALGLIB --
59098 : Copyright 2005 by Bochkanov Sergey
59099 : *************************************************************************/
59100 0 : double rmatrixludet(/* Real */ ae_matrix* a,
59101 : /* Integer */ ae_vector* pivots,
59102 : ae_int_t n,
59103 : ae_state *_state)
59104 : {
59105 : ae_int_t i;
59106 : ae_int_t s;
59107 : double result;
59108 :
59109 :
59110 0 : ae_assert(n>=1, "RMatrixLUDet: N<1!", _state);
59111 0 : ae_assert(pivots->cnt>=n, "RMatrixLUDet: Pivots array is too short!", _state);
59112 0 : ae_assert(a->rows>=n, "RMatrixLUDet: rows(A)<N!", _state);
59113 0 : ae_assert(a->cols>=n, "RMatrixLUDet: cols(A)<N!", _state);
59114 0 : ae_assert(apservisfinitematrix(a, n, n, _state), "RMatrixLUDet: A contains infinite or NaN values!", _state);
59115 0 : result = (double)(1);
59116 0 : s = 1;
59117 0 : for(i=0; i<=n-1; i++)
59118 : {
59119 0 : result = result*a->ptr.pp_double[i][i];
59120 0 : if( pivots->ptr.p_int[i]!=i )
59121 : {
59122 0 : s = -s;
59123 : }
59124 : }
59125 0 : result = result*s;
59126 0 : return result;
59127 : }
59128 :
59129 :
59130 : /*************************************************************************
59131 : Calculation of the determinant of a general matrix
59132 :
59133 : Input parameters:
59134 : A - matrix, array[0..N-1, 0..N-1]
59135 : N - (optional) size of matrix A:
59136 : * if given, only principal NxN submatrix is processed and
59137 : overwritten. other elements are unchanged.
59138 : * if not given, automatically determined from matrix size
59139 : (A must be square matrix)
59140 :
59141 : Result: determinant of matrix A.
59142 :
59143 : -- ALGLIB --
59144 : Copyright 2005 by Bochkanov Sergey
59145 : *************************************************************************/
59146 0 : double rmatrixdet(/* Real */ ae_matrix* a,
59147 : ae_int_t n,
59148 : ae_state *_state)
59149 : {
59150 : ae_frame _frame_block;
59151 : ae_matrix _a;
59152 : ae_vector pivots;
59153 : double result;
59154 :
59155 0 : ae_frame_make(_state, &_frame_block);
59156 0 : memset(&_a, 0, sizeof(_a));
59157 0 : memset(&pivots, 0, sizeof(pivots));
59158 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
59159 0 : a = &_a;
59160 0 : ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
59161 :
59162 0 : ae_assert(n>=1, "RMatrixDet: N<1!", _state);
59163 0 : ae_assert(a->rows>=n, "RMatrixDet: rows(A)<N!", _state);
59164 0 : ae_assert(a->cols>=n, "RMatrixDet: cols(A)<N!", _state);
59165 0 : ae_assert(apservisfinitematrix(a, n, n, _state), "RMatrixDet: A contains infinite or NaN values!", _state);
59166 0 : rmatrixlu(a, n, n, &pivots, _state);
59167 0 : result = rmatrixludet(a, &pivots, n, _state);
59168 0 : ae_frame_leave(_state);
59169 0 : return result;
59170 : }
59171 :
59172 :
59173 : /*************************************************************************
59174 : Determinant calculation of the matrix given by its LU decomposition.
59175 :
59176 : Input parameters:
59177 : A - LU decomposition of the matrix (output of
59178 : RMatrixLU subroutine).
59179 : Pivots - table of permutations which were made during
59180 : the LU decomposition.
59181 : Output of RMatrixLU subroutine.
59182 : N - (optional) size of matrix A:
59183 : * if given, only principal NxN submatrix is processed and
59184 : overwritten. other elements are unchanged.
59185 : * if not given, automatically determined from matrix size
59186 : (A must be square matrix)
59187 :
59188 : Result: matrix determinant.
59189 :
59190 : -- ALGLIB --
59191 : Copyright 2005 by Bochkanov Sergey
59192 : *************************************************************************/
59193 0 : ae_complex cmatrixludet(/* Complex */ ae_matrix* a,
59194 : /* Integer */ ae_vector* pivots,
59195 : ae_int_t n,
59196 : ae_state *_state)
59197 : {
59198 : ae_int_t i;
59199 : ae_int_t s;
59200 : ae_complex result;
59201 :
59202 :
59203 0 : ae_assert(n>=1, "CMatrixLUDet: N<1!", _state);
59204 0 : ae_assert(pivots->cnt>=n, "CMatrixLUDet: Pivots array is too short!", _state);
59205 0 : ae_assert(a->rows>=n, "CMatrixLUDet: rows(A)<N!", _state);
59206 0 : ae_assert(a->cols>=n, "CMatrixLUDet: cols(A)<N!", _state);
59207 0 : ae_assert(apservisfinitecmatrix(a, n, n, _state), "CMatrixLUDet: A contains infinite or NaN values!", _state);
59208 0 : result = ae_complex_from_i(1);
59209 0 : s = 1;
59210 0 : for(i=0; i<=n-1; i++)
59211 : {
59212 0 : result = ae_c_mul(result,a->ptr.pp_complex[i][i]);
59213 0 : if( pivots->ptr.p_int[i]!=i )
59214 : {
59215 0 : s = -s;
59216 : }
59217 : }
59218 0 : result = ae_c_mul_d(result,(double)(s));
59219 0 : return result;
59220 : }
59221 :
59222 :
59223 : /*************************************************************************
59224 : Calculation of the determinant of a general matrix
59225 :
59226 : Input parameters:
59227 : A - matrix, array[0..N-1, 0..N-1]
59228 : N - (optional) size of matrix A:
59229 : * if given, only principal NxN submatrix is processed and
59230 : overwritten. other elements are unchanged.
59231 : * if not given, automatically determined from matrix size
59232 : (A must be square matrix)
59233 :
59234 : Result: determinant of matrix A.
59235 :
59236 : -- ALGLIB --
59237 : Copyright 2005 by Bochkanov Sergey
59238 : *************************************************************************/
59239 0 : ae_complex cmatrixdet(/* Complex */ ae_matrix* a,
59240 : ae_int_t n,
59241 : ae_state *_state)
59242 : {
59243 : ae_frame _frame_block;
59244 : ae_matrix _a;
59245 : ae_vector pivots;
59246 : ae_complex result;
59247 :
59248 0 : ae_frame_make(_state, &_frame_block);
59249 0 : memset(&_a, 0, sizeof(_a));
59250 0 : memset(&pivots, 0, sizeof(pivots));
59251 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
59252 0 : a = &_a;
59253 0 : ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
59254 :
59255 0 : ae_assert(n>=1, "CMatrixDet: N<1!", _state);
59256 0 : ae_assert(a->rows>=n, "CMatrixDet: rows(A)<N!", _state);
59257 0 : ae_assert(a->cols>=n, "CMatrixDet: cols(A)<N!", _state);
59258 0 : ae_assert(apservisfinitecmatrix(a, n, n, _state), "CMatrixDet: A contains infinite or NaN values!", _state);
59259 0 : cmatrixlu(a, n, n, &pivots, _state);
59260 0 : result = cmatrixludet(a, &pivots, n, _state);
59261 0 : ae_frame_leave(_state);
59262 0 : return result;
59263 : }
59264 :
59265 :
59266 : /*************************************************************************
59267 : Determinant calculation of the matrix given by the Cholesky decomposition.
59268 :
59269 : Input parameters:
59270 : A - Cholesky decomposition,
59271 : output of SMatrixCholesky subroutine.
59272 : N - (optional) size of matrix A:
59273 : * if given, only principal NxN submatrix is processed and
59274 : overwritten. other elements are unchanged.
59275 : * if not given, automatically determined from matrix size
59276 : (A must be square matrix)
59277 :
59278 : As the determinant is equal to the product of squares of diagonal elements,
59279 : it's not necessary to specify which triangle - lower or upper - the matrix
59280 : is stored in.
59281 :
59282 : Result:
59283 : matrix determinant.
59284 :
59285 : -- ALGLIB --
59286 : Copyright 2005-2008 by Bochkanov Sergey
59287 : *************************************************************************/
59288 0 : double spdmatrixcholeskydet(/* Real */ ae_matrix* a,
59289 : ae_int_t n,
59290 : ae_state *_state)
59291 : {
59292 : ae_int_t i;
59293 : ae_bool f;
59294 : double result;
59295 :
59296 :
59297 0 : ae_assert(n>=1, "SPDMatrixCholeskyDet: N<1!", _state);
59298 0 : ae_assert(a->rows>=n, "SPDMatrixCholeskyDet: rows(A)<N!", _state);
59299 0 : ae_assert(a->cols>=n, "SPDMatrixCholeskyDet: cols(A)<N!", _state);
59300 0 : f = ae_true;
59301 0 : for(i=0; i<=n-1; i++)
59302 : {
59303 0 : f = f&&ae_isfinite(a->ptr.pp_double[i][i], _state);
59304 : }
59305 0 : ae_assert(f, "SPDMatrixCholeskyDet: A contains infinite or NaN values!", _state);
59306 0 : result = (double)(1);
59307 0 : for(i=0; i<=n-1; i++)
59308 : {
59309 0 : result = result*ae_sqr(a->ptr.pp_double[i][i], _state);
59310 : }
59311 0 : return result;
59312 : }
59313 :
59314 :
59315 : /*************************************************************************
59316 : Determinant calculation of the symmetric positive definite matrix.
59317 :
59318 : Input parameters:
59319 : A - matrix. Array with elements [0..N-1, 0..N-1].
59320 : N - (optional) size of matrix A:
59321 : * if given, only principal NxN submatrix is processed and
59322 : overwritten. other elements are unchanged.
59323 : * if not given, automatically determined from matrix size
59324 : (A must be square matrix)
59325 : IsUpper - (optional) storage type:
59326 : * if True, symmetric matrix A is given by its upper
59327 : triangle, and the lower triangle isn't used/changed by
59328 : function
59329 : * if False, symmetric matrix A is given by its lower
59330 : triangle, and the upper triangle isn't used/changed by
59331 : function
59332 : * if not given, both lower and upper triangles must be
59333 : filled.
59334 :
59335 : Result:
59336 : determinant of matrix A.
59337 : If matrix A is not positive definite, exception is thrown.
59338 :
59339 : -- ALGLIB --
59340 : Copyright 2005-2008 by Bochkanov Sergey
59341 : *************************************************************************/
59342 0 : double spdmatrixdet(/* Real */ ae_matrix* a,
59343 : ae_int_t n,
59344 : ae_bool isupper,
59345 : ae_state *_state)
59346 : {
59347 : ae_frame _frame_block;
59348 : ae_matrix _a;
59349 : ae_bool b;
59350 : double result;
59351 :
59352 0 : ae_frame_make(_state, &_frame_block);
59353 0 : memset(&_a, 0, sizeof(_a));
59354 0 : ae_matrix_init_copy(&_a, a, _state, ae_true);
59355 0 : a = &_a;
59356 :
59357 0 : ae_assert(n>=1, "SPDMatrixDet: N<1!", _state);
59358 0 : ae_assert(a->rows>=n, "SPDMatrixDet: rows(A)<N!", _state);
59359 0 : ae_assert(a->cols>=n, "SPDMatrixDet: cols(A)<N!", _state);
59360 0 : ae_assert(isfinitertrmatrix(a, n, isupper, _state), "SPDMatrixDet: A contains infinite or NaN values!", _state);
59361 0 : b = spdmatrixcholesky(a, n, isupper, _state);
59362 0 : ae_assert(b, "SPDMatrixDet: A is not SPD!", _state);
59363 0 : result = spdmatrixcholeskydet(a, n, _state);
59364 0 : ae_frame_leave(_state);
59365 0 : return result;
59366 : }
59367 :
59368 :
59369 : #endif
59370 :
59371 : }
59372 :
|