Skip to content

Commit b003c28

Browse files
committed
complex tests work, BUT THERE IS A CATCH ERROR I DO NOT GET
1 parent 49ee179 commit b003c28

File tree

6 files changed

+146
-66
lines changed

6 files changed

+146
-66
lines changed

cpp11test/src/grow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#include "cpp11/doubles.hpp"
21
#include "cpp11/complexes.hpp"
2+
#include "cpp11/doubles.hpp"
33

44
[[cpp11::register]] cpp11::writable::doubles grow_(R_xlen_t n) {
55
cpp11::writable::doubles x;

inst/include/cpp11/complexes.hpp

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
#pragma once
22

3-
#include <algorithm> // for min
4-
#include <array> // for array
3+
#include <algorithm> // for std::transform
54
#include <complex> // for std::complex
6-
#include <initializer_list> // for initializer_list
5+
#include <initializer_list> // for std::initializer_list
76

8-
#include "cpp11/R.hpp" // for SEXP, SEXPREC, Rf_allocVector
9-
#include "cpp11/as.hpp" // for as_sexp
10-
#include "cpp11/attribute_proxy.hpp" // for attribute_proxy
11-
#include "cpp11/named_arg.hpp" // for named_arg
12-
#include "cpp11/protect.hpp" // for preserved
13-
#include "cpp11/r_complex.hpp" // for r_complex
14-
#include "cpp11/r_vector.hpp" // for r_vector, r_vector<>::proxy
15-
#include "cpp11/sexp.hpp" // for sexp
7+
#include "cpp11/R.hpp" // for SEXP, SEXPREC, Rf_allocVector, COMPLEX, COMPLEX_ELT, SET_COMPLEX_ELT
8+
#include "cpp11/as.hpp" // for as_sexp
9+
#include "cpp11/protect.hpp" // for safe
10+
#include "cpp11/r_complex.hpp" // for r_complex
11+
#include "cpp11/r_vector.hpp" // for r_vector, r_vector<>::proxy
12+
#include "cpp11/sexp.hpp" // for sexp
1613

1714
namespace cpp11 {
1815

@@ -26,7 +23,7 @@ inline SEXPTYPE r_vector<r_complex>::get_sexptype() {
2623
template <>
2724
inline typename r_vector<r_complex>::underlying_type r_vector<r_complex>::get_elt(
2825
SEXP x, R_xlen_t i) {
29-
return r_complex(COMPLEX_ELT(x, i));
26+
return COMPLEX_ELT(x, i);
3027
}
3128

3229
template <>
@@ -35,20 +32,20 @@ inline typename r_vector<r_complex>::underlying_type* r_vector<r_complex>::get_p
3532
if (is_altrep) {
3633
return nullptr;
3734
} else {
38-
return reinterpret_cast<r_complex*>(COMPLEX(data));
35+
return COMPLEX(data);
3936
}
4037
}
4138

4239
template <>
4340
inline typename r_vector<r_complex>::underlying_type const*
4441
r_vector<r_complex>::get_const_p(bool is_altrep, SEXP data) {
45-
return reinterpret_cast<const r_complex*>(COMPLEX_OR_NULL(data));
42+
return COMPLEX_OR_NULL(data);
4643
}
4744

4845
template <>
4946
inline void r_vector<r_complex>::get_region(SEXP x, R_xlen_t i, R_xlen_t n,
5047
typename r_vector::underlying_type* buf) {
51-
COMPLEX_GET_REGION(x, i, n, reinterpret_cast<Rcomplex*>(buf));
48+
COMPLEX_GET_REGION(x, i, n, buf);
5249
}
5350

5451
template <>
@@ -61,9 +58,9 @@ typedef r_vector<r_complex> complexes;
6158
namespace writable {
6259

6360
template <>
64-
inline void r_vector<r_complex>::set_elt(SEXP x, R_xlen_t i,
65-
r_vector::underlying_type value) {
66-
COMPLEX(x)[i] = static_cast<Rcomplex>(value);
61+
inline void r_vector<r_complex>::set_elt(
62+
SEXP x, R_xlen_t i, typename cpp11::r_vector<r_complex>::underlying_type value) {
63+
COMPLEX(x)[i] = value;
6764
}
6865

6966
typedef r_vector<r_complex> complexes;
@@ -98,11 +95,8 @@ class r_vector<r_complex>::proxy {
9895
proxy(SEXP data, R_xlen_t index)
9996
: data_(data), index_(index), buf_(nullptr), is_altrep_(false) {}
10097

101-
proxy(SEXP data, R_xlen_t index, r_complex* buf, bool is_altrep)
102-
: data_(data),
103-
index_(index),
104-
buf_(reinterpret_cast<Rcomplex*>(buf)),
105-
is_altrep_(is_altrep) {}
98+
proxy(SEXP data, R_xlen_t index, Rcomplex* buf, bool is_altrep)
99+
: data_(data), index_(index), buf_(buf), is_altrep_(is_altrep) {}
106100

107101
operator r_complex() const {
108102
if (is_altrep_ && buf_ != nullptr) {
@@ -219,4 +213,20 @@ inline std::complex<T>& operator+=(std::complex<T>& lhs, const cpp11::r_complex&
219213
return lhs;
220214
}
221215

216+
// Add constructor for initializer_list
217+
template <>
218+
inline r_vector<r_complex>::r_vector(std::initializer_list<r_complex> il) {
219+
R_xlen_t size = il.size();
220+
SEXP data = PROTECT(Rf_allocVector(CPLXSXP, size));
221+
auto it = il.begin();
222+
for (R_xlen_t i = 0; i < size; ++i, ++it) {
223+
Rcomplex r;
224+
r.r = it->real();
225+
r.i = it->imag();
226+
COMPLEX(data)[i] = r;
227+
}
228+
UNPROTECT(1);
229+
data_ = data;
230+
}
231+
222232
} // namespace cpp11

inst/include/cpp11/matrix.hpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
#include <iterator>
44
#include <string> // for string
55

6-
#include "cpp11/R.hpp" // for SEXP, SEXPREC, R_xlen_t, INT...
7-
#include "cpp11/r_bool.hpp" // for r_bool
8-
#include "cpp11/r_complex.hpp" // for r_complex
9-
#include "cpp11/r_string.hpp" // for r_string
10-
#include "cpp11/r_vector.hpp" // for r_vector
11-
#include "cpp11/sexp.hpp" // for sexp
6+
#include "cpp11/R.hpp" // for SEXP, SEXPREC, R_xlen_t, INT...
7+
#include "cpp11/r_bool.hpp" // for r_bool
8+
#include "cpp11/r_string.hpp" // for r_string
9+
#include "cpp11/r_vector.hpp" // for r_vector
10+
#include "cpp11/sexp.hpp" // for sexp
1211

1312
namespace cpp11 {
1413

@@ -215,8 +214,6 @@ template <typename S = by_column>
215214
using logicals_matrix = matrix<r_vector<r_bool>, r_bool, S>;
216215
template <typename S = by_column>
217216
using strings_matrix = matrix<r_vector<r_string>, r_string, S>;
218-
template <typename S = by_column>
219-
using complex_matrix = matrix<r_vector<r_complex>, r_complex, S>;
220217

221218
namespace writable {
222219
template <typename S = by_column>
@@ -227,8 +224,6 @@ template <typename S = by_column>
227224
using logicals_matrix = matrix<r_vector<r_bool>, r_vector<r_bool>::proxy, S>;
228225
template <typename S = by_column>
229226
using strings_matrix = matrix<r_vector<r_string>, r_vector<r_string>::proxy, S>;
230-
template <typename S = by_column>
231-
using complex_matrix = matrix<r_vector<r_complex>, r_vector<r_complex>::proxy, S>;
232227
} // namespace writable
233228

234229
// TODO: Add tests for Matrix class

inst/include/cpp11/r_complex.hpp

Lines changed: 103 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#pragma once
22

3-
#include <complex> // for complex
3+
#include <complex> // for complex
44
#include <ostream>
5-
#include <type_traits> // for is_convertible, enable_if
5+
#include <type_traits> // for is_convertible, enable_if
66

77
#include "R_ext/Arith.h" // for NA_REAL
88
#include "R_ext/Complex.h" // for Rcomplex
@@ -16,46 +16,120 @@ namespace cpp11 {
1616

1717
class r_complex {
1818
public:
19-
r_complex() : r_(NA_REAL), i_(NA_REAL) {}
20-
r_complex(double r, double i) : r_(r), i_(i) {}
21-
r_complex(const std::complex<double>& c) : r_(c.real()), i_(c.imag()) {}
22-
r_complex(const Rcomplex& rc) : r_(rc.r), i_(rc.i) {}
19+
r_complex() = default;
20+
r_complex(SEXP data) : data_(data) {}
21+
r_complex(double real, double imag) : data_(safe[Rf_allocVector](CPLXSXP, 1)) {
22+
COMPLEX(data_)[0].r = real;
23+
COMPLEX(data_)[0].i = imag;
24+
}
25+
r_complex(const std::complex<double>& data) : r_complex(data.real(), data.imag()) {}
26+
r_complex(const Rcomplex& data) : r_complex(data.r, data.i) {}
2327

24-
double real() const { return r_; }
25-
double imag() const { return i_; }
28+
operator SEXP() const { return data_; }
29+
operator sexp() const { return data_; }
30+
operator std::complex<double>() const {
31+
return {COMPLEX(data_)[0].r, COMPLEX(data_)[0].i};
32+
}
33+
operator Rcomplex() const {
34+
Rcomplex r;
35+
r.r = real();
36+
r.i = imag();
37+
return r;
38+
}
2639

27-
operator std::complex<double>() const { return std::complex<double>(r_, i_); }
28-
operator Rcomplex() const { return {r_, i_}; }
40+
double real() const { return COMPLEX(data_)[0].r; }
41+
double imag() const { return COMPLEX(data_)[0].i; }
2942

30-
bool operator==(const r_complex& other) const {
31-
return r_ == other.r_ && i_ == other.i_;
43+
bool operator==(const r_complex& rhs) const {
44+
return real() == rhs.real() && imag() == rhs.imag();
3245
}
3346

34-
private:
35-
double r_;
36-
double i_;
37-
};
47+
bool operator!=(const r_complex& rhs) const { return !(*this == rhs); }
3848

39-
// Specialization for r_complex
40-
template <>
41-
inline void writable::r_vector<r_complex>::push_back(r_complex value) {
42-
while (this->length_ >= this->capacity_) {
43-
this->reserve(this->capacity_ == 0 ? 1 : this->capacity_ * 2);
49+
r_complex& operator+=(const r_complex& rhs) {
50+
*this = r_complex(real() + rhs.real(), imag() + rhs.imag());
51+
return *this;
52+
}
53+
54+
r_complex& operator-=(const r_complex& rhs) {
55+
*this = r_complex(real() - rhs.real(), imag() - rhs.imag());
56+
return *this;
57+
}
58+
59+
r_complex& operator*=(const r_complex& rhs) {
60+
std::complex<double> lhs = *this;
61+
lhs *= static_cast<std::complex<double>>(rhs);
62+
*this = r_complex(lhs.real(), lhs.imag());
63+
return *this;
64+
}
65+
66+
r_complex& operator/=(const r_complex& rhs) {
67+
std::complex<double> lhs = *this;
68+
lhs /= static_cast<std::complex<double>>(rhs);
69+
*this = r_complex(lhs.real(), lhs.imag());
70+
return *this;
71+
}
72+
73+
friend r_complex operator+(r_complex lhs, const r_complex& rhs) {
74+
lhs += rhs;
75+
return lhs;
4476
}
4577

46-
if (this->data_p_ != nullptr) {
47-
this->data_p_[this->length_] = static_cast<Rcomplex>(value);
48-
} else {
49-
set_elt(this->data_, this->length_, value);
78+
friend r_complex operator-(r_complex lhs, const r_complex& rhs) {
79+
lhs -= rhs;
80+
return lhs;
5081
}
5182

52-
++this->length_;
83+
friend r_complex operator*(r_complex lhs, const r_complex& rhs) {
84+
lhs *= rhs;
85+
return lhs;
86+
}
87+
88+
friend r_complex operator/(r_complex lhs, const r_complex& rhs) {
89+
lhs /= rhs;
90+
return lhs;
91+
}
92+
93+
private:
94+
sexp data_ = R_NilValue;
95+
};
96+
97+
inline SEXP as_sexp(const r_complex& from) {
98+
sexp res;
99+
unwind_protect([&] {
100+
res = Rf_allocVector(CPLXSXP, 1);
101+
COMPLEX(res)[0].r = from.real();
102+
COMPLEX(res)[0].i = from.imag();
103+
});
104+
105+
return res;
106+
}
107+
108+
inline SEXP as_sexp(std::initializer_list<r_complex> il) {
109+
R_xlen_t size = il.size();
110+
111+
sexp data;
112+
unwind_protect([&] {
113+
data = Rf_allocVector(CPLXSXP, size);
114+
auto it = il.begin();
115+
for (R_xlen_t i = 0; i < size; ++i, ++it) {
116+
COMPLEX(data)[i].r = it->real();
117+
COMPLEX(data)[i].i = it->imag();
118+
}
119+
});
120+
return data;
53121
}
54122

55-
// Specialization for std::complex<double>
56123
template <>
57-
inline void writable::r_vector<r_complex>::push_back(const std::complex<double>& value) {
58-
this->push_back(r_complex(value.real(), value.imag()));
124+
inline r_complex na() {
125+
return r_complex(NA_REAL, NA_REAL);
59126
}
60127

128+
namespace traits {
129+
template <>
130+
struct get_underlying_type<r_complex> {
131+
using type = Rcomplex;
132+
};
133+
} // namespace traits
134+
61135
} // namespace cpp11

inst/include/cpp11/r_vector.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "cpp11/attribute_proxy.hpp" // for attribute_proxy
1919
#include "cpp11/named_arg.hpp" // for named_arg
2020
#include "cpp11/protect.hpp" // for store
21+
#include "cpp11/r_complex.hpp" // for r_complex
2122
#include "cpp11/r_string.hpp" // for r_string
2223
#include "cpp11/sexp.hpp" // for sexp
2324

@@ -30,7 +31,6 @@ template <typename T>
3031
class r_vector;
3132
} // namespace writable
3233

33-
// Declarations
3434
template <typename T>
3535
class r_vector {
3636
public:
@@ -60,6 +60,7 @@ class r_vector {
6060
r_vector(const r_vector& x);
6161
r_vector(r_vector<T>&& x);
6262
r_vector(const writable::r_vector<T>& x);
63+
r_vector(std::initializer_list<T> il);
6364
r_vector(named_arg) = delete;
6465

6566
r_vector& operator=(const r_vector& rhs);
@@ -238,7 +239,7 @@ class r_vector : public cpp11::r_vector<T> {
238239
/// Implemented in `strings.hpp`
239240
void push_back(const named_arg& value);
240241
// Implemented in `complexes.hpp`
241-
void push_back(const std::complex<double>& value);
242+
void push_back(const Rcomplex& value);
242243
void pop_back();
243244

244245
void resize(R_xlen_t count);

inst/include/cpp11/sexp.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
#include <stddef.h> // for size_t
44

5-
#include <string> // for string, basic_string
65
#include <complex> // for complex
6+
#include <string> // for string, basic_string
77

88
#include "cpp11/R.hpp" // for SEXP, SEXPREC, REAL_ELT, R_NilV...
99
#include "cpp11/attribute_proxy.hpp" // for attribute_proxy

0 commit comments

Comments
 (0)