class Rangefinder
Constants
- INIT_SAMP
- MAX
- MAX_GAP
- MAX_SAMP
- VERSION
Public Instance Methods
probe(options = {}, &blk)
click to toggle source
# File lib/rangefinder.rb, line 12 def probe(options = {}, &blk) ranges, _, _ = probe_with_hits_and_misses(options, &blk) ranges end
probe_with_hits_and_misses(options = {}, &blk)
click to toggle source
# File lib/rangefinder.rb, line 17 def probe_with_hits_and_misses(options = {}, &blk) memo = Memo.new _probe(memo, options, &blk) [ ::RangesMerger.merge(memo.ranges), memo.hits, memo.misses ] end
Private Instance Methods
_probe(memo, options = {}, &blk)
click to toggle source
# File lib/rangefinder.rb, line 25 def _probe(memo, options = {}, &blk) first = [options.fetch(:first, 0), 0].max.round last = [options.fetch(:last, MAX), MAX].min.round max_gap = options.fetch(:max_gap, MAX_GAP) samp = options.fetch(:samp, INIT_SAMP) random = options.fetch(:random, ::Random.new) if samp >= MAX_SAMP memo.ranges << (first..last) else min_range = (10 ** (2 - Math.log(samp, 10))).round anything = false first_good = nil i = first last_good = first begin if blk.call(i) memo.hit! anything = true first_good ||= i last_good = i else memo.miss! end gap = i - last_good if first_good and gap > min_range _probe memo, {first: first_good-min_range, last: last_good+min_range, samp: samp*3}, &blk first_good = nil last_good = i gap = 0 end samp1 = gap > 10 ? samp * Math.log(gap, 10) : samp i += (random.rand(100) * (1 - samp1)).round end until i >= last or (gap > max_gap and anything) # sorry for mixed metaphor end end