m01ndc searches a strictly ordered vector of double numbers and returns the indices of the largest numbers in the vector which are smaller than or equal to the sought-after items.
The function may be called by the names: m01ndc or nag_sort_realvec_vec_search.
3Description
m01ndc searches an array, $X$, of $n$ strictly-increasing double numbers, ${X}_{i}<{X}_{i+1}$, $i=1\dots (n-1)$, for the elements of an unordered array of $m$ double numbers, $Z$. If a value equal to a sought-after item ${Z}_{i}$ is not found in $X$, the index of the immediate lower value is returned. If ${Z}_{i}$ is less than ${X}_{1}$, $\mathrm{-1}$ is returned.
The function implements the direct search algorithm presented as Algorithm 8 in Cannizzo (2018). It precomputes a scalar, $H$, and a reference vector of indices, $K$, that it uses to speed up searches of $X$. The length of $K$ is a function of the number of entries in $X$ and their values, and the function provides a mechanism to compute what this length should be.
If the amount of memory required for $K$ is infeasible, m01ndc
implements offset-based binary search (Algorithm 5 in Cannizzo (2018)) as an alternative that does not require $K$ to be used.
See Section 9 for more information on the relative time complexities of the two search algorithms.
4References
Cannizzo F (2018) A fast and vectorizable alternative to binary search in O(1) with wide applicability to arrays of floating point numbers Journal of Parallel and Distributed Computing113 37–54
5Arguments
1: $\mathbf{validate}$ – Nag_BooleanInput
On entry: if validate is set to Nag_TRUE argument checking will be performed. If validate is set to Nag_FALSE m01ndc will be called without argument checking (which includes checking that array rv is sorted in strictly ascending order). See Section 9 for further details.
2: $\mathbf{mode}$ – IntegerInput
On entry: a code for selecting the operation to be performed by the function. The first call to m01ndc must be made with ${\mathbf{mode}}=0$. This must be followed by a second setup call with ${\mathbf{mode}}=1$ or a combined setup and search call with ${\mathbf{mode}}=4$. Thereafter repeated searches of rv can be made through repeated calls with ${\mathbf{mode}}=2$.
${\mathbf{mode}}=0$
Compute h and lk. Following a call with ${\mathbf{mode}}=0$, k must be allocated to hold lk elements and then the function must be called again with ${\mathbf{mode}}=1$ or $4$.
${\mathbf{mode}}=1$
Set up k (the reference vector) using the values of h and lk returned from a prior call to m01ndc with ${\mathbf{mode}}=0$.
${\mathbf{mode}}=2$
Direct search using h and k set up in prior calls to m01ndc with ${\mathbf{mode}}=0$, $1$ or $4$.
${\mathbf{mode}}=3$
Search using offset-based binary search, which does not require h or k to be used.
${\mathbf{mode}}=4$
Set up as with ${\mathbf{mode}}=1$ and follow by a single direct search as with ${\mathbf{mode}}=2$.
Constraint:
${\mathbf{mode}}=0$, $1$, $2$, $3$ or $4$.
On exit: if ${\mathbf{mode}}\ne 0$, ${\mathbf{idx}}\left[i-1\right]$ contains the index of the largest entry in rv which is smaller than or equal to ${\mathbf{item}}\left[i-1\right]$.
10: $\mathbf{h}$ – double *Communication
On entry: $H$, the reference scalar required by the direct search algorithm. If ${\mathbf{mode}}=0$, m01ndc calculates the value of h required by the direct search function for the given values in rv. Otherwise, the value of h as declared in the function from which m01ndc is called. If ${\mathbf{mode}}=0$, h is not referenced.
On exit: the value of h required by the direct search function for the given values in rv.
Constraint:
if ${\mathbf{mode}}=1$, $2$ or $4$, h must be unchanged from the previous call to m01ndc.
On entry: if ${\mathbf{mode}}=2$, k, the reference vector from the previous call to m01ndc. If ${\mathbf{mode}}=0$ or $3$, k is not referenced and may be NULL.
On exit: if ${\mathbf{mode}}=1$, $2$ or $4$, the reference vector.
Constraint:
if ${\mathbf{mode}}=2$, k must be unchanged from the previous call to m01ndc.
12: $\mathbf{lk}$ – Integer *Input/Output
On entry: if ${\mathbf{mode}}=0$, m01ndc calculates the dimension of k required by the direct search function for the given values in rv. Otherwise, the dimension of the array k as declared in the function from which m01ndc is called. If ${\mathbf{mode}}=3$, lk is not referenced.
On exit: if ${\mathbf{mode}}=0$, the dimension of the array k required by the direct search function for the given values in rv. Otherwise, the dimension of the array k as declared in the function from which m01ndc is called.
Constraint:
if ${\mathbf{mode}}=1$, $2$ or $4$, lk must be unchanged from the previous call to m01ndc.
13: $\mathbf{fail}$ – NagError *Input/Output
The NAG error argument (see Section 7 in the Introduction to the NAG Library CL Interface).
6Error Indicators and Warnings
NE_ALLOC_FAIL
Dynamic memory allocation failed.
See Section 3.1.2 in the Introduction to the NAG Library CL Interface for further information.
NE_BAD_PARAM
Either m01ndc was not called with ${\mathbf{mode}}=0$, $1$ or $4$, or the values of h, k or lk may have become corrupted.
On entry, argument $\u27e8\mathit{\text{value}}\u27e9$ had an illegal value.
NE_INT
On entry, ${\mathbf{m}}=\u27e8\mathit{\text{value}}\u27e9$. Constraint: ${\mathbf{m}}\ge 1$.
On entry, ${\mathbf{m1}}=\u27e8\mathit{\text{value}}\u27e9$. Constraint: ${\mathbf{m1}}\ge 0$.
On entry, ${\mathbf{mode}}=\u27e8\mathit{\text{value}}\u27e9$. Constraint: ${\mathbf{mode}}=0$, $1$, $2$, $3$ or $4$.
On entry, ${\mathbf{n}}=\u27e8\mathit{\text{value}}\u27e9$. Constraint: ${\mathbf{n}}\ge 2$.
NE_INT_2
On entry, ${\mathbf{m1}}=\u27e8\mathit{\text{value}}\u27e9$, ${\mathbf{m2}}=\u27e8\mathit{\text{value}}\u27e9$, ${\mathbf{n}}=\u27e8\mathit{\text{value}}\u27e9$. Constraint: ${\mathbf{m1}}\le {\mathbf{m2}}\le {\mathbf{n}}-1$.
NE_INTERNAL_ERROR
An internal error has occurred in this function. Check the function call and any array sizes. If the call is correct then please contact NAG for assistance.
See Section 7.5 in the Introduction to the NAG Library CL Interface for further information.
NE_NO_LICENCE
Your licence key may have expired or may not have been installed correctly.
See Section 8 in the Introduction to the NAG Library CL Interface for further information.
NE_NOT_STRICTLY_INCREASING
On entry, rv must be sorted in strictly ascending order: ${\mathbf{rv}}\text{ element}\u27e8\mathit{\text{value}}\u27e9>\text{ element}\u27e8\mathit{\text{value}}\u27e9$.
NE_OVERFLOW
On entry, the values in rv are such that the required value of lk would overflow the current platform's largest positive integer value. This error should only appear when m01ndc is called with ${\mathbf{mode}}=0$ (i.e., when the function is asked to calculate the required value of lk for the given rv).
7Accuracy
Not applicable.
8Parallelism and Performance
m01ndc is threaded by NAG for parallel execution in multithreaded implementations of the NAG Library.
Please consult the X06 Chapter Introduction for information on how to control and interrogate the OpenMP environment used within this function. Please also consult the Users' Note for your implementation for any additional implementation-specific information.
9Further Comments
The argument validate should be used with caution. Set it to Nag_FALSE only if you are confident that the other arguments are correct, in particular that array rv is in fact arranged in strictly ascending order. If you wish to search the same array rv many times, you are recommended to set validate to Nag_TRUE on the first call of m01ndc and to Nag_FALSE on subsequent calls, in order to minimize the amount of time spent checking rv, which may be significant if rv is large.
The time taken by m01ndc to construct the reference vector (i.e., when the function is called with ${\mathbf{mode}}=1$ or $4$) is $\mathit{O}\left(n\right)$. Note that the values stored in k depend on all entries of rv, and not just those in the interval $[{\mathbf{m1}},{\mathbf{m2}}]$. Thereafter, searching for m items using direct search (i.e., when the function is called with ${\mathbf{mode}}=2$ or $4$) is $\mathit{O}\left(m\right)$. In contrast offset-based binary search (i.e., when the function is called with ${\mathbf{mode}}=3$), does not require construction of the reference vector and has time complexity $\mathit{O}(m\hspace{0.17em}\mathrm{log}\left(n\right))$. Although this is the same as classical binary search, offset-based binary search may be faster in practice because the implementation does not feature conditional branches. Direct search is preferable when the overhead of constructing the reference vector can be offset by conducting multiple searches on an unchanged rv.
10Example
This example reads a list of double numbers and a list of sought-after items and performs the search for these items. The example demonstrates how to use m01ndc for both direct search (i.e., ${\mathbf{mode}}=4$) and offset-based binary search (${\mathbf{mode}}=3$).