Rcpp- und int64-NA-Wert

8

Wie kann ich einen NA-Wert von Rcpp an R in einem 64-Bit-Vektor übergeben?

Mein erster Ansatz wäre:

// [[Rcpp::export]]                                     
Rcpp::NumericVector foo() {
  Rcpp::NumericVector res(2);

  int64_t val = 1234567890123456789;
  std::memcpy(&(res[0]), &(val), sizeof(double));
  res[1] = NA_REAL;

  res.attr("class") = "integer64";
  return res;
}

Aber es gibt nach

#> foo()
integer64
[1] 1234567890123456789 9218868437227407266

Ich benötige

#> foo()
integer64
[1] 1234567890123456789 <NA>
David
quelle
Sie können NA_REALnach dem nicht verwenden, memcpyda das Bitmuster an diesem Punkt das von a ist int64.
Dirk Eddelbuettel
Ich würde auch den Titel bearbeiten. Die Standard-64-Bit-NA ist genau NA_realdas, worum es in Ihrer Frage nicht geht.
Dirk Eddelbuettel
Aber der Memcpy kopiert nur 64 Bit ( sizeof(double)), oder? So res[0]bekommt 64 Bits aus valund dann Einstellen res[1] = ...Anwendungen die nächsten 64 Bits. Ich bin mit dem Ergebnis einverstanden, aber folge deinem ersten Kommentar nicht wirklich.
David
1
Der springende Punkt ist , dass der Inhalt des Vektors ist dann Stück für Stück ein , int64_tdas lediglich wird als „geparkt“ in einem doubleVektor (aka NumericVector). Es gibt keine magische Logikkopie. Jems erledigt die ganze harte Arbeit von Hand. Einschließlich Mapping-NAs.
Dirk Eddelbuettel
1
Das. Ist. Was. Ich habe. Gewesen. Ich versuche es. Zu. Erklären. Schauen Sie sich zB die R-Quelle für die vorhandenen NA-Definitionen an. Schauen Sie sich einige Pakete mit an int64und sehen Sie, was sie tun.
Dirk Eddelbuettel

Antworten:

6

Okay, ich glaube ich habe eine Antwort gefunden ... (nicht schön, aber funktionierend).

Kurze Antwort:

// [[Rcpp::export]]                                     
Rcpp::NumericVector foo() {
  Rcpp::NumericVector res(2);

  int64_t val = 1234567890123456789;
  std::memcpy(&(res[0]), &(val), sizeof(double));

  # This is the magic:
  int64_t v = 1ULL << 63;
  std::memcpy(&(res[1]), &(v), sizeof(double));

  res.attr("class") = "integer64";
  return res;
}

was in ... resultiert

#> foo()
integer64
[1] 1234567890123456789 <NA>

Längere Antwort

Überprüfen, wie bit64einNA

# the last value is the max value of a 64 bit number
a <- bit64::as.integer64(c(1, 2, NA, 9223372036854775807))
a
#> integer64
#> [1] 1    2    <NA> <NA>
bit64::as.bitstring(a[3])
#> [1] "1000000000000000000000000000000000000000000000000000000000000000"
bit64::as.bitstring(a[4])
#> [1] "1000000000000000000000000000000000000000000000000000000000000000"

Erstellt am 23.04.2020 durch das reprex-Paket (v0.3.0)

wir sehen, dass es ein ist 10000.... Dies kann mit neu erstellt Rcppwerden int64_t val = 1ULL << 63;. Die Verwendung memcpy()anstelle einer einfachen Zuweisung mit =stellt sicher, dass keine Bits geändert werden!

David
quelle
1
Ja. Wenn Sie sich einige Quellpakete ansehen, sehen Sie die entsprechende #defineAnweisung, ein Bitmuster (häufig entweder minoder max) als NA-Wert zu deklarieren .
Dirk Eddelbuettel
6

Es ist wirklich viel, viel einfacher. Wir haben das Verhalten einesint64 in R, das von (mehreren) Add-On-Paketen angeboten wird, von denen das Beste darin besteht bit64, uns die integer64S3-Klasse und das damit verbundene Verhalten zu geben.

Und es definiert die NA intern wie folgt:

#define NA_INTEGER64 LLONG_MIN

Und das ist alles was es gibt. R und seine Pakete sind in erster Linie C-Code und LLONG_MINexistieren dort und gehen (fast) bis zu den Gründervätern zurück.

Hier gibt es zwei Lektionen. Die erste ist die Erweiterung von IEEE, die NaN und Inf für Gleitkommawerte definiert . R geht tatsächlich weit darüber hinaus und fügt hinzuNA für jeden seiner Typen hinzu . So ziemlich wie oben: durch Reservieren eines bestimmten Bitmusters. (In einem Fall ist dies der Geburtstag eines der beiden ursprünglichen R-Schöpfer.)

Die andere besteht darin, die Menge Arbeit zu bewundern, die Jens mit dem bit64Paket geleistet hat , sowie alle erforderlichen Konvertierungs- und Bedienerfunktionen. Die nahtlose Konvertierung aller möglichen Werte, einschließlich NA, NaN, Inf, ... ist keine leichte Aufgabe.

Und es ist ein ordentliches Thema, das nicht zu viele Menschen kennen. Ich bin froh, dass Sie die Frage gestellt haben, denn wir haben jetzt eine Aufzeichnung hier.

Dirk Eddelbuettel
quelle