Eigenvalue SoLvers for Petaflop-Applications (ELPA) 2025.01.002
Loading...
Searching...
No Matches
elpa_impl_math_template.F90
Go to the documentation of this file.
1!
2! Copyright 2017, L. Hüdepohl and A. Marek, MPCDF
3!
4! This file is part of ELPA.
5!
6! The ELPA library was originally created by the ELPA consortium,
7! consisting of the following organizations:
8!
9! - Max Planck Computing and Data Facility (MPCDF), formerly known as
10! Rechenzentrum Garching der Max-Planck-Gesellschaft (RZG),
11! - Bergische Universität Wuppertal, Lehrstuhl für angewandte
12! Informatik,
13! - Technische Universität München, Lehrstuhl für Informatik mit
14! Schwerpunkt Wissenschaftliches Rechnen ,
15! - Fritz-Haber-Institut, Berlin, Abt. Theorie,
16! - Max-Plack-Institut für Mathematik in den Naturwissenschaften,
17! Leipzig, Abt. Komplexe Strukutren in Biologie und Kognition,
18! and
19! - IBM Deutschland GmbH
20!
21! This particular source code file contains additions, changes and
22! enhancements authored by Intel Corporation which is not part of
23! the ELPA consortium.
24!
25! More information can be found here:
26! http://elpa.mpcdf.mpg.de/
27!
28! ELPA is free software: you can redistribute it and/or modify
29! it under the terms of the version 3 of the license of the
30! GNU Lesser General Public License as published by the Free
31! Software Foundation.
32!
33! ELPA is distributed in the hope that it will be useful,
34! but WITHOUT ANY WARRANTY; without even the implied warranty of
35! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36! GNU Lesser General Public License for more details.
37!
38! You should have received a copy of the GNU Lesser General Public License
39! along with ELPA. If not, see <http://www.gnu.org/licenses/>
40!
41! ELPA reflects a substantial effort on the part of the original
42! ELPA consortium, and we ask you to respect the spirit of the
43! license that we chose: i.e., please contribute any changes you
44! may have back to the original ELPA library distribution, and keep
45! any derivatives of ELPA under the same license that we chose for
46! the original distribution, the GNU Lesser General Public License.
47!
48
49!__________________________________________________________________________________________________________________________________
50
51 ! hermitian_multiply
52
53 !> \brief elpa_hermitian_multiply_a_h_a_d: class method to perform C : = A**T * B
54 !> where A is a square matrix (self%na,self%na) which is optionally upper or lower triangular
55 !> B is a (self%na,ncb) matrix
56 !> C is a (self%na,ncb) matrix where optionally only the upper or lower
57 !> triangle may be computed
58 !>
59 !> the MPI commicators and the block-cyclic distribution block size are already known to the type.
60 !> Thus the class method "setup" must be called BEFORE this method is used
61 !>
62 !> \details
63 !>
64 !> \param self class(elpa_t), the ELPA object
65 !> \param uplo_a 'U' if A is upper triangular
66 !> 'L' if A is lower triangular
67 !> anything else if A is a full matrix
68 !> Please note: This pertains to the original A (as set in the calling program)
69 !> whereas the transpose of A is used for calculations
70 !> If uplo_a is 'U' or 'L', the other triangle is not used at all,
71 !> i.e. it may contain arbitrary numbers
72 !> \param uplo_c 'U' if only the upper diagonal part of C is needed
73 !> 'L' if only the upper diagonal part of C is needed
74 !> anything else if the full matrix C is needed
75 !> Please note: Even when uplo_c is 'U' or 'L', the other triangle may be
76 !> written to a certain extent, i.e. one shouldn't rely on the content there!
77 !> \param ncb Number of columns of global matrices B and C
78 !> \param a matrix a
79 !> \param local_nrows number of rows of local (sub) matrix a, set with class method set("local_nrows",value)
80 !> \param local_ncols number of columns of local (sub) matrix a, set with class method set("local_ncols",value)
81 !> \param b matrix b
82 !> \param nrows_b number of rows of local (sub) matrix b
83 !> \param ncols_b number of columns of local (sub) matrix b
84 !> \param c matrix c
85 !> \param nrows_c number of rows of local (sub) matrix c
86 !> \param ncols_c number of columns of local (sub) matrix c
87 !> \param error optional argument, error code which can be queried with elpa_strerr
88 subroutine elpa_hermitian_multiply_a_h_a_&
89 &elpa_impl_suffix&
90 & (self, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, &
91 c, nrows_c, ncols_c, error)
92 class(elpa_impl_t) :: self
93 character*1 :: uplo_a, uplo_c
94 integer(kind=c_int), intent(in) :: nrows_b, ncols_b, nrows_c, ncols_c, ncb
95#ifdef USE_ASSUMED_SIZE
96 math_datatype(kind=c_datatype_kind) :: a(self%local_nrows,*), b(nrows_b,*), c(nrows_c,*)
97#else
98 math_datatype(kind=c_datatype_kind) :: a(self%local_nrows,self%local_ncols), b(nrows_b,ncols_b), c(nrows_c,ncols_c)
99#endif
100#ifdef USE_FORTRAN2008
101 integer, optional :: error
102#else
103 integer :: error
104#endif
105 logical :: success_l
106
107 success_l = .false.
108
109#if defined(INCLUDE_ROUTINES)
110 success_l = elpa_hermitian_multiply_a_h_a_&
111 &math_datatype&
112 &_&
113 &precision&
114 &_impl(self, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, &
115 c, nrows_c, ncols_c)
116#endif
117
118#ifdef USE_FORTRAN2008
119 if (present(error)) then
120 if (success_l) then
121 error = elpa_ok
122 else
123 error = elpa_error
124 endif
125 else if (.not. success_l) then
126 write(error_unit,'(a)') "ELPA: Error in hermitian_multiply() and you did not check for errors!"
127 endif
128#else
129 if (success_l) then
130 error = elpa_ok
131 else
132 error = elpa_error
133 endif
134#endif
135 end subroutine
136
137
138 !> \brief elpa_hermitian_multiply_d_ptr_d: class method to perform C : = A**T * B
139 !> where A is a square matrix (self%na,self%na) which is optionally upper or lower triangular
140 !> B is a (self%na,ncb) matrix
141 !> C is a (self%na,ncb) matrix where optionally only the upper or lower
142 !> triangle may be computed
143 !>
144 !> the MPI commicators and the block-cyclic distribution block size are already known to the type.
145 !> Thus the class method "setup" must be called BEFORE this method is used
146 !>
147 !> \details
148 !>
149 !> \param self class(elpa_t), the ELPA object
150 !> \param uplo_a 'U' if A is upper triangular
151 !> 'L' if A is lower triangular
152 !> anything else if A is a full matrix
153 !> Please note: This pertains to the original A (as set in the calling program)
154 !> whereas the transpose of A is used for calculations
155 !> If uplo_a is 'U' or 'L', the other triangle is not used at all,
156 !> i.e. it may contain arbitrary numbers
157 !> \param uplo_c 'U' if only the upper-triangle part of C is needed
158 !> 'L' if only the lower-triangle part of C is needed
159 !> anything else if the full matrix C is needed
160 !> Please note: Even when uplo_c is 'U' or 'L', the other triangle may be
161 !> written to a certain extent, i.e. one shouldn't rely on the content there!
162 !> \param ncb Number of columns of global matrices B and C
163 !> \param a matrix a, as device pointer of type(c_ptr)
164 !> \param local_nrows number of rows of local (sub) matrix a, set with class method set("local_nrows",value)
165 !> \param local_ncols number of columns of local (sub) matrix a, set with class method set("local_ncols",value)
166 !> \param b matrix b, as device pointer of type(c_ptr)
167 !> \param nrows_b number of rows of local (sub) matrix b
168 !> \param ncols_b number of columns of local (sub) matrix b
169 !> \param c matrix c, as device pointer of type(c_ptr)
170 !> \param nrows_c number of rows of local (sub) matrix c
171 !> \param ncols_c number of columns of local (sub) matrix c
172 !> \param error optional argument, error code which can be queried with elpa_strerr
173 subroutine elpa_hermitian_multiply_d_ptr_&
174 &elpa_impl_suffix&
175 & (self, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, &
176 c, nrows_c, ncols_c, error)
177 class(elpa_impl_t) :: self
178 character*1 :: uplo_a, uplo_c
179 integer(kind=c_int), intent(in) :: nrows_b, ncols_b, nrows_c, ncols_c, ncb
180 type(c_ptr) :: a, b, c
181#ifdef USE_FORTRAN2008
182 integer, optional :: error
183#else
184 integer :: error
185#endif
186 logical :: success_l
187
188 success_l = .false.
189
190#if defined(INCLUDE_ROUTINES)
191 success_l = elpa_hermitian_multiply_d_ptr_&
192 &math_datatype&
193 &_&
194 &precision&
195 &_impl(self, uplo_a, uplo_c, ncb, a, b, nrows_b, ncols_b, &
196 c, nrows_c, ncols_c)
197#endif
198
199#ifdef USE_FORTRAN2008
200 if (present(error)) then
201 if (success_l) then
202 error = elpa_ok
203 else
204 error = elpa_error
205 endif
206 else if (.not. success_l) then
207 write(error_unit,'(a)') "ELPA: Error in hermitian_multiply() and you did not check for errors!"
208 endif
209#else
210 if (success_l) then
211 error = elpa_ok
212 else
213 error = elpa_error
214 endif
215#endif
216 end subroutine
217
218 !c> // /src/elpa_impl_math_template.F90
219
220#ifdef REALCASE
221#ifdef DOUBLE_PRECISION_REAL
222 !c> void elpa_hermitian_multiply_a_h_a_d(elpa_t handle, char uplo_a, char uplo_c, int ncb, double *a, double *b, int nrows_b, int ncols_b, double *c, int nrows_c, int ncols_c, int *error);
223#endif
224#ifdef SINGLE_PRECISION_REAL
225 !c> void elpa_hermitian_multiply_a_h_a_f(elpa_t handle, char uplo_a, char uplo_c, int ncb, float *a, float *b, int nrows_b, int ncols_b, float *c, int nrows_c, int ncols_c, int *error);
226#endif
227#endif
228#ifdef COMPLEXCASE
229#ifdef DOUBLE_PRECISION_COMPLEX
230 !c> void elpa_hermitian_multiply_a_h_a_dc(elpa_t handle, char uplo_a, char uplo_c, int ncb, double_complex *a, double_complex *b, int nrows_b, int ncols_b, double_complex *c, int nrows_c, int ncols_c, int *error);
231#endif
232#ifdef SINGLE_PRECISION_COMPLEX
233 !c> void elpa_hermitian_multiply_a_h_a_fc(elpa_t handle, char uplo_a, char uplo_c, int ncb, float_complex *a, float_complex *b, int nrows_b, int ncols_b, float_complex *c, int nrows_c, int ncols_c, int *error);
234#endif
235#endif
236 subroutine elpa_hermitian_multiply_a_h_a_&
237 &elpa_impl_suffix&
238 &_c(handle, uplo_a, uplo_c, ncb, a_p, b_p, nrows_b, &
239 ncols_b, c_p, nrows_c, ncols_c, error) &
240#ifdef REALCASE
241#ifdef DOUBLE_PRECISION_REAL
242 bind(C, name="elpa_hermitian_multiply_a_h_a_d")
243#endif
244#ifdef SINGLE_PRECISION_REAL
245 bind(C, name="elpa_hermitian_multiply_a_h_a_f")
246#endif
247#endif
248#ifdef COMPLEXCASE
249#ifdef DOUBLE_PRECISION_COMPLEX
250 bind(C, name="elpa_hermitian_multiply_a_h_a_dc")
251#endif
252#ifdef SINGLE_PRECISION_COMPLEX
253 bind(C, name="elpa_hermitian_multiply_a_h_a_fc")
254#endif
255#endif
256
257 type(c_ptr), intent(in), value :: handle, a_p, b_p, c_p
258 character(1,C_CHAR), value :: uplo_a, uplo_c
259 integer(kind=c_int), value :: ncb, nrows_b, ncols_b, nrows_c, ncols_c
260#ifdef USE_FORTRAN2008
261 integer(kind=c_int), optional, intent(in) :: error
262#else
263 integer(kind=c_int), intent(in) :: error
264#endif
265 math_datatype(kind=c_datatype_kind), pointer :: a(:, :), b(:,:), c(:,:)
266!#ifdef USE_ASSUMED_SIZE
267! MATH_DATATYPE(kind=C_DATATYPE_KIND), pointer :: b(nrows_b,*), c(nrows_c,*)
268!#else
269! MATH_DATATYPE(kind=C_DATATYPE_KIND), pointer :: b(nrows_b,ncols_b), c(nrows_c,ncols_c)
270!#endif
271 type(elpa_impl_t), pointer :: self
272
273 call c_f_pointer(handle, self)
274 call c_f_pointer(a_p, a, [self%local_nrows, self%local_ncols])
275 call c_f_pointer(b_p, b, [nrows_b, ncols_b])
276 call c_f_pointer(c_p, c, [nrows_c, ncols_c])
277
278 call elpa_hermitian_multiply_a_h_a_&
279 &elpa_impl_suffix&
280 & (self, uplo_a, uplo_c, ncb, a, b, nrows_b, &
281 ncols_b, c, nrows_c, ncols_c, error)
282 end subroutine
283
284#ifdef REALCASE
285#ifdef DOUBLE_PRECISION_REAL
286 !c> void elpa_hermitian_multiply_d_ptr_d(elpa_t handle, char uplo_a, char uplo_c, int ncb, double *a, double *b, int nrows_b, int ncols_b, double *c, int nrows_c, int ncols_c, int *error);
287#endif
288#ifdef SINGLE_PRECISION_REAL
289 !c> void elpa_hermitian_multiply_d_ptr_f(elpa_t handle, char uplo_a, char uplo_c, int ncb, float *a, float *b, int nrows_b, int ncols_b, float *c, int nrows_c, int ncols_c, int *error);
290#endif
291#endif
292#ifdef COMPLEXCASE
293#ifdef DOUBLE_PRECISION_COMPLEX
294 !c> void elpa_hermitian_multiply_d_ptr_dc(elpa_t handle, char uplo_a, char uplo_c, int ncb, double_complex *a, double_complex *b, int nrows_b, int ncols_b, double_complex *c, int nrows_c, int ncols_c, int *error);
295#endif
296#ifdef SINGLE_PRECISION_COMPLEX
297 !c> void elpa_hermitian_multiply_d_ptr_fc(elpa_t handle, char uplo_a, char uplo_c, int ncb, float_complex *a, float_complex *b, int nrows_b, int ncols_b, float_complex *c, int nrows_c, int ncols_c, int *error);
298#endif
299#endif
300 subroutine elpa_hermitian_multiply_d_ptr_&
301 &elpa_impl_suffix&
302 &_c(handle, uplo_a, uplo_c, ncb, a_p, b_p, nrows_b, &
303 ncols_b, c_p, nrows_c, ncols_c, error) &
304#ifdef REALCASE
305#ifdef DOUBLE_PRECISION_REAL
306 bind(C, name="elpa_hermitian_multiply_d_ptr_d")
307#endif
308#ifdef SINGLE_PRECISION_REAL
309 bind(C, name="elpa_hermitian_multiply_d_ptr_f")
310#endif
311#endif
312#ifdef COMPLEXCASE
313#ifdef DOUBLE_PRECISION_COMPLEX
314 bind(C, name="elpa_hermitian_multiply_d_ptr_dc")
315#endif
316#ifdef SINGLE_PRECISION_COMPLEX
317 bind(C, name="elpa_hermitian_multiply_d_ptr_fc")
318#endif
319#endif
320
321 type(c_ptr), intent(in), value :: handle, a_p, b_p, c_p
322 character(1,C_CHAR), value :: uplo_a, uplo_c
323 integer(kind=c_int), value :: ncb, nrows_b, ncols_b, nrows_c, ncols_c
324#ifdef USE_FORTRAN2008
325 integer(kind=c_int), optional, intent(in) :: error
326#else
327 integer(kind=c_int), intent(in) :: error
328#endif
329 type(elpa_impl_t), pointer :: self
330
331 call c_f_pointer(handle, self)
332 !call c_f_pointer(a_p, a, [self%local_nrows, self%local_ncols])
333
334 call elpa_hermitian_multiply_d_ptr_&
335 &elpa_impl_suffix&
336 & (self, uplo_a, uplo_c, ncb, a_p, b_p, nrows_b, &
337 ncols_b, c_p, nrows_c, ncols_c, error)
338 end subroutine
339
340!__________________________________________________________________________________________________________________________________
341 ! PETERDEBUG: fix description here and below
342 ! pxgemm_multiply
343
344 !> \brief elpa_pxgemm_multiply_a_h_a_d: class method to perform C : = op(A) * B
345 !> where op(A) is one of: A, A**T, A**H
346 !> A is a square matrix (self%na,self%na) which is optionally upper or lower triangular ! PETERDEBUG: does the matrix have to be square?
347 !> B is a (self%na,ncb) matrix
348 !> C is a (self%na,ncb) matrix where optionally only the upper or lower
349 !> triangle may be computed
350 !>
351 !> the MPI commicators and the block-cyclic distribution block size are already known to the type.
352 !> Thus the class method "setup" must be called BEFORE this method is used
353 !>
354 !> \details
355 !>
356 !> \param self class(elpa_t), the ELPA object
357 !> \param trans_a 'U' if A is upper triangular ! PETERDEBUG:
358 !> 'L' if A is lower triangular
359 !> anything else if A is a full matrix
360 !> Please note: U/L label pertains to the original A (as set in the calling program)
361 !> whereas the transpose of A is might be used for calculations
362 !> If uplo_a is 'U' or 'L', the other triangle is not used at all,
363 !> i.e. it may contain arbitrary numbers
364 !> \param trans_b 'U' if only the upper-triangle part of C is needed
365 !> 'L' if only the lower-triangle part of C is needed
366 !> anything else if the full matrix C is needed
367 !> Please note: Even when uplo_c is 'U' or 'L', the other triangle may be
368 !> written to a certain extent, i.e. one shouldn't rely on the content there!
369 !> \param ncb Number of columns of global matrices B and C
370 !> \param a matrix a
371 !> \param local_nrows number of rows of local (sub) matrix a, set with class method set("local_nrows",value)
372 !> \param local_ncols number of columns of local (sub) matrix a, set with class method set("local_ncols",value)
373 !> \param b matrix b
374 !> \param nrows_b number of rows of local (sub) matrix b
375 !> \param ncols_b number of columns of local (sub) matrix b
376 !> \param c matrix c
377 !> \param nrows_c number of rows of local (sub) matrix c
378 !> \param ncols_c number of columns of local (sub) matrix c
379 !> \param error optional argument, error code which can be queried with elpa_strerr
380 subroutine elpa_pxgemm_multiply_a_h_a_&
381 &elpa_impl_suffix&
382 & (self, trans_a, trans_b, ncb, a, b, nrows_b, ncols_b, &
383 c, nrows_c, ncols_c, error)
384 class(elpa_impl_t) :: self
385 character*1 :: trans_a, trans_b
386 integer(kind=c_int), intent(in) :: nrows_b, ncols_b, nrows_c, ncols_c, ncb
387#ifdef USE_ASSUMED_SIZE
388 math_datatype(kind=c_datatype_kind) :: a(self%local_nrows,*), b(nrows_b,*), c(nrows_c,*)
389#else
390 math_datatype(kind=c_datatype_kind) :: a(self%local_nrows,self%local_ncols), b(nrows_b,ncols_b), c(nrows_c,ncols_c)
391#endif
392#ifdef USE_FORTRAN2008
393 integer, optional :: error
394#else
395 integer :: error
396#endif
397 logical :: success_l
398
399 success_l = .false.
400#if defined(INCLUDE_ROUTINES)
401 success_l = elpa_pxgemm_multiply_a_h_a_&
402 &math_datatype&
403 &_&
404 &precision&
405 &_impl(self, trans_a, trans_b, ncb, a, b, nrows_b, ncols_b, c, nrows_c, ncols_c)
406#endif
407#ifdef USE_FORTRAN2008
408 if (present(error)) then
409 if (success_l) then
410 error = elpa_ok
411 else
412 error = elpa_error
413 endif
414 else if (.not. success_l) then
415 write(error_unit,'(a)') "ELPA: Error in pxgemm_multiply() and you did not check for errors!"
416 endif
417#else
418 if (success_l) then
419 error = elpa_ok
420 else
421 error = elpa_error
422 endif
423#endif
424 end subroutine
425
426
427 !> \brief elpa_pxgemm_multiply_d_ptr_d: class method to perform C : = A**T * B
428 !> where A is a square matrix (self%na,self%na) which is optionally upper or lower triangular
429 !> B is a (self%na,ncb) matrix
430 !> C is a (self%na,ncb) matrix where optionally only the upper or lower
431 !> triangle may be computed
432 !>
433 !> the MPI commicators and the block-cyclic distribution block size are already known to the type.
434 !> Thus the class method "setup" must be called BEFORE this method is used
435 !>
436 !> \details
437 !>
438 !> \param self class(elpa_t), the ELPA object
439 !> \param trans_a 'U' if A is upper triangular
440 !> 'L' if A is lower triangular
441 !> anything else if A is a full matrix
442 !> Please note: This pertains to the original A (as set in the calling program)
443 !> whereas the transpose of A is used for calculations
444 !> If uplo_a is 'U' or 'L', the other triangle is not used at all,
445 !> i.e. it may contain arbitrary numbers
446 !> \param trans_b 'U' if only the upper diagonal part of C is needed
447 !> 'L' if only the upper diagonal part of C is needed
448 !> anything else if the full matrix C is needed
449 !> Please note: Even when uplo_c is 'U' or 'L', the other triangle may be
450 !> written to a certain extent, i.e. one shouldn't rely on the content there!
451 !> \param ncb Number of columns of global matrices B and C
452 !> \param a matrix a, as device pointer of type(c_ptr)
453 !> \param local_nrows number of rows of local (sub) matrix a, set with class method set("local_nrows",value)
454 !> \param local_ncols number of columns of local (sub) matrix a, set with class method set("local_ncols",value)
455 !> \param b matrix b, as device pointer of type(c_ptr)
456 !> \param nrows_b number of rows of local (sub) matrix b
457 !> \param ncols_b number of columns of local (sub) matrix b
458 !> \param c matrix c, as device pointer of type(c_ptr)
459 !> \param nrows_c number of rows of local (sub) matrix c
460 !> \param ncols_c number of columns of local (sub) matrix c
461 !> \param error optional argument, error code which can be queried with elpa_strerr
462 subroutine elpa_pxgemm_multiply_d_ptr_&
463 &elpa_impl_suffix&
464 & (self, trans_a, trans_b, ncb, a, b, nrows_b, ncols_b, &
465 c, nrows_c, ncols_c, error)
466 class(elpa_impl_t) :: self
467 character*1 :: trans_a, trans_b
468 integer(kind=c_int), intent(in) :: nrows_b, ncols_b, nrows_c, ncols_c, ncb
469 type(c_ptr) :: a, b, c
470#ifdef USE_FORTRAN2008
471 integer, optional :: error
472#else
473 integer :: error
474#endif
475 logical :: success_l
476
477 success_l = .false.
478#if defined(INCLUDE_ROUTINES)
479 success_l = elpa_pxgemm_multiply_d_ptr_&
480 &math_datatype&
481 &_&
482 &precision&
483 &_impl(self, trans_a, trans_b, ncb, a, b, nrows_b, ncols_b, c, nrows_c, ncols_c)
484#endif
485#ifdef USE_FORTRAN2008
486 if (present(error)) then
487 if (success_l) then
488 error = elpa_ok
489 else
490 error = elpa_error
491 endif
492 else if (.not. success_l) then
493 write(error_unit,'(a)') "ELPA: Error in pxgemm_multiply() and you did not check for errors!"
494 endif
495#else
496 if (success_l) then
497 error = elpa_ok
498 else
499 error = elpa_error
500 endif
501#endif
502 end subroutine
503
504 !c> // /src/elpa_impl_math_template.F90
505
506#ifdef REALCASE
507#ifdef DOUBLE_PRECISION_REAL
508 !c> void elpa_pxgemm_multiply_a_h_a_d(elpa_t handle, char trans_a, char trans_b, int ncb, double *a, double *b, int nrows_b, int ncols_b, double *c, int nrows_c, int ncols_c, int *error);
509#endif
510#ifdef SINGLE_PRECISION_REAL
511 !c> void elpa_pxgemm_multiply_a_h_a_f(elpa_t handle, char trans_a, char trans_b, int ncb, float *a, float *b, int nrows_b, int ncols_b, float *c, int nrows_c, int ncols_c, int *error);
512#endif
513#endif
514#ifdef COMPLEXCASE
515#ifdef DOUBLE_PRECISION_COMPLEX
516 !c> void elpa_pxgemm_multiply_a_h_a_dc(elpa_t handle, char trans_a, char trans_b, int ncb, double_complex *a, double_complex *b, int nrows_b, int ncols_b, double_complex *c, int nrows_c, int ncols_c, int *error);
517#endif
518#ifdef SINGLE_PRECISION_COMPLEX
519 !c> void elpa_pxgemm_multiply_a_h_a_fc(elpa_t handle, char trans_a, char trans_b, int ncb, float_complex *a, float_complex *b, int nrows_b, int ncols_b, float_complex *c, int nrows_c, int ncols_c, int *error);
520#endif
521#endif
522 subroutine elpa_pxgemm_multiply_a_h_a_&
523 &elpa_impl_suffix&
524 &_c(handle, trans_a, trans_b, ncb, a_p, b_p, nrows_b, &
525 ncols_b, c_p, nrows_c, ncols_c, error) &
526#ifdef REALCASE
527#ifdef DOUBLE_PRECISION_REAL
528 bind(C, name="elpa_pxgemm_multiply_a_h_a_d")
529#endif
530#ifdef SINGLE_PRECISION_REAL
531 bind(C, name="elpa_pxgemm_multiply_a_h_a_f")
532#endif
533#endif
534#ifdef COMPLEXCASE
535#ifdef DOUBLE_PRECISION_COMPLEX
536 bind(C, name="elpa_pxgemm_multiply_a_h_a_dc")
537#endif
538#ifdef SINGLE_PRECISION_COMPLEX
539 bind(C, name="elpa_pxgemm_multiply_a_h_a_fc")
540#endif
541#endif
542
543 type(c_ptr), intent(in), value :: handle, a_p, b_p, c_p
544 character(1, c_char), value :: trans_a, trans_b
545 integer(kind=c_int), value :: ncb, nrows_b, ncols_b, nrows_c, ncols_c
546#ifdef USE_FORTRAN2008
547 integer(kind=c_int), optional, intent(in) :: error
548#else
549 integer(kind=c_int), intent(in) :: error
550#endif
551 math_datatype(kind=c_datatype_kind), pointer :: a(:, :), b(:,:), c(:,:)
552!#ifdef USE_ASSUMED_SIZE
553! MATH_DATATYPE(kind=C_DATATYPE_KIND), pointer :: b(nrows_b,*), c(nrows_c,*)
554!#else
555! MATH_DATATYPE(kind=C_DATATYPE_KIND), pointer :: b(nrows_b,ncols_b), c(nrows_c,ncols_c)
556!#endif
557 type(elpa_impl_t), pointer :: self
558
559 call c_f_pointer(handle, self)
560 call c_f_pointer(a_p, a, [self%local_nrows, self%local_ncols])
561 call c_f_pointer(b_p, b, [nrows_b, ncols_b])
562 call c_f_pointer(c_p, c, [nrows_c, ncols_c])
563
564 call elpa_pxgemm_multiply_a_h_a_&
565 &elpa_impl_suffix&
566 & (self, trans_a, trans_b, ncb, a, b, nrows_b, ncols_b, c, nrows_c, ncols_c, error)
567 end subroutine
568
569#ifdef REALCASE
570#ifdef DOUBLE_PRECISION_REAL
571 !c> void elpa_pxgemm_multiply_d_ptr_d(elpa_t handle, char trans_a, char trans_b, int ncb, double *a, double *b, int nrows_b, int ncols_b, double *c, int nrows_c, int ncols_c, int *error);
572#endif
573#ifdef SINGLE_PRECISION_REAL
574 !c> void elpa_pxgemm_multiply_d_ptr_f(elpa_t handle, char trans_a, char trans_b, int ncb, float *a, float *b, int nrows_b, int ncols_b, float *c, int nrows_c, int ncols_c, int *error);
575#endif
576#endif
577#ifdef COMPLEXCASE
578#ifdef DOUBLE_PRECISION_COMPLEX
579 !c> void elpa_pxgemm_multiply_d_ptr_dc(elpa_t handle, char trans_a, char trans_b, int ncb, double_complex *a, double_complex *b, int nrows_b, int ncols_b, double_complex *c, int nrows_c, int ncols_c, int *error);
580#endif
581#ifdef SINGLE_PRECISION_COMPLEX
582 !c> void elpa_pxgemm_multiply_d_ptr_fc(elpa_t handle, char trans_a, char trans_b, int ncb, float_complex *a, float_complex *b, int nrows_b, int ncols_b, float_complex *c, int nrows_c, int ncols_c, int *error);
583#endif
584#endif
585 subroutine elpa_pxgemm_multiply_d_ptr_&
586 &elpa_impl_suffix&
587 &_c(handle, trans_a, trans_b, ncb, a_p, b_p, nrows_b, ncols_b, c_p, nrows_c, ncols_c, error) &
588#ifdef REALCASE
589#ifdef DOUBLE_PRECISION_REAL
590 bind(C, name="elpa_pxgemm_multiply_d_ptr_d")
591#endif
592#ifdef SINGLE_PRECISION_REAL
593 bind(C, name="elpa_pxgemm_multiply_d_ptr_f")
594#endif
595#endif
596#ifdef COMPLEXCASE
597#ifdef DOUBLE_PRECISION_COMPLEX
598 bind(C, name="elpa_pxgemm_multiply_d_ptr_dc")
599#endif
600#ifdef SINGLE_PRECISION_COMPLEX
601 bind(C, name="elpa_pxgemm_multiply_d_ptr_fc")
602#endif
603#endif
604
605 type(c_ptr), intent(in), value :: handle, a_p, b_p, c_p
606 character(1, c_char), value :: trans_a, trans_b
607 integer(kind=c_int), value :: ncb, nrows_b, ncols_b, nrows_c, ncols_c
608#ifdef USE_FORTRAN2008
609 integer(kind=c_int), optional, intent(in) :: error
610#else
611 integer(kind=c_int), intent(in) :: error
612#endif
613 type(elpa_impl_t), pointer :: self
614
615 call c_f_pointer(handle, self)
616 !call c_f_pointer(a_p, a, [self%local_nrows, self%local_ncols])
617
618 call elpa_pxgemm_multiply_d_ptr_&
619 &elpa_impl_suffix&
620 & (self, trans_a, trans_b, ncb, a_p, b_p, nrows_b, ncols_b, c_p, nrows_c, ncols_c, error)
621 end subroutine
622
623! _________________________________________________________________________________________________________________________________
624
625 ! cholesky
626
627 !> \brief elpa_cholesky_a_h_a_d: class method to do a cholesky factorization
628 !>
629 !> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
630 !> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
631 !> with the class method "setup"
632 !>
633 !> It is possible to change the behaviour of the method by setting tunable parameters with the
634 !> class method "set"
635 !>
636 !> Parameters
637 !>
638 !> \param a Distributed matrix for which eigenvalues are to be computed.
639 !> Distribution is like in Scalapack.
640 !> The full matrix must be set (not only one half like in scalapack).
641 !> Destroyed on exit (upper and lower half).
642 !>
643 !> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
644 subroutine elpa_cholesky_a_h_a_&
645 &elpa_impl_suffix&
646 & (self, a, error)
647 class(elpa_impl_t) :: self
648#ifdef USE_ASSUMED_SIZE
649 math_datatype(kind=c_datatype_kind) :: a(self%local_nrows,*)
650#else
651 math_datatype(kind=c_datatype_kind) :: a(self%local_nrows,self%local_ncols)
652#endif
653#ifdef USE_FORTRAN2008
654 integer, optional :: error
655#else
656 integer :: error
657#endif
658 logical :: success_l
659
660 success_l = .false.
661#if defined(INCLUDE_ROUTINES)
662 success_l = elpa_cholesky_a_h_a_&
663 &math_datatype&
664 &_&
665 &precision&
666 &_impl(self, a)
667#endif
668
669#ifdef USE_FORTRAN2008
670 if (present(error)) then
671 if (success_l) then
672 error = elpa_ok
673 else
674 error = elpa_error
675 endif
676 else if (.not. success_l) then
677 write(error_unit,'(a)') "ELPA: Error in cholesky() and you did not check for errors!"
678 endif
679#else
680 if (success_l) then
681 error = elpa_ok
682 else
683 error = elpa_error
684 endif
685#endif
686 end subroutine
687
688#ifdef REALCASE
689#ifdef DOUBLE_PRECISION_REAL
690 !c> void elpa_cholesky_a_h_a_d(elpa_t handle, double *a, int *error);
691#endif
692#ifdef SINGLE_PRECISION_REAL
693 !c> void elpa_cholesky_a_h_a_f(elpa_t handle, float *a, int *error);
694#endif
695#endif
696#ifdef COMPLEXCASE
697#ifdef DOUBLE_PRECISION_COMPLEX
698 !c> void elpa_cholesky_a_h_a_dc(elpa_t handle, double_complex *a, int *error);
699#endif
700#ifdef SINGLE_PRECISION_COMPLEX
701 !c> void elpa_cholesky_a_h_a_fc(elpa_t handle, float_complex *a, int *error);
702#endif
703#endif
704 subroutine elpa_choleksy_a_h_a_&
705 &elpa_impl_suffix&
706 &_c(handle, a_p, error) &
707#ifdef REALCASE
708#ifdef DOUBLE_PRECISION_REAL
709 bind(C, name="elpa_cholesky_a_h_a_d")
710#endif
711#ifdef SINGLE_PRECISION_REAL
712 bind(C, name="elpa_cholesky_a_h_a_f")
713#endif
714#endif
715#ifdef COMPLEXCASE
716#ifdef DOUBLE_PRECISION_COMPLEX
717 bind(C, name="elpa_cholesky_a_h_a_dc")
718#endif
719#ifdef SINGLE_PRECISION_COMPLEX
720 bind(C, name="elpa_cholesky_a_h_a_fc")
721#endif
722#endif
723
724 type(c_ptr), intent(in), value :: handle, a_p
725#ifdef USE_FORTRAN2008
726 integer(kind=c_int), optional, intent(in) :: error
727#else
728 integer(kind=c_int), intent(in) :: error
729#endif
730 math_datatype(kind=c_datatype_kind), pointer :: a(:, :)
731 type(elpa_impl_t), pointer :: self
732
733 call c_f_pointer(handle, self)
734 call c_f_pointer(a_p, a, [self%local_nrows, self%local_ncols])
735
736 call elpa_cholesky_a_h_a_&
737 &elpa_impl_suffix&
738 & (self, a, error)
739 end subroutine
740
741
742 !> \brief elpa_cholesky_d_ptr_d: class method to do a cholesky factorization
743 !>
744 !> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
745 !> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
746 !> with the class method "setup"
747 !>
748 !> It is possible to change the behaviour of the method by setting tunable parameters with the
749 !> class method "set"
750 !>
751 !> Parameters
752 !>
753 !> \param a Distributed matrix for which eigenvalues are to be computed as type(c_ptr) on a device
754 !> Distribution is like in Scalapack.
755 !> The full matrix must be set (not only one half like in scalapack).
756 !> Destroyed on exit (upper and lower half).
757 !>
758 !> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
759 subroutine elpa_cholesky_d_ptr_&
760 &elpa_impl_suffix&
761 & (self, a, error)
762 use iso_c_binding
763 class(elpa_impl_t) :: self
764 type(c_ptr) :: a
765#ifdef USE_FORTRAN2008
766 integer, optional :: error
767#else
768 integer :: error
769#endif
770 logical :: success_l
771
772 success_l = .false.
773#if defined(INCLUDE_ROUTINES)
774 success_l = elpa_cholesky_d_ptr_&
775 &math_datatype&
776 &_&
777 &precision&
778 &_impl(self, a)
779#endif
780
781#ifdef USE_FORTRAN2008
782 if (present(error)) then
783 if (success_l) then
784 error = elpa_ok
785 else
786 error = elpa_error
787 endif
788 else if (.not. success_l) then
789 write(error_unit,'(a)') "ELPA: Error in cholesky() and you did not check for errors!"
790 endif
791#else
792 if (success_l) then
793 error = elpa_ok
794 else
795 error = elpa_error
796 endif
797#endif
798 end subroutine
799
800#ifdef REALCASE
801#ifdef DOUBLE_PRECISION_REAL
802 !c> void elpa_cholesky_d_ptr_d(elpa_t handle, double *a, int *error);
803#endif
804#ifdef SINGLE_PRECISION_REAL
805 !c> void elpa_cholesky_d_ptr_f(elpa_t handle, float *a, int *error);
806#endif
807#endif
808#ifdef COMPLEXCASE
809#ifdef DOUBLE_PRECISION_COMPLEX
810 !c> void elpa_cholesky_d_ptr_dc(elpa_t handle, double_complex *a, int *error);
811#endif
812#ifdef SINGLE_PRECISION_COMPLEX
813 !c> void elpa_cholesky_d_ptr_fc(elpa_t handle, float_complex *a, int *error);
814#endif
815#endif
816 subroutine elpa_choleksy_d_ptr_&
817 &elpa_impl_suffix&
818 &_c(handle, a_p, error) &
819#ifdef REALCASE
820#ifdef DOUBLE_PRECISION_REAL
821 bind(C, name="elpa_cholesky_d_ptr_d")
822#endif
823#ifdef SINGLE_PRECISION_REAL
824 bind(C, name="elpa_cholesky_d_ptr_f")
825#endif
826#endif
827#ifdef COMPLEXCASE
828#ifdef DOUBLE_PRECISION_COMPLEX
829 bind(C, name="elpa_cholesky_d_ptr_dc")
830#endif
831#ifdef SINGLE_PRECISION_COMPLEX
832 bind(C, name="elpa_cholesky_d_ptr_fc")
833#endif
834#endif
835
836 type(c_ptr), intent(in), value :: handle, a_p
837#ifdef USE_FORTRAN2008
838 integer(kind=c_int), optional, intent(in) :: error
839#else
840 integer(kind=c_int), intent(in) :: error
841#endif
842 type(elpa_impl_t), pointer :: self
843
844 call c_f_pointer(handle, self)
845 !call c_f_pointer(a_p, a, [self%local_nrows, self%local_ncols])
846
847 call elpa_cholesky_d_ptr_&
848 &elpa_impl_suffix&
849 & (self, a_p, error)
850 end subroutine
851
852 !_____________________________________________________________________________________________________________________
853 ! invert_trm
854
855 !> \brief elpa_invert_trm_a_h_a_d: class method to invert a triangular
856 !>
857 !> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
858 !> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
859 !> with the class method "setup"
860 !>
861 !> It is possible to change the behaviour of the method by setting tunable parameters with the
862 !> class method "set"
863 !>
864 !> Parameters
865 !>
866 !> \param a Distributed matrix for which eigenvalues are to be computed.
867 !> Distribution is like in Scalapack.
868 !> The full matrix must be set (not only one half like in scalapack).
869 !> Destroyed on exit (upper and lower half).
870 !>
871 !> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
872 subroutine elpa_invert_trm_a_h_a_&
873 &elpa_impl_suffix&
874 & (self, a, error)
875 class(elpa_impl_t) :: self
876#ifdef USE_ASSUMED_SIZE
877 math_datatype(kind=c_datatype_kind) :: a(self%local_nrows,*)
878#else
879 math_datatype(kind=c_datatype_kind) :: a(self%local_nrows,self%local_ncols)
880#endif
881#ifdef USE_FORTRAN2008
882 integer, optional :: error
883#else
884 integer :: error
885#endif
886 logical :: success_l
887
888 success_l = .false.
889#if defined(INCLUDE_ROUTINES)
890 success_l = elpa_invert_trm_a_h_a_&
891 &math_datatype&
892 &_&
893 &precision&
894 &_impl(self, a)
895#endif
896
897#ifdef USE_FORTRAN2008
898 if (present(error)) then
899 if (success_l) then
900 error = elpa_ok
901 else
902 error = elpa_error
903 endif
904 else if (.not. success_l) then
905 write(error_unit,'(a)') "ELPA: Error in invert_trm() and you did not check for errors!"
906 endif
907#else
908 if (success_l) then
909 error = elpa_ok
910 else
911 error = elpa_error
912 endif
913#endif
914 end subroutine
915
916
917
918#ifdef REALCASE
919#ifdef DOUBLE_PRECISION_REAL
920 !c> void elpa_invert_trm_a_h_a_d(elpa_t handle, double *a, int *error);
921#endif
922#ifdef SINGLE_PRECISION_REAL
923 !c> void elpa_invert_trm_a_h_a_f(elpa_t handle, float *a, int *error);
924#endif
925#endif
926#ifdef COMPLEXCASE
927#ifdef DOUBLE_PRECISION_COMPLEX
928 !c> void elpa_invert_trm_a_h_a_dc(elpa_t handle, double_complex *a, int *error);
929#endif
930#ifdef SINGLE_PRECISION_COMPLEX
931 !c> void elpa_invert_trm_a_h_a_fc(elpa_t handle, float_complex *a, int *error);
932#endif
933#endif
934 subroutine elpa_invert_trm_a_h_a_&
935 &elpa_impl_suffix&
936 &_c(handle, a_p, error) &
937#ifdef REALCASE
938#ifdef DOUBLE_PRECISION_REAL
939 bind(C, name="elpa_invert_trm_a_h_a_d")
940#endif
941#ifdef SINGLE_PRECISION_REAL
942 bind(C, name="elpa_invert_trm_a_h_a_f")
943#endif
944#endif
945#ifdef COMPLEXCASE
946#ifdef DOUBLE_PRECISION_COMPLEX
947 bind(C, name="elpa_invert_trm_a_h_a_dc")
948#endif
949#ifdef SINGLE_PRECISION_COMPLEX
950 bind(C, name="elpa_invert_trm_a_h_a_fc")
951#endif
952#endif
953
954 type(c_ptr), intent(in), value :: handle, a_p
955#ifdef USE_FORTRAN2008
956 integer(kind=c_int), optional, intent(in) :: error
957#else
958 integer(kind=c_int), intent(in) :: error
959#endif
960 math_datatype(kind=c_datatype_kind), pointer :: a(:, :)
961 type(elpa_impl_t), pointer :: self
962
963 call c_f_pointer(handle, self)
964 call c_f_pointer(a_p, a, [self%local_nrows, self%local_ncols])
965
966 call elpa_invert_trm_a_h_a_&
967 &elpa_impl_suffix&
968 & (self, a, error)
969 end subroutine
970
971
972 !> \brief elpa_invert_trm_d_ptr_d: class method to invert a triangular
973 !>
974 !> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
975 !> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
976 !> with the class method "setup"
977 !>
978 !> It is possible to change the behaviour of the method by setting tunable parameters with the
979 !> class method "set"
980 !>
981 !> Parameters
982 !>
983 !> \param a Distributed matrix for which eigenvalues are to be computed as device pointer
984 !> Distribution is like in Scalapack.
985 !> The full matrix must be set (not only one half like in scalapack).
986 !> Destroyed on exit (upper and lower half).
987 !>
988 !> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
989 subroutine elpa_invert_trm_d_ptr_&
990 &elpa_impl_suffix&
991 & (self, a, error)
992 use iso_c_binding
993 class(elpa_impl_t) :: self
994 type(c_ptr) :: a
995#ifdef USE_FORTRAN2008
996 integer, optional :: error
997#else
998 integer :: error
999#endif
1000 logical :: success_l
1001
1002 success_l = .false.
1003#if defined(INCLUDE_ROUTINES)
1004 success_l = elpa_invert_trm_d_ptr_&
1005 &math_datatype&
1006 &_&
1007 &precision&
1008 &_impl(self, a)
1009#endif
1010
1011#ifdef USE_FORTRAN2008
1012 if (present(error)) then
1013 if (success_l) then
1014 error = elpa_ok
1015 else
1016 error = elpa_error
1017 endif
1018 else if (.not. success_l) then
1019 write(error_unit,'(a)') "ELPA: Error in invert_trm() and you did not check for errors!"
1020 endif
1021#else
1022 if (success_l) then
1023 error = elpa_ok
1024 else
1025 error = elpa_error
1026 endif
1027#endif
1028 end subroutine
1029
1030
1031
1032#ifdef REALCASE
1033#ifdef DOUBLE_PRECISION_REAL
1034 !c> void elpa_invert_trm_d_ptr_d(elpa_t handle, double *a, int *error);
1035#endif
1036#ifdef SINGLE_PRECISION_REAL
1037 !c> void elpa_invert_trm_d_ptr_f(elpa_t handle, float *a, int *error);
1038#endif
1039#endif
1040#ifdef COMPLEXCASE
1041#ifdef DOUBLE_PRECISION_COMPLEX
1042 !c> void elpa_invert_trm_d_ptr_dc(elpa_t handle, double_complex *a, int *error);
1043#endif
1044#ifdef SINGLE_PRECISION_COMPLEX
1045 !c> void elpa_invert_trm_d_ptr_fc(elpa_t handle, float_complex *a, int *error);
1046#endif
1047#endif
1048 subroutine elpa_invert_trm_d_ptr_&
1049 &elpa_impl_suffix&
1050 &_c(handle, a_p, error) &
1051#ifdef REALCASE
1052#ifdef DOUBLE_PRECISION_REAL
1053 bind(C, name="elpa_invert_trm_d_ptr_d")
1054#endif
1055#ifdef SINGLE_PRECISION_REAL
1056 bind(C, name="elpa_invert_trm_d_ptr_f")
1057#endif
1058#endif
1059#ifdef COMPLEXCASE
1060#ifdef DOUBLE_PRECISION_COMPLEX
1061 bind(C, name="elpa_invert_trm_d_ptr_dc")
1062#endif
1063#ifdef SINGLE_PRECISION_COMPLEX
1064 bind(C, name="elpa_invert_trm_d_ptr_fc")
1065#endif
1066#endif
1067
1068 type(c_ptr), intent(in), value :: handle, a_p
1069#ifdef USE_FORTRAN2008
1070 integer(kind=c_int), optional, intent(in) :: error
1071#else
1072 integer(kind=c_int), intent(in) :: error
1073#endif
1074 type(elpa_impl_t), pointer :: self
1075
1076 call c_f_pointer(handle, self)
1077
1078 call elpa_invert_trm_d_ptr_&
1079 &elpa_impl_suffix&
1080 & (self, a_p, error)
1081 end subroutine
1082
1083 !_____________________________________________________________________________________________________________________
1084 ! solve_tridiagonal
1085
1086 !> \brief elpa_solve_tridiagonal_d: class method to solve the eigenvalue problem for a tridiagonal matrix a
1087 !>
1088 !> The dimensions of the matrix a (locally ditributed and global), the block-cylic-distribution
1089 !> block size, and the MPI communicators are already known to the object and MUST be set BEFORE
1090 !> with the class method "setup"
1091 !>
1092 !> It is possible to change the behaviour of the method by setting tunable parameters with the
1093 !> class method "set"
1094 !>
1095 !> Parameters
1096 !>
1097 !> \param d array d on input diagonal elements of tridiagonal matrix, on
1098 !> output the eigenvalues in ascending order
1099 !> \param e array e on input subdiagonal elements of matrix, on exit destroyed
1100 !> \param q matrix on exit : contains the eigenvectors
1101 !> \param error integer, optional: returns an error code, which can be queried with elpa_strerr
1102 subroutine elpa_solve_tridiagonal_&
1103 &elpa_impl_suffix&
1104 & (self, d, e, q, error)
1105 use solve_tridi
1106 implicit none
1107 class(elpa_impl_t) :: self
1108 real(kind=c_real_datatype) :: d(self%na), e(self%na)
1109#ifdef USE_ASSUMED_SIZE
1110 real(kind=c_real_datatype) :: q(self%local_nrows,*)
1111#else
1112 real(kind=c_real_datatype) :: q(self%local_nrows,self%local_ncols)
1113#endif
1114#ifdef USE_FORTRAN2008
1115 integer, optional :: error
1116#else
1117 integer :: error
1118#endif
1119 logical :: success_l
1120
1121#if defined(INCLUDE_ROUTINES)
1122 success_l = elpa_solve_tridi_&
1123 &precision&
1124 &_impl(self, d, e, q)
1125#else
1126 write(error_unit,*) "ELPA is not compiled with single-precision support"
1127#ifdef USE_FORTRAN2008
1128 if (present(error)) then
1129 error = elpa_error
1130 return
1131 else
1132 return
1133 endif
1134#else
1135 error = elpa_error
1136 return
1137#endif
1138#endif
1139#ifdef USE_FORTRAN2008
1140 if (present(error)) then
1141 if (success_l) then
1142 error = elpa_ok
1143 else
1144 error = elpa_error
1145 endif
1146 else if (.not. success_l) then
1147 write(error_unit,'(a)') "ELPA: Error in solve_tridiagonal() and you did not check for errors!"
1148 endif
1149#else
1150 if (success_l) then
1151 error = elpa_ok
1152 else
1153 error = elpa_error
1154 endif
1155#endif
1156 end subroutine
1157
1158
1159#ifdef DOUBLE_PRECISION_REAL
1160 !c> void elpa_solve_tridiagonal_d(elpa_t handle, double *d, double *e, double *q, int *error);
1161#endif
1162#ifdef SINGLE_PRECISION_REAL
1163 !c> void elpa_solve_tridiagonal_f(elpa_t handle, float *d, float *e, float *q, int *error);
1164#endif
1165
1166 subroutine elpa_solve_tridiagonal_&
1167 &elpa_impl_suffix&
1168 &_c(handle, d_p, e_p, q_p, error) &
1169#ifdef REALCASE
1170#ifdef DOUBLE_PRECISION_REAL
1171 bind(C, name="elpa_solve_tridiagonal_d")
1172#endif
1173#ifdef SINGLE_PRECISION_REAL
1174 bind(C, name="elpa_solve_tridiagonal_f")
1175#endif
1176#endif
1177#ifdef COMPLEXCASE
1178#ifdef DOUBLE_PRECISION_COMPLEX
1179 & !bind(C, name="elpa_solve_tridiagonal_dc")
1180#endif
1181#ifdef SINGLE_PRECISION_COMPLEX
1182 & !bind(C, name="elpa_solve_tridiagonal_fc")
1183#endif
1184#endif
1185
1186 type(c_ptr), intent(in), value :: handle, d_p, e_p, q_p
1187#ifdef USE_FORTRAN2008
1188 integer(kind=c_int), optional, intent(in) :: error
1189#else
1190 integer(kind=c_int), intent(in) :: error
1191#endif
1192 real(kind=c_real_datatype), pointer :: d(:), e(:), q(:, :)
1193 type(elpa_impl_t), pointer :: self
1194
1195 call c_f_pointer(handle, self)
1196 call c_f_pointer(d_p, d, [self%na])
1197 call c_f_pointer(e_p, e, [self%na])
1198 call c_f_pointer(q_p, q, [self%local_nrows, self%local_ncols])
1199
1200 call elpa_solve_tridiagonal_&
1201 &elpa_impl_suffix&
1202 & (self, d, e, q, error)
1203 end subroutine
1204
Definition mod_solve_tridi.F90:3