"""
Template for functions of IndexEngine subclasses.

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

# ----------------------------------------------------------------------
# IndexEngine Subclass Methods
# ----------------------------------------------------------------------

{{py:

# name, dtype
dtypes = [('Float64', 'float64'),
          ('Float32', 'float32'),
          ('Int64', 'int64'),
          ('Int32', 'int32'),
          ('Int16', 'int16'),
          ('Int8', 'int8'),
          ('UInt64', 'uint64'),
          ('UInt32', 'uint32'),
          ('UInt16', 'uint16'),
          ('UInt8', 'uint8'),
          ('Complex64', 'complex64'),
          ('Complex128', 'complex128'),
          ]

engines = [('', 'IndexEngine'), ('Masked', 'MaskedIndexEngine')]

}}

{{for name, dtype in dtypes}}

{{for prefix, engine in engines}}

cdef class {{prefix}}{{name}}Engine({{engine}}):

    cdef _make_hash_table(self, Py_ssize_t n):
    {{if engine == 'MaskedIndexEngine'}}
        return _hash.{{name}}HashTable(n, uses_mask=True)
    {{else}}
        return _hash.{{name}}HashTable(n)
    {{endif}}

    cdef _check_type(self, object val):
    {{if engine == 'MaskedIndexEngine'}}
        if val is C_NA:
            return val
    {{endif}}
    {{if name not in {'Float64', 'Float32', 'Complex64', 'Complex128'} }}
        if not util.is_integer_object(val):
            if util.is_float_object(val):
                # Make sure Int64Index.get_loc(2.0) works
                if val.is_integer():
                    return int(val)
            raise KeyError(val)
        {{if name.startswith("U")}}
        if val < 0:
            # cannot have negative values with unsigned int dtype
            raise KeyError(val)
        {{endif}}
    {{elif name not in {'Complex64', 'Complex128'} }}
        if not util.is_integer_object(val) and not util.is_float_object(val):
            # in particular catch bool and avoid casting True -> 1.0
            raise KeyError(val)
    {{else}}
        if (not util.is_integer_object(val)
            and not util.is_float_object(val)
            and not util.is_complex_object(val)
        ):
            # in particular catch bool and avoid casting True -> 1.0
            raise KeyError(val)
    {{endif}}
        return val

{{endfor}}

{{endfor}}
