| 85 | // base case |
| 86 | template <int RTYPE, bool NA, typename T, bool NA_RM = false> |
| 87 | class Median { |
| 88 | public: |
| 89 | typedef typename median_detail::result<RTYPE>::type result_type; |
| 90 | typedef typename Rcpp::traits::storage_type<RTYPE>::type stored_type; |
| 91 | enum { RESULT_RTYPE = median_detail::result<RTYPE>::rtype }; |
| 92 | typedef T VECTOR; |
| 93 | |
| 94 | private: |
| 95 | VECTOR x; |
| 96 | |
| 97 | public: |
| 98 | Median(const VECTOR& xx) |
| 99 | : x(Rcpp::clone(xx)) {} |
| 100 | |
| 101 | operator result_type() { |
| 102 | if (x.size() < 1) { |
| 103 | return Rcpp::traits::get_na<RESULT_RTYPE>(); |
| 104 | } |
| 105 | |
| 106 | if (Rcpp::any(Rcpp::is_na(x))) { |
| 107 | return Rcpp::traits::get_na<RESULT_RTYPE>(); |
| 108 | } |
| 109 | |
| 110 | R_xlen_t n = x.size() / 2; |
| 111 | std::nth_element( |
| 112 | x.begin(), x.begin() + n, x.end(), |
| 113 | median_detail::less<stored_type>); |
| 114 | |
| 115 | if (x.size() % 2) return x[n]; |
| 116 | return median_detail::half( |
| 117 | x[n] + *std::max_element( |
| 118 | x.begin(), x.begin() + n, |
| 119 | median_detail::less<stored_type>)); |
| 120 | } |
| 121 | }; |
| 122 | |
| 123 | // na.rm = TRUE |
| 124 | template <int RTYPE, bool NA, typename T> |