linalg 1.8.2
A linear algebra library that provides a user-friendly interface to several BLAS and LAPACK routines.
Loading...
Searching...
No Matches
linalg_solve.f90
1! linalg_solve.f90
2
7submodule(linalg) linalg_solve
8 use blas
9 use lapack
10 implicit none
11contains
12! ******************************************************************************
13! TRIANGULAR MATRIX SOLUTION ROUTINES
14! ------------------------------------------------------------------------------
15 module subroutine solve_tri_mtx(lside, upper, trans, nounit, alpha, a, b, err)
16 ! Arguments
17 logical, intent(in) :: lside, upper, trans, nounit
18 real(real64), intent(in) :: alpha
19 real(real64), intent(in), dimension(:,:) :: a
20 real(real64), intent(inout), dimension(:,:) :: b
21 class(errors), intent(inout), optional, target :: err
22
23 ! Parameters
24 character :: side, uplo, transa, diag
25
26 ! Local Variables
27 integer(int32) :: m, n, nrowa
28 class(errors), pointer :: errmgr
29 type(errors), target :: deferr
30
31 ! Initialization
32 m = size(b, 1)
33 n = size(b, 2)
34 if (lside) then
35 nrowa = m
36 side = 'L'
37 else
38 nrowa = n
39 side = 'R'
40 end if
41 if (upper) then
42 uplo = 'U'
43 else
44 uplo = 'L'
45 end if
46 if (trans) then
47 transa = 'T'
48 else
49 transa = 'N'
50 end if
51 if (nounit) then
52 diag = 'N'
53 else
54 diag = 'U'
55 end if
56 if (present(err)) then
57 errmgr => err
58 else
59 errmgr => deferr
60 end if
61
62 ! Input Check - matrix A must be square
63 if (size(a, 1) /= nrowa .or. size(a, 2) /= nrowa) then
64 ! ERROR: A must be square
65 call errmgr%report_error("solve_tri_mtx", &
66 "The input matrix must be square.", la_array_size_error)
67 return
68 end if
69
70 ! Call DTRSM
71 call dtrsm(side, uplo, transa, diag, m, n, alpha, a, nrowa, b, m)
72 end subroutine
73
74! ------------------------------------------------------------------------------
75 module subroutine solve_tri_mtx_cmplx(lside, upper, trans, nounit, alpha, a, b, err)
76 ! Arguments
77 logical, intent(in) :: lside, upper, trans, nounit
78 complex(real64), intent(in) :: alpha
79 complex(real64), intent(in), dimension(:,:) :: a
80 complex(real64), intent(inout), dimension(:,:) :: b
81 class(errors), intent(inout), optional, target :: err
82
83 ! Parameters
84 character :: side, uplo, transa, diag
85
86 ! Local Variables
87 integer(int32) :: m, n, nrowa
88 class(errors), pointer :: errmgr
89 type(errors), target :: deferr
90
91 ! Initialization
92 m = size(b, 1)
93 n = size(b, 2)
94 if (lside) then
95 nrowa = m
96 side = 'L'
97 else
98 nrowa = n
99 side = 'R'
100 end if
101 if (upper) then
102 uplo = 'U'
103 else
104 uplo = 'L'
105 end if
106 if (trans) then
107 transa = 'C'
108 else
109 transa = 'N'
110 end if
111 if (nounit) then
112 diag = 'N'
113 else
114 diag = 'U'
115 end if
116 if (present(err)) then
117 errmgr => err
118 else
119 errmgr => deferr
120 end if
121
122 ! Input Check - matrix A must be square
123 if (size(a, 1) /= nrowa .or. size(a, 2) /= nrowa) then
124 ! ERROR: A must be square
125 call errmgr%report_error("solve_tri_mtx_cmplx", &
126 "The input matrix must be square.", la_array_size_error)
127 return
128 end if
129
130 ! Call ZTRSM
131 call ztrsm(side, uplo, transa, diag, m, n, alpha, a, nrowa, b, m)
132 end subroutine
133
134! ------------------------------------------------------------------------------
135 module subroutine solve_tri_vec(upper, trans, nounit, a, x, err)
136 ! Arguments
137 logical, intent(in) :: upper, trans, nounit
138 real(real64), intent(in), dimension(:,:) :: a
139 real(real64), intent(inout), dimension(:) :: x
140 class(errors), intent(inout), optional, target :: err
141
142 ! Parameters
143 real(real64), parameter :: zero = 0.0d0
144
145 ! Local Variables
146 character :: uplo, t, diag
147 integer(int32) :: n
148 class(errors), pointer :: errmgr
149 type(errors), target :: deferr
150
151 ! Initialization
152 n = size(a, 1)
153 if (upper) then
154 uplo = 'U'
155 else
156 uplo = 'L'
157 end if
158 if (trans) then
159 t = 'T'
160 else
161 t = 'N'
162 end if
163 if (nounit) then
164 diag = 'N'
165 else
166 diag = 'U'
167 end if
168 if (present(err)) then
169 errmgr => err
170 else
171 errmgr => deferr
172 end if
173
174 ! Input Check
175 if (size(a, 2) /= n) then
176 ! ERROR: A must be square
177 call errmgr%report_error("solve_tri_vec", &
178 "The input matrix must be square.", la_array_size_error)
179 return
180 else if (size(x) /= n) then
181 ! ERROR: Inner matrix dimensions must agree
182 call errmgr%report_error("solve_tri_vec", &
183 "The inner matrix dimensions must be equal.", &
184 la_array_size_error)
185 return
186 end if
187
188 ! Call DTRSV
189 call dtrsv(uplo, t, diag, n, a, n, x, 1)
190 end subroutine
191
192! ------------------------------------------------------------------------------
193 module subroutine solve_tri_vec_cmplx(upper, trans, nounit, a, x, err)
194 ! Arguments
195 logical, intent(in) :: upper, trans, nounit
196 complex(real64), intent(in), dimension(:,:) :: a
197 complex(real64), intent(inout), dimension(:) :: x
198 class(errors), intent(inout), optional, target :: err
199
200 ! Parameters
201 real(real64), parameter :: zero = 0.0d0
202
203 ! Local Variables
204 character :: uplo, t, diag
205 integer(int32) :: n
206 class(errors), pointer :: errmgr
207 type(errors), target :: deferr
208
209 ! Initialization
210 n = size(a, 1)
211 if (upper) then
212 uplo = 'U'
213 else
214 uplo = 'L'
215 end if
216 if (trans) then
217 t = 'C'
218 else
219 t = 'N'
220 end if
221 if (nounit) then
222 diag = 'N'
223 else
224 diag = 'U'
225 end if
226 if (present(err)) then
227 errmgr => err
228 else
229 errmgr => deferr
230 end if
231
232 ! Input Check
233 if (size(a, 2) /= n) then
234 ! ERROR: A must be square
235 call errmgr%report_error("solve_tri_vec_cmplx", &
236 "The input matrix must be square.", la_array_size_error)
237 return
238 else if (size(x) /= n) then
239 ! ERROR: Inner matrix dimensions must agree
240 call errmgr%report_error("solve_tri_vec_cmplx", &
241 "The inner matrix dimensions must be equal.", &
242 la_array_size_error)
243 return
244 end if
245
246 ! Call ZTRSV
247 call ztrsv(uplo, t, diag, n, a, n, x, 1)
248 end subroutine
249
250! ******************************************************************************
251! LU SOLUTION
252! ------------------------------------------------------------------------------
253 module subroutine solve_lu_mtx(a, ipvt, b, err)
254 ! Arguments
255 real(real64), intent(in), dimension(:,:) :: a
256 integer(int32), intent(in), dimension(:) :: ipvt
257 real(real64), intent(inout), dimension(:,:) :: b
258 class(errors), intent(inout), optional, target :: err
259
260 ! Local Variables
261 integer(int32) :: n, nrhs, flag
262 class(errors), pointer :: errmgr
263 type(errors), target :: deferr
264 character(len = :), allocatable :: errmsg
265
266 ! Initialization
267 n = size(a, 1)
268 nrhs = size(b, 2)
269 if (present(err)) then
270 errmgr => err
271 else
272 errmgr => deferr
273 end if
274
275 ! Input Check
276 flag = 0
277 if (size(a, 2) /= n) then
278 flag = 1
279 else if (size(ipvt) /= n) then
280 flag = 2
281 else if (size(b, 1) /= n) then
282 flag = 3
283 end if
284 if (flag /= 0) then
285 ! One of the input arrays is not sized correctly
286 allocate(character(len = 256) :: errmsg)
287 write(errmsg, 100) "Input number ", flag, &
288 " is not sized correctly."
289 call errmgr%report_error("solve_lu_mtx", trim(errmsg), &
290 la_array_size_error)
291 return
292 end if
293
294 ! Call DGETRS
295 call dgetrs("N", n, nrhs, a, n, ipvt, b, n, flag)
296
297 ! Formatting
298100 format(a, i0, a)
299 end subroutine
300
301! ------------------------------------------------------------------------------
302 module subroutine solve_lu_mtx_cmplx(a, ipvt, b, err)
303 ! Arguments
304 complex(real64), intent(in), dimension(:,:) :: a
305 integer(int32), intent(in), dimension(:) :: ipvt
306 complex(real64), intent(inout), dimension(:,:) :: b
307 class(errors), intent(inout), optional, target :: err
308
309 ! Local Variables
310 integer(int32) :: n, nrhs, flag
311 class(errors), pointer :: errmgr
312 type(errors), target :: deferr
313 character(len = :), allocatable :: errmsg
314
315 ! Initialization
316 n = size(a, 1)
317 nrhs = size(b, 2)
318 if (present(err)) then
319 errmgr => err
320 else
321 errmgr => deferr
322 end if
323
324 ! Input Check
325 flag = 0
326 if (size(a, 2) /= n) then
327 flag = 1
328 else if (size(ipvt) /= n) then
329 flag = 2
330 else if (size(b, 1) /= n) then
331 flag = 3
332 end if
333 if (flag /= 0) then
334 ! One of the input arrays is not sized correctly
335 allocate(character(len = 256) :: errmsg)
336 write(errmsg, 100) "Input number ", flag, &
337 " is not sized correctly."
338 call errmgr%report_error("solve_lu_mtx_cmplx", trim(errmsg), &
339 la_array_size_error)
340 return
341 end if
342
343 ! Call ZGETRS
344 call zgetrs("N", n, nrhs, a, n, ipvt, b, n, flag)
345
346 ! Formatting
347100 format(a, i0, a)
348 end subroutine
349
350! ------------------------------------------------------------------------------
351 module subroutine solve_lu_vec(a, ipvt, b, err)
352 ! Arguments
353 real(real64), intent(in), dimension(:,:) :: a
354 integer(int32), intent(in), dimension(:) :: ipvt
355 real(real64), intent(inout), dimension(:) :: b
356 class(errors), intent(inout), optional, target :: err
357
358 ! Local Variables
359 integer(int32) :: n, flag
360 class(errors), pointer :: errmgr
361 type(errors), target :: deferr
362 character(len = :), allocatable :: errmsg
363
364 ! Initialization
365 n = size(a, 1)
366 if (present(err)) then
367 errmgr => err
368 else
369 errmgr => deferr
370 end if
371
372 ! Input Check
373 flag = 0
374 if (size(a, 2) /= n) then
375 flag = 1
376 else if (size(ipvt) /= n) then
377 flag = 2
378 else if (size(b) /= n) then
379 flag = 3
380 end if
381 if (flag /= 0) then
382 ! One of the input arrays is not sized correctly
383 allocate(character(len = 256) :: errmsg)
384 write(errmsg, 100) "Input number ", flag, &
385 " is not sized correctly."
386 call errmgr%report_error("solve_lu_vec", trim(errmsg), &
387 la_array_size_error)
388 return
389 end if
390
391 ! Call DGETRS
392 call dgetrs("N", n, 1, a, n, ipvt, b, n, flag)
393
394 ! Formatting
395100 format(a, i0, a)
396 end subroutine
397
398! ------------------------------------------------------------------------------
399 module subroutine solve_lu_vec_cmplx(a, ipvt, b, err)
400 ! Arguments
401 complex(real64), intent(in), dimension(:,:) :: a
402 integer(int32), intent(in), dimension(:) :: ipvt
403 complex(real64), intent(inout), dimension(:) :: b
404 class(errors), intent(inout), optional, target :: err
405
406 ! Local Variables
407 integer(int32) :: n, flag
408 class(errors), pointer :: errmgr
409 type(errors), target :: deferr
410 character(len = :), allocatable :: errmsg
411
412 ! Initialization
413 n = size(a, 1)
414 if (present(err)) then
415 errmgr => err
416 else
417 errmgr => deferr
418 end if
419
420 ! Input Check
421 flag = 0
422 if (size(a, 2) /= n) then
423 flag = 1
424 else if (size(ipvt) /= n) then
425 flag = 2
426 else if (size(b) /= n) then
427 flag = 3
428 end if
429 if (flag /= 0) then
430 ! One of the input arrays is not sized correctly
431 allocate(character(len = 256) :: errmsg)
432 write(errmsg, 100) "Input number ", flag, &
433 " is not sized correctly."
434 call errmgr%report_error("solve_lu_vec_cmplx", trim(errmsg), &
435 la_array_size_error)
436 return
437 end if
438
439 ! Call ZGETRS
440 call zgetrs("N", n, 1, a, n, ipvt, b, n, flag)
441
442 ! Formatting
443100 format(a, i0, a)
444 end subroutine
445
446! ******************************************************************************
447! QR SOLUTION
448! ------------------------------------------------------------------------------
449 module subroutine solve_qr_no_pivot_mtx(a, tau, b, work, olwork, err)
450 ! Arguments
451 real(real64), intent(inout), dimension(:,:) :: a, b
452 real(real64), intent(in), dimension(:) :: tau
453 real(real64), intent(out), target, optional, dimension(:) :: work
454 integer(int32), intent(out), optional :: olwork
455 class(errors), intent(inout), optional, target :: err
456
457 ! Parameters
458 real(real64), parameter :: one = 1.0d0
459
460 ! Local Variables
461 integer(int32) :: m, n, nrhs, k, lwork, flag, istat
462 real(real64), pointer, dimension(:) :: wptr
463 real(real64), allocatable, target, dimension(:) :: wrk
464 class(errors), pointer :: errmgr
465 type(errors), target :: deferr
466 character(len = :), allocatable :: errmsg
467
468 ! Initialization
469 m = size(a, 1)
470 n = size(a, 2)
471 nrhs = size(b, 2)
472 k = min(m, n)
473 if (present(err)) then
474 errmgr => err
475 else
476 errmgr => deferr
477 end if
478
479 ! Input Check
480 flag = 0
481 if (m < n) then
482 flag = 1
483 else if (size(tau) /= k) then
484 flag = 2
485 else if (size(b, 1) /= m) then
486 flag = 3
487 end if
488 if (flag /= 0) then
489 ! ERROR: One of the input arrays is not sized correctly
490 allocate(character(len = 256) :: errmsg)
491 write(errmsg, 100) "Input number ", flag, &
492 " is not sized correctly."
493 call errmgr%report_error("solve_qr_no_pivot_mtx", trim(errmsg), &
494 la_array_size_error)
495 return
496 end if
497
498 ! Workspace Query
499 call mult_qr(.true., .true., a, tau, b, olwork = lwork)
500 if (present(olwork)) then
501 olwork = lwork
502 return
503 end if
504
505 ! Local Memory Allocation
506 if (present(work)) then
507 if (size(work) < lwork) then
508 ! ERROR: WORK not sized correctly
509 call errmgr%report_error("solve_qr_no_pivot_mtx", &
510 "Incorrectly sized input array WORK, argument 4.", &
511 la_array_size_error)
512 return
513 end if
514 wptr => work(1:lwork)
515 else
516 allocate(wrk(lwork), stat = istat)
517 if (istat /= 0) then
518 ! ERROR: Out of memory
519 call errmgr%report_error("solve_qr_no_pivot_mtx", &
520 "Insufficient memory available.", &
521 la_out_of_memory_error)
522 return
523 end if
524 wptr => wrk
525 end if
526
527 ! Compute Q**T * B, and store in B
528 call mult_qr(.true., .true., a, tau, b, wptr)
529
530 ! Solve the triangular system: A(1:N,1:N)*X = B(1:N,:)
531 call solve_triangular_system(.true., .true., .false., .true., one, &
532 a(1:n,1:n), b(1:n,:))
533
534 ! Formatting
535100 format(a, i0, a)
536 end subroutine
537
538! ------------------------------------------------------------------------------
539 module subroutine solve_qr_no_pivot_mtx_cmplx(a, tau, b, work, olwork, err)
540 ! Arguments
541 complex(real64), intent(inout), dimension(:,:) :: a, b
542 complex(real64), intent(in), dimension(:) :: tau
543 complex(real64), intent(out), target, optional, dimension(:) :: work
544 integer(int32), intent(out), optional :: olwork
545 class(errors), intent(inout), optional, target :: err
546
547 ! Parameters
548 complex(real64), parameter :: one = (1.0d0, 0.0d0)
549
550 ! Local Variables
551 integer(int32) :: m, n, nrhs, k, lwork, flag, istat
552 complex(real64), pointer, dimension(:) :: wptr
553 complex(real64), allocatable, target, dimension(:) :: wrk
554 class(errors), pointer :: errmgr
555 type(errors), target :: deferr
556 character(len = :), allocatable :: errmsg
557
558 ! Initialization
559 m = size(a, 1)
560 n = size(a, 2)
561 nrhs = size(b, 2)
562 k = min(m, n)
563 if (present(err)) then
564 errmgr => err
565 else
566 errmgr => deferr
567 end if
568
569 ! Input Check
570 flag = 0
571 if (m < n) then
572 flag = 1
573 else if (size(tau) /= k) then
574 flag = 2
575 else if (size(b, 1) /= m) then
576 flag = 3
577 end if
578 if (flag /= 0) then
579 ! ERROR: One of the input arrays is not sized correctly
580 allocate(character(len = 256) :: errmsg)
581 write(errmsg, 100) "Input number ", flag, &
582 " is not sized correctly."
583 call errmgr%report_error("solve_qr_no_pivot_mtx_cmplx", &
584 trim(errmsg), la_array_size_error)
585 return
586 end if
587
588 ! Workspace Query
589 call mult_qr(.true., .true., a, tau, b, olwork = lwork)
590 if (present(olwork)) then
591 olwork = lwork
592 return
593 end if
594
595 ! Local Memory Allocation
596 if (present(work)) then
597 if (size(work) < lwork) then
598 ! ERROR: WORK not sized correctly
599 call errmgr%report_error("solve_qr_no_pivot_mtx_cmplx", &
600 "Incorrectly sized input array WORK, argument 4.", &
601 la_array_size_error)
602 return
603 end if
604 wptr => work(1:lwork)
605 else
606 allocate(wrk(lwork), stat = istat)
607 if (istat /= 0) then
608 ! ERROR: Out of memory
609 call errmgr%report_error("solve_qr_no_pivot_mtx_cmplx", &
610 "Insufficient memory available.", &
611 la_out_of_memory_error)
612 return
613 end if
614 wptr => wrk
615 end if
616
617 ! Compute Q**T * B, and store in B
618 call mult_qr(.true., .true., a, tau, b, wptr)
619
620 ! Solve the triangular system: A(1:N,1:N)*X = B(1:N,:)
621 call solve_triangular_system(.true., .true., .false., .true., one, &
622 a(1:n,1:n), b(1:n,:))
623
624 ! Formatting
625100 format(a, i0, a)
626 end subroutine
627
628! ------------------------------------------------------------------------------
629 module subroutine solve_qr_no_pivot_vec(a, tau, b, work, olwork, err)
630 ! Arguments
631 real(real64), intent(inout), dimension(:,:) :: a
632 real(real64), intent(in), dimension(:) :: tau
633 real(real64), intent(inout), dimension(:) :: b
634 real(real64), intent(out), target, optional, dimension(:) :: work
635 integer(int32), intent(out), optional :: olwork
636 class(errors), intent(inout), optional, target :: err
637
638 ! Local Variables
639 integer(int32) :: m, n, k, flag, lwork, istat
640 real(real64), pointer, dimension(:) :: wptr
641 real(real64), allocatable, target, dimension(:) :: wrk
642 class(errors), pointer :: errmgr
643 type(errors), target :: deferr
644 character(len = :), allocatable :: errmsg
645
646 ! Initialization
647 m = size(a, 1)
648 n = size(a, 2)
649 k = min(m, n)
650 if (present(err)) then
651 errmgr => err
652 else
653 errmgr => deferr
654 end if
655
656 ! Input Check
657 flag = 0
658 if (m < n) then
659 flag = 1
660 else if (size(tau) /= k) then
661 flag = 2
662 else if (size(b) /= m) then
663 flag = 3
664 end if
665 if (flag /= 0) then
666 ! ERROR: One of the input arrays is not sized correctly
667 allocate(character(len = 256) :: errmsg)
668 write(errmsg, 100) "Input number ", flag, &
669 " is not sized correctly."
670 call errmgr%report_error("solve_qr_no_pivot_vec", trim(errmsg), &
671 la_array_size_error)
672 return
673 end if
674
675 ! Workspace Query
676 call mult_qr(.true., a, tau, b, olwork = lwork)
677 if (present(olwork)) then
678 olwork = lwork
679 return
680 end if
681
682 ! Local Memory Allocation
683 if (present(work)) then
684 if (size(work) < lwork) then
685 ! ERROR: WORK not sized correctly
686 call errmgr%report_error("solve_qr_no_pivot_vec", &
687 "Incorrectly sized input array WORK, argument 4.", &
688 la_array_size_error)
689 return
690 end if
691 wptr => work(1:lwork)
692 else
693 allocate(wrk(lwork), stat = istat)
694 if (istat /= 0) then
695 ! ERROR: Out of memory
696 call errmgr%report_error("solve_qr_no_pivot_vec", &
697 "Insufficient memory available.", &
698 la_out_of_memory_error)
699 return
700 end if
701 wptr => wrk
702 end if
703
704 ! Compute Q**T * B, and store in B
705 call mult_qr(.true., a, tau, b, work = wptr)
706
707 ! Solve the triangular system: A(1:N,1:N)*X = B(1:N)
708 call solve_triangular_system(.true., .false., .true., a(1:n,1:n), b)
709
710 ! Formatting
711100 format(a, i0, a)
712 end subroutine
713
714! ------------------------------------------------------------------------------
715 module subroutine solve_qr_no_pivot_vec_cmplx(a, tau, b, work, olwork, err)
716 ! Arguments
717 complex(real64), intent(inout), dimension(:,:) :: a
718 complex(real64), intent(in), dimension(:) :: tau
719 complex(real64), intent(inout), dimension(:) :: b
720 complex(real64), intent(out), target, optional, dimension(:) :: work
721 integer(int32), intent(out), optional :: olwork
722 class(errors), intent(inout), optional, target :: err
723
724 ! Local Variables
725 integer(int32) :: m, n, k, flag, lwork, istat
726 complex(real64), pointer, dimension(:) :: wptr
727 complex(real64), allocatable, target, dimension(:) :: wrk
728 class(errors), pointer :: errmgr
729 type(errors), target :: deferr
730 character(len = :), allocatable :: errmsg
731
732 ! Initialization
733 m = size(a, 1)
734 n = size(a, 2)
735 k = min(m, n)
736 if (present(err)) then
737 errmgr => err
738 else
739 errmgr => deferr
740 end if
741
742 ! Input Check
743 flag = 0
744 if (m < n) then
745 flag = 1
746 else if (size(tau) /= k) then
747 flag = 2
748 else if (size(b) /= m) then
749 flag = 3
750 end if
751 if (flag /= 0) then
752 ! ERROR: One of the input arrays is not sized correctly
753 allocate(character(len = 256) :: errmsg)
754 write(errmsg, 100) "Input number ", flag, &
755 " is not sized correctly."
756 call errmgr%report_error("solve_qr_no_pivot_vec_cmplx", &
757 trim(errmsg), la_array_size_error)
758 return
759 end if
760
761 ! Workspace Query
762 call mult_qr(.true., a, tau, b, olwork = lwork)
763 if (present(olwork)) then
764 olwork = lwork
765 return
766 end if
767
768 ! Local Memory Allocation
769 if (present(work)) then
770 if (size(work) < lwork) then
771 ! ERROR: WORK not sized correctly
772 call errmgr%report_error("solve_qr_no_pivot_vec_cmplx", &
773 "Incorrectly sized input array WORK, argument 4.", &
774 la_array_size_error)
775 return
776 end if
777 wptr => work(1:lwork)
778 else
779 allocate(wrk(lwork), stat = istat)
780 if (istat /= 0) then
781 ! ERROR: Out of memory
782 call errmgr%report_error("solve_qr_no_pivot_vec_cmplx", &
783 "Insufficient memory available.", &
784 la_out_of_memory_error)
785 return
786 end if
787 wptr => wrk
788 end if
789
790 ! Compute Q**T * B, and store in B
791 call mult_qr(.true., a, tau, b, work = wptr)
792
793 ! Solve the triangular system: A(1:N,1:N)*X = B(1:N)
794 call solve_triangular_system(.true., .false., .true., a(1:n,1:n), b)
795
796 ! Formatting
797100 format(a, i0, a)
798 end subroutine
799
800! ------------------------------------------------------------------------------
801 module subroutine solve_qr_pivot_mtx(a, tau, jpvt, b, work, olwork, err)
802 ! Arguments
803 real(real64), intent(inout), dimension(:,:) :: a
804 real(real64), intent(in), dimension(:) :: tau
805 integer(int32), intent(in), dimension(:) :: jpvt
806 real(real64), intent(inout), dimension(:,:) :: b
807 real(real64), intent(out), target, optional, dimension(:) :: work
808 integer(int32), intent(out), optional :: olwork
809 class(errors), intent(inout), optional, target :: err
810
811 ! Parameters
812 integer(int32), parameter :: imin = 2
813 integer(int32), parameter :: imax = 1
814 real(real64), parameter :: zero = 0.0d0
815 real(real64), parameter :: one = 1.0d0
816
817 ! Local Variables
818 integer(int32) :: i, j, m, n, mn, nrhs, lwork, ismin, ismax, &
819 rnk, maxmn, flag, istat, lwork1, lwork2, lwork3
820 real(real64) :: rcond, smax, smin, smaxpr, sminpr, s1, c1, s2, c2
821 real(real64), pointer, dimension(:) :: wptr, w, tau2
822 real(real64), allocatable, target, dimension(:) :: wrk
823 class(errors), pointer :: errmgr
824 type(errors), target :: deferr
825 character(len = :), allocatable :: errmsg
826
827 ! Initialization
828 m = size(a, 1)
829 n = size(a, 2)
830 mn = min(m, n)
831 maxmn = max(m, n)
832 nrhs = size(b, 2)
833 ismin = mn + 1
834 ismax = 2 * mn + 1
835 rcond = epsilon(rcond)
836 if (present(err)) then
837 errmgr => err
838 else
839 errmgr => deferr
840 end if
841
842 ! Input Check
843 flag = 0
844 if (size(tau) /= mn) then
845 flag = 2
846 else if (size(jpvt) /= n) then
847 flag = 3
848 else if (size(b, 1) /= maxmn) then
849 flag = 4
850 end if
851 if (flag /= 0) then
852 ! ERROR: One of the input arrays is not sized correctly
853 allocate(character(len = 256) :: errmsg)
854 write(errmsg, 100) "Input number ", flag, &
855 " is not sized correctly."
856 call errmgr%report_error("solve_qr_pivot_mtx", trim(errmsg), &
857 la_array_size_error)
858 return
859 end if
860
861 ! Workspace Query
862 call rz_factor(a(1:mn,:), a(1:mn,1), olwork = lwork1)
863 call mult_qr(.true., .true., a, tau, b(1:m,:), olwork = lwork2)
864 call mult_rz(.true., .true., n, a(1:mn,:), a(1:mn,1), b(1:n,:), &
865 olwork = lwork3)
866 lwork = max(lwork1, lwork2, lwork3, 2 * mn + 1) + mn
867 if (present(olwork)) then
868 olwork = lwork
869 return
870 end if
871
872 ! Local Memory Allocation
873 if (present(work)) then
874 if (size(work) < lwork) then
875 ! ERROR: WORK not sized correctly
876 call errmgr%report_error("solve_qr_no_pivot_mtx", &
877 "Incorrectly sized input array WORK, argument 5.", &
878 la_array_size_error)
879 return
880 end if
881 wptr => work(1:lwork)
882 else
883 allocate(wrk(lwork), stat = istat)
884 if (istat /= 0) then
885 ! ERROR: Out of memory
886 call errmgr%report_error("solve_qr_pivot_mtx", &
887 "Insufficient memory available.", &
888 la_out_of_memory_error)
889 return
890 end if
891 wptr => wrk
892 end if
893
894 ! Determine the rank of R11 using an incremental condition estimation
895 wptr(ismin) = one
896 wptr(ismax) = one
897 smax = abs(a(1,1))
898 smin = smax
899 if (abs(a(1,1)) == zero) then
900 rnk = 0
901 b(1:maxmn,:) = zero
902 return
903 else
904 rnk = 1
905 end if
906 do
907 if (rnk < mn) then
908 i = rnk + 1
909 call dlaic1(imin, rnk, wptr(ismin:ismin+rnk-1), smin, &
910 a(1:rnk-1,i), a(i,i), sminpr, s1, c1)
911 call dlaic1(imax, rnk, wptr(ismax:ismax+rnk-1), smax, &
912 a(1:rnk-1,i), a(i,i), smaxpr, s2, c2)
913 if (smaxpr * rcond <= sminpr) then
914 do i = 1, rnk
915 wptr(ismin+i-1) = s1 * wptr(ismin+i-1)
916 wptr(ismax+i-1) = s2 * wptr(ismax+i-1)
917 end do
918 wptr(ismin+rnk) = c1
919 wptr(ismax+rnk) = c2
920 smin = sminpr
921 smax = smaxpr
922 rnk = rnk + 1
923 cycle
924 end if
925 end if
926 exit
927 end do
928
929 ! Partition R = [R11 R12]
930 ! [ 0 R22]
931 tau2 => wptr(1:rnk)
932 w => wptr(rnk+1:lwork)
933 if (rnk < n) call rz_factor(a(1:rnk,:), tau2, w)
934
935 ! Compute B(1:m,1:NRHS) = Q**T * B(1:M,1:NRHS)
936 call mult_qr(.true., .true., a, tau, b(1:m,:), w)
937
938 ! Solve the triangular system T11 * B(1:rnk,1:nrhs) = B(1:rnk,1:nrhs)
939 call solve_triangular_system(.true., .true., .false., .true., one, &
940 a(1:rnk,1:rnk), b(1:rnk,:))
941 if (n > rnk) b(rnk+1:n,:) = zero
942
943 ! Compute B(1:n,1:nrhs) = Y**T * B(1:n,1:nrhs)
944 if (rnk < n) then
945 call mult_rz(.true., .true., n - rnk, a(1:rnk,:), tau2, b(1:n,:), w)
946 end if
947
948 ! Apply the pivoting: B(1:N,1:NRHS) = P * B(1:N,1:NRHS)
949 do j = 1, nrhs
950 do i = 1, n
951 wptr(jpvt(i)) = b(i,j)
952 end do
953 b(1:n,j) = wptr(1:n)
954 end do
955
956 ! Formatting
957100 format(a, i0, a)
958 end subroutine
959
960! ------------------------------------------------------------------------------
961 module subroutine solve_qr_pivot_mtx_cmplx(a, tau, jpvt, b, work, olwork, err)
962 ! Arguments
963 complex(real64), intent(inout), dimension(:,:) :: a
964 complex(real64), intent(in), dimension(:) :: tau
965 integer(int32), intent(in), dimension(:) :: jpvt
966 complex(real64), intent(inout), dimension(:,:) :: b
967 complex(real64), intent(out), target, optional, dimension(:) :: work
968 integer(int32), intent(out), optional :: olwork
969 class(errors), intent(inout), optional, target :: err
970
971 ! Parameters
972 integer(int32), parameter :: imin = 2
973 integer(int32), parameter :: imax = 1
974 complex(real64), parameter :: zero = (0.0d0, 0.0d0)
975 complex(real64), parameter :: one = (1.0d0, 0.0d0)
976
977 ! Local Variables
978 integer(int32) :: i, j, m, n, mn, nrhs, lwork, ismin, ismax, &
979 rnk, maxmn, flag, istat, lwork1, lwork2, lwork3
980 real(real64) :: rcond, smax, smin, smaxpr, sminpr
981 complex(real64) :: s1, c1, s2, c2
982 complex(real64), pointer, dimension(:) :: wptr, w, tau2
983 complex(real64), allocatable, target, dimension(:) :: wrk
984 class(errors), pointer :: errmgr
985 type(errors), target :: deferr
986 character(len = :), allocatable :: errmsg
987
988 ! Initialization
989 m = size(a, 1)
990 n = size(a, 2)
991 mn = min(m, n)
992 maxmn = max(m, n)
993 nrhs = size(b, 2)
994 ismin = mn + 1
995 ismax = 2 * mn + 1
996 rcond = epsilon(rcond)
997 if (present(err)) then
998 errmgr => err
999 else
1000 errmgr => deferr
1001 end if
1002
1003 ! Input Check
1004 flag = 0
1005 if (size(tau) /= mn) then
1006 flag = 2
1007 else if (size(jpvt) /= n) then
1008 flag = 3
1009 else if (size(b, 1) /= maxmn) then
1010 flag = 4
1011 end if
1012 if (flag /= 0) then
1013 ! ERROR: One of the input arrays is not sized correctly
1014 allocate(character(len = 256) :: errmsg)
1015 write(errmsg, 100) "Input number ", flag, &
1016 " is not sized correctly."
1017 call errmgr%report_error("solve_qr_pivot_mtx_cmplx", &
1018 trim(errmsg), la_array_size_error)
1019 return
1020 end if
1021
1022 ! Workspace Query
1023 call rz_factor(a(1:mn,:), a(1:mn,1), olwork = lwork1)
1024 call mult_qr(.true., .true., a, tau, b(1:m,:), olwork = lwork2)
1025 call mult_rz(.true., .true., n, a(1:mn,:), a(1:mn,1), b(1:n,:), &
1026 olwork = lwork3)
1027 lwork = max(lwork1, lwork2, lwork3, 2 * mn + 1) + mn
1028 if (present(olwork)) then
1029 olwork = lwork
1030 return
1031 end if
1032
1033 ! Local Memory Allocation
1034 if (present(work)) then
1035 if (size(work) < lwork) then
1036 ! ERROR: WORK not sized correctly
1037 call errmgr%report_error("solve_qr_no_pivot_mtx_cmplx", &
1038 "Incorrectly sized input array WORK, argument 5.", &
1039 la_array_size_error)
1040 return
1041 end if
1042 wptr => work(1:lwork)
1043 else
1044 allocate(wrk(lwork), stat = istat)
1045 if (istat /= 0) then
1046 ! ERROR: Out of memory
1047 call errmgr%report_error("solve_qr_pivot_mtx_cmplx", &
1048 "Insufficient memory available.", &
1049 la_out_of_memory_error)
1050 return
1051 end if
1052 wptr => wrk
1053 end if
1054
1055 ! Determine the rank of R11 using an incremental condition estimation
1056 wptr(ismin) = one
1057 wptr(ismax) = one
1058 smax = abs(a(1,1))
1059 smin = smax
1060 if (abs(a(1,1)) == zero) then
1061 rnk = 0
1062 b(1:maxmn,:) = zero
1063 return
1064 else
1065 rnk = 1
1066 end if
1067 do
1068 if (rnk < mn) then
1069 i = rnk + 1
1070 call zlaic1(imin, rnk, wptr(ismin:ismin+rnk-1), smin, &
1071 a(1:rnk-1,i), a(i,i), sminpr, s1, c1)
1072 call zlaic1(imax, rnk, wptr(ismax:ismax+rnk-1), smax, &
1073 a(1:rnk-1,i), a(i,i), smaxpr, s2, c2)
1074 if (smaxpr * rcond <= sminpr) then
1075 do i = 1, rnk
1076 wptr(ismin+i-1) = s1 * wptr(ismin+i-1)
1077 wptr(ismax+i-1) = s2 * wptr(ismax+i-1)
1078 end do
1079 wptr(ismin+rnk) = c1
1080 wptr(ismax+rnk) = c2
1081 smin = sminpr
1082 smax = smaxpr
1083 rnk = rnk + 1
1084 cycle
1085 end if
1086 end if
1087 exit
1088 end do
1089
1090 ! Partition R = [R11 R12]
1091 ! [ 0 R22]
1092 tau2 => wptr(1:rnk)
1093 w => wptr(rnk+1:lwork)
1094 if (rnk < n) call rz_factor(a(1:rnk,:), tau2, w)
1095
1096 ! Compute B(1:m,1:NRHS) = Q**T * B(1:M,1:NRHS)
1097 call mult_qr(.true., .true., a, tau, b(1:m,:), w)
1098
1099 ! Solve the triangular system T11 * B(1:rnk,1:nrhs) = B(1:rnk,1:nrhs)
1100 call solve_triangular_system(.true., .true., .false., .true., one, &
1101 a(1:rnk,1:rnk), b(1:rnk,:))
1102 if (n > rnk) b(rnk+1:n,:) = zero
1103
1104 ! Compute B(1:n,1:nrhs) = Y**T * B(1:n,1:nrhs)
1105 if (rnk < n) then
1106 call mult_rz(.true., .true., n - rnk, a(1:rnk,:), tau2, b(1:n,:), w)
1107 end if
1108
1109 ! Apply the pivoting: B(1:N,1:NRHS) = P * B(1:N,1:NRHS)
1110 do j = 1, nrhs
1111 do i = 1, n
1112 wptr(jpvt(i)) = b(i,j)
1113 end do
1114 b(1:n,j) = wptr(1:n)
1115 end do
1116
1117 ! Formatting
1118100 format(a, i0, a)
1119 end subroutine
1120
1121! ------------------------------------------------------------------------------
1122 module subroutine solve_qr_pivot_vec(a, tau, jpvt, b, work, olwork, err)
1123 ! Arguments
1124 real(real64), intent(inout), dimension(:,:) :: a
1125 real(real64), intent(in), dimension(:) :: tau
1126 integer(int32), intent(in), dimension(:) :: jpvt
1127 real(real64), intent(inout), dimension(:) :: b
1128 real(real64), intent(out), target, optional, dimension(:) :: work
1129 integer(int32), intent(out), optional :: olwork
1130 class(errors), intent(inout), optional, target :: err
1131
1132 ! Parameters
1133 integer(int32), parameter :: imin = 2
1134 integer(int32), parameter :: imax = 1
1135 real(real64), parameter :: zero = 0.0d0
1136 real(real64), parameter :: one = 1.0d0
1137
1138 ! Local Variables
1139 integer(int32) :: i, m, n, mn, lwork, ismin, ismax, rnk, maxmn, flag, &
1140 istat, lwork1, lwork2
1141 real(real64) :: rcond, smax, smin, smaxpr, sminpr, s1, c1, s2, c2
1142 real(real64), pointer, dimension(:) :: wptr, w, tau2
1143 real(real64), allocatable, target, dimension(:) :: wrk
1144 class(errors), pointer :: errmgr
1145 type(errors), target :: deferr
1146 character(len = :), allocatable :: errmsg
1147
1148 ! Initialization
1149 m = size(a, 1)
1150 n = size(a, 2)
1151 mn = min(m, n)
1152 maxmn = max(m, n)
1153 ismin = mn + 1
1154 ismax = 2 * mn + 1
1155 rcond = epsilon(rcond)
1156 if (present(err)) then
1157 errmgr => err
1158 else
1159 errmgr => deferr
1160 end if
1161
1162 ! Input Check
1163 flag = 0
1164 if (size(tau) /= mn) then
1165 flag = 2
1166 else if (size(jpvt) /= n) then
1167 flag = 3
1168 else if (size(b) /= maxmn) then
1169 flag = 4
1170 end if
1171 if (flag /= 0) then
1172 ! ERROR: One of the input arrays is not sized correctly
1173 allocate(character(len = 256) :: errmsg)
1174 write(errmsg, 100) "Input number ", flag, &
1175 " is not sized correctly."
1176 call errmgr%report_error("solve_qr_pivot_vec", trim(errmsg), &
1177 la_array_size_error)
1178 return
1179 end if
1180
1181 ! Workspace Query
1182 call rz_factor(a(1:mn,:), a(1:mn,1), olwork = lwork1)
1183 call mult_rz(.true., n, a(1:mn,:), a(1:mn,1), b(1:n), olwork = lwork2)
1184 lwork = max(lwork1, lwork2, 2 * mn + 1) + mn
1185 if (present(olwork)) then
1186 olwork = lwork
1187 return
1188 end if
1189
1190 ! Local Memory Allocation
1191 if (present(work)) then
1192 if (size(work) < lwork) then
1193 ! ERROR: WORK not sized correctly
1194 call errmgr%report_error("solve_qr_no_pivot_mtx", &
1195 "Incorrectly sized input array WORK, argument 5.", &
1196 la_array_size_error)
1197 return
1198 end if
1199 wptr => work(1:lwork)
1200 else
1201 allocate(wrk(lwork), stat = istat)
1202 if (istat /= 0) then
1203 ! ERROR: Out of memory
1204 call errmgr%report_error("solve_qr_pivot_vec", &
1205 "Insufficient memory available.", &
1206 la_out_of_memory_error)
1207 return
1208 end if
1209 wptr => wrk
1210 end if
1211
1212 ! Determine the rank of R11 using an incremental condition estimation
1213 wptr(ismin) = one
1214 wptr(ismax) = one
1215 smax = abs(a(1,1))
1216 smin = smax
1217 if (abs(a(1,1)) == zero) then
1218 rnk = 0
1219 b(maxmn) = zero
1220 return
1221 else
1222 rnk = 1
1223 end if
1224 do
1225 if (rnk < mn) then
1226 i = rnk + 1
1227 call dlaic1(imin, rnk, wptr(ismin:ismin+rnk-1), smin, &
1228 a(1:rnk-1,i), a(i,i), sminpr, s1, c1)
1229 call dlaic1(imax, rnk, wptr(ismax:ismax+rnk-1), smax, &
1230 a(1:rnk-1,i), a(i,i), smaxpr, s2, c2)
1231 if (smaxpr * rcond <= sminpr) then
1232 do i = 1, rnk
1233 wptr(ismin+i-1) = s1 * wptr(ismin+i-1)
1234 wptr(ismax+i-1) = s2 * wptr(ismax+i-1)
1235 end do
1236 wptr(ismin+rnk) = c1
1237 wptr(ismax+rnk) = c2
1238 smin = sminpr
1239 smax = smaxpr
1240 rnk = rnk + 1
1241 cycle
1242 end if
1243 end if
1244 exit
1245 end do
1246
1247 ! Partition R = [R11 R12]
1248 ! [ 0 R22]
1249 tau2 => wptr(1:rnk)
1250 w => wptr(rnk+1:lwork)
1251 if (rnk < n) call rz_factor(a(1:rnk,:), tau2, w)
1252
1253 ! Compute B(1:m,1:NRHS) = Q**T * B(1:M,1:NRHS)
1254 call mult_qr(.true., a, tau, b(1:m))
1255
1256 ! Solve the triangular system T11 * B(1:rnk) = B(1:rnk)
1257 call solve_triangular_system(.true., .false., .true., a(1:rnk,1:rnk), &
1258 b(1:rnk))
1259 if (n > rnk) b(rnk+1:n) = zero
1260
1261 ! Compute B(1:n) = Y**T * B(1:n)
1262 if (rnk < n) then
1263 call mult_rz(.true., n - rnk, a(1:rnk,:), tau2, b(1:n), w)
1264 end if
1265
1266 ! Apply the pivoting: B(1:N) = P * B(1:N)
1267 do i = 1, n
1268 wptr(jpvt(i)) = b(i)
1269 end do
1270 b = wptr(1:n)
1271
1272 ! Formatting
1273100 format(a, i0, a)
1274 end subroutine
1275
1276! ------------------------------------------------------------------------------
1277 module subroutine solve_qr_pivot_vec_cmplx(a, tau, jpvt, b, work, olwork, err)
1278 ! Arguments
1279 complex(real64), intent(inout), dimension(:,:) :: a
1280 complex(real64), intent(in), dimension(:) :: tau
1281 integer(int32), intent(in), dimension(:) :: jpvt
1282 complex(real64), intent(inout), dimension(:) :: b
1283 complex(real64), intent(out), target, optional, dimension(:) :: work
1284 integer(int32), intent(out), optional :: olwork
1285 class(errors), intent(inout), optional, target :: err
1286
1287 ! Parameters
1288 integer(int32), parameter :: imin = 2
1289 integer(int32), parameter :: imax = 1
1290 complex(real64), parameter :: zero = (0.0d0, 0.0d0)
1291 complex(real64), parameter :: one = (1.0d0, 0.0d0)
1292
1293 ! Local Variables
1294 integer(int32) :: i, m, n, mn, lwork, ismin, ismax, rnk, maxmn, flag, &
1295 istat, lwork1, lwork2
1296 real(real64) :: rcond, smax, smin, smaxpr, sminpr
1297 complex(real64) :: s1, c1, s2, c2
1298 complex(real64), pointer, dimension(:) :: wptr, w, tau2
1299 complex(real64), allocatable, target, dimension(:) :: wrk
1300 class(errors), pointer :: errmgr
1301 type(errors), target :: deferr
1302 character(len = :), allocatable :: errmsg
1303
1304 ! Initialization
1305 m = size(a, 1)
1306 n = size(a, 2)
1307 mn = min(m, n)
1308 maxmn = max(m, n)
1309 ismin = mn + 1
1310 ismax = 2 * mn + 1
1311 rcond = epsilon(rcond)
1312 if (present(err)) then
1313 errmgr => err
1314 else
1315 errmgr => deferr
1316 end if
1317
1318 ! Input Check
1319 flag = 0
1320 if (size(tau) /= mn) then
1321 flag = 2
1322 else if (size(jpvt) /= n) then
1323 flag = 3
1324 else if (size(b) /= maxmn) then
1325 flag = 4
1326 end if
1327 if (flag /= 0) then
1328 ! ERROR: One of the input arrays is not sized correctly
1329 allocate(character(len = 256) :: errmsg)
1330 write(errmsg, 100) "Input number ", flag, &
1331 " is not sized correctly."
1332 call errmgr%report_error("solve_qr_pivot_vec_cmplx", trim(errmsg), &
1333 la_array_size_error)
1334 return
1335 end if
1336
1337 ! Workspace Query
1338 call rz_factor(a(1:mn,:), a(1:mn,1), olwork = lwork1)
1339 call mult_rz(.true., n, a(1:mn,:), a(1:mn,1), b(1:n), olwork = lwork2)
1340 lwork = max(lwork1, lwork2, 2 * mn + 1) + mn
1341 if (present(olwork)) then
1342 olwork = lwork
1343 return
1344 end if
1345
1346 ! Local Memory Allocation
1347 if (present(work)) then
1348 if (size(work) < lwork) then
1349 ! ERROR: WORK not sized correctly
1350 call errmgr%report_error("solve_qr_no_pivot_mtx_cmplx", &
1351 "Incorrectly sized input array WORK, argument 5.", &
1352 la_array_size_error)
1353 return
1354 end if
1355 wptr => work(1:lwork)
1356 else
1357 allocate(wrk(lwork), stat = istat)
1358 if (istat /= 0) then
1359 ! ERROR: Out of memory
1360 call errmgr%report_error("solve_qr_pivot_vec_cmplx", &
1361 "Insufficient memory available.", &
1362 la_out_of_memory_error)
1363 return
1364 end if
1365 wptr => wrk
1366 end if
1367
1368 ! Determine the rank of R11 using an incremental condition estimation
1369 wptr(ismin) = one
1370 wptr(ismax) = one
1371 smax = abs(a(1,1))
1372 smin = smax
1373 if (abs(a(1,1)) == zero) then
1374 rnk = 0
1375 b(maxmn) = zero
1376 return
1377 else
1378 rnk = 1
1379 end if
1380 do
1381 if (rnk < mn) then
1382 i = rnk + 1
1383 call zlaic1(imin, rnk, wptr(ismin:ismin+rnk-1), smin, &
1384 a(1:rnk-1,i), a(i,i), sminpr, s1, c1)
1385 call zlaic1(imax, rnk, wptr(ismax:ismax+rnk-1), smax, &
1386 a(1:rnk-1,i), a(i,i), smaxpr, s2, c2)
1387 if (smaxpr * rcond <= sminpr) then
1388 do i = 1, rnk
1389 wptr(ismin+i-1) = s1 * wptr(ismin+i-1)
1390 wptr(ismax+i-1) = s2 * wptr(ismax+i-1)
1391 end do
1392 wptr(ismin+rnk) = c1
1393 wptr(ismax+rnk) = c2
1394 smin = sminpr
1395 smax = smaxpr
1396 rnk = rnk + 1
1397 cycle
1398 end if
1399 end if
1400 exit
1401 end do
1402
1403 ! Partition R = [R11 R12]
1404 ! [ 0 R22]
1405 tau2 => wptr(1:rnk)
1406 w => wptr(rnk+1:lwork)
1407 if (rnk < n) call rz_factor(a(1:rnk,:), tau2, w)
1408
1409 ! Compute B(1:m,1:NRHS) = Q**T * B(1:M,1:NRHS)
1410 call mult_qr(.true., a, tau, b(1:m))
1411
1412 ! Solve the triangular system T11 * B(1:rnk) = B(1:rnk)
1413 call solve_triangular_system(.true., .false., .true., a(1:rnk,1:rnk), &
1414 b(1:rnk))
1415 if (n > rnk) b(rnk+1:n) = zero
1416
1417 ! Compute B(1:n) = Y**T * B(1:n)
1418 if (rnk < n) then
1419 call mult_rz(.true., n - rnk, a(1:rnk,:), tau2, b(1:n), w)
1420 end if
1421
1422 ! Apply the pivoting: B(1:N) = P * B(1:N)
1423 do i = 1, n
1424 wptr(jpvt(i)) = b(i)
1425 end do
1426 b = wptr(1:n)
1427
1428 ! Formatting
1429100 format(a, i0, a)
1430 end subroutine
1431
1432! ******************************************************************************
1433! CHOLESKY SOLVE
1434! ------------------------------------------------------------------------------
1435 module subroutine solve_cholesky_mtx(upper, a, b, err)
1436 ! Arguments
1437 logical, intent(in) :: upper
1438 real(real64), intent(in), dimension(:,:) :: a
1439 real(real64), intent(inout), dimension(:,:) :: b
1440 class(errors), intent(inout), optional, target :: err
1441
1442 ! Local Variables
1443 character :: uplo
1444 integer(int32) :: n, nrhs, flag
1445 class(errors), pointer :: errmgr
1446 type(errors), target :: deferr
1447 character(len = :), allocatable :: errmsg
1448
1449 ! Initialization
1450 n = size(a, 1)
1451 nrhs = size(b, 2)
1452 if (upper) then
1453 uplo = 'U'
1454 else
1455 uplo = 'L'
1456 end if
1457 if (present(err)) then
1458 errmgr => err
1459 else
1460 errmgr => deferr
1461 end if
1462
1463 ! Input Check
1464 flag = 0
1465 if (size(a, 2) /= n) then
1466 flag = 2
1467 else if (size(b, 1) /= n) then
1468 flag = 3
1469 end if
1470 if (flag /= 0) then
1471 allocate(character(len = 256) :: errmsg)
1472 write(errmsg, 100) "Input number ", flag, &
1473 " is not sized correctly."
1474 call errmgr%report_error("solve_cholesky_mtx", trim(errmsg), &
1475 la_array_size_error)
1476 return
1477 end if
1478
1479 ! Process
1480 call dpotrs(uplo, n, nrhs, a, n, b, n, flag)
1481
1482 ! Formatting
1483100 format(a, i0, a)
1484 end subroutine
1485
1486! ------------------------------------------------------------------------------
1487 module subroutine solve_cholesky_mtx_cmplx(upper, a, b, err)
1488 ! Arguments
1489 logical, intent(in) :: upper
1490 complex(real64), intent(in), dimension(:,:) :: a
1491 complex(real64), intent(inout), dimension(:,:) :: b
1492 class(errors), intent(inout), optional, target :: err
1493
1494 ! Local Variables
1495 character :: uplo
1496 integer(int32) :: n, nrhs, flag
1497 class(errors), pointer :: errmgr
1498 type(errors), target :: deferr
1499 character(len = :), allocatable :: errmsg
1500
1501 ! Initialization
1502 n = size(a, 1)
1503 nrhs = size(b, 2)
1504 if (upper) then
1505 uplo = 'U'
1506 else
1507 uplo = 'L'
1508 end if
1509 if (present(err)) then
1510 errmgr => err
1511 else
1512 errmgr => deferr
1513 end if
1514
1515 ! Input Check
1516 flag = 0
1517 if (size(a, 2) /= n) then
1518 flag = 2
1519 else if (size(b, 1) /= n) then
1520 flag = 3
1521 end if
1522 if (flag /= 0) then
1523 allocate(character(len = 256) :: errmsg)
1524 write(errmsg, 100) "Input number ", flag, &
1525 " is not sized correctly."
1526 call errmgr%report_error("solve_cholesky_mtx_cmplx", trim(errmsg), &
1527 la_array_size_error)
1528 return
1529 end if
1530
1531 ! Process
1532 call zpotrs(uplo, n, nrhs, a, n, b, n, flag)
1533
1534 ! Formatting
1535100 format(a, i0, a)
1536 end subroutine
1537
1538! ------------------------------------------------------------------------------
1539 module subroutine solve_cholesky_vec(upper, a, b, err)
1540 ! Arguments
1541 logical, intent(in) :: upper
1542 real(real64), intent(in), dimension(:,:) :: a
1543 real(real64), intent(inout), dimension(:) :: b
1544 class(errors), intent(inout), optional, target :: err
1545
1546 ! Local Variables
1547 character :: uplo
1548 integer(int32) :: n, flag
1549 class(errors), pointer :: errmgr
1550 type(errors), target :: deferr
1551 character(len = :), allocatable :: errmsg
1552
1553 ! Initialization
1554 n = size(a, 1)
1555 if (upper) then
1556 uplo = 'U'
1557 else
1558 uplo = 'L'
1559 end if
1560 if (present(err)) then
1561 errmgr => err
1562 else
1563 errmgr => deferr
1564 end if
1565
1566 ! Input Check
1567 flag = 0
1568 if (size(a, 2) /= n) then
1569 flag = 2
1570 else if (size(b) /= n) then
1571 flag = 3
1572 end if
1573 if (flag /= 0) then
1574 allocate(character(len = 256) :: errmsg)
1575 write(errmsg, 100) "Input number ", flag, &
1576 " is not sized correctly."
1577 call errmgr%report_error("solve_cholesky_vec", trim(errmsg), &
1578 la_array_size_error)
1579 return
1580 end if
1581
1582 ! Process
1583 call dpotrs(uplo, n, 1, a, n, b, n, flag)
1584
1585 ! Formatting
1586100 format(a, i0, a)
1587 end subroutine
1588
1589! ------------------------------------------------------------------------------
1590 module subroutine solve_cholesky_vec_cmplx(upper, a, b, err)
1591 ! Arguments
1592 logical, intent(in) :: upper
1593 complex(real64), intent(in), dimension(:,:) :: a
1594 complex(real64), intent(inout), dimension(:) :: b
1595 class(errors), intent(inout), optional, target :: err
1596
1597 ! Local Variables
1598 character :: uplo
1599 integer(int32) :: n, flag
1600 class(errors), pointer :: errmgr
1601 type(errors), target :: deferr
1602 character(len = :), allocatable :: errmsg
1603
1604 ! Initialization
1605 n = size(a, 1)
1606 if (upper) then
1607 uplo = 'U'
1608 else
1609 uplo = 'L'
1610 end if
1611 if (present(err)) then
1612 errmgr => err
1613 else
1614 errmgr => deferr
1615 end if
1616
1617 ! Input Check
1618 flag = 0
1619 if (size(a, 2) /= n) then
1620 flag = 2
1621 else if (size(b) /= n) then
1622 flag = 3
1623 end if
1624 if (flag /= 0) then
1625 allocate(character(len = 256) :: errmsg)
1626 write(errmsg, 100) "Input number ", flag, &
1627 " is not sized correctly."
1628 call errmgr%report_error("solve_cholesky_vec_cmplx", trim(errmsg), &
1629 la_array_size_error)
1630 return
1631 end if
1632
1633 ! Process
1634 call zpotrs(uplo, n, 1, a, n, b, n, flag)
1635
1636 ! Formatting
1637100 format(a, i0, a)
1638 end subroutine
1639
1640! ******************************************************************************
1641! MATRIX INVERSION ROUTINES
1642! ------------------------------------------------------------------------------
1643 module subroutine mtx_inverse_dbl(a, iwork, work, olwork, err)
1644 ! Arguments
1645 real(real64), intent(inout), dimension(:,:) :: a
1646 integer(int32), intent(out), target, optional, dimension(:) :: iwork
1647 real(real64), intent(out), target, optional, dimension(:) :: work
1648 integer(int32), intent(out), optional :: olwork
1649 class(errors), intent(inout), optional, target :: err
1650
1651 ! Local Variables
1652 integer(int32) :: n, liwork, lwork, istat, flag, itemp(1)
1653 integer(int32), pointer, dimension(:) :: iptr
1654 integer(int32), allocatable, target, dimension(:) :: iwrk
1655 real(real64), pointer, dimension(:) :: wptr
1656 real(real64), allocatable, target, dimension(:) :: wrk
1657 real(real64), dimension(1) :: temp
1658 class(errors), pointer :: errmgr
1659 type(errors), target :: deferr
1660
1661 ! Initialization
1662 n = size(a, 1)
1663 liwork = n
1664 if (present(err)) then
1665 errmgr => err
1666 else
1667 errmgr => deferr
1668 end if
1669
1670 ! Input Check
1671 if (size(a, 2) /= n) then
1672 call errmgr%report_error("mtx_inverse", &
1673 "The matrix must be squre to invert.", la_array_size_error)
1674 return
1675 end if
1676
1677 ! Workspace Query
1678 call dgetri(n, a, n, itemp, temp, -1, flag)
1679 lwork = int(temp(1), int32)
1680 if (present(olwork)) then
1681 olwork = lwork
1682 return
1683 end if
1684
1685 ! Workspace Allocation
1686 if (present(work)) then
1687 if (size(work) < lwork) then
1688 ! ERROR: WORK not sized correctly
1689 call errmgr%report_error("mtx_inverse_dbl", &
1690 "Incorrectly sized input array WORK, argument 3.", &
1691 la_array_size_error)
1692 return
1693 end if
1694 wptr => work(1:lwork)
1695 else
1696 allocate(wrk(lwork), stat = istat)
1697 if (istat /= 0) then
1698 ! ERROR: Out of memory
1699 call errmgr%report_error("mtx_inverse_dbl", &
1700 "Insufficient memory available.", &
1701 la_out_of_memory_error)
1702 return
1703 end if
1704 wptr => wrk
1705 end if
1706
1707 ! Integer Workspace Allocation
1708 if (present(iwork)) then
1709 if (size(iwork) < liwork) then
1710 ! ERROR: IWORK not sized correctly
1711 call errmgr%report_error("mtx_inverse_dbl", &
1712 "Incorrectly sized input array IWORK, argument 2.", &
1713 la_array_size_error)
1714 return
1715 end if
1716 iptr => iwork(1:liwork)
1717 else
1718 allocate(iwrk(liwork), stat = istat)
1719 if (istat /= 0) then
1720 ! ERROR: Out of memory
1721 call errmgr%report_error("mtx_inverse_dbl", &
1722 "Insufficient memory available.", &
1723 la_out_of_memory_error)
1724 return
1725 end if
1726 iptr => iwrk
1727 end if
1728
1729 ! Compute the LU factorization of A
1730 call dgetrf(n, n, a, n, iptr, flag)
1731
1732 ! Compute the inverse of the LU factored matrix
1733 call dgetri(n, a, n, iptr, wptr, lwork, flag)
1734
1735 ! Check for a singular matrix
1736 if (flag > 0) then
1737 call errmgr%report_error("mtx_inverse_dbl", &
1738 "The matrix is singular; therefore, the inverse could " // &
1739 "not be computed.", la_singular_matrix_error)
1740 end if
1741 end subroutine
1742
1743! ------------------------------------------------------------------------------
1744 module subroutine mtx_inverse_cmplx(a, iwork, work, olwork, err)
1745 ! Arguments
1746 complex(real64), intent(inout), dimension(:,:) :: a
1747 integer(int32), intent(out), target, optional, dimension(:) :: iwork
1748 complex(real64), intent(out), target, optional, dimension(:) :: work
1749 integer(int32), intent(out), optional :: olwork
1750 class(errors), intent(inout), optional, target :: err
1751
1752 ! Local Variables
1753 integer(int32) :: n, liwork, lwork, istat, flag, itemp(1)
1754 integer(int32), pointer, dimension(:) :: iptr
1755 integer(int32), allocatable, target, dimension(:) :: iwrk
1756 complex(real64), pointer, dimension(:) :: wptr
1757 complex(real64), allocatable, target, dimension(:) :: wrk
1758 complex(real64), dimension(1) :: temp
1759 class(errors), pointer :: errmgr
1760 type(errors), target :: deferr
1761
1762 ! Initialization
1763 n = size(a, 1)
1764 liwork = n
1765 if (present(err)) then
1766 errmgr => err
1767 else
1768 errmgr => deferr
1769 end if
1770
1771 ! Input Check
1772 if (size(a, 2) /= n) then
1773 call errmgr%report_error("mtx_inverse_cmplx", &
1774 "The matrix must be squre to invert.", la_array_size_error)
1775 return
1776 end if
1777
1778 ! Workspace Query
1779 call zgetri(n, a, n, itemp, temp, -1, flag)
1780 lwork = int(temp(1), int32)
1781 if (present(olwork)) then
1782 olwork = lwork
1783 return
1784 end if
1785
1786 ! Workspace Allocation
1787 if (present(work)) then
1788 if (size(work) < lwork) then
1789 ! ERROR: WORK not sized correctly
1790 call errmgr%report_error("mtx_inverse_cmplx", &
1791 "Incorrectly sized input array WORK, argument 3.", &
1792 la_array_size_error)
1793 return
1794 end if
1795 wptr => work(1:lwork)
1796 else
1797 allocate(wrk(lwork), stat = istat)
1798 if (istat /= 0) then
1799 ! ERROR: Out of memory
1800 call errmgr%report_error("mtx_inverse_cmplx", &
1801 "Insufficient memory available.", &
1802 la_out_of_memory_error)
1803 return
1804 end if
1805 wptr => wrk
1806 end if
1807
1808 ! Integer Workspace Allocation
1809 if (present(iwork)) then
1810 if (size(iwork) < liwork) then
1811 ! ERROR: IWORK not sized correctly
1812 call errmgr%report_error("mtx_inverse_cmplx", &
1813 "Incorrectly sized input array IWORK, argument 2.", &
1814 la_array_size_error)
1815 return
1816 end if
1817 iptr => iwork(1:liwork)
1818 else
1819 allocate(iwrk(liwork), stat = istat)
1820 if (istat /= 0) then
1821 ! ERROR: Out of memory
1822 call errmgr%report_error("mtx_inverse_cmplx", &
1823 "Insufficient memory available.", &
1824 la_out_of_memory_error)
1825 return
1826 end if
1827 iptr => iwrk
1828 end if
1829
1830 ! Compute the LU factorization of A
1831 call zgetrf(n, n, a, n, iptr, flag)
1832
1833 ! Compute the inverse of the LU factored matrix
1834 call zgetri(n, a, n, iptr, wptr, lwork, flag)
1835
1836 ! Check for a singular matrix
1837 if (flag > 0) then
1838 call errmgr%report_error("mtx_inverse_cmplx", &
1839 "The matrix is singular; therefore, the inverse could " // &
1840 "not be computed.", la_singular_matrix_error)
1841 end if
1842 end subroutine
1843
1844! ------------------------------------------------------------------------------
1845 module subroutine mtx_pinverse_dbl(a, ainv, tol, work, olwork, err)
1846 ! Arguments
1847 real(real64), intent(inout), dimension(:,:) :: a
1848 real(real64), intent(out), dimension(:,:) :: ainv
1849 real(real64), intent(in), optional :: tol
1850 real(real64), intent(out), target, dimension(:), optional :: work
1851 integer(int32), intent(out), optional :: olwork
1852 class(errors), intent(inout), optional, target :: err
1853
1854 ! Parameters
1855 real(real64), parameter :: zero = 0.0d0
1856 real(real64), parameter :: one = 1.0d0
1857
1858 ! Local Variables
1859 integer(int32) :: i, m, n, mn, lwork, istat, flag, i1, i2a, i2b, i3a, &
1860 i3b, i4, lrwork
1861 real(real64), pointer, dimension(:) :: s, wptr, w
1862 real(real64), pointer, dimension(:,:) :: u, vt
1863 real(real64), allocatable, target, dimension(:) :: wrk
1864 real(real64), dimension(1) :: temp
1865 real(real64) :: t, tref, tolcheck, ss
1866 class(errors), pointer :: errmgr
1867 type(errors), target :: deferr
1868 character(len = :), allocatable :: errmsg
1869
1870 ! Initialization
1871 m = size(a, 1)
1872 n = size(a, 2)
1873 mn = min(m, n)
1874 i1 = m * mn
1875 i2a = i1 + 1
1876 i2b = i2a + n * mn - 1
1877 i3a = i2b + 1
1878 i3b = i3a + mn - 1
1879 i4 = i3b + 1
1880 tolcheck = dlamch('s')
1881 if (present(err)) then
1882 errmgr => err
1883 else
1884 errmgr => deferr
1885 end if
1886
1887 ! Input Check
1888 if (size(ainv, 1) /= n .or. size(ainv, 2) /= m) then
1889 allocate(character(len = 256) :: errmsg)
1890 write(errmsg, 100) &
1891 "The output matrix AINV is not sized appropriately. " // &
1892 "It is expected to be ", n, "-by-", m, "."
1893 call errmgr%report_error("mtx_pinverse", errmsg, &
1894 la_array_size_error)
1895 return
1896 end if
1897
1898 ! Workspace Query
1899 call dgesvd('S', 'S', m, n, a, m, temp, a, m, a, n, temp, -1, flag)
1900 lrwork = int(temp(1), int32)
1901 lwork = lrwork + m * m + n * n + mn
1902 if (present(olwork)) then
1903 olwork = lwork
1904 return
1905 end if
1906
1907 ! Local Memory Allocation
1908 if (present(work)) then
1909 if (size(work) < lwork) then
1910 ! ERROR: WORK not sized correctly
1911 call errmgr%report_error("mtx_pinverse", &
1912 "Incorrectly sized input array WORK, argument 4.", &
1913 la_array_size_error)
1914 return
1915 end if
1916 wptr => work(1:lwork)
1917 else
1918 allocate(wrk(lwork), stat = istat)
1919 if (istat /= 0) then
1920 ! ERROR: Out of memory
1921 call errmgr%report_error("mtx_pinverse", &
1922 "Insufficient memory available.", &
1923 la_out_of_memory_error)
1924 return
1925 end if
1926 wptr => wrk
1927 end if
1928 u(1:m,1:mn) => wptr(1:i1)
1929 vt(1:mn,1:n) => wptr(i2a:i2b)
1930 s => wptr(i3a:i3b)
1931 w => wptr(i4:lwork)
1932
1933 ! Compute the SVD of A
1934 call dgesvd('S', 'S', m, n, a, m, s, u, m, vt, n, w, lrwork, flag)
1935
1936 ! Check for convergence
1937 if (flag > 0) then
1938 allocate(character(len = 256) :: errmsg)
1939 write(errmsg, 101) flag, " superdiagonals could not " // &
1940 "converge to zero as part of the QR iteration process."
1941 call errmgr%report_warning("mtx_pinverse", errmsg, &
1942 la_convergence_error)
1943 return
1944 end if
1945
1946 ! Determine the threshold tolerance for the singular values such that
1947 ! singular values less than the threshold result in zero when inverted.
1948 tref = max(m, n) * epsilon(t) * s(1)
1949 if (present(tol)) then
1950 t = tol
1951 else
1952 t = tref
1953 end if
1954 !if (t < safe_denom(t)) then
1955 if (t < tolcheck) then
1956 ! The supplied tolerance is too small, simply fall back to the
1957 ! default, but issue a warning to the user
1958 t = tref
1959 ! call errmgr%report_warning("pinverse_1", "The supplied tolerance was " // &
1960 ! "smaller than a value that would result in an overflow " // &
1961 ! "condition, or is negative; therefore, the tolerance has " // &
1962 ! "been reset to its default value.")
1963 end if
1964
1965 ! Compute the pseudoinverse such that pinv(A) = V * inv(S) * U**T by
1966 ! first computing inv(S) * U**T
1967 do i = 1, mn
1968 if (s(i) < t) then
1969 ss = s(i)
1970 else
1971 ss = 1.0d0 / s(i)
1972 end if
1973 call dscal(m, ss, u(:,i), 1)
1974 end do
1975 call dgemm("T", "T", n, m, mn, one, vt, n, u, m, zero, ainv, n)
1976
1977 ! Formatting
1978100 format(a, i0, a, i0, a)
1979101 format(i0, a)
1980 end subroutine
1981
1982! ------------------------------------------------------------------------------
1983 module subroutine mtx_pinverse_cmplx(a, ainv, tol, work, olwork, rwork, err)
1984 ! Arguments
1985 complex(real64), intent(inout), dimension(:,:) :: a
1986 complex(real64), intent(out), dimension(:,:) :: ainv
1987 real(real64), intent(in), optional :: tol
1988 complex(real64), intent(out), target, dimension(:), optional :: work
1989 integer(int32), intent(out), optional :: olwork
1990 real(real64), intent(out), target, dimension(:), optional :: rwork
1991 class(errors), intent(inout), optional, target :: err
1992
1993 ! External Function Interfaces
1994 interface
1995 function dlamch(cmach) result(x)
1996 use, intrinsic :: iso_fortran_env, only : real64
1997 character, intent(in) :: cmach
1998 real(real64) :: x
1999 end function
2000 end interface
2001
2002 ! Parameters
2003 complex(real64), parameter :: zero = (0.0d0, 0.0d0)
2004 complex(real64), parameter :: one = (1.0d0, 0.0d0)
2005
2006 ! Local Variables
2007 integer(int32) :: i, m, n, mn, lwork, istat, flag, i1, i2a, i2b, i3, &
2008 lrwork, j, k
2009 real(real64), pointer, dimension(:) :: s, rwptr, rw
2010 real(real64), allocatable, target, dimension(:) :: rwrk
2011 complex(real64), pointer, dimension(:) :: wptr, w
2012 complex(real64), pointer, dimension(:,:) :: u, vt
2013 complex(real64), allocatable, target, dimension(:) :: wrk
2014 complex(real64) :: temp(1), val
2015 real(real64) :: t, tref, tolcheck, rtemp(1)
2016 class(errors), pointer :: errmgr
2017 type(errors), target :: deferr
2018 character(len = :), allocatable :: errmsg
2019
2020 ! Initialization
2021 m = size(a, 1)
2022 n = size(a, 2)
2023 mn = min(m, n)
2024 lrwork = 6 * mn
2025 i1 = m * mn
2026 i2a = i1 + 1
2027 i2b = i2a + n * n - 1
2028 i3 = i2b + 1
2029 tolcheck = dlamch('s')
2030 if (present(err)) then
2031 errmgr => err
2032 else
2033 errmgr => deferr
2034 end if
2035
2036 ! Input Check
2037 if (size(ainv, 1) /= n .or. size(ainv, 2) /= m) then
2038 allocate(character(len = 256) :: errmsg)
2039 write(errmsg, 100) &
2040 "The output matrix AINV is not sized appropriately. " // &
2041 "It is expected to be ", n, "-by-", m, "."
2042 call errmgr%report_error("mtx_pinverse_cmplx", errmsg, &
2043 la_array_size_error)
2044 return
2045 end if
2046
2047 ! Workspace Query
2048 call zgesvd('S', 'A', m, n, a, m, rtemp, a, m, a, n, temp, -1, &
2049 rtemp, flag)
2050 lwork = int(temp(1), int32)
2051 lwork = lwork + m * mn + n * n
2052 if (present(olwork)) then
2053 olwork = lwork
2054 return
2055 end if
2056
2057 ! Local Memory Allocation
2058 if (present(work)) then
2059 if (size(work) < lwork) then
2060 ! ERROR: WORK not sized correctly
2061 call errmgr%report_error("mtx_pinverse_cmplx", &
2062 "Incorrectly sized input array WORK, argument 4.", &
2063 la_array_size_error)
2064 return
2065 end if
2066 wptr => work(1:lwork)
2067 else
2068 allocate(wrk(lwork), stat = istat)
2069 if (istat /= 0) then
2070 ! ERROR: Out of memory
2071 call errmgr%report_error("mtx_pinverse_cmplx", &
2072 "Insufficient memory available.", &
2073 la_out_of_memory_error)
2074 return
2075 end if
2076 wptr => wrk
2077 end if
2078
2079 if (present(rwork)) then
2080 if (size(rwork) < lrwork) then
2081 ! ERROR: WORK not sized correctly
2082 call errmgr%report_error("mtx_pinverse_cmplx", &
2083 "Incorrectly sized input array RWORK, argument 6.", &
2084 la_array_size_error)
2085 return
2086 end if
2087 rwptr => rwork(1:lrwork)
2088 else
2089 allocate(rwrk(lrwork), stat = istat)
2090 if (istat /= 0) then
2091 ! ERROR: Out of memory
2092 call errmgr%report_error("mtx_pinverse_cmplx", &
2093 "Insufficient memory available.", &
2094 la_out_of_memory_error)
2095 return
2096 end if
2097 rwptr => rwrk
2098 end if
2099 u(1:m,1:mn) => wptr(1:i1)
2100 vt(1:n,1:n) => wptr(i2a:i2b)
2101 w => wptr(i3:lwork)
2102 s => rwptr(1:mn)
2103 rw => rwptr(mn+1:lrwork)
2104
2105 ! Compute the SVD of A
2106 call zgesvd('S', 'A', m, n, a, m, s, u, m, vt, n, w, size(w), rw, flag)
2107
2108 ! Check for convergence
2109 if (flag > 0) then
2110 allocate(character(len = 256) :: errmsg)
2111 write(errmsg, 101) flag, " superdiagonals could not " // &
2112 "converge to zero as part of the QR iteration process."
2113 call errmgr%report_warning("mtx_pinverse_cmplx", errmsg, &
2114 la_convergence_error)
2115 return
2116 end if
2117
2118 ! Determine the threshold tolerance for the singular values such that
2119 ! singular values less than the threshold result in zero when inverted.
2120 tref = max(m, n) * epsilon(t) * s(1)
2121 if (present(tol)) then
2122 t = tol
2123 else
2124 t = tref
2125 end if
2126 !if (t < safe_denom(t)) then
2127 if (t < tolcheck) then
2128 ! The supplied tolerance is too small, simply fall back to the
2129 ! default, but issue a warning to the user
2130 t = tref
2131 ! call errmgr%report_warning("pinverse_1", "The supplied tolerance was " // &
2132 ! "smaller than a value that would result in an overflow " // &
2133 ! "condition, or is negative; therefore, the tolerance has " // &
2134 ! "been reset to its default value.")
2135 end if
2136
2137 ! Compute the pseudoinverse such that pinv(A) = V * inv(S) * U**T by
2138 ! first computing V * inv(S) (result is N-by-M), and store in the first
2139 ! MN rows of VT in a transposed manner.
2140 do i = 1, mn
2141 ! Apply 1 / S(I) to VT(I,:)
2142 if (s(i) < t) then
2143 vt(i,:) = zero
2144 else
2145 ! call recip_mult_array(s(i), vt(i,1:n))
2146 vt(i,1:n) = conjg(vt(i,1:n)) / s(i)
2147 end if
2148 end do
2149
2150 ! Compute (VT**T * inv(S)) * U**H
2151 ! ainv = n-by-m
2152 ! vt is n-by-n
2153 ! u is m-by-mn such that u**H = mn-by-m
2154 ! Compute ainv = vt**T * u**H
2155 do j = 1, m
2156 do i = 1, n
2157 val = zero
2158 do k = 1, mn
2159 val = val + vt(k,i) * conjg(u(j,k))
2160 end do
2161 ainv(i,j) = val
2162 end do
2163 end do
2164
2165 ! Formatting
2166100 format(a, i0, a, i0, a)
2167101 format(i0, a)
2168 end subroutine
2169
2170! ******************************************************************************
2171! LEAST SQUARES SOLUTION ROUTINES
2172! ------------------------------------------------------------------------------
2173 module subroutine solve_least_squares_mtx(a, b, work, olwork, err)
2174 ! Arguments
2175 real(real64), intent(inout), dimension(:,:) :: a, b
2176 real(real64), intent(out), target, optional, dimension(:) :: work
2177 integer(int32), intent(out), optional :: olwork
2178 class(errors), intent(inout), optional, target :: err
2179
2180 ! Local Variables
2181 integer(int32) :: m, n, maxmn, nrhs, lwork, istat, flag
2182 real(real64), pointer, dimension(:) :: wptr
2183 real(real64), allocatable, target, dimension(:) :: wrk
2184 real(real64), dimension(1) :: temp
2185 class(errors), pointer :: errmgr
2186 type(errors), target :: deferr
2187
2188 ! Initialization
2189 m = size(a, 1)
2190 n = size(a, 2)
2191 maxmn = max(m, n)
2192 nrhs = size(b, 2)
2193 if (present(err)) then
2194 errmgr => err
2195 else
2196 errmgr => deferr
2197 end if
2198
2199 ! Input Check
2200 if (size(b, 1) /= maxmn) then
2201 call errmgr%report_error("solve_least_squares_mtx", &
2202 "Input 2 is not sized correctly.", la_array_size_error)
2203 return
2204 end if
2205
2206 ! Workspace Query
2207 call dgels('N', m, n, nrhs, a, m, b, maxmn, temp, -1, flag)
2208 lwork = int(temp(1), int32)
2209 if (present(olwork)) then
2210 olwork = lwork
2211 return
2212 end if
2213
2214 ! Local Memory Allocation
2215 if (present(work)) then
2216 if (size(work) < lwork) then
2217 ! ERROR: WORK not sized correctly
2218 call errmgr%report_error("solve_least_squares_mtx", &
2219 "Incorrectly sized input array WORK, argument 3.", &
2220 la_array_size_error)
2221 return
2222 end if
2223 wptr => work(1:lwork)
2224 else
2225 allocate(wrk(lwork), stat = istat)
2226 if (istat /= 0) then
2227 ! ERROR: Out of memory
2228 call errmgr%report_error("solve_least_squares_mtx", &
2229 "Insufficient memory available.", &
2230 la_out_of_memory_error)
2231 return
2232 end if
2233 wptr => wrk
2234 end if
2235
2236 ! Process
2237 call dgels('N', m, n, nrhs, a, m, b, maxmn, wptr, lwork, flag)
2238 if (flag > 0) then
2239 call errmgr%report_error("solve_least_squares_mtx", &
2240 "The supplied matrix is not of full rank; therefore, " // &
2241 "the solution could not be computed via this routine. " // &
2242 "Try a routine that utilizes column pivoting.", &
2243 la_invalid_operation_error)
2244 end if
2245 end subroutine
2246
2247! ------------------------------------------------------------------------------
2248 module subroutine solve_least_squares_mtx_cmplx(a, b, work, olwork, err)
2249 ! Arguments
2250 complex(real64), intent(inout), dimension(:,:) :: a, b
2251 complex(real64), intent(out), target, optional, dimension(:) :: work
2252 integer(int32), intent(out), optional :: olwork
2253 class(errors), intent(inout), optional, target :: err
2254
2255 ! Local Variables
2256 integer(int32) :: m, n, maxmn, nrhs, lwork, istat, flag
2257 complex(real64), pointer, dimension(:) :: wptr
2258 complex(real64), allocatable, target, dimension(:) :: wrk
2259 complex(real64), dimension(1) :: temp
2260 class(errors), pointer :: errmgr
2261 type(errors), target :: deferr
2262
2263 ! Initialization
2264 m = size(a, 1)
2265 n = size(a, 2)
2266 maxmn = max(m, n)
2267 nrhs = size(b, 2)
2268 if (present(err)) then
2269 errmgr => err
2270 else
2271 errmgr => deferr
2272 end if
2273
2274 ! Input Check
2275 if (size(b, 1) /= maxmn) then
2276 call errmgr%report_error("solve_least_squares_mtx_cmplx", &
2277 "Input 2 is not sized correctly.", la_array_size_error)
2278 return
2279 end if
2280
2281 ! Workspace Query
2282 call zgels('N', m, n, nrhs, a, m, b, maxmn, temp, -1, flag)
2283 lwork = int(temp(1), int32)
2284 if (present(olwork)) then
2285 olwork = lwork
2286 return
2287 end if
2288
2289 ! Local Memory Allocation
2290 if (present(work)) then
2291 if (size(work) < lwork) then
2292 ! ERROR: WORK not sized correctly
2293 call errmgr%report_error("solve_least_squares_mtx_cmplx", &
2294 "Incorrectly sized input array WORK, argument 3.", &
2295 la_array_size_error)
2296 return
2297 end if
2298 wptr => work(1:lwork)
2299 else
2300 allocate(wrk(lwork), stat = istat)
2301 if (istat /= 0) then
2302 ! ERROR: Out of memory
2303 call errmgr%report_error("solve_least_squares_mtx_cmplx", &
2304 "Insufficient memory available.", &
2305 la_out_of_memory_error)
2306 return
2307 end if
2308 wptr => wrk
2309 end if
2310
2311 ! Process
2312 call zgels('N', m, n, nrhs, a, m, b, maxmn, wptr, lwork, flag)
2313 if (flag > 0) then
2314 call errmgr%report_error("solve_least_squares_mtx_cmplx", &
2315 "The supplied matrix is not of full rank; therefore, " // &
2316 "the solution could not be computed via this routine. " // &
2317 "Try a routine that utilizes column pivoting.", &
2318 la_invalid_operation_error)
2319 end if
2320 end subroutine
2321
2322! ------------------------------------------------------------------------------
2323 module subroutine solve_least_squares_vec(a, b, work, olwork, err)
2324 ! Arguments
2325 real(real64), intent(inout), dimension(:,:) :: a
2326 real(real64), intent(inout), dimension(:) :: b
2327 real(real64), intent(out), target, optional, dimension(:) :: work
2328 integer(int32), intent(out), optional :: olwork
2329 class(errors), intent(inout), optional, target :: err
2330
2331 ! Local Variables
2332 integer(int32) :: m, n, maxmn, lwork, istat, flag
2333 real(real64), pointer, dimension(:) :: wptr
2334 real(real64), allocatable, target, dimension(:) :: wrk
2335 real(real64), dimension(1) :: temp
2336 class(errors), pointer :: errmgr
2337 type(errors), target :: deferr
2338
2339 ! Initialization
2340 m = size(a, 1)
2341 n = size(a, 2)
2342 maxmn = max(m, n)
2343 if (present(err)) then
2344 errmgr => err
2345 else
2346 errmgr => deferr
2347 end if
2348
2349 ! Input Check
2350 if (size(b) /= maxmn) then
2351 call errmgr%report_error("solve_least_squares_vec", &
2352 "Input 2 is not sized correctly.", la_array_size_error)
2353 return
2354 end if
2355
2356 ! Workspace Query
2357 call dgels('N', m, n, 1, a, m, b, maxmn, temp, -1, flag)
2358 lwork = int(temp(1), int32)
2359 if (present(olwork)) then
2360 olwork = lwork
2361 return
2362 end if
2363
2364 ! Local Memory Allocation
2365 if (present(work)) then
2366 if (size(work) < lwork) then
2367 ! ERROR: WORK not sized correctly
2368 call errmgr%report_error("solve_least_squares_vec", &
2369 "Incorrectly sized input array WORK, argument 3.", &
2370 la_array_size_error)
2371 return
2372 end if
2373 wptr => work(1:lwork)
2374 else
2375 allocate(wrk(lwork), stat = istat)
2376 if (istat /= 0) then
2377 ! ERROR: Out of memory
2378 call errmgr%report_error("solve_least_squares_vec", &
2379 "Insufficient memory available.", &
2380 la_out_of_memory_error)
2381 return
2382 end if
2383 wptr => wrk
2384 end if
2385
2386 ! Process
2387 call dgels('N', m, n, 1, a, m, b, maxmn, wptr, lwork, flag)
2388 if (flag > 0) then
2389 call errmgr%report_error("solve_least_squares_mtx", &
2390 "The supplied matrix is not of full rank; therefore, " // &
2391 "the solution could not be computed via this routine. " // &
2392 "Try a routine that utilizes column pivoting.", &
2393 la_invalid_operation_error)
2394 end if
2395 end subroutine
2396
2397! ------------------------------------------------------------------------------
2398 module subroutine solve_least_squares_vec_cmplx(a, b, work, olwork, err)
2399 ! Arguments
2400 complex(real64), intent(inout), dimension(:,:) :: a
2401 complex(real64), intent(inout), dimension(:) :: b
2402 complex(real64), intent(out), target, optional, dimension(:) :: work
2403 integer(int32), intent(out), optional :: olwork
2404 class(errors), intent(inout), optional, target :: err
2405
2406 ! Local Variables
2407 integer(int32) :: m, n, maxmn, lwork, istat, flag
2408 complex(real64), pointer, dimension(:) :: wptr
2409 complex(real64), allocatable, target, dimension(:) :: wrk
2410 complex(real64), dimension(1) :: temp
2411 class(errors), pointer :: errmgr
2412 type(errors), target :: deferr
2413
2414 ! Initialization
2415 m = size(a, 1)
2416 n = size(a, 2)
2417 maxmn = max(m, n)
2418 if (present(err)) then
2419 errmgr => err
2420 else
2421 errmgr => deferr
2422 end if
2423
2424 ! Input Check
2425 if (size(b) /= maxmn) then
2426 call errmgr%report_error("solve_least_squares_vec_cmplx", &
2427 "Input 2 is not sized correctly.", la_array_size_error)
2428 return
2429 end if
2430
2431 ! Workspace Query
2432 call zgels('N', m, n, 1, a, m, b, maxmn, temp, -1, flag)
2433 lwork = int(temp(1), int32)
2434 if (present(olwork)) then
2435 olwork = lwork
2436 return
2437 end if
2438
2439 ! Local Memory Allocation
2440 if (present(work)) then
2441 if (size(work) < lwork) then
2442 ! ERROR: WORK not sized correctly
2443 call errmgr%report_error("solve_least_squares_vec_cmplx", &
2444 "Incorrectly sized input array WORK, argument 3.", &
2445 la_array_size_error)
2446 return
2447 end if
2448 wptr => work(1:lwork)
2449 else
2450 allocate(wrk(lwork), stat = istat)
2451 if (istat /= 0) then
2452 ! ERROR: Out of memory
2453 call errmgr%report_error("solve_least_squares_vec_cmplx", &
2454 "Insufficient memory available.", &
2455 la_out_of_memory_error)
2456 return
2457 end if
2458 wptr => wrk
2459 end if
2460
2461 ! Process
2462 call zgels('N', m, n, 1, a, m, b, maxmn, wptr, lwork, flag)
2463 if (flag > 0) then
2464 call errmgr%report_error("solve_least_squares_mtx_cmplx", &
2465 "The supplied matrix is not of full rank; therefore, " // &
2466 "the solution could not be computed via this routine. " // &
2467 "Try a routine that utilizes column pivoting.", &
2468 la_invalid_operation_error)
2469 end if
2470 end subroutine
2471
2472! ------------------------------------------------------------------------------
2473 module subroutine solve_least_squares_mtx_pvt(a, b, ipvt, arnk, work, olwork, err)
2474 ! Arguments
2475 real(real64), intent(inout), dimension(:,:) :: a, b
2476 integer(int32), intent(inout), target, optional, dimension(:) :: ipvt
2477 integer(int32), intent(out), optional :: arnk
2478 real(real64), intent(out), target, optional, dimension(:) :: work
2479 integer(int32), intent(out), optional :: olwork
2480 class(errors), intent(inout), optional, target :: err
2481
2482 ! Local Variables
2483 integer(int32) :: m, n, maxmn, nrhs, lwork, istat, flag, rnk
2484 real(real64), pointer, dimension(:) :: wptr
2485 real(real64), allocatable, target, dimension(:) :: wrk
2486 integer(int32), allocatable, target, dimension(:) :: iwrk
2487 integer(int32), pointer, dimension(:) :: iptr
2488 real(real64), dimension(1) :: temp
2489 integer(int32), dimension(1) :: itemp
2490 real(real64) :: rc
2491 class(errors), pointer :: errmgr
2492 type(errors), target :: deferr
2493 character(len = :), allocatable :: errmsg
2494
2495 ! Initialization
2496 m = size(a, 1)
2497 n = size(a, 2)
2498 maxmn = max(m, n)
2499 nrhs = size(b, 2)
2500 rc = epsilon(rc)
2501 if (present(arnk)) arnk = 0
2502 if (present(err)) then
2503 errmgr => err
2504 else
2505 errmgr => deferr
2506 end if
2507
2508 ! Input Check
2509 flag = 0
2510 if (size(b, 1) /= maxmn) then
2511 flag = 2
2512 end if
2513 if (flag /= 0) then
2514 allocate(character(len = 256) :: errmsg)
2515 write(errmsg, 100) "Input number ", flag, &
2516 " is not sized correctly."
2517 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2518 trim(errmsg), la_array_size_error)
2519 return
2520 end if
2521
2522 ! Workspace Query
2523 call dgelsy(m, n, nrhs, a, m, b, maxmn, itemp, rc, rnk, temp, -1, flag)
2524 lwork = int(temp(1), int32)
2525 if (present(olwork)) then
2526 olwork = lwork
2527 return
2528 end if
2529
2530 ! Local Memory Allocation
2531 if (present(ipvt)) then
2532 if (size(ipvt) < n) then
2533 ! ERROR: IPVT is not big enough
2534 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2535 "Incorrectly sized pivot array, argument 3.", &
2536 la_array_size_error)
2537 return
2538 end if
2539 iptr => ipvt(1:n)
2540 else
2541 allocate(iwrk(n), stat = istat)
2542 if (istat /= 0) then
2543 ! ERROR: Out of memory
2544 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2545 "Insufficient memory available.", &
2546 la_out_of_memory_error)
2547 return
2548 end if
2549 iptr => iwrk
2550 iptr = 0
2551 end if
2552
2553 if (present(work)) then
2554 if (size(work) < lwork) then
2555 ! ERROR: WORK not sized correctly
2556 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2557 "Incorrectly sized input array WORK, argument 5.", &
2558 la_array_size_error)
2559 return
2560 end if
2561 wptr => work(1:lwork)
2562 else
2563 allocate(wrk(lwork), stat = istat)
2564 if (istat /= 0) then
2565 ! ERROR: Out of memory
2566 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2567 "Insufficient memory available.", &
2568 la_out_of_memory_error)
2569 return
2570 end if
2571 wptr => wrk
2572 end if
2573
2574 ! Process
2575 call dgelsy(m, n, nrhs, a, m, b, maxmn, iptr, rc, rnk, wptr, lwork, &
2576 flag)
2577 if (present(arnk)) arnk = rnk
2578
2579 ! Formatting
2580100 format(a, i0, a)
2581 end subroutine
2582
2583! ------------------------------------------------------------------------------
2584 module subroutine solve_least_squares_mtx_pvt_cmplx(a, b, ipvt, arnk, &
2585 work, olwork, rwork, err)
2586 ! Arguments
2587 complex(real64), intent(inout), dimension(:,:) :: a, b
2588 integer(int32), intent(inout), target, optional, dimension(:) :: ipvt
2589 integer(int32), intent(out), optional :: arnk
2590 complex(real64), intent(out), target, optional, dimension(:) :: work
2591 integer(int32), intent(out), optional :: olwork
2592 real(real64), intent(out), target, optional, dimension(:) :: rwork
2593 class(errors), intent(inout), optional, target :: err
2594
2595 ! Local Variables
2596 integer(int32) :: m, n, maxmn, nrhs, lwork, istat, flag, rnk, lrwork
2597 complex(real64), pointer, dimension(:) :: wptr
2598 complex(real64), allocatable, target, dimension(:) :: wrk
2599 real(real64), pointer, dimension(:) :: rwptr
2600 real(real64), allocatable, target, dimension(:) :: rwrk
2601 integer(int32), allocatable, target, dimension(:) :: iwrk
2602 integer(int32), pointer, dimension(:) :: iptr
2603 complex(real64), dimension(1) :: temp
2604 real(real64), dimension(1) :: rtemp
2605 integer(int32), dimension(1) :: itemp
2606 real(real64) :: rc
2607 class(errors), pointer :: errmgr
2608 type(errors), target :: deferr
2609 character(len = :), allocatable :: errmsg
2610
2611 ! Initialization
2612 m = size(a, 1)
2613 n = size(a, 2)
2614 maxmn = max(m, n)
2615 nrhs = size(b, 2)
2616 lrwork = 2 * n
2617 rc = epsilon(rc)
2618 if (present(arnk)) arnk = 0
2619 if (present(err)) then
2620 errmgr => err
2621 else
2622 errmgr => deferr
2623 end if
2624
2625 ! Input Check
2626 flag = 0
2627 if (size(b, 1) /= maxmn) then
2628 flag = 2
2629 end if
2630 if (flag /= 0) then
2631 allocate(character(len = 256) :: errmsg)
2632 write(errmsg, 100) "Input number ", flag, &
2633 " is not sized correctly."
2634 call errmgr%report_error("solve_least_squares_mtx_pvt_cmplx", &
2635 trim(errmsg), la_array_size_error)
2636 return
2637 end if
2638
2639 ! Workspace Query
2640 call zgelsy(m, n, nrhs, a, m, b, maxmn, itemp, rc, rnk, temp, -1, &
2641 rtemp, flag)
2642 lwork = int(temp(1), int32)
2643 if (present(olwork)) then
2644 olwork = lwork
2645 return
2646 end if
2647
2648 ! Local Memory Allocation
2649 if (present(ipvt)) then
2650 if (size(ipvt) < n) then
2651 ! ERROR: IPVT is not big enough
2652 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2653 "Incorrectly sized pivot array, argument 3.", &
2654 la_array_size_error)
2655 return
2656 end if
2657 iptr => ipvt(1:n)
2658 else
2659 allocate(iwrk(n), stat = istat)
2660 if (istat /= 0) then
2661 ! ERROR: Out of memory
2662 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2663 "Insufficient memory available.", &
2664 la_out_of_memory_error)
2665 return
2666 end if
2667 iptr => iwrk
2668 iptr = 0
2669 end if
2670
2671 if (present(work)) then
2672 if (size(work) < lwork) then
2673 ! ERROR: WORK not sized correctly
2674 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2675 "Incorrectly sized input array WORK, argument 5.", &
2676 la_array_size_error)
2677 return
2678 end if
2679 wptr => work(1:lwork)
2680 else
2681 allocate(wrk(lwork), stat = istat)
2682 if (istat /= 0) then
2683 ! ERROR: Out of memory
2684 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2685 "Insufficient memory available.", &
2686 la_out_of_memory_error)
2687 return
2688 end if
2689 wptr => wrk
2690 end if
2691
2692 if (present(rwork)) then
2693 if (size(rwork) < lrwork) then
2694 ! ERROR: RWORK not sized correctly
2695 call errmgr%report_error("solve_least_squares_mtx_pvt_cmplx", &
2696 "Incorrectly sized input array RWORK, argument 7.", &
2697 la_array_size_error)
2698 return
2699 end if
2700 rwptr => rwork(1:lrwork)
2701 else
2702 allocate(rwrk(lrwork), stat = istat)
2703 if (istat /= 0) then
2704 ! ERROR: Out of memory
2705 call errmgr%report_error("solve_least_squares_mtx_pvt_cmplx", &
2706 "Insufficient memory available.", &
2707 la_out_of_memory_error)
2708 return
2709 end if
2710 rwptr => rwrk
2711 end if
2712
2713 ! Process
2714 call zgelsy(m, n, nrhs, a, m, b, maxmn, iptr, rc, rnk, wptr, lwork, &
2715 rwptr, flag)
2716 if (present(arnk)) arnk = rnk
2717
2718 ! Formatting
2719100 format(a, i0, a)
2720 end subroutine
2721
2722! ------------------------------------------------------------------------------
2723 module subroutine solve_least_squares_vec_pvt(a, b, ipvt, arnk, work, olwork, err)
2724 ! Arguments
2725 real(real64), intent(inout), dimension(:,:) :: a
2726 real(real64), intent(inout), dimension(:) :: b
2727 integer(int32), intent(inout), target, optional, dimension(:) :: ipvt
2728 integer(int32), intent(out), optional :: arnk
2729 real(real64), intent(out), target, optional, dimension(:) :: work
2730 integer(int32), intent(out), optional :: olwork
2731 class(errors), intent(inout), optional, target :: err
2732
2733 ! Local Variables
2734 integer(int32) :: m, n, maxmn, lwork, istat, flag, rnk
2735 real(real64), pointer, dimension(:) :: wptr
2736 real(real64), allocatable, target, dimension(:) :: wrk
2737 integer(int32), allocatable, target, dimension(:) :: iwrk
2738 integer(int32), pointer, dimension(:) :: iptr
2739 real(real64), dimension(1) :: temp
2740 integer(int32), dimension(1) :: itemp
2741 real(real64) :: rc
2742 class(errors), pointer :: errmgr
2743 type(errors), target :: deferr
2744 character(len = :), allocatable :: errmsg
2745
2746 ! Initialization
2747 m = size(a, 1)
2748 n = size(a, 2)
2749 maxmn = max(m, n)
2750 rc = epsilon(rc)
2751 if (present(arnk)) arnk = 0
2752 if (present(err)) then
2753 errmgr => err
2754 else
2755 errmgr => deferr
2756 end if
2757
2758 ! Input Check
2759 flag = 0
2760 if (size(b, 1) /= maxmn) then
2761 flag = 2
2762 end if
2763 if (flag /= 0) then
2764 allocate(character(len = 256) :: errmsg)
2765 write(errmsg, 100) "Input number ", flag, &
2766 " is not sized correctly."
2767 call errmgr%report_error("solve_least_squares_vec_pvt", &
2768 trim(errmsg), la_array_size_error)
2769 return
2770 end if
2771
2772 ! Workspace Query
2773 call dgelsy(m, n, 1, a, m, b, maxmn, itemp, rc, rnk, temp, -1, flag)
2774 lwork = int(temp(1), int32)
2775 if (present(olwork)) then
2776 olwork = lwork
2777 return
2778 end if
2779
2780 ! Local Memory Allocation
2781 if (present(ipvt)) then
2782 if (size(ipvt) < n) then
2783 ! ERROR: IPVT is not big enough
2784 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2785 "Incorrectly sized pivot array, argument 3.", &
2786 la_array_size_error)
2787 return
2788 end if
2789 iptr => ipvt(1:n)
2790 else
2791 allocate(iwrk(n), stat = istat)
2792 if (istat /= 0) then
2793 ! ERROR: Out of memory
2794 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2795 "Insufficient memory available.", &
2796 la_out_of_memory_error)
2797 return
2798 end if
2799 iptr => iwrk
2800 iptr = 0
2801 end if
2802
2803 if (present(work)) then
2804 if (size(work) < lwork) then
2805 ! ERROR: WORK not sized correctly
2806 call errmgr%report_error("solve_least_squares_vec_pvt", &
2807 "Incorrectly sized input array WORK, argument 5.", &
2808 la_array_size_error)
2809 return
2810 end if
2811 wptr => work(1:lwork)
2812 else
2813 allocate(wrk(lwork), stat = istat)
2814 if (istat /= 0) then
2815 ! ERROR: Out of memory
2816 call errmgr%report_error("solve_least_squares_vec_pvt", &
2817 "Insufficient memory available.", &
2818 la_out_of_memory_error)
2819 return
2820 end if
2821 wptr => wrk
2822 end if
2823
2824 ! Process
2825 call dgelsy(m, n, 1, a, m, b, maxmn, iptr, rc, rnk, wptr, lwork, flag)
2826 if (present(arnk)) arnk = rnk
2827
2828 ! Formatting
2829100 format(a, i0, a)
2830 end subroutine
2831
2832! ------------------------------------------------------------------------------
2833 module subroutine solve_least_squares_vec_pvt_cmplx(a, b, ipvt, arnk, &
2834 work, olwork, rwork, err)
2835 ! Arguments
2836 complex(real64), intent(inout), dimension(:,:) :: a
2837 complex(real64), intent(inout), dimension(:) :: b
2838 integer(int32), intent(inout), target, optional, dimension(:) :: ipvt
2839 integer(int32), intent(out), optional :: arnk
2840 complex(real64), intent(out), target, optional, dimension(:) :: work
2841 integer(int32), intent(out), optional :: olwork
2842 real(real64), intent(out), target, optional, dimension(:) :: rwork
2843 class(errors), intent(inout), optional, target :: err
2844
2845 ! Local Variables
2846 integer(int32) :: m, n, maxmn, lwork, lrwork, istat, flag, rnk
2847 complex(real64), pointer, dimension(:) :: wptr
2848 complex(real64), allocatable, target, dimension(:) :: wrk
2849 real(real64), pointer, dimension(:) :: rwptr
2850 real(real64), allocatable, target, dimension(:) :: rwrk
2851 integer(int32), allocatable, target, dimension(:) :: iwrk
2852 integer(int32), pointer, dimension(:) :: iptr
2853 complex(real64), dimension(1) :: temp
2854 real(real64), dimension(1) :: rtemp
2855 integer(int32), dimension(1) :: itemp
2856 real(real64) :: rc
2857 class(errors), pointer :: errmgr
2858 type(errors), target :: deferr
2859 character(len = :), allocatable :: errmsg
2860
2861 ! Initialization
2862 m = size(a, 1)
2863 n = size(a, 2)
2864 maxmn = max(m, n)
2865 lrwork = 2 * n
2866 rc = epsilon(rc)
2867 if (present(arnk)) arnk = 0
2868 if (present(err)) then
2869 errmgr => err
2870 else
2871 errmgr => deferr
2872 end if
2873
2874 ! Input Check
2875 flag = 0
2876 if (size(b, 1) /= maxmn) then
2877 flag = 2
2878 end if
2879 if (flag /= 0) then
2880 allocate(character(len = 256) :: errmsg)
2881 write(errmsg, 100) "Input number ", flag, &
2882 " is not sized correctly."
2883 call errmgr%report_error("solve_least_squares_vec_pvt_cmplx", &
2884 trim(errmsg), la_array_size_error)
2885 return
2886 end if
2887
2888 ! Workspace Query
2889 call zgelsy(m, n, 1, a, m, b, maxmn, itemp, rc, rnk, temp, -1, rtemp, &
2890 flag)
2891 lwork = int(temp(1), int32)
2892 if (present(olwork)) then
2893 olwork = lwork
2894 return
2895 end if
2896
2897 ! Local Memory Allocation
2898 if (present(ipvt)) then
2899 if (size(ipvt) < n) then
2900 ! ERROR: IPVT is not big enough
2901 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2902 "Incorrectly sized pivot array, argument 3.", &
2903 la_array_size_error)
2904 return
2905 end if
2906 iptr => ipvt(1:n)
2907 else
2908 allocate(iwrk(n), stat = istat)
2909 if (istat /= 0) then
2910 ! ERROR: Out of memory
2911 call errmgr%report_error("solve_least_squares_mtx_pvt", &
2912 "Insufficient memory available.", &
2913 la_out_of_memory_error)
2914 return
2915 end if
2916 iptr => iwrk
2917 iptr = 0
2918 end if
2919
2920 if (present(work)) then
2921 if (size(work) < lwork) then
2922 ! ERROR: WORK not sized correctly
2923 call errmgr%report_error("solve_least_squares_vec_pvt_cmplx", &
2924 "Incorrectly sized input array WORK, argument 5.", &
2925 la_array_size_error)
2926 return
2927 end if
2928 wptr => work(1:lwork)
2929 else
2930 allocate(wrk(lwork), stat = istat)
2931 if (istat /= 0) then
2932 ! ERROR: Out of memory
2933 call errmgr%report_error("solve_least_squares_vec_pvt_cmplx", &
2934 "Insufficient memory available.", &
2935 la_out_of_memory_error)
2936 return
2937 end if
2938 wptr => wrk
2939 end if
2940
2941 if (present(rwork)) then
2942 if (size(rwork) < lrwork) then
2943 ! ERROR: WORK not sized correctly
2944 call errmgr%report_error("solve_least_squares_vec_pvt_cmplx", &
2945 "Incorrectly sized input array RWORK, argument 7.", &
2946 la_array_size_error)
2947 return
2948 end if
2949 rwptr => rwork(1:lrwork)
2950 else
2951 allocate(rwrk(lrwork), stat = istat)
2952 if (istat /= 0) then
2953 ! ERROR: Out of memory
2954 call errmgr%report_error("solve_least_squares_vec_pvt_cmplx", &
2955 "Insufficient memory available.", &
2956 la_out_of_memory_error)
2957 return
2958 end if
2959 rwptr => rwrk
2960 end if
2961
2962 ! Process
2963 call zgelsy(m, n, 1, a, m, b, maxmn, iptr, rc, rnk, wptr, lwork, &
2964 rwptr, flag)
2965 if (present(arnk)) arnk = rnk
2966
2967 ! Formatting
2968100 format(a, i0, a)
2969 end subroutine
2970
2971! ------------------------------------------------------------------------------
2972 module subroutine solve_least_squares_mtx_svd(a, b, s, arnk, work, olwork, err)
2973 ! Arguments
2974 real(real64), intent(inout), dimension(:,:) :: a, b
2975 integer(int32), intent(out), optional :: arnk
2976 real(real64), intent(out), target, optional, dimension(:) :: work, s
2977 integer(int32), intent(out), optional :: olwork
2978 class(errors), intent(inout), optional, target :: err
2979
2980 ! Local Variables
2981 integer(int32) :: m, n, nrhs, mn, maxmn, istat, flag, lwork, rnk
2982 real(real64), pointer, dimension(:) :: wptr, sptr
2983 real(real64), allocatable, target, dimension(:) :: wrk, sing
2984 real(real64), dimension(1) :: temp
2985 real(real64) :: rcond
2986 class(errors), pointer :: errmgr
2987 type(errors), target :: deferr
2988 character(len = :), allocatable :: errmsg
2989
2990 ! Initialization
2991 m = size(a, 1)
2992 n = size(a, 2)
2993 nrhs = size(b, 2)
2994 mn = min(m, n)
2995 maxmn = max(m, n)
2996 rcond = epsilon(rcond)
2997 if (present(arnk)) arnk = 0
2998 if (present(err)) then
2999 errmgr => err
3000 else
3001 errmgr => deferr
3002 end if
3003
3004 ! Input Check
3005 flag = 0
3006 if (size(b, 1) /= maxmn) then
3007 flag = 2
3008 end if
3009 if (flag /= 0) then
3010 ! ERROR: One of the input arrays is not sized correctly
3011 allocate(character(len = 256) :: errmsg)
3012 write(errmsg, 100) "Input number ", flag, &
3013 " is not sized correctly."
3014 call errmgr%report_error("solve_least_squares_mtx_svd", &
3015 trim(errmsg), la_array_size_error)
3016 return
3017 end if
3018
3019 ! Workspace Query
3020 call dgelss(m, n, nrhs, a, m, b, maxmn, temp, rcond, rnk, temp, -1, &
3021 flag)
3022 lwork = int(temp(1), int32)
3023 if (present(olwork)) then
3024 olwork = lwork
3025 return
3026 end if
3027
3028 ! Local Memory Allocation
3029 if (present(s)) then
3030 if (size(s) < mn) then
3031 ! ERROR: S not sized correctly
3032 call errmgr%report_error("solve_least_squares_mtx_svd", &
3033 "Incorrectly sized input array S, argument 3.", &
3034 la_array_size_error)
3035 return
3036 end if
3037 sptr => s(1:mn)
3038 else
3039 allocate(sing(mn), stat = istat)
3040 if (istat /= 0) then
3041 ! ERROR: Out of memory
3042 call errmgr%report_error("solve_least_squares_mtx_svd", &
3043 "Insufficient memory available.", &
3044 la_out_of_memory_error)
3045 return
3046 end if
3047 sptr => sing
3048 end if
3049
3050 if (present(work)) then
3051 if (size(work) < lwork) then
3052 ! ERROR: WORK not sized correctly
3053 call errmgr%report_error("solve_least_squares_mtx_svd", &
3054 "Incorrectly sized input array WORK, argument 5.", &
3055 la_array_size_error)
3056 return
3057 end if
3058 wptr => work(1:lwork)
3059 else
3060 allocate(wrk(lwork), stat = istat)
3061 if (istat /= 0) then
3062 ! ERROR: Out of memory
3063 call errmgr%report_error("solve_least_squares_mtx_svd", &
3064 "Insufficient memory available.", &
3065 la_out_of_memory_error)
3066 return
3067 end if
3068 wptr => wrk
3069 end if
3070
3071 ! Process
3072 call dgelss(m, n, nrhs, a, m, b, maxmn, sptr, rcond, rnk, wptr, lwork, &
3073 flag)
3074 if (present(arnk)) arnk = rnk
3075 if (flag > 0) then
3076 allocate(character(len = 256) :: errmsg)
3077 write(errmsg, 101) flag, " superdiagonals could not " // &
3078 "converge to zero as part of the QR iteration process."
3079 call errmgr%report_warning("solve_least_squares_mtx_svd", errmsg, &
3080 la_convergence_error)
3081 end if
3082
3083 ! Formatting
3084100 format(a, i0, a)
3085101 format(i0, a)
3086 end subroutine
3087
3088! ------------------------------------------------------------------------------
3089 module subroutine solve_least_squares_mtx_svd_cmplx(a, b, s, arnk, work, &
3090 olwork, rwork, err)
3091 ! Arguments
3092 complex(real64), intent(inout), dimension(:,:) :: a, b
3093 integer(int32), intent(out), optional :: arnk
3094 complex(real64), intent(out), target, optional, dimension(:) :: work
3095 real(real64), intent(out), target, optional, dimension(:) :: s, rwork
3096 integer(int32), intent(out), optional :: olwork
3097 class(errors), intent(inout), optional, target :: err
3098
3099 ! Local Variables
3100 integer(int32) :: m, n, nrhs, mn, maxmn, istat, flag, lwork, rnk, lrwork
3101 complex(real64), pointer, dimension(:) :: wptr
3102 complex(real64), allocatable, target, dimension(:) :: wrk
3103 real(real64), pointer, dimension(:) :: rwptr, sptr
3104 real(real64), allocatable, target, dimension(:) :: rwrk, sing
3105 complex(real64), dimension(1) :: temp
3106 real(real64), dimension(1) :: rtemp
3107 real(real64) :: rcond
3108 class(errors), pointer :: errmgr
3109 type(errors), target :: deferr
3110 character(len = :), allocatable :: errmsg
3111
3112 ! Initialization
3113 m = size(a, 1)
3114 n = size(a, 2)
3115 nrhs = size(b, 2)
3116 mn = min(m, n)
3117 lrwork = 5 * mn
3118 maxmn = max(m, n)
3119 rcond = epsilon(rcond)
3120 if (present(arnk)) arnk = 0
3121 if (present(err)) then
3122 errmgr => err
3123 else
3124 errmgr => deferr
3125 end if
3126
3127 ! Input Check
3128 flag = 0
3129 if (size(b, 1) /= maxmn) then
3130 flag = 2
3131 end if
3132 if (flag /= 0) then
3133 ! ERROR: One of the input arrays is not sized correctly
3134 allocate(character(len = 256) :: errmsg)
3135 write(errmsg, 100) "Input number ", flag, &
3136 " is not sized correctly."
3137 call errmgr%report_error("solve_least_squares_mtx_svd_cmplx", &
3138 trim(errmsg), la_array_size_error)
3139 return
3140 end if
3141
3142 ! Workspace Query
3143 call zgelss(m, n, nrhs, a, m, b, maxmn, rtemp, rcond, rnk, temp, -1, &
3144 rtemp, flag)
3145 lwork = int(temp(1), int32)
3146 if (present(olwork)) then
3147 olwork = lwork
3148 return
3149 end if
3150
3151 ! Local Memory Allocation
3152 if (present(s)) then
3153 if (size(s) < mn) then
3154 ! ERROR: S not sized correctly
3155 call errmgr%report_error("solve_least_squares_mtx_svd_cmplx", &
3156 "Incorrectly sized input array S, argument 3.", &
3157 la_array_size_error)
3158 return
3159 end if
3160 sptr => s(1:mn)
3161 else
3162 allocate(sing(mn), stat = istat)
3163 if (istat /= 0) then
3164 ! ERROR: Out of memory
3165 call errmgr%report_error("solve_least_squares_mtx_svd_cmplx", &
3166 "Insufficient memory available.", &
3167 la_out_of_memory_error)
3168 return
3169 end if
3170 sptr => sing
3171 end if
3172
3173 if (present(work)) then
3174 if (size(work) < lwork) then
3175 ! ERROR: WORK not sized correctly
3176 call errmgr%report_error("solve_least_squares_mtx_svd_cmplx", &
3177 "Incorrectly sized input array WORK, argument 5.", &
3178 la_array_size_error)
3179 return
3180 end if
3181 wptr => work(1:lwork)
3182 else
3183 allocate(wrk(lwork), stat = istat)
3184 if (istat /= 0) then
3185 ! ERROR: Out of memory
3186 call errmgr%report_error("solve_least_squares_mtx_svd_cmplx", &
3187 "Insufficient memory available.", &
3188 la_out_of_memory_error)
3189 return
3190 end if
3191 wptr => wrk
3192 end if
3193
3194 if (present(rwork)) then
3195 if (size(rwork) < lrwork) then
3196 ! ERROR: WORK not sized correctly
3197 call errmgr%report_error("solve_least_squares_mtx_svd_cmplx", &
3198 "Incorrectly sized input array RWORK, argument 7.", &
3199 la_array_size_error)
3200 return
3201 end if
3202 rwptr => rwork(1:lrwork)
3203 else
3204 allocate(rwrk(lrwork), stat = istat)
3205 if (istat /= 0) then
3206 ! ERROR: Out of memory
3207 call errmgr%report_error("solve_least_squares_mtx_svd_cmplx", &
3208 "Insufficient memory available.", &
3209 la_out_of_memory_error)
3210 return
3211 end if
3212 rwptr => rwrk
3213 end if
3214
3215 ! Process
3216 call zgelss(m, n, nrhs, a, m, b, maxmn, sptr, rcond, rnk, wptr, lwork, &
3217 rwptr, flag)
3218 if (present(arnk)) arnk = rnk
3219 if (flag > 0) then
3220 allocate(character(len = 256) :: errmsg)
3221 write(errmsg, 101) flag, " superdiagonals could not " // &
3222 "converge to zero as part of the QR iteration process."
3223 call errmgr%report_warning("solve_least_squares_mtx_svd_cmplx", &
3224 errmsg, la_convergence_error)
3225 end if
3226
3227 ! Formatting
3228100 format(a, i0, a)
3229101 format(i0, a)
3230 end subroutine
3231
3232! ------------------------------------------------------------------------------
3233 module subroutine solve_least_squares_vec_svd(a, b, s, arnk, work, olwork, err)
3234 ! Arguments
3235 real(real64), intent(inout), dimension(:,:) :: a
3236 real(real64), intent(inout), dimension(:) :: b
3237 integer(int32), intent(out), optional :: arnk
3238 real(real64), intent(out), target, optional, dimension(:) :: work, s
3239 integer(int32), intent(out), optional :: olwork
3240 class(errors), intent(inout), optional, target :: err
3241
3242 ! Local Variables
3243 integer(int32) :: m, n, mn, maxmn, istat, flag, lwork, rnk
3244 real(real64), pointer, dimension(:) :: wptr, sptr
3245 real(real64), allocatable, target, dimension(:) :: wrk, sing
3246 real(real64), dimension(1) :: temp
3247 real(real64) :: rcond
3248 class(errors), pointer :: errmgr
3249 type(errors), target :: deferr
3250 character(len = :), allocatable :: errmsg
3251
3252 ! Initialization
3253 m = size(a, 1)
3254 n = size(a, 2)
3255 mn = min(m, n)
3256 maxmn = max(m, n)
3257 rcond = epsilon(rcond)
3258 if (present(arnk)) arnk = 0
3259 if (present(err)) then
3260 errmgr => err
3261 else
3262 errmgr => deferr
3263 end if
3264
3265 ! Input Check
3266 flag = 0
3267 if (size(b) /= maxmn) then
3268 flag = 2
3269 end if
3270 if (flag /= 0) then
3271 ! ERROR: One of the input arrays is not sized correctly
3272 allocate(character(len = 256) :: errmsg)
3273 write(errmsg, 100) "Input number ", flag, &
3274 " is not sized correctly."
3275 call errmgr%report_error("solve_least_squares_vec_svd", &
3276 trim(errmsg), la_array_size_error)
3277 return
3278 end if
3279
3280 ! Workspace Query
3281 call dgelss(m, n, 1, a, m, b, maxmn, temp, rcond, rnk, temp, -1, flag)
3282 lwork = int(temp(1), int32)
3283 if (present(olwork)) then
3284 olwork = lwork
3285 return
3286 end if
3287
3288 ! Local Memory Allocation
3289 if (present(s)) then
3290 if (size(s) < mn) then
3291 ! ERROR: S not sized correctly
3292 call errmgr%report_error("solve_least_squares_vec_svd", &
3293 "Incorrectly sized input array S, argument 3.", &
3294 la_array_size_error)
3295 return
3296 end if
3297 sptr => s(1:mn)
3298 else
3299 allocate(sing(mn), stat = istat)
3300 if (istat /= 0) then
3301 ! ERROR: Out of memory
3302 call errmgr%report_error("solve_least_squares_vec_svd", &
3303 "Insufficient memory available.", &
3304 la_out_of_memory_error)
3305 return
3306 end if
3307 sptr => sing
3308 end if
3309
3310 if (present(work)) then
3311 if (size(work) < lwork) then
3312 ! ERROR: WORK not sized correctly
3313 call errmgr%report_error("solve_least_squares_vec_svd", &
3314 "Incorrectly sized input array WORK, argument 5.", &
3315 la_array_size_error)
3316 return
3317 end if
3318 wptr => work(1:lwork)
3319 else
3320 allocate(wrk(lwork), stat = istat)
3321 if (istat /= 0) then
3322 ! ERROR: Out of memory
3323 call errmgr%report_error("solve_least_squares_vec_svd", &
3324 "Insufficient memory available.", &
3325 la_out_of_memory_error)
3326 return
3327 end if
3328 wptr => wrk
3329 end if
3330
3331 ! Process
3332 call dgelss(m, n, 1, a, m, b, maxmn, sptr, rcond, rnk, wptr, lwork, &
3333 flag)
3334 if (present(arnk)) arnk = rnk
3335 if (flag > 0) then
3336 allocate(character(len = 256) :: errmsg)
3337 write(errmsg, 101) flag, " superdiagonals could not " // &
3338 "converge to zero as part of the QR iteration process."
3339 call errmgr%report_warning("solve_least_squares_vec_svd", errmsg, &
3340 la_convergence_error)
3341 end if
3342
3343 ! Formatting
3344100 format(a, i0, a)
3345101 format(i0, a)
3346 end subroutine
3347
3348! ------------------------------------------------------------------------------
3349 module subroutine solve_least_squares_vec_svd_cmplx(a, b, s, arnk, work, &
3350 olwork, rwork, err)
3351 ! Arguments
3352 complex(real64), intent(inout), dimension(:,:) :: a
3353 complex(real64), intent(inout), dimension(:) :: b
3354 integer(int32), intent(out), optional :: arnk
3355 complex(real64), intent(out), target, optional, dimension(:) :: work
3356 real(real64), intent(out), target, optional, dimension(:) :: rwork, s
3357 integer(int32), intent(out), optional :: olwork
3358 class(errors), intent(inout), optional, target :: err
3359
3360 ! Local Variables
3361 integer(int32) :: m, n, mn, maxmn, istat, flag, lwork, rnk, lrwork
3362 real(real64), pointer, dimension(:) :: rwptr, sptr
3363 real(real64), allocatable, target, dimension(:) :: rwrk, sing
3364 complex(real64), pointer, dimension(:) :: wptr
3365 complex(real64), allocatable, target, dimension(:) :: wrk
3366 complex(real64), dimension(1) :: temp
3367 real(real64), dimension(1) :: rtemp
3368 real(real64) :: rcond
3369 class(errors), pointer :: errmgr
3370 type(errors), target :: deferr
3371 character(len = :), allocatable :: errmsg
3372
3373 ! Initialization
3374 m = size(a, 1)
3375 n = size(a, 2)
3376 mn = min(m, n)
3377 lrwork = 5 * mn
3378 maxmn = max(m, n)
3379 rcond = epsilon(rcond)
3380 if (present(arnk)) arnk = 0
3381 if (present(err)) then
3382 errmgr => err
3383 else
3384 errmgr => deferr
3385 end if
3386
3387 ! Input Check
3388 flag = 0
3389 if (size(b) /= maxmn) then
3390 flag = 2
3391 end if
3392 if (flag /= 0) then
3393 ! ERROR: One of the input arrays is not sized correctly
3394 allocate(character(len = 256) :: errmsg)
3395 write(errmsg, 100) "Input number ", flag, &
3396 " is not sized correctly."
3397 call errmgr%report_error("solve_least_squares_vec_svd_cmplx", &
3398 trim(errmsg), la_array_size_error)
3399 return
3400 end if
3401
3402 ! Workspace Query
3403 call zgelss(m, n, 1, a, m, b, maxmn, rtemp, rcond, rnk, temp, -1, &
3404 rtemp, flag)
3405 lwork = int(temp(1), int32)
3406 if (present(olwork)) then
3407 olwork = lwork
3408 return
3409 end if
3410
3411 ! Local Memory Allocation
3412 if (present(s)) then
3413 if (size(s) < mn) then
3414 ! ERROR: S not sized correctly
3415 call errmgr%report_error("solve_least_squares_vec_svd_cmplx", &
3416 "Incorrectly sized input array S, argument 3.", &
3417 la_array_size_error)
3418 return
3419 end if
3420 sptr => s(1:mn)
3421 else
3422 allocate(sing(mn), stat = istat)
3423 if (istat /= 0) then
3424 ! ERROR: Out of memory
3425 call errmgr%report_error("solve_least_squares_vec_svd_cmplx", &
3426 "Insufficient memory available.", &
3427 la_out_of_memory_error)
3428 return
3429 end if
3430 sptr => sing
3431 end if
3432
3433 if (present(work)) then
3434 if (size(work) < lwork) then
3435 ! ERROR: WORK not sized correctly
3436 call errmgr%report_error("solve_least_squares_vec_svd_cmplx", &
3437 "Incorrectly sized input array WORK, argument 5.", &
3438 la_array_size_error)
3439 return
3440 end if
3441 wptr => work(1:lwork)
3442 else
3443 allocate(wrk(lwork), stat = istat)
3444 if (istat /= 0) then
3445 ! ERROR: Out of memory
3446 call errmgr%report_error("solve_least_squares_vec_svd_cmplx", &
3447 "Insufficient memory available.", &
3448 la_out_of_memory_error)
3449 return
3450 end if
3451 wptr => wrk
3452 end if
3453
3454 if (present(rwork)) then
3455 if (size(rwork) < lrwork) then
3456 ! ERROR: WORK not sized correctly
3457 call errmgr%report_error("solve_least_squares_vec_svd_cmplx", &
3458 "Incorrectly sized input array RWORK, argument 7.", &
3459 la_array_size_error)
3460 return
3461 end if
3462 rwptr => rwork(1:lrwork)
3463 else
3464 allocate(rwrk(lrwork), stat = istat)
3465 if (istat /= 0) then
3466 ! ERROR: Out of memory
3467 call errmgr%report_error("solve_least_squares_vec_svd_cmplx", &
3468 "Insufficient memory available.", &
3469 la_out_of_memory_error)
3470 return
3471 end if
3472 rwptr => rwrk
3473 end if
3474
3475 ! Process
3476 call zgelss(m, n, 1, a, m, b, maxmn, sptr, rcond, rnk, wptr, lwork, &
3477 rwptr, flag)
3478 if (present(arnk)) arnk = rnk
3479 if (flag > 0) then
3480 allocate(character(len = 256) :: errmsg)
3481 write(errmsg, 101) flag, " superdiagonals could not " // &
3482 "converge to zero as part of the QR iteration process."
3483 call errmgr%report_warning("solve_least_squares_vec_svd_cmplx", &
3484 errmsg, la_convergence_error)
3485 end if
3486
3487 ! Formatting
3488100 format(a, i0, a)
3489101 format(i0, a)
3490 end subroutine
3491
3492! ******************************************************************************
3493! LQ SOLUTION
3494! ------------------------------------------------------------------------------
3495 module subroutine solve_lq_mtx(a, tau, b, work, olwork, err)
3496 ! Arguments
3497 real(real64), intent(in), dimension(:,:) :: a
3498 real(real64), intent(in), dimension(:) :: tau
3499 real(real64), intent(inout), dimension(:,:) :: b
3500 real(real64), intent(out), target, optional, dimension(:) :: work
3501 integer(int32), intent(out), optional :: olwork
3502 class(errors), intent(inout), optional, target :: err
3503
3504 ! Parameters
3505 real(real64), parameter :: one = 1.0d0
3506
3507 ! Local Variables
3508 integer(int32) :: m, n, nrhs, k, lwork, flag, istat
3509 real(real64), pointer, dimension(:) :: wptr
3510 real(real64), allocatable, target, dimension(:) :: wrk
3511 class(errors), pointer :: errmgr
3512 type(errors), target :: deferr
3513 character(len = :), allocatable :: errmsg
3514
3515 ! Initialization
3516 m = size(a, 1)
3517 n = size(a, 2)
3518 nrhs = size(b, 2)
3519 k = min(m, n)
3520 if (present(err)) then
3521 errmgr => err
3522 else
3523 errmgr => deferr
3524 end if
3525
3526 ! Input Check
3527 flag = 0
3528 if (m > n) then
3529 flag = 1
3530 else if (size(tau) /= k) then
3531 flag = 2
3532 else if (size(b, 1) /= n) then
3533 flag = 3
3534 end if
3535
3536 if (flag /= 0) then
3537 ! ERROR: One of the input arrays is not sized correctly
3538 allocate(character(len = 256) :: errmsg)
3539 write(errmsg, 100) "Input number ", flag, &
3540 " is not sized correctly."
3541 call errmgr%report_error("solve_lq_mtx", trim(errmsg), &
3542 la_array_size_error)
3543 return
3544 end if
3545
3546 ! Workspace Query
3547 call mult_lq(.true., .true., a, tau, b, olwork = lwork)
3548
3549 if (present(olwork)) then
3550 olwork = lwork
3551 return
3552 end if
3553
3554 ! Local Memory Allocation
3555 if (present(work)) then
3556 if (size(work) < lwork) then
3557 ! ERROR: WORK not sized correctly
3558 call errmgr%report_error("solve_lq_mtx", &
3559 "Incorrectly sized input array WORK, argument 4.", &
3560 la_array_size_error)
3561 return
3562 end if
3563 wptr => work(1:lwork)
3564 else
3565 allocate(wrk(lwork), stat = istat)
3566 if (istat /= 0) then
3567 ! ERROR: Out of memory
3568 call errmgr%report_error("solve_lq_mtx", &
3569 "Insufficient memory available.", &
3570 la_out_of_memory_error)
3571 return
3572 end if
3573 wptr => wrk
3574 end if
3575
3576 ! Solve the lower triangular system L * Y = B for Y, where Y = Q * X.
3577 ! The lower triangular system is M-by-M and Y is M-by-NHRS.
3578 call solve_triangular_system(.true., .false., .false., .true., one, &
3579 a(1:m,1:m), b(1:m,:), errmgr)
3580 if (errmgr%has_error_occurred()) return
3581
3582 ! Compute Q**T * Y = X
3583 call mult_lq(.true., .true., a, tau, b, work = wptr, err = errmgr)
3584 if (errmgr%has_error_occurred()) return
3585
3586 ! Formatting
3587100 format(a, i0, a)
3588 end subroutine
3589
3590! ------------------------------------------------------------------------------
3591 module subroutine solve_lq_mtx_cmplx(a, tau, b, work, olwork, err)
3592 ! Arguments
3593 complex(real64), intent(in), dimension(:,:) :: a
3594 complex(real64), intent(in), dimension(:) :: tau
3595 complex(real64), intent(inout), dimension(:,:) :: b
3596 complex(real64), intent(out), target, optional, dimension(:) :: work
3597 integer(int32), intent(out), optional :: olwork
3598 class(errors), intent(inout), optional, target :: err
3599
3600 ! Parameters
3601 complex(real64), parameter :: one = (1.0d0, 0.0d0)
3602
3603 ! Local Variables
3604 integer(int32) :: m, n, nrhs, k, lwork, flag, istat
3605 complex(real64), pointer, dimension(:) :: wptr
3606 complex(real64), allocatable, target, dimension(:) :: wrk
3607 class(errors), pointer :: errmgr
3608 type(errors), target :: deferr
3609 character(len = :), allocatable :: errmsg
3610
3611 ! Initialization
3612 m = size(a, 1)
3613 n = size(a, 2)
3614 nrhs = size(b, 2)
3615 k = min(m, n)
3616 if (present(err)) then
3617 errmgr => err
3618 else
3619 errmgr => deferr
3620 end if
3621
3622 ! Input Check
3623 flag = 0
3624 if (m > n) then
3625 flag = 1
3626 else if (size(tau) /= k) then
3627 flag = 2
3628 else if (size(b, 1) /= n) then
3629 flag = 3
3630 end if
3631
3632 if (flag /= 0) then
3633 ! ERROR: One of the input arrays is not sized correctly
3634 allocate(character(len = 256) :: errmsg)
3635 write(errmsg, 100) "Input number ", flag, &
3636 " is not sized correctly."
3637 call errmgr%report_error("solve_lq_mtx_cmplx", trim(errmsg), &
3638 la_array_size_error)
3639 return
3640 end if
3641
3642 ! Workspace Query
3643 call mult_lq(.true., .true., a, tau, b, olwork = lwork)
3644
3645 if (present(olwork)) then
3646 olwork = lwork
3647 return
3648 end if
3649
3650 ! Local Memory Allocation
3651 if (present(work)) then
3652 if (size(work) < lwork) then
3653 ! ERROR: WORK not sized correctly
3654 call errmgr%report_error("solve_lq_mtx_cmplx", &
3655 "Incorrectly sized input array WORK, argument 4.", &
3656 la_array_size_error)
3657 return
3658 end if
3659 wptr => work(1:lwork)
3660 else
3661 allocate(wrk(lwork), stat = istat)
3662 if (istat /= 0) then
3663 ! ERROR: Out of memory
3664 call errmgr%report_error("solve_lq_mtx_cmplx", &
3665 "Insufficient memory available.", &
3666 la_out_of_memory_error)
3667 return
3668 end if
3669 wptr => wrk
3670 end if
3671
3672 ! Solve the lower triangular system L * Y = B for Y, where Y = Q * X.
3673 ! The lower triangular system is M-by-M and Y is M-by-NHRS.
3674 call solve_triangular_system(.true., .false., .false., .true., one, &
3675 a(1:m,1:m), b(1:m,:), errmgr)
3676 if (errmgr%has_error_occurred()) return
3677
3678 ! Compute Q**T * Y = X
3679 call mult_lq(.true., .true., a, tau, b, work = wptr, err = errmgr)
3680 if (errmgr%has_error_occurred()) return
3681
3682 ! Formatting
3683100 format(a, i0, a)
3684 end subroutine
3685
3686! ------------------------------------------------------------------------------
3687 module subroutine solve_lq_vec(a, tau, b, work, olwork, err)
3688 ! Arguments
3689 real(real64), intent(in), dimension(:,:) :: a
3690 real(real64), intent(in), dimension(:) :: tau
3691 real(real64), intent(inout), dimension(:) :: b
3692 real(real64), intent(out), target, optional, dimension(:) :: work
3693 integer(int32), intent(out), optional :: olwork
3694 class(errors), intent(inout), optional, target :: err
3695
3696 ! Local Variables
3697 integer(int32) :: m, n, k, lwork, flag, istat
3698 real(real64), pointer, dimension(:) :: wptr
3699 real(real64), allocatable, target, dimension(:) :: wrk
3700 class(errors), pointer :: errmgr
3701 type(errors), target :: deferr
3702 character(len = :), allocatable :: errmsg
3703
3704 ! Initialization
3705 m = size(a, 1)
3706 n = size(a, 2)
3707 k = min(m, n)
3708 if (present(err)) then
3709 errmgr => err
3710 else
3711 errmgr => deferr
3712 end if
3713
3714 ! Input Check
3715 flag = 0
3716 if (m > n) then
3717 flag = 1
3718 else if (size(tau) /= k) then
3719 flag = 2
3720 else if (size(b) /= n) then
3721 flag = 3
3722 end if
3723
3724 if (flag /= 0) then
3725 ! ERROR: One of the input arrays is not sized correctly
3726 allocate(character(len = 256) :: errmsg)
3727 write(errmsg, 100) "Input number ", flag, &
3728 " is not sized correctly."
3729 call errmgr%report_error("solve_lq_vec", trim(errmsg), &
3730 la_array_size_error)
3731 return
3732 end if
3733
3734 ! Workspace Query
3735 call mult_lq(.true., a, tau, b, olwork = lwork)
3736
3737 if (present(olwork)) then
3738 olwork = lwork
3739 return
3740 end if
3741
3742 ! Local Memory Allocation
3743 if (present(work)) then
3744 if (size(work) < lwork) then
3745 ! ERROR: WORK not sized correctly
3746 call errmgr%report_error("solve_lq_vec", &
3747 "Incorrectly sized input array WORK, argument 4.", &
3748 la_array_size_error)
3749 return
3750 end if
3751 wptr => work(1:lwork)
3752 else
3753 allocate(wrk(lwork), stat = istat)
3754 if (istat /= 0) then
3755 ! ERROR: Out of memory
3756 call errmgr%report_error("solve_lq_vec", &
3757 "Insufficient memory available.", &
3758 la_out_of_memory_error)
3759 return
3760 end if
3761 wptr => wrk
3762 end if
3763
3764 ! Solve the lower triangular system L * Y = B for Y, where Y = Q * X.
3765 ! The lower triangular system is M-by-M and Y is M-by-NHRS.
3766 call solve_triangular_system(.false., .false., .true., a(1:m,1:m), &
3767 b(1:m), errmgr)
3768 if (errmgr%has_error_occurred()) return
3769
3770 ! Compute Q**T * Y = X
3771 call mult_lq(.true., a, tau, b, work = wptr, err = errmgr)
3772 if (errmgr%has_error_occurred()) return
3773
3774 ! Formatting
3775100 format(a, i0, a)
3776 end subroutine
3777
3778! ------------------------------------------------------------------------------
3779 module subroutine solve_lq_vec_cmplx(a, tau, b, work, olwork, err)
3780 ! Arguments
3781 complex(real64), intent(in), dimension(:,:) :: a
3782 complex(real64), intent(in), dimension(:) :: tau
3783 complex(real64), intent(inout), dimension(:) :: b
3784 complex(real64), intent(out), target, optional, dimension(:) :: work
3785 integer(int32), intent(out), optional :: olwork
3786 class(errors), intent(inout), optional, target :: err
3787
3788 ! Local Variables
3789 integer(int32) :: m, n, k, lwork, flag, istat
3790 complex(real64), pointer, dimension(:) :: wptr
3791 complex(real64), allocatable, target, dimension(:) :: wrk
3792 class(errors), pointer :: errmgr
3793 type(errors), target :: deferr
3794 character(len = :), allocatable :: errmsg
3795
3796 ! Initialization
3797 m = size(a, 1)
3798 n = size(a, 2)
3799 k = min(m, n)
3800 if (present(err)) then
3801 errmgr => err
3802 else
3803 errmgr => deferr
3804 end if
3805
3806 ! Input Check
3807 flag = 0
3808 if (m > n) then
3809 flag = 1
3810 else if (size(tau) /= k) then
3811 flag = 2
3812 else if (size(b) /= n) then
3813 flag = 3
3814 end if
3815
3816 if (flag /= 0) then
3817 ! ERROR: One of the input arrays is not sized correctly
3818 allocate(character(len = 256) :: errmsg)
3819 write(errmsg, 100) "Input number ", flag, &
3820 " is not sized correctly."
3821 call errmgr%report_error("solve_lq_vec_cmplx", trim(errmsg), &
3822 la_array_size_error)
3823 return
3824 end if
3825
3826 ! Workspace Query
3827 call mult_lq(.true., a, tau, b, olwork = lwork)
3828
3829 if (present(olwork)) then
3830 olwork = lwork
3831 return
3832 end if
3833
3834 ! Local Memory Allocation
3835 if (present(work)) then
3836 if (size(work) < lwork) then
3837 ! ERROR: WORK not sized correctly
3838 call errmgr%report_error("solve_lq_vec_cmplx", &
3839 "Incorrectly sized input array WORK, argument 4.", &
3840 la_array_size_error)
3841 return
3842 end if
3843 wptr => work(1:lwork)
3844 else
3845 allocate(wrk(lwork), stat = istat)
3846 if (istat /= 0) then
3847 ! ERROR: Out of memory
3848 call errmgr%report_error("solve_lq_vec_cmplx", &
3849 "Insufficient memory available.", &
3850 la_out_of_memory_error)
3851 return
3852 end if
3853 wptr => wrk
3854 end if
3855
3856 ! Solve the lower triangular system L * Y = B for Y, where Y = Q * X.
3857 ! The lower triangular system is M-by-M and Y is M-by-NHRS.
3858 call solve_triangular_system(.false., .false., .true., a(1:m,1:m), &
3859 b(1:m), errmgr)
3860 if (errmgr%has_error_occurred()) return
3861
3862 ! Compute Q**T * Y = X
3863 call mult_lq(.true., a, tau, b, work = wptr, err = errmgr)
3864 if (errmgr%has_error_occurred()) return
3865
3866 ! Formatting
3867100 format(a, i0, a)
3868 end subroutine
3869
3870! ------------------------------------------------------------------------------
3871end submodule
A module providing explicit interfaces to BLAS routines.
Definition blas.f90:2
Provides a set of common linear algebra routines.
Definition linalg.f90:145