+void AnalogSignal::perform_autoranging(bool force_update)
+{
+ const deque< shared_ptr<pv::data::AnalogSegment> > &segments =
+ base_->analog_data()->analog_segments();
+
+ if (segments.empty())
+ return;
+
+ static double prev_min = 0, prev_max = 0;
+ double min = 0, max = 0;
+
+ for (shared_ptr<pv::data::AnalogSegment> segment : segments) {
+ pair<double, double> mm = segment->get_min_max();
+ min = std::min(min, mm.first);
+ max = std::max(max, mm.second);
+ }
+
+ if ((min == prev_min) && (max == prev_max) && !force_update)
+ return;
+
+ prev_min = min;
+ prev_max = max;
+
+ // Use all divs for the positive range if there are no negative values
+ if ((min == 0) && (neg_vdivs_ > 0)) {
+ pos_vdivs_ += neg_vdivs_;
+ neg_vdivs_ = 0;
+ }
+
+ // Split up the divs if there are negative values but no negative divs
+ if ((min < 0) && (neg_vdivs_ == 0)) {
+ neg_vdivs_ = pos_vdivs_ / 2;
+ pos_vdivs_ -= neg_vdivs_;
+ }
+
+ double min_value_per_div;
+ if ((pos_vdivs_ > 0) && (neg_vdivs_ > 0))
+ min_value_per_div = std::max(max / pos_vdivs_, -min / neg_vdivs_);
+ else if (pos_vdivs_ > 0)
+ min_value_per_div = max / pos_vdivs_;
+ else
+ min_value_per_div = -min / neg_vdivs_;
+
+ // Find first scale value that is bigger than the value we need
+ for (int i = MinScaleIndex; i < MaxScaleIndex; i++)
+ if (get_resolution(i) > min_value_per_div) {
+ scale_index_ = i;
+ break;
+ }
+
+ update_scale();
+}
+