1 #ifndef PETSC_STRING_H 2 #define PETSC_STRING_H 3 4 #include <petscsystypes.h> 5 #include <petscerror.h> 6 #include <petscmacros.h> 7 #include <petscsys.h> 8 9 /* SUBMANSEC = Sys */ 10 11 #include <stddef.h> /* size_t */ 12 #include <string.h> /* for memcpy, memset */ 13 14 PETSC_EXTERN PetscErrorCode PetscMemcmp(const void *, const void *, size_t, PetscBool *); 15 PETSC_EXTERN PetscErrorCode PetscStrToArray(const char[], char, int *, char ***); 16 PETSC_EXTERN PetscErrorCode PetscStrToArrayDestroy(int, char **); 17 PETSC_EXTERN PetscErrorCode PetscStrcasecmp(const char[], const char[], PetscBool *); 18 PETSC_EXTERN PetscErrorCode PetscStrendswithwhich(const char[], const char *const *, PetscInt *); 19 PETSC_EXTERN PetscErrorCode PetscStrArrayallocpy(const char *const *, char ***); 20 PETSC_EXTERN PetscErrorCode PetscStrArrayDestroy(char ***); 21 PETSC_EXTERN PetscErrorCode PetscStrNArrayallocpy(PetscInt, const char *const *, char ***); 22 PETSC_EXTERN PetscErrorCode PetscStrNArrayDestroy(PetscInt, char ***); 23 PETSC_EXTERN PetscErrorCode PetscStrreplace(MPI_Comm, const char[], char[], size_t); 24 25 PETSC_EXTERN PetscErrorCode PetscTokenCreate(const char[], char, PetscToken *); 26 PETSC_EXTERN PetscErrorCode PetscTokenFind(PetscToken, char *[]); 27 PETSC_EXTERN PetscErrorCode PetscTokenDestroy(PetscToken *); 28 29 PETSC_EXTERN PetscErrorCode PetscStrInList(const char[], const char[], char, PetscBool *); 30 PETSC_EXTERN const char *PetscBasename(const char[]); 31 PETSC_EXTERN PetscErrorCode PetscEListFind(PetscInt, const char *const *, const char *, PetscInt *, PetscBool *); 32 PETSC_EXTERN PetscErrorCode PetscEnumFind(const char *const *, const char *, PetscEnum *, PetscBool *); 33 34 PETSC_EXTERN PetscErrorCode PetscStrcat(char[], const char[]); 35 PETSC_EXTERN PetscErrorCode PetscStrcpy(char[], const char[]); 36 37 #define PetscAssertPointer_Private(ptr, arg) PetscAssert((ptr), PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter '" PetscStringize(ptr) "' # " PetscStringize(arg)) 38 39 /*@C 40 PetscStrtolower - Converts string to lower case 41 42 Not Collective, No Fortran Support 43 44 Input Parameters: 45 . a - pointer to string 46 47 Level: intermediate 48 49 .seealso: `PetscStrtoupper()` 50 @*/ 51 static inline PetscErrorCode PetscStrtolower(char a[]) 52 { 53 PetscFunctionBegin; 54 PetscAssertPointer_Private(a, 1); 55 while (*a) { 56 if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A'; 57 a++; 58 } 59 PetscFunctionReturn(PETSC_SUCCESS); 60 } 61 62 /*@C 63 PetscStrtoupper - Converts string to upper case 64 65 Not Collective, No Fortran Support 66 67 Input Parameters: 68 . a - pointer to string 69 70 Level: intermediate 71 72 .seealso: `PetscStrtolower()` 73 @*/ 74 static inline PetscErrorCode PetscStrtoupper(char a[]) 75 { 76 PetscFunctionBegin; 77 PetscAssertPointer_Private(a, 1); 78 while (*a) { 79 if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a'; 80 a++; 81 } 82 PetscFunctionReturn(PETSC_SUCCESS); 83 } 84 85 /*@C 86 PetscStrlen - Gets length of a string 87 88 Not Collective, No Fortran Support 89 90 Input Parameters: 91 . s - pointer to string 92 93 Output Parameter: 94 . len - length in bytes 95 96 Level: intermediate 97 98 Notes: 99 This routine is analogous to `strlen()`. `NULL` string returns a length of zero. 100 101 .seealso: `PetscStrallocpy()` 102 @*/ 103 static inline PetscErrorCode PetscStrlen(const char s[], size_t *len) 104 { 105 PetscFunctionBegin; 106 PetscAssertPointer_Private(len, 2); 107 if (s) { 108 #if PetscHasBuiltin(__builtin_strlen) 109 *len = __builtin_strlen(s); 110 #else 111 *len = strlen(s); 112 #endif 113 } else { 114 *len = 0; 115 } 116 PetscFunctionReturn(PETSC_SUCCESS); 117 } 118 119 /*@C 120 PetscStrallocpy - Allocates space to hold a copy of a string then copies the string in the new space 121 122 Not Collective, No Fortran Support 123 124 Input Parameters: 125 . s - pointer to string 126 127 Output Parameter: 128 . t - the copied string 129 130 Level: intermediate 131 132 Notes: 133 `NULL` string returns a new `NULL` string. 134 135 If `t` has previously been allocated then that memory is lost, you may need to `PetscFree()` 136 the array before calling this routine. 137 138 .seealso: `PetscStrArrayallocpy()`, `PetscStrNArrayallocpy()` 139 @*/ 140 static inline PetscErrorCode PetscStrallocpy(const char s[], char *t[]) 141 { 142 PetscFunctionBegin; 143 PetscAssertPointer_Private(t, 2); 144 *t = PETSC_NULLPTR; 145 if (s) { 146 size_t len; 147 char *tmp; 148 149 PetscAssertPointer_Private(s, 1); 150 PetscCall(PetscStrlen(s, &len)); 151 PetscCall(PetscMalloc1(len + 1, &tmp)); 152 #if PetscHasBuiltin(__builtin_memcpy) 153 __builtin_memcpy(tmp, s, len); 154 #else 155 memcpy(tmp, s, len); 156 #endif 157 tmp[len] = '\0'; 158 *t = tmp; 159 } 160 PetscFunctionReturn(PETSC_SUCCESS); 161 } 162 163 static inline void PetscStrcmpNoError(const char a[], const char b[], PetscBool *flg) 164 { 165 if (!a && !b) { 166 *flg = PETSC_TRUE; 167 } else if (!a || !b) { 168 *flg = PETSC_FALSE; 169 } else { 170 #if PetscHasBuiltin(__builtin_strcmp) 171 *flg = __builtin_strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE; 172 #else 173 *flg = strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE; 174 #endif 175 } 176 } 177 178 /*@C 179 PetscStrcmp - Compares two strings, 180 181 Not Collective, No Fortran Support 182 183 Input Parameters: 184 + a - pointer to string first string 185 - b - pointer to second string 186 187 Output Parameter: 188 . flg - `PETSC_TRUE` if the two strings are equal 189 190 Level: intermediate 191 192 .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()` 193 @*/ 194 static inline PetscErrorCode PetscStrcmp(const char a[], const char b[], PetscBool *flg) 195 { 196 PetscFunctionBegin; 197 PetscAssertPointer_Private(flg, 3); 198 PetscStrcmpNoError(a, b, flg); 199 PetscFunctionReturn(PETSC_SUCCESS); 200 } 201 202 /*@C 203 PetscStrncpy - Copies a string up to a certain length 204 205 Not Collective 206 207 Input Parameters: 208 + t - pointer to string 209 - n - the length to copy 210 211 Output Parameter: 212 . s - the copied string 213 214 Level: intermediate 215 216 Notes: 217 `NULL` string returns a string starting with zero. 218 219 If the string that is being copied is of length `n` or larger, then the entire string is not 220 copied and the final location of `s` is set to `NULL`. This is different then the behavior of 221 `strncpy()` which leaves `s` non-terminated if there is not room for the entire string. 222 223 Developers Notes: 224 Should this be `PetscStrlcpy()` to reflect its behavior which is like `strlcpy()` not 225 `strncpy()`? 226 227 .seealso: `PetscStrlcat()`, `PetscStrallocpy()` 228 @*/ 229 static inline PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n) 230 { 231 PetscFunctionBegin; 232 if (s) PetscAssert(n, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Requires an output string of length at least 1 to hold the termination character"); 233 if (t) { 234 PetscAssertPointer_Private(s, 1); 235 #if defined(__GNUC__) && !defined(__clang__) 236 #if __GNUC__ >= 8 237 #pragma GCC diagnostic push 238 #pragma GCC diagnostic ignored "-Wstringop-truncation" 239 #endif 240 #endif 241 #if PetscHasBuiltin(__builtin_strncpy) 242 __builtin_strncpy(s, t, n); 243 #else 244 strncpy(s, t, n); 245 #endif 246 #if defined(__GNUC__) && !defined(__clang__) 247 #if __GNUC__ >= 8 248 #pragma GCC diagnostic pop 249 #endif 250 #endif 251 s[n - 1] = '\0'; 252 } else if (s) { 253 s[0] = '\0'; 254 } 255 PetscFunctionReturn(PETSC_SUCCESS); 256 } 257 258 /*@C 259 PetscStrlcat - Concatenates a string onto a given string, up to a given length 260 261 Not Collective, No Fortran Support 262 263 Input Parameters: 264 + s - pointer to string to be added to at end 265 . t - string to be added 266 - n - length of the original allocated string 267 268 Level: intermediate 269 270 Notes: 271 Unlike the system call `strncat()`, the length passed in is the length of the 272 original allocated space, not the length of the left-over space. This is 273 similar to the BSD system call `strlcat()`. 274 275 .seealso: `PetscStrncpy()` 276 @*/ 277 static inline PetscErrorCode PetscStrlcat(char s[], const char t[], size_t n) 278 { 279 size_t len; 280 281 PetscFunctionBegin; 282 if (!t) PetscFunctionReturn(PETSC_SUCCESS); 283 PetscAssert(n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "String buffer length must be positive"); 284 PetscCall(PetscStrlen(s, &len)); 285 #if PetscHasBuiltin(__builtin_strncat) 286 __builtin_strncat(s, t, n - len); 287 #else 288 strncat(s, t, n - len); 289 #endif 290 s[n - 1] = '\0'; 291 PetscFunctionReturn(PETSC_SUCCESS); 292 } 293 294 /*@C 295 PetscStrncmp - Compares two strings, up to a certain length 296 297 Not Collective, No Fortran Support 298 299 Input Parameters: 300 + a - pointer to first string 301 . b - pointer to second string 302 - n - length to compare up to 303 304 Output Parameter: 305 . t - `PETSC_TRUE` if the two strings are equal, `PETSC_FALSE` otherwise 306 307 Level: intermediate 308 309 Notes: 310 If `n` is `0`, `t` is set to `PETSC_FALSE`. `a` and/or `b` may be `NULL` in this case. 311 312 .seealso: `PetscStrgrt()`, `PetscStrcmp()`, `PetscStrcasecmp()` 313 @*/ 314 static inline PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t) 315 { 316 PetscFunctionBegin; 317 PetscAssertPointer_Private(t, 4); 318 *t = PETSC_FALSE; 319 if (n) { 320 PetscAssertPointer_Private(a, 1); 321 PetscAssertPointer_Private(b, 2); 322 } 323 #if PetscHasBuiltin(__builtin_strncmp) 324 *t = __builtin_strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE; 325 #else 326 *t = strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE; 327 #endif 328 PetscFunctionReturn(PETSC_SUCCESS); 329 } 330 331 /*@C 332 PetscStrrstr - Locates last occurrence of string in another string 333 334 Not Collective, No Fortran Support 335 336 Input Parameters: 337 + a - pointer to string 338 - b - string to find 339 340 Output Parameter: 341 . tmp - location of occurrence 342 343 Level: intermediate 344 345 .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, 346 `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`, 347 `PetscStrcmp()` 348 @*/ 349 static inline PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[]) 350 { 351 const char *ltmp = PETSC_NULLPTR; 352 353 PetscFunctionBegin; 354 PetscAssertPointer_Private(a, 1); 355 PetscAssertPointer_Private(b, 2); 356 PetscAssertPointer_Private(tmp, 3); 357 while (a) { 358 #if PetscHasBuiltin(__builtin_strstr) 359 a = (char *)__builtin_strstr(a, b); 360 #else 361 a = (char *)strstr(a, b); 362 #endif 363 if (a) ltmp = a++; 364 } 365 *tmp = (char *)ltmp; 366 PetscFunctionReturn(PETSC_SUCCESS); 367 } 368 369 /*@C 370 PetscStrstr - Locates first occurrence of string in another string 371 372 Not Collective, No Fortran Support 373 374 Input Parameters: 375 + haystack - string to search 376 - needle - string to find 377 378 Output Parameter: 379 . tmp - location of `needle` within `haystack`, `NULL` if `needle` is not found 380 381 Level: intermediate 382 383 .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, 384 `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`, 385 `PetscStrcmp()` 386 @*/ 387 static inline PetscErrorCode PetscStrstr(const char haystack[], const char needle[], char *tmp[]) 388 { 389 PetscFunctionBegin; 390 PetscAssertPointer_Private(haystack, 1); 391 PetscAssertPointer_Private(needle, 2); 392 PetscAssertPointer_Private(tmp, 3); 393 #if PetscHasBuiltin(__builtin_strstr) 394 *tmp = (char *)__builtin_strstr(haystack, needle); 395 #else 396 *tmp = (char *)strstr(haystack, needle); 397 #endif 398 PetscFunctionReturn(PETSC_SUCCESS); 399 } 400 401 /*@C 402 PetscStrgrt - If first string is greater than the second 403 404 Not Collective, No Fortran Support 405 406 Input Parameters: 407 + a - pointer to first string 408 - b - pointer to second string 409 410 Output Parameter: 411 . flg - `PETSC_TRUE` if `a` is strictly greater than `b`, `PETSC_FALSE` otherwise 412 413 Level: intermediate 414 415 Notes: 416 `NULL` arguments are OK, a `NULL` string is considered smaller than all others. If both `a` 417 and `b` are `NULL` then `t` is set to `PETSC_FALSE`. 418 419 .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrcasecmp()` 420 @*/ 421 static inline PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t) 422 { 423 PetscFunctionBegin; 424 PetscAssertPointer_Private(t, 3); 425 if (!a && !b) { 426 *t = PETSC_FALSE; 427 } else if (a && !b) { 428 *t = PETSC_TRUE; 429 } else if (!a && b) { 430 *t = PETSC_FALSE; 431 } else { 432 #if PetscHasBuiltin(__builtin_strcmp) 433 *t = __builtin_strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE; 434 #else 435 *t = strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE; 436 #endif 437 } 438 PetscFunctionReturn(PETSC_SUCCESS); 439 } 440 441 /*@C 442 PetscStrchr - Locates first occurrence of a character in a string 443 444 Not Collective, No Fortran Support 445 446 Input Parameters: 447 + a - pointer to string 448 - b - character 449 450 Output Parameter: 451 . c - location of occurrence, `NULL` if not found 452 453 Level: intermediate 454 455 .seealso: `PetscStrrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()` 456 @*/ 457 static inline PetscErrorCode PetscStrchr(const char a[], char b, char *c[]) 458 { 459 PetscFunctionBegin; 460 PetscAssertPointer_Private(a, 1); 461 PetscAssertPointer_Private(c, 3); 462 #if PetscHasBuiltin(__builtin_strchr) 463 *c = (char *)__builtin_strchr(a, b); 464 #else 465 *c = (char *)strchr(a, b); 466 #endif 467 PetscFunctionReturn(PETSC_SUCCESS); 468 } 469 470 /*@C 471 PetscStrrchr - Locates one location past the last occurrence of a character in a string, if 472 the character is not found then returns entire string 473 474 Not Collective, No Fortran Support 475 476 Input Parameters: 477 + a - pointer to string 478 - b - character 479 480 Output Parameter: 481 . tmp - one past location of `b` in `a`, or `a` if `b` was not found 482 483 Level: intermediate 484 485 .seealso: `PetscStrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()` 486 @*/ 487 static inline PetscErrorCode PetscStrrchr(const char a[], char b, char *tmp[]) 488 { 489 PetscFunctionBegin; 490 PetscAssertPointer_Private(a, 1); 491 PetscAssertPointer_Private(tmp, 3); 492 #if PetscHasBuiltin(__builtin_strrchr) 493 *tmp = (char *)__builtin_strrchr(a, b); 494 #else 495 *tmp = (char *)strrchr(a, b); 496 #endif 497 if (!*tmp) { 498 *tmp = (char *)a; 499 } else { 500 *tmp = *tmp + 1; 501 } 502 PetscFunctionReturn(PETSC_SUCCESS); 503 } 504 505 /*@C 506 PetscStrendswith - Determines if a string ends with a certain string 507 508 Not Collective, No Fortran Support 509 510 Input Parameters: 511 + a - string to search 512 - b - string to end with 513 514 Output Parameter: 515 . flg - `PETSC_TRUE` if `a` ends with `b`, `PETSC_FALSE` otherwise 516 517 Level: intermediate 518 519 Notes: 520 Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) bot not either. 521 522 .seealso: `PetscStrendswithwhich()`, `PetscStrbeginswith()`, `PetscStrtoupper`, 523 `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`, 524 `PetscStrcmp()` 525 @*/ 526 static inline PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg) 527 { 528 size_t na = 0, nb = 0; 529 530 PetscFunctionBegin; 531 PetscAssertPointer_Private(flg, 3); 532 // do this here to silence stupid "may be used uninitialized"" warnings 533 *flg = PETSC_FALSE; 534 PetscCall(PetscStrlen(a, &na)); 535 PetscCall(PetscStrlen(b, &nb)); 536 if (na >= nb) { 537 #if PetscHasBuiltin(__builtin_memcmp) 538 *flg = __builtin_memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE; 539 #else 540 *flg = memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE; 541 #endif 542 } 543 PetscFunctionReturn(PETSC_SUCCESS); 544 } 545 546 /*@C 547 PetscStrbeginswith - Determines if a string begins with a certain string 548 549 Not Collective, No Fortran Support 550 551 Input Parameters: 552 + a - string to search 553 - b - string to begin with 554 555 Output Parameter: 556 . flg - `PETSC_TRUE` if `a` begins with `b`, `PETSC_FALSE` otherwise 557 558 Level: intermediate 559 560 Notes: 561 Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) but not 562 either. Both `a` and `b` may point to the same string. 563 564 .seealso: `PetscStrendswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`, 565 `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`, 566 `PetscStrcmp()` 567 @*/ 568 static inline PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg) 569 { 570 size_t len = 0; 571 572 PetscFunctionBegin; 573 PetscAssertPointer_Private(flg, 3); 574 // do this here to silence stupid "may be used uninitialized"" warnings 575 *flg = PETSC_FALSE; 576 PetscCall(PetscStrlen(b, &len)); 577 PetscCall(PetscStrncmp(a, b, len, flg)); 578 PetscFunctionReturn(PETSC_SUCCESS); 579 } 580 581 #undef PetscAssertPointer_Private 582 583 /*@C 584 PetscMemmove - Copies n bytes, beginning at location b, to the space 585 beginning at location a. Copying between regions that overlap will 586 take place correctly. Use `PetscMemcpy()` if the locations do not overlap 587 588 Not Collective 589 590 Input Parameters: 591 + b - pointer to initial memory space 592 . a - pointer to copy space 593 - n - length (in bytes) of space to copy 594 595 Level: intermediate 596 597 Notes: 598 `PetscArraymove()` is preferred 599 600 This routine is analogous to `memmove()`. 601 602 Developers Notes: 603 This is inlined for performance 604 605 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscStrallocpy()`, 606 `PetscArraymove()` 607 @*/ 608 static inline PetscErrorCode PetscMemmove(void *a, const void *b, size_t n) 609 { 610 PetscFunctionBegin; 611 if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS); 612 PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to null pointer (Argument #1)", n); 613 PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n); 614 #if PetscDefined(HAVE_MEMMOVE) 615 memmove((char *)a, (const char *)b, n); 616 #else 617 if (a < b) { 618 if ((char *)a <= (char *)b - n) { 619 memcpy(a, b, n); 620 } else { 621 const size_t ptr_diff = (size_t)((char *)b - (char *)a); 622 623 memcpy(a, b, ptr_diff); 624 PetscCall(PetscMemmove((void *)b, (char *)b + ptr_diff, n - ptr_diff)); 625 } 626 } else { 627 if ((char *)b <= (char *)a - n) { 628 memcpy(a, b, n); 629 } else { 630 const size_t ptr_diff = (size_t)((char *)a - (char *)b); 631 632 memcpy((void *)((char *)b + n), (char *)b + (n - ptr_diff), ptr_diff); 633 PetscCall(PetscMemmove(a, b, n - ptr_diff)); 634 } 635 } 636 #endif 637 PetscFunctionReturn(PETSC_SUCCESS); 638 } 639 640 /*@C 641 PetscMemcpy - Copies n bytes, beginning at location b, to the space 642 beginning at location a. The two memory regions CANNOT overlap, use 643 `PetscMemmove()` in that case. 644 645 Not Collective 646 647 Input Parameters: 648 + b - pointer to initial memory space 649 - n - length (in bytes) of space to copy 650 651 Output Parameter: 652 . a - pointer to copy space 653 654 Level: intermediate 655 656 Compile Option: 657 `PETSC_PREFER_DCOPY_FOR_MEMCPY` will cause the BLAS dcopy() routine to be used 658 for memory copies on double precision values. 659 `PETSC_PREFER_COPY_FOR_MEMCPY` will cause C code to be used 660 for memory copies on double precision values. 661 `PETSC_PREFER_FORTRAN_FORMEMCPY` will cause Fortran code to be used 662 for memory copies on double precision values. 663 664 Notes: 665 Prefer `PetscArraycpy()` 666 667 This routine is analogous to `memcpy()`. 668 669 Developer Notes: 670 This is inlined for fastest performance 671 672 .seealso: `PetscMemzero()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()` 673 @*/ 674 static inline PetscErrorCode PetscMemcpy(void *a, const void *b, size_t n) 675 { 676 const PETSC_UINTPTR_T al = (PETSC_UINTPTR_T)a; 677 const PETSC_UINTPTR_T bl = (PETSC_UINTPTR_T)b; 678 679 PetscFunctionBegin; 680 if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS); 681 PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to a null pointer (Argument #1)", n); 682 PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n); 683 PetscAssert(!(((al > bl) && (al - bl) < n) || (bl - al) < n), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Memory regions overlap: either use PetscMemmove()\nor make sure your copy regions and lengths are correct.\nLength (bytes) %zu first address %" PRIxPTR " second address %" PRIxPTR, n, al, bl); 684 if (PetscDefined(PREFER_DCOPY_FOR_MEMCPY) || PetscDefined(PREFER_COPY_FOR_MEMCPY) || PetscDefined(PREFER_FORTRAN_FORMEMCPY)) { 685 if (!(al % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) { 686 const size_t scalar_len = n / sizeof(PetscScalar); 687 const PetscScalar *x = (PetscScalar *)b; 688 PetscScalar *y = (PetscScalar *)a; 689 690 #if PetscDefined(PREFER_DCOPY_FOR_MEMCPY) 691 { 692 const PetscBLASInt one = 1; 693 PetscBLASInt blen; 694 695 PetscCall(PetscBLASIntCast(scalar_len, &blen)); 696 PetscCallBLAS("BLAScopy", BLAScopy_(&blen, x, &one, y, &one)); 697 } 698 #elif PetscDefined(PREFER_FORTRAN_FORMEMCPY) 699 fortrancopy_(&scalar_len, x, y); 700 #else 701 for (size_t i = 0; i < scalar_len; i++) y[i] = x[i]; 702 #endif 703 PetscFunctionReturn(PETSC_SUCCESS); 704 } 705 } 706 memcpy(a, b, n); 707 PetscFunctionReturn(PETSC_SUCCESS); 708 } 709 710 /*@C 711 PetscMemzero - Zeros the specified memory. 712 713 Not Collective 714 715 Input Parameters: 716 + a - pointer to beginning memory location 717 - n - length (in bytes) of memory to initialize 718 719 Level: intermediate 720 721 Compile Option: 722 `PETSC_PREFER_BZERO` - on certain machines (the IBM RS6000) the bzero() routine happens 723 to be faster than the memset() routine. This flag causes the bzero() routine to be used. 724 725 Notes: 726 Prefer `PetscArrayzero()` 727 728 Developer Notes: 729 This is inlined for fastest performance 730 731 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()` 732 @*/ 733 static inline PetscErrorCode PetscMemzero(void *a, size_t n) 734 { 735 PetscFunctionBegin; 736 if (PetscUnlikely(n == 0)) PetscFunctionReturn(PETSC_SUCCESS); 737 PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to zero %zu bytes at a null pointer", n); 738 if (PetscDefined(PREFER_ZERO_FOR_MEMZERO) || PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)) { 739 if (!(((PETSC_UINTPTR_T)a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) { 740 const size_t scalar_len = n / sizeof(PetscScalar); 741 PetscScalar *x = (PetscScalar *)a; 742 743 if (PetscDefined(PREFER_ZERO_FOR_MEMZERO)) { 744 for (size_t i = 0; i < scalar_len; ++i) x[i] = 0; 745 } else { 746 #if PetscDefined(PREFER_FORTRAN_FOR_MEMZERO) 747 fortranzero_(&scalar_len, x); 748 #else 749 (void)scalar_len; 750 (void)x; 751 #endif 752 } 753 PetscFunctionReturn(PETSC_SUCCESS); 754 } 755 } 756 #if PetscDefined(PREFER_BZERO) 757 bzero(a, n); 758 #else 759 memset(a, 0, n); 760 #endif 761 PetscFunctionReturn(PETSC_SUCCESS); 762 } 763 764 /*MC 765 PetscArraycmp - Compares two arrays in memory. 766 767 Synopsis: 768 #include <petscstring.h> 769 PetscErrorCode PetscArraycmp(const anytype *str1,const anytype *str2,size_t cnt,PetscBool *e) 770 771 Not Collective 772 773 Input Parameters: 774 + str1 - First array 775 . str2 - Second array 776 - cnt - Count of the array, not in bytes, but number of entries in the arrays 777 778 Output Parameters: 779 . e - `PETSC_TRUE` if equal else `PETSC_FALSE`. 780 781 Level: intermediate 782 783 Notes: 784 This routine is a preferred replacement to `PetscMemcmp()` 785 786 The arrays must be of the same type 787 788 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`, 789 `PetscArraymove()` 790 M*/ 791 #define PetscArraycmp(str1, str2, cnt, e) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcmp((str1), (str2), (size_t)(cnt) * sizeof(*(str1)), (e)) : PETSC_ERR_ARG_SIZ) 792 793 /*MC 794 PetscArraymove - Copies from one array in memory to another, the arrays may overlap. Use `PetscArraycpy()` when the arrays 795 do not overlap 796 797 Synopsis: 798 #include <petscstring.h> 799 PetscErrorCode PetscArraymove(anytype *str1,const anytype *str2,size_t cnt) 800 801 Not Collective 802 803 Input Parameters: 804 + str1 - First array 805 . str2 - Second array 806 - cnt - Count of the array, not in bytes, but number of entries in the arrays 807 808 Level: intermediate 809 810 Notes: 811 This routine is a preferred replacement to `PetscMemmove()` 812 813 The arrays must be of the same type 814 815 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()` 816 M*/ 817 #define PetscArraymove(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemmove((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ) 818 819 /*MC 820 PetscArraycpy - Copies from one array in memory to another 821 822 Synopsis: 823 #include <petscstring.h> 824 PetscErrorCode PetscArraycpy(anytype *str1,const anytype *str2,size_t cnt) 825 826 Not Collective 827 828 Input Parameters: 829 + str1 - First array (destination) 830 . str2 - Second array (source) 831 - cnt - Count of the array, not in bytes, but number of entries in the arrays 832 833 Level: intermediate 834 835 Notes: 836 This routine is a preferred replacement to `PetscMemcpy()` 837 838 The arrays must be of the same type 839 840 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraymove()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()` 841 M*/ 842 #define PetscArraycpy(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcpy((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ) 843 844 /*MC 845 PetscArrayzero - Zeros an array in memory. 846 847 Synopsis: 848 #include <petscstring.h> 849 PetscErrorCode PetscArrayzero(anytype *str1,size_t cnt) 850 851 Not Collective 852 853 Input Parameters: 854 + str1 - array 855 - cnt - Count of the array, not in bytes, but number of entries in the array 856 857 Level: intermediate 858 859 Notes: 860 This routine is a preferred replacement to `PetscMemzero()` 861 862 .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`, `PetscArraymove()` 863 M*/ 864 #define PetscArrayzero(str1, cnt) PetscMemzero((str1), (size_t)(cnt) * sizeof(*(str1))) 865 866 #endif // PETSC_STRING_H 867