1 /++ 2 Low level ndslice wrapper for LAPACK. 3 4 $(RED Attention: LAPACK and this module has column major API.) 5 ndslice rows correspond to LAPACK columns. 6 7 Functions with `*_wq` suffix are wrappers for workspace queries. 8 9 Authors: Ilya Yaroshenko 10 Copyright: Copyright © 2017, Symmetry Investments & Kaleidic Associates 11 +/ 12 module mir.lapack; 13 14 import mir.ndslice.slice; 15 import mir.ndslice.topology: retro; 16 import mir.ndslice.iterator; 17 import mir.utility: min, max; 18 import mir.internal.utility : realType, isComplex; 19 20 static import lapack; 21 22 public import lapack: lapackint; 23 24 import lapack.lapack: _cfloat, _cdouble; 25 26 @trusted pure nothrow @nogc: 27 28 /// 29 lapackint ilaenv()(lapackint ispec, scope const(char)* name, scope const(char)* opts, lapackint n1, lapackint n2, lapackint n3, lapackint n4) 30 { 31 return ilaenv_(ispec, name, opts, n1, n2, n3, n4); 32 } 33 34 /// 35 lapackint ilaenv2stage()(lapackint ispec, scope const(char)* name, scope const(char)* opts, lapackint n1, lapackint n2, lapackint n3, lapackint n4) 36 { 37 return ilaenv2stage_(ispec, name, opts, n1, n2, n3, n4); 38 } 39 40 /// `getri` work space query. 41 size_t getri_wq(T)(Slice!(T*, 2, Canonical) a) 42 in 43 { 44 assert(a.length!0 == a.length!1, "getri: The input 'a' must be a square matrix."); 45 } 46 do 47 { 48 lapackint n = cast(lapackint) a.length; 49 lapackint lda = cast(lapackint) a._stride.max(1); 50 T work; 51 lapackint lwork = -1; 52 lapackint info; 53 54 lapack.getri_(n, null, lda, null, &work, lwork, info); 55 56 assert(info == 0); 57 return cast(size_t) work.re; 58 } 59 60 unittest 61 { 62 alias s = getri_wq!float; 63 alias d = getri_wq!double; 64 alias c = getri_wq!_cfloat; 65 alias z = getri_wq!_cdouble; 66 } 67 68 /// 69 size_t getri(T)( 70 Slice!(T*, 2, Canonical) a, 71 Slice!(lapackint*) ipiv, 72 Slice!(T*) work, 73 ) 74 in 75 { 76 assert(a.length!0 == a.length!1, "getri: The input 'a' must be a square matrix."); 77 assert(ipiv.length == a.length!0, "getri: The length of 'ipiv' must be equal to the number of rows of 'a'."); 78 assert(work.length, "getri: work must have a non-zero length."); 79 } 80 do 81 { 82 lapackint n = cast(lapackint) a.length; 83 lapackint lda = cast(lapackint) a._stride.max(1); 84 lapackint lwork = cast(lapackint) work.length; 85 lapackint info; 86 87 lapack.getri_(n, a.iterator, lda, ipiv.iterator, work.iterator, lwork, info); 88 89 assert(info >= 0); 90 return info; 91 } 92 93 unittest 94 { 95 alias s = getri!float; 96 alias d = getri!double; 97 alias c = getri!_cfloat; 98 alias z = getri!_cdouble; 99 } 100 101 /// 102 size_t getrf(T)( 103 Slice!(T*, 2, Canonical) a, 104 Slice!(lapackint*) ipiv, 105 ) 106 in 107 { 108 assert(ipiv.length >= min(a.length!0, a.length!1), "getrf: The length of 'ipiv' must be at least the smaller of 'a''s dimensions"); 109 } 110 do 111 { 112 lapackint m = cast(lapackint) a.length!1; 113 lapackint n = cast(lapackint) a.length!0; 114 lapackint lda = cast(lapackint) a._stride.max(1); 115 lapackint info; 116 117 lapack.getrf_(m, n, a.iterator, lda, ipiv.iterator, info); 118 119 assert(info >= 0); 120 return info; 121 } 122 123 unittest 124 { 125 alias s = getrf!float; 126 alias d = getrf!double; 127 alias c = getrf!_cfloat; 128 alias z = getrf!_cdouble; 129 } 130 131 /// 132 template sptrf(T) 133 { 134 /// `sptrf` for upper triangular input. 135 size_t sptrf( 136 Slice!(StairsIterator!(T*, "+")) ap, 137 Slice!(lapackint*) ipiv, 138 ) 139 in 140 { 141 assert(ipiv.length == ap.length, "sptrf: The length of 'ipiv' must be equal to the length 'ap'."); 142 } 143 do 144 { 145 char uplo = 'U'; 146 lapackint n = cast(lapackint) ap.length; 147 lapackint info; 148 149 lapack.sptrf_(uplo, n, &ap[0][0], ipiv.iterator, info); 150 151 assert(info >= 0); 152 return info; 153 } 154 155 /// `sptrf` for lower triangular input. 156 size_t sptrf( 157 Slice!(StairsIterator!(T*, "-")) ap, 158 Slice!(lapackint*) ipiv, 159 ) 160 in 161 { 162 assert(ipiv.length == ap.length, "sptrf: The length of 'ipiv' must be equal to the length 'ap'."); 163 } 164 do 165 { 166 char uplo = 'L'; 167 lapackint n = cast(lapackint) ap.length; 168 lapackint info; 169 170 lapack.sptrf_(uplo, n, &ap[0][0], ipiv.iterator, info); 171 172 assert(info >= 0); 173 return info; 174 } 175 } 176 177 unittest 178 { 179 alias s = sptrf!float; 180 alias d = sptrf!double; 181 } 182 183 /// 184 size_t gesv(T)( 185 Slice!(T*, 2, Canonical) a, 186 Slice!(lapackint*) ipiv, 187 Slice!(T*, 2, Canonical) b, 188 ) 189 in 190 { 191 assert(a.length!0 == a.length!1, "gesv: The input 'a' must be a square matrix."); 192 assert(ipiv.length == a.length!0, "gesv: The length of 'ipiv' must be equal to the number of rows of 'a'."); 193 assert(b.length!1 == a.length!0, "gesv: The number of columns of 'b' must equal the number of rows of 'a'"); 194 } 195 do 196 { 197 lapackint n = cast(lapackint) a.length; 198 lapackint nrhs = cast(lapackint) b.length; 199 lapackint lda = cast(lapackint) a._stride.max(1); 200 lapackint ldb = cast(lapackint) b._stride.max(1); 201 lapackint info; 202 203 lapack.gesv_(n, nrhs, a.iterator, lda, ipiv.iterator, b.iterator, ldb, info); 204 205 assert(info >= 0); 206 return info; 207 } 208 209 unittest 210 { 211 alias s = gesv!float; 212 alias d = gesv!double; 213 } 214 215 /// `gelsd` work space query. 216 size_t gelsd_wq(T)( 217 Slice!(T*, 2, Canonical) a, 218 Slice!(T*, 2, Canonical) b, 219 ref size_t liwork, 220 ) 221 if(!isComplex!T) 222 in 223 { 224 assert(b.length!1 == a.length!1, "gelsd_wq: The number of columns of 'b' must equal the number of columns of 'a'"); 225 } 226 do 227 { 228 lapackint m = cast(lapackint) a.length!1; 229 lapackint n = cast(lapackint) a.length!0; 230 lapackint nrhs = cast(lapackint) b.length; 231 lapackint lda = cast(lapackint) a._stride.max(1); 232 lapackint ldb = cast(lapackint) b._stride.max(1); 233 T rcond; 234 lapackint rank; 235 T work; 236 lapackint lwork = -1; 237 lapackint iwork; 238 lapackint info; 239 240 lapack.gelsd_(m, n, nrhs, a.iterator, lda, b.iterator, ldb, null, rcond, rank, &work, lwork, &iwork, info); 241 242 assert(info == 0); 243 liwork = iwork; 244 return cast(size_t) work.re; 245 } 246 247 248 /// ditto 249 size_t gelsd_wq(T)( 250 Slice!(T*, 2, Canonical) a, 251 Slice!(T*, 2, Canonical) b, 252 ref size_t lrwork, 253 ref size_t liwork, 254 ) 255 if(isComplex!T) 256 in 257 { 258 assert(b.length!1 == a.length!1, "gelsd_wq: The number of columns of 'b' must equal the number of columns of 'a'"); 259 } 260 do 261 { 262 lapackint m = cast(lapackint) a.length!1; 263 lapackint n = cast(lapackint) a.length!0; 264 lapackint nrhs = cast(lapackint) b.length; 265 lapackint lda = cast(lapackint) a._stride.max(1); 266 lapackint ldb = cast(lapackint) b._stride.max(1); 267 realType!T rcond; 268 lapackint rank; 269 T work; 270 lapackint lwork = -1; 271 realType!T rwork; 272 lapackint iwork; 273 lapackint info; 274 275 lapack.gelsd_(m, n, nrhs, a.iterator, lda, b.iterator, ldb, null, rcond, rank, &work, lwork, &rwork, &iwork, info); 276 277 assert(info == 0); 278 lrwork = cast(size_t)rwork; 279 liwork = iwork; 280 return cast(size_t) work.re; 281 } 282 283 unittest 284 { 285 alias s = gelsd_wq!float; 286 alias d = gelsd_wq!double; 287 alias c = gelsd_wq!_cfloat; 288 alias z = gelsd_wq!_cdouble; 289 } 290 291 /// 292 size_t gelsd(T)( 293 Slice!(T*, 2, Canonical) a, 294 Slice!(T*, 2, Canonical) b, 295 Slice!(T*) s, 296 T rcond, 297 ref size_t rank, 298 Slice!(T*) work, 299 Slice!(lapackint*) iwork, 300 ) 301 if(!isComplex!T) 302 in 303 { 304 assert(b.length!1 == a.length!1, "gelsd: The number of columns of 'b' must equal the number of columns of 'a'"); 305 assert(s.length == min(a.length!0, a.length!1), "gelsd: The length of 's' must equal the smaller of the dimensions of 'a'"); 306 } 307 do 308 { 309 lapackint m = cast(lapackint) a.length!1; 310 lapackint n = cast(lapackint) a.length!0; 311 lapackint nrhs = cast(lapackint) b.length; 312 lapackint lda = cast(lapackint) a._stride.max(1); 313 lapackint ldb = cast(lapackint) b._stride.max(1); 314 lapackint rank_; 315 lapackint lwork = cast(lapackint) work.length; 316 lapackint info; 317 318 lapack.gelsd_(m, n, nrhs, a.iterator, lda, b.iterator, ldb, s.iterator, rcond, rank_, work.iterator, lwork, iwork.iterator, info); 319 320 assert(info >= 0); 321 rank = rank_; 322 return info; 323 } 324 325 /// ditto 326 size_t gelsd(T)( 327 Slice!(T*, 2, Canonical) a, 328 Slice!(T*, 2, Canonical) b, 329 Slice!(realType!T*) s, 330 realType!T rcond, 331 ref size_t rank, 332 Slice!(T*) work, 333 Slice!(realType!T*) rwork, 334 Slice!(lapackint*) iwork, 335 ) 336 if(isComplex!T) 337 in 338 { 339 assert(b.length!1 == a.length!1, "gelsd: The number of columns of 'b' must equal the number of columns of 'a'"); 340 assert(s.length == min(a.length!0, a.length!1), "gelsd: The length of 's' must equal the smaller of the dimensions of 'a'"); 341 } 342 do 343 { 344 lapackint m = cast(lapackint) a.length!1; 345 lapackint n = cast(lapackint) a.length!0; 346 lapackint nrhs = cast(lapackint) b.length; 347 lapackint lda = cast(lapackint) a._stride.max(1); 348 lapackint ldb = cast(lapackint) b._stride.max(1); 349 lapackint rank_; 350 lapackint lwork = cast(lapackint) work.length; 351 lapackint info; 352 353 lapack.gelsd_(m, n, nrhs, a.iterator, lda, b.iterator, ldb, s.iterator, rcond, rank_, work.iterator, lwork, rwork.iterator, iwork.iterator, info); 354 355 assert(info >= 0); 356 rank = rank_; 357 return info; 358 } 359 360 unittest 361 { 362 alias s = gelsd!float; 363 alias d = gelsd!double; 364 alias c = gelsd!_cfloat; 365 alias z = gelsd!_cdouble; 366 } 367 368 /// `gesdd` work space query 369 size_t gesdd_wq(T)( 370 char jobz, 371 Slice!(T*, 2, Canonical) a, 372 Slice!(T*, 2, Canonical) u, 373 Slice!(T*, 2, Canonical) vt, 374 ) 375 { 376 lapackint m = cast(lapackint) a.length!1; 377 lapackint n = cast(lapackint) a.length!0; 378 lapackint lda = cast(lapackint) a._stride.max(1); 379 lapackint ldu = cast(lapackint) u._stride.max(1); 380 lapackint ldvt = cast(lapackint) vt._stride.max(1); 381 T work; 382 lapackint lwork = -1; 383 lapackint info; 384 385 static if(!isComplex!T) 386 { 387 lapack.gesdd_(jobz, m, n, null, lda, null, null, ldu, null, ldvt, &work, lwork, null, info); 388 } 389 else 390 { 391 lapack.gesdd_(jobz, m, n, null, lda, null, null, ldu, null, ldvt, &work, lwork, null, null, info); 392 } 393 394 assert(info == 0); 395 return cast(size_t) work.re; 396 } 397 398 unittest 399 { 400 alias s = gesdd_wq!float; 401 alias d = gesdd_wq!double; 402 alias c = gesdd_wq!_cfloat; 403 alias z = gesdd_wq!_cdouble; 404 } 405 406 /// 407 size_t gesdd(T)( 408 char jobz, 409 Slice!(T*, 2, Canonical) a, 410 Slice!(T*) s, 411 Slice!(T*, 2, Canonical) u, 412 Slice!(T*, 2, Canonical) vt, 413 Slice!(T*) work, 414 Slice!(lapackint*) iwork, 415 ) 416 if(!isComplex!T) 417 { 418 lapackint m = cast(lapackint) a.length!1; 419 lapackint n = cast(lapackint) a.length!0; 420 lapackint lda = cast(lapackint) a._stride.max(1); 421 lapackint ldu = cast(lapackint) u._stride.max(1); 422 lapackint ldvt = cast(lapackint) vt._stride.max(1); 423 lapackint lwork = cast(lapackint) work.length; 424 lapackint info; 425 426 lapack.gesdd_(jobz, m, n, a.iterator, lda, s.iterator, u.iterator, ldu, vt.iterator, ldvt, work.iterator, lwork, iwork.iterator, info); 427 428 assert(info >= 0); 429 return info; 430 } 431 432 /// ditto 433 size_t gesdd(T)( 434 char jobz, 435 Slice!(T*, 2, Canonical) a, 436 Slice!(realType!T*) s, 437 Slice!(T*, 2, Canonical) u, 438 Slice!(T*, 2, Canonical) vt, 439 Slice!(T*) work, 440 Slice!(realType!T*) rwork, 441 Slice!(lapackint*) iwork, 442 ) 443 if(isComplex!T) 444 { 445 lapackint m = cast(lapackint) a.length!1; 446 lapackint n = cast(lapackint) a.length!0; 447 lapackint lda = cast(lapackint) a._stride.max(1); 448 lapackint ldu = cast(lapackint) u._stride.max(1); 449 lapackint ldvt = cast(lapackint) vt._stride.max(1); 450 lapackint lwork = cast(lapackint) work.length; 451 lapackint info; 452 453 lapack.gesdd_(jobz, m, n, a.iterator, lda, s.iterator, u.iterator, ldu, vt.iterator, ldvt, work.iterator, lwork, rwork.iterator, iwork.iterator, info); 454 455 assert(info >= 0); 456 return info; 457 } 458 459 unittest 460 { 461 alias s = gesdd!float; 462 alias d = gesdd!double; 463 alias c = gesdd!_cfloat; 464 alias z = gesdd!_cdouble; 465 } 466 467 /// `gesvd` work space query 468 size_t gesvd_wq(T)( 469 char jobu, 470 char jobvt, 471 Slice!(T*, 2, Canonical) a, 472 Slice!(T*, 2, Canonical) u, 473 Slice!(T*, 2, Canonical) vt, 474 ) 475 { 476 lapackint m = cast(lapackint) a.length!1; 477 lapackint n = cast(lapackint) a.length!0; 478 lapackint lda = cast(lapackint) a._stride.max(1); 479 lapackint ldu = cast(lapackint) u._stride.max(1); 480 lapackint ldvt = cast(lapackint) vt._stride.max(1); 481 T work; 482 lapackint lwork = -1; 483 lapackint info; 484 485 static if(!isComplex!T) 486 { 487 lapack.gesvd_(jobu, jobvt, m, n, null, lda, null, null, ldu, null, ldvt, &work, lwork, info); 488 } 489 else 490 { 491 lapack.gesvd_(jobu, jobvt, m, n, null, lda, null, null, ldu, null, ldvt, &work, lwork, null, info); 492 } 493 494 assert(info == 0); 495 return cast(size_t) work.re; 496 } 497 498 unittest 499 { 500 alias s = gesvd_wq!float; 501 alias d = gesvd_wq!double; 502 alias c = gesvd_wq!_cfloat; 503 alias z = gesvd_wq!_cdouble; 504 } 505 506 /// 507 size_t gesvd(T)( 508 char jobu, 509 char jobvt, 510 Slice!(T*, 2, Canonical) a, 511 Slice!(T*) s, 512 Slice!(T*, 2, Canonical) u, 513 Slice!(T*, 2, Canonical) vt, 514 Slice!(T*) work, 515 ) 516 if(!isComplex!T) 517 { 518 lapackint m = cast(lapackint) a.length!1; 519 lapackint n = cast(lapackint) a.length!0; 520 lapackint lda = cast(lapackint) a._stride.max(1); 521 lapackint ldu = cast(lapackint) u._stride.max(1); 522 lapackint ldvt = cast(lapackint) vt._stride.max(1); 523 lapackint lwork = cast(lapackint) work.length; 524 lapackint info; 525 526 lapack.gesvd_(jobu, jobvt, m, n, a.iterator, lda, s.iterator, u.iterator, ldu, vt.iterator, ldvt, work.iterator, lwork, info); 527 528 assert(info >= 0); 529 return info; 530 } 531 532 /// ditto 533 size_t gesvd(T)( 534 char jobu, 535 char jobvt, 536 Slice!(T*, 2, Canonical) a, 537 Slice!(realType!T*) s, 538 Slice!(T*, 2, Canonical) u, 539 Slice!(T*, 2, Canonical) vt, 540 Slice!(T*) work, 541 Slice!(realType!T*) rwork, 542 ) 543 if(isComplex!T) 544 { 545 lapackint m = cast(lapackint) a.length!1; 546 lapackint n = cast(lapackint) a.length!0; 547 lapackint lda = cast(lapackint) a._stride.max(1); 548 lapackint ldu = cast(lapackint) u._stride.max(1); 549 lapackint ldvt = cast(lapackint) vt._stride.max(1); 550 lapackint lwork = cast(lapackint) work.length; 551 lapackint info; 552 553 lapack.gesvd_(jobu, jobvt, m, n, a.iterator, lda, s.iterator, u.iterator, ldu, vt.iterator, ldvt, work.iterator, lwork, rwork.iterator, info); 554 555 assert(info >= 0); 556 return info; 557 } 558 559 unittest 560 { 561 alias s = gesvd!float; 562 alias d = gesvd!double; 563 alias c = gesvd!_cfloat; 564 alias z = gesvd!_cdouble; 565 } 566 567 /// 568 template spev(T) 569 { 570 /// 571 size_t spev( 572 char jobz, 573 Slice!(StairsIterator!(T*, "+")) ap, 574 Slice!(T*) w, 575 Slice!(T*, 2, Canonical) z, 576 Slice!(T*) work, 577 ) 578 in 579 { 580 assert(work.length == 3 * ap.length, "spev: The length of 'work' must equal three times the length of 'ap'."); 581 assert(w.length == ap.length, "spev: The length of 'w' must equal the length of 'ap'."); 582 } 583 do 584 { 585 char uplo = 'U'; 586 lapackint n = cast(lapackint) ap.length; 587 lapackint ldz = cast(lapackint) z._stride.max(1); 588 lapackint info; 589 590 lapack.spev_(jobz, uplo, n, &ap[0][0], w.iterator, z.iterator, ldz, work.iterator, info); 591 592 assert(info >= 0); 593 return info; 594 } 595 596 /// 597 size_t spev( 598 char jobz, 599 Slice!(StairsIterator!(T*, "-")) ap, 600 Slice!(T*) w, 601 Slice!(T*, 2, Canonical) z, 602 Slice!(T*) work, 603 ) 604 in 605 { 606 assert(work.length == 3 * ap.length, "spev: The length of 'work' must equal three times the length of 'ap'."); 607 assert(w.length == ap.length, "spev: The length of 'w' must equal the length of 'ap'."); 608 } 609 do 610 { 611 char uplo = 'L'; 612 lapackint n = cast(lapackint) ap.length; 613 lapackint ldz = cast(lapackint) z._stride.max(1); 614 lapackint info; 615 616 lapack.spev_(jobz, uplo, n, &ap[0][0], w.iterator, z.iterator, ldz, work.iterator, info); 617 618 assert(info >= 0); 619 return info; 620 } 621 } 622 623 unittest 624 { 625 alias s = spev!float; 626 alias d = spev!double; 627 } 628 629 /// 630 size_t sytrf(T)( 631 char uplo, 632 Slice!(T*, 2, Canonical) a, 633 Slice!(lapackint*) ipiv, 634 Slice!(T*) work, 635 ) 636 in 637 { 638 assert(a.length!0 == a.length!1, "sytrf: The input 'a' must be a square matrix."); 639 } 640 do 641 { 642 lapackint info; 643 lapackint n = cast(lapackint) a.length; 644 lapackint lda = cast(lapackint) a._stride.max(1); 645 lapackint lwork = cast(lapackint) work.length; 646 647 lapack.sytrf_(uplo, n, a.iterator, lda, ipiv.iterator, work.iterator, lwork, info); 648 ///if info = 0: successful exit. 649 ///if info > 0: if info = i, D(i, i) is exactly zero. The factorization has been 650 ///completed, but the block diagonal matrix D is exactly singular, and division by 651 ///zero will occur if it is used to solve a system of equations. 652 ///if info < 0: if info == -i, the i-th argument had an illegal value. 653 assert(info >= 0); 654 return info; 655 } 656 657 unittest 658 { 659 alias s = sytrf!float; 660 alias d = sytrf!double; 661 alias c = sytrf!_cfloat; 662 alias z = sytrf!_cdouble; 663 } 664 665 /// 666 size_t geqrf(T)( 667 Slice!(T*, 2, Canonical) a, 668 Slice!(T*) tau, 669 Slice!(T*) work 670 ) 671 in 672 { 673 assert(a.length!0 >= 0, "geqrf: The number of columns of 'a' must be " ~ 674 "greater than or equal to zero."); //n>=0 675 assert(a.length!1 >= a.length!0, "geqrf: The number of columns of 'a' " ~ 676 "must be greater than or equal to the number of its rows."); //m>=n 677 assert(tau.length >= 0, "geqrf: The input 'tau' must have length greater " ~ 678 "than or equal to zero."); //k>=0 679 assert(a.length!0 >= tau.length, "geqrf: The number of columns of 'a' " ~ 680 "must be greater than or equal to the length of 'tau'."); //n>=k 681 assert(work.length >= a.length!0, "geqrf: The length of 'work' must be " ~ 682 "greater than or equal to the number of rows of 'a'."); //lwork>=n 683 } 684 do 685 { 686 lapackint m = cast(lapackint) a.length!1; 687 lapackint n = cast(lapackint) a.length!0; 688 lapackint lda = cast(lapackint) a._stride.max(1); 689 lapackint lwork = cast(lapackint) work.length; 690 lapackint info; 691 692 lapack.geqrf_(m, n, a.iterator, lda, tau.iterator, work.iterator, lwork, info); 693 694 ///if info == 0: successful exit; 695 ///if info < 0: if info == -i, the i-th argument had an illegal value. 696 assert(info >= 0); 697 return info; 698 } 699 700 unittest 701 { 702 alias s = geqrf!float; 703 alias d = geqrf!double; 704 alias c = geqrf!_cfloat; 705 alias z = geqrf!_cdouble; 706 } 707 708 /// 709 size_t getrs(T)( 710 char trans, 711 Slice!(T*, 2, Canonical) a, 712 Slice!(T*, 2, Canonical) b, 713 Slice!(lapackint*) ipiv, 714 ) 715 in 716 { 717 assert(a.length!0 == a.length!1, "getrs: The input 'a' must be a square matrix."); 718 assert(ipiv.length == a.length!0, "getrs: The length of 'ipiv' must be equal to the number of rows of 'a'."); 719 } 720 do 721 { 722 lapackint n = cast(lapackint) a.length; 723 lapackint nrhs = cast(lapackint) b.length; 724 lapackint lda = cast(lapackint) a._stride.max(1); 725 lapackint ldb = cast(lapackint) b._stride.max(1); 726 lapackint info; 727 728 lapack.getrs_(trans, n, nrhs, a.iterator, lda, ipiv.iterator, b.iterator, ldb, info); 729 730 ///if info == 0: successful exit. 731 ///if info < 0: if info == -i, the i-th argument had an illegal value. 732 assert(info >= 0); 733 return info; 734 } 735 736 unittest 737 { 738 alias s = getrs!float; 739 alias d = getrs!double; 740 alias c = getrs!_cfloat; 741 alias z = getrs!_cdouble; 742 } 743 744 /// 745 size_t potrs(T)( 746 char uplo, 747 Slice!(T*, 2, Canonical) a, 748 Slice!(T*, 2, Canonical) b, 749 ) 750 in 751 { 752 assert(a.length!0 == a.length!1, "potrs: The input 'a' must be a square matrix."); 753 } 754 do 755 { 756 lapackint n = cast(lapackint) a.length; 757 lapackint nrhs = cast(lapackint) b.length; 758 lapackint lda = cast(lapackint) a._stride.max(1); 759 lapackint ldb = cast(lapackint) b._stride.max(1); 760 lapackint info; 761 762 lapack.potrs_(uplo, n, nrhs, a.iterator, lda, b.iterator, ldb, info); 763 764 ///if info == 0: successful exit. 765 ///if info < 0: if info == -i, the i-th argument had an illegal value. 766 assert(info >= 0); 767 return info; 768 } 769 770 unittest 771 { 772 alias s = potrs!float; 773 alias d = potrs!double; 774 alias c = potrs!_cfloat; 775 alias z = potrs!_cdouble; 776 } 777 778 /// 779 size_t sytrs2(T)( 780 Slice!(T*, 2, Canonical) a, 781 Slice!(T*, 2, Canonical) b, 782 Slice!(lapackint*) ipiv, 783 Slice!(T*) work, 784 char uplo, 785 ) 786 in 787 { 788 assert(a.length!0 == a.length!1, "sytrs2: The input 'a' must be a square matrix."); 789 } 790 do 791 { 792 lapackint n = cast(lapackint) a.length; 793 lapackint nrhs = cast(lapackint) b.length; 794 lapackint lda = cast(lapackint) a._stride.max(1); 795 lapackint ldb = cast(lapackint) b._stride.max(1); 796 lapackint info; 797 798 lapack.sytrs2_(uplo, n, nrhs, a.iterator, lda, ipiv.iterator, b.iterator, ldb, work.iterator, info); 799 800 ///if info == 0: successful exit. 801 ///if info < 0: if info == -i, the i-th argument had an illegal value. 802 assert(info >= 0); 803 return info; 804 } 805 806 unittest 807 { 808 alias s = sytrs2!float; 809 alias d = sytrs2!double; 810 alias c = sytrs2!_cfloat; 811 alias z = sytrs2!_cdouble; 812 } 813 814 /// 815 size_t geqrs(T)( 816 Slice!(T*, 2, Canonical) a, 817 Slice!(T*, 2, Canonical) b, 818 Slice!(T*) tau, 819 Slice!(T*) work 820 ) 821 in 822 { 823 assert(a.length!0 >= 0, "geqrs: The number of columns of 'a' must be " ~ 824 "greater than or equal to zero."); //n>=0 825 assert(a.length!1 >= a.length!0, "geqrs: The number of columns of 'a' " ~ 826 "must be greater than or equal to the number of its rows."); //m>=n 827 assert(tau.length >= 0, "geqrs: The input 'tau' must have length greater " ~ 828 "than or equal to zero."); //k>=0 829 assert(a.length!0 >= tau.length, "geqrs: The number of columns of 'a' " ~ 830 "must be greater than or equal to the length of 'tau'."); //n>=k 831 assert(work.length >= a.length!0, "geqrs: The length of 'work' must be " ~ 832 "greater than or equal to the number of rows of 'a'."); //lwork>=n 833 } 834 do 835 { 836 lapackint m = cast(lapackint) a.length!1; 837 lapackint n = cast(lapackint) a.length!0; 838 lapackint nrhs = cast(lapackint) b.length; 839 lapackint lda = cast(lapackint) a._stride.max(1); 840 lapackint ldb = cast(lapackint) b._stride.max(1); 841 lapackint lwork = cast(lapackint) work.length; 842 lapackint info; 843 844 lapack.geqrs_(m, n, nrhs, a.iterator, lda, tau.iterator, b.iterator, ldb, work.iterator, lwork, info); 845 846 ///if info == 0: successful exit. 847 ///if info < 0: if info == -i, the i-th argument had an illegal value. 848 assert(info >= 0); 849 return info; 850 } 851 852 version(none) 853 unittest 854 { 855 alias s = geqrs!float; 856 alias d = geqrs!double; 857 alias c = geqrs!_cfloat; 858 alias z = geqrs!_cdouble; 859 } 860 861 /// 862 size_t sysv_rook_wk(T)( 863 char uplo, 864 Slice!(T*, 2, Canonical) a, 865 Slice!(T*, 2, Canonical) b, 866 ) 867 in 868 { 869 assert(a.length!0 == a.length!1, "sysv_rook_wk: The input 'a' must be a square matrix."); 870 assert(b.length!1 == a.length!0, "sysv_rook_wk: The number of columns of 'b' must equal the number of rows of 'a'."); 871 } 872 do 873 { 874 lapackint n = cast(lapackint) a.length; 875 lapackint nrhs = cast(lapackint) b.length; 876 lapackint lda = cast(lapackint) a._stride.max(1); 877 lapackint ldb = cast(lapackint) b._stride.max(1); 878 T work; 879 lapackint lwork = -1; 880 lapackint info; 881 882 lapack.sysv_rook_(uplo, n, nrhs, a._iterator, lda, null, b._iterator, ldb, &work, lwork, info); 883 884 return cast(size_t) work.re; 885 } 886 887 unittest 888 { 889 alias s = sysv_rook_wk!float; 890 alias d = sysv_rook_wk!double; 891 alias c = sysv_rook_wk!_cfloat; 892 alias z = sysv_rook_wk!_cdouble; 893 } 894 895 /// 896 size_t sysv_rook(T)( 897 char uplo, 898 Slice!(T*, 2, Canonical) a, 899 Slice!(lapackint*) ipiv, 900 Slice!(T*, 2, Canonical) b, 901 Slice!(T*) work, 902 ) 903 in 904 { 905 assert(a.length!0 == a.length!1, "sysv_rook: The input 'a' must be a square matrix."); 906 assert(ipiv.length == a.length!0, "sysv_rook: The length of 'ipiv' must be equal to the number of rows of 'a'"); 907 assert(b.length!1 == a.length!0, "sysv_rook: The number of columns of 'b' must equal the number of rows of 'a'."); 908 } 909 do 910 { 911 lapackint n = cast(lapackint) a.length; 912 lapackint nrhs = cast(lapackint) b.length; 913 lapackint lda = cast(lapackint) a._stride.max(1); 914 lapackint ldb = cast(lapackint) b._stride.max(1); 915 lapackint lwork = cast(lapackint) work.length; 916 lapackint info; 917 918 lapack.sysv_rook_(uplo, n, nrhs, a._iterator, lda, ipiv._iterator, b._iterator, ldb, work._iterator, lwork, info); 919 920 assert(info >= 0); 921 return info; 922 } 923 924 unittest 925 { 926 alias s = sysv_rook!float; 927 alias d = sysv_rook!double; 928 alias c = sysv_rook!_cfloat; 929 alias z = sysv_rook!_cdouble; 930 } 931 932 /// 933 size_t syev_wk(T)( 934 char jobz, 935 char uplo, 936 Slice!(T*, 2, Canonical) a, 937 Slice!(T*) w, 938 ) 939 in 940 { 941 assert(a.length!0 == a.length!1, "syev_wk: The input 'a' must be a square matrix."); 942 assert(w.length == a.length!0, "syev_wk: The length of 'w' must equal the number of rows of 'a'."); 943 } 944 do 945 { 946 lapackint n = cast(lapackint) a.length; 947 lapackint lda = cast(lapackint) a._stride.max(1); 948 T work; 949 lapackint lwork = -1; 950 lapackint info; 951 952 lapack.syev_(jobz, uplo, n, a._iterator, lda, w._iterator, &work, lwork, info); 953 954 return cast(size_t) work.re; 955 } 956 957 unittest 958 { 959 alias s = syev_wk!float; 960 alias d = syev_wk!double; 961 } 962 963 /// 964 size_t syev(T)( 965 char jobz, 966 char uplo, 967 Slice!(T*, 2, Canonical) a, 968 Slice!(T*) w, 969 Slice!(T*) work, 970 ) 971 in 972 { 973 assert(a.length!0 == a.length!1, "syev: The input 'a' must be a square matrix."); 974 assert(w.length == a.length!0, "syev: The length of 'w' must equal the number of rows of 'a'."); 975 } 976 do 977 { 978 lapackint n = cast(lapackint) a.length; 979 lapackint lda = cast(lapackint) a._stride.max(1); 980 lapackint lwork = cast(lapackint) work.length; 981 lapackint info; 982 983 lapack.syev_(jobz, uplo, n, a._iterator, lda, w._iterator, work._iterator, lwork, info); 984 985 assert(info >= 0); 986 return info; 987 } 988 989 unittest 990 { 991 alias s = syev!float; 992 alias d = syev!double; 993 } 994 995 /// 996 size_t syev_2stage_wk(T)( 997 char jobz, 998 char uplo, 999 Slice!(T*, 2, Canonical) a, 1000 Slice!(T*) w, 1001 ) 1002 in 1003 { 1004 assert(a.length!0 == a.length!1, "syev_2stage_wk: The input 'a' must be a square matrix."); 1005 assert(w.length == a.length, "syev_2stage_wk: The length of 'w' must equal the number of rows of 'a'."); 1006 } 1007 do 1008 { 1009 lapackint n = cast(lapackint) a.length; 1010 lapackint lda = cast(lapackint) a._stride.max(1); 1011 T work; 1012 lapackint lwork = -1; 1013 lapackint info; 1014 1015 lapack.syev_2stage_(jobz, uplo, n, a._iterator, lda, w._iterator, &work, lwork, info); 1016 1017 return cast(size_t) work.re; 1018 } 1019 1020 version(none) 1021 unittest 1022 { 1023 alias s = syev_2stage_wk!float; 1024 alias d = syev_2stage_wk!double; 1025 } 1026 1027 /// 1028 size_t syev_2stage(T)( 1029 char jobz, 1030 char uplo, 1031 Slice!(T*, 2, Canonical) a, 1032 Slice!(T*) w, 1033 Slice!(T*) work, 1034 ) 1035 in 1036 { 1037 assert(a.length!0 == a.length!1, "syev_2stage: The input 'a' must be a square matrix."); 1038 assert(w.length == a.length, "syev_2stage: The length of 'w' must equal the number of rows of 'a'."); 1039 } 1040 do 1041 { 1042 lapackint n = cast(lapackint) a.length; 1043 lapackint lda = cast(lapackint) a._stride.max(1); 1044 lapackint lwork = cast(lapackint) work.length; 1045 lapackint info; 1046 1047 lapack.syev_2stage_(jobz, uplo, n, a._iterator, lda, w._iterator, work._iterator, lwork, info); 1048 1049 assert(info >= 0); 1050 return info; 1051 } 1052 1053 version(none) 1054 unittest 1055 { 1056 alias s = syev_2stage!float; 1057 alias d = syev_2stage!double; 1058 } 1059 1060 /// 1061 size_t potrf(T)( 1062 char uplo, 1063 Slice!(T*, 2, Canonical) a, 1064 ) 1065 in 1066 { 1067 assert(a.length!0 == a.length!1, "potrf: The input 'a' must be a square matrix."); 1068 } 1069 do 1070 { 1071 lapackint n = cast(lapackint) a.length; 1072 lapackint lda = cast(lapackint) a._stride.max(1); 1073 lapackint info; 1074 1075 lapack.potrf_(uplo, n, a.iterator, lda, info); 1076 1077 assert(info >= 0); 1078 1079 return info; 1080 } 1081 1082 unittest 1083 { 1084 alias s = potrf!float; 1085 alias d = potrf!double; 1086 alias c = potrf!_cfloat; 1087 alias z = potrf!_cdouble; 1088 } 1089 1090 /// 1091 size_t pptrf(T)( 1092 char uplo, 1093 Slice!(T*, 2, Canonical) ap, 1094 ) 1095 { 1096 lapackint n = cast(lapackint) ap.length; 1097 lapackint info; 1098 1099 lapack.pptrf_(uplo, n, ap.iterator, info); 1100 1101 assert(info >= 0); 1102 1103 return info; 1104 } 1105 1106 unittest 1107 { 1108 alias s = pptrf!float; 1109 alias d = pptrf!double; 1110 alias c = pptrf!_cfloat; 1111 alias z = pptrf!_cdouble; 1112 } 1113 1114 /// 1115 template sptri(T) 1116 { 1117 /// `sptri` for upper triangular input. 1118 size_t sptri( 1119 Slice!(StairsIterator!(T*, "+")) ap, 1120 Slice!(lapackint*) ipiv, 1121 Slice!(T*) work 1122 ) 1123 in 1124 { 1125 assert(ipiv.length == ap.length, "sptri: The length of 'ipiv' must be equal to the length of 'ap'."); 1126 assert(work.length == ap.length, "sptri: The length of 'work' must be equal to the length of 'ap'."); 1127 } 1128 do 1129 { 1130 lapackint n = cast(lapackint) ap.length; 1131 lapackint info; 1132 1133 char uplo = 'U'; 1134 lapack.sptri_(uplo, n, &ap[0][0], ipiv.iterator, work.iterator, info); 1135 1136 assert(info >= 0); 1137 return info; 1138 } 1139 1140 /// `sptri` for lower triangular input. 1141 size_t sptri( 1142 Slice!(StairsIterator!(T*, "-")) ap, 1143 Slice!(lapackint*) ipiv, 1144 Slice!(T*) work 1145 ) 1146 in 1147 { 1148 assert(ipiv.length == ap.length, "sptri: The length of 'ipiv' must be equal to the length of 'ap'."); 1149 assert(work.length == ap.length, "sptri: The length of 'work' must be equal to the length of 'ap'."); 1150 } 1151 do 1152 { 1153 lapackint n = cast(lapackint) ap.length; 1154 lapackint info; 1155 1156 char uplo = 'L'; 1157 lapack.sptri_(uplo, n, &ap[0][0], ipiv.iterator, work.iterator, info); 1158 1159 assert(info >= 0); 1160 return info; 1161 } 1162 } 1163 1164 unittest 1165 { 1166 alias s = sptri!float; 1167 alias d = sptri!double; 1168 alias c = sptri!_cfloat; 1169 alias z = sptri!_cdouble; 1170 } 1171 1172 /// 1173 size_t potri(T)( 1174 char uplo, 1175 Slice!(T*, 2, Canonical) a, 1176 ) 1177 in 1178 { 1179 assert(a.length!0 == a.length!1, "potri: The input 'a' must be a square matrix."); 1180 } 1181 do 1182 { 1183 lapackint n = cast(lapackint) a.length; 1184 lapackint lda = cast(lapackint) a._stride.max(1); 1185 lapackint info; 1186 1187 lapack.potri_(uplo, n, a.iterator, lda, info); 1188 1189 assert(info >= 0); 1190 return info; 1191 } 1192 1193 unittest 1194 { 1195 alias s = potri!float; 1196 alias d = potri!double; 1197 alias c = potri!_cfloat; 1198 alias z = potri!_cdouble; 1199 } 1200 1201 /// 1202 template pptri(T) 1203 { 1204 /// `pptri` for upper triangular input. 1205 size_t pptri( 1206 Slice!(StairsIterator!(T*, "+")) ap 1207 ) 1208 { 1209 lapackint n = cast(lapackint) ap.length; 1210 lapackint info; 1211 1212 char uplo = 'U'; 1213 lapack.pptri_(uplo, n, &ap[0][0], info); 1214 1215 assert(info >= 0); 1216 return info; 1217 } 1218 1219 /// `pptri` for lower triangular input. 1220 size_t pptri( 1221 Slice!(StairsIterator!(T*, "-")) ap 1222 ) 1223 { 1224 lapackint n = cast(lapackint) ap.length; 1225 lapackint info; 1226 1227 char uplo = 'L'; 1228 lapack.pptri_(uplo, n, &ap[0][0], info); 1229 1230 assert(info >= 0); 1231 return info; 1232 } 1233 } 1234 1235 unittest 1236 { 1237 alias s = pptri!float; 1238 alias d = pptri!double; 1239 alias c = pptri!_cfloat; 1240 alias z = pptri!_cdouble; 1241 } 1242 1243 /// 1244 size_t trtri(T)( 1245 char uplo, 1246 char diag, 1247 Slice!(T*, 2, Canonical) a, 1248 ) 1249 in 1250 { 1251 assert(a.length!0 == a.length!1, "trtri: The input 'a' must be a square matrix."); 1252 } 1253 do 1254 { 1255 lapackint n = cast(lapackint) a.length; 1256 lapackint lda = cast(lapackint) a._stride.max(1); 1257 lapackint info; 1258 1259 lapack.trtri_(uplo, diag, n, a.iterator, lda, info); 1260 1261 assert(info >= 0); 1262 return info; 1263 } 1264 1265 unittest 1266 { 1267 alias s = trtri!float; 1268 alias d = trtri!double; 1269 alias c = trtri!_cfloat; 1270 alias z = trtri!_cdouble; 1271 } 1272 1273 /// 1274 size_t gtsv(T)( 1275 Slice!(T*) dl, 1276 Slice!(T*) d, 1277 Slice!(T*) du, 1278 Slice!(T*, 2, Canonical) b, 1279 ) 1280 in (d.length == 0 && dl.length == 0 || dl.length + 1 == d.length, "gtsv: 'dl' has to have length equal to N - 1, where N is length of 'd'.") 1281 in (du.length == dl.length, "gtsv: 'du' has to have length equal to N - 1, where N is length of 'd'.") 1282 in (d.length!0 == b.length!1, "gtsv: The input 'b' has to be N-by-NRHS matrix where N is length of 'd'.") 1283 out (info; info >= 0) 1284 { 1285 1286 lapackint n = cast(lapackint) b.length!1; 1287 lapackint nrhs = cast(lapackint) b.length; 1288 lapackint ldb = cast(lapackint) b._stride.max(1); 1289 lapackint info; 1290 1291 lapack.gtsv_(n, nrhs, dl.iterator, d.iterator, du.iterator, b.iterator, ldb, info); 1292 return info; 1293 } 1294 1295 unittest 1296 { 1297 alias s = gtsv!float; 1298 alias d = gtsv!double; 1299 alias c = gtsv!_cfloat; 1300 alias z = gtsv!_cdouble; 1301 } 1302 1303 /// 1304 size_t trtrs(T)( 1305 char uplo, 1306 char diag, 1307 char trans, 1308 Slice!(const(T)*, 2, Canonical) a, 1309 Slice!(T*, 2, Canonical) b, 1310 ) 1311 in (a.length!0 == a.length!1, "trtrs: The input 'a' must be a square matrix.") 1312 in (a.length!0 == b.length!1, "trtrs: The input 'b' has to be N-by-NRHS matrix where N is order of 'a'.") 1313 out (info; info >= 0) 1314 { 1315 lapackint n = cast(lapackint) a.length; 1316 lapackint nrhs = cast(lapackint) b.length; 1317 lapackint lda = cast(lapackint) a._stride.max(1); 1318 lapackint ldb = cast(lapackint) b._stride.max(1); 1319 lapackint info; 1320 1321 lapack.trtrs_(uplo, diag, trans, n, nrhs, a.iterator, lda, b.iterator, ldb, info); 1322 return info; 1323 } 1324 1325 unittest 1326 { 1327 alias s = trtrs!float; 1328 alias d = trtrs!double; 1329 alias c = trtrs!_cfloat; 1330 alias z = trtrs!_cdouble; 1331 } 1332 1333 /// 1334 template tptri(T) 1335 { 1336 /// `tptri` for upper triangular input. 1337 size_t tptri( 1338 char diag, 1339 Slice!(StairsIterator!(T*, "+")) ap, 1340 ) 1341 { 1342 lapackint n = cast(lapackint) ap.length; 1343 lapackint info; 1344 1345 char uplo = 'U'; 1346 lapack.tptri_(uplo, diag, n, &ap[0][0], info); 1347 1348 assert(info >= 0); 1349 return info; 1350 } 1351 1352 /// `tptri` for lower triangular input. 1353 size_t tptri( 1354 char diag, 1355 Slice!(StairsIterator!(T*, "-")) ap, 1356 ) 1357 { 1358 lapackint n = cast(lapackint) ap.length; 1359 lapackint info; 1360 1361 char uplo = 'L'; 1362 lapack.tptri_(uplo, diag, n, &ap[0][0], info); 1363 1364 assert(info >= 0); 1365 return info; 1366 1367 } 1368 } 1369 1370 unittest 1371 { 1372 alias s = tptri!float; 1373 alias d = tptri!double; 1374 alias c = tptri!_cfloat; 1375 alias z = tptri!_cdouble; 1376 } 1377 1378 /// 1379 size_t ormqr(T)( 1380 char side, 1381 char trans, 1382 Slice!(T*, 2, Canonical) a, 1383 Slice!(T*) tau, 1384 Slice!(T*, 2, Canonical) c, 1385 Slice!(T*) work, 1386 ) 1387 { 1388 lapackint m = cast(lapackint) c.length!1; 1389 lapackint n = cast(lapackint) c.length!0; 1390 lapackint k = cast(lapackint) tau.length; 1391 lapackint lda = cast(lapackint) a._stride.max(1); 1392 lapackint ldc = cast(lapackint) c._stride.max(1); 1393 lapackint lwork = cast(lapackint) work.length; 1394 lapackint info; 1395 1396 lapack.ormqr_(side, trans, m, n, k, a.iterator, lda, tau.iterator, c.iterator, ldc, work.iterator, lwork, info); 1397 1398 ///if info == 0: successful exit. 1399 ///if info < 0: if info == -i, the i-th argument had an illegal value. 1400 assert(info >= 0); 1401 return info; 1402 } 1403 1404 unittest 1405 { 1406 alias s = ormqr!float; 1407 alias d = ormqr!double; 1408 } 1409 1410 /// 1411 size_t unmqr(T)( 1412 char side, 1413 char trans, 1414 Slice!(T*, 2, Canonical) a, 1415 Slice!(T*) tau, 1416 Slice!(T*, 2, Canonical) c, 1417 Slice!(T*) work, 1418 ) 1419 { 1420 lapackint m = cast(lapackint) c.length!1; 1421 lapackint n = cast(lapackint) c.length!0; 1422 lapackint k = cast(lapackint) tau.length; 1423 lapackint lda = cast(lapackint) a._stride.max(1); 1424 lapackint ldc = cast(lapackint) c._stride.max(1); 1425 lapackint lwork = cast(lapackint) work.length; 1426 lapackint info; 1427 1428 lapack.unmqr_(side, trans, m, n, k, a.iterator, lda, tau.iterator, c.iterator, ldc, work.iterator, lwork, info); 1429 1430 ///if info == 0: successful exit. 1431 ///if info < 0: if info == -i, the i-th argument had an illegal value. 1432 assert(info >= 0); 1433 return info; 1434 } 1435 1436 unittest 1437 { 1438 alias s = unmqr!_cfloat; 1439 alias d = unmqr!_cdouble; 1440 } 1441 1442 /// 1443 size_t orgqr(T)( 1444 Slice!(T*, 2, Canonical) a, 1445 Slice!(T*) tau, 1446 Slice!(T*) work, 1447 ) 1448 in 1449 { 1450 assert(a.length!0 >= 0, "orgqr: The number of columns of 'a' must be " ~ 1451 "greater than or equal to zero."); //n>=0 1452 assert(a.length!1 >= a.length!0, "orgqr: The number of columns of 'a' " ~ 1453 "must be greater than or equal to the number of its rows."); //m>=n 1454 assert(tau.length >= 0, "orgqr: The input 'tau' must have length greater " ~ 1455 "than or equal to zero."); //k>=0 1456 assert(a.length!0 >= tau.length, "orgqr: The number of columns of 'a' " ~ 1457 "must be greater than or equal to the length of 'tau'."); //n>=k 1458 assert(work.length >= a.length!0, "orgqr: The length of 'work' must be " ~ 1459 "greater than or equal to the number of rows of 'a'."); //lwork>=n 1460 } 1461 do 1462 { 1463 lapackint m = cast(lapackint) a.length!1; 1464 lapackint n = cast(lapackint) a.length!0; 1465 lapackint k = cast(lapackint) tau.length; 1466 lapackint lda = cast(lapackint) a._stride.max(1); 1467 lapackint lwork = cast(lapackint) work.length; 1468 lapackint info; 1469 1470 lapack.orgqr_(m, n, k, a.iterator, lda, tau.iterator, work.iterator, lwork, info); 1471 1472 ///if info == 0: successful exit. 1473 ///if info < 0: if info == -i, the i-th argument had an illegal value. 1474 assert(info >= 0); 1475 return info; 1476 } 1477 1478 unittest 1479 { 1480 alias s = orgqr!float; 1481 alias d = orgqr!double; 1482 } 1483 1484 /// 1485 size_t ungqr(T)( 1486 Slice!(T*, 2, Canonical) a, 1487 Slice!(T*) tau, 1488 Slice!(T*) work, 1489 ) 1490 in 1491 { 1492 assert(a.length!1 >= a.length!0, "ungqr: The number of columns of 'a' must be greater than or equal to the number of its rows."); //m>=n 1493 assert(a.length!0 >= tau.length, "ungqr: The number of columns of 'a' must be greater than or equal to the length of 'tau'."); //n>=k 1494 assert(work.length >= a.length!0, "ungqr: The length of 'work' must be greater than or equal to the number of rows of 'a'."); //lwork>=n 1495 } 1496 do 1497 { 1498 lapackint m = cast(lapackint) a.length!1; 1499 lapackint n = cast(lapackint) a.length!0; 1500 lapackint k = cast(lapackint) tau.length; 1501 lapackint lda = cast(lapackint) a._stride.max(1); 1502 lapackint lwork = cast(lapackint) work.length; 1503 lapackint info; 1504 1505 lapack.ungqr_(m, n, k, a.iterator, lda, tau.iterator, work.iterator, lwork, info); 1506 1507 ///if info == 0: successful exit. 1508 ///if info < 0: if info == -i, the i-th argument had an illegal value. 1509 assert(info >= 0); 1510 return info; 1511 } 1512 1513 unittest 1514 { 1515 alias s = ungqr!_cfloat; 1516 alias d = ungqr!_cdouble; 1517 } 1518 1519 alias orghr = unghr; // this is the name for the real type vairant of ungqr 1520 1521 /// 1522 size_t unghr(T)( 1523 Slice!(T*, 2, Canonical) a, 1524 Slice!(T*) tau, 1525 Slice!(T*) work, 1526 ) 1527 in 1528 { 1529 assert(a.length!1 >= a.length!0); //m>=n 1530 assert(a.length!0 >= tau.length); //n>=k 1531 assert(work.length >= a.length!0); //lwork>=n 1532 } 1533 do 1534 { 1535 lapackint m = cast(lapackint) a.length!1; 1536 lapackint n = cast(lapackint) a.length!0; 1537 lapackint k = cast(lapackint) tau.length; 1538 lapackint lda = cast(lapackint) a._stride.max(1); 1539 lapackint lwork = cast(lapackint) work.length; 1540 lapackint info; 1541 static if (isComplex!T){ 1542 lapack.ungqr_(m, n, k, a.iterator, lda, tau.iterator, work.iterator, lwork, info); 1543 } 1544 else { 1545 lapack.orgqr_(m, n, k, a.iterator, lda, tau.iterator, work.iterator, lwork, info); 1546 } 1547 1548 ///if info == 0: successful exit. 1549 ///if info < 0: if info == -i, the i-th argument had an illegal value. 1550 assert(info >= 0); 1551 return cast(size_t)info; 1552 } 1553 1554 unittest 1555 { 1556 alias orghrf = orghr!float; 1557 alias orghrd = orghr!double; 1558 alias unghrf = unghr!float; 1559 alias unghrd = unghr!double; 1560 alias unghrcf = unghr!_cfloat; 1561 alias unghrcd = unghr!_cdouble; 1562 } 1563 1564 /// 1565 size_t gehrd(T)( 1566 Slice!(T*, 2, Canonical) a, 1567 Slice!(T*) tau, 1568 Slice!(T*) work, 1569 lapackint ilo, 1570 lapackint ihi 1571 ) 1572 in 1573 { 1574 assert(a.length!1 >= a.length!0, "gehrd: The number of columns of 'a' must be greater than or equal to the number of its rows."); //m>=n 1575 assert(a.length!0 >= tau.length, "gehrd: The number of columns of 'a' must be greater than or equal to the length of 'tau'."); //n>=k 1576 assert(work.length >= a.length!0, "gehrd: The length of 'work' must be greater than or equal to the number of rows of 'a'."); //lwork>=n 1577 } 1578 do 1579 { 1580 lapackint n = cast(lapackint) a.length!0; 1581 lapackint lda = cast(lapackint) a._stride.max(1); 1582 lapackint lwork = cast(lapackint) work.length; 1583 lapackint info; 1584 lapack.gehrd_(n, ilo, ihi, a.iterator, lda, tau.iterator, work.iterator, lwork, info); 1585 ///if info == 0: successful exit. 1586 ///if info < 0: if info == -i, the i-th argument had an illegal value. 1587 assert(info >= 0); 1588 return cast(size_t)info; 1589 } 1590 1591 unittest 1592 { 1593 alias s = gehrd!_cfloat; 1594 alias d = gehrd!_cdouble; 1595 } 1596 1597 size_t hsein(T)( 1598 char side, 1599 char eigsrc, 1600 char initv, 1601 ref lapackint select, //actually a logical bitset stored in here 1602 Slice!(T*, 2, Canonical) h, 1603 Slice!(T*) wr, 1604 Slice!(T*) wi, 1605 Slice!(T*, 2, Canonical) vl, 1606 Slice!(T*, 2, Canonical) vr, 1607 ref lapackint m, 1608 Slice!(T*) work, 1609 ref lapackint ifaill, 1610 ref lapackint ifailr, 1611 ) 1612 if (!isComplex!T) 1613 in 1614 { 1615 assert(h.length!1 >= h.length!0, "hsein: The number of columns of 'h' " ~ 1616 "must be greater than or equal to the number of its rows."); //m>=n 1617 assert(wr.length >= 1, "hsein: The input 'wr' must have length greater " ~ 1618 "than or equal to one."); 1619 assert(wr.length >= h.length!0, "hsein: The input 'wr' must have length greater " ~ 1620 "than or equal to the number of rows of 'h'."); 1621 assert(wr.length >= 1.0, "hsein: The input 'wr' must have length greater " ~ 1622 "than or equal to 1."); 1623 assert(wi.length >= 1, "hsein: The input 'wi' must have length greater " ~ 1624 "than or equal to one."); 1625 assert(wi.length >= h.length!0, "hsein: The input 'wi' must have length greater " ~ 1626 "than or equal to the number of rows of 'h'."); 1627 assert(wi.length >= 1.0, "hsein: The input 'wi' must have length greater " ~ 1628 "than or equal to 1."); 1629 assert(work.length >= h.length!0 * (h.length!0 + 2), "hsein: The length of 'work' must be " ~ 1630 "greater than or equal to the square of the number of rows of 'h' plus two additional rows for real types."); 1631 assert(side == 'R' || side == 'L' || side == 'B', "hsein: The char, 'side' must be " ~ 1632 "one of 'R', 'L' or 'B'."); 1633 assert(eigsrc == 'Q' || eigsrc == 'N', "hsein: The char, 'eigsrc', must be " ~ 1634 "one of 'Q' or 'R'."); 1635 assert(initv == 'N' || initv == 'U', "hsein: The char, 'initv', must be " ~ 1636 "one of 'N' or 'U'."); 1637 assert(side != 'L' || side != 'B' || vl.length!1 >= 1, "hsein: Slice 'vl' must be" ~ 1638 "at least the size of '1' when 'side' is set to 'L' or 'B'."); 1639 assert(side != 'R' || vl.length!1 >= 1, "hsein: Slice 'vl' must be" ~ 1640 "length greater than 1 when 'side' is 'R'."); 1641 assert(side != 'R' || side != 'B' || vr.length!1 >= 1, "hsein: Slice 'vr' must be" ~ 1642 "at least the size of '1' when 'side' is set to 'R' or 'B'."); 1643 assert(side != 'L' || vl.length!1 >= 1, "hsein: Slice 'vr' must be" ~ 1644 "length greater than 1 when 'side' is 'L'."); 1645 } 1646 do 1647 { 1648 lapackint info; 1649 lapackint mm = cast(lapackint) vl.length!1; 1650 lapackint n = cast(lapackint) h.length!0; 1651 lapackint ldh = cast(lapackint) h._stride.max(1); 1652 lapackint ldvl = cast(lapackint) vl._stride.max(1); 1653 lapackint ldvr = cast(lapackint) vr._stride.max(1); 1654 //need to seperate these methods then probably provide a wrap which does this as that's the easiest way without bloating the base methods 1655 lapack.hsein_(side, eigsrc, initv, select, n, h.iterator, ldh, wr.iterator, wi.iterator, vl.iterator, ldvl, vr.iterator, ldvr, mm, m, work.iterator, ifaill, ifailr, info); 1656 assert(info >= 0); 1657 ///if any of ifaill or ifailr entries are non-zero then that has failed to converge. 1658 ///ifail?[i] = j > 0 if the eigenvector stored in the i-th column of v?, coresponding to the jth eigenvalue, fails to converge. 1659 assert(ifaill == 0); 1660 assert(ifailr == 0); 1661 return info; 1662 } 1663 1664 size_t hsein(T, realT)( 1665 char side, 1666 char eigsrc, 1667 char initv, 1668 lapackint select, //actually a logical bitset stored in here 1669 Slice!(T*, 2, Canonical) h, 1670 Slice!(T*) w, 1671 Slice!(T*, 2, Canonical) vl, 1672 Slice!(T*, 2, Canonical) vr, 1673 lapackint* m, 1674 Slice!(T*) work, 1675 Slice!(realT*) rwork, 1676 lapackint ifaill, 1677 lapackint ifailr, 1678 ) 1679 if (isComplex!T && is(realType!T == realT)) 1680 in 1681 { 1682 assert(h.length!1 >= h.length!0, "hsein: The number of columns of 'h' " ~ 1683 "must be greater than or equal to the number of its rows."); //m>=n 1684 assert(w.length >= 1, "hsein: The input 'w' must have length greater " ~ 1685 "than or equal to one."); 1686 assert(w.length >= h.length!0, "hsein: The input 'w' must have length greater " ~ 1687 "than or equal to the number of rows of 'h'."); 1688 assert(w.length >= 1.0, "hsein: The input 'w' must have length greater " ~ 1689 "than or equal to 1."); 1690 assert(work.length >= h.length!0 * h.length!0, "hsein: The length of 'work' must be " ~ 1691 "greater than or equal to the square of the number of rows of 'h' for complex types."); 1692 assert(side == 'R' || side == 'L' || side == 'B', "hsein: The char, 'side' must be " ~ 1693 "one of 'R', 'L' or 'B'."); 1694 assert(eigsrc == 'Q' || eigsrc == 'N', "hsein: The char, 'eigsrc', must be " ~ 1695 "one of 'Q' or 'R'."); 1696 assert(initv == 'N' || initv == 'U', "hsein: The char, 'initv', must be " ~ 1697 "one of 'N' or 'U'."); 1698 assert(side != 'L' || side != 'B' || vl.length!1 >= 1, "hsein: Slice 'vl' must be" ~ 1699 "at least the size of '1' when 'side' is set to 'L' or 'B'."); 1700 assert(side != 'R' || vl.length!1 >= 1, "hsein: Slice 'vl' must be" ~ 1701 "length greater than 1 when 'side' is 'R'."); 1702 assert(side != 'R' || side != 'B' || vr.length!1 >= 1, "hsein: Slice 'vr' must be" ~ 1703 "at least the size of '1' when 'side' is set to 'R' or 'B'."); 1704 assert(side != 'L' || vl.length!1 >= 1, "hsein: Slice 'vr' must be" ~ 1705 "length greater than 1 when 'side' is 'L'."); 1706 } 1707 do { 1708 lapackint n = cast(lapackint) h.length!0; 1709 lapackint ldh = cast(lapackint) h._stride.max(1); 1710 lapackint ldvl = cast(lapackint) vl._stride.max(1); 1711 lapackint ldvr = cast(lapackint) vr._stride.max(1); 1712 lapackint mm = cast(lapackint) vl.length!1; 1713 lapackint info; 1714 //could compute mm and m from vl and/or vr and T 1715 lapack.hsein_(side, eigsrc, initv, select, n, h.iterator, ldh, w.iterator, vl.iterator, ldvl, vr.iterator, ldvr, mm, *m, work.iterator, rwork.iterator, ifaill, ifailr, info); 1716 assert(info >= 0); 1717 ///if any of ifaill or ifailr entries are non-zero then that has failed to converge. 1718 ///ifail?[i] = j > 0 if the eigenvector stored in the i-th column of v?, coresponding to the jth eigenvalue, fails to converge. 1719 assert(ifaill == 0); 1720 assert(ifailr == 0); 1721 return info; 1722 } 1723 1724 1725 unittest 1726 { 1727 alias f = hsein!(float); 1728 alias d = hsein!(double); 1729 alias s = hsein!(_cfloat, float); 1730 alias c = hsein!(_cdouble, double); 1731 } 1732 1733 alias ormhr = unmhr; 1734 1735 /// 1736 size_t unmhr(T)( 1737 char side, 1738 char trans, 1739 Slice!(T*, 2, Canonical) a, 1740 Slice!(T*) tau, 1741 Slice!(T*, 2, Canonical) c, 1742 Slice!(T*) work, 1743 lapackint ilo, 1744 lapackint ihi 1745 ) 1746 in 1747 { 1748 assert(a.length!0 >= 0, "ormhr: The number of columns of 'a' must be " ~ 1749 "greater than or equal to zero."); //n>=0 1750 assert(a.length!1 >= a.length!0, "ormhr: The number of columns of 'a' " ~ 1751 "must be greater than or equal to the number of its rows."); //m>=n 1752 assert(c.length!0 >= 0, "ormhr: The number of columns of 'c' must be " ~ 1753 "greater than or equal to zero."); //n>=0 1754 assert(c.length!1 >= c.length!0, "ormhr: The number of columns of 'c' " ~ 1755 "must be greater than or equal to the number of its rows."); //m>=n 1756 assert(tau.length >= 0, "ormhr: The input 'tau' must have length greater " ~ 1757 "than or equal to zero."); //k>=0 1758 assert(a.length!0 >= tau.length, "ormhr: The number of columns of 'a' " ~ 1759 "must be greater than or equal to the length of 'tau'."); //n>=k 1760 assert(work.length >= a.length!0, "ormhr: The length of 'work' must be " ~ 1761 "greater than or equal to the number of rows of 'a'."); //lwork>=n 1762 assert(side == 'L' || side == 'R', "ormhr: 'side' must be" ~ 1763 "one of 'L' or 'R'."); 1764 assert(trans == 'N' || trans == 'T', "ormhr: 'trans' must be" ~ 1765 "one of 'N' or 'T'."); 1766 } 1767 do 1768 { 1769 lapackint m = cast(lapackint) a.length!0; 1770 lapackint n = cast(lapackint) a.length!1; 1771 lapackint lda = cast(lapackint) a._stride.max(1); 1772 lapackint ldc = cast(lapackint) c._stride.max(1); 1773 lapackint lwork = cast(lapackint) work.length; 1774 lapackint info; 1775 static if (!isComplex!T){ 1776 lapack.ormhr_(side, trans, m, n, ilo, ihi, a.iterator, lda, tau.iterator, c.iterator, ldc, work.iterator, lwork, info); 1777 } 1778 else { 1779 lapack.unmhr_(side, trans, m, n, ilo, ihi, a.iterator, lda, tau.iterator, c.iterator, ldc, work.iterator, lwork, info); 1780 } 1781 ///if info == 0: successful exit. 1782 ///if info < 0: if info == -i, the i-th argument had an illegal value. 1783 assert(info >= 0); 1784 return cast(size_t)info; 1785 } 1786 1787 unittest 1788 { 1789 alias s = unmhr!_cfloat; 1790 alias d = unmhr!_cdouble; 1791 alias a = ormhr!double; 1792 alias b = ormhr!float; 1793 } 1794 1795 /// 1796 size_t hseqr(T)( 1797 char job, 1798 char compz, 1799 Slice!(T*, 2, Canonical) h, 1800 Slice!(T*) w, 1801 Slice!(T*, 2, Canonical) z, 1802 Slice!(T*) work, 1803 lapackint ilo, 1804 lapackint ihi 1805 ) 1806 if (isComplex!T) 1807 in 1808 { 1809 assert(job == 'E' || job == 'S', "hseqr"); 1810 assert(compz == 'N' || compz == 'I' || compz == 'V', "hseqr"); 1811 assert(h.length!1 >= h.length!0, "hseqr"); 1812 assert(h.length!1 >= 1, "hseqr"); 1813 assert(compz != 'V' || compz != 'I' || (z.length!1 >= h.length!0 && z.length!1 >= 1), "hseqr"); 1814 assert(compz != 'N' || z.length!1 >= 1); 1815 assert(work.length!0 >= 1, "hseqr"); 1816 assert(work.length!0 >= h.length!0, "hseqr"); 1817 } 1818 do 1819 { 1820 lapackint n = cast(lapackint) h.length!0; 1821 lapackint ldh = cast(lapackint) h._stride.max(1); 1822 lapackint ldz = cast(lapackint) z._stride.max(1); 1823 lapackint lwork = cast(lapackint) work.length!0; 1824 lapackint info; 1825 lapack.hseqr_(job,compz,n,ilo,ihi,h.iterator, ldh, w.iterator, z.iterator, ldz, work.iterator, lwork, info); 1826 assert(info >= 0); 1827 return cast(size_t)info; 1828 } 1829 1830 /// 1831 size_t hseqr(T)( 1832 char job, 1833 char compz, 1834 Slice!(T*, 2, Canonical) h, 1835 Slice!(T*) wr, 1836 Slice!(T*) wi, 1837 Slice!(T*, 2, Canonical) z, 1838 Slice!(T*) work, 1839 lapackint ilo, 1840 lapackint ihi 1841 ) 1842 if (!isComplex!T) 1843 in 1844 { 1845 assert(job == 'E' || job == 'S', "hseqr"); 1846 assert(compz == 'N' || compz == 'I' || compz == 'V', "hseqr"); 1847 assert(h.length!1 >= h.length!0, "hseqr"); 1848 assert(h.length!1 >= 1, "hseqr"); 1849 assert(compz != 'V' || compz != 'I' || (z.length!1 >= h.length!0 && z.length!1 >= 1), "hseqr"); 1850 assert(compz != 'N' || z.length!1 >= 1); 1851 assert(work.length!0 >= 1, "hseqr"); 1852 assert(work.length!0 >= h.length!0, "hseqr"); 1853 } 1854 do 1855 { 1856 lapackint n = cast(lapackint) h.length!0; 1857 lapackint ldh = cast(lapackint) h._stride.max(1); 1858 lapackint ldz = cast(lapackint) z._stride.max(1); 1859 lapackint lwork = cast(lapackint) work.length!0; 1860 lapackint info; 1861 lapack.hseqr_(job,compz,n,ilo,ihi,h.iterator, ldh, wr.iterator, wi.iterator, z.iterator, ldz, work.iterator, lwork, info); 1862 assert(info >= 0); 1863 return cast(size_t)info; 1864 } 1865 1866 unittest 1867 { 1868 alias f = hseqr!float; 1869 alias d = hseqr!double; 1870 alias s = hseqr!_cfloat; 1871 alias c = hseqr!_cdouble; 1872 } 1873 1874 /// 1875 size_t trevc(T)(char side, 1876 char howmany, 1877 lapackint select, 1878 Slice!(T*, 2, Canonical) t, 1879 Slice!(T*, 2, Canonical) vl, 1880 Slice!(T*, 2, Canonical) vr, 1881 lapackint m, 1882 Slice!(T*) work 1883 ) 1884 do 1885 { 1886 lapackint n = cast(lapackint)t.length!0; 1887 lapackint ldt = cast(lapackint) t._stride.max(1); 1888 lapackint ldvl = cast(lapackint) vl._stride.max(1); 1889 lapackint ldvr = cast(lapackint) vr._stride.max(1); 1890 lapackint mm = cast(lapackint) vr.length!1; 1891 //select should be lapack_logical 1892 lapackint info; 1893 static if(!isComplex!T){ 1894 lapack.trevc_(side, howmany, select, n, t.iterator, ldt, vl.iterator, ldvl, vr.iterator, ldvr, mm, m, work.iterator, info); 1895 } 1896 else { 1897 lapack.trevc_(side, howmany, select, n, t.iterator, ldt, vl.iterator, ldvl, vr.iterator, ldvr, mm, m, work.iterator, null, info); 1898 } 1899 assert(info >= 0); 1900 return cast(size_t)info; 1901 } 1902 1903 unittest 1904 { 1905 alias f = trevc!float; 1906 alias d = trevc!double; 1907 alias s = trevc!_cfloat; 1908 alias c = trevc!_cdouble; 1909 } 1910 1911 /// 1912 size_t gebal(T, realT)(char job, 1913 Slice!(T*, 2, Canonical) a, 1914 lapackint ilo, 1915 lapackint ihi, 1916 Slice!(realT*) scale 1917 ) 1918 if (!isComplex!T || (isComplex!T && is(realType!T == realT))) 1919 { 1920 lapackint n = cast(lapackint) a.length!0; 1921 lapackint lda = cast(lapackint) a._stride.max(1); 1922 lapackint info; 1923 lapack.gebal_(job, n, a.iterator, lda, ilo, ihi, scale.iterator, info); 1924 assert(info >= 0); 1925 return cast(size_t)info; 1926 } 1927 1928 unittest 1929 { 1930 alias a = gebal!(double, double); 1931 alias b = gebal!(_cdouble, double); 1932 alias c = gebal!(float, float); 1933 alias d = gebal!(_cfloat, float); 1934 } 1935 1936 /// 1937 size_t gebak(T, realT)( 1938 char job, 1939 char side, 1940 lapackint ilo, 1941 lapackint ihi, 1942 Slice!(realT*) scale, 1943 Slice!(T*, 2, Canonical) v 1944 ) 1945 if (!isComplex!T || (isComplex!T && is(realType!T == realT))) 1946 { 1947 lapackint n = cast(lapackint) scale.length!0; 1948 lapackint m = cast(lapackint) v.length!1;//num evects 1949 lapackint ldv = cast(lapackint) v._stride.max(1); 1950 lapackint info; 1951 lapack.gebak_(job, side, n, ilo, ihi, scale.iterator, m, v.iterator, ldv, info); 1952 assert(info >= 0); 1953 return cast(size_t)info; 1954 } 1955 1956 unittest 1957 { 1958 alias a = gebak!(double, double); 1959 alias b = gebak!(_cdouble, double); 1960 alias c = gebak!(float, float); 1961 alias d = gebak!(_cfloat, float); 1962 } 1963 1964 /// 1965 size_t geev(T, realT)( 1966 char jobvl, 1967 char jobvr, 1968 Slice!(T*, 2, Canonical) a, 1969 Slice!(T*) w, 1970 Slice!(T*, 2, Canonical) vl, 1971 Slice!(T*, 2, Canonical) vr, 1972 Slice!(T*) work, 1973 Slice!(realT*) rwork 1974 ) 1975 if (isComplex!T && is(realType!T == realT)) 1976 { 1977 lapackint n = cast(lapackint) a.length!0; 1978 lapackint lda = cast(lapackint) a._stride.max(1); 1979 lapackint ldvr = cast(lapackint) vr._stride.max(1); 1980 lapackint ldvl = cast(lapackint) vl._stride.max(1); 1981 lapackint info; 1982 lapackint lwork = cast(lapackint)work.length!0; 1983 lapack.geev_(jobvl, jobvr, n, a.iterator, lda, w.iterator, vl.iterator, ldvl, vr.iterator, ldvr, work.iterator, lwork, rwork.iterator, info); 1984 assert(info >= 0); 1985 return info; 1986 } 1987 1988 /// 1989 size_t geev(T)( 1990 char jobvl, 1991 char jobvr, 1992 Slice!(T*, 2, Canonical) a, 1993 Slice!(T*) wr, 1994 Slice!(T*) wi, 1995 Slice!(T*, 2, Canonical) vl, 1996 Slice!(T*, 2, Canonical) vr, 1997 Slice!(T*) work 1998 ) 1999 if (!isComplex!T) 2000 { 2001 lapackint n = cast(lapackint) a.length!0; 2002 lapackint lda = cast(lapackint) a._stride.max(1); 2003 lapackint ldvr = cast(lapackint) vr._stride.max(1); 2004 lapackint ldvl = cast(lapackint) vl._stride.max(1); 2005 lapackint info; 2006 lapackint lwork = cast(lapackint)work.length!0; 2007 lapack.geev_(jobvl, jobvr, n, a.iterator, lda, wr.iterator, wi.iterator, vl.iterator, ldvl, vr.iterator, ldvr, work.iterator, lwork, info); 2008 assert(info >= 0); 2009 return info; 2010 } 2011 2012 /// 2013 size_t steqr(T, realT = realType!T)( 2014 char compz, 2015 Slice!(realT*) d, 2016 Slice!(realT*) e, 2017 Slice!(T*, 2, Canonical) z, 2018 Slice!(realT*) work) 2019 if (is(realType!T == realT)) 2020 in { 2021 assert(d.length == e.length + 1); 2022 assert(work.length >= (e.length * 2).max(1u)); 2023 assert(z.length!0 == d.length); 2024 assert(z.length!1 == d.length); 2025 assert(z._stride >= d.length); 2026 } 2027 do { 2028 lapackint n = cast(lapackint) d.length; 2029 lapackint ldz = cast(lapackint) z._stride.max(1); 2030 lapackint info; 2031 2032 lapack.steqr_(compz, n, d.iterator, e.iterator, z.iterator, ldz, work.iterator, info); 2033 assert(info >= 0); 2034 return info; 2035 } 2036 2037 unittest 2038 { 2039 alias a = steqr!float; 2040 alias b = steqr!double; 2041 alias c = steqr!_cfloat; 2042 alias d = steqr!_cdouble; 2043 } 2044 2045 2046 /// 2047 @trusted 2048 size_t sytrs_3(T)( 2049 char uplo, 2050 Slice!(const(T)*, 2, Canonical) a, 2051 Slice!(const(T)*) e, 2052 Slice!(const(lapackint)*) ipiv, 2053 Slice!(T*, 2, Canonical) b, 2054 ) 2055 in 2056 { 2057 assert(a.length!0 == a.length!1, "sytrs_3: 'a' must be a square matrix."); 2058 assert(e.length == a.length, "sytrs_3: 'e' must have the same length as 'a'."); 2059 assert(b.length!1 == a.length, "sytrs_3: 'b.length!1' must must be equal to 'a.length'."); 2060 } 2061 do 2062 { 2063 lapackint n = cast(lapackint) a.length; 2064 lapackint nrhs = cast(lapackint) b.length; 2065 lapackint lda = cast(lapackint) a._stride.max(1); 2066 lapackint ldb = cast(lapackint) b._stride.max(1); 2067 lapackint info; 2068 // ref char uplo, ref lapackint n, ref lapackint nrhs, float *a, ref lapackint lda, float* e, lapackint *ipiv, float *b, ref lapackint ldb, ref lapackint info 2069 lapack.sytrs_3_(uplo, n, nrhs, a.iterator, lda, e.iterator, ipiv.iterator, b.iterator, ldb, info); 2070 assert(info >= 0); 2071 return info; 2072 } 2073 2074 version(none) 2075 unittest 2076 { 2077 alias s = sytrs_3!float; 2078 alias d = sytrs_3!double; 2079 alias c = sytrs_3!_cfloat; 2080 alias z = sytrs_3!_cdouble; 2081 } 2082 2083 /// 2084 @trusted 2085 size_t sytrf_rk(T)( 2086 char uplo, 2087 Slice!(T*, 2, Canonical) a, 2088 Slice!(T*) e, 2089 Slice!(lapackint*) ipiv, 2090 Slice!(T*) work, 2091 ) 2092 in 2093 { 2094 assert(a.length!0 == a.length!1, "sytrf_rk: 'a' must be a square matrix."); 2095 assert(e.length == a.length, "sytrf_rk: 'e' must have the same length as 'a'."); 2096 } 2097 do 2098 { 2099 lapackint info; 2100 lapackint n = cast(lapackint) a.length; 2101 lapackint lda = cast(lapackint) a._stride.max(1); 2102 lapackint lwork = cast(lapackint) work.length; 2103 lapack.sytrf_rk_(uplo, n, a.iterator, lda, e.iterator, ipiv.iterator, work.iterator, lwork, info); 2104 assert(info >= 0); 2105 return info; 2106 } 2107 2108 version(none) 2109 unittest 2110 { 2111 alias s = sytrf_rk!float; 2112 alias d = sytrf_rk!double; 2113 alias c = sytrf_rk!_cfloat; 2114 alias z = sytrf_rk!_cdouble; 2115 } 2116 2117 2118 /// 2119 size_t sytrf_rk_wk(T)( 2120 char uplo, 2121 Slice!(T*, 2, Canonical) a, 2122 ) 2123 in 2124 { 2125 assert(a.length!0 == a.length!1, "sytrf_rk_wk: 'a' must be a square matrix."); 2126 } 2127 do 2128 { 2129 2130 lapackint info; 2131 lapackint n = cast(lapackint) a.length; 2132 lapackint lda = cast(lapackint) a._stride.max(1); 2133 lapackint lwork = -1; 2134 lapackint info; 2135 T e; 2136 T work; 2137 lapackint ipiv; 2138 2139 lapack.sytrf_rk_(uplo, n, a.iterator, lda, &e, &ipiv, &work, lwork, info); 2140 2141 return cast(size_t) work.re; 2142 } 2143 2144 version(none) 2145 unittest 2146 { 2147 alias s = sytrf_rk!float; 2148 alias d = sytrf_rk!double; 2149 } 2150 2151 /// 2152 template posvx(T) 2153 if (is(T == double) || is(T == float)) 2154 { 2155 @trusted 2156 size_t posvx( 2157 char fact, 2158 char uplo, 2159 Slice!(T*, 2, Canonical) a, 2160 Slice!(T*, 2, Canonical) af, 2161 char equed, 2162 Slice!(T*) s, 2163 Slice!(T*, 2, Canonical) b, 2164 Slice!(T*, 2, Canonical) x, 2165 out T rcond, 2166 Slice!(T*) ferr, 2167 Slice!(T*) berr, 2168 Slice!(T*) work, 2169 Slice!(lapackint*) iwork, 2170 ) 2171 in { 2172 assert(fact == 'F' || fact == 'N' || fact == 'E'); 2173 assert(uplo == 'U' || uplo == 'L'); 2174 auto n = a.length!0; 2175 auto nrhs = x.length; 2176 assert(a.length!1 == n); 2177 assert(af.length!0 == n); 2178 assert(af.length!1 == n); 2179 assert(x.length!1 == n); 2180 assert(b.length!1 == n); 2181 assert(b.length!0 == nrhs); 2182 assert(ferr.length == nrhs); 2183 assert(berr.length == nrhs); 2184 assert(work.length == n * 3); 2185 assert(iwork.length == n); 2186 } 2187 do { 2188 lapackint n = cast(lapackint) a.length!0; 2189 lapackint nrhs = cast(lapackint) x.length; 2190 lapackint lda = cast(lapackint) a._stride.max(1); 2191 lapackint ldaf = cast(lapackint) af._stride.max(1); 2192 lapackint ldx = cast(lapackint) x._stride.max(1); 2193 lapackint ldb = cast(lapackint) b._stride.max(1); 2194 lapackint info; 2195 lapack.posvx_(fact, uplo, n, nrhs, a._iterator, lda, af._iterator, ldaf, equed, s._iterator, b._iterator, ldb, x._iterator, ldx, rcond, ferr._iterator, berr._iterator, work._iterator, iwork._iterator, info); 2196 assert(info >= 0); 2197 return info; 2198 } 2199 2200 @trusted 2201 size_t posvx( 2202 char fact, 2203 char uplo, 2204 Slice!(T*, 2, Canonical) a, 2205 Slice!(T*, 2, Canonical) af, 2206 char equed, 2207 Slice!(T*) s, 2208 Slice!(T*) b, 2209 Slice!(T*) x, 2210 out T rcond, 2211 out T ferr, 2212 out T berr, 2213 Slice!(T*) work, 2214 Slice!(lapackint*) iwork, 2215 ) 2216 in { 2217 assert(fact == 'F' || fact == 'N' || fact == 'E'); 2218 assert(uplo == 'U' || uplo == 'L'); 2219 auto n = a.length!0; 2220 assert(a.length!1 == n); 2221 assert(af.length!0 == n); 2222 assert(af.length!1 == n); 2223 assert(x.length == n); 2224 assert(b.length == n); 2225 assert(work.length == n * 3); 2226 assert(iwork.length == n); 2227 } 2228 do { 2229 import mir.ndslice.topology: canonical; 2230 return posvx(fact, uplo, a, af, equed, s, b.sliced(1, b.length).canonical, x.sliced(1, x.length).canonical, rcond, sliced(&ferr, 1), sliced(&berr, 1), work, iwork); 2231 } 2232 } 2233 2234 version(none) 2235 unittest 2236 { 2237 alias s = posvx!float; 2238 alias d = posvx!double; 2239 } 2240 2241 /// 2242 size_t sytrf_wk(T)( 2243 char uplo, 2244 Slice!(T*, 2, Canonical) a, 2245 ) 2246 in 2247 { 2248 assert(a.length!0 == a.length!1, "sytrf_wk: 'a' must be a square matrix."); 2249 } 2250 do 2251 { 2252 lapackint n = cast(lapackint) a.length; 2253 lapackint lda = cast(lapackint) a._stride.max(1); 2254 lapackint lwork = -1; 2255 lapackint info; 2256 T work; 2257 lapackint ipiv; 2258 2259 lapack.sytrf_(uplo, n, a.iterator, lda, &ipiv, &work, lwork, info); 2260 2261 return cast(size_t) work.re; 2262 } 2263 2264 unittest 2265 { 2266 alias s = sytrf_wk!float; 2267 alias d = sytrf_wk!double; 2268 } 2269 2270 /// 2271 template posv(T) 2272 if (is(T == double) || is(T == float)) 2273 { 2274 @trusted 2275 size_t posv( 2276 char uplo, 2277 Slice!(T*, 2, Canonical) a, 2278 Slice!(T*, 2, Canonical) b 2279 ) 2280 in { 2281 assert(uplo == 'U' || uplo == 'L'); 2282 auto n = a.length!0; 2283 auto nrhs = b.length!0; 2284 assert(a.length!1 == n); 2285 assert(b.length!1 == n); 2286 assert(b.length!0 == nrhs); 2287 } 2288 do { 2289 lapackint n = cast(lapackint) a.length!0; 2290 lapackint nrhs = cast(lapackint) b.length!0; 2291 lapackint lda = cast(lapackint) a._stride.max(1); 2292 lapackint ldb = cast(lapackint) b._stride.max(1); 2293 lapackint info; 2294 lapack.posv_(uplo, n, nrhs, a._iterator, lda, b._iterator, ldb, info); 2295 assert(info >= 0); 2296 return info; 2297 } 2298 2299 @trusted 2300 size_t posv( 2301 char uplo, 2302 Slice!(T*, 2, Canonical) a, 2303 Slice!(T*) b 2304 ) 2305 in { 2306 assert(uplo == 'U' || uplo == 'L'); 2307 assert(a.length!0 == a.length!1); 2308 assert(b.length == a.length!0); 2309 } 2310 do { 2311 import mir.ndslice.topology: canonical; 2312 return posv(uplo, a, b.sliced(1, b.length).canonical); 2313 } 2314 } 2315 2316 version(none) 2317 unittest 2318 { 2319 alias s = posv!float; 2320 alias d = posv!double; 2321 }