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