Skip to content

[R-pkg-devel] fortran integer(kind=)

2 messages · Berry Boessenkool, Ivan Krylov

#
Dear list members,

my R package dwdradar uses Fortran code with the input parameter integer(KIND=2):
https://github.com/brry/dwdradar/blob/master/src/binary_to_num.f90#L20
https://github.com/brry/dwdradar/blob/master/src/binary_to_num.f90#L55

The CRAN team wrote to change that (line breaks added):
According to the Fortran standards, numerical values are just an enumeration.
What e.g. real(kind=4) means (or even if it is accepted) is implementation dependent.
Please change them to something portable.
kind(1.0) or kind(1.0d0} are  commonly used, as is c_double from iso_c_binding.

There are differing(?) answers on stackoverflow that I don't understand:
https://stackoverflow.com/a/3170438

With what should I replace the current code?
A pointer to relevant info would already be highly appreciated.

Thanks ahead,
Berry

PS: I contacted the original author, but his Fortran skills also do not suffice to solve this issue...
PPS: a related issue came up in this list yesterday:
https://stat.ethz.ch/pipermail/r-package-devel/2023q3/009514.html
#
On Thu, 31 Aug 2023 06:52:47 +0000
Berry Boessenkool <berryboessenkool at hotmail.com> wrote:

            
The "raw" argument of the Fortran function originates from the
"dat" argument to the R function "bin2num", which, in turn, originates
from readBin(what = raw()):
https://github.com/brry/dwdradar/blob/master/R/bin2num.R#L21-L25
https://github.com/brry/dwdradar/blob/master/R/readRadarFile.R#L51

"Raw" vectors correspond to the C type unsigned char, which you seem to
be interpreting as 16-bit integers instead. (This might be a violation
of aliasing rules, but the compiler is not in a position to see it, and
it's been working for years.) The 16-bit integer type in Fortran can be
declared using the iso_c_binding module:

use, intrinsic :: iso_c_binding, only: c_int16_t
integer(KIND=c_int16_t),DIMENSION(Flength),INTENT(in)::raw

There's probably a safer and only slightly less performant way to
implement binary_to_num in R:

dat <- as.integer(dat)
# interpret the bytes as little-endian double-byte integers
dat <- dat[seq(1, length(dat), 2)] + 256 * dat[seq(2, length(dat), 2)]
# extract the 12-bit data
out <- bitwAnd(dat, 4095)
# set the missing flag
is.na(out) <- as.logical(bitwAnd(dat, bitwShiftL(1, 13)))
# set the negative flag
out <- -1 * as.logical(bitwAnd(dat, bitwShiftL(1, 14)))
# set the clutter flag
out[as.logical(bitwAnd(dat, bitwShiftL(1, 15)))] <- clutter