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