Rcpp Version 0.12.12
piWithInterrupts.cpp
Go to the documentation of this file.
1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
2 
3 #include <Rcpp.h>
4 
5 #ifdef _OPENMP
6 #include <omp.h>
7 #endif
8 
9 #include <R_ext/Utils.h>
10 
15 class interrupt_exception : public std::exception {
16 public:
22  interrupt_exception(std::string message)
23  : detailed_message(message)
24  {};
25 
29  virtual ~interrupt_exception() throw() {};
30 
35  virtual const char* what() const throw() {
36  return detailed_message.c_str();
37  }
38 
42  std::string detailed_message;
43 };
44 
50 static inline void check_interrupt_impl(void* /*dummy*/) {
51  R_CheckUserInterrupt();
52 }
53 
64 inline bool check_interrupt() {
65  return (R_ToplevelExec(check_interrupt_impl, NULL) == FALSE);
66 }
67 
75 RcppExport SEXP PiLeibniz(SEXP n, SEXP frequency)
76 {
78 
79  // cast parameters
80  int n_cycles = Rcpp::as<int>(n);
81  int interrupt_check_frequency = Rcpp::as<int>(frequency);
82 
83  // user interrupt flag
84  bool interrupt = false;
85 
86  double pi = 0;
87 #ifdef _OPENMP
88 #pragma omp parallel for \
89  shared(interrupt_check_frequency, n_cycles, interrupt) \
90  reduction(+:pi)
91 #endif
92  for (int i=0; i<n_cycles; i+=interrupt_check_frequency) {
93  // check for user interrupt
94  if (interrupt) {
95  continue;
96  }
97 
98 #ifdef _OPENMP
99  if (omp_get_thread_num() == 0) // only in master thread!
100 #endif
101  if (check_interrupt()) {
102  interrupt = true;
103  }
104 
105  // do actual computations
106  int j_end = std::min(i+interrupt_check_frequency, n_cycles);
107  for (int j=i; j<j_end; ++j) {
108  double summand = 1.0 / (double)(2*j + 1);
109  if (j % 2 == 0) {
110  pi += summand;
111  }
112  else {
113  pi -= summand;
114  }
115  }
116  }
117 
118  // additional check, in case frequency was too large
119  if (check_interrupt()) {
120  interrupt = true;
121  }
122 
123  // throw exception if interrupt occurred
124  if (interrupt) {
125  throw interrupt_exception("The computation of pi was interrupted.");
126  }
127 
128  pi *= 4.0;
129 
130  // result list
131  return Rcpp::wrap(pi);
132 
133  END_RCPP
134 }
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
bool check_interrupt()
#define RcppExport
Definition: RcppCommon.h:129
static void check_interrupt_impl(void *)
virtual const char * what() const
#define BEGIN_RCPP
Definition: macros.h:30
RcppExport SEXP PiLeibniz(SEXP n, SEXP frequency)
#define END_RCPP
Definition: macros.h:67
SEXP wrap(const Date &date)
Definition: Date.h:38
interrupt_exception(std::string message)
std::string detailed_message