Very fast uniqify routine for numpy record arrays (or ndarrays with 
    structured dtype).

    Record array version of func:`tabular.fast.arrayuniqify`.

    **Parameters**

            **X** :  numpy recarray

                    Determine the unique elements of this numpy recarray.

            **retainorder** :  Boolean, optional

                    Whether or not to return indices corresponding to unique 
                    values of `X` that also sort the values.  Default value is 
                    `False`, in which case `[D,s]` is  returned.  This can be 
                    used to produce a uniqified  version of `X` by simply 
                    taking::

                            X[s][D]

                    or::

                            X[s[D.nonzero()[0]]]

    **Returns**

            **D** :  numpy recarray

                    List of "first differences" in the sorted verion of `X`.  
                    Returned when `retainorder` is `False` (default).

            **s** :  numpy array

                    Permutation that will sort `X`.  Returned when 
                    `retainorder` is `False` (default).

            **ind** :  numpy array

                    List of indices that correspond to unique values of `X`, 
                    without sorting those values.  Returned when `retainorder` 
                    is `True`.

    **See Also:**

            :func:`tabular.fast.arrayuniqify`

def recarrayuniqify(X, retainorder=False):
    """
    Very fast uniqify routine for numpy record arrays (or ndarrays with 
    structured dtype).

    Record array version of func:`tabular.fast.arrayuniqify`.

    **Parameters**

            **X** :  numpy recarray

                    Determine the unique elements of this numpy recarray.

            **retainorder** :  Boolean, optional

                    Whether or not to return indices corresponding to unique 
                    values of `X` that also sort the values.  Default value is 
                    `False`, in which case `[D,s]` is  returned.  This can be 
                    used to produce a uniqified  version of `X` by simply 
                    taking::

                            X[s][D]

                    or::

                            X[s[D.nonzero()[0]]]

    **Returns**

            **D** :  numpy recarray

                    List of "first differences" in the sorted verion of `X`.  
                    Returned when `retainorder` is `False` (default).

            **s** :  numpy array

                    Permutation that will sort `X`.  Returned when 
                    `retainorder` is `False` (default).

            **ind** :  numpy array

                    List of indices that correspond to unique values of `X`, 
                    without sorting those values.  Returned when `retainorder` 
                    is `True`.

    **See Also:**

            :func:`tabular.fast.arrayuniqify`

    """
    N = X.dtype.names
    s = X.argsort(order=N)
    s = s.view(np.ndarray)
    X = X[s]
    D = np.append([True],X[1:] != X[:-1])
    if retainorder:
        DD = np.append(D.nonzero()[0],len(X))
        ind = [min(s[x:DD[i+1]]) for (i,x) in enumerate(DD[:-1])]
        ind.sort()
        return ind
    else:
        return [D,s]