Skip to content

Commit e642aa6

Browse files
committed
passed all test for cplx :D
1 parent b003c28 commit e642aa6

File tree

3 files changed

+79
-27
lines changed

3 files changed

+79
-27
lines changed

cpp11test/src/test-complex.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -357,17 +357,29 @@ context("complexes-C++") {
357357
}
358358

359359
test_that("comparison operator works") {
360-
cpp11::r_complex one{1, 1};
361-
cpp11::r_complex two{2, 2};
362-
cpp11::r_complex three{3, 3};
363-
364360
using namespace cpp11;
365-
cpp11::complexes base({one, two});
366-
cpp11::complexes same_values({one, two});
367-
cpp11::complexes diff_length({one});
368-
cpp11::complexes diff_values({one, three});
369361

370-
expect_true(base == base);
362+
// SEXP base = PROTECT(Rf_allocVector(CPLXSXP, 2));
363+
// SEXP same_values = PROTECT(Rf_allocVector(CPLXSXP, 2));
364+
// SEXP diff_length = PROTECT(Rf_allocVector(CPLXSXP, 1));
365+
// SEXP diff_values = PROTECT(Rf_allocVector(CPLXSXP, 2));
366+
367+
cpp11::complexes base(Rf_allocVector(CPLXSXP, 2));
368+
cpp11::complexes same_values(Rf_allocVector(CPLXSXP, 2));
369+
cpp11::complexes diff_length(Rf_allocVector(CPLXSXP, 1));
370+
cpp11::complexes diff_values(Rf_allocVector(CPLXSXP, 2));
371+
372+
COMPLEX(base)[0] = Rcomplex{1, 1};
373+
COMPLEX(base)[1] = Rcomplex{2, 2};
374+
375+
COMPLEX(same_values)[0] = Rcomplex{1, 1};
376+
COMPLEX(same_values)[1] = Rcomplex{2, 2};
377+
378+
COMPLEX(diff_length)[0] = Rcomplex{1, 1};
379+
380+
COMPLEX(diff_values)[0] = Rcomplex{1, 1};
381+
COMPLEX(diff_values)[1] = Rcomplex{3, 3};
382+
371383
expect_true(base == base);
372384
expect_true(base == same_values);
373385
expect_true(!(base == diff_length));
@@ -377,6 +389,8 @@ context("complexes-C++") {
377389
expect_true(!(base != same_values));
378390
expect_true(base != diff_length);
379391
expect_true(base != diff_values);
392+
393+
UNPROTECT(4);
380394
}
381395

382396
test_that("proxy comparison works symmetrically") {

inst/include/cpp11/complexes.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,4 +229,19 @@ inline r_vector<r_complex>::r_vector(std::initializer_list<r_complex> il) {
229229
data_ = data;
230230
}
231231

232+
// Comparison operators for r_vector<r_complex>
233+
template <>
234+
inline bool operator==(const r_vector<r_complex>& lhs, const r_vector<r_complex>& rhs) {
235+
if (lhs.size() != rhs.size()) return false;
236+
for (R_xlen_t i = 0; i < lhs.size(); ++i) {
237+
if (!(lhs[i] == rhs[i])) return false;
238+
}
239+
return true;
240+
}
241+
242+
template <>
243+
inline bool operator!=(const r_vector<r_complex>& lhs, const r_vector<r_complex>& rhs) {
244+
return !(lhs == rhs);
245+
}
246+
232247
} // namespace cpp11

inst/include/cpp11/r_complex.hpp

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

3-
#include <complex> // for complex
4-
#include <ostream>
5-
#include <type_traits> // for is_convertible, enable_if
6-
7-
#include "R_ext/Arith.h" // for NA_REAL
8-
#include "R_ext/Complex.h" // for Rcomplex
9-
#include "cpp11/R.hpp" // for SEXP, SEXPREC, ...
10-
#include "cpp11/as.hpp" // for as_sexp
11-
#include "cpp11/protect.hpp" // for unwind_protect, preserved
12-
#include "cpp11/r_vector.hpp" // for r_vector
13-
#include "cpp11/sexp.hpp" // for sexp
3+
#include <complex> // for std::complex
4+
5+
#include "cpp11/R.hpp" // for SEXP, SEXPREC, Rf_mkCharCE, Rf_translateCharUTF8
6+
#include "cpp11/as.hpp" // for as_sexp
7+
#include "cpp11/protect.hpp" // for unwind_protect, protect, protect::function
8+
#include "cpp11/sexp.hpp" // for sexp
149

1510
namespace cpp11 {
1611

1712
class r_complex {
1813
public:
19-
r_complex() = default;
20-
r_complex(SEXP data) : data_(data) {}
14+
r_complex() : data_(safe[Rf_allocVector](CPLXSXP, 1)) {
15+
COMPLEX(data_)[0].r = 0;
16+
COMPLEX(data_)[0].i = 0;
17+
}
18+
r_complex(SEXP data) : data_(data) {
19+
if (data_ == R_NilValue) {
20+
data_ = PROTECT(Rf_allocVector(CPLXSXP, 0));
21+
UNPROTECT(1);
22+
}
23+
}
2124
r_complex(double real, double imag) : data_(safe[Rf_allocVector](CPLXSXP, 1)) {
2225
COMPLEX(data_)[0].r = real;
2326
COMPLEX(data_)[0].i = imag;
@@ -28,20 +31,38 @@ class r_complex {
2831
operator SEXP() const { return data_; }
2932
operator sexp() const { return data_; }
3033
operator std::complex<double>() const {
34+
if (data_ == R_NilValue || Rf_length(data_) == 0) {
35+
return {NA_REAL, NA_REAL};
36+
}
3137
return {COMPLEX(data_)[0].r, COMPLEX(data_)[0].i};
3238
}
3339
operator Rcomplex() const {
3440
Rcomplex r;
35-
r.r = real();
36-
r.i = imag();
41+
if (data_ == R_NilValue || Rf_length(data_) == 0) {
42+
r.r = NA_REAL;
43+
r.i = NA_REAL;
44+
} else {
45+
r.r = real();
46+
r.i = imag();
47+
}
3748
return r;
3849
}
3950

40-
double real() const { return COMPLEX(data_)[0].r; }
41-
double imag() const { return COMPLEX(data_)[0].i; }
51+
double real() const {
52+
if (data_ == R_NilValue || Rf_length(data_) == 0) {
53+
return NA_REAL;
54+
}
55+
return COMPLEX(data_)[0].r;
56+
}
57+
double imag() const {
58+
if (data_ == R_NilValue || Rf_length(data_) == 0) {
59+
return NA_REAL;
60+
}
61+
return COMPLEX(data_)[0].i;
62+
}
4263

4364
bool operator==(const r_complex& rhs) const {
44-
return real() == rhs.real() && imag() == rhs.imag();
65+
return (is_na() && rhs.is_na()) || (real() == rhs.real() && imag() == rhs.imag());
4566
}
4667

4768
bool operator!=(const r_complex& rhs) const { return !(*this == rhs); }
@@ -90,6 +111,8 @@ class r_complex {
90111
return lhs;
91112
}
92113

114+
bool is_na() const { return R_IsNA(real()) || R_IsNA(imag()); }
115+
93116
private:
94117
sexp data_ = R_NilValue;
95118
};

0 commit comments

Comments
 (0)