Changeset 3892 for LMDZ6/branches/LMDZ-tracers
- Timestamp:
- May 11, 2021, 2:28:09 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
LMDZ6/branches/LMDZ-tracers/libf/misc/strings_mod.F90
r3852 r3892 17 17 INTERFACE strHead; MODULE PROCEDURE strHead_1, strHead_m; END INTERFACE strHead 18 18 INTERFACE strTail; MODULE PROCEDURE strTail_1, strTail_m; END INTERFACE strTail 19 INTERFACE strStack; MODULE PROCEDURE strStack_1, strStack_2; END INTERFACE strStack20 19 INTERFACE strClean; MODULE PROCEDURE strClean_1, strClean_m; END INTERFACE strClean 21 20 INTERFACE strReduce; MODULE PROCEDURE strReduce_1, strReduce_2; END INTERFACE strReduce … … 66 65 CHARACTER(LEN=*), INTENT(IN) :: def 67 66 val = def; CALL getin(nam, val) 68 WRITE(lunout,*)TRIM(nam)//' = '//TRIM(val)67 IF(val/=def) WRITE(lunout,*)TRIM(nam)//' = '//TRIM(val) 69 68 END SUBROUTINE getin_s 70 69 !============================================================================================================================== … … 75 74 INTEGER, INTENT(IN) :: def 76 75 val = def; CALL getin(nam, val) 77 WRITE(lunout,*)TRIM(nam)//' = '//TRIM(int2str(val))76 IF(val/=def) WRITE(lunout,*)TRIM(nam)//' = '//TRIM(int2str(val)) 78 77 END SUBROUTINE getin_i 79 78 !============================================================================================================================== … … 84 83 REAL, INTENT(IN) :: def 85 84 val = def; CALL getin(nam, val) 86 WRITE(lunout,*)TRIM(nam)//' = '//TRIM(real2str(val))85 IF(val/=def) WRITE(lunout,*)TRIM(nam)//' = '//TRIM(real2str(val)) 87 86 END SUBROUTINE getin_r 88 87 !============================================================================================================================== … … 93 92 LOGICAL, INTENT(IN) :: def 94 93 val = def; CALL getin(nam, val) 95 WRITE(lunout,*)TRIM(nam)//' = '//TRIM(bool2str(val))94 IF(val/=def) WRITE(lunout,*)TRIM(nam)//' = '//TRIM(bool2str(val)) 96 95 END SUBROUTINE getin_l 97 96 !============================================================================================================================== … … 190 189 !============================================================================================================================== 191 190 CHARACTER(LEN=256) FUNCTION strHead_1(str,sep) RESULT(out) 192 CHARACTER(LEN=*), INTENT(IN) :: str, sep 193 out = str(1:INDEX(str,sep)-1); IF(out=='') out=str 191 CHARACTER(LEN=*), INTENT(IN) :: str 192 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep 193 IF(PRESENT(sep)) THEN 194 out = str(1:INDEX(str,sep,.TRUE.)-1) 195 ELSE 196 out = str(1:INDEX(str,'/',.TRUE.)-1) 197 END IF 198 IF(out == '') out = str 194 199 END FUNCTION strHead_1 195 200 !============================================================================================================================== 196 201 CHARACTER(LEN=256) FUNCTION strTail_1(str,sep) RESULT(out) 197 CHARACTER(LEN=*), INTENT(IN) :: str, sep 198 out = str(INDEX(str,sep,.TRUE.)+LEN(sep):LEN_TRIM(str)); IF(out=='') out=str 202 CHARACTER(LEN=*), INTENT(IN) :: str 203 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep 204 IF(PRESENT(sep)) THEN 205 out = str(INDEX(str,sep,.TRUE.)+LEN(sep):LEN_TRIM(str)) 206 ELSE 207 out = str(INDEX(str,'/',.TRUE.)+1:LEN_TRIM(str)) 208 END IF 209 IF(out == '') out = str 199 210 END FUNCTION strTail_1 200 211 !============================================================================================================================== 201 212 FUNCTION strHead_m(str,sep) RESULT(out) 202 CHARACTER(LEN=256), ALLOCATABLE :: out(:) 203 CHARACTER(LEN=*), INTENT(IN) :: str(:), sep 213 CHARACTER(LEN=256), ALLOCATABLE :: out(:) 214 CHARACTER(LEN=*), INTENT(IN) :: str(:) 215 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep 204 216 INTEGER :: k 205 out = [(strHead_1(str(k),sep), k=1, SIZE(str))] 217 IF(PRESENT(sep)) THEN 218 out = [(strHead_1(str(k),sep), k=1, SIZE(str))] 219 ELSE 220 out = [(strHead_1(str(k)), k=1, SIZE(str))] 221 END IF 222 206 223 END FUNCTION strHead_m 207 224 !============================================================================================================================== 208 225 FUNCTION strTail_m(str,sep) RESULT(out) 209 CHARACTER(LEN=256), ALLOCATABLE :: out(:) 210 CHARACTER(LEN=*), INTENT(IN) :: str(:), sep 226 CHARACTER(LEN=256), ALLOCATABLE :: out(:) 227 CHARACTER(LEN=*), INTENT(IN) :: str(:) 228 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep 211 229 INTEGER :: k 212 out = [(strTail_1(str(k),sep), k=1, SIZE(str))] 230 IF(PRESENT(sep)) THEN 231 out = [(strTail_1(str(k),sep), k=1, SIZE(str))] 232 ELSE 233 out = [(strTail_1(str(k)), k=1, SIZE(str))] 234 END IF 213 235 END FUNCTION strTail_m 214 236 !============================================================================================================================== … … 218 240 !=== Concatenates the strings "str(:)" with separator "sep" into a single string using a separator (',' by default). ========== 219 241 !============================================================================================================================== 220 FUNCTION strStack _1(str, sep) RESULT(out)242 FUNCTION strStack(str, sep) RESULT(out) 221 243 CHARACTER(LEN=:), ALLOCATABLE :: out 222 244 CHARACTER(LEN=*), INTENT(IN) :: str(:) … … 225 247 INTEGER :: is 226 248 IF(SIZE(str) == 0) THEN; out = ''; RETURN; END IF 227 ALLOCATE(s, SOURCE=','); IF(PRESENT(sep)) s=sep 228 out = TRIM(str(1)); DO is=2,SIZE(str, DIM=1); out = TRIM(out)//s//' '//TRIM(str(is)); END DO 229 END FUNCTION strStack_1 230 !============================================================================================================================== 231 FUNCTION strStack_2(str1, str2, sep) RESULT(out) 232 CHARACTER(LEN=:), ALLOCATABLE :: out 233 CHARACTER(LEN=*), INTENT(IN) :: str1(:), str2(:) 234 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep 235 CHARACTER(LEN=:), ALLOCATABLE :: s 236 INTEGER :: is 237 IF(SIZE(str1) == 0) THEN; out = ''; RETURN; END IF 238 ALLOCATE(s, SOURCE=','); IF(PRESENT(sep)) s=sep 239 out = TRIM(str1(1))//'='//TRIM(str2(1)) 240 DO is=2,SIZE(str1); out = TRIM(out)//s//' '//TRIM(str1(is))//'='//TRIM(str2(is)); END DO 241 END FUNCTION strStack_2 249 ALLOCATE(s, SOURCE=', '); IF(PRESENT(sep)) s=sep 250 out = str(1); DO is=2,SIZE(str, DIM=1); out = TRIM(out)//s//TRIM(str(is)); END DO 251 END FUNCTION strStack 242 252 !============================================================================================================================== 243 253 !=== Concatenate the strings "str(:)" with separator "sep" into one or several lines of "nmax" characters max (for display) === … … 304 314 CHARACTER(LEN=256), ALLOCATABLE :: s1(:) 305 315 INTEGER :: k, n, n1 316 IF(PRESENT(nb)) nb = 0 306 317 CALL MOVE_ALLOC(FROM = str1, TO = s1); CALL strClean(s1) 307 318 n1 = SIZE(s1, DIM=1) !--- Total nb of elements in "s1" … … 406 417 407 418 INTEGER, ALLOCATABLE :: ii(:) 408 LOGICAL :: ll 419 LOGICAL :: ll, ls 409 420 CHARACTER(LEN=256) :: d 410 421 ! modname = 'strIdx' 411 422 lerr = .FALSE. 412 423 idx = strIdx1(rawList, del, ibeg, idel) 413 IF(idx == 0) RETURN !--- No separator found => finished 414 IF(.NOT.PRESENT(lSc)) RETURN; IF(.NOT.lSc ) RETURN !--- No need to check exceptions for numbers => finished 415 IF(INDEX('+-',del(idel))==0) RETURN !--- No possible sign ambiguity => finished 416 ll = idx == 1 !--- This is a front sign of a number 417 IF(idx /= 1) ll = INDEX('^*/+-',rawList(idx-1:idx-1)) /= 0 !--- This is a front sign of a number after an operator 418 IF(ll) idx = strIdx1(rawList, del,idx+1,idel) !--- => TO THE NEXT DELIMITER 419 IF(idx /= 0) THEN 420 IF(idx /= 1) ll = INDEX('eE' ,rawList(idx-1:idx-1)) /= 0 !--- Exponent sign of a number in scientific notation ? 421 IF(ll) idx = strIdx1(rawList, del,idx+1,idel) !--- Identify the next delimiter 422 END IF 423 IF(idx /= 0) lerr = is_numeric(rawList(ibeg:idx -1)) !--- Check whether the previous word was a number 424 IF(idx == 0) lerr = is_numeric(rawList(ibeg:LEN_TRIM(rawList)-1)) !--- Check whether the previous word was a number 425 IF(idx == 0) idel = 0 424 IF(.NOT.PRESENT(lSc)) RETURN !--- No need to check exceptions for numbers => finished 425 IF(.NOT. lSc ) RETURN !--- No need to check exceptions for numbers => finished 426 IF(idx == 0) THEN 427 lerr = .NOT.is_numeric(rawList(ibeg:)); RETURN !--- No separator detected: string must be a number 428 END IF 429 IF(test(idx==1.AND.INDEX('+-',del(idel))/=0, lerr)) RETURN !--- Front separator different from +/-: error 430 IF(is_numeric(rawList(ibeg:idx-1))) RETURN !--- The input string tail is a valid number 431 idx = strIdx1(rawList, del, idx+1, idel) !--- => TO THE NEXT DELIMITER 432 IF(idx == 0) THEN 433 lerr = .NOT.is_numeric(rawList(ibeg:)); RETURN !--- No separator detected: string must be a number 434 END IF 435 IF(is_numeric(rawList(ibeg:idx-1))) RETURN !--- The input string tail is a valid number 436 IF(test( INDEX('eE',rawList(idx-1:idx-1)) /= 0 & !--- Sole possible exception: scientific notation: E+/- 437 .OR. INDEX('+-',del(idel)) /=0, lerr)) RETURN 438 idx = strIdx1(rawList, del, idx+1, idel) !--- => TO THE NEXT DELIMITER 439 IF(idx == 0) THEN 440 lerr = .NOT.is_numeric(rawList(ibeg:)); RETURN !--- No separator detected: string must be a number 441 END IF 442 lerr = .NOT.is_numeric(rawList(ibeg:idx-1)) 426 443 427 444 CONTAINS … … 446 463 447 464 END FUNCTION strIdx_prv 465 !============================================================================================================================== 466 467 468 !============================================================================================================================== 469 !=== Return the index of first appearance of "del" in "str" starting from index "ib" 470 !============================================================================================================================== 471 INTEGER FUNCTION strIndex(str, del, ib) RESULT(idx) 472 CHARACTER(LEN=*), INTENT(IN) :: str 473 CHARACTER(LEN=*), INTENT(IN) :: del 474 INTEGER, INTENT(IN) :: ib 475 idx = INDEX( str(ib:LEN_TRIM(str)), del ) + ib -1 476 END FUNCTION strIndex 448 477 !============================================================================================================================== 449 478 … … 484 513 INTEGER, INTENT(OUT) :: nb 485 514 LOGICAL, OPTIONAL, INTENT(IN) :: lSc 486 487 515 INTEGER :: ib, ie, jd, nr 488 516 LOGICAL :: ll 489 517 CHARACTER(LEN=1024) :: r 490 491 modname = 'strCount' 518 ! modname = 'strCount' 492 519 lerr = .FALSE. 493 520 ll = .FALSE.; IF(PRESENT(lSc)) ll = lSc … … 518 545 INTEGER, OPTIONAL, INTENT(OUT) :: n 519 546 LOGICAL :: ll 520 modname = 'strParse'547 ! modname = 'strParse' 521 548 ll = .FALSE.; IF(PRESENT(lSc)) ll = lSc 522 549 IF(.NOT.PRESENT(vals)) lerr = strParse_m(rawList, [delimiter], keys, ll) … … 527 554 LOGICAL FUNCTION strParse_m(rawList, delimiter, keys, lSc, vals, n, id) RESULT(lerr) 528 555 CHARACTER(LEN=*), INTENT(IN) :: rawList, delimiter(:) 529 CHARACTER(LEN=256), ALLOCATABLE, INTENT(OUT) :: keys(:) 556 CHARACTER(LEN=256), ALLOCATABLE, INTENT(OUT) :: keys(:) !--- Parsed keys vector 530 557 LOGICAL, OPTIONAL, INTENT(IN) :: lSc !--- Take care about numbers in scientific notation 531 CHARACTER(LEN=256), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: vals(:) 532 INTEGER, OPTIONAL, INTENT(OUT) :: n 533 INTEGER, OPTIONAL, ALLOCATABLE, INTENT(OUT) :: id(:) 558 CHARACTER(LEN=256), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: vals(:) !--- Values for <name>=<value> keys 559 INTEGER, OPTIONAL, INTENT(OUT) :: n !--- Length of the parsed vector 560 INTEGER, OPTIONAL, ALLOCATABLE, INTENT(OUT) :: id(:) !--- Indexes of the separators in "delimiter(:)" vector 534 561 535 562 CHARACTER(LEN=1024) :: r … … 537 564 LOGICAL :: ll 538 565 539 modname = 'strParse'566 ! modname = 'strParse' 540 567 ll = .FALSE.; IF(PRESENT(lSc)) ll = lSc 541 568 IF(test(fmsg(strCount_1m(rawList, delimiter, nk, ll), "Couldn't parse list: non-numerical strings were found"),lerr)) RETURN … … 813 840 LOGICAL :: ls, li, lr 814 841 815 modname = 'dispTable'842 ! modname = 'dispTable' 816 843 rFm = '*'; IF(PRESENT(rFmt)) rFm = rFmt !--- Specified format for reals 817 844 unt = lunout; IF(PRESENT(unit)) unt = unit !--- Specified output unit … … 892 919 LOGICAL :: ls, li, lr, la 893 920 894 modname = 'dispNamelist'921 ! modname = 'dispNamelist' 895 922 rFm = '*'; IF(PRESENT(rFmt)) rFm = rFmt !--- Specified format for reals 896 923 ls = PRESENT(s); li = PRESENT(i); lr = PRESENT(r) … … 1077 1104 !============================================================================================================================== 1078 1105 LOGICAL FUNCTION reduceExpr_1(str, val) RESULT(out) 1079 CHARACTER(LEN=*), INTENT(IN) :: str 1080 CHARACTER(LEN=256), INTENT(OUT) :: val 1106 CHARACTER(LEN=*), INTENT(IN) :: str 1107 CHARACTER(LEN=256), INTENT(OUT) :: val 1108 1109 CHARACTER(LEN=256) :: v 1081 1110 CHARACTER(LEN=1024) :: s, vv 1082 CHARACTER(LEN=256) :: v1083 ! CHARACTER(LEN=:), ALLOCATABLE :: v1084 1111 CHARACTER(LEN=1024), ALLOCATABLE :: vl(:) 1085 1112 INTEGER, ALLOCATABLE :: ip(:) 1086 1113 INTEGER :: nl, nn, i, j, im, ix 1087 1114 LOGICAL :: ll 1088 modname = 'reduceExpr_1'1115 ! modname = 'reduceExpr_1' 1089 1116 s = str 1090 1117 … … 1128 1155 LOGICAL FUNCTION reduceExpr_basic(str, val) RESULT(out) 1129 1156 CHARACTER(LEN=*), INTENT(IN) :: str 1130 CHARACTER(LEN= 256),INTENT(OUT) :: val1157 CHARACTER(LEN=*), INTENT(OUT) :: val 1131 1158 DOUBLE PRECISION, ALLOCATABLE :: vl(:) 1132 1159 INTEGER, ALLOCATABLE :: id(:) … … 1139 1166 LOGICAL :: ll 1140 1167 1141 modname = 'reduceExpr_basic'1168 ! modname = 'reduceExpr_basic' 1142 1169 out = .TRUE. 1143 print*,TRIM(str),is_numeric(str) 1144 ! val ='' 1145 print*,"coincoin 1",len(str),len_trim(str) 1146 IF(is_numeric(str)) THEN; val = TRIM(str); RETURN; END IF 1147 print*,"coincoin 2" 1170 IF(is_numeric(str)) THEN; val=TRIM(str); RETURN; END IF 1148 1171 op = ['^','/','*','+','-'] !--- List of recognized operations 1149 1172 s = str … … 1157 1180 IF(id(i) /= io) CYCLE !--- Current found operator is not op(io) 1158 1181 vm = vl(i); vp = vl(i+1) !--- Couple of values used for current operation 1159 SELECT CASE( op(io))!--- Perform operation on the two values1160 CASE( '^'); v = vm**vp1161 CASE( '/'); v = vm/vp1162 CASE( '*'); v = vm*vp1163 CASE( '+'); v = vm+vp1164 CASE( '-'); v = vm-vp1182 SELECT CASE(io) !--- Perform operation on the two values 1183 CASE(1); v = vm**vp !--- ^ 1184 CASE(2); v = vm/vp !--- / 1185 CASE(3); v = vm*vp !--- * 1186 CASE(4); v = vm+vp !--- + 1187 CASE(5); v = vm-vp !--- + 1165 1188 END SELECT 1166 1189 IF(i == ni) THEN; vl = [vl(1:ni-1), v]; ELSE; vl = [vl(1:i-1), v, vl(i+2:ni+1)]; END IF … … 1175 1198 !============================================================================================================================== 1176 1199 FUNCTION reduceExpr_m(str, val) RESULT(out) 1177 CHARACTER(LEN=*), INTENT(IN) :: str(:)1178 CHARACTER(LEN= 256), INTENT(OUT) :: val(SIZE(str))1179 LOGICAL :: out(SIZE(str))1200 LOGICAL, ALLOCATABLE :: out(:) 1201 CHARACTER(LEN=*), INTENT(IN) :: str(:) 1202 CHARACTER(LEN=256), ALLOCATABLE, INTENT(OUT) :: val(:) 1180 1203 INTEGER :: i 1181 out = [(reduceExpr_1(str(i), val(i)), i=1, SIZE(str))] 1204 ALLOCATE(out(SIZE(str)),val(SIZE(str))) 1205 out(:) = [(reduceExpr_1(str(i), val(i)), i=1, SIZE(str))] 1182 1206 END FUNCTION reduceExpr_m 1183 1207 !============================================================================================================================== … … 1194 1218 WRITE(fmt,'("(f",i0,".0)")') LEN_TRIM(str) 1195 1219 READ(str,fmt,IOSTAT=e) x 1196 out = e==0 1220 out = e==0 .AND. INDEX('Ee',str(LEN_TRIM(str):LEN_TRIM(str)))==0 1221 IF(str == '') out = .FALSE. 1197 1222 END FUNCTION is_numeric 1198 1223 !============================================================================================================================== … … 1237 1262 END FUNCTION bool2str 1238 1263 !============================================================================================================================== 1239 ELEMENTAL CHARACTER(LEN=256) FUNCTION int2str(i) RESULT(out) 1240 INTEGER, INTENT(IN) :: i 1264 ELEMENTAL CHARACTER(LEN=256) FUNCTION int2str(i, nDigits) RESULT(out) 1265 INTEGER, INTENT(IN) :: i 1266 INTEGER, OPTIONAL, INTENT(IN) :: nDigits 1241 1267 WRITE(out,*)i 1242 1268 out = ADJUSTL(out) 1269 IF(.NOT.PRESENT(nDigits)) RETURN 1270 IF(nDigits > LEN_TRIM(out)) out = REPEAT('0', nDigits - LEN_TRIM(out))//TRIM(out) 1243 1271 END FUNCTION int2str 1244 1272 !==============================================================================================================================
Note: See TracChangeset
for help on using the changeset viewer.