PageRenderTime 55ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/other/netcdf_write_matrix/src/nf_test/util.F

https://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 1334 lines | 989 code | 157 blank | 188 comment | 184 complexity | a9440a287e71c7b8d8b3be869226f42b MD5 | raw file
Possible License(s): AGPL-1.0
  1. !*********************************************************************
  2. ! Copyright 1996, UCAR/Unidata
  3. ! See netcdf/COPYRIGHT file for copying and redistribution conditions.
  4. ! $Id: util.F,v 1.13 2000/07/13 15:22:25 steve Exp $
  5. !********************************************************************/
  6. SUBROUTINE PRINT_NOK(NOK)
  7. IMPLICIT NONE
  8. INTEGER NOK
  9. #include "tests.inc"
  10. IF (VERBOSE .OR. NFAILS .GT. 0) PRINT *, ' '
  11. IF (VERBOSE) PRINT *, NOK, ' good comparisons.'
  12. END
  13. ! Is value within external type range? */
  14. FUNCTION INRANGE(VALUE, DATATYPE)
  15. IMPLICIT NONE
  16. DOUBLEPRECISION VALUE
  17. INTEGER DATATYPE
  18. #include "tests.inc"
  19. DOUBLEPRECISION MIN
  20. DOUBLEPRECISION MAX
  21. IF (DATATYPE .EQ. NF_CHAR) THEN
  22. MIN = X_CHAR_MIN
  23. MAX = X_CHAR_MAX
  24. ELSE IF (DATATYPE .EQ. NF_BYTE) THEN
  25. MIN = X_BYTE_MIN
  26. MAX = X_BYTE_MAX
  27. ELSE IF (DATATYPE .EQ. NF_SHORT) THEN
  28. MIN = X_SHORT_MIN
  29. MAX = X_SHORT_MAX
  30. ELSE IF (DATATYPE .EQ. NF_INT) THEN
  31. MIN = X_INT_MIN
  32. MAX = X_INT_MAX
  33. ELSE IF (DATATYPE .EQ. NF_FLOAT) THEN
  34. MIN = X_FLOAT_MIN
  35. MAX = X_FLOAT_MAX
  36. ELSE IF (DATATYPE .EQ. NF_DOUBLE) THEN
  37. MIN = X_DOUBLE_MIN
  38. MAX = X_DOUBLE_MAX
  39. ELSE
  40. CALL UDABORT
  41. END IF
  42. INRANGE = (VALUE .GE. MIN) .AND. (VALUE .LE. MAX)
  43. END
  44. FUNCTION INRANGE_UCHAR(VALUE, DATATYPE)
  45. IMPLICIT NONE
  46. DOUBLEPRECISION VALUE
  47. INTEGER DATATYPE
  48. #include "tests.inc"
  49. IF (DATATYPE .EQ. NF_BYTE) THEN
  50. INRANGE_UCHAR = (VALUE .GE. 0) .AND. (VALUE .LE. 255)
  51. ELSE
  52. INRANGE_UCHAR = INRANGE(VALUE, DATATYPE)
  53. END IF
  54. END
  55. FUNCTION INRANGE_FLOAT(VALUE, DATATYPE)
  56. IMPLICIT NONE
  57. DOUBLEPRECISION VALUE
  58. INTEGER DATATYPE
  59. #include "tests.inc"
  60. DOUBLEPRECISION MIN
  61. DOUBLEPRECISION MAX
  62. REAL FVALUE
  63. IF (DATATYPE .EQ. NF_CHAR) THEN
  64. MIN = X_CHAR_MIN
  65. MAX = X_CHAR_MAX
  66. ELSE IF (DATATYPE .EQ. NF_BYTE) THEN
  67. MIN = X_BYTE_MIN
  68. MAX = X_BYTE_MAX
  69. ELSE IF (DATATYPE .EQ. NF_SHORT) THEN
  70. MIN = X_SHORT_MIN
  71. MAX = X_SHORT_MAX
  72. ELSE IF (DATATYPE .EQ. NF_INT) THEN
  73. MIN = X_INT_MIN
  74. MAX = X_INT_MAX
  75. ELSE IF (DATATYPE .EQ. NF_FLOAT) THEN
  76. IF (internal_max(NFT_REAL) .LT. X_FLOAT_MAX) THEN
  77. MIN = -internal_max(NFT_REAL)
  78. MAX = internal_max(NFT_REAL)
  79. ELSE
  80. MIN = X_FLOAT_MIN
  81. MAX = X_FLOAT_MAX
  82. END IF
  83. ELSE IF (DATATYPE .EQ. NF_DOUBLE) THEN
  84. IF (internal_max(NFT_REAL) .LT. X_DOUBLE_MAX) THEN
  85. MIN = -internal_max(NFT_REAL)
  86. MAX = internal_max(NFT_REAL)
  87. ELSE
  88. MIN = X_DOUBLE_MIN
  89. MAX = X_DOUBLE_MAX
  90. END IF
  91. ELSE
  92. CALL UDABORT
  93. END IF
  94. IF (.NOT.((VALUE .GE. MIN) .AND. (VALUE .LE. MAX))) THEN
  95. INRANGE_FLOAT = .FALSE.
  96. ELSE
  97. FVALUE = VALUE
  98. INRANGE_FLOAT = (FVALUE .GE. MIN) .AND. (FVALUE .LE. MAX)
  99. END IF
  100. END
  101. ! wrapper for inrange to handle special NF_BYTE/uchar adjustment */
  102. function inrange3(value, datatype, itype)
  103. implicit none
  104. doubleprecision value
  105. integer datatype
  106. integer itype
  107. #include "tests.inc"
  108. if (itype .eq. NFT_REAL) then
  109. inrange3 = inrange_float(value, datatype)
  110. else
  111. inrange3 = inrange(value, datatype)
  112. end if
  113. end
  114. !
  115. ! Does x == y, where one is internal and other external (netCDF)?
  116. ! Use tolerant comparison based on IEEE FLT_EPSILON or DBL_EPSILON.
  117. !
  118. function equal(x, y, extType, itype)
  119. implicit none
  120. doubleprecision x
  121. doubleprecision y
  122. integer extType !!/* external data type */
  123. integer itype
  124. #include "tests.inc"
  125. doubleprecision epsilon
  126. if ((extType .eq. NF_REAL) .or. (itype .eq. NFT_REAL)) then
  127. epsilon = 1.19209290E-07
  128. else
  129. epsilon = 2.2204460492503131E-16
  130. end if
  131. equal = abs(x-y) .le. epsilon * max( abs(x), abs(y))
  132. end
  133. ! Test whether two int vectors are equal. If so return 1, else 0 */
  134. function int_vec_eq(v1, v2, n)
  135. implicit none
  136. integer n
  137. integer v1(n)
  138. integer v2(n)
  139. #include "tests.inc"
  140. integer i
  141. int_vec_eq = .true.
  142. if (n .le. 0)
  143. + return
  144. do 1, i=1, n
  145. if (v1(i) .ne. v2(i)) then
  146. int_vec_eq = .false.
  147. return
  148. end if
  149. 1 continue
  150. end
  151. !
  152. ! Generate random integer from 0 through n-1
  153. ! Like throwing an n-sided dice marked 0, 1, 2, ..., n-1
  154. !
  155. function roll(n)
  156. implicit none
  157. integer n
  158. #include "tests.inc"
  159. doubleprecision udrand
  160. external udrand
  161. 1 roll = (udrand(0) * (n-1)) + 0.5
  162. if (roll .ge. n) goto 1
  163. end
  164. !
  165. ! Convert an origin-1 cumulative index to a netCDF index vector.
  166. ! Grosset dimension first; finest dimension last.
  167. !
  168. ! Authors: Harvey Davies, Unidata/UCAR, Boulder, Colorado
  169. ! Steve Emmerson, (same place)
  170. !
  171. function index2ncindexes(index, rank, base, indexes)
  172. implicit none
  173. integer index !!/* index to be converted */
  174. integer rank !/* number of dimensions */
  175. integer base(rank) !/* base(rank) ignored */
  176. integer indexes(rank) !/* returned FORTRAN indexes */
  177. #include "tests.inc"
  178. integer i
  179. integer offset
  180. if (rank .gt. 0) then
  181. offset = index - 1
  182. do 1, i = rank, 1, -1
  183. if (base(i) .eq. 0) then
  184. index2ncindexes = 1
  185. return
  186. end if
  187. indexes(i) = 1 + mod(offset, base(i))
  188. offset = offset / base(i)
  189. 1 continue
  190. end if
  191. index2ncindexes = 0
  192. end
  193. !
  194. ! Convert an origin-1 cumulative index to a FORTRAN index vector.
  195. ! Finest dimension first; grossest dimension last.
  196. !
  197. ! Authors: Harvey Davies, Unidata/UCAR, Boulder, Colorado
  198. ! Steve Emmerson, (same place)
  199. !
  200. function index2indexes(index, rank, base, indexes)
  201. implicit none
  202. integer index !/* index to be converted */
  203. integer rank !/* number of dimensions */
  204. integer base(rank) !/* base(rank) ignored */
  205. integer indexes(rank) !/* returned FORTRAN indexes */
  206. #include "tests.inc"
  207. integer i
  208. integer offset
  209. if (rank .gt. 0) then
  210. offset = index - 1
  211. do 1, i = 1, rank
  212. if (base(i) .eq. 0) then
  213. index2indexes = 1
  214. return
  215. end if
  216. indexes(i) = 1 + mod(offset, base(i))
  217. offset = offset / base(i)
  218. 1 continue
  219. end if
  220. index2indexes = 0
  221. end
  222. !
  223. ! Convert a FORTRAN index vector to an origin-1 cumulative index.
  224. ! Finest dimension first; grossest dimension last.
  225. !
  226. ! Authors: Harvey Davies, Unidata/UCAR, Boulder, Colorado
  227. ! Steve Emmerson, (same place)
  228. !
  229. function indexes2index(rank, indexes, base)
  230. implicit none
  231. integer rank !/* number of dimensions */
  232. integer indexes(rank) !/* FORTRAN indexes */
  233. integer base(rank) !/* base(rank) ignored */
  234. #include "tests.inc"
  235. integer i
  236. indexes2index = 0
  237. if (rank .gt. 0) then
  238. do 1, i = rank, 1, -1
  239. indexes2index = (indexes2index-1) * base(i) + indexes(i)
  240. 1 continue
  241. end if
  242. end
  243. ! Generate data values as function of type, rank (-1 for attribute), index */
  244. function hash(type, rank, index)
  245. implicit none
  246. integer type
  247. integer rank
  248. integer index(*)
  249. #include "tests.inc"
  250. doubleprecision base
  251. doubleprecision result
  252. integer d !/* index of dimension */
  253. !/* If vector then elements 1 & 2 are min & max. Elements 3 & 4 are */
  254. !/* just < min & > max (except for NF_CHAR & NF_DOUBLE) */
  255. if (abs(rank) .eq. 1 .and. index(1) .le. 4) then
  256. if (index(1) .eq. 1) then
  257. if (type .eq. NF_CHAR) then
  258. hash = X_CHAR_MIN
  259. else if (type .eq. NF_BYTE) then
  260. hash = X_BYTE_MIN
  261. else if (type .eq. NF_SHORT) then
  262. hash = X_SHORT_MIN
  263. else if (type .eq. NF_INT) then
  264. hash = X_INT_MIN
  265. else if (type .eq. NF_FLOAT) then
  266. hash = X_FLOAT_MIN
  267. else if (type .eq. NF_DOUBLE) then
  268. hash = X_DOUBLE_MIN
  269. else
  270. call udabort
  271. end if
  272. else if (index(1) .eq. 2) then
  273. if (type .eq. NF_CHAR) then
  274. hash = X_CHAR_MAX
  275. else if (type .eq. NF_BYTE) then
  276. hash = X_BYTE_MAX
  277. else if (type .eq. NF_SHORT) then
  278. hash = X_SHORT_MAX
  279. else if (type .eq. NF_INT) then
  280. hash = X_INT_MAX
  281. else if (type .eq. NF_FLOAT) then
  282. hash = X_FLOAT_MAX
  283. else if (type .eq. NF_DOUBLE) then
  284. hash = X_DOUBLE_MAX
  285. else
  286. call udabort
  287. end if
  288. else if (index(1) .eq. 3) then
  289. if (type .eq. NF_CHAR) then
  290. hash = ichar('A')
  291. else if (type .eq. NF_BYTE) then
  292. hash = X_BYTE_MIN-1.0
  293. else if (type .eq. NF_SHORT) then
  294. hash = X_SHORT_MIN-1.0
  295. else if (type .eq. NF_INT) then
  296. hash = X_INT_MIN
  297. else if (type .eq. NF_FLOAT) then
  298. hash = X_FLOAT_MIN
  299. else if (type .eq. NF_DOUBLE) then
  300. hash = -1.0
  301. else
  302. call udabort
  303. end if
  304. else if (index(1) .eq. 4) then
  305. if (type .eq. NF_CHAR) then
  306. hash = ichar('Z')
  307. else if (type .eq. NF_BYTE) then
  308. hash = X_BYTE_MAX+1.0
  309. else if (type .eq. NF_SHORT) then
  310. hash = X_SHORT_MAX+1.0
  311. else if (type .eq. NF_INT) then
  312. hash = X_INT_MAX+1.0
  313. else if (type .eq. NF_FLOAT) then
  314. hash = X_FLOAT_MAX
  315. else if (type .eq. NF_DOUBLE) then
  316. hash = 1.0
  317. else
  318. call udabort
  319. end if
  320. end if
  321. else
  322. if (type .eq. NF_CHAR) then
  323. base = 2
  324. else if (type .eq. NF_BYTE) then
  325. base = -2
  326. else if (type .eq. NF_SHORT) then
  327. base = -5
  328. else if (type .eq. NF_INT) then
  329. base = -20
  330. else if (type .eq. NF_FLOAT) then
  331. base = -9
  332. else if (type .eq. NF_DOUBLE) then
  333. base = -10
  334. else
  335. stop 'in hash()'
  336. end if
  337. if (rank .lt. 0) then
  338. result = base * 7
  339. else
  340. result = base * (rank + 1)
  341. end if
  342. ! /*
  343. ! * NB: Finest netCDF dimension assumed first.
  344. ! */
  345. do 1, d = abs(rank), 1, -1
  346. result = base * (result + index(d) - 1)
  347. 1 continue
  348. hash = result
  349. end if
  350. end
  351. ! wrapper for hash to handle special NC_BYTE/uchar adjustment */
  352. function hash4(type, rank, index, itype)
  353. implicit none
  354. integer type
  355. integer rank
  356. integer index(*)
  357. integer itype
  358. #include "tests.inc"
  359. hash4 = hash( type, rank, index )
  360. if ((itype .eq. NFT_CHAR) .and. (type .eq. NF_BYTE) .and.
  361. + (hash4 .ge. -128) .and. (hash4 .lt. 0)) hash4 = hash4 + 256
  362. end
  363. integer function char2type(letter)
  364. implicit none
  365. character*1 letter
  366. #include "tests.inc"
  367. if (letter .eq. 'c') then
  368. char2type = NF_CHAR
  369. else if (letter .eq. 'b') then
  370. char2type = NF_BYTE
  371. else if (letter .eq. 's') then
  372. char2type = NF_SHORT
  373. else if (letter .eq. 'i') then
  374. char2type = NF_INT
  375. else if (letter .eq. 'f') then
  376. char2type = NF_FLOAT
  377. else if (letter .eq. 'd') then
  378. char2type = NF_DOUBLE
  379. else
  380. stop 'char2type(): invalid type-letter'
  381. end if
  382. end
  383. subroutine init_dims(digit)
  384. implicit none
  385. character*1 digit(NDIMS)
  386. #include "tests.inc"
  387. integer dimid !/* index of dimension */
  388. do 1, dimid = 1, NDIMS
  389. if (dimid .eq. RECDIM) then
  390. dim_len(dimid) = NRECS
  391. else
  392. dim_len(dimid) = dimid - 1
  393. endif
  394. dim_name(dimid) = 'D' // digit(dimid)
  395. 1 continue
  396. end
  397. subroutine init_gatts(type_letter)
  398. implicit none
  399. character*1 type_letter(NTYPES)
  400. #include "tests.inc"
  401. integer attid
  402. integer char2type
  403. do 1, attid = 1, NTYPES
  404. gatt_name(attid) = 'G' // type_letter(attid)
  405. gatt_len(attid) = attid
  406. gatt_type(attid) = char2type(type_letter(attid))
  407. 1 continue
  408. end
  409. integer function prod(nn, sp)
  410. implicit none
  411. integer nn
  412. integer sp(MAX_RANK)
  413. #include "tests.inc"
  414. integer i
  415. prod = 1
  416. do 1, i = 1, nn
  417. prod = prod * sp(i)
  418. 1 continue
  419. end
  420. !
  421. ! define global variables:
  422. ! dim_name, dim_len,
  423. ! var_name, var_type, var_rank, var_shape, var_natts, var_dimid, var_nels
  424. ! att_name, gatt_name, att_type, gatt_type, att_len, gatt_len
  425. !
  426. subroutine init_gvars
  427. implicit none
  428. #include "tests.inc"
  429. integer max_dim_len(MAX_RANK)
  430. character*1 type_letter(NTYPES)
  431. character*1 digit(10)
  432. integer rank
  433. integer vn !/* var number */
  434. integer xtype !/* index of type */
  435. integer an !/* origin-0 cumulative attribute index */
  436. integer nvars
  437. integer jj
  438. integer ntypes
  439. integer tc
  440. integer tmp(MAX_RANK)
  441. integer ac !/* attribute index */
  442. integer dn !/* dimension number */
  443. integer prod !/* function */
  444. integer char2type !/* function */
  445. integer err
  446. data max_dim_len /0, MAX_DIM_LEN, MAX_DIM_LEN/
  447. data type_letter /'c', 'b', 's', 'i', 'f', 'd'/
  448. data digit /'r', '1', '2', '3', '4', '5',
  449. + '6', '7', '8', '9'/
  450. max_dim_len(1) = MAX_DIM_LEN + 1
  451. call init_dims(digit)
  452. vn = 1
  453. xtype = 1
  454. an = 0
  455. ! /* Loop over variable ranks */
  456. do 1, rank = 0, MAX_RANK
  457. nvars = prod(rank, max_dim_len)
  458. !/* Loop over variable shape vectors */
  459. do 2, jj = 1, nvars !/* 1, 5, 20, 80 */
  460. !/* number types of this shape */
  461. if (rank .lt. 2) then
  462. ntypes = NTYPES !/* 6 */
  463. else
  464. ntypes = 1
  465. end if
  466. !/* Loop over external data types */
  467. do 3, tc = 1, ntypes !/* 6, 1 */
  468. var_name(vn) = type_letter(xtype)
  469. var_type(vn) = char2type(type_letter(xtype))
  470. var_rank(vn) = rank
  471. if (rank .eq. 0) then
  472. var_natts(vn) = mod(vn - 1, MAX_NATTS + 1)
  473. else
  474. var_natts(vn) = 0
  475. end if
  476. do 4, ac = 1, var_natts(vn)
  477. attname(ac,vn) =
  478. + type_letter(1+mod(an, NTYPES))
  479. attlen(ac,vn) = an
  480. atttype(ac,vn) =
  481. + char2type(type_letter(1+mod(an, NTYPES)))
  482. an = an + 1
  483. 4 continue
  484. !/* Construct initial shape vector */
  485. err = index2ncindexes(jj, rank, max_dim_len, tmp)
  486. do 5, dn = 1, rank
  487. var_dimid(dn,vn) = tmp(1+rank-dn)
  488. 5 continue
  489. var_nels(vn) = 1
  490. do 6, dn = 1, rank
  491. if (dn .lt. rank) then
  492. var_dimid(dn,vn) = var_dimid(dn,vn) + 1
  493. end if
  494. if (var_dimid(dn,vn) .gt. 9) then
  495. stop 'Invalid var_dimid vector'
  496. end if
  497. var_name(vn)(rank+2-dn:rank+2-dn) =
  498. + digit(var_dimid(dn,vn))
  499. if (var_dimid(dn,vn) .ne. RECDIM) then
  500. var_shape(dn,vn) = var_dimid(dn,vn) - 1
  501. else
  502. var_shape(dn,vn) = NRECS
  503. end if
  504. var_nels(vn) = var_nels(vn) * var_shape(dn,vn)
  505. 6 continue
  506. vn = vn + 1
  507. xtype = 1 + mod(xtype, NTYPES)
  508. 3 continue
  509. 2 continue
  510. 1 continue
  511. call init_gatts(type_letter)
  512. end
  513. ! define dims defined by global variables */
  514. subroutine def_dims(ncid)
  515. implicit none
  516. integer ncid
  517. #include "tests.inc"
  518. integer err !/* status */
  519. integer i
  520. integer dimid !/* dimension id */
  521. do 1, i = 1, NDIMS
  522. if (i .eq. RECDIM) then
  523. err = nf_def_dim(ncid, dim_name(i), NF_UNLIMITED,
  524. + dimid)
  525. else
  526. err = nf_def_dim(ncid, dim_name(i), dim_len(i),
  527. + dimid)
  528. end if
  529. if (err .ne. 0) then
  530. call errore('nf_def_dim: ', err)
  531. end if
  532. 1 continue
  533. end
  534. ! define vars defined by global variables */
  535. subroutine def_vars(ncid)
  536. implicit none
  537. integer ncid
  538. #include "tests.inc"
  539. integer err !/* status */
  540. integer i
  541. integer var_id
  542. do 1, i = 1, NVARS
  543. err = nf_def_var(ncid, var_name(i), var_type(i),
  544. + var_rank(i), var_dimid(1,i), var_id)
  545. if (err .ne. 0) then
  546. call errore('nf_def_var: ', err)
  547. end if
  548. 1 continue
  549. end
  550. ! put attributes defined by global variables */
  551. subroutine put_atts(ncid)
  552. implicit none
  553. integer ncid
  554. #include "tests.inc"
  555. integer err !/* netCDF status */
  556. integer i !/* variable index (0 => global
  557. ! * attribute */
  558. integer k !/* attribute index */
  559. integer j !/* index of attribute */
  560. integer ndx(1)
  561. logical allInRange
  562. doubleprecision att(MAX_NELS)
  563. character*(MAX_NELS+2) catt
  564. do 1, i = 0, NVARS !/* var 0 => NF_GLOBAL attributes */
  565. do 2, j = 1, NATTS(i)
  566. if (NF_CHAR .eq. ATT_TYPE(j,i)) then
  567. catt = ' '
  568. do 3, k = 1, ATT_LEN(j,i)
  569. ndx(1) = k
  570. catt(k:k) = char(int(hash(ATT_TYPE(j,i), -1,
  571. + ndx)))
  572. 3 continue
  573. ! /*
  574. ! * The following ensures that the text buffer doesn't
  575. ! * start with 4 zeros (which is a CFORTRAN NULL pointer
  576. ! * indicator) yet contains a zero (which causes the
  577. ! * CFORTRAN interface to pass the address of the
  578. ! * actual text buffer).
  579. ! */
  580. catt(ATT_LEN(j,i)+1:ATT_LEN(j,i)+1) = char(1)
  581. catt(ATT_LEN(j,i)+2:ATT_LEN(j,i)+2) = char(0)
  582. err = nf_put_att_text(ncid, varid(i),
  583. + ATT_NAME(j,i),
  584. + ATT_LEN(j,i), catt)
  585. if (err .ne. 0) then
  586. call errore('nf_put_att_text: ', err)
  587. end if
  588. else
  589. allInRange = .true.
  590. do 4, k = 1, ATT_LEN(j,i)
  591. ndx(1) = k
  592. att(k) = hash(ATT_TYPE(j,i), -1, ndx)
  593. allInRange = allInRange .and.
  594. + inRange(att(k), ATT_TYPE(j,i))
  595. 4 continue
  596. err = nf_put_att_double(ncid, varid(i),
  597. + ATT_NAME(j,i),
  598. + ATT_TYPE(j,i),
  599. + ATT_LEN(j,i), att)
  600. if (allInRange) then
  601. if (err .ne. 0) then
  602. call errore('nf_put_att_double: ', err)
  603. end if
  604. else
  605. if (err .ne. NF_ERANGE) then
  606. call errore(
  607. + 'type-conversion range error: status = ',
  608. + err)
  609. end if
  610. end if
  611. end if
  612. 2 continue
  613. 1 continue
  614. end
  615. ! put variables defined by global variables */
  616. subroutine put_vars(ncid)
  617. implicit none
  618. integer ncid
  619. #include "tests.inc"
  620. integer start(MAX_RANK)
  621. integer index(MAX_RANK)
  622. integer err !/* netCDF status */
  623. integer i
  624. integer j
  625. doubleprecision value(MAX_NELS)
  626. character*(MAX_NELS+2) text
  627. logical allInRange
  628. do 1, j = 1, MAX_RANK
  629. start(j) = 1
  630. 1 continue
  631. do 2, i = 1, NVARS
  632. allInRange = .true.
  633. do 3, j = 1, var_nels(i)
  634. err = index2indexes(j, var_rank(i), var_shape(1,i),
  635. + index)
  636. if (err .ne. 0) then
  637. call errori(
  638. + 'Error calling index2indexes() for var ', j)
  639. end if
  640. if (var_name(i)(1:1) .eq. 'c') then
  641. text(j:j) =
  642. + char(int(hash(var_type(i), var_rank(i), index)))
  643. else
  644. value(j) = hash(var_type(i), var_rank(i), index)
  645. allInRange = allInRange .and.
  646. + inRange(value(j), var_type(i))
  647. end if
  648. 3 continue
  649. if (var_name(i)(1:1) .eq. 'c') then
  650. ! /*
  651. ! * The following statement ensures that the first 4
  652. ! * characters in 'text' are not all zeros (which is
  653. ! * a cfortran.h NULL indicator) and that the string
  654. ! * contains a zero (which will cause the address of the
  655. ! * actual string buffer to be passed).
  656. ! */
  657. text(var_nels(i)+1:var_nels(i)+1) = char(1)
  658. text(var_nels(i)+2:var_nels(i)+2) = char(0)
  659. err = nf_put_vara_text(ncid, i, start, var_shape(1,i),
  660. + text)
  661. if (err .ne. 0) then
  662. call errore('nf_put_vara_text: ', err)
  663. end if
  664. else
  665. err = nf_put_vara_double(ncid, i, start, var_shape(1,i),
  666. + value)
  667. if (allInRange) then
  668. if (err .ne. 0) then
  669. call errore('nf_put_vara_double: ', err)
  670. end if
  671. else
  672. if (err .ne. NF_ERANGE) then
  673. call errore(
  674. + 'type-conversion range error: status = ',
  675. + err)
  676. end if
  677. end if
  678. end if
  679. 2 continue
  680. end
  681. ! Create & write all of specified file using global variables */
  682. subroutine write_file(filename)
  683. implicit none
  684. character*(*) filename
  685. #include "tests.inc"
  686. integer ncid !/* netCDF id */
  687. integer err !/* netCDF status */
  688. err = nf_create(filename, NF_CLOBBER, ncid)
  689. if (err .ne. 0) then
  690. call errore('nf_create: ', err)
  691. end if
  692. call def_dims(ncid)
  693. call def_vars(ncid)
  694. call put_atts(ncid)
  695. err = nf_enddef(ncid)
  696. if (err .ne. 0) then
  697. call errore('nf_enddef: ', err)
  698. end if
  699. call put_vars(ncid)
  700. err = nf_close(ncid)
  701. if (err .ne. 0) then
  702. call errore('nf_close: ', err)
  703. end if
  704. end
  705. !
  706. ! check dimensions of specified file have expected name & length
  707. !
  708. subroutine check_dims(ncid)
  709. implicit none
  710. integer ncid
  711. #include "tests.inc"
  712. character*(NF_MAX_NAME) name
  713. integer length
  714. integer i
  715. integer err !/* netCDF status */
  716. do 1, i = 1, NDIMS
  717. err = nf_inq_dim(ncid, i, name, length)
  718. if (err .ne. 0) then
  719. call errore('nf_inq_dim: ', err)
  720. end if
  721. if (name .ne. dim_name(i)) then
  722. call errori('Unexpected name of dimension ', i)
  723. end if
  724. if (length .ne. dim_len(i)) then
  725. call errori('Unexpected length of dimension ', i)
  726. end if
  727. 1 continue
  728. end
  729. !
  730. ! check variables of specified file have expected name, type, shape & values
  731. !
  732. subroutine check_vars(ncid)
  733. implicit none
  734. integer ncid
  735. #include "tests.inc"
  736. integer index(MAX_RANK)
  737. integer err !/* netCDF status */
  738. integer i
  739. integer j
  740. character*1 text
  741. doubleprecision value
  742. integer datatype
  743. integer ndims
  744. integer natt
  745. integer dimids(MAX_RANK)
  746. logical isChar
  747. doubleprecision expect
  748. character*(NF_MAX_NAME) name
  749. integer length
  750. integer nok !/* count of valid comparisons */
  751. nok = 0
  752. do 1, i = 1, NVARS
  753. isChar = var_type(i) .eq. NF_CHAR
  754. err = nf_inq_var(ncid, i, name, datatype, ndims, dimids,
  755. + natt)
  756. if (err .ne. 0) then
  757. call errore('nf_inq_var: ', err)
  758. end if
  759. if (name .ne. var_name(i)) then
  760. call errori('Unexpected var_name for variable ', i)
  761. end if
  762. if (datatype .ne. var_type(i)) then
  763. call errori('Unexpected type for variable ', i)
  764. end if
  765. if (ndims .ne. var_rank(i)) then
  766. call errori('Unexpected rank for variable ', i)
  767. end if
  768. do 2, j = 1, ndims
  769. err = nf_inq_dim(ncid, dimids(j), name, length)
  770. if (err .ne. 0) then
  771. call errore('nf_inq_dim: ', err)
  772. end if
  773. if (length .ne. var_shape(j,i)) then
  774. call errori('Unexpected shape for variable ', i)
  775. end if
  776. 2 continue
  777. do 3, j = 1, var_nels(i)
  778. err = index2indexes(j, var_rank(i), var_shape(1,i),
  779. + index)
  780. if (err .ne. 0) then
  781. call errori('error in index2indexes() 2, variable ',
  782. + i)
  783. end if
  784. expect = hash(var_type(i), var_rank(i), index )
  785. if (isChar) then
  786. err = nf_get_var1_text(ncid, i, index, text)
  787. if (err .ne. 0) then
  788. call errore('nf_get_var1_text: ', err)
  789. end if
  790. if (ichar(text) .ne. expect) then
  791. call errori(
  792. + 'Var value read not that expected for variable ', i)
  793. else
  794. nok = nok + 1
  795. end if
  796. else
  797. err = nf_get_var1_double(ncid, i, index, value)
  798. if (inRange(expect,var_type(i))) then
  799. if (err .ne. 0) then
  800. call errore('nf_get_var1_double: ', err)
  801. else
  802. if (.not. equal(value,expect,var_type(i),
  803. + NFT_DOUBLE)) then
  804. call errori(
  805. + 'Var value read not that expected for variable ', i)
  806. else
  807. nok = nok + 1
  808. end if
  809. end if
  810. end if
  811. end if
  812. 3 continue
  813. 1 continue
  814. call print_nok(nok)
  815. end
  816. !
  817. ! check attributes of specified file have expected name, type, length & values
  818. !
  819. subroutine check_atts(ncid)
  820. implicit none
  821. integer ncid
  822. #include "tests.inc"
  823. integer err !/* netCDF status */
  824. integer i
  825. integer j
  826. integer k
  827. integer vid !/* "variable" ID */
  828. integer datatype
  829. integer ndx(1)
  830. character*(NF_MAX_NAME) name
  831. integer length
  832. character*(MAX_NELS) text
  833. doubleprecision value(MAX_NELS)
  834. doubleprecision expect
  835. integer nok !/* count of valid comparisons */
  836. nok = 0
  837. do 1, vid = 0, NVARS
  838. i = varid(vid)
  839. do 2, j = 1, NATTS(i)
  840. err = nf_inq_attname(ncid, i, j, name)
  841. if (err .ne. 0) then
  842. call errore('nf_inq_attname: ', err)
  843. end if
  844. if (name .ne. ATT_NAME(j,i)) then
  845. call errori(
  846. + 'nf_inq_attname: unexpected name for var ', i)
  847. end if
  848. err = nf_inq_att(ncid, i, name, datatype, length)
  849. if (err .ne. 0) then
  850. call errore('nf_inq_att: ', err)
  851. end if
  852. if (datatype .ne. ATT_TYPE(j,i)) then
  853. call errori('nf_inq_att: unexpected type for var ',
  854. + i)
  855. end if
  856. if (length .ne. ATT_LEN(j,i)) then
  857. call errori(
  858. + 'nf_inq_att: unexpected length for var ', i)
  859. end if
  860. if (datatype .eq. NF_CHAR) then
  861. err = nf_get_att_text(ncid, i, name, text)
  862. if (err .ne. 0) then
  863. call errore('nf_get_att_text: ', err)
  864. end if
  865. do 3, k = 1, ATT_LEN(j,i)
  866. ndx(1) = k
  867. if (ichar(text(k:k)) .ne. hash(datatype, -1,
  868. + ndx))
  869. + then
  870. call errori(
  871. + 'nf_get_att_text: unexpected value for var ', i)
  872. else
  873. nok = nok + 1
  874. end if
  875. 3 continue
  876. else
  877. err = nf_get_att_double(ncid, i, name, value)
  878. do 4, k = 1, ATT_LEN(j,i)
  879. ndx(1) = k
  880. expect = hash(datatype, -1, ndx)
  881. if (inRange(expect,ATT_TYPE(j,i))) then
  882. if (err .ne. 0) then
  883. call errore('nf_get_att_double: ', err)
  884. end if
  885. if (.not. equal(value(k), expect,
  886. + ATT_TYPE(j,i), NFT_DOUBLE)) then
  887. call errori(
  888. + 'Att value read not that expected for var ', i)
  889. else
  890. nok = nok + 1
  891. end if
  892. end if
  893. 4 continue
  894. end if
  895. 2 continue
  896. 1 continue
  897. call print_nok(nok)
  898. end
  899. ! Check file (dims, vars, atts) corresponds to global variables */
  900. subroutine check_file(filename)
  901. implicit none
  902. character*(*) filename
  903. #include "tests.inc"
  904. integer ncid !/* netCDF id */
  905. integer err !/* netCDF status */
  906. err = nf_open(filename, NF_NOWRITE, ncid)
  907. if (err .ne. 0) then
  908. call errore('nf_open: ', err)
  909. else
  910. call check_dims(ncid)
  911. call check_vars(ncid)
  912. call check_atts(ncid)
  913. err = nf_close (ncid)
  914. if (err .ne. 0) then
  915. call errore('nf_close: ', err)
  916. end if
  917. end if
  918. end
  919. !
  920. ! Functions for accessing attribute test data.
  921. !
  922. ! NB: 'varid' is 0 for global attributes; thus, global attributes can
  923. ! be handled in the same loop as variable attributes.
  924. !
  925. FUNCTION VARID(VID)
  926. IMPLICIT NONE
  927. INTEGER VID
  928. #include "tests.inc"
  929. IF (VID .LT. 1) THEN
  930. VARID = NF_GLOBAL
  931. ELSE
  932. VARID = VID
  933. ENDIF
  934. end
  935. FUNCTION NATTS(VID)
  936. IMPLICIT NONE
  937. INTEGER VID
  938. #include "tests.inc"
  939. IF (VID .LT. 1) THEN
  940. NATTS = NGATTS
  941. ELSE
  942. NATTS = VAR_NATTS(VID)
  943. ENDIF
  944. END
  945. FUNCTION ATT_NAME(J,VID)
  946. IMPLICIT NONE
  947. INTEGER J
  948. INTEGER VID
  949. #include "tests.inc"
  950. IF (VID .LT. 1) THEN
  951. ATT_NAME = GATT_NAME(J)
  952. ELSE
  953. ATT_NAME = ATTNAME(J,VID)
  954. ENDIF
  955. END
  956. FUNCTION ATT_TYPE(J,VID)
  957. IMPLICIT NONE
  958. INTEGER J
  959. INTEGER VID
  960. #include "tests.inc"
  961. IF (VID .LT. 1) THEN
  962. ATT_TYPE = GATT_TYPE(J)
  963. ELSE
  964. ATT_TYPE = ATTTYPE(J,VID)
  965. ENDIF
  966. END
  967. FUNCTION ATT_LEN(J,VID)
  968. IMPLICIT NONE
  969. INTEGER J
  970. INTEGER VID
  971. #include "tests.inc"
  972. IF (VID .LT. 1) THEN
  973. ATT_LEN = GATT_LEN(J)
  974. ELSE
  975. ATT_LEN = ATTLEN(J,VID)
  976. ENDIF
  977. END
  978. !
  979. ! Return the minimum value of an internal type.
  980. !
  981. function internal_min(type)
  982. implicit none
  983. integer type
  984. doubleprecision min_schar
  985. doubleprecision min_short
  986. doubleprecision min_int
  987. doubleprecision min_long
  988. doubleprecision max_float
  989. doubleprecision max_double
  990. #include "tests.inc"
  991. if (type .eq. NFT_CHAR) then
  992. internal_min = 0
  993. else if (type .eq. NFT_INT1) then
  994. #if NF_INT1_IS_C_SIGNED_CHAR
  995. internal_min = min_schar()
  996. #elif NF_INT1_IS_C_SHORT
  997. internal_min = min_short()
  998. #elif NF_INT1_IS_C_INT
  999. internal_min = min_int()
  1000. #elif NF_INT1_IS_C_LONG
  1001. internal_min = min_long()
  1002. #else
  1003. #include "No C equivalent to Fortran INTEGER*1"
  1004. #endif
  1005. else if (type .eq. NFT_INT2) then
  1006. #if NF_INT2_IS_C_SHORT
  1007. internal_min = min_short()
  1008. #elif NF_INT2_IS_C_INT
  1009. internal_min = min_int()
  1010. #elif NF_INT2_IS_C_LONG
  1011. internal_min = min_long()
  1012. #else
  1013. #include "No C equivalent to Fortran INTEGER*2"
  1014. #endif
  1015. else if (type .eq. NFT_INT) then
  1016. #if NF_INT_IS_C_INT
  1017. internal_min = min_int()
  1018. #elif NF_INT_IS_C_LONG
  1019. internal_min = min_long()
  1020. #else
  1021. #include "No C equivalent to Fortran INTEGER"
  1022. #endif
  1023. else if (type .eq. NFT_REAL) then
  1024. #if NF_REAL_IS_C_FLOAT
  1025. internal_min = -max_float()
  1026. #elif NF_REAL_IS_C_DOUBLE
  1027. internal_min = -max_double()
  1028. #else
  1029. #include "No C equivalent to Fortran REAL"
  1030. #endif
  1031. else if (type .eq. NFT_DOUBLE) then
  1032. #if NF_DOUBLEPRECISION_IS_C_DOUBLE
  1033. internal_min = -max_double()
  1034. #elif NF_DOUBLEPRECISION_IS_C_FLOAT
  1035. internal_min = -max_float()
  1036. #else
  1037. #include "No C equivalent to Fortran DOUBLE"
  1038. #endif
  1039. else
  1040. stop 'internal_min(): invalid type'
  1041. end if
  1042. end
  1043. !
  1044. ! Return the maximum value of an internal type.
  1045. !
  1046. function internal_max(type)
  1047. implicit none
  1048. integer type
  1049. doubleprecision max_schar
  1050. doubleprecision max_short
  1051. doubleprecision max_int
  1052. doubleprecision max_long
  1053. doubleprecision max_float
  1054. doubleprecision max_double
  1055. #include "tests.inc"
  1056. if (type .eq. NFT_CHAR) then
  1057. internal_max = 255
  1058. else if (type .eq. NFT_INT1) then
  1059. #if NF_INT1_IS_C_SIGNED_CHAR
  1060. internal_max = max_schar()
  1061. #elif NF_INT1_IS_C_SHORT
  1062. internal_max = max_short()
  1063. #elif NF_INT1_IS_C_INT
  1064. internal_max = max_int()
  1065. #elif NF_INT1_IS_C_LONG
  1066. internal_max = max_long()
  1067. #else
  1068. #include "No C equivalent to Fortran INTEGER*1"
  1069. #endif
  1070. else if (type .eq. NFT_INT2) then
  1071. #if NF_INT2_IS_C_SHORT
  1072. internal_max = max_short()
  1073. #elif NF_INT2_IS_C_INT
  1074. internal_max = max_int()
  1075. #elif NF_INT2_IS_C_LONG
  1076. internal_max = max_long()
  1077. #else
  1078. #include "No C equivalent to Fortran INTEGER*2"
  1079. #endif
  1080. else if (type .eq. NFT_INT) then
  1081. #if NF_INT_IS_C_INT
  1082. internal_max = max_int()
  1083. #elif NF_INT_IS_C_LONG
  1084. internal_max = max_long()
  1085. #else
  1086. #include "No C equivalent to Fortran INTEGER"
  1087. #endif
  1088. else if (type .eq. NFT_REAL) then
  1089. #if NF_REAL_IS_C_FLOAT
  1090. internal_max = max_float()
  1091. #elif NF_REAL_IS_C_DOUBLE
  1092. internal_max = max_double()
  1093. #else
  1094. #include "No C equivalent to Fortran REAL"
  1095. #endif
  1096. else if (type .eq. NFT_DOUBLE) then
  1097. #if NF_DOUBLEPRECISION_IS_C_DOUBLE
  1098. internal_max = max_double()
  1099. #elif NF_DOUBLEPRECISION_IS_C_FLOAT
  1100. internal_max = max_float()
  1101. #else
  1102. #include "No C equivalent to Fortran DOUBLE"
  1103. #endif
  1104. else
  1105. stop 'internal_max(): invalid type'
  1106. end if
  1107. end
  1108. !
  1109. ! Return the minimum value of an external type.
  1110. !
  1111. function external_min(type)
  1112. implicit none
  1113. integer type
  1114. #include "tests.inc"
  1115. if (type .eq. NF_BYTE) then
  1116. external_min = X_BYTE_MIN
  1117. else if (type .eq. NF_CHAR) then
  1118. external_min = X_CHAR_MIN
  1119. else if (type .eq. NF_SHORT) then
  1120. external_min = X_SHORT_MIN
  1121. else if (type .eq. NF_INT) then
  1122. external_min = X_INT_MIN
  1123. else if (type .eq. NF_FLOAT) then
  1124. external_min = X_FLOAT_MIN
  1125. else if (type .eq. NF_DOUBLE) then
  1126. external_min = X_DOUBLE_MIN
  1127. else
  1128. stop 'external_min(): invalid type'
  1129. end if
  1130. end
  1131. !
  1132. ! Return the maximum value of an internal type.
  1133. !
  1134. function external_max(type)
  1135. implicit none
  1136. integer type
  1137. #include "tests.inc"
  1138. if (type .eq. NF_BYTE) then
  1139. external_max = X_BYTE_MAX
  1140. else if (type .eq. NF_CHAR) then
  1141. external_max = X_CHAR_MAX
  1142. else if (type .eq. NF_SHORT) then
  1143. external_max = X_SHORT_MAX
  1144. else if (type .eq. NF_INT) then
  1145. external_max = X_INT_MAX
  1146. else if (type .eq. NF_FLOAT) then
  1147. external_max = X_FLOAT_MAX
  1148. else if (type .eq. NF_DOUBLE) then
  1149. external_max = X_DOUBLE_MAX
  1150. else
  1151. stop 'external_max(): invalid type'
  1152. end if
  1153. end
  1154. !
  1155. ! Indicate whether or not a value lies in the range of an internal type.
  1156. !
  1157. function in_internal_range(itype, value)
  1158. implicit none
  1159. integer itype
  1160. doubleprecision value
  1161. #include "tests.inc"
  1162. in_internal_range = value .ge. internal_min(itype) .and.
  1163. + value .le. internal_max(itype)
  1164. end
  1165. !
  1166. ! Return the length of a character variable minus any trailing blanks.
  1167. !
  1168. function len_trim(string)
  1169. implicit none
  1170. character*(*) string
  1171. #include "tests.inc"
  1172. do 1, len_trim = len(string), 1, -1
  1173. if (string(len_trim:len_trim) .ne. ' ')
  1174. + goto 2
  1175. 1 continue
  1176. 2 return
  1177. end