Besseres Idiom zum Füllen eines C ++ - Arrays von einem NumericVector

8

Ich verwende Rcpp , um einen (nicht von mir) geschriebenen Algorithmus in C-ähnliches C ++ zu schreiben (keine STL, kein Boost, nichts, soweit ich das beurteilen kann). Sie können den implementierten Algorithmus hier sehen (Ich verpacke kmeans_w_03 ). Folglich gebe ich einen numeric Vektor von R ein, der dann in ein double Array konvertiert werden muss.

Momentan schleife ich Element für Element und fülle das aus dem 'tother, wie folgt:

%Vor%

Aber mit numerischen Vektoren mit einzelnen Elementen kann ich Rcpps schöne as Casting-Funktionalität nutzen:

%Vor%

Versuchen Sie etwas ähnliches für die Länge & gt; 1 numerische Vektoren führen jedoch abhängig von der genauen Syntaxvariante zu einem Absturz oder einem Fehler:

%Vor%

Ich mag die Schleife nicht unbedingt, aber ich bin ein totaler Neuling und vermute, dass es einen besseren Weg gibt. Ich habe Rcpp-Einleitung, hadleys Wiki-Tutorial und RcppExamples gelesen und noch nichts gefunden, was diese Frage angeht, aber das bedeutet nicht, dass ich es nicht einfach vermisst habe. Meine Lektüre der Doxygen Rcpp Dokumente ist, dass as in einen STL-Vektor, aber kein Array umwandeln kann (aber ich habe es sehr schwer, diese Dokumente zu lesen, also vermute ich, dass ich da falsch liege). Wenn dem so ist, könnte ich zu einem Vektor und von dort zu einem Array umwandeln ...

Also meine Frage: Gibt es eine bessere (weniger Codezeilen, mehr expressiven Code und vielleicht sogar zu vermeidende Speicherzuweisung), um eine NumericVector in eine double[] ?     

Ari B. Friedman 24.12.2012, 13:48
quelle

3 Antworten

7

Ari, in der vorherigen Antwort, John macht einen guten Punkt. Um ein wenig zu erweitern, gibt es ein paar Probleme hier

  • Sie haben es mit einer Bibliothek mit antiquiertem Kodierungsstandard zu tun, die ein double[] oder *double möchte
  • Sie möchten bessere Codierungsstandards verwenden und Rcpp .
  • nutzen

Nun, fürchte nicht, wir haben eine einfache Lösung. Bilde die Rcpp::NumericVector X(weightvec); wie üblich in Sekundenschnelle und gib sie dann an deine Funktion foo() (oder was auch immer) als

weiter %Vor%

gibt Ihnen die erforderliche double* und bei Bedarf X.size() gibt die Länge an. Da Sie aus R kommen, müssen Sie sich nicht um Umfang und Lebensdauer sorgen, wenn Sie danach zu R zurückkehren.

Falls Sie expliziter sein müssen, habe ich auch das hässlichere &(X[0]) verwendet.

Auch der Rcpp::as<>() Caster funktioniert auch auf std::vector<double> , also kannst du

machen %Vor%

aber abgesehen von der Umwandlung in C ++ - Typen erhält es hier nichts.

Schließlich, falls Josh oder andere C-Diehards in der Nähe sind, nutzt all dies die Tatsache, dass der SEXP du von R garantiert den zusammenhängenden C-Zeiger hat, also könntest du auch über die sehr alte Schule gehen REAL(weightvec) .

    
Dirk Eddelbuettel 24.12.2012, 14:40
quelle
4

Das Schreiben eines C ++ - Programms, das nicht die Standardbibliothek verwendet (was Sie als "STL" bezeichnen), ist nicht das, was ich als "herkömmliches C ++" bezeichnen würde. Die Standardbibliothek ist Teil von der Sprache, wie sie im Standard definiert ist. Daher ist die Verwendung der im Standard definierten Funktionen kein unkonventionelles C ++. Ganz im Gegenteil, ich würde vorschlagen, dass das absichtliche Ignorieren dieser Einrichtungen unkonventionell ist. Es verwendet C ++ als ein "besseres C" oder ein "C mit Klassen". und das fehlt der Punkt.

Wenn Sie sich vor Augen halten, was Ihre Schleife erreichen möchte, verwenden Sie transform , um die Quelle zum Ziel zu kopieren, und vector als Ziel.

Sie haben hier auch einen Vermittler - Sie kopieren weightVec zuerst in ein neu erstelltes NumericVector und kopieren dann die Elemente daraus - aber das NumericVector wird weggeworfen . Das erscheint mir verschwenderisch.

Hier ist das Grundmuster, das ich mir beim Schreiben dieses Codes vorstellen würde:

%Vor%

Hier fehlen einige syntaktische Bits, die ich nicht ausfüllen kann, ohne mehr über die Compnents im Spiel zu wissen. Aber angesichts dessen, was Sie tun, scheint die Philosophie solide.

Beispielsweise hat das SEXP -Objekt möglicherweise nicht die Methoden begin() oder end() . Sie konstruieren jedoch bereits direkt ein NumericVector aus dem SEXP -Objekt, so dass% code_% wahrscheinlich analoge Möglichkeiten für SEXP und begin() hat, die Sie übernehmen oder möglicherweise sogar direkt verwenden können.

Das obige end() -Konstrukt ist ein Platzhalter für eine Funktion, einen Funktor oder ein Lambda (in C ++ 11), der ein einzelnes converter() -Element in ein SEXP umwandelt. Wiederum kenne ich nicht die Details, die ich brauche, um dies zu implementieren, aber es muss möglich sein, da Sie dies bereits auf eine andere Weise tun.

    
John Dibling 24.12.2012 14:15
quelle
0

Wenn Ihre Frage ist, wie Daten von Rcpp::NumericVector nach C ++ Array kopiert werden, ist transform() eine gute Antwort. Wenn Sie jedoch das innere Array von Rcpp::NumericVector erhalten möchten, das kein Kopieren enthält, können Sie genau das gleiche wie das extrahierende Array von std::vector :

tun %Vor%

wobei vec ein Rcpp::NumericVector ist.

    
David 10.01.2017 15:21
quelle

Tags und Links