1 // Copyright (C) 2010 Davis E. King (davis@dlib.net) 2 // License: Boost Software License See LICENSE.txt for the full license. 3 #ifndef DLIB_MATRiX_TRSM_Hh_ 4 #define DLIB_MATRiX_TRSM_Hh_ 5 #include "lapack/fortran_id.h" 6 #include "cblas_constants.h" 7 8 namespace dlib 9 { 10 namespace blas_bindings 11 { 12 #ifdef DLIB_USE_BLAS 13 #ifdef DLIB_DEFINE_CBLAS_API 14 extern "C" 15 { 16 void cblas_strsm(const CBLAS_ORDER Order, const CBLAS_SIDE Side, 17 const CBLAS_UPLO Uplo, const CBLAS_TRANSPOSE TransA, 18 const CBLAS_DIAG Diag, const CBLAS_INT_TYPE M, const CBLAS_INT_TYPE N, 19 const float alpha, const float *A, const CBLAS_INT_TYPE lda, 20 float *B, const CBLAS_INT_TYPE ldb); 21 22 void cblas_dtrsm(const CBLAS_ORDER Order, const CBLAS_SIDE Side, 23 const CBLAS_UPLO Uplo, const CBLAS_TRANSPOSE TransA, 24 const CBLAS_DIAG Diag, const CBLAS_INT_TYPE M, const CBLAS_INT_TYPE N, 25 const double alpha, const double *A, const CBLAS_INT_TYPE lda, 26 double *B, const CBLAS_INT_TYPE ldb); 27 } 28 #endif // if DLIB_DEFINE_CBLAS_API 29 #endif // if DLIB_USE_BLAS 30 31 // ------------------------------------------------------------------------------------ 32 33 /* Purpose */ 34 /* ======= */ 35 36 /* DTRSM solves one of the matrix equations */ 37 38 /* op( A )*X = alpha*B, or X*op( A ) = alpha*B, */ 39 40 /* where alpha is a scalar, X and B are m by n matrices, A is a unit, or */ 41 /* non-unit, upper or lower triangular matrix and op( A ) is one of */ 42 43 /* op( A ) = A or op( A ) = A'. */ 44 45 /* The matrix X is overwritten on B. */ 46 47 /* Arguments */ 48 /* ========== */ 49 50 /* SIDE - CHARACTER*1. */ 51 /* On entry, SIDE specifies whether op( A ) appears on the left */ 52 /* or right of X as follows: */ 53 54 /* SIDE = 'L' or 'l' op( A )*X = alpha*B. */ 55 56 /* SIDE = 'R' or 'r' X*op( A ) = alpha*B. */ 57 58 /* Unchanged on exit. */ 59 60 /* UPLO - CHARACTER*1. */ 61 /* On entry, UPLO specifies whether the matrix A is an upper or */ 62 /* lower triangular matrix as follows: */ 63 64 /* UPLO = 'U' or 'u' A is an upper triangular matrix. */ 65 66 /* UPLO = 'L' or 'l' A is a lower triangular matrix. */ 67 68 /* Unchanged on exit. */ 69 70 /* TRANSA - CHARACTER*1. */ 71 /* On entry, TRANSA specifies the form of op( A ) to be used in */ 72 /* the matrix multiplication as follows: */ 73 74 /* TRANSA = 'N' or 'n' op( A ) = A. */ 75 76 /* TRANSA = 'T' or 't' op( A ) = A'. */ 77 78 /* TRANSA = 'C' or 'c' op( A ) = A'. */ 79 80 /* Unchanged on exit. */ 81 82 /* DIAG - CHARACTER*1. */ 83 /* On entry, DIAG specifies whether or not A is unit triangular */ 84 /* as follows: */ 85 86 /* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ 87 88 /* DIAG = 'N' or 'n' A is not assumed to be unit */ 89 /* triangular. */ 90 91 /* Unchanged on exit. */ 92 93 /* M - INTEGER. */ 94 /* On entry, M specifies the number of rows of B. M must be at */ 95 /* least zero. */ 96 /* Unchanged on exit. */ 97 98 /* N - INTEGER. */ 99 /* On entry, N specifies the number of columns of B. N must be */ 100 /* at least zero. */ 101 /* Unchanged on exit. */ 102 103 /* ALPHA - DOUBLE PRECISION. */ 104 /* On entry, ALPHA specifies the scalar alpha. When alpha is */ 105 /* zero then A is not referenced and B need not be set before */ 106 /* entry. */ 107 /* Unchanged on exit. */ 108 109 /* A - DOUBLE PRECISION array of DIMENSION ( LDA, k ), where k is m */ 110 /* when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. */ 111 /* Before entry with UPLO = 'U' or 'u', the leading k by k */ 112 /* upper triangular part of the array A must contain the upper */ 113 /* triangular matrix and the strictly lower triangular part of */ 114 /* A is not referenced. */ 115 /* Before entry with UPLO = 'L' or 'l', the leading k by k */ 116 /* lower triangular part of the array A must contain the lower */ 117 /* triangular matrix and the strictly upper triangular part of */ 118 /* A is not referenced. */ 119 /* Note that when DIAG = 'U' or 'u', the diagonal elements of */ 120 /* A are not referenced either, but are assumed to be unity. */ 121 /* Unchanged on exit. */ 122 123 /* LDA - INTEGER. */ 124 /* On entry, LDA specifies the first dimension of A as declared */ 125 /* in the calling (sub) program. When SIDE = 'L' or 'l' then */ 126 /* LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' */ 127 /* then LDA must be at least max( 1, n ). */ 128 /* Unchanged on exit. */ 129 130 /* B - DOUBLE PRECISION array of DIMENSION ( LDB, n ). */ 131 /* Before entry, the leading m by n part of the array B must */ 132 /* contain the right-hand side matrix B, and on exit is */ 133 /* overwritten by the solution matrix X. */ 134 135 /* LDB - INTEGER. */ 136 /* On entry, LDB specifies the first dimension of B as declared */ 137 /* in the calling (sub) program. LDB must be at least */ 138 /* max( 1, m ). */ 139 /* Unchanged on exit. */ 140 141 142 /* Level 3 Blas routine. */ 143 144 145 /* -- Written on 8-February-1989. */ 146 /* Jack Dongarra, Argonne National Laboratory. */ 147 /* Iain Duff, AERE Harwell. */ 148 /* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ 149 /* Sven Hammarling, Numerical Algorithms Group Ltd. */ 150 151 template <typename T> local_trsm(const CBLAS_ORDER Order,CBLAS_SIDE Side,CBLAS_UPLO Uplo,const CBLAS_TRANSPOSE TransA,const CBLAS_DIAG Diag,long m,long n,T alpha,const T * a,long lda,T * b,long ldb)152 void local_trsm( 153 const CBLAS_ORDER Order, 154 CBLAS_SIDE Side, 155 CBLAS_UPLO Uplo, 156 const CBLAS_TRANSPOSE TransA, 157 const CBLAS_DIAG Diag, 158 long m, 159 long n, 160 T alpha, 161 const T *a, 162 long lda, 163 T *b, 164 long ldb 165 ) 166 /*! 167 This is a copy of the dtrsm routine from the netlib.org BLAS which was run though 168 f2c and converted into this form for use when a BLAS library is not available. 169 !*/ 170 { 171 if (Order == CblasRowMajor) 172 { 173 // since row major ordering looks like transposition to FORTRAN we need to flip a 174 // few things. 175 if (Side == CblasLeft) 176 Side = CblasRight; 177 else 178 Side = CblasLeft; 179 180 if (Uplo == CblasUpper) 181 Uplo = CblasLower; 182 else 183 Uplo = CblasUpper; 184 185 std::swap(m,n); 186 } 187 188 /* System generated locals */ 189 long a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3; 190 191 /* Local variables */ 192 long i__, j, k, info; 193 T temp; 194 bool lside; 195 long nrowa; 196 bool upper; 197 bool nounit; 198 199 /* Parameter adjustments */ 200 a_dim1 = lda; 201 a_offset = 1 + a_dim1; 202 a -= a_offset; 203 b_dim1 = ldb; 204 b_offset = 1 + b_dim1; 205 b -= b_offset; 206 207 /* Function Body */ 208 lside = (Side == CblasLeft); 209 if (lside) 210 { 211 nrowa = m; 212 } else 213 { 214 nrowa = n; 215 } 216 nounit = (Diag == CblasNonUnit); 217 upper = (Uplo == CblasUpper); 218 219 info = 0; 220 if (! lside && ! (Side == CblasRight)) { 221 info = 1; 222 } else if (! upper && !(Uplo == CblasLower) ) { 223 info = 2; 224 } else if (!(TransA == CblasNoTrans) && 225 !(TransA == CblasTrans) && 226 !(TransA == CblasConjTrans)) { 227 info = 3; 228 } else if (!(Diag == CblasUnit) && 229 !(Diag == CblasNonUnit) ) { 230 info = 4; 231 } else if (m < 0) { 232 info = 5; 233 } else if (n < 0) { 234 info = 6; 235 } else if (lda < std::max<long>(1,nrowa)) { 236 info = 9; 237 } else if (ldb < std::max<long>(1,m)) { 238 info = 11; 239 } 240 DLIB_CASSERT( info == 0, "Invalid inputs given to local_trsm"); 241 242 /* Quick return if possible. */ 243 244 if (m == 0 || n == 0) { 245 return; 246 } 247 248 /* And when alpha.eq.zero. */ 249 250 if (alpha == 0.) { 251 i__1 = n; 252 for (j = 1; j <= i__1; ++j) { 253 i__2 = m; 254 for (i__ = 1; i__ <= i__2; ++i__) { 255 b[i__ + j * b_dim1] = 0.; 256 /* L10: */ 257 } 258 /* L20: */ 259 } 260 return; 261 } 262 263 /* Start the operations. */ 264 265 if (lside) { 266 if (TransA == CblasNoTrans) { 267 268 /* Form B := alpha*inv( A )*B. */ 269 270 if (upper) { 271 i__1 = n; 272 for (j = 1; j <= i__1; ++j) { 273 if (alpha != 1.) { 274 i__2 = m; 275 for (i__ = 1; i__ <= i__2; ++i__) { 276 b[i__ + j * b_dim1] = alpha * b[i__ + j * b_dim1] 277 ; 278 /* L30: */ 279 } 280 } 281 for (k = m; k >= 1; --k) { 282 if (b[k + j * b_dim1] != 0.) { 283 if (nounit) { 284 b[k + j * b_dim1] /= a[k + k * a_dim1]; 285 } 286 i__2 = k - 1; 287 for (i__ = 1; i__ <= i__2; ++i__) { 288 b[i__ + j * b_dim1] -= b[k + j * b_dim1] * a[ 289 i__ + k * a_dim1]; 290 /* L40: */ 291 } 292 } 293 /* L50: */ 294 } 295 /* L60: */ 296 } 297 } else { 298 i__1 = n; 299 for (j = 1; j <= i__1; ++j) { 300 if (alpha != 1.) { 301 i__2 = m; 302 for (i__ = 1; i__ <= i__2; ++i__) { 303 b[i__ + j * b_dim1] = alpha * b[i__ + j * b_dim1] 304 ; 305 /* L70: */ 306 } 307 } 308 i__2 = m; 309 for (k = 1; k <= i__2; ++k) { 310 if (b[k + j * b_dim1] != 0.) { 311 if (nounit) { 312 b[k + j * b_dim1] /= a[k + k * a_dim1]; 313 } 314 i__3 = m; 315 for (i__ = k + 1; i__ <= i__3; ++i__) { 316 b[i__ + j * b_dim1] -= b[k + j * b_dim1] * a[ 317 i__ + k * a_dim1]; 318 /* L80: */ 319 } 320 } 321 /* L90: */ 322 } 323 /* L100: */ 324 } 325 } 326 } else { 327 328 /* Form B := alpha*inv( A' )*B. */ 329 330 if (upper) { 331 i__1 = n; 332 for (j = 1; j <= i__1; ++j) { 333 i__2 = m; 334 for (i__ = 1; i__ <= i__2; ++i__) { 335 temp = alpha * b[i__ + j * b_dim1]; 336 i__3 = i__ - 1; 337 for (k = 1; k <= i__3; ++k) { 338 temp -= a[k + i__ * a_dim1] * b[k + j * b_dim1]; 339 /* L110: */ 340 } 341 if (nounit) { 342 temp /= a[i__ + i__ * a_dim1]; 343 } 344 b[i__ + j * b_dim1] = temp; 345 /* L120: */ 346 } 347 /* L130: */ 348 } 349 } else { 350 i__1 = n; 351 for (j = 1; j <= i__1; ++j) { 352 for (i__ = m; i__ >= 1; --i__) { 353 temp = alpha * b[i__ + j * b_dim1]; 354 i__2 = m; 355 for (k = i__ + 1; k <= i__2; ++k) { 356 temp -= a[k + i__ * a_dim1] * b[k + j * b_dim1]; 357 /* L140: */ 358 } 359 if (nounit) { 360 temp /= a[i__ + i__ * a_dim1]; 361 } 362 b[i__ + j * b_dim1] = temp; 363 /* L150: */ 364 } 365 /* L160: */ 366 } 367 } 368 } 369 } else { 370 if (TransA == CblasNoTrans) { 371 372 /* Form B := alpha*B*inv( A ). */ 373 374 if (upper) { 375 i__1 = n; 376 for (j = 1; j <= i__1; ++j) { 377 if (alpha != 1.) { 378 i__2 = m; 379 for (i__ = 1; i__ <= i__2; ++i__) { 380 b[i__ + j * b_dim1] = alpha * b[i__ + j * b_dim1] 381 ; 382 /* L170: */ 383 } 384 } 385 i__2 = j - 1; 386 for (k = 1; k <= i__2; ++k) { 387 if (a[k + j * a_dim1] != 0.) { 388 i__3 = m; 389 for (i__ = 1; i__ <= i__3; ++i__) { 390 b[i__ + j * b_dim1] -= a[k + j * a_dim1] * b[ 391 i__ + k * b_dim1]; 392 /* L180: */ 393 } 394 } 395 /* L190: */ 396 } 397 if (nounit) { 398 temp = 1. / a[j + j * a_dim1]; 399 i__2 = m; 400 for (i__ = 1; i__ <= i__2; ++i__) { 401 b[i__ + j * b_dim1] = temp * b[i__ + j * b_dim1]; 402 /* L200: */ 403 } 404 } 405 /* L210: */ 406 } 407 } else { 408 for (j = n; j >= 1; --j) { 409 if (alpha != 1.) { 410 i__1 = m; 411 for (i__ = 1; i__ <= i__1; ++i__) { 412 b[i__ + j * b_dim1] = alpha * b[i__ + j * b_dim1] 413 ; 414 /* L220: */ 415 } 416 } 417 i__1 = n; 418 for (k = j + 1; k <= i__1; ++k) { 419 if (a[k + j * a_dim1] != 0.) { 420 i__2 = m; 421 for (i__ = 1; i__ <= i__2; ++i__) { 422 b[i__ + j * b_dim1] -= a[k + j * a_dim1] * b[ 423 i__ + k * b_dim1]; 424 /* L230: */ 425 } 426 } 427 /* L240: */ 428 } 429 if (nounit) { 430 temp = 1. / a[j + j * a_dim1]; 431 i__1 = m; 432 for (i__ = 1; i__ <= i__1; ++i__) { 433 b[i__ + j * b_dim1] = temp * b[i__ + j * b_dim1]; 434 /* L250: */ 435 } 436 } 437 /* L260: */ 438 } 439 } 440 } else { 441 442 /* Form B := alpha*B*inv( A' ). */ 443 444 if (upper) { 445 for (k = n; k >= 1; --k) { 446 if (nounit) { 447 temp = 1. / a[k + k * a_dim1]; 448 i__1 = m; 449 for (i__ = 1; i__ <= i__1; ++i__) { 450 b[i__ + k * b_dim1] = temp * b[i__ + k * b_dim1]; 451 /* L270: */ 452 } 453 } 454 i__1 = k - 1; 455 for (j = 1; j <= i__1; ++j) { 456 if (a[j + k * a_dim1] != 0.) { 457 temp = a[j + k * a_dim1]; 458 i__2 = m; 459 for (i__ = 1; i__ <= i__2; ++i__) { 460 b[i__ + j * b_dim1] -= temp * b[i__ + k * 461 b_dim1]; 462 /* L280: */ 463 } 464 } 465 /* L290: */ 466 } 467 if (alpha != 1.) { 468 i__1 = m; 469 for (i__ = 1; i__ <= i__1; ++i__) { 470 b[i__ + k * b_dim1] = alpha * b[i__ + k * b_dim1] 471 ; 472 /* L300: */ 473 } 474 } 475 /* L310: */ 476 } 477 } else { 478 i__1 = n; 479 for (k = 1; k <= i__1; ++k) { 480 if (nounit) { 481 temp = 1. / a[k + k * a_dim1]; 482 i__2 = m; 483 for (i__ = 1; i__ <= i__2; ++i__) { 484 b[i__ + k * b_dim1] = temp * b[i__ + k * b_dim1]; 485 /* L320: */ 486 } 487 } 488 i__2 = n; 489 for (j = k + 1; j <= i__2; ++j) { 490 if (a[j + k * a_dim1] != 0.) { 491 temp = a[j + k * a_dim1]; 492 i__3 = m; 493 for (i__ = 1; i__ <= i__3; ++i__) { 494 b[i__ + j * b_dim1] -= temp * b[i__ + k * 495 b_dim1]; 496 /* L330: */ 497 } 498 } 499 /* L340: */ 500 } 501 if (alpha != 1.) { 502 i__2 = m; 503 for (i__ = 1; i__ <= i__2; ++i__) { 504 b[i__ + k * b_dim1] = alpha * b[i__ + k * b_dim1] 505 ; 506 /* L350: */ 507 } 508 } 509 /* L360: */ 510 } 511 } 512 } 513 } 514 } 515 516 // ------------------------------------------------------------------------------------ 517 cblas_trsm(const CBLAS_ORDER Order,const CBLAS_SIDE Side,const CBLAS_UPLO Uplo,const CBLAS_TRANSPOSE TransA,const CBLAS_DIAG Diag,const int M,const int N,const float alpha,const float * A,const int lda,float * B,const int ldb)518 inline void cblas_trsm(const CBLAS_ORDER Order, const CBLAS_SIDE Side, 519 const CBLAS_UPLO Uplo, const CBLAS_TRANSPOSE TransA, 520 const CBLAS_DIAG Diag, const int M, const int N, 521 const float alpha, const float *A, const int lda, 522 float *B, const int ldb) 523 { 524 #ifdef DLIB_USE_BLAS 525 if (M > 4) 526 { 527 cblas_strsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); 528 return; 529 } 530 #endif 531 local_trsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); 532 } 533 cblas_trsm(const CBLAS_ORDER Order,const CBLAS_SIDE Side,const CBLAS_UPLO Uplo,const CBLAS_TRANSPOSE TransA,const CBLAS_DIAG Diag,const int M,const int N,const double alpha,const double * A,const int lda,double * B,const int ldb)534 inline void cblas_trsm(const CBLAS_ORDER Order, const CBLAS_SIDE Side, 535 const CBLAS_UPLO Uplo, const CBLAS_TRANSPOSE TransA, 536 const CBLAS_DIAG Diag, const int M, const int N, 537 const double alpha, const double *A, const int lda, 538 double *B, const int ldb) 539 { 540 #ifdef DLIB_USE_BLAS 541 if (M > 4) 542 { 543 cblas_dtrsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); 544 return; 545 } 546 #endif 547 local_trsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); 548 } 549 cblas_trsm(const CBLAS_ORDER Order,const CBLAS_SIDE Side,const CBLAS_UPLO Uplo,const CBLAS_TRANSPOSE TransA,const CBLAS_DIAG Diag,const int M,const int N,const long double alpha,const long double * A,const int lda,long double * B,const int ldb)550 inline void cblas_trsm(const CBLAS_ORDER Order, const CBLAS_SIDE Side, 551 const CBLAS_UPLO Uplo, const CBLAS_TRANSPOSE TransA, 552 const CBLAS_DIAG Diag, const int M, const int N, 553 const long double alpha, const long double *A, const int lda, 554 long double *B, const int ldb) 555 { 556 local_trsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); 557 } 558 559 // ------------------------------------------------------------------------------------ 560 561 template < 562 typename T, 563 long NR1, long NR2, 564 long NC1, long NC2, 565 typename MM 566 > triangular_solver(const CBLAS_SIDE Side,const CBLAS_UPLO Uplo,const CBLAS_TRANSPOSE TransA,const CBLAS_DIAG Diag,const matrix<T,NR1,NC1,MM,row_major_layout> & A,const T alpha,matrix<T,NR2,NC2,MM,row_major_layout> & B)567 inline void triangular_solver ( 568 const CBLAS_SIDE Side, 569 const CBLAS_UPLO Uplo, 570 const CBLAS_TRANSPOSE TransA, 571 const CBLAS_DIAG Diag, 572 const matrix<T,NR1,NC1,MM,row_major_layout>& A, 573 const T alpha, 574 matrix<T,NR2,NC2,MM,row_major_layout>& B 575 ) 576 { 577 cblas_trsm(CblasRowMajor, Side, Uplo, TransA, Diag, B.nr(), B.nc(), 578 alpha, &A(0,0), A.nc(), &B(0,0), B.nc()); 579 } 580 581 // ------------------------------------------------------------------------------------ 582 583 template < 584 typename T, 585 long NR1, long NR2, 586 long NC1, long NC2, 587 typename MM 588 > triangular_solver(const CBLAS_SIDE Side,const CBLAS_UPLO Uplo,const CBLAS_TRANSPOSE TransA,const CBLAS_DIAG Diag,const matrix<T,NR1,NC1,MM,column_major_layout> & A,const T alpha,matrix<T,NR2,NC2,MM,column_major_layout> & B)589 inline void triangular_solver ( 590 const CBLAS_SIDE Side, 591 const CBLAS_UPLO Uplo, 592 const CBLAS_TRANSPOSE TransA, 593 const CBLAS_DIAG Diag, 594 const matrix<T,NR1,NC1,MM,column_major_layout>& A, 595 const T alpha, 596 matrix<T,NR2,NC2,MM,column_major_layout>& B 597 ) 598 { 599 cblas_trsm(CblasColMajor, Side, Uplo, TransA, Diag, B.nr(), B.nc(), 600 alpha, &A(0,0), A.nr(), &B(0,0), B.nr()); 601 } 602 603 // ------------------------------------------------------------------------------------ 604 605 template < 606 typename T, 607 long NR1, long NR2, 608 long NC1, long NC2, 609 typename MM 610 > triangular_solver(const CBLAS_SIDE Side,const CBLAS_UPLO Uplo,const CBLAS_TRANSPOSE TransA,const CBLAS_DIAG Diag,const matrix<T,NR1,NC1,MM,column_major_layout> & A,matrix<T,NR2,NC2,MM,column_major_layout> & B,long rows_of_B)611 inline void triangular_solver ( 612 const CBLAS_SIDE Side, 613 const CBLAS_UPLO Uplo, 614 const CBLAS_TRANSPOSE TransA, 615 const CBLAS_DIAG Diag, 616 const matrix<T,NR1,NC1,MM,column_major_layout>& A, 617 matrix<T,NR2,NC2,MM,column_major_layout>& B, 618 long rows_of_B 619 ) 620 { 621 const T alpha = 1; 622 cblas_trsm(CblasColMajor, Side, Uplo, TransA, Diag, rows_of_B, B.nc(), 623 alpha, &A(0,0), A.nr(), &B(0,0), B.nr()); 624 } 625 626 // ------------------------------------------------------------------------------------ 627 628 template < 629 typename T, 630 long NR1, long NR2, 631 long NC1, long NC2, 632 typename MM, 633 typename layout 634 > triangular_solver(const CBLAS_SIDE Side,const CBLAS_UPLO Uplo,const CBLAS_TRANSPOSE TransA,const CBLAS_DIAG Diag,const matrix<T,NR1,NC1,MM,layout> & A,matrix<T,NR2,NC2,MM,layout> & B)635 inline void triangular_solver ( 636 const CBLAS_SIDE Side, 637 const CBLAS_UPLO Uplo, 638 const CBLAS_TRANSPOSE TransA, 639 const CBLAS_DIAG Diag, 640 const matrix<T,NR1,NC1,MM,layout>& A, 641 matrix<T,NR2,NC2,MM,layout>& B 642 ) 643 { 644 const T alpha = 1; 645 triangular_solver(Side, Uplo, TransA, Diag, A, alpha, B); 646 } 647 648 // ------------------------------------------------------------------------------------ 649 650 } 651 } 652 653 #endif // DLIB_MATRiX_TRSM_Hh_ 654 655