Rcpp Version 1.1.2
Loading...
Searching...
No Matches
algorithm.h
Go to the documentation of this file.
1// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2//
3// algorithm.h: Rcpp R/C++ interface class library -- data frames
4//
5// Copyright (C) 2016 - 2024 Daniel C. Dillon
6// Copyright (C) 2025 Daniel C. Dillon and IƱaki Ucar
7//
8// This file is part of Rcpp.
9//
10// Rcpp is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 2 of the License, or
13// (at your option) any later version.
14//
15// Rcpp is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
22
23#ifndef Rcpp__Algorithm_h
24#define Rcpp__Algorithm_h
25
26namespace Rcpp {
27namespace algorithm {
28
29namespace helpers {
30 typedef struct {char a[1];} CTYPE_CHAR;
31 typedef struct {char a[2];} CTYPE_SHORT;
32 typedef struct {char a[3];} CTYPE_INT;
33 typedef struct {char a[4];} CTYPE_LONG;
34 typedef struct {char a[5];} CTYPE_LONG_LONG;
35 typedef struct {char a[6];} CTYPE_FLOAT;
36 typedef struct {char a[7];} CTYPE_DOUBLE;
37 typedef struct {char a[8];} CTYPE_LONG_DOUBLE;
38 typedef struct {char a[9];} CTYPE_STRING;
39 typedef struct {char a[10];} CTYPE_UNSIGNED_CHAR;
40 typedef struct {char a[11];} CTYPE_UNSIGNED_SHORT;
41 typedef struct {char a[12];} CTYPE_UNSIGNED_INT;
42 typedef struct {char a[13];} CTYPE_UNSIGNED_LONG;
43 typedef struct {char a[14];} CTYPE_UNSIGNED_LONG_LONG;
44 typedef struct {char a[128];} CTYPE_UNKNOWN;
45
46 template< std::size_t I >
47 struct ctype_helper { static const bool value = false; };
48
49 template<>
50 struct ctype_helper< sizeof(CTYPE_CHAR) > { typedef char type; static const bool value = true; };
51
52 template<>
53 struct ctype_helper< sizeof(CTYPE_SHORT) > { typedef short type; static const bool value = true; };
54
55 template<>
56 struct ctype_helper< sizeof(CTYPE_INT) > { typedef int type; static const bool value = true; };
57
58 template<>
59 struct ctype_helper< sizeof(CTYPE_LONG) > { typedef long type; static const bool value = true; };
60
61 template<>
62 struct ctype_helper< sizeof(CTYPE_LONG_LONG) > { typedef rcpp_long_long_type type; static const bool value = true; };
63
64 template<>
65 struct ctype_helper< sizeof(CTYPE_FLOAT) > { typedef float type; static const bool value = true; };
66
67 template<>
68 struct ctype_helper< sizeof(CTYPE_DOUBLE) > { typedef double type; static const bool value = true; };
69
70 template<>
71 struct ctype_helper< sizeof(CTYPE_LONG_DOUBLE) > { typedef long double type; static const bool value = true; };
72
73 template<>
74 struct ctype_helper< sizeof(CTYPE_STRING) > { typedef std::string type; static const bool value = true; };
75
76 template<>
77 struct ctype_helper< sizeof(CTYPE_UNSIGNED_CHAR) > { typedef unsigned char type; static const bool value = true; };
78
79 template<>
80 struct ctype_helper< sizeof(CTYPE_UNSIGNED_SHORT) > { typedef unsigned short type; static const bool value = true; };
81
82 template<>
83 struct ctype_helper< sizeof(CTYPE_UNSIGNED_INT) > { typedef unsigned int type; static const bool value = true; };
84
85 template<>
86 struct ctype_helper< sizeof(CTYPE_UNSIGNED_LONG) > { typedef unsigned long type; static const bool value = true; };
87
88 template<>
89 struct ctype_helper< sizeof(CTYPE_UNSIGNED_LONG_LONG) > { typedef rcpp_ulong_long_type type; static const bool value = true; };
90
91 template< typename T >
92 struct ctype
93 {
94 static CTYPE_CHAR test(const char &);
95 static CTYPE_SHORT test(const short &);
96 static CTYPE_INT test(const int &);
97 static CTYPE_LONG test(const long &);
99 static CTYPE_FLOAT test(const float &);
100 static CTYPE_DOUBLE test(const double &);
101 static CTYPE_LONG_DOUBLE test(const long double &);
102 static CTYPE_STRING test(const std::string &);
103 static CTYPE_UNSIGNED_CHAR test(const unsigned char &);
104 static CTYPE_UNSIGNED_SHORT test(const unsigned short &);
105 static CTYPE_UNSIGNED_INT test(const unsigned int &);
106 static CTYPE_UNSIGNED_LONG test(const unsigned long &);
108 static CTYPE_UNKNOWN test(...);
109
110 static T make();
111
112 typedef typename ctype_helper< sizeof(test(make())) >::type type;
113 };
114
115 template< typename T >
117 {
118 static CTYPE_CHAR test(const char &);
119 static CTYPE_SHORT test(const short &);
120 static CTYPE_INT test(const int &);
121 static CTYPE_LONG test(const long &);
123 static CTYPE_FLOAT test(const float &);
124 static CTYPE_DOUBLE test(const double &);
125 static CTYPE_LONG_DOUBLE test(const long double &);
126 static CTYPE_STRING test(const std::string &);
127 static CTYPE_UNSIGNED_CHAR test(const unsigned char &);
128 static CTYPE_UNSIGNED_SHORT test(const unsigned short &);
129 static CTYPE_UNSIGNED_INT test(const unsigned int &);
130 static CTYPE_UNSIGNED_LONG test(const unsigned long &);
132 static CTYPE_UNKNOWN test(...);
133
134 static T make();
135
136 static const bool value = ctype_helper< sizeof(test(make())) >::value;
137 };
138
139 template< typename T >
141 };
142
143 template<>
144 struct rtype_helper< double > {
145 typedef double type;
146 static constexpr int RTYPE = REALSXP;
147 static inline double NA() { return NA_REAL; }
148 static inline constexpr double ZERO() { return 0.0; }
149 static inline constexpr double ONE() { return 1.0; }
150 };
151
152 template<>
153 struct rtype_helper< int > {
154 typedef int type;
155 static constexpr int RTYPE = INTSXP;
156 static inline int NA() { return NA_INTEGER; }
157 static inline constexpr int ZERO() { return 0; }
158 static inline constexpr int ONE() { return 1; }
159 };
160
161 template< typename T >
162 struct rtype {
165 static constexpr int RTYPE = helper_type::RTYPE;
166 static inline T NA() { return helper_type::NA(); }
167 static inline constexpr T ZERO() { return helper_type::ZERO(); }
168 static inline constexpr T ONE() { return helper_type::ONE(); }
169 };
170
171 struct log {
172 template< typename T >
173 inline double operator()(T val) {
174 if (!Vector< rtype< T >::RTYPE >::is_na(val)) {
175 return std::log(val);
176 }
177
178 return rtype< double >::NA();
179 }
180 };
181
182 struct exp {
183 template< typename T >
184 inline double operator()(T val) {
185 if (!Vector< rtype< T >::RTYPE >::is_na(val)) {
186 return std::exp(val);
187 }
188
189 return rtype< double >::NA();
190 }
191 };
192
193 struct sqrt {
194 template< typename T >
195 inline double operator()(T val) {
196 if (!Vector< rtype< T >::RTYPE >::is_na(val)) {
197 return std::sqrt(val);
198 }
199
200 return rtype< double >::NA();
201 }
202 };
203} // namespace helpers
204
205template< typename InputIterator >
207 typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
208 sum(InputIterator begin, InputIterator end) {
209
211 typedef typename helpers::rtype< value_type > rtype;
212
213 if (begin != end) {
214 value_type start = rtype::ZERO();
215
216 while (begin != end) {
217 if (!Vector< rtype::RTYPE >::is_na(*begin)) {
218 start += *begin++;
219 } else {
220 return rtype::NA();
221 }
222 }
223
224 return start;
225 }
226
227 return rtype::ZERO();
228}
229
230template< typename InputIterator >
232 typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
233 sum_nona(InputIterator begin, InputIterator end) {
234
236 typedef typename helpers::rtype< value_type > rtype;
237
238 if (begin != end) {
239 value_type start = rtype::ZERO();
240
241 while (begin != end) {
242 start += *begin++;
243 }
244
245 return start;
246 }
247
248 return rtype::ZERO();
249}
250
251template< typename InputIterator >
253 typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
254 prod(InputIterator begin, InputIterator end) {
255
257 typedef typename helpers::rtype< value_type > rtype;
258
259 if (begin != end) {
260 value_type start = rtype::ONE();
261
262 while (begin != end) {
263 if (!Vector< rtype::RTYPE >::is_na(*begin)) {
264 start *= *begin++;
265 } else {
266 return rtype::NA();
267 }
268 }
269
270 return start;
271 }
272
273 return rtype::ONE();
274}
275
276template< typename InputIterator >
278 typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
279 prod_nona(InputIterator begin, InputIterator end) {
280
282 typedef typename helpers::rtype< value_type > rtype;
283
284 if (begin != end) {
285 value_type start = rtype::ONE();
286
287 while (begin != end) {
288 start *= *begin++;
289 }
290
291 return start;
292 }
293
294 return rtype::ONE();
295}
296
297template< typename InputIterator >
299 typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
300 max(InputIterator begin, InputIterator end) {
301
303 typedef typename helpers::rtype< value_type > rtype;
304
305 if (begin != end) {
306 value_type max = *begin;
307
308 while (begin != end) {
309 if (!Vector< rtype::RTYPE >::is_na(*begin)) {
310 max = std::max(max, *begin++);
311 } else {
312 return rtype::NA();
313 }
314 }
315
316 return max;
317 }
318
319 return std::numeric_limits< typename rtype::type >::infinity() * -rtype::ONE();
320}
321
322template< typename InputIterator >
324 typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
325 max_nona(InputIterator begin, InputIterator end) {
326
328 typedef typename helpers::rtype< value_type > rtype;
329
330 if (begin != end) {
331 value_type max = *begin;
332
333 while (begin != end) {
334 max = std::max(max, *begin++);
335 }
336
337 return max;
338 }
339
340 return std::numeric_limits< typename rtype::type >::infinity() * -rtype::ONE();
341}
342
343template< typename InputIterator >
345 typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
346 min(InputIterator begin, InputIterator end) {
347
349 typedef typename helpers::rtype< value_type > rtype;
350
351 if (begin != end) {
352 value_type min = *begin;
353
354 while (begin != end) {
355 if (!Vector< rtype::RTYPE >::is_na(*begin)) {
356 min = std::min(min, *begin++);
357 } else {
358 return rtype::NA();
359 }
360 }
361
362 return min;
363 }
364
365 return std::numeric_limits< typename rtype::type >::infinity();
366}
367
368template< typename InputIterator >
370 typename helpers::ctype< typename std::iterator_traits< InputIterator >::value_type >::type >::type
371 min_nona(InputIterator begin, InputIterator end) {
372
374 typedef typename helpers::rtype< value_type > rtype;
375
376 if (begin != end) {
377 value_type min = *begin;
378
379 while (begin != end) {
380 min = std::min(min, *begin++);
381 }
382
383 return min;
384 }
385
386 return std::numeric_limits< typename rtype::type >::infinity();
387}
388
389// for REALSXP
390template< typename InputIterator >
393 mean(InputIterator begin, InputIterator end)
394{
395 if (begin != end)
396 {
397 std::size_t n = end - begin;
398 long double s = std::accumulate(begin, end, 0.0L);
399 s /= n;
400
401 if (R_FINITE((double) s)) {
402 long double t = 0.0L;
403 while (begin != end) {
404 t += *begin++ - s;
405 }
406
407 s += t / n;
408 }
409
410 return (double) s;
411 }
412
414}
415
416// for LGLSXP and INTSXP
417template< typename InputIterator >
420 mean(InputIterator begin, InputIterator end)
421{
422 if (begin != end)
423 {
424 std::size_t n = end - begin;
425 long double s = std::accumulate(begin, end, 0.0L);
426 s /= n;
427
428 if (R_FINITE((double) s)) {
429 long double t = 0.0L;
430 while (begin != end) {
432 t += *begin++ - s;
433 }
434
435 s += t / n;
436 }
437
438 return (double) s;
439 }
440
442}
443
444template< typename InputIterator, typename OutputIterator >
445void log(InputIterator begin, InputIterator end, OutputIterator out) {
446 std::transform(begin, end, out, helpers::log());
447}
448
449template< typename InputIterator, typename OutputIterator >
450void exp(InputIterator begin, InputIterator end, OutputIterator out) {
451 std::transform(begin, end, out, helpers::exp());
452}
453
454template< typename InputIterator, typename OutputIterator >
455void sqrt(InputIterator begin, InputIterator end, OutputIterator out) {
456 std::transform(begin, end, out, helpers::sqrt());
457}
458
459} // namespace algorithm
460} // namespace Rcpp
461
462#endif
static bool is_na(stored_type x)
Definition Vector.h:253
long long int rcpp_long_long_type
Definition longlong.h:26
unsigned long long int rcpp_ulong_long_type
Definition longlong.h:27
void exp(InputIterator begin, InputIterator end, OutputIterator out)
Definition algorithm.h:450
traits::enable_if< helpers::decays_to_ctype< typenamestd::iterator_traits< InputIterator >::value_type >::value, typenamehelpers::ctype< typenamestd::iterator_traits< InputIterator >::value_type >::type >::type max_nona(InputIterator begin, InputIterator end)
Definition algorithm.h:325
traits::enable_if< helpers::decays_to_ctype< typenamestd::iterator_traits< InputIterator >::value_type >::value &&traits::same_type< typenamehelpers::ctype< typenamestd::iterator_traits< InputIterator >::value_type >::type, double >::value, double >::type mean(InputIterator begin, InputIterator end)
Definition algorithm.h:393
traits::enable_if< helpers::decays_to_ctype< typenamestd::iterator_traits< InputIterator >::value_type >::value, typenamehelpers::ctype< typenamestd::iterator_traits< InputIterator >::value_type >::type >::type sum(InputIterator begin, InputIterator end)
Definition algorithm.h:208
traits::enable_if< helpers::decays_to_ctype< typenamestd::iterator_traits< InputIterator >::value_type >::value, typenamehelpers::ctype< typenamestd::iterator_traits< InputIterator >::value_type >::type >::type prod(InputIterator begin, InputIterator end)
Definition algorithm.h:254
void log(InputIterator begin, InputIterator end, OutputIterator out)
Definition algorithm.h:445
void sqrt(InputIterator begin, InputIterator end, OutputIterator out)
Definition algorithm.h:455
traits::enable_if< helpers::decays_to_ctype< typenamestd::iterator_traits< InputIterator >::value_type >::value, typenamehelpers::ctype< typenamestd::iterator_traits< InputIterator >::value_type >::type >::type max(InputIterator begin, InputIterator end)
Definition algorithm.h:300
traits::enable_if< helpers::decays_to_ctype< typenamestd::iterator_traits< InputIterator >::value_type >::value, typenamehelpers::ctype< typenamestd::iterator_traits< InputIterator >::value_type >::type >::type min(InputIterator begin, InputIterator end)
Definition algorithm.h:346
traits::enable_if< helpers::decays_to_ctype< typenamestd::iterator_traits< InputIterator >::value_type >::value, typenamehelpers::ctype< typenamestd::iterator_traits< InputIterator >::value_type >::type >::type sum_nona(InputIterator begin, InputIterator end)
Definition algorithm.h:233
traits::enable_if< helpers::decays_to_ctype< typenamestd::iterator_traits< InputIterator >::value_type >::value, typenamehelpers::ctype< typenamestd::iterator_traits< InputIterator >::value_type >::type >::type prod_nona(InputIterator begin, InputIterator end)
Definition algorithm.h:279
traits::enable_if< helpers::decays_to_ctype< typenamestd::iterator_traits< InputIterator >::value_type >::value, typenamehelpers::ctype< typenamestd::iterator_traits< InputIterator >::value_type >::type >::type min_nona(InputIterator begin, InputIterator end)
Definition algorithm.h:371
Rcpp API.
Definition algo.h:28
sugar::IsNa< RTYPE, NA, T > is_na(const Rcpp::VectorBase< RTYPE, NA, T > &t)
Definition is_na.h:91
static CTYPE_STRING test(const std::string &)
static CTYPE_LONG_LONG test(const rcpp_long_long_type &)
static CTYPE_LONG test(const long &)
static CTYPE_CHAR test(const char &)
static CTYPE_UNSIGNED_INT test(const unsigned int &)
static CTYPE_INT test(const int &)
static CTYPE_UNSIGNED_LONG_LONG test(const rcpp_ulong_long_type &)
static CTYPE_UNSIGNED_SHORT test(const unsigned short &)
static CTYPE_UNSIGNED_CHAR test(const unsigned char &)
static CTYPE_SHORT test(const short &)
static CTYPE_UNKNOWN test(...)
ctype_helper< sizeof(test(make()))>::type type
Definition algorithm.h:112
static CTYPE_DOUBLE test(const double &)
static CTYPE_FLOAT test(const float &)
static CTYPE_UNSIGNED_LONG test(const unsigned long &)
static CTYPE_LONG_DOUBLE test(const long double &)
static CTYPE_CHAR test(const char &)
static CTYPE_FLOAT test(const float &)
static CTYPE_UNSIGNED_LONG test(const unsigned long &)
static CTYPE_LONG_LONG test(const rcpp_long_long_type &)
static CTYPE_SHORT test(const short &)
static CTYPE_UNSIGNED_INT test(const unsigned int &)
static CTYPE_UNSIGNED_CHAR test(const unsigned char &)
static CTYPE_DOUBLE test(const double &)
static CTYPE_LONG_DOUBLE test(const long double &)
static CTYPE_UNSIGNED_LONG_LONG test(const rcpp_ulong_long_type &)
static CTYPE_STRING test(const std::string &)
static CTYPE_INT test(const int &)
static CTYPE_LONG test(const long &)
static CTYPE_UNSIGNED_SHORT test(const unsigned short &)
rtype_helper< typename ctype< T >::type > helper_type
Definition algorithm.h:164
static constexpr T ONE()
Definition algorithm.h:168
static constexpr int RTYPE
Definition algorithm.h:165
static constexpr T ZERO()
Definition algorithm.h:167
rtype_helper< typenamectype< T >::type >::type type
Definition algorithm.h:163