You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

stfsm.f 35 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. *> \brief \b STFSM solves a matrix equation (one operand is a triangular matrix in RFP format).
  2. *
  3. * =========== DOCUMENTATION ===========
  4. *
  5. * Online html documentation available at
  6. * http://www.netlib.org/lapack/explore-html/
  7. *
  8. *> \htmlonly
  9. *> Download STFSM + dependencies
  10. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/stfsm.f">
  11. *> [TGZ]</a>
  12. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/stfsm.f">
  13. *> [ZIP]</a>
  14. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/stfsm.f">
  15. *> [TXT]</a>
  16. *> \endhtmlonly
  17. *
  18. * Definition:
  19. * ===========
  20. *
  21. * SUBROUTINE STFSM( TRANSR, SIDE, UPLO, TRANS, DIAG, M, N, ALPHA, A,
  22. * B, LDB )
  23. *
  24. * .. Scalar Arguments ..
  25. * CHARACTER TRANSR, DIAG, SIDE, TRANS, UPLO
  26. * INTEGER LDB, M, N
  27. * REAL ALPHA
  28. * ..
  29. * .. Array Arguments ..
  30. * REAL A( 0: * ), B( 0: LDB-1, 0: * )
  31. * ..
  32. *
  33. *
  34. *> \par Purpose:
  35. * =============
  36. *>
  37. *> \verbatim
  38. *>
  39. *> Level 3 BLAS like routine for A in RFP Format.
  40. *>
  41. *> STFSM solves the matrix equation
  42. *>
  43. *> op( A )*X = alpha*B or X*op( A ) = alpha*B
  44. *>
  45. *> where alpha is a scalar, X and B are m by n matrices, A is a unit, or
  46. *> non-unit, upper or lower triangular matrix and op( A ) is one of
  47. *>
  48. *> op( A ) = A or op( A ) = A**T.
  49. *>
  50. *> A is in Rectangular Full Packed (RFP) Format.
  51. *>
  52. *> The matrix X is overwritten on B.
  53. *> \endverbatim
  54. *
  55. * Arguments:
  56. * ==========
  57. *
  58. *> \param[in] TRANSR
  59. *> \verbatim
  60. *> TRANSR is CHARACTER*1
  61. *> = 'N': The Normal Form of RFP A is stored;
  62. *> = 'T': The Transpose Form of RFP A is stored.
  63. *> \endverbatim
  64. *>
  65. *> \param[in] SIDE
  66. *> \verbatim
  67. *> SIDE is CHARACTER*1
  68. *> On entry, SIDE specifies whether op( A ) appears on the left
  69. *> or right of X as follows:
  70. *>
  71. *> SIDE = 'L' or 'l' op( A )*X = alpha*B.
  72. *>
  73. *> SIDE = 'R' or 'r' X*op( A ) = alpha*B.
  74. *>
  75. *> Unchanged on exit.
  76. *> \endverbatim
  77. *>
  78. *> \param[in] UPLO
  79. *> \verbatim
  80. *> UPLO is CHARACTER*1
  81. *> On entry, UPLO specifies whether the RFP matrix A came from
  82. *> an upper or lower triangular matrix as follows:
  83. *> UPLO = 'U' or 'u' RFP A came from an upper triangular matrix
  84. *> UPLO = 'L' or 'l' RFP A came from a lower triangular matrix
  85. *>
  86. *> Unchanged on exit.
  87. *> \endverbatim
  88. *>
  89. *> \param[in] TRANS
  90. *> \verbatim
  91. *> TRANS is CHARACTER*1
  92. *> On entry, TRANS specifies the form of op( A ) to be used
  93. *> in the matrix multiplication as follows:
  94. *>
  95. *> TRANS = 'N' or 'n' op( A ) = A.
  96. *>
  97. *> TRANS = 'T' or 't' op( A ) = A'.
  98. *>
  99. *> Unchanged on exit.
  100. *> \endverbatim
  101. *>
  102. *> \param[in] DIAG
  103. *> \verbatim
  104. *> DIAG is CHARACTER*1
  105. *> On entry, DIAG specifies whether or not RFP A is unit
  106. *> triangular as follows:
  107. *>
  108. *> DIAG = 'U' or 'u' A is assumed to be unit triangular.
  109. *>
  110. *> DIAG = 'N' or 'n' A is not assumed to be unit
  111. *> triangular.
  112. *>
  113. *> Unchanged on exit.
  114. *> \endverbatim
  115. *>
  116. *> \param[in] M
  117. *> \verbatim
  118. *> M is INTEGER
  119. *> On entry, M specifies the number of rows of B. M must be at
  120. *> least zero.
  121. *> Unchanged on exit.
  122. *> \endverbatim
  123. *>
  124. *> \param[in] N
  125. *> \verbatim
  126. *> N is INTEGER
  127. *> On entry, N specifies the number of columns of B. N must be
  128. *> at least zero.
  129. *> Unchanged on exit.
  130. *> \endverbatim
  131. *>
  132. *> \param[in] ALPHA
  133. *> \verbatim
  134. *> ALPHA is REAL
  135. *> On entry, ALPHA specifies the scalar alpha. When alpha is
  136. *> zero then A is not referenced and B need not be set before
  137. *> entry.
  138. *> Unchanged on exit.
  139. *> \endverbatim
  140. *>
  141. *> \param[in] A
  142. *> \verbatim
  143. *> A is REAL array, dimension (NT)
  144. *> NT = N*(N+1)/2. On entry, the matrix A in RFP Format.
  145. *> RFP Format is described by TRANSR, UPLO and N as follows:
  146. *> If TRANSR='N' then RFP A is (0:N,0:K-1) when N is even;
  147. *> K=N/2. RFP A is (0:N-1,0:K) when N is odd; K=N/2. If
  148. *> TRANSR = 'T' then RFP is the transpose of RFP A as
  149. *> defined when TRANSR = 'N'. The contents of RFP A are defined
  150. *> by UPLO as follows: If UPLO = 'U' the RFP A contains the NT
  151. *> elements of upper packed A either in normal or
  152. *> transpose Format. If UPLO = 'L' the RFP A contains
  153. *> the NT elements of lower packed A either in normal or
  154. *> transpose Format. The LDA of RFP A is (N+1)/2 when
  155. *> TRANSR = 'T'. When TRANSR is 'N' the LDA is N+1 when N is
  156. *> even and is N when is odd.
  157. *> See the Note below for more details. Unchanged on exit.
  158. *> \endverbatim
  159. *>
  160. *> \param[in,out] B
  161. *> \verbatim
  162. *> B is REAL array, dimension (LDB,N)
  163. *> Before entry, the leading m by n part of the array B must
  164. *> contain the right-hand side matrix B, and on exit is
  165. *> overwritten by the solution matrix X.
  166. *> \endverbatim
  167. *>
  168. *> \param[in] LDB
  169. *> \verbatim
  170. *> LDB is INTEGER
  171. *> On entry, LDB specifies the first dimension of B as declared
  172. *> in the calling (sub) program. LDB must be at least
  173. *> max( 1, m ).
  174. *> Unchanged on exit.
  175. *> \endverbatim
  176. *
  177. * Authors:
  178. * ========
  179. *
  180. *> \author Univ. of Tennessee
  181. *> \author Univ. of California Berkeley
  182. *> \author Univ. of Colorado Denver
  183. *> \author NAG Ltd.
  184. *
  185. *> \ingroup realOTHERcomputational
  186. *
  187. *> \par Further Details:
  188. * =====================
  189. *>
  190. *> \verbatim
  191. *>
  192. *> We first consider Rectangular Full Packed (RFP) Format when N is
  193. *> even. We give an example where N = 6.
  194. *>
  195. *> AP is Upper AP is Lower
  196. *>
  197. *> 00 01 02 03 04 05 00
  198. *> 11 12 13 14 15 10 11
  199. *> 22 23 24 25 20 21 22
  200. *> 33 34 35 30 31 32 33
  201. *> 44 45 40 41 42 43 44
  202. *> 55 50 51 52 53 54 55
  203. *>
  204. *>
  205. *> Let TRANSR = 'N'. RFP holds AP as follows:
  206. *> For UPLO = 'U' the upper trapezoid A(0:5,0:2) consists of the last
  207. *> three columns of AP upper. The lower triangle A(4:6,0:2) consists of
  208. *> the transpose of the first three columns of AP upper.
  209. *> For UPLO = 'L' the lower trapezoid A(1:6,0:2) consists of the first
  210. *> three columns of AP lower. The upper triangle A(0:2,0:2) consists of
  211. *> the transpose of the last three columns of AP lower.
  212. *> This covers the case N even and TRANSR = 'N'.
  213. *>
  214. *> RFP A RFP A
  215. *>
  216. *> 03 04 05 33 43 53
  217. *> 13 14 15 00 44 54
  218. *> 23 24 25 10 11 55
  219. *> 33 34 35 20 21 22
  220. *> 00 44 45 30 31 32
  221. *> 01 11 55 40 41 42
  222. *> 02 12 22 50 51 52
  223. *>
  224. *> Now let TRANSR = 'T'. RFP A in both UPLO cases is just the
  225. *> transpose of RFP A above. One therefore gets:
  226. *>
  227. *>
  228. *> RFP A RFP A
  229. *>
  230. *> 03 13 23 33 00 01 02 33 00 10 20 30 40 50
  231. *> 04 14 24 34 44 11 12 43 44 11 21 31 41 51
  232. *> 05 15 25 35 45 55 22 53 54 55 22 32 42 52
  233. *>
  234. *>
  235. *> We then consider Rectangular Full Packed (RFP) Format when N is
  236. *> odd. We give an example where N = 5.
  237. *>
  238. *> AP is Upper AP is Lower
  239. *>
  240. *> 00 01 02 03 04 00
  241. *> 11 12 13 14 10 11
  242. *> 22 23 24 20 21 22
  243. *> 33 34 30 31 32 33
  244. *> 44 40 41 42 43 44
  245. *>
  246. *>
  247. *> Let TRANSR = 'N'. RFP holds AP as follows:
  248. *> For UPLO = 'U' the upper trapezoid A(0:4,0:2) consists of the last
  249. *> three columns of AP upper. The lower triangle A(3:4,0:1) consists of
  250. *> the transpose of the first two columns of AP upper.
  251. *> For UPLO = 'L' the lower trapezoid A(0:4,0:2) consists of the first
  252. *> three columns of AP lower. The upper triangle A(0:1,1:2) consists of
  253. *> the transpose of the last two columns of AP lower.
  254. *> This covers the case N odd and TRANSR = 'N'.
  255. *>
  256. *> RFP A RFP A
  257. *>
  258. *> 02 03 04 00 33 43
  259. *> 12 13 14 10 11 44
  260. *> 22 23 24 20 21 22
  261. *> 00 33 34 30 31 32
  262. *> 01 11 44 40 41 42
  263. *>
  264. *> Now let TRANSR = 'T'. RFP A in both UPLO cases is just the
  265. *> transpose of RFP A above. One therefore gets:
  266. *>
  267. *> RFP A RFP A
  268. *>
  269. *> 02 12 22 00 01 00 10 20 30 40 50
  270. *> 03 13 23 33 11 33 11 21 31 41 51
  271. *> 04 14 24 34 44 43 44 22 32 42 52
  272. *> \endverbatim
  273. *
  274. * =====================================================================
  275. SUBROUTINE STFSM( TRANSR, SIDE, UPLO, TRANS, DIAG, M, N, ALPHA, A,
  276. $ B, LDB )
  277. *
  278. * -- LAPACK computational routine --
  279. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  280. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  281. *
  282. * .. Scalar Arguments ..
  283. CHARACTER TRANSR, DIAG, SIDE, TRANS, UPLO
  284. INTEGER LDB, M, N
  285. REAL ALPHA
  286. * ..
  287. * .. Array Arguments ..
  288. REAL A( 0: * ), B( 0: LDB-1, 0: * )
  289. * ..
  290. *
  291. * =====================================================================
  292. *
  293. * ..
  294. * .. Parameters ..
  295. REAL ONE, ZERO
  296. PARAMETER ( ONE = 1.0E+0, ZERO = 0.0E+0 )
  297. * ..
  298. * .. Local Scalars ..
  299. LOGICAL LOWER, LSIDE, MISODD, NISODD, NORMALTRANSR,
  300. $ NOTRANS
  301. INTEGER M1, M2, N1, N2, K, INFO, I, J
  302. * ..
  303. * .. External Functions ..
  304. LOGICAL LSAME
  305. EXTERNAL LSAME
  306. * ..
  307. * .. External Subroutines ..
  308. EXTERNAL SGEMM, STRSM, XERBLA
  309. * ..
  310. * .. Intrinsic Functions ..
  311. INTRINSIC MAX, MOD
  312. * ..
  313. * .. Executable Statements ..
  314. *
  315. * Test the input parameters.
  316. *
  317. INFO = 0
  318. NORMALTRANSR = LSAME( TRANSR, 'N' )
  319. LSIDE = LSAME( SIDE, 'L' )
  320. LOWER = LSAME( UPLO, 'L' )
  321. NOTRANS = LSAME( TRANS, 'N' )
  322. IF( .NOT.NORMALTRANSR .AND. .NOT.LSAME( TRANSR, 'T' ) ) THEN
  323. INFO = -1
  324. ELSE IF( .NOT.LSIDE .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN
  325. INFO = -2
  326. ELSE IF( .NOT.LOWER .AND. .NOT.LSAME( UPLO, 'U' ) ) THEN
  327. INFO = -3
  328. ELSE IF( .NOT.NOTRANS .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN
  329. INFO = -4
  330. ELSE IF( .NOT.LSAME( DIAG, 'N' ) .AND. .NOT.LSAME( DIAG, 'U' ) )
  331. $ THEN
  332. INFO = -5
  333. ELSE IF( M.LT.0 ) THEN
  334. INFO = -6
  335. ELSE IF( N.LT.0 ) THEN
  336. INFO = -7
  337. ELSE IF( LDB.LT.MAX( 1, M ) ) THEN
  338. INFO = -11
  339. END IF
  340. IF( INFO.NE.0 ) THEN
  341. CALL XERBLA( 'STFSM ', -INFO )
  342. RETURN
  343. END IF
  344. *
  345. * Quick return when ( (N.EQ.0).OR.(M.EQ.0) )
  346. *
  347. IF( ( M.EQ.0 ) .OR. ( N.EQ.0 ) )
  348. $ RETURN
  349. *
  350. * Quick return when ALPHA.EQ.(0D+0)
  351. *
  352. IF( ALPHA.EQ.ZERO ) THEN
  353. DO 20 J = 0, N - 1
  354. DO 10 I = 0, M - 1
  355. B( I, J ) = ZERO
  356. 10 CONTINUE
  357. 20 CONTINUE
  358. RETURN
  359. END IF
  360. *
  361. IF( LSIDE ) THEN
  362. *
  363. * SIDE = 'L'
  364. *
  365. * A is M-by-M.
  366. * If M is odd, set NISODD = .TRUE., and M1 and M2.
  367. * If M is even, NISODD = .FALSE., and M.
  368. *
  369. IF( MOD( M, 2 ).EQ.0 ) THEN
  370. MISODD = .FALSE.
  371. K = M / 2
  372. ELSE
  373. MISODD = .TRUE.
  374. IF( LOWER ) THEN
  375. M2 = M / 2
  376. M1 = M - M2
  377. ELSE
  378. M1 = M / 2
  379. M2 = M - M1
  380. END IF
  381. END IF
  382. *
  383. IF( MISODD ) THEN
  384. *
  385. * SIDE = 'L' and N is odd
  386. *
  387. IF( NORMALTRANSR ) THEN
  388. *
  389. * SIDE = 'L', N is odd, and TRANSR = 'N'
  390. *
  391. IF( LOWER ) THEN
  392. *
  393. * SIDE ='L', N is odd, TRANSR = 'N', and UPLO = 'L'
  394. *
  395. IF( NOTRANS ) THEN
  396. *
  397. * SIDE ='L', N is odd, TRANSR = 'N', UPLO = 'L', and
  398. * TRANS = 'N'
  399. *
  400. IF( M.EQ.1 ) THEN
  401. CALL STRSM( 'L', 'L', 'N', DIAG, M1, N, ALPHA,
  402. $ A, M, B, LDB )
  403. ELSE
  404. CALL STRSM( 'L', 'L', 'N', DIAG, M1, N, ALPHA,
  405. $ A( 0 ), M, B, LDB )
  406. CALL SGEMM( 'N', 'N', M2, N, M1, -ONE, A( M1 ),
  407. $ M, B, LDB, ALPHA, B( M1, 0 ), LDB )
  408. CALL STRSM( 'L', 'U', 'T', DIAG, M2, N, ONE,
  409. $ A( M ), M, B( M1, 0 ), LDB )
  410. END IF
  411. *
  412. ELSE
  413. *
  414. * SIDE ='L', N is odd, TRANSR = 'N', UPLO = 'L', and
  415. * TRANS = 'T'
  416. *
  417. IF( M.EQ.1 ) THEN
  418. CALL STRSM( 'L', 'L', 'T', DIAG, M1, N, ALPHA,
  419. $ A( 0 ), M, B, LDB )
  420. ELSE
  421. CALL STRSM( 'L', 'U', 'N', DIAG, M2, N, ALPHA,
  422. $ A( M ), M, B( M1, 0 ), LDB )
  423. CALL SGEMM( 'T', 'N', M1, N, M2, -ONE, A( M1 ),
  424. $ M, B( M1, 0 ), LDB, ALPHA, B, LDB )
  425. CALL STRSM( 'L', 'L', 'T', DIAG, M1, N, ONE,
  426. $ A( 0 ), M, B, LDB )
  427. END IF
  428. *
  429. END IF
  430. *
  431. ELSE
  432. *
  433. * SIDE ='L', N is odd, TRANSR = 'N', and UPLO = 'U'
  434. *
  435. IF( .NOT.NOTRANS ) THEN
  436. *
  437. * SIDE ='L', N is odd, TRANSR = 'N', UPLO = 'U', and
  438. * TRANS = 'N'
  439. *
  440. CALL STRSM( 'L', 'L', 'N', DIAG, M1, N, ALPHA,
  441. $ A( M2 ), M, B, LDB )
  442. CALL SGEMM( 'T', 'N', M2, N, M1, -ONE, A( 0 ), M,
  443. $ B, LDB, ALPHA, B( M1, 0 ), LDB )
  444. CALL STRSM( 'L', 'U', 'T', DIAG, M2, N, ONE,
  445. $ A( M1 ), M, B( M1, 0 ), LDB )
  446. *
  447. ELSE
  448. *
  449. * SIDE ='L', N is odd, TRANSR = 'N', UPLO = 'U', and
  450. * TRANS = 'T'
  451. *
  452. CALL STRSM( 'L', 'U', 'N', DIAG, M2, N, ALPHA,
  453. $ A( M1 ), M, B( M1, 0 ), LDB )
  454. CALL SGEMM( 'N', 'N', M1, N, M2, -ONE, A( 0 ), M,
  455. $ B( M1, 0 ), LDB, ALPHA, B, LDB )
  456. CALL STRSM( 'L', 'L', 'T', DIAG, M1, N, ONE,
  457. $ A( M2 ), M, B, LDB )
  458. *
  459. END IF
  460. *
  461. END IF
  462. *
  463. ELSE
  464. *
  465. * SIDE = 'L', N is odd, and TRANSR = 'T'
  466. *
  467. IF( LOWER ) THEN
  468. *
  469. * SIDE ='L', N is odd, TRANSR = 'T', and UPLO = 'L'
  470. *
  471. IF( NOTRANS ) THEN
  472. *
  473. * SIDE ='L', N is odd, TRANSR = 'T', UPLO = 'L', and
  474. * TRANS = 'N'
  475. *
  476. IF( M.EQ.1 ) THEN
  477. CALL STRSM( 'L', 'U', 'T', DIAG, M1, N, ALPHA,
  478. $ A( 0 ), M1, B, LDB )
  479. ELSE
  480. CALL STRSM( 'L', 'U', 'T', DIAG, M1, N, ALPHA,
  481. $ A( 0 ), M1, B, LDB )
  482. CALL SGEMM( 'T', 'N', M2, N, M1, -ONE,
  483. $ A( M1*M1 ), M1, B, LDB, ALPHA,
  484. $ B( M1, 0 ), LDB )
  485. CALL STRSM( 'L', 'L', 'N', DIAG, M2, N, ONE,
  486. $ A( 1 ), M1, B( M1, 0 ), LDB )
  487. END IF
  488. *
  489. ELSE
  490. *
  491. * SIDE ='L', N is odd, TRANSR = 'T', UPLO = 'L', and
  492. * TRANS = 'T'
  493. *
  494. IF( M.EQ.1 ) THEN
  495. CALL STRSM( 'L', 'U', 'N', DIAG, M1, N, ALPHA,
  496. $ A( 0 ), M1, B, LDB )
  497. ELSE
  498. CALL STRSM( 'L', 'L', 'T', DIAG, M2, N, ALPHA,
  499. $ A( 1 ), M1, B( M1, 0 ), LDB )
  500. CALL SGEMM( 'N', 'N', M1, N, M2, -ONE,
  501. $ A( M1*M1 ), M1, B( M1, 0 ), LDB,
  502. $ ALPHA, B, LDB )
  503. CALL STRSM( 'L', 'U', 'N', DIAG, M1, N, ONE,
  504. $ A( 0 ), M1, B, LDB )
  505. END IF
  506. *
  507. END IF
  508. *
  509. ELSE
  510. *
  511. * SIDE ='L', N is odd, TRANSR = 'T', and UPLO = 'U'
  512. *
  513. IF( .NOT.NOTRANS ) THEN
  514. *
  515. * SIDE ='L', N is odd, TRANSR = 'T', UPLO = 'U', and
  516. * TRANS = 'N'
  517. *
  518. CALL STRSM( 'L', 'U', 'T', DIAG, M1, N, ALPHA,
  519. $ A( M2*M2 ), M2, B, LDB )
  520. CALL SGEMM( 'N', 'N', M2, N, M1, -ONE, A( 0 ), M2,
  521. $ B, LDB, ALPHA, B( M1, 0 ), LDB )
  522. CALL STRSM( 'L', 'L', 'N', DIAG, M2, N, ONE,
  523. $ A( M1*M2 ), M2, B( M1, 0 ), LDB )
  524. *
  525. ELSE
  526. *
  527. * SIDE ='L', N is odd, TRANSR = 'T', UPLO = 'U', and
  528. * TRANS = 'T'
  529. *
  530. CALL STRSM( 'L', 'L', 'T', DIAG, M2, N, ALPHA,
  531. $ A( M1*M2 ), M2, B( M1, 0 ), LDB )
  532. CALL SGEMM( 'T', 'N', M1, N, M2, -ONE, A( 0 ), M2,
  533. $ B( M1, 0 ), LDB, ALPHA, B, LDB )
  534. CALL STRSM( 'L', 'U', 'N', DIAG, M1, N, ONE,
  535. $ A( M2*M2 ), M2, B, LDB )
  536. *
  537. END IF
  538. *
  539. END IF
  540. *
  541. END IF
  542. *
  543. ELSE
  544. *
  545. * SIDE = 'L' and N is even
  546. *
  547. IF( NORMALTRANSR ) THEN
  548. *
  549. * SIDE = 'L', N is even, and TRANSR = 'N'
  550. *
  551. IF( LOWER ) THEN
  552. *
  553. * SIDE ='L', N is even, TRANSR = 'N', and UPLO = 'L'
  554. *
  555. IF( NOTRANS ) THEN
  556. *
  557. * SIDE ='L', N is even, TRANSR = 'N', UPLO = 'L',
  558. * and TRANS = 'N'
  559. *
  560. CALL STRSM( 'L', 'L', 'N', DIAG, K, N, ALPHA,
  561. $ A( 1 ), M+1, B, LDB )
  562. CALL SGEMM( 'N', 'N', K, N, K, -ONE, A( K+1 ),
  563. $ M+1, B, LDB, ALPHA, B( K, 0 ), LDB )
  564. CALL STRSM( 'L', 'U', 'T', DIAG, K, N, ONE,
  565. $ A( 0 ), M+1, B( K, 0 ), LDB )
  566. *
  567. ELSE
  568. *
  569. * SIDE ='L', N is even, TRANSR = 'N', UPLO = 'L',
  570. * and TRANS = 'T'
  571. *
  572. CALL STRSM( 'L', 'U', 'N', DIAG, K, N, ALPHA,
  573. $ A( 0 ), M+1, B( K, 0 ), LDB )
  574. CALL SGEMM( 'T', 'N', K, N, K, -ONE, A( K+1 ),
  575. $ M+1, B( K, 0 ), LDB, ALPHA, B, LDB )
  576. CALL STRSM( 'L', 'L', 'T', DIAG, K, N, ONE,
  577. $ A( 1 ), M+1, B, LDB )
  578. *
  579. END IF
  580. *
  581. ELSE
  582. *
  583. * SIDE ='L', N is even, TRANSR = 'N', and UPLO = 'U'
  584. *
  585. IF( .NOT.NOTRANS ) THEN
  586. *
  587. * SIDE ='L', N is even, TRANSR = 'N', UPLO = 'U',
  588. * and TRANS = 'N'
  589. *
  590. CALL STRSM( 'L', 'L', 'N', DIAG, K, N, ALPHA,
  591. $ A( K+1 ), M+1, B, LDB )
  592. CALL SGEMM( 'T', 'N', K, N, K, -ONE, A( 0 ), M+1,
  593. $ B, LDB, ALPHA, B( K, 0 ), LDB )
  594. CALL STRSM( 'L', 'U', 'T', DIAG, K, N, ONE,
  595. $ A( K ), M+1, B( K, 0 ), LDB )
  596. *
  597. ELSE
  598. *
  599. * SIDE ='L', N is even, TRANSR = 'N', UPLO = 'U',
  600. * and TRANS = 'T'
  601. CALL STRSM( 'L', 'U', 'N', DIAG, K, N, ALPHA,
  602. $ A( K ), M+1, B( K, 0 ), LDB )
  603. CALL SGEMM( 'N', 'N', K, N, K, -ONE, A( 0 ), M+1,
  604. $ B( K, 0 ), LDB, ALPHA, B, LDB )
  605. CALL STRSM( 'L', 'L', 'T', DIAG, K, N, ONE,
  606. $ A( K+1 ), M+1, B, LDB )
  607. *
  608. END IF
  609. *
  610. END IF
  611. *
  612. ELSE
  613. *
  614. * SIDE = 'L', N is even, and TRANSR = 'T'
  615. *
  616. IF( LOWER ) THEN
  617. *
  618. * SIDE ='L', N is even, TRANSR = 'T', and UPLO = 'L'
  619. *
  620. IF( NOTRANS ) THEN
  621. *
  622. * SIDE ='L', N is even, TRANSR = 'T', UPLO = 'L',
  623. * and TRANS = 'N'
  624. *
  625. CALL STRSM( 'L', 'U', 'T', DIAG, K, N, ALPHA,
  626. $ A( K ), K, B, LDB )
  627. CALL SGEMM( 'T', 'N', K, N, K, -ONE,
  628. $ A( K*( K+1 ) ), K, B, LDB, ALPHA,
  629. $ B( K, 0 ), LDB )
  630. CALL STRSM( 'L', 'L', 'N', DIAG, K, N, ONE,
  631. $ A( 0 ), K, B( K, 0 ), LDB )
  632. *
  633. ELSE
  634. *
  635. * SIDE ='L', N is even, TRANSR = 'T', UPLO = 'L',
  636. * and TRANS = 'T'
  637. *
  638. CALL STRSM( 'L', 'L', 'T', DIAG, K, N, ALPHA,
  639. $ A( 0 ), K, B( K, 0 ), LDB )
  640. CALL SGEMM( 'N', 'N', K, N, K, -ONE,
  641. $ A( K*( K+1 ) ), K, B( K, 0 ), LDB,
  642. $ ALPHA, B, LDB )
  643. CALL STRSM( 'L', 'U', 'N', DIAG, K, N, ONE,
  644. $ A( K ), K, B, LDB )
  645. *
  646. END IF
  647. *
  648. ELSE
  649. *
  650. * SIDE ='L', N is even, TRANSR = 'T', and UPLO = 'U'
  651. *
  652. IF( .NOT.NOTRANS ) THEN
  653. *
  654. * SIDE ='L', N is even, TRANSR = 'T', UPLO = 'U',
  655. * and TRANS = 'N'
  656. *
  657. CALL STRSM( 'L', 'U', 'T', DIAG, K, N, ALPHA,
  658. $ A( K*( K+1 ) ), K, B, LDB )
  659. CALL SGEMM( 'N', 'N', K, N, K, -ONE, A( 0 ), K, B,
  660. $ LDB, ALPHA, B( K, 0 ), LDB )
  661. CALL STRSM( 'L', 'L', 'N', DIAG, K, N, ONE,
  662. $ A( K*K ), K, B( K, 0 ), LDB )
  663. *
  664. ELSE
  665. *
  666. * SIDE ='L', N is even, TRANSR = 'T', UPLO = 'U',
  667. * and TRANS = 'T'
  668. *
  669. CALL STRSM( 'L', 'L', 'T', DIAG, K, N, ALPHA,
  670. $ A( K*K ), K, B( K, 0 ), LDB )
  671. CALL SGEMM( 'T', 'N', K, N, K, -ONE, A( 0 ), K,
  672. $ B( K, 0 ), LDB, ALPHA, B, LDB )
  673. CALL STRSM( 'L', 'U', 'N', DIAG, K, N, ONE,
  674. $ A( K*( K+1 ) ), K, B, LDB )
  675. *
  676. END IF
  677. *
  678. END IF
  679. *
  680. END IF
  681. *
  682. END IF
  683. *
  684. ELSE
  685. *
  686. * SIDE = 'R'
  687. *
  688. * A is N-by-N.
  689. * If N is odd, set NISODD = .TRUE., and N1 and N2.
  690. * If N is even, NISODD = .FALSE., and K.
  691. *
  692. IF( MOD( N, 2 ).EQ.0 ) THEN
  693. NISODD = .FALSE.
  694. K = N / 2
  695. ELSE
  696. NISODD = .TRUE.
  697. IF( LOWER ) THEN
  698. N2 = N / 2
  699. N1 = N - N2
  700. ELSE
  701. N1 = N / 2
  702. N2 = N - N1
  703. END IF
  704. END IF
  705. *
  706. IF( NISODD ) THEN
  707. *
  708. * SIDE = 'R' and N is odd
  709. *
  710. IF( NORMALTRANSR ) THEN
  711. *
  712. * SIDE = 'R', N is odd, and TRANSR = 'N'
  713. *
  714. IF( LOWER ) THEN
  715. *
  716. * SIDE ='R', N is odd, TRANSR = 'N', and UPLO = 'L'
  717. *
  718. IF( NOTRANS ) THEN
  719. *
  720. * SIDE ='R', N is odd, TRANSR = 'N', UPLO = 'L', and
  721. * TRANS = 'N'
  722. *
  723. CALL STRSM( 'R', 'U', 'T', DIAG, M, N2, ALPHA,
  724. $ A( N ), N, B( 0, N1 ), LDB )
  725. CALL SGEMM( 'N', 'N', M, N1, N2, -ONE, B( 0, N1 ),
  726. $ LDB, A( N1 ), N, ALPHA, B( 0, 0 ),
  727. $ LDB )
  728. CALL STRSM( 'R', 'L', 'N', DIAG, M, N1, ONE,
  729. $ A( 0 ), N, B( 0, 0 ), LDB )
  730. *
  731. ELSE
  732. *
  733. * SIDE ='R', N is odd, TRANSR = 'N', UPLO = 'L', and
  734. * TRANS = 'T'
  735. *
  736. CALL STRSM( 'R', 'L', 'T', DIAG, M, N1, ALPHA,
  737. $ A( 0 ), N, B( 0, 0 ), LDB )
  738. CALL SGEMM( 'N', 'T', M, N2, N1, -ONE, B( 0, 0 ),
  739. $ LDB, A( N1 ), N, ALPHA, B( 0, N1 ),
  740. $ LDB )
  741. CALL STRSM( 'R', 'U', 'N', DIAG, M, N2, ONE,
  742. $ A( N ), N, B( 0, N1 ), LDB )
  743. *
  744. END IF
  745. *
  746. ELSE
  747. *
  748. * SIDE ='R', N is odd, TRANSR = 'N', and UPLO = 'U'
  749. *
  750. IF( NOTRANS ) THEN
  751. *
  752. * SIDE ='R', N is odd, TRANSR = 'N', UPLO = 'U', and
  753. * TRANS = 'N'
  754. *
  755. CALL STRSM( 'R', 'L', 'T', DIAG, M, N1, ALPHA,
  756. $ A( N2 ), N, B( 0, 0 ), LDB )
  757. CALL SGEMM( 'N', 'N', M, N2, N1, -ONE, B( 0, 0 ),
  758. $ LDB, A( 0 ), N, ALPHA, B( 0, N1 ),
  759. $ LDB )
  760. CALL STRSM( 'R', 'U', 'N', DIAG, M, N2, ONE,
  761. $ A( N1 ), N, B( 0, N1 ), LDB )
  762. *
  763. ELSE
  764. *
  765. * SIDE ='R', N is odd, TRANSR = 'N', UPLO = 'U', and
  766. * TRANS = 'T'
  767. *
  768. CALL STRSM( 'R', 'U', 'T', DIAG, M, N2, ALPHA,
  769. $ A( N1 ), N, B( 0, N1 ), LDB )
  770. CALL SGEMM( 'N', 'T', M, N1, N2, -ONE, B( 0, N1 ),
  771. $ LDB, A( 0 ), N, ALPHA, B( 0, 0 ), LDB )
  772. CALL STRSM( 'R', 'L', 'N', DIAG, M, N1, ONE,
  773. $ A( N2 ), N, B( 0, 0 ), LDB )
  774. *
  775. END IF
  776. *
  777. END IF
  778. *
  779. ELSE
  780. *
  781. * SIDE = 'R', N is odd, and TRANSR = 'T'
  782. *
  783. IF( LOWER ) THEN
  784. *
  785. * SIDE ='R', N is odd, TRANSR = 'T', and UPLO = 'L'
  786. *
  787. IF( NOTRANS ) THEN
  788. *
  789. * SIDE ='R', N is odd, TRANSR = 'T', UPLO = 'L', and
  790. * TRANS = 'N'
  791. *
  792. CALL STRSM( 'R', 'L', 'N', DIAG, M, N2, ALPHA,
  793. $ A( 1 ), N1, B( 0, N1 ), LDB )
  794. CALL SGEMM( 'N', 'T', M, N1, N2, -ONE, B( 0, N1 ),
  795. $ LDB, A( N1*N1 ), N1, ALPHA, B( 0, 0 ),
  796. $ LDB )
  797. CALL STRSM( 'R', 'U', 'T', DIAG, M, N1, ONE,
  798. $ A( 0 ), N1, B( 0, 0 ), LDB )
  799. *
  800. ELSE
  801. *
  802. * SIDE ='R', N is odd, TRANSR = 'T', UPLO = 'L', and
  803. * TRANS = 'T'
  804. *
  805. CALL STRSM( 'R', 'U', 'N', DIAG, M, N1, ALPHA,
  806. $ A( 0 ), N1, B( 0, 0 ), LDB )
  807. CALL SGEMM( 'N', 'N', M, N2, N1, -ONE, B( 0, 0 ),
  808. $ LDB, A( N1*N1 ), N1, ALPHA, B( 0, N1 ),
  809. $ LDB )
  810. CALL STRSM( 'R', 'L', 'T', DIAG, M, N2, ONE,
  811. $ A( 1 ), N1, B( 0, N1 ), LDB )
  812. *
  813. END IF
  814. *
  815. ELSE
  816. *
  817. * SIDE ='R', N is odd, TRANSR = 'T', and UPLO = 'U'
  818. *
  819. IF( NOTRANS ) THEN
  820. *
  821. * SIDE ='R', N is odd, TRANSR = 'T', UPLO = 'U', and
  822. * TRANS = 'N'
  823. *
  824. CALL STRSM( 'R', 'U', 'N', DIAG, M, N1, ALPHA,
  825. $ A( N2*N2 ), N2, B( 0, 0 ), LDB )
  826. CALL SGEMM( 'N', 'T', M, N2, N1, -ONE, B( 0, 0 ),
  827. $ LDB, A( 0 ), N2, ALPHA, B( 0, N1 ),
  828. $ LDB )
  829. CALL STRSM( 'R', 'L', 'T', DIAG, M, N2, ONE,
  830. $ A( N1*N2 ), N2, B( 0, N1 ), LDB )
  831. *
  832. ELSE
  833. *
  834. * SIDE ='R', N is odd, TRANSR = 'T', UPLO = 'U', and
  835. * TRANS = 'T'
  836. *
  837. CALL STRSM( 'R', 'L', 'N', DIAG, M, N2, ALPHA,
  838. $ A( N1*N2 ), N2, B( 0, N1 ), LDB )
  839. CALL SGEMM( 'N', 'N', M, N1, N2, -ONE, B( 0, N1 ),
  840. $ LDB, A( 0 ), N2, ALPHA, B( 0, 0 ),
  841. $ LDB )
  842. CALL STRSM( 'R', 'U', 'T', DIAG, M, N1, ONE,
  843. $ A( N2*N2 ), N2, B( 0, 0 ), LDB )
  844. *
  845. END IF
  846. *
  847. END IF
  848. *
  849. END IF
  850. *
  851. ELSE
  852. *
  853. * SIDE = 'R' and N is even
  854. *
  855. IF( NORMALTRANSR ) THEN
  856. *
  857. * SIDE = 'R', N is even, and TRANSR = 'N'
  858. *
  859. IF( LOWER ) THEN
  860. *
  861. * SIDE ='R', N is even, TRANSR = 'N', and UPLO = 'L'
  862. *
  863. IF( NOTRANS ) THEN
  864. *
  865. * SIDE ='R', N is even, TRANSR = 'N', UPLO = 'L',
  866. * and TRANS = 'N'
  867. *
  868. CALL STRSM( 'R', 'U', 'T', DIAG, M, K, ALPHA,
  869. $ A( 0 ), N+1, B( 0, K ), LDB )
  870. CALL SGEMM( 'N', 'N', M, K, K, -ONE, B( 0, K ),
  871. $ LDB, A( K+1 ), N+1, ALPHA, B( 0, 0 ),
  872. $ LDB )
  873. CALL STRSM( 'R', 'L', 'N', DIAG, M, K, ONE,
  874. $ A( 1 ), N+1, B( 0, 0 ), LDB )
  875. *
  876. ELSE
  877. *
  878. * SIDE ='R', N is even, TRANSR = 'N', UPLO = 'L',
  879. * and TRANS = 'T'
  880. *
  881. CALL STRSM( 'R', 'L', 'T', DIAG, M, K, ALPHA,
  882. $ A( 1 ), N+1, B( 0, 0 ), LDB )
  883. CALL SGEMM( 'N', 'T', M, K, K, -ONE, B( 0, 0 ),
  884. $ LDB, A( K+1 ), N+1, ALPHA, B( 0, K ),
  885. $ LDB )
  886. CALL STRSM( 'R', 'U', 'N', DIAG, M, K, ONE,
  887. $ A( 0 ), N+1, B( 0, K ), LDB )
  888. *
  889. END IF
  890. *
  891. ELSE
  892. *
  893. * SIDE ='R', N is even, TRANSR = 'N', and UPLO = 'U'
  894. *
  895. IF( NOTRANS ) THEN
  896. *
  897. * SIDE ='R', N is even, TRANSR = 'N', UPLO = 'U',
  898. * and TRANS = 'N'
  899. *
  900. CALL STRSM( 'R', 'L', 'T', DIAG, M, K, ALPHA,
  901. $ A( K+1 ), N+1, B( 0, 0 ), LDB )
  902. CALL SGEMM( 'N', 'N', M, K, K, -ONE, B( 0, 0 ),
  903. $ LDB, A( 0 ), N+1, ALPHA, B( 0, K ),
  904. $ LDB )
  905. CALL STRSM( 'R', 'U', 'N', DIAG, M, K, ONE,
  906. $ A( K ), N+1, B( 0, K ), LDB )
  907. *
  908. ELSE
  909. *
  910. * SIDE ='R', N is even, TRANSR = 'N', UPLO = 'U',
  911. * and TRANS = 'T'
  912. *
  913. CALL STRSM( 'R', 'U', 'T', DIAG, M, K, ALPHA,
  914. $ A( K ), N+1, B( 0, K ), LDB )
  915. CALL SGEMM( 'N', 'T', M, K, K, -ONE, B( 0, K ),
  916. $ LDB, A( 0 ), N+1, ALPHA, B( 0, 0 ),
  917. $ LDB )
  918. CALL STRSM( 'R', 'L', 'N', DIAG, M, K, ONE,
  919. $ A( K+1 ), N+1, B( 0, 0 ), LDB )
  920. *
  921. END IF
  922. *
  923. END IF
  924. *
  925. ELSE
  926. *
  927. * SIDE = 'R', N is even, and TRANSR = 'T'
  928. *
  929. IF( LOWER ) THEN
  930. *
  931. * SIDE ='R', N is even, TRANSR = 'T', and UPLO = 'L'
  932. *
  933. IF( NOTRANS ) THEN
  934. *
  935. * SIDE ='R', N is even, TRANSR = 'T', UPLO = 'L',
  936. * and TRANS = 'N'
  937. *
  938. CALL STRSM( 'R', 'L', 'N', DIAG, M, K, ALPHA,
  939. $ A( 0 ), K, B( 0, K ), LDB )
  940. CALL SGEMM( 'N', 'T', M, K, K, -ONE, B( 0, K ),
  941. $ LDB, A( ( K+1 )*K ), K, ALPHA,
  942. $ B( 0, 0 ), LDB )
  943. CALL STRSM( 'R', 'U', 'T', DIAG, M, K, ONE,
  944. $ A( K ), K, B( 0, 0 ), LDB )
  945. *
  946. ELSE
  947. *
  948. * SIDE ='R', N is even, TRANSR = 'T', UPLO = 'L',
  949. * and TRANS = 'T'
  950. *
  951. CALL STRSM( 'R', 'U', 'N', DIAG, M, K, ALPHA,
  952. $ A( K ), K, B( 0, 0 ), LDB )
  953. CALL SGEMM( 'N', 'N', M, K, K, -ONE, B( 0, 0 ),
  954. $ LDB, A( ( K+1 )*K ), K, ALPHA,
  955. $ B( 0, K ), LDB )
  956. CALL STRSM( 'R', 'L', 'T', DIAG, M, K, ONE,
  957. $ A( 0 ), K, B( 0, K ), LDB )
  958. *
  959. END IF
  960. *
  961. ELSE
  962. *
  963. * SIDE ='R', N is even, TRANSR = 'T', and UPLO = 'U'
  964. *
  965. IF( NOTRANS ) THEN
  966. *
  967. * SIDE ='R', N is even, TRANSR = 'T', UPLO = 'U',
  968. * and TRANS = 'N'
  969. *
  970. CALL STRSM( 'R', 'U', 'N', DIAG, M, K, ALPHA,
  971. $ A( ( K+1 )*K ), K, B( 0, 0 ), LDB )
  972. CALL SGEMM( 'N', 'T', M, K, K, -ONE, B( 0, 0 ),
  973. $ LDB, A( 0 ), K, ALPHA, B( 0, K ), LDB )
  974. CALL STRSM( 'R', 'L', 'T', DIAG, M, K, ONE,
  975. $ A( K*K ), K, B( 0, K ), LDB )
  976. *
  977. ELSE
  978. *
  979. * SIDE ='R', N is even, TRANSR = 'T', UPLO = 'U',
  980. * and TRANS = 'T'
  981. *
  982. CALL STRSM( 'R', 'L', 'N', DIAG, M, K, ALPHA,
  983. $ A( K*K ), K, B( 0, K ), LDB )
  984. CALL SGEMM( 'N', 'N', M, K, K, -ONE, B( 0, K ),
  985. $ LDB, A( 0 ), K, ALPHA, B( 0, 0 ), LDB )
  986. CALL STRSM( 'R', 'U', 'T', DIAG, M, K, ONE,
  987. $ A( ( K+1 )*K ), K, B( 0, 0 ), LDB )
  988. *
  989. END IF
  990. *
  991. END IF
  992. *
  993. END IF
  994. *
  995. END IF
  996. END IF
  997. *
  998. RETURN
  999. *
  1000. * End of STFSM
  1001. *
  1002. END