PRO find_elements_in_set_with_tolerance, v1, v2, tol, nmatch, lo_ind, hi_ind, status, V1_ALREADY_SORTED = v1_already_sorted, NO_PAR_CHECK = no_par_check
; Description: For each element in the set of data "v1", the module searches for the set of
; values from a set of input data "v2" that match within a tolerance "tol". A
; value y from "v2" is considered to match a value x from "v1" within a
; tolerance of "tol" if it lies in the range "(x - tol) <= y <= (x + 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. For
; each element in the set of data "v1", the module returns the number of
; matching data values from "v2" via the vector "nmatch", and it returns the
; indices of the smallest and largest matching data values from "v2" via the
; vectors "lo_ind" and "hi_ind" respectively.
;
; N.B: (i) The code for the binary search algorithm in this module is a copy of
; the code from the DanIDL module "binary_search_with_tolerance.pro"
; and it has been written "in-line" in this module for reasons of
; efficiency. Any changes to "binary_search_with_tolerance.pro" should
; therefore be reflected in this module aswell.
;
; (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 SCALAR/VECTOR/ARRAY - The set of data 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 VECTOR - A one-dimensional vector with the same number of elements as
; the input parameter "v1", where each element represents the
; number of data values from "v2" that match within a tolerance
; "tol" of the corresponding element of "v1". A value y from "v2"
; is considered to match a value x from "v1" within a tolerance
; of "tol" if it lies in the range "(x - tol) <= y <= (x + tol)".
; lo_ind - LONG VECTOR - A one-dimensional vector with the same number of elements as
; the input parameter "v1", where each element represents the
; index in "v2" of the smallest matching data value from "v2" for
; the corresponding element of "v1". If there are no matching
; data values in "v2" for an element of "v1", then the corresponding
; element of "lo_ind" is set to a value of "-1".
; hi_ind - LONG VECTOR - A one-dimensional vector with the same number of elements as
; the input parameter "v1", where each element represents the
; index in "v2" of the largest matching data value from "v2" for
; the corresponding element of "v1". If there are no matching
; data values in "v2" for an element of "v1", then the corresponding
; element of "hi_ind" is set to a value of "-1".
; status - INTEGER - If the module successfully completed its processing, then "status"
; is returned with a value of "1", otherwise it is returned with a
; value of "0".
;
; Keywords:
;
; If the keyword V1_ALREADY_SORTED is set (as "/V1_ALREADY_SORTED"), then the module will
; assume that the values of "v1" are sorted into ascending order. This option can be used
; to avoid a sort operation on the input parameter "v1", which allows the user to build
; more efficient code with this module.
;
; 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:
;
; 07/10/2011 - Added the keyword V1_ALREADY_SORTED (dmb).
; 28/07/2010 - Module created (dmb).
;Set the default output parameter values
;Perform parameter checking if not instructed otherwise
;Check that "v1" contains number data 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 "v1" and "v2"
;Set up the output parameter vectors
;Determine the subscripts of "v1" when it is sorted into ascending order
;For each element of "v1"
;Determine the current element of "v1" when it is sorted into ascending order
;If the value of the current element of "v1" plus the search tolerance "tol" is less than
;the minimum value of "v2", then there are no data values in "v2" that match within the
;tolerance "tol" of the current element of "v1", and the module will move on to the next
;element of "v1" when it is sorted into ascending order
;If the value of the current element of "v1" minus the search tolerance "tol" is greater
;than the maximum value of "v2", then there are no data values in "v2" that match within
;the tolerance "tol" of the current element of "v1", and the module will exit the loop
;over the elements of "v1" because all of the remaining elements of "v1" when it is sorted
;into ascending order are also greater than the maximum value of "v2"
;Find the lowest subscript in the set of data values "v2" such that the corresponding
;value is greater than or equal to the current element of "v1" minus the search tolerance
;"tol". Note that for extra speed, the first index in the binary search is set to the lower
;index for the range of matching indices in "v2" for the previously considered element of
;"v1", since we are considering the elements of "v1" in ascending order.
;Find the highest subscript in the set of data values "v2" such that the corresponding
;value is less than or equal to the current element of "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 current element of "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 current element of "v1". In this
;case, the module will move on to the next element of "v1" when it is sorted into
;ascending order.
;Count the number of matching data values
;Save the range of indices for the matching data values from "v2"
;Set "status" to "1"