50 swap( lhs.bins_, rhs.bins_);
51 swap( lhs.ranges_, rhs.ranges_);
52 swap( lhs.out_of_range_behaviour_, rhs.out_of_range_behaviour_);
57 return lhs.ranges_ == rhs.ranges_;
73 const size_t num_bins,
74 const double range_min,
75 const double range_max
78 , ranges_ (num_bins + 1)
82 throw std::domain_error(
"__FUNCTION__: domain_error");
89 const std::vector<double>& ranges
91 : bins_ (ranges.size() - 1, 0.0)
95 if (ranges.size() < 2) {
96 throw std::domain_error(
"__FUNCTION__: domain_error");
98 if (!std::is_sorted(ranges.begin(), ranges.end())) {
99 throw std::invalid_argument(
"__FUNCTION__: invalid_argument");
109 if (ranges.size() != ranges_.size() || !std::is_sorted(ranges.begin(), ranges.end())) {
110 throw std::invalid_argument(
"__FUNCTION__: invalid_argument");
123 throw std::invalid_argument(
"__FUNCTION__: invalid_argument");
134 const double n =
static_cast<double>(
bins());
135 for (
size_t i = 0; i <
bins() + 1; ++i) {
136 const double p =
static_cast<double>(i);
138 const double f1 = (n - p) / n;
139 const double f2 = p / n;
141 ranges_[i] = f1 * min + f2 * max;
152 for (
auto& b : bins_) {
159 return out_of_range_behaviour_;
164 out_of_range_behaviour_ = v;
173 return bins_ == rhs.bins_ && ranges_ == rhs.ranges_;
182 if (bin_num >= bins_.size()) {
183 throw std::out_of_range(
"__FUNCTION__: out_of_range");
185 return bins_.at(bin_num);
190 if (bin_num >= bins_.size()) {
191 throw std::out_of_range(
"__FUNCTION__: out_of_range");
193 return bins_.at(bin_num);
198 return bins_[bin_num];
203 return bins_[bin_num];
212 return bins_.begin();
222 return bins_.cbegin();
232 return bins_.cbegin();
251 return std::make_pair(ranges_[bin_num], ranges_[bin_num + 1]);
256 return (ranges_[bin_num] + ranges_[bin_num + 1]) / 2;
261 return ranges_[bin_num + 1] - ranges_[bin_num];
266 const auto r_min = ranges_.front();
267 const auto r_max = ranges_.back();
272 if( x < r_min || std::isnan( x )) {
280 const double bin_width = (r_max - r_min) /
static_cast<double>( bins_.size() );
281 const long bin =
static_cast<long>( std::floor( (x - r_min) /
bin_width ) );
284 assert(r_min <= x && x < r_max);
287 if (ranges_[bin] <= x && x < ranges_[bin + 1]) {
292 const auto it = std::upper_bound(ranges_.begin(), ranges_.end(), x);
293 return std::distance(ranges_.begin(), it) - 1;
298 return ranges_.front();
303 return ranges_.back();
326 if (bin < 0 ||
static_cast <size_t>(bin) >=
bins()) {
340 throw std::out_of_range(
"__FUNCTION__: out_of_range");
345 bins_[bin] += weight;
356 if( bin >= bins_.size() ) {
357 throw std::out_of_range(
"__FUNCTION__: out_of_range");
360 bins_[bin] += weight;