"""
Template for each `dtype` helper function for hashtable

WARNING: DO NOT edit .pxi FILE directly, .pxi is generated from .pxi.in
"""

#----------------------------------------------------------------------
# VectorData
#----------------------------------------------------------------------

{{py:

# name
dtypes = ['float64', 'int64']

}}

{{for dtype in dtypes}}


@cython.wraparound(False)
@cython.boundscheck(False)
cdef build_count_table_{{dtype}}({{dtype}}_t[:] values,
                                 kh_{{dtype}}_t *table, bint dropna):
    cdef:
        khiter_t k
        Py_ssize_t i, n = len(values)
        {{dtype}}_t val
        int ret = 0

    with nogil:
        kh_resize_{{dtype}}(table, n)

        for i in range(n):
            val = values[i]
            if val == val or not dropna:
                k = kh_get_{{dtype}}(table, val)
                if k != table.n_buckets:
                    table.vals[k] += 1
                else:
                    k = kh_put_{{dtype}}(table, val, &ret)
                    table.vals[k] = 1


@cython.wraparound(False)
@cython.boundscheck(False)
cpdef value_count_{{dtype}}({{dtype}}_t[:] values, bint dropna):
    cdef:
        Py_ssize_t i=0
        kh_{{dtype}}_t *table
        {{dtype}}_t[:] result_keys
        int64_t[:] result_counts
        int k

    table = kh_init_{{dtype}}()
    build_count_table_{{dtype}}(values, table, dropna)

    result_keys = np.empty(table.n_occupied, dtype=np.{{dtype}})
    result_counts = np.zeros(table.n_occupied, dtype=np.int64)

    with nogil:
        for k in range(table.n_buckets):
            if kh_exist_{{dtype}}(table, k):
                result_keys[i] = table.keys[k]
                result_counts[i] = table.vals[k]
                i += 1
    kh_destroy_{{dtype}}(table)

    return np.asarray(result_keys), np.asarray(result_counts)


@cython.wraparound(False)
@cython.boundscheck(False)
def duplicated_{{dtype}}({{dtype}}_t[:] values,
                         object keep='first'):
    cdef:
        int ret = 0, k
        {{dtype}}_t value
        Py_ssize_t i, n = len(values)
        kh_{{dtype}}_t * table = kh_init_{{dtype}}()
        ndarray[uint8_t, ndim=1, cast=True] out = np.empty(n, dtype='bool')

    kh_resize_{{dtype}}(table, min(n, _SIZE_HINT_LIMIT))

    if keep not in ('last', 'first', False):
        raise ValueError('keep must be either "first", "last" or False')

    if keep == 'last':
        with nogil:
            for i from n > i >=0:
                kh_put_{{dtype}}(table, values[i], &ret)
                out[i] = ret == 0
    elif keep == 'first':
        with nogil:
            for i from 0 <= i < n:
                kh_put_{{dtype}}(table, values[i], &ret)
                out[i] = ret == 0
    else:
        with nogil:
            for i from 0 <= i < n:
                value = values[i]
                k = kh_get_{{dtype}}(table, value)
                if k != table.n_buckets:
                    out[table.vals[k]] = 1
                    out[i] = 1
                else:
                    k = kh_put_{{dtype}}(table, value, &ret)
                    table.keys[k] = value
                    table.vals[k] = i
                    out[i] = 0
    kh_destroy_{{dtype}}(table)
    return out

{{endfor}}
