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.

dtfsm.f 35 kB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. *> \brief \b DTFSM 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 DTFSM + dependencies
  10. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dtfsm.f">
  11. *> [TGZ]</a>
  12. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dtfsm.f">
  13. *> [ZIP]</a>
  14. *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtfsm.f">
  15. *> [TXT]</a>
  16. *> \endhtmlonly
  17. *
  18. * Definition:
  19. * ===========
  20. *
  21. * SUBROUTINE DTFSM( 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. * DOUBLE PRECISION ALPHA
  28. * ..
  29. * .. Array Arguments ..
  30. * DOUBLE PRECISION 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. *> DTFSM 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 DOUBLE PRECISION
  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 DOUBLE PRECISION 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 DOUBLE PRECISION 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. *> \date December 2016
  186. *
  187. *> \ingroup doubleOTHERcomputational
  188. *
  189. *> \par Further Details:
  190. * =====================
  191. *>
  192. *> \verbatim
  193. *>
  194. *> We first consider Rectangular Full Packed (RFP) Format when N is
  195. *> even. We give an example where N = 6.
  196. *>
  197. *> AP is Upper AP is Lower
  198. *>
  199. *> 00 01 02 03 04 05 00
  200. *> 11 12 13 14 15 10 11
  201. *> 22 23 24 25 20 21 22
  202. *> 33 34 35 30 31 32 33
  203. *> 44 45 40 41 42 43 44
  204. *> 55 50 51 52 53 54 55
  205. *>
  206. *>
  207. *> Let TRANSR = 'N'. RFP holds AP as follows:
  208. *> For UPLO = 'U' the upper trapezoid A(0:5,0:2) consists of the last
  209. *> three columns of AP upper. The lower triangle A(4:6,0:2) consists of
  210. *> the transpose of the first three columns of AP upper.
  211. *> For UPLO = 'L' the lower trapezoid A(1:6,0:2) consists of the first
  212. *> three columns of AP lower. The upper triangle A(0:2,0:2) consists of
  213. *> the transpose of the last three columns of AP lower.
  214. *> This covers the case N even and TRANSR = 'N'.
  215. *>
  216. *> RFP A RFP A
  217. *>
  218. *> 03 04 05 33 43 53
  219. *> 13 14 15 00 44 54
  220. *> 23 24 25 10 11 55
  221. *> 33 34 35 20 21 22
  222. *> 00 44 45 30 31 32
  223. *> 01 11 55 40 41 42
  224. *> 02 12 22 50 51 52
  225. *>
  226. *> Now let TRANSR = 'T'. RFP A in both UPLO cases is just the
  227. *> transpose of RFP A above. One therefore gets:
  228. *>
  229. *>
  230. *> RFP A RFP A
  231. *>
  232. *> 03 13 23 33 00 01 02 33 00 10 20 30 40 50
  233. *> 04 14 24 34 44 11 12 43 44 11 21 31 41 51
  234. *> 05 15 25 35 45 55 22 53 54 55 22 32 42 52
  235. *>
  236. *>
  237. *> We then consider Rectangular Full Packed (RFP) Format when N is
  238. *> odd. We give an example where N = 5.
  239. *>
  240. *> AP is Upper AP is Lower
  241. *>
  242. *> 00 01 02 03 04 00
  243. *> 11 12 13 14 10 11
  244. *> 22 23 24 20 21 22
  245. *> 33 34 30 31 32 33
  246. *> 44 40 41 42 43 44
  247. *>
  248. *>
  249. *> Let TRANSR = 'N'. RFP holds AP as follows:
  250. *> For UPLO = 'U' the upper trapezoid A(0:4,0:2) consists of the last
  251. *> three columns of AP upper. The lower triangle A(3:4,0:1) consists of
  252. *> the transpose of the first two columns of AP upper.
  253. *> For UPLO = 'L' the lower trapezoid A(0:4,0:2) consists of the first
  254. *> three columns of AP lower. The upper triangle A(0:1,1:2) consists of
  255. *> the transpose of the last two columns of AP lower.
  256. *> This covers the case N odd and TRANSR = 'N'.
  257. *>
  258. *> RFP A RFP A
  259. *>
  260. *> 02 03 04 00 33 43
  261. *> 12 13 14 10 11 44
  262. *> 22 23 24 20 21 22
  263. *> 00 33 34 30 31 32
  264. *> 01 11 44 40 41 42
  265. *>
  266. *> Now let TRANSR = 'T'. RFP A in both UPLO cases is just the
  267. *> transpose of RFP A above. One therefore gets:
  268. *>
  269. *> RFP A RFP A
  270. *>
  271. *> 02 12 22 00 01 00 10 20 30 40 50
  272. *> 03 13 23 33 11 33 11 21 31 41 51
  273. *> 04 14 24 34 44 43 44 22 32 42 52
  274. *> \endverbatim
  275. *
  276. * =====================================================================
  277. SUBROUTINE DTFSM( TRANSR, SIDE, UPLO, TRANS, DIAG, M, N, ALPHA, A,
  278. $ B, LDB )
  279. *
  280. * -- LAPACK computational routine (version 3.7.0) --
  281. * -- LAPACK is a software package provided by Univ. of Tennessee, --
  282. * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  283. * December 2016
  284. *
  285. * .. Scalar Arguments ..
  286. CHARACTER TRANSR, DIAG, SIDE, TRANS, UPLO
  287. INTEGER LDB, M, N
  288. DOUBLE PRECISION ALPHA
  289. * ..
  290. * .. Array Arguments ..
  291. DOUBLE PRECISION A( 0: * ), B( 0: LDB-1, 0: * )
  292. * ..
  293. *
  294. * =====================================================================
  295. *
  296. * ..
  297. * .. Parameters ..
  298. DOUBLE PRECISION ONE, ZERO
  299. PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
  300. * ..
  301. * .. Local Scalars ..
  302. LOGICAL LOWER, LSIDE, MISODD, NISODD, NORMALTRANSR,
  303. $ NOTRANS
  304. INTEGER M1, M2, N1, N2, K, INFO, I, J
  305. * ..
  306. * .. External Functions ..
  307. LOGICAL LSAME
  308. EXTERNAL LSAME
  309. * ..
  310. * .. External Subroutines ..
  311. EXTERNAL XERBLA, DGEMM, DTRSM
  312. * ..
  313. * .. Intrinsic Functions ..
  314. INTRINSIC MAX, MOD
  315. * ..
  316. * .. Executable Statements ..
  317. *
  318. * Test the input parameters.
  319. *
  320. INFO = 0
  321. NORMALTRANSR = LSAME( TRANSR, 'N' )
  322. LSIDE = LSAME( SIDE, 'L' )
  323. LOWER = LSAME( UPLO, 'L' )
  324. NOTRANS = LSAME( TRANS, 'N' )
  325. IF( .NOT.NORMALTRANSR .AND. .NOT.LSAME( TRANSR, 'T' ) ) THEN
  326. INFO = -1
  327. ELSE IF( .NOT.LSIDE .AND. .NOT.LSAME( SIDE, 'R' ) ) THEN
  328. INFO = -2
  329. ELSE IF( .NOT.LOWER .AND. .NOT.LSAME( UPLO, 'U' ) ) THEN
  330. INFO = -3
  331. ELSE IF( .NOT.NOTRANS .AND. .NOT.LSAME( TRANS, 'T' ) ) THEN
  332. INFO = -4
  333. ELSE IF( .NOT.LSAME( DIAG, 'N' ) .AND. .NOT.LSAME( DIAG, 'U' ) )
  334. $ THEN
  335. INFO = -5
  336. ELSE IF( M.LT.0 ) THEN
  337. INFO = -6
  338. ELSE IF( N.LT.0 ) THEN
  339. INFO = -7
  340. ELSE IF( LDB.LT.MAX( 1, M ) ) THEN
  341. INFO = -11
  342. END IF
  343. IF( INFO.NE.0 ) THEN
  344. CALL XERBLA( 'DTFSM ', -INFO )
  345. RETURN
  346. END IF
  347. *
  348. * Quick return when ( (N.EQ.0).OR.(M.EQ.0) )
  349. *
  350. IF( ( M.EQ.0 ) .OR. ( N.EQ.0 ) )
  351. $ RETURN
  352. *
  353. * Quick return when ALPHA.EQ.(0D+0)
  354. *
  355. IF( ALPHA.EQ.ZERO ) THEN
  356. DO 20 J = 0, N - 1
  357. DO 10 I = 0, M - 1
  358. B( I, J ) = ZERO
  359. 10 CONTINUE
  360. 20 CONTINUE
  361. RETURN
  362. END IF
  363. *
  364. IF( LSIDE ) THEN
  365. *
  366. * SIDE = 'L'
  367. *
  368. * A is M-by-M.
  369. * If M is odd, set NISODD = .TRUE., and M1 and M2.
  370. * If M is even, NISODD = .FALSE., and M.
  371. *
  372. IF( MOD( M, 2 ).EQ.0 ) THEN
  373. MISODD = .FALSE.
  374. K = M / 2
  375. ELSE
  376. MISODD = .TRUE.
  377. IF( LOWER ) THEN
  378. M2 = M / 2
  379. M1 = M - M2
  380. ELSE
  381. M1 = M / 2
  382. M2 = M - M1
  383. END IF
  384. END IF
  385. *
  386. *
  387. IF( MISODD ) THEN
  388. *
  389. * SIDE = 'L' and N is odd
  390. *
  391. IF( NORMALTRANSR ) THEN
  392. *
  393. * SIDE = 'L', N is odd, and TRANSR = 'N'
  394. *
  395. IF( LOWER ) THEN
  396. *
  397. * SIDE ='L', N is odd, TRANSR = 'N', and UPLO = 'L'
  398. *
  399. IF( NOTRANS ) THEN
  400. *
  401. * SIDE ='L', N is odd, TRANSR = 'N', UPLO = 'L', and
  402. * TRANS = 'N'
  403. *
  404. IF( M.EQ.1 ) THEN
  405. CALL DTRSM( 'L', 'L', 'N', DIAG, M1, N, ALPHA,
  406. $ A, M, B, LDB )
  407. ELSE
  408. CALL DTRSM( 'L', 'L', 'N', DIAG, M1, N, ALPHA,
  409. $ A( 0 ), M, B, LDB )
  410. CALL DGEMM( 'N', 'N', M2, N, M1, -ONE, A( M1 ),
  411. $ M, B, LDB, ALPHA, B( M1, 0 ), LDB )
  412. CALL DTRSM( 'L', 'U', 'T', DIAG, M2, N, ONE,
  413. $ A( M ), M, B( M1, 0 ), LDB )
  414. END IF
  415. *
  416. ELSE
  417. *
  418. * SIDE ='L', N is odd, TRANSR = 'N', UPLO = 'L', and
  419. * TRANS = 'T'
  420. *
  421. IF( M.EQ.1 ) THEN
  422. CALL DTRSM( 'L', 'L', 'T', DIAG, M1, N, ALPHA,
  423. $ A( 0 ), M, B, LDB )
  424. ELSE
  425. CALL DTRSM( 'L', 'U', 'N', DIAG, M2, N, ALPHA,
  426. $ A( M ), M, B( M1, 0 ), LDB )
  427. CALL DGEMM( 'T', 'N', M1, N, M2, -ONE, A( M1 ),
  428. $ M, B( M1, 0 ), LDB, ALPHA, B, LDB )
  429. CALL DTRSM( 'L', 'L', 'T', DIAG, M1, N, ONE,
  430. $ A( 0 ), M, B, LDB )
  431. END IF
  432. *
  433. END IF
  434. *
  435. ELSE
  436. *
  437. * SIDE ='L', N is odd, TRANSR = 'N', and UPLO = 'U'
  438. *
  439. IF( .NOT.NOTRANS ) THEN
  440. *
  441. * SIDE ='L', N is odd, TRANSR = 'N', UPLO = 'U', and
  442. * TRANS = 'N'
  443. *
  444. CALL DTRSM( 'L', 'L', 'N', DIAG, M1, N, ALPHA,
  445. $ A( M2 ), M, B, LDB )
  446. CALL DGEMM( 'T', 'N', M2, N, M1, -ONE, A( 0 ), M,
  447. $ B, LDB, ALPHA, B( M1, 0 ), LDB )
  448. CALL DTRSM( 'L', 'U', 'T', DIAG, M2, N, ONE,
  449. $ A( M1 ), M, B( M1, 0 ), LDB )
  450. *
  451. ELSE
  452. *
  453. * SIDE ='L', N is odd, TRANSR = 'N', UPLO = 'U', and
  454. * TRANS = 'T'
  455. *
  456. CALL DTRSM( 'L', 'U', 'N', DIAG, M2, N, ALPHA,
  457. $ A( M1 ), M, B( M1, 0 ), LDB )
  458. CALL DGEMM( 'N', 'N', M1, N, M2, -ONE, A( 0 ), M,
  459. $ B( M1, 0 ), LDB, ALPHA, B, LDB )
  460. CALL DTRSM( 'L', 'L', 'T', DIAG, M1, N, ONE,
  461. $ A( M2 ), M, B, LDB )
  462. *
  463. END IF
  464. *
  465. END IF
  466. *
  467. ELSE
  468. *
  469. * SIDE = 'L', N is odd, and TRANSR = 'T'
  470. *
  471. IF( LOWER ) THEN
  472. *
  473. * SIDE ='L', N is odd, TRANSR = 'T', and UPLO = 'L'
  474. *
  475. IF( NOTRANS ) THEN
  476. *
  477. * SIDE ='L', N is odd, TRANSR = 'T', UPLO = 'L', and
  478. * TRANS = 'N'
  479. *
  480. IF( M.EQ.1 ) THEN
  481. CALL DTRSM( 'L', 'U', 'T', DIAG, M1, N, ALPHA,
  482. $ A( 0 ), M1, B, LDB )
  483. ELSE
  484. CALL DTRSM( 'L', 'U', 'T', DIAG, M1, N, ALPHA,
  485. $ A( 0 ), M1, B, LDB )
  486. CALL DGEMM( 'T', 'N', M2, N, M1, -ONE,
  487. $ A( M1*M1 ), M1, B, LDB, ALPHA,
  488. $ B( M1, 0 ), LDB )
  489. CALL DTRSM( 'L', 'L', 'N', DIAG, M2, N, ONE,
  490. $ A( 1 ), M1, B( M1, 0 ), LDB )
  491. END IF
  492. *
  493. ELSE
  494. *
  495. * SIDE ='L', N is odd, TRANSR = 'T', UPLO = 'L', and
  496. * TRANS = 'T'
  497. *
  498. IF( M.EQ.1 ) THEN
  499. CALL DTRSM( 'L', 'U', 'N', DIAG, M1, N, ALPHA,
  500. $ A( 0 ), M1, B, LDB )
  501. ELSE
  502. CALL DTRSM( 'L', 'L', 'T', DIAG, M2, N, ALPHA,
  503. $ A( 1 ), M1, B( M1, 0 ), LDB )
  504. CALL DGEMM( 'N', 'N', M1, N, M2, -ONE,
  505. $ A( M1*M1 ), M1, B( M1, 0 ), LDB,
  506. $ ALPHA, B, LDB )
  507. CALL DTRSM( 'L', 'U', 'N', DIAG, M1, N, ONE,
  508. $ A( 0 ), M1, B, LDB )
  509. END IF
  510. *
  511. END IF
  512. *
  513. ELSE
  514. *
  515. * SIDE ='L', N is odd, TRANSR = 'T', and UPLO = 'U'
  516. *
  517. IF( .NOT.NOTRANS ) THEN
  518. *
  519. * SIDE ='L', N is odd, TRANSR = 'T', UPLO = 'U', and
  520. * TRANS = 'N'
  521. *
  522. CALL DTRSM( 'L', 'U', 'T', DIAG, M1, N, ALPHA,
  523. $ A( M2*M2 ), M2, B, LDB )
  524. CALL DGEMM( 'N', 'N', M2, N, M1, -ONE, A( 0 ), M2,
  525. $ B, LDB, ALPHA, B( M1, 0 ), LDB )
  526. CALL DTRSM( 'L', 'L', 'N', DIAG, M2, N, ONE,
  527. $ A( M1*M2 ), M2, B( M1, 0 ), LDB )
  528. *
  529. ELSE
  530. *
  531. * SIDE ='L', N is odd, TRANSR = 'T', UPLO = 'U', and
  532. * TRANS = 'T'
  533. *
  534. CALL DTRSM( 'L', 'L', 'T', DIAG, M2, N, ALPHA,
  535. $ A( M1*M2 ), M2, B( M1, 0 ), LDB )
  536. CALL DGEMM( 'T', 'N', M1, N, M2, -ONE, A( 0 ), M2,
  537. $ B( M1, 0 ), LDB, ALPHA, B, LDB )
  538. CALL DTRSM( 'L', 'U', 'N', DIAG, M1, N, ONE,
  539. $ A( M2*M2 ), M2, B, LDB )
  540. *
  541. END IF
  542. *
  543. END IF
  544. *
  545. END IF
  546. *
  547. ELSE
  548. *
  549. * SIDE = 'L' and N is even
  550. *
  551. IF( NORMALTRANSR ) THEN
  552. *
  553. * SIDE = 'L', N is even, and TRANSR = 'N'
  554. *
  555. IF( LOWER ) THEN
  556. *
  557. * SIDE ='L', N is even, TRANSR = 'N', and UPLO = 'L'
  558. *
  559. IF( NOTRANS ) THEN
  560. *
  561. * SIDE ='L', N is even, TRANSR = 'N', UPLO = 'L',
  562. * and TRANS = 'N'
  563. *
  564. CALL DTRSM( 'L', 'L', 'N', DIAG, K, N, ALPHA,
  565. $ A( 1 ), M+1, B, LDB )
  566. CALL DGEMM( 'N', 'N', K, N, K, -ONE, A( K+1 ),
  567. $ M+1, B, LDB, ALPHA, B( K, 0 ), LDB )
  568. CALL DTRSM( 'L', 'U', 'T', DIAG, K, N, ONE,
  569. $ A( 0 ), M+1, B( K, 0 ), LDB )
  570. *
  571. ELSE
  572. *
  573. * SIDE ='L', N is even, TRANSR = 'N', UPLO = 'L',
  574. * and TRANS = 'T'
  575. *
  576. CALL DTRSM( 'L', 'U', 'N', DIAG, K, N, ALPHA,
  577. $ A( 0 ), M+1, B( K, 0 ), LDB )
  578. CALL DGEMM( 'T', 'N', K, N, K, -ONE, A( K+1 ),
  579. $ M+1, B( K, 0 ), LDB, ALPHA, B, LDB )
  580. CALL DTRSM( 'L', 'L', 'T', DIAG, K, N, ONE,
  581. $ A( 1 ), M+1, B, LDB )
  582. *
  583. END IF
  584. *
  585. ELSE
  586. *
  587. * SIDE ='L', N is even, TRANSR = 'N', and UPLO = 'U'
  588. *
  589. IF( .NOT.NOTRANS ) THEN
  590. *
  591. * SIDE ='L', N is even, TRANSR = 'N', UPLO = 'U',
  592. * and TRANS = 'N'
  593. *
  594. CALL DTRSM( 'L', 'L', 'N', DIAG, K, N, ALPHA,
  595. $ A( K+1 ), M+1, B, LDB )
  596. CALL DGEMM( 'T', 'N', K, N, K, -ONE, A( 0 ), M+1,
  597. $ B, LDB, ALPHA, B( K, 0 ), LDB )
  598. CALL DTRSM( 'L', 'U', 'T', DIAG, K, N, ONE,
  599. $ A( K ), M+1, B( K, 0 ), LDB )
  600. *
  601. ELSE
  602. *
  603. * SIDE ='L', N is even, TRANSR = 'N', UPLO = 'U',
  604. * and TRANS = 'T'
  605. CALL DTRSM( 'L', 'U', 'N', DIAG, K, N, ALPHA,
  606. $ A( K ), M+1, B( K, 0 ), LDB )
  607. CALL DGEMM( 'N', 'N', K, N, K, -ONE, A( 0 ), M+1,
  608. $ B( K, 0 ), LDB, ALPHA, B, LDB )
  609. CALL DTRSM( 'L', 'L', 'T', DIAG, K, N, ONE,
  610. $ A( K+1 ), M+1, B, LDB )
  611. *
  612. END IF
  613. *
  614. END IF
  615. *
  616. ELSE
  617. *
  618. * SIDE = 'L', N is even, and TRANSR = 'T'
  619. *
  620. IF( LOWER ) THEN
  621. *
  622. * SIDE ='L', N is even, TRANSR = 'T', and UPLO = 'L'
  623. *
  624. IF( NOTRANS ) THEN
  625. *
  626. * SIDE ='L', N is even, TRANSR = 'T', UPLO = 'L',
  627. * and TRANS = 'N'
  628. *
  629. CALL DTRSM( 'L', 'U', 'T', DIAG, K, N, ALPHA,
  630. $ A( K ), K, B, LDB )
  631. CALL DGEMM( 'T', 'N', K, N, K, -ONE,
  632. $ A( K*( K+1 ) ), K, B, LDB, ALPHA,
  633. $ B( K, 0 ), LDB )
  634. CALL DTRSM( 'L', 'L', 'N', DIAG, K, N, ONE,
  635. $ A( 0 ), K, B( K, 0 ), LDB )
  636. *
  637. ELSE
  638. *
  639. * SIDE ='L', N is even, TRANSR = 'T', UPLO = 'L',
  640. * and TRANS = 'T'
  641. *
  642. CALL DTRSM( 'L', 'L', 'T', DIAG, K, N, ALPHA,
  643. $ A( 0 ), K, B( K, 0 ), LDB )
  644. CALL DGEMM( 'N', 'N', K, N, K, -ONE,
  645. $ A( K*( K+1 ) ), K, B( K, 0 ), LDB,
  646. $ ALPHA, B, LDB )
  647. CALL DTRSM( 'L', 'U', 'N', DIAG, K, N, ONE,
  648. $ A( K ), K, B, LDB )
  649. *
  650. END IF
  651. *
  652. ELSE
  653. *
  654. * SIDE ='L', N is even, TRANSR = 'T', and UPLO = 'U'
  655. *
  656. IF( .NOT.NOTRANS ) THEN
  657. *
  658. * SIDE ='L', N is even, TRANSR = 'T', UPLO = 'U',
  659. * and TRANS = 'N'
  660. *
  661. CALL DTRSM( 'L', 'U', 'T', DIAG, K, N, ALPHA,
  662. $ A( K*( K+1 ) ), K, B, LDB )
  663. CALL DGEMM( 'N', 'N', K, N, K, -ONE, A( 0 ), K, B,
  664. $ LDB, ALPHA, B( K, 0 ), LDB )
  665. CALL DTRSM( 'L', 'L', 'N', DIAG, K, N, ONE,
  666. $ A( K*K ), K, B( K, 0 ), LDB )
  667. *
  668. ELSE
  669. *
  670. * SIDE ='L', N is even, TRANSR = 'T', UPLO = 'U',
  671. * and TRANS = 'T'
  672. *
  673. CALL DTRSM( 'L', 'L', 'T', DIAG, K, N, ALPHA,
  674. $ A( K*K ), K, B( K, 0 ), LDB )
  675. CALL DGEMM( 'T', 'N', K, N, K, -ONE, A( 0 ), K,
  676. $ B( K, 0 ), LDB, ALPHA, B, LDB )
  677. CALL DTRSM( 'L', 'U', 'N', DIAG, K, N, ONE,
  678. $ A( K*( K+1 ) ), K, B, LDB )
  679. *
  680. END IF
  681. *
  682. END IF
  683. *
  684. END IF
  685. *
  686. END IF
  687. *
  688. ELSE
  689. *
  690. * SIDE = 'R'
  691. *
  692. * A is N-by-N.
  693. * If N is odd, set NISODD = .TRUE., and N1 and N2.
  694. * If N is even, NISODD = .FALSE., and K.
  695. *
  696. IF( MOD( N, 2 ).EQ.0 ) THEN
  697. NISODD = .FALSE.
  698. K = N / 2
  699. ELSE
  700. NISODD = .TRUE.
  701. IF( LOWER ) THEN
  702. N2 = N / 2
  703. N1 = N - N2
  704. ELSE
  705. N1 = N / 2
  706. N2 = N - N1
  707. END IF
  708. END IF
  709. *
  710. IF( NISODD ) THEN
  711. *
  712. * SIDE = 'R' and N is odd
  713. *
  714. IF( NORMALTRANSR ) THEN
  715. *
  716. * SIDE = 'R', N is odd, and TRANSR = 'N'
  717. *
  718. IF( LOWER ) THEN
  719. *
  720. * SIDE ='R', N is odd, TRANSR = 'N', and UPLO = 'L'
  721. *
  722. IF( NOTRANS ) THEN
  723. *
  724. * SIDE ='R', N is odd, TRANSR = 'N', UPLO = 'L', and
  725. * TRANS = 'N'
  726. *
  727. CALL DTRSM( 'R', 'U', 'T', DIAG, M, N2, ALPHA,
  728. $ A( N ), N, B( 0, N1 ), LDB )
  729. CALL DGEMM( 'N', 'N', M, N1, N2, -ONE, B( 0, N1 ),
  730. $ LDB, A( N1 ), N, ALPHA, B( 0, 0 ),
  731. $ LDB )
  732. CALL DTRSM( 'R', 'L', 'N', DIAG, M, N1, ONE,
  733. $ A( 0 ), N, B( 0, 0 ), LDB )
  734. *
  735. ELSE
  736. *
  737. * SIDE ='R', N is odd, TRANSR = 'N', UPLO = 'L', and
  738. * TRANS = 'T'
  739. *
  740. CALL DTRSM( 'R', 'L', 'T', DIAG, M, N1, ALPHA,
  741. $ A( 0 ), N, B( 0, 0 ), LDB )
  742. CALL DGEMM( 'N', 'T', M, N2, N1, -ONE, B( 0, 0 ),
  743. $ LDB, A( N1 ), N, ALPHA, B( 0, N1 ),
  744. $ LDB )
  745. CALL DTRSM( 'R', 'U', 'N', DIAG, M, N2, ONE,
  746. $ A( N ), N, B( 0, N1 ), LDB )
  747. *
  748. END IF
  749. *
  750. ELSE
  751. *
  752. * SIDE ='R', N is odd, TRANSR = 'N', and UPLO = 'U'
  753. *
  754. IF( NOTRANS ) THEN
  755. *
  756. * SIDE ='R', N is odd, TRANSR = 'N', UPLO = 'U', and
  757. * TRANS = 'N'
  758. *
  759. CALL DTRSM( 'R', 'L', 'T', DIAG, M, N1, ALPHA,
  760. $ A( N2 ), N, B( 0, 0 ), LDB )
  761. CALL DGEMM( 'N', 'N', M, N2, N1, -ONE, B( 0, 0 ),
  762. $ LDB, A( 0 ), N, ALPHA, B( 0, N1 ),
  763. $ LDB )
  764. CALL DTRSM( 'R', 'U', 'N', DIAG, M, N2, ONE,
  765. $ A( N1 ), N, B( 0, N1 ), LDB )
  766. *
  767. ELSE
  768. *
  769. * SIDE ='R', N is odd, TRANSR = 'N', UPLO = 'U', and
  770. * TRANS = 'T'
  771. *
  772. CALL DTRSM( 'R', 'U', 'T', DIAG, M, N2, ALPHA,
  773. $ A( N1 ), N, B( 0, N1 ), LDB )
  774. CALL DGEMM( 'N', 'T', M, N1, N2, -ONE, B( 0, N1 ),
  775. $ LDB, A( 0 ), N, ALPHA, B( 0, 0 ), LDB )
  776. CALL DTRSM( 'R', 'L', 'N', DIAG, M, N1, ONE,
  777. $ A( N2 ), N, B( 0, 0 ), LDB )
  778. *
  779. END IF
  780. *
  781. END IF
  782. *
  783. ELSE
  784. *
  785. * SIDE = 'R', N is odd, and TRANSR = 'T'
  786. *
  787. IF( LOWER ) THEN
  788. *
  789. * SIDE ='R', N is odd, TRANSR = 'T', and UPLO = 'L'
  790. *
  791. IF( NOTRANS ) THEN
  792. *
  793. * SIDE ='R', N is odd, TRANSR = 'T', UPLO = 'L', and
  794. * TRANS = 'N'
  795. *
  796. CALL DTRSM( 'R', 'L', 'N', DIAG, M, N2, ALPHA,
  797. $ A( 1 ), N1, B( 0, N1 ), LDB )
  798. CALL DGEMM( 'N', 'T', M, N1, N2, -ONE, B( 0, N1 ),
  799. $ LDB, A( N1*N1 ), N1, ALPHA, B( 0, 0 ),
  800. $ LDB )
  801. CALL DTRSM( 'R', 'U', 'T', DIAG, M, N1, ONE,
  802. $ A( 0 ), N1, B( 0, 0 ), LDB )
  803. *
  804. ELSE
  805. *
  806. * SIDE ='R', N is odd, TRANSR = 'T', UPLO = 'L', and
  807. * TRANS = 'T'
  808. *
  809. CALL DTRSM( 'R', 'U', 'N', DIAG, M, N1, ALPHA,
  810. $ A( 0 ), N1, B( 0, 0 ), LDB )
  811. CALL DGEMM( 'N', 'N', M, N2, N1, -ONE, B( 0, 0 ),
  812. $ LDB, A( N1*N1 ), N1, ALPHA, B( 0, N1 ),
  813. $ LDB )
  814. CALL DTRSM( 'R', 'L', 'T', DIAG, M, N2, ONE,
  815. $ A( 1 ), N1, B( 0, N1 ), LDB )
  816. *
  817. END IF
  818. *
  819. ELSE
  820. *
  821. * SIDE ='R', N is odd, TRANSR = 'T', and UPLO = 'U'
  822. *
  823. IF( NOTRANS ) THEN
  824. *
  825. * SIDE ='R', N is odd, TRANSR = 'T', UPLO = 'U', and
  826. * TRANS = 'N'
  827. *
  828. CALL DTRSM( 'R', 'U', 'N', DIAG, M, N1, ALPHA,
  829. $ A( N2*N2 ), N2, B( 0, 0 ), LDB )
  830. CALL DGEMM( 'N', 'T', M, N2, N1, -ONE, B( 0, 0 ),
  831. $ LDB, A( 0 ), N2, ALPHA, B( 0, N1 ),
  832. $ LDB )
  833. CALL DTRSM( 'R', 'L', 'T', DIAG, M, N2, ONE,
  834. $ A( N1*N2 ), N2, B( 0, N1 ), LDB )
  835. *
  836. ELSE
  837. *
  838. * SIDE ='R', N is odd, TRANSR = 'T', UPLO = 'U', and
  839. * TRANS = 'T'
  840. *
  841. CALL DTRSM( 'R', 'L', 'N', DIAG, M, N2, ALPHA,
  842. $ A( N1*N2 ), N2, B( 0, N1 ), LDB )
  843. CALL DGEMM( 'N', 'N', M, N1, N2, -ONE, B( 0, N1 ),
  844. $ LDB, A( 0 ), N2, ALPHA, B( 0, 0 ),
  845. $ LDB )
  846. CALL DTRSM( 'R', 'U', 'T', DIAG, M, N1, ONE,
  847. $ A( N2*N2 ), N2, B( 0, 0 ), LDB )
  848. *
  849. END IF
  850. *
  851. END IF
  852. *
  853. END IF
  854. *
  855. ELSE
  856. *
  857. * SIDE = 'R' and N is even
  858. *
  859. IF( NORMALTRANSR ) THEN
  860. *
  861. * SIDE = 'R', N is even, and TRANSR = 'N'
  862. *
  863. IF( LOWER ) THEN
  864. *
  865. * SIDE ='R', N is even, TRANSR = 'N', and UPLO = 'L'
  866. *
  867. IF( NOTRANS ) THEN
  868. *
  869. * SIDE ='R', N is even, TRANSR = 'N', UPLO = 'L',
  870. * and TRANS = 'N'
  871. *
  872. CALL DTRSM( 'R', 'U', 'T', DIAG, M, K, ALPHA,
  873. $ A( 0 ), N+1, B( 0, K ), LDB )
  874. CALL DGEMM( 'N', 'N', M, K, K, -ONE, B( 0, K ),
  875. $ LDB, A( K+1 ), N+1, ALPHA, B( 0, 0 ),
  876. $ LDB )
  877. CALL DTRSM( 'R', 'L', 'N', DIAG, M, K, ONE,
  878. $ A( 1 ), N+1, B( 0, 0 ), LDB )
  879. *
  880. ELSE
  881. *
  882. * SIDE ='R', N is even, TRANSR = 'N', UPLO = 'L',
  883. * and TRANS = 'T'
  884. *
  885. CALL DTRSM( 'R', 'L', 'T', DIAG, M, K, ALPHA,
  886. $ A( 1 ), N+1, B( 0, 0 ), LDB )
  887. CALL DGEMM( 'N', 'T', M, K, K, -ONE, B( 0, 0 ),
  888. $ LDB, A( K+1 ), N+1, ALPHA, B( 0, K ),
  889. $ LDB )
  890. CALL DTRSM( 'R', 'U', 'N', DIAG, M, K, ONE,
  891. $ A( 0 ), N+1, B( 0, K ), LDB )
  892. *
  893. END IF
  894. *
  895. ELSE
  896. *
  897. * SIDE ='R', N is even, TRANSR = 'N', and UPLO = 'U'
  898. *
  899. IF( NOTRANS ) THEN
  900. *
  901. * SIDE ='R', N is even, TRANSR = 'N', UPLO = 'U',
  902. * and TRANS = 'N'
  903. *
  904. CALL DTRSM( 'R', 'L', 'T', DIAG, M, K, ALPHA,
  905. $ A( K+1 ), N+1, B( 0, 0 ), LDB )
  906. CALL DGEMM( 'N', 'N', M, K, K, -ONE, B( 0, 0 ),
  907. $ LDB, A( 0 ), N+1, ALPHA, B( 0, K ),
  908. $ LDB )
  909. CALL DTRSM( 'R', 'U', 'N', DIAG, M, K, ONE,
  910. $ A( K ), N+1, B( 0, K ), LDB )
  911. *
  912. ELSE
  913. *
  914. * SIDE ='R', N is even, TRANSR = 'N', UPLO = 'U',
  915. * and TRANS = 'T'
  916. *
  917. CALL DTRSM( 'R', 'U', 'T', DIAG, M, K, ALPHA,
  918. $ A( K ), N+1, B( 0, K ), LDB )
  919. CALL DGEMM( 'N', 'T', M, K, K, -ONE, B( 0, K ),
  920. $ LDB, A( 0 ), N+1, ALPHA, B( 0, 0 ),
  921. $ LDB )
  922. CALL DTRSM( 'R', 'L', 'N', DIAG, M, K, ONE,
  923. $ A( K+1 ), N+1, B( 0, 0 ), LDB )
  924. *
  925. END IF
  926. *
  927. END IF
  928. *
  929. ELSE
  930. *
  931. * SIDE = 'R', N is even, and TRANSR = 'T'
  932. *
  933. IF( LOWER ) THEN
  934. *
  935. * SIDE ='R', N is even, TRANSR = 'T', and UPLO = 'L'
  936. *
  937. IF( NOTRANS ) THEN
  938. *
  939. * SIDE ='R', N is even, TRANSR = 'T', UPLO = 'L',
  940. * and TRANS = 'N'
  941. *
  942. CALL DTRSM( 'R', 'L', 'N', DIAG, M, K, ALPHA,
  943. $ A( 0 ), K, B( 0, K ), LDB )
  944. CALL DGEMM( 'N', 'T', M, K, K, -ONE, B( 0, K ),
  945. $ LDB, A( ( K+1 )*K ), K, ALPHA,
  946. $ B( 0, 0 ), LDB )
  947. CALL DTRSM( 'R', 'U', 'T', DIAG, M, K, ONE,
  948. $ A( K ), K, B( 0, 0 ), LDB )
  949. *
  950. ELSE
  951. *
  952. * SIDE ='R', N is even, TRANSR = 'T', UPLO = 'L',
  953. * and TRANS = 'T'
  954. *
  955. CALL DTRSM( 'R', 'U', 'N', DIAG, M, K, ALPHA,
  956. $ A( K ), K, B( 0, 0 ), LDB )
  957. CALL DGEMM( 'N', 'N', M, K, K, -ONE, B( 0, 0 ),
  958. $ LDB, A( ( K+1 )*K ), K, ALPHA,
  959. $ B( 0, K ), LDB )
  960. CALL DTRSM( 'R', 'L', 'T', DIAG, M, K, ONE,
  961. $ A( 0 ), K, B( 0, K ), LDB )
  962. *
  963. END IF
  964. *
  965. ELSE
  966. *
  967. * SIDE ='R', N is even, TRANSR = 'T', and UPLO = 'U'
  968. *
  969. IF( NOTRANS ) THEN
  970. *
  971. * SIDE ='R', N is even, TRANSR = 'T', UPLO = 'U',
  972. * and TRANS = 'N'
  973. *
  974. CALL DTRSM( 'R', 'U', 'N', DIAG, M, K, ALPHA,
  975. $ A( ( K+1 )*K ), K, B( 0, 0 ), LDB )
  976. CALL DGEMM( 'N', 'T', M, K, K, -ONE, B( 0, 0 ),
  977. $ LDB, A( 0 ), K, ALPHA, B( 0, K ), LDB )
  978. CALL DTRSM( 'R', 'L', 'T', DIAG, M, K, ONE,
  979. $ A( K*K ), K, B( 0, K ), LDB )
  980. *
  981. ELSE
  982. *
  983. * SIDE ='R', N is even, TRANSR = 'T', UPLO = 'U',
  984. * and TRANS = 'T'
  985. *
  986. CALL DTRSM( 'R', 'L', 'N', DIAG, M, K, ALPHA,
  987. $ A( K*K ), K, B( 0, K ), LDB )
  988. CALL DGEMM( 'N', 'N', M, K, K, -ONE, B( 0, K ),
  989. $ LDB, A( 0 ), K, ALPHA, B( 0, 0 ), LDB )
  990. CALL DTRSM( 'R', 'U', 'T', DIAG, M, K, ONE,
  991. $ A( ( K+1 )*K ), K, B( 0, 0 ), LDB )
  992. *
  993. END IF
  994. *
  995. END IF
  996. *
  997. END IF
  998. *
  999. END IF
  1000. END IF
  1001. *
  1002. RETURN
  1003. *
  1004. * End of DTFSM
  1005. *
  1006. END