kmat 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +10 -0
- data/README.md +11 -11
- data/ext/kmat/arith/binary.c +161 -139
- data/ext/kmat/arith/math.c +1 -1
- data/ext/kmat/arith/statistics.c +11 -11
- data/ext/kmat/arith/unary.c +6 -6
- data/ext/kmat/extconf.rb +3 -0
- data/ext/kmat/km_util.h +34 -13
- data/ext/kmat/kmat.h +3 -3
- data/ext/kmat/linalg/dla.c +185 -133
- data/ext/kmat/linalg/linalg.c +33 -17
- data/ext/kmat/linalg/norm.c +83 -69
- data/ext/kmat/linalg/vla.c +23 -23
- data/ext/kmat/linalg/working.c +42 -38
- data/ext/kmat/main.c +4 -4
- data/ext/kmat/smat/accessor.c +104 -104
- data/ext/kmat/smat/array.c +3 -3
- data/ext/kmat/smat/boxmuller.c +5 -5
- data/ext/kmat/smat/constructer.c +52 -52
- data/ext/kmat/smat/convert.c +21 -21
- data/ext/kmat/smat/elem.c +7 -7
- data/ext/kmat/smat/fund.c +37 -37
- data/ext/kmat/smat/share.c +28 -27
- data/ext/kmat/smat/smat.c +58 -42
- data/ext/kmat/smat/sort.c +148 -146
- data/kmat.gemspec +5 -4
- data/lib/kmat/accessor.rb +5 -5
- data/lib/kmat/linalg.rb +1 -2
- data/lib/kmat/random.rb +2 -2
- data/lib/kmat/version.rb +1 -1
- data/lib/kmat.rb +9 -9
- metadata +25 -10
data/ext/kmat/linalg/dla.c
CHANGED
@@ -11,7 +11,7 @@ km_check_info_opt(int info, const char *funcname)
|
|
11
11
|
static void
|
12
12
|
km_vec2diag(int m, int n, double *body, int ld)
|
13
13
|
{
|
14
|
-
int lm1 = MIN(m, n)-1, mp1=ld+1
|
14
|
+
const int lm1 = MIN(m, n)-1, mp1=ld+1; int i=1;
|
15
15
|
dcopy_(&lm1, body+1, &i, body+mp1, &mp1);
|
16
16
|
for ( ; i<=lm1; i++ ) { body[i] = 0.0; }
|
17
17
|
}
|
@@ -37,11 +37,12 @@ km_unbal_body(VALUE data)
|
|
37
37
|
char job[]="B", side[]="R";
|
38
38
|
KALLOC(a->at, (a->n)*(a->n));
|
39
39
|
KALLOCn(a->body, a->smat);
|
40
|
-
|
40
|
+
int ld = s2i(a->body.ld);
|
41
|
+
dgebak_(job, side, &(a->n), &(a->ilo), &(a->ihi), a->scale, &(a->n), a->body.d, &ld, &info); // multiply D from the left
|
41
42
|
km_check_info(info, rb_eRuntimeError, "unexpected info value", "dgebak");
|
42
|
-
a->sat = km_smat_alloc_with(a->n, a->n, VT_DOUBLE, a->body.body);
|
43
|
+
a->sat = km_smat_alloc_with(i2s(a->n), i2s(a->n), VT_DOUBLE, a->body.body);
|
43
44
|
a->sat->trans = true;
|
44
|
-
km_copy2work(a->at, a->n, a->sat); // take transpose
|
45
|
+
km_copy2work(a->at, i2s(a->n), a->sat); // take transpose
|
45
46
|
side[0] = 'L';
|
46
47
|
dgebak_(job, side, &(a->n), &(a->ilo), &(a->ihi), a->scale, &(a->n), a->at, &(a->n), &info); // multiply D^(-T) from the left
|
47
48
|
km_check_info(info, rb_eRuntimeError, "unexpected info value", "dgebak");
|
@@ -63,16 +64,16 @@ km_unbal_ensure(VALUE data)
|
|
63
64
|
static void
|
64
65
|
km_unbal(SMAT *smat, double *scale, int ilo, int ihi)
|
65
66
|
{
|
66
|
-
struct km_unbal_arg a = {smat, scale, ilo, ihi, smat->m, {{NULL}, 0, false}, NULL, NULL};
|
67
|
+
struct km_unbal_arg a = {smat, scale, ilo, ihi, s2i(smat->m), {{NULL}, 0, false}, NULL, NULL};
|
67
68
|
|
68
69
|
km_ensure(km_unbal_body, (VALUE)(&a), km_unbal_ensure, (VALUE)(&a));
|
69
70
|
}
|
70
71
|
|
71
72
|
static void
|
72
|
-
km_check_finite_func_d(double *ent,
|
73
|
+
km_check_finite_func_d(double *ent, size_t i, size_t j, void *null)
|
73
74
|
{
|
74
75
|
if ( !isfinite(*ent) ) {
|
75
|
-
rb_raise(km_eUncomp, "the matrix has an illegal (infinite or nan) element at (%
|
76
|
+
rb_raise(km_eUncomp, "the matrix has an illegal (infinite or nan) element at (%zu, %zu)", i, j);
|
76
77
|
}
|
77
78
|
}
|
78
79
|
static inline void
|
@@ -98,8 +99,8 @@ km_dmat_solve_body(VALUE data)
|
|
98
99
|
{
|
99
100
|
struct km_dmat_solve_arg *a = (struct km_dmat_solve_arg *)data;
|
100
101
|
|
101
|
-
int n=a->sx->m, nrhs=a->sx->n;
|
102
|
-
km_check_size(4, a->sa->m,n, a->sa->n,n, a->sb->m,n, a->sb->n,nrhs);
|
102
|
+
int n=s2i(a->sx->m), nrhs=s2i(a->sx->n);
|
103
|
+
km_check_size(4, s2i(a->sa->m),n, s2i(a->sa->n),n, s2i(a->sb->m),n, s2i(a->sb->n),nrhs);
|
103
104
|
|
104
105
|
int info;
|
105
106
|
char equed[2];
|
@@ -117,9 +118,10 @@ km_dmat_solve_body(VALUE data)
|
|
117
118
|
KALLOC(a->iwork, n);
|
118
119
|
KALLOCn(a->x, a->sx);
|
119
120
|
double rcond;
|
121
|
+
int ldx=s2i(a->x.ld);
|
120
122
|
|
121
123
|
dgesvx_(fact, trans, &n, &nrhs, a->a, &n, a->af, &n, a->ipiv, equed, a->r, a->c, a->b, &n,
|
122
|
-
a->x.d, &
|
124
|
+
a->x.d, &ldx, &rcond, a->ferr, a->berr, a->work, a->iwork, &info);
|
123
125
|
km_check_info(info, km_eUncomp, "A is singular or near singular", "dgesvx");
|
124
126
|
|
125
127
|
return Qnil;
|
@@ -165,9 +167,9 @@ km_dmat_inverse(VALUE self, VALUE va)
|
|
165
167
|
SMAT *sx = km_mat2smat(self), *sa = km_mat2smat(va);
|
166
168
|
km_check_double(2, sx, sa);
|
167
169
|
km_check_finite(sa);
|
168
|
-
|
169
|
-
|
170
|
-
return km_dmat_solve(self, va, kmm_Mat_identity(km_cMat,
|
170
|
+
const size_t n = sa->m;
|
171
|
+
km_check_size_s(3, sx->m,n, sx->n,n, sa->n,n);
|
172
|
+
return km_dmat_solve(self, va, kmm_Mat_identity(km_cMat, ZU2NUM(n)));
|
171
173
|
}
|
172
174
|
|
173
175
|
// compute X with the smallest norm which minimize ||AX-B||. `self' is output
|
@@ -180,9 +182,9 @@ static VALUE
|
|
180
182
|
km_mat_ls_body(VALUE data)
|
181
183
|
{
|
182
184
|
struct km_ls_arg *a = (struct km_ls_arg *)data;
|
183
|
-
int m=a->sa->m, n=a->sa->n, nrhs=a->sx->n;
|
185
|
+
int m=s2i(a->sa->m), n=s2i(a->sa->n), nrhs=s2i(a->sx->n);
|
184
186
|
int ldb = MAX(m, n);
|
185
|
-
km_check_size(3, a->sx->m,n, a->sb->m,m, a->sb->n,nrhs);
|
187
|
+
km_check_size(3, s2i(a->sx->m),n, s2i(a->sb->m),m, s2i(a->sb->n),nrhs);
|
186
188
|
|
187
189
|
int rank, lwork=-1, liwork, info;
|
188
190
|
double rcond=-1.0, opt;
|
@@ -191,13 +193,13 @@ km_mat_ls_body(VALUE data)
|
|
191
193
|
lwork = (int)opt;
|
192
194
|
KALLOCc(a->a, a->sa);
|
193
195
|
KALLOC(a->b, ldb*nrhs); // don't use KALLOCc becaus ldb can be greater than sb->m
|
194
|
-
km_copy2work(a->b, ldb, a->sb);
|
196
|
+
km_copy2work(a->b, i2s(ldb), a->sb);
|
195
197
|
KALLOC(a->s, MIN(m, n));
|
196
198
|
KALLOC(a->work, lwork);
|
197
199
|
KALLOC(a->iwork, liwork);
|
198
200
|
dgelsd_(&m, &n, &nrhs, a->a, &m, a->b, &ldb, a->s, &rcond, &rank, a->work, &lwork, a->iwork, &info);
|
199
201
|
km_check_info(info, rb_eRuntimeError, "compution the SVD faild to converge", "dgelsd");
|
200
|
-
km_copy_from_work(a->sx, a->b, ldb);
|
202
|
+
km_copy_from_work(a->sx, a->b, i2s(ldb));
|
201
203
|
|
202
204
|
return Qnil;
|
203
205
|
}
|
@@ -239,8 +241,8 @@ VALUE
|
|
239
241
|
kmm_mat_tls_destl(VALUE self, VALUE va, VALUE vb)
|
240
242
|
{
|
241
243
|
SMAT *sa = km_mat2smat(va), *sb = km_mat2smat(vb);
|
242
|
-
sa->trans = !(sa->trans); SWAP(
|
243
|
-
sb->trans = !(sb->trans); SWAP(
|
244
|
+
sa->trans = !(sa->trans); SWAP(size_t, sa->m, sa->n);
|
245
|
+
sb->trans = !(sb->trans); SWAP(size_t, sb->m, sb->n);
|
244
246
|
VALUE vab = rb_ary_new3(2, va, vb);
|
245
247
|
km_ensure(km_mat_ls_wrap, rb_ary_new3(3, self, va, vb), km_recover_trans, vab);
|
246
248
|
return self;
|
@@ -264,13 +266,13 @@ km_mat_ls_conj_body(VALUE data)
|
|
264
266
|
{
|
265
267
|
struct km_ls_conj_arg *a = (struct km_ls_conj_arg *)data;
|
266
268
|
|
267
|
-
int m = a->sa->m, n = a->sa->n;
|
269
|
+
const int m = s2i(a->sa->m), n = s2i(a->sa->n);
|
268
270
|
if ( m < n ) {
|
269
271
|
rb_raise(km_eDim, "A must be row-full-rank");
|
270
272
|
}
|
271
273
|
km_check_size(4, a->sx->m,n, a->sx->n,1, a->sb->m,m, a->sb->n,1);
|
272
274
|
|
273
|
-
const int ione=1; double dzero=0.0, done=1.0;
|
275
|
+
const int ione=1; const double dzero=0.0, done=1.0;
|
274
276
|
KALLOC(a->r, n);
|
275
277
|
KALLOC(a->p, n);
|
276
278
|
KALLOC(a->ap, n);
|
@@ -304,7 +306,7 @@ km_mat_ls_conj_body(VALUE data)
|
|
304
306
|
rb_raise(km_eUncomp, "A may not be positive definite");
|
305
307
|
}
|
306
308
|
}
|
307
|
-
double bet = rrp/rr;
|
309
|
+
const double bet = rrp/rr;
|
308
310
|
for ( int j=0; j<n; j++ ) {
|
309
311
|
a->p[j] = bet*a->p[j]+a->r[j];
|
310
312
|
}
|
@@ -363,11 +365,11 @@ km_mat_glm_body(VALUE data)
|
|
363
365
|
{
|
364
366
|
struct km_glm_arg *a = (struct km_glm_arg *)data;
|
365
367
|
|
366
|
-
int n=a->sa->m, m=a->sa->n, p=a->sb->n; // m, n are swapped from those of sa
|
368
|
+
int n=s2i(a->sa->m), m=s2i(a->sa->n), p=s2i(a->sb->n); // m, n are swapped from those of sa
|
367
369
|
if ( n < m || m+p < n ) {
|
368
370
|
rb_raise(km_eDim, "m <= n <= m+p must be satisfied for glm, given are (m, n, p) = (%d, %d, %d)", m, n, p);
|
369
371
|
}
|
370
|
-
km_check_size(5, a->sb->m,n, MIN(a->sx->m,a->sx->n),1,
|
372
|
+
km_check_size(5, s2i(a->sb->m),n, s2i(MIN(a->sx->m,a->sx->n)),1, LENGTHi(a->sx),m, s2i(MIN(a->sd->m, a->sd->n)),1, LENGTHi(a->sd),n);
|
371
373
|
|
372
374
|
double opt; int lwork=-1, info;
|
373
375
|
dggglm_(&n, &m, &p, NULL, &n, NULL, &n, NULL, NULL, NULL, &opt, &lwork, &info);
|
@@ -431,8 +433,8 @@ km_sym_ev_body(VALUE data)
|
|
431
433
|
{
|
432
434
|
struct km_sym_ev_arg *a = (struct km_sym_ev_arg *)data;
|
433
435
|
|
434
|
-
int n =
|
435
|
-
km_check_size(3, MIN(a->sd->m, a->sd->n),1, a->sa->m,n, a->sa->n,n);
|
436
|
+
int n = LENGTHi(a->sd);
|
437
|
+
km_check_size(3, s2i(MIN(a->sd->m, a->sd->n)),1, s2i(a->sa->m),n, s2i(a->sa->n),n);
|
436
438
|
|
437
439
|
char cmach[] = "S";
|
438
440
|
double abstol = dlamch_(cmach);
|
@@ -496,8 +498,8 @@ km_sym_evd_body(VALUE data)
|
|
496
498
|
{
|
497
499
|
struct km_sym_evd_arg *a = (struct km_sym_evd_arg *)data;
|
498
500
|
|
499
|
-
int n = a->sa->m;
|
500
|
-
km_check_size(5, a->sa->n,n, a->sv->m,n, a->sv->n,n, a->sd->m,n, a->sd->n,n);
|
501
|
+
int n = s2i(a->sa->m);
|
502
|
+
km_check_size(5, s2i(a->sa->n),n, s2i(a->sv->m),n, s2i(a->sv->n),n, s2i(a->sd->m),n, s2i(a->sd->n),n);
|
501
503
|
|
502
504
|
char cmach[] = "S";
|
503
505
|
double dopt, abstol = dlamch_(cmach);
|
@@ -513,11 +515,12 @@ km_sym_evd_body(VALUE data)
|
|
513
515
|
KALLOC(a->iwork, liwork);
|
514
516
|
KALLOCz(a->w, a->sd);
|
515
517
|
KALLOCn(a->z, a->sv);
|
518
|
+
int ldz=s2i(a->z.ld);
|
516
519
|
|
517
520
|
dsyevr_(jobz, range, upto, &n, a->a, &n, NULL, NULL, NULL, NULL, &abstol, &m,
|
518
|
-
a->w.d, a->z.d, &
|
521
|
+
a->w.d, a->z.d, &ldz, a->isuppz, a->work, &lwork, a->iwork, &liwork, &info);
|
519
522
|
km_check_info(info, rb_eRuntimeError, "internal error occured while invoking dsyevr", "dsyevr");
|
520
|
-
km_vec2diag(n, n, a->w.d, a->w.ld);
|
523
|
+
km_vec2diag(n, n, a->w.d, s2i(a->w.ld));
|
521
524
|
|
522
525
|
return Qnil;
|
523
526
|
}
|
@@ -551,7 +554,7 @@ kmm_mat_sym_evd_destl(VALUE self, VALUE vv, VALUE vd)
|
|
551
554
|
VALUE
|
552
555
|
kmm_mat_sym_evd(VALUE self)
|
553
556
|
{
|
554
|
-
|
557
|
+
const size_t n = km_mat2smat(self)->n;
|
555
558
|
VALUE vv = km_Mat(n, n, VT_DOUBLE);
|
556
559
|
VALUE vd = km_Mat(n, n, VT_DOUBLE);
|
557
560
|
kmm_mat_sym_evd_destl(self, vv, vd);
|
@@ -564,7 +567,7 @@ struct km_ge_eigen_values_arg {
|
|
564
567
|
double *a, *wr, *wi, *scale, *work;
|
565
568
|
};
|
566
569
|
static void
|
567
|
-
km_ge_ev_cpack(COMPLEX *ent,
|
570
|
+
km_ge_ev_cpack(COMPLEX *ent, size_t i, size_t j, void *data)
|
568
571
|
{
|
569
572
|
struct km_ge_eigen_values_arg *a = (struct km_ge_eigen_values_arg *)data;
|
570
573
|
*ent = cpack(a->wr[i+j], a->wr[i+j]); // i==0 for column-vector or j==0 for row-vector
|
@@ -574,8 +577,8 @@ km_ge_eigen_values_body(VALUE data)
|
|
574
577
|
{
|
575
578
|
struct km_ge_eigen_values_arg *a = (struct km_ge_eigen_values_arg *)data;
|
576
579
|
|
577
|
-
int n =
|
578
|
-
km_check_size(3, MIN(a->sd->m, a->sd->n),1, a->sa->m,n, a->sa->n,n);
|
580
|
+
int n = LENGTHi(a->sd);
|
581
|
+
km_check_size(3, s2i(MIN(a->sd->m, a->sd->n)),1, s2i(a->sa->m),n, s2i(a->sa->n),n);
|
579
582
|
|
580
583
|
double opt;
|
581
584
|
int lwork=-1, ilo, ihi, info;
|
@@ -629,20 +632,20 @@ kmm_mat_ge_eigen_values(VALUE va)
|
|
629
632
|
return kmm_mat_ge_eigen_values_destl(km_Mat(km_mat2smat(va)->m, 1, VT_COMPLEX), va);
|
630
633
|
}
|
631
634
|
|
632
|
-
// compute a matrix consists of right-eigenvectors V and a diagonal matrix consists of right-eigenvalues D, AV=
|
635
|
+
// compute a matrix consists of right-eigenvectors V and a diagonal matrix consists of right-eigenvalues D, AV=VD of a non-symmetric matrix A.
|
633
636
|
// the arguments are outputs
|
634
637
|
struct km_ge_evd_arg {
|
635
638
|
SMAT *sa, *sv, *sd;
|
636
|
-
double *a, *wr, *wi, *scale, *work;
|
637
|
-
LAWORK vr;
|
639
|
+
double *a, *wr, *wi, *scale, *work, *vr;
|
638
640
|
};
|
639
641
|
static VALUE
|
640
642
|
km_ge_evd_body(VALUE data)
|
641
643
|
{
|
642
644
|
struct km_ge_evd_arg *a = (struct km_ge_evd_arg *)data;
|
643
645
|
|
644
|
-
|
645
|
-
|
646
|
+
const size_t n_s = a->sa->m;
|
647
|
+
int n = s2i(n_s);
|
648
|
+
km_check_size(5, s2i(a->sa->n),n, s2i(a->sv->m),n, s2i(a->sv->n),n, s2i(a->sd->m),n, s2i(a->sd->n),n);
|
646
649
|
|
647
650
|
double opt; int lwork=-1, ilo, ihi, info;
|
648
651
|
char balanc[]="B", jobvl[]="N", jobvr[]="V", sense[]="N";
|
@@ -656,18 +659,59 @@ km_ge_evd_body(VALUE data)
|
|
656
659
|
KALLOC(a->wi, n);
|
657
660
|
KALLOC(a->scale, n);
|
658
661
|
KALLOC(a->work, lwork);
|
659
|
-
|
662
|
+
KALLOC(a->vr, n*n);
|
660
663
|
|
661
664
|
double abnrm;
|
662
|
-
dgeevx_(balanc, jobvl, jobvr, sense, &n, a->a, &n, a->wr, a->wi, NULL, &n, a->vr
|
665
|
+
dgeevx_(balanc, jobvl, jobvr, sense, &n, a->a, &n, a->wr, a->wi, NULL, &n, a->vr, &n,
|
663
666
|
&ilo, &ihi, a->scale, &abnrm, NULL, NULL, a->work, &lwork, NULL, &info);
|
664
667
|
km_check_info(info, rb_eRuntimeError, "the QR algorithm failed to compute all the eigenvalues", "dgeevx");
|
665
668
|
if ( a->sd->stype == ST_RSUB ) {
|
666
|
-
for (
|
669
|
+
for ( size_t j=0; j<n_s; j++ ) {
|
670
|
+
if (a->wi[j] == 0.0) {
|
671
|
+
for ( size_t i=0; i<n_s; i++ ) {
|
672
|
+
ENTITYr0(a->sv, z, INDEX(a->sv, i, j)) = cpack(a->vr[i+j*n_s], 0.0);
|
673
|
+
}
|
674
|
+
} else if (j == 0) {
|
675
|
+
for ( size_t i=0; i<n_s; i++ ) {
|
676
|
+
ENTITYr0(a->sv, z, INDEX(a->sv, i, j)) = cpack(a->vr[i], a->vr[i+n_s]);
|
677
|
+
}
|
678
|
+
} else if (a->wr[j] == a->wr[j+1] && a->wi[j] == -a->wi[j+1]) {
|
679
|
+
for ( size_t i=0; i<n_s; i++ ) {
|
680
|
+
ENTITYr0(a->sv, z, INDEX(a->sv, i, j)) = cpack(a->vr[i+j*n_s], a->vr[i+(j+1)*n_s]);
|
681
|
+
}
|
682
|
+
} else {
|
683
|
+
for ( size_t i=0; i<n_s; i++ ) {
|
684
|
+
ENTITYr0(a->sv, z, INDEX(a->sv, i, j)) = cpack(a->vr[i+(j-1)*n_s], -a->vr[i+j*n_s]);
|
685
|
+
}
|
686
|
+
}
|
687
|
+
}
|
688
|
+
} else {
|
689
|
+
for ( size_t j=0; j<n_s; j++ ) {
|
690
|
+
if (a->wi[j] == 0.0) {
|
691
|
+
for ( size_t i=0; i<n_s; i++ ) {
|
692
|
+
ENTITYd0(a->sv, z, INDEX(a->sv, i, j)) = cpack(a->vr[i+j*n_s], 0.0);
|
693
|
+
}
|
694
|
+
} else if (j == 0) {
|
695
|
+
for ( size_t i=0; i<n_s; i++ ) {
|
696
|
+
ENTITYd0(a->sv, z, INDEX(a->sv, i, j)) = cpack(a->vr[i], a->vr[i+n_s]);
|
697
|
+
}
|
698
|
+
} else if (a->wr[j] == a->wr[j+1] && a->wi[j] == -a->wi[j+1]) {
|
699
|
+
for ( size_t i=0; i<n_s; i++ ) {
|
700
|
+
ENTITYd0(a->sv, z, INDEX(a->sv, i, j)) = cpack(a->vr[i+j*n_s], a->vr[i+(j+1)*n_s]);
|
701
|
+
}
|
702
|
+
} else {
|
703
|
+
for ( size_t i=0; i<n_s; i++ ) {
|
704
|
+
ENTITYd0(a->sv, z, INDEX(a->sv, i, j)) = cpack(a->vr[i+(j-1)*n_s], -a->vr[i+j*n_s]);
|
705
|
+
}
|
706
|
+
}
|
707
|
+
}
|
708
|
+
}
|
709
|
+
if ( a->sd->stype == ST_RSUB ) {
|
710
|
+
for ( size_t i=0; i<n_s; i++ ) {
|
667
711
|
ENTITYr0(a->sd, z, i+i*(a->sd->ld)) = cpack(a->wr[i], a->wi[i]);
|
668
712
|
}
|
669
713
|
} else {
|
670
|
-
for (
|
714
|
+
for ( size_t i=0; i<n_s; i++ ) {
|
671
715
|
ENTITYd0(a->sd, z, i+i*(a->sd->ld)) = cpack(a->wr[i], a->wi[i]);
|
672
716
|
}
|
673
717
|
}
|
@@ -679,7 +723,7 @@ km_ge_evd_ensure(VALUE data)
|
|
679
723
|
{
|
680
724
|
struct km_ge_evd_arg *a = (struct km_ge_evd_arg *)data;
|
681
725
|
|
682
|
-
|
726
|
+
ruby_xfree(a->vr);
|
683
727
|
ruby_xfree(a->work);
|
684
728
|
ruby_xfree(a->scale);
|
685
729
|
ruby_xfree(a->wi);
|
@@ -694,7 +738,7 @@ kmm_mat_ge_evd_destl(VALUE self, VALUE vv, VALUE vd)
|
|
694
738
|
km_check_frozen(vv); km_check_frozen(vd);
|
695
739
|
struct km_ge_evd_arg a; memset(&a, 0, sizeof(a));
|
696
740
|
a.sa = km_mat2smat(self); a.sv = km_mat2smat(vv); a.sd = km_mat2smat(vd);
|
697
|
-
km_check_double(
|
741
|
+
km_check_double(1, a.sa, a.sv); km_check_complex(2, a.sv, a.sd);
|
698
742
|
km_check_finite(a.sa);
|
699
743
|
|
700
744
|
kmm_mat_zero(vd);
|
@@ -705,8 +749,8 @@ kmm_mat_ge_evd_destl(VALUE self, VALUE vv, VALUE vd)
|
|
705
749
|
VALUE
|
706
750
|
kmm_mat_ge_evd(VALUE self)
|
707
751
|
{
|
708
|
-
|
709
|
-
VALUE vv = km_Mat(n, n,
|
752
|
+
const size_t n = km_mat2smat(self)->n;
|
753
|
+
VALUE vv = km_Mat(n, n, VT_COMPLEX);
|
710
754
|
VALUE vd = km_Mat(n, n, VT_COMPLEX);
|
711
755
|
kmm_mat_ge_evd_destl(self, vv, vd);
|
712
756
|
return rb_ary_new3(2, vv, vd);
|
@@ -725,8 +769,8 @@ km_singular_values_body(VALUE data)
|
|
725
769
|
{
|
726
770
|
struct km_singular_values_arg *a = (struct km_singular_values_arg *)data;
|
727
771
|
|
728
|
-
int m = a->sa->m, n = a->sa->n;
|
729
|
-
km_check_size(2,
|
772
|
+
int m = s2i(a->sa->m), n = s2i(a->sa->n);
|
773
|
+
km_check_size(2, LENGTHi(a->ss),MIN(m, n), s2i(MIN(a->ss->m,a->ss->n)),1);
|
730
774
|
|
731
775
|
double opt; int lwork=-1, info;
|
732
776
|
char jobz[] = "N";
|
@@ -789,8 +833,8 @@ km_svd_body(VALUE data)
|
|
789
833
|
{
|
790
834
|
struct km_svd_arg *a = (struct km_svd_arg *)data;
|
791
835
|
|
792
|
-
int m = a->sa->m, n = a->sa->n;
|
793
|
-
km_check_size(6, a->su->m,m, a->su->n,m, a->ss->m,m, a->ss->n,n, a->sv->m,n, a->sv->n,n);
|
836
|
+
int m = s2i(a->sa->m), n = s2i(a->sa->n);
|
837
|
+
km_check_size(6, s2i(a->su->m),m, s2i(a->su->n),m, s2i(a->ss->m),m, s2i(a->ss->n),n, s2i(a->sv->m),n, s2i(a->sv->n),n);
|
794
838
|
|
795
839
|
double opt; int lwork=-1, info;
|
796
840
|
char jobz[] = "A";
|
@@ -804,10 +848,11 @@ km_svd_body(VALUE data)
|
|
804
848
|
KALLOCz(a->s, a->ss);
|
805
849
|
KALLOCn(a->u, a->su);
|
806
850
|
KALLOCn(a->vt, a->sv);
|
851
|
+
int ldu=s2i(a->u.ld), ldvt=s2i(a->vt.ld);
|
807
852
|
|
808
|
-
dgesdd_(jobz, &m, &n, a->a, &m, a->s.d, a->u.d, &
|
853
|
+
dgesdd_(jobz, &m, &n, a->a, &m, a->s.d, a->u.d, &ldu, a->vt.d, &ldvt, a->work, &lwork, a->iwork, &info);
|
809
854
|
km_check_info(info, rb_eRuntimeError, "DBDSDC did not converge", "dgesvd");
|
810
|
-
km_vec2diag(m, n, a->s.d, a->s.ld);
|
855
|
+
km_vec2diag(m, n, a->s.d, s2i(a->s.ld));
|
811
856
|
|
812
857
|
return Qnil;
|
813
858
|
}
|
@@ -843,7 +888,7 @@ VALUE
|
|
843
888
|
kmm_mat_svd(VALUE self)
|
844
889
|
{
|
845
890
|
SMAT *sa = km_mat2smat(self);
|
846
|
-
|
891
|
+
const size_t m = sa->m, n = sa->n;
|
847
892
|
VALUE vu = km_Mat(m, m, VT_DOUBLE);
|
848
893
|
VALUE vs = km_Mat(m, n, VT_DOUBLE);
|
849
894
|
VALUE vv = km_Mat(n, n, VT_DOUBLE);
|
@@ -863,8 +908,8 @@ VALUE km_svd_symmetrize_body(VALUE data)
|
|
863
908
|
{
|
864
909
|
struct km_svd_symmetrize_arg *a = (struct km_svd_symmetrize_arg *)data;
|
865
910
|
|
866
|
-
int n = a->sa->m;
|
867
|
-
km_check_size(1, a->sa->n,n);
|
911
|
+
int n = s2i(a->sa->m);
|
912
|
+
km_check_size(1, s2i(a->sa->n),n);
|
868
913
|
|
869
914
|
double opt; int lwork=-1, info;
|
870
915
|
char jobz[] = "A";
|
@@ -878,8 +923,9 @@ VALUE km_svd_symmetrize_body(VALUE data)
|
|
878
923
|
KALLOC(a->s, n);
|
879
924
|
KALLOC(a->u, n*n);
|
880
925
|
KALLOC(a->vt, n*n);
|
926
|
+
int lda = s2i(a->a.ld);
|
881
927
|
|
882
|
-
dgesdd_(jobz, &n, &n, a->a.d, &
|
928
|
+
dgesdd_(jobz, &n, &n, a->a.d, &lda, a->s, a->u, &n, a->vt, &n, a->work, &lwork, a->iwork, &info);
|
883
929
|
km_check_info(info, rb_eRuntimeError, "DBDSDC did not converge", "dgesvd");
|
884
930
|
|
885
931
|
int one=1;
|
@@ -890,7 +936,7 @@ VALUE km_svd_symmetrize_body(VALUE data)
|
|
890
936
|
char ta[] = "N";
|
891
937
|
char tb[] = "T";
|
892
938
|
double alpha = 1.0, beta=0.0;
|
893
|
-
dgemm_(ta, tb, &n, &n, &n, &alpha, a->vt, &n, a->u, &n, &beta, a->a.d, &
|
939
|
+
dgemm_(ta, tb, &n, &n, &n, &alpha, a->vt, &n, a->u, &n, &beta, a->a.d, &lda);
|
894
940
|
|
895
941
|
return Qnil;
|
896
942
|
}
|
@@ -934,9 +980,9 @@ km_lu_body(VALUE data)
|
|
934
980
|
{
|
935
981
|
struct km_lu_arg *a = (struct km_lu_arg *)data;
|
936
982
|
|
937
|
-
int m = a->sa->m, n = a->sa->n;
|
938
|
-
int k = MIN(m, n);
|
939
|
-
km_check_size(4, a->spl->m,m, a->spl->n,k, a->su->m,k, a->su->n,n);
|
983
|
+
int m = s2i(a->sa->m), n = s2i(a->sa->n);
|
984
|
+
const int k = MIN(m, n);
|
985
|
+
km_check_size(4, s2i(a->spl->m),m, s2i(a->spl->n),k, s2i(a->su->m),k, s2i(a->su->n),n);
|
940
986
|
|
941
987
|
KALLOCc(a->a, a->sa);
|
942
988
|
KALLOC(a->ipiv, k);
|
@@ -956,18 +1002,19 @@ km_lu_body(VALUE data)
|
|
956
1002
|
SWAP(int, (a->perm)[i], (a->perm)[s]);
|
957
1003
|
}
|
958
1004
|
}
|
1005
|
+
const int ldpl=s2i(a->pl.ld), ldu = s2i(a->u.ld);
|
959
1006
|
for ( int i=0; i<k; i++ ) {
|
960
1007
|
int s = (a->perm)[i];
|
961
|
-
dcopy_(&i, (a->a)+i, &m, (a->pl.d)+s, &
|
962
|
-
(a->pl.d)[s+i*
|
1008
|
+
dcopy_(&i, (a->a)+i, &m, (a->pl.d)+s, &ldpl);
|
1009
|
+
(a->pl.d)[s+i*ldpl] = 1.0;
|
963
1010
|
int izero = 0, len = k-i-1; double dzero = 0.0;
|
964
|
-
dcopy_(&len, &dzero, &izero, (a->pl.d)+(s+(i+1)*(a->pl.ld)), &
|
965
|
-
dcopy_(&i, &dzero, &izero, (a->u.d)+i, &
|
1011
|
+
dcopy_(&len, &dzero, &izero, (a->pl.d)+(s+(i+1)*s2i(a->pl.ld)), &ldpl);
|
1012
|
+
dcopy_(&i, &dzero, &izero, (a->u.d)+i, &ldu);
|
966
1013
|
len = n-i;
|
967
|
-
dcopy_(&len, (a->a)+(i+i*m), &m, (a->u.d)+(i+i*
|
1014
|
+
dcopy_(&len, (a->a)+(i+i*m), &m, (a->u.d)+(i+i*ldu), &ldu);
|
968
1015
|
}
|
969
1016
|
for ( int i=m; i<k; i++ ) {
|
970
|
-
dcopy_(&n, a->a+i, &m, (a->pl.d)+(a->perm)[i], &
|
1017
|
+
dcopy_(&n, a->a+i, &m, (a->pl.d)+(a->perm)[i], &ldpl);
|
971
1018
|
}
|
972
1019
|
|
973
1020
|
return Qnil;
|
@@ -1002,8 +1049,8 @@ VALUE
|
|
1002
1049
|
kmm_mat_lu(VALUE self)
|
1003
1050
|
{
|
1004
1051
|
SMAT *sa = km_mat2smat(self);
|
1005
|
-
|
1006
|
-
|
1052
|
+
const size_t m = sa->m, n = sa->n;
|
1053
|
+
const size_t k = MIN(m, n);
|
1007
1054
|
VALUE vpl = km_Mat(m, k, VT_DOUBLE);
|
1008
1055
|
VALUE vu = km_Mat(k, n, VT_DOUBLE);
|
1009
1056
|
kmm_mat_lu_destl(self, vpl, vu);
|
@@ -1023,9 +1070,9 @@ km_lup_body(VALUE data)
|
|
1023
1070
|
{
|
1024
1071
|
struct km_lup_arg *a = (struct km_lup_arg *)data;
|
1025
1072
|
|
1026
|
-
int m = a->sa->m, n = a->sa->n;
|
1027
|
-
int k = MIN(m, n);
|
1028
|
-
km_check_size(6, a->sl->m,m, a->sl->n,k, a->su->m,k, a->su->n,n, a->sp->m,m, a->sp->n,m);
|
1073
|
+
int m = s2i(a->sa->m), n = s2i(a->sa->n);
|
1074
|
+
const int k = MIN(m, n);
|
1075
|
+
km_check_size(6, s2i(a->sl->m),m, s2i(a->sl->n),k, s2i(a->su->m),k, s2i(a->su->n),n, s2i(a->sp->m),m, s2i(a->sp->n),m);
|
1029
1076
|
|
1030
1077
|
KALLOCc(a->a, a->sa);
|
1031
1078
|
KALLOC(a->ipiv, k);
|
@@ -1041,24 +1088,25 @@ km_lup_body(VALUE data)
|
|
1041
1088
|
dgetrf_(&m, &n, a->a, &m, a->ipiv, &info);
|
1042
1089
|
km_check_info(info, Qnil, NULL, "dgetrf");
|
1043
1090
|
for ( int i=0; i<k; i++ ) {
|
1044
|
-
int s = (a->ipiv)[i]-1;
|
1091
|
+
const int s = (a->ipiv)[i]-1;
|
1045
1092
|
if ( s != i ) {
|
1046
1093
|
SWAP(int, (a->perm)[i], (a->perm)[s]);
|
1047
1094
|
}
|
1048
1095
|
}
|
1096
|
+
const int ldl = s2i(a->l.ld), ldu = s2i(a->u.ld);
|
1049
1097
|
for ( int i=0; i<k; i++ ) {
|
1050
|
-
(a->p.d)[i+(a->perm)[i]*(a->p.ld)] = 1.0;
|
1051
|
-
dcopy_(&i, (a->a)+i, &m, (a->l.d)+i, &
|
1052
|
-
(a->l.d)[i+i*
|
1053
|
-
int len = k-i-1, izero = 0; double dzero = 0.0;
|
1054
|
-
dcopy_(&len, &dzero, &izero, (a->l.d)+(i+(i+1)*
|
1055
|
-
dcopy_(&i, &dzero, &izero, (a->u.d)+i, &
|
1098
|
+
(a->p.d)[i+(a->perm)[i]*s2i(a->p.ld)] = 1.0;
|
1099
|
+
dcopy_(&i, (a->a)+i, &m, (a->l.d)+i, &ldl);
|
1100
|
+
(a->l.d)[i+i*ldl] = 1.0;
|
1101
|
+
int len = k-i-1, izero = 0; const double dzero = 0.0;
|
1102
|
+
dcopy_(&len, &dzero, &izero, (a->l.d)+(i+(i+1)*ldl), &ldl);
|
1103
|
+
dcopy_(&i, &dzero, &izero, (a->u.d)+i, &ldu);
|
1056
1104
|
len = n-i;
|
1057
|
-
dcopy_(&len, (a->a)+(i+i*m), &m, (a->u.d)+(i+i*
|
1105
|
+
dcopy_(&len, (a->a)+(i+i*m), &m, (a->u.d)+(i+i*ldu), &ldu);
|
1058
1106
|
}
|
1059
1107
|
for ( int i=m; i<k; i++ ) {
|
1060
|
-
(a->p.d)[i+(a->perm)[i]*(a->p.ld)] = 1.0;
|
1061
|
-
dcopy_(&n, (a->a)+i, &m, (a->l.d)+i, &
|
1108
|
+
(a->p.d)[i+(a->perm)[i]*s2i(a->p.ld)] = 1.0;
|
1109
|
+
dcopy_(&n, (a->a)+i, &m, (a->l.d)+i, &ldl);
|
1062
1110
|
}
|
1063
1111
|
|
1064
1112
|
return Qnil;
|
@@ -1095,7 +1143,7 @@ VALUE
|
|
1095
1143
|
kmm_mat_lup(VALUE self)
|
1096
1144
|
{
|
1097
1145
|
SMAT *sa = km_mat2smat(self);
|
1098
|
-
|
1146
|
+
const size_t m = sa->m, n = sa->n; const size_t k = MIN(m, n);
|
1099
1147
|
VALUE vl = km_Mat(m, k, VT_DOUBLE);
|
1100
1148
|
VALUE vu = km_Mat(k, n, VT_DOUBLE);
|
1101
1149
|
VALUE vp = km_Mat(m, m, VT_DOUBLE);
|
@@ -1114,8 +1162,8 @@ km_det_body(VALUE data)
|
|
1114
1162
|
{
|
1115
1163
|
struct km_det_arg *a = (struct km_det_arg *)data;
|
1116
1164
|
|
1117
|
-
int n = a->sa->m;
|
1118
|
-
km_check_size(1, a->sa->n,n);
|
1165
|
+
int n = s2i(a->sa->m);
|
1166
|
+
km_check_size(1, s2i(a->sa->n),n);
|
1119
1167
|
if ( n == 0 ) { return rb_float_new(1.0); }
|
1120
1168
|
|
1121
1169
|
KALLOCc(a->a, a->sa);
|
@@ -1165,9 +1213,9 @@ km_qr_body(VALUE data)
|
|
1165
1213
|
{
|
1166
1214
|
struct km_qr_arg *a = (struct km_qr_arg *)data;
|
1167
1215
|
|
1168
|
-
int m = a->sa->m, n = a->sa->n;
|
1216
|
+
int m = s2i(a->sa->m), n = s2i(a->sa->n);
|
1169
1217
|
int k = MIN(m, n);
|
1170
|
-
km_check_size(4, a->sq->m,m, a->sq->n,m, a->sr->m,m, a->sr->n,n);
|
1218
|
+
km_check_size(4, s2i(a->sq->m),m, s2i(a->sq->n),m, s2i(a->sr->m),m, s2i(a->sr->n),n);
|
1171
1219
|
|
1172
1220
|
double opt; int lwork=-1, info;
|
1173
1221
|
dgeqrf_(&m, &n, NULL, &m, NULL, &opt, &lwork, &info);
|
@@ -1187,24 +1235,25 @@ km_qr_body(VALUE data)
|
|
1187
1235
|
KALLOC(a->work, lwork);
|
1188
1236
|
KALLOCn(a->q, a->sq);
|
1189
1237
|
KALLOCn(a->r, a->sr);
|
1238
|
+
int ldr=s2i(a->r.ld), ldq=s2i(a->q.ld);
|
1190
1239
|
for ( int i=m; i<k; i++ ) { // 0 clear (i>=k)-th rows of r and (i>=k)-th columns of q
|
1191
|
-
int izero=0; double dzero=0.0;
|
1192
|
-
dcopy_(&n, &dzero, &izero, (a->r.d)+i, &
|
1193
|
-
int ione=1;
|
1194
|
-
dcopy_(&m, &dzero, &izero, (a->q.d)+i*
|
1240
|
+
const int izero=0; const double dzero=0.0;
|
1241
|
+
dcopy_(&n, &dzero, &izero, (a->r.d)+i, &ldr);
|
1242
|
+
const int ione=1;
|
1243
|
+
dcopy_(&m, &dzero, &izero, (a->q.d)+i*ldq, &(ione));
|
1195
1244
|
}
|
1196
1245
|
for ( int i=0; i<k; i++ ) { // copy the results of `dgeqrf' to q.d, rd, construct R and prepare to call `dorgqr'
|
1197
|
-
int izero=0; double dzero=0.0;
|
1198
|
-
dcopy_(&i, &dzero, &izero, (a->r.d)+i, &
|
1246
|
+
const int izero=0; const double dzero=0.0;
|
1247
|
+
dcopy_(&i, &dzero, &izero, (a->r.d)+i, &ldr);
|
1199
1248
|
int l = n-i;
|
1200
|
-
dcopy_(&l, (a->a)+(i+i*m), &m, (a->r.d)+(i+i*
|
1201
|
-
int ione = 1;
|
1202
|
-
dcopy_(&i, &dzero, &izero, (a->q.d)+(i*
|
1203
|
-
(a->q.d)[i+i*
|
1249
|
+
dcopy_(&l, (a->a)+(i+i*m), &m, (a->r.d)+(i+i*ldr), &ldr);
|
1250
|
+
const int ione = 1;
|
1251
|
+
dcopy_(&i, &dzero, &izero, (a->q.d)+(i*ldq), &ione);
|
1252
|
+
(a->q.d)[i+i*ldq] = 1.0;
|
1204
1253
|
l = m-i-1;
|
1205
|
-
dcopy_(&l, (a->a)+(i+i*m+1), &ione, (a->q.d)+(i+i*
|
1254
|
+
dcopy_(&l, (a->a)+(i+i*m+1), &ione, (a->q.d)+(i+i*ldq+1), &ione);
|
1206
1255
|
}
|
1207
|
-
dorgqr_(&m, &m, &k, a->q.d, &
|
1256
|
+
dorgqr_(&m, &m, &k, a->q.d, &ldq, a->tau, a->work, &lwork, &info);
|
1208
1257
|
km_check_info(info, rb_eRuntimeError, "unexpected info value", "dorgqr");
|
1209
1258
|
|
1210
1259
|
return Qnil;
|
@@ -1258,8 +1307,8 @@ km_rand_orth_body(VALUE data)
|
|
1258
1307
|
{
|
1259
1308
|
struct km_rand_orth_arg *a = (struct km_rand_orth_arg *)data;
|
1260
1309
|
|
1261
|
-
int n = a->smat->m;
|
1262
|
-
km_check_size(1, a->smat->n,n);
|
1310
|
+
int n = s2i(a->smat->m);
|
1311
|
+
km_check_size(1, s2i(a->smat->n),n);
|
1263
1312
|
|
1264
1313
|
double opt; int lwork=-1, info;
|
1265
1314
|
dgeqrf_(&n, &n, NULL, &n, NULL, &opt, &lwork, &info);
|
@@ -1268,8 +1317,9 @@ km_rand_orth_body(VALUE data)
|
|
1268
1317
|
|
1269
1318
|
KALLOC(a->tau, n);
|
1270
1319
|
KALLOC(a->work, lwork);
|
1320
|
+
KALLOCn(a->a, a->smat);
|
1271
1321
|
|
1272
|
-
km_fill_normal(n*n, a->a.d, a->random);
|
1322
|
+
km_fill_normal(i2s(n*n), a->a.d, a->random);
|
1273
1323
|
dgeqrf_(&n, &n, a->a.d, &n, a->tau, a->work, &lwork, &info);
|
1274
1324
|
km_check_info(info, rb_eRuntimeError, "unexpected info value", "dgeqrf");
|
1275
1325
|
ruby_xfree(a->work);
|
@@ -1280,18 +1330,18 @@ km_rand_orth_body(VALUE data)
|
|
1280
1330
|
lwork = (int)opt;
|
1281
1331
|
|
1282
1332
|
KALLOC(a->work, lwork);
|
1283
|
-
|
1333
|
+
int lda = s2i(a->a.ld);
|
1284
1334
|
|
1285
1335
|
for (int i=0; i<n; i++ ) { // clear R to prepare to call `dorgqr'
|
1286
|
-
int l = n-i
|
1287
|
-
dcopy_(&l, &dzero, &izero, (a->a.d)+x, &
|
1336
|
+
const int l = n-i, izero = 0; const double dzero = 0.0; const int x=i+i*lda;
|
1337
|
+
dcopy_(&l, &dzero, &izero, (a->a.d)+x, &lda);
|
1288
1338
|
(a->a.d)[x] = 1.0;
|
1289
1339
|
}
|
1290
|
-
dorgqr_(&n, &n, &n, a->a.d, &
|
1340
|
+
dorgqr_(&n, &n, &n, a->a.d, &lda, a->tau, a->work, &lwork, &info);
|
1291
1341
|
km_check_info(info, rb_eRuntimeError, "unexpected info value", "dorgqr");
|
1292
1342
|
// multiply by scalar -1 with probability 1/2
|
1293
1343
|
if ( rb_funcall(a->random, id_rand, 1, INT2NUM(2)) == INT2NUM(0) ) {
|
1294
|
-
int l = n*n, ione=1; double m1=-1.0;
|
1344
|
+
const int l = n*n, ione=1; const double m1=-1.0;
|
1295
1345
|
dscal_(&l, &m1, a->a.d, &ione);
|
1296
1346
|
}
|
1297
1347
|
|
@@ -1336,8 +1386,8 @@ km_balance_body(VALUE data)
|
|
1336
1386
|
{
|
1337
1387
|
struct km_balance_arg *a = (struct km_balance_arg *)data;
|
1338
1388
|
|
1339
|
-
int n = a->sa->m;
|
1340
|
-
km_check_size(5, a->sa->n,n, a->sd->m,n, a->sd->n,n, a->saa->m,n, a->saa->n,n);
|
1389
|
+
int n = s2i(a->sa->m);
|
1390
|
+
km_check_size(5, s2i(a->sa->n),n, s2i(a->sd->m),n, s2i(a->sd->n),n, s2i(a->saa->m),n, s2i(a->saa->n),n);
|
1341
1391
|
|
1342
1392
|
KALLOC(a->scale, n);
|
1343
1393
|
KALLOC(a->perm, n);
|
@@ -1349,7 +1399,8 @@ km_balance_body(VALUE data)
|
|
1349
1399
|
|
1350
1400
|
int ilo, ihi, info;
|
1351
1401
|
char job[] = "B";
|
1352
|
-
|
1402
|
+
int lda=s2i(a->a.ld);
|
1403
|
+
dgebal_(job, &n, a->a.d, &lda, &ilo, &ihi, a->scale, &info);
|
1353
1404
|
km_check_info(info, rb_eRuntimeError, "unexpected info value", "dgebal");
|
1354
1405
|
for ( int i=ilo-2; 0 <= i; i-- ) {
|
1355
1406
|
SWAP(int, (a->perm)[i], (a->perm)[(int)((a->scale)[i])-1]);
|
@@ -1359,9 +1410,9 @@ km_balance_body(VALUE data)
|
|
1359
1410
|
}
|
1360
1411
|
for ( int i=0; i<n; i++ ) {
|
1361
1412
|
if ( i < ilo-1 || ihi <= i ) { // permutation
|
1362
|
-
(a->d.d)[(a->perm)[i]+i*(a->d.ld)] = 1.0;
|
1413
|
+
(a->d.d)[(a->perm)[i]+i*s2i(a->d.ld)] = 1.0;
|
1363
1414
|
} else {
|
1364
|
-
(a->d.d)[(a->perm)[i]+i*(a->d.ld)] = (a->scale)[i];
|
1415
|
+
(a->d.d)[(a->perm)[i]+i*s2i(a->d.ld)] = (a->scale)[i];
|
1365
1416
|
}
|
1366
1417
|
}
|
1367
1418
|
|
@@ -1395,7 +1446,7 @@ kmm_mat_balance_destl(VALUE self, VALUE vd, VALUE vaa)
|
|
1395
1446
|
VALUE
|
1396
1447
|
kmm_mat_balance(VALUE self)
|
1397
1448
|
{
|
1398
|
-
|
1449
|
+
const size_t n = km_mat2smat(self)->m;
|
1399
1450
|
VALUE vd = km_Mat(n, n, VT_DOUBLE);
|
1400
1451
|
VALUE vaa = km_Mat(n, n, VT_DOUBLE);
|
1401
1452
|
kmm_mat_balance_destl(self, vd, vaa);
|
@@ -1418,23 +1469,24 @@ km_expm_body(VALUE data)
|
|
1418
1469
|
{
|
1419
1470
|
struct km_expm_arg *a = (struct km_expm_arg *)data;
|
1420
1471
|
|
1421
|
-
int n = a->sa->m; int n2 = n*n;
|
1422
|
-
km_check_size(1, a->sa->n,n);
|
1472
|
+
int n = s2i(a->sa->m); const int n2 = n*n;
|
1473
|
+
km_check_size(1, s2i(a->sa->n),n);
|
1423
1474
|
|
1424
1475
|
// trace reduction
|
1425
1476
|
double neg_max = -DBL_MAX;
|
1426
1477
|
KALLOCn(a->a, a->sa);
|
1478
|
+
int lda=s2i(a->a.ld);
|
1427
1479
|
for ( int i=0; i<n; i++ ) { for ( int j=0; j<n; j++ ) {
|
1428
|
-
if ( (a->a.d)[i+j*
|
1480
|
+
if ( (a->a.d)[i+j*lda] < neg_max ) { (a->a.d)[i+j*lda] = neg_max; }
|
1429
1481
|
} }
|
1430
1482
|
double trshift = 0.0;
|
1431
1483
|
for ( int i=0; i<n; i++ ) {
|
1432
|
-
trshift += (a->a.d)[i+i*
|
1484
|
+
trshift += (a->a.d)[i+i*lda];
|
1433
1485
|
}
|
1434
1486
|
if ( 0 < trshift ) {
|
1435
1487
|
trshift /= n;
|
1436
1488
|
for ( int i=0; i<n; i++ ) {
|
1437
|
-
(a->a.d)[i+i*
|
1489
|
+
(a->a.d)[i+i*lda] -= trshift;
|
1438
1490
|
}
|
1439
1491
|
}
|
1440
1492
|
|
@@ -1442,14 +1494,14 @@ km_expm_body(VALUE data)
|
|
1442
1494
|
int ilo, ihi, info;
|
1443
1495
|
char job[] = "B";
|
1444
1496
|
KALLOC(a->scale, n);
|
1445
|
-
dgebal_(job, &n, a->a.d, &
|
1497
|
+
dgebal_(job, &n, a->a.d, &lda, &ilo, &ihi, a->scale, &info);
|
1446
1498
|
km_check_info(info, rb_eRuntimeError, "unexpected info value", "dgebal");
|
1447
1499
|
|
1448
1500
|
// scaling
|
1449
|
-
int ione=1;
|
1501
|
+
const int ione=1;
|
1450
1502
|
double s = 0.0;
|
1451
1503
|
for ( int i=0; i<n; i++ ) {
|
1452
|
-
double foo = dasum_(&n, (a->a.d)+i, &
|
1504
|
+
double foo = dasum_(&n, (a->a.d)+i, &lda);
|
1453
1505
|
if ( s < foo ) { s = foo; }
|
1454
1506
|
}
|
1455
1507
|
s = logb(s);
|
@@ -1458,27 +1510,27 @@ km_expm_body(VALUE data)
|
|
1458
1510
|
} else if ( 1023.0 < s ) {
|
1459
1511
|
s = 1023.0;
|
1460
1512
|
}
|
1461
|
-
double ps = exp2(-s);
|
1513
|
+
const double ps = exp2(-s);
|
1462
1514
|
for ( int i=0; i<n; i++ ) {
|
1463
|
-
dscal_(&n, &ps, (a->a.d)+(i*
|
1515
|
+
dscal_(&n, &ps, (a->a.d)+(i*lda), &ione);
|
1464
1516
|
}
|
1465
1517
|
|
1466
1518
|
// Pade approximation
|
1467
1519
|
static const double c[] = { 5.0000000000000000e-1, 1.1666666666666667e-1, 1.6666666666666667e-2, 1.6025641025641026e-3,
|
1468
1520
|
1.0683760683760684e-4, 4.8562548562548563e-6, 1.3875013875013875e-7, 1.9270852604185938e-9 };
|
1469
|
-
int np1 = n+1;
|
1521
|
+
const int np1 = n+1;
|
1470
1522
|
KALLOC(a->a2, n2);
|
1471
1523
|
KALLOC(a->x, n2);
|
1472
1524
|
KALLOC(a->y, n2);
|
1473
1525
|
KALLOC(a->foo, n2);
|
1474
1526
|
#define MPROD(_r, _a, _b) km_dmprod(n, n, n, _a, _b, _r)
|
1475
|
-
#define A a->a.d,
|
1527
|
+
#define A a->a.d, lda
|
1476
1528
|
#define A2 a->a2, n
|
1477
1529
|
#define X a->x, n
|
1478
1530
|
#define Y a->y, n
|
1479
1531
|
#define FOO a->foo, n
|
1480
1532
|
MPROD(A2, A, A); // a2 = a*a
|
1481
|
-
memcpy( a->foo, a->a2, sizeof(double)*(
|
1533
|
+
memcpy( a->foo, a->a2, sizeof(double)*i2s(n2) ); // foo = a2
|
1482
1534
|
dscal_( &n2, c+7, a->foo, &ione ); // foo *= c[7]
|
1483
1535
|
for ( int i=0; i<n; i++ ) { a->foo[i*np1] += c[5]; } // foo += c[5]*I
|
1484
1536
|
MPROD(X, FOO, A2); // x = foo*a2 = a^4*c[7]+a^2*c[5]
|
@@ -1514,14 +1566,14 @@ km_expm_body(VALUE data)
|
|
1514
1566
|
char fact[]="E";
|
1515
1567
|
char trans[]="N";
|
1516
1568
|
dgesvx_(fact, trans, &n, &n, a->y, &n, a->a2, &n, a->ipiv, equed, a->r, a->c, a->x, &n,
|
1517
|
-
a->a.d, &
|
1569
|
+
a->a.d, &lda, &alp, a->ferr, a->berr, a->work, a->iwork, &info);
|
1518
1570
|
km_check_info(info, km_eUncomp, "an internal matrix is singular or near singular", "dgesvx");
|
1519
1571
|
|
1520
1572
|
// undo scaling by repeated squaring
|
1521
|
-
int is = (int)s;
|
1573
|
+
const int is = (int)s;
|
1522
1574
|
if ( is & 1 ) { // if is is odd, then r = r^2
|
1523
1575
|
MPROD(FOO, A, A);
|
1524
|
-
dlacpy_(job, &n, &n, a->foo, &n, a->a.d, &
|
1576
|
+
dlacpy_(job, &n, &n, a->foo, &n, a->a.d, &lda);
|
1525
1577
|
}
|
1526
1578
|
for ( int i=0; i<is/2; i++ ) {
|
1527
1579
|
MPROD(FOO, A, A);
|
@@ -1587,16 +1639,17 @@ km_chol_body(VALUE data)
|
|
1587
1639
|
{
|
1588
1640
|
struct km_chol_arg *a = (struct km_chol_arg *)data;
|
1589
1641
|
|
1590
|
-
int n = a->sa->m, info;
|
1642
|
+
int n = s2i(a->sa->m), info;
|
1591
1643
|
|
1592
1644
|
KALLOCn(a->a, a->sa);
|
1593
1645
|
char uplo[] = "U";
|
1594
|
-
|
1646
|
+
int lda=s2i(a->a.ld);
|
1647
|
+
dpotrf_(uplo, &n, a->a.d, &lda, &info);
|
1595
1648
|
km_check_info(info, km_eUncomp, "self is not positive definite", "dpotrf");
|
1596
1649
|
int ione=1, izero=0; double dzero=0.0;
|
1597
1650
|
for ( int i=0; i<n-1; i++ ) {
|
1598
1651
|
const int len=n-i-1;
|
1599
|
-
dcopy_(&len, &dzero, &izero, (a->a.d)+(i+i*
|
1652
|
+
dcopy_(&len, &dzero, &izero, (a->a.d)+(i+i*lda+1), &ione);
|
1600
1653
|
}
|
1601
1654
|
|
1602
1655
|
return Qnil;
|
@@ -1626,4 +1679,3 @@ kmm_mat_chol_dest(VALUE self)
|
|
1626
1679
|
|
1627
1680
|
return self;
|
1628
1681
|
}
|
1629
|
-
|