PRO binary_search_with_tolerance, v1, v2, tol, nmatch, lo_ind, hi_ind, NO_PAR_CHECK = no_par_check
; Description: This module searches for the set of values from a set of input data "v2" that
; match within a tolerance "tol" of the value "v1". A value x from "v2" is
; considered to match the value "v1" within a tolerance of "tol" if it lies in
; the range "(v1 - tol) <= x <= (v1 + tol)". The module employs a fast binary
; search algorithm and it is for this reason that the set of data values "v2"
; must already be sorted into ascending order. The indices of the smallest and
; largest matching data values from "v2" are returned as the indices "lo_ind"
; and "hi_ind" respectively.
;
; N.B: (i) If you want to perform multiple binary searches with tolerance on
; the same data "v2", but with different values of "v1", then it is
; much more efficient to use the DanIDL module
; "find_elements_in_set_with_tolerance.pro" because the data "v2" is
; not copied on each call to the binary search algorithm.
;
; (ii) I have proved using proof by induction that the algorithm
; implemented in this code will always give the correct answer.
;
; Input Parameters:
;
; v1 - FLOAT/DOUBLE - The value for which matching data values in "v2" are to be found.
; v2 - FLOAT/DOUBLE SCALAR/VECTOR/ARRAY - The set of data values to be searched for
; matches, already sorted into ascending order.
; tol - FLOAT/DOUBLE - The maximum difference between values that is considered a match.
; This parameter must be non-negative.
;
; Output Parameters:
;
; nmatch - LONG - The number of values from "v2" that match within a tolerance "tol"
; of the value "v1". A value x from "v2" is considered to match the
; value "v1" within a tolerance of "tol" if it lies in the range
; "(v1 - tol) <= x <= (v1 + tol)". If the module fails, then the value
; of this parameter is set to "-1".
; lo_ind - LONG - The index of the smallest matching data value from "v2". If there
; are no matching data values, then "lo_ind" is returned with a value
; of "-1".
; hi_ind - LONG - The index of the largest matching data value from "v2". If there
; are no matching data values, then "hi_ind" is returned with a value
; of "-1".
;
; Keywords:
;
; If the keyword NO_PAR_CHECK is set (as "/NO_PAR_CHECK"), then the module will not
; perform parameter checking on the input parameters, reducing module overheads.
;
; Author: Dan Bramich (dan.bramich@hotmail.co.uk)
;
; History:
;
; 03/07/2010 - Module created (dmb).
;Set the default output parameter values
;Perform parameter checking if not instructed otherwise
;Check that "v1" is a number of the correct type
;Check that "v2" contains number data of the correct type
;Check that "tol" is a non-negative number of the correct type
;Determine the number of elements in "v2"
;If "v1" does not lie in the range of the data values in "v2" including the tolerance,
;then there are no data values in "v2" that match within a tolerance "tol" of the
;value "v1", and the module will finish
;Find the lowest subscript in the set of data values "v2" such that the corresponding
;value is greater than or equal to the value "v1" minus the search tolerance "tol"
;Find the highest subscript in the set of data values "v2" such that the corresponding
;value is less than or equal to the value "v1" plus the search tolerance "tol"
;If the lowest subscript that was found is greater than the highest subscript that was
;found, then this implies that the tolerance range around the value "v1" lies between
;two consecutive data values in "v2", and therefore there are no data values in "v2"
;that match within the tolerance "tol" of the value "v1". In this case, the module
;will finish.
;Count the number of matching data values