1 /*
2 !
3 !    Copyright 2017, L. Hüdepohl and A. Marek, MPCDF
4 !
5 !    This file is part of ELPA.
6 !
7 !    The ELPA library was originally created by the ELPA consortium,
8 !    consisting of the following organizations:
9 !
10 !    - Max Planck Computing and Data Facility (MPCDF), formerly known as
11 !      Rechenzentrum Garching der Max-Planck-Gesellschaft (RZG),
12 !    - Bergische Universität Wuppertal, Lehrstuhl für angewandte
13 !      Informatik,
14 !    - Technische Universität München, Lehrstuhl für Informatik mit
15 !      Schwerpunkt Wissenschaftliches Rechnen ,
16 !    - Fritz-Haber-Institut, Berlin, Abt. Theorie,
17 !    - Max-Plack-Institut für Mathematik in den Naturwissenschaften,
18 !      Leipzig, Abt. Komplexe Strukutren in Biologie und Kognition,
19 !      and
20 !    - IBM Deutschland GmbH
21 !
22 !    This particular source code file contains additions, changes and
23 !    enhancements authored by Intel Corporation which is not part of
24 !    the ELPA consortium.
25 !
26 !    More information can be found here:
27 !    http://elpa.mpcdf.mpg.de/
28 !
29 !    ELPA is free software: you can redistribute it and/or modify
30 !    it under the terms of the version 3 of the license of the
31 !    GNU Lesser General Public License as published by the Free
32 !    Software Foundation.
33 !
34 !    ELPA is distributed in the hope that it will be useful,
35 !    but WITHOUT ANY WARRANTY; without even the implied warranty of
36 !    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37 !    GNU Lesser General Public License for more details.
38 !
39 !    You should have received a copy of the GNU Lesser General Public License
40 !    along with ELPA.  If not, see <http://www.gnu.org/licenses/>
41 !
42 !    ELPA reflects a substantial effort on the part of the original
43 !    ELPA consortium, and we ask you to respect the spirit of the
44 !    license that we chose: i.e., please contribute any changes you
45 !    may have back to the original ELPA library distribution, and keep
46 !    any derivatives of ELPA under the same license that we chose for
47 !    the original distribution, the GNU Lesser General Public License.
48 !
49 */
50 #pragma once
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <search.h>
55 #include <math.h>
56 
57 #include "config.h"
58 #include <elpa/elpa.h>
59 
60 #define nelements(x) (sizeof(x)/sizeof(x[0]))
61 
62 #define FOR_ALL_TYPES(X) \
63         X(int, "%d", "%d", -1) \
64         X(double, "%g", "%lg", NAN)
65 
66 /* A simple structure for storing values to a pre-set
67  * number of keys */
68 
69 /* Forward declaration of configuration structure */
70 typedef struct elpa_index_struct* elpa_index_t;
71 
72 /* Function type for the cardinality */
73 typedef int (*elpa_index_cardinality_t)(elpa_index_t index);
74 
75 /* Function type to enumerate all possible values, starting from 0 */
76 typedef int (*elpa_index_enumerate_int_option_t)(elpa_index_t index, int i);
77 
78 /* Function types to check the validity of a value */
79 typedef int (*elpa_index_valid_int_t)(elpa_index_t index, int n, int new_value);
80 typedef int (*elpa_index_valid_double_t)(elpa_index_t index, int n, double new_value);
81 
82 /* Function type to give a string representation of a value */
83 typedef const char* (*elpa_index_to_string_int_t)(int n);
84 
85 
86 typedef struct {
87         char *name;
88         char *description;
89         char *env_default;
90         char *env_force;
91         int once;
92         int readonly;
93         int print_flag;
94 } elpa_index_entry_t;
95 
96 
97 typedef struct {
98         elpa_index_entry_t base;
99         int default_value;
100         int autotune_level;
101         int autotune_domain;
102         elpa_index_valid_int_t valid;
103         elpa_index_cardinality_t cardinality;
104         elpa_index_enumerate_int_option_t enumerate;
105         elpa_index_to_string_int_t to_string;
106 } elpa_index_int_entry_t;
107 
108 
109 typedef struct {
110         elpa_index_entry_t base;
111         double default_value;
112         elpa_index_valid_double_t valid;
113 } elpa_index_double_entry_t;
114 
115 enum NOTIFY_FLAGS {
116         NOTIFY_ENV_DEFAULT = (1<<0),
117         NOTIFY_ENV_FORCE   = (1<<1),
118 };
119 
120 enum PRINT_FLAGS {
121         PRINT_STRUCTURE,
122         PRINT_YES,
123         PRINT_NO,
124 };
125 
126 struct elpa_index_struct {
127 #define STRUCT_MEMBERS(TYPE, ...) \
128         struct { \
129         TYPE *values; \
130         int *is_set; \
131         int *notified; \
132         } TYPE##_options;
133         FOR_ALL_TYPES(STRUCT_MEMBERS)
134 };
135 
136 
137 /*
138  !f> interface
139  !f>   function elpa_index_instance_c() result(index) bind(C, name="elpa_index_instance")
140  !f>     import c_ptr
141  !f>     type(c_ptr) :: index
142  !f>   end function
143  !f> end interface
144  */
145 elpa_index_t elpa_index_instance();
146 
147 
148 /*
149  !f> interface
150  !f>   subroutine elpa_index_free_c(index) bind(C, name="elpa_index_free")
151  !f>     import c_ptr
152  !f>     type(c_ptr), value :: index
153  !f>   end subroutine
154  !f> end interface
155  */
156 void elpa_index_free(elpa_index_t index);
157 
158 
159 /*
160  !f> interface
161  !f>   function elpa_index_get_int_value_c(index, name, success) result(value) &
162  !f>       bind(C, name="elpa_index_get_int_value")
163  !f>     import c_ptr, c_int, c_char
164  !f>     type(c_ptr), value                         :: index
165  !f>     character(kind=c_char), intent(in)         :: name(*)
166  !f>#ifdef USE_FORTRAN2008
167  !f>     integer(kind=c_int), optional, intent(out) :: success
168  !f>#else
169  !f>     integer(kind=c_int), intent(out)           :: success
170  !f>#endif
171  !f>     integer(kind=c_int)                        :: value
172  !f>   end function
173  !f> end interface
174  */
175 int elpa_index_get_int_value(elpa_index_t index, char *name, int *success);
176 
177 
178 /*
179  !f> interface
180  !f>   function elpa_index_set_int_value_c(index, name, value) result(success) &
181  !f>       bind(C, name="elpa_index_set_int_value")
182  !f>     import c_ptr, c_int, c_char
183  !f>     type(c_ptr), value                    :: index
184  !f>     character(kind=c_char), intent(in)    :: name(*)
185  !f>     integer(kind=c_int),intent(in), value :: value
186  !f>     integer(kind=c_int)                   :: success
187  !f>   end function
188  !f> end interface
189  */
190 int elpa_index_set_int_value(elpa_index_t index, char *name, int value);
191 
192 
193 /*
194  !f> interface
195  !f>   function elpa_index_int_value_is_set_c(index, name) result(success) bind(C, name="elpa_index_int_value_is_set")
196  !f>     import c_ptr, c_int, c_char
197  !f>     type(c_ptr), value                    :: index
198  !f>     character(kind=c_char), intent(in)    :: name(*)
199  !f>     integer(kind=c_int)                   :: success
200  !f>   end function
201  !f> end interface
202  */
203 int elpa_index_int_value_is_set(elpa_index_t index, char *name);
204 
205 
206 /*
207  !f> interface
208  !f>   function elpa_index_get_int_loc_c(index, name) result(loc) bind(C, name="elpa_index_get_int_loc")
209  !f>     import c_ptr, c_char
210  !f>     type(c_ptr), value                 :: index
211  !f>     character(kind=c_char), intent(in) :: name(*)
212  !f>     type(c_ptr)                        :: loc
213  !f>   end function
214  !f> end interface
215  */
216 int* elpa_index_get_int_loc(elpa_index_t index, char *name);
217 
218 
219 /*
220  !f> interface
221  !f>   function elpa_index_get_double_value_c(index, name, success) result(value) bind(C, name="elpa_index_get_double_value")
222  !f>     import c_ptr, c_int, c_double, c_char
223  !f>     type(c_ptr), value                              :: index
224  !f>     character(kind=c_char), intent(in)              :: name(*)
225  !f>#ifdef USE_FORTRAN2008
226  !f>     integer(kind=c_int), intent(out), optional      :: success
227  !f>#else
228  !f>     integer(kind=c_int), intent(out)                :: success
229  !f>#endif
230  !f>     real(kind=c_double)                             :: value
231  !f>   end function
232  !f> end interface
233  */
234 double elpa_index_get_double_value(elpa_index_t index, char *name, int *success);
235 
236 
237 /*
238  !f> interface
239  !f>   function elpa_index_set_double_value_c(index, name, value) result(success) &
240  !f>       bind(C, name="elpa_index_set_double_value")
241  !f>     import c_ptr, c_int, c_double, c_char
242  !f>     type(c_ptr), value                    :: index
243  !f>     character(kind=c_char), intent(in)    :: name(*)
244  !f>     real(kind=c_double),intent(in), value :: value
245  !f>     integer(kind=c_int)                   :: success
246  !f>   end function
247  !f> end interface
248  */
249 int elpa_index_set_double_value(elpa_index_t index, char *name, double value);
250 
251 
252 /*
253  !f> interface
254  !f>   function elpa_index_double_value_is_set_c(index, name) result(success) &
255  !f>       bind(C, name="elpa_index_double_value_is_set")
256  !f>     import c_ptr, c_int, c_char
257  !f>     type(c_ptr), value                    :: index
258  !f>     character(kind=c_char), intent(in)    :: name(*)
259  !f>     integer(kind=c_int)                   :: success
260  !f>   end function
261  !f> end interface
262  */
263 int elpa_index_double_value_is_set(elpa_index_t index, char *name);
264 
265 
266 /*
267  !f> interface
268  !f>   function elpa_index_get_double_loc_c(index, name) result(loc) bind(C, name="elpa_index_get_double_loc")
269  !f>     import c_ptr, c_char
270  !f>     type(c_ptr), value                 :: index
271  !f>     character(kind=c_char), intent(in) :: name(*)
272  !f>     type(c_ptr)                        :: loc
273  !f>   end function
274  !f> end interface
275  */
276 double* elpa_index_get_double_loc(elpa_index_t index, char *name);
277 
278 
279 /*
280  !f> interface
281  !f>   function elpa_index_value_is_set_c(index, name) result(success) bind(C, name="elpa_index_value_is_set")
282  !f>     import c_ptr, c_int, c_char
283  !f>     type(c_ptr), value                    :: index
284  !f>     character(kind=c_char), intent(in)    :: name(*)
285  !f>     integer(kind=c_int)                   :: success
286  !f>   end function
287  !f> end interface
288  */
289 int elpa_index_value_is_set(elpa_index_t index, char *name);
290 
291 
292 /*
293  !pf> interface
294  !pf>   function elpa_int_value_to_string_c(name, value, string) &
295  !pf>              result(error) bind(C, name="elpa_int_value_to_string")
296  !pf>     import c_int, c_ptr, c_char
297  !pf>     character(kind=c_char), intent(in) :: name(*)
298  !pf>     integer(kind=c_int), intent(in), value :: value
299  !pf>     type(c_ptr), intent(out) :: string
300  !pf>     integer(kind=c_int) :: error
301  !pf>   end function
302  !pf> end interface
303  !pf>
304  */
305 int elpa_int_value_to_string(char *name, int value, const char **string);
306 
307 
308 /*
309  !pf> interface
310  !pf>   pure function elpa_int_value_to_strlen_c(name, value) &
311  !pf>                   result(length) bind(C, name="elpa_int_value_to_strlen")
312  !pf>     import c_int, c_ptr, c_char
313  !pf>     character(kind=c_char), intent(in) :: name(*)
314  !pf>     integer(kind=c_int), intent(in), value :: value
315  !pf>     integer(kind=c_int) :: length
316  !pf>   end function
317  !pf> end interface
318  !pf>
319  */
320 int elpa_int_value_to_strlen(char *name, int value);
321 
322 
323 /*
324  !f> interface
325  !f>   pure function elpa_index_int_value_to_strlen_c(index, name) &
326  !f>                   result(length) bind(C, name="elpa_index_int_value_to_strlen")
327  !f>     import c_int, c_ptr, c_char
328  !f>     type(c_ptr), intent(in), value :: index
329  !f>     character(kind=c_char), intent(in) :: name(*)
330  !f>     integer(kind=c_int) :: length
331  !f>   end function
332  !f> end interface
333  !f>
334  */
335 int elpa_index_int_value_to_strlen(elpa_index_t index, char *name);
336 
337 
338 /*
339  !f> interface
340  !f>   function elpa_int_string_to_value_c(name, string, value) result(error) bind(C, name="elpa_int_string_to_value")
341  !f>     import c_int, c_ptr, c_char
342  !f>     character(kind=c_char), intent(in) :: name(*)
343  !f>     character(kind=c_char), intent(in) :: string(*)
344  !f>     integer(kind=c_int), intent(out) :: value
345  !f>     integer(kind=c_int) :: error
346  !f>   end function
347  !f> end interface
348  !f>
349  */
350 int elpa_int_string_to_value(char *name, char *string, int *value);
351 
352 
353 /*
354  !f> interface
355  !f>   function elpa_option_cardinality_c(name) result(n) bind(C, name="elpa_option_cardinality")
356  !f>     import c_int, c_char
357  !f>     character(kind=c_char), intent(in) :: name(*)
358  !f>     integer(kind=c_int) :: n
359  !f>   end function
360  !f> end interface
361  !f>
362  */
363 int elpa_option_cardinality(char *name);
364 
365 /*
366  !f> interface
367  !f>   function elpa_option_enumerate_c(name, i) result(value) bind(C, name="elpa_option_enumerate")
368  !f>     import c_int, c_char
369  !f>     character(kind=c_char), intent(in) :: name(*)
370  !f>     integer(kind=c_int), intent(in), value :: i
371  !f>     integer(kind=c_int) :: value
372  !f>   end function
373  !f> end interface
374  !f>
375  */
376 int elpa_option_enumerate(char *name, int i);
377 
378 
379 /*
380  !f> interface
381  !f>   function elpa_index_int_is_valid_c(index, name, new_value) result(success) &
382  !f>       bind(C, name="elpa_index_int_is_valid")
383  !f>     import c_int, c_ptr, c_char
384  !f>     type(c_ptr), intent(in), value :: index
385  !f>     character(kind=c_char), intent(in) :: name(*)
386  !f>     integer(kind=c_int), intent(in), value :: new_value
387  !f>     integer(kind=c_int) :: success
388  !f>   end function
389  !f> end interface
390  !f>
391  */
392 int elpa_index_int_is_valid(elpa_index_t index, char *name, int new_value);
393 
394 
395 /*
396  !f> interface
397  !f>   function elpa_index_autotune_cardinality_c(index, autotune_level, autotune_domain) result(n) &
398  !f>       bind(C, name="elpa_index_autotune_cardinality")
399  !f>     import c_int, c_ptr, c_char
400  !f>     type(c_ptr), intent(in), value :: index
401  !f>     integer(kind=c_int), intent(in), value :: autotune_level, autotune_domain
402  !f>     integer(kind=c_int) :: n
403  !f>   end function
404  !f> end interface
405  !f>
406  */
407 int elpa_index_autotune_cardinality(elpa_index_t index, int autotune_level, int autotune_domain);
408 
409 
410 /*
411  !f> interface
412  !f>   function elpa_index_set_autotune_parameters_c(index, autotune_level, autotune_domain, n) result(success) &
413  !f>       bind(C, name="elpa_index_set_autotune_parameters")
414  !f>     import c_int, c_ptr, c_char
415  !f>     type(c_ptr), intent(in), value :: index
416  !f>     integer(kind=c_int), intent(in), value :: autotune_level, autotune_domain, n
417  !f>     integer(kind=c_int) :: success
418  !f>   end function
419  !f> end interface
420  !f>
421  */
422 int elpa_index_set_autotune_parameters(elpa_index_t index, int autotune_level, int autotune_domain, int n);
423 
424 /*
425  !f> interface
426  !f>   function elpa_index_print_autotune_parameters_c(index, autotune_level, autotune_domain) result(success) &
427  !f>       bind(C, name="elpa_index_print_autotune_parameters")
428  !f>     import c_int, c_ptr, c_char
429  !f>     type(c_ptr), intent(in), value :: index
430  !f>     integer(kind=c_int), intent(in), value :: autotune_level, autotune_domain
431  !f>     integer(kind=c_int) :: success
432  !f>   end function
433  !f> end interface
434  !f>
435  */
436 int elpa_index_print_autotune_parameters(elpa_index_t index, int autotune_level, int autotune_domain);
437 
438 /*
439  !f> interface
440  !f>   function elpa_index_print_settings_c(index, file_name) result(success) &
441  !f>       bind(C, name="elpa_index_print_settings")
442  !f>     import c_int, c_ptr, c_char
443  !f>     type(c_ptr), intent(in), value :: index
444  !f>     character(kind=c_char), intent(in)     :: file_name(*)
445  !f>     integer(kind=c_int) :: success
446  !f>   end function
447  !f> end interface
448  !f>
449  */
450 int elpa_index_print_settings(elpa_index_t index, char* filename);
451 
452 /*
453  !f> interface
454  !f>   function elpa_index_load_settings_c(index, file_name) result(success) &
455  !f>       bind(C, name="elpa_index_load_settings")
456  !f>     import c_int, c_ptr, c_char
457  !f>     type(c_ptr), intent(in), value :: index
458  !f>     character(kind=c_char), intent(in)     :: file_name(*)
459  !f>     integer(kind=c_int) :: success
460  !f>   end function
461  !f> end interface
462  !f>
463  */
464 int elpa_index_load_settings(elpa_index_t index, char* filename);
465 
466 /*
467  !f> interface
468  !f>   function elpa_index_print_autotune_state_c(index, autotune_level, autotune_domain, min_loc, &
469  !f>                                              min_val, current, cardinality, file_name) result(success) &
470  !f>       bind(C, name="elpa_index_print_autotune_state")
471  !f>     import c_int, c_ptr, c_char, c_double
472  !f>     type(c_ptr), intent(in), value :: index
473  !f>     integer(kind=c_int), intent(in), value :: autotune_level, autotune_domain, min_loc, current, cardinality
474  !f>     real(kind=c_double), intent(in), value :: min_val
475  !f>     character(kind=c_char), intent(in)     :: file_name(*)
476  !f>     integer(kind=c_int) :: success
477  !f>   end function
478  !f> end interface
479  !f>
480  */
481 int elpa_index_print_autotune_state(elpa_index_t index, int autotune_level, int autotune_domain, int min_loc,
482                                     double min_val, int current, int cardinality, char* filename);
483 
484 /*
485  !f> interface
486  !f>   function elpa_index_load_autotune_state_c(index, autotune_level, autotune_domain, min_loc, &
487  !f>                                              min_val, current, cardinality, file_name) result(success) &
488  !f>       bind(C, name="elpa_index_load_autotune_state")
489  !f>     import c_int, c_ptr, c_char, c_double
490  !f>     type(c_ptr), intent(in), value :: index
491  !f>     integer(kind=c_int), intent(in) :: autotune_level, autotune_domain, min_loc, current, cardinality
492  !f>     real(kind=c_double), intent(in) :: min_val
493  !f>     character(kind=c_char), intent(in)     :: file_name(*)
494  !f>     integer(kind=c_int) :: success
495  !f>   end function
496  !f> end interface
497  !f>
498  */
499 int elpa_index_load_autotune_state(elpa_index_t index, int* autotune_level, int* autotune_domain, int* min_loc,
500                                     double* min_val, int* current, int* cardinality, char* filename);
501 
502 int elpa_index_is_printing_mpi_rank(elpa_index_t index);
503