Cereri de extragere Cpp11 pentru a îmbunătăți integrarea R și C++

URMĂREȘTE-NE
16,065FaniÎmi place
1,142CititoriConectați-vă

(Acest articol a fost publicat pentru prima dată pe pacha.dev/blogși cu amabilitate a contribuit la R-bloggeri). (Puteți raporta problema legată de conținutul acestei pagini aici)


Doriți să vă distribuiți conținutul pe R-bloggeri? dați clic aici dacă aveți un blog, sau aici dacă nu aveți.

Despre

Din descrierea cpp11: „Oferă doar un antet, interfața C++11 către interfața C a lui R. În comparație cu alte abordări, „cpp11” se străduiește să fie în siguranță împotriva salturilor în lungime de la API-ul C, precum și de la excepțiile C++, se conformează semanticii normale a funcției R și acceptă interacțiunea cu vectorii „ALTREP”.

Am folosit cpp11 timp de doi ani imediat după ce am început să învăț C++ fără cunoștințe anterioare de C/C++. Acum am sugerat următoarele modificări ale bazei de cod pentru a îmbunătăți experiența utilizatorului și pentru a reduce numărul de linii de cod necesare pentru a efectua sarcini comune. Am exclus descrierea PR-urilor care se referă doar la aspecte tehnice sau la teste.

PR-uri

Conversia logicii în numere întregi și duble

as_integers() şi as_doubles() acum înțelegeți intrările logice (#426).

Iată un exemplu de ceva care a returnat o eroare înainte:

test_that("as_doubles(logicals)") {
  cpp11::writable::logicals y;

  for (int i = 0; i < 4; i++) {
    y.push_back(i % 2 == 0);
  }

  cpp11::doubles i(cpp11::as_doubles(y));

  expect_true(i(0) == 1.0);
  expect_true(i(1) == 0.0);
  expect_true(i(2) == 1.0);
  expect_true(i(3) == 0.0);
  expect_true(cpp11::detail::r_typeof(i) == REALSXP);
}

Îmbunătățirea performanței vectorului șir pentru push_back și atribuirea indicelui

Am adăugat refactori și test care se traduc într-un push_back care este mai aproape de un raport de viteză 1:1 decât 1:4 în comparație cu atribuirea directă (#430).

Anterior, push_back a fost de 4 ori mai lentă decât atribuirea directă din cauza protecțiilor aplicate în cazurile în care există o atribuire imediată fără traducere.

# A tibble: 14 × 6
   expression                       len      min mem_alloc n_itr  n_gc
                            
 1 assign_cpp11_(n = len, 123L) 1000000 590.79ms   21.63MB    12     8
 2 assign_rcpp_(n = len, 123L)  1000000 441.09ms    7.63MB    15     5

# A tibble: 3 × 6
  expression                          len      min mem_alloc n_itr  n_gc
                              
1 grow_strings_cpp11_(len, 123L)  1000000    462ms   23.63MB     7    13
2 grow_strings_rcpp_(len, 123L)   1000000    453ms    7.63MB    16     4
3 grow_strings_manual_(len, 123L) 1000000    438ms   23.63MB     8    12

Convertiți hărți C++ ordonate și neordonate în liste R

Hărțile C++ ordonate și neordonate sunt convertite acum în liste R (#437).

Iată un exemplu de ceva ce nu era posibil înainte:

((cpp11::register)) SEXP ordered_map_to_list_(cpp11::doubles x) {
  std::map counts;
  int n = x.size();
  for (int i = 0; i < n; i++) {
    counts(x(i))++;
  }
  return cpp11::as_sexp(counts);
}

Setați corect numele pentru matrice

Anterior, cpp11 a ignorat numele coloanelor sau rândurilor și nu a permis să le definească pe cele din partea C++ pentru o doubles_matrix sau integers_matrixcu excepția cazului în care a fost convertit în a SEXP (#428).

Iată un exemplu de corectare:

((cpp11::register)) cpp11::doubles_matrix<> mat_mat_create_dimnames() {
  cpp11::writable::doubles_matrix<> out(2, 2);

  out(0, 0) = 1;
  out(0, 1) = 2;
  out(1, 0) = 3;
  out(1, 1) = 4;

  cpp11::writable::list dimnames(2);
  dimnames(0) = cpp11::strings({"a", "b"});
  dimnames(1) = cpp11::strings({"c", "d"});

  out.attr("dimnames") = dimnames;

  return out;
}

Copiați numere complexe, vectori sau matrici din R în C++ și invers

Anterior, treceam numere complexe de la R la C++ și invers, transformându-le într-o listă cu partea reală și partea imaginară exprimată ca primul și al doilea vector al listei. Acum este posibil să le treci direct (#427).

Iată un exemplu de ceva ce nu era posibil înainte:

test_that("vector objects can be created, filled, and copied") {
  cpp11::writable::complexes v(2);
  v(0) = std::complex(1, 2);
  v(1) = std::complex(3, 4);

  cpp11::complexes vc = v;

  expect_true(v.size() == vc.size());

  for (int i = 0; i < 2; ++i) {
   expect_true(v(i) == vc(i));
  }
}

Documentați funcțiile cu Roxygen direct în scripturi C++

Pentru a reduce dezordinea în fluxul meu de lucru, am adăugat un cod pentru a putea roxygenize direct în fișierele cpp, în loc să documentez funcțiile separat (#440).

Iată un exemplu de ceva ce nu era posibil înainte:

#include "cpp11/doubles.hpp"
using namespace cpp11;

/* roxygen start
@title Roxygenised x plus 1
@param x numeric value
@description Dummy function to test roxygen2. It adds 1.0 to a double.
@export
@examples roxcpp_(1.0)
roxygen end */
((cpp11::register)) double roxcpp_(double x) {
  double y = x + 1.0;
  return y;
}

Dominic Botezariu
Dominic Botezariuhttps://www.noobz.ro/
Creator de site și redactor-șef.

Cele mai noi știri

Pe același subiect

LĂSAȚI UN MESAJ

Vă rugăm să introduceți comentariul dvs.!
Introduceți aici numele dvs.