R on Debian's riscv64 port

Summary

R has the concept of missing values in the statistical sense (NA). It encodes missing numeric values (NA_real_) as an IEEE-754 NaN with a distinctive payload; many fast paths rely on hardware arithmetic to “carry” that payload through computations. IEEE-754 does not require payload propagation (although it recommends it), and also does not fully specify payload propagation in all cases (especially binary operations with multiple NaN operands), so payload behavior can legitimately differ by platform.

On RISC-V hardware, and thus in our riscv64 port, floating-point implementations commonly canonicalize NaNs (dropping payload information), so arithmetic involving NA_real_ may yield an ordinary NaN rather than NA. This is a RISC-V design decision, the R developers are aware of it and decided that the issue won't be fixed on R's end.

This is within documented R behavior, which warns that the NA vs NaN distinction after computation is not guaranteed and may depend on the platform, compiler optimizations, or dynamic translation/instrumentation. Similar issues have been dealt with on ARM in the past by adjusting FPU mode at startup and general guidance is given to porters in the R admin guide appendix C7.

Debian context

We run R and R package test suites on more architectures than CRAN, including riscv64. Regressions that only trigger on riscv64 can block migration to testing and cascade to many reverse-dependencies.

A concrete example is r-cran-data.table (GitHub issue #7695): two tests expected NA but observed NaN on riscv64; the diagnosis was loss of the NA payload through arithmetic / conversions. In this case upstream chose to fix the issue by skipping tests when NA payload does not propagate.

When reporting regressions upstream, do not assume that “riscv64 implies payload loss” is the only relevant condition; similar behavior can appear on other architectures, or in other situations such as under Valgrind. It is up to Upstream to decide whether to add safeguards and extra handling for NA propagation in their packages, or to ignore the failures as corner cases. In that case you can suggest them to gate fragile tests (or optional strictness) on observable R behavior like in data.table PR #7702, which tests for identical(NA_real_ + 0, NA_real_).

Suggestions for R packages developers

This issue is particularly visible on riscv64 due to NaN canonicalization, but it is not specific to that platform. Similar behavior can occur on other architectures, compilers, or execution environments.

As a package developer, you are best placed to decide whether preservation of NA (as distinct from NaN) after arithmetic is essential for the correctness of your package, and whether it is worth the effort to support platforms where this property does not hold.

If you choose not to enforce strict NA propagation, you can make your tests more portable by adapting them to observable behavior:

If strict NA propagation is required for your package, but you cannot support platforms where it does not hold, you can make this explicit by failing tests early: if (!identical(NA_real_ + 0, NA_real_)) stop("This package requires NA payload propagation (NA_real_ must be preserved by arithmetic).")

This makes the limitation explicit to downstream users and distributions.