comparison liboctave/numeric/gsvd.cc @ 31607:aac27ad79be6 stable

maint: Re-indent code after switch to using namespace macros. * build-env.h, build-env.in.cc, Cell.h, __betainc__.cc, __eigs__.cc, __ftp__.cc, __ichol__.cc, __ilu__.cc, __isprimelarge__.cc, __magick_read__.cc, __pchip_deriv__.cc, amd.cc, base-text-renderer.cc, base-text-renderer.h, besselj.cc, bitfcns.cc, bsxfun.cc, c-file-ptr-stream.h, call-stack.cc, call-stack.h, ccolamd.cc, cellfun.cc, chol.cc, colamd.cc, dasrt.cc, data.cc, debug.cc, defaults.cc, defaults.h, det.cc, display.cc, display.h, dlmread.cc, dynamic-ld.cc, dynamic-ld.h, ellipj.cc, environment.cc, environment.h, error.cc, error.h, errwarn.h, event-manager.cc, event-manager.h, event-queue.cc, event-queue.h, fcn-info.cc, fcn-info.h, fft.cc, fft2.cc, file-io.cc, filter.cc, find.cc, ft-text-renderer.cc, ft-text-renderer.h, gcd.cc, gl-render.cc, gl-render.h, gl2ps-print.cc, gl2ps-print.h, graphics-toolkit.cc, graphics-toolkit.h, graphics.cc, gsvd.cc, gtk-manager.cc, gtk-manager.h, help.cc, help.h, hook-fcn.cc, hook-fcn.h, input.cc, input.h, interpreter-private.cc, interpreter-private.h, interpreter.cc, interpreter.h, inv.cc, jsondecode.cc, jsonencode.cc, latex-text-renderer.cc, latex-text-renderer.h, load-path.cc, load-path.h, load-save.cc, load-save.h, lookup.cc, ls-hdf5.cc, ls-mat4.cc, ls-mat5.cc, lsode.cc, lu.cc, mappers.cc, matrix_type.cc, max.cc, mex.cc, mexproto.h, mxarray.h, mxtypes.in.h, oct-errno.in.cc, oct-hdf5-types.cc, oct-hist.cc, oct-hist.h, oct-map.cc, oct-map.h, oct-opengl.h, oct-prcstrm.h, oct-process.cc, oct-process.h, oct-stdstrm.h, oct-stream.cc, oct-stream.h, oct-strstrm.h, octave-default-image.h, ordqz.cc, ordschur.cc, pager.cc, pager.h, pinv.cc, pow2.cc, pr-output.cc, psi.cc, qr.cc, quadcc.cc, rand.cc, regexp.cc, settings.cc, settings.h, sighandlers.cc, sighandlers.h, sparse-xpow.cc, sqrtm.cc, stack-frame.cc, stack-frame.h, stream-euler.cc, strfns.cc, svd.cc, syminfo.cc, syminfo.h, symrcm.cc, symrec.cc, symrec.h, symscope.cc, symscope.h, symtab.cc, symtab.h, sysdep.cc, sysdep.h, text-engine.cc, text-engine.h, text-renderer.cc, text-renderer.h, time.cc, toplev.cc, typecast.cc, url-handle-manager.cc, url-handle-manager.h, urlwrite.cc, utils.cc, utils.h, variables.cc, variables.h, xdiv.cc, __delaunayn__.cc, __init_fltk__.cc, __init_gnuplot__.cc, __ode15__.cc, __voronoi__.cc, audioread.cc, convhulln.cc, gzip.cc, cdef-class.cc, cdef-class.h, cdef-fwd.h, cdef-manager.cc, cdef-manager.h, cdef-method.cc, cdef-method.h, cdef-object.cc, cdef-object.h, cdef-package.cc, cdef-package.h, cdef-property.cc, cdef-property.h, cdef-utils.cc, cdef-utils.h, ov-base-diag.cc, ov-base-int.cc, ov-base-mat.cc, ov-base-mat.h, ov-base-scalar.cc, ov-base.cc, ov-base.h, ov-bool-mat.cc, ov-bool-mat.h, ov-bool-sparse.cc, ov-bool.cc, ov-builtin.h, ov-cell.cc, ov-ch-mat.cc, ov-class.cc, ov-class.h, ov-classdef.cc, ov-classdef.h, ov-complex.cc, ov-cx-diag.cc, ov-cx-mat.cc, ov-cx-sparse.cc, ov-dld-fcn.cc, ov-dld-fcn.h, ov-fcn-handle.cc, ov-fcn-handle.h, ov-fcn.h, ov-float.cc, ov-flt-complex.cc, ov-flt-cx-diag.cc, ov-flt-cx-mat.cc, ov-flt-re-diag.cc, ov-flt-re-mat.cc, ov-flt-re-mat.h, ov-intx.h, ov-java.cc, ov-lazy-idx.cc, ov-legacy-range.cc, ov-magic-int.cc, ov-mex-fcn.cc, ov-mex-fcn.h, ov-null-mat.cc, ov-perm.cc, ov-range.cc, ov-re-diag.cc, ov-re-mat.cc, ov-re-mat.h, ov-re-sparse.cc, ov-scalar.cc, ov-str-mat.cc, ov-struct.cc, ov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc, ov-usr-fcn.h, ov.cc, ov.h, ovl.h, octave.cc, octave.h, op-b-sbm.cc, op-bm-sbm.cc, op-cs-scm.cc, op-fm-fcm.cc, op-fs-fcm.cc, op-s-scm.cc, op-scm-cs.cc, op-scm-s.cc, op-sm-cs.cc, ops.h, anon-fcn-validator.cc, anon-fcn-validator.h, bp-table.cc, bp-table.h, comment-list.cc, comment-list.h, filepos.h, lex.h, oct-lvalue.cc, oct-lvalue.h, parse.h, profiler.cc, profiler.h, pt-anon-scopes.cc, pt-anon-scopes.h, pt-arg-list.cc, pt-arg-list.h, pt-args-block.cc, pt-args-block.h, pt-array-list.cc, pt-array-list.h, pt-assign.cc, pt-assign.h, pt-binop.cc, pt-binop.h, pt-bp.cc, pt-bp.h, pt-cbinop.cc, pt-cbinop.h, pt-cell.cc, pt-cell.h, pt-check.cc, pt-check.h, pt-classdef.cc, pt-classdef.h, pt-cmd.h, pt-colon.cc, pt-colon.h, pt-const.cc, pt-const.h, pt-decl.cc, pt-decl.h, pt-eval.cc, pt-eval.h, pt-except.cc, pt-except.h, pt-exp.cc, pt-exp.h, pt-fcn-handle.cc, pt-fcn-handle.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h, pt-jump.h, pt-loop.cc, pt-loop.h, pt-mat.cc, pt-mat.h, pt-misc.cc, pt-misc.h, pt-pr-code.cc, pt-pr-code.h, pt-select.cc, pt-select.h, pt-spmd.cc, pt-spmd.h, pt-stmt.cc, pt-stmt.h, pt-tm-const.cc, pt-tm-const.h, pt-unop.cc, pt-unop.h, pt-walk.cc, pt-walk.h, pt.cc, pt.h, token.cc, token.h, Range.cc, Range.h, idx-vector.cc, idx-vector.h, range-fwd.h, CollocWt.cc, CollocWt.h, aepbalance.cc, aepbalance.h, chol.cc, chol.h, gepbalance.cc, gepbalance.h, gsvd.cc, gsvd.h, hess.cc, hess.h, lo-mappers.cc, lo-mappers.h, lo-specfun.cc, lo-specfun.h, lu.cc, lu.h, oct-convn.cc, oct-convn.h, oct-fftw.cc, oct-fftw.h, oct-norm.cc, oct-norm.h, oct-rand.cc, oct-rand.h, oct-spparms.cc, oct-spparms.h, qr.cc, qr.h, qrp.cc, qrp.h, randgamma.cc, randgamma.h, randmtzig.cc, randmtzig.h, randpoisson.cc, randpoisson.h, schur.cc, schur.h, sparse-chol.cc, sparse-chol.h, sparse-lu.cc, sparse-lu.h, sparse-qr.cc, sparse-qr.h, svd.cc, svd.h, child-list.cc, child-list.h, dir-ops.cc, dir-ops.h, file-ops.cc, file-ops.h, file-stat.cc, file-stat.h, lo-sysdep.cc, lo-sysdep.h, lo-sysinfo.cc, lo-sysinfo.h, mach-info.cc, mach-info.h, oct-env.cc, oct-env.h, oct-group.cc, oct-group.h, oct-password.cc, oct-password.h, oct-syscalls.cc, oct-syscalls.h, oct-time.cc, oct-time.h, oct-uname.cc, oct-uname.h, action-container.cc, action-container.h, base-list.h, cmd-edit.cc, cmd-edit.h, cmd-hist.cc, cmd-hist.h, f77-fcn.h, file-info.cc, file-info.h, lo-array-errwarn.cc, lo-array-errwarn.h, lo-hash.cc, lo-hash.h, lo-ieee.h, lo-regexp.cc, lo-regexp.h, lo-utils.cc, lo-utils.h, oct-base64.cc, oct-base64.h, oct-glob.cc, oct-glob.h, oct-inttypes.h, oct-mutex.cc, oct-mutex.h, oct-refcount.h, oct-shlib.cc, oct-shlib.h, oct-sparse.cc, oct-sparse.h, oct-string.h, octave-preserve-stream-state.h, pathsearch.cc, pathsearch.h, quit.cc, quit.h, unwind-prot.cc, unwind-prot.h, url-transfer.cc, url-transfer.h: Re-indent code after switch to using namespace macros.
author Rik <rik@octave.org>
date Thu, 01 Dec 2022 18:02:15 -0800
parents e88a07dec498
children 597f3ee61a48
comparison
equal deleted inserted replaced
31605:e88a07dec498 31607:aac27ad79be6
42 #include "oct-locbuf.h" 42 #include "oct-locbuf.h"
43 #include "oct-shlib.h" 43 #include "oct-shlib.h"
44 44
45 OCTAVE_BEGIN_NAMESPACE(octave) 45 OCTAVE_BEGIN_NAMESPACE(octave)
46 46
47 static std::unordered_map<std::string, void *> gsvd_fcn; 47 static std::unordered_map<std::string, void *> gsvd_fcn;
48 48
49 static bool have_DGGSVD3 = false; 49 static bool have_DGGSVD3 = false;
50 static bool gsvd_initialized = false; 50 static bool gsvd_initialized = false;
51 51
52 /* Hack to stringize results of F77_FUNC macro. */ 52 /* Hack to stringize results of F77_FUNC macro. */
53 #define xSTRINGIZE(x) #x 53 #define xSTRINGIZE(x) #x
54 #define STRINGIZE(x) xSTRINGIZE(x) 54 #define STRINGIZE(x) xSTRINGIZE(x)
55 55
56 static void initialize_gsvd (void) 56 static void initialize_gsvd (void)
57 { 57 {
58 if (gsvd_initialized) 58 if (gsvd_initialized)
59 return; 59 return;
60 60
61 dynamic_library libs (""); 61 dynamic_library libs ("");
62 if (! libs) 62 if (! libs)
63 (*current_liboctave_error_handler) 63 (*current_liboctave_error_handler)
64 ("gsvd: unable to query LAPACK library"); 64 ("gsvd: unable to query LAPACK library");
65 65
66 have_DGGSVD3 = (libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3))) 66 have_DGGSVD3 = (libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3)))
67 != nullptr); 67 != nullptr);
68 68
69 if (have_DGGSVD3) 69 if (have_DGGSVD3)
70 { 70 {
71 gsvd_fcn["dg"] = libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3))); 71 gsvd_fcn["dg"] = libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3)));
72 gsvd_fcn["sg"] = libs.search (STRINGIZE (F77_FUNC (sggsvd3, SGGSVD3))); 72 gsvd_fcn["sg"] = libs.search (STRINGIZE (F77_FUNC (sggsvd3, SGGSVD3)));
73 gsvd_fcn["zg"] = libs.search (STRINGIZE (F77_FUNC (zggsvd3, ZGGSVD3))); 73 gsvd_fcn["zg"] = libs.search (STRINGIZE (F77_FUNC (zggsvd3, ZGGSVD3)));
74 gsvd_fcn["cg"] = libs.search (STRINGIZE (F77_FUNC (cggsvd3, CGGSVD3))); 74 gsvd_fcn["cg"] = libs.search (STRINGIZE (F77_FUNC (cggsvd3, CGGSVD3)));
75 } 75 }
76 else 76 else
77 { 77 {
78 gsvd_fcn["dg"] = libs.search (STRINGIZE (F77_FUNC (dggsvd, DGGSVD))); 78 gsvd_fcn["dg"] = libs.search (STRINGIZE (F77_FUNC (dggsvd, DGGSVD)));
79 gsvd_fcn["sg"] = libs.search (STRINGIZE (F77_FUNC (sggsvd, SGGSVD))); 79 gsvd_fcn["sg"] = libs.search (STRINGIZE (F77_FUNC (sggsvd, SGGSVD)));
80 gsvd_fcn["zg"] = libs.search (STRINGIZE (F77_FUNC (zggsvd, ZGGSVD))); 80 gsvd_fcn["zg"] = libs.search (STRINGIZE (F77_FUNC (zggsvd, ZGGSVD)));
81 gsvd_fcn["cg"] = libs.search (STRINGIZE (F77_FUNC (cggsvd, CGGSVD))); 81 gsvd_fcn["cg"] = libs.search (STRINGIZE (F77_FUNC (cggsvd, CGGSVD)));
82 } 82 }
83 83
84 gsvd_initialized = true; 84 gsvd_initialized = true;
85 } 85 }
86 86
87 /* Clean up macro namespace as soon as we are done using them */ 87 /* Clean up macro namespace as soon as we are done using them */
88 #undef xSTRINGIZE 88 #undef xSTRINGIZE
89 #undef STRINGIZE 89 #undef STRINGIZE
90 90
91 template<class T1> 91 template<class T1>
92 struct real_ggsvd_ptr 92 struct real_ggsvd_ptr
93 { 93 {
94 typedef F77_RET_T (*type) 94 typedef F77_RET_T (*type)
95 (F77_CONST_CHAR_ARG_DECL, // JOBU 95 (F77_CONST_CHAR_ARG_DECL, // JOBU
96 F77_CONST_CHAR_ARG_DECL, // JOBV 96 F77_CONST_CHAR_ARG_DECL, // JOBV
97 F77_CONST_CHAR_ARG_DECL, // JOBQ 97 F77_CONST_CHAR_ARG_DECL, // JOBQ
98 const F77_INT&, // M 98 const F77_INT&, // M
99 const F77_INT&, // N 99 const F77_INT&, // N
100 const F77_INT&, // P 100 const F77_INT&, // P
101 F77_INT&, // K 101 F77_INT&, // K
102 F77_INT&, // L 102 F77_INT&, // L
103 T1 *, // A(LDA,N) 103 T1 *, // A(LDA,N)
104 const F77_INT&, // LDA 104 const F77_INT&, // LDA
105 T1 *, // B(LDB,N) 105 T1 *, // B(LDB,N)
106 const F77_INT&, // LDB 106 const F77_INT&, // LDB
107 T1 *, // ALPHA(N) 107 T1 *, // ALPHA(N)
108 T1 *, // BETA(N) 108 T1 *, // BETA(N)
109 T1 *, // U(LDU,M) 109 T1 *, // U(LDU,M)
110 const F77_INT&, // LDU 110 const F77_INT&, // LDU
111 T1 *, // V(LDV,P) 111 T1 *, // V(LDV,P)
112 const F77_INT&, // LDV 112 const F77_INT&, // LDV
113 T1 *, // Q(LDQ,N) 113 T1 *, // Q(LDQ,N)
114 const F77_INT&, // LDQ 114 const F77_INT&, // LDQ
115 T1 *, // WORK 115 T1 *, // WORK
116 F77_INT *, // IWORK(N) 116 F77_INT *, // IWORK(N)
117 F77_INT& // INFO 117 F77_INT& // INFO
118 F77_CHAR_ARG_LEN_DECL 118 F77_CHAR_ARG_LEN_DECL
119 F77_CHAR_ARG_LEN_DECL 119 F77_CHAR_ARG_LEN_DECL
120 F77_CHAR_ARG_LEN_DECL); 120 F77_CHAR_ARG_LEN_DECL);
121 }; 121 };
122 122
123 template<class T1> 123 template<class T1>
124 struct real_ggsvd3_ptr 124 struct real_ggsvd3_ptr
125 { 125 {
126 typedef F77_RET_T (*type) 126 typedef F77_RET_T (*type)
127 (F77_CONST_CHAR_ARG_DECL, // JOBU 127 (F77_CONST_CHAR_ARG_DECL, // JOBU
128 F77_CONST_CHAR_ARG_DECL, // JOBV 128 F77_CONST_CHAR_ARG_DECL, // JOBV
129 F77_CONST_CHAR_ARG_DECL, // JOBQ 129 F77_CONST_CHAR_ARG_DECL, // JOBQ
130 const F77_INT&, // M 130 const F77_INT&, // M
131 const F77_INT&, // N 131 const F77_INT&, // N
132 const F77_INT&, // P 132 const F77_INT&, // P
133 F77_INT&, // K 133 F77_INT&, // K
134 F77_INT&, // L 134 F77_INT&, // L
135 T1 *, // A(LDA,N) 135 T1 *, // A(LDA,N)
136 const F77_INT&, // LDA 136 const F77_INT&, // LDA
137 T1 *, // B(LDB,N) 137 T1 *, // B(LDB,N)
138 const F77_INT&, // LDB 138 const F77_INT&, // LDB
139 T1 *, // ALPHA(N) 139 T1 *, // ALPHA(N)
140 T1 *, // BETA(N) 140 T1 *, // BETA(N)
141 T1 *, // U(LDU,M) 141 T1 *, // U(LDU,M)
142 const F77_INT&, // LDU 142 const F77_INT&, // LDU
143 T1 *, // V(LDV,P) 143 T1 *, // V(LDV,P)
144 const F77_INT&, // LDV 144 const F77_INT&, // LDV
145 T1 *, // Q(LDQ,N) 145 T1 *, // Q(LDQ,N)
146 const F77_INT&, // LDQ 146 const F77_INT&, // LDQ
147 T1 *, // WORK 147 T1 *, // WORK
148 const F77_INT&, // LWORK 148 const F77_INT&, // LWORK
149 F77_INT *, // IWORK(N) 149 F77_INT *, // IWORK(N)
150 F77_INT& // INFO 150 F77_INT& // INFO
151 F77_CHAR_ARG_LEN_DECL 151 F77_CHAR_ARG_LEN_DECL
152 F77_CHAR_ARG_LEN_DECL 152 F77_CHAR_ARG_LEN_DECL
153 F77_CHAR_ARG_LEN_DECL); 153 F77_CHAR_ARG_LEN_DECL);
154 }; 154 };
155 155
156 template<class T1, class T2> 156 template<class T1, class T2>
157 struct comp_ggsvd_ptr 157 struct comp_ggsvd_ptr
158 { 158 {
159 typedef F77_RET_T (*type) 159 typedef F77_RET_T (*type)
160 (F77_CONST_CHAR_ARG_DECL, // JOBU 160 (F77_CONST_CHAR_ARG_DECL, // JOBU
161 F77_CONST_CHAR_ARG_DECL, // JOBV 161 F77_CONST_CHAR_ARG_DECL, // JOBV
162 F77_CONST_CHAR_ARG_DECL, // JOBQ 162 F77_CONST_CHAR_ARG_DECL, // JOBQ
163 const F77_INT&, // M 163 const F77_INT&, // M
164 const F77_INT&, // N 164 const F77_INT&, // N
165 const F77_INT&, // P 165 const F77_INT&, // P
166 F77_INT&, // K 166 F77_INT&, // K
167 F77_INT&, // L 167 F77_INT&, // L
168 T1 *, // A(LDA,N) 168 T1 *, // A(LDA,N)
169 const F77_INT&, // LDA 169 const F77_INT&, // LDA
170 T1 *, // B(LDB,N) 170 T1 *, // B(LDB,N)
171 const F77_INT&, // LDB 171 const F77_INT&, // LDB
172 T2 *, // ALPHA(N) 172 T2 *, // ALPHA(N)
173 T2 *, // BETA(N) 173 T2 *, // BETA(N)
174 T1 *, // U(LDU,M) 174 T1 *, // U(LDU,M)
175 const F77_INT&, // LDU 175 const F77_INT&, // LDU
176 T1 *, // V(LDV,P) 176 T1 *, // V(LDV,P)
177 const F77_INT&, // LDV 177 const F77_INT&, // LDV
178 T1 *, // Q(LDQ,N) 178 T1 *, // Q(LDQ,N)
179 const F77_INT&, // LDQ 179 const F77_INT&, // LDQ
180 T1 *, // WORK 180 T1 *, // WORK
181 T2 *, // RWORK 181 T2 *, // RWORK
182 F77_INT *, // IWORK(N) 182 F77_INT *, // IWORK(N)
183 F77_INT& // INFO 183 F77_INT& // INFO
184 F77_CHAR_ARG_LEN_DECL 184 F77_CHAR_ARG_LEN_DECL
185 F77_CHAR_ARG_LEN_DECL 185 F77_CHAR_ARG_LEN_DECL
186 F77_CHAR_ARG_LEN_DECL); 186 F77_CHAR_ARG_LEN_DECL);
187 }; 187 };
188 188
189 template<class T1, class T2> 189 template<class T1, class T2>
190 struct comp_ggsvd3_ptr 190 struct comp_ggsvd3_ptr
191 { 191 {
192 typedef F77_RET_T (*type) 192 typedef F77_RET_T (*type)
193 (F77_CONST_CHAR_ARG_DECL, // JOBU 193 (F77_CONST_CHAR_ARG_DECL, // JOBU
194 F77_CONST_CHAR_ARG_DECL, // JOBV 194 F77_CONST_CHAR_ARG_DECL, // JOBV
195 F77_CONST_CHAR_ARG_DECL, // JOBQ 195 F77_CONST_CHAR_ARG_DECL, // JOBQ
196 const F77_INT&, // M 196 const F77_INT&, // M
197 const F77_INT&, // N 197 const F77_INT&, // N
198 const F77_INT&, // P 198 const F77_INT&, // P
199 F77_INT&, // K 199 F77_INT&, // K
200 F77_INT&, // L 200 F77_INT&, // L
201 T1 *, // A(LDA,N) 201 T1 *, // A(LDA,N)
202 const F77_INT&, // LDA 202 const F77_INT&, // LDA
203 T1 *, // B(LDB,N) 203 T1 *, // B(LDB,N)
204 const F77_INT&, // LDB 204 const F77_INT&, // LDB
205 T2 *, // ALPHA(N) 205 T2 *, // ALPHA(N)
206 T2 *, // BETA(N) 206 T2 *, // BETA(N)
207 T1 *, // U(LDU,M) 207 T1 *, // U(LDU,M)
208 const F77_INT&, // LDU 208 const F77_INT&, // LDU
209 T1 *, // V(LDV,P) 209 T1 *, // V(LDV,P)
210 const F77_INT&, // LDV 210 const F77_INT&, // LDV
211 T1 *, // Q(LDQ,N) 211 T1 *, // Q(LDQ,N)
212 const F77_INT&, // LDQ 212 const F77_INT&, // LDQ
213 T1 *, // WORK 213 T1 *, // WORK
214 const F77_INT&, // LWORK 214 const F77_INT&, // LWORK
215 T2 *, // RWORK 215 T2 *, // RWORK
216 F77_INT *, // IWORK(N) 216 F77_INT *, // IWORK(N)
217 F77_INT& // INFO 217 F77_INT& // INFO
218 F77_CHAR_ARG_LEN_DECL 218 F77_CHAR_ARG_LEN_DECL
219 F77_CHAR_ARG_LEN_DECL 219 F77_CHAR_ARG_LEN_DECL
220 F77_CHAR_ARG_LEN_DECL); 220 F77_CHAR_ARG_LEN_DECL);
221 }; 221 };
222 222
223 // template specializations 223 // template specializations
224 typedef real_ggsvd_ptr<F77_DBLE>::type dggsvd_type; 224 typedef real_ggsvd_ptr<F77_DBLE>::type dggsvd_type;
225 typedef real_ggsvd3_ptr<F77_DBLE>::type dggsvd3_type; 225 typedef real_ggsvd3_ptr<F77_DBLE>::type dggsvd3_type;
226 typedef real_ggsvd_ptr<F77_REAL>::type sggsvd_type; 226 typedef real_ggsvd_ptr<F77_REAL>::type sggsvd_type;
227 typedef real_ggsvd3_ptr<F77_REAL>::type sggsvd3_type; 227 typedef real_ggsvd3_ptr<F77_REAL>::type sggsvd3_type;
228 typedef comp_ggsvd_ptr<F77_DBLE_CMPLX, F77_DBLE>::type zggsvd_type; 228 typedef comp_ggsvd_ptr<F77_DBLE_CMPLX, F77_DBLE>::type zggsvd_type;
229 typedef comp_ggsvd3_ptr<F77_DBLE_CMPLX, F77_DBLE>::type zggsvd3_type; 229 typedef comp_ggsvd3_ptr<F77_DBLE_CMPLX, F77_DBLE>::type zggsvd3_type;
230 typedef comp_ggsvd_ptr<F77_CMPLX, F77_REAL>::type cggsvd_type; 230 typedef comp_ggsvd_ptr<F77_CMPLX, F77_REAL>::type cggsvd_type;
231 typedef comp_ggsvd3_ptr<F77_CMPLX, F77_REAL>::type cggsvd3_type; 231 typedef comp_ggsvd3_ptr<F77_CMPLX, F77_REAL>::type cggsvd3_type;
232 232
233 OCTAVE_BEGIN_NAMESPACE(math) 233 OCTAVE_BEGIN_NAMESPACE(math)
234 234
235 template <> 235 template <>
236 void 236 void
237 gsvd<Matrix>::ggsvd (char& jobu, char& jobv, char& jobq, F77_INT m, 237 gsvd<Matrix>::ggsvd (char& jobu, char& jobv, char& jobq, F77_INT m,
238 F77_INT n, F77_INT p, F77_INT& k, F77_INT& l, 238 F77_INT n, F77_INT p, F77_INT& k, F77_INT& l,
239 double *tmp_dataA, F77_INT m1, double *tmp_dataB, 239 double *tmp_dataA, F77_INT m1, double *tmp_dataB,
240 F77_INT p1, Matrix& alpha, Matrix& beta, double *u, 240 F77_INT p1, Matrix& alpha, Matrix& beta, double *u,
241 F77_INT nrow_u, double *v, F77_INT nrow_v, double *q, 241 F77_INT nrow_u, double *v, F77_INT nrow_v, double *q,
242 F77_INT nrow_q, double *work, F77_INT lwork, 242 F77_INT nrow_q, double *work, F77_INT lwork,
243 F77_INT *iwork, F77_INT& info) 243 F77_INT *iwork, F77_INT& info)
244 { 244 {
245 if (! gsvd_initialized) 245 if (! gsvd_initialized)
246 initialize_gsvd (); 246 initialize_gsvd ();
247 247
248 if (have_DGGSVD3) 248 if (have_DGGSVD3)
249 {
250 dggsvd3_type f_ptr = reinterpret_cast<dggsvd3_type> (gsvd_fcn["dg"]);
251 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
252 F77_CONST_CHAR_ARG2 (&jobv, 1),
253 F77_CONST_CHAR_ARG2 (&jobq, 1),
254 m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,
255 alpha.fortran_vec (), beta.fortran_vec (),
256 u, nrow_u, v, nrow_v, q, nrow_q,
257 work, lwork, iwork, info
258 F77_CHAR_ARG_LEN (1)
259 F77_CHAR_ARG_LEN (1)
260 F77_CHAR_ARG_LEN (1));
261 }
262 else
263 {
264 dggsvd_type f_ptr = reinterpret_cast<dggsvd_type> (gsvd_fcn["dg"]);
265 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
266 F77_CONST_CHAR_ARG2 (&jobv, 1),
267 F77_CONST_CHAR_ARG2 (&jobq, 1),
268 m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,
269 alpha.fortran_vec (), beta.fortran_vec (),
270 u, nrow_u, v, nrow_v, q, nrow_q,
271 work, iwork, info
272 F77_CHAR_ARG_LEN (1)
273 F77_CHAR_ARG_LEN (1)
274 F77_CHAR_ARG_LEN (1));
275 }
276 }
277
278 template <>
279 void
280 gsvd<FloatMatrix>::ggsvd (char& jobu, char& jobv, char& jobq, F77_INT m,
281 F77_INT n, F77_INT p, F77_INT& k, F77_INT& l,
282 float *tmp_dataA, F77_INT m1, float *tmp_dataB,
283 F77_INT p1, FloatMatrix& alpha,
284 FloatMatrix& beta, float *u, F77_INT nrow_u,
285 float *v, F77_INT nrow_v, float *q,
286 F77_INT nrow_q, float *work,
287 F77_INT lwork, F77_INT *iwork, F77_INT& info)
288 {
289 if (! gsvd_initialized)
290 initialize_gsvd ();
291
292 if (have_DGGSVD3)
293 {
294 sggsvd3_type f_ptr = reinterpret_cast<sggsvd3_type> (gsvd_fcn["sg"]);
295 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
296 F77_CONST_CHAR_ARG2 (&jobv, 1),
297 F77_CONST_CHAR_ARG2 (&jobq, 1),
298 m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,
299 alpha.fortran_vec (), beta.fortran_vec (),
300 u, nrow_u, v, nrow_v, q, nrow_q,
301 work, lwork, iwork, info
302 F77_CHAR_ARG_LEN (1)
303 F77_CHAR_ARG_LEN (1)
304 F77_CHAR_ARG_LEN (1));
305 }
306 else
307 {
308 sggsvd_type f_ptr = reinterpret_cast<sggsvd_type> (gsvd_fcn["sg"]);
309 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
310 F77_CONST_CHAR_ARG2 (&jobv, 1),
311 F77_CONST_CHAR_ARG2 (&jobq, 1),
312 m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,
313 alpha.fortran_vec (), beta.fortran_vec (),
314 u, nrow_u, v, nrow_v, q, nrow_q,
315 work, iwork, info
316 F77_CHAR_ARG_LEN (1)
317 F77_CHAR_ARG_LEN (1)
318 F77_CHAR_ARG_LEN (1));
319 }
320 }
321
322 template <>
323 void
324 gsvd<ComplexMatrix>::ggsvd (char& jobu, char& jobv, char& jobq,
325 F77_INT m, F77_INT n, F77_INT p, F77_INT& k,
326 F77_INT& l, Complex *tmp_dataA, F77_INT m1,
327 Complex *tmp_dataB, F77_INT p1, Matrix& alpha,
328 Matrix& beta, Complex *u, F77_INT nrow_u,
329 Complex *v, F77_INT nrow_v, Complex *q,
330 F77_INT nrow_q, Complex *work,
331 F77_INT lwork, F77_INT *iwork, F77_INT& info)
332 {
333 if (! gsvd_initialized)
334 initialize_gsvd ();
335
336 OCTAVE_LOCAL_BUFFER(double, rwork, 2*n);
337
338 if (have_DGGSVD3)
339 {
340 zggsvd3_type f_ptr = reinterpret_cast<zggsvd3_type> (gsvd_fcn["zg"]);
341 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
342 F77_CONST_CHAR_ARG2 (&jobv, 1),
343 F77_CONST_CHAR_ARG2 (&jobq, 1),
344 m, n, p, k, l,
345 F77_DBLE_CMPLX_ARG (tmp_dataA), m1,
346 F77_DBLE_CMPLX_ARG (tmp_dataB), p1,
347 alpha.fortran_vec (), beta.fortran_vec (),
348 F77_DBLE_CMPLX_ARG (u), nrow_u,
349 F77_DBLE_CMPLX_ARG (v), nrow_v,
350 F77_DBLE_CMPLX_ARG (q), nrow_q,
351 F77_DBLE_CMPLX_ARG (work),
352 lwork, rwork, iwork, info
353 F77_CHAR_ARG_LEN (1)
354 F77_CHAR_ARG_LEN (1)
355 F77_CHAR_ARG_LEN (1));
356 }
357 else
358 {
359 zggsvd_type f_ptr = reinterpret_cast<zggsvd_type> (gsvd_fcn["zg"]);
360 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
361 F77_CONST_CHAR_ARG2 (&jobv, 1),
362 F77_CONST_CHAR_ARG2 (&jobq, 1),
363 m, n, p, k, l,
364 F77_DBLE_CMPLX_ARG (tmp_dataA), m1,
365 F77_DBLE_CMPLX_ARG (tmp_dataB), p1,
366 alpha.fortran_vec (), beta.fortran_vec (),
367 F77_DBLE_CMPLX_ARG (u), nrow_u,
368 F77_DBLE_CMPLX_ARG (v), nrow_v,
369 F77_DBLE_CMPLX_ARG (q), nrow_q,
370 F77_DBLE_CMPLX_ARG (work),
371 rwork, iwork, info
372 F77_CHAR_ARG_LEN (1)
373 F77_CHAR_ARG_LEN (1)
374 F77_CHAR_ARG_LEN (1));
375 }
376 }
377
378 template <>
379 void
380 gsvd<FloatComplexMatrix>::ggsvd (char& jobu, char& jobv, char& jobq,
381 F77_INT m, F77_INT n, F77_INT p,
382 F77_INT& k, F77_INT& l,
383 FloatComplex *tmp_dataA, F77_INT m1,
384 FloatComplex *tmp_dataB, F77_INT p1,
385 FloatMatrix& alpha, FloatMatrix& beta,
386 FloatComplex *u, F77_INT nrow_u,
387 FloatComplex *v, F77_INT nrow_v,
388 FloatComplex *q, F77_INT nrow_q,
389 FloatComplex *work, F77_INT lwork,
390 F77_INT *iwork, F77_INT& info)
391 {
392 if (! gsvd_initialized)
393 initialize_gsvd ();
394
395 OCTAVE_LOCAL_BUFFER(float, rwork, 2*n);
396
397 if (have_DGGSVD3)
398 {
399 cggsvd3_type f_ptr = reinterpret_cast<cggsvd3_type> (gsvd_fcn["cg"]);
400 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
401 F77_CONST_CHAR_ARG2 (&jobv, 1),
402 F77_CONST_CHAR_ARG2 (&jobq, 1),
403 m, n, p, k, l,
404 F77_CMPLX_ARG (tmp_dataA), m1,
405 F77_CMPLX_ARG (tmp_dataB), p1,
406 alpha.fortran_vec (), beta.fortran_vec (),
407 F77_CMPLX_ARG (u), nrow_u,
408 F77_CMPLX_ARG (v), nrow_v,
409 F77_CMPLX_ARG (q), nrow_q,
410 F77_CMPLX_ARG (work), lwork,
411 rwork, iwork, info
412 F77_CHAR_ARG_LEN (1)
413 F77_CHAR_ARG_LEN (1)
414 F77_CHAR_ARG_LEN (1));
415 }
416 else
417 {
418 cggsvd_type f_ptr = reinterpret_cast<cggsvd_type> (gsvd_fcn["cg"]);
419 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
420 F77_CONST_CHAR_ARG2 (&jobv, 1),
421 F77_CONST_CHAR_ARG2 (&jobq, 1),
422 m, n, p, k, l,
423 F77_CMPLX_ARG (tmp_dataA), m1,
424 F77_CMPLX_ARG (tmp_dataB), p1,
425 alpha.fortran_vec (), beta.fortran_vec (),
426 F77_CMPLX_ARG (u), nrow_u,
427 F77_CMPLX_ARG (v), nrow_v,
428 F77_CMPLX_ARG (q), nrow_q,
429 F77_CMPLX_ARG (work),
430 rwork, iwork, info
431 F77_CHAR_ARG_LEN (1)
432 F77_CHAR_ARG_LEN (1)
433 F77_CHAR_ARG_LEN (1));
434 }
435 }
436
437 template <typename T>
438 T
439 gsvd<T>::left_singular_matrix_A (void) const
440 {
441 if (m_type == gsvd::Type::sigma_only)
442 (*current_liboctave_error_handler)
443 ("gsvd: U not computed because type == gsvd::sigma_only");
444
445 return m_left_smA;
446 }
447
448 template <typename T>
449 T
450 gsvd<T>::left_singular_matrix_B (void) const
451 {
452 if (m_type == gsvd::Type::sigma_only)
453 (*current_liboctave_error_handler)
454 ("gsvd: V not computed because type == gsvd::sigma_only");
455
456 return m_left_smB;
457 }
458
459 template <typename T>
460 T
461 gsvd<T>::right_singular_matrix (void) const
462 {
463 if (m_type == gsvd::Type::sigma_only)
464 (*current_liboctave_error_handler)
465 ("gsvd: X not computed because type == gsvd::sigma_only");
466
467 return m_right_sm;
468 }
469
470 template <typename T>
471 gsvd<T>::gsvd (const T& a, const T& b, gsvd::Type gsvd_type)
472 {
473 if (a.isempty () || b.isempty ())
474 (*current_liboctave_error_handler)
475 ("gsvd: A and B cannot be empty matrices");
476
477 F77_INT info;
478
479 F77_INT m = to_f77_int (a.rows ());
480 F77_INT n = to_f77_int (a.cols ());
481 F77_INT p = to_f77_int (b.rows ());
482
483 T atmp = a;
484 P *tmp_dataA = atmp.fortran_vec ();
485
486 T btmp = b;
487 P *tmp_dataB = btmp.fortran_vec ();
488
489 char jobu = 'U';
490 char jobv = 'V';
491 char jobq = 'Q';
492
493 F77_INT nrow_u = m;
494 F77_INT nrow_v = p;
495 F77_INT nrow_q = n;
496
497 F77_INT k, l;
498
499 switch (gsvd_type)
500 {
501 case gsvd<T>::Type::sigma_only:
502
503 // FIXME: In LAPACK 3.0, problem below seems to be fixed,
504 // so we now set jobX = 'N'.
505 //
506 // For calculating sigma_only, both jobu and jobv should be 'N', but
507 // there seems to be a bug in dgesvd from LAPACK V2.0. To
508 // demonstrate the bug, set both jobu and jobv to 'N' and find the
509 // singular values of [eye(3), eye(3)]. The result is
510 // [-sqrt(2), -sqrt(2), -sqrt(2)].
511
512 jobu = jobv = jobq = 'N';
513 nrow_u = nrow_v = nrow_q = 1;
514 break;
515
516 default:
517 break;
518 }
519
520 m_type = gsvd_type;
521
522 if (jobu != 'N')
523 m_left_smA.resize (nrow_u, m);
524
525 P *u = m_left_smA.fortran_vec ();
526
527 if (jobv != 'N')
528 m_left_smB.resize (nrow_v, p);
529
530 P *v = m_left_smB.fortran_vec ();
531
532 if (jobq != 'N')
533 m_right_sm.resize (nrow_q, n);
534
535 P *q = m_right_sm.fortran_vec ();
536
537 real_matrix alpha (n, 1);
538 real_matrix beta (n, 1);
539
540 OCTAVE_LOCAL_BUFFER(F77_INT, iwork, n);
541
542 if (! gsvd_initialized)
543 initialize_gsvd ();
544
545 F77_INT lwork;
546 if (have_DGGSVD3)
547 {
548 lwork = -1;
549 P work_tmp;
550
551 gsvd<T>::ggsvd (jobu, jobv, jobq, m, n, p, k, l,
552 tmp_dataA, m, tmp_dataB, p,
553 alpha, beta, u, nrow_u, v, nrow_v, q, nrow_q,
554 &work_tmp, lwork, iwork, info);
555
556 lwork = static_cast<F77_INT> (std::abs (work_tmp));
557 }
558 else
559 {
560 lwork = std::max ({3*n, m, p}) + n;
561 }
562 info = 0;
563
564 OCTAVE_LOCAL_BUFFER(P, work, lwork);
565
566 gsvd<T>::ggsvd (jobu, jobv, jobq, m, n, p, k, l,
567 tmp_dataA, m, tmp_dataB, p,
568 alpha, beta, u, nrow_u, v, nrow_v, q, nrow_q,
569 work, lwork, iwork, info);
570
571 if (info < 0)
572 (*current_liboctave_error_handler)
573 ("*ggsvd.f: argument %" OCTAVE_F77_INT_TYPE_FORMAT " illegal",
574 -info);
575
576 if (info > 0)
577 (*current_liboctave_error_handler)
578 ("*ggsvd.f: Jacobi-type procedure failed to converge");
579
580 F77_INT i, j;
581
582 if (gsvd_type != gsvd<T>::Type::sigma_only)
583 {
584 // Size according to LAPACK is k+l,k+l, but this needs
585 // to be nxn for Matlab compatibility.
586 T R (n, n, 0.0);
587 int astart = n-k-l;
588 if (m - k - l >= 0)
249 { 589 {
250 dggsvd3_type f_ptr = reinterpret_cast<dggsvd3_type> (gsvd_fcn["dg"]); 590 // R is stored in A(1:K+L,N-K-L+1:N)
251 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), 591 for (i = 0; i < k+l; i++)
252 F77_CONST_CHAR_ARG2 (&jobv, 1), 592 for (j = 0; j < k+l; j++)
253 F77_CONST_CHAR_ARG2 (&jobq, 1), 593 R.xelem (i, j) = atmp.xelem (i, astart + j);
254 m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,
255 alpha.fortran_vec (), beta.fortran_vec (),
256 u, nrow_u, v, nrow_v, q, nrow_q,
257 work, lwork, iwork, info
258 F77_CHAR_ARG_LEN (1)
259 F77_CHAR_ARG_LEN (1)
260 F77_CHAR_ARG_LEN (1));
261 } 594 }
262 else 595 else
263 { 596 {
264 dggsvd_type f_ptr = reinterpret_cast<dggsvd_type> (gsvd_fcn["dg"]); 597 // (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N)
265 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), 598 // ( 0 R22 R23 )
266 F77_CONST_CHAR_ARG2 (&jobv, 1), 599 for (i = 0; i < m; i++)
267 F77_CONST_CHAR_ARG2 (&jobq, 1), 600 for (j = 0; j < k+l; j++)
268 m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1, 601 R.xelem (i, j) = atmp.xelem (i, astart + j);
269 alpha.fortran_vec (), beta.fortran_vec (), 602 // and R33 is stored in B(M-K+1:L,N+M-K-L+1:N)
270 u, nrow_u, v, nrow_v, q, nrow_q, 603 for (i = m; i < k + l; i++)
271 work, iwork, info 604 for (j = n - l - k + m; j < n; j++)
272 F77_CHAR_ARG_LEN (1) 605 R.xelem (i, j) = btmp.xelem (i - k, j);
273 F77_CHAR_ARG_LEN (1)
274 F77_CHAR_ARG_LEN (1));
275 } 606 }
276 } 607
277 608 // Output X = Q*R'
278 template <> 609 // FIXME: Is there a way to call BLAS multiply directly
279 void 610 // with flags so that R is transposed?
280 gsvd<FloatMatrix>::ggsvd (char& jobu, char& jobv, char& jobq, F77_INT m, 611 m_right_sm = m_right_sm * R.hermitian ();
281 F77_INT n, F77_INT p, F77_INT& k, F77_INT& l, 612 }
282 float *tmp_dataA, F77_INT m1, float *tmp_dataB, 613
283 F77_INT p1, FloatMatrix& alpha, 614 // Fill in C and S
284 FloatMatrix& beta, float *u, F77_INT nrow_u, 615 F77_INT rank;
285 float *v, F77_INT nrow_v, float *q, 616 bool fill_ptn;
286 F77_INT nrow_q, float *work, 617 if (m-k-l >= 0)
287 F77_INT lwork, F77_INT *iwork, F77_INT& info) 618 {
288 { 619 rank = l;
289 if (! gsvd_initialized) 620 fill_ptn = true;
290 initialize_gsvd (); 621 }
291 622 else
292 if (have_DGGSVD3) 623 {
624 rank = m-k;
625 fill_ptn = false;
626 }
627
628 if (gsvd_type == gsvd<T>::Type::sigma_only)
629 {
630 // Return column vector with results
631 m_sigmaA.resize (k+l, 1);
632 m_sigmaB.resize (k+l, 1);
633
634 if (fill_ptn)
293 { 635 {
294 sggsvd3_type f_ptr = reinterpret_cast<sggsvd3_type> (gsvd_fcn["sg"]); 636 for (i = 0; i < k; i++)
295 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), 637 {
296 F77_CONST_CHAR_ARG2 (&jobv, 1), 638 m_sigmaA.xelem (i) = 1.0;
297 F77_CONST_CHAR_ARG2 (&jobq, 1), 639 m_sigmaB.xelem (i) = 0.0;
298 m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1, 640 }
299 alpha.fortran_vec (), beta.fortran_vec (), 641 for (i = k, j = k+l-1; i < k+l; i++, j--)
300 u, nrow_u, v, nrow_v, q, nrow_q, 642 {
301 work, lwork, iwork, info 643 m_sigmaA.xelem (i) = alpha.xelem (i);
302 F77_CHAR_ARG_LEN (1) 644 m_sigmaB.xelem (i) = beta.xelem (i);
303 F77_CHAR_ARG_LEN (1) 645 }
304 F77_CHAR_ARG_LEN (1));
305 } 646 }
306 else 647 else
307 { 648 {
308 sggsvd_type f_ptr = reinterpret_cast<sggsvd_type> (gsvd_fcn["sg"]); 649 for (i = 0; i < k; i++)
309 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
310 F77_CONST_CHAR_ARG2 (&jobv, 1),
311 F77_CONST_CHAR_ARG2 (&jobq, 1),
312 m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,
313 alpha.fortran_vec (), beta.fortran_vec (),
314 u, nrow_u, v, nrow_v, q, nrow_q,
315 work, iwork, info
316 F77_CHAR_ARG_LEN (1)
317 F77_CHAR_ARG_LEN (1)
318 F77_CHAR_ARG_LEN (1));
319 }
320 }
321
322 template <>
323 void
324 gsvd<ComplexMatrix>::ggsvd (char& jobu, char& jobv, char& jobq,
325 F77_INT m, F77_INT n, F77_INT p, F77_INT& k,
326 F77_INT& l, Complex *tmp_dataA, F77_INT m1,
327 Complex *tmp_dataB, F77_INT p1, Matrix& alpha,
328 Matrix& beta, Complex *u, F77_INT nrow_u,
329 Complex *v, F77_INT nrow_v, Complex *q,
330 F77_INT nrow_q, Complex *work,
331 F77_INT lwork, F77_INT *iwork, F77_INT& info)
332 {
333 if (! gsvd_initialized)
334 initialize_gsvd ();
335
336 OCTAVE_LOCAL_BUFFER(double, rwork, 2*n);
337
338 if (have_DGGSVD3)
339 {
340 zggsvd3_type f_ptr = reinterpret_cast<zggsvd3_type> (gsvd_fcn["zg"]);
341 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
342 F77_CONST_CHAR_ARG2 (&jobv, 1),
343 F77_CONST_CHAR_ARG2 (&jobq, 1),
344 m, n, p, k, l,
345 F77_DBLE_CMPLX_ARG (tmp_dataA), m1,
346 F77_DBLE_CMPLX_ARG (tmp_dataB), p1,
347 alpha.fortran_vec (), beta.fortran_vec (),
348 F77_DBLE_CMPLX_ARG (u), nrow_u,
349 F77_DBLE_CMPLX_ARG (v), nrow_v,
350 F77_DBLE_CMPLX_ARG (q), nrow_q,
351 F77_DBLE_CMPLX_ARG (work),
352 lwork, rwork, iwork, info
353 F77_CHAR_ARG_LEN (1)
354 F77_CHAR_ARG_LEN (1)
355 F77_CHAR_ARG_LEN (1));
356 }
357 else
358 {
359 zggsvd_type f_ptr = reinterpret_cast<zggsvd_type> (gsvd_fcn["zg"]);
360 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
361 F77_CONST_CHAR_ARG2 (&jobv, 1),
362 F77_CONST_CHAR_ARG2 (&jobq, 1),
363 m, n, p, k, l,
364 F77_DBLE_CMPLX_ARG (tmp_dataA), m1,
365 F77_DBLE_CMPLX_ARG (tmp_dataB), p1,
366 alpha.fortran_vec (), beta.fortran_vec (),
367 F77_DBLE_CMPLX_ARG (u), nrow_u,
368 F77_DBLE_CMPLX_ARG (v), nrow_v,
369 F77_DBLE_CMPLX_ARG (q), nrow_q,
370 F77_DBLE_CMPLX_ARG (work),
371 rwork, iwork, info
372 F77_CHAR_ARG_LEN (1)
373 F77_CHAR_ARG_LEN (1)
374 F77_CHAR_ARG_LEN (1));
375 }
376 }
377
378 template <>
379 void
380 gsvd<FloatComplexMatrix>::ggsvd (char& jobu, char& jobv, char& jobq,
381 F77_INT m, F77_INT n, F77_INT p,
382 F77_INT& k, F77_INT& l,
383 FloatComplex *tmp_dataA, F77_INT m1,
384 FloatComplex *tmp_dataB, F77_INT p1,
385 FloatMatrix& alpha, FloatMatrix& beta,
386 FloatComplex *u, F77_INT nrow_u,
387 FloatComplex *v, F77_INT nrow_v,
388 FloatComplex *q, F77_INT nrow_q,
389 FloatComplex *work, F77_INT lwork,
390 F77_INT *iwork, F77_INT& info)
391 {
392 if (! gsvd_initialized)
393 initialize_gsvd ();
394
395 OCTAVE_LOCAL_BUFFER(float, rwork, 2*n);
396
397 if (have_DGGSVD3)
398 {
399 cggsvd3_type f_ptr = reinterpret_cast<cggsvd3_type> (gsvd_fcn["cg"]);
400 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
401 F77_CONST_CHAR_ARG2 (&jobv, 1),
402 F77_CONST_CHAR_ARG2 (&jobq, 1),
403 m, n, p, k, l,
404 F77_CMPLX_ARG (tmp_dataA), m1,
405 F77_CMPLX_ARG (tmp_dataB), p1,
406 alpha.fortran_vec (), beta.fortran_vec (),
407 F77_CMPLX_ARG (u), nrow_u,
408 F77_CMPLX_ARG (v), nrow_v,
409 F77_CMPLX_ARG (q), nrow_q,
410 F77_CMPLX_ARG (work), lwork,
411 rwork, iwork, info
412 F77_CHAR_ARG_LEN (1)
413 F77_CHAR_ARG_LEN (1)
414 F77_CHAR_ARG_LEN (1));
415 }
416 else
417 {
418 cggsvd_type f_ptr = reinterpret_cast<cggsvd_type> (gsvd_fcn["cg"]);
419 f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1),
420 F77_CONST_CHAR_ARG2 (&jobv, 1),
421 F77_CONST_CHAR_ARG2 (&jobq, 1),
422 m, n, p, k, l,
423 F77_CMPLX_ARG (tmp_dataA), m1,
424 F77_CMPLX_ARG (tmp_dataB), p1,
425 alpha.fortran_vec (), beta.fortran_vec (),
426 F77_CMPLX_ARG (u), nrow_u,
427 F77_CMPLX_ARG (v), nrow_v,
428 F77_CMPLX_ARG (q), nrow_q,
429 F77_CMPLX_ARG (work),
430 rwork, iwork, info
431 F77_CHAR_ARG_LEN (1)
432 F77_CHAR_ARG_LEN (1)
433 F77_CHAR_ARG_LEN (1));
434 }
435 }
436
437 template <typename T>
438 T
439 gsvd<T>::left_singular_matrix_A (void) const
440 {
441 if (m_type == gsvd::Type::sigma_only)
442 (*current_liboctave_error_handler)
443 ("gsvd: U not computed because type == gsvd::sigma_only");
444
445 return m_left_smA;
446 }
447
448 template <typename T>
449 T
450 gsvd<T>::left_singular_matrix_B (void) const
451 {
452 if (m_type == gsvd::Type::sigma_only)
453 (*current_liboctave_error_handler)
454 ("gsvd: V not computed because type == gsvd::sigma_only");
455
456 return m_left_smB;
457 }
458
459 template <typename T>
460 T
461 gsvd<T>::right_singular_matrix (void) const
462 {
463 if (m_type == gsvd::Type::sigma_only)
464 (*current_liboctave_error_handler)
465 ("gsvd: X not computed because type == gsvd::sigma_only");
466
467 return m_right_sm;
468 }
469
470 template <typename T>
471 gsvd<T>::gsvd (const T& a, const T& b, gsvd::Type gsvd_type)
472 {
473 if (a.isempty () || b.isempty ())
474 (*current_liboctave_error_handler)
475 ("gsvd: A and B cannot be empty matrices");
476
477 F77_INT info;
478
479 F77_INT m = to_f77_int (a.rows ());
480 F77_INT n = to_f77_int (a.cols ());
481 F77_INT p = to_f77_int (b.rows ());
482
483 T atmp = a;
484 P *tmp_dataA = atmp.fortran_vec ();
485
486 T btmp = b;
487 P *tmp_dataB = btmp.fortran_vec ();
488
489 char jobu = 'U';
490 char jobv = 'V';
491 char jobq = 'Q';
492
493 F77_INT nrow_u = m;
494 F77_INT nrow_v = p;
495 F77_INT nrow_q = n;
496
497 F77_INT k, l;
498
499 switch (gsvd_type)
500 {
501 case gsvd<T>::Type::sigma_only:
502
503 // FIXME: In LAPACK 3.0, problem below seems to be fixed,
504 // so we now set jobX = 'N'.
505 //
506 // For calculating sigma_only, both jobu and jobv should be 'N', but
507 // there seems to be a bug in dgesvd from LAPACK V2.0. To
508 // demonstrate the bug, set both jobu and jobv to 'N' and find the
509 // singular values of [eye(3), eye(3)]. The result is
510 // [-sqrt(2), -sqrt(2), -sqrt(2)].
511
512 jobu = jobv = jobq = 'N';
513 nrow_u = nrow_v = nrow_q = 1;
514 break;
515
516 default:
517 break;
518 }
519
520 m_type = gsvd_type;
521
522 if (jobu != 'N')
523 m_left_smA.resize (nrow_u, m);
524
525 P *u = m_left_smA.fortran_vec ();
526
527 if (jobv != 'N')
528 m_left_smB.resize (nrow_v, p);
529
530 P *v = m_left_smB.fortran_vec ();
531
532 if (jobq != 'N')
533 m_right_sm.resize (nrow_q, n);
534
535 P *q = m_right_sm.fortran_vec ();
536
537 real_matrix alpha (n, 1);
538 real_matrix beta (n, 1);
539
540 OCTAVE_LOCAL_BUFFER(F77_INT, iwork, n);
541
542 if (! gsvd_initialized)
543 initialize_gsvd ();
544
545 F77_INT lwork;
546 if (have_DGGSVD3)
547 {
548 lwork = -1;
549 P work_tmp;
550
551 gsvd<T>::ggsvd (jobu, jobv, jobq, m, n, p, k, l,
552 tmp_dataA, m, tmp_dataB, p,
553 alpha, beta, u, nrow_u, v, nrow_v, q, nrow_q,
554 &work_tmp, lwork, iwork, info);
555
556 lwork = static_cast<F77_INT> (std::abs (work_tmp));
557 }
558 else
559 {
560 lwork = std::max ({3*n, m, p}) + n;
561 }
562 info = 0;
563
564 OCTAVE_LOCAL_BUFFER(P, work, lwork);
565
566 gsvd<T>::ggsvd (jobu, jobv, jobq, m, n, p, k, l,
567 tmp_dataA, m, tmp_dataB, p,
568 alpha, beta, u, nrow_u, v, nrow_v, q, nrow_q,
569 work, lwork, iwork, info);
570
571 if (info < 0)
572 (*current_liboctave_error_handler)
573 ("*ggsvd.f: argument %" OCTAVE_F77_INT_TYPE_FORMAT " illegal",
574 -info);
575
576 if (info > 0)
577 (*current_liboctave_error_handler)
578 ("*ggsvd.f: Jacobi-type procedure failed to converge");
579
580 F77_INT i, j;
581
582 if (gsvd_type != gsvd<T>::Type::sigma_only)
583 {
584 // Size according to LAPACK is k+l,k+l, but this needs
585 // to be nxn for Matlab compatibility.
586 T R (n, n, 0.0);
587 int astart = n-k-l;
588 if (m - k - l >= 0)
589 { 650 {
590 // R is stored in A(1:K+L,N-K-L+1:N) 651 m_sigmaA.xelem (i) = 1.0;
591 for (i = 0; i < k+l; i++) 652 m_sigmaB.xelem (i) = 0.0;
592 for (j = 0; j < k+l; j++)
593 R.xelem (i, j) = atmp.xelem (i, astart + j);
594 } 653 }
595 else 654 for (i = k; i < m; i++)
596 { 655 {
597 // (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N) 656 m_sigmaA.xelem (i) = alpha.xelem (i);
598 // ( 0 R22 R23 ) 657 m_sigmaB.xelem (i) = beta.xelem (i);
599 for (i = 0; i < m; i++)
600 for (j = 0; j < k+l; j++)
601 R.xelem (i, j) = atmp.xelem (i, astart + j);
602 // and R33 is stored in B(M-K+1:L,N+M-K-L+1:N)
603 for (i = m; i < k + l; i++)
604 for (j = n - l - k + m; j < n; j++)
605 R.xelem (i, j) = btmp.xelem (i - k, j);
606 } 658 }
607 659 for (i = m; i < k+l; i++)
608 // Output X = Q*R'
609 // FIXME: Is there a way to call BLAS multiply directly
610 // with flags so that R is transposed?
611 m_right_sm = m_right_sm * R.hermitian ();
612 }
613
614 // Fill in C and S
615 F77_INT rank;
616 bool fill_ptn;
617 if (m-k-l >= 0)
618 {
619 rank = l;
620 fill_ptn = true;
621 }
622 else
623 {
624 rank = m-k;
625 fill_ptn = false;
626 }
627
628 if (gsvd_type == gsvd<T>::Type::sigma_only)
629 {
630 // Return column vector with results
631 m_sigmaA.resize (k+l, 1);
632 m_sigmaB.resize (k+l, 1);
633
634 if (fill_ptn)
635 { 660 {
636 for (i = 0; i < k; i++) 661 m_sigmaA.xelem (i) = 0.0;
637 { 662 m_sigmaB.xelem (i) = 1.0;
638 m_sigmaA.xelem (i) = 1.0;
639 m_sigmaB.xelem (i) = 0.0;
640 }
641 for (i = k, j = k+l-1; i < k+l; i++, j--)
642 {
643 m_sigmaA.xelem (i) = alpha.xelem (i);
644 m_sigmaB.xelem (i) = beta.xelem (i);
645 }
646 }
647 else
648 {
649 for (i = 0; i < k; i++)
650 {
651 m_sigmaA.xelem (i) = 1.0;
652 m_sigmaB.xelem (i) = 0.0;
653 }
654 for (i = k; i < m; i++)
655 {
656 m_sigmaA.xelem (i) = alpha.xelem (i);
657 m_sigmaB.xelem (i) = beta.xelem (i);
658 }
659 for (i = m; i < k+l; i++)
660 {
661 m_sigmaA.xelem (i) = 0.0;
662 m_sigmaB.xelem (i) = 1.0;
663 }
664 } 663 }
665 } 664 }
666 else // returning all matrices 665 }
666 else // returning all matrices
667 {
668 // Number of columns according to LAPACK is k+l, but this needs
669 // to be n for Matlab compatibility.
670 m_sigmaA.resize (m, n);
671 m_sigmaB.resize (p, n);
672
673 for (i = 0; i < k; i++)
674 m_sigmaA.xelem (i, i) = 1.0;
675
676 for (i = 0; i < rank; i++)
667 { 677 {
668 // Number of columns according to LAPACK is k+l, but this needs 678 m_sigmaA.xelem (k+i, k+i) = alpha.xelem (k+i);
669 // to be n for Matlab compatibility. 679 m_sigmaB.xelem (i, k+i) = beta.xelem (k+i);
670 m_sigmaA.resize (m, n);
671 m_sigmaB.resize (p, n);
672
673 for (i = 0; i < k; i++)
674 m_sigmaA.xelem (i, i) = 1.0;
675
676 for (i = 0; i < rank; i++)
677 {
678 m_sigmaA.xelem (k+i, k+i) = alpha.xelem (k+i);
679 m_sigmaB.xelem (i, k+i) = beta.xelem (k+i);
680 }
681
682 if (! fill_ptn)
683 {
684 for (i = m; i < n; i++)
685 m_sigmaB.xelem (i-k, i) = 1.0;
686 }
687
688 } 680 }
689 } 681
690 682 if (! fill_ptn)
691 // Instantiations needed in octave::math namespace. 683 {
692 template class gsvd<Matrix>; 684 for (i = m; i < n; i++)
693 template class gsvd<FloatMatrix>; 685 m_sigmaB.xelem (i-k, i) = 1.0;
694 template class gsvd<ComplexMatrix>; 686 }
695 template class gsvd<FloatComplexMatrix>; 687
688 }
689 }
690
691 // Instantiations needed in octave::math namespace.
692 template class gsvd<Matrix>;
693 template class gsvd<FloatMatrix>;
694 template class gsvd<ComplexMatrix>;
695 template class gsvd<FloatComplexMatrix>;
696 696
697 OCTAVE_END_NAMESPACE(math) 697 OCTAVE_END_NAMESPACE(math)
698 OCTAVE_END_NAMESPACE(octave) 698 OCTAVE_END_NAMESPACE(octave)