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