@@ -85,7 +85,7 @@ struct is_std_complex<std::complex<T>> : std::true_type {};
8585
8686// https://stackoverflow.com/a/1521682/2055486
8787//
88- inline bool is_convertible_without_loss_to_integer (double value) {
88+ inline bool is_convertible_without_loss_to_integer (double value) noexcept {
8989 double int_part;
9090 return std::modf (value, &int_part) == 0.0 ;
9191}
@@ -102,25 +102,23 @@ enable_if_is_sexp<T, T> as_cpp(SEXP from) {
102102
103103template <typename T>
104104enable_if_integral<T, T> as_cpp (SEXP from) {
105- if (Rf_isInteger (from)) {
106- if (Rf_xlength (from) == 1 ) {
107- return INTEGER_ELT (from, 0 );
105+ if (__builtin_expect (Rf_xlength (from) != 1 , 0 )) {
106+ throw std::length_error (" Expected single integer value" );
107+ }
108+
109+ if (__builtin_expect (Rf_isInteger (from), 1 )) {
110+ return INTEGER_ELT (from, 0 );
111+ } else if (__builtin_expect (Rf_isReal (from), 0 )) {
112+ if (__builtin_expect (ISNA (REAL_ELT (from, 0 )), 0 )) {
113+ return NA_INTEGER;
108114 }
109- } else if (Rf_isReal (from)) {
110- if (Rf_xlength (from) == 1 ) {
111- if (ISNA (REAL_ELT (from, 0 ))) {
112- return NA_INTEGER;
113- }
114- double value = REAL_ELT (from, 0 );
115- if (is_convertible_without_loss_to_integer (value)) {
116- return value;
117- }
115+ double value = REAL_ELT (from, 0 );
116+ if (__builtin_expect (is_convertible_without_loss_to_integer (value), 1 )) {
117+ return value;
118118 }
119- } else if (Rf_isLogical (from)) {
120- if (Rf_xlength (from) == 1 ) {
121- if (LOGICAL_ELT (from, 0 ) == NA_LOGICAL) {
122- return NA_INTEGER;
123- }
119+ } else if (__builtin_expect (Rf_isLogical (from), 0 )) {
120+ if (__builtin_expect (LOGICAL_ELT (from, 0 ) == NA_LOGICAL, 0 )) {
121+ return NA_INTEGER;
124122 }
125123 }
126124
@@ -143,77 +141,63 @@ enable_if_enum<E, E> as_cpp(SEXP from) {
143141
144142template <typename T>
145143enable_if_bool<T, T> as_cpp (SEXP from) {
146- if (Rf_isLogical (from)) {
147- if (Rf_xlength (from) == 1 ) {
148- return LOGICAL_ELT (from, 0 ) == 1 ;
149- }
144+ if (__builtin_expect (Rf_isLogical (from) && Rf_xlength (from) == 1 , 1 )) {
145+ return LOGICAL_ELT (from, 0 ) == 1 ;
150146 }
151147
152148 throw std::length_error (" Expected single logical value" );
153149}
154150
155151template <typename T>
156152enable_if_floating_point<T, T> as_cpp (SEXP from) {
157- if (Rf_isReal (from)) {
158- if (Rf_xlength (from) == 1 ) {
159- return REAL_ELT (from, 0 );
160- }
153+ if (__builtin_expect (Rf_xlength (from) != 1 , 0 )) {
154+ throw std::length_error (" Expected single double value" );
155+ }
156+
157+ if (__builtin_expect (Rf_isReal (from), 1 )) {
158+ return REAL_ELT (from, 0 );
161159 }
162160 // All 32 bit integers can be coerced to doubles, so we just convert them.
163- if (Rf_isInteger (from)) {
164- if (Rf_xlength (from) == 1 ) {
165- if (INTEGER_ELT (from, 0 ) == NA_INTEGER) {
166- return NA_REAL;
167- }
168- return INTEGER_ELT (from, 0 );
161+ if (__builtin_expect (Rf_isInteger (from), 0 )) {
162+ if (__builtin_expect (INTEGER_ELT (from, 0 ) == NA_INTEGER, 0 )) {
163+ return NA_REAL;
169164 }
165+ return INTEGER_ELT (from, 0 );
170166 }
171167
172168 // Also allow NA values
173- if (Rf_isLogical (from)) {
174- if (Rf_xlength (from) == 1 ) {
175- if (LOGICAL_ELT (from, 0 ) == NA_LOGICAL) {
176- return NA_REAL;
177- }
169+ if (__builtin_expect (Rf_isLogical (from), 0 )) {
170+ if (__builtin_expect (LOGICAL_ELT (from, 0 ) == NA_LOGICAL, 0 )) {
171+ return NA_REAL;
178172 }
179173 }
180174
181175 throw std::length_error (" Expected single double value" );
182176}
183177
184- // Definition for converting SEXP to std::complex<double>
185- inline std::complex <double > as_cpp (SEXP x) {
186- if (TYPEOF (x) != CPLXSXP || Rf_length (x) != 1 ) {
187- throw std::invalid_argument (" Expected a single complex number." );
188- }
189- Rcomplex c = COMPLEX (x)[0 ];
190- return {c.r , c.i };
191- }
178+ // Removed generic complex template to avoid ambiguity - use specific specializations
179+ // instead
192180
193181template <typename T>
194182enable_if_char<T, T> as_cpp (SEXP from) {
195- if (Rf_isString (from)) {
196- if (Rf_xlength (from) == 1 ) {
197- return unwind_protect ([&] { return Rf_translateCharUTF8 (STRING_ELT (from, 0 ))[0 ]; });
198- }
183+ if (__builtin_expect (Rf_isString (from) && Rf_xlength (from) == 1 , 1 )) {
184+ return unwind_protect ([&] { return Rf_translateCharUTF8 (STRING_ELT (from, 0 ))[0 ]; });
199185 }
200186
201187 throw std::length_error (" Expected string vector of length 1" );
202188}
203189
204190template <typename T>
205191enable_if_c_string<T, T> as_cpp (SEXP from) {
206- if (Rf_isString (from)) {
207- if (Rf_xlength (from) == 1 ) {
208- void * vmax = vmaxget ();
192+ if (__builtin_expect (Rf_isString (from) && Rf_xlength (from) == 1 , 1 )) {
193+ void * vmax = vmaxget ();
209194
210- const char * result =
211- unwind_protect ([&] { return Rf_translateCharUTF8 (STRING_ELT (from, 0 )); });
195+ const char * result =
196+ unwind_protect ([&] { return Rf_translateCharUTF8 (STRING_ELT (from, 0 )); });
212197
213- vmaxset (vmax);
198+ vmaxset (vmax);
214199
215- return {result};
216- }
200+ return {result};
217201 }
218202
219203 throw std::length_error (" Expected string vector of length 1" );
@@ -224,33 +208,28 @@ enable_if_std_string<T, T> as_cpp(SEXP from) {
224208 return {as_cpp<const char *>(from)};
225209}
226210
227- // / Temporary workaround for compatibility with cpp4r 0.1.0
211+ // Specialization for converting std::complex<T> to SEXP
228212template <typename T>
229- enable_if_t <!std::is_same<decay_t <T>, T>::value, decay_t <T>> as_cpp (SEXP from) {
230- return as_cpp<decay_t <T>>(from);
231- }
232-
233- // Specialization for converting std::complex<double> to SEXP
234- inline SEXP as_sexp (const std::complex <double >& x) {
213+ inline SEXP as_sexp (const std::complex <T>& x) {
235214 SEXP result = PROTECT (Rf_allocVector (CPLXSXP, 1 ));
236- COMPLEX (result)[0 ].r = x.real ();
237- COMPLEX (result)[0 ].i = x.imag ();
215+ COMPLEX (result)[0 ].r = static_cast < double >( x.real () );
216+ COMPLEX (result)[0 ].i = static_cast < double >( x.imag () );
238217 UNPROTECT (1 );
239218 return result;
240219}
241220
242221template <typename T>
243- enable_if_integral<T, SEXP> as_sexp (T from) {
222+ enable_if_integral<T, SEXP> as_sexp (T from) noexcept {
244223 return safe[Rf_ScalarInteger](from);
245224}
246225
247226template <typename T>
248- enable_if_floating_point<T, SEXP> as_sexp (T from) {
227+ enable_if_floating_point<T, SEXP> as_sexp (T from) noexcept {
249228 return safe[Rf_ScalarReal](from);
250229}
251230
252231template <typename T>
253- enable_if_bool<T, SEXP> as_sexp (T from) {
232+ enable_if_bool<T, SEXP> as_sexp (T from) noexcept {
254233 return safe[Rf_ScalarLogical](from);
255234}
256235
@@ -272,7 +251,7 @@ enable_if_integral<T, SEXP> as_sexp(const Container& from) {
272251
273252 auto it = from.begin ();
274253 int * data_p = INTEGER (data);
275- for (R_xlen_t i = 0 ; i < size; ++i, ++it) {
254+ for (R_xlen_t i = 0 ; __builtin_expect ( i < size, 1 ) ; ++i, ++it) {
276255 data_p[i] = *it;
277256 }
278257 return data;
@@ -291,7 +270,7 @@ enable_if_floating_point<T, SEXP> as_sexp(const Container& from) {
291270
292271 auto it = from.begin ();
293272 double * data_p = REAL (data);
294- for (R_xlen_t i = 0 ; i < size; ++i, ++it) {
273+ for (R_xlen_t i = 0 ; __builtin_expect ( i < size, 1 ) ; ++i, ++it) {
295274 data_p[i] = *it;
296275 }
297276 return data;
@@ -310,7 +289,7 @@ enable_if_bool<T, SEXP> as_sexp(const Container& from) {
310289
311290 auto it = from.begin ();
312291 int * data_p = LOGICAL (data);
313- for (R_xlen_t i = 0 ; i < size; ++i, ++it) {
292+ for (R_xlen_t i = 0 ; __builtin_expect ( i < size, 1 ) ; ++i, ++it) {
314293 data_p[i] = *it;
315294 }
316295 return data;
0 commit comments