summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/base/src/Internal/C/lapack-aux.c50
-rw-r--r--packages/base/src/Internal/LAPACK.hs37
2 files changed, 34 insertions, 53 deletions
diff --git a/packages/base/src/Internal/C/lapack-aux.c b/packages/base/src/Internal/C/lapack-aux.c
index 8524962..72c44cb 100644
--- a/packages/base/src/Internal/C/lapack-aux.c
+++ b/packages/base/src/Internal/C/lapack-aux.c
@@ -354,12 +354,12 @@ int svd_l_Cdd(KOCMAT(a),OCMAT(u), DVEC(s),OCMAT(v)) {
354 354
355//////////////////// general complex eigensystem //////////// 355//////////////////// general complex eigensystem ////////////
356 356
357/* Subroutine */ int zgeev_(char *jobvl, char *jobvr, integer *n, 357int zgeev_(char *jobvl, char *jobvr, integer *n,
358 doublecomplex *a, integer *lda, doublecomplex *w, doublecomplex *vl, 358 doublecomplex *a, integer *lda, doublecomplex *w, doublecomplex *vl,
359 integer *ldvl, doublecomplex *vr, integer *ldvr, doublecomplex *work, 359 integer *ldvl, doublecomplex *vr, integer *ldvr, doublecomplex *work,
360 integer *lwork, doublereal *rwork, integer *info); 360 integer *lwork, doublereal *rwork, integer *info);
361 361
362int eig_l_C(KOCMAT(a), OCMAT(u), CVEC(s),OCMAT(v)) { 362int eig_l_C(OCMAT(a), OCMAT(u), CVEC(s),OCMAT(v)) {
363 integer n = ar; 363 integer n = ar;
364 REQUIRES(ac==n && sn==n, BAD_SIZE); 364 REQUIRES(ac==n && sn==n, BAD_SIZE);
365 REQUIRES(up==NULL || (ur==n && uc==n), BAD_SIZE); 365 REQUIRES(up==NULL || (ur==n && uc==n), BAD_SIZE);
@@ -367,18 +367,14 @@ int eig_l_C(KOCMAT(a), OCMAT(u), CVEC(s),OCMAT(v)) {
367 REQUIRES(vp==NULL || (vr==n && vc==n), BAD_SIZE); 367 REQUIRES(vp==NULL || (vr==n && vc==n), BAD_SIZE);
368 char jobvr = vp==NULL?'N':'V'; 368 char jobvr = vp==NULL?'N':'V';
369 DEBUGMSG("eig_l_C"); 369 DEBUGMSG("eig_l_C");
370 doublecomplex *B = (doublecomplex*)malloc(n*n*sizeof(doublecomplex));
371 CHECK(!B,MEM);
372 memcpy(B,ap,n*n*sizeof(doublecomplex));
373 double *rwork = (double*) malloc(2*n*sizeof(double)); 370 double *rwork = (double*) malloc(2*n*sizeof(double));
374 CHECK(!rwork,MEM); 371 CHECK(!rwork,MEM);
375 integer lwork = -1; 372 integer lwork = -1;
376 integer res; 373 integer res;
377 // ask for optimal lwork 374 // ask for optimal lwork
378 doublecomplex ans; 375 doublecomplex ans;
379 //printf("ask zgeev\n");
380 zgeev_ (&jobvl,&jobvr, 376 zgeev_ (&jobvl,&jobvr,
381 &n,B,&n, 377 &n,ap,&n,
382 sp, 378 sp,
383 up,&n, 379 up,&n,
384 vp,&n, 380 vp,&n,
@@ -386,12 +382,10 @@ int eig_l_C(KOCMAT(a), OCMAT(u), CVEC(s),OCMAT(v)) {
386 rwork, 382 rwork,
387 &res); 383 &res);
388 lwork = ceil(ans.r); 384 lwork = ceil(ans.r);
389 //printf("ans = %d\n",lwork);
390 doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex)); 385 doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex));
391 CHECK(!work,MEM); 386 CHECK(!work,MEM);
392 //printf("zgeev\n");
393 zgeev_ (&jobvl,&jobvr, 387 zgeev_ (&jobvl,&jobvr,
394 &n,B,&n, 388 &n,ap,&n,
395 sp, 389 sp,
396 up,&n, 390 up,&n,
397 vp,&n, 391 vp,&n,
@@ -401,7 +395,6 @@ int eig_l_C(KOCMAT(a), OCMAT(u), CVEC(s),OCMAT(v)) {
401 CHECK(res,res); 395 CHECK(res,res);
402 free(work); 396 free(work);
403 free(rwork); 397 free(rwork);
404 free(B);
405 OK 398 OK
406} 399}
407 400
@@ -409,12 +402,12 @@ int eig_l_C(KOCMAT(a), OCMAT(u), CVEC(s),OCMAT(v)) {
409 402
410//////////////////// general real eigensystem //////////// 403//////////////////// general real eigensystem ////////////
411 404
412/* Subroutine */ int dgeev_(char *jobvl, char *jobvr, integer *n, doublereal * 405int dgeev_(char *jobvl, char *jobvr, integer *n, doublereal *
413 a, integer *lda, doublereal *wr, doublereal *wi, doublereal *vl, 406 a, integer *lda, doublereal *wr, doublereal *wi, doublereal *vl,
414 integer *ldvl, doublereal *vr, integer *ldvr, doublereal *work, 407 integer *ldvl, doublereal *vr, integer *ldvr, doublereal *work,
415 integer *lwork, integer *info); 408 integer *lwork, integer *info);
416 409
417int eig_l_R(KODMAT(a),ODMAT(u), CVEC(s),ODMAT(v)) { 410int eig_l_R(ODMAT(a),ODMAT(u), CVEC(s),ODMAT(v)) {
418 integer n = ar; 411 integer n = ar;
419 REQUIRES(ac==n && sn==n, BAD_SIZE); 412 REQUIRES(ac==n && sn==n, BAD_SIZE);
420 REQUIRES(up==NULL || (ur==n && uc==n), BAD_SIZE); 413 REQUIRES(up==NULL || (ur==n && uc==n), BAD_SIZE);
@@ -422,28 +415,22 @@ int eig_l_R(KODMAT(a),ODMAT(u), CVEC(s),ODMAT(v)) {
422 REQUIRES(vp==NULL || (vr==n && vc==n), BAD_SIZE); 415 REQUIRES(vp==NULL || (vr==n && vc==n), BAD_SIZE);
423 char jobvr = vp==NULL?'N':'V'; 416 char jobvr = vp==NULL?'N':'V';
424 DEBUGMSG("eig_l_R"); 417 DEBUGMSG("eig_l_R");
425 double *B = (double*)malloc(n*n*sizeof(double));
426 CHECK(!B,MEM);
427 memcpy(B,ap,n*n*sizeof(double));
428 integer lwork = -1; 418 integer lwork = -1;
429 integer res; 419 integer res;
430 // ask for optimal lwork 420 // ask for optimal lwork
431 double ans; 421 double ans;
432 //printf("ask dgeev\n");
433 dgeev_ (&jobvl,&jobvr, 422 dgeev_ (&jobvl,&jobvr,
434 &n,B,&n, 423 &n,ap,&n,
435 (double*)sp, (double*)sp+n, 424 (double*)sp, (double*)sp+n,
436 up,&n, 425 up,&n,
437 vp,&n, 426 vp,&n,
438 &ans, &lwork, 427 &ans, &lwork,
439 &res); 428 &res);
440 lwork = ceil(ans); 429 lwork = ceil(ans);
441 //printf("ans = %d\n",lwork);
442 double * work = (double*)malloc(lwork*sizeof(double)); 430 double * work = (double*)malloc(lwork*sizeof(double));
443 CHECK(!work,MEM); 431 CHECK(!work,MEM);
444 //printf("dgeev\n");
445 dgeev_ (&jobvl,&jobvr, 432 dgeev_ (&jobvl,&jobvr,
446 &n,B,&n, 433 &n,ap,&n,
447 (double*)sp, (double*)sp+n, 434 (double*)sp, (double*)sp+n,
448 up,&n, 435 up,&n,
449 vp,&n, 436 vp,&n,
@@ -451,37 +438,32 @@ int eig_l_R(KODMAT(a),ODMAT(u), CVEC(s),ODMAT(v)) {
451 &res); 438 &res);
452 CHECK(res,res); 439 CHECK(res,res);
453 free(work); 440 free(work);
454 free(B);
455 OK 441 OK
456} 442}
457 443
458 444
459//////////////////// symmetric real eigensystem //////////// 445//////////////////// symmetric real eigensystem ////////////
460 446
461/* Subroutine */ int dsyev_(char *jobz, char *uplo, integer *n, doublereal *a, 447int dsyev_(char *jobz, char *uplo, integer *n, doublereal *a,
462 integer *lda, doublereal *w, doublereal *work, integer *lwork, 448 integer *lda, doublereal *w, doublereal *work, integer *lwork,
463 integer *info); 449 integer *info);
464 450
465int eig_l_S(int wantV,KODMAT(a),DVEC(s),ODMAT(v)) { 451int eig_l_S(int wantV,DVEC(s),ODMAT(v)) {
466 integer n = ar; 452 integer n = sn;
467 REQUIRES(ac==n && sn==n, BAD_SIZE);
468 REQUIRES(vr==n && vc==n, BAD_SIZE); 453 REQUIRES(vr==n && vc==n, BAD_SIZE);
469 char jobz = wantV?'V':'N'; 454 char jobz = wantV?'V':'N';
470 DEBUGMSG("eig_l_S"); 455 DEBUGMSG("eig_l_S");
471 memcpy(vp,ap,n*n*sizeof(double));
472 integer lwork = -1; 456 integer lwork = -1;
473 char uplo = 'U'; 457 char uplo = 'U';
474 integer res; 458 integer res;
475 // ask for optimal lwork 459 // ask for optimal lwork
476 double ans; 460 double ans;
477 //printf("ask dsyev\n");
478 dsyev_ (&jobz,&uplo, 461 dsyev_ (&jobz,&uplo,
479 &n,vp,&n, 462 &n,vp,&n,
480 sp, 463 sp,
481 &ans, &lwork, 464 &ans, &lwork,
482 &res); 465 &res);
483 lwork = ceil(ans); 466 lwork = ceil(ans);
484 //printf("ans = %d\n",lwork);
485 double * work = (double*)malloc(lwork*sizeof(double)); 467 double * work = (double*)malloc(lwork*sizeof(double));
486 CHECK(!work,MEM); 468 CHECK(!work,MEM);
487 dsyev_ (&jobz,&uplo, 469 dsyev_ (&jobz,&uplo,
@@ -496,17 +478,15 @@ int eig_l_S(int wantV,KODMAT(a),DVEC(s),ODMAT(v)) {
496 478
497//////////////////// hermitian complex eigensystem //////////// 479//////////////////// hermitian complex eigensystem ////////////
498 480
499/* Subroutine */ int zheev_(char *jobz, char *uplo, integer *n, doublecomplex 481int zheev_(char *jobz, char *uplo, integer *n, doublecomplex
500 *a, integer *lda, doublereal *w, doublecomplex *work, integer *lwork, 482 *a, integer *lda, doublereal *w, doublecomplex *work, integer *lwork,
501 doublereal *rwork, integer *info); 483 doublereal *rwork, integer *info);
502 484
503int eig_l_H(int wantV,KOCMAT(a),DVEC(s),OCMAT(v)) { 485int eig_l_H(int wantV,DVEC(s),OCMAT(v)) {
504 integer n = ar; 486 integer n = sn;
505 REQUIRES(ac==n && sn==n, BAD_SIZE);
506 REQUIRES(vr==n && vc==n, BAD_SIZE); 487 REQUIRES(vr==n && vc==n, BAD_SIZE);
507 char jobz = wantV?'V':'N'; 488 char jobz = wantV?'V':'N';
508 DEBUGMSG("eig_l_H"); 489 DEBUGMSG("eig_l_H");
509 memcpy(vp,ap,2*n*n*sizeof(double));
510 double *rwork = (double*) malloc((3*n-2)*sizeof(double)); 490 double *rwork = (double*) malloc((3*n-2)*sizeof(double));
511 CHECK(!rwork,MEM); 491 CHECK(!rwork,MEM);
512 integer lwork = -1; 492 integer lwork = -1;
@@ -514,7 +494,6 @@ int eig_l_H(int wantV,KOCMAT(a),DVEC(s),OCMAT(v)) {
514 integer res; 494 integer res;
515 // ask for optimal lwork 495 // ask for optimal lwork
516 doublecomplex ans; 496 doublecomplex ans;
517 //printf("ask zheev\n");
518 zheev_ (&jobz,&uplo, 497 zheev_ (&jobz,&uplo,
519 &n,vp,&n, 498 &n,vp,&n,
520 sp, 499 sp,
@@ -522,7 +501,6 @@ int eig_l_H(int wantV,KOCMAT(a),DVEC(s),OCMAT(v)) {
522 rwork, 501 rwork,
523 &res); 502 &res);
524 lwork = ceil(ans.r); 503 lwork = ceil(ans.r);
525 //printf("ans = %d\n",lwork);
526 doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex)); 504 doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex));
527 CHECK(!work,MEM); 505 CHECK(!work,MEM);
528 zheev_ (&jobz,&uplo, 506 zheev_ (&jobz,&uplo,
diff --git a/packages/base/src/Internal/LAPACK.hs b/packages/base/src/Internal/LAPACK.hs
index 65deceb..049c11e 100644
--- a/packages/base/src/Internal/LAPACK.hs
+++ b/packages/base/src/Internal/LAPACK.hs
@@ -225,13 +225,14 @@ leftSVAux f st x = unsafePerformIO $ do
225 225
226foreign import ccall unsafe "eig_l_R" dgeev :: R ::> R ::> C :> R ::> Ok 226foreign import ccall unsafe "eig_l_R" dgeev :: R ::> R ::> C :> R ::> Ok
227foreign import ccall unsafe "eig_l_C" zgeev :: C ::> C ::> C :> C ::> Ok 227foreign import ccall unsafe "eig_l_C" zgeev :: C ::> C ::> C :> C ::> Ok
228foreign import ccall unsafe "eig_l_S" dsyev :: CInt -> R ::> R :> R ::> Ok 228foreign import ccall unsafe "eig_l_S" dsyev :: CInt -> R :> R ::> Ok
229foreign import ccall unsafe "eig_l_H" zheev :: CInt -> C ::> R :> C ::> Ok 229foreign import ccall unsafe "eig_l_H" zheev :: CInt -> R :> C ::> Ok
230 230
231eigAux f st m = unsafePerformIO $ do 231eigAux f st m = unsafePerformIO $ do
232 a <- copy ColumnMajor m
232 l <- createVector r 233 l <- createVector r
233 v <- createMatrix ColumnMajor r r 234 v <- createMatrix ColumnMajor r r
234 g # m # l # v #| st 235 g # a # l # v #| st
235 return (l,v) 236 return (l,v)
236 where 237 where
237 r = rows m 238 r = rows m
@@ -241,11 +242,12 @@ eigAux f st m = unsafePerformIO $ do
241-- | Eigenvalues and right eigenvectors of a general complex matrix, using LAPACK's /zgeev/. 242-- | Eigenvalues and right eigenvectors of a general complex matrix, using LAPACK's /zgeev/.
242-- The eigenvectors are the columns of v. The eigenvalues are not sorted. 243-- The eigenvectors are the columns of v. The eigenvalues are not sorted.
243eigC :: Matrix (Complex Double) -> (Vector (Complex Double), Matrix (Complex Double)) 244eigC :: Matrix (Complex Double) -> (Vector (Complex Double), Matrix (Complex Double))
244eigC = eigAux zgeev "eigC" . fmat 245eigC = eigAux zgeev "eigC"
245 246
246eigOnlyAux f st m = unsafePerformIO $ do 247eigOnlyAux f st m = unsafePerformIO $ do
248 a <- copy ColumnMajor m
247 l <- createVector r 249 l <- createVector r
248 g # m # l #| st 250 g # a # l #| st
249 return l 251 return l
250 where 252 where
251 r = rows m 253 r = rows m
@@ -254,22 +256,23 @@ eigOnlyAux f st m = unsafePerformIO $ do
254-- | Eigenvalues of a general complex matrix, using LAPACK's /zgeev/ with jobz == \'N\'. 256-- | Eigenvalues of a general complex matrix, using LAPACK's /zgeev/ with jobz == \'N\'.
255-- The eigenvalues are not sorted. 257-- The eigenvalues are not sorted.
256eigOnlyC :: Matrix (Complex Double) -> Vector (Complex Double) 258eigOnlyC :: Matrix (Complex Double) -> Vector (Complex Double)
257eigOnlyC = eigOnlyAux zgeev "eigOnlyC" . fmat 259eigOnlyC = eigOnlyAux zgeev "eigOnlyC"
258 260
259-- | Eigenvalues and right eigenvectors of a general real matrix, using LAPACK's /dgeev/. 261-- | Eigenvalues and right eigenvectors of a general real matrix, using LAPACK's /dgeev/.
260-- The eigenvectors are the columns of v. The eigenvalues are not sorted. 262-- The eigenvectors are the columns of v. The eigenvalues are not sorted.
261eigR :: Matrix Double -> (Vector (Complex Double), Matrix (Complex Double)) 263eigR :: Matrix Double -> (Vector (Complex Double), Matrix (Complex Double))
262eigR m = (s', v'') 264eigR m = (s', v'')
263 where (s,v) = eigRaux (fmat m) 265 where (s,v) = eigRaux m
264 s' = fixeig1 s 266 s' = fixeig1 s
265 v' = toRows $ trans v 267 v' = toRows $ trans v
266 v'' = fromColumns $ fixeig (toList s') v' 268 v'' = fromColumns $ fixeig (toList s') v'
267 269
268eigRaux :: Matrix Double -> (Vector (Complex Double), Matrix Double) 270eigRaux :: Matrix Double -> (Vector (Complex Double), Matrix Double)
269eigRaux m = unsafePerformIO $ do 271eigRaux m = unsafePerformIO $ do
272 a <- copy ColumnMajor m
270 l <- createVector r 273 l <- createVector r
271 v <- createMatrix ColumnMajor r r 274 v <- createMatrix ColumnMajor r r
272 g # m # l # v #| "eigR" 275 g # a # l # v #| "eigR"
273 return (l,v) 276 return (l,v)
274 where 277 where
275 r = rows m 278 r = rows m
@@ -289,15 +292,15 @@ fixeig _ _ = error "fixeig with impossible inputs"
289-- | Eigenvalues of a general real matrix, using LAPACK's /dgeev/ with jobz == \'N\'. 292-- | Eigenvalues of a general real matrix, using LAPACK's /dgeev/ with jobz == \'N\'.
290-- The eigenvalues are not sorted. 293-- The eigenvalues are not sorted.
291eigOnlyR :: Matrix Double -> Vector (Complex Double) 294eigOnlyR :: Matrix Double -> Vector (Complex Double)
292eigOnlyR = fixeig1 . eigOnlyAux dgeev "eigOnlyR" . fmat 295eigOnlyR = fixeig1 . eigOnlyAux dgeev "eigOnlyR"
293 296
294 297
295----------------------------------------------------------------------------- 298-----------------------------------------------------------------------------
296 299
297eigSHAux f st m = unsafePerformIO $ do 300eigSHAux f st m = unsafePerformIO $ do
298 l <- createVector r 301 l <- createVector r
299 v <- createMatrix ColumnMajor r r 302 v <- copy ColumnMajor m
300 f # m # l # v #| st 303 f # l # v #| st
301 return (l,v) 304 return (l,v)
302 where 305 where
303 r = rows m 306 r = rows m
@@ -307,12 +310,12 @@ eigSHAux f st m = unsafePerformIO $ do
307-- The eigenvalues are sorted in descending order (use 'eigS'' for ascending order). 310-- The eigenvalues are sorted in descending order (use 'eigS'' for ascending order).
308eigS :: Matrix Double -> (Vector Double, Matrix Double) 311eigS :: Matrix Double -> (Vector Double, Matrix Double)
309eigS m = (s', fliprl v) 312eigS m = (s', fliprl v)
310 where (s,v) = eigS' (fmat m) 313 where (s,v) = eigS' m
311 s' = fromList . reverse . toList $ s 314 s' = fromList . reverse . toList $ s
312 315
313-- | 'eigS' in ascending order 316-- | 'eigS' in ascending order
314eigS' :: Matrix Double -> (Vector Double, Matrix Double) 317eigS' :: Matrix Double -> (Vector Double, Matrix Double)
315eigS' = eigSHAux (dsyev 1) "eigS'" . fmat 318eigS' = eigSHAux (dsyev 1) "eigS'"
316 319
317-- | Eigenvalues and right eigenvectors of a hermitian complex matrix, using LAPACK's /zheev/. 320-- | Eigenvalues and right eigenvectors of a hermitian complex matrix, using LAPACK's /zheev/.
318-- The eigenvectors are the columns of v. 321-- The eigenvectors are the columns of v.
@@ -320,23 +323,23 @@ eigS' = eigSHAux (dsyev 1) "eigS'" . fmat
320eigH :: Matrix (Complex Double) -> (Vector Double, Matrix (Complex Double)) 323eigH :: Matrix (Complex Double) -> (Vector Double, Matrix (Complex Double))
321eigH m = (s', fliprl v) 324eigH m = (s', fliprl v)
322 where 325 where
323 (s,v) = eigH' (fmat m) 326 (s,v) = eigH' m
324 s' = fromList . reverse . toList $ s 327 s' = fromList . reverse . toList $ s
325 328
326-- | 'eigH' in ascending order 329-- | 'eigH' in ascending order
327eigH' :: Matrix (Complex Double) -> (Vector Double, Matrix (Complex Double)) 330eigH' :: Matrix (Complex Double) -> (Vector Double, Matrix (Complex Double))
328eigH' = eigSHAux (zheev 1) "eigH'" . fmat 331eigH' = eigSHAux (zheev 1) "eigH'"
329 332
330 333
331-- | Eigenvalues of a symmetric real matrix, using LAPACK's /dsyev/ with jobz == \'N\'. 334-- | Eigenvalues of a symmetric real matrix, using LAPACK's /dsyev/ with jobz == \'N\'.
332-- The eigenvalues are sorted in descending order. 335-- The eigenvalues are sorted in descending order.
333eigOnlyS :: Matrix Double -> Vector Double 336eigOnlyS :: Matrix Double -> Vector Double
334eigOnlyS = vrev . fst. eigSHAux (dsyev 0) "eigS'" . fmat 337eigOnlyS = vrev . fst. eigSHAux (dsyev 0) "eigS'"
335 338
336-- | Eigenvalues of a hermitian complex matrix, using LAPACK's /zheev/ with jobz == \'N\'. 339-- | Eigenvalues of a hermitian complex matrix, using LAPACK's /zheev/ with jobz == \'N\'.
337-- The eigenvalues are sorted in descending order. 340-- The eigenvalues are sorted in descending order.
338eigOnlyH :: Matrix (Complex Double) -> Vector Double 341eigOnlyH :: Matrix (Complex Double) -> Vector Double
339eigOnlyH = vrev . fst. eigSHAux (zheev 0) "eigH'" . fmat 342eigOnlyH = vrev . fst. eigSHAux (zheev 0) "eigH'"
340 343
341vrev = flatten . flipud . reshape 1 344vrev = flatten . flipud . reshape 1
342 345