Skip to content

Commit ea98a87

Browse files
committed
almost ok, push_back for complexes is pending
1 parent 17ba519 commit ea98a87

File tree

9 files changed

+145
-54
lines changed

9 files changed

+145
-54
lines changed

cpp11test/R/cpp11.R

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ grow_ <- function(n) {
8484
.Call(`_cpp11test_grow_`, n)
8585
}
8686

87+
grow_cplx_ <- function(n) {
88+
.Call(`_cpp11test_grow_cplx_`, n)
89+
}
90+
8791
cpp11_insert_ <- function(num_sxp) {
8892
.Call(`_cpp11test_cpp11_insert_`, num_sxp)
8993
}
@@ -220,6 +224,18 @@ sum_cplx_for_6_ <- function(x_sxp) {
220224
.Call(`_cpp11test_sum_cplx_for_6_`, x_sxp)
221225
}
222226

227+
sum_cplx_foreach_ <- function(x) {
228+
.Call(`_cpp11test_sum_cplx_foreach_`, x)
229+
}
230+
231+
sum_cplx_accumulate_ <- function(x) {
232+
.Call(`_cpp11test_sum_cplx_accumulate_`, x)
233+
}
234+
235+
sum_cplx_for2_ <- function(x_sxp) {
236+
.Call(`_cpp11test_sum_cplx_for2_`, x_sxp)
237+
}
238+
223239
sum_int_for_ <- function(x) {
224240
.Call(`_cpp11test_sum_int_for_`, x)
225241
}

cpp11test/src/cpp11.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,13 @@ extern "C" SEXP _cpp11test_grow_(SEXP n) {
166166
return cpp11::as_sexp(grow_(cpp11::as_cpp<cpp11::decay_t<R_xlen_t>>(n)));
167167
END_CPP11
168168
}
169+
// grow.cpp
170+
cpp11::writable::complexes grow_cplx_(R_xlen_t n);
171+
extern "C" SEXP _cpp11test_grow_cplx_(SEXP n) {
172+
BEGIN_CPP11
173+
return cpp11::as_sexp(grow_cplx_(cpp11::as_cpp<cpp11::decay_t<R_xlen_t>>(n)));
174+
END_CPP11
175+
}
169176
// insert.cpp
170177
SEXP cpp11_insert_(SEXP num_sxp);
171178
extern "C" SEXP _cpp11test_cpp11_insert_(SEXP num_sxp) {
@@ -415,6 +422,27 @@ extern "C" SEXP _cpp11test_sum_cplx_for_6_(SEXP x_sxp) {
415422
return cpp11::as_sexp(sum_cplx_for_6_(cpp11::as_cpp<cpp11::decay_t<SEXP>>(x_sxp)));
416423
END_CPP11
417424
}
425+
// sum.cpp
426+
std::complex<double> sum_cplx_foreach_(cpp11::complexes x);
427+
extern "C" SEXP _cpp11test_sum_cplx_foreach_(SEXP x) {
428+
BEGIN_CPP11
429+
return cpp11::as_sexp(sum_cplx_foreach_(cpp11::as_cpp<cpp11::decay_t<cpp11::complexes>>(x)));
430+
END_CPP11
431+
}
432+
// sum.cpp
433+
std::complex<double> sum_cplx_accumulate_(cpp11::complexes x);
434+
extern "C" SEXP _cpp11test_sum_cplx_accumulate_(SEXP x) {
435+
BEGIN_CPP11
436+
return cpp11::as_sexp(sum_cplx_accumulate_(cpp11::as_cpp<cpp11::decay_t<cpp11::complexes>>(x)));
437+
END_CPP11
438+
}
439+
// sum.cpp
440+
std::complex<double> sum_cplx_for2_(SEXP x_sxp);
441+
extern "C" SEXP _cpp11test_sum_cplx_for2_(SEXP x_sxp) {
442+
BEGIN_CPP11
443+
return cpp11::as_sexp(sum_cplx_for2_(cpp11::as_cpp<cpp11::decay_t<SEXP>>(x_sxp)));
444+
END_CPP11
445+
}
418446
// sum_int.cpp
419447
double sum_int_for_(cpp11::integers x);
420448
extern "C" SEXP _cpp11test_sum_int_for_(SEXP x) {
@@ -530,6 +558,7 @@ static const R_CallMethodDef CallEntries[] = {
530558
{"_cpp11test_gibbs_rcpp", (DL_FUNC) &_cpp11test_gibbs_rcpp, 2},
531559
{"_cpp11test_gibbs_rcpp2", (DL_FUNC) &_cpp11test_gibbs_rcpp2, 2},
532560
{"_cpp11test_grow_", (DL_FUNC) &_cpp11test_grow_, 1},
561+
{"_cpp11test_grow_cplx_", (DL_FUNC) &_cpp11test_grow_cplx_, 1},
533562
{"_cpp11test_my_message", (DL_FUNC) &_cpp11test_my_message, 2},
534563
{"_cpp11test_my_message_n1", (DL_FUNC) &_cpp11test_my_message_n1, 1},
535564
{"_cpp11test_my_message_n1fmt", (DL_FUNC) &_cpp11test_my_message_n1fmt, 1},
@@ -562,12 +591,15 @@ static const R_CallMethodDef CallEntries[] = {
562591
{"_cpp11test_row_sums", (DL_FUNC) &_cpp11test_row_sums, 1},
563592
{"_cpp11test_string_proxy_assignment_", (DL_FUNC) &_cpp11test_string_proxy_assignment_, 0},
564593
{"_cpp11test_string_push_back_", (DL_FUNC) &_cpp11test_string_push_back_, 0},
594+
{"_cpp11test_sum_cplx_accumulate_", (DL_FUNC) &_cpp11test_sum_cplx_accumulate_, 1},
595+
{"_cpp11test_sum_cplx_for2_", (DL_FUNC) &_cpp11test_sum_cplx_for2_, 1},
565596
{"_cpp11test_sum_cplx_for_", (DL_FUNC) &_cpp11test_sum_cplx_for_, 1},
566597
{"_cpp11test_sum_cplx_for_2_", (DL_FUNC) &_cpp11test_sum_cplx_for_2_, 1},
567598
{"_cpp11test_sum_cplx_for_3_", (DL_FUNC) &_cpp11test_sum_cplx_for_3_, 1},
568599
{"_cpp11test_sum_cplx_for_4_", (DL_FUNC) &_cpp11test_sum_cplx_for_4_, 1},
569600
{"_cpp11test_sum_cplx_for_5_", (DL_FUNC) &_cpp11test_sum_cplx_for_5_, 1},
570601
{"_cpp11test_sum_cplx_for_6_", (DL_FUNC) &_cpp11test_sum_cplx_for_6_, 1},
602+
{"_cpp11test_sum_cplx_foreach_", (DL_FUNC) &_cpp11test_sum_cplx_foreach_, 1},
571603
{"_cpp11test_sum_dbl_accumulate2_", (DL_FUNC) &_cpp11test_sum_dbl_accumulate2_, 1},
572604
{"_cpp11test_sum_dbl_accumulate_", (DL_FUNC) &_cpp11test_sum_dbl_accumulate_, 1},
573605
{"_cpp11test_sum_dbl_for2_", (DL_FUNC) &_cpp11test_sum_dbl_for2_, 1},

cpp11test/src/grow.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "cpp11/doubles.hpp"
2+
#include "cpp11/complexes.hpp"
23

34
[[cpp11::register]] cpp11::writable::doubles grow_(R_xlen_t n) {
45
cpp11::writable::doubles x;
@@ -9,3 +10,14 @@
910

1011
return x;
1112
}
13+
14+
[[cpp11::register]] cpp11::writable::complexes grow_cplx_(R_xlen_t n) {
15+
cpp11::writable::complexes x;
16+
R_xlen_t i = 0;
17+
while (i < n) {
18+
x.push_back(std::complex<double>(i, i));
19+
i++;
20+
}
21+
22+
return x;
23+
}

cpp11test/src/sum.cpp

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,15 @@
6060
return std::accumulate(x.cbegin(), x.cend(), 0.);
6161
}
6262

63-
// Functions for complex data type
63+
// Pacha: Functions for complex data type
6464

6565
[[cpp11::register]] cpp11::r_complex sum_cplx_for_(cpp11::complexes x) {
6666
std::complex<double> sum = {0.0, 0.0};
6767
R_xlen_t n = x.size();
6868
for (R_xlen_t i = 0; i < n; ++i) {
69-
sum.real(sum.real() + x[i].real());
70-
sum.imag(sum.imag() + x[i].imag());
69+
// sum.real(sum.real() + x[i].real());
70+
// sum.imag(sum.imag() + x[i].imag());
71+
sum += x[i];
7172
}
7273

7374
return cpp11::r_complex(sum.real(), sum.imag());
@@ -77,12 +78,15 @@
7778
std::complex<double> sum = {0.0, 0.0};
7879
R_xlen_t n = x.size();
7980
for (R_xlen_t i = 0; i < n; ++i) {
80-
sum.real(sum.real() + x[i].real());
81-
sum.imag(sum.imag() + x[i].imag());
81+
// sum.real(sum.real() + x[i].real());
82+
// sum.imag(sum.imag() + x[i].imag());
83+
sum += x[i];
8284
}
8385

8486
cpp11::writable::complexes result(1);
85-
result[0] = cpp11::r_complex(sum.real(), sum.imag());
87+
// result[0] = cpp11::r_complex(sum.real(), sum.imag());
88+
result[0] = sum;
89+
8690
return result;
8791
}
8892

@@ -91,8 +95,9 @@
9195
const cpp11::complexes x(x_sxp, false);
9296
R_xlen_t n = x.size();
9397
for (R_xlen_t i = 0; i < n; ++i) {
94-
sum.real(sum.real() + x[i].real());
95-
sum.imag(sum.imag() + x[i].imag());
98+
// sum.real(sum.real() + x[i].real());
99+
// sum.imag(sum.imag() + x[i].imag());
100+
sum += x[i];
96101
}
97102

98103
return sum;
@@ -103,8 +108,9 @@
103108
const cpp11::complexes x(x_sxp, false);
104109
R_xlen_t n = x.size();
105110
for (R_xlen_t i = 0; i < n; ++i) {
106-
sum.real(sum.real() + x[i].real());
107-
sum.imag(sum.imag() + x[i].imag());
111+
// sum.real(sum.real() + x[i].real());
112+
// sum.imag(sum.imag() + x[i].imag());
113+
sum += x[i];
108114
}
109115

110116
return sum;
@@ -115,8 +121,9 @@
115121
const cpp11::complexes x(x_sxp, false);
116122
R_xlen_t n = x.size();
117123
for (R_xlen_t i = 0; i < n; ++i) {
118-
sum.real(sum.real() + x[i].real());
119-
sum.imag(sum.imag() + x[i].imag());
124+
// sum.real(sum.real() + x[i].real());
125+
// sum.imag(sum.imag() + x[i].imag());
126+
sum += x[i];
120127
}
121128

122129
return cpp11::as_sexp(sum);
@@ -127,9 +134,36 @@
127134
const cpp11::complexes x(x_sxp, false);
128135
R_xlen_t n = x.size();
129136
for (R_xlen_t i = 0; i < n; ++i) {
130-
sum.real(sum.real() + x[i].real());
131-
sum.imag(sum.imag() + x[i].imag());
137+
// sum.real(sum.real() + x[i].real());
138+
// sum.imag(sum.imag() + x[i].imag());
139+
sum += x[i];
132140
}
133141

134142
return cpp11::as_sexp(sum);
135143
}
144+
145+
[[cpp11::register]] std::complex<double> sum_cplx_foreach_(cpp11::complexes x) {
146+
std::complex<double> sum = {0.0, 0.0};
147+
for (const auto&& val : x) {
148+
// sum.real(sum.real() + val.real());
149+
// sum.imag(sum.imag() + val.imag());
150+
sum += val;
151+
}
152+
153+
return sum;
154+
}
155+
156+
[[cpp11::register]] std::complex<double> sum_cplx_accumulate_(cpp11::complexes x) {
157+
return std::accumulate(x.cbegin(), x.cend(), std::complex<double>(0.0, 0.0));
158+
}
159+
160+
[[cpp11::register]] std::complex<double> sum_cplx_for2_(SEXP x_sxp) {
161+
std::complex<double> sum = {0.0, 0.0};
162+
const cpp11::complexes x(x_sxp);
163+
R_xlen_t n = x.size();
164+
for (R_xlen_t i = 0; i < n; ++i) {
165+
sum += x[i];
166+
}
167+
168+
return sum;
169+
}

cpp11test/src/test-complex.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ context("complexes-C++") {
484484
// expect_error(--x0);
485485
}
486486

487-
test_that("writable::complexes convert to complexes with correct size (#128)") {
487+
test_that("writable::complexes convert to complexes with correct size") {
488488
cpp11::r_complex one{1, 1};
489489
cpp11::r_complex two{2, 2};
490490
cpp11::r_complex three{3, 3};

cpp11test/tests/testthat/test-complex.R

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@ test_that("complex iterators work with normal vectors", {
44
x <- complex(real = rnorm(len), imaginary = rnorm(len))
55
sum_base <- sum(x)
66

7+
# Pacha: I know this is redundant, but exhanging equivalent types
8+
# allowed me to test for errors in the implementation
79
expect_equal(sum_cplx_for_(x), sum_base)
810
expect_equal(sum_cplx_for_2_(x), sum_base)
911
expect_equal(sum_cplx_for_3_(x), sum_base)
1012
expect_equal(sum_cplx_for_4_(x), sum_base)
1113
expect_equal(sum_cplx_for_5_(x), sum_base)
1214
expect_equal(sum_cplx_for_6_(x), sum_base)
13-
# expect_equal(sum_cplx_foreach_(x), sum_base)
14-
# expect_equal(sum_cplx_accumulate_(x), sum_base)
15-
# expect_equal(sum_cplx_for2_(x), sum_base)
15+
16+
expect_equal(sum_cplx_foreach_(x), sum_base)
17+
expect_equal(sum_cplx_accumulate_(x), sum_base)
18+
expect_equal(sum_cplx_for2_(x), sum_base)
1619
})
1720

1821
test_that("complex iterators work with altrep vectors", {
@@ -24,15 +27,15 @@ test_that("complex iterators work with altrep vectors", {
2427
sum_base <- sum(x)
2528

2629
expect_equal(sum_cplx_for_(x), sum_base)
27-
# expect_equal(sum_cplx_foreach_(x), sum_base)
28-
# expect_equal(sum_cplx_accumulate_(x), sum_base)
29-
# expect_equal(sum_cplx_for2_(x), sum_base)
30+
expect_equal(sum_cplx_foreach_(x), sum_base)
31+
expect_equal(sum_cplx_accumulate_(x), sum_base)
32+
expect_equal(sum_cplx_for2_(x), sum_base)
3033
})
3134

32-
# test_that("writable::complex grow", {
33-
# len <- 1e5L
34-
# expect_equal(grow_cplx_(len), complex(
35-
# real = as.numeric(seq(0, len - 1)),
36-
# imaginary = as.numeric(seq(0, len - 1))
37-
# ))
38-
# })
35+
test_that("writable::complex grow", {
36+
len <- 1e5L
37+
expect_equal(grow_cplx_(len), complex(
38+
real = as.numeric(seq(0, len - 1)),
39+
imaginary = as.numeric(seq(0, len - 1))
40+
))
41+
})

inst/include/cpp11/as.hpp

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -334,28 +334,21 @@ enable_if_convertible_to_sexp<T, SEXP> as_sexp(const T& from) {
334334
return from;
335335
}
336336

337+
// Definition for converting SEXP to std::complex<double>
338+
inline std::complex<double> as_cpp(SEXP x) {
339+
if (TYPEOF(x) != CPLXSXP || Rf_length(x) != 1) {
340+
throw std::invalid_argument("Expected a single complex number.");
341+
}
342+
Rcomplex c = COMPLEX(x)[0];
343+
return {c.r, c.i};
344+
}
345+
337346
// Specialization for converting std::complex<double> to SEXP
338-
template <>
339347
inline SEXP as_sexp(const std::complex<double>& x) {
340348
SEXP result = PROTECT(Rf_allocVector(CPLXSXP, 1));
341349
COMPLEX(result)[0].r = x.real();
342350
COMPLEX(result)[0].i = x.imag();
343351
UNPROTECT(1);
344352
return result;
345353
}
346-
347-
// Declaration for converting SEXP to std::complex<double>
348-
template <>
349-
std::complex<double> as_cpp(SEXP x);
350-
351-
// Specialization for as_cpp with std::complex<double>
352-
template <>
353-
inline std::complex<double> as_cpp<std::complex<double>>(SEXP x) {
354-
if (TYPEOF(x) != CPLXSXP || Rf_length(x) != 1) {
355-
throw std::invalid_argument("Expected a single complex number.");
356-
}
357-
Rcomplex c = COMPLEX(x)[0];
358-
return {c.r, c.i};
359-
}
360-
361354
} // namespace cpp11

inst/include/cpp11/r_complex.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,15 @@ struct get_underlying_type<r_complex> {
140140
};
141141
} // namespace traits
142142

143+
// Define operator+ for std::complex<double> and r_complex
144+
inline std::complex<double> operator+(const std::complex<double>& lhs,
145+
const r_complex& rhs) {
146+
return std::complex<double>(lhs.real() + rhs.real(), lhs.imag() + rhs.imag());
147+
}
148+
149+
inline std::complex<double> operator+(const r_complex& lhs,
150+
const std::complex<double>& rhs) {
151+
return std::complex<double>(lhs.real() + rhs.real(), lhs.imag() + rhs.imag());
152+
}
153+
143154
} // namespace cpp11

inst/include/cpp11/sexp.hpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,4 @@ class sexp {
7676
operator bool() const { return LOGICAL_ELT(data_, 0); }
7777
};
7878

79-
// Specialization for converting std::complex<double> to SEXP
80-
template <>
81-
inline SEXP as_sexp(const std::complex<double>& from) {
82-
SEXP result = PROTECT(Rf_allocVector(CPLXSXP, 1));
83-
COMPLEX(result)[0].r = from.real();
84-
COMPLEX(result)[0].i = from.imag();
85-
UNPROTECT(1);
86-
return result;
87-
}
88-
8979
} // namespace cpp11

0 commit comments

Comments
 (0)