1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
#include "rb_lapack.h"
extern VOID ctgsja_(char* jobu, char* jobv, char* jobq, integer* m, integer* p, integer* n, integer* k, integer* l, complex* a, integer* lda, complex* b, integer* ldb, real* tola, real* tolb, real* alpha, real* beta, complex* u, integer* ldu, complex* v, integer* ldv, complex* q, integer* ldq, complex* work, integer* ncycle, integer* info);
static VALUE
rblapack_ctgsja(int argc, VALUE *argv, VALUE self){
VALUE rblapack_jobu;
char jobu;
VALUE rblapack_jobv;
char jobv;
VALUE rblapack_jobq;
char jobq;
VALUE rblapack_k;
integer k;
VALUE rblapack_l;
integer l;
VALUE rblapack_a;
complex *a;
VALUE rblapack_b;
complex *b;
VALUE rblapack_tola;
real tola;
VALUE rblapack_tolb;
real tolb;
VALUE rblapack_u;
complex *u;
VALUE rblapack_v;
complex *v;
VALUE rblapack_q;
complex *q;
VALUE rblapack_alpha;
real *alpha;
VALUE rblapack_beta;
real *beta;
VALUE rblapack_ncycle;
integer ncycle;
VALUE rblapack_info;
integer info;
VALUE rblapack_a_out__;
complex *a_out__;
VALUE rblapack_b_out__;
complex *b_out__;
VALUE rblapack_u_out__;
complex *u_out__;
VALUE rblapack_v_out__;
complex *v_out__;
VALUE rblapack_q_out__;
complex *q_out__;
complex *work;
integer lda;
integer n;
integer ldb;
integer ldu;
integer m;
integer ldv;
integer p;
integer ldq;
VALUE rblapack_options;
if (argc > 0 && TYPE(argv[argc-1]) == T_HASH) {
argc--;
rblapack_options = argv[argc];
if (rb_hash_aref(rblapack_options, sHelp) == Qtrue) {
printf("%s\n", "USAGE:\n alpha, beta, ncycle, info, a, b, u, v, q = NumRu::Lapack.ctgsja( jobu, jobv, jobq, k, l, a, b, tola, tolb, u, v, q, [:usage => usage, :help => help])\n\n\nFORTRAN MANUAL\n SUBROUTINE CTGSJA( JOBU, JOBV, JOBQ, M, P, N, K, L, A, LDA, B, LDB, TOLA, TOLB, ALPHA, BETA, U, LDU, V, LDV, Q, LDQ, WORK, NCYCLE, INFO )\n\n* Purpose\n* =======\n*\n* CTGSJA computes the generalized singular value decomposition (GSVD)\n* of two complex upper triangular (or trapezoidal) matrices A and B.\n*\n* On entry, it is assumed that matrices A and B have the following\n* forms, which may be obtained by the preprocessing subroutine CGGSVP\n* from a general M-by-N matrix A and P-by-N matrix B:\n*\n* N-K-L K L\n* A = K ( 0 A12 A13 ) if M-K-L >= 0;\n* L ( 0 0 A23 )\n* M-K-L ( 0 0 0 )\n*\n* N-K-L K L\n* A = K ( 0 A12 A13 ) if M-K-L < 0;\n* M-K ( 0 0 A23 )\n*\n* N-K-L K L\n* B = L ( 0 0 B13 )\n* P-L ( 0 0 0 )\n*\n* where the K-by-K matrix A12 and L-by-L matrix B13 are nonsingular\n* upper triangular; A23 is L-by-L upper triangular if M-K-L >= 0,\n* otherwise A23 is (M-K)-by-L upper trapezoidal.\n*\n* On exit,\n*\n* U'*A*Q = D1*( 0 R ), V'*B*Q = D2*( 0 R ),\n*\n* where U, V and Q are unitary matrices, Z' denotes the conjugate\n* transpose of Z, R is a nonsingular upper triangular matrix, and D1\n* and D2 are ``diagonal'' matrices, which are of the following\n* structures:\n*\n* If M-K-L >= 0,\n*\n* K L\n* D1 = K ( I 0 )\n* L ( 0 C )\n* M-K-L ( 0 0 )\n*\n* K L\n* D2 = L ( 0 S )\n* P-L ( 0 0 )\n*\n* N-K-L K L\n* ( 0 R ) = K ( 0 R11 R12 ) K\n* L ( 0 0 R22 ) L\n*\n* where\n*\n* C = diag( ALPHA(K+1), ... , ALPHA(K+L) ),\n* S = diag( BETA(K+1), ... , BETA(K+L) ),\n* C**2 + S**2 = I.\n*\n* R is stored in A(1:K+L,N-K-L+1:N) on exit.\n*\n* If M-K-L < 0,\n*\n* K M-K K+L-M\n* D1 = K ( I 0 0 )\n* M-K ( 0 C 0 )\n*\n* K M-K K+L-M\n* D2 = M-K ( 0 S 0 )\n* K+L-M ( 0 0 I )\n* P-L ( 0 0 0 )\n*\n* N-K-L K M-K K+L-M\n* ( 0 R ) = K ( 0 R11 R12 R13 )\n* M-K ( 0 0 R22 R23 )\n* K+L-M ( 0 0 0 R33 )\n*\n* where\n* C = diag( ALPHA(K+1), ... , ALPHA(M) ),\n* S = diag( BETA(K+1), ... , BETA(M) ),\n* C**2 + S**2 = I.\n*\n* R = ( R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N) and R33 is stored\n* ( 0 R22 R23 )\n* in B(M-K+1:L,N+M-K-L+1:N) on exit.\n*\n* The computation of the unitary transformation matrices U, V or Q\n* is optional. These matrices may either be formed explicitly, or they\n* may be postmultiplied into input matrices U1, V1, or Q1.\n*\n\n* Arguments\n* =========\n*\n* JOBU (input) CHARACTER*1\n* = 'U': U must contain a unitary matrix U1 on entry, and\n* the product U1*U is returned;\n* = 'I': U is initialized to the unit matrix, and the\n* unitary matrix U is returned;\n* = 'N': U is not computed.\n*\n* JOBV (input) CHARACTER*1\n* = 'V': V must contain a unitary matrix V1 on entry, and\n* the product V1*V is returned;\n* = 'I': V is initialized to the unit matrix, and the\n* unitary matrix V is returned;\n* = 'N': V is not computed.\n*\n* JOBQ (input) CHARACTER*1\n* = 'Q': Q must contain a unitary matrix Q1 on entry, and\n* the product Q1*Q is returned;\n* = 'I': Q is initialized to the unit matrix, and the\n* unitary matrix Q is returned;\n* = 'N': Q is not computed.\n*\n* M (input) INTEGER\n* The number of rows of the matrix A. M >= 0.\n*\n* P (input) INTEGER\n* The number of rows of the matrix B. P >= 0.\n*\n* N (input) INTEGER\n* The number of columns of the matrices A and B. N >= 0.\n*\n* K (input) INTEGER\n* L (input) INTEGER\n* K and L specify the subblocks in the input matrices A and B:\n* A23 = A(K+1:MIN(K+L,M),N-L+1:N) and B13 = B(1:L,,N-L+1:N)\n* of A and B, whose GSVD is going to be computed by CTGSJA.\n* See Further Details.\n*\n* A (input/output) COMPLEX array, dimension (LDA,N)\n* On entry, the M-by-N matrix A.\n* On exit, A(N-K+1:N,1:MIN(K+L,M) ) contains the triangular\n* matrix R or part of R. See Purpose for details.\n*\n* LDA (input) INTEGER\n* The leading dimension of the array A. LDA >= max(1,M).\n*\n* B (input/output) COMPLEX array, dimension (LDB,N)\n* On entry, the P-by-N matrix B.\n* On exit, if necessary, B(M-K+1:L,N+M-K-L+1:N) contains\n* a part of R. See Purpose for details.\n*\n* LDB (input) INTEGER\n* The leading dimension of the array B. LDB >= max(1,P).\n*\n* TOLA (input) REAL\n* TOLB (input) REAL\n* TOLA and TOLB are the convergence criteria for the Jacobi-\n* Kogbetliantz iteration procedure. Generally, they are the\n* same as used in the preprocessing step, say\n* TOLA = MAX(M,N)*norm(A)*MACHEPS,\n* TOLB = MAX(P,N)*norm(B)*MACHEPS.\n*\n* ALPHA (output) REAL array, dimension (N)\n* BETA (output) REAL array, dimension (N)\n* On exit, ALPHA and BETA contain the generalized singular\n* value pairs of A and B;\n* ALPHA(1:K) = 1,\n* BETA(1:K) = 0,\n* and if M-K-L >= 0,\n* ALPHA(K+1:K+L) = diag(C),\n* BETA(K+1:K+L) = diag(S),\n* or if M-K-L < 0,\n* ALPHA(K+1:M)= C, ALPHA(M+1:K+L)= 0\n* BETA(K+1:M) = S, BETA(M+1:K+L) = 1.\n* Furthermore, if K+L < N,\n* ALPHA(K+L+1:N) = 0\n* BETA(K+L+1:N) = 0.\n*\n* U (input/output) COMPLEX array, dimension (LDU,M)\n* On entry, if JOBU = 'U', U must contain a matrix U1 (usually\n* the unitary matrix returned by CGGSVP).\n* On exit,\n* if JOBU = 'I', U contains the unitary matrix U;\n* if JOBU = 'U', U contains the product U1*U.\n* If JOBU = 'N', U is not referenced.\n*\n* LDU (input) INTEGER\n* The leading dimension of the array U. LDU >= max(1,M) if\n* JOBU = 'U'; LDU >= 1 otherwise.\n*\n* V (input/output) COMPLEX array, dimension (LDV,P)\n* On entry, if JOBV = 'V', V must contain a matrix V1 (usually\n* the unitary matrix returned by CGGSVP).\n* On exit,\n* if JOBV = 'I', V contains the unitary matrix V;\n* if JOBV = 'V', V contains the product V1*V.\n* If JOBV = 'N', V is not referenced.\n*\n* LDV (input) INTEGER\n* The leading dimension of the array V. LDV >= max(1,P) if\n* JOBV = 'V'; LDV >= 1 otherwise.\n*\n* Q (input/output) COMPLEX array, dimension (LDQ,N)\n* On entry, if JOBQ = 'Q', Q must contain a matrix Q1 (usually\n* the unitary matrix returned by CGGSVP).\n* On exit,\n* if JOBQ = 'I', Q contains the unitary matrix Q;\n* if JOBQ = 'Q', Q contains the product Q1*Q.\n* If JOBQ = 'N', Q is not referenced.\n*\n* LDQ (input) INTEGER\n* The leading dimension of the array Q. LDQ >= max(1,N) if\n* JOBQ = 'Q'; LDQ >= 1 otherwise.\n*\n* WORK (workspace) COMPLEX array, dimension (2*N)\n*\n* NCYCLE (output) INTEGER\n* The number of cycles required for convergence.\n*\n* INFO (output) INTEGER\n* = 0: successful exit\n* < 0: if INFO = -i, the i-th argument had an illegal value.\n* = 1: the procedure does not converge after MAXIT cycles.\n*\n* Internal Parameters\n* ===================\n*\n* MAXIT INTEGER\n* MAXIT specifies the total loops that the iterative procedure\n* may take. If after MAXIT cycles, the routine fails to\n* converge, we return INFO = 1.\n*\n\n* Further Details\n* ===============\n*\n* CTGSJA essentially uses a variant of Kogbetliantz algorithm to reduce\n* min(L,M-K)-by-L triangular (or trapezoidal) matrix A23 and L-by-L\n* matrix B13 to the form:\n*\n* U1'*A13*Q1 = C1*R1; V1'*B13*Q1 = S1*R1,\n*\n* where U1, V1 and Q1 are unitary matrix, and Z' is the conjugate\n* transpose of Z. C1 and S1 are diagonal matrices satisfying\n*\n* C1**2 + S1**2 = I,\n*\n* and R1 is an L-by-L nonsingular upper triangular matrix.\n*\n* =====================================================================\n*\n\n");
return Qnil;
}
if (rb_hash_aref(rblapack_options, sUsage) == Qtrue) {
printf("%s\n", "USAGE:\n alpha, beta, ncycle, info, a, b, u, v, q = NumRu::Lapack.ctgsja( jobu, jobv, jobq, k, l, a, b, tola, tolb, u, v, q, [:usage => usage, :help => help])\n");
return Qnil;
}
} else
rblapack_options = Qnil;
if (argc != 12 && argc != 12)
rb_raise(rb_eArgError,"wrong number of arguments (%d for 12)", argc);
rblapack_jobu = argv[0];
rblapack_jobv = argv[1];
rblapack_jobq = argv[2];
rblapack_k = argv[3];
rblapack_l = argv[4];
rblapack_a = argv[5];
rblapack_b = argv[6];
rblapack_tola = argv[7];
rblapack_tolb = argv[8];
rblapack_u = argv[9];
rblapack_v = argv[10];
rblapack_q = argv[11];
if (argc == 12) {
} else if (rblapack_options != Qnil) {
} else {
}
jobu = StringValueCStr(rblapack_jobu)[0];
jobq = StringValueCStr(rblapack_jobq)[0];
l = NUM2INT(rblapack_l);
if (!NA_IsNArray(rblapack_b))
rb_raise(rb_eArgError, "b (7th argument) must be NArray");
if (NA_RANK(rblapack_b) != 2)
rb_raise(rb_eArgError, "rank of b (7th argument) must be %d", 2);
ldb = NA_SHAPE0(rblapack_b);
n = NA_SHAPE1(rblapack_b);
if (NA_TYPE(rblapack_b) != NA_SCOMPLEX)
rblapack_b = na_change_type(rblapack_b, NA_SCOMPLEX);
b = NA_PTR_TYPE(rblapack_b, complex*);
tolb = (real)NUM2DBL(rblapack_tolb);
if (!NA_IsNArray(rblapack_v))
rb_raise(rb_eArgError, "v (11th argument) must be NArray");
if (NA_RANK(rblapack_v) != 2)
rb_raise(rb_eArgError, "rank of v (11th argument) must be %d", 2);
ldv = NA_SHAPE0(rblapack_v);
p = NA_SHAPE1(rblapack_v);
if (NA_TYPE(rblapack_v) != NA_SCOMPLEX)
rblapack_v = na_change_type(rblapack_v, NA_SCOMPLEX);
v = NA_PTR_TYPE(rblapack_v, complex*);
jobv = StringValueCStr(rblapack_jobv)[0];
if (!NA_IsNArray(rblapack_a))
rb_raise(rb_eArgError, "a (6th argument) must be NArray");
if (NA_RANK(rblapack_a) != 2)
rb_raise(rb_eArgError, "rank of a (6th argument) must be %d", 2);
lda = NA_SHAPE0(rblapack_a);
if (NA_SHAPE1(rblapack_a) != n)
rb_raise(rb_eRuntimeError, "shape 1 of a must be the same as shape 1 of b");
if (NA_TYPE(rblapack_a) != NA_SCOMPLEX)
rblapack_a = na_change_type(rblapack_a, NA_SCOMPLEX);
a = NA_PTR_TYPE(rblapack_a, complex*);
if (!NA_IsNArray(rblapack_u))
rb_raise(rb_eArgError, "u (10th argument) must be NArray");
if (NA_RANK(rblapack_u) != 2)
rb_raise(rb_eArgError, "rank of u (10th argument) must be %d", 2);
ldu = NA_SHAPE0(rblapack_u);
m = NA_SHAPE1(rblapack_u);
if (NA_TYPE(rblapack_u) != NA_SCOMPLEX)
rblapack_u = na_change_type(rblapack_u, NA_SCOMPLEX);
u = NA_PTR_TYPE(rblapack_u, complex*);
k = NUM2INT(rblapack_k);
if (!NA_IsNArray(rblapack_q))
rb_raise(rb_eArgError, "q (12th argument) must be NArray");
if (NA_RANK(rblapack_q) != 2)
rb_raise(rb_eArgError, "rank of q (12th argument) must be %d", 2);
ldq = NA_SHAPE0(rblapack_q);
if (NA_SHAPE1(rblapack_q) != n)
rb_raise(rb_eRuntimeError, "shape 1 of q must be the same as shape 1 of b");
if (NA_TYPE(rblapack_q) != NA_SCOMPLEX)
rblapack_q = na_change_type(rblapack_q, NA_SCOMPLEX);
q = NA_PTR_TYPE(rblapack_q, complex*);
tola = (real)NUM2DBL(rblapack_tola);
{
na_shape_t shape[1];
shape[0] = n;
rblapack_alpha = na_make_object(NA_SFLOAT, 1, shape, cNArray);
}
alpha = NA_PTR_TYPE(rblapack_alpha, real*);
{
na_shape_t shape[1];
shape[0] = n;
rblapack_beta = na_make_object(NA_SFLOAT, 1, shape, cNArray);
}
beta = NA_PTR_TYPE(rblapack_beta, real*);
{
na_shape_t shape[2];
shape[0] = lda;
shape[1] = n;
rblapack_a_out__ = na_make_object(NA_SCOMPLEX, 2, shape, cNArray);
}
a_out__ = NA_PTR_TYPE(rblapack_a_out__, complex*);
MEMCPY(a_out__, a, complex, NA_TOTAL(rblapack_a));
rblapack_a = rblapack_a_out__;
a = a_out__;
{
na_shape_t shape[2];
shape[0] = ldb;
shape[1] = n;
rblapack_b_out__ = na_make_object(NA_SCOMPLEX, 2, shape, cNArray);
}
b_out__ = NA_PTR_TYPE(rblapack_b_out__, complex*);
MEMCPY(b_out__, b, complex, NA_TOTAL(rblapack_b));
rblapack_b = rblapack_b_out__;
b = b_out__;
{
na_shape_t shape[2];
shape[0] = ldu;
shape[1] = m;
rblapack_u_out__ = na_make_object(NA_SCOMPLEX, 2, shape, cNArray);
}
u_out__ = NA_PTR_TYPE(rblapack_u_out__, complex*);
MEMCPY(u_out__, u, complex, NA_TOTAL(rblapack_u));
rblapack_u = rblapack_u_out__;
u = u_out__;
{
na_shape_t shape[2];
shape[0] = ldv;
shape[1] = p;
rblapack_v_out__ = na_make_object(NA_SCOMPLEX, 2, shape, cNArray);
}
v_out__ = NA_PTR_TYPE(rblapack_v_out__, complex*);
MEMCPY(v_out__, v, complex, NA_TOTAL(rblapack_v));
rblapack_v = rblapack_v_out__;
v = v_out__;
{
na_shape_t shape[2];
shape[0] = ldq;
shape[1] = n;
rblapack_q_out__ = na_make_object(NA_SCOMPLEX, 2, shape, cNArray);
}
q_out__ = NA_PTR_TYPE(rblapack_q_out__, complex*);
MEMCPY(q_out__, q, complex, NA_TOTAL(rblapack_q));
rblapack_q = rblapack_q_out__;
q = q_out__;
work = ALLOC_N(complex, (2*n));
ctgsja_(&jobu, &jobv, &jobq, &m, &p, &n, &k, &l, a, &lda, b, &ldb, &tola, &tolb, alpha, beta, u, &ldu, v, &ldv, q, &ldq, work, &ncycle, &info);
free(work);
rblapack_ncycle = INT2NUM(ncycle);
rblapack_info = INT2NUM(info);
return rb_ary_new3(9, rblapack_alpha, rblapack_beta, rblapack_ncycle, rblapack_info, rblapack_a, rblapack_b, rblapack_u, rblapack_v, rblapack_q);
}
void
init_lapack_ctgsja(VALUE mLapack, VALUE sH, VALUE sU, VALUE zero){
sHelp = sH;
sUsage = sU;
rblapack_ZERO = zero;
rb_define_module_function(mLapack, "ctgsja", rblapack_ctgsja, -1);
}
|