2 #if XSYTRF_ALLOW_MALLOC
6 static void RELAPACK_zsytrf_rec(const char *, const int *, const int *, int *,
7 double *, const int *, int *, double *, const int *, int *);
10 /** ZSYTRF computes the factorization of a complex symmetric matrix A using the Bunch-Kaufman diagonal pivoting method.
12 * This routine is functionally equivalent to LAPACK's zsytrf.
13 * For details on its interface, see
14 * http://www.netlib.org/lapack/explore-html/da/d94/zsytrf_8f.html
17 const char *uplo, const int *n,
18 double *A, const int *ldA, int *ipiv,
19 double *Work, const int *lWork, int *info
23 const int cleanlWork = *n * (*n / 2);
24 int minlWork = cleanlWork;
25 #if XSYTRF_ALLOW_MALLOC
30 const int lower = LAPACK(lsame)(uplo, "L");
31 const int upper = LAPACK(lsame)(uplo, "U");
37 else if (*ldA < MAX(1, *n))
39 else if (*lWork < minlWork && *lWork != -1)
41 else if (*lWork == -1) {
48 double *cleanWork = Work;
49 #if XSYTRF_ALLOW_MALLOC
50 if (!*info && *lWork < cleanlWork) {
51 cleanWork = malloc(cleanlWork * 2 * sizeof(double));
58 const int minfo = -*info;
59 LAPACK(xerbla)("ZSYTRF", &minfo);
63 // Clean char * arguments
64 const char cleanuplo = lower ? 'L' : 'U';
70 RELAPACK_zsytrf_rec(&cleanuplo, n, n, &nout, A, ldA, ipiv, cleanWork, n, info);
72 #if XSYTRF_ALLOW_MALLOC
73 if (cleanWork != Work)
79 /** zsytrf's recursive compute kernel */
80 static void RELAPACK_zsytrf_rec(
81 const char *uplo, const int *n_full, const int *n, int *n_out,
82 double *A, const int *ldA, int *ipiv,
83 double *Work, const int *ldWork, int *info
86 // top recursion level?
87 const int top = *n_full == *n;
89 if (*n <= MAX(CROSSOVER_ZSYTRF, 3)) {
92 LAPACK(zsytf2)(uplo, n, A, ldA, ipiv, info);
95 RELAPACK_zsytrf_rec2(uplo, n_full, n, n_out, A, ldA, ipiv, Work, ldWork, info);
102 const double ONE[] = { 1., 0. };
103 const double MONE[] = { -1., 0. };
104 const int iONE[] = { 1 };
109 const int n_rest = *n_full - *n;
113 int n1 = ZREC_SPLIT(*n);
117 double *const Work_L = Work;
121 RELAPACK_zsytrf_rec(uplo, n_full, &n1, &n1_out, A, ldA, ipiv, Work_L, ldWork, &info1);
124 // Splitting (continued)
126 const int n_full2 = *n_full - n1;
131 double *const A_BL = A + 2 * n1;
132 double *const A_BR = A + 2 * *ldA * n1 + 2 * n1;
133 double *const A_BL_B = A + 2 * *n;
134 double *const A_BR_B = A + 2 * *ldA * n1 + 2 * *n;
139 // (top recursion level: use Work as Work_BR)
140 double *const Work_BL = Work + 2 * n1;
141 double *const Work_BR = top ? Work : Work + 2 * *ldWork * n1 + 2 * n1;
142 const int ldWork_BR = top ? n2 : *ldWork;
146 int *const ipiv_B = ipiv + n1;
148 // A_BR = A_BR - A_BL Work_BL'
149 RELAPACK_zgemmt(uplo, "N", "T", &n2, &n1, MONE, A_BL, ldA, Work_BL, ldWork, ONE, A_BR, ldA);
150 BLAS(zgemm)("N", "T", &n_rest, &n2, &n1, MONE, A_BL_B, ldA, Work_BL, ldWork, ONE, A_BR_B, ldA);
154 RELAPACK_zsytrf_rec(uplo, &n_full2, &n2, &n2_out, A_BR, ldA, ipiv_B, Work_BR, &ldWork_BR, &info2);
157 // undo 1 column of updates
158 const int n_restp1 = n_rest + 1;
160 // last column of A_BR
161 double *const A_BR_r = A_BR + 2 * *ldA * n2_out + 2 * n2_out;
164 double *const A_BL_b = A_BL + 2 * n2_out;
166 // last row of Work_BL
167 double *const Work_BL_b = Work_BL + 2 * n2_out;
169 // A_BR_r = A_BR_r + A_BL_b Work_BL_b'
170 BLAS(zgemv)("N", &n_restp1, &n1, ONE, A_BL_b, ldA, Work_BL_b, ldWork, ONE, A_BR_r, iONE);
175 for (i = 0; i < n2; i++)
181 *info = info1 || info2;
185 int n2 = ZREC_SPLIT(*n);
189 // (top recursion level: use Work as Work_R)
190 double *const Work_R = top ? Work : Work + 2 * *ldWork * n1;
194 RELAPACK_zsytrf_rec(uplo, n_full, &n2, &n2_out, A, ldA, ipiv, Work_R, ldWork, &info2);
195 const int n2_diff = n2 - n2_out;
198 // Splitting (continued)
200 const int n_full1 = *n_full - n2;
205 double *const A_TL_T = A + 2 * *ldA * n_rest;
206 double *const A_TR_T = A + 2 * *ldA * (n_rest + n1);
207 double *const A_TL = A + 2 * *ldA * n_rest + 2 * n_rest;
208 double *const A_TR = A + 2 * *ldA * (n_rest + n1) + 2 * n_rest;
213 // (top recursion level: Work_R was Work)
214 double *const Work_L = Work;
215 double *const Work_TR = Work + 2 * *ldWork * (top ? n2_diff : n1) + 2 * n_rest;
216 const int ldWork_L = top ? n1 : *ldWork;
218 // A_TL = A_TL - A_TR Work_TR'
219 RELAPACK_zgemmt(uplo, "N", "T", &n1, &n2, MONE, A_TR, ldA, Work_TR, ldWork, ONE, A_TL, ldA);
220 BLAS(zgemm)("N", "T", &n_rest, &n1, &n2, MONE, A_TR_T, ldA, Work_TR, ldWork, ONE, A_TL_T, ldA);
224 RELAPACK_zsytrf_rec(uplo, &n_full1, &n1, &n1_out, A, ldA, ipiv, Work_L, &ldWork_L, &info1);
227 // undo 1 column of updates
228 const int n_restp1 = n_rest + 1;
230 // A_TL_T_l = A_TL_T_l + A_TR_T Work_TR_t'
231 BLAS(zgemv)("N", &n_restp1, &n2, ONE, A_TR_T, ldA, Work_TR, ldWork, ONE, A_TL_T, iONE);
235 *info = info2 || info1;