|
4 | 4 | #include <ostream> |
5 | 5 | #include <type_traits> // for is_convertible, enable_if |
6 | 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/sexp.hpp" // for sexp |
| 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 |
13 | 14 |
|
14 | 15 | namespace cpp11 { |
15 | 16 |
|
16 | 17 | class r_complex { |
17 | 18 | public: |
18 | | - r_complex() = default; |
| 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 | 23 |
|
20 | | - r_complex(SEXP data) { |
21 | | - if (Rf_isComplex(data) && Rf_xlength(data) == 1) { |
22 | | - Rcomplex elt = COMPLEX_ELT(data, 0); |
23 | | - real_ = elt.r; |
24 | | - imag_ = elt.i; |
25 | | - } else { |
26 | | - throw std::invalid_argument("Invalid r_complex value"); |
27 | | - } |
28 | | - } |
29 | | - |
30 | | - r_complex(double real, double imag) : real_(real), imag_(imag) {} |
31 | | - |
32 | | - explicit r_complex(Rcomplex value) : real_(value.r), imag_(value.i) {} |
33 | | - explicit r_complex(std::complex<double> value) |
34 | | - : real_(value.real()), imag_(value.imag()) {} |
35 | | - |
36 | | - explicit operator Rcomplex() const { return Rcomplex{real_, imag_}; } |
37 | | - explicit operator std::complex<double>() const { |
38 | | - return std::complex<double>(real_, imag_); |
39 | | - } |
40 | | - |
41 | | - double real() const { return real_; } |
42 | | - double imag() const { return imag_; } |
43 | | - |
44 | | - r_complex& operator+=(const r_complex& other) { |
45 | | - real_ += other.real_; |
46 | | - imag_ += other.imag_; |
47 | | - return *this; |
48 | | - } |
49 | | - |
50 | | - r_complex& operator-=(const r_complex& other) { |
51 | | - real_ -= other.real_; |
52 | | - imag_ -= other.imag_; |
53 | | - return *this; |
54 | | - } |
| 24 | + double real() const { return r_; } |
| 25 | + double imag() const { return i_; } |
55 | 26 |
|
56 | | - r_complex& operator*=(const r_complex& other) { |
57 | | - double r = real_ * other.real_ - imag_ * other.imag_; |
58 | | - double i = real_ * other.imag_ + imag_ * other.real_; |
59 | | - real_ = r; |
60 | | - imag_ = i; |
61 | | - return *this; |
62 | | - } |
| 27 | + operator std::complex<double>() const { return std::complex<double>(r_, i_); } |
| 28 | + operator Rcomplex() const { return {r_, i_}; } |
63 | 29 |
|
64 | | - r_complex& operator/=(const r_complex& other) { |
65 | | - double denom = other.real_ * other.real_ + other.imag_ * other.imag_; |
66 | | - double r = (real_ * other.real_ + imag_ * other.imag_) / denom; |
67 | | - double i = (imag_ * other.real_ - real_ * other.imag_) / denom; |
68 | | - real_ = r; |
69 | | - imag_ = i; |
70 | | - return *this; |
| 30 | + bool operator==(const r_complex& other) const { |
| 31 | + return r_ == other.r_ && i_ == other.i_; |
71 | 32 | } |
72 | 33 |
|
73 | 34 | private: |
74 | | - double real_; |
75 | | - double imag_; |
| 35 | + double r_; |
| 36 | + double i_; |
76 | 37 | }; |
77 | 38 |
|
78 | | -inline r_complex operator+(r_complex lhs, const r_complex& rhs) { |
79 | | - lhs += rhs; |
80 | | - return lhs; |
81 | | -} |
82 | | - |
83 | | -inline r_complex operator-(r_complex lhs, const r_complex& rhs) { |
84 | | - lhs -= rhs; |
85 | | - return lhs; |
86 | | -} |
87 | | - |
88 | | -inline r_complex operator*(r_complex lhs, const r_complex& rhs) { |
89 | | - lhs *= rhs; |
90 | | - return lhs; |
91 | | -} |
92 | | - |
93 | | -inline r_complex operator/(r_complex lhs, const r_complex& rhs) { |
94 | | - lhs /= rhs; |
95 | | - return lhs; |
96 | | -} |
97 | | - |
98 | | -inline bool operator==(const r_complex& x, const r_complex& y) { |
99 | | - return (x.real() == y.real()) && (x.imag() == y.imag()); |
100 | | -} |
101 | | - |
102 | | -inline std::ostream& operator<<(std::ostream& os, const r_complex& value) { |
103 | | - os << value.real() << "+" << value.imag() << "i"; |
104 | | - return os; |
105 | | -} |
106 | | - |
| 39 | +// Specialization for r_complex |
107 | 40 | template <> |
108 | | -inline r_complex na() { |
109 | | - return r_complex(NA_REAL, NA_REAL); |
110 | | -} |
111 | | - |
112 | | -template <> |
113 | | -inline bool is_na(const r_complex& x) { |
114 | | - return ISNA(x.real()) || ISNA(x.imag()); |
115 | | -} |
116 | | - |
117 | | -template <typename T> |
118 | | -struct is_r_complex : std::false_type {}; |
| 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); |
| 44 | + } |
119 | 45 |
|
120 | | -template <> |
121 | | -struct is_r_complex<r_complex> : std::true_type {}; |
| 46 | + Rcomplex r_value = static_cast<Rcomplex>(value); |
122 | 47 |
|
123 | | -template <typename T, typename R = void> |
124 | | -using enable_if_r_complex = std::enable_if_t<is_r_complex<T>::value, R>; |
| 48 | + if (this->data_p_ != nullptr) { |
| 49 | + this->data_p_[this->length_] = r_value; |
| 50 | + } else { |
| 51 | + this->set_elt(this->data_, this->length_, r_value); |
| 52 | + } |
125 | 53 |
|
126 | | -template <typename T> |
127 | | -enable_if_r_complex<T, SEXP> as_sexp(T from) { |
128 | | - SEXP res = PROTECT(Rf_allocVector(CPLXSXP, 1)); |
129 | | - Rcomplex* r = COMPLEX(res); |
130 | | - r[0].r = from.real(); |
131 | | - r[0].i = from.imag(); |
132 | | - UNPROTECT(1); |
133 | | - return res; |
| 54 | + ++this->length_; |
134 | 55 | } |
135 | 56 |
|
136 | | -namespace traits { |
| 57 | +// Specialization for std::complex<double> |
137 | 58 | template <> |
138 | | -struct get_underlying_type<r_complex> { |
139 | | - using type = Rcomplex; |
140 | | -}; |
141 | | -} // namespace traits |
142 | | - |
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()); |
| 59 | +inline void writable::r_vector<r_complex>::push_back(const std::complex<double>& value) { |
| 60 | + this->push_back(r_complex(value.real(), value.imag())); |
152 | 61 | } |
153 | 62 |
|
154 | 63 | } // namespace cpp11 |
0 commit comments