# This file was automatically generated by SWIG (https://www.swig.org).
# Version 4.4.1
#
# Do not make changes to this file unless you know what you are doing - modify
# the SWIG interface file instead.

from sys import version_info as _swig_python_version_info
# Import the low-level C/C++ module
if getattr(globals().get("__spec__"), "parent", None) or __package__ or "." in __name__:
    from . import _swigfaiss
else:
    import _swigfaiss

try:
    import builtins as __builtin__
except ImportError:
    import __builtin__

def _swig_repr(self):
    try:
        strthis = "proxy of " + self.this.__repr__()
    except __builtin__.Exception:
        strthis = ""
    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)


def _swig_setattr_nondynamic_instance_variable(set):
    def set_instance_attr(self, name, value):
        if name == "this":
            set(self, name, value)
        elif name == "thisown":
            self.this.own(value)
        elif hasattr(self, name) and isinstance(getattr(type(self), name), property):
            set(self, name, value)
        else:
            raise AttributeError("You cannot add instance attributes to %s" % self)
    return set_instance_attr


def _swig_setattr_nondynamic_class_variable(set):
    def set_class_attr(cls, name, value):
        if hasattr(cls, name) and not isinstance(getattr(cls, name), property):
            set(cls, name, value)
        else:
            raise AttributeError("You cannot add class attributes to %s" % cls)
    return set_class_attr


def _swig_add_metaclass(metaclass):
    """Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass"""
    def wrapper(cls):
        return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())
    return wrapper


class _SwigNonDynamicMeta(type):
    """Meta class to enforce nondynamic attributes (no new attributes) for a class"""
    __setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)


class SwigPyIterator(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    __swig_destroy__ = _swigfaiss.delete_SwigPyIterator

    def value(self):
        return _swigfaiss.SwigPyIterator_value(self)

    def incr(self, n=1):
        return _swigfaiss.SwigPyIterator_incr(self, n)

    def decr(self, n=1):
        return _swigfaiss.SwigPyIterator_decr(self, n)

    def distance(self, x):
        return _swigfaiss.SwigPyIterator_distance(self, x)

    def equal(self, x):
        return _swigfaiss.SwigPyIterator_equal(self, x)

    def copy(self):
        return _swigfaiss.SwigPyIterator_copy(self)

    def next(self):
        return _swigfaiss.SwigPyIterator_next(self)

    def __next__(self):
        return _swigfaiss.SwigPyIterator___next__(self)

    def previous(self):
        return _swigfaiss.SwigPyIterator_previous(self)

    def advance(self, n):
        return _swigfaiss.SwigPyIterator_advance(self, n)

    def __eq__(self, x):
        return _swigfaiss.SwigPyIterator___eq__(self, x)

    def __ne__(self, x):
        return _swigfaiss.SwigPyIterator___ne__(self, x)

    def __iadd__(self, n):
        return _swigfaiss.SwigPyIterator___iadd__(self, n)

    def __isub__(self, n):
        return _swigfaiss.SwigPyIterator___isub__(self, n)

    def __add__(self, n):
        return _swigfaiss.SwigPyIterator___add__(self, n)

    def __sub__(self, *args):
        return _swigfaiss.SwigPyIterator___sub__(self, *args)
    def __iter__(self):
        return self

# Register SwigPyIterator in _swigfaiss:
_swigfaiss.SwigPyIterator_swigregister(SwigPyIterator)
SHARED_PTR_DISOWN = _swigfaiss.SHARED_PTR_DISOWN
class Float32Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.Float32Vector_swiginit(self, _swigfaiss.new_Float32Vector())

    def push_back(self, arg2):
        return _swigfaiss.Float32Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.Float32Vector_clear(self)

    def data(self):
        return _swigfaiss.Float32Vector_data(self)

    def size(self):
        return _swigfaiss.Float32Vector_size(self)

    def at(self, n):
        return _swigfaiss.Float32Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.Float32Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.Float32Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_Float32Vector

# Register Float32Vector in _swigfaiss:
_swigfaiss.Float32Vector_swigregister(Float32Vector)
class Float64Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.Float64Vector_swiginit(self, _swigfaiss.new_Float64Vector())

    def push_back(self, arg2):
        return _swigfaiss.Float64Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.Float64Vector_clear(self)

    def data(self):
        return _swigfaiss.Float64Vector_data(self)

    def size(self):
        return _swigfaiss.Float64Vector_size(self)

    def at(self, n):
        return _swigfaiss.Float64Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.Float64Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.Float64Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_Float64Vector

# Register Float64Vector in _swigfaiss:
_swigfaiss.Float64Vector_swigregister(Float64Vector)
class Int8Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.Int8Vector_swiginit(self, _swigfaiss.new_Int8Vector())

    def push_back(self, arg2):
        return _swigfaiss.Int8Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.Int8Vector_clear(self)

    def data(self):
        return _swigfaiss.Int8Vector_data(self)

    def size(self):
        return _swigfaiss.Int8Vector_size(self)

    def at(self, n):
        return _swigfaiss.Int8Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.Int8Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.Int8Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_Int8Vector

# Register Int8Vector in _swigfaiss:
_swigfaiss.Int8Vector_swigregister(Int8Vector)
class Int16Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.Int16Vector_swiginit(self, _swigfaiss.new_Int16Vector())

    def push_back(self, arg2):
        return _swigfaiss.Int16Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.Int16Vector_clear(self)

    def data(self):
        return _swigfaiss.Int16Vector_data(self)

    def size(self):
        return _swigfaiss.Int16Vector_size(self)

    def at(self, n):
        return _swigfaiss.Int16Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.Int16Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.Int16Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_Int16Vector

# Register Int16Vector in _swigfaiss:
_swigfaiss.Int16Vector_swigregister(Int16Vector)
class Int32Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.Int32Vector_swiginit(self, _swigfaiss.new_Int32Vector())

    def push_back(self, arg2):
        return _swigfaiss.Int32Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.Int32Vector_clear(self)

    def data(self):
        return _swigfaiss.Int32Vector_data(self)

    def size(self):
        return _swigfaiss.Int32Vector_size(self)

    def at(self, n):
        return _swigfaiss.Int32Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.Int32Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.Int32Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_Int32Vector

# Register Int32Vector in _swigfaiss:
_swigfaiss.Int32Vector_swigregister(Int32Vector)
class Int64Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.Int64Vector_swiginit(self, _swigfaiss.new_Int64Vector())

    def push_back(self, arg2):
        return _swigfaiss.Int64Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.Int64Vector_clear(self)

    def data(self):
        return _swigfaiss.Int64Vector_data(self)

    def size(self):
        return _swigfaiss.Int64Vector_size(self)

    def at(self, n):
        return _swigfaiss.Int64Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.Int64Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.Int64Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_Int64Vector

# Register Int64Vector in _swigfaiss:
_swigfaiss.Int64Vector_swigregister(Int64Vector)
class UInt8Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.UInt8Vector_swiginit(self, _swigfaiss.new_UInt8Vector())

    def push_back(self, arg2):
        return _swigfaiss.UInt8Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.UInt8Vector_clear(self)

    def data(self):
        return _swigfaiss.UInt8Vector_data(self)

    def size(self):
        return _swigfaiss.UInt8Vector_size(self)

    def at(self, n):
        return _swigfaiss.UInt8Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.UInt8Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.UInt8Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_UInt8Vector

# Register UInt8Vector in _swigfaiss:
_swigfaiss.UInt8Vector_swigregister(UInt8Vector)
class UInt16Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.UInt16Vector_swiginit(self, _swigfaiss.new_UInt16Vector())

    def push_back(self, arg2):
        return _swigfaiss.UInt16Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.UInt16Vector_clear(self)

    def data(self):
        return _swigfaiss.UInt16Vector_data(self)

    def size(self):
        return _swigfaiss.UInt16Vector_size(self)

    def at(self, n):
        return _swigfaiss.UInt16Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.UInt16Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.UInt16Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_UInt16Vector

# Register UInt16Vector in _swigfaiss:
_swigfaiss.UInt16Vector_swigregister(UInt16Vector)
class UInt32Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.UInt32Vector_swiginit(self, _swigfaiss.new_UInt32Vector())

    def push_back(self, arg2):
        return _swigfaiss.UInt32Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.UInt32Vector_clear(self)

    def data(self):
        return _swigfaiss.UInt32Vector_data(self)

    def size(self):
        return _swigfaiss.UInt32Vector_size(self)

    def at(self, n):
        return _swigfaiss.UInt32Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.UInt32Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.UInt32Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_UInt32Vector

# Register UInt32Vector in _swigfaiss:
_swigfaiss.UInt32Vector_swigregister(UInt32Vector)
class UInt64Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.UInt64Vector_swiginit(self, _swigfaiss.new_UInt64Vector())

    def push_back(self, arg2):
        return _swigfaiss.UInt64Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.UInt64Vector_clear(self)

    def data(self):
        return _swigfaiss.UInt64Vector_data(self)

    def size(self):
        return _swigfaiss.UInt64Vector_size(self)

    def at(self, n):
        return _swigfaiss.UInt64Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.UInt64Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.UInt64Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_UInt64Vector

# Register UInt64Vector in _swigfaiss:
_swigfaiss.UInt64Vector_swigregister(UInt64Vector)
class Float32VectorVector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.Float32VectorVector_swiginit(self, _swigfaiss.new_Float32VectorVector())

    def push_back(self, arg2):
        return _swigfaiss.Float32VectorVector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.Float32VectorVector_clear(self)

    def data(self):
        return _swigfaiss.Float32VectorVector_data(self)

    def size(self):
        return _swigfaiss.Float32VectorVector_size(self)

    def at(self, n):
        return _swigfaiss.Float32VectorVector_at(self, n)

    def resize(self, n):
        return _swigfaiss.Float32VectorVector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.Float32VectorVector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_Float32VectorVector

# Register Float32VectorVector in _swigfaiss:
_swigfaiss.Float32VectorVector_swigregister(Float32VectorVector)
class UInt8VectorVector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.UInt8VectorVector_swiginit(self, _swigfaiss.new_UInt8VectorVector())

    def push_back(self, arg2):
        return _swigfaiss.UInt8VectorVector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.UInt8VectorVector_clear(self)

    def data(self):
        return _swigfaiss.UInt8VectorVector_data(self)

    def size(self):
        return _swigfaiss.UInt8VectorVector_size(self)

    def at(self, n):
        return _swigfaiss.UInt8VectorVector_at(self, n)

    def resize(self, n):
        return _swigfaiss.UInt8VectorVector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.UInt8VectorVector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_UInt8VectorVector

# Register UInt8VectorVector in _swigfaiss:
_swigfaiss.UInt8VectorVector_swigregister(UInt8VectorVector)
class Int32VectorVector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.Int32VectorVector_swiginit(self, _swigfaiss.new_Int32VectorVector())

    def push_back(self, arg2):
        return _swigfaiss.Int32VectorVector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.Int32VectorVector_clear(self)

    def data(self):
        return _swigfaiss.Int32VectorVector_data(self)

    def size(self):
        return _swigfaiss.Int32VectorVector_size(self)

    def at(self, n):
        return _swigfaiss.Int32VectorVector_at(self, n)

    def resize(self, n):
        return _swigfaiss.Int32VectorVector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.Int32VectorVector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_Int32VectorVector

# Register Int32VectorVector in _swigfaiss:
_swigfaiss.Int32VectorVector_swigregister(Int32VectorVector)
class Int64VectorVector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.Int64VectorVector_swiginit(self, _swigfaiss.new_Int64VectorVector())

    def push_back(self, arg2):
        return _swigfaiss.Int64VectorVector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.Int64VectorVector_clear(self)

    def data(self):
        return _swigfaiss.Int64VectorVector_data(self)

    def size(self):
        return _swigfaiss.Int64VectorVector_size(self)

    def at(self, n):
        return _swigfaiss.Int64VectorVector_at(self, n)

    def resize(self, n):
        return _swigfaiss.Int64VectorVector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.Int64VectorVector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_Int64VectorVector

# Register Int64VectorVector in _swigfaiss:
_swigfaiss.Int64VectorVector_swigregister(Int64VectorVector)
class VectorTransformVector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.VectorTransformVector_swiginit(self, _swigfaiss.new_VectorTransformVector())

    def push_back(self, arg2):
        return _swigfaiss.VectorTransformVector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.VectorTransformVector_clear(self)

    def data(self):
        return _swigfaiss.VectorTransformVector_data(self)

    def size(self):
        return _swigfaiss.VectorTransformVector_size(self)

    def at(self, n):
        return _swigfaiss.VectorTransformVector_at(self, n)

    def resize(self, n):
        return _swigfaiss.VectorTransformVector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.VectorTransformVector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_VectorTransformVector

# Register VectorTransformVector in _swigfaiss:
_swigfaiss.VectorTransformVector_swigregister(VectorTransformVector)
class OperatingPointVector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.OperatingPointVector_swiginit(self, _swigfaiss.new_OperatingPointVector())

    def push_back(self, arg2):
        return _swigfaiss.OperatingPointVector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.OperatingPointVector_clear(self)

    def data(self):
        return _swigfaiss.OperatingPointVector_data(self)

    def size(self):
        return _swigfaiss.OperatingPointVector_size(self)

    def at(self, n):
        return _swigfaiss.OperatingPointVector_at(self, n)

    def resize(self, n):
        return _swigfaiss.OperatingPointVector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.OperatingPointVector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_OperatingPointVector

# Register OperatingPointVector in _swigfaiss:
_swigfaiss.OperatingPointVector_swigregister(OperatingPointVector)
class InvertedListsPtrVector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.InvertedListsPtrVector_swiginit(self, _swigfaiss.new_InvertedListsPtrVector())

    def push_back(self, arg2):
        return _swigfaiss.InvertedListsPtrVector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.InvertedListsPtrVector_clear(self)

    def data(self):
        return _swigfaiss.InvertedListsPtrVector_data(self)

    def size(self):
        return _swigfaiss.InvertedListsPtrVector_size(self)

    def at(self, n):
        return _swigfaiss.InvertedListsPtrVector_at(self, n)

    def resize(self, n):
        return _swigfaiss.InvertedListsPtrVector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.InvertedListsPtrVector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_InvertedListsPtrVector

# Register InvertedListsPtrVector in _swigfaiss:
_swigfaiss.InvertedListsPtrVector_swigregister(InvertedListsPtrVector)
class RepeatVector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.RepeatVector_swiginit(self, _swigfaiss.new_RepeatVector())

    def push_back(self, arg2):
        return _swigfaiss.RepeatVector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.RepeatVector_clear(self)

    def data(self):
        return _swigfaiss.RepeatVector_data(self)

    def size(self):
        return _swigfaiss.RepeatVector_size(self)

    def at(self, n):
        return _swigfaiss.RepeatVector_at(self, n)

    def resize(self, n):
        return _swigfaiss.RepeatVector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.RepeatVector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_RepeatVector

# Register RepeatVector in _swigfaiss:
_swigfaiss.RepeatVector_swigregister(RepeatVector)
class ClusteringIterationStatsVector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.ClusteringIterationStatsVector_swiginit(self, _swigfaiss.new_ClusteringIterationStatsVector())

    def push_back(self, arg2):
        return _swigfaiss.ClusteringIterationStatsVector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.ClusteringIterationStatsVector_clear(self)

    def data(self):
        return _swigfaiss.ClusteringIterationStatsVector_data(self)

    def size(self):
        return _swigfaiss.ClusteringIterationStatsVector_size(self)

    def at(self, n):
        return _swigfaiss.ClusteringIterationStatsVector_at(self, n)

    def resize(self, n):
        return _swigfaiss.ClusteringIterationStatsVector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.ClusteringIterationStatsVector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_ClusteringIterationStatsVector

# Register ClusteringIterationStatsVector in _swigfaiss:
_swigfaiss.ClusteringIterationStatsVector_swigregister(ClusteringIterationStatsVector)
class ParameterRangeVector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.ParameterRangeVector_swiginit(self, _swigfaiss.new_ParameterRangeVector())

    def push_back(self, arg2):
        return _swigfaiss.ParameterRangeVector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.ParameterRangeVector_clear(self)

    def data(self):
        return _swigfaiss.ParameterRangeVector_data(self)

    def size(self):
        return _swigfaiss.ParameterRangeVector_size(self)

    def at(self, n):
        return _swigfaiss.ParameterRangeVector_at(self, n)

    def resize(self, n):
        return _swigfaiss.ParameterRangeVector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.ParameterRangeVector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_ParameterRangeVector

# Register ParameterRangeVector in _swigfaiss:
_swigfaiss.ParameterRangeVector_swigregister(ParameterRangeVector)
class MaybeOwnedVectorUInt8Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.MaybeOwnedVectorUInt8Vector_swiginit(self, _swigfaiss.new_MaybeOwnedVectorUInt8Vector())

    def push_back(self, arg2):
        return _swigfaiss.MaybeOwnedVectorUInt8Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.MaybeOwnedVectorUInt8Vector_clear(self)

    def data(self):
        return _swigfaiss.MaybeOwnedVectorUInt8Vector_data(self)

    def size(self):
        return _swigfaiss.MaybeOwnedVectorUInt8Vector_size(self)

    def at(self, n):
        return _swigfaiss.MaybeOwnedVectorUInt8Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.MaybeOwnedVectorUInt8Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.MaybeOwnedVectorUInt8Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_MaybeOwnedVectorUInt8Vector

# Register MaybeOwnedVectorUInt8Vector in _swigfaiss:
_swigfaiss.MaybeOwnedVectorUInt8Vector_swigregister(MaybeOwnedVectorUInt8Vector)
class MaybeOwnedVectorInt32Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.MaybeOwnedVectorInt32Vector_swiginit(self, _swigfaiss.new_MaybeOwnedVectorInt32Vector())

    def push_back(self, arg2):
        return _swigfaiss.MaybeOwnedVectorInt32Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.MaybeOwnedVectorInt32Vector_clear(self)

    def data(self):
        return _swigfaiss.MaybeOwnedVectorInt32Vector_data(self)

    def size(self):
        return _swigfaiss.MaybeOwnedVectorInt32Vector_size(self)

    def at(self, n):
        return _swigfaiss.MaybeOwnedVectorInt32Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.MaybeOwnedVectorInt32Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.MaybeOwnedVectorInt32Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_MaybeOwnedVectorInt32Vector

# Register MaybeOwnedVectorInt32Vector in _swigfaiss:
_swigfaiss.MaybeOwnedVectorInt32Vector_swigregister(MaybeOwnedVectorInt32Vector)
class MaybeOwnedVectorFloat32Vector(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _swigfaiss.MaybeOwnedVectorFloat32Vector_swiginit(self, _swigfaiss.new_MaybeOwnedVectorFloat32Vector())

    def push_back(self, arg2):
        return _swigfaiss.MaybeOwnedVectorFloat32Vector_push_back(self, arg2)

    def clear(self):
        return _swigfaiss.MaybeOwnedVectorFloat32Vector_clear(self)

    def data(self):
        return _swigfaiss.MaybeOwnedVectorFloat32Vector_data(self)

    def size(self):
        return _swigfaiss.MaybeOwnedVectorFloat32Vector_size(self)

    def at(self, n):
        return _swigfaiss.MaybeOwnedVectorFloat32Vector_at(self, n)

    def resize(self, n):
        return _swigfaiss.MaybeOwnedVectorFloat32Vector_resize(self, n)

    def swap(self, other):
        return _swigfaiss.MaybeOwnedVectorFloat32Vector_swap(self, other)
    __swig_destroy__ = _swigfaiss.delete_MaybeOwnedVectorFloat32Vector

# Register MaybeOwnedVectorFloat32Vector in _swigfaiss:
_swigfaiss.MaybeOwnedVectorFloat32Vector_swigregister(MaybeOwnedVectorFloat32Vector)

def simd_histogram_8(data, n, min, shift, hist):
    r"""
     low level SIMD histogramming functions  8-bin histogram of (x - min) >> shift
    values outside the range are ignored.
    the data table should be aligned on 32 bytes
    """
    return _swigfaiss.simd_histogram_8(data, n, min, shift, hist)

def simd_histogram_16(data, n, min, shift, hist):
    r"""same for 16-bin histogram"""
    return _swigfaiss.simd_histogram_16(data, n, min, shift, hist)
class PartitionStats(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    bisect_cycles = property(_swigfaiss.PartitionStats_bisect_cycles_get, _swigfaiss.PartitionStats_bisect_cycles_set)
    compress_cycles = property(_swigfaiss.PartitionStats_compress_cycles_get, _swigfaiss.PartitionStats_compress_cycles_set)

    def __init__(self):
        _swigfaiss.PartitionStats_swiginit(self, _swigfaiss.new_PartitionStats())

    def reset(self):
        return _swigfaiss.PartitionStats_reset(self)
    __swig_destroy__ = _swigfaiss.delete_PartitionStats

# Register PartitionStats in _swigfaiss:
_swigfaiss.PartitionStats_swigregister(PartitionStats)

def popcount32(x):
    return _swigfaiss.popcount32(x)

def popcount64(x):
    return _swigfaiss.popcount64(x)

def bitvec_print(b, d):
    return _swigfaiss.bitvec_print(b, d)

def fvecs2bitvecs(x, b, d, n):
    return _swigfaiss.fvecs2bitvecs(x, b, d, n)

def bitvecs2fvecs(b, x, d, n):
    return _swigfaiss.bitvecs2fvecs(b, x, d, n)

def fvec2bitvec(x, b, d):
    return _swigfaiss.fvec2bitvec(x, b, d)

def bitvec_shuffle(n, da, db, order, a, b):
    r"""Shuffle the bits from b(i, j) := a(i, order[j])"""
    return _swigfaiss.bitvec_shuffle(n, da, db, order, a, b)
class BitstringWriter(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    code = property(_swigfaiss.BitstringWriter_code_get, _swigfaiss.BitstringWriter_code_set)
    code_size = property(_swigfaiss.BitstringWriter_code_size_get, _swigfaiss.BitstringWriter_code_size_set)
    i = property(_swigfaiss.BitstringWriter_i_get, _swigfaiss.BitstringWriter_i_set)

    def __init__(self, code, code_size):
        _swigfaiss.BitstringWriter_swiginit(self, _swigfaiss.new_BitstringWriter(code, code_size))

    def write(self, x, nbit):
        return _swigfaiss.BitstringWriter_write(self, x, nbit)
    __swig_destroy__ = _swigfaiss.delete_BitstringWriter

# Register BitstringWriter in _swigfaiss:
_swigfaiss.BitstringWriter_swigregister(BitstringWriter)
cvar = _swigfaiss.cvar

class BitstringReader(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    code = property(_swigfaiss.BitstringReader_code_get, _swigfaiss.BitstringReader_code_set)
    code_size = property(_swigfaiss.BitstringReader_code_size_get, _swigfaiss.BitstringReader_code_size_set)
    i = property(_swigfaiss.BitstringReader_i_get, _swigfaiss.BitstringReader_i_set)

    def __init__(self, code, code_size):
        _swigfaiss.BitstringReader_swiginit(self, _swigfaiss.new_BitstringReader(code, code_size))

    def read(self, nbit):
        return _swigfaiss.BitstringReader_read(self, nbit)
    __swig_destroy__ = _swigfaiss.delete_BitstringReader

# Register BitstringReader in _swigfaiss:
_swigfaiss.BitstringReader_swigregister(BitstringReader)

def hammings(a, b, na, nb, nbytespercode, dis):
    r"""
     Compute a set of Hamming distances between na and nb binary vectors

    :type a: uint8_t
    :param a:             size na * nbytespercode
    :type b: uint8_t
    :param b:             size nb * nbytespercode
    :type nbytespercode: int
    :param nbytespercode: should be multiple of 8
    :type dis: int
    :param dis:           output distances, size na * nb
    """
    return _swigfaiss.hammings(a, b, na, nb, nbytespercode, dis)

def hammings_knn_hc(*args):
    r"""
     Return the k smallest Hamming distances for a set of binary query vectors,
    using a max heap.
    :type a: uint8_t
    :param a:       queries, size ha->nh * ncodes
    :type b: uint8_t
    :param b:       database, size nb * ncodes
    :type nb: int
    :param nb:      number of database vectors
    :type ncodes: int
    :param ncodes:  size of the binary codes (bytes)
    :type ordered: int
    :param ordered: if != 0: order the results by decreasing distance
                       (may be bottleneck for k/n > 0.01)
    :type approx_topk_mode: int, optional
    :param approx_topk_mode: allows to use approximate top-k facilities
                                to speedup heap
    """
    return _swigfaiss.hammings_knn_hc(*args)

def hammings_knn(ha, a, b, nb, ncodes, ordered):
    return _swigfaiss.hammings_knn(ha, a, b, nb, ncodes, ordered)

def hammings_knn_mc(a, b, na, nb, k, ncodes, distances, labels, sel=None):
    r"""
     Return the k smallest Hamming distances for a set of binary query vectors,
    using counting max.
    :type a: uint8_t
    :param a:       queries, size na * ncodes
    :type b: uint8_t
    :param b:       database, size nb * ncodes
    :type na: int
    :param na:      number of query vectors
    :type nb: int
    :param nb:      number of database vectors
    :type k: int
    :param k:       number of vectors/distances to return
    :type ncodes: int
    :param ncodes:  size of the binary codes (bytes)
    :type distances: int
    :param distances: output distances from each query vector to its k nearest
                       neighbors
    :type labels: int
    :param labels:  output ids of the k nearest neighbors to each query vector
    """
    return _swigfaiss.hammings_knn_mc(a, b, na, nb, k, ncodes, distances, labels, sel)

def hamming_range_search(a, b, na, nb, radius, ncodes, result, sel=None):
    r"""same as hammings_knn except we are doing a range search with radius"""
    return _swigfaiss.hamming_range_search(a, b, na, nb, radius, ncodes, result, sel)

def hamming_count_thres(bs1, bs2, n1, n2, ht, ncodes, nptr):
    return _swigfaiss.hamming_count_thres(bs1, bs2, n1, n2, ht, ncodes, nptr)

def match_hamming_thres(bs1, bs2, n1, n2, ht, ncodes, idx, dis):
    return _swigfaiss.match_hamming_thres(bs1, bs2, n1, n2, ht, ncodes, idx, dis)

def crosshamming_count_thres(dbs, n, ht, ncodes, nptr):
    return _swigfaiss.crosshamming_count_thres(dbs, n, ht, ncodes, nptr)

def generalized_hammings_knn_hc(ha, a, b, nb, code_size, ordered=1):
    r"""
    generalized Hamming distances (= count number of code bytes that
       are the same)
    """
    return _swigfaiss.generalized_hammings_knn_hc(ha, a, b, nb, code_size, ordered)

def pack_bitstrings(*args):
    r"""
    *Overload 1:*
     Pack a set of n codes of size M * nbit

    :type n: int
    :param n:           number of codes to pack
    :type M: int
    :param M:           number of elementary codes per code
    :type nbit: int
    :param nbit:        number of bits per elementary code
    :type unpacked: int
    :param unpacked:    input unpacked codes, size (n, M)
    :type packed: uint8_t
    :param packed:      output packed codes, size (n, code_size)
    :type code_size: int
    :param code_size:   should be >= ceil(M * nbit / 8)

    |

    *Overload 2:*
     Pack a set of n codes of variable sizes

    :param nbit:       number of bits per entry (size M)
    """
    return _swigfaiss.pack_bitstrings(*args)

def unpack_bitstrings(*args):
    r"""
    *Overload 1:*
     Unpack a set of n codes of size M * nbit

    :type n: int
    :param n:           number of codes to pack
    :type M: int
    :param M:           number of elementary codes per code
    :type nbit: int
    :param nbit:        number of bits per elementary code
    :type unpacked: int
    :param unpacked:    input unpacked codes, size (n, M)
    :type packed: uint8_t
    :param packed:      output packed codes, size (n, code_size)
    :type code_size: int
    :param code_size:   should be >= ceil(M * nbit / 8)

    |

    *Overload 2:*
     Unpack a set of n codes of variable sizes

    :param nbit:       number of bits per entry (size M)
    """
    return _swigfaiss.unpack_bitstrings(*args)

def generalized_hamming_64(a):
    return _swigfaiss.generalized_hamming_64(a)

def get_num_gpus():
    return _swigfaiss.get_num_gpus()

def gpu_profiler_start():
    return _swigfaiss.gpu_profiler_start()

def gpu_profiler_stop():
    return _swigfaiss.gpu_profiler_stop()

def gpu_sync_all_devices():
    return _swigfaiss.gpu_sync_all_devices()

def get_compile_options():
    r"""get compile options"""
    return _swigfaiss.get_compile_options()

def get_version():
    return _swigfaiss.get_version()

def getmillisecs():
    r"""ms elapsed since some arbitrary epoch"""
    return _swigfaiss.getmillisecs()

def get_mem_usage_kb():
    r"""get current RSS usage in kB"""
    return _swigfaiss.get_mem_usage_kb()

def get_cycles():
    return _swigfaiss.get_cycles()

def reflection(u, x, n, d, nu):
    return _swigfaiss.reflection(u, x, n, d, nu)

def matrix_qr(m, n, a):
    r"""
     compute the Q of the QR decomposition for m > n
    :type a: float
    :param a:   size n * m: input matrix and output Q
    """
    return _swigfaiss.matrix_qr(m, n, a)

def ranklist_handle_ties(k, idx, dis):
    r"""distances are supposed to be sorted. Sorts indices with same distance"""
    return _swigfaiss.ranklist_handle_ties(k, idx, dis)

def ranklist_intersection_size(k1, v1, k2, v2):
    r"""
     count the number of common elements between v1 and v2
    algorithm = sorting + bisection to avoid double-counting duplicates
    """
    return _swigfaiss.ranklist_intersection_size(k1, v1, k2, v2)

def merge_result_table_with(n, k, I0, D0, I1, D1, keep_min=True, translation=0):
    r"""
     merge a result table into another one

    :type I0: int
    :param I0:, D0       first result table, size (n, k)
    :type I1: int
    :param I1:, D1       second result table, size (n, k)
    :type keep_min: boolean, optional
    :param keep_min:     if true, keep min values, otherwise keep max
    :type translation: int, optional
    :param translation:  add this value to all I1's indexes
    :rtype: int
    :return: nb of values that were taken from the second table
    """
    return _swigfaiss.merge_result_table_with(n, k, I0, D0, I1, D1, keep_min, translation)

def imbalance_factor(*args):
    r"""
    *Overload 1:*
    a balanced assignment has a IF of 1, a completely unbalanced assignment has
    an IF = k.

    |

    *Overload 2:*
    same, takes a histogram as input
    """
    return _swigfaiss.imbalance_factor(*args)

def ivec_hist(n, v, vmax, hist):
    r"""compute histogram on v"""
    return _swigfaiss.ivec_hist(n, v, vmax, hist)

def bincode_hist(n, nbits, codes, hist):
    r"""
     Compute histogram of bits on a code array

    :type codes: uint8_t
    :param codes:   size(n, nbits / 8)
    :type hist: int
    :param hist:    size(nbits): nb of 1s in the array of codes
    """
    return _swigfaiss.bincode_hist(n, nbits, codes, hist)

def ivec_checksum(n, a):
    r"""compute a checksum on a table."""
    return _swigfaiss.ivec_checksum(n, a)

def bvec_checksum(n, a):
    r"""compute a checksum on a table."""
    return _swigfaiss.bvec_checksum(n, a)

def bvecs_checksum(n, d, a, cs):
    r"""
     compute checksums for the rows of a matrix

    :type n: int
    :param n:   number of rows
    :type d: int
    :param d:   size per row
    :type a: uint8_t
    :param a:   matrix to handle, size n * d
    :type cs: int
    :param cs:  output checksums, size n
    """
    return _swigfaiss.bvecs_checksum(n, d, a, cs)

def fvecs_maybe_subsample(d, n, nmax, x, verbose=False, seed=1234):
    r"""
     random subsamples a set of vectors if there are too many of them

    :type d: int
    :param d:      dimension of the vectors
    :type n: int
    :param n:      on input: nb of input vectors, output: nb of output vectors
    :type nmax: int
    :param nmax:   max nb of vectors to keep
    :type x: float
    :param x:      input array, size *n-by-d
    :type seed: int, optional
    :param seed:   random seed to use for sampling
    :rtype: float
    :return: x or an array allocated with new [] with *n vectors
    """
    return _swigfaiss.fvecs_maybe_subsample(d, n, nmax, x, verbose, seed)

def binary_to_real(d, x_in, x_out):
    r"""
     Convert binary vector to +1/-1 valued float vector.

    :type d: int
    :param d:      dimension of the vector (multiple of 8)
    :type x_in: uint8_t
    :param x_in:   input binary vector (uint8_t table of size d / 8)
    :type x_out: float
    :param x_out:  output float vector (float table of size d)
    """
    return _swigfaiss.binary_to_real(d, x_in, x_out)

def real_to_binary(d, x_in, x_out):
    r"""
     Convert float vector to binary vector. Components > 0 are converted to 1,
    others to 0.

    :type d: int
    :param d:      dimension of the vector (multiple of 8)
    :type x_in: float
    :param x_in:   input float vector (float table of size d)
    :type x_out: uint8_t
    :param x_out:  output binary vector (uint8_t table of size d / 8)
    """
    return _swigfaiss.real_to_binary(d, x_in, x_out)

def hash_bytes(bytes, n):
    r"""A reasonable hashing function"""
    return _swigfaiss.hash_bytes(bytes, n)

def check_openmp():
    r"""Whether OpenMP annotations were respected."""
    return _swigfaiss.check_openmp()
class CodeSet(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    d = property(_swigfaiss.CodeSet_d_get, _swigfaiss.CodeSet_d_set)
    s = property(_swigfaiss.CodeSet_s_get, _swigfaiss.CodeSet_s_set)

    def __init__(self, d_in):
        _swigfaiss.CodeSet_swiginit(self, _swigfaiss.new_CodeSet(d_in))

    def insert(self, n, codes, inserted):
        return _swigfaiss.CodeSet_insert(self, n, codes, inserted)
    __swig_destroy__ = _swigfaiss.delete_CodeSet

# Register CodeSet in _swigfaiss:
_swigfaiss.CodeSet_swigregister(CodeSet)
hamdis_tab_ham_bytes = cvar.hamdis_tab_ham_bytes

class CombinerRangeKNNfloat(object):
    r"""
     This class is used to combine range and knn search results
    in contrib.exhaustive_search.range_search_gpu
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nq = property(_swigfaiss.CombinerRangeKNNfloat_nq_get, _swigfaiss.CombinerRangeKNNfloat_nq_set)
    k = property(_swigfaiss.CombinerRangeKNNfloat_k_get, _swigfaiss.CombinerRangeKNNfloat_k_set, doc=r"""nb of queries""")
    r2 = property(_swigfaiss.CombinerRangeKNNfloat_r2_get, _swigfaiss.CombinerRangeKNNfloat_r2_set, doc=r"""number of neighbors for the knn search part""")
    keep_max = property(_swigfaiss.CombinerRangeKNNfloat_keep_max_get, _swigfaiss.CombinerRangeKNNfloat_keep_max_set, doc=r"""range search radius""")

    def __init__(self, nq_in, k_in, r2_in, keep_max_in):
        r"""whether to keep max values instead of min."""
        _swigfaiss.CombinerRangeKNNfloat_swiginit(self, _swigfaiss.new_CombinerRangeKNNfloat(nq_in, k_in, r2_in, keep_max_in))
    I = property(_swigfaiss.CombinerRangeKNNfloat_I_get, _swigfaiss.CombinerRangeKNNfloat_I_set, doc=r"""Knn search results""")
    D = property(_swigfaiss.CombinerRangeKNNfloat_D_get, _swigfaiss.CombinerRangeKNNfloat_D_set, doc=r"""size nq * k""")
    mask = property(_swigfaiss.CombinerRangeKNNfloat_mask_get, _swigfaiss.CombinerRangeKNNfloat_mask_set, doc=r"""
    size nq * k
    optional: range search results (ignored if mask is NULL)
    """)
    lim_remain = property(_swigfaiss.CombinerRangeKNNfloat_lim_remain_get, _swigfaiss.CombinerRangeKNNfloat_lim_remain_set, doc=r"""mask for where knn results are valid, size nq""")
    D_remain = property(_swigfaiss.CombinerRangeKNNfloat_D_remain_get, _swigfaiss.CombinerRangeKNNfloat_D_remain_set, doc=r"""size nrange + 1""")
    I_remain = property(_swigfaiss.CombinerRangeKNNfloat_I_remain_get, _swigfaiss.CombinerRangeKNNfloat_I_remain_set, doc=r"""size lim_remain[nrange]""")
    L_res = property(_swigfaiss.CombinerRangeKNNfloat_L_res_get, _swigfaiss.CombinerRangeKNNfloat_L_res_set, doc=r"""size lim_remain[nrange]""")

    def compute_sizes(self, L_res):
        r"""size nq + 1"""
        return _swigfaiss.CombinerRangeKNNfloat_compute_sizes(self, L_res)

    def write_result(self, D_res, I_res):
        r"""
        Phase 2: caller allocates D_res and I_res (size L_res[nq])
        Phase 3: fill in D_res and I_res
        """
        return _swigfaiss.CombinerRangeKNNfloat_write_result(self, D_res, I_res)
    __swig_destroy__ = _swigfaiss.delete_CombinerRangeKNNfloat

# Register CombinerRangeKNNfloat in _swigfaiss:
_swigfaiss.CombinerRangeKNNfloat_swigregister(CombinerRangeKNNfloat)
class CombinerRangeKNNint16(object):
    r"""
     This class is used to combine range and knn search results
    in contrib.exhaustive_search.range_search_gpu
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nq = property(_swigfaiss.CombinerRangeKNNint16_nq_get, _swigfaiss.CombinerRangeKNNint16_nq_set)
    k = property(_swigfaiss.CombinerRangeKNNint16_k_get, _swigfaiss.CombinerRangeKNNint16_k_set, doc=r"""nb of queries""")
    r2 = property(_swigfaiss.CombinerRangeKNNint16_r2_get, _swigfaiss.CombinerRangeKNNint16_r2_set, doc=r"""number of neighbors for the knn search part""")
    keep_max = property(_swigfaiss.CombinerRangeKNNint16_keep_max_get, _swigfaiss.CombinerRangeKNNint16_keep_max_set, doc=r"""range search radius""")

    def __init__(self, nq_in, k_in, r2_in, keep_max_in):
        r"""whether to keep max values instead of min."""
        _swigfaiss.CombinerRangeKNNint16_swiginit(self, _swigfaiss.new_CombinerRangeKNNint16(nq_in, k_in, r2_in, keep_max_in))
    I = property(_swigfaiss.CombinerRangeKNNint16_I_get, _swigfaiss.CombinerRangeKNNint16_I_set, doc=r"""Knn search results""")
    D = property(_swigfaiss.CombinerRangeKNNint16_D_get, _swigfaiss.CombinerRangeKNNint16_D_set, doc=r"""size nq * k""")
    mask = property(_swigfaiss.CombinerRangeKNNint16_mask_get, _swigfaiss.CombinerRangeKNNint16_mask_set, doc=r"""
    size nq * k
    optional: range search results (ignored if mask is NULL)
    """)
    lim_remain = property(_swigfaiss.CombinerRangeKNNint16_lim_remain_get, _swigfaiss.CombinerRangeKNNint16_lim_remain_set, doc=r"""mask for where knn results are valid, size nq""")
    D_remain = property(_swigfaiss.CombinerRangeKNNint16_D_remain_get, _swigfaiss.CombinerRangeKNNint16_D_remain_set, doc=r"""size nrange + 1""")
    I_remain = property(_swigfaiss.CombinerRangeKNNint16_I_remain_get, _swigfaiss.CombinerRangeKNNint16_I_remain_set, doc=r"""size lim_remain[nrange]""")
    L_res = property(_swigfaiss.CombinerRangeKNNint16_L_res_get, _swigfaiss.CombinerRangeKNNint16_L_res_set, doc=r"""size lim_remain[nrange]""")

    def compute_sizes(self, L_res):
        r"""size nq + 1"""
        return _swigfaiss.CombinerRangeKNNint16_compute_sizes(self, L_res)

    def write_result(self, D_res, I_res):
        r"""
        Phase 2: caller allocates D_res and I_res (size L_res[nq])
        Phase 3: fill in D_res and I_res
        """
        return _swigfaiss.CombinerRangeKNNint16_write_result(self, D_res, I_res)
    __swig_destroy__ = _swigfaiss.delete_CombinerRangeKNNint16

# Register CombinerRangeKNNint16 in _swigfaiss:
_swigfaiss.CombinerRangeKNNint16_swigregister(CombinerRangeKNNint16)
SIMDLevel_NONE = _swigfaiss.SIMDLevel_NONE
SIMDLevel_AVX2 = _swigfaiss.SIMDLevel_AVX2
SIMDLevel_AVX512 = _swigfaiss.SIMDLevel_AVX512
SIMDLevel_AVX512_SPR = _swigfaiss.SIMDLevel_AVX512_SPR
SIMDLevel_ARM_NEON = _swigfaiss.SIMDLevel_ARM_NEON
SIMDLevel_ARM_SVE = _swigfaiss.SIMDLevel_ARM_SVE
SIMDLevel_RISCV_RVV = _swigfaiss.SIMDLevel_RISCV_RVV
SIMDLevel_COUNT = _swigfaiss.SIMDLevel_COUNT

def to_string(level):
    r"""Convert SIMDLevel to string. Throws FaissException for invalid level."""
    return _swigfaiss.to_string(level)

def to_simd_level(level_str):
    r"""Parse string to SIMDLevel. Throws FaissException for invalid strings."""
    return _swigfaiss.to_simd_level(level_str)
class SIMDConfig(object):
    r"""
    Current SIMD configuration.

    This class provides a uniform API for querying and setting the SIMD level,
    regardless of whether faiss was built with Dynamic Dispatch (DD) or static
    SIMD selection.

    In DD mode:
      - get_level() returns the runtime-detected or user-set level
      - set_level() changes the runtime level (if level is supported)
      - supported_simd_levels() returns bitmask of all compiled-in levels

    In static mode:
      - get_level() returns the compiled-in level
      - set_level() succeeds only if level matches compiled-in level
      - supported_simd_levels() returns bitmask with single level
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    level = property(_swigfaiss.SIMDConfig_level_get, _swigfaiss.SIMDConfig_level_set)
    supported_simd_levels = property(_swigfaiss.SIMDConfig_supported_simd_levels_get, _swigfaiss.SIMDConfig_supported_simd_levels_set, doc=r"""Returns bitmask of supported SIMD levels (1 << SIMDLevel).""")

    @staticmethod
    def auto_detect_simd_level():
        return _swigfaiss.SIMDConfig_auto_detect_simd_level()

    def __init__(self, faiss_simd_level_env=None):
        _swigfaiss.SIMDConfig_swiginit(self, _swigfaiss.new_SIMDConfig(faiss_simd_level_env))

    @staticmethod
    def set_level(level):
        r"""Set the SIMD level. Throws FaissException if level is not supported."""
        return _swigfaiss.SIMDConfig_set_level(level)

    @staticmethod
    def get_level():
        return _swigfaiss.SIMDConfig_get_level()

    @staticmethod
    def get_level_name():
        return _swigfaiss.SIMDConfig_get_level_name()

    @staticmethod
    def is_simd_level_available(level):
        r"""Check if a SIMD level is available (compiled in)."""
        return _swigfaiss.SIMDConfig_is_simd_level_available(level)

    @staticmethod
    def get_dispatched_level():
        r"""
        Returns the SIMD level via the dispatch mechanism.
        In DD mode, uses with_simd_level internally.
        In static mode, returns the compiled-in level.
        Useful for verification: get_level() == get_dispatched_level()
        """
        return _swigfaiss.SIMDConfig_get_dispatched_level()
    __swig_destroy__ = _swigfaiss.delete_SIMDConfig

# Register SIMDConfig in _swigfaiss:
_swigfaiss.SIMDConfig_swigregister(SIMDConfig)
SINGLE_SIMD_LEVEL = cvar.SINGLE_SIMD_LEVEL
SINGLE_SIMD_LEVEL_256 = cvar.SINGLE_SIMD_LEVEL_256
SINGLE_SIMD_LEVEL_512 = cvar.SINGLE_SIMD_LEVEL_512


def fvec_L2sqr(x, y, d):
    r"""Squared L2 distance between two vectors"""
    return _swigfaiss.fvec_L2sqr(x, y, d)

def fvec_inner_product(x, y, d):
    r"""inner product"""
    return _swigfaiss.fvec_inner_product(x, y, d)

def fvec_L1(x, y, d):
    r"""L1 distance"""
    return _swigfaiss.fvec_L1(x, y, d)

def fvec_Linf(x, y, d):
    r"""infinity distance"""
    return _swigfaiss.fvec_Linf(x, y, d)

def fvec_inner_product_batch_4(x, y0, y1, y2, y3, d, dis0, dis1, dis2, dis3):
    r"""
    Special version of inner product that computes 4 distances
    between x and yi, which is performance oriented.
    """
    return _swigfaiss.fvec_inner_product_batch_4(x, y0, y1, y2, y3, d, dis0, dis1, dis2, dis3)

def fvec_L2sqr_batch_4(x, y0, y1, y2, y3, d, dis0, dis1, dis2, dis3):
    r"""
    Special version of L2sqr that computes 4 distances
    between x and yi, which is performance oriented.
    """
    return _swigfaiss.fvec_L2sqr_batch_4(x, y0, y1, y2, y3, d, dis0, dis1, dis2, dis3)

def pairwise_L2sqr(d, nq, xq, nb, xb, dis, ldq=-1, ldb=-1, ldd=-1):
    r"""
     Compute pairwise distances between sets of vectors

    :type d: int
    :param d:     dimension of the vectors
    :type nq: int
    :param nq:    nb of query vectors
    :type nb: int
    :param nb:    nb of database vectors
    :type xq: float
    :param xq:    query vectors (size nq * d)
    :type xb: float
    :param xb:    database vectors (size nb * d)
    :type dis: float
    :param dis:   output distances (size nq * nb)
    :param ldq,ldb:, ldd strides for the matrices
    """
    return _swigfaiss.pairwise_L2sqr(d, nq, xq, nb, xb, dis, ldq, ldb, ldd)

def fvec_inner_products_ny(ip, x, y, d, ny):
    return _swigfaiss.fvec_inner_products_ny(ip, x, y, d, ny)

def fvec_L2sqr_ny(dis, x, y, d, ny):
    return _swigfaiss.fvec_L2sqr_ny(dis, x, y, d, ny)

def fvec_L2sqr_ny_transposed(dis, x, y, y_sqlen, d, d_offset, ny):
    return _swigfaiss.fvec_L2sqr_ny_transposed(dis, x, y, y_sqlen, d, d_offset, ny)

def fvec_L2sqr_ny_nearest(distances_tmp_buffer, x, y, d, ny):
    return _swigfaiss.fvec_L2sqr_ny_nearest(distances_tmp_buffer, x, y, d, ny)

def fvec_L2sqr_ny_nearest_y_transposed(distances_tmp_buffer, x, y, y_sqlen, d, d_offset, ny):
    return _swigfaiss.fvec_L2sqr_ny_nearest_y_transposed(distances_tmp_buffer, x, y, y_sqlen, d, d_offset, ny)

def fvec_norm_L2sqr(x, d):
    r"""squared norm of a vector"""
    return _swigfaiss.fvec_norm_L2sqr(x, d)

def fvec_norms_L2(norms, x, d, nx):
    r"""
     compute the L2 norms for a set of vectors

    :type norms: float
    :param norms:    output norms, size nx
    :type x: float
    :param x:        set of vectors, size nx * d
    """
    return _swigfaiss.fvec_norms_L2(norms, x, d, nx)

def fvec_norms_L2sqr(norms, x, d, nx):
    r"""same as fvec_norms_L2, but computes squared norms"""
    return _swigfaiss.fvec_norms_L2sqr(norms, x, d, nx)

def fvec_renorm_L2(d, nx, x):
    return _swigfaiss.fvec_renorm_L2(d, nx, x)

def inner_product_to_L2sqr(dis, nr1, nr2, n1, n2):
    return _swigfaiss.inner_product_to_L2sqr(dis, nr1, nr2, n1, n2)

def fvec_add(*args):
    r"""
    *Overload 1:*
     compute c := a + b for vectors

    c and a can overlap, c and b can overlap

    :type a: float
    :param a: size d
    :type b: float
    :param b: size d
    :type c: float
    :param c: size d

    |

    *Overload 2:*
     compute c := a + b for a, c vectors and b a scalar

    c and a can overlap

    :type a: float
    :param a: size d
    :type c: float
    :param c: size d
    """
    return _swigfaiss.fvec_add(*args)

def fvec_sub(d, a, b, c):
    r"""
     compute c := a - b for vectors

    c and a can overlap, c and b can overlap

    :type a: float
    :param a: size d
    :type b: float
    :param b: size d
    :type c: float
    :param c: size d
    """
    return _swigfaiss.fvec_sub(d, a, b, c)

def fvec_inner_products_by_idx(ip, x, y, ids, d, nx, ny):
    r"""
     compute the inner product between x and a subset y of ny vectors defined by
    ids

    ip(i, j) = inner_product(x(i, :), y(ids(i, j), :))

    :type ip: float
    :param ip:    output array, size nx * ny
    :type x: float
    :param x:     first-term vector, size nx * d
    :type y: float
    :param y:     second-term vector, size (max(ids) + 1) * d
    :type ids: int
    :param ids:   ids to sample from y, size nx * ny
    """
    return _swigfaiss.fvec_inner_products_by_idx(ip, x, y, ids, d, nx, ny)

def fvec_L2sqr_by_idx(dis, x, y, ids, d, nx, ny):
    r"""
     compute the squared L2 distances between x and a subset y of ny vectors
    defined by ids

    dis(i, j) = inner_product(x(i, :), y(ids(i, j), :))

    :type dis: float
    :param dis:   output array, size nx * ny
    :type x: float
    :param x:     first-term vector, size nx * d
    :type y: float
    :param y:     second-term vector, size (max(ids) + 1) * d
    :type ids: int
    :param ids:   ids to sample from y, size nx * ny
    """
    return _swigfaiss.fvec_L2sqr_by_idx(dis, x, y, ids, d, nx, ny)

def pairwise_indexed_L2sqr(d, n, x, ix, y, iy, dis):
    r"""
     compute dis[j] = L2sqr(x[ix[j]], y[iy[j]]) forall j=0..n-1

    :type x: float
    :param x:  size (max(ix) + 1, d)
    :type y: float
    :param y:  size (max(iy) + 1, d)
    :type ix: int
    :param ix: size n
    :type iy: int
    :param iy: size n
    :type dis: float
    :param dis: size n
    """
    return _swigfaiss.pairwise_indexed_L2sqr(d, n, x, ix, y, iy, dis)

def pairwise_indexed_inner_product(d, n, x, ix, y, iy, dis):
    r"""
     compute dis[j] = inner_product(x[ix[j]], y[iy[j]]) forall j=0..n-1

    :type x: float
    :param x:  size (max(ix) + 1, d)
    :type y: float
    :param y:  size (max(iy) + 1, d)
    :type ix: int
    :param ix: size n
    :type iy: int
    :param iy: size n
    :type dis: float
    :param dis: size n
    """
    return _swigfaiss.pairwise_indexed_inner_product(d, n, x, ix, y, iy, dis)

def knn_inner_product(*args):
    r"""
    *Overload 1:*
     Return the k nearest neighbors of each of the nx vectors x among the ny
     vector y, w.r.t to max inner product.

    :type x: float
    :param x:    query vectors, size nx * d
    :type y: float
    :param y:    database vectors, size ny * d
    :type res: :py:class:`float_minheap_array_t`
    :param res:  result heap structure, which also provides k. Sorted on output

    |

    *Overload 2:*
      Return the k nearest neighbors of each of the nx vectors x among the ny
     vector y, for the inner product metric.

    :type x: float
    :param x:    query vectors, size nx * d
    :type y: float
    :param y:    database vectors, size ny * d
    :type distances: float
    :param distances:  output distances, size nq * k
    :type indexes: int
    :param indexes:    output vector ids, size nq * k

    |

    *Overload 3:*
      Return the k nearest neighbors of each of the nx vectors x among the ny
     vector y, for the inner product metric.

    :type x: float
    :param x:    query vectors, size nx * d
    :type y: float
    :param y:    database vectors, size ny * d
    :type distances: float
    :param distances:  output distances, size nq * k
    :type indexes: int
    :param indexes:    output vector ids, size nq * k
    """
    return _swigfaiss.knn_inner_product(*args)

def knn_L2sqr(*args):
    r"""
    *Overload 1:*
     Return the k nearest neighbors of each of the nx vectors x among the ny
     vector y, for the L2 distance
    :type x: float
    :param x:    query vectors, size nx * d
    :type y: float
    :param y:    database vectors, size ny * d
    :type res: :py:class:`float_maxheap_array_t`
    :param res:  result heap structure, which also provides k. Sorted on output
    :type y_norm2: float, optional
    :param y_norm2:    (optional) norms for the y vectors (nullptr or size ny)
    :type sel: :py:class:`IDSelector`, optional
    :param sel:  search in this subset of vectors

    |

    *Overload 2:*
      Return the k nearest neighbors of each of the nx vectors x among the ny
     vector y, for the L2 distance

    :type x: float
    :param x:    query vectors, size nx * d
    :type y: float
    :param y:    database vectors, size ny * d
    :type distances: float
    :param distances:  output distances, size nq * k
    :type indexes: int
    :param indexes:    output vector ids, size nq * k
    :type y_norm2: float, optional
    :param y_norm2:    (optional) norms for the y vectors (nullptr or size ny)
    :type sel: :py:class:`IDSelector`, optional
    :param sel:  search in this subset of vectors

    |

    *Overload 3:*
      Return the k nearest neighbors of each of the nx vectors x among the ny
     vector y, for the L2 distance

    :type x: float
    :param x:    query vectors, size nx * d
    :type y: float
    :param y:    database vectors, size ny * d
    :type distances: float
    :param distances:  output distances, size nq * k
    :type indexes: int
    :param indexes:    output vector ids, size nq * k
    :type y_norm2: float, optional
    :param y_norm2:    (optional) norms for the y vectors (nullptr or size ny)
    :param sel:  search in this subset of vectors

    |

    *Overload 4:*
      Return the k nearest neighbors of each of the nx vectors x among the ny
     vector y, for the L2 distance

    :type x: float
    :param x:    query vectors, size nx * d
    :type y: float
    :param y:    database vectors, size ny * d
    :type distances: float
    :param distances:  output distances, size nq * k
    :type indexes: int
    :param indexes:    output vector ids, size nq * k
    :param y_norm2:    (optional) norms for the y vectors (nullptr or size ny)
    :param sel:  search in this subset of vectors
    """
    return _swigfaiss.knn_L2sqr(*args)

def knn_inner_products_by_idx(x, y, subset, d, nx, ny, nsubset, k, vals, ids, ld_ids=-1):
    r"""
     Find the max inner product neighbors for nx queries in a set of ny vectors
    indexed by ids. May be useful for re-ranking a pre-selected vector list

    :type x: float
    :param x:    query vectors, size nx * d
    :type y: float
    :param y:    database vectors, size (max(ids) + 1) * d
    :type ids: int
    :param ids:  subset of database vectors to consider, size (nx, nsubset)
    :param res:  result structure
    :type ld_ids: int, optional
    :param ld_ids: stride for the ids array. -1: use nsubset, 0: all queries
        process the same subset
    """
    return _swigfaiss.knn_inner_products_by_idx(x, y, subset, d, nx, ny, nsubset, k, vals, ids, ld_ids)

def knn_L2sqr_by_idx(x, y, subset, d, nx, ny, nsubset, k, vals, ids, ld_subset=-1):
    r"""
     Find the nearest neighbors for nx queries in a set of ny vectors
    indexed by ids. May be useful for re-ranking a pre-selected vector list

    :type x: float
    :param x:    query vectors, size nx * d
    :type y: float
    :param y:    database vectors, size (max(ids) + 1) * d
    :type subset: int
    :param subset: subset of database vectors to consider, size (nx, nsubset)
    :param res:  result structure
    :type ld_subset: int, optional
    :param ld_subset: stride for the subset array. -1: use nsubset, 0: all queries
        process the same subset
    """
    return _swigfaiss.knn_L2sqr_by_idx(x, y, subset, d, nx, ny, nsubset, k, vals, ids, ld_subset)

def range_search_L2sqr(x, y, d, nx, ny, radius, result, sel=None):
    r"""
     Return the k nearest neighbors of each of the nx vectors x among the ny
     vector y, w.r.t to max inner product

    :type x: float
    :param x:      query vectors, size nx * d
    :type y: float
    :param y:      database vectors, size ny * d
    :type radius: float
    :param radius: search radius around the x vectors
    :type result: :py:class:`RangeSearchResult`
    :param result: result structure
    """
    return _swigfaiss.range_search_L2sqr(x, y, d, nx, ny, radius, result, sel)

def range_search_inner_product(x, y, d, nx, ny, radius, result, sel=None):
    r"""same as range_search_L2sqr for the inner product similarity"""
    return _swigfaiss.range_search_inner_product(x, y, d, nx, ny, radius, result, sel)

def compute_PQ_dis_tables_dsub2(d, ksub, centroids, nx, x, is_inner_product, dis_tables):
    r"""specialized function for PQ2"""
    return _swigfaiss.compute_PQ_dis_tables_dsub2(d, ksub, centroids, nx, x, is_inner_product, dis_tables)

def fvec_madd(n, a, bf, b, c):
    r"""
     compute c := a + bf * b for a, b and c tables

    :type n: int
    :param n:   size of the tables
    :type a: float
    :param a:   size n
    :type b: float
    :param b:   size n
    :type c: float
    :param c:   result table, size n
    """
    return _swigfaiss.fvec_madd(n, a, bf, b, c)

def fvec_madd_and_argmin(n, a, bf, b, c):
    r"""
     same as fvec_madd, also return index of the min of the result table
    :rtype: int
    :return: index of the min of table c
    """
    return _swigfaiss.fvec_madd_and_argmin(n, a, bf, b, c)
class RandomGenerator(object):
    r"""random generator that can be used in multithreaded contexts"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    mt = property(_swigfaiss.RandomGenerator_mt_get, _swigfaiss.RandomGenerator_mt_set)

    def rand_int64(self):
        r"""random int64_t"""
        return _swigfaiss.RandomGenerator_rand_int64(self)

    def rand_int(self, *args):
        r"""
        *Overload 1:*
        random positive integer

        |

        *Overload 2:*
        generate random integer between 0 and max-1
        """
        return _swigfaiss.RandomGenerator_rand_int(self, *args)

    def rand_float(self):
        r"""between 0 and 1"""
        return _swigfaiss.RandomGenerator_rand_float(self)

    def rand_double(self):
        return _swigfaiss.RandomGenerator_rand_double(self)

    def __init__(self, seed=1234):
        _swigfaiss.RandomGenerator_swiginit(self, _swigfaiss.new_RandomGenerator(seed))
    __swig_destroy__ = _swigfaiss.delete_RandomGenerator

# Register RandomGenerator in _swigfaiss:
_swigfaiss.RandomGenerator_swigregister(RandomGenerator)
class SplitMix64RandomGenerator(object):
    r"""
    fast random generator that cannot be used in multithreaded contexts.
    based on https://prng.di.unimi.it/
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    state = property(_swigfaiss.SplitMix64RandomGenerator_state_get, _swigfaiss.SplitMix64RandomGenerator_state_set)

    def rand_int64(self):
        r"""random int64_t"""
        return _swigfaiss.SplitMix64RandomGenerator_rand_int64(self)

    def rand_int(self, *args):
        r"""
        *Overload 1:*
        random positive integer

        |

        *Overload 2:*
        generate random integer between 0 and max-1
        """
        return _swigfaiss.SplitMix64RandomGenerator_rand_int(self, *args)

    def rand_float(self):
        r"""between 0 and 1"""
        return _swigfaiss.SplitMix64RandomGenerator_rand_float(self)

    def rand_double(self):
        return _swigfaiss.SplitMix64RandomGenerator_rand_double(self)

    def __init__(self, seed=1234):
        _swigfaiss.SplitMix64RandomGenerator_swiginit(self, _swigfaiss.new_SplitMix64RandomGenerator(seed))

    def next(self):
        return _swigfaiss.SplitMix64RandomGenerator_next(self)
    __swig_destroy__ = _swigfaiss.delete_SplitMix64RandomGenerator

# Register SplitMix64RandomGenerator in _swigfaiss:
_swigfaiss.SplitMix64RandomGenerator_swigregister(SplitMix64RandomGenerator)

def float_rand(x, n, seed):
    return _swigfaiss.float_rand(x, n, seed)

def float_randn(x, n, seed):
    return _swigfaiss.float_randn(x, n, seed)

def int64_rand(x, n, seed):
    return _swigfaiss.int64_rand(x, n, seed)

def byte_rand(x, n, seed):
    return _swigfaiss.byte_rand(x, n, seed)

def int64_rand_max(x, n, max, seed):
    return _swigfaiss.int64_rand_max(x, n, max, seed)

def rand_perm(perm, n, seed):
    return _swigfaiss.rand_perm(perm, n, seed)

def rand_perm_splitmix64(perm, n, seed):
    return _swigfaiss.rand_perm_splitmix64(perm, n, seed)

def rand_smooth_vectors(n, d, x, seed):
    return _swigfaiss.rand_smooth_vectors(n, d, x, seed)

def fvec_argsort(n, vals, perm):
    r"""
     Indirect sort of a floating-point array

    :type n: int
    :param n:     size of the array
    :type vals: float
    :param vals:  array to sort, size n
    :type perm: int
    :param perm:  output: permutation of [0..n-1], st.
                     vals[perm[i + 1]] >= vals[perm[i]]
    """
    return _swigfaiss.fvec_argsort(n, vals, perm)

def fvec_argsort_parallel(n, vals, perm):
    r"""Same as fvec_argsort, parallelized"""
    return _swigfaiss.fvec_argsort_parallel(n, vals, perm)

def bucket_sort(nval, vals, nbucket, lims, perm, nt=0):
    r"""
     Bucket sort of a list of values

    :type vals: int
    :param vals:     values to sort, size nval, max value nbucket - 1
    :type lims: int
    :param lims:     output limits of buckets, size nbucket + 1
    :type perm: int
    :param perm:     output buckets, the elements of bucket
                        i are in perm[lims[i]:lims[i + 1]]
    :type nt: int, optional
    :param nt:       number of threads (0 = pure sequential code)
    """
    return _swigfaiss.bucket_sort(nval, vals, nbucket, lims, perm, nt)

def matrix_bucket_sort_inplace(*args):
    r"""
    *Overload 1:*
     in-place bucket sort (with attention to memory=>int32)
    on input the values are in a nrow * col matrix
    we want to store the row numbers in the output.

    :type vals: int
    :param vals:     positive values to sort, size nrow * ncol,
                        max value nbucket - 1
    :type lims: int
    :param lims:     output limits of buckets, size nbucket + 1
    :type nt: int, optional
    :param nt:       number of threads (0 = pure sequential code)

    |

    *Overload 2:*
     same with int64 elements

    |

    *Overload 3:*
     same with int64 elements
    """
    return _swigfaiss.matrix_bucket_sort_inplace(*args)

def hashtable_int64_to_int64_init(log2_capacity, tab):
    r"""
     Hashtable implementation for int64 -> int64 with external storage
    implemented for fast batch add and lookup.

    tab is of size  2 * (1 << log2_capacity)
    n is the number of elements to add or search

    adding several values in a same batch: an arbitrary one gets added
    in different batches: the newer batch overwrites.
    raises an exception if capacity is exhausted.
    """
    return _swigfaiss.hashtable_int64_to_int64_init(log2_capacity, tab)

def hashtable_int64_to_int64_add(log2_capacity, tab, n, keys, vals):
    return _swigfaiss.hashtable_int64_to_int64_add(log2_capacity, tab, n, keys, vals)

def hashtable_int64_to_int64_lookup(log2_capacity, tab, n, keys, vals):
    return _swigfaiss.hashtable_int64_to_int64_lookup(log2_capacity, tab, n, keys, vals)
METRIC_INNER_PRODUCT = _swigfaiss.METRIC_INNER_PRODUCT
r"""maximum inner product search"""
METRIC_L2 = _swigfaiss.METRIC_L2
r"""squared L2 search"""
METRIC_L1 = _swigfaiss.METRIC_L1
r"""L1 (aka cityblock)"""
METRIC_Linf = _swigfaiss.METRIC_Linf
r"""infinity distance"""
METRIC_Lp = _swigfaiss.METRIC_Lp
r"""L_p distance, p is given by a faiss::Index"""
METRIC_Canberra = _swigfaiss.METRIC_Canberra
r"""
    metric_arg
    some additional metrics defined in scipy.spatial.distance
    """
METRIC_BrayCurtis = _swigfaiss.METRIC_BrayCurtis
METRIC_JensenShannon = _swigfaiss.METRIC_JensenShannon
METRIC_Jaccard = _swigfaiss.METRIC_Jaccard
r"""sum_i(min(a_i, b_i)) / sum_i(max(a_i, b_i)) where a_i, b_i > 0"""
METRIC_NaNEuclidean = _swigfaiss.METRIC_NaNEuclidean
r"""Squared Euclidean distance, ignoring NaNs"""
METRIC_GOWER = _swigfaiss.METRIC_GOWER
r"""
    Gower's distance - numeric dimensions are in [0,1] and categorical
    dimensions are negative integers
    """

def is_similarity_metric(metric_type):
    r"""
    this function is used to distinguish between min and max indexes since
    we need to support similarity and dis-similarity metrics in a flexible way
    """
    return _swigfaiss.is_similarity_metric(metric_type)

def metric_type_from_int(x):
    r"""
    Convert an integer to MetricType with range validation.
    Throws FaissException if the value is not a valid MetricType.
    """
    return _swigfaiss.metric_type_from_int(x)

def metric_type_count():
    r"""Count of entries in the MetricType enum."""
    return _swigfaiss.metric_type_count()
FAISS_VERSION_MAJOR = _swigfaiss.FAISS_VERSION_MAJOR
FAISS_VERSION_MINOR = _swigfaiss.FAISS_VERSION_MINOR
FAISS_VERSION_PATCH = _swigfaiss.FAISS_VERSION_PATCH
VERSION_STRING = _swigfaiss.VERSION_STRING
Float32 = _swigfaiss.Float32
Float16 = _swigfaiss.Float16
UInt8 = _swigfaiss.UInt8
Int8 = _swigfaiss.Int8

def get_numeric_type_size(numeric_type):
    return _swigfaiss.get_numeric_type_size(numeric_type)
class SearchParameters(object):
    r"""
     Parent class for the optional search parameters.

    Sub-classes with additional search parameters should inherit this class.
    Ownership of the object fields is always to the caller.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    sel = property(_swigfaiss.SearchParameters_sel_get, _swigfaiss.SearchParameters_sel_set, doc=r"""if non-null, only these IDs will be considered during search.""")
    __swig_destroy__ = _swigfaiss.delete_SearchParameters

    def __init__(self):
        _swigfaiss.SearchParameters_swiginit(self, _swigfaiss.new_SearchParameters())

# Register SearchParameters in _swigfaiss:
_swigfaiss.SearchParameters_swigregister(SearchParameters)
class Index(object):
    r"""
     Abstract structure for an index, supports adding vectors and searching
    them.

    All vectors provided at add or search time are 32-bit float arrays,
    although the internal representation may vary.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    d = property(_swigfaiss.Index_d_get, _swigfaiss.Index_d_set, doc=r"""vector dimension""")
    ntotal = property(_swigfaiss.Index_ntotal_get, _swigfaiss.Index_ntotal_set, doc=r"""total nb of indexed vectors""")
    verbose = property(_swigfaiss.Index_verbose_get, _swigfaiss.Index_verbose_set, doc=r"""verbosity level""")
    is_trained = property(_swigfaiss.Index_is_trained_get, _swigfaiss.Index_is_trained_set, doc=r"""
    set if the Index does not require training, or if training is
    done already
    """)
    metric_type = property(_swigfaiss.Index_metric_type_get, _swigfaiss.Index_metric_type_set, doc=r"""type of metric this index uses for search""")
    metric_arg = property(_swigfaiss.Index_metric_arg_get, _swigfaiss.Index_metric_arg_set, doc=r"""argument of the metric type""")
    __swig_destroy__ = _swigfaiss.delete_Index

    def train(self, n, x):
        r"""
         Perform training on a representative set of vectors

        :type n: int
        :param n:      nb of training vectors
        :type x: float
        :param x:      training vectors, size n * d
        """
        return _swigfaiss.Index_train(self, n, x)

    def train_with_queries(self, n, x, n_train_q, xq_train):
        r"""
         Perform training on a representative set of vectors and a representative
        set of queries

        :type n: int
        :param n:         nb of training vectors
        :type x: float
        :param x:         training vectors, size n * d
        :type n_train_q: int
        :param n_train_q: nb of training queries
        :type xq_train: float
        :param xq_train:  training queries, size n_train_q * d
        """
        return _swigfaiss.Index_train_with_queries(self, n, x, n_train_q, xq_train)

    def train_ex(self, n, x, numeric_type):
        return _swigfaiss.Index_train_ex(self, n, x, numeric_type)

    def add(self, n, x):
        r"""
         Add n vectors of dimension d to the index.

        Vectors are implicitly assigned labels ntotal .. ntotal + n - 1
        This function slices the input vectors in chunks smaller than
        blocksize_add and calls add_core.
        :type n: int
        :param n:      number of vectors
        :type x: float
        :param x:      input matrix, size n * d
        """
        return _swigfaiss.Index_add(self, n, x)

    def add_ex(self, n, x, numeric_type):
        return _swigfaiss.Index_add_ex(self, n, x, numeric_type)

    def add_with_ids(self, n, x, xids):
        r"""
         Same as add, but stores xids instead of sequential ids.

        The default implementation fails with an assertion, as it is
        not supported by all indexes.

        :type n: int
        :param n:         number of vectors
        :type x: float
        :param x:         input vectors, size n * d
        :type xids: int
        :param xids:      if non-null, ids to store for the vectors (size n)
        """
        return _swigfaiss.Index_add_with_ids(self, n, x, xids)

    def add_with_ids_ex(self, n, x, numeric_type, xids):
        return _swigfaiss.Index_add_with_ids_ex(self, n, x, numeric_type, xids)

    def search(self, n, x, k, distances, labels, params=None):
        r"""
         query n vectors of dimension d to the index.

        return at most k vectors. If there are not enough results for a
        query, the result array is padded with -1s.

        :type n: int
        :param n:           number of vectors
        :type x: float
        :param x:           input vectors to search, size n * d
        :type k: int
        :param k:           number of extracted vectors
        :type distances: float
        :param distances:   output pairwise distances, size n*k
        :type labels: int
        :param labels:      output labels of the NNs, size n*k
        """
        return _swigfaiss.Index_search(self, n, x, k, distances, labels, params)

    def search_ex(self, n, x, numeric_type, k, distances, labels, params=None):
        return _swigfaiss.Index_search_ex(self, n, x, numeric_type, k, distances, labels, params)

    def search1(self, x, handler, params=None):
        r"""search one vector with a custom result handler"""
        return _swigfaiss.Index_search1(self, x, handler, params)

    def range_search(self, n, x, radius, result, params=None):
        r"""
         query n vectors of dimension d to the index.

        return all vectors with distance < radius. Note that many
        indexes do not implement the range_search (only the k-NN search
        is mandatory).

        :type n: int
        :param n:           number of vectors
        :type x: float
        :param x:           input vectors to search, size n * d
        :type radius: float
        :param radius:      search radius
        :type result: :py:class:`RangeSearchResult`
        :param result:      result table
        """
        return _swigfaiss.Index_range_search(self, n, x, radius, result, params)

    def assign(self, n, x, labels, k=1):
        r"""
         return the indexes of the k vectors closest to the query x.

        This function is identical as search but only return labels of
        neighbors.
        :type n: int
        :param n:           number of vectors
        :type x: float
        :param x:           input vectors to search, size n * d
        :type labels: int
        :param labels:      output labels of the NNs, size n*k
        :type k: int, optional
        :param k:           number of nearest neighbours
        """
        return _swigfaiss.Index_assign(self, n, x, labels, k)

    def reset(self):
        r"""removes all elements from the database."""
        return _swigfaiss.Index_reset(self)

    def remove_ids(self, sel):
        r"""
         removes IDs from the index. Not supported by all
        indexes. Returns the number of elements removed.
        """
        return _swigfaiss.Index_remove_ids(self, sel)

    def reconstruct(self, key, recons):
        r"""
         Reconstruct a stored vector (or an approximation if lossy coding)

        this function may not be defined for some indexes
        :type key: int
        :param key:         id of the vector to reconstruct
        :type recons: float
        :param recons:      reconstructed vector (size d)
        """
        return _swigfaiss.Index_reconstruct(self, key, recons)

    def reconstruct_batch(self, n, keys, recons):
        r"""
         Reconstruct several stored vectors (or an approximation if lossy
        coding)

        this function may not be defined for some indexes
        :type n: int
        :param n:           number of vectors to reconstruct
        :type keys: int
        :param keys:        ids of the vectors to reconstruct (size n)
        :type recons: float
        :param recons:      reconstructed vector (size n * d)
        """
        return _swigfaiss.Index_reconstruct_batch(self, n, keys, recons)

    def reconstruct_n(self, i0, ni, recons):
        r"""
         Reconstruct vectors i0 to i0 + ni - 1

        this function may not be defined for some indexes
        :type i0: int
        :param i0:          index of the first vector in the sequence
        :type ni: int
        :param ni:          number of vectors in the sequence
        :type recons: float
        :param recons:      reconstructed vector (size ni * d)
        """
        return _swigfaiss.Index_reconstruct_n(self, i0, ni, recons)

    def search_and_reconstruct(self, n, x, k, distances, labels, recons, params=None):
        r"""
         Similar to search, but also reconstructs the stored vectors (or an
        approximation in the case of lossy coding) for the search results.

        If there are not enough results for a query, the resulting arrays
        is padded with -1s.

        :type n: int
        :param n:           number of vectors
        :type x: float
        :param x:           input vectors to search, size n * d
        :type k: int
        :param k:           number of extracted vectors
        :type distances: float
        :param distances:   output pairwise distances, size n*k
        :type labels: int
        :param labels:      output labels of the NNs, size n*k
        :type recons: float
        :param recons:      reconstructed vectors size (n, k, d)
        """
        return _swigfaiss.Index_search_and_reconstruct(self, n, x, k, distances, labels, recons, params)

    def search_subset(self, n, x, k_base, base_labels, k, distances, labels):
        r"""
         Similar to search, but operates on a potentially different subset
        of the dataset for each query.

        The default implementation fails with an assertion, as it is
        not supported by all indexes.

        :type n: int
        :param n:           number of vectors
        :type x: float
        :param x:           input vectors, size n * d
        :type k_base: int
        :param k_base:      number of vectors to search from
        :type base_labels: int
        :param base_labels: ids of the vectors to search from
        :type k: int
        :param k:           desired number of results per query
        :type distances: float
        :param distances:   output pairwise distances, size n*k
        :type labels: int
        :param labels:      output labels of the NNs, size n*k
        """
        return _swigfaiss.Index_search_subset(self, n, x, k_base, base_labels, k, distances, labels)

    def compute_residual(self, x, residual, key):
        r"""
         Computes a residual vector after indexing encoding.

        The residual vector is the difference between a vector and the
        reconstruction that can be decoded from its representation in
        the index. The residual can be used for multiple-stage indexing
        methods, like IndexIVF's methods.

        :type x: float
        :param x:           input vector, size d
        :type residual: float
        :param residual:    output residual vector, size d
        :type key: int
        :param key:         encoded index, as returned by search and assign
        """
        return _swigfaiss.Index_compute_residual(self, x, residual, key)

    def compute_residual_n(self, n, xs, residuals, keys):
        r"""
         Computes a residual vector after indexing encoding (batch form).
        Equivalent to calling compute_residual for each vector.

        The residual vector is the difference between a vector and the
        reconstruction that can be decoded from its representation in
        the index. The residual can be used for multiple-stage indexing
        methods, like IndexIVF's methods.

        :type n: int
        :param n:           number of vectors
        :type xs: float
        :param xs:          input vectors, size (n x d)
        :type residuals: float
        :param residuals:   output residual vectors, size (n x d)
        :type keys: int
        :param keys:        encoded index, as returned by search and assign
        """
        return _swigfaiss.Index_compute_residual_n(self, n, xs, residuals, keys)

    def get_distance_computer(self):
        r"""
         Get a DistanceComputer (defined in AuxIndexStructures) object
        for this kind of index.

        DistanceComputer is implemented for indexes that support random
        access of their vectors.
        """
        return _swigfaiss.Index_get_distance_computer(self)

    def sa_code_size(self):
        r"""size of the produced codes in bytes"""
        return _swigfaiss.Index_sa_code_size(self)

    def sa_encode(self, n, x, bytes):
        r"""
         encode a set of vectors

        :type n: int
        :param n:       number of vectors
        :type x: float
        :param x:       input vectors, size n * d
        :type bytes: uint8_t
        :param bytes:   output encoded vectors, size n * sa_code_size()
        """
        return _swigfaiss.Index_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        r"""
         decode a set of vectors

        :type n: int
        :param n:       number of vectors
        :type bytes: uint8_t
        :param bytes:   input encoded vectors, size n * sa_code_size()
        :type x: float
        :param x:       output vectors, size n * d
        """
        return _swigfaiss.Index_sa_decode(self, n, bytes, x)

    def merge_from(self, otherIndex, add_id=0):
        r"""
         moves the entries from another dataset to self.
        On output, other is empty.
        add_id is added to all moved ids
        (for sequential ids, this would be this->ntotal)
        """
        return _swigfaiss.Index_merge_from(self, otherIndex, add_id)

    def check_compatible_for_merge(self, otherIndex):
        r"""
         check that the two indexes are compatible (ie, they are
        trained in the same way and have the same
        parameters). Otherwise throw.
        """
        return _swigfaiss.Index_check_compatible_for_merge(self, otherIndex)

    def add_sa_codes(self, n, codes, xids):
        r"""
         Add vectors that are computed with the standalone codec

        :type codes: uint8_t
        :param codes:  codes to add size n * sa_code_size()
        :type xids: int
        :param xids:   corresponding ids, size n
        """
        return _swigfaiss.Index_add_sa_codes(self, n, codes, xids)

# Register Index in _swigfaiss:
_swigfaiss.Index_swigregister(Index)
class DistanceComputer(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr

    def set_query(self, x):
        r"""
        called before computing distances. Pointer x should remain valid
        while operator () is called
        """
        return _swigfaiss.DistanceComputer_set_query(self, x)

    def __call__(self, i):
        r"""compute distance of vector i to current query"""
        return _swigfaiss.DistanceComputer___call__(self, i)

    def distances_batch_4(self, idx0, idx1, idx2, idx3, dis0, dis1, dis2, dis3):
        r"""
        compute distances of current query to 4 stored vectors.
        certain DistanceComputer implementations may benefit
        heavily from this.
        """
        return _swigfaiss.DistanceComputer_distances_batch_4(self, idx0, idx1, idx2, idx3, dis0, dis1, dis2, dis3)

    def symmetric_dis(self, i, j):
        r"""compute distance between two stored vectors"""
        return _swigfaiss.DistanceComputer_symmetric_dis(self, i, j)
    __swig_destroy__ = _swigfaiss.delete_DistanceComputer

# Register DistanceComputer in _swigfaiss:
_swigfaiss.DistanceComputer_swigregister(DistanceComputer)
class NegativeDistanceComputer(DistanceComputer):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    basedis = property(_swigfaiss.NegativeDistanceComputer_basedis_get, _swigfaiss.NegativeDistanceComputer_basedis_set, doc=r"""owned by this""")

    def __init__(self, basedis_):
        _swigfaiss.NegativeDistanceComputer_swiginit(self, _swigfaiss.new_NegativeDistanceComputer(basedis_))

    def set_query(self, x):
        return _swigfaiss.NegativeDistanceComputer_set_query(self, x)

    def __call__(self, i):
        r"""compute distance of vector i to current query"""
        return _swigfaiss.NegativeDistanceComputer___call__(self, i)

    def distances_batch_4(self, idx0, idx1, idx2, idx3, dis0, dis1, dis2, dis3):
        return _swigfaiss.NegativeDistanceComputer_distances_batch_4(self, idx0, idx1, idx2, idx3, dis0, dis1, dis2, dis3)

    def symmetric_dis(self, i, j):
        r"""compute distance between two stored vectors"""
        return _swigfaiss.NegativeDistanceComputer_symmetric_dis(self, i, j)
    __swig_destroy__ = _swigfaiss.delete_NegativeDistanceComputer

# Register NegativeDistanceComputer in _swigfaiss:
_swigfaiss.NegativeDistanceComputer_swigregister(NegativeDistanceComputer)
class FlatCodesDistanceComputer(DistanceComputer):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    codes = property(_swigfaiss.FlatCodesDistanceComputer_codes_get, _swigfaiss.FlatCodesDistanceComputer_codes_set)
    code_size = property(_swigfaiss.FlatCodesDistanceComputer_code_size_get, _swigfaiss.FlatCodesDistanceComputer_code_size_set)
    q = property(_swigfaiss.FlatCodesDistanceComputer_q_get, _swigfaiss.FlatCodesDistanceComputer_q_set)

    def __call__(self, i):
        return _swigfaiss.FlatCodesDistanceComputer___call__(self, i)

    def partial_dot_product(self, arg2, arg3, arg4):
        r"""
        Computes a partial dot product over a slice of the query vector.
        The slice is defined by the following parameters:
          — `offset`: the starting index of the first component to include
          — `num_components`: the number of consecutive components to include

        Components refer to raw dimensions of the flat (uncompressed) query
        vector.

        By default, this method throws an error, as it is only implemented
        in specific subclasses such as `FlatL2Dis`. Other flat distance
        computers may override this when partial dot product support is needed.

        Over time, this method might be changed to a pure virtual function (`=
        0`) to enforce implementation in subclasses that require this
        functionality.

        This method is not part of the generic `DistanceComputer` interface
        because for compressed representations (e.g., product quantization),
        calling `partial_dot_product` repeatedly is often less efficient than
        computing the full distance at once.

        Supporting efficient partial scans generally requires a different memory
        layout, such as interleaved blocks that keep SIMD lanes full. This is a
        non-trivial change and not supported in the current flat layout.

        For more details on partial (or chunked) dot product computations and
        the performance trade-offs involved, refer to the Panorama paper:
        https://arxiv.org/pdf/2510.00566
        """
        return _swigfaiss.FlatCodesDistanceComputer_partial_dot_product(self, arg2, arg3, arg4)

    def distance_to_code(self, code):
        r"""compute distance of current query to an encoded vector"""
        return _swigfaiss.FlatCodesDistanceComputer_distance_to_code(self, code)

    def partial_dot_product_batch_4(self, idx0, idx1, idx2, idx3, dp0, dp1, dp2, dp3, offset, num_components):
        r"""
        Compute partial dot products of current query to 4 stored vectors.
        See `partial_dot_product` for more details.
        """
        return _swigfaiss.FlatCodesDistanceComputer_partial_dot_product_batch_4(self, idx0, idx1, idx2, idx3, dp0, dp1, dp2, dp3, offset, num_components)
    __swig_destroy__ = _swigfaiss.delete_FlatCodesDistanceComputer

# Register FlatCodesDistanceComputer in _swigfaiss:
_swigfaiss.FlatCodesDistanceComputer_swigregister(FlatCodesDistanceComputer)
class IOReader(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    name = property(_swigfaiss.IOReader_name_get, _swigfaiss.IOReader_name_set)

    def __call__(self, ptr, size, nitems):
        return _swigfaiss.IOReader___call__(self, ptr, size, nitems)

    def filedescriptor(self):
        return _swigfaiss.IOReader_filedescriptor(self)
    __swig_destroy__ = _swigfaiss.delete_IOReader

# Register IOReader in _swigfaiss:
_swigfaiss.IOReader_swigregister(IOReader)
class IOWriter(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    name = property(_swigfaiss.IOWriter_name_get, _swigfaiss.IOWriter_name_set)

    def __call__(self, ptr, size, nitems):
        return _swigfaiss.IOWriter___call__(self, ptr, size, nitems)

    def filedescriptor(self):
        return _swigfaiss.IOWriter_filedescriptor(self)
    __swig_destroy__ = _swigfaiss.delete_IOWriter

# Register IOWriter in _swigfaiss:
_swigfaiss.IOWriter_swigregister(IOWriter)
class VectorIOReader(IOReader):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    data = property(_swigfaiss.VectorIOReader_data_get, _swigfaiss.VectorIOReader_data_set)
    rp = property(_swigfaiss.VectorIOReader_rp_get, _swigfaiss.VectorIOReader_rp_set)

    def __call__(self, ptr, size, nitems):
        return _swigfaiss.VectorIOReader___call__(self, ptr, size, nitems)

    def __init__(self):
        _swigfaiss.VectorIOReader_swiginit(self, _swigfaiss.new_VectorIOReader())
    __swig_destroy__ = _swigfaiss.delete_VectorIOReader

# Register VectorIOReader in _swigfaiss:
_swigfaiss.VectorIOReader_swigregister(VectorIOReader)
class VectorIOWriter(IOWriter):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    data = property(_swigfaiss.VectorIOWriter_data_get, _swigfaiss.VectorIOWriter_data_set)

    def __call__(self, ptr, size, nitems):
        return _swigfaiss.VectorIOWriter___call__(self, ptr, size, nitems)

    def __init__(self):
        _swigfaiss.VectorIOWriter_swiginit(self, _swigfaiss.new_VectorIOWriter())
    __swig_destroy__ = _swigfaiss.delete_VectorIOWriter

# Register VectorIOWriter in _swigfaiss:
_swigfaiss.VectorIOWriter_swigregister(VectorIOWriter)
class FileIOReader(IOReader):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    f = property(_swigfaiss.FileIOReader_f_get, _swigfaiss.FileIOReader_f_set)
    need_close = property(_swigfaiss.FileIOReader_need_close_get, _swigfaiss.FileIOReader_need_close_set)

    def __init__(self, *args):
        _swigfaiss.FileIOReader_swiginit(self, _swigfaiss.new_FileIOReader(*args))
    __swig_destroy__ = _swigfaiss.delete_FileIOReader

    def __call__(self, ptr, size, nitems):
        return _swigfaiss.FileIOReader___call__(self, ptr, size, nitems)

    def filedescriptor(self):
        return _swigfaiss.FileIOReader_filedescriptor(self)

# Register FileIOReader in _swigfaiss:
_swigfaiss.FileIOReader_swigregister(FileIOReader)
class FileIOWriter(IOWriter):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    f = property(_swigfaiss.FileIOWriter_f_get, _swigfaiss.FileIOWriter_f_set)
    need_close = property(_swigfaiss.FileIOWriter_need_close_get, _swigfaiss.FileIOWriter_need_close_set)

    def __init__(self, *args):
        _swigfaiss.FileIOWriter_swiginit(self, _swigfaiss.new_FileIOWriter(*args))
    __swig_destroy__ = _swigfaiss.delete_FileIOWriter

    def __call__(self, ptr, size, nitems):
        return _swigfaiss.FileIOWriter___call__(self, ptr, size, nitems)

    def filedescriptor(self):
        return _swigfaiss.FileIOWriter_filedescriptor(self)

# Register FileIOWriter in _swigfaiss:
_swigfaiss.FileIOWriter_swigregister(FileIOWriter)
class BufferedIOReader(IOReader):
    r"""wraps an ioreader to make buffered reads to avoid too small reads"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    reader = property(_swigfaiss.BufferedIOReader_reader_get, _swigfaiss.BufferedIOReader_reader_set)
    bsz = property(_swigfaiss.BufferedIOReader_bsz_get, _swigfaiss.BufferedIOReader_bsz_set)
    ofs = property(_swigfaiss.BufferedIOReader_ofs_get, _swigfaiss.BufferedIOReader_ofs_set, doc=r"""offset in input stream""")
    ofs2 = property(_swigfaiss.BufferedIOReader_ofs2_get, _swigfaiss.BufferedIOReader_ofs2_set, doc=r"""number of bytes returned to caller""")
    b0 = property(_swigfaiss.BufferedIOReader_b0_get, _swigfaiss.BufferedIOReader_b0_set, doc=r"""range of available bytes in the buffer""")
    b1 = property(_swigfaiss.BufferedIOReader_b1_get, _swigfaiss.BufferedIOReader_b1_set)
    buffer = property(_swigfaiss.BufferedIOReader_buffer_get, _swigfaiss.BufferedIOReader_buffer_set)

    def __init__(self, *args):
        r"""
        :type bsz: int, optional
        :param bsz:    buffer size (bytes). Reads will be done by batched of
                          this size
        """
        _swigfaiss.BufferedIOReader_swiginit(self, _swigfaiss.new_BufferedIOReader(*args))

    def __call__(self, ptr, size, nitems):
        return _swigfaiss.BufferedIOReader___call__(self, ptr, size, nitems)
    __swig_destroy__ = _swigfaiss.delete_BufferedIOReader

# Register BufferedIOReader in _swigfaiss:
_swigfaiss.BufferedIOReader_swigregister(BufferedIOReader)
class BufferedIOWriter(IOWriter):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    writer = property(_swigfaiss.BufferedIOWriter_writer_get, _swigfaiss.BufferedIOWriter_writer_set)
    bsz = property(_swigfaiss.BufferedIOWriter_bsz_get, _swigfaiss.BufferedIOWriter_bsz_set)
    ofs = property(_swigfaiss.BufferedIOWriter_ofs_get, _swigfaiss.BufferedIOWriter_ofs_set)
    ofs2 = property(_swigfaiss.BufferedIOWriter_ofs2_get, _swigfaiss.BufferedIOWriter_ofs2_set, doc=r"""number of bytes received from caller""")
    b0 = property(_swigfaiss.BufferedIOWriter_b0_get, _swigfaiss.BufferedIOWriter_b0_set, doc=r"""amount of data in buffer""")
    buffer = property(_swigfaiss.BufferedIOWriter_buffer_get, _swigfaiss.BufferedIOWriter_buffer_set)

    def __init__(self, *args):
        _swigfaiss.BufferedIOWriter_swiginit(self, _swigfaiss.new_BufferedIOWriter(*args))

    def __call__(self, ptr, size, nitems):
        return _swigfaiss.BufferedIOWriter___call__(self, ptr, size, nitems)
    __swig_destroy__ = _swigfaiss.delete_BufferedIOWriter

# Register BufferedIOWriter in _swigfaiss:
_swigfaiss.BufferedIOWriter_swigregister(BufferedIOWriter)

def fourcc(*args):
    r"""cast a 4-character string to a uint32_t that can be written and read easily"""
    return _swigfaiss.fourcc(*args)

def fourcc_inv(*args):
    return _swigfaiss.fourcc_inv(*args)

def fourcc_inv_printable(x):
    return _swigfaiss.fourcc_inv_printable(x)
class MaybeOwnedVectorOwner(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    __swig_destroy__ = _swigfaiss.delete_MaybeOwnedVectorOwner

    def __init__(self):
        _swigfaiss.MaybeOwnedVectorOwner_swiginit(self, _swigfaiss.new_MaybeOwnedVectorOwner())

# Register MaybeOwnedVectorOwner in _swigfaiss:
_swigfaiss.MaybeOwnedVectorOwner_swigregister(MaybeOwnedVectorOwner)
class MmappedFileMappingOwner(MaybeOwnedVectorOwner):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.MmappedFileMappingOwner_swiginit(self, _swigfaiss.new_MmappedFileMappingOwner(*args))
    __swig_destroy__ = _swigfaiss.delete_MmappedFileMappingOwner

    def data(self):
        return _swigfaiss.MmappedFileMappingOwner_data(self)

    def size(self):
        return _swigfaiss.MmappedFileMappingOwner_size(self)

# Register MmappedFileMappingOwner in _swigfaiss:
_swigfaiss.MmappedFileMappingOwner_swigregister(MmappedFileMappingOwner)
class MappedFileIOReader(IOReader):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    mmap_owner = property(_swigfaiss.MappedFileIOReader_mmap_owner_get, _swigfaiss.MappedFileIOReader_mmap_owner_set)
    pos = property(_swigfaiss.MappedFileIOReader_pos_get, _swigfaiss.MappedFileIOReader_pos_set)

    def __init__(self, owner):
        _swigfaiss.MappedFileIOReader_swiginit(self, _swigfaiss.new_MappedFileIOReader(owner))

    def __call__(self, ptr, size, nitems):
        return _swigfaiss.MappedFileIOReader___call__(self, ptr, size, nitems)

    def mmap(self, ptr, size, nitems):
        return _swigfaiss.MappedFileIOReader_mmap(self, ptr, size, nitems)

    def filedescriptor(self):
        return _swigfaiss.MappedFileIOReader_filedescriptor(self)
    __swig_destroy__ = _swigfaiss.delete_MappedFileIOReader

# Register MappedFileIOReader in _swigfaiss:
_swigfaiss.MappedFileIOReader_swigregister(MappedFileIOReader)
class ZeroCopyIOReader(IOReader):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    data_ = property(_swigfaiss.ZeroCopyIOReader_data__get, _swigfaiss.ZeroCopyIOReader_data__set)
    rp_ = property(_swigfaiss.ZeroCopyIOReader_rp__get, _swigfaiss.ZeroCopyIOReader_rp__set)
    total_ = property(_swigfaiss.ZeroCopyIOReader_total__get, _swigfaiss.ZeroCopyIOReader_total__set)

    def __init__(self, data, size):
        _swigfaiss.ZeroCopyIOReader_swiginit(self, _swigfaiss.new_ZeroCopyIOReader(data, size))
    __swig_destroy__ = _swigfaiss.delete_ZeroCopyIOReader

    def reset(self):
        return _swigfaiss.ZeroCopyIOReader_reset(self)

    def get_data_view(self, ptr, size, nitems):
        return _swigfaiss.ZeroCopyIOReader_get_data_view(self, ptr, size, nitems)

    def __call__(self, ptr, size, nitems):
        return _swigfaiss.ZeroCopyIOReader___call__(self, ptr, size, nitems)

    def filedescriptor(self):
        return _swigfaiss.ZeroCopyIOReader_filedescriptor(self)

# Register ZeroCopyIOReader in _swigfaiss:
_swigfaiss.ZeroCopyIOReader_swigregister(ZeroCopyIOReader)
class IndexFlatCodes(Index):
    r"""
     Index that encodes all vectors as fixed-size codes (size code_size). Storage
    is in the codes vector
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    code_size = property(_swigfaiss.IndexFlatCodes_code_size_get, _swigfaiss.IndexFlatCodes_code_size_set)
    codes = property(_swigfaiss.IndexFlatCodes_codes_get, _swigfaiss.IndexFlatCodes_codes_set, doc=r"""encoded dataset, size ntotal * code_size""")

    def __init__(self, *args):
        _swigfaiss.IndexFlatCodes_swiginit(self, _swigfaiss.new_IndexFlatCodes(*args))

    def add(self, n, x):
        r"""default add uses sa_encode"""
        return _swigfaiss.IndexFlatCodes_add(self, n, x)

    def reset(self):
        return _swigfaiss.IndexFlatCodes_reset(self)

    def reconstruct_n(self, i0, ni, recons):
        return _swigfaiss.IndexFlatCodes_reconstruct_n(self, i0, ni, recons)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexFlatCodes_reconstruct(self, key, recons)

    def sa_code_size(self):
        return _swigfaiss.IndexFlatCodes_sa_code_size(self)

    def remove_ids(self, sel):
        r"""
         remove some ids. NB that because of the structure of the
        index, the semantics of this operation are
        different from the usual ones: the new ids are shifted
        """
        return _swigfaiss.IndexFlatCodes_remove_ids(self, sel)

    def get_FlatCodesDistanceComputer(self):
        r"""
         a FlatCodesDistanceComputer offers a distance_to_code method

        The default implementation explicitly decodes the vector with sa_decode.
        """
        return _swigfaiss.IndexFlatCodes_get_FlatCodesDistanceComputer(self)

    def get_distance_computer(self):
        return _swigfaiss.IndexFlatCodes_get_distance_computer(self)

    def search(self, n, x, k, distances, labels, params=None):
        r"""
         Search implemented by decoding (most index types will have a faster
        implementation)
        """
        return _swigfaiss.IndexFlatCodes_search(self, n, x, k, distances, labels, params)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexFlatCodes_range_search(self, n, x, radius, result, params)

    def search1(self, x, handler, params=None):
        return _swigfaiss.IndexFlatCodes_search1(self, x, handler, params)

    def get_CodePacker(self):
        return _swigfaiss.IndexFlatCodes_get_CodePacker(self)

    def check_compatible_for_merge(self, otherIndex):
        return _swigfaiss.IndexFlatCodes_check_compatible_for_merge(self, otherIndex)

    def merge_from(self, otherIndex, add_id=0):
        return _swigfaiss.IndexFlatCodes_merge_from(self, otherIndex, add_id)

    def add_sa_codes(self, n, x, xids):
        return _swigfaiss.IndexFlatCodes_add_sa_codes(self, n, x, xids)

    def permute_entries(self, perm):
        return _swigfaiss.IndexFlatCodes_permute_entries(self, perm)
    __swig_destroy__ = _swigfaiss.delete_IndexFlatCodes

# Register IndexFlatCodes in _swigfaiss:
_swigfaiss.IndexFlatCodes_swigregister(IndexFlatCodes)
class IndexFlat(IndexFlatCodes):
    r"""Index that stores the full vectors and performs exhaustive search"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexFlat_search(self, n, x, k, distances, labels, params)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexFlat_range_search(self, n, x, radius, result, params)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexFlat_reconstruct(self, key, recons)

    def compute_distance_subset(self, n, x, k, distances, labels):
        r"""
         compute distance with a subset of vectors

        :type x: float
        :param x:       query vectors, size n * d
        :type labels: int
        :param labels:  indices of the vectors that should be compared
                           for each query vector, size n * k
        :type distances: float
        :param distances:
                           corresponding output distances, size n * k
        """
        return _swigfaiss.IndexFlat_compute_distance_subset(self, n, x, k, distances, labels)

    def get_xb(self, *args):
        return _swigfaiss.IndexFlat_get_xb(self, *args)

    def __init__(self, *args):
        _swigfaiss.IndexFlat_swiginit(self, _swigfaiss.new_IndexFlat(*args))

    def get_FlatCodesDistanceComputer(self):
        return _swigfaiss.IndexFlat_get_FlatCodesDistanceComputer(self)

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.IndexFlat_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexFlat_sa_decode(self, n, bytes, x)
    __swig_destroy__ = _swigfaiss.delete_IndexFlat

# Register IndexFlat in _swigfaiss:
_swigfaiss.IndexFlat_swigregister(IndexFlat)
class IndexFlatIP(IndexFlat):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexFlatIP_swiginit(self, _swigfaiss.new_IndexFlatIP(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexFlatIP

# Register IndexFlatIP in _swigfaiss:
_swigfaiss.IndexFlatIP_swigregister(IndexFlatIP)
class IndexFlatL2(IndexFlat):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    cached_l2norms = property(_swigfaiss.IndexFlatL2_cached_l2norms_get, _swigfaiss.IndexFlatL2_cached_l2norms_set)

    def __init__(self, *args):
        r""":param d: dimensionality of the input vectors"""
        _swigfaiss.IndexFlatL2_swiginit(self, _swigfaiss.new_IndexFlatL2(*args))

    def get_FlatCodesDistanceComputer(self):
        return _swigfaiss.IndexFlatL2_get_FlatCodesDistanceComputer(self)

    def sync_l2norms(self):
        return _swigfaiss.IndexFlatL2_sync_l2norms(self)

    def clear_l2norms(self):
        return _swigfaiss.IndexFlatL2_clear_l2norms(self)
    __swig_destroy__ = _swigfaiss.delete_IndexFlatL2

# Register IndexFlatL2 in _swigfaiss:
_swigfaiss.IndexFlatL2_swigregister(IndexFlatL2)
class IndexFlatPanorama(IndexFlat):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    batch_size = property(_swigfaiss.IndexFlatPanorama_batch_size_get)
    n_levels = property(_swigfaiss.IndexFlatPanorama_n_levels_get)
    cum_sums = property(_swigfaiss.IndexFlatPanorama_cum_sums_get, _swigfaiss.IndexFlatPanorama_cum_sums_set)

    def __init__(self, d_in, metric, n_levels_in, batch_size_in):
        r"""
        :param d: dimensionality of the input vectors
        :type metric: int
        :param metric: metric type
        :param n_levels: number of Panorama levels
        :param batch_size: batch size for Panorama storage
        """
        _swigfaiss.IndexFlatPanorama_swiginit(self, _swigfaiss.new_IndexFlatPanorama(d_in, metric, n_levels_in, batch_size_in))

    def add(self, n, x):
        return _swigfaiss.IndexFlatPanorama_add(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexFlatPanorama_search(self, n, x, k, distances, labels, params)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexFlatPanorama_range_search(self, n, x, radius, result, params)

    def search_subset(self, n, x, k_base, base_labels, k, distances, labels):
        return _swigfaiss.IndexFlatPanorama_search_subset(self, n, x, k_base, base_labels, k, distances, labels)

    def reset(self):
        return _swigfaiss.IndexFlatPanorama_reset(self)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexFlatPanorama_reconstruct(self, key, recons)

    def reconstruct_n(self, i, n, recons):
        return _swigfaiss.IndexFlatPanorama_reconstruct_n(self, i, n, recons)

    def remove_ids(self, sel):
        return _swigfaiss.IndexFlatPanorama_remove_ids(self, sel)

    def merge_from(self, otherIndex, add_id):
        return _swigfaiss.IndexFlatPanorama_merge_from(self, otherIndex, add_id)

    def add_sa_codes(self, n, codes_in, xids):
        return _swigfaiss.IndexFlatPanorama_add_sa_codes(self, n, codes_in, xids)

    def permute_entries(self, perm):
        return _swigfaiss.IndexFlatPanorama_permute_entries(self, perm)
    __swig_destroy__ = _swigfaiss.delete_IndexFlatPanorama

# Register IndexFlatPanorama in _swigfaiss:
_swigfaiss.IndexFlatPanorama_swigregister(IndexFlatPanorama)
class IndexFlatL2Panorama(IndexFlatPanorama):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, d_in, n_levels_in, batch_size_in=512):
        r"""
        :param d: dimensionality of the input vectors
        :param n_levels: number of Panorama levels
        :param batch_size: batch size for Panorama storage
        """
        _swigfaiss.IndexFlatL2Panorama_swiginit(self, _swigfaiss.new_IndexFlatL2Panorama(d_in, n_levels_in, batch_size_in))
    __swig_destroy__ = _swigfaiss.delete_IndexFlatL2Panorama

# Register IndexFlatL2Panorama in _swigfaiss:
_swigfaiss.IndexFlatL2Panorama_swigregister(IndexFlatL2Panorama)
class IndexFlatIPPanorama(IndexFlatPanorama):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, d_in, n_levels_in, batch_size_in=512):
        r"""
        :param d: dimensionality of the input vectors
        :param n_levels: number of Panorama levels
        :param batch_size: batch size for Panorama storage
        """
        _swigfaiss.IndexFlatIPPanorama_swiginit(self, _swigfaiss.new_IndexFlatIPPanorama(d_in, n_levels_in, batch_size_in))
    __swig_destroy__ = _swigfaiss.delete_IndexFlatIPPanorama

# Register IndexFlatIPPanorama in _swigfaiss:
_swigfaiss.IndexFlatIPPanorama_swigregister(IndexFlatIPPanorama)
class IndexFlat1D(IndexFlatL2):
    r"""optimized version for 1D "vectors"."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    continuous_update = property(_swigfaiss.IndexFlat1D_continuous_update_get, _swigfaiss.IndexFlat1D_continuous_update_set, doc=r"""is the permutation updated continuously?""")
    perm = property(_swigfaiss.IndexFlat1D_perm_get, _swigfaiss.IndexFlat1D_perm_set, doc=r"""sorted database indices""")

    def __init__(self, continuous_update=True):
        _swigfaiss.IndexFlat1D_swiginit(self, _swigfaiss.new_IndexFlat1D(continuous_update))

    def update_permutation(self):
        r"""
        if not continuous_update, call this between the last add and
        the first search
        """
        return _swigfaiss.IndexFlat1D_update_permutation(self)

    def add(self, n, x):
        return _swigfaiss.IndexFlat1D_add(self, n, x)

    def reset(self):
        return _swigfaiss.IndexFlat1D_reset(self)

    def search(self, n, x, k, distances, labels, params=None):
        r"""Warn: the distances returned are L1 not L2"""
        return _swigfaiss.IndexFlat1D_search(self, n, x, k, distances, labels, params)
    __swig_destroy__ = _swigfaiss.delete_IndexFlat1D

# Register IndexFlat1D in _swigfaiss:
_swigfaiss.IndexFlat1D_swigregister(IndexFlat1D)
ClusteringInitMethod_RANDOM = _swigfaiss.ClusteringInitMethod_RANDOM
r"""
    Random sampling: select k random points uniformly from the dataset.
    Time complexity: O(k)
    """
ClusteringInitMethod_KMEANS_PLUS_PLUS = _swigfaiss.ClusteringInitMethod_KMEANS_PLUS_PLUS
r"""
    k-means++: select centroids with probability proportional to D(x)²,
    where D(x) is the distance to the nearest existing centroid.
    Reference: Arthur, D., & Vassilvitskii, S. (2006). k-means++:
    The advantages of careful seeding. Stanford.
    Time complexity: O(nkd)
    """
ClusteringInitMethod_AFK_MC2 = _swigfaiss.ClusteringInitMethod_AFK_MC2
r"""
    AFK-MC²: Assumption-Free K-MC² using Markov Chain Monte Carlo.
    Provides theoretical guarantees without assumptions on data
    distribution.
    Uses a non-uniform proposal distribution based on D²-sampling from
    the first center, combined with uniform sampling for regularization.
    Reference: Bachem, O., Lucic, M., Hassani, H., & Krause, A. (2016).
    Fast and provably good seedings for k-means. Advances in neural
    information processing systems, 29.
    Time complexity: O(nd) preprocessing + O(mk²d) main loop
    """
class ClusteringInitialization(object):
    r"""
    Centroid initialization for k-means clustering.

    This class provides different algorithms for selecting initial centroids
    before running k-means iterations. Good initialization can significantly
    improve clustering quality and convergence speed.

    Example usage:

    .. code-block:: c++

            ClusteringInitialization init(128, 1000);  // d=128, k=1000
            init.method = ClusteringInitMethod::KMEANS_PLUS_PLUS;
            init.seed = 42;

            std::vector<float> centroids(128 * 1000);
            init.init_centroids(n, x, centroids.data());
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    d = property(_swigfaiss.ClusteringInitialization_d_get, _swigfaiss.ClusteringInitialization_d_set, doc=r"""vector dimension""")
    k = property(_swigfaiss.ClusteringInitialization_k_get, _swigfaiss.ClusteringInitialization_k_set, doc=r"""number of centroids to initialize""")
    method = property(_swigfaiss.ClusteringInitialization_method_get, _swigfaiss.ClusteringInitialization_method_set, doc=r"""Initialization method to use""")
    seed = property(_swigfaiss.ClusteringInitialization_seed_get, _swigfaiss.ClusteringInitialization_seed_set, doc=r"""Random seed.""")
    afkmc2_chain_length = property(_swigfaiss.ClusteringInitialization_afkmc2_chain_length_get, _swigfaiss.ClusteringInitialization_afkmc2_chain_length_set, doc=r"""
    Chain length for AFK-MC² (only used when method = AFK_MC2).
    Longer chains give better approximation to k-means++ but are slower.
    """)

    def __init__(self, d, k):
        _swigfaiss.ClusteringInitialization_swiginit(self, _swigfaiss.new_ClusteringInitialization(d, k))

    def init_centroids(self, n, x, centroids, n_existing_centroids=0, existing_centroids=None):
        r"""
        Initialize k centroids from n input vectors.

        :type n: int
        :param n:          number of input vectors
        :type x: float
        :param x:          input vectors, size (n, d), row-major
        :type centroids: float
        :param centroids:  output centroids, size (k, d), row-major
        :type n_existing_centroids: int, optional
        :param n_existing_centroids:  number of pre-existing centroids to
            consider
                                         when computing distances (for k-means++ and
                                         AFK-MC²). These centroids are not modified.
        :type existing_centroids: float, optional
        :param existing_centroids:    pre-existing centroids, size
                                         (n_existing_centroids, d), row-major.
                                         New centroids will be selected to be far
                                         from these existing ones.
        """
        return _swigfaiss.ClusteringInitialization_init_centroids(self, n, x, centroids, n_existing_centroids, existing_centroids)
    __swig_destroy__ = _swigfaiss.delete_ClusteringInitialization

# Register ClusteringInitialization in _swigfaiss:
_swigfaiss.ClusteringInitialization_swigregister(ClusteringInitialization)
class ClusteringParameters(object):
    r"""
     Class for the clustering parameters. Can be passed to the
    constructor of the Clustering object.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    niter = property(_swigfaiss.ClusteringParameters_niter_get, _swigfaiss.ClusteringParameters_niter_set, doc=r"""number of clustering iterations""")
    nredo = property(_swigfaiss.ClusteringParameters_nredo_get, _swigfaiss.ClusteringParameters_nredo_set, doc=r"""
    redo clustering this many times and keep the clusters with the best
    objective
    """)
    verbose = property(_swigfaiss.ClusteringParameters_verbose_get, _swigfaiss.ClusteringParameters_verbose_set)
    spherical = property(_swigfaiss.ClusteringParameters_spherical_get, _swigfaiss.ClusteringParameters_spherical_set, doc=r"""
    whether to normalize centroids after each iteration (useful for inner
    product clustering)
    """)
    int_centroids = property(_swigfaiss.ClusteringParameters_int_centroids_get, _swigfaiss.ClusteringParameters_int_centroids_set, doc=r"""round centroids coordinates to integer after each iteration?""")
    update_index = property(_swigfaiss.ClusteringParameters_update_index_get, _swigfaiss.ClusteringParameters_update_index_set, doc=r"""re-train index after each iteration?""")
    frozen_centroids = property(_swigfaiss.ClusteringParameters_frozen_centroids_get, _swigfaiss.ClusteringParameters_frozen_centroids_set, doc=r"""
    Use the subset of centroids provided as input and do not change them
    during iterations
    """)
    min_points_per_centroid = property(_swigfaiss.ClusteringParameters_min_points_per_centroid_get, _swigfaiss.ClusteringParameters_min_points_per_centroid_set, doc=r"""
    If fewer than this number of training vectors per centroid are provided,
    writes a warning. Note that fewer than 1 point per centroid raises an
    exception.
    """)
    max_points_per_centroid = property(_swigfaiss.ClusteringParameters_max_points_per_centroid_get, _swigfaiss.ClusteringParameters_max_points_per_centroid_set, doc=r"""to limit size of dataset, otherwise the training set is subsampled""")
    seed = property(_swigfaiss.ClusteringParameters_seed_get, _swigfaiss.ClusteringParameters_seed_set, doc=r"""
    seed for the random number generator.
    negative values lead to seeding an internal rng with
    std::high_resolution_clock.
    """)
    decode_block_size = property(_swigfaiss.ClusteringParameters_decode_block_size_get, _swigfaiss.ClusteringParameters_decode_block_size_set, doc=r"""when the training set is encoded, batch size of the codec decoder""")
    check_input_data_for_NaNs = property(_swigfaiss.ClusteringParameters_check_input_data_for_NaNs_get, _swigfaiss.ClusteringParameters_check_input_data_for_NaNs_set, doc=r"""whether to check for NaNs in an input data""")
    use_faster_subsampling = property(_swigfaiss.ClusteringParameters_use_faster_subsampling_get, _swigfaiss.ClusteringParameters_use_faster_subsampling_set, doc=r"""
    Whether to use splitmix64-based random number generator for subsampling,
    which is faster, but may pick duplicate points.
    """)
    init_method = property(_swigfaiss.ClusteringParameters_init_method_get, _swigfaiss.ClusteringParameters_init_method_set, doc=r"""
    Initialization method for centroids.
    RANDOM: uniform random sampling (default, current behavior)
    KMEANS_PLUS_PLUS: k-means++ (O(nkd), better quality)
    AFK_MC2: Assumption-Free K-MC² (O(nd) + O(mk²d), fast approximation)
    """)
    afkmc2_chain_length = property(_swigfaiss.ClusteringParameters_afkmc2_chain_length_get, _swigfaiss.ClusteringParameters_afkmc2_chain_length_set, doc=r"""
    Chain length for AFK-MC² initialization.
    Only used when init_method = AFK_MC2.
    Longer chains give better approximation but are slower.
    """)
    early_stop_threshold = property(_swigfaiss.ClusteringParameters_early_stop_threshold_get, _swigfaiss.ClusteringParameters_early_stop_threshold_set, doc=r"""
    Early stop threshold, the range is [0, 1].
    The value of 0 implies a default Faiss behavior,
    so the training process stops only if an error
    is unchanged from the previous iteration.
    """)

    def __init__(self):
        _swigfaiss.ClusteringParameters_swiginit(self, _swigfaiss.new_ClusteringParameters())
    __swig_destroy__ = _swigfaiss.delete_ClusteringParameters

# Register ClusteringParameters in _swigfaiss:
_swigfaiss.ClusteringParameters_swigregister(ClusteringParameters)
class ClusteringIterationStats(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    obj = property(_swigfaiss.ClusteringIterationStats_obj_get, _swigfaiss.ClusteringIterationStats_obj_set, doc=r"""objective values (sum of distances reported by index)""")
    time = property(_swigfaiss.ClusteringIterationStats_time_get, _swigfaiss.ClusteringIterationStats_time_set, doc=r"""seconds for iteration""")
    time_search = property(_swigfaiss.ClusteringIterationStats_time_search_get, _swigfaiss.ClusteringIterationStats_time_search_set, doc=r"""seconds for just search""")
    imbalance_factor = property(_swigfaiss.ClusteringIterationStats_imbalance_factor_get, _swigfaiss.ClusteringIterationStats_imbalance_factor_set, doc=r"""imbalance factor of iteration""")
    nsplit = property(_swigfaiss.ClusteringIterationStats_nsplit_get, _swigfaiss.ClusteringIterationStats_nsplit_set, doc=r"""number of cluster splits""")

    def __init__(self):
        _swigfaiss.ClusteringIterationStats_swiginit(self, _swigfaiss.new_ClusteringIterationStats())
    __swig_destroy__ = _swigfaiss.delete_ClusteringIterationStats

# Register ClusteringIterationStats in _swigfaiss:
_swigfaiss.ClusteringIterationStats_swigregister(ClusteringIterationStats)
class Clustering(ClusteringParameters):
    r"""
     K-means clustering based on assignment - centroid update iterations

    The clustering is based on an Index object that assigns training
    points to the centroids. Therefore, at each iteration the centroids
    are added to the index.

    On output, the centroids table is set to the latest version
    of the centroids and they are also added to the index. If the
    centroids table it is not empty on input, it is also used for
    initialization.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    d = property(_swigfaiss.Clustering_d_get, _swigfaiss.Clustering_d_set, doc=r"""dimension of the vectors""")
    k = property(_swigfaiss.Clustering_k_get, _swigfaiss.Clustering_k_set, doc=r"""nb of centroids""")
    centroids = property(_swigfaiss.Clustering_centroids_get, _swigfaiss.Clustering_centroids_set, doc=r"""
     centroids (k * d)
    if centroids are set on input to train, they will be used as
    initialization
    """)
    iteration_stats = property(_swigfaiss.Clustering_iteration_stats_get, _swigfaiss.Clustering_iteration_stats_set, doc=r"""stats at every iteration of clustering""")

    def __init__(self, *args):
        _swigfaiss.Clustering_swiginit(self, _swigfaiss.new_Clustering(*args))

    def train(self, n, x, index, x_weights=None):
        r"""
         run k-means training

        :type x: float
        :param x:          training vectors, size n * d
        :type index: :py:class:`Index`
        :param index:      index used for assignment
        :type x_weights: float, optional
        :param x_weights:  weight associated to each vector: NULL or size n
        """
        return _swigfaiss.Clustering_train(self, n, x, index, x_weights)

    def train_encoded(self, nx, x_in, codec, index, weights=None):
        r"""
         run with encoded vectors

        in addition to train()'s parameters takes a codec as parameter
        to decode the input vectors.

        :type codec: :py:class:`Index`
        :param codec:      codec used to decode the vectors (nullptr =
                              vectors are in fact floats)
        """
        return _swigfaiss.Clustering_train_encoded(self, nx, x_in, codec, index, weights)

    def post_process_centroids(self):
        r"""
        Post-process the centroids after each centroid update.
        includes optional L2 normalization and nearest integer rounding
        """
        return _swigfaiss.Clustering_post_process_centroids(self)
    __swig_destroy__ = _swigfaiss.delete_Clustering

# Register Clustering in _swigfaiss:
_swigfaiss.Clustering_swigregister(Clustering)
class Clustering1D(Clustering):
    r"""
     Exact 1D clustering algorithm

    Since it does not use an index, it does not overload the train() function
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.Clustering1D_swiginit(self, _swigfaiss.new_Clustering1D(*args))

    def train_exact(self, n, x):
        return _swigfaiss.Clustering1D_train_exact(self, n, x)
    __swig_destroy__ = _swigfaiss.delete_Clustering1D

# Register Clustering1D in _swigfaiss:
_swigfaiss.Clustering1D_swigregister(Clustering1D)
class ProgressiveDimClusteringParameters(ClusteringParameters):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    progressive_dim_steps = property(_swigfaiss.ProgressiveDimClusteringParameters_progressive_dim_steps_get, _swigfaiss.ProgressiveDimClusteringParameters_progressive_dim_steps_set, doc=r"""number of incremental steps""")
    apply_pca = property(_swigfaiss.ProgressiveDimClusteringParameters_apply_pca_get, _swigfaiss.ProgressiveDimClusteringParameters_apply_pca_set, doc=r"""apply PCA on input""")

    def __init__(self):
        _swigfaiss.ProgressiveDimClusteringParameters_swiginit(self, _swigfaiss.new_ProgressiveDimClusteringParameters())
    __swig_destroy__ = _swigfaiss.delete_ProgressiveDimClusteringParameters

# Register ProgressiveDimClusteringParameters in _swigfaiss:
_swigfaiss.ProgressiveDimClusteringParameters_swigregister(ProgressiveDimClusteringParameters)
class ProgressiveDimIndexFactory(object):
    r"""generates an index suitable for clustering when called"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __call__(self, dim):
        r"""ownership transferred to caller"""
        return _swigfaiss.ProgressiveDimIndexFactory___call__(self, dim)
    __swig_destroy__ = _swigfaiss.delete_ProgressiveDimIndexFactory

    def __init__(self):
        _swigfaiss.ProgressiveDimIndexFactory_swiginit(self, _swigfaiss.new_ProgressiveDimIndexFactory())

# Register ProgressiveDimIndexFactory in _swigfaiss:
_swigfaiss.ProgressiveDimIndexFactory_swigregister(ProgressiveDimIndexFactory)
class ProgressiveDimClustering(ProgressiveDimClusteringParameters):
    r"""
     K-means clustering with progressive dimensions used

    The clustering first happens in dim 1, then with exponentially increasing
    dimension until d (I steps). This is typically applied after a PCA
    transformation (optional). Reference:

    "Improved Residual Vector Quantization for High-dimensional Approximate
    Nearest Neighbor Search"

    Shicong Liu, Hongtao Lu, Junru Shao, AAAI'15

    https://arxiv.org/abs/1509.05195
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    d = property(_swigfaiss.ProgressiveDimClustering_d_get, _swigfaiss.ProgressiveDimClustering_d_set, doc=r"""dimension of the vectors""")
    k = property(_swigfaiss.ProgressiveDimClustering_k_get, _swigfaiss.ProgressiveDimClustering_k_set, doc=r"""nb of centroids""")
    centroids = property(_swigfaiss.ProgressiveDimClustering_centroids_get, _swigfaiss.ProgressiveDimClustering_centroids_set, doc=r"""centroids (k * d)""")
    iteration_stats = property(_swigfaiss.ProgressiveDimClustering_iteration_stats_get, _swigfaiss.ProgressiveDimClustering_iteration_stats_set, doc=r"""stats at every iteration of clustering""")

    def __init__(self, *args):
        _swigfaiss.ProgressiveDimClustering_swiginit(self, _swigfaiss.new_ProgressiveDimClustering(*args))

    def train(self, n, x, factory):
        return _swigfaiss.ProgressiveDimClustering_train(self, n, x, factory)
    __swig_destroy__ = _swigfaiss.delete_ProgressiveDimClustering

# Register ProgressiveDimClustering in _swigfaiss:
_swigfaiss.ProgressiveDimClustering_swigregister(ProgressiveDimClustering)

def kmeans_clustering(d, n, k, x, centroids):
    r"""
     simplified interface

    :type d: int
    :param d: dimension of the data
    :type n: int
    :param n: nb of training vectors
    :type k: int
    :param k: nb of output centroids
    :type x: float
    :param x: training set (size n * d)
    :type centroids: float
    :param centroids: output centroids (size k * d)
    :rtype: float
    :return: final quantization error
    """
    return _swigfaiss.kmeans_clustering(d, n, k, x, centroids)
class SuperKMeansParameters(ClusteringParameters):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    d_prime_fraction = property(_swigfaiss.SuperKMeansParameters_d_prime_fraction_get, _swigfaiss.SuperKMeansParameters_d_prime_fraction_set, doc=r"""Initial d_prime as a fraction of d (GEMM/PRUNING split).""")
    pdx_block_size = property(_swigfaiss.SuperKMeansParameters_pdx_block_size_get, _swigfaiss.SuperKMeansParameters_pdx_block_size_set, doc=r"""Matches block_l2 SIMD width.""")
    ad_epsilon_factor = property(_swigfaiss.SuperKMeansParameters_ad_epsilon_factor_get, _swigfaiss.SuperKMeansParameters_ad_epsilon_factor_set, doc=r"""ADSampling significance: epsilon = ad_epsilon_factor / d.""")
    pruning_target_low = property(_swigfaiss.SuperKMeansParameters_pruning_target_low_get, _swigfaiss.SuperKMeansParameters_pruning_target_low_set, doc=r"""
    Adaptive d_prime stay-in-band controller. Per iteration:
      pruning > high → shrink d_prime  (over-pruning, cheaper threshold)
      pruning < low  → grow   d_prime  (under-pruning, more GEMM work)
      else: hold.
    """)
    pruning_target_high = property(_swigfaiss.SuperKMeansParameters_pruning_target_high_get, _swigfaiss.SuperKMeansParameters_pruning_target_high_set)
    d_prime_adjust = property(_swigfaiss.SuperKMeansParameters_d_prime_adjust_get, _swigfaiss.SuperKMeansParameters_d_prime_adjust_set, doc=r"""Relative step size for d_prime adjustments.""")
    d_prime_min = property(_swigfaiss.SuperKMeansParameters_d_prime_min_get, _swigfaiss.SuperKMeansParameters_d_prime_min_set, doc=r"""Floor on d_prime; below this the chi-squared bound is unvalidated.""")
    x_batch = property(_swigfaiss.SuperKMeansParameters_x_batch_get, _swigfaiss.SuperKMeansParameters_x_batch_set)
    y_batch = property(_swigfaiss.SuperKMeansParameters_y_batch_get, _swigfaiss.SuperKMeansParameters_y_batch_set)
    omp_chunk = property(_swigfaiss.SuperKMeansParameters_omp_chunk_get, _swigfaiss.SuperKMeansParameters_omp_chunk_set, doc=r"""OpenMP dynamic-schedule chunk size for the pruning loop.""")

    def __init__(self):
        _swigfaiss.SuperKMeansParameters_swiginit(self, _swigfaiss.new_SuperKMeansParameters())
    __swig_destroy__ = _swigfaiss.delete_SuperKMeansParameters

# Register SuperKMeansParameters in _swigfaiss:
_swigfaiss.SuperKMeansParameters_swigregister(SuperKMeansParameters)
class SuperKMeans(object):
    r"""
     Drop-in faster k-means: same interface as faiss::Clustering. Per iteration:
      iter 0:           full GEMM over all d dims (vanilla Lloyd's).
      iter 1..niter-1:  GEMM over front d_prime dims, then ADSampling
                        progressive pruning over PDX-laid trailing dims.

    Trains in a randomly-rotated space; centroids are un-rotated before return.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    cp = property(_swigfaiss.SuperKMeans_cp_get, _swigfaiss.SuperKMeans_cp_set)
    d = property(_swigfaiss.SuperKMeans_d_get, _swigfaiss.SuperKMeans_d_set)
    k = property(_swigfaiss.SuperKMeans_k_get, _swigfaiss.SuperKMeans_k_set)
    centroids = property(_swigfaiss.SuperKMeans_centroids_get, _swigfaiss.SuperKMeans_centroids_set, doc=r"""Output: k * d floats, row-major, un-rotated.""")
    iteration_stats = property(_swigfaiss.SuperKMeans_iteration_stats_get, _swigfaiss.SuperKMeans_iteration_stats_set, doc=r"""
    Per-iter stats. `obj`, `time`, and `nsplit` are populated faithfully.
    `time_search` mirrors `time` (phases not timed separately) and
    `imbalance_factor` is set to NaN (not computed).
    """)
    gemm_pruning_rates = property(_swigfaiss.SuperKMeans_gemm_pruning_rates_get, _swigfaiss.SuperKMeans_gemm_pruning_rates_set, doc=r"""
    Per-iter fraction of (vector, centroid) pairs pruned at the d_prime
    GEMM-boundary chi-squared check. Per-PDX-block early-exits are NOT
    counted. iter 0 uses full GEMM, so gemm_pruning_rates[0] == 0.0f.
    """)

    def __init__(self, *args):
        _swigfaiss.SuperKMeans_swiginit(self, _swigfaiss.new_SuperKMeans(*args))

    def train(self, n, x):
        r"""
        Train on `n` row-major vectors of dimension `d`. Honors the applicable
        ClusteringParameters fields (niter, seed, verbose,
        max_points_per_centroid, use_faster_subsampling,
        check_input_data_for_NaNs).
        """
        return _swigfaiss.SuperKMeans_train(self, n, x)
    __swig_destroy__ = _swigfaiss.delete_SuperKMeans

# Register SuperKMeans in _swigfaiss:
_swigfaiss.SuperKMeans_swigregister(SuperKMeans)

def pairwise_extra_distances(d, nq, xq, nb, xb, mt, metric_arg, dis, ldq=-1, ldb=-1, ldd=-1):
    return _swigfaiss.pairwise_extra_distances(d, nq, xq, nb, xb, mt, metric_arg, dis, ldq, ldb, ldd)

def knn_extra_metrics(x, y, d, nx, ny, mt, metric_arg, k, distances, indexes, sel=None):
    return _swigfaiss.knn_extra_metrics(x, y, d, nx, ny, mt, metric_arg, k, distances, indexes, sel)

def get_extra_distance_computer(d, mt, metric_arg, nb, xb):
    r"""
    get a DistanceComputer that refers to this type of distance and
    indexes a flat array of size nb
    """
    return _swigfaiss.get_extra_distance_computer(d, mt, metric_arg, nb, xb)
class Quantizer(object):
    r"""General interface for quantizer objects"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    d = property(_swigfaiss.Quantizer_d_get, _swigfaiss.Quantizer_d_set, doc=r"""size of the input vectors""")
    code_size = property(_swigfaiss.Quantizer_code_size_get, _swigfaiss.Quantizer_code_size_set, doc=r"""bytes per indexed vector""")

    def train(self, n, x):
        r"""
         Train the quantizer

        :type x: float
        :param x:       training vectors, size n * d
        """
        return _swigfaiss.Quantizer_train(self, n, x)

    def compute_codes(self, x, codes, n):
        r"""
         Quantize a set of vectors

        :type x: float
        :param x:        input vectors, size n * d
        :type codes: uint8_t
        :param codes:    output codes, size n * code_size
        """
        return _swigfaiss.Quantizer_compute_codes(self, x, codes, n)

    def decode(self, code, x, n):
        r"""
         Decode a set of vectors

        :param codes:    input codes, size n * code_size
        :type x: float
        :param x:        output vectors, size n * d
        """
        return _swigfaiss.Quantizer_decode(self, code, x, n)
    __swig_destroy__ = _swigfaiss.delete_Quantizer

# Register Quantizer in _swigfaiss:
_swigfaiss.Quantizer_swigregister(Quantizer)
class ProductQuantizer(Quantizer):
    r"""
     Product Quantizer.
    PQ is trained using k-means, minimizing the L2 distance to centroids.
    PQ supports L2 and Inner Product search, however the quantization error is
    biased towards L2 distance.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    M = property(_swigfaiss.ProductQuantizer_M_get, _swigfaiss.ProductQuantizer_M_set, doc=r"""number of subquantizers""")
    nbits = property(_swigfaiss.ProductQuantizer_nbits_get, _swigfaiss.ProductQuantizer_nbits_set, doc=r"""number of bits per quantization index""")
    dsub = property(_swigfaiss.ProductQuantizer_dsub_get, _swigfaiss.ProductQuantizer_dsub_set, doc=r"""dimensionality of each subvector""")
    ksub = property(_swigfaiss.ProductQuantizer_ksub_get, _swigfaiss.ProductQuantizer_ksub_set, doc=r"""number of centroids for each subquantizer""")
    verbose = property(_swigfaiss.ProductQuantizer_verbose_get, _swigfaiss.ProductQuantizer_verbose_set, doc=r"""verbose during training?""")
    Train_default = _swigfaiss.ProductQuantizer_Train_default
    Train_hot_start = _swigfaiss.ProductQuantizer_Train_hot_start
    r"""the centroids are already initialized"""
    Train_shared = _swigfaiss.ProductQuantizer_Train_shared
    r"""share dictionary across PQ segments"""
    Train_hypercube = _swigfaiss.ProductQuantizer_Train_hypercube
    r"""initialize centroids with nbits-D hypercube"""
    Train_hypercube_pca = _swigfaiss.ProductQuantizer_Train_hypercube_pca
    r"""initialize centroids with nbits-D hypercube"""
    train_type = property(_swigfaiss.ProductQuantizer_train_type_get, _swigfaiss.ProductQuantizer_train_type_set)
    cp = property(_swigfaiss.ProductQuantizer_cp_get, _swigfaiss.ProductQuantizer_cp_set, doc=r"""parameters used during clustering""")
    assign_index = property(_swigfaiss.ProductQuantizer_assign_index_get, _swigfaiss.ProductQuantizer_assign_index_set, doc=r"""
    if non-NULL, use this index for assignment (should be of size
    d / M)
    """)
    centroids = property(_swigfaiss.ProductQuantizer_centroids_get, _swigfaiss.ProductQuantizer_centroids_set, doc=r"""
    Centroid table, size M * ksub * dsub.
    Layout: (M, ksub, dsub)
    """)
    transposed_centroids = property(_swigfaiss.ProductQuantizer_transposed_centroids_get, _swigfaiss.ProductQuantizer_transposed_centroids_set, doc=r"""
    Transposed centroid table, size M * ksub * dsub.
    Layout: (dsub, M, ksub)
    """)
    centroids_sq_lengths = property(_swigfaiss.ProductQuantizer_centroids_sq_lengths_get, _swigfaiss.ProductQuantizer_centroids_sq_lengths_set, doc=r"""
    Squared lengths of centroids, size M * ksub
    Layout: (M, ksub)
    """)

    def get_centroids(self, m, i):
        r"""return the centroids associated with subvector m"""
        return _swigfaiss.ProductQuantizer_get_centroids(self, m, i)

    def train(self, n, x):
        return _swigfaiss.ProductQuantizer_train(self, n, x)

    def __init__(self, *args):
        _swigfaiss.ProductQuantizer_swiginit(self, _swigfaiss.new_ProductQuantizer(*args))

    def set_derived_values(self):
        r"""compute derived values when d, M and nbits have been set"""
        return _swigfaiss.ProductQuantizer_set_derived_values(self)

    def set_params(self, centroids, m):
        r"""Define the centroids for subquantizer m"""
        return _swigfaiss.ProductQuantizer_set_params(self, centroids, m)

    def compute_code(self, x, code):
        r"""Quantize one vector with the product quantizer"""
        return _swigfaiss.ProductQuantizer_compute_code(self, x, code)

    def compute_codes(self, x, codes, n):
        r"""same as compute_code for several vectors"""
        return _swigfaiss.ProductQuantizer_compute_codes(self, x, codes, n)

    def compute_codes_with_assign_index(self, x, codes, n):
        r"""
        speed up code assignment using assign_index
        (non-const because the index is changed)
        """
        return _swigfaiss.ProductQuantizer_compute_codes_with_assign_index(self, x, codes, n)

    def decode(self, *args):
        r"""decode a vector from a given code (or n vectors if third argument)"""
        return _swigfaiss.ProductQuantizer_decode(self, *args)

    def compute_code_from_distance_table(self, tab, code):
        r"""
        If we happen to have the distance tables precomputed, this is
        more efficient to compute the codes.
        """
        return _swigfaiss.ProductQuantizer_compute_code_from_distance_table(self, tab, code)

    def compute_distance_table(self, x, dis_table):
        r"""
         Compute distance table for one vector.

        The distance table for x = [x_0 x_1 .. x_(M-1)] is a M * ksub
        matrix that contains

          dis_table (m, j) = || x_m - c_(m, j)||^2
          for m = 0..M-1 and j = 0 .. ksub - 1

        where c_(m, j) is the centroid no j of sub-quantizer m.

        :type x: float
        :param x:         input vector size d
        :type dis_table: float
        :param dis_table: output table, size M * ksub
        """
        return _swigfaiss.ProductQuantizer_compute_distance_table(self, x, dis_table)

    def compute_inner_prod_table(self, x, dis_table):
        return _swigfaiss.ProductQuantizer_compute_inner_prod_table(self, x, dis_table)

    def compute_distance_tables(self, nx, x, dis_tables):
        r"""
         compute distance table for several vectors
        :type nx: int
        :param nx:        nb of input vectors
        :type x: float
        :param x:         input vector size nx * d
        :param dis_table: output table, size nx * M * ksub
        """
        return _swigfaiss.ProductQuantizer_compute_distance_tables(self, nx, x, dis_tables)

    def compute_inner_prod_tables(self, nx, x, dis_tables):
        return _swigfaiss.ProductQuantizer_compute_inner_prod_tables(self, nx, x, dis_tables)

    def search(self, x, nx, codes, ncodes, res, init_finalize_heap=True):
        r"""
         perform a search (L2 distance)
        :type x: float
        :param x:        query vectors, size nx * d
        :type nx: int
        :param nx:       nb of queries
        :type codes: uint8_t
        :param codes:    database codes, size ncodes * code_size
        :type ncodes: int
        :param ncodes:   nb of nb vectors
        :type res: :py:class:`float_maxheap_array_t`
        :param res:      heap array to store results (nh == nx)
        :type init_finalize_heap: boolean, optional
        :param init_finalize_heap:  initialize heap (input) and sort (output)?
        """
        return _swigfaiss.ProductQuantizer_search(self, x, nx, codes, ncodes, res, init_finalize_heap)

    def search_ip(self, x, nx, codes, ncodes, res, init_finalize_heap=True):
        r"""same as search, but with inner product similarity"""
        return _swigfaiss.ProductQuantizer_search_ip(self, x, nx, codes, ncodes, res, init_finalize_heap)
    sdc_table = property(_swigfaiss.ProductQuantizer_sdc_table_get, _swigfaiss.ProductQuantizer_sdc_table_set, doc=r"""Symmetric Distance Table""")

    def compute_sdc_table(self):
        return _swigfaiss.ProductQuantizer_compute_sdc_table(self)

    def search_sdc(self, qcodes, nq, bcodes, ncodes, res, init_finalize_heap=True):
        return _swigfaiss.ProductQuantizer_search_sdc(self, qcodes, nq, bcodes, ncodes, res, init_finalize_heap)

    def sync_transposed_centroids(self):
        r"""
        Sync transposed centroids with regular centroids. This call
        is needed if centroids were edited directly.
        """
        return _swigfaiss.ProductQuantizer_sync_transposed_centroids(self)

    def clear_transposed_centroids(self):
        r"""Clear transposed centroids table so ones are no longer used."""
        return _swigfaiss.ProductQuantizer_clear_transposed_centroids(self)
    __swig_destroy__ = _swigfaiss.delete_ProductQuantizer

# Register ProductQuantizer in _swigfaiss:
_swigfaiss.ProductQuantizer_swigregister(ProductQuantizer)
class PQEncoderGeneric(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    code = property(_swigfaiss.PQEncoderGeneric_code_get, _swigfaiss.PQEncoderGeneric_code_set, doc=r"""code for this vector""")
    offset = property(_swigfaiss.PQEncoderGeneric_offset_get, _swigfaiss.PQEncoderGeneric_offset_set)
    nbits = property(_swigfaiss.PQEncoderGeneric_nbits_get, doc=r"""number of bits per subquantizer index""")
    reg = property(_swigfaiss.PQEncoderGeneric_reg_get, _swigfaiss.PQEncoderGeneric_reg_set)

    def __init__(self, code, nbits, offset=0):
        _swigfaiss.PQEncoderGeneric_swiginit(self, _swigfaiss.new_PQEncoderGeneric(code, nbits, offset))

    def encode(self, x):
        return _swigfaiss.PQEncoderGeneric_encode(self, x)
    __swig_destroy__ = _swigfaiss.delete_PQEncoderGeneric

# Register PQEncoderGeneric in _swigfaiss:
_swigfaiss.PQEncoderGeneric_swigregister(PQEncoderGeneric)
class PQEncoder8(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    code = property(_swigfaiss.PQEncoder8_code_get, _swigfaiss.PQEncoder8_code_set)

    def __init__(self, code, nbits):
        _swigfaiss.PQEncoder8_swiginit(self, _swigfaiss.new_PQEncoder8(code, nbits))

    def encode(self, x):
        return _swigfaiss.PQEncoder8_encode(self, x)
    __swig_destroy__ = _swigfaiss.delete_PQEncoder8

# Register PQEncoder8 in _swigfaiss:
_swigfaiss.PQEncoder8_swigregister(PQEncoder8)
class PQEncoder16(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    code = property(_swigfaiss.PQEncoder16_code_get, _swigfaiss.PQEncoder16_code_set)

    def __init__(self, code, nbits):
        _swigfaiss.PQEncoder16_swiginit(self, _swigfaiss.new_PQEncoder16(code, nbits))

    def encode(self, x):
        return _swigfaiss.PQEncoder16_encode(self, x)
    __swig_destroy__ = _swigfaiss.delete_PQEncoder16

# Register PQEncoder16 in _swigfaiss:
_swigfaiss.PQEncoder16_swigregister(PQEncoder16)
class PQDecoderGeneric(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    code = property(_swigfaiss.PQDecoderGeneric_code_get, _swigfaiss.PQDecoderGeneric_code_set)
    offset = property(_swigfaiss.PQDecoderGeneric_offset_get, _swigfaiss.PQDecoderGeneric_offset_set)
    nbits = property(_swigfaiss.PQDecoderGeneric_nbits_get)
    mask = property(_swigfaiss.PQDecoderGeneric_mask_get)
    reg = property(_swigfaiss.PQDecoderGeneric_reg_get, _swigfaiss.PQDecoderGeneric_reg_set)

    def __init__(self, code, nbits):
        _swigfaiss.PQDecoderGeneric_swiginit(self, _swigfaiss.new_PQDecoderGeneric(code, nbits))

    def decode(self):
        return _swigfaiss.PQDecoderGeneric_decode(self)
    __swig_destroy__ = _swigfaiss.delete_PQDecoderGeneric

# Register PQDecoderGeneric in _swigfaiss:
_swigfaiss.PQDecoderGeneric_swigregister(PQDecoderGeneric)
class PQDecoder8(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nbits = _swigfaiss.PQDecoder8_nbits
    code = property(_swigfaiss.PQDecoder8_code_get, _swigfaiss.PQDecoder8_code_set)

    def __init__(self, code, nbits):
        _swigfaiss.PQDecoder8_swiginit(self, _swigfaiss.new_PQDecoder8(code, nbits))

    def decode(self):
        return _swigfaiss.PQDecoder8_decode(self)
    __swig_destroy__ = _swigfaiss.delete_PQDecoder8

# Register PQDecoder8 in _swigfaiss:
_swigfaiss.PQDecoder8_swigregister(PQDecoder8)
class PQDecoder16(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nbits = _swigfaiss.PQDecoder16_nbits
    code = property(_swigfaiss.PQDecoder16_code_get, _swigfaiss.PQDecoder16_code_set)

    def __init__(self, code, nbits):
        _swigfaiss.PQDecoder16_swiginit(self, _swigfaiss.new_PQDecoder16(code, nbits))

    def decode(self):
        return _swigfaiss.PQDecoder16_decode(self)
    __swig_destroy__ = _swigfaiss.delete_PQDecoder16

# Register PQDecoder16 in _swigfaiss:
_swigfaiss.PQDecoder16_swigregister(PQDecoder16)
class AdditiveQuantizer(Quantizer):
    r"""
     Abstract structure for additive quantizers

    Different from the product quantizer in which the decoded vector is the
    concatenation of M sub-vectors, additive quantizers sum M sub-vectors
    to get the decoded vector.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    M = property(_swigfaiss.AdditiveQuantizer_M_get, _swigfaiss.AdditiveQuantizer_M_set, doc=r"""number of codebooks""")
    nbits = property(_swigfaiss.AdditiveQuantizer_nbits_get, _swigfaiss.AdditiveQuantizer_nbits_set, doc=r"""bits for each step""")
    codebooks = property(_swigfaiss.AdditiveQuantizer_codebooks_get, _swigfaiss.AdditiveQuantizer_codebooks_set, doc=r"""codebooks""")
    codebook_offsets = property(_swigfaiss.AdditiveQuantizer_codebook_offsets_get, _swigfaiss.AdditiveQuantizer_codebook_offsets_set, doc=r"""
    codebook #1 is stored in rows codebook_offsets[i]:codebook_offsets[i+1]
    in the codebooks table of size total_codebook_size by d
    """)
    tot_bits = property(_swigfaiss.AdditiveQuantizer_tot_bits_get, _swigfaiss.AdditiveQuantizer_tot_bits_set, doc=r"""total number of bits (indexes + norms)""")
    norm_bits = property(_swigfaiss.AdditiveQuantizer_norm_bits_get, _swigfaiss.AdditiveQuantizer_norm_bits_set, doc=r"""bits allocated for the norms""")
    total_codebook_size = property(_swigfaiss.AdditiveQuantizer_total_codebook_size_get, _swigfaiss.AdditiveQuantizer_total_codebook_size_set, doc=r"""size of the codebook in vectors""")
    only_8bit = property(_swigfaiss.AdditiveQuantizer_only_8bit_get, _swigfaiss.AdditiveQuantizer_only_8bit_set, doc=r"""are all nbits = 8 (use faster decoder)""")
    verbose = property(_swigfaiss.AdditiveQuantizer_verbose_get, _swigfaiss.AdditiveQuantizer_verbose_set, doc=r"""verbose during training?""")
    is_trained = property(_swigfaiss.AdditiveQuantizer_is_trained_get, _swigfaiss.AdditiveQuantizer_is_trained_set, doc=r"""is trained or not""")
    norm_tabs = property(_swigfaiss.AdditiveQuantizer_norm_tabs_get, _swigfaiss.AdditiveQuantizer_norm_tabs_set, doc=r"""
    auxiliary data for ST_norm_lsq2x4 and ST_norm_rq2x4
    store norms of codebook entries for 4-bit fastscan
    """)
    qnorm = property(_swigfaiss.AdditiveQuantizer_qnorm_get, _swigfaiss.AdditiveQuantizer_qnorm_set, doc=r"""store and search norms""")

    def compute_codebook_tables(self):
        return _swigfaiss.AdditiveQuantizer_compute_codebook_tables(self)
    centroid_norms = property(_swigfaiss.AdditiveQuantizer_centroid_norms_get, _swigfaiss.AdditiveQuantizer_centroid_norms_set, doc=r"""norms of all codebook entries (size total_codebook_size)""")
    codebook_cross_products = property(_swigfaiss.AdditiveQuantizer_codebook_cross_products_get, _swigfaiss.AdditiveQuantizer_codebook_cross_products_set, doc=r"""
    dot products of all codebook entries with the previous codebooks
    size sum(codebook_offsets[m] * 2^nbits[m], m=0..M-1)
    """)
    max_mem_distances = property(_swigfaiss.AdditiveQuantizer_max_mem_distances_get, _swigfaiss.AdditiveQuantizer_max_mem_distances_set, doc=r"""
    norms and distance matrixes with beam search can get large, so use this
    to control for the amount of memory that can be allocated
    """)

    def encode_norm(self, norm):
        r"""encode a norm into norm_bits bits"""
        return _swigfaiss.AdditiveQuantizer_encode_norm(self, norm)

    def encode_qcint(self, x):
        r"""encode norm by non-uniform scalar quantization"""
        return _swigfaiss.AdditiveQuantizer_encode_qcint(self, x)

    def decode_qcint(self, c):
        r"""decode norm by non-uniform scalar quantization"""
        return _swigfaiss.AdditiveQuantizer_decode_qcint(self, c)
    ST_decompress = _swigfaiss.AdditiveQuantizer_ST_decompress
    r"""decompress database vector"""
    ST_LUT_nonorm = _swigfaiss.AdditiveQuantizer_ST_LUT_nonorm
    r"""
    use a LUT, don't include norms (OK for IP or
    normalized vectors)
    """
    ST_norm_from_LUT = _swigfaiss.AdditiveQuantizer_ST_norm_from_LUT
    r"""
    compute the norms from the look-up tables (cost
    is in O(M^2))
    """
    ST_norm_float = _swigfaiss.AdditiveQuantizer_ST_norm_float
    r"""use a LUT, and store float32 norm with the vectors"""
    ST_norm_qint8 = _swigfaiss.AdditiveQuantizer_ST_norm_qint8
    r"""use a LUT, and store 8bit-quantized norm"""
    ST_norm_qint4 = _swigfaiss.AdditiveQuantizer_ST_norm_qint4
    ST_norm_cqint8 = _swigfaiss.AdditiveQuantizer_ST_norm_cqint8
    r"""use a LUT, and store non-uniform quantized norm"""
    ST_norm_cqint4 = _swigfaiss.AdditiveQuantizer_ST_norm_cqint4
    ST_norm_lsq2x4 = _swigfaiss.AdditiveQuantizer_ST_norm_lsq2x4
    r"""
    use a 2x4 bits lsq as norm quantizer (for fast
    scan)
    """
    ST_norm_rq2x4 = _swigfaiss.AdditiveQuantizer_ST_norm_rq2x4
    r"""use a 2x4 bits rq as norm quantizer (for fast scan)"""
    ST_count = _swigfaiss.AdditiveQuantizer_ST_count

    def set_derived_values(self):
        r"""Train the norm quantizer"""
        return _swigfaiss.AdditiveQuantizer_set_derived_values(self)

    def train_norm(self, n, norms):
        return _swigfaiss.AdditiveQuantizer_train_norm(self, n, norms)

    def compute_codes(self, x, codes, n):
        return _swigfaiss.AdditiveQuantizer_compute_codes(self, x, codes, n)

    def compute_codes_add_centroids(self, x, codes, n, centroids=None):
        r"""
         Encode a set of vectors

        :type x: float
        :param x:      vectors to encode, size n * d
        :type codes: uint8_t
        :param codes:  output codes, size n * code_size
        :type centroids: float, optional
        :param centroids:  centroids to be added to x, size n * d
        """
        return _swigfaiss.AdditiveQuantizer_compute_codes_add_centroids(self, x, codes, n, centroids)

    def pack_codes(self, n, codes, packed_codes, ld_codes=-1, norms=None, centroids=None):
        r"""
         pack a series of code to bit-compact format

        :type codes: int
        :param codes:        codes to be packed, size n * code_size
        :type packed_codes: uint8_t
        :param packed_codes: output bit-compact codes
        :type ld_codes: int, optional
        :param ld_codes:     leading dimension of codes
        :type norms: float, optional
        :param norms:        norms of the vectors (size n). Will be computed if
                                needed but not provided
        :type centroids: float, optional
        :param centroids:    centroids to be added to x, size n * d
        """
        return _swigfaiss.AdditiveQuantizer_pack_codes(self, n, codes, packed_codes, ld_codes, norms, centroids)

    def decode(self, codes, x, n):
        r"""
         Decode a set of vectors

        :type codes: uint8_t
        :param codes:  codes to decode, size n * code_size
        :type x: float
        :param x:      output vectors, size n * d
        """
        return _swigfaiss.AdditiveQuantizer_decode(self, codes, x, n)

    def decode_unpacked(self, codes, x, n, ld_codes=-1):
        r"""
         Decode a set of vectors in non-packed format

        :type codes: int
        :param codes:  codes to decode, size n * ld_codes
        :type x: float
        :param x:      output vectors, size n * d
        """
        return _swigfaiss.AdditiveQuantizer_decode_unpacked(self, codes, x, n, ld_codes)
    search_type = property(_swigfaiss.AdditiveQuantizer_search_type_get, _swigfaiss.AdditiveQuantizer_search_type_set, doc=r"""Also determines what's in the codes""")
    norm_min = property(_swigfaiss.AdditiveQuantizer_norm_min_get, _swigfaiss.AdditiveQuantizer_norm_min_set, doc=r"""min/max for quantization of norms""")
    norm_max = property(_swigfaiss.AdditiveQuantizer_norm_max_get, _swigfaiss.AdditiveQuantizer_norm_max_set)

    def decode_64bit(self, n, x):
        r"""decoding function for a code in a 64-bit word"""
        return _swigfaiss.AdditiveQuantizer_decode_64bit(self, n, x)

    def compute_LUT(self, n, xq, LUT, alpha=1.0, ld_lut=-1):
        r"""
         Compute inner-product look-up tables. Used in the centroid search
        functions.

        :type xq: float
        :param xq:     query vector, size (n, d)
        :type LUT: float
        :param LUT:    look-up table, size (n, total_codebook_size)
        :type alpha: float, optional
        :param alpha:  compute alpha * inner-product
        :type ld_lut: int, optional
        :param ld_lut:  leading dimension of LUT
        """
        return _swigfaiss.AdditiveQuantizer_compute_LUT(self, n, xq, LUT, alpha, ld_lut)

    def knn_centroids_inner_product(self, n, xq, k, distances, labels):
        r"""exact IP search"""
        return _swigfaiss.AdditiveQuantizer_knn_centroids_inner_product(self, n, xq, k, distances, labels)

    def compute_centroid_norms(self, norms):
        r"""
         For L2 search we need the L2 norms of the centroids

        :type norms: float
        :param norms:    output norms table, size total_codebook_size
        """
        return _swigfaiss.AdditiveQuantizer_compute_centroid_norms(self, norms)

    def knn_centroids_L2(self, n, xq, k, distances, labels, centroid_norms):
        r"""Exact L2 search, with precomputed norms"""
        return _swigfaiss.AdditiveQuantizer_knn_centroids_L2(self, n, xq, k, distances, labels, centroid_norms)
    __swig_destroy__ = _swigfaiss.delete_AdditiveQuantizer

# Register AdditiveQuantizer in _swigfaiss:
_swigfaiss.AdditiveQuantizer_swigregister(AdditiveQuantizer)

def beam_search_encode_step(*args):
    r"""
     Encode a residual by sampling from a centroid table.

    This is a single encoding step the residual quantizer.
    It allows low-level access to the encoding function, exposed mainly for unit
    tests.

    :type n: int
    :param n:              number of vectors to handle
    :type residuals: float
    :param residuals:      vectors to encode, size (n, beam_size, d)
    :type cent: float
    :param cent:           centroids, size (K, d)
    :type beam_size: int
    :param beam_size:      input beam size
    :type m: int
    :param m:              size of the codes for the previous encoding steps
    :type codes: int
    :param codes:          code array for the previous steps of the beam (n,
        beam_size, m)
    :type new_beam_size: int
    :param new_beam_size:  output beam size (should be <= K * beam_size)
    :type new_codes: int
    :param new_codes:      output codes, size (n, new_beam_size, m + 1)
    :type new_residuals: float
    :param new_residuals:  output residuals, size (n, new_beam_size, d)
    :type new_distances: float
    :param new_distances:  output distances, size (n, new_beam_size)
    :type assign_index: :py:class:`Index`, optional
    :param assign_index:   if non-NULL, will be used to perform assignment
    """
    return _swigfaiss.beam_search_encode_step(*args)

def beam_search_encode_step_tab(*args):
    r"""
     Encode a set of vectors using their dot products with the codebooks

    :type K: int
    :param K:           number of vectors in the codebook
    :type n: int
    :param n:           nb of vectors to encode
    :type beam_size: int
    :param beam_size:   input beam size
    :type codebook_cross_norms: float
    :param codebook_cross_norms: inner product of this codebook with the m
                                    previously encoded codebooks
    :type codebook_offsets: int
    :param codebook_offsets:     offsets into codebook_cross_norms for each
                                    previous codebook
    :type query_cp: float
    :param query_cp:    dot products of query vectors with ???
    :type cent_norms_i: float
    :param cent_norms_i:  norms of centroids
    """
    return _swigfaiss.beam_search_encode_step_tab(*args)
class RefineBeamMemoryPool(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    new_codes = property(_swigfaiss.RefineBeamMemoryPool_new_codes_get, _swigfaiss.RefineBeamMemoryPool_new_codes_set)
    new_residuals = property(_swigfaiss.RefineBeamMemoryPool_new_residuals_get, _swigfaiss.RefineBeamMemoryPool_new_residuals_set)
    residuals = property(_swigfaiss.RefineBeamMemoryPool_residuals_get, _swigfaiss.RefineBeamMemoryPool_residuals_set)
    codes = property(_swigfaiss.RefineBeamMemoryPool_codes_get, _swigfaiss.RefineBeamMemoryPool_codes_set)
    distances = property(_swigfaiss.RefineBeamMemoryPool_distances_get, _swigfaiss.RefineBeamMemoryPool_distances_set)

    def __init__(self):
        _swigfaiss.RefineBeamMemoryPool_swiginit(self, _swigfaiss.new_RefineBeamMemoryPool())
    __swig_destroy__ = _swigfaiss.delete_RefineBeamMemoryPool

# Register RefineBeamMemoryPool in _swigfaiss:
_swigfaiss.RefineBeamMemoryPool_swigregister(RefineBeamMemoryPool)

def refine_beam_mp(rq, n, beam_size, x, out_beam_size, out_codes, out_residuals, out_distances, pool):
    return _swigfaiss.refine_beam_mp(rq, n, beam_size, x, out_beam_size, out_codes, out_residuals, out_distances, pool)
class RefineBeamLUTMemoryPool(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    new_codes = property(_swigfaiss.RefineBeamLUTMemoryPool_new_codes_get, _swigfaiss.RefineBeamLUTMemoryPool_new_codes_set)
    new_distances = property(_swigfaiss.RefineBeamLUTMemoryPool_new_distances_get, _swigfaiss.RefineBeamLUTMemoryPool_new_distances_set)
    codes = property(_swigfaiss.RefineBeamLUTMemoryPool_codes_get, _swigfaiss.RefineBeamLUTMemoryPool_codes_set)
    distances = property(_swigfaiss.RefineBeamLUTMemoryPool_distances_get, _swigfaiss.RefineBeamLUTMemoryPool_distances_set)

    def __init__(self):
        _swigfaiss.RefineBeamLUTMemoryPool_swiginit(self, _swigfaiss.new_RefineBeamLUTMemoryPool())
    __swig_destroy__ = _swigfaiss.delete_RefineBeamLUTMemoryPool

# Register RefineBeamLUTMemoryPool in _swigfaiss:
_swigfaiss.RefineBeamLUTMemoryPool_swigregister(RefineBeamLUTMemoryPool)

def refine_beam_LUT_mp(rq, n, query_norms, query_cp, out_beam_size, out_codes, out_distances, pool):
    return _swigfaiss.refine_beam_LUT_mp(rq, n, query_norms, query_cp, out_beam_size, out_codes, out_distances, pool)
class ComputeCodesAddCentroidsLUT0MemoryPool(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    codes = property(_swigfaiss.ComputeCodesAddCentroidsLUT0MemoryPool_codes_get, _swigfaiss.ComputeCodesAddCentroidsLUT0MemoryPool_codes_set)
    norms = property(_swigfaiss.ComputeCodesAddCentroidsLUT0MemoryPool_norms_get, _swigfaiss.ComputeCodesAddCentroidsLUT0MemoryPool_norms_set)
    distances = property(_swigfaiss.ComputeCodesAddCentroidsLUT0MemoryPool_distances_get, _swigfaiss.ComputeCodesAddCentroidsLUT0MemoryPool_distances_set)
    residuals = property(_swigfaiss.ComputeCodesAddCentroidsLUT0MemoryPool_residuals_get, _swigfaiss.ComputeCodesAddCentroidsLUT0MemoryPool_residuals_set)
    refine_beam_pool = property(_swigfaiss.ComputeCodesAddCentroidsLUT0MemoryPool_refine_beam_pool_get, _swigfaiss.ComputeCodesAddCentroidsLUT0MemoryPool_refine_beam_pool_set)

    def __init__(self):
        _swigfaiss.ComputeCodesAddCentroidsLUT0MemoryPool_swiginit(self, _swigfaiss.new_ComputeCodesAddCentroidsLUT0MemoryPool())
    __swig_destroy__ = _swigfaiss.delete_ComputeCodesAddCentroidsLUT0MemoryPool

# Register ComputeCodesAddCentroidsLUT0MemoryPool in _swigfaiss:
_swigfaiss.ComputeCodesAddCentroidsLUT0MemoryPool_swigregister(ComputeCodesAddCentroidsLUT0MemoryPool)

def compute_codes_add_centroids_mp_lut0(rq, x, codes_out, n, centroids, pool):
    return _swigfaiss.compute_codes_add_centroids_mp_lut0(rq, x, codes_out, n, centroids, pool)
class ComputeCodesAddCentroidsLUT1MemoryPool(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    codes = property(_swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_codes_get, _swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_codes_set)
    distances = property(_swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_distances_get, _swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_distances_set)
    query_norms = property(_swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_query_norms_get, _swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_query_norms_set)
    query_cp = property(_swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_query_cp_get, _swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_query_cp_set)
    residuals = property(_swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_residuals_get, _swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_residuals_set)
    refine_beam_lut_pool = property(_swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_refine_beam_lut_pool_get, _swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_refine_beam_lut_pool_set)

    def __init__(self):
        _swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_swiginit(self, _swigfaiss.new_ComputeCodesAddCentroidsLUT1MemoryPool())
    __swig_destroy__ = _swigfaiss.delete_ComputeCodesAddCentroidsLUT1MemoryPool

# Register ComputeCodesAddCentroidsLUT1MemoryPool in _swigfaiss:
_swigfaiss.ComputeCodesAddCentroidsLUT1MemoryPool_swigregister(ComputeCodesAddCentroidsLUT1MemoryPool)

def compute_codes_add_centroids_mp_lut1(rq, x, codes_out, n, centroids, pool):
    return _swigfaiss.compute_codes_add_centroids_mp_lut1(rq, x, codes_out, n, centroids, pool)
class ResidualQuantizer(AdditiveQuantizer):
    r"""
     Residual quantizer with variable number of bits per sub-quantizer

    The residual centroids are stored in a big cumulative centroid table.
    The codes are represented either as a non-compact table of size (n, M) or
    as the compact output (n, code_size).
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    train_type = property(_swigfaiss.ResidualQuantizer_train_type_get, _swigfaiss.ResidualQuantizer_train_type_set, doc=r"""Binary or of the Train_* flags below""")
    Train_default = _swigfaiss.ResidualQuantizer_Train_default
    r"""regular k-means (minimal amount of computation)"""
    Train_progressive_dim = _swigfaiss.ResidualQuantizer_Train_progressive_dim
    r"""progressive dim clustering (set by default)"""
    Train_refine_codebook = _swigfaiss.ResidualQuantizer_Train_refine_codebook
    r"""do a few iterations of codebook refinement after first level estimation"""
    niter_codebook_refine = property(_swigfaiss.ResidualQuantizer_niter_codebook_refine_get, _swigfaiss.ResidualQuantizer_niter_codebook_refine_set, doc=r"""number of iterations for codebook refinement.""")
    Train_top_beam = _swigfaiss.ResidualQuantizer_Train_top_beam
    r"""
    set this bit on train_type if beam is to be trained only on the
    first element of the beam (faster but less accurate)
    """
    Skip_codebook_tables = _swigfaiss.ResidualQuantizer_Skip_codebook_tables
    r"""
     set this bit to *not* automatically compute the codebook tables
    after training
    """
    max_beam_size = property(_swigfaiss.ResidualQuantizer_max_beam_size_get, _swigfaiss.ResidualQuantizer_max_beam_size_set, doc=r"""beam size used for training and for encoding""")
    use_beam_LUT = property(_swigfaiss.ResidualQuantizer_use_beam_LUT_get, _swigfaiss.ResidualQuantizer_use_beam_LUT_set, doc=r"""use LUT for beam search""")
    approx_topk_mode = property(_swigfaiss.ResidualQuantizer_approx_topk_mode_get, _swigfaiss.ResidualQuantizer_approx_topk_mode_set, doc=r"""
    Currently used mode of approximate min-k computations.
    Default value is EXACT_TOPK.
    """)
    cp = property(_swigfaiss.ResidualQuantizer_cp_get, _swigfaiss.ResidualQuantizer_cp_set, doc=r"""clustering parameters""")
    assign_index_factory = property(_swigfaiss.ResidualQuantizer_assign_index_factory_get, _swigfaiss.ResidualQuantizer_assign_index_factory_set, doc=r"""if non-NULL, use this index for assignment""")

    def __init__(self, *args):
        _swigfaiss.ResidualQuantizer_swiginit(self, _swigfaiss.new_ResidualQuantizer(*args))

    def train(self, n, x):
        r"""Train the residual quantizer"""
        return _swigfaiss.ResidualQuantizer_train(self, n, x)

    def initialize_from(self, other, skip_M=0):
        r"""Copy the M codebook levels from other, starting from skip_M"""
        return _swigfaiss.ResidualQuantizer_initialize_from(self, other, skip_M)

    def retrain_AQ_codebook(self, n, x):
        r"""
         Encode the vectors and compute codebook that minimizes the quantization
        error on these codes

        :type x: float
        :param x:      training vectors, size n * d
        :type n: int
        :param n:      nb of training vectors, n >= total_codebook_size
        :rtype: float
        :return: returns quantization error for the new codebook with old
            codes
        """
        return _swigfaiss.ResidualQuantizer_retrain_AQ_codebook(self, n, x)

    def compute_codes_add_centroids(self, x, codes, n, centroids=None):
        r"""
         Encode a set of vectors

        :type x: float
        :param x:      vectors to encode, size n * d
        :type codes: uint8_t
        :param codes:  output codes, size n * code_size
        :type centroids: float, optional
        :param centroids:  centroids to be added to x, size n * d
        """
        return _swigfaiss.ResidualQuantizer_compute_codes_add_centroids(self, x, codes, n, centroids)

    def refine_beam(self, n, beam_size, residuals, new_beam_size, new_codes, new_residuals=None, new_distances=None):
        r"""
         lower-level encode function

        :type n: int
        :param n:              number of vectors to handle
        :type residuals: float
        :param residuals:      vectors to encode, size (n, beam_size, d)
        :type beam_size: int
        :param beam_size:      input beam size
        :type new_beam_size: int
        :param new_beam_size:  output beam size (should be <= K * beam_size)
        :type new_codes: int
        :param new_codes:      output codes, size (n, new_beam_size, m + 1)
        :type new_residuals: float, optional
        :param new_residuals:  output residuals, size (n, new_beam_size, d)
        :type new_distances: float, optional
        :param new_distances:  output distances, size (n, new_beam_size)
        """
        return _swigfaiss.ResidualQuantizer_refine_beam(self, n, beam_size, residuals, new_beam_size, new_codes, new_residuals, new_distances)

    def refine_beam_LUT(self, n, query_norms, query_cp, new_beam_size, new_codes, new_distances=None):
        return _swigfaiss.ResidualQuantizer_refine_beam_LUT(self, n, query_norms, query_cp, new_beam_size, new_codes, new_distances)

    def memory_per_point(self, beam_size=-1):
        r"""
         Beam search can consume a lot of memory. This function estimates the
        amount of mem used by refine_beam to adjust the batch size

        :type beam_size: int, optional
        :param beam_size:  if != -1, override the beam size
        """
        return _swigfaiss.ResidualQuantizer_memory_per_point(self, beam_size)
    __swig_destroy__ = _swigfaiss.delete_ResidualQuantizer

# Register ResidualQuantizer in _swigfaiss:
_swigfaiss.ResidualQuantizer_swigregister(ResidualQuantizer)
class LocalSearchQuantizer(AdditiveQuantizer):
    r"""
     Implementation of LSQ/LSQ++ described in the following two papers:

    Revisiting additive quantization
    Julieta Martinez, et al. ECCV 2016

    LSQ++: Lower running time and higher recall in multi-codebook quantization
    Julieta Martinez, et al. ECCV 2018

    This implementation is mostly translated from the Julia implementations
    by Julieta Martinez:
    (https://github.com/una-dinosauria/local-search-quantization,
     https://github.com/una-dinosauria/Rayuela.jl)

    The trained codes are stored in `codebooks` which is called
    `centroids` in PQ and RQ.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    K = property(_swigfaiss.LocalSearchQuantizer_K_get, _swigfaiss.LocalSearchQuantizer_K_set, doc=r"""number of codes per codebook""")
    train_iters = property(_swigfaiss.LocalSearchQuantizer_train_iters_get, _swigfaiss.LocalSearchQuantizer_train_iters_set, doc=r"""number of iterations in training""")
    encode_ils_iters = property(_swigfaiss.LocalSearchQuantizer_encode_ils_iters_get, _swigfaiss.LocalSearchQuantizer_encode_ils_iters_set, doc=r"""iterations of local search in encoding""")
    train_ils_iters = property(_swigfaiss.LocalSearchQuantizer_train_ils_iters_get, _swigfaiss.LocalSearchQuantizer_train_ils_iters_set, doc=r"""iterations of local search in training""")
    icm_iters = property(_swigfaiss.LocalSearchQuantizer_icm_iters_get, _swigfaiss.LocalSearchQuantizer_icm_iters_set, doc=r"""number of iterations in icm""")
    p = property(_swigfaiss.LocalSearchQuantizer_p_get, _swigfaiss.LocalSearchQuantizer_p_set, doc=r"""temperature factor""")
    lambd = property(_swigfaiss.LocalSearchQuantizer_lambd_get, _swigfaiss.LocalSearchQuantizer_lambd_set, doc=r"""regularization factor""")
    chunk_size = property(_swigfaiss.LocalSearchQuantizer_chunk_size_get, _swigfaiss.LocalSearchQuantizer_chunk_size_set, doc=r"""nb of vectors to encode at a time""")
    random_seed = property(_swigfaiss.LocalSearchQuantizer_random_seed_get, _swigfaiss.LocalSearchQuantizer_random_seed_set, doc=r"""seed for random generator""")
    nperts = property(_swigfaiss.LocalSearchQuantizer_nperts_get, _swigfaiss.LocalSearchQuantizer_nperts_set, doc=r"""
    number of perturbation in each code
    if non-NULL, use this encoder to encode (owned by the object)
    """)
    icm_encoder_factory = property(_swigfaiss.LocalSearchQuantizer_icm_encoder_factory_get, _swigfaiss.LocalSearchQuantizer_icm_encoder_factory_set)
    update_codebooks_with_double = property(_swigfaiss.LocalSearchQuantizer_update_codebooks_with_double_get, _swigfaiss.LocalSearchQuantizer_update_codebooks_with_double_set)

    def __init__(self, *args):
        _swigfaiss.LocalSearchQuantizer_swiginit(self, _swigfaiss.new_LocalSearchQuantizer(*args))
    __swig_destroy__ = _swigfaiss.delete_LocalSearchQuantizer

    def train(self, n, x):
        return _swigfaiss.LocalSearchQuantizer_train(self, n, x)

    def compute_codes_add_centroids(self, x, codes, n, centroids=None):
        r"""
         Encode a set of vectors

        :type x: float
        :param x:      vectors to encode, size n * d
        :type codes: uint8_t
        :param codes:  output codes, size n * code_size
        :type n: int
        :param n:      number of vectors
        :type centroids: float, optional
        :param centroids:  centroids to be added to x, size n * d
        """
        return _swigfaiss.LocalSearchQuantizer_compute_codes_add_centroids(self, x, codes, n, centroids)

    def update_codebooks(self, x, codes, n):
        r"""
         Update codebooks given encodings

        :type x: float
        :param x:      training vectors, size n * d
        :type codes: int
        :param codes:  encoded training vectors, size n * M
        :type n: int
        :param n:      number of vectors
        """
        return _swigfaiss.LocalSearchQuantizer_update_codebooks(self, x, codes, n)

    def icm_encode(self, codes, x, n, ils_iters, gen):
        r"""
         Encode vectors given codebooks using iterative conditional mode (icm).

        :type codes: int
        :param codes:     output codes, size n * M
        :type x: float
        :param x:         vectors to encode, size n * d
        :type n: int
        :param n:         number of vectors
        :type ils_iters: int
        :param ils_iters: number of iterations of iterative local search
        """
        return _swigfaiss.LocalSearchQuantizer_icm_encode(self, codes, x, n, ils_iters, gen)

    def icm_encode_impl(self, codes, x, unaries, gen, n, ils_iters, verbose):
        return _swigfaiss.LocalSearchQuantizer_icm_encode_impl(self, codes, x, unaries, gen, n, ils_iters, verbose)

    def icm_encode_step(self, codes, unaries, binaries, n, n_iters):
        return _swigfaiss.LocalSearchQuantizer_icm_encode_step(self, codes, unaries, binaries, n, n_iters)

    def perturb_codes(self, codes, n, gen):
        r"""
         Add some perturbation to codes

        :type codes: int
        :param codes: codes to be perturbed, size n * M
        :type n: int
        :param n:     number of vectors
        """
        return _swigfaiss.LocalSearchQuantizer_perturb_codes(self, codes, n, gen)

    def perturb_codebooks(self, T, stddev, gen):
        r"""
         Add some perturbation to codebooks

        :type T: float
        :param T:         temperature of simulated annealing
        :type stddev: std::vector< float >
        :param stddev:    standard deviations of each dimension in training data
        """
        return _swigfaiss.LocalSearchQuantizer_perturb_codebooks(self, T, stddev, gen)

    def compute_binary_terms(self, binaries):
        r"""
         Compute binary terms

        :type binaries: float
        :param binaries: binary terms, size M * M * K * K
        """
        return _swigfaiss.LocalSearchQuantizer_compute_binary_terms(self, binaries)

    def compute_unary_terms(self, x, unaries, n):
        r"""
         Compute unary terms

        :type n: int
        :param n:       number of vectors
        :type x: float
        :param x:       vectors to encode, size n * d
        :type unaries: float
        :param unaries: unary terms, size n * M * K
        """
        return _swigfaiss.LocalSearchQuantizer_compute_unary_terms(self, x, unaries, n)

    def evaluate(self, codes, x, n, objs=None):
        r"""
         Helper function to compute reconstruction error

        :type codes: int
        :param codes: encoded codes, size n * M
        :type x: float
        :param x:     vectors to encode, size n * d
        :type n: int
        :param n:     number of vectors
        :type objs: float, optional
        :param objs:  if it is not null, store reconstruction
                                error of each vector into it, size n
        """
        return _swigfaiss.LocalSearchQuantizer_evaluate(self, codes, x, n, objs)

# Register LocalSearchQuantizer in _swigfaiss:
_swigfaiss.LocalSearchQuantizer_swigregister(LocalSearchQuantizer)
class IcmEncoder(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    binaries = property(_swigfaiss.IcmEncoder_binaries_get, _swigfaiss.IcmEncoder_binaries_set)
    verbose = property(_swigfaiss.IcmEncoder_verbose_get, _swigfaiss.IcmEncoder_verbose_set)
    lsq = property(_swigfaiss.IcmEncoder_lsq_get, _swigfaiss.IcmEncoder_lsq_set)

    def __init__(self, lsq):
        _swigfaiss.IcmEncoder_swiginit(self, _swigfaiss.new_IcmEncoder(lsq))
    __swig_destroy__ = _swigfaiss.delete_IcmEncoder

    def set_binary_term(self):
        return _swigfaiss.IcmEncoder_set_binary_term(self)

    def encode(self, codes, x, gen, n, ils_iters):
        r"""
         Encode vectors given codebooks

        :type codes: int
        :param codes:     output codes, size n * M
        :type x: float
        :param x:         vectors to encode, size n * d
        :type gen: std::mt19937
        :param gen:       random generator
        :type n: int
        :param n:         number of vectors
        :type ils_iters: int
        :param ils_iters: number of iterations of iterative local search
        """
        return _swigfaiss.IcmEncoder_encode(self, codes, x, gen, n, ils_iters)

# Register IcmEncoder in _swigfaiss:
_swigfaiss.IcmEncoder_swigregister(IcmEncoder)
class IcmEncoderFactory(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def get(self, lsq):
        return _swigfaiss.IcmEncoderFactory_get(self, lsq)
    __swig_destroy__ = _swigfaiss.delete_IcmEncoderFactory

    def __init__(self):
        _swigfaiss.IcmEncoderFactory_swiginit(self, _swigfaiss.new_IcmEncoderFactory())

# Register IcmEncoderFactory in _swigfaiss:
_swigfaiss.IcmEncoderFactory_swigregister(IcmEncoderFactory)
class LSQTimer(object):
    r"""
    A helper struct to count consuming time during training.
    It is NOT thread-safe.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    t = property(_swigfaiss.LSQTimer_t_get, _swigfaiss.LSQTimer_t_set)

    def __init__(self):
        _swigfaiss.LSQTimer_swiginit(self, _swigfaiss.new_LSQTimer())

    def get(self, name):
        return _swigfaiss.LSQTimer_get(self, name)

    def add(self, name, delta):
        return _swigfaiss.LSQTimer_add(self, name, delta)

    def reset(self):
        return _swigfaiss.LSQTimer_reset(self)
    __swig_destroy__ = _swigfaiss.delete_LSQTimer

# Register LSQTimer in _swigfaiss:
_swigfaiss.LSQTimer_swigregister(LSQTimer)
class LSQTimerScope(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    t0 = property(_swigfaiss.LSQTimerScope_t0_get, _swigfaiss.LSQTimerScope_t0_set)
    timer = property(_swigfaiss.LSQTimerScope_timer_get, _swigfaiss.LSQTimerScope_timer_set)
    name = property(_swigfaiss.LSQTimerScope_name_get, _swigfaiss.LSQTimerScope_name_set)
    finished = property(_swigfaiss.LSQTimerScope_finished_get, _swigfaiss.LSQTimerScope_finished_set)

    def __init__(self, timer, name):
        _swigfaiss.LSQTimerScope_swiginit(self, _swigfaiss.new_LSQTimerScope(timer, name))

    def finish(self):
        return _swigfaiss.LSQTimerScope_finish(self)
    __swig_destroy__ = _swigfaiss.delete_LSQTimerScope

# Register LSQTimerScope in _swigfaiss:
_swigfaiss.LSQTimerScope_swigregister(LSQTimerScope)
class ProductAdditiveQuantizer(AdditiveQuantizer):
    r"""
     Product Additive Quantizers

    The product additive quantizer is a variant of AQ and PQ.
    It first splits the vector space into multiple orthogonal sub-spaces
    just like PQ does. And then it quantizes each sub-space by an independent
    additive quantizer.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nsplits = property(_swigfaiss.ProductAdditiveQuantizer_nsplits_get, _swigfaiss.ProductAdditiveQuantizer_nsplits_set, doc=r"""number of sub-vectors we split a vector into""")
    quantizers = property(_swigfaiss.ProductAdditiveQuantizer_quantizers_get, _swigfaiss.ProductAdditiveQuantizer_quantizers_set)

    def __init__(self, *args):
        r"""
         Construct a product additive quantizer.

        The additive quantizers passed in will be cloned into the
        ProductAdditiveQuantizer object.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type aqs: std::vector< faiss::AdditiveQuantizer * >
        :param aqs:    sub-additive quantizers
        :type search_type: int, optional
        :param search_type:  AQ search type
        """
        _swigfaiss.ProductAdditiveQuantizer_swiginit(self, _swigfaiss.new_ProductAdditiveQuantizer(*args))
    __swig_destroy__ = _swigfaiss.delete_ProductAdditiveQuantizer

    def init(self, d, aqs, search_type):
        return _swigfaiss.ProductAdditiveQuantizer_init(self, d, aqs, search_type)

    def subquantizer(self, m):
        r"""Train the product additive quantizer"""
        return _swigfaiss.ProductAdditiveQuantizer_subquantizer(self, m)

    def train(self, n, x):
        return _swigfaiss.ProductAdditiveQuantizer_train(self, n, x)

    def compute_codes_add_centroids(self, x, codes, n, centroids=None):
        r"""
         Encode a set of vectors

        :type x: float
        :param x:      vectors to encode, size n * d
        :type codes: uint8_t
        :param codes:  output codes, size n * code_size
        :type centroids: float, optional
        :param centroids:  centroids to be added to x, size n * d
        """
        return _swigfaiss.ProductAdditiveQuantizer_compute_codes_add_centroids(self, x, codes, n, centroids)

    def compute_unpacked_codes(self, x, codes, n, centroids=None):
        return _swigfaiss.ProductAdditiveQuantizer_compute_unpacked_codes(self, x, codes, n, centroids)

    def decode_unpacked(self, codes, x, n, ld_codes=-1):
        r"""
         Decode a set of vectors in non-packed format

        :type codes: int
        :param codes:  codes to decode, size n * ld_codes
        :type x: float
        :param x:      output vectors, size n * d
        """
        return _swigfaiss.ProductAdditiveQuantizer_decode_unpacked(self, codes, x, n, ld_codes)

    def decode(self, codes, x, n):
        r"""
         Decode a set of vectors

        :type codes: uint8_t
        :param codes:  codes to decode, size n * code_size
        :type x: float
        :param x:      output vectors, size n * d
        """
        return _swigfaiss.ProductAdditiveQuantizer_decode(self, codes, x, n)

    def compute_LUT(self, n, xq, LUT, alpha=1.0, ld_lut=-1):
        r"""
         Compute inner-product look-up tables. Used in the search functions.

        :type xq: float
        :param xq:     query vector, size (n, d)
        :type LUT: float
        :param LUT:    look-up table, size (n, total_codebook_size)
        :type alpha: float, optional
        :param alpha:  compute alpha * inner-product
        :type ld_lut: int, optional
        :param ld_lut:  leading dimension of LUT
        """
        return _swigfaiss.ProductAdditiveQuantizer_compute_LUT(self, n, xq, LUT, alpha, ld_lut)

# Register ProductAdditiveQuantizer in _swigfaiss:
_swigfaiss.ProductAdditiveQuantizer_swigregister(ProductAdditiveQuantizer)
class ProductLocalSearchQuantizer(ProductAdditiveQuantizer):
    r"""Product Local Search Quantizer"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        r"""
         Construct a product LSQ object.

        :type d: int
        :param d:   dimensionality of the input vectors
        :type nsplits: int
        :param nsplits:  number of sub-vectors we split a vector into
        :type Msub: int
        :param Msub:     number of codebooks of each LSQ
        :type nbits: int
        :param nbits:    bits for each step
        :type search_type: int, optional
        :param search_type:  AQ search type
        """
        _swigfaiss.ProductLocalSearchQuantizer_swiginit(self, _swigfaiss.new_ProductLocalSearchQuantizer(*args))
    __swig_destroy__ = _swigfaiss.delete_ProductLocalSearchQuantizer

# Register ProductLocalSearchQuantizer in _swigfaiss:
_swigfaiss.ProductLocalSearchQuantizer_swigregister(ProductLocalSearchQuantizer)
class ProductResidualQuantizer(ProductAdditiveQuantizer):
    r"""Product Residual Quantizer"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        r"""
         Construct a product RQ object.

        :type d: int
        :param d:   dimensionality of the input vectors
        :type nsplits: int
        :param nsplits:  number of sub-vectors we split a vector into
        :type Msub: int
        :param Msub:     number of codebooks of each RQ
        :type nbits: int
        :param nbits:    bits for each step
        :type search_type: int, optional
        :param search_type:  AQ search type
        """
        _swigfaiss.ProductResidualQuantizer_swiginit(self, _swigfaiss.new_ProductResidualQuantizer(*args))
    __swig_destroy__ = _swigfaiss.delete_ProductResidualQuantizer

# Register ProductResidualQuantizer in _swigfaiss:
_swigfaiss.ProductResidualQuantizer_swigregister(ProductResidualQuantizer)
class CodePacker(object):
    r"""
    Packing consists in combining a fixed number of codes of constant size
    (code_size) into a block of data where they may (or may not) be interleaved
    for efficient consumption by distance computation kernels. This exists for
    the "fast_scan" indexes on CPU and for some GPU kernels.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    code_size = property(_swigfaiss.CodePacker_code_size_get, _swigfaiss.CodePacker_code_size_set)
    nvec = property(_swigfaiss.CodePacker_nvec_get, _swigfaiss.CodePacker_nvec_set)
    block_size = property(_swigfaiss.CodePacker_block_size_get, _swigfaiss.CodePacker_block_size_set)

    def pack_1(self, flat_code, offset, block):
        return _swigfaiss.CodePacker_pack_1(self, flat_code, offset, block)

    def unpack_1(self, block, offset, flat_code):
        return _swigfaiss.CodePacker_unpack_1(self, block, offset, flat_code)

    def pack_all(self, flat_codes, block):
        return _swigfaiss.CodePacker_pack_all(self, flat_codes, block)

    def unpack_all(self, block, flat_codes):
        return _swigfaiss.CodePacker_unpack_all(self, block, flat_codes)

    def clone(self):
        return _swigfaiss.CodePacker_clone(self)
    __swig_destroy__ = _swigfaiss.delete_CodePacker

# Register CodePacker in _swigfaiss:
_swigfaiss.CodePacker_swigregister(CodePacker)
class CodePackerFlat(CodePacker):
    r"""Trivial code packer where codes are stored one by one"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, code_size):
        _swigfaiss.CodePackerFlat_swiginit(self, _swigfaiss.new_CodePackerFlat(code_size))

    def clone(self):
        return _swigfaiss.CodePackerFlat_clone(self)

    def pack_1(self, flat_code, offset, block):
        return _swigfaiss.CodePackerFlat_pack_1(self, flat_code, offset, block)

    def unpack_1(self, block, offset, flat_code):
        return _swigfaiss.CodePackerFlat_unpack_1(self, block, offset, flat_code)

    def pack_all(self, flat_codes, block):
        return _swigfaiss.CodePackerFlat_pack_all(self, flat_codes, block)

    def unpack_all(self, block, flat_codes):
        return _swigfaiss.CodePackerFlat_unpack_all(self, block, flat_codes)
    __swig_destroy__ = _swigfaiss.delete_CodePackerFlat

# Register CodePackerFlat in _swigfaiss:
_swigfaiss.CodePackerFlat_swigregister(CodePackerFlat)
class Panorama(object):
    r"""
    Implements the core logic of Panorama-based refinement.
    arXiv: https://arxiv.org/abs/2510.00566

    Panorama partitions the dimensions of all vectors into L contiguous levels.
    During the refinement stage of ANNS, it computes distances between the query
    and its candidates level-by-level. After processing each level, it prunes the
    candidates whose lower bound exceeds the k-th best distance.

    In order to enable speedups, the dimensions (or codes) of each vector are
    stored in a batched, level-major manner. Within each batch of b vectors, the
    dimensions corresponding to level 1 will be stored first (for all elements in
    that batch), followed by level 2, and so on. This allows for efficient memory
    access patterns.

    Coupled with the appropriate orthogonal PreTransform (e.g. PCA, Cayley,
    etc.), Panorama can prune the vast majority of dimensions, greatly
    accelerating the refinement stage.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    kDefaultBatchSize = _swigfaiss.Panorama_kDefaultBatchSize
    d = property(_swigfaiss.Panorama_d_get, _swigfaiss.Panorama_d_set)
    code_size = property(_swigfaiss.Panorama_code_size_get, _swigfaiss.Panorama_code_size_set)
    n_levels = property(_swigfaiss.Panorama_n_levels_get, _swigfaiss.Panorama_n_levels_set)
    level_width = property(_swigfaiss.Panorama_level_width_get, _swigfaiss.Panorama_level_width_set)
    level_width_floats = property(_swigfaiss.Panorama_level_width_floats_get, _swigfaiss.Panorama_level_width_floats_set)
    batch_size = property(_swigfaiss.Panorama_batch_size_get, _swigfaiss.Panorama_batch_size_set)

    def __init__(self, code_size, n_levels, batch_size):
        _swigfaiss.Panorama_swiginit(self, _swigfaiss.new_Panorama(code_size, n_levels, batch_size))

    def set_derived_values(self):
        return _swigfaiss.Panorama_set_derived_values(self)

    def copy_codes_to_level_layout(self, codes, offset, n_entry, code):
        r"""
        Helper method to copy codes into level-oriented batch layout at a given
        offset in the list.
        """
        return _swigfaiss.Panorama_copy_codes_to_level_layout(self, codes, offset, n_entry, code)

    def compute_cumulative_sums(self, cumsum_base, offset, n_entry, vectors):
        r"""
        Helper method to compute the cumulative sums of the codes.
        The cumsums also follow the level-oriented batch layout to minimize the
        number of random memory accesses.
        """
        return _swigfaiss.Panorama_compute_cumulative_sums(self, cumsum_base, offset, n_entry, vectors)

    def compute_query_cum_sums(self, query, query_cum_sums):
        r"""Compute the cumulative sums of the query vector."""
        return _swigfaiss.Panorama_compute_query_cum_sums(self, query, query_cum_sums)

    def copy_entry(self, dest_codes, src_codes, dest_cum_sums, src_cum_sums, dest_idx, src_idx):
        r"""Copy single entry (code and cum_sum) from one location to another."""
        return _swigfaiss.Panorama_copy_entry(self, dest_codes, src_codes, dest_cum_sums, src_cum_sums, dest_idx, src_idx)

    def reconstruct(self, key, recons, codes_base):
        r"""
        Panorama's core progressive filtering algorithm:
        Process vectors in batches for cache efficiency. For each batch:
        1. Apply ID selection filter and initialize distances
        (||y||^2 + ||x||^2).
        2. Maintain an "active set" of candidate indices that haven't been
        pruned yet.
        3. For each level, refine distances incrementally and compact the active
        set:
           - Compute dot product for current level: exact_dist -= 2*<x,y>.
           - Use Cauchy-Schwarz bound on remaining levels to get lower bound
           - Prune candidates whose lower bound exceeds k-th best distance.
           - Compact active_indices to remove pruned candidates (branchless)
        4. After all levels, survivors are exact distances; update heap.
        This achieves early termination while maintaining SIMD-friendly
        sequential access patterns in the level-oriented storage layout.
        """
        return _swigfaiss.Panorama_reconstruct(self, key, recons, codes_base)
    __swig_destroy__ = _swigfaiss.delete_Panorama

# Register Panorama in _swigfaiss:
_swigfaiss.Panorama_swigregister(Panorama)
class PanoramaStats(object):
    r"""
    Statistics are not robust to internal threading nor to
    concurrent Panorama searches. Use these values in a
    single-threaded context to accurately gauge Panorama's
    pruning effectiveness.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    total_dims_scanned = property(_swigfaiss.PanoramaStats_total_dims_scanned_get, _swigfaiss.PanoramaStats_total_dims_scanned_set)
    total_dims = property(_swigfaiss.PanoramaStats_total_dims_get, _swigfaiss.PanoramaStats_total_dims_set)
    ratio_dims_scanned = property(_swigfaiss.PanoramaStats_ratio_dims_scanned_get, _swigfaiss.PanoramaStats_ratio_dims_scanned_set)

    def __init__(self):
        _swigfaiss.PanoramaStats_swiginit(self, _swigfaiss.new_PanoramaStats())

    def reset(self):
        return _swigfaiss.PanoramaStats_reset(self)

    def add(self, other):
        return _swigfaiss.PanoramaStats_add(self, other)
    __swig_destroy__ = _swigfaiss.delete_PanoramaStats

# Register PanoramaStats in _swigfaiss:
_swigfaiss.PanoramaStats_swigregister(PanoramaStats)
class VectorTransform(object):
    r"""Any transformation applied on a set of vectors"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    d_in = property(_swigfaiss.VectorTransform_d_in_get, _swigfaiss.VectorTransform_d_in_set)
    d_out = property(_swigfaiss.VectorTransform_d_out_get, _swigfaiss.VectorTransform_d_out_set, doc=r"""input dimension""")
    is_trained = property(_swigfaiss.VectorTransform_is_trained_get, _swigfaiss.VectorTransform_is_trained_set, doc=r"""
    set if the VectorTransform does not require training, or if
    training is done already
    """)

    def train(self, n, x):
        r"""
         Perform training on a representative set of vectors. Does
        nothing by default.

        :type n: int
        :param n:      nb of training vectors
        :type x: float
        :param x:      training vectors, size n * d
        """
        return _swigfaiss.VectorTransform_train(self, n, x)

    def apply(self, n, x):
        r"""
         apply the transformation and return the result in an allocated pointer
        :type n: int
        :param n: number of vectors to transform
        :type x: float
        :param x: input vectors, size n * d_in
        :rtype: float
        :return: output vectors, size n * d_out
        """
        return _swigfaiss.VectorTransform_apply(self, n, x)

    def apply_noalloc(self, n, x, xt):
        r"""
         apply the transformation and return the result in a provided matrix
        :type n: int
        :param n: number of vectors to transform
        :type x: float
        :param x: input vectors, size n * d_in
        :type xt: float
        :param xt: output vectors, size n * d_out
        """
        return _swigfaiss.VectorTransform_apply_noalloc(self, n, x, xt)

    def reverse_transform(self, n, xt, x):
        r"""
        reverse transformation. May not be implemented or may return
        approximate result
        """
        return _swigfaiss.VectorTransform_reverse_transform(self, n, xt, x)

    def check_identical(self, other):
        return _swigfaiss.VectorTransform_check_identical(self, other)
    __swig_destroy__ = _swigfaiss.delete_VectorTransform

# Register VectorTransform in _swigfaiss:
_swigfaiss.VectorTransform_swigregister(VectorTransform)
class LinearTransform(VectorTransform):
    r"""
     Generic linear transformation, with bias term applied on output
    y = A * x + b
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    have_bias = property(_swigfaiss.LinearTransform_have_bias_get, _swigfaiss.LinearTransform_have_bias_set)
    is_orthonormal = property(_swigfaiss.LinearTransform_is_orthonormal_get, _swigfaiss.LinearTransform_is_orthonormal_set, doc=r"""
    whether to use the bias term
     check if matrix A is orthonormal (enables reverse_transform)
    """)
    A = property(_swigfaiss.LinearTransform_A_get, _swigfaiss.LinearTransform_A_set, doc=r"""Transformation matrix, size d_out * d_in""")
    b = property(_swigfaiss.LinearTransform_b_get, _swigfaiss.LinearTransform_b_set, doc=r"""bias vector, size d_out""")

    def __init__(self, din=0, dout=0, have_bias_in=False):
        r"""both d_in > d_out and d_out < d_in are supported"""
        _swigfaiss.LinearTransform_swiginit(self, _swigfaiss.new_LinearTransform(din, dout, have_bias_in))

    def apply_noalloc(self, n, x, xt):
        r"""same as apply, but result is pre-allocated"""
        return _swigfaiss.LinearTransform_apply_noalloc(self, n, x, xt)

    def transform_transpose(self, n, y, x):
        r"""
        compute x = A^T * (x - b)
        is reverse transform if A has orthonormal lines
        """
        return _swigfaiss.LinearTransform_transform_transpose(self, n, y, x)

    def reverse_transform(self, n, xt, x):
        r"""works only if is_orthonormal"""
        return _swigfaiss.LinearTransform_reverse_transform(self, n, xt, x)

    def set_is_orthonormal(self):
        r"""compute A^T * A to set the is_orthonormal flag"""
        return _swigfaiss.LinearTransform_set_is_orthonormal(self)
    verbose = property(_swigfaiss.LinearTransform_verbose_get, _swigfaiss.LinearTransform_verbose_set)

    def print_if_verbose(self, name, mat, n, d):
        return _swigfaiss.LinearTransform_print_if_verbose(self, name, mat, n, d)

    def check_identical(self, other):
        return _swigfaiss.LinearTransform_check_identical(self, other)
    __swig_destroy__ = _swigfaiss.delete_LinearTransform

# Register LinearTransform in _swigfaiss:
_swigfaiss.LinearTransform_swigregister(LinearTransform)
class RandomRotationMatrix(LinearTransform):
    r"""Randomly rotate a set of vectors"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def init(self, seed):
        r"""must be called before the transform is used"""
        return _swigfaiss.RandomRotationMatrix_init(self, seed)

    def train(self, n, x):
        return _swigfaiss.RandomRotationMatrix_train(self, n, x)

    def __init__(self, *args):
        r"""both d_in > d_out and d_out < d_in are supported"""
        _swigfaiss.RandomRotationMatrix_swiginit(self, _swigfaiss.new_RandomRotationMatrix(*args))
    __swig_destroy__ = _swigfaiss.delete_RandomRotationMatrix

# Register RandomRotationMatrix in _swigfaiss:
_swigfaiss.RandomRotationMatrix_swigregister(RandomRotationMatrix)
class HadamardRotation(VectorTransform):
    r"""
     Three rounds of random sign-flip + Fast Walsh-Hadamard Transform.
    Produces a pseudo-random rotation in O(d log d) time.
    d_out is the smallest power of 2 >= d_in (zero-padded as needed).
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    seed = property(_swigfaiss.HadamardRotation_seed_get, _swigfaiss.HadamardRotation_seed_set)
    signs1 = property(_swigfaiss.HadamardRotation_signs1_get, _swigfaiss.HadamardRotation_signs1_set, doc=r"""Sign-flip vectors, each of size d_out, generated from seed.""")
    signs2 = property(_swigfaiss.HadamardRotation_signs2_get, _swigfaiss.HadamardRotation_signs2_set)
    signs3 = property(_swigfaiss.HadamardRotation_signs3_get, _swigfaiss.HadamardRotation_signs3_set)

    def init(self, seed_in):
        return _swigfaiss.HadamardRotation_init(self, seed_in)

    def train(self, n, x):
        return _swigfaiss.HadamardRotation_train(self, n, x)

    def apply_noalloc(self, n, x, xt):
        return _swigfaiss.HadamardRotation_apply_noalloc(self, n, x, xt)

    def check_identical(self, other):
        return _swigfaiss.HadamardRotation_check_identical(self, other)

    def __init__(self, *args):
        _swigfaiss.HadamardRotation_swiginit(self, _swigfaiss.new_HadamardRotation(*args))
    __swig_destroy__ = _swigfaiss.delete_HadamardRotation

# Register HadamardRotation in _swigfaiss:
_swigfaiss.HadamardRotation_swigregister(HadamardRotation)
class PCAMatrix(LinearTransform):
    r"""
    Applies a principal component analysis on a set of vectors,
    with optionally whitening and random rotation.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    eigen_power = property(_swigfaiss.PCAMatrix_eigen_power_get, _swigfaiss.PCAMatrix_eigen_power_set, doc=r"""
     after transformation the components are multiplied by
    eigenvalues^eigen_power

    =0: no whitening
    =-0.5: full whitening
    """)
    epsilon = property(_swigfaiss.PCAMatrix_epsilon_get, _swigfaiss.PCAMatrix_epsilon_set, doc=r"""value added to eigenvalues to avoid division by 0 when whitening""")
    random_rotation = property(_swigfaiss.PCAMatrix_random_rotation_get, _swigfaiss.PCAMatrix_random_rotation_set, doc=r"""random rotation after PCA""")
    max_points_per_d = property(_swigfaiss.PCAMatrix_max_points_per_d_get, _swigfaiss.PCAMatrix_max_points_per_d_set, doc=r"""ratio between # training vectors and dimension""")
    balanced_bins = property(_swigfaiss.PCAMatrix_balanced_bins_get, _swigfaiss.PCAMatrix_balanced_bins_set, doc=r"""try to distribute output eigenvectors in this many bins""")
    mean = property(_swigfaiss.PCAMatrix_mean_get, _swigfaiss.PCAMatrix_mean_set, doc=r"""Mean, size d_in""")
    eigenvalues = property(_swigfaiss.PCAMatrix_eigenvalues_get, _swigfaiss.PCAMatrix_eigenvalues_set, doc=r"""eigenvalues of covariance matrix (= squared singular values)""")
    PCAMat = property(_swigfaiss.PCAMatrix_PCAMat_get, _swigfaiss.PCAMatrix_PCAMat_set, doc=r"""PCA matrix, size d_in * d_in""")

    def __init__(self, din=0, dout=0, eigen_power_in=0, random_rotation_in=False):
        _swigfaiss.PCAMatrix_swiginit(self, _swigfaiss.new_PCAMatrix(din, dout, eigen_power_in, random_rotation_in))

    def train(self, n, x):
        r"""
        train on n vectors. If n < d_in then the eigenvector matrix
        will be completed with 0s
        """
        return _swigfaiss.PCAMatrix_train(self, n, x)

    def copy_from(self, other):
        r"""copy pre-trained PCA matrix"""
        return _swigfaiss.PCAMatrix_copy_from(self, other)

    def prepare_Ab(self):
        r"""called after mean, PCAMat and eigenvalues are computed"""
        return _swigfaiss.PCAMatrix_prepare_Ab(self)
    __swig_destroy__ = _swigfaiss.delete_PCAMatrix

# Register PCAMatrix in _swigfaiss:
_swigfaiss.PCAMatrix_swigregister(PCAMatrix)
class ITQMatrix(LinearTransform):
    r"""
     ITQ implementation from

        Iterative quantization: A procrustean approach to learning binary codes
        for large-scale image retrieval,

    Yunchao Gong, Svetlana Lazebnik, Albert Gordo, Florent Perronnin,
    PAMI'12.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    max_iter = property(_swigfaiss.ITQMatrix_max_iter_get, _swigfaiss.ITQMatrix_max_iter_set)
    seed = property(_swigfaiss.ITQMatrix_seed_get, _swigfaiss.ITQMatrix_seed_set)
    init_rotation = property(_swigfaiss.ITQMatrix_init_rotation_get, _swigfaiss.ITQMatrix_init_rotation_set)

    def __init__(self, d=0):
        _swigfaiss.ITQMatrix_swiginit(self, _swigfaiss.new_ITQMatrix(d))

    def train(self, n, x):
        return _swigfaiss.ITQMatrix_train(self, n, x)
    __swig_destroy__ = _swigfaiss.delete_ITQMatrix

# Register ITQMatrix in _swigfaiss:
_swigfaiss.ITQMatrix_swigregister(ITQMatrix)
class ITQTransform(VectorTransform):
    r"""The full ITQ transform, including normalizations and PCA transformation"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    mean = property(_swigfaiss.ITQTransform_mean_get, _swigfaiss.ITQTransform_mean_set)
    do_pca = property(_swigfaiss.ITQTransform_do_pca_get, _swigfaiss.ITQTransform_do_pca_set)
    itq = property(_swigfaiss.ITQTransform_itq_get, _swigfaiss.ITQTransform_itq_set)
    max_train_per_dim = property(_swigfaiss.ITQTransform_max_train_per_dim_get, _swigfaiss.ITQTransform_max_train_per_dim_set, doc=r"""max training points per dimension""")
    pca_then_itq = property(_swigfaiss.ITQTransform_pca_then_itq_get, _swigfaiss.ITQTransform_pca_then_itq_set)

    def __init__(self, din=0, dout=0, do_pca_in=False):
        _swigfaiss.ITQTransform_swiginit(self, _swigfaiss.new_ITQTransform(din, dout, do_pca_in))

    def train(self, n, x):
        return _swigfaiss.ITQTransform_train(self, n, x)

    def apply_noalloc(self, n, x, xt):
        return _swigfaiss.ITQTransform_apply_noalloc(self, n, x, xt)

    def check_identical(self, other):
        return _swigfaiss.ITQTransform_check_identical(self, other)
    __swig_destroy__ = _swigfaiss.delete_ITQTransform

# Register ITQTransform in _swigfaiss:
_swigfaiss.ITQTransform_swigregister(ITQTransform)
class OPQMatrix(LinearTransform):
    r"""
     Applies a rotation to align the dimensions with a PQ to minimize
     the reconstruction error. Can be used before an IndexPQ or an
     IndexIVFPQ. The method is the non-parametric version described in:

    "Optimized Product Quantization for Approximate Nearest Neighbor Search"
    Tiezheng Ge, Kaiming He, Qifa Ke, Jian Sun, CVPR'13
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    M = property(_swigfaiss.OPQMatrix_M_get, _swigfaiss.OPQMatrix_M_set, doc=r"""nb of subquantizers""")
    niter = property(_swigfaiss.OPQMatrix_niter_get, _swigfaiss.OPQMatrix_niter_set, doc=r"""Number of outer training iterations""")
    niter_pq = property(_swigfaiss.OPQMatrix_niter_pq_get, _swigfaiss.OPQMatrix_niter_pq_set, doc=r"""Number of training iterations for the PQ""")
    niter_pq_0 = property(_swigfaiss.OPQMatrix_niter_pq_0_get, _swigfaiss.OPQMatrix_niter_pq_0_set, doc=r"""same, for the first outer iteration""")
    max_train_points = property(_swigfaiss.OPQMatrix_max_train_points_get, _swigfaiss.OPQMatrix_max_train_points_set, doc=r"""if there are too many training points, resample""")
    verbose = property(_swigfaiss.OPQMatrix_verbose_get, _swigfaiss.OPQMatrix_verbose_set)
    pq = property(_swigfaiss.OPQMatrix_pq_get, _swigfaiss.OPQMatrix_pq_set, doc=r"""
    if non-NULL, use this product quantizer for training
    should be constructed with (d_out, M, _)
    """)

    def __init__(self, d=0, M_in=1, d2=-1):
        r"""if d2 != -1, output vectors of this dimension"""
        _swigfaiss.OPQMatrix_swiginit(self, _swigfaiss.new_OPQMatrix(d, M_in, d2))

    def train(self, n, x):
        return _swigfaiss.OPQMatrix_train(self, n, x)
    __swig_destroy__ = _swigfaiss.delete_OPQMatrix

# Register OPQMatrix in _swigfaiss:
_swigfaiss.OPQMatrix_swigregister(OPQMatrix)
class RemapDimensionsTransform(VectorTransform):
    r"""
     remap dimensions for input vectors, possibly inserting 0s
    strictly speaking this is also a linear transform but we don't want
    to compute it with matrix multiplies
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    map = property(_swigfaiss.RemapDimensionsTransform_map_get, _swigfaiss.RemapDimensionsTransform_map_set, doc=r"""
    map from output dimension to input, size d_out
    -1 -> set output to 0
    """)

    def apply_noalloc(self, n, x, xt):
        return _swigfaiss.RemapDimensionsTransform_apply_noalloc(self, n, x, xt)

    def reverse_transform(self, n, xt, x):
        r"""reverse transform correct only when the mapping is a permutation"""
        return _swigfaiss.RemapDimensionsTransform_reverse_transform(self, n, xt, x)

    def __init__(self, *args):
        r"""
        *Overload 1:*
        remap input to output, skipping or inserting dimensions as needed
        if uniform: distribute dimensions uniformly
        otherwise just take the d_out first ones.

        |

        *Overload 2:*
        remap input to output, skipping or inserting dimensions as needed
        if uniform: distribute dimensions uniformly
        otherwise just take the d_out first ones.
        """
        _swigfaiss.RemapDimensionsTransform_swiginit(self, _swigfaiss.new_RemapDimensionsTransform(*args))

    def check_identical(self, other):
        return _swigfaiss.RemapDimensionsTransform_check_identical(self, other)
    __swig_destroy__ = _swigfaiss.delete_RemapDimensionsTransform

# Register RemapDimensionsTransform in _swigfaiss:
_swigfaiss.RemapDimensionsTransform_swigregister(RemapDimensionsTransform)
class NormalizationTransform(VectorTransform):
    r"""per-vector normalization"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    norm = property(_swigfaiss.NormalizationTransform_norm_get, _swigfaiss.NormalizationTransform_norm_set)

    def __init__(self, *args):
        _swigfaiss.NormalizationTransform_swiginit(self, _swigfaiss.new_NormalizationTransform(*args))

    def apply_noalloc(self, n, x, xt):
        return _swigfaiss.NormalizationTransform_apply_noalloc(self, n, x, xt)

    def reverse_transform(self, n, xt, x):
        r"""Identity transform since norm is not revertible"""
        return _swigfaiss.NormalizationTransform_reverse_transform(self, n, xt, x)

    def check_identical(self, other):
        return _swigfaiss.NormalizationTransform_check_identical(self, other)
    __swig_destroy__ = _swigfaiss.delete_NormalizationTransform

# Register NormalizationTransform in _swigfaiss:
_swigfaiss.NormalizationTransform_swigregister(NormalizationTransform)
class CenteringTransform(VectorTransform):
    r"""Subtract the mean of each component from the vectors."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    mean = property(_swigfaiss.CenteringTransform_mean_get, _swigfaiss.CenteringTransform_mean_set, doc=r"""Mean, size d_in = d_out""")

    def __init__(self, d=0):
        _swigfaiss.CenteringTransform_swiginit(self, _swigfaiss.new_CenteringTransform(d))

    def train(self, n, x):
        r"""train on n vectors."""
        return _swigfaiss.CenteringTransform_train(self, n, x)

    def apply_noalloc(self, n, x, xt):
        r"""subtract the mean"""
        return _swigfaiss.CenteringTransform_apply_noalloc(self, n, x, xt)

    def reverse_transform(self, n, xt, x):
        r"""add the mean"""
        return _swigfaiss.CenteringTransform_reverse_transform(self, n, xt, x)

    def check_identical(self, other):
        return _swigfaiss.CenteringTransform_check_identical(self, other)
    __swig_destroy__ = _swigfaiss.delete_CenteringTransform

# Register CenteringTransform in _swigfaiss:
_swigfaiss.CenteringTransform_swigregister(CenteringTransform)
class SearchParametersPreTransform(SearchParameters):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    index_params = property(_swigfaiss.SearchParametersPreTransform_index_params_get, _swigfaiss.SearchParametersPreTransform_index_params_set)

    def __init__(self):
        _swigfaiss.SearchParametersPreTransform_swiginit(self, _swigfaiss.new_SearchParametersPreTransform())
    __swig_destroy__ = _swigfaiss.delete_SearchParametersPreTransform

# Register SearchParametersPreTransform in _swigfaiss:
_swigfaiss.SearchParametersPreTransform_swigregister(SearchParametersPreTransform)
class IndexPreTransform(Index):
    r"""
    Index that applies a LinearTransform transform on vectors before
    handing them over to a sub-index
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    chain = property(_swigfaiss.IndexPreTransform_chain_get, _swigfaiss.IndexPreTransform_chain_set)
    index = property(_swigfaiss.IndexPreTransform_index_get, _swigfaiss.IndexPreTransform_index_set, doc=r"""chain of transforms""")
    own_fields = property(_swigfaiss.IndexPreTransform_own_fields_get, _swigfaiss.IndexPreTransform_own_fields_set, doc=r"""the sub-index""")

    def __init__(self, *args):
        r"""
        *Overload 1:*
        whether pointers are deleted in destructor

        |

        *Overload 2:*
         ltrans is the last transform before the index
        """
        _swigfaiss.IndexPreTransform_swiginit(self, _swigfaiss.new_IndexPreTransform(*args))

    def prepend_transform(self, ltrans):
        return _swigfaiss.IndexPreTransform_prepend_transform(self, ltrans)

    def train(self, n, x):
        return _swigfaiss.IndexPreTransform_train(self, n, x)

    def add(self, n, x):
        return _swigfaiss.IndexPreTransform_add(self, n, x)

    def add_with_ids(self, n, x, xids):
        return _swigfaiss.IndexPreTransform_add_with_ids(self, n, x, xids)

    def reset(self):
        return _swigfaiss.IndexPreTransform_reset(self)

    def remove_ids(self, sel):
        r"""removes IDs from the index. Not supported by all indexes."""
        return _swigfaiss.IndexPreTransform_remove_ids(self, sel)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexPreTransform_search(self, n, x, k, distances, labels, params)

    def search_subset(self, n, x, k_base, base_labels, k, distances, labels):
        return _swigfaiss.IndexPreTransform_search_subset(self, n, x, k_base, base_labels, k, distances, labels)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexPreTransform_range_search(self, n, x, radius, result, params)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexPreTransform_reconstruct(self, key, recons)

    def reconstruct_n(self, i0, ni, recons):
        return _swigfaiss.IndexPreTransform_reconstruct_n(self, i0, ni, recons)

    def search_and_reconstruct(self, n, x, k, distances, labels, recons, params=None):
        return _swigfaiss.IndexPreTransform_search_and_reconstruct(self, n, x, k, distances, labels, recons, params)

    def apply_chain(self, n, x):
        r"""
        apply the transforms in the chain. The returned float * may be
        equal to x, otherwise it should be deallocated.
        """
        return _swigfaiss.IndexPreTransform_apply_chain(self, n, x)

    def reverse_chain(self, n, xt, x):
        r"""
        Reverse the transforms in the chain. May not be implemented for
        all transforms in the chain or may return approximate results.
        """
        return _swigfaiss.IndexPreTransform_reverse_chain(self, n, xt, x)

    def get_distance_computer(self):
        return _swigfaiss.IndexPreTransform_get_distance_computer(self)

    def sa_code_size(self):
        return _swigfaiss.IndexPreTransform_sa_code_size(self)

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.IndexPreTransform_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexPreTransform_sa_decode(self, n, bytes, x)

    def merge_from(self, otherIndex, add_id=0):
        return _swigfaiss.IndexPreTransform_merge_from(self, otherIndex, add_id)

    def check_compatible_for_merge(self, otherIndex):
        return _swigfaiss.IndexPreTransform_check_compatible_for_merge(self, otherIndex)
    __swig_destroy__ = _swigfaiss.delete_IndexPreTransform

# Register IndexPreTransform in _swigfaiss:
_swigfaiss.IndexPreTransform_swigregister(IndexPreTransform)
class IndexRefineSearchParameters(SearchParameters):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    k_factor = property(_swigfaiss.IndexRefineSearchParameters_k_factor_get, _swigfaiss.IndexRefineSearchParameters_k_factor_set)
    base_index_params = property(_swigfaiss.IndexRefineSearchParameters_base_index_params_get, _swigfaiss.IndexRefineSearchParameters_base_index_params_set)
    __swig_destroy__ = _swigfaiss.delete_IndexRefineSearchParameters

    def __init__(self):
        _swigfaiss.IndexRefineSearchParameters_swiginit(self, _swigfaiss.new_IndexRefineSearchParameters())

# Register IndexRefineSearchParameters in _swigfaiss:
_swigfaiss.IndexRefineSearchParameters_swigregister(IndexRefineSearchParameters)
class IndexRefine(Index):
    r"""
    Index that queries in a base_index (a fast one) and refines the
    results with an exact search, hopefully improving the results.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    base_index = property(_swigfaiss.IndexRefine_base_index_get, _swigfaiss.IndexRefine_base_index_set, doc=r"""faster index to pre-select the vectors that should be filtered""")
    refine_index = property(_swigfaiss.IndexRefine_refine_index_get, _swigfaiss.IndexRefine_refine_index_set, doc=r"""refinement index""")
    own_fields = property(_swigfaiss.IndexRefine_own_fields_get, _swigfaiss.IndexRefine_own_fields_set, doc=r"""should the base index be deallocated?""")
    own_refine_index = property(_swigfaiss.IndexRefine_own_refine_index_get, _swigfaiss.IndexRefine_own_refine_index_set, doc=r"""same with the refinement index""")
    k_factor = property(_swigfaiss.IndexRefine_k_factor_get, _swigfaiss.IndexRefine_k_factor_set, doc=r"""
    factor between k requested in search and the k requested from
    the base_index (should be >= 1)
    """)

    def __init__(self, *args):
        r"""initialize from empty index"""
        _swigfaiss.IndexRefine_swiginit(self, _swigfaiss.new_IndexRefine(*args))

    def train(self, n, x):
        return _swigfaiss.IndexRefine_train(self, n, x)

    def add(self, n, x):
        return _swigfaiss.IndexRefine_add(self, n, x)

    def reset(self):
        return _swigfaiss.IndexRefine_reset(self)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexRefine_search(self, n, x, k, distances, labels, params)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexRefine_range_search(self, n, x, radius, result, params)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexRefine_reconstruct(self, key, recons)

    def sa_code_size(self):
        return _swigfaiss.IndexRefine_sa_code_size(self)

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.IndexRefine_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        r"""
        The sa_decode decodes from the index_refine, which is assumed to be more
        accurate
        """
        return _swigfaiss.IndexRefine_sa_decode(self, n, bytes, x)
    __swig_destroy__ = _swigfaiss.delete_IndexRefine

# Register IndexRefine in _swigfaiss:
_swigfaiss.IndexRefine_swigregister(IndexRefine)
class IndexRefineFlat(IndexRefine):
    r"""
     Version where the refinement index is an IndexFlat. It has one additional
    constructor that takes a table of elements to add to the flat refinement
    index
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexRefineFlat_swiginit(self, _swigfaiss.new_IndexRefineFlat(*args))

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexRefineFlat_search(self, n, x, k, distances, labels, params)
    __swig_destroy__ = _swigfaiss.delete_IndexRefineFlat

# Register IndexRefineFlat in _swigfaiss:
_swigfaiss.IndexRefineFlat_swigregister(IndexRefineFlat)
class IndexRefinePanorama(IndexRefine):
    r"""
     Version where the search calls search_subset, allowing for Panorama
    refinement.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexRefinePanorama_swiginit(self, _swigfaiss.new_IndexRefinePanorama(*args))

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexRefinePanorama_search(self, n, x, k, distances, labels, params)
    __swig_destroy__ = _swigfaiss.delete_IndexRefinePanorama

# Register IndexRefinePanorama in _swigfaiss:
_swigfaiss.IndexRefinePanorama_swigregister(IndexRefinePanorama)
class IndexLSH(IndexFlatCodes):
    r"""The sign of each vector component is put in a binary signature"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nbits = property(_swigfaiss.IndexLSH_nbits_get, _swigfaiss.IndexLSH_nbits_set, doc=r"""nb of bits per vector""")
    rotate_data = property(_swigfaiss.IndexLSH_rotate_data_get, _swigfaiss.IndexLSH_rotate_data_set, doc=r"""whether to apply a random rotation to input""")
    train_thresholds = property(_swigfaiss.IndexLSH_train_thresholds_get, _swigfaiss.IndexLSH_train_thresholds_set, doc=r"""whether we train thresholds or use 0""")
    rrot = property(_swigfaiss.IndexLSH_rrot_get, _swigfaiss.IndexLSH_rrot_set, doc=r"""optional random rotation""")
    thresholds = property(_swigfaiss.IndexLSH_thresholds_get, _swigfaiss.IndexLSH_thresholds_set, doc=r"""thresholds to compare with""")

    def apply_preprocess(self, n, x):
        r"""
         Preprocesses and resizes the input to the size required to
        binarize the data

        :type x: float
        :param x: input vectors, size n * d
        :rtype: float
        :return: output vectors, size n * bits. May be the same pointer
                    as x, otherwise it should be deleted by the caller
        """
        return _swigfaiss.IndexLSH_apply_preprocess(self, n, x)

    def train(self, n, x):
        return _swigfaiss.IndexLSH_train(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexLSH_search(self, n, x, k, distances, labels, params)

    def transfer_thresholds(self, vt):
        r"""
        transfer the thresholds to a pre-processing stage (and unset
        train_thresholds)
        """
        return _swigfaiss.IndexLSH_transfer_thresholds(self, vt)
    __swig_destroy__ = _swigfaiss.delete_IndexLSH

    def __init__(self, *args):
        _swigfaiss.IndexLSH_swiginit(self, _swigfaiss.new_IndexLSH(*args))

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.IndexLSH_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexLSH_sa_decode(self, n, bytes, x)

# Register IndexLSH in _swigfaiss:
_swigfaiss.IndexLSH_swigregister(IndexLSH)
class SimulatedAnnealingParameters(object):
    r"""parameters used for the simulated annealing method"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    init_temperature = property(_swigfaiss.SimulatedAnnealingParameters_init_temperature_get, _swigfaiss.SimulatedAnnealingParameters_init_temperature_set)
    temperature_decay = property(_swigfaiss.SimulatedAnnealingParameters_temperature_decay_get, _swigfaiss.SimulatedAnnealingParameters_temperature_decay_set)
    n_iter = property(_swigfaiss.SimulatedAnnealingParameters_n_iter_get, _swigfaiss.SimulatedAnnealingParameters_n_iter_set)
    n_redo = property(_swigfaiss.SimulatedAnnealingParameters_n_redo_get, _swigfaiss.SimulatedAnnealingParameters_n_redo_set)
    seed = property(_swigfaiss.SimulatedAnnealingParameters_seed_get, _swigfaiss.SimulatedAnnealingParameters_seed_set)
    verbose = property(_swigfaiss.SimulatedAnnealingParameters_verbose_get, _swigfaiss.SimulatedAnnealingParameters_verbose_set)
    only_bit_flips = property(_swigfaiss.SimulatedAnnealingParameters_only_bit_flips_get, _swigfaiss.SimulatedAnnealingParameters_only_bit_flips_set)
    init_random = property(_swigfaiss.SimulatedAnnealingParameters_init_random_get, _swigfaiss.SimulatedAnnealingParameters_init_random_set)

    def __init__(self):
        _swigfaiss.SimulatedAnnealingParameters_swiginit(self, _swigfaiss.new_SimulatedAnnealingParameters())
    __swig_destroy__ = _swigfaiss.delete_SimulatedAnnealingParameters

# Register SimulatedAnnealingParameters in _swigfaiss:
_swigfaiss.SimulatedAnnealingParameters_swigregister(SimulatedAnnealingParameters)
class PermutationObjective(object):
    r"""abstract class for the loss function"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    n = property(_swigfaiss.PermutationObjective_n_get, _swigfaiss.PermutationObjective_n_set)

    def compute_cost(self, perm):
        return _swigfaiss.PermutationObjective_compute_cost(self, perm)

    def cost_update(self, perm, iw, jw):
        return _swigfaiss.PermutationObjective_cost_update(self, perm, iw, jw)
    __swig_destroy__ = _swigfaiss.delete_PermutationObjective

# Register PermutationObjective in _swigfaiss:
_swigfaiss.PermutationObjective_swigregister(PermutationObjective)
class ReproduceDistancesObjective(PermutationObjective):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    dis_weight_factor = property(_swigfaiss.ReproduceDistancesObjective_dis_weight_factor_get, _swigfaiss.ReproduceDistancesObjective_dis_weight_factor_set)

    @staticmethod
    def sqr(x):
        return _swigfaiss.ReproduceDistancesObjective_sqr(x)

    def dis_weight(self, x):
        return _swigfaiss.ReproduceDistancesObjective_dis_weight(self, x)
    source_dis = property(_swigfaiss.ReproduceDistancesObjective_source_dis_get, _swigfaiss.ReproduceDistancesObjective_source_dis_set, doc=r""""real" corrected distances (size n^2)""")
    target_dis = property(_swigfaiss.ReproduceDistancesObjective_target_dis_get, _swigfaiss.ReproduceDistancesObjective_target_dis_set, doc=r"""wanted distances (size n^2)""")
    weights = property(_swigfaiss.ReproduceDistancesObjective_weights_get, _swigfaiss.ReproduceDistancesObjective_weights_set, doc=r"""weights for each distance (size n^2)""")

    def get_source_dis(self, i, j):
        return _swigfaiss.ReproduceDistancesObjective_get_source_dis(self, i, j)

    def compute_cost(self, perm):
        return _swigfaiss.ReproduceDistancesObjective_compute_cost(self, perm)

    def cost_update(self, perm, iw, jw):
        return _swigfaiss.ReproduceDistancesObjective_cost_update(self, perm, iw, jw)

    def __init__(self, n_in, source_dis_in, target_dis_in, dis_weight_factor_in):
        _swigfaiss.ReproduceDistancesObjective_swiginit(self, _swigfaiss.new_ReproduceDistancesObjective(n_in, source_dis_in, target_dis_in, dis_weight_factor_in))

    @staticmethod
    def compute_mean_stdev(tab, n2, mean_out, stddev_out):
        return _swigfaiss.ReproduceDistancesObjective_compute_mean_stdev(tab, n2, mean_out, stddev_out)

    def set_affine_target_dis(self, source_dis_in):
        return _swigfaiss.ReproduceDistancesObjective_set_affine_target_dis(self, source_dis_in)
    __swig_destroy__ = _swigfaiss.delete_ReproduceDistancesObjective

# Register ReproduceDistancesObjective in _swigfaiss:
_swigfaiss.ReproduceDistancesObjective_swigregister(ReproduceDistancesObjective)
class SimulatedAnnealingOptimizer(SimulatedAnnealingParameters):
    r"""Simulated annealing optimization algorithm for permutations."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    obj = property(_swigfaiss.SimulatedAnnealingOptimizer_obj_get, _swigfaiss.SimulatedAnnealingOptimizer_obj_set)
    n = property(_swigfaiss.SimulatedAnnealingOptimizer_n_get, _swigfaiss.SimulatedAnnealingOptimizer_n_set, doc=r"""size of the permutation""")
    logfile = property(_swigfaiss.SimulatedAnnealingOptimizer_logfile_get, _swigfaiss.SimulatedAnnealingOptimizer_logfile_set)

    def __init__(self, obj_in, p):
        r"""logs values of the cost function"""
        _swigfaiss.SimulatedAnnealingOptimizer_swiginit(self, _swigfaiss.new_SimulatedAnnealingOptimizer(obj_in, p))
    rnd = property(_swigfaiss.SimulatedAnnealingOptimizer_rnd_get, _swigfaiss.SimulatedAnnealingOptimizer_rnd_set)
    init_cost = property(_swigfaiss.SimulatedAnnealingOptimizer_init_cost_get, _swigfaiss.SimulatedAnnealingOptimizer_init_cost_set, doc=r"""remember initial cost of optimization""")

    def optimize(self, perm):
        return _swigfaiss.SimulatedAnnealingOptimizer_optimize(self, perm)

    def run_optimization(self, best_perm):
        return _swigfaiss.SimulatedAnnealingOptimizer_run_optimization(self, best_perm)
    __swig_destroy__ = _swigfaiss.delete_SimulatedAnnealingOptimizer

# Register SimulatedAnnealingOptimizer in _swigfaiss:
_swigfaiss.SimulatedAnnealingOptimizer_swigregister(SimulatedAnnealingOptimizer)
class PolysemousTraining(SimulatedAnnealingParameters):
    r"""optimizes the order of indices in a ProductQuantizer"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    OT_None = _swigfaiss.PolysemousTraining_OT_None
    OT_ReproduceDistances_affine = _swigfaiss.PolysemousTraining_OT_ReproduceDistances_affine
    r"""default"""
    OT_Ranking_weighted_diff = _swigfaiss.PolysemousTraining_OT_Ranking_weighted_diff
    r"""
    same as _2, but use rank of y+ - rank of
    y-
    """
    optimization_type = property(_swigfaiss.PolysemousTraining_optimization_type_get, _swigfaiss.PolysemousTraining_optimization_type_set)
    ntrain_permutation = property(_swigfaiss.PolysemousTraining_ntrain_permutation_get, _swigfaiss.PolysemousTraining_ntrain_permutation_set, doc=r"""
     use 1/4 of the training points for the optimization, with
    max. ntrain_permutation. If ntrain_permutation == 0: train on
    centroids
    """)
    dis_weight_factor = property(_swigfaiss.PolysemousTraining_dis_weight_factor_get, _swigfaiss.PolysemousTraining_dis_weight_factor_set, doc=r"""decay of exp that weights distance loss""")
    max_memory = property(_swigfaiss.PolysemousTraining_max_memory_get, _swigfaiss.PolysemousTraining_max_memory_set, doc=r"""refuse to train if it would require more than that amount of RAM""")
    log_pattern = property(_swigfaiss.PolysemousTraining_log_pattern_get, _swigfaiss.PolysemousTraining_log_pattern_set)

    def __init__(self):
        _swigfaiss.PolysemousTraining_swiginit(self, _swigfaiss.new_PolysemousTraining())

    def optimize_pq_for_hamming(self, pq, n, x):
        r"""
        reorder the centroids so that the Hamming distance becomes a
        good approximation of the SDC distance (called by train)
        """
        return _swigfaiss.PolysemousTraining_optimize_pq_for_hamming(self, pq, n, x)

    def optimize_ranking(self, pq, n, x):
        r"""called by optimize_pq_for_hamming"""
        return _swigfaiss.PolysemousTraining_optimize_ranking(self, pq, n, x)

    def optimize_reproduce_distances(self, pq):
        r"""called by optimize_pq_for_hamming"""
        return _swigfaiss.PolysemousTraining_optimize_reproduce_distances(self, pq)

    def memory_usage_per_thread(self, pq):
        r"""make sure we don't blow up the memory"""
        return _swigfaiss.PolysemousTraining_memory_usage_per_thread(self, pq)
    __swig_destroy__ = _swigfaiss.delete_PolysemousTraining

# Register PolysemousTraining in _swigfaiss:
_swigfaiss.PolysemousTraining_swigregister(PolysemousTraining)
class IndexPQ(IndexFlatCodes):
    r"""
     Index based on a product quantizer. Stored vectors are
    approximated by PQ codes.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    pq = property(_swigfaiss.IndexPQ_pq_get, _swigfaiss.IndexPQ_pq_set, doc=r"""The product quantizer used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type M: int
        :param M:      number of subquantizers
        :type nbits: int
        :param nbits:  number of bit per subvector index
        """
        _swigfaiss.IndexPQ_swiginit(self, _swigfaiss.new_IndexPQ(*args))

    def train(self, n, x):
        return _swigfaiss.IndexPQ_train(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexPQ_search(self, n, x, k, distances, labels, params)

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.IndexPQ_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexPQ_sa_decode(self, n, bytes, x)

    def get_FlatCodesDistanceComputer(self):
        return _swigfaiss.IndexPQ_get_FlatCodesDistanceComputer(self)
    do_polysemous_training = property(_swigfaiss.IndexPQ_do_polysemous_training_get, _swigfaiss.IndexPQ_do_polysemous_training_set, doc=r"""false = standard PQ""")
    polysemous_training = property(_swigfaiss.IndexPQ_polysemous_training_get, _swigfaiss.IndexPQ_polysemous_training_set, doc=r"""parameters used for the polysemous training""")
    ST_PQ = _swigfaiss.IndexPQ_ST_PQ
    r"""asymmetric product quantizer (default)"""
    ST_HE = _swigfaiss.IndexPQ_ST_HE
    r"""Hamming distance on codes"""
    ST_generalized_HE = _swigfaiss.IndexPQ_ST_generalized_HE
    r"""nb of same codes"""
    ST_SDC = _swigfaiss.IndexPQ_ST_SDC
    r"""symmetric product quantizer (SDC)"""
    ST_polysemous = _swigfaiss.IndexPQ_ST_polysemous
    r"""HE filter (using ht) + PQ combination"""
    ST_polysemous_generalize = _swigfaiss.IndexPQ_ST_polysemous_generalize
    r"""Filter on generalized Hamming"""
    search_type = property(_swigfaiss.IndexPQ_search_type_get, _swigfaiss.IndexPQ_search_type_set)
    encode_signs = property(_swigfaiss.IndexPQ_encode_signs_get, _swigfaiss.IndexPQ_encode_signs_set)
    polysemous_ht = property(_swigfaiss.IndexPQ_polysemous_ht_get, _swigfaiss.IndexPQ_polysemous_ht_set, doc=r"""Hamming threshold used for polysemy""")

    def search_core_polysemous(self, n, x, k, distances, labels, polysemous_ht, generalized_hamming):
        return _swigfaiss.IndexPQ_search_core_polysemous(self, n, x, k, distances, labels, polysemous_ht, generalized_hamming)

    def hamming_distance_histogram(self, n, x, nb, xb, dist_histogram):
        r"""
        prepare query for a polysemous search, but instead of
        computing the result, just get the histogram of Hamming
        distances. May be computed on a provided dataset if xb != NULL
        :type dist_histogram: int
        :param dist_histogram: (M * nbits + 1)
        """
        return _swigfaiss.IndexPQ_hamming_distance_histogram(self, n, x, nb, xb, dist_histogram)

    def hamming_distance_table(self, n, x, dis):
        r"""
         compute pairwise distances between queries and database

        :type n: int
        :param n:    nb of query vectors
        :type x: float
        :param x:    query vector, size n * d
        :type dis: int
        :param dis:  output distances, size n * ntotal
        """
        return _swigfaiss.IndexPQ_hamming_distance_table(self, n, x, dis)
    __swig_destroy__ = _swigfaiss.delete_IndexPQ

# Register IndexPQ in _swigfaiss:
_swigfaiss.IndexPQ_swigregister(IndexPQ)
class SearchParametersPQ(SearchParameters):
    r"""override search parameters from the class"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    search_type = property(_swigfaiss.SearchParametersPQ_search_type_get, _swigfaiss.SearchParametersPQ_search_type_set)
    polysemous_ht = property(_swigfaiss.SearchParametersPQ_polysemous_ht_get, _swigfaiss.SearchParametersPQ_polysemous_ht_set)

    def __init__(self):
        _swigfaiss.SearchParametersPQ_swiginit(self, _swigfaiss.new_SearchParametersPQ())
    __swig_destroy__ = _swigfaiss.delete_SearchParametersPQ

# Register SearchParametersPQ in _swigfaiss:
_swigfaiss.SearchParametersPQ_swigregister(SearchParametersPQ)
class IndexPQStats(object):
    r"""
    statistics are robust to internal threading, but not if
    IndexPQ::search is called by multiple threads
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nq = property(_swigfaiss.IndexPQStats_nq_get, _swigfaiss.IndexPQStats_nq_set)
    ncode = property(_swigfaiss.IndexPQStats_ncode_get, _swigfaiss.IndexPQStats_ncode_set)
    n_hamming_pass = property(_swigfaiss.IndexPQStats_n_hamming_pass_get, _swigfaiss.IndexPQStats_n_hamming_pass_set)

    def __init__(self):
        _swigfaiss.IndexPQStats_swiginit(self, _swigfaiss.new_IndexPQStats())

    def reset(self):
        return _swigfaiss.IndexPQStats_reset(self)
    __swig_destroy__ = _swigfaiss.delete_IndexPQStats

# Register IndexPQStats in _swigfaiss:
_swigfaiss.IndexPQStats_swigregister(IndexPQStats)
class MultiIndexQuantizer(Index):
    r"""
    Quantizer where centroids are virtual: they are the Cartesian
    product of sub-centroids.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    pq = property(_swigfaiss.MultiIndexQuantizer_pq_get, _swigfaiss.MultiIndexQuantizer_pq_set)

    def train(self, n, x):
        return _swigfaiss.MultiIndexQuantizer_train(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.MultiIndexQuantizer_search(self, n, x, k, distances, labels, params)

    def add(self, n, x):
        r"""add and reset will crash at runtime"""
        return _swigfaiss.MultiIndexQuantizer_add(self, n, x)

    def reset(self):
        return _swigfaiss.MultiIndexQuantizer_reset(self)

    def __init__(self, *args):
        r"""
         number of bit per subvector index
        :type d: int
        :param d: dimension of the input vectors
        :type M: int
        :param M: number of subquantizers
        """
        _swigfaiss.MultiIndexQuantizer_swiginit(self, _swigfaiss.new_MultiIndexQuantizer(*args))

    def reconstruct(self, key, recons):
        return _swigfaiss.MultiIndexQuantizer_reconstruct(self, key, recons)
    __swig_destroy__ = _swigfaiss.delete_MultiIndexQuantizer

# Register MultiIndexQuantizer in _swigfaiss:
_swigfaiss.MultiIndexQuantizer_swigregister(MultiIndexQuantizer)
class MultiIndexQuantizer2(MultiIndexQuantizer):
    r"""MultiIndexQuantizer where the PQ assignment is performed by sub-indexes"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    assign_indexes = property(_swigfaiss.MultiIndexQuantizer2_assign_indexes_get, _swigfaiss.MultiIndexQuantizer2_assign_indexes_set, doc=r"""M Indexes on d / M dimensions""")
    own_fields = property(_swigfaiss.MultiIndexQuantizer2_own_fields_get, _swigfaiss.MultiIndexQuantizer2_own_fields_set)

    def __init__(self, *args):
        _swigfaiss.MultiIndexQuantizer2_swiginit(self, _swigfaiss.new_MultiIndexQuantizer2(*args))

    def train(self, n, x):
        return _swigfaiss.MultiIndexQuantizer2_train(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.MultiIndexQuantizer2_search(self, n, x, k, distances, labels, params)
    __swig_destroy__ = _swigfaiss.delete_MultiIndexQuantizer2

# Register MultiIndexQuantizer2 in _swigfaiss:
_swigfaiss.MultiIndexQuantizer2_swigregister(MultiIndexQuantizer2)
class IndexAdditiveQuantizer(IndexFlatCodes):
    r"""Abstract class for additive quantizers. The search functions are in common."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    aq = property(_swigfaiss.IndexAdditiveQuantizer_aq_get, _swigfaiss.IndexAdditiveQuantizer_aq_set)

    def __init__(self, *args):
        _swigfaiss.IndexAdditiveQuantizer_swiginit(self, _swigfaiss.new_IndexAdditiveQuantizer(*args))

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexAdditiveQuantizer_search(self, n, x, k, distances, labels, params)

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.IndexAdditiveQuantizer_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexAdditiveQuantizer_sa_decode(self, n, bytes, x)

    def get_FlatCodesDistanceComputer(self):
        return _swigfaiss.IndexAdditiveQuantizer_get_FlatCodesDistanceComputer(self)
    __swig_destroy__ = _swigfaiss.delete_IndexAdditiveQuantizer

# Register IndexAdditiveQuantizer in _swigfaiss:
_swigfaiss.IndexAdditiveQuantizer_swigregister(IndexAdditiveQuantizer)
class IndexResidualQuantizer(IndexAdditiveQuantizer):
    r"""
     Index based on a residual quantizer. Stored vectors are
    approximated by residual quantization codes.
    Can also be used as a codec
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    rq = property(_swigfaiss.IndexResidualQuantizer_rq_get, _swigfaiss.IndexResidualQuantizer_rq_set, doc=r"""The residual quantizer used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type M: int
        :param M:      number of subquantizers
        :type nbits: int
        :param nbits:  number of bit per subvector index

        :type d: int
        :param d: dimensionality of the input vectors
        :type M: int
        :param M: number of subquantizers
        :type nbits: int
        :param nbits: number of bit per subvector index
        """
        _swigfaiss.IndexResidualQuantizer_swiginit(self, _swigfaiss.new_IndexResidualQuantizer(*args))

    def train(self, n, x):
        return _swigfaiss.IndexResidualQuantizer_train(self, n, x)
    __swig_destroy__ = _swigfaiss.delete_IndexResidualQuantizer

# Register IndexResidualQuantizer in _swigfaiss:
_swigfaiss.IndexResidualQuantizer_swigregister(IndexResidualQuantizer)
class IndexLocalSearchQuantizer(IndexAdditiveQuantizer):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    lsq = property(_swigfaiss.IndexLocalSearchQuantizer_lsq_get, _swigfaiss.IndexLocalSearchQuantizer_lsq_set)

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type M: int
        :param M:      number of subquantizers
        :type nbits: int
        :param nbits:  number of bit per subvector index

        :type d: int
        :param d: dimensionality of the input vectors
        :type M: int
        :param M: number of subquantizers
        :type nbits: int
        :param nbits: number of bit per subvector index
        """
        _swigfaiss.IndexLocalSearchQuantizer_swiginit(self, _swigfaiss.new_IndexLocalSearchQuantizer(*args))

    def train(self, n, x):
        return _swigfaiss.IndexLocalSearchQuantizer_train(self, n, x)
    __swig_destroy__ = _swigfaiss.delete_IndexLocalSearchQuantizer

# Register IndexLocalSearchQuantizer in _swigfaiss:
_swigfaiss.IndexLocalSearchQuantizer_swigregister(IndexLocalSearchQuantizer)
class IndexProductResidualQuantizer(IndexAdditiveQuantizer):
    r"""Index based on a product residual quantizer."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    prq = property(_swigfaiss.IndexProductResidualQuantizer_prq_get, _swigfaiss.IndexProductResidualQuantizer_prq_set, doc=r"""The product residual quantizer used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type nsplits: int
        :param nsplits:  number of residual quantizers
        :type Msub: int
        :param Msub:      number of subquantizers per RQ
        :type nbits: int
        :param nbits:  number of bit per subvector index

        :type d: int
        :param d: dimensionality of the input vectors
        :type nsplits: int
        :param nsplits: number of residual quantizers
        :type Msub: int
        :param Msub: number of subquantizers per RQ
        :type nbits: int
        :param nbits: number of bit per subvector index
        """
        _swigfaiss.IndexProductResidualQuantizer_swiginit(self, _swigfaiss.new_IndexProductResidualQuantizer(*args))

    def train(self, n, x):
        return _swigfaiss.IndexProductResidualQuantizer_train(self, n, x)
    __swig_destroy__ = _swigfaiss.delete_IndexProductResidualQuantizer

# Register IndexProductResidualQuantizer in _swigfaiss:
_swigfaiss.IndexProductResidualQuantizer_swigregister(IndexProductResidualQuantizer)
class IndexProductLocalSearchQuantizer(IndexAdditiveQuantizer):
    r"""Index based on a product local search quantizer."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    plsq = property(_swigfaiss.IndexProductLocalSearchQuantizer_plsq_get, _swigfaiss.IndexProductLocalSearchQuantizer_plsq_set, doc=r"""The product local search quantizer used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type nsplits: int
        :param nsplits:  number of local search quantizers
        :type Msub: int
        :param Msub:     number of subquantizers per LSQ
        :type nbits: int
        :param nbits:  number of bit per subvector index

        :type d: int
        :param d: dimensionality of the input vectors
        :type nsplits: int
        :param nsplits: number of local search quantizers
        :type Msub: int
        :param Msub: number of subquantizers per LSQ
        :type nbits: int
        :param nbits: number of bit per subvector index
        """
        _swigfaiss.IndexProductLocalSearchQuantizer_swiginit(self, _swigfaiss.new_IndexProductLocalSearchQuantizer(*args))

    def train(self, n, x):
        return _swigfaiss.IndexProductLocalSearchQuantizer_train(self, n, x)
    __swig_destroy__ = _swigfaiss.delete_IndexProductLocalSearchQuantizer

# Register IndexProductLocalSearchQuantizer in _swigfaiss:
_swigfaiss.IndexProductLocalSearchQuantizer_swigregister(IndexProductLocalSearchQuantizer)
class AdditiveCoarseQuantizer(Index):
    r"""
     A "virtual" index where the elements are the residual quantizer centroids.

    Intended for use as a coarse quantizer in an IndexIVF.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    aq = property(_swigfaiss.AdditiveCoarseQuantizer_aq_get, _swigfaiss.AdditiveCoarseQuantizer_aq_set)

    def __init__(self, *args):
        _swigfaiss.AdditiveCoarseQuantizer_swiginit(self, _swigfaiss.new_AdditiveCoarseQuantizer(*args))
    centroid_norms = property(_swigfaiss.AdditiveCoarseQuantizer_centroid_norms_get, _swigfaiss.AdditiveCoarseQuantizer_centroid_norms_set, doc=r"""norms of centroids, useful for knn-search""")

    def add(self, n, x):
        r"""N/A"""
        return _swigfaiss.AdditiveCoarseQuantizer_add(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.AdditiveCoarseQuantizer_search(self, n, x, k, distances, labels, params)

    def reconstruct(self, key, recons):
        return _swigfaiss.AdditiveCoarseQuantizer_reconstruct(self, key, recons)

    def train(self, n, x):
        return _swigfaiss.AdditiveCoarseQuantizer_train(self, n, x)

    def reset(self):
        r"""N/A"""
        return _swigfaiss.AdditiveCoarseQuantizer_reset(self)
    __swig_destroy__ = _swigfaiss.delete_AdditiveCoarseQuantizer

# Register AdditiveCoarseQuantizer in _swigfaiss:
_swigfaiss.AdditiveCoarseQuantizer_swigregister(AdditiveCoarseQuantizer)
class SearchParametersResidualCoarseQuantizer(SearchParameters):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    beam_factor = property(_swigfaiss.SearchParametersResidualCoarseQuantizer_beam_factor_get, _swigfaiss.SearchParametersResidualCoarseQuantizer_beam_factor_set)
    __swig_destroy__ = _swigfaiss.delete_SearchParametersResidualCoarseQuantizer

    def __init__(self):
        _swigfaiss.SearchParametersResidualCoarseQuantizer_swiginit(self, _swigfaiss.new_SearchParametersResidualCoarseQuantizer())

# Register SearchParametersResidualCoarseQuantizer in _swigfaiss:
_swigfaiss.SearchParametersResidualCoarseQuantizer_swigregister(SearchParametersResidualCoarseQuantizer)
class ResidualCoarseQuantizer(AdditiveCoarseQuantizer):
    r"""
     The ResidualCoarseQuantizer is a bit specialized compared to the
    default AdditiveCoarseQuantizer because it can use a beam search
    at search time (slow but may be useful for very large vocabularies)
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    rq = property(_swigfaiss.ResidualCoarseQuantizer_rq_get, _swigfaiss.ResidualCoarseQuantizer_rq_set, doc=r"""The residual quantizer used to encode the vectors""")
    beam_factor = property(_swigfaiss.ResidualCoarseQuantizer_beam_factor_get, _swigfaiss.ResidualCoarseQuantizer_beam_factor_set, doc=r"""
    factor between the beam size and the search k
    if negative, use exact search-to-centroid
    """)

    def set_beam_factor(self, new_beam_factor):
        r"""computes centroid norms if required"""
        return _swigfaiss.ResidualCoarseQuantizer_set_beam_factor(self, new_beam_factor)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.ResidualCoarseQuantizer_search(self, n, x, k, distances, labels, params)

    def initialize_from(self, other):
        r"""
         Copy the M first codebook levels from other. Useful to crop a
        ResidualQuantizer to its first M quantizers.
        """
        return _swigfaiss.ResidualCoarseQuantizer_initialize_from(self, other)

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type M: int
        :param M:      number of subquantizers
        :type nbits: int
        :param nbits:  number of bit per subvector index

        :type d: int
        :param d: dimensionality of the input vectors
        :type M: int
        :param M: number of subquantizers
        :type nbits: int
        :param nbits: number of bit per subvector index
        """
        _swigfaiss.ResidualCoarseQuantizer_swiginit(self, _swigfaiss.new_ResidualCoarseQuantizer(*args))
    __swig_destroy__ = _swigfaiss.delete_ResidualCoarseQuantizer

# Register ResidualCoarseQuantizer in _swigfaiss:
_swigfaiss.ResidualCoarseQuantizer_swigregister(ResidualCoarseQuantizer)
class LocalSearchCoarseQuantizer(AdditiveCoarseQuantizer):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    lsq = property(_swigfaiss.LocalSearchCoarseQuantizer_lsq_get, _swigfaiss.LocalSearchCoarseQuantizer_lsq_set, doc=r"""The residual quantizer used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type M: int
        :param M:      number of subquantizers
        :type nbits: int
        :param nbits:  number of bit per subvector index

        :type d: int
        :param d: dimensionality of the input vectors
        :type M: int
        :param M: number of subquantizers
        :type nbits: int
        :param nbits: number of bit per subvector index
        """
        _swigfaiss.LocalSearchCoarseQuantizer_swiginit(self, _swigfaiss.new_LocalSearchCoarseQuantizer(*args))
    __swig_destroy__ = _swigfaiss.delete_LocalSearchCoarseQuantizer

# Register LocalSearchCoarseQuantizer in _swigfaiss:
_swigfaiss.LocalSearchCoarseQuantizer_swigregister(LocalSearchCoarseQuantizer)
class InvertedListsIterator(object):
    r"""
    Definition of inverted lists + a few common classes that implement
    the interface.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    __swig_destroy__ = _swigfaiss.delete_InvertedListsIterator

    def is_available(self):
        return _swigfaiss.InvertedListsIterator_is_available(self)

    def next(self):
        return _swigfaiss.InvertedListsIterator_next(self)

    def get_id_and_codes(self):
        return _swigfaiss.InvertedListsIterator_get_id_and_codes(self)
    has_search_callbacks_ = property(_swigfaiss.InvertedListsIterator_has_search_callbacks__get, _swigfaiss.InvertedListsIterator_has_search_callbacks__set, doc=r"""
    When true, iterate_codes will invoke on_distance_computed() and
    on_heap_changed() via virtual dispatch. When false (the default),
    iterate_codes skips the callbacks entirely — the guard branch is
    perfectly predicted and costs ~0 cycles, so non-callback users
    pay no overhead. Derived classes that override the callbacks
    should set this to true in their constructor.
    """)

    def on_distance_computed(self, arg2, arg3):
        r"""
        Called from iterate_codes after distance computation for the vector
        returned by the most recent get_id_and_codes(). Default: no-op.
        Only invoked when has_search_callbacks_ is true.
        """
        return _swigfaiss.InvertedListsIterator_on_distance_computed(self, arg2, arg3)

    def on_heap_changed(self, arg2, arg3):
        r"""
        Called from iterate_codes when a vector replaces the current worst
        in the top-K heap. evicted_id is the displaced entry. Default: no-op.
        Only invoked when has_search_callbacks_ is true.
        """
        return _swigfaiss.InvertedListsIterator_on_heap_changed(self, arg2, arg3)

# Register InvertedListsIterator in _swigfaiss:
_swigfaiss.InvertedListsIterator_swigregister(InvertedListsIterator)
class InvertedLists(object):
    r"""
     Table of inverted lists
    multithreading rules:
    - concurrent read accesses are allowed
    - concurrent update accesses are allowed
    - for resize and add_entries, only concurrent access to different lists
      are allowed
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    nlist = property(_swigfaiss.InvertedLists_nlist_get, _swigfaiss.InvertedLists_nlist_set, doc=r"""number of possible key values""")
    code_size = property(_swigfaiss.InvertedLists_code_size_get, _swigfaiss.InvertedLists_code_size_set, doc=r"""code size per vector in bytes""")
    use_iterator = property(_swigfaiss.InvertedLists_use_iterator_get, _swigfaiss.InvertedLists_use_iterator_set, doc=r"""request to use iterator rather than get_codes / get_ids""")
    __swig_destroy__ = _swigfaiss.delete_InvertedLists
    INVALID_CODE_SIZE = _swigfaiss.InvertedLists_INVALID_CODE_SIZE
    r"""
    used for BlockInvertedLists, where the codes are packed into groups
    and the individual code size is meaningless
    """

    def list_size(self, list_no):
        r"""get the size of a list"""
        return _swigfaiss.InvertedLists_list_size(self, list_no)

    def get_codes(self, list_no):
        r"""
         get the codes for an inverted list
        must be released by release_codes

        :rtype: uint8_t
        :return: codes    size list_size * code_size
        """
        return _swigfaiss.InvertedLists_get_codes(self, list_no)

    def get_ids(self, list_no):
        r"""
         get the ids for an inverted list
        must be released by release_ids

        :rtype: int
        :return: ids      size list_size
        """
        return _swigfaiss.InvertedLists_get_ids(self, list_no)

    def release_codes(self, list_no, codes):
        r"""release codes returned by get_codes (default implementation is nop"""
        return _swigfaiss.InvertedLists_release_codes(self, list_no, codes)

    def release_ids(self, list_no, ids):
        r"""release ids returned by get_ids"""
        return _swigfaiss.InvertedLists_release_ids(self, list_no, ids)

    def get_single_id(self, list_no, offset):
        r"""
        :rtype: int
        :return: a single id in an inverted list
        """
        return _swigfaiss.InvertedLists_get_single_id(self, list_no, offset)

    def get_single_code(self, list_no, offset):
        r"""
        :rtype: uint8_t
        :return: a single code in an inverted list
            (should be deallocated with release_codes)
        """
        return _swigfaiss.InvertedLists_get_single_code(self, list_no, offset)

    def prefetch_lists(self, list_nos, nlist_in):
        r"""
        prepare the following lists (default does nothing)
        a list can be -1 hence the signed long
        """
        return _swigfaiss.InvertedLists_prefetch_lists(self, list_nos, nlist_in)

    def is_empty(self, list_no, inverted_list_context=None):
        r"""check if the list is empty"""
        return _swigfaiss.InvertedLists_is_empty(self, list_no, inverted_list_context)

    def get_iterator(self, list_no, inverted_list_context=None):
        r"""get iterable for lists that use_iterator"""
        return _swigfaiss.InvertedLists_get_iterator(self, list_no, inverted_list_context)

    def add_entry(self, list_no, theid, code, inverted_list_context=None):
        r"""add one entry to an inverted list"""
        return _swigfaiss.InvertedLists_add_entry(self, list_no, theid, code, inverted_list_context)

    def add_entries(self, list_no, n_entry, ids, code):
        return _swigfaiss.InvertedLists_add_entries(self, list_no, n_entry, ids, code)

    def update_entry(self, list_no, offset, id, code):
        return _swigfaiss.InvertedLists_update_entry(self, list_no, offset, id, code)

    def update_entries(self, list_no, offset, n_entry, ids, code):
        return _swigfaiss.InvertedLists_update_entries(self, list_no, offset, n_entry, ids, code)

    def resize(self, list_no, new_size):
        return _swigfaiss.InvertedLists_resize(self, list_no, new_size)

    def reset(self):
        return _swigfaiss.InvertedLists_reset(self)

    def merge_from(self, oivf, add_id):
        r"""move all entries from oivf (empty on output)"""
        return _swigfaiss.InvertedLists_merge_from(self, oivf, add_id)
    SUBSET_TYPE_ID_RANGE = _swigfaiss.InvertedLists_SUBSET_TYPE_ID_RANGE
    SUBSET_TYPE_ID_MOD = _swigfaiss.InvertedLists_SUBSET_TYPE_ID_MOD
    SUBSET_TYPE_ELEMENT_RANGE = _swigfaiss.InvertedLists_SUBSET_TYPE_ELEMENT_RANGE
    SUBSET_TYPE_INVLIST_FRACTION = _swigfaiss.InvertedLists_SUBSET_TYPE_INVLIST_FRACTION
    SUBSET_TYPE_INVLIST = _swigfaiss.InvertedLists_SUBSET_TYPE_INVLIST

    def copy_subset_to(self, other, subset_type, a1, a2):
        r"""
         copy a subset of the entries index to the other index
        :rtype: int
        :return: number of entries copied
        """
        return _swigfaiss.InvertedLists_copy_subset_to(self, other, subset_type, a1, a2)

    def imbalance_factor(self):
        r"""1= perfectly balanced, >1: imbalanced"""
        return _swigfaiss.InvertedLists_imbalance_factor(self)

    def print_stats(self):
        r"""display some stats about the inverted lists"""
        return _swigfaiss.InvertedLists_print_stats(self)

    def compute_ntotal(self):
        r"""sum up list sizes"""
        return _swigfaiss.InvertedLists_compute_ntotal(self)

# Register InvertedLists in _swigfaiss:
_swigfaiss.InvertedLists_swigregister(InvertedLists)
class ArrayInvertedLists(InvertedLists):
    r"""simple (default) implementation as an array of inverted lists"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    codes = property(_swigfaiss.ArrayInvertedLists_codes_get, _swigfaiss.ArrayInvertedLists_codes_set)
    ids = property(_swigfaiss.ArrayInvertedLists_ids_get, _swigfaiss.ArrayInvertedLists_ids_set, doc=r"""Inverted lists for indexes""")

    def __init__(self, nlist_in, code_size_in):
        _swigfaiss.ArrayInvertedLists_swiginit(self, _swigfaiss.new_ArrayInvertedLists(nlist_in, code_size_in))

    def list_size(self, list_no):
        return _swigfaiss.ArrayInvertedLists_list_size(self, list_no)

    def get_codes(self, list_no):
        return _swigfaiss.ArrayInvertedLists_get_codes(self, list_no)

    def get_ids(self, list_no):
        return _swigfaiss.ArrayInvertedLists_get_ids(self, list_no)

    def add_entries(self, list_no, n_entry, ids, code):
        return _swigfaiss.ArrayInvertedLists_add_entries(self, list_no, n_entry, ids, code)

    def update_entries(self, list_no, offset, n_entry, ids, code):
        return _swigfaiss.ArrayInvertedLists_update_entries(self, list_no, offset, n_entry, ids, code)

    def resize(self, list_no, new_size):
        return _swigfaiss.ArrayInvertedLists_resize(self, list_no, new_size)

    def permute_invlists(self, map):
        r"""permute the inverted lists, map maps new_id to old_id"""
        return _swigfaiss.ArrayInvertedLists_permute_invlists(self, map)

    def is_empty(self, list_no, inverted_list_context=None):
        return _swigfaiss.ArrayInvertedLists_is_empty(self, list_no, inverted_list_context)
    __swig_destroy__ = _swigfaiss.delete_ArrayInvertedLists

# Register ArrayInvertedLists in _swigfaiss:
_swigfaiss.ArrayInvertedLists_swigregister(ArrayInvertedLists)
class ArrayInvertedListsPanorama(ArrayInvertedLists):
    r"""
    Level-oriented storage as defined in the IVFFlat section of Panorama
    (https://www.arxiv.org/pdf/2510.00566).
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    cum_sums = property(_swigfaiss.ArrayInvertedListsPanorama_cum_sums_get, _swigfaiss.ArrayInvertedListsPanorama_cum_sums_set)
    n_levels = property(_swigfaiss.ArrayInvertedListsPanorama_n_levels_get)
    level_width = property(_swigfaiss.ArrayInvertedListsPanorama_level_width_get)
    pano = property(_swigfaiss.ArrayInvertedListsPanorama_pano_get, _swigfaiss.ArrayInvertedListsPanorama_pano_set)

    def __init__(self, *args):
        _swigfaiss.ArrayInvertedListsPanorama_swiginit(self, _swigfaiss.new_ArrayInvertedListsPanorama(*args))

    def get_cum_sums(self, list_no):
        return _swigfaiss.ArrayInvertedListsPanorama_get_cum_sums(self, list_no)

    def add_entries(self, list_no, n_entry, ids, code):
        return _swigfaiss.ArrayInvertedListsPanorama_add_entries(self, list_no, n_entry, ids, code)

    def update_entries(self, list_no, offset, n_entry, ids, code):
        return _swigfaiss.ArrayInvertedListsPanorama_update_entries(self, list_no, offset, n_entry, ids, code)

    def resize(self, list_no, new_size):
        return _swigfaiss.ArrayInvertedListsPanorama_resize(self, list_no, new_size)

    def get_iterator(self, list_no, inverted_list_context=None):
        r"""
        Panorama's layout make it impractical to support iterators as defined
        by Faiss (i.e. `InvertedListsIterator` API). The iterator would require
        to allocate and reassemble the vector at each call.
        Hence, we override this method to throw an error, this effectively
        disables the `iterate_codes` and `iterate_codes_range` methods.
        """
        return _swigfaiss.ArrayInvertedListsPanorama_get_iterator(self, list_no, inverted_list_context)

    def get_single_code(self, list_no, offset):
        r"""Reconstructs a single code from level-oriented storage to flat format."""
        return _swigfaiss.ArrayInvertedListsPanorama_get_single_code(self, list_no, offset)

    def release_codes(self, list_no, codes_in):
        r"""Frees codes returned by `get_single_code`."""
        return _swigfaiss.ArrayInvertedListsPanorama_release_codes(self, list_no, codes_in)
    __swig_destroy__ = _swigfaiss.delete_ArrayInvertedListsPanorama

# Register ArrayInvertedListsPanorama in _swigfaiss:
_swigfaiss.ArrayInvertedListsPanorama_swigregister(ArrayInvertedListsPanorama)
class ReadOnlyInvertedLists(InvertedLists):
    r"""invlists that fail for all write functions"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr

    def add_entries(self, list_no, n_entry, ids, code):
        return _swigfaiss.ReadOnlyInvertedLists_add_entries(self, list_no, n_entry, ids, code)

    def update_entries(self, list_no, offset, n_entry, ids, code):
        return _swigfaiss.ReadOnlyInvertedLists_update_entries(self, list_no, offset, n_entry, ids, code)

    def resize(self, list_no, new_size):
        return _swigfaiss.ReadOnlyInvertedLists_resize(self, list_no, new_size)
    __swig_destroy__ = _swigfaiss.delete_ReadOnlyInvertedLists

# Register ReadOnlyInvertedLists in _swigfaiss:
_swigfaiss.ReadOnlyInvertedLists_swigregister(ReadOnlyInvertedLists)
class HStackInvertedLists(ReadOnlyInvertedLists):
    r"""Horizontal stack of inverted lists"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    ils = property(_swigfaiss.HStackInvertedLists_ils_get, _swigfaiss.HStackInvertedLists_ils_set)

    def __init__(self, n_il, ils):
        r"""build InvertedLists by concatenating nil of them"""
        _swigfaiss.HStackInvertedLists_swiginit(self, _swigfaiss.new_HStackInvertedLists(n_il, ils))

    def list_size(self, list_no):
        return _swigfaiss.HStackInvertedLists_list_size(self, list_no)

    def get_codes(self, list_no):
        return _swigfaiss.HStackInvertedLists_get_codes(self, list_no)

    def get_ids(self, list_no):
        return _swigfaiss.HStackInvertedLists_get_ids(self, list_no)

    def prefetch_lists(self, list_nos, nlist_in):
        return _swigfaiss.HStackInvertedLists_prefetch_lists(self, list_nos, nlist_in)

    def release_codes(self, list_no, codes):
        return _swigfaiss.HStackInvertedLists_release_codes(self, list_no, codes)

    def release_ids(self, list_no, ids):
        return _swigfaiss.HStackInvertedLists_release_ids(self, list_no, ids)

    def get_single_id(self, list_no, offset):
        return _swigfaiss.HStackInvertedLists_get_single_id(self, list_no, offset)

    def get_single_code(self, list_no, offset):
        return _swigfaiss.HStackInvertedLists_get_single_code(self, list_no, offset)
    __swig_destroy__ = _swigfaiss.delete_HStackInvertedLists

# Register HStackInvertedLists in _swigfaiss:
_swigfaiss.HStackInvertedLists_swigregister(HStackInvertedLists)
class SliceInvertedLists(ReadOnlyInvertedLists):
    r"""vertical slice of indexes in another InvertedLists"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    il = property(_swigfaiss.SliceInvertedLists_il_get, _swigfaiss.SliceInvertedLists_il_set)
    i0 = property(_swigfaiss.SliceInvertedLists_i0_get, _swigfaiss.SliceInvertedLists_i0_set)
    i1 = property(_swigfaiss.SliceInvertedLists_i1_get, _swigfaiss.SliceInvertedLists_i1_set)

    def __init__(self, il_, i0_, i1_):
        _swigfaiss.SliceInvertedLists_swiginit(self, _swigfaiss.new_SliceInvertedLists(il_, i0_, i1_))

    def list_size(self, list_no):
        return _swigfaiss.SliceInvertedLists_list_size(self, list_no)

    def get_codes(self, list_no):
        return _swigfaiss.SliceInvertedLists_get_codes(self, list_no)

    def get_ids(self, list_no):
        return _swigfaiss.SliceInvertedLists_get_ids(self, list_no)

    def release_codes(self, list_no, codes):
        return _swigfaiss.SliceInvertedLists_release_codes(self, list_no, codes)

    def release_ids(self, list_no, ids):
        return _swigfaiss.SliceInvertedLists_release_ids(self, list_no, ids)

    def get_single_id(self, list_no, offset):
        return _swigfaiss.SliceInvertedLists_get_single_id(self, list_no, offset)

    def get_single_code(self, list_no, offset):
        return _swigfaiss.SliceInvertedLists_get_single_code(self, list_no, offset)

    def prefetch_lists(self, list_nos, nlist_in):
        return _swigfaiss.SliceInvertedLists_prefetch_lists(self, list_nos, nlist_in)
    __swig_destroy__ = _swigfaiss.delete_SliceInvertedLists

# Register SliceInvertedLists in _swigfaiss:
_swigfaiss.SliceInvertedLists_swigregister(SliceInvertedLists)
class VStackInvertedLists(ReadOnlyInvertedLists):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    ils = property(_swigfaiss.VStackInvertedLists_ils_get, _swigfaiss.VStackInvertedLists_ils_set)
    cumsz = property(_swigfaiss.VStackInvertedLists_cumsz_get, _swigfaiss.VStackInvertedLists_cumsz_set)

    def __init__(self, n_il, ils):
        r"""build InvertedLists by concatenating nil of them"""
        _swigfaiss.VStackInvertedLists_swiginit(self, _swigfaiss.new_VStackInvertedLists(n_il, ils))

    def list_size(self, list_no):
        return _swigfaiss.VStackInvertedLists_list_size(self, list_no)

    def get_codes(self, list_no):
        return _swigfaiss.VStackInvertedLists_get_codes(self, list_no)

    def get_ids(self, list_no):
        return _swigfaiss.VStackInvertedLists_get_ids(self, list_no)

    def release_codes(self, list_no, codes):
        return _swigfaiss.VStackInvertedLists_release_codes(self, list_no, codes)

    def release_ids(self, list_no, ids):
        return _swigfaiss.VStackInvertedLists_release_ids(self, list_no, ids)

    def get_single_id(self, list_no, offset):
        return _swigfaiss.VStackInvertedLists_get_single_id(self, list_no, offset)

    def get_single_code(self, list_no, offset):
        return _swigfaiss.VStackInvertedLists_get_single_code(self, list_no, offset)

    def prefetch_lists(self, list_nos, nlist_in):
        return _swigfaiss.VStackInvertedLists_prefetch_lists(self, list_nos, nlist_in)
    __swig_destroy__ = _swigfaiss.delete_VStackInvertedLists

# Register VStackInvertedLists in _swigfaiss:
_swigfaiss.VStackInvertedLists_swigregister(VStackInvertedLists)
class MaskedInvertedLists(ReadOnlyInvertedLists):
    r"""
     use the first inverted lists if they are non-empty otherwise use the second

    This is useful if il1 has a few inverted lists that are too long,
    and that il0 has replacement lists for those, with empty lists for
    the others.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    il0 = property(_swigfaiss.MaskedInvertedLists_il0_get, _swigfaiss.MaskedInvertedLists_il0_set)
    il1 = property(_swigfaiss.MaskedInvertedLists_il1_get, _swigfaiss.MaskedInvertedLists_il1_set)

    def __init__(self, il0_in, il1_in):
        _swigfaiss.MaskedInvertedLists_swiginit(self, _swigfaiss.new_MaskedInvertedLists(il0_in, il1_in))

    def list_size(self, list_no):
        return _swigfaiss.MaskedInvertedLists_list_size(self, list_no)

    def get_codes(self, list_no):
        return _swigfaiss.MaskedInvertedLists_get_codes(self, list_no)

    def get_ids(self, list_no):
        return _swigfaiss.MaskedInvertedLists_get_ids(self, list_no)

    def release_codes(self, list_no, codes):
        return _swigfaiss.MaskedInvertedLists_release_codes(self, list_no, codes)

    def release_ids(self, list_no, ids):
        return _swigfaiss.MaskedInvertedLists_release_ids(self, list_no, ids)

    def get_single_id(self, list_no, offset):
        return _swigfaiss.MaskedInvertedLists_get_single_id(self, list_no, offset)

    def get_single_code(self, list_no, offset):
        return _swigfaiss.MaskedInvertedLists_get_single_code(self, list_no, offset)

    def prefetch_lists(self, list_nos, nlist_in):
        return _swigfaiss.MaskedInvertedLists_prefetch_lists(self, list_nos, nlist_in)
    __swig_destroy__ = _swigfaiss.delete_MaskedInvertedLists

# Register MaskedInvertedLists in _swigfaiss:
_swigfaiss.MaskedInvertedLists_swigregister(MaskedInvertedLists)
class StopWordsInvertedLists(ReadOnlyInvertedLists):
    r"""
    if the inverted list in il is smaller than maxsize then return it,
    otherwise return an empty invlist
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    il0 = property(_swigfaiss.StopWordsInvertedLists_il0_get, _swigfaiss.StopWordsInvertedLists_il0_set)
    maxsize = property(_swigfaiss.StopWordsInvertedLists_maxsize_get, _swigfaiss.StopWordsInvertedLists_maxsize_set)

    def __init__(self, il0_in, maxsize_in):
        _swigfaiss.StopWordsInvertedLists_swiginit(self, _swigfaiss.new_StopWordsInvertedLists(il0_in, maxsize_in))

    def list_size(self, list_no):
        return _swigfaiss.StopWordsInvertedLists_list_size(self, list_no)

    def get_codes(self, list_no):
        return _swigfaiss.StopWordsInvertedLists_get_codes(self, list_no)

    def get_ids(self, list_no):
        return _swigfaiss.StopWordsInvertedLists_get_ids(self, list_no)

    def release_codes(self, list_no, codes):
        return _swigfaiss.StopWordsInvertedLists_release_codes(self, list_no, codes)

    def release_ids(self, list_no, ids):
        return _swigfaiss.StopWordsInvertedLists_release_ids(self, list_no, ids)

    def get_single_id(self, list_no, offset):
        return _swigfaiss.StopWordsInvertedLists_get_single_id(self, list_no, offset)

    def get_single_code(self, list_no, offset):
        return _swigfaiss.StopWordsInvertedLists_get_single_code(self, list_no, offset)

    def prefetch_lists(self, list_nos, nlist_in):
        return _swigfaiss.StopWordsInvertedLists_prefetch_lists(self, list_nos, nlist_in)
    __swig_destroy__ = _swigfaiss.delete_StopWordsInvertedLists

# Register StopWordsInvertedLists in _swigfaiss:
_swigfaiss.StopWordsInvertedLists_swigregister(StopWordsInvertedLists)
class CappedInvertedLists(InvertedLists):
    r"""
    Cap list sizes to maxsize for searching, while allowing writes.
    Unlike StopWordsInvertedLists which skips large lists entirely,
    this caps each list to maxsize entries (partial scan).
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    il0 = property(_swigfaiss.CappedInvertedLists_il0_get, _swigfaiss.CappedInvertedLists_il0_set)
    maxsize = property(_swigfaiss.CappedInvertedLists_maxsize_get, _swigfaiss.CappedInvertedLists_maxsize_set)

    def __init__(self, il, maxsize):
        _swigfaiss.CappedInvertedLists_swiginit(self, _swigfaiss.new_CappedInvertedLists(il, maxsize))

    def list_size(self, list_no):
        return _swigfaiss.CappedInvertedLists_list_size(self, list_no)

    def real_list_size(self, list_no):
        return _swigfaiss.CappedInvertedLists_real_list_size(self, list_no)

    def get_codes(self, list_no):
        return _swigfaiss.CappedInvertedLists_get_codes(self, list_no)

    def get_ids(self, list_no):
        return _swigfaiss.CappedInvertedLists_get_ids(self, list_no)

    def release_codes(self, list_no, codes):
        return _swigfaiss.CappedInvertedLists_release_codes(self, list_no, codes)

    def release_ids(self, list_no, ids):
        return _swigfaiss.CappedInvertedLists_release_ids(self, list_no, ids)

    def get_single_id(self, list_no, offset):
        return _swigfaiss.CappedInvertedLists_get_single_id(self, list_no, offset)

    def get_single_code(self, list_no, offset):
        return _swigfaiss.CappedInvertedLists_get_single_code(self, list_no, offset)

    def prefetch_lists(self, list_nos, nlist):
        return _swigfaiss.CappedInvertedLists_prefetch_lists(self, list_nos, nlist)

    def add_entries(self, list_no, n_entry, ids, code):
        return _swigfaiss.CappedInvertedLists_add_entries(self, list_no, n_entry, ids, code)

    def update_entries(self, list_no, offset, n_entry, ids, code):
        return _swigfaiss.CappedInvertedLists_update_entries(self, list_no, offset, n_entry, ids, code)

    def resize(self, list_no, new_size):
        return _swigfaiss.CappedInvertedLists_resize(self, list_no, new_size)
    __swig_destroy__ = _swigfaiss.delete_CappedInvertedLists

# Register CappedInvertedLists in _swigfaiss:
_swigfaiss.CappedInvertedLists_swigregister(CappedInvertedLists)
class InvertedListsIOHook(object):
    r"""
     Callbacks to handle other types of InvertedList objects.

    The callbacks should be registered with add_callback before calling
    read_index or read_InvertedLists. The callbacks for
    OnDiskInvertedLists are registrered by default. The invlist type is
    identified by:

    - the key (a fourcc) at read time
    - the class name (as given by typeid.name) at write time
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    key = property(_swigfaiss.InvertedListsIOHook_key_get, doc=r"""string version of the fourcc""")
    classname = property(_swigfaiss.InvertedListsIOHook_classname_get, doc=r"""typeid.name""")

    def write(self, ils, f):
        r"""write the index to the IOWriter (including the fourcc)"""
        return _swigfaiss.InvertedListsIOHook_write(self, ils, f)

    def read(self, f, io_flags):
        r"""called when the fourcc matches this class's fourcc"""
        return _swigfaiss.InvertedListsIOHook_read(self, f, io_flags)

    def read_ArrayInvertedLists(self, f, io_flags, nlist, code_size, sizes):
        r"""
         read from a ArrayInvertedLists into this invertedlist type.
        For this to work, the callback has to be enabled and the io_flag has to
        be set to IO_FLAG_SKIP_IVF_DATA | (16 upper bits of the fourcc)

        (default implementation fails)
        """
        return _swigfaiss.InvertedListsIOHook_read_ArrayInvertedLists(self, f, io_flags, nlist, code_size, sizes)
    __swig_destroy__ = _swigfaiss.delete_InvertedListsIOHook

    @staticmethod
    def add_callback(arg1):
        return _swigfaiss.InvertedListsIOHook_add_callback(arg1)

    @staticmethod
    def print_callbacks():
        return _swigfaiss.InvertedListsIOHook_print_callbacks()

    @staticmethod
    def lookup(h):
        return _swigfaiss.InvertedListsIOHook_lookup(h)

    @staticmethod
    def lookup_classname(classname):
        return _swigfaiss.InvertedListsIOHook_lookup_classname(classname)

# Register InvertedListsIOHook in _swigfaiss:
_swigfaiss.InvertedListsIOHook_swigregister(InvertedListsIOHook)
class BlockInvertedLists(InvertedLists):
    r"""
     Inverted Lists that are organized by blocks.

    Different from the regular inverted lists, the codes are organized by blocks
    of size block_size bytes that represent a set of n_per_block. Therefore, code
    allocations are always rounded up to block_size bytes. The codes are also
    aligned on 32-byte boundaries for use with SIMD.

    To avoid misinterpretations, the code_size is set to (size_t)(-1), even if
    arguably the amount of memory consumed by code is block_size / n_per_block.

    The writing functions add_entries and update_entries operate on block-aligned
    data.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    n_per_block = property(_swigfaiss.BlockInvertedLists_n_per_block_get, _swigfaiss.BlockInvertedLists_n_per_block_set)
    block_size = property(_swigfaiss.BlockInvertedLists_block_size_get, _swigfaiss.BlockInvertedLists_block_size_set)
    packer = property(_swigfaiss.BlockInvertedLists_packer_get, _swigfaiss.BlockInvertedLists_packer_set)
    codes = property(_swigfaiss.BlockInvertedLists_codes_get, _swigfaiss.BlockInvertedLists_codes_set)
    ids = property(_swigfaiss.BlockInvertedLists_ids_get, _swigfaiss.BlockInvertedLists_ids_set)

    def __init__(self, *args):
        _swigfaiss.BlockInvertedLists_swiginit(self, _swigfaiss.new_BlockInvertedLists(*args))

    def list_size(self, list_no):
        return _swigfaiss.BlockInvertedLists_list_size(self, list_no)

    def get_codes(self, list_no):
        return _swigfaiss.BlockInvertedLists_get_codes(self, list_no)

    def get_ids(self, list_no):
        return _swigfaiss.BlockInvertedLists_get_ids(self, list_no)

    def remove_ids(self, sel):
        r"""remove ids from the InvertedLists"""
        return _swigfaiss.BlockInvertedLists_remove_ids(self, sel)

    def add_entries(self, list_no, n_entry, ids, code):
        return _swigfaiss.BlockInvertedLists_add_entries(self, list_no, n_entry, ids, code)

    def update_entries(self, list_no, offset, n_entry, ids, code):
        r"""not implemented"""
        return _swigfaiss.BlockInvertedLists_update_entries(self, list_no, offset, n_entry, ids, code)

    def resize(self, list_no, new_size):
        return _swigfaiss.BlockInvertedLists_resize(self, list_no, new_size)
    __swig_destroy__ = _swigfaiss.delete_BlockInvertedLists

# Register BlockInvertedLists in _swigfaiss:
_swigfaiss.BlockInvertedLists_swigregister(BlockInvertedLists)

def lo_build(list_id, offset):
    return _swigfaiss.lo_build(list_id, offset)

def lo_listno(lo):
    return _swigfaiss.lo_listno(lo)

def lo_offset(lo):
    return _swigfaiss.lo_offset(lo)
class DirectMap(object):
    r"""Direct map: a way to map back from ids to inverted lists"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    NoMap = _swigfaiss.DirectMap_NoMap
    Array = _swigfaiss.DirectMap_Array
    Hashtable = _swigfaiss.DirectMap_Hashtable
    DMT_count = _swigfaiss.DirectMap_DMT_count
    type = property(_swigfaiss.DirectMap_type_get, _swigfaiss.DirectMap_type_set)
    array = property(_swigfaiss.DirectMap_array_get, _swigfaiss.DirectMap_array_set, doc=r"""map for direct access to the elements. Map ids to LO-encoded entries.""")
    hashtable = property(_swigfaiss.DirectMap_hashtable_get, _swigfaiss.DirectMap_hashtable_set)

    def __init__(self):
        _swigfaiss.DirectMap_swiginit(self, _swigfaiss.new_DirectMap())

    def set_type(self, new_type, invlists, ntotal):
        r"""set type and initialize"""
        return _swigfaiss.DirectMap_set_type(self, new_type, invlists, ntotal)

    def get(self, id):
        r"""get an entry"""
        return _swigfaiss.DirectMap_get(self, id)

    def no(self):
        r"""for quick checks"""
        return _swigfaiss.DirectMap_no(self)

    def check_can_add(self, ids):
        r"""
        update the direct_map

         throw if Array and ids is not NULL
        """
        return _swigfaiss.DirectMap_check_can_add(self, ids)

    def add_single_id(self, id, list_no, offset):
        r"""non thread-safe version"""
        return _swigfaiss.DirectMap_add_single_id(self, id, list_no, offset)

    def clear(self):
        r"""remove all entries"""
        return _swigfaiss.DirectMap_clear(self)

    def remove_ids(self, sel, invlists):
        r"""
        operations on inverted lists that require translation with a DirectMap

         remove ids from the InvertedLists, possibly using the direct map
        """
        return _swigfaiss.DirectMap_remove_ids(self, sel, invlists)

    def update_codes(self, invlists, n, ids, list_nos, codes):
        r"""update entries, using the direct map"""
        return _swigfaiss.DirectMap_update_codes(self, invlists, n, ids, list_nos, codes)
    __swig_destroy__ = _swigfaiss.delete_DirectMap

# Register DirectMap in _swigfaiss:
_swigfaiss.DirectMap_swigregister(DirectMap)
class DirectMapAdd(object):
    r"""Thread-safe way of updating the direct_map"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    direct_map = property(_swigfaiss.DirectMapAdd_direct_map_get, _swigfaiss.DirectMapAdd_direct_map_set)
    type = property(_swigfaiss.DirectMapAdd_type_get, _swigfaiss.DirectMapAdd_type_set)
    ntotal = property(_swigfaiss.DirectMapAdd_ntotal_get, _swigfaiss.DirectMapAdd_ntotal_set)
    n = property(_swigfaiss.DirectMapAdd_n_get, _swigfaiss.DirectMapAdd_n_set)
    xids = property(_swigfaiss.DirectMapAdd_xids_get, _swigfaiss.DirectMapAdd_xids_set)
    all_ofs = property(_swigfaiss.DirectMapAdd_all_ofs_get, _swigfaiss.DirectMapAdd_all_ofs_set)

    def __init__(self, direct_map, n, xids):
        _swigfaiss.DirectMapAdd_swiginit(self, _swigfaiss.new_DirectMapAdd(direct_map, n, xids))

    def add(self, i, list_no, offset):
        r"""add vector i (with id xids[i]) at list_no and offset"""
        return _swigfaiss.DirectMapAdd_add(self, i, list_no, offset)
    __swig_destroy__ = _swigfaiss.delete_DirectMapAdd

# Register DirectMapAdd in _swigfaiss:
_swigfaiss.DirectMapAdd_swigregister(DirectMapAdd)
class InvertedListScannerStats(object):
    r"""Per-list statistics returned by inverted-list scanners."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    scan_cnt = property(_swigfaiss.InvertedListScannerStats_scan_cnt_get, _swigfaiss.InvertedListScannerStats_scan_cnt_set, doc=r"""Number of distances computed after IDSelector filtering.""")
    nheap_updates = property(_swigfaiss.InvertedListScannerStats_nheap_updates_get, _swigfaiss.InvertedListScannerStats_nheap_updates_set, doc=r"""Number of heap updates.""")

    def __init__(self):
        _swigfaiss.InvertedListScannerStats_swiginit(self, _swigfaiss.new_InvertedListScannerStats())
    __swig_destroy__ = _swigfaiss.delete_InvertedListScannerStats

# Register InvertedListScannerStats in _swigfaiss:
_swigfaiss.InvertedListScannerStats_swigregister(InvertedListScannerStats)
class Level1Quantizer(object):
    r"""
     Encapsulates a quantizer object for the IndexIVF

    The class isolates the fields that are independent of the storage
    of the lists (especially training)
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    quantizer = property(_swigfaiss.Level1Quantizer_quantizer_get, _swigfaiss.Level1Quantizer_quantizer_set, doc=r"""quantizer that maps vectors to inverted lists""")
    nlist = property(_swigfaiss.Level1Quantizer_nlist_get, _swigfaiss.Level1Quantizer_nlist_set, doc=r"""number of inverted lists""")
    quantizer_trains_alone = property(_swigfaiss.Level1Quantizer_quantizer_trains_alone_get, _swigfaiss.Level1Quantizer_quantizer_trains_alone_set, doc=r"""
    = 0: use the quantizer as index in a kmeans training
    = 1: just pass on the training set to the train() of the quantizer
    = 2: kmeans training on a flat index + add the centroids to the quantizer
    """)
    own_fields = property(_swigfaiss.Level1Quantizer_own_fields_get, _swigfaiss.Level1Quantizer_own_fields_set, doc=r"""whether object owns the quantizer""")
    cp = property(_swigfaiss.Level1Quantizer_cp_get, _swigfaiss.Level1Quantizer_cp_set, doc=r"""to override default clustering params""")
    clustering_index = property(_swigfaiss.Level1Quantizer_clustering_index_get, _swigfaiss.Level1Quantizer_clustering_index_set, doc=r"""to override index used during clustering""")

    def train_q1(self, n, x, verbose, metric_type):
        r"""Trains the quantizer and calls train_residual to train sub-quantizers"""
        return _swigfaiss.Level1Quantizer_train_q1(self, n, x, verbose, metric_type)

    def coarse_code_size(self):
        r"""compute the number of bytes required to store list ids"""
        return _swigfaiss.Level1Quantizer_coarse_code_size(self)

    def encode_listno(self, list_no, code):
        return _swigfaiss.Level1Quantizer_encode_listno(self, list_no, code)

    def decode_listno(self, code):
        return _swigfaiss.Level1Quantizer_decode_listno(self, code)

    def __init__(self, *args):
        _swigfaiss.Level1Quantizer_swiginit(self, _swigfaiss.new_Level1Quantizer(*args))
    __swig_destroy__ = _swigfaiss.delete_Level1Quantizer

# Register Level1Quantizer in _swigfaiss:
_swigfaiss.Level1Quantizer_swigregister(Level1Quantizer)
class SearchParametersIVF(SearchParameters):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nprobe = property(_swigfaiss.SearchParametersIVF_nprobe_get, _swigfaiss.SearchParametersIVF_nprobe_set, doc=r"""number of probes at query time""")
    max_codes = property(_swigfaiss.SearchParametersIVF_max_codes_get, _swigfaiss.SearchParametersIVF_max_codes_set, doc=r"""max nb of codes to visit to do a query""")
    max_lists_num = property(_swigfaiss.SearchParametersIVF_max_lists_num_get, _swigfaiss.SearchParametersIVF_max_lists_num_set, doc=r"""
    FastScan k-NN only: maximum number of inverted lists to visit.
    0 means unlimited, i.e. bounded only by nprobe. When set together
    with max_codes, either budget may stop the scan. With
    ensure_topk_full, this limit is treated as at least k lists.
    """)
    ensure_topk_full = property(_swigfaiss.SearchParametersIVF_ensure_topk_full_get, _swigfaiss.SearchParametersIVF_ensure_topk_full_set, doc=r"""
    For k-NN search, make small early-stop budgets less aggressive:
    max_codes is treated as at least k post-IDSelector scans. Supported
    by generic IVF in parallel_mode 0 and 3, and by FastScan k-NN
    implementations 10 and 11.
    """)
    max_empty_result_buckets = property(_swigfaiss.SearchParametersIVF_max_empty_result_buckets_get, _swigfaiss.SearchParametersIVF_max_empty_result_buckets_set, doc=r"""
    Range-search only: stop after this many consecutive probed lists add
    no in-radius results. 0 disables the heuristic. This trades recall
    for less work. Supported in parallel_mode 0; FastScan range search
    uses implementation 10 for this option.
    """)
    quantizer_params = property(_swigfaiss.SearchParametersIVF_quantizer_params_get, _swigfaiss.SearchParametersIVF_quantizer_params_set)
    inverted_list_context = property(_swigfaiss.SearchParametersIVF_inverted_list_context_get, _swigfaiss.SearchParametersIVF_inverted_list_context_set, doc=r"""context object to pass to InvertedLists""")
    __swig_destroy__ = _swigfaiss.delete_SearchParametersIVF

    def __init__(self):
        _swigfaiss.SearchParametersIVF_swiginit(self, _swigfaiss.new_SearchParametersIVF())

# Register SearchParametersIVF in _swigfaiss:
_swigfaiss.SearchParametersIVF_swigregister(SearchParametersIVF)
class IndexIVFInterface(Level1Quantizer):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    nprobe = property(_swigfaiss.IndexIVFInterface_nprobe_get, _swigfaiss.IndexIVFInterface_nprobe_set, doc=r"""number of probes at query time""")
    max_codes = property(_swigfaiss.IndexIVFInterface_max_codes_get, _swigfaiss.IndexIVFInterface_max_codes_set, doc=r"""max nb of codes to visit to do a query""")

    def search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params=None, stats=None):
        r"""
         search a set of vectors, that are pre-quantized by the IVF
         quantizer. Fill in the corresponding heaps with the query
         results. The default implementation uses InvertedListScanners
         to do the search.

        :type n: int
        :param n:      nb of vectors to query
        :type x: float
        :param x:      query vectors, size nx * d
        :type assign: int
        :param assign: coarse quantization indices, size nx * nprobe
        :type centroid_dis: float
        :param centroid_dis:
                          distances to coarse centroids, size nx * nprobe
        :param distance:
                          output distances, size n * k
        :type labels: int
        :param labels: output labels, size n * k
        :type store_pairs: boolean
        :param store_pairs: store inv list index + inv list offset
                                instead in upper/lower 32 bit of result,
                                instead of ids (used for reranking).
        :type params: :py:class:`IVFSearchParameters`, optional
        :param params: used to override the object's search parameters
        :type stats: :py:class:`IndexIVFStats`, optional
        :param stats:  search stats to be updated (can be null)
        """
        return _swigfaiss.IndexIVFInterface_search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params, stats)

    def range_search_preassigned(self, nx, x, radius, keys, coarse_dis, result, store_pairs=False, params=None, stats=None):
        r"""
         Range search a set of vectors, that are pre-quantized by the IVF
         quantizer. Fill in the RangeSearchResults results. The default
        implementation uses InvertedListScanners to do the search.

        :param n:      nb of vectors to query
        :type x: float
        :param x:      query vectors, size nx * d
        :param assign: coarse quantization indices, size nx * nprobe
        :param centroid_dis:
                          distances to coarse centroids, size nx * nprobe
        :type result: :py:class:`RangeSearchResult`
        :param result: Output results
        :type store_pairs: boolean, optional
        :param store_pairs: store inv list index + inv list offset
                                instead in upper/lower 32 bit of result,
                                instead of ids (used for reranking).
        :type params: :py:class:`IVFSearchParameters`, optional
        :param params: used to override the object's search parameters
        :type stats: :py:class:`IndexIVFStats`, optional
        :param stats:  search stats to be updated (can be null)
        """
        return _swigfaiss.IndexIVFInterface_range_search_preassigned(self, nx, x, radius, keys, coarse_dis, result, store_pairs, params, stats)
    __swig_destroy__ = _swigfaiss.delete_IndexIVFInterface

# Register IndexIVFInterface in _swigfaiss:
_swigfaiss.IndexIVFInterface_swigregister(IndexIVFInterface)
class IndexIVF(Index, IndexIVFInterface):
    r"""
     Index based on a inverted file (IVF)

    In the inverted file, the quantizer (an Index instance) provides a
    quantization index for each vector to be added. The quantization
    index maps to a list (aka inverted list or posting list), where the
    id of the vector is stored.

    The inverted list object is required only after training. If none is
    set externally, an ArrayInvertedLists is used automatically.

    At search time, the vector to be searched is also quantized, and
    only the list corresponding to the quantization index is
    searched. This speeds up the search by making it
    non-exhaustive. This can be relaxed using multi-probe search: a few
    (nprobe) quantization indices are selected and several inverted
    lists are visited.

    Sub-classes implement a post-filtering of the index that refines
    the distance estimation from the query to database vectors.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    invlists = property(_swigfaiss.IndexIVF_invlists_get, _swigfaiss.IndexIVF_invlists_set, doc=r"""Access to the actual data""")
    own_invlists = property(_swigfaiss.IndexIVF_own_invlists_get, _swigfaiss.IndexIVF_own_invlists_set)
    code_size = property(_swigfaiss.IndexIVF_code_size_get, _swigfaiss.IndexIVF_code_size_set, doc=r"""code size per vector in bytes""")
    parallel_mode = property(_swigfaiss.IndexIVF_parallel_mode_get, _swigfaiss.IndexIVF_parallel_mode_set, doc=r"""
     Parallel mode determines how queries are parallelized with OpenMP

    0 (default): split over queries
    1: parallelize over inverted lists
    2: parallelize over both
    3: split over queries with a finer granularity

    PARALLEL_MODE_NO_HEAP_INIT: binary or with the previous to
    prevent the heap to be initialized and finalized
    """)
    PARALLEL_MODE_NO_HEAP_INIT = property(_swigfaiss.IndexIVF_PARALLEL_MODE_NO_HEAP_INIT_get)
    direct_map = property(_swigfaiss.IndexIVF_direct_map_get, _swigfaiss.IndexIVF_direct_map_set, doc=r"""
    optional map that maps back ids to invlist entries. This
    enables reconstruct()
    """)
    by_residual = property(_swigfaiss.IndexIVF_by_residual_get, _swigfaiss.IndexIVF_by_residual_set, doc=r"""
    do the codes in the invlists encode the vectors relative to the
    centroids?
    """)

    def reset(self):
        return _swigfaiss.IndexIVF_reset(self)

    def train(self, n, x):
        r"""Trains the quantizer and calls train_encoder to train sub-quantizers"""
        return _swigfaiss.IndexIVF_train(self, n, x)

    def add(self, n, x):
        r"""Calls add_with_ids with NULL ids"""
        return _swigfaiss.IndexIVF_add(self, n, x)

    def add_with_ids(self, n, x, xids):
        r"""default implementation that calls encode_vectors"""
        return _swigfaiss.IndexIVF_add_with_ids(self, n, x, xids)

    def add_core(self, n, x, xids, precomputed_idx, inverted_list_context=None):
        r"""
         Implementation of vector addition where the vector assignments are
        predefined. The default implementation hands over the code extraction to
        encode_vectors.

        :type precomputed_idx: int
        :param precomputed_idx:    quantization indices for the input vectors
            (size n)
        """
        return _swigfaiss.IndexIVF_add_core(self, n, x, xids, precomputed_idx, inverted_list_context)

    def encode_vectors(self, n, x, list_nos, codes, include_listno=False):
        r"""
         Encodes a set of vectors as they would appear in the inverted lists

        :type list_nos: int
        :param list_nos:   inverted list ids as returned by the
                              quantizer (size n). -1s are ignored.
        :type codes: uint8_t
        :param codes:      output codes, size n * code_size
        :type include_listno: boolean, optional
        :param include_listno:
                              include the list ids in the code (in this case add
                              ceil(log8(nlist)) to the code size)
        """
        return _swigfaiss.IndexIVF_encode_vectors(self, n, x, list_nos, codes, include_listno)

    def decode_vectors(self, n, codes, list_nos, x):
        r"""
         Decodes a set of vectors as they would appear in a given set of inverted
        lists (inverse of encode_vectors)

        :type codes: uint8_t
        :param codes:      input codes, size n * code_size
        :type x: float
        :param x:          output decoded vectors
        :type list_nos: int
        :param list_nos:   input listnos, size n
        """
        return _swigfaiss.IndexIVF_decode_vectors(self, n, codes, list_nos, x)

    def add_sa_codes(self, n, codes, xids):
        r"""
         Add vectors that are computed with the standalone codec

        :type codes: uint8_t
        :param codes:  codes to add size n * sa_code_size()
        :type xids: int
        :param xids:   corresponding ids, size n
        """
        return _swigfaiss.IndexIVF_add_sa_codes(self, n, codes, xids)

    def train_encoder(self, n, x, assign):
        r"""
         Train the encoder for the vectors.

        If by_residual then it is called with residuals and corresponding assign
        array, otherwise x is the raw training vectors and assign=nullptr
        """
        return _swigfaiss.IndexIVF_train_encoder(self, n, x, assign)

    def train_encoder_num_vectors(self):
        r"""
        can be redefined by subclasses to indicate how many training vectors
        they need
        """
        return _swigfaiss.IndexIVF_train_encoder_num_vectors(self)

    def search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params=None, stats=None):
        return _swigfaiss.IndexIVF_search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params, stats)

    def range_search_preassigned(self, nx, x, radius, keys, coarse_dis, result, store_pairs=False, params=None, stats=None):
        return _swigfaiss.IndexIVF_range_search_preassigned(self, nx, x, radius, keys, coarse_dis, result, store_pairs, params, stats)

    def search(self, n, x, k, distances, labels, params=None):
        r"""assign the vectors, then call search_preassign"""
        return _swigfaiss.IndexIVF_search(self, n, x, k, distances, labels, params)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexIVF_range_search(self, n, x, radius, result, params)

    def search1(self, x, handler, params=None):
        r"""search one vector with a custom result handler"""
        return _swigfaiss.IndexIVF_search1(self, x, handler, params)

    def get_InvertedListScanner(self, store_pairs=False, sel=None, params=None):
        r"""
         Get a scanner for this index (store_pairs means ignore labels)

        The default search implementation uses this to compute the distances.
        Use sel instead of params->sel, because sel is initialized with
        params->sel, but may get overridden by IndexIVF's internal logic.
        """
        return _swigfaiss.IndexIVF_get_InvertedListScanner(self, store_pairs, sel, params)

    def reconstruct(self, key, recons):
        r"""reconstruct a vector. Works only if maintain_direct_map is set to 1 or 2"""
        return _swigfaiss.IndexIVF_reconstruct(self, key, recons)

    def update_vectors(self, nv, idx, v):
        r"""
         Update a subset of vectors.

        The index must have a direct_map

        :type nv: int
        :param nv:     nb of vectors to update
        :type idx: int
        :param idx:    vector indices to update, size nv
        :type v: float
        :param v:      vectors of new values, size nv*d
        """
        return _swigfaiss.IndexIVF_update_vectors(self, nv, idx, v)

    def reconstruct_n(self, i0, ni, recons):
        r"""
         Reconstruct a subset of the indexed vectors.

        Overrides default implementation to bypass reconstruct() which requires
        direct_map to be maintained.

        :type i0: int
        :param i0:     first vector to reconstruct
        :type ni: int
        :param ni:     nb of vectors to reconstruct
        :type recons: float
        :param recons: output array of reconstructed vectors, size ni * d
        """
        return _swigfaiss.IndexIVF_reconstruct_n(self, i0, ni, recons)

    def search_and_reconstruct(self, n, x, k, distances, labels, recons, params=None):
        r"""
         Similar to search, but also reconstructs the stored vectors (or an
        approximation in the case of lossy coding) for the search results.

        Overrides default implementation to avoid having to maintain direct_map
        and instead fetch the code offsets through the `store_pairs` flag in
        search_preassigned().

        :type recons: float
        :param recons:      reconstructed vectors size (n, k, d)
        """
        return _swigfaiss.IndexIVF_search_and_reconstruct(self, n, x, k, distances, labels, recons, params)

    def search_and_return_codes(self, n, x, k, distances, labels, recons, include_listno=False, params=None):
        r"""
         Similar to search, but also returns the codes corresponding to the
        stored vectors for the search results.

        :param codes:      codes (n, k, code_size)
        :type include_listno: boolean, optional
        :param include_listno:
                              include the list ids in the code (in this case add
                              ceil(log8(nlist)) to the code size)
        """
        return _swigfaiss.IndexIVF_search_and_return_codes(self, n, x, k, distances, labels, recons, include_listno, params)

    def reconstruct_from_offset(self, list_no, offset, recons):
        r"""
         Reconstruct a vector given the location in terms of (inv list index +
        inv list offset) instead of the id.

        Useful for reconstructing when the direct_map is not maintained and
        the inv list offset is computed by search_preassigned() with
        `store_pairs` set.
        """
        return _swigfaiss.IndexIVF_reconstruct_from_offset(self, list_no, offset, recons)

    def remove_ids(self, sel):
        r"""Dataset manipulation functions"""
        return _swigfaiss.IndexIVF_remove_ids(self, sel)

    def check_compatible_for_merge(self, otherIndex):
        return _swigfaiss.IndexIVF_check_compatible_for_merge(self, otherIndex)

    def merge_from(self, otherIndex, add_id):
        return _swigfaiss.IndexIVF_merge_from(self, otherIndex, add_id)

    def get_CodePacker(self):
        return _swigfaiss.IndexIVF_get_CodePacker(self)

    def copy_subset_to(self, other, subset_type, a1, a2):
        r"""
         copy a subset of the entries index to the other index
        see Invlists::copy_subset_to for the meaning of subset_type
        """
        return _swigfaiss.IndexIVF_copy_subset_to(self, other, subset_type, a1, a2)
    __swig_destroy__ = _swigfaiss.delete_IndexIVF

    def get_list_size(self, list_no):
        return _swigfaiss.IndexIVF_get_list_size(self, list_no)

    def check_ids_sorted(self):
        r"""are the ids sorted?"""
        return _swigfaiss.IndexIVF_check_ids_sorted(self)

    def make_direct_map(self, new_maintain_direct_map=True):
        r"""
         initialize a direct map

        :type new_maintain_direct_map: boolean, optional
        :param new_maintain_direct_map:    if true, create a direct map,
                                              else clear it
        """
        return _swigfaiss.IndexIVF_make_direct_map(self, new_maintain_direct_map)

    def set_direct_map_type(self, type):
        return _swigfaiss.IndexIVF_set_direct_map_type(self, type)

    def replace_invlists(self, il, own=False):
        r"""replace the inverted lists, old one is deallocated if own_invlists"""
        return _swigfaiss.IndexIVF_replace_invlists(self, il, own)

    def sa_code_size(self):
        return _swigfaiss.IndexIVF_sa_code_size(self)

    def sa_encode(self, n, x, bytes):
        r"""
         encode a set of vectors
        sa_encode will call encode_vectors with include_listno=true
        :type n: int
        :param n:      nb of vectors to encode
        :type x: float
        :param x:      the vectors to encode
        :type bytes: uint8_t
        :param bytes:  output array for the codes
        :rtype: void
        :return: nb of bytes written to codes
        """
        return _swigfaiss.IndexIVF_sa_encode(self, n, x, bytes)

# Register IndexIVF in _swigfaiss:
_swigfaiss.IndexIVF_swigregister(IndexIVF)
class InvertedListScanner(object):
    r"""
     Object that handles a query. The inverted lists to scan are
    provided externally. The object has a lot of state, but
    distance_to_code and scan_codes can be called in multiple
    threads
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    list_no = property(_swigfaiss.InvertedListScanner_list_no_get, _swigfaiss.InvertedListScanner_list_no_set, doc=r"""remember current list""")
    keep_max = property(_swigfaiss.InvertedListScanner_keep_max_get, _swigfaiss.InvertedListScanner_keep_max_set, doc=r"""keep maximum instead of minimum""")
    store_pairs = property(_swigfaiss.InvertedListScanner_store_pairs_get, _swigfaiss.InvertedListScanner_store_pairs_set, doc=r"""store positions in invlists rather than labels""")
    sel = property(_swigfaiss.InvertedListScanner_sel_get, _swigfaiss.InvertedListScanner_sel_set, doc=r"""search in this subset of ids""")
    code_size = property(_swigfaiss.InvertedListScanner_code_size_get, _swigfaiss.InvertedListScanner_code_size_set, doc=r"""used in default implementation of scan_codes""")

    def set_query(self, query_vector):
        r"""from now on we handle this query."""
        return _swigfaiss.InvertedListScanner_set_query(self, query_vector)

    def set_list(self, list_no, coarse_dis):
        r"""following codes come from this inverted list"""
        return _swigfaiss.InvertedListScanner_set_list(self, list_no, coarse_dis)

    def distance_to_code(self, code):
        r"""compute a single query-to-code distance"""
        return _swigfaiss.InvertedListScanner_distance_to_code(self, code)

    def iterate_codes(self, iterator, distances, labels, k, list_size):
        return _swigfaiss.InvertedListScanner_iterate_codes(self, iterator, distances, labels, k, list_size)

    def scan_codes_range(self, n, codes, ids, radius, result):
        r"""
         scan a set of codes, compute distances to current query and
        update results if distances are below radius

        (default implementation fails)
        """
        return _swigfaiss.InvertedListScanner_scan_codes_range(self, n, codes, ids, radius, result)

    def iterate_codes_range(self, iterator, radius, result, list_size):
        return _swigfaiss.InvertedListScanner_iterate_codes_range(self, iterator, radius, result, list_size)

    def scan_codes(self, *args):
        r"""
         scan a set of codes, compute distances to current query, and
        update heap of results if necessary. Default implementation
        calls distance_to_code.

        :type n: int
        :param n:          number of codes to scan
        :type codes: uint8_t
        :param codes:      codes to scan (n * code_size)
        :type ids: int
        :param ids:        corresponding ids (ignored if store_pairs)
        :type distances: float
        :param distances:  heap distances (size k)
        :type labels: int
        :param labels:     heap labels (size k)
        :type k: int
        :param k:          heap size
        :rtype: int
        :return: number of heap updates performed
        """
        return _swigfaiss.InvertedListScanner_scan_codes(self, *args)
    __swig_destroy__ = _swigfaiss.delete_InvertedListScanner

# Register InvertedListScanner in _swigfaiss:
_swigfaiss.InvertedListScanner_swigregister(InvertedListScanner)
class IndexIVFStats(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nq = property(_swigfaiss.IndexIVFStats_nq_get, _swigfaiss.IndexIVFStats_nq_set)
    nlist = property(_swigfaiss.IndexIVFStats_nlist_get, _swigfaiss.IndexIVFStats_nlist_set)
    ndis = property(_swigfaiss.IndexIVFStats_ndis_get, _swigfaiss.IndexIVFStats_ndis_set)
    nheap_updates = property(_swigfaiss.IndexIVFStats_nheap_updates_get, _swigfaiss.IndexIVFStats_nheap_updates_set)
    quantization_time = property(_swigfaiss.IndexIVFStats_quantization_time_get, _swigfaiss.IndexIVFStats_quantization_time_set)
    search_time = property(_swigfaiss.IndexIVFStats_search_time_get, _swigfaiss.IndexIVFStats_search_time_set)

    def __init__(self):
        _swigfaiss.IndexIVFStats_swiginit(self, _swigfaiss.new_IndexIVFStats())

    def reset(self):
        return _swigfaiss.IndexIVFStats_reset(self)

    def add(self, other):
        return _swigfaiss.IndexIVFStats_add(self, other)
    __swig_destroy__ = _swigfaiss.delete_IndexIVFStats

# Register IndexIVFStats in _swigfaiss:
_swigfaiss.IndexIVFStats_swigregister(IndexIVFStats)

def check_compatible_for_merge(index1, index2):
    r"""
     check if two indexes have the same parameters and are trained in
    the same way, otherwise throw.
    """
    return _swigfaiss.check_compatible_for_merge(index1, index2)

def extract_index_ivf(*args):
    r"""
     get an IndexIVF from an index. The index may be an IndexIVF or
    some wrapper class that encloses an IndexIVF

    throws an exception if this is not the case.
    """
    return _swigfaiss.extract_index_ivf(*args)

def try_extract_index_ivf(*args):
    r"""same as above but returns nullptr instead of throwing on failure"""
    return _swigfaiss.try_extract_index_ivf(*args)

def merge_into(index0, index1, shift_ids):
    r"""
     Merge index1 into index0. Works on IndexIVF's and IndexIVF's
     embedded in a IndexPreTransform. On output, the index1 is empty.

    :type shift_ids: boolean
    :param shift_ids:: translate the ids from index1 to index0->prev_ntotal
    """
    return _swigfaiss.merge_into(index0, index1, shift_ids)

def search_centroid(index, x, n, centroid_ids):
    return _swigfaiss.search_centroid(index, x, n, centroid_ids)

def search_and_return_centroids(index, n, xin, k, distances, labels, query_centroid_ids, result_centroid_ids):
    return _swigfaiss.search_and_return_centroids(index, n, xin, k, distances, labels, query_centroid_ids, result_centroid_ids)
class SlidingIndexWindow(object):
    r"""
     A set of IndexIVFs concatenated together in a FIFO fashion.
    at each "step", the oldest index slice is removed and a new index is added.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    index = property(_swigfaiss.SlidingIndexWindow_index_get, _swigfaiss.SlidingIndexWindow_index_set, doc=r"""common index that contains the sliding window""")
    ils = property(_swigfaiss.SlidingIndexWindow_ils_get, _swigfaiss.SlidingIndexWindow_ils_set, doc=r"""InvertedLists of index""")
    n_slice = property(_swigfaiss.SlidingIndexWindow_n_slice_get, _swigfaiss.SlidingIndexWindow_n_slice_set, doc=r"""number of slices currently in index""")
    nlist = property(_swigfaiss.SlidingIndexWindow_nlist_get, _swigfaiss.SlidingIndexWindow_nlist_set, doc=r"""same as index->nlist""")
    sizes = property(_swigfaiss.SlidingIndexWindow_sizes_get, _swigfaiss.SlidingIndexWindow_sizes_set, doc=r"""cumulative list sizes at each slice""")

    def __init__(self, index):
        r"""index should be initially empty and trained"""
        _swigfaiss.SlidingIndexWindow_swiginit(self, _swigfaiss.new_SlidingIndexWindow(index))

    def step(self, sub_index, remove_oldest):
        r"""
         Add one index to the current index and remove the oldest one.

        :type sub_index: :py:class:`Index`
        :param sub_index:        slice to swap in (can be NULL)
        :type remove_oldest: boolean
        :param remove_oldest:    if true, remove the oldest slices
        """
        return _swigfaiss.SlidingIndexWindow_step(self, sub_index, remove_oldest)
    __swig_destroy__ = _swigfaiss.delete_SlidingIndexWindow

# Register SlidingIndexWindow in _swigfaiss:
_swigfaiss.SlidingIndexWindow_swigregister(SlidingIndexWindow)

def get_invlist_range(index, i0, i1):
    r"""Get a subset of inverted lists [i0, i1)"""
    return _swigfaiss.get_invlist_range(index, i0, i1)

def set_invlist_range(index, i0, i1, src):
    r"""Set a subset of inverted lists"""
    return _swigfaiss.set_invlist_range(index, i0, i1, src)

def search_with_parameters(index, n, x, k, distances, labels, params, nb_dis=None, ms_per_stage=None):
    r"""
     search an IndexIVF, possibly embedded in an IndexPreTransform with
    given parameters. This is a way to set the nprobe and get
    statdistics in a thread-safe way.

    Optionally returns (if non-nullptr):
    - nb_dis: number of distances computed
    - ms_per_stage: [0]: preprocessing time
                    [1]: coarse quantization,
                    [2]: list scanning
    """
    return _swigfaiss.search_with_parameters(index, n, x, k, distances, labels, params, nb_dis, ms_per_stage)

def range_search_with_parameters(index, n, x, radius, result, params, nb_dis=None, ms_per_stage=None):
    r"""same as search_with_parameters but for range search"""
    return _swigfaiss.range_search_with_parameters(index, n, x, radius, result, params, nb_dis, ms_per_stage)

def ivf_residual_from_quantizer(arg1, nlevel):
    r"""
     Build an IndexIVFResidualQuantizer from an ResidualQuantizer, using the
    nlevel first components as coarse quantizer and the rest as codes in invlists
    """
    return _swigfaiss.ivf_residual_from_quantizer(arg1, nlevel)

def ivf_residual_add_from_flat_codes(ivfrq, ncode, codes, code_size=-1):
    r"""
     add from codes. NB that the norm component is not used, so the code_size can
    be provided.

    :type ivfrq: :py:class:`IndexIVFResidualQuantizer`
    :param ivfrq:      index to populate with the codes
    :type codes: uint8_t
    :param codes:      codes to add, size (ncode, code_size)
    :type code_size: int, optional
    :param code_size:  override the ivfrq's code_size, useful if the norm encoding
                          is different
    """
    return _swigfaiss.ivf_residual_add_from_flat_codes(ivfrq, ncode, codes, code_size)
class ShardingFunction(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr

    def __call__(self, i, shard_count):
        return _swigfaiss.ShardingFunction___call__(self, i, shard_count)
    __swig_destroy__ = _swigfaiss.delete_ShardingFunction

# Register ShardingFunction in _swigfaiss:
_swigfaiss.ShardingFunction_swigregister(ShardingFunction)
class DefaultShardingFunction(ShardingFunction):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __call__(self, i, shard_count):
        return _swigfaiss.DefaultShardingFunction___call__(self, i, shard_count)

    def __init__(self):
        _swigfaiss.DefaultShardingFunction_swiginit(self, _swigfaiss.new_DefaultShardingFunction())
    __swig_destroy__ = _swigfaiss.delete_DefaultShardingFunction

# Register DefaultShardingFunction in _swigfaiss:
_swigfaiss.DefaultShardingFunction_swigregister(DefaultShardingFunction)

def shard_ivf_index_centroids(*args):
    r"""
    Shards an IVF index centroids by the given sharding function, and writes
    the index to the path given by filename_generator. The centroids must already
    be added to the index quantizer.

    :type index: :py:class:`IndexIVF`
    :param index:             The IVF index containing centroids to shard.
    :type shard_count: int, optional
    :param shard_count:       Number of shards.
    :type filename_template: string, optional
    :param filename_template: Template for shard filenames.
    :type sharding_function: :py:class:`ShardingFunction`, optional
    :param sharding_function: The function to shard by. The default is ith vector
                                 mod shard_count.
    :type generate_ids: boolean, optional
    :param generate_ids:      Generates ids using IndexIDMap2. If true, ids will
                                 match the default ids in the unsharded index.
    :rtype: void
    :return: The number of shards written.
    """
    return _swigfaiss.shard_ivf_index_centroids(*args)

def shard_binary_ivf_index_centroids(*args):
    return _swigfaiss.shard_binary_ivf_index_centroids(*args)
class ScalarQuantizer(Quantizer):
    r"""
    The uniform quantizer has a range [vmin, vmax]. The range can be
    the same for all dimensions (uniform) or specific per dimension
    (default).
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    QT_8bit = _swigfaiss.ScalarQuantizer_QT_8bit
    r"""8 bits per component"""
    QT_4bit = _swigfaiss.ScalarQuantizer_QT_4bit
    r"""4 bits per component"""
    QT_8bit_uniform = _swigfaiss.ScalarQuantizer_QT_8bit_uniform
    r"""same, shared range for all dimensions"""
    QT_4bit_uniform = _swigfaiss.ScalarQuantizer_QT_4bit_uniform
    QT_fp16 = _swigfaiss.ScalarQuantizer_QT_fp16
    QT_8bit_direct = _swigfaiss.ScalarQuantizer_QT_8bit_direct
    r"""fast indexing of uint8s"""
    QT_6bit = _swigfaiss.ScalarQuantizer_QT_6bit
    r"""6 bits per component"""
    QT_bf16 = _swigfaiss.ScalarQuantizer_QT_bf16
    QT_8bit_direct_signed = _swigfaiss.ScalarQuantizer_QT_8bit_direct_signed
    r"""
    fast indexing of signed int8s ranging from
    [-128 to 127]
    """
    QT_0bit = _swigfaiss.ScalarQuantizer_QT_0bit
    r"""0 bits per component, centroid-only distance (for IVF)"""
    QT_1bit_tqmse = _swigfaiss.ScalarQuantizer_QT_1bit_tqmse
    r"""TurboQuant MSE-optimized, 1 bit per component"""
    QT_2bit_tqmse = _swigfaiss.ScalarQuantizer_QT_2bit_tqmse
    r"""TurboQuant MSE-optimized, 2 bits per component"""
    QT_3bit_tqmse = _swigfaiss.ScalarQuantizer_QT_3bit_tqmse
    r"""TurboQuant MSE-optimized, 3 bits per component"""
    QT_4bit_tqmse = _swigfaiss.ScalarQuantizer_QT_4bit_tqmse
    r"""TurboQuant MSE-optimized, 4 bits per component"""
    QT_8bit_tqmse = _swigfaiss.ScalarQuantizer_QT_8bit_tqmse
    r"""TurboQuant MSE-optimized, 8 bits per component"""
    QT_2bit_tq = _swigfaiss.ScalarQuantizer_QT_2bit_tq
    r"""Full TurboQuant (1-bit MSE + 1-bit QJL + factors)"""
    QT_3bit_tq = _swigfaiss.ScalarQuantizer_QT_3bit_tq
    r"""Full TurboQuant (2-bit MSE + 1-bit QJL + factors)"""
    QT_4bit_tq = _swigfaiss.ScalarQuantizer_QT_4bit_tq
    r"""Full TurboQuant (3-bit MSE + 1-bit QJL + factors)"""
    QT_5bit_tq = _swigfaiss.ScalarQuantizer_QT_5bit_tq
    r"""Full TurboQuant (4-bit MSE + 1-bit QJL + factors)"""
    QT_count = _swigfaiss.ScalarQuantizer_QT_count
    qtype = property(_swigfaiss.ScalarQuantizer_qtype_get, _swigfaiss.ScalarQuantizer_qtype_set)
    RS_minmax = _swigfaiss.ScalarQuantizer_RS_minmax
    r"""[min - rs*(max-min), max + rs*(max-min)]"""
    RS_meanstd = _swigfaiss.ScalarQuantizer_RS_meanstd
    r"""[mean - std * rs, mean + std * rs]"""
    RS_quantiles = _swigfaiss.ScalarQuantizer_RS_quantiles
    r"""[Q(rs), Q(1-rs)]"""
    RS_optim = _swigfaiss.ScalarQuantizer_RS_optim
    r"""alternate optimization of reconstruction error"""
    rangestat = property(_swigfaiss.ScalarQuantizer_rangestat_get, _swigfaiss.ScalarQuantizer_rangestat_set)
    rangestat_arg = property(_swigfaiss.ScalarQuantizer_rangestat_arg_get, _swigfaiss.ScalarQuantizer_rangestat_arg_set)
    bits = property(_swigfaiss.ScalarQuantizer_bits_get, _swigfaiss.ScalarQuantizer_bits_set, doc=r"""bits per scalar code""")
    trained = property(_swigfaiss.ScalarQuantizer_trained_get, _swigfaiss.ScalarQuantizer_trained_set, doc=r"""trained values (including the range)""")

    def __init__(self, *args):
        _swigfaiss.ScalarQuantizer_swiginit(self, _swigfaiss.new_ScalarQuantizer(*args))

    def set_derived_sizes(self):
        r"""updates internal values based on qtype and d"""
        return _swigfaiss.ScalarQuantizer_set_derived_sizes(self)

    def train(self, n, x):
        return _swigfaiss.ScalarQuantizer_train(self, n, x)

    def compute_codes(self, x, codes, n):
        r"""
         Encode a set of vectors

        :type x: float
        :param x:      vectors to encode, size n * d
        :type codes: uint8_t
        :param codes:  output codes, size n * code_size
        """
        return _swigfaiss.ScalarQuantizer_compute_codes(self, x, codes, n)

    def decode(self, code, x, n):
        r"""
         Decode a set of vectors

        :param codes:  codes to decode, size n * code_size
        :type x: float
        :param x:      output vectors, size n * d
        """
        return _swigfaiss.ScalarQuantizer_decode(self, code, x, n)

    def select_quantizer(self):
        return _swigfaiss.ScalarQuantizer_select_quantizer(self)
    turboq_refine = property(_swigfaiss.ScalarQuantizer_turboq_refine_get, _swigfaiss.ScalarQuantizer_turboq_refine_set)

    def get_distance_computer(self, *args):
        return _swigfaiss.ScalarQuantizer_get_distance_computer(self, *args)

    def select_InvertedListScanner(self, mt, quantizer, store_pairs, sel, by_residual=False):
        return _swigfaiss.ScalarQuantizer_select_InvertedListScanner(self, mt, quantizer, store_pairs, sel, by_residual)
    __swig_destroy__ = _swigfaiss.delete_ScalarQuantizer

# Register ScalarQuantizer in _swigfaiss:
_swigfaiss.ScalarQuantizer_swigregister(ScalarQuantizer)
class IndexScalarQuantizer(IndexFlatCodes):
    r"""Flat index built on a scalar quantizer."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    sq = property(_swigfaiss.IndexScalarQuantizer_sq_get, _swigfaiss.IndexScalarQuantizer_sq_set, doc=r"""Used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type qtype: int
        :param qtype:  type of scalar quantizer (e.g., QT_4bit)
        :type metric: int, optional
        :param metric: distance metric used for search (default: METRIC_L2)
        """
        _swigfaiss.IndexScalarQuantizer_swiginit(self, _swigfaiss.new_IndexScalarQuantizer(*args))

    def train(self, n, x):
        return _swigfaiss.IndexScalarQuantizer_train(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexScalarQuantizer_search(self, n, x, k, distances, labels, params)

    def get_FlatCodesDistanceComputer(self):
        return _swigfaiss.IndexScalarQuantizer_get_FlatCodesDistanceComputer(self)

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.IndexScalarQuantizer_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexScalarQuantizer_sa_decode(self, n, bytes, x)
    __swig_destroy__ = _swigfaiss.delete_IndexScalarQuantizer

# Register IndexScalarQuantizer in _swigfaiss:
_swigfaiss.IndexScalarQuantizer_swigregister(IndexScalarQuantizer)
class IVFSQTurboQSearchParameters(SearchParametersIVF):
    r"""
     An IVF implementation where the components of the residuals are
    encoded with a scalar quantizer. All distance computations
    are asymmetric, so the encoded vectors are decoded and approximate
    distances are computed.

     Search parameters for TurboQuant full types (QT_*_tq).
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    qb = property(_swigfaiss.IVFSQTurboQSearchParameters_qb_get, _swigfaiss.IVFSQTurboQSearchParameters_qb_set, doc=r"""
    Query quantization bits for integer MSE pre-screening.
    0 = float path (default), 1-8 = integer popcount path.
    """)
    int_qjl = property(_swigfaiss.IVFSQTurboQSearchParameters_int_qjl_get, _swigfaiss.IVFSQTurboQSearchParameters_int_qjl_set, doc=r"""Also use integer popcount for QJL stage (requires qb > 0).""")

    def __init__(self):
        _swigfaiss.IVFSQTurboQSearchParameters_swiginit(self, _swigfaiss.new_IVFSQTurboQSearchParameters())
    __swig_destroy__ = _swigfaiss.delete_IVFSQTurboQSearchParameters

# Register IVFSQTurboQSearchParameters in _swigfaiss:
_swigfaiss.IVFSQTurboQSearchParameters_swigregister(IVFSQTurboQSearchParameters)
class IndexIVFScalarQuantizer(IndexIVF):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    sq = property(_swigfaiss.IndexIVFScalarQuantizer_sq_get, _swigfaiss.IndexIVFScalarQuantizer_sq_set)

    def __init__(self, *args):
        _swigfaiss.IndexIVFScalarQuantizer_swiginit(self, _swigfaiss.new_IndexIVFScalarQuantizer(*args))

    def train_encoder(self, n, x, assign):
        return _swigfaiss.IndexIVFScalarQuantizer_train_encoder(self, n, x, assign)

    def train_encoder_num_vectors(self):
        return _swigfaiss.IndexIVFScalarQuantizer_train_encoder_num_vectors(self)

    def encode_vectors(self, n, x, list_nos, codes, include_listnos=False):
        return _swigfaiss.IndexIVFScalarQuantizer_encode_vectors(self, n, x, list_nos, codes, include_listnos)

    def decode_vectors(self, n, codes, list_nos, x):
        return _swigfaiss.IndexIVFScalarQuantizer_decode_vectors(self, n, codes, list_nos, x)

    def add_core(self, n, x, xids, precomputed_idx, inverted_list_context=None):
        return _swigfaiss.IndexIVFScalarQuantizer_add_core(self, n, x, xids, precomputed_idx, inverted_list_context)

    def get_InvertedListScanner(self, store_pairs, sel, params):
        return _swigfaiss.IndexIVFScalarQuantizer_get_InvertedListScanner(self, store_pairs, sel, params)

    def reconstruct_from_offset(self, list_no, offset, recons):
        return _swigfaiss.IndexIVFScalarQuantizer_reconstruct_from_offset(self, list_no, offset, recons)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexIVFScalarQuantizer_sa_decode(self, n, bytes, x)
    __swig_destroy__ = _swigfaiss.delete_IndexIVFScalarQuantizer

# Register IndexIVFScalarQuantizer in _swigfaiss:
_swigfaiss.IndexIVFScalarQuantizer_swigregister(IndexIVFScalarQuantizer)
class IndexIVFSpectralHash(IndexIVF):
    r"""
     Inverted list that stores binary codes of size nbit. Before the
    binary conversion, the dimension of the vectors is transformed from
    dim d into dim nbit by vt (a random rotation by default).

    Each coordinate is subtracted from a value determined by
    threshold_type, and split into intervals of size period. Half of
    the interval is a 0 bit, the other half a 1.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    vt = property(_swigfaiss.IndexIVFSpectralHash_vt_get, _swigfaiss.IndexIVFSpectralHash_vt_set, doc=r"""transformation from d to nbit dim""")
    own_fields = property(_swigfaiss.IndexIVFSpectralHash_own_fields_get, _swigfaiss.IndexIVFSpectralHash_own_fields_set, doc=r"""own the vt""")
    nbit = property(_swigfaiss.IndexIVFSpectralHash_nbit_get, _swigfaiss.IndexIVFSpectralHash_nbit_set, doc=r"""nb of bits of the binary signature""")
    period = property(_swigfaiss.IndexIVFSpectralHash_period_get, _swigfaiss.IndexIVFSpectralHash_period_set, doc=r"""interval size for 0s and 1s""")
    Thresh_global = _swigfaiss.IndexIVFSpectralHash_Thresh_global
    r"""global threshold at 0"""
    Thresh_centroid = _swigfaiss.IndexIVFSpectralHash_Thresh_centroid
    r"""compare to centroid"""
    Thresh_centroid_half = _swigfaiss.IndexIVFSpectralHash_Thresh_centroid_half
    r"""central interval around centroid"""
    Thresh_median = _swigfaiss.IndexIVFSpectralHash_Thresh_median
    r"""median of training set"""
    threshold_type = property(_swigfaiss.IndexIVFSpectralHash_threshold_type_get, _swigfaiss.IndexIVFSpectralHash_threshold_type_set)
    trained = property(_swigfaiss.IndexIVFSpectralHash_trained_get, _swigfaiss.IndexIVFSpectralHash_trained_set, doc=r"""
    Trained threshold.
    size nlist * nbit or 0 if Thresh_global
    """)

    def __init__(self, *args):
        _swigfaiss.IndexIVFSpectralHash_swiginit(self, _swigfaiss.new_IndexIVFSpectralHash(*args))

    def train_encoder(self, n, x, assign):
        return _swigfaiss.IndexIVFSpectralHash_train_encoder(self, n, x, assign)

    def encode_vectors(self, n, x, list_nos, codes, include_listnos=False):
        return _swigfaiss.IndexIVFSpectralHash_encode_vectors(self, n, x, list_nos, codes, include_listnos)

    def get_InvertedListScanner(self, store_pairs, sel, params):
        return _swigfaiss.IndexIVFSpectralHash_get_InvertedListScanner(self, store_pairs, sel, params)

    def replace_vt(self, *args):
        r"""
        *Overload 1:*
         replace the vector transform for an empty (and possibly untrained) index

        |

        *Overload 2:*
         convenience function to get the VT from an index constructed by an
        index_factory (should end in "LSH")

        |

        *Overload 3:*
         convenience function to get the VT from an index constructed by an
        index_factory (should end in "LSH")
        """
        return _swigfaiss.IndexIVFSpectralHash_replace_vt(self, *args)
    __swig_destroy__ = _swigfaiss.delete_IndexIVFSpectralHash

# Register IndexIVFSpectralHash in _swigfaiss:
_swigfaiss.IndexIVFSpectralHash_swigregister(IndexIVFSpectralHash)
class IndexIVFAdditiveQuantizer(IndexIVF):
    r"""
    Abstract class for IVF additive quantizers.
    The search functions are in common.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    aq = property(_swigfaiss.IndexIVFAdditiveQuantizer_aq_get, _swigfaiss.IndexIVFAdditiveQuantizer_aq_set)
    use_precomputed_table = property(_swigfaiss.IndexIVFAdditiveQuantizer_use_precomputed_table_get, _swigfaiss.IndexIVFAdditiveQuantizer_use_precomputed_table_set)

    def __init__(self, *args):
        _swigfaiss.IndexIVFAdditiveQuantizer_swiginit(self, _swigfaiss.new_IndexIVFAdditiveQuantizer(*args))

    def train_encoder(self, n, x, assign):
        return _swigfaiss.IndexIVFAdditiveQuantizer_train_encoder(self, n, x, assign)

    def train_encoder_num_vectors(self):
        return _swigfaiss.IndexIVFAdditiveQuantizer_train_encoder_num_vectors(self)

    def encode_vectors(self, n, x, list_nos, codes, include_listnos=False):
        return _swigfaiss.IndexIVFAdditiveQuantizer_encode_vectors(self, n, x, list_nos, codes, include_listnos)

    def decode_vectors(self, n, codes, list_nos, x):
        return _swigfaiss.IndexIVFAdditiveQuantizer_decode_vectors(self, n, codes, list_nos, x)

    def get_InvertedListScanner(self, store_pairs, sel, params):
        return _swigfaiss.IndexIVFAdditiveQuantizer_get_InvertedListScanner(self, store_pairs, sel, params)

    def sa_decode(self, n, codes, x):
        return _swigfaiss.IndexIVFAdditiveQuantizer_sa_decode(self, n, codes, x)

    def reconstruct_from_offset(self, list_no, offset, recons):
        return _swigfaiss.IndexIVFAdditiveQuantizer_reconstruct_from_offset(self, list_no, offset, recons)
    __swig_destroy__ = _swigfaiss.delete_IndexIVFAdditiveQuantizer

# Register IndexIVFAdditiveQuantizer in _swigfaiss:
_swigfaiss.IndexIVFAdditiveQuantizer_swigregister(IndexIVFAdditiveQuantizer)
class IndexIVFResidualQuantizer(IndexIVFAdditiveQuantizer):
    r"""
     IndexIVF based on a residual quantizer. Stored vectors are
    approximated by residual quantization codes.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    rq = property(_swigfaiss.IndexIVFResidualQuantizer_rq_get, _swigfaiss.IndexIVFResidualQuantizer_rq_set, doc=r"""The residual quantizer used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :param M:      number of subquantizers
        :type nbits: std::vector< size_t >
        :param nbits:  number of bit per subvector index
        """
        _swigfaiss.IndexIVFResidualQuantizer_swiginit(self, _swigfaiss.new_IndexIVFResidualQuantizer(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFResidualQuantizer

# Register IndexIVFResidualQuantizer in _swigfaiss:
_swigfaiss.IndexIVFResidualQuantizer_swigregister(IndexIVFResidualQuantizer)
class IndexIVFLocalSearchQuantizer(IndexIVFAdditiveQuantizer):
    r"""
     IndexIVF based on a residual quantizer. Stored vectors are
    approximated by residual quantization codes.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    lsq = property(_swigfaiss.IndexIVFLocalSearchQuantizer_lsq_get, _swigfaiss.IndexIVFLocalSearchQuantizer_lsq_set, doc=r"""The LSQ quantizer used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type M: int
        :param M:      number of subquantizers
        :type nbits: int
        :param nbits:  number of bit per subvector index
        """
        _swigfaiss.IndexIVFLocalSearchQuantizer_swiginit(self, _swigfaiss.new_IndexIVFLocalSearchQuantizer(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFLocalSearchQuantizer

# Register IndexIVFLocalSearchQuantizer in _swigfaiss:
_swigfaiss.IndexIVFLocalSearchQuantizer_swigregister(IndexIVFLocalSearchQuantizer)
class IndexIVFProductResidualQuantizer(IndexIVFAdditiveQuantizer):
    r"""
     IndexIVF based on a product residual quantizer. Stored vectors are
    approximated by product residual quantization codes.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    prq = property(_swigfaiss.IndexIVFProductResidualQuantizer_prq_get, _swigfaiss.IndexIVFProductResidualQuantizer_prq_set, doc=r"""The product residual quantizer used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type nsplits: int
        :param nsplits:  number of residual quantizers
        :type Msub: int
        :param Msub:   number of subquantizers per RQ
        :type nbits: int
        :param nbits:  number of bit per subvector index
        """
        _swigfaiss.IndexIVFProductResidualQuantizer_swiginit(self, _swigfaiss.new_IndexIVFProductResidualQuantizer(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFProductResidualQuantizer

# Register IndexIVFProductResidualQuantizer in _swigfaiss:
_swigfaiss.IndexIVFProductResidualQuantizer_swigregister(IndexIVFProductResidualQuantizer)
class IndexIVFProductLocalSearchQuantizer(IndexIVFAdditiveQuantizer):
    r"""
     IndexIVF based on a product local search quantizer. Stored vectors are
    approximated by product local search quantization codes.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    plsq = property(_swigfaiss.IndexIVFProductLocalSearchQuantizer_plsq_get, _swigfaiss.IndexIVFProductLocalSearchQuantizer_plsq_set, doc=r"""The product local search quantizer used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type nsplits: int
        :param nsplits:  number of local search quantizers
        :type Msub: int
        :param Msub:   number of subquantizers per LSQ
        :type nbits: int
        :param nbits:  number of bit per subvector index
        """
        _swigfaiss.IndexIVFProductLocalSearchQuantizer_swiginit(self, _swigfaiss.new_IndexIVFProductLocalSearchQuantizer(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFProductLocalSearchQuantizer

# Register IndexIVFProductLocalSearchQuantizer in _swigfaiss:
_swigfaiss.IndexIVFProductLocalSearchQuantizer_swigregister(IndexIVFProductLocalSearchQuantizer)
class SearchParametersHNSW(SearchParameters):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    efSearch = property(_swigfaiss.SearchParametersHNSW_efSearch_get, _swigfaiss.SearchParametersHNSW_efSearch_set)
    check_relative_distance = property(_swigfaiss.SearchParametersHNSW_check_relative_distance_get, _swigfaiss.SearchParametersHNSW_check_relative_distance_set)
    bounded_queue = property(_swigfaiss.SearchParametersHNSW_bounded_queue_get, _swigfaiss.SearchParametersHNSW_bounded_queue_set)
    __swig_destroy__ = _swigfaiss.delete_SearchParametersHNSW

    def __init__(self):
        _swigfaiss.SearchParametersHNSW_swiginit(self, _swigfaiss.new_SearchParametersHNSW())

# Register SearchParametersHNSW in _swigfaiss:
_swigfaiss.SearchParametersHNSW_swigregister(SearchParametersHNSW)
class HNSW(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    assign_probas = property(_swigfaiss.HNSW_assign_probas_get, _swigfaiss.HNSW_assign_probas_set, doc=r"""assignment probability to each layer (sum=1)""")
    cum_nneighbor_per_level = property(_swigfaiss.HNSW_cum_nneighbor_per_level_get, _swigfaiss.HNSW_cum_nneighbor_per_level_set, doc=r"""
    number of neighbors stored per layer (cumulative), should not
    be changed after first add
    """)
    levels = property(_swigfaiss.HNSW_levels_get, _swigfaiss.HNSW_levels_set, doc=r"""level of each vector (base level = 1), size = ntotal""")
    offsets = property(_swigfaiss.HNSW_offsets_get, _swigfaiss.HNSW_offsets_set, doc=r"""
    offsets[i] is the offset in the neighbors array where vector i is stored
    size ntotal + 1
    """)
    neighbors = property(_swigfaiss.HNSW_neighbors_get, _swigfaiss.HNSW_neighbors_set, doc=r"""
    neighbors[offsets[i]:offsets[i+1]] is the list of neighbors of vector i
    for all levels. this is where all storage goes.
    """)
    entry_point = property(_swigfaiss.HNSW_entry_point_get, _swigfaiss.HNSW_entry_point_set, doc=r"""
    entry point in the search structure (one of the points with maximum
    level
    """)
    rng = property(_swigfaiss.HNSW_rng_get, _swigfaiss.HNSW_rng_set)
    max_level = property(_swigfaiss.HNSW_max_level_get, _swigfaiss.HNSW_max_level_set, doc=r"""maximum level""")
    efConstruction = property(_swigfaiss.HNSW_efConstruction_get, _swigfaiss.HNSW_efConstruction_set, doc=r"""expansion factor at construction time""")
    efSearch = property(_swigfaiss.HNSW_efSearch_get, _swigfaiss.HNSW_efSearch_set, doc=r"""expansion factor at search time""")
    prune_headroom = property(_swigfaiss.HNSW_prune_headroom_get, _swigfaiss.HNSW_prune_headroom_set, doc=r"""
    when pruning, leave room for more neighbors to avoid O(n^2)
    costs and lock contention on frequently-pruned nodes.
    """)
    check_relative_distance = property(_swigfaiss.HNSW_check_relative_distance_get, _swigfaiss.HNSW_check_relative_distance_set, doc=r"""
    during search: do we check whether the next best distance is good
    enough?
    """)
    search_bounded_queue = property(_swigfaiss.HNSW_search_bounded_queue_get, _swigfaiss.HNSW_search_bounded_queue_set, doc=r"""use bounded queue during exploration""")
    is_panorama = property(_swigfaiss.HNSW_is_panorama_get, _swigfaiss.HNSW_is_panorama_set, doc=r"""use Panorama progressive pruning in search""")
    is_similarity = property(_swigfaiss.HNSW_is_similarity_get, _swigfaiss.HNSW_is_similarity_set, doc=r"""
    distance comparison semantics: when true, distances are treated as
    similarity scores (larger is better). Default false matches the
    historical L2/Hamming behavior (smaller is better).
    Not serialized: must be re-set by the owning Index after loading.
    """)
    use_visited_hashset = property(_swigfaiss.HNSW_use_visited_hashset_get, _swigfaiss.HNSW_use_visited_hashset_set)

    def set_default_probas(self, M, levelMult):
        r"""
        initialize the assign_probas and cum_nneighbor_per_level to
        have 2*M links on level 0 and M links on levels > 0
        """
        return _swigfaiss.HNSW_set_default_probas(self, M, levelMult)

    def set_nb_neighbors(self, level_no, n):
        r"""set nb of neighbors for this level (before adding anything)"""
        return _swigfaiss.HNSW_set_nb_neighbors(self, level_no, n)

    def nb_neighbors(self, layer_no):
        r"""nb of neighbors for this level"""
        return _swigfaiss.HNSW_nb_neighbors(self, layer_no)

    def cum_nb_neighbors(self, layer_no):
        r"""cumulative nb up to (and excluding) this level"""
        return _swigfaiss.HNSW_cum_nb_neighbors(self, layer_no)

    def neighbor_range(self, no, layer_no, begin, end):
        r"""range of entries in the neighbors table of vertex no at layer_no"""
        return _swigfaiss.HNSW_neighbor_range(self, no, layer_no, begin, end)

    def __init__(self, M=32):
        r"""only mandatory parameter: nb of neighbors"""
        _swigfaiss.HNSW_swiginit(self, _swigfaiss.new_HNSW(M))

    def random_level(self):
        r"""pick a random level for a new point"""
        return _swigfaiss.HNSW_random_level(self)

    def fill_with_random_links(self, n):
        r"""add n random levels to table (for debugging...)"""
        return _swigfaiss.HNSW_fill_with_random_links(self, n)

    def add_links_starting_from(self, ptdis, pt_id, nearest, d_nearest, level, locks, vt, keep_max_size_level0=False):
        return _swigfaiss.HNSW_add_links_starting_from(self, ptdis, pt_id, nearest, d_nearest, level, locks, vt, keep_max_size_level0)

    def add_with_locks(self, ptdis, pt_level, pt_id, locks, vt, keep_max_size_level0=False):
        r"""
         add point pt_id on all levels <= pt_level and build the link
        structure for them.
        """
        return _swigfaiss.HNSW_add_with_locks(self, ptdis, pt_level, pt_id, locks, vt, keep_max_size_level0)

    def search(self, qdis, index, res, vt, params=None):
        r"""
        Search interface for 1 point, single thread

        NOTE: We pass a reference to the index itself to allow for additional
        state information to be passed (used for Panorama progressive pruning).
        The alternative would be to override both HNSW::search and
        HNSWIndex::search, which would be a nuisance of code duplication.
        """
        return _swigfaiss.HNSW_search(self, qdis, index, res, vt, params)

    def search_level_0(self, qdis, res, nprobe, nearest_i, nearest_d, search_type, search_stats, vt, params=None):
        r"""search only in level 0 from a given vertex"""
        return _swigfaiss.HNSW_search_level_0(self, qdis, res, nprobe, nearest_i, nearest_d, search_type, search_stats, vt, params)

    def reset(self):
        return _swigfaiss.HNSW_reset(self)

    def clear_neighbor_tables(self, level):
        return _swigfaiss.HNSW_clear_neighbor_tables(self, level)

    def print_neighbor_stats(self, level):
        return _swigfaiss.HNSW_print_neighbor_stats(self, level)

    def prepare_level_tab(self, n, preset_levels=False):
        return _swigfaiss.HNSW_prepare_level_tab(self, n, preset_levels)

    def permute_entries(self, map):
        return _swigfaiss.HNSW_permute_entries(self, map)
    __swig_destroy__ = _swigfaiss.delete_HNSW

# Register HNSW in _swigfaiss:
_swigfaiss.HNSW_swigregister(HNSW)
class HNSWStats(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    n1 = property(_swigfaiss.HNSWStats_n1_get, _swigfaiss.HNSWStats_n1_set)
    n2 = property(_swigfaiss.HNSWStats_n2_get, _swigfaiss.HNSWStats_n2_set, doc=r"""number of vectors searched""")
    ndis = property(_swigfaiss.HNSWStats_ndis_get, _swigfaiss.HNSWStats_ndis_set, doc=r"""number of queries for which the candidate list is exhausted""")
    nhops = property(_swigfaiss.HNSWStats_nhops_get, _swigfaiss.HNSWStats_nhops_set, doc=r"""number of distances computed""")

    def reset(self):
        r"""number of hops aka number of edges traversed"""
        return _swigfaiss.HNSWStats_reset(self)

    def combine(self, other):
        return _swigfaiss.HNSWStats_combine(self, other)

    def __init__(self):
        _swigfaiss.HNSWStats_swiginit(self, _swigfaiss.new_HNSWStats())
    __swig_destroy__ = _swigfaiss.delete_HNSWStats

# Register HNSWStats in _swigfaiss:
_swigfaiss.HNSWStats_swigregister(HNSWStats)

def search_from_candidates(hnsw, qdis, res, candidates, vt, stats, level, nres_in=0, params=None):
    r"""
    Internal HNSW algorithm helpers. These are not part of the public API; they
    are exposed here only so that unit tests (and a few cross-TU callers such as
    the Panorama search variant) can reach them.
    """
    return _swigfaiss.search_from_candidates(hnsw, qdis, res, candidates, vt, stats, level, nres_in, params)

def search_from_candidates_panorama(hnsw, index, qdis, res, candidates, vt, stats, level, nres_in=0, params=None):
    r"""
    Equivalent to `search_from_candidates`, but applies pruning with progressive
    refinement bounds.
    This is used in `IndexHNSWFlatPanorama` to improve the search performance
    for higher dimensional vectors.
    """
    return _swigfaiss.search_from_candidates_panorama(hnsw, index, qdis, res, candidates, vt, stats, level, nres_in, params)

def greedy_update_nearest(hnsw, qdis, level, nearest, d_nearest):
    return _swigfaiss.greedy_update_nearest(hnsw, qdis, level, nearest, d_nearest)

def search_from_candidate_unbounded(hnsw, node, qdis, ef, vt, stats):
    return _swigfaiss.search_from_candidate_unbounded(hnsw, node, qdis, ef, vt, stats)

def search_neighbors_to_add(hnsw, qdis, results, entry_point, d_entry_point, level, vt, reference_version=False):
    return _swigfaiss.search_neighbors_to_add(hnsw, qdis, results, entry_point, d_entry_point, level, vt, reference_version)
class IndexHNSW(Index):
    r"""
     The HNSW index is a normal random-access index with a HNSW
    link structure built on top
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    hnsw = property(_swigfaiss.IndexHNSW_hnsw_get, _swigfaiss.IndexHNSW_hnsw_set)
    own_fields = property(_swigfaiss.IndexHNSW_own_fields_get, _swigfaiss.IndexHNSW_own_fields_set)
    storage = property(_swigfaiss.IndexHNSW_storage_get, _swigfaiss.IndexHNSW_storage_set)
    init_level0 = property(_swigfaiss.IndexHNSW_init_level0_get, _swigfaiss.IndexHNSW_init_level0_set)
    keep_max_size_level0 = property(_swigfaiss.IndexHNSW_keep_max_size_level0_get, _swigfaiss.IndexHNSW_keep_max_size_level0_set)
    use_visited_hashset = property(_swigfaiss.IndexHNSW_use_visited_hashset_get, _swigfaiss.IndexHNSW_use_visited_hashset_set)
    retain_locks = property(_swigfaiss.IndexHNSW_retain_locks_get, _swigfaiss.IndexHNSW_retain_locks_set)

    def __init__(self, *args):
        _swigfaiss.IndexHNSW_swiginit(self, _swigfaiss.new_IndexHNSW(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexHNSW

    def add(self, n, x):
        r"""Adds vectors to the index. May not be called concurrently."""
        return _swigfaiss.IndexHNSW_add(self, n, x)

    def train(self, n, x):
        r"""Trains the storage if needed"""
        return _swigfaiss.IndexHNSW_train(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        r"""entry point for search"""
        return _swigfaiss.IndexHNSW_search(self, n, x, k, distances, labels, params)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexHNSW_range_search(self, n, x, radius, result, params)

    def search1(self, x, handler, params=None):
        r"""search one vector with a custom result handler"""
        return _swigfaiss.IndexHNSW_search1(self, x, handler, params)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexHNSW_reconstruct(self, key, recons)

    def reset(self):
        return _swigfaiss.IndexHNSW_reset(self)

    def shrink_level_0_neighbors(self, size):
        return _swigfaiss.IndexHNSW_shrink_level_0_neighbors(self, size)

    def search_level_0(self, n, x, k, nearest, nearest_d, distances, labels, nprobe=1, search_type=1, params=None):
        r"""
         Perform search only on level 0, given the starting points for
        each vertex.

        :type search_type: int, optional
        :param search_type: 1:perform one search per nprobe, 2: enqueue
                               all entry points
        """
        return _swigfaiss.IndexHNSW_search_level_0(self, n, x, k, nearest, nearest_d, distances, labels, nprobe, search_type, params)

    def init_level_0_from_knngraph(self, k, D, I):
        r"""alternative graph building"""
        return _swigfaiss.IndexHNSW_init_level_0_from_knngraph(self, k, D, I)

    def init_level_0_from_entry_points(self, npt, points, nearests):
        r"""alternative graph building"""
        return _swigfaiss.IndexHNSW_init_level_0_from_entry_points(self, npt, points, nearests)

    def reorder_links(self):
        return _swigfaiss.IndexHNSW_reorder_links(self)

    def link_singletons(self):
        return _swigfaiss.IndexHNSW_link_singletons(self)

    def permute_entries(self, perm):
        return _swigfaiss.IndexHNSW_permute_entries(self, perm)

    def get_distance_computer(self):
        return _swigfaiss.IndexHNSW_get_distance_computer(self)

# Register IndexHNSW in _swigfaiss:
_swigfaiss.IndexHNSW_swigregister(IndexHNSW)
class IndexHNSWFlat(IndexHNSW):
    r"""
    Flat index topped with with a HNSW structure to access elements
    more efficiently.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexHNSWFlat_swiginit(self, _swigfaiss.new_IndexHNSWFlat(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexHNSWFlat

# Register IndexHNSWFlat in _swigfaiss:
_swigfaiss.IndexHNSWFlat_swigregister(IndexHNSWFlat)
class IndexHNSWFlatPanorama(IndexHNSWFlat):
    r"""
     Panorama implementation of IndexHNSWFlat following
    https://www.arxiv.org/pdf/2510.00566.

    Unlike cluster-based Panorama, the vectors have to be higher dimensional
    (i.e. typically d > 512) and/or be able to compress a lot of their energy in
    the early dimensions to be effective. This is because HNSW accesses vectors
    in a random order, which makes cache misses dominate the distance computation
    time.

    The `num_panorama_levels` parameter controls the granularity of progressive
    distance refinement, allowing candidates to be eliminated early using partial
    distance computations rather than computing full distances.

    NOTE: This version of HNSW handles search slightly differently than the
    vanilla HNSW, as it uses partial distance computations with progressive
    refinement bounds. Instead of computing full distances immediately for all
    candidates, Panorama maintains lower and upper bounds that are incrementally
    tightened across refinement levels. Candidates are inserted into the search
    beam using approximate distance estimates (LB+UB)/2 and are only fully
    evaluated when they survive pruning and enter the result heap. This allows
    the algorithm to prune unpromising candidates early using Cauchy-Schwarz
    bounds on partial inner products. Hence, recall is not guaranteed to be the
    same as vanilla HNSW due to the heterogeneous precision within the search
    beam (exact vs. partial distance estimates affecting traversal order).
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexHNSWFlatPanorama_swiginit(self, _swigfaiss.new_IndexHNSWFlatPanorama(*args))

    def add(self, n, x):
        return _swigfaiss.IndexHNSWFlatPanorama_add(self, n, x)

    def reset(self):
        return _swigfaiss.IndexHNSWFlatPanorama_reset(self)

    def permute_entries(self, perm):
        return _swigfaiss.IndexHNSWFlatPanorama_permute_entries(self, perm)

    def get_cum_sum(self, i):
        r"""Inline for performance - called frequently in search hot path."""
        return _swigfaiss.IndexHNSWFlatPanorama_get_cum_sum(self, i)
    cum_sums = property(_swigfaiss.IndexHNSWFlatPanorama_cum_sums_get, _swigfaiss.IndexHNSWFlatPanorama_cum_sums_set)
    pano = property(_swigfaiss.IndexHNSWFlatPanorama_pano_get, _swigfaiss.IndexHNSWFlatPanorama_pano_set)
    num_panorama_levels = property(_swigfaiss.IndexHNSWFlatPanorama_num_panorama_levels_get)
    __swig_destroy__ = _swigfaiss.delete_IndexHNSWFlatPanorama

# Register IndexHNSWFlatPanorama in _swigfaiss:
_swigfaiss.IndexHNSWFlatPanorama_swigregister(IndexHNSWFlatPanorama)
class IndexHNSWPQ(IndexHNSW):
    r"""
    PQ index topped with with a HNSW structure to access elements
    more efficiently.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexHNSWPQ_swiginit(self, _swigfaiss.new_IndexHNSWPQ(*args))

    def train(self, n, x):
        return _swigfaiss.IndexHNSWPQ_train(self, n, x)
    __swig_destroy__ = _swigfaiss.delete_IndexHNSWPQ

# Register IndexHNSWPQ in _swigfaiss:
_swigfaiss.IndexHNSWPQ_swigregister(IndexHNSWPQ)
class IndexHNSWSQ(IndexHNSW):
    r"""
    SQ index topped with a HNSW structure to access elements
    more efficiently.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexHNSWSQ_swiginit(self, _swigfaiss.new_IndexHNSWSQ(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexHNSWSQ

# Register IndexHNSWSQ in _swigfaiss:
_swigfaiss.IndexHNSWSQ_swigregister(IndexHNSWSQ)
class IndexHNSW2Level(IndexHNSW):
    r"""2-level code structure with fast random access"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexHNSW2Level_swiginit(self, _swigfaiss.new_IndexHNSW2Level(*args))

    def flip_to_ivf(self):
        return _swigfaiss.IndexHNSW2Level_flip_to_ivf(self)

    def search(self, n, x, k, distances, labels, params=None):
        r"""entry point for search"""
        return _swigfaiss.IndexHNSW2Level_search(self, n, x, k, distances, labels, params)
    __swig_destroy__ = _swigfaiss.delete_IndexHNSW2Level

# Register IndexHNSW2Level in _swigfaiss:
_swigfaiss.IndexHNSW2Level_swigregister(IndexHNSW2Level)
class IndexHNSWCagra(IndexHNSW):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexHNSWCagra_swiginit(self, _swigfaiss.new_IndexHNSWCagra(*args))
    base_level_only = property(_swigfaiss.IndexHNSWCagra_base_level_only_get, _swigfaiss.IndexHNSWCagra_base_level_only_set, doc=r"""
    When set to true, the index is immutable.
    This option is used to copy the knn graph from GpuIndexCagra
    to the base level of IndexHNSWCagra without adding upper levels.
    Doing so enables to search the HNSW index, but removes the
    ability to add vectors.
    """)
    num_base_level_search_entrypoints = property(_swigfaiss.IndexHNSWCagra_num_base_level_search_entrypoints_get, _swigfaiss.IndexHNSWCagra_num_base_level_search_entrypoints_set, doc=r"""
    When `base_level_only` is set to `True`, the search function
    searches only the base level knn graph of the HNSW index.
    This parameter selects the entry point by randomly selecting
    some points and using the best one.
    """)

    def add(self, n, x):
        return _swigfaiss.IndexHNSWCagra_add(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        r"""entry point for search"""
        return _swigfaiss.IndexHNSWCagra_search(self, n, x, k, distances, labels, params)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexHNSWCagra_range_search(self, n, x, radius, result, params)

    def get_numeric_type(self):
        return _swigfaiss.IndexHNSWCagra_get_numeric_type(self)

    def set_numeric_type(self, numeric_type):
        return _swigfaiss.IndexHNSWCagra_set_numeric_type(self, numeric_type)
    numeric_type_ = property(_swigfaiss.IndexHNSWCagra_numeric_type__get, _swigfaiss.IndexHNSWCagra_numeric_type__set)
    __swig_destroy__ = _swigfaiss.delete_IndexHNSWCagra

# Register IndexHNSWCagra in _swigfaiss:
_swigfaiss.IndexHNSWCagra_swigregister(IndexHNSWCagra)

def smawk(nrows, ncols, x, argmins):
    r"""
     SMAWK algorithm. Find the row minima of a monotone matrix.

    Expose this for testing.

    :type nrows: int
    :param nrows:    number of rows
    :type ncols: int
    :param ncols:    number of columns
    :type x: float
    :param x:        input matrix, size (nrows, ncols)
    :type argmins: int
    :param argmins:  argmin of each row
    """
    return _swigfaiss.smawk(nrows, ncols, x, argmins)

def kmeans1d(x, n, nclusters, centroids):
    r"""
     Exact 1D K-Means by dynamic programming

    From  "Fast Exact k-Means, k-Medians and Bregman Divergence Clustering in 1D"
    Allan Grønlund, Kasper Green Larsen, Alexander Mathiasen, Jesper Sindahl
    Nielsen, Stefan Schneider, Mingzhou Song, ArXiV'17

    Section 2.2

    https://arxiv.org/abs/1701.07204

    :type x: float
    :param x:          input 1D array
    :type n: int
    :param n:          input array length
    :type nclusters: int
    :param nclusters:  number of clusters
    :type centroids: float
    :param centroids:  output centroids, size nclusters
    :rtype: float
    :return: imbalance factor
    """
    return _swigfaiss.kmeans1d(x, n, nclusters, centroids)
class Neighbor(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    id = property(_swigfaiss.Neighbor_id_get, _swigfaiss.Neighbor_id_set)
    distance = property(_swigfaiss.Neighbor_distance_get, _swigfaiss.Neighbor_distance_set)
    flag = property(_swigfaiss.Neighbor_flag_get, _swigfaiss.Neighbor_flag_set)

    def __init__(self, *args):
        _swigfaiss.Neighbor_swiginit(self, _swigfaiss.new_Neighbor(*args))

    def __lt__(self, other):
        return _swigfaiss.Neighbor___lt__(self, other)
    __swig_destroy__ = _swigfaiss.delete_Neighbor

# Register Neighbor in _swigfaiss:
_swigfaiss.Neighbor_swigregister(Neighbor)
class Nhood(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    pool = property(_swigfaiss.Nhood_pool_get, _swigfaiss.Nhood_pool_set)
    M = property(_swigfaiss.Nhood_M_get, _swigfaiss.Nhood_M_set)
    nn_old = property(_swigfaiss.Nhood_nn_old_get, _swigfaiss.Nhood_nn_old_set)
    nn_new = property(_swigfaiss.Nhood_nn_new_get, _swigfaiss.Nhood_nn_new_set)
    rnn_old = property(_swigfaiss.Nhood_rnn_old_get, _swigfaiss.Nhood_rnn_old_set)
    rnn_new = property(_swigfaiss.Nhood_rnn_new_get, _swigfaiss.Nhood_rnn_new_set)

    def __init__(self, *args):
        _swigfaiss.Nhood_swiginit(self, _swigfaiss.new_Nhood(*args))

    def insert(self, id, dist):
        return _swigfaiss.Nhood_insert(self, id, dist)
    __swig_destroy__ = _swigfaiss.delete_Nhood

# Register Nhood in _swigfaiss:
_swigfaiss.Nhood_swigregister(Nhood)
class NNDescent(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, d, K):
        _swigfaiss.NNDescent_swiginit(self, _swigfaiss.new_NNDescent(d, K))
    __swig_destroy__ = _swigfaiss.delete_NNDescent

    def build(self, qdis, n, verbose):
        return _swigfaiss.NNDescent_build(self, qdis, n, verbose)

    def search(self, qdis, topk, indices, dists, vt):
        return _swigfaiss.NNDescent_search(self, qdis, topk, indices, dists, vt)

    def reset(self):
        return _swigfaiss.NNDescent_reset(self)

    def init_graph(self, qdis):
        r"""Initialize the KNN graph randomly"""
        return _swigfaiss.NNDescent_init_graph(self, qdis)

    def nndescent(self, qdis, verbose):
        r"""Perform NNDescent algorithm"""
        return _swigfaiss.NNDescent_nndescent(self, qdis, verbose)

    def join(self, qdis):
        r"""Perform local join on each node"""
        return _swigfaiss.NNDescent_join(self, qdis)

    def update(self):
        r"""Sample new neighbors for each node to perform local join later"""
        return _swigfaiss.NNDescent_update(self)

    def generate_eval_set(self, qdis, c, v, N):
        r"""Sample a small number of points to evaluate the quality of KNNG built"""
        return _swigfaiss.NNDescent_generate_eval_set(self, qdis, c, v, N)

    def eval_recall(self, ctrl_points, acc_eval_set):
        r"""Evaluate the quality of KNNG built"""
        return _swigfaiss.NNDescent_eval_recall(self, ctrl_points, acc_eval_set)
    has_built = property(_swigfaiss.NNDescent_has_built_get, _swigfaiss.NNDescent_has_built_set)
    S = property(_swigfaiss.NNDescent_S_get, _swigfaiss.NNDescent_S_set)
    R = property(_swigfaiss.NNDescent_R_get, _swigfaiss.NNDescent_R_set)
    iter = property(_swigfaiss.NNDescent_iter_get, _swigfaiss.NNDescent_iter_set)
    search_L = property(_swigfaiss.NNDescent_search_L_get, _swigfaiss.NNDescent_search_L_set)
    random_seed = property(_swigfaiss.NNDescent_random_seed_get, _swigfaiss.NNDescent_random_seed_set)
    K = property(_swigfaiss.NNDescent_K_get, _swigfaiss.NNDescent_K_set)
    d = property(_swigfaiss.NNDescent_d_get, _swigfaiss.NNDescent_d_set)
    L = property(_swigfaiss.NNDescent_L_get, _swigfaiss.NNDescent_L_set)
    ntotal = property(_swigfaiss.NNDescent_ntotal_get, _swigfaiss.NNDescent_ntotal_set)
    graph = property(_swigfaiss.NNDescent_graph_get, _swigfaiss.NNDescent_graph_set)
    final_graph = property(_swigfaiss.NNDescent_final_graph_get, _swigfaiss.NNDescent_final_graph_set)

# Register NNDescent in _swigfaiss:
_swigfaiss.NNDescent_swigregister(NNDescent)
class IndexNNDescent(Index):
    r"""
     The NNDescent index is a normal random-access index with an NNDescent
    link structure built on top
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nndescent = property(_swigfaiss.IndexNNDescent_nndescent_get, _swigfaiss.IndexNNDescent_nndescent_set, doc=r"""Faiss results are 64-bit""")
    own_fields = property(_swigfaiss.IndexNNDescent_own_fields_get, _swigfaiss.IndexNNDescent_own_fields_set)
    storage = property(_swigfaiss.IndexNNDescent_storage_get, _swigfaiss.IndexNNDescent_storage_set)

    def __init__(self, *args):
        _swigfaiss.IndexNNDescent_swiginit(self, _swigfaiss.new_IndexNNDescent(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexNNDescent

    def add(self, n, x):
        return _swigfaiss.IndexNNDescent_add(self, n, x)

    def train(self, n, x):
        r"""Trains the storage if needed"""
        return _swigfaiss.IndexNNDescent_train(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        r"""entry point for search"""
        return _swigfaiss.IndexNNDescent_search(self, n, x, k, distances, labels, params)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexNNDescent_reconstruct(self, key, recons)

    def reset(self):
        return _swigfaiss.IndexNNDescent_reset(self)

# Register IndexNNDescent in _swigfaiss:
_swigfaiss.IndexNNDescent_swigregister(IndexNNDescent)
class IndexNNDescentFlat(IndexNNDescent):
    r"""
    Flat index topped with with a NNDescent structure to access elements
    more efficiently.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexNNDescentFlat_swiginit(self, _swigfaiss.new_IndexNNDescentFlat(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexNNDescentFlat

# Register IndexNNDescentFlat in _swigfaiss:
_swigfaiss.IndexNNDescentFlat_swigregister(IndexNNDescentFlat)
class IndexIVFFlat(IndexIVF):
    r"""
     Inverted file with stored vectors. Here the inverted file
    pre-selects the vectors to be searched, but they are not otherwise
    encoded, the code array just contains the raw float entries.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def add_core(self, n, x, xids, precomputed_idx, inverted_list_context=None):
        return _swigfaiss.IndexIVFFlat_add_core(self, n, x, xids, precomputed_idx, inverted_list_context)

    def encode_vectors(self, n, x, list_nos, codes, include_listnos=False):
        return _swigfaiss.IndexIVFFlat_encode_vectors(self, n, x, list_nos, codes, include_listnos)

    def decode_vectors(self, n, codes, list_nos, x):
        return _swigfaiss.IndexIVFFlat_decode_vectors(self, n, codes, list_nos, x)

    def get_InvertedListScanner(self, store_pairs, sel, params):
        return _swigfaiss.IndexIVFFlat_get_InvertedListScanner(self, store_pairs, sel, params)

    def reconstruct_from_offset(self, list_no, offset, recons):
        return _swigfaiss.IndexIVFFlat_reconstruct_from_offset(self, list_no, offset, recons)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexIVFFlat_sa_decode(self, n, bytes, x)

    def __init__(self, *args):
        _swigfaiss.IndexIVFFlat_swiginit(self, _swigfaiss.new_IndexIVFFlat(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFFlat

# Register IndexIVFFlat in _swigfaiss:
_swigfaiss.IndexIVFFlat_swigregister(IndexIVFFlat)
class IndexIVFFlatDedup(IndexIVFFlat):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def train(self, n, x):
        r"""also dedups the training set"""
        return _swigfaiss.IndexIVFFlatDedup_train(self, n, x)

    def add_with_ids(self, n, x, xids):
        r"""implemented for all IndexIVF* classes"""
        return _swigfaiss.IndexIVFFlatDedup_add_with_ids(self, n, x, xids)

    def search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params=None, stats=None):
        return _swigfaiss.IndexIVFFlatDedup_search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params, stats)

    def remove_ids(self, sel):
        return _swigfaiss.IndexIVFFlatDedup_remove_ids(self, sel)

    def range_search(self, n, x, radius, result, params=None):
        r"""not implemented"""
        return _swigfaiss.IndexIVFFlatDedup_range_search(self, n, x, radius, result, params)

    def update_vectors(self, nv, idx, v):
        r"""not implemented"""
        return _swigfaiss.IndexIVFFlatDedup_update_vectors(self, nv, idx, v)

    def reconstruct_from_offset(self, list_no, offset, recons):
        r"""not implemented"""
        return _swigfaiss.IndexIVFFlatDedup_reconstruct_from_offset(self, list_no, offset, recons)

    def __init__(self, *args):
        _swigfaiss.IndexIVFFlatDedup_swiginit(self, _swigfaiss.new_IndexIVFFlatDedup(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFFlatDedup

# Register IndexIVFFlatDedup in _swigfaiss:
_swigfaiss.IndexIVFFlatDedup_swigregister(IndexIVFFlatDedup)
class IndexIVFFlatPanorama(IndexIVFFlat):
    r"""
    Panorama adaptation of IndexIVFFlat following
    https://www.arxiv.org/pdf/2510.00566.

    IDEA:
    Panorama adapts the storage layout within each cluster and uses
    pruning with bounds to improve the search performance.
    Combined with orthogonal transforms upstream that concentrate the energy
    in the early dimensions (like PCA, Cayley, etc.), Panorama can prune up
    to 95% of the vectors in the cluster.

    OVERHEAD:
    To be more efficient, we compute the residual energies at insertion time
    and store them along the vectors, which comes with an additional storage
    overhead of exactly (nlevels + 1) floats per vector. Add time is also
    slightly higher due to the overhead of transposing the vectors.

    NOTE:
    We inherit from IndexIVFFlat instead of IndexIVF so we can keep the same
    insertion logic. The code responsible for level-oriented storage is in
    `ArrayInvertedListsPanorama`, which is a struct member of `IndexIVF`.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    n_levels = property(_swigfaiss.IndexIVFFlatPanorama_n_levels_get, _swigfaiss.IndexIVFFlatPanorama_n_levels_set)
    batch_size = property(_swigfaiss.IndexIVFFlatPanorama_batch_size_get, _swigfaiss.IndexIVFFlatPanorama_batch_size_set)
    cum_sums = property(_swigfaiss.IndexIVFFlatPanorama_cum_sums_get, _swigfaiss.IndexIVFFlatPanorama_cum_sums_set)

    def get_InvertedListScanner(self, store_pairs, sel, params):
        return _swigfaiss.IndexIVFFlatPanorama_get_InvertedListScanner(self, store_pairs, sel, params)

    def reconstruct_from_offset(self, list_no, offset, recons):
        return _swigfaiss.IndexIVFFlatPanorama_reconstruct_from_offset(self, list_no, offset, recons)

    def __init__(self, *args):
        _swigfaiss.IndexIVFFlatPanorama_swiginit(self, _swigfaiss.new_IndexIVFFlatPanorama(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFFlatPanorama

# Register IndexIVFFlatPanorama in _swigfaiss:
_swigfaiss.IndexIVFFlatPanorama_swigregister(IndexIVFFlatPanorama)

def storage_distance_computer(storage):
    return _swigfaiss.storage_distance_computer(storage)
class NSG(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    ntotal = property(_swigfaiss.NSG_ntotal_get, _swigfaiss.NSG_ntotal_set, doc=r"""nb of nodes""")
    R = property(_swigfaiss.NSG_R_get, _swigfaiss.NSG_R_set, doc=r"""nb of neighbors per node""")
    L = property(_swigfaiss.NSG_L_get, _swigfaiss.NSG_L_set, doc=r"""length of the search path at construction time""")
    C = property(_swigfaiss.NSG_C_get, _swigfaiss.NSG_C_set, doc=r"""candidate pool size at construction time""")
    search_L = property(_swigfaiss.NSG_search_L_get, _swigfaiss.NSG_search_L_set, doc=r"""length of the search path""")
    use_visited_hashset = property(_swigfaiss.NSG_use_visited_hashset_get, _swigfaiss.NSG_use_visited_hashset_set)
    enterpoint = property(_swigfaiss.NSG_enterpoint_get, _swigfaiss.NSG_enterpoint_set, doc=r"""enterpoint""")
    final_graph = property(_swigfaiss.NSG_final_graph_get, _swigfaiss.NSG_final_graph_set, doc=r"""NSG graph structure""")
    is_built = property(_swigfaiss.NSG_is_built_get, _swigfaiss.NSG_is_built_set, doc=r"""NSG is built or not""")
    rng = property(_swigfaiss.NSG_rng_get, _swigfaiss.NSG_rng_set, doc=r"""random generator""")

    def __init__(self, R=32):
        _swigfaiss.NSG_swiginit(self, _swigfaiss.new_NSG(R))

    def build(self, storage, n, knn_graph, verbose):
        return _swigfaiss.NSG_build(self, storage, n, knn_graph, verbose)

    def reset(self):
        return _swigfaiss.NSG_reset(self)

    def search(self, dis, k, I, D, vt):
        return _swigfaiss.NSG_search(self, dis, k, I, D, vt)

    def init_graph(self, storage, knn_graph):
        return _swigfaiss.NSG_init_graph(self, storage, knn_graph)

    def add_reverse_links(self, q, locks, dis, graph):
        return _swigfaiss.NSG_add_reverse_links(self, q, locks, dis, graph)

    def sync_prune(self, q, pool, dis, vt, knn_graph, graph):
        return _swigfaiss.NSG_sync_prune(self, q, pool, dis, vt, knn_graph, graph)

    def link(self, storage, knn_graph, graph, verbose):
        return _swigfaiss.NSG_link(self, storage, knn_graph, graph, verbose)

    def tree_grow(self, storage, degrees):
        return _swigfaiss.NSG_tree_grow(self, storage, degrees)

    def dfs(self, vt, root, cnt):
        return _swigfaiss.NSG_dfs(self, vt, root, cnt)

    def attach_unlinked(self, storage, vt, vt2, degrees):
        return _swigfaiss.NSG_attach_unlinked(self, storage, vt, vt2, degrees)

    def check_graph(self):
        return _swigfaiss.NSG_check_graph(self)

    def get_final_graph(self):
        return _swigfaiss.NSG_get_final_graph(self)
    __swig_destroy__ = _swigfaiss.delete_NSG

# Register NSG in _swigfaiss:
_swigfaiss.NSG_swigregister(NSG)
class NSG_Graph_int(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    data = property(_swigfaiss.NSG_Graph_int_data_get, _swigfaiss.NSG_Graph_int_data_set, doc=r"""the flattened adjacency matrix, size N-by-K""")
    K = property(_swigfaiss.NSG_Graph_int_K_get, _swigfaiss.NSG_Graph_int_K_set, doc=r"""nb of neighbors per node""")
    N = property(_swigfaiss.NSG_Graph_int_N_get, _swigfaiss.NSG_Graph_int_N_set, doc=r"""total nb of nodes""")
    own_fields = property(_swigfaiss.NSG_Graph_int_own_fields_get, _swigfaiss.NSG_Graph_int_own_fields_set, doc=r"""the underlying data owned by itself or not""")

    def __init__(self, *args):
        _swigfaiss.NSG_Graph_int_swiginit(self, _swigfaiss.new_NSG_Graph_int(*args))
    __swig_destroy__ = _swigfaiss.delete_NSG_Graph_int

    def at(self, *args):
        return _swigfaiss.NSG_Graph_int_at(self, *args)

    def get_neighbors(self, i, neighbors):
        return _swigfaiss.NSG_Graph_int_get_neighbors(self, i, neighbors)

# Register NSG_Graph_int in _swigfaiss:
_swigfaiss.NSG_Graph_int_swigregister(NSG_Graph_int)
class IndexNSG(Index):
    r"""
     The NSG index is a normal random-access index with a NSG
    link structure built on top
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nsg = property(_swigfaiss.IndexNSG_nsg_get, _swigfaiss.IndexNSG_nsg_set, doc=r"""the link structure""")
    own_fields = property(_swigfaiss.IndexNSG_own_fields_get, _swigfaiss.IndexNSG_own_fields_set, doc=r"""the sequential storage""")
    storage = property(_swigfaiss.IndexNSG_storage_get, _swigfaiss.IndexNSG_storage_set)
    is_built = property(_swigfaiss.IndexNSG_is_built_get, _swigfaiss.IndexNSG_is_built_set, doc=r"""the index is built or not""")
    GK = property(_swigfaiss.IndexNSG_GK_get, _swigfaiss.IndexNSG_GK_set, doc=r"""K of KNN graph for building""")
    build_type = property(_swigfaiss.IndexNSG_build_type_get, _swigfaiss.IndexNSG_build_type_set, doc=r"""
    indicate how to build a knn graph
    - 0: build NSG with brute force search
    - 1: build NSG with NNDescent
    """)
    nndescent_S = property(_swigfaiss.IndexNSG_nndescent_S_get, _swigfaiss.IndexNSG_nndescent_S_set, doc=r"""parameters for nndescent""")
    nndescent_R = property(_swigfaiss.IndexNSG_nndescent_R_get, _swigfaiss.IndexNSG_nndescent_R_set)
    nndescent_L = property(_swigfaiss.IndexNSG_nndescent_L_get, _swigfaiss.IndexNSG_nndescent_L_set)
    nndescent_iter = property(_swigfaiss.IndexNSG_nndescent_iter_get, _swigfaiss.IndexNSG_nndescent_iter_set)

    def __init__(self, *args):
        _swigfaiss.IndexNSG_swiginit(self, _swigfaiss.new_IndexNSG(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexNSG

    def build(self, n, x, knn_graph, GK):
        return _swigfaiss.IndexNSG_build(self, n, x, knn_graph, GK)

    def add(self, n, x):
        return _swigfaiss.IndexNSG_add(self, n, x)

    def train(self, n, x):
        r"""Trains the storage if needed"""
        return _swigfaiss.IndexNSG_train(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        r"""entry point for search"""
        return _swigfaiss.IndexNSG_search(self, n, x, k, distances, labels, params)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexNSG_reconstruct(self, key, recons)

    def reset(self):
        return _swigfaiss.IndexNSG_reset(self)

    def check_knn_graph(self, knn_graph, n, K):
        return _swigfaiss.IndexNSG_check_knn_graph(self, knn_graph, n, K)

# Register IndexNSG in _swigfaiss:
_swigfaiss.IndexNSG_swigregister(IndexNSG)
class IndexNSGFlat(IndexNSG):
    r"""
    Flat index topped with with a NSG structure to access elements
    more efficiently.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexNSGFlat_swiginit(self, _swigfaiss.new_IndexNSGFlat(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexNSGFlat

# Register IndexNSGFlat in _swigfaiss:
_swigfaiss.IndexNSGFlat_swigregister(IndexNSGFlat)
class IndexNSGPQ(IndexNSG):
    r"""
    PQ index topped with with a NSG structure to access elements
    more efficiently.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexNSGPQ_swiginit(self, _swigfaiss.new_IndexNSGPQ(*args))

    def train(self, n, x):
        return _swigfaiss.IndexNSGPQ_train(self, n, x)
    __swig_destroy__ = _swigfaiss.delete_IndexNSGPQ

# Register IndexNSGPQ in _swigfaiss:
_swigfaiss.IndexNSGPQ_swigregister(IndexNSGPQ)
class IndexNSGSQ(IndexNSG):
    r"""
    SQ index topped with with a NSG structure to access elements
    more efficiently.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexNSGSQ_swiginit(self, _swigfaiss.new_IndexNSGSQ(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexNSGSQ

# Register IndexNSGSQ in _swigfaiss:
_swigfaiss.IndexNSGSQ_swigregister(IndexNSGSQ)
class ZnSphereSearch(object):
    r"""
     returns the nearest vertex in the sphere to a query. Returns only
    the coordinates, not an id.

    Algorithm: all points are derived from a one atom vector up to a
    permutation and sign changes. The search function finds the most
    appropriate atom and transformation.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    dimS = property(_swigfaiss.ZnSphereSearch_dimS_get, _swigfaiss.ZnSphereSearch_dimS_set)
    r2 = property(_swigfaiss.ZnSphereSearch_r2_get, _swigfaiss.ZnSphereSearch_r2_set)
    natom = property(_swigfaiss.ZnSphereSearch_natom_get, _swigfaiss.ZnSphereSearch_natom_set)
    voc = property(_swigfaiss.ZnSphereSearch_voc_get, _swigfaiss.ZnSphereSearch_voc_set, doc=r"""size dim * natom""")

    def __init__(self, dim, r2_in):
        _swigfaiss.ZnSphereSearch_swiginit(self, _swigfaiss.new_ZnSphereSearch(dim, r2_in))

    def search(self, *args):
        r"""
        *Overload 1:*
        find nearest centroid. x does not need to be normalized

        |

        *Overload 2:*
        full call. Requires externally-allocated temp space

        |

        *Overload 3:*
        full call. Requires externally-allocated temp space
        """
        return _swigfaiss.ZnSphereSearch_search(self, *args)

    def search_multi(self, n, x, c_out, dp_out):
        return _swigfaiss.ZnSphereSearch_search_multi(self, n, x, c_out, dp_out)
    __swig_destroy__ = _swigfaiss.delete_ZnSphereSearch

# Register ZnSphereSearch in _swigfaiss:
_swigfaiss.ZnSphereSearch_swigregister(ZnSphereSearch)
class EnumeratedVectors(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    nv = property(_swigfaiss.EnumeratedVectors_nv_get, _swigfaiss.EnumeratedVectors_nv_set, doc=r"""size of the collection""")
    dim = property(_swigfaiss.EnumeratedVectors_dim_get, _swigfaiss.EnumeratedVectors_dim_set)

    def encode(self, x):
        r"""encode a vector from a collection"""
        return _swigfaiss.EnumeratedVectors_encode(self, x)

    def decode(self, code, c):
        r"""decode it"""
        return _swigfaiss.EnumeratedVectors_decode(self, code, c)

    def encode_multi(self, nc, c, codes):
        return _swigfaiss.EnumeratedVectors_encode_multi(self, nc, c, codes)

    def decode_multi(self, nc, codes, c):
        return _swigfaiss.EnumeratedVectors_decode_multi(self, nc, codes, c)

    def find_nn(self, n, codes, nq, xq, idx, dis):
        return _swigfaiss.EnumeratedVectors_find_nn(self, n, codes, nq, xq, idx, dis)
    __swig_destroy__ = _swigfaiss.delete_EnumeratedVectors

# Register EnumeratedVectors in _swigfaiss:
_swigfaiss.EnumeratedVectors_swigregister(EnumeratedVectors)
class Repeat(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    val = property(_swigfaiss.Repeat_val_get, _swigfaiss.Repeat_val_set)
    n = property(_swigfaiss.Repeat_n_get, _swigfaiss.Repeat_n_set)

    def __init__(self):
        _swigfaiss.Repeat_swiginit(self, _swigfaiss.new_Repeat())
    __swig_destroy__ = _swigfaiss.delete_Repeat

# Register Repeat in _swigfaiss:
_swigfaiss.Repeat_swigregister(Repeat)
class Repeats(object):
    r"""
    Repeats: used to encode a vector that has n occurrences of
    val. Encodes the signs and permutation of the vector. Useful for
    atoms.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    dim = property(_swigfaiss.Repeats_dim_get, _swigfaiss.Repeats_dim_set)
    repeats = property(_swigfaiss.Repeats_repeats_get, _swigfaiss.Repeats_repeats_set)

    def __init__(self, dim_in=0, c=None):
        _swigfaiss.Repeats_swiginit(self, _swigfaiss.new_Repeats(dim_in, c))

    def count(self):
        return _swigfaiss.Repeats_count(self)

    def encode(self, c):
        return _swigfaiss.Repeats_encode(self, c)

    def decode(self, code, c):
        return _swigfaiss.Repeats_decode(self, code, c)
    __swig_destroy__ = _swigfaiss.delete_Repeats

# Register Repeats in _swigfaiss:
_swigfaiss.Repeats_swigregister(Repeats)
class ZnSphereCodec(ZnSphereSearch, EnumeratedVectors):
    r"""
     codec that can return ids for the encoded vectors

    uses the ZnSphereSearch to encode the vector by encoding the
    permutation and signs. Depends on ZnSphereSearch because it uses
    the atom numbers
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    code_segments = property(_swigfaiss.ZnSphereCodec_code_segments_get, _swigfaiss.ZnSphereCodec_code_segments_set)
    nv = property(_swigfaiss.ZnSphereCodec_nv_get, _swigfaiss.ZnSphereCodec_nv_set)
    code_size = property(_swigfaiss.ZnSphereCodec_code_size_get, _swigfaiss.ZnSphereCodec_code_size_set)

    def __init__(self, dim_in, r2_in):
        _swigfaiss.ZnSphereCodec_swiginit(self, _swigfaiss.new_ZnSphereCodec(dim_in, r2_in))

    def search_and_encode(self, x):
        return _swigfaiss.ZnSphereCodec_search_and_encode(self, x)

    def decode(self, code, c):
        return _swigfaiss.ZnSphereCodec_decode(self, code, c)

    def encode(self, x):
        r"""takes vectors that do not need to be centroids"""
        return _swigfaiss.ZnSphereCodec_encode(self, x)
    __swig_destroy__ = _swigfaiss.delete_ZnSphereCodec

# Register ZnSphereCodec in _swigfaiss:
_swigfaiss.ZnSphereCodec_swigregister(ZnSphereCodec)
class ZnSphereCodecRec(EnumeratedVectors):
    r"""
     recursive sphere codec

    Uses a recursive decomposition on the dimensions to encode
    centroids found by the ZnSphereSearch. The codes are *not*
    compatible with the ones of ZnSphereCodec
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    r2 = property(_swigfaiss.ZnSphereCodecRec_r2_get, _swigfaiss.ZnSphereCodecRec_r2_set)
    log2_dim = property(_swigfaiss.ZnSphereCodecRec_log2_dim_get, _swigfaiss.ZnSphereCodecRec_log2_dim_set)
    code_size = property(_swigfaiss.ZnSphereCodecRec_code_size_get, _swigfaiss.ZnSphereCodecRec_code_size_set)

    def __init__(self, dim_in, r2_in):
        _swigfaiss.ZnSphereCodecRec_swiginit(self, _swigfaiss.new_ZnSphereCodecRec(dim_in, r2_in))

    def encode_centroid(self, c):
        return _swigfaiss.ZnSphereCodecRec_encode_centroid(self, c)

    def decode(self, code, c):
        return _swigfaiss.ZnSphereCodecRec_decode(self, code, c)

    def encode(self, x):
        r"""
        vectors need to be centroids (does not work on arbitrary
        vectors)
        """
        return _swigfaiss.ZnSphereCodecRec_encode(self, x)
    all_nv = property(_swigfaiss.ZnSphereCodecRec_all_nv_get, _swigfaiss.ZnSphereCodecRec_all_nv_set)
    all_nv_cum = property(_swigfaiss.ZnSphereCodecRec_all_nv_cum_get, _swigfaiss.ZnSphereCodecRec_all_nv_cum_set)
    decode_cache_ld = property(_swigfaiss.ZnSphereCodecRec_decode_cache_ld_get, _swigfaiss.ZnSphereCodecRec_decode_cache_ld_set)
    decode_cache = property(_swigfaiss.ZnSphereCodecRec_decode_cache_get, _swigfaiss.ZnSphereCodecRec_decode_cache_set)

    def get_nv(self, ld, r2a):
        return _swigfaiss.ZnSphereCodecRec_get_nv(self, ld, r2a)

    def get_nv_cum(self, ld, r2t, r2a):
        return _swigfaiss.ZnSphereCodecRec_get_nv_cum(self, ld, r2t, r2a)

    def set_nv_cum(self, ld, r2t, r2a, v):
        return _swigfaiss.ZnSphereCodecRec_set_nv_cum(self, ld, r2t, r2a, v)
    __swig_destroy__ = _swigfaiss.delete_ZnSphereCodecRec

# Register ZnSphereCodecRec in _swigfaiss:
_swigfaiss.ZnSphereCodecRec_swigregister(ZnSphereCodecRec)
class ZnSphereCodecAlt(ZnSphereCodec):
    r"""
     Codec that uses the recursive codec if dim is a power of 2 and
    the regular one otherwise
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    use_rec = property(_swigfaiss.ZnSphereCodecAlt_use_rec_get, _swigfaiss.ZnSphereCodecAlt_use_rec_set)
    znc_rec = property(_swigfaiss.ZnSphereCodecAlt_znc_rec_get, _swigfaiss.ZnSphereCodecAlt_znc_rec_set)

    def __init__(self, dim_in, r2_in):
        _swigfaiss.ZnSphereCodecAlt_swiginit(self, _swigfaiss.new_ZnSphereCodecAlt(dim_in, r2_in))

    def encode(self, x):
        return _swigfaiss.ZnSphereCodecAlt_encode(self, x)

    def decode(self, code, c):
        return _swigfaiss.ZnSphereCodecAlt_decode(self, code, c)
    __swig_destroy__ = _swigfaiss.delete_ZnSphereCodecAlt

# Register ZnSphereCodecAlt in _swigfaiss:
_swigfaiss.ZnSphereCodecAlt_swigregister(ZnSphereCodecAlt)
class IndexLattice(IndexFlatCodes):
    r"""Index that encodes a vector with a series of Zn lattice quantizers"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nsq = property(_swigfaiss.IndexLattice_nsq_get, _swigfaiss.IndexLattice_nsq_set, doc=r"""number of sub-vectors""")
    dsq = property(_swigfaiss.IndexLattice_dsq_get, _swigfaiss.IndexLattice_dsq_set, doc=r"""dimension of sub-vectors""")
    zn_sphere_codec = property(_swigfaiss.IndexLattice_zn_sphere_codec_get, _swigfaiss.IndexLattice_zn_sphere_codec_set, doc=r"""the lattice quantizer""")
    scale_nbit = property(_swigfaiss.IndexLattice_scale_nbit_get, _swigfaiss.IndexLattice_scale_nbit_set, doc=r"""nb bits used to encode the scale, per subvector""")
    lattice_nbit = property(_swigfaiss.IndexLattice_lattice_nbit_get, _swigfaiss.IndexLattice_lattice_nbit_set)
    trained = property(_swigfaiss.IndexLattice_trained_get, _swigfaiss.IndexLattice_trained_set, doc=r"""mins and maxes of the vector norms, per subquantizer""")

    def __init__(self, d, nsq, scale_nbit, r2):
        _swigfaiss.IndexLattice_swiginit(self, _swigfaiss.new_IndexLattice(d, nsq, scale_nbit, r2))

    def train(self, n, x):
        return _swigfaiss.IndexLattice_train(self, n, x)

    def sa_code_size(self):
        return _swigfaiss.IndexLattice_sa_code_size(self)

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.IndexLattice_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexLattice_sa_decode(self, n, bytes, x)
    __swig_destroy__ = _swigfaiss.delete_IndexLattice

# Register IndexLattice in _swigfaiss:
_swigfaiss.IndexLattice_swigregister(IndexLattice)
class IVFPQSearchParameters(SearchParametersIVF):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    scan_table_threshold = property(_swigfaiss.IVFPQSearchParameters_scan_table_threshold_get, _swigfaiss.IVFPQSearchParameters_scan_table_threshold_set, doc=r"""use table computation or on-the-fly?""")
    polysemous_ht = property(_swigfaiss.IVFPQSearchParameters_polysemous_ht_get, _swigfaiss.IVFPQSearchParameters_polysemous_ht_set, doc=r"""Hamming thresh for polysemous filtering""")

    def __init__(self):
        _swigfaiss.IVFPQSearchParameters_swiginit(self, _swigfaiss.new_IVFPQSearchParameters())
    __swig_destroy__ = _swigfaiss.delete_IVFPQSearchParameters

# Register IVFPQSearchParameters in _swigfaiss:
_swigfaiss.IVFPQSearchParameters_swigregister(IVFPQSearchParameters)
class IndexIVFPQ(IndexIVF):
    r"""
     Inverted file with Product Quantizer encoding. Each residual
    vector is encoded as a product quantizer code.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    pq = property(_swigfaiss.IndexIVFPQ_pq_get, _swigfaiss.IndexIVFPQ_pq_set, doc=r"""produces the codes""")
    do_polysemous_training = property(_swigfaiss.IndexIVFPQ_do_polysemous_training_get, _swigfaiss.IndexIVFPQ_do_polysemous_training_set, doc=r"""reorder PQ centroids after training?""")
    polysemous_training = property(_swigfaiss.IndexIVFPQ_polysemous_training_get, _swigfaiss.IndexIVFPQ_polysemous_training_set, doc=r"""if NULL, use default""")
    scan_table_threshold = property(_swigfaiss.IndexIVFPQ_scan_table_threshold_get, _swigfaiss.IndexIVFPQ_scan_table_threshold_set, doc=r"""use table computation or on-the-fly?""")
    polysemous_ht = property(_swigfaiss.IndexIVFPQ_polysemous_ht_get, _swigfaiss.IndexIVFPQ_polysemous_ht_set, doc=r"""Hamming thresh for polysemous filtering""")
    use_precomputed_table = property(_swigfaiss.IndexIVFPQ_use_precomputed_table_get, _swigfaiss.IndexIVFPQ_use_precomputed_table_set, doc=r"""
     Precompute table that speed up query preprocessing at some
    memory cost (used only for by_residual with L2 metric)
    """)
    precomputed_table = property(_swigfaiss.IndexIVFPQ_precomputed_table_get, _swigfaiss.IndexIVFPQ_precomputed_table_set, doc=r"""
    if use_precompute_table
    size nlist * pq.M * pq.ksub
    """)

    def encode_vectors(self, n, x, list_nos, codes, include_listnos=False):
        return _swigfaiss.IndexIVFPQ_encode_vectors(self, n, x, list_nos, codes, include_listnos)

    def decode_vectors(self, n, codes, listnos, x):
        return _swigfaiss.IndexIVFPQ_decode_vectors(self, n, codes, listnos, x)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexIVFPQ_sa_decode(self, n, bytes, x)

    def add_core(self, n, x, xids, precomputed_idx, inverted_list_context=None):
        return _swigfaiss.IndexIVFPQ_add_core(self, n, x, xids, precomputed_idx, inverted_list_context)

    def add_core_o(self, n, x, xids, residuals_2, precomputed_idx=None, inverted_list_context=None):
        r"""
        same as add_core, also:
        - output 2nd level residuals if residuals_2 != NULL
        - accepts precomputed_idx = nullptr
        """
        return _swigfaiss.IndexIVFPQ_add_core_o(self, n, x, xids, residuals_2, precomputed_idx, inverted_list_context)

    def train_encoder(self, n, x, assign):
        r"""trains the product quantizer"""
        return _swigfaiss.IndexIVFPQ_train_encoder(self, n, x, assign)

    def train_encoder_num_vectors(self):
        return _swigfaiss.IndexIVFPQ_train_encoder_num_vectors(self)

    def reconstruct_from_offset(self, list_no, offset, recons):
        return _swigfaiss.IndexIVFPQ_reconstruct_from_offset(self, list_no, offset, recons)

    def find_duplicates(self, ids, lims):
        r"""
         Find exact duplicates in the dataset.

        the duplicates are returned in pre-allocated arrays (see the
        max sizes).

        :type lims: int
        :param lims:   limits between groups of duplicates
                           (max size ntotal / 2 + 1)
        :type ids: int
        :param ids:    ids[lims[i]] : ids[lims[i+1]-1] is a group of
                           duplicates (max size ntotal)
        :rtype: int
        :return: n      number of groups found
        """
        return _swigfaiss.IndexIVFPQ_find_duplicates(self, ids, lims)

    def encode(self, key, x, code):
        return _swigfaiss.IndexIVFPQ_encode(self, key, x, code)

    def encode_multiple(self, n, keys, x, codes, compute_keys=False):
        r"""
         Encode multiple vectors

        :type n: int
        :param n:       nb vectors to encode
        :type keys: int
        :param keys:    posting list ids for those vectors (size n)
        :type x: float
        :param x:       vectors (size n * d)
        :type codes: uint8_t
        :param codes:   output codes (size n * code_size)
        :type compute_keys: boolean, optional
        :param compute_keys:  if false, assume keys are precomputed,
                                 otherwise compute them
        """
        return _swigfaiss.IndexIVFPQ_encode_multiple(self, n, keys, x, codes, compute_keys)

    def decode_multiple(self, n, keys, xcodes, x):
        r"""inverse of encode_multiple"""
        return _swigfaiss.IndexIVFPQ_decode_multiple(self, n, keys, xcodes, x)

    def get_InvertedListScanner(self, store_pairs, sel, params):
        return _swigfaiss.IndexIVFPQ_get_InvertedListScanner(self, store_pairs, sel, params)

    def precompute_table(self):
        r"""build precomputed table"""
        return _swigfaiss.IndexIVFPQ_precompute_table(self)

    def __init__(self, *args):
        _swigfaiss.IndexIVFPQ_swiginit(self, _swigfaiss.new_IndexIVFPQ(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFPQ

# Register IndexIVFPQ in _swigfaiss:
_swigfaiss.IndexIVFPQ_swigregister(IndexIVFPQ)

def initialize_IVFPQ_precomputed_table(use_precomputed_table, quantizer, pq, precomputed_table, by_residual, verbose):
    r"""
     Pre-compute distance tables for IVFPQ with by-residual and METRIC_L2

    :type use_precomputed_table: int
    :param use_precomputed_table: (I/O)
               =-1: force disable
               =0: decide heuristically (default: use tables only if they are
                   < precomputed_tables_max_bytes), set use_precomputed_table on
        output =1: tables that work for all quantizers (size 256 * nlist * M) =2:
        specific version for MultiIndexQuantizer (much more compact)
    :type precomputed_table: faiss::AlignedTable< float,32 >
    :param precomputed_table: precomputed table to initialize
    """
    return _swigfaiss.initialize_IVFPQ_precomputed_table(use_precomputed_table, quantizer, pq, precomputed_table, by_residual, verbose)
class IndexIVFPQStats(object):
    r"""
    statistics are robust to internal threading, but not if
    IndexIVFPQ::search_preassigned is called by multiple threads
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nrefine = property(_swigfaiss.IndexIVFPQStats_nrefine_get, _swigfaiss.IndexIVFPQStats_nrefine_set, doc=r"""nb of refines (IVFPQR)""")
    n_hamming_pass = property(_swigfaiss.IndexIVFPQStats_n_hamming_pass_get, _swigfaiss.IndexIVFPQStats_n_hamming_pass_set, doc=r"""nb of passed Hamming distance tests (for polysemous)""")
    search_cycles = property(_swigfaiss.IndexIVFPQStats_search_cycles_get, _swigfaiss.IndexIVFPQStats_search_cycles_set)
    refine_cycles = property(_swigfaiss.IndexIVFPQStats_refine_cycles_get, _swigfaiss.IndexIVFPQStats_refine_cycles_set, doc=r"""only for IVFPQR""")

    def __init__(self):
        _swigfaiss.IndexIVFPQStats_swiginit(self, _swigfaiss.new_IndexIVFPQStats())

    def reset(self):
        return _swigfaiss.IndexIVFPQStats_reset(self)
    __swig_destroy__ = _swigfaiss.delete_IndexIVFPQStats

# Register IndexIVFPQStats in _swigfaiss:
_swigfaiss.IndexIVFPQStats_swigregister(IndexIVFPQStats)
class IndexIVFPQR(IndexIVFPQ):
    r"""Index with an additional level of PQ refinement"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    refine_pq = property(_swigfaiss.IndexIVFPQR_refine_pq_get, _swigfaiss.IndexIVFPQR_refine_pq_set, doc=r"""3rd level quantizer""")
    refine_codes = property(_swigfaiss.IndexIVFPQR_refine_codes_get, _swigfaiss.IndexIVFPQR_refine_codes_set, doc=r"""corresponding codes""")
    k_factor = property(_swigfaiss.IndexIVFPQR_k_factor_get, _swigfaiss.IndexIVFPQR_k_factor_set, doc=r"""factor between k requested in search and the k requested from the IVFPQ""")

    def reset(self):
        return _swigfaiss.IndexIVFPQR_reset(self)

    def remove_ids(self, sel):
        return _swigfaiss.IndexIVFPQR_remove_ids(self, sel)

    def train_encoder(self, n, x, assign):
        r"""trains the two product quantizers"""
        return _swigfaiss.IndexIVFPQR_train_encoder(self, n, x, assign)

    def train_encoder_num_vectors(self):
        return _swigfaiss.IndexIVFPQR_train_encoder_num_vectors(self)

    def add_with_ids(self, n, x, xids):
        return _swigfaiss.IndexIVFPQR_add_with_ids(self, n, x, xids)

    def add_core(self, n, x, xids, precomputed_idx, inverted_list_context=None):
        r"""same as add_with_ids, but optionally use the precomputed list ids"""
        return _swigfaiss.IndexIVFPQR_add_core(self, n, x, xids, precomputed_idx, inverted_list_context)

    def reconstruct_from_offset(self, list_no, offset, recons):
        return _swigfaiss.IndexIVFPQR_reconstruct_from_offset(self, list_no, offset, recons)

    def merge_from(self, otherIndex, add_id):
        return _swigfaiss.IndexIVFPQR_merge_from(self, otherIndex, add_id)

    def search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params=None, stats=None):
        return _swigfaiss.IndexIVFPQR_search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params, stats)

    def __init__(self, *args):
        _swigfaiss.IndexIVFPQR_swiginit(self, _swigfaiss.new_IndexIVFPQR(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFPQR

# Register IndexIVFPQR in _swigfaiss:
_swigfaiss.IndexIVFPQR_swigregister(IndexIVFPQR)
class Index2Layer(IndexFlatCodes):
    r"""
     Same as an IndexIVFPQ without the inverted lists: codes are stored
    sequentially

    The class is mainly intended to store encoded vectors that can be
    accessed randomly, the search function is not implemented.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    q1 = property(_swigfaiss.Index2Layer_q1_get, _swigfaiss.Index2Layer_q1_set, doc=r"""first level quantizer""")
    pq = property(_swigfaiss.Index2Layer_pq_get, _swigfaiss.Index2Layer_pq_set, doc=r"""second level quantizer is always a PQ""")
    code_size_1 = property(_swigfaiss.Index2Layer_code_size_1_get, _swigfaiss.Index2Layer_code_size_1_set, doc=r"""size of the code for the first level (ceil(log8(q1.nlist)))""")
    code_size_2 = property(_swigfaiss.Index2Layer_code_size_2_get, _swigfaiss.Index2Layer_code_size_2_set, doc=r"""size of the code for the second level""")

    def __init__(self, *args):
        _swigfaiss.Index2Layer_swiginit(self, _swigfaiss.new_Index2Layer(*args))
    __swig_destroy__ = _swigfaiss.delete_Index2Layer

    def train(self, n, x):
        return _swigfaiss.Index2Layer_train(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        r"""not implemented"""
        return _swigfaiss.Index2Layer_search(self, n, x, k, distances, labels, params)

    def get_distance_computer(self):
        return _swigfaiss.Index2Layer_get_distance_computer(self)

    def transfer_to_IVFPQ(self, other):
        r"""transfer the flat codes to an IVFPQ index"""
        return _swigfaiss.Index2Layer_transfer_to_IVFPQ(self, other)

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.Index2Layer_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.Index2Layer_sa_decode(self, n, bytes, x)

# Register Index2Layer in _swigfaiss:
_swigfaiss.Index2Layer_swigregister(Index2Layer)
class FastScanDistancePostProcessing(object):
    r"""Simple context object that holds processors for FastScan operations."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    pq2x4_scale = property(_swigfaiss.FastScanDistancePostProcessing_pq2x4_scale_get, _swigfaiss.FastScanDistancePostProcessing_pq2x4_scale_set, doc=r"""
    Norm scaling processor for Additive Quantizers.
    The scale is encoded in a 2x4 bit PQ table, then scaled by this int.
    Set to 0 if unused.
    """)
    query_factors = property(_swigfaiss.FastScanDistancePostProcessing_query_factors_get, _swigfaiss.FastScanDistancePostProcessing_query_factors_set, doc=r"""
    Query factors data pointer for RaBitQ (nullptr if not needed)
    This pointer should point to the beginning of the relevant
    QueryFactorsData subset for this context.
    """)
    nprobe = property(_swigfaiss.FastScanDistancePostProcessing_nprobe_get, _swigfaiss.FastScanDistancePostProcessing_nprobe_set, doc=r"""
    The nprobe value used when allocating query_factors storage.
    This is needed because the allocation size (n * nprobe) may use a
    different nprobe than index->nprobe if search params override it.
    Set to 0 to use index->nprobe as fallback.
    """)
    qb = property(_swigfaiss.FastScanDistancePostProcessing_qb_get, _swigfaiss.FastScanDistancePostProcessing_qb_set, doc=r"""
    RaBitQ query quantization bits override.
    Set to 0 to use the index default (index->qb).
    """)
    centered = property(_swigfaiss.FastScanDistancePostProcessing_centered_get, _swigfaiss.FastScanDistancePostProcessing_centered_set, doc=r"""
    RaBitQ centered scalar quantizer override.
    Only used when qb > 0 (i.e., when params are overridden).
    """)

    def __init__(self):
        r"""Default constructor - no processing"""
        _swigfaiss.FastScanDistancePostProcessing_swiginit(self, _swigfaiss.new_FastScanDistancePostProcessing())

    def has_norm_scaling(self):
        r"""Check if norm scaling is enabled"""
        return _swigfaiss.FastScanDistancePostProcessing_has_norm_scaling(self)

    def has_query_processing(self):
        r"""Check if query factors processing is enabled"""
        return _swigfaiss.FastScanDistancePostProcessing_has_query_processing(self)
    __swig_destroy__ = _swigfaiss.delete_FastScanDistancePostProcessing

# Register FastScanDistancePostProcessing in _swigfaiss:
_swigfaiss.FastScanDistancePostProcessing_swigregister(FastScanDistancePostProcessing)
class IndexFastScan(Index):
    r"""
     Fast scan version of IndexPQ and IndexAQ. Works for 4-bit PQ and AQ for now.

    The codes are not stored sequentially but grouped in blocks of size bbs.
    This makes it possible to compute distances quickly with SIMD instructions.
    The trailing codes (padding codes that are added to complete the last code)
    are garbage.

    Implementations:
    12: blocked loop with internal loop on Q with qbs
    13: same with reservoir accumulator to store results
    14: no qbs with heap accumulator
    15: no qbs with reservoir accumulator
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    implem = property(_swigfaiss.IndexFastScan_implem_get, _swigfaiss.IndexFastScan_implem_set)
    skip = property(_swigfaiss.IndexFastScan_skip_get, _swigfaiss.IndexFastScan_skip_set)
    bbs = property(_swigfaiss.IndexFastScan_bbs_get, _swigfaiss.IndexFastScan_bbs_set)
    qbs = property(_swigfaiss.IndexFastScan_qbs_get, _swigfaiss.IndexFastScan_qbs_set)
    M = property(_swigfaiss.IndexFastScan_M_get, _swigfaiss.IndexFastScan_M_set)
    nbits = property(_swigfaiss.IndexFastScan_nbits_get, _swigfaiss.IndexFastScan_nbits_set)
    ksub = property(_swigfaiss.IndexFastScan_ksub_get, _swigfaiss.IndexFastScan_ksub_set)
    code_size = property(_swigfaiss.IndexFastScan_code_size_get, _swigfaiss.IndexFastScan_code_size_set)
    ntotal2 = property(_swigfaiss.IndexFastScan_ntotal2_get, _swigfaiss.IndexFastScan_ntotal2_set)
    M2 = property(_swigfaiss.IndexFastScan_M2_get, _swigfaiss.IndexFastScan_M2_set)
    codes = property(_swigfaiss.IndexFastScan_codes_get, _swigfaiss.IndexFastScan_codes_set)
    orig_codes = property(_swigfaiss.IndexFastScan_orig_codes_get, _swigfaiss.IndexFastScan_orig_codes_set)

    def init_fastscan(self, d, M, nbits, metric, bbs):
        r"""
         Initialize the fast scan index

        :type d: int
        :param d:         dimensionality of vectors
        :type M: int
        :param M:         number of subquantizers
        :type nbits: int
        :param nbits:     number of bits per subquantizer
        :type metric: int
        :param metric:    distance metric to use
        :type bbs: int
        :param bbs:       block size for SIMD processing
        """
        return _swigfaiss.IndexFastScan_init_fastscan(self, d, M, nbits, metric, bbs)

    def reset(self):
        return _swigfaiss.IndexFastScan_reset(self)

    def search(self, n, x, k, distances, labels, params=None):
        r"""
         Search for k nearest neighbors

        :type n: int
        :param n:          number of query vectors
        :type x: float
        :param x:          query vectors (n * d)
        :type k: int
        :param k:          number of nearest neighbors to find
        :type distances: float
        :param distances:  output distances (n * k)
        :type labels: int
        :param labels:     output labels/indices (n * k)
        :type params: :py:class:`SearchParameters`, optional
        :param params:     optional search parameters
        """
        return _swigfaiss.IndexFastScan_search(self, n, x, k, distances, labels, params)

    def add(self, n, x):
        r"""
         Add vectors to the index

        :type n: int
        :param n:  number of vectors to add
        :type x: float
        :param x:  vectors to add (n * d)
        """
        return _swigfaiss.IndexFastScan_add(self, n, x)

    def compute_codes(self, codes, n, x):
        r"""
         Compute codes for vectors

        :type codes: uint8_t
        :param codes:  output codes
        :type n: int
        :param n:      number of vectors to encode
        :type x: float
        :param x:      vectors to encode (n * d)
        """
        return _swigfaiss.IndexFastScan_compute_codes(self, codes, n, x)

    def compute_float_LUT(self, lut, n, x, context):
        r"""
         Compute floating-point lookup table for distance computation

        :type lut: float
        :param lut:          output lookup table
        :type n: int
        :param n:            number of query vectors
        :type x: float
        :param x:            query vectors (n * d)
        :type context: :py:class:`FastScanDistancePostProcessing`
        :param context:      processing context containing all processors
        """
        return _swigfaiss.IndexFastScan_compute_float_LUT(self, lut, n, x, context)

    def compute_quantized_LUT(self, n, x, lut, normalizers, context):
        return _swigfaiss.IndexFastScan_compute_quantized_LUT(self, n, x, lut, normalizers, context)

    def reconstruct(self, key, recons):
        r"""
         Reconstruct a vector from its code

        :type key: int
        :param key:     index of vector to reconstruct
        :type recons: float
        :param recons:  output reconstructed vector
        """
        return _swigfaiss.IndexFastScan_reconstruct(self, key, recons)

    def remove_ids(self, sel):
        r"""
         Remove vectors by ID selector

        :type sel: :py:class:`IDSelector`
        :param sel:  selector defining which vectors to remove
        :rtype: int
        :return: number of vectors removed
        """
        return _swigfaiss.IndexFastScan_remove_ids(self, sel)

    def get_CodePacker(self):
        r"""
         Get the code packer for this index

        :rtype: :py:class:`CodePacker`
        :return: pointer to the code packer
        """
        return _swigfaiss.IndexFastScan_get_CodePacker(self)

    def get_block_stride(self):
        r"""
         Get stride in bytes between consecutive SIMD blocks.

        Derived from get_CodePacker()->block_size so that there is a
        single source of truth for the block layout.

        :rtype: int
        :return: stride in bytes
        """
        return _swigfaiss.IndexFastScan_get_block_stride(self)

    def merge_from(self, otherIndex, add_id=0):
        r"""
         Merge another index into this one

        :type otherIndex: :py:class:`Index`
        :param otherIndex:  index to merge from
        :type add_id: int, optional
        :param add_id:      ID offset to add to merged vectors
        """
        return _swigfaiss.IndexFastScan_merge_from(self, otherIndex, add_id)

    def check_compatible_for_merge(self, otherIndex):
        r"""
         Check if another index is compatible for merging

        :type otherIndex: :py:class:`Index`
        :param otherIndex:  index to check compatibility with
        """
        return _swigfaiss.IndexFastScan_check_compatible_for_merge(self, otherIndex)

    def sa_code_size(self):
        r"""standalone codes interface (but the codes are flattened)"""
        return _swigfaiss.IndexFastScan_sa_code_size(self)

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.IndexFastScan_sa_encode(self, n, x, bytes)

    def fast_scan_code_size(self):
        r"""
         Get the size of the code portion packed by pq4_pack_codes.

        Returns the number of bytes per vector that are interleaved into
        SIMD blocks by pq4_pack_codes, excluding any embedded metadata
        (e.g., RaBitQ factors). The meaning of these bytes depends on the
        quantizer: for PQ/AQ they are 4-bit sub-quantizer nibbles, for
        RaBitQ they are 1-bit-per-dimension sign bits packed into nibbles.

        Must be implemented by all derived classes.
        """
        return _swigfaiss.IndexFastScan_fast_scan_code_size(self)
    __swig_destroy__ = _swigfaiss.delete_IndexFastScan

# Register IndexFastScan in _swigfaiss:
_swigfaiss.IndexFastScan_swigregister(IndexFastScan)
class FastScanStats(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    t0 = property(_swigfaiss.FastScanStats_t0_get, _swigfaiss.FastScanStats_t0_set)
    t1 = property(_swigfaiss.FastScanStats_t1_get, _swigfaiss.FastScanStats_t1_set)
    t2 = property(_swigfaiss.FastScanStats_t2_get, _swigfaiss.FastScanStats_t2_set)
    t3 = property(_swigfaiss.FastScanStats_t3_get, _swigfaiss.FastScanStats_t3_set)

    def __init__(self):
        _swigfaiss.FastScanStats_swiginit(self, _swigfaiss.new_FastScanStats())

    def reset(self):
        return _swigfaiss.FastScanStats_reset(self)
    __swig_destroy__ = _swigfaiss.delete_FastScanStats

# Register FastScanStats in _swigfaiss:
_swigfaiss.FastScanStats_swigregister(FastScanStats)
class IndexAdditiveQuantizerFastScan(IndexFastScan):
    r"""
     Fast scan version of IndexAQ. Works for 4-bit AQ for now.

    The codes are not stored sequentially but grouped in blocks of size bbs.
    This makes it possible to compute distances quickly with SIMD instructions.

    Implementations:
    12: blocked loop with internal loop on Q with qbs
    13: same with reservoir accumulator to store results
    14: no qbs with heap accumulator
    15: no qbs with reservoir accumulator
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    aq = property(_swigfaiss.IndexAdditiveQuantizerFastScan_aq_get, _swigfaiss.IndexAdditiveQuantizerFastScan_aq_set)
    rescale_norm = property(_swigfaiss.IndexAdditiveQuantizerFastScan_rescale_norm_get, _swigfaiss.IndexAdditiveQuantizerFastScan_rescale_norm_set)
    norm_scale = property(_swigfaiss.IndexAdditiveQuantizerFastScan_norm_scale_get, _swigfaiss.IndexAdditiveQuantizerFastScan_norm_scale_set)
    max_train_points = property(_swigfaiss.IndexAdditiveQuantizerFastScan_max_train_points_get, _swigfaiss.IndexAdditiveQuantizerFastScan_max_train_points_set)

    def init(self, *args):
        return _swigfaiss.IndexAdditiveQuantizerFastScan_init(self, *args)
    __swig_destroy__ = _swigfaiss.delete_IndexAdditiveQuantizerFastScan

    def __init__(self, *args):
        r"""
        *Overload 1:*
        build from an existing IndexAQ

        |

        *Overload 2:*
        build from an existing IndexAQ
        """
        _swigfaiss.IndexAdditiveQuantizerFastScan_swiginit(self, _swigfaiss.new_IndexAdditiveQuantizerFastScan(*args))

    def train(self, n, x):
        return _swigfaiss.IndexAdditiveQuantizerFastScan_train(self, n, x)

    def estimate_norm_scale(self, n, x):
        return _swigfaiss.IndexAdditiveQuantizerFastScan_estimate_norm_scale(self, n, x)

    def compute_codes(self, codes, n, x):
        return _swigfaiss.IndexAdditiveQuantizerFastScan_compute_codes(self, codes, n, x)

    def compute_float_LUT(self, lut, n, x, context):
        return _swigfaiss.IndexAdditiveQuantizerFastScan_compute_float_LUT(self, lut, n, x, context)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexAdditiveQuantizerFastScan_search(self, n, x, k, distances, labels, params)

    def sa_decode(self, n, bytes, x):
        r"""
         Decode a set of vectors.

         NOTE: The codes in the IndexAdditiveQuantizerFastScan object are non-
               contiguous. But this method requires a contiguous representation.

        :type n: int
        :param n:       number of vectors
        :type bytes: uint8_t
        :param bytes:   input encoded vectors, size n * code_size
        :type x: float
        :param x:       output vectors, size n * d
        """
        return _swigfaiss.IndexAdditiveQuantizerFastScan_sa_decode(self, n, bytes, x)

    def fast_scan_code_size(self):
        r"""Packed code size: M2 / 2 bytes (4-bit AQ sub-quantizer nibbles)"""
        return _swigfaiss.IndexAdditiveQuantizerFastScan_fast_scan_code_size(self)

# Register IndexAdditiveQuantizerFastScan in _swigfaiss:
_swigfaiss.IndexAdditiveQuantizerFastScan_swigregister(IndexAdditiveQuantizerFastScan)
class IndexResidualQuantizerFastScan(IndexAdditiveQuantizerFastScan):
    r"""
     Index based on a residual quantizer. Stored vectors are
    approximated by residual quantization codes.
    Can also be used as a codec
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    rq = property(_swigfaiss.IndexResidualQuantizerFastScan_rq_get, _swigfaiss.IndexResidualQuantizerFastScan_rq_set, doc=r"""The residual quantizer used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type M: int
        :param M:      number of subquantizers
        :type nbits: int
        :param nbits:  number of bit per subvector index
        :type metric: int, optional
        :param metric:  metric type
        :type search_type: int, optional
        :param search_type: AQ search type

        :type d: int
        :param d: dimensionality of the input vectors
        :type M: int
        :param M: number of subquantizers
        :type nbits: int
        :param nbits: number of bit per subvector index
        """
        _swigfaiss.IndexResidualQuantizerFastScan_swiginit(self, _swigfaiss.new_IndexResidualQuantizerFastScan(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexResidualQuantizerFastScan

# Register IndexResidualQuantizerFastScan in _swigfaiss:
_swigfaiss.IndexResidualQuantizerFastScan_swigregister(IndexResidualQuantizerFastScan)
class IndexLocalSearchQuantizerFastScan(IndexAdditiveQuantizerFastScan):
    r"""
     Index based on a local search quantizer. Stored vectors are
    approximated by local search quantization codes.
    Can also be used as a codec
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    lsq = property(_swigfaiss.IndexLocalSearchQuantizerFastScan_lsq_get, _swigfaiss.IndexLocalSearchQuantizerFastScan_lsq_set)

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type M: int
        :param M:      number of subquantizers
        :type nbits: int
        :param nbits:  number of bit per subvector index
        :type metric: int, optional
        :param metric:  metric type
        :type search_type: int, optional
        :param search_type: AQ search type

        :type d: int
        :param d: dimensionality of the input vectors
        :type M: int
        :param M: number of subquantizers
        :type nbits: int
        :param nbits: number of bit per subvector index
        """
        _swigfaiss.IndexLocalSearchQuantizerFastScan_swiginit(self, _swigfaiss.new_IndexLocalSearchQuantizerFastScan(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexLocalSearchQuantizerFastScan

# Register IndexLocalSearchQuantizerFastScan in _swigfaiss:
_swigfaiss.IndexLocalSearchQuantizerFastScan_swigregister(IndexLocalSearchQuantizerFastScan)
class IndexProductResidualQuantizerFastScan(IndexAdditiveQuantizerFastScan):
    r"""
     Index based on a product residual quantizer. Stored vectors are
    approximated by product residual quantization codes.
    Can also be used as a codec
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    prq = property(_swigfaiss.IndexProductResidualQuantizerFastScan_prq_get, _swigfaiss.IndexProductResidualQuantizerFastScan_prq_set, doc=r"""The product residual quantizer used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type nsplits: int
        :param nsplits:  number of residual quantizers
        :type Msub: int
        :param Msub:     number of subquantizers per RQ
        :type nbits: int
        :param nbits:  number of bit per subvector index
        :type metric: int, optional
        :param metric:  metric type
        :type search_type: int, optional
        :param search_type: AQ search type

        :type d: int
        :param d: dimensionality of the input vectors
        :type nsplits: int
        :param nsplits: number of residual quantizers
        :type Msub: int
        :param Msub: number of subquantizers per RQ
        :type nbits: int
        :param nbits: number of bit per subvector index
        """
        _swigfaiss.IndexProductResidualQuantizerFastScan_swiginit(self, _swigfaiss.new_IndexProductResidualQuantizerFastScan(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexProductResidualQuantizerFastScan

# Register IndexProductResidualQuantizerFastScan in _swigfaiss:
_swigfaiss.IndexProductResidualQuantizerFastScan_swigregister(IndexProductResidualQuantizerFastScan)
class IndexProductLocalSearchQuantizerFastScan(IndexAdditiveQuantizerFastScan):
    r"""
     Index based on a product local search quantizer. Stored vectors are
    approximated by product local search quantization codes.
    Can also be used as a codec
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    plsq = property(_swigfaiss.IndexProductLocalSearchQuantizerFastScan_plsq_get, _swigfaiss.IndexProductLocalSearchQuantizerFastScan_plsq_set, doc=r"""The product local search quantizer used to encode the vectors""")

    def __init__(self, *args):
        r"""
         Constructor.

        :type d: int
        :param d:      dimensionality of the input vectors
        :type nsplits: int
        :param nsplits:  number of local search quantizers
        :type Msub: int
        :param Msub:     number of subquantizers per LSQ
        :type nbits: int
        :param nbits:  number of bit per subvector index
        :type metric: int, optional
        :param metric:  metric type
        :type search_type: int, optional
        :param search_type: AQ search type

        :type d: int
        :param d: dimensionality of the input vectors
        :type nsplits: int
        :param nsplits: number of local search quantizers
        :type Msub: int
        :param Msub: number of subquantizers per LSQ
        :type nbits: int
        :param nbits: number of bit per subvector index
        """
        _swigfaiss.IndexProductLocalSearchQuantizerFastScan_swiginit(self, _swigfaiss.new_IndexProductLocalSearchQuantizerFastScan(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexProductLocalSearchQuantizerFastScan

# Register IndexProductLocalSearchQuantizerFastScan in _swigfaiss:
_swigfaiss.IndexProductLocalSearchQuantizerFastScan_swigregister(IndexProductLocalSearchQuantizerFastScan)
class IndexPQFastScan(IndexFastScan):
    r"""
     Fast scan version of IndexPQ. Works for 4-bit PQ for now.

    The codes are not stored sequentially but grouped in blocks of size bbs.
    This makes it possible to compute distances quickly with SIMD instructions.

    Implementations:
    12: blocked loop with internal loop on Q with qbs
    13: same with reservoir accumulator to store results
    14: no qbs with heap accumulator
    15: no qbs with reservoir accumulator
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    pq = property(_swigfaiss.IndexPQFastScan_pq_get, _swigfaiss.IndexPQFastScan_pq_set)

    def __init__(self, *args):
        r"""
        *Overload 1:*
        build from an existing IndexPQ

        |

        *Overload 2:*
        build from an existing IndexPQ
        """
        _swigfaiss.IndexPQFastScan_swiginit(self, _swigfaiss.new_IndexPQFastScan(*args))

    def train(self, n, x):
        return _swigfaiss.IndexPQFastScan_train(self, n, x)

    def compute_codes(self, codes, n, x):
        return _swigfaiss.IndexPQFastScan_compute_codes(self, codes, n, x)

    def compute_float_LUT(self, lut, n, x, context):
        return _swigfaiss.IndexPQFastScan_compute_float_LUT(self, lut, n, x, context)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexPQFastScan_sa_decode(self, n, bytes, x)

    def fast_scan_code_size(self):
        r"""Packed code size: M2 / 2 bytes (4-bit PQ sub-quantizer nibbles)"""
        return _swigfaiss.IndexPQFastScan_fast_scan_code_size(self)
    __swig_destroy__ = _swigfaiss.delete_IndexPQFastScan

# Register IndexPQFastScan in _swigfaiss:
_swigfaiss.IndexPQFastScan_swigregister(IndexPQFastScan)
class IndexIVFFastScan(IndexIVF):
    r"""
     Fast scan version of IVFPQ and IVFAQ. Works for 4-bit PQ/AQ for now.

    The codes in the inverted lists are not stored sequentially but
    grouped in blocks of size bbs. This makes it possible to very quickly
    compute distances with SIMD instructions.

    Implementations (implem):
    0: auto-select implementation (default)
    1: orig's search, re-implemented
    2: orig's search, re-ordered by invlist
    10: optimizer int16 search, collect results in heap, no qbs
    11: idem, collect results in reservoir
    12: optimizer int16 search, collect results in heap, uses qbs
    13: idem, collect results in reservoir
    14: internally multithreaded implem over nq * nprobe
    15: same with reservoir

    For range search, only 10 and 12 are supported.
    add 100 to the implem to force single-thread scanning (the coarse quantizer
    may still use multiple threads).
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    bbs = property(_swigfaiss.IndexIVFFastScan_bbs_get, _swigfaiss.IndexIVFFastScan_bbs_set)
    M = property(_swigfaiss.IndexIVFFastScan_M_get, _swigfaiss.IndexIVFFastScan_M_set)
    nbits = property(_swigfaiss.IndexIVFFastScan_nbits_get, _swigfaiss.IndexIVFFastScan_nbits_set)
    ksub = property(_swigfaiss.IndexIVFFastScan_ksub_get, _swigfaiss.IndexIVFFastScan_ksub_set)
    M2 = property(_swigfaiss.IndexIVFFastScan_M2_get, _swigfaiss.IndexIVFFastScan_M2_set)
    implem = property(_swigfaiss.IndexIVFFastScan_implem_get, _swigfaiss.IndexIVFFastScan_implem_set)
    skip = property(_swigfaiss.IndexIVFFastScan_skip_get, _swigfaiss.IndexIVFFastScan_skip_set)
    qbs = property(_swigfaiss.IndexIVFFastScan_qbs_get, _swigfaiss.IndexIVFFastScan_qbs_set)
    qbs2 = property(_swigfaiss.IndexIVFFastScan_qbs2_get, _swigfaiss.IndexIVFFastScan_qbs2_set)
    fine_quantizer = property(_swigfaiss.IndexIVFFastScan_fine_quantizer_get, _swigfaiss.IndexIVFFastScan_fine_quantizer_set)

    def init_fastscan(self, fine_quantizer, M, nbits, nlist, metric, bbs, own_invlists):
        r"""
         Initialize the fast scan functionality (called by implementations)

        :type fine_quantizer: :py:class:`Quantizer`
        :param fine_quantizer:  fine quantizer for encoding
        :type M: int
        :param M:               number of subquantizers
        :type nbits: int
        :param nbits:           number of bits per subquantizer
        :type nlist: int
        :param nlist:           number of inverted lists
        :type metric: int
        :param metric:          distance metric to use
        :type bbs: int
        :param bbs:             block size for SIMD processing
        :type own_invlists: boolean
        :param own_invlists:    whether to own the inverted lists
        """
        return _swigfaiss.IndexIVFFastScan_init_fastscan(self, fine_quantizer, M, nbits, nlist, metric, bbs, own_invlists)

    def init_code_packer(self):
        return _swigfaiss.IndexIVFFastScan_init_code_packer(self)
    __swig_destroy__ = _swigfaiss.delete_IndexIVFFastScan
    orig_invlists = property(_swigfaiss.IndexIVFFastScan_orig_invlists_get, _swigfaiss.IndexIVFFastScan_orig_invlists_set, doc=r"""orig's inverted lists (for debugging)""")

    def add_with_ids(self, n, x, xids):
        r"""
         Add vectors with specific IDs to the index

        :type n: int
        :param n:     number of vectors to add
        :type x: float
        :param x:     vectors to add (n * d)
        :type xids: int
        :param xids:  IDs for the vectors (n)
        """
        return _swigfaiss.IndexIVFFastScan_add_with_ids(self, n, x, xids)

    def lookup_table_is_3d(self):
        return _swigfaiss.IndexIVFFastScan_lookup_table_is_3d(self)

    def compute_LUT(self, n, x, cq, dis_tables, biases, context):
        return _swigfaiss.IndexIVFFastScan_compute_LUT(self, n, x, cq, dis_tables, biases, context)

    def compute_LUT_uint8(self, n, x, cq, dis_tables, biases, normalizers, context):
        r"""
         Compute quantized lookup tables for distance computation

        :type n: int
        :param n:             number of query vectors
        :type x: float
        :param x:             query vectors (n * d)
        :type cq: faiss::IndexIVFFastScan::CoarseQuantized
        :param cq:            coarse quantization results
        :type dis_tables: faiss::AlignedTable< uint8_t >
        :param dis_tables:    output quantized distance tables
        :type biases: faiss::AlignedTable< uint16_t >
        :param biases:        output quantized bias values
        :type normalizers: float
        :param normalizers:   output normalization factors
        :type context: :py:class:`FastScanDistancePostProcessing`
        :param context:       processing context containing query factors
            processor
        """
        return _swigfaiss.IndexIVFFastScan_compute_LUT_uint8(self, n, x, cq, dis_tables, biases, normalizers, context)

    def search(self, n, x, k, distances, labels, params=None):
        r"""
         Search for k nearest neighbors

        :type n: int
        :param n:          number of query vectors
        :type x: float
        :param x:          query vectors (n * d)
        :type k: int
        :param k:          number of nearest neighbors to find
        :type distances: float
        :param distances:  output distances (n * k)
        :type labels: int
        :param labels:     output labels/indices (n * k)
        :type params: :py:class:`SearchParameters`, optional
        :param params:     optional search parameters
        """
        return _swigfaiss.IndexIVFFastScan_search(self, n, x, k, distances, labels, params)

    def search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params=None, stats=None):
        r"""
         Search with pre-assigned coarse quantization

        :type n: int
        :param n:             number of query vectors
        :type x: float
        :param x:             query vectors (n * d)
        :type k: int
        :param k:             number of nearest neighbors to find
        :type assign: int
        :param assign:        coarse cluster assignments (n * nprobe)
        :type centroid_dis: float
        :param centroid_dis:  distances to centroids (n * nprobe)
        :type distances: float
        :param distances:     output distances (n * k)
        :type labels: int
        :param labels:        output labels/indices (n * k)
        :type store_pairs: boolean
        :param store_pairs:   whether to store cluster-relative pairs
        :type params: :py:class:`IVFSearchParameters`, optional
        :param params:        optional IVF search parameters
        :type stats: :py:class:`IndexIVFStats`, optional
        :param stats:         optional search statistics
        """
        return _swigfaiss.IndexIVFFastScan_search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params, stats)

    def range_search(self, n, x, radius, result, params=None):
        r"""
         Range search for all neighbors within radius

        :type n: int
        :param n:       number of query vectors
        :type x: float
        :param x:       query vectors (n * d)
        :type radius: float
        :param radius:  search radius
        :type result: :py:class:`RangeSearchResult`
        :param result:  output range search results
        :type params: :py:class:`SearchParameters`, optional
        :param params:  optional search parameters
        """
        return _swigfaiss.IndexIVFFastScan_range_search(self, n, x, radius, result, params)

    def search_dispatch_implem(self, n, x, k, distances, labels, cq, context, params=None):
        return _swigfaiss.IndexIVFFastScan_search_dispatch_implem(self, n, x, k, distances, labels, cq, context, params)

    def range_search_dispatch_implem(self, n, x, radius, rres, cq_in, context, params=None):
        return _swigfaiss.IndexIVFFastScan_range_search_dispatch_implem(self, n, x, radius, rres, cq_in, context, params)

    def search_implem_14(self, n, x, k, distances, labels, cq, impl, context, params=None):
        return _swigfaiss.IndexIVFFastScan_search_implem_14(self, n, x, k, distances, labels, cq, impl, context, params)

    def reconstruct_from_offset(self, list_no, offset, recons):
        return _swigfaiss.IndexIVFFastScan_reconstruct_from_offset(self, list_no, offset, recons)

    def get_CodePacker(self):
        return _swigfaiss.IndexIVFFastScan_get_CodePacker(self)

    def reconstruct_orig_invlists(self):
        return _swigfaiss.IndexIVFFastScan_reconstruct_orig_invlists(self)

    def sa_decode(self, n, bytes, x):
        r"""
         Decode a set of vectors

        NOTE: The codes in the IndexFastScan object are non-contiguous.
              But this method requires a contiguous representation.

        :type n: int
        :param n:       number of vectors
        :type bytes: uint8_t
        :param bytes:   input encoded vectors, size n * code_size
        :type x: float
        :param x:       output vectors, size n * d
        """
        return _swigfaiss.IndexIVFFastScan_sa_decode(self, n, bytes, x)

    def fast_scan_code_size(self):
        r"""
         Get the size of the code portion packed by pq4_pack_codes.

        Returns the number of bytes per vector that are interleaved into
        SIMD blocks by pq4_pack_codes, excluding any embedded metadata
        (e.g., RaBitQ factors). The meaning of these bytes depends on the
        quantizer: for PQ/AQ they are 4-bit sub-quantizer nibbles, for
        RaBitQ they are 1-bit-per-dimension sign bits packed into nibbles.

        Must be implemented by all derived classes.
        """
        return _swigfaiss.IndexIVFFastScan_fast_scan_code_size(self)

    def get_block_stride(self):
        r"""
         Get stride in bytes between consecutive SIMD blocks.

        Derived from get_CodePacker()->block_size so that there is a
        single source of truth for the block layout.

        :rtype: int
        :return: stride in bytes
        """
        return _swigfaiss.IndexIVFFastScan_get_block_stride(self)

    def postprocess_packed_codes(self, list_no, list_offset, n_added, flat_codes):
        r"""
         Post-process packed codes after pq4_pack_codes_range.

        Called during add_with_ids after codes have been packed into
        SIMD-friendly blocks.

        :type list_no: int
        :param list_no:       inverted list number
        :type list_offset: int
        :param list_offset:   starting offset within the list (pre-existing size)
        :type n_added: int
        :param n_added:       number of vectors added in this batch
        :type flat_codes: uint8_t
        :param flat_codes:    encoded vectors for this batch (n_added * code_size)
        """
        return _swigfaiss.IndexIVFFastScan_postprocess_packed_codes(self, list_no, list_offset, n_added, flat_codes)

# Register IndexIVFFastScan in _swigfaiss:
_swigfaiss.IndexIVFFastScan_swigregister(IndexIVFFastScan)
class IVFFastScanStats(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    times = property(_swigfaiss.IVFFastScanStats_times_get, _swigfaiss.IVFFastScanStats_times_set)
    t_compute_distance_tables = property(_swigfaiss.IVFFastScanStats_t_compute_distance_tables_get, _swigfaiss.IVFFastScanStats_t_compute_distance_tables_set)
    t_round = property(_swigfaiss.IVFFastScanStats_t_round_get, _swigfaiss.IVFFastScanStats_t_round_set)
    t_copy_pack = property(_swigfaiss.IVFFastScanStats_t_copy_pack_get, _swigfaiss.IVFFastScanStats_t_copy_pack_set)
    t_scan = property(_swigfaiss.IVFFastScanStats_t_scan_get, _swigfaiss.IVFFastScanStats_t_scan_set)
    t_to_flat = property(_swigfaiss.IVFFastScanStats_t_to_flat_get, _swigfaiss.IVFFastScanStats_t_to_flat_set)
    reservoir_times = property(_swigfaiss.IVFFastScanStats_reservoir_times_get, _swigfaiss.IVFFastScanStats_reservoir_times_set)
    t_aq_encode = property(_swigfaiss.IVFFastScanStats_t_aq_encode_get, _swigfaiss.IVFFastScanStats_t_aq_encode_set)
    t_aq_norm_encode = property(_swigfaiss.IVFFastScanStats_t_aq_norm_encode_get, _swigfaiss.IVFFastScanStats_t_aq_norm_encode_set)

    def Mcy_at(self, i):
        return _swigfaiss.IVFFastScanStats_Mcy_at(self, i)

    def Mcy_reservoir_at(self, i):
        return _swigfaiss.IVFFastScanStats_Mcy_reservoir_at(self, i)

    def __init__(self):
        _swigfaiss.IVFFastScanStats_swiginit(self, _swigfaiss.new_IVFFastScanStats())

    def reset(self):
        return _swigfaiss.IVFFastScanStats_reset(self)
    __swig_destroy__ = _swigfaiss.delete_IVFFastScanStats

# Register IVFFastScanStats in _swigfaiss:
_swigfaiss.IVFFastScanStats_swigregister(IVFFastScanStats)
class IndexIVFAdditiveQuantizerFastScan(IndexIVFFastScan):
    r"""
     Fast scan version of IVFAQ. Works for 4-bit AQ for now.

    The codes in the inverted lists are not stored sequentially but
    grouped in blocks of size bbs. This makes it possible to very quickly
    compute distances with SIMD instructions.

    Implementations (implem):
    0: auto-select implementation (default)
    1: orig's search, re-implemented
    2: orig's search, re-ordered by invlist
    10: optimizer int16 search, collect results in heap, no qbs
    11: idem, collect results in reservoir
    12: optimizer int16 search, collect results in heap, uses qbs
    13: idem, collect results in reservoir
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    aq = property(_swigfaiss.IndexIVFAdditiveQuantizerFastScan_aq_get, _swigfaiss.IndexIVFAdditiveQuantizerFastScan_aq_set)
    rescale_norm = property(_swigfaiss.IndexIVFAdditiveQuantizerFastScan_rescale_norm_get, _swigfaiss.IndexIVFAdditiveQuantizerFastScan_rescale_norm_set)
    norm_scale = property(_swigfaiss.IndexIVFAdditiveQuantizerFastScan_norm_scale_get, _swigfaiss.IndexIVFAdditiveQuantizerFastScan_norm_scale_set)
    max_train_points = property(_swigfaiss.IndexIVFAdditiveQuantizerFastScan_max_train_points_get, _swigfaiss.IndexIVFAdditiveQuantizerFastScan_max_train_points_set)

    def init(self, aq, nlist, metric, bbs, own_invlists):
        return _swigfaiss.IndexIVFAdditiveQuantizerFastScan_init(self, aq, nlist, metric, bbs, own_invlists)
    __swig_destroy__ = _swigfaiss.delete_IndexIVFAdditiveQuantizerFastScan

    def __init__(self, *args):
        _swigfaiss.IndexIVFAdditiveQuantizerFastScan_swiginit(self, _swigfaiss.new_IndexIVFAdditiveQuantizerFastScan(*args))

    def fast_scan_code_size(self):
        r"""Packed code size: M2 / 2 bytes (4-bit AQ sub-quantizer nibbles)"""
        return _swigfaiss.IndexIVFAdditiveQuantizerFastScan_fast_scan_code_size(self)

    def train_encoder(self, n, x, assign):
        return _swigfaiss.IndexIVFAdditiveQuantizerFastScan_train_encoder(self, n, x, assign)

    def train_encoder_num_vectors(self):
        return _swigfaiss.IndexIVFAdditiveQuantizerFastScan_train_encoder_num_vectors(self)

    def estimate_norm_scale(self, n, x):
        return _swigfaiss.IndexIVFAdditiveQuantizerFastScan_estimate_norm_scale(self, n, x)

    def encode_vectors(self, n, x, list_nos, codes, include_listno=False):
        r"""
        same as the regular IVFAQ encoder. The codes are not reorganized by
        blocks a that point
        """
        return _swigfaiss.IndexIVFAdditiveQuantizerFastScan_encode_vectors(self, n, x, list_nos, codes, include_listno)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexIVFAdditiveQuantizerFastScan_search(self, n, x, k, distances, labels, params)

    def lookup_table_is_3d(self):
        return _swigfaiss.IndexIVFAdditiveQuantizerFastScan_lookup_table_is_3d(self)

    def compute_LUT(self, n, x, cq, dis_tables, biases, context):
        return _swigfaiss.IndexIVFAdditiveQuantizerFastScan_compute_LUT(self, n, x, cq, dis_tables, biases, context)

# Register IndexIVFAdditiveQuantizerFastScan in _swigfaiss:
_swigfaiss.IndexIVFAdditiveQuantizerFastScan_swigregister(IndexIVFAdditiveQuantizerFastScan)
class IndexIVFLocalSearchQuantizerFastScan(IndexIVFAdditiveQuantizerFastScan):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    lsq = property(_swigfaiss.IndexIVFLocalSearchQuantizerFastScan_lsq_get, _swigfaiss.IndexIVFLocalSearchQuantizerFastScan_lsq_set)

    def __init__(self, *args):
        _swigfaiss.IndexIVFLocalSearchQuantizerFastScan_swiginit(self, _swigfaiss.new_IndexIVFLocalSearchQuantizerFastScan(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFLocalSearchQuantizerFastScan

# Register IndexIVFLocalSearchQuantizerFastScan in _swigfaiss:
_swigfaiss.IndexIVFLocalSearchQuantizerFastScan_swigregister(IndexIVFLocalSearchQuantizerFastScan)
class IndexIVFResidualQuantizerFastScan(IndexIVFAdditiveQuantizerFastScan):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    rq = property(_swigfaiss.IndexIVFResidualQuantizerFastScan_rq_get, _swigfaiss.IndexIVFResidualQuantizerFastScan_rq_set)

    def __init__(self, *args):
        _swigfaiss.IndexIVFResidualQuantizerFastScan_swiginit(self, _swigfaiss.new_IndexIVFResidualQuantizerFastScan(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFResidualQuantizerFastScan

# Register IndexIVFResidualQuantizerFastScan in _swigfaiss:
_swigfaiss.IndexIVFResidualQuantizerFastScan_swigregister(IndexIVFResidualQuantizerFastScan)
class IndexIVFProductLocalSearchQuantizerFastScan(IndexIVFAdditiveQuantizerFastScan):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    plsq = property(_swigfaiss.IndexIVFProductLocalSearchQuantizerFastScan_plsq_get, _swigfaiss.IndexIVFProductLocalSearchQuantizerFastScan_plsq_set)

    def __init__(self, *args):
        _swigfaiss.IndexIVFProductLocalSearchQuantizerFastScan_swiginit(self, _swigfaiss.new_IndexIVFProductLocalSearchQuantizerFastScan(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFProductLocalSearchQuantizerFastScan

# Register IndexIVFProductLocalSearchQuantizerFastScan in _swigfaiss:
_swigfaiss.IndexIVFProductLocalSearchQuantizerFastScan_swigregister(IndexIVFProductLocalSearchQuantizerFastScan)
class IndexIVFProductResidualQuantizerFastScan(IndexIVFAdditiveQuantizerFastScan):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    prq = property(_swigfaiss.IndexIVFProductResidualQuantizerFastScan_prq_get, _swigfaiss.IndexIVFProductResidualQuantizerFastScan_prq_set)

    def __init__(self, *args):
        _swigfaiss.IndexIVFProductResidualQuantizerFastScan_swiginit(self, _swigfaiss.new_IndexIVFProductResidualQuantizerFastScan(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexIVFProductResidualQuantizerFastScan

# Register IndexIVFProductResidualQuantizerFastScan in _swigfaiss:
_swigfaiss.IndexIVFProductResidualQuantizerFastScan_swigregister(IndexIVFProductResidualQuantizerFastScan)
class IndexIVFIndependentQuantizer(Index):
    r"""
     An IVF index with a quantizer that has a different input dimension from the
    payload size. The vectors to encode are obtained from the input vectors by a
    VectorTransform.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    quantizer = property(_swigfaiss.IndexIVFIndependentQuantizer_quantizer_get, _swigfaiss.IndexIVFIndependentQuantizer_quantizer_set, doc=r"""quantizer is fed directly with the input vectors""")
    vt = property(_swigfaiss.IndexIVFIndependentQuantizer_vt_get, _swigfaiss.IndexIVFIndependentQuantizer_vt_set, doc=r"""transform before the IVF vectors are applied""")
    index_ivf = property(_swigfaiss.IndexIVFIndependentQuantizer_index_ivf_get, _swigfaiss.IndexIVFIndependentQuantizer_index_ivf_set, doc=r"""the IVF index, controls nlist and nprobe""")
    own_fields = property(_swigfaiss.IndexIVFIndependentQuantizer_own_fields_get, _swigfaiss.IndexIVFIndependentQuantizer_own_fields_set, doc=r"""whether *this owns the 3 fields""")

    def __init__(self, *args):
        _swigfaiss.IndexIVFIndependentQuantizer_swiginit(self, _swigfaiss.new_IndexIVFIndependentQuantizer(*args))

    def train(self, n, x):
        return _swigfaiss.IndexIVFIndependentQuantizer_train(self, n, x)

    def add(self, n, x):
        return _swigfaiss.IndexIVFIndependentQuantizer_add(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexIVFIndependentQuantizer_search(self, n, x, k, distances, labels, params)

    def reset(self):
        return _swigfaiss.IndexIVFIndependentQuantizer_reset(self)
    __swig_destroy__ = _swigfaiss.delete_IndexIVFIndependentQuantizer

# Register IndexIVFIndependentQuantizer in _swigfaiss:
_swigfaiss.IndexIVFIndependentQuantizer_swigregister(IndexIVFIndependentQuantizer)
class IndexIVFPQFastScan(IndexIVFFastScan):
    r"""
     Fast scan version of IVFPQ. Works for 4-bit PQ for now.

    The codes in the inverted lists are not stored sequentially but
    grouped in blocks of size bbs. This makes it possible to very quickly
    compute distances with SIMD instructions.

    Implementations (implem):
    0: auto-select implementation (default)
    1: orig's search, re-implemented
    2: orig's search, re-ordered by invlist
    10: optimizer int16 search, collect results in heap, no qbs
    11: idem, collect results in reservoir
    12: optimizer int16 search, collect results in heap, uses qbs
    13: idem, collect results in reservoir
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    pq = property(_swigfaiss.IndexIVFPQFastScan_pq_get, _swigfaiss.IndexIVFPQFastScan_pq_set, doc=r"""produces the codes""")
    use_precomputed_table = property(_swigfaiss.IndexIVFPQFastScan_use_precomputed_table_get, _swigfaiss.IndexIVFPQFastScan_use_precomputed_table_set, doc=r"""precomputed tables management""")
    precomputed_table = property(_swigfaiss.IndexIVFPQFastScan_precomputed_table_get, _swigfaiss.IndexIVFPQFastScan_precomputed_table_set, doc=r"""if use_precompute_table size (nlist, pq.M, pq.ksub)""")

    def __init__(self, *args):
        _swigfaiss.IndexIVFPQFastScan_swiginit(self, _swigfaiss.new_IndexIVFPQFastScan(*args))

    def fast_scan_code_size(self):
        r"""Packed code size: M2 / 2 bytes (4-bit PQ sub-quantizer nibbles)"""
        return _swigfaiss.IndexIVFPQFastScan_fast_scan_code_size(self)

    def train_encoder(self, n, x, assign):
        return _swigfaiss.IndexIVFPQFastScan_train_encoder(self, n, x, assign)

    def train_encoder_num_vectors(self):
        return _swigfaiss.IndexIVFPQFastScan_train_encoder_num_vectors(self)

    def precompute_table(self):
        r"""build precomputed table, possibly updating use_precomputed_table"""
        return _swigfaiss.IndexIVFPQFastScan_precompute_table(self)

    def encode_vectors(self, n, x, list_nos, codes, include_listno=False):
        r"""
        same as the regular IVFPQ encoder. The codes are not reorganized by
        blocks a that point
        """
        return _swigfaiss.IndexIVFPQFastScan_encode_vectors(self, n, x, list_nos, codes, include_listno)

    def lookup_table_is_3d(self):
        return _swigfaiss.IndexIVFPQFastScan_lookup_table_is_3d(self)

    def compute_LUT(self, n, x, cq, dis_tables, biases, context):
        return _swigfaiss.IndexIVFPQFastScan_compute_LUT(self, n, x, cq, dis_tables, biases, context)

    def get_InvertedListScanner(self, store_pairs, sel, arg4):
        return _swigfaiss.IndexIVFPQFastScan_get_InvertedListScanner(self, store_pairs, sel, arg4)
    __swig_destroy__ = _swigfaiss.delete_IndexIVFPQFastScan

# Register IndexIVFPQFastScan in _swigfaiss:
_swigfaiss.IndexIVFPQFastScan_swigregister(IndexIVFPQFastScan)

def round_uint8_per_column(tab, n, d, a_out=None, b_out=None):
    r"""
     Functions to quantize PQ floating-point Look Up Tables (LUT) to uint8, and
    biases to uint16. The accumulation is supposed to take place in uint16.
    The quantization coefficients are float (a, b) such that

         original_value = quantized_value * a / b

    The hardest part of the quantization is with multiple LUTs that need to be
    added up together. In that case, coefficient a has to be chosen so that
    the sum fits in a uint16 accumulator.
    """
    return _swigfaiss.round_uint8_per_column(tab, n, d, a_out, b_out)

def round_uint8_per_column_multi(tab, m, n, d, a_out=None, b_out=None):
    return _swigfaiss.round_uint8_per_column_multi(tab, m, n, d, a_out, b_out)

def quantize_LUT_and_bias(nprobe, M, ksub, lut_is_3d, LUT, bias, LUTq, M2, biasq, a_out=None, b_out=None):
    r"""
     LUT quantization to uint8 and bias to uint16.

    (nprobe, M, ksub, lut_is_3d) determine the size of the LUT

     LUT input:
     - 2D size (M, ksub): single matrix per probe (lut_is_3d=false)
     - 3D size (nprobe, M, ksub): separate LUT per probe (lut_is_3d=true)
     bias input:
     - nullptr: bias is 0
     - size (nprobe): one bias per probe
     Output:
     - LUTq uint8 version of the LUT (M size is rounded up to M2)
     - biasq (or nullptr): uint16 version of the LUT
     - a, b: scalars to approximate the true distance
    """
    return _swigfaiss.quantize_LUT_and_bias(nprobe, M, ksub, lut_is_3d, LUT, bias, LUTq, M2, biasq, a_out, b_out)

def aq_quantize_LUT_and_bias(nprobe, M, ksub, LUT, bias, M_norm, norm_scale, LUTq, M2, biasq, a_out, b_out):
    return _swigfaiss.aq_quantize_LUT_and_bias(nprobe, M, ksub, LUT, bias, M_norm, norm_scale, LUTq, M2, biasq, a_out, b_out)

def aq_estimate_norm_scale(M, ksub, M_norm, LUT):
    return _swigfaiss.aq_estimate_norm_scale(M, ksub, M_norm, LUT)
class IndexBinary(object):
    r"""
     Abstract structure for a binary index.

    Supports adding vertices and searching them.

    All queries are symmetric because there is no distinction between codes and
    vectors.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    d = property(_swigfaiss.IndexBinary_d_get, _swigfaiss.IndexBinary_d_set, doc=r"""vector dimension""")
    code_size = property(_swigfaiss.IndexBinary_code_size_get, _swigfaiss.IndexBinary_code_size_set, doc=r"""number of bytes per vector ( = d / 8 )""")
    ntotal = property(_swigfaiss.IndexBinary_ntotal_get, _swigfaiss.IndexBinary_ntotal_set, doc=r"""total nb of indexed vectors""")
    verbose = property(_swigfaiss.IndexBinary_verbose_get, _swigfaiss.IndexBinary_verbose_set, doc=r"""verbosity level""")
    is_trained = property(_swigfaiss.IndexBinary_is_trained_get, _swigfaiss.IndexBinary_is_trained_set, doc=r"""
    set if the Index does not require training, or if training is done
    already
    """)
    metric_type = property(_swigfaiss.IndexBinary_metric_type_get, _swigfaiss.IndexBinary_metric_type_set, doc=r"""type of metric this index uses for search""")
    __swig_destroy__ = _swigfaiss.delete_IndexBinary

    def train(self, n, x):
        r"""
         Perform training on a representative set of vectors.

        :type n: int
        :param n:      nb of training vectors
        :type x: uint8_t
        :param x:      training vectors, size n * d / 8
        """
        return _swigfaiss.IndexBinary_train(self, n, x)

    def train_ex(self, n, x, numeric_type):
        return _swigfaiss.IndexBinary_train_ex(self, n, x, numeric_type)

    def add(self, n, x):
        r"""
         Add n vectors of dimension d to the index.

        Vectors are implicitly assigned labels ntotal .. ntotal + n - 1
        :type x: uint8_t
        :param x:      input matrix, size n * d / 8
        """
        return _swigfaiss.IndexBinary_add(self, n, x)

    def add_ex(self, n, x, numeric_type):
        return _swigfaiss.IndexBinary_add_ex(self, n, x, numeric_type)

    def add_with_ids(self, n, x, xids):
        r"""
         Same as add, but stores xids instead of sequential ids.

        The default implementation fails with an assertion, as it is
        not supported by all indexes.

        :type xids: int
        :param xids: if non-null, ids to store for the vectors (size n)
        """
        return _swigfaiss.IndexBinary_add_with_ids(self, n, x, xids)

    def add_with_ids_ex(self, n, x, numeric_type, xids):
        return _swigfaiss.IndexBinary_add_with_ids_ex(self, n, x, numeric_type, xids)

    def search(self, n, x, k, distances, labels, params=None):
        r"""
         Query n vectors of dimension d to the index.

        return at most k vectors. If there are not enough results for a
        query, the result array is padded with -1s.

        :type x: uint8_t
        :param x:           input vectors to search, size n * d / 8
        :type labels: int
        :param labels:      output labels of the NNs, size n*k
        :type distances: int
        :param distances:   output pairwise distances, size n*k
        """
        return _swigfaiss.IndexBinary_search(self, n, x, k, distances, labels, params)

    def search_ex(self, n, x, numeric_type, k, distances, labels, params=None):
        return _swigfaiss.IndexBinary_search_ex(self, n, x, numeric_type, k, distances, labels, params)

    def range_search(self, n, x, radius, result, params=None):
        r"""
         Query n vectors of dimension d to the index.

        return all vectors with distance < radius. Note that many indexes
        do not implement the range_search (only the k-NN search is
        mandatory). The distances are converted to float to reuse the
        RangeSearchResult structure, but they are integer. By convention,
        only distances < radius (strict comparison) are returned,
        ie. radius = 0 does not return any result and 1 returns only
        exact same vectors.

        :type x: uint8_t
        :param x:           input vectors to search, size n * d / 8
        :type radius: int
        :param radius:      search radius
        :type result: :py:class:`RangeSearchResult`
        :param result:      result table
        """
        return _swigfaiss.IndexBinary_range_search(self, n, x, radius, result, params)

    def assign(self, n, x, labels, k=1):
        r"""
         Return the indexes of the k vectors closest to the query x.

        This function is identical to search but only returns labels of
        neighbors.
        :type x: uint8_t
        :param x:           input vectors to search, size n * d / 8
        :type labels: int
        :param labels:      output labels of the NNs, size n*k
        """
        return _swigfaiss.IndexBinary_assign(self, n, x, labels, k)

    def reset(self):
        r"""Removes all elements from the database."""
        return _swigfaiss.IndexBinary_reset(self)

    def remove_ids(self, sel):
        r"""Removes IDs from the index. Not supported by all indexes."""
        return _swigfaiss.IndexBinary_remove_ids(self, sel)

    def reconstruct(self, key, recons):
        r"""
         Reconstruct a stored vector.

        This function may not be defined for some indexes.
        :type key: int
        :param key:         id of the vector to reconstruct
        :type recons: uint8_t
        :param recons:      reconstructed vector (size d / 8)
        """
        return _swigfaiss.IndexBinary_reconstruct(self, key, recons)

    def reconstruct_n(self, i0, ni, recons):
        r"""
         Reconstruct vectors i0 to i0 + ni - 1.

        This function may not be defined for some indexes.
        :type recons: uint8_t
        :param recons:      reconstructed vectors (size ni * d / 8)
        """
        return _swigfaiss.IndexBinary_reconstruct_n(self, i0, ni, recons)

    def search_and_reconstruct(self, n, x, k, distances, labels, recons, params=None):
        r"""
         Similar to search, but also reconstructs the stored vectors (or an
        approximation in the case of lossy coding) for the search results.

        If there are not enough results for a query, the resulting array
        is padded with -1s.

        :type recons: uint8_t
        :param recons:      reconstructed vectors size (n, k, d)
        """
        return _swigfaiss.IndexBinary_search_and_reconstruct(self, n, x, k, distances, labels, recons, params)

    def display(self):
        r"""Display the actual class name and some more info."""
        return _swigfaiss.IndexBinary_display(self)

    def merge_from(self, otherIndex, add_id=0):
        r"""
         moves the entries from another dataset to self.
        On output, other is empty.
        add_id is added to all moved ids
        (for sequential ids, this would be this->ntotal)
        """
        return _swigfaiss.IndexBinary_merge_from(self, otherIndex, add_id)

    def check_compatible_for_merge(self, otherIndex):
        r"""
         check that the two indexes are compatible (ie, they are
        trained in the same way and have the same
        parameters). Otherwise throw.
        """
        return _swigfaiss.IndexBinary_check_compatible_for_merge(self, otherIndex)

    def sa_code_size(self):
        r"""size of the produced codes in bytes"""
        return _swigfaiss.IndexBinary_sa_code_size(self)

    def add_sa_codes(self, n, codes, xids):
        r"""Same as add_with_ids for IndexBinary."""
        return _swigfaiss.IndexBinary_add_sa_codes(self, n, codes, xids)

# Register IndexBinary in _swigfaiss:
_swigfaiss.IndexBinary_swigregister(IndexBinary)
class IndexBinaryFlat(IndexBinary):
    r"""Index that stores the full vectors and performs exhaustive search."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    xb = property(_swigfaiss.IndexBinaryFlat_xb_get, _swigfaiss.IndexBinaryFlat_xb_set, doc=r"""database vectors, size ntotal * d / 8""")
    use_heap = property(_swigfaiss.IndexBinaryFlat_use_heap_get, _swigfaiss.IndexBinaryFlat_use_heap_set, doc=r"""
     Select between using a heap or counting to select the k smallest values
    when scanning inverted lists.
    """)
    query_batch_size = property(_swigfaiss.IndexBinaryFlat_query_batch_size_get, _swigfaiss.IndexBinaryFlat_query_batch_size_set)
    approx_topk_mode = property(_swigfaiss.IndexBinaryFlat_approx_topk_mode_get, _swigfaiss.IndexBinaryFlat_approx_topk_mode_set)

    def add(self, n, x):
        return _swigfaiss.IndexBinaryFlat_add(self, n, x)

    def reset(self):
        return _swigfaiss.IndexBinaryFlat_reset(self)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexBinaryFlat_search(self, n, x, k, distances, labels, params)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexBinaryFlat_range_search(self, n, x, radius, result, params)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexBinaryFlat_reconstruct(self, key, recons)

    def remove_ids(self, sel):
        r"""
         Remove some ids. Note that because of the indexing structure,
        the semantics of this operation are different from the usual ones:
        the new ids are shifted.
        """
        return _swigfaiss.IndexBinaryFlat_remove_ids(self, sel)

    def __init__(self, *args):
        _swigfaiss.IndexBinaryFlat_swiginit(self, _swigfaiss.new_IndexBinaryFlat(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexBinaryFlat

# Register IndexBinaryFlat in _swigfaiss:
_swigfaiss.IndexBinaryFlat_swigregister(IndexBinaryFlat)
class IndexBinaryIVF(IndexBinary):
    r"""
     Index based on a inverted file (IVF)

    In the inverted file, the quantizer (an IndexBinary instance) provides a
    quantization index for each vector to be added. The quantization
    index maps to a list (aka inverted list or posting list), where the
    id of the vector is stored.

    Otherwise the object is similar to the IndexIVF
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    invlists = property(_swigfaiss.IndexBinaryIVF_invlists_get, _swigfaiss.IndexBinaryIVF_invlists_set, doc=r"""Access to the actual data""")
    own_invlists = property(_swigfaiss.IndexBinaryIVF_own_invlists_get, _swigfaiss.IndexBinaryIVF_own_invlists_set)
    nprobe = property(_swigfaiss.IndexBinaryIVF_nprobe_get, _swigfaiss.IndexBinaryIVF_nprobe_set, doc=r"""number of probes at query time""")
    max_codes = property(_swigfaiss.IndexBinaryIVF_max_codes_get, _swigfaiss.IndexBinaryIVF_max_codes_set, doc=r"""max nb of codes to visit to do a query""")
    use_heap = property(_swigfaiss.IndexBinaryIVF_use_heap_get, _swigfaiss.IndexBinaryIVF_use_heap_set, doc=r"""
     Select between using a heap or counting to select the k smallest values
    when scanning inverted lists.
    """)
    per_invlist_search = property(_swigfaiss.IndexBinaryIVF_per_invlist_search_get, _swigfaiss.IndexBinaryIVF_per_invlist_search_set, doc=r"""collect computations per batch""")
    direct_map = property(_swigfaiss.IndexBinaryIVF_direct_map_get, _swigfaiss.IndexBinaryIVF_direct_map_set, doc=r"""map for direct access to the elements. Enables reconstruct().""")
    quantizer = property(_swigfaiss.IndexBinaryIVF_quantizer_get, _swigfaiss.IndexBinaryIVF_quantizer_set, doc=r"""quantizer that maps vectors to inverted lists""")
    nlist = property(_swigfaiss.IndexBinaryIVF_nlist_get, _swigfaiss.IndexBinaryIVF_nlist_set, doc=r"""number of possible key values""")
    own_fields = property(_swigfaiss.IndexBinaryIVF_own_fields_get, _swigfaiss.IndexBinaryIVF_own_fields_set, doc=r"""whether object owns the quantizer""")
    cp = property(_swigfaiss.IndexBinaryIVF_cp_get, _swigfaiss.IndexBinaryIVF_cp_set, doc=r"""to override default clustering params""")
    clustering_index = property(_swigfaiss.IndexBinaryIVF_clustering_index_get, _swigfaiss.IndexBinaryIVF_clustering_index_set, doc=r"""to override index used during clustering""")

    def __init__(self, *args):
        r"""
         The Inverted file takes a quantizer (an IndexBinary) on input,
        which implements the function mapping a vector to a list
        identifier. The pointer is borrowed: the quantizer should not
        be deleted while the IndexBinaryIVF is in use.
        """
        _swigfaiss.IndexBinaryIVF_swiginit(self, _swigfaiss.new_IndexBinaryIVF(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexBinaryIVF

    def reset(self):
        return _swigfaiss.IndexBinaryIVF_reset(self)

    def train(self, n, x):
        r"""Trains the quantizer"""
        return _swigfaiss.IndexBinaryIVF_train(self, n, x)

    def add(self, n, x):
        return _swigfaiss.IndexBinaryIVF_add(self, n, x)

    def add_with_ids(self, n, x, xids):
        return _swigfaiss.IndexBinaryIVF_add_with_ids(self, n, x, xids)

    def add_core(self, n, x, xids, precomputed_idx):
        r"""
         Implementation of vector addition where the vector assignments are
        predefined.

        :type precomputed_idx: int
        :param precomputed_idx:    quantization indices for the input vectors
            (size n)
        """
        return _swigfaiss.IndexBinaryIVF_add_core(self, n, x, xids, precomputed_idx)

    def search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params=None):
        r"""
         Search a set of vectors, that are pre-quantized by the IVF
         quantizer. Fill in the corresponding heaps with the query
         results. search() calls this.

        :type n: int
        :param n:      nb of vectors to query
        :type x: uint8_t
        :param x:      query vectors, size nx * d
        :type assign: int
        :param assign: coarse quantization indices, size nx * nprobe
        :type centroid_dis: int
        :param centroid_dis:
                          distances to coarse centroids, size nx * nprobe
        :param distance:
                          output distances, size n * k
        :type labels: int
        :param labels: output labels, size n * k
        :type store_pairs: boolean
        :param store_pairs: store inv list index + inv list offset
                                instead in upper/lower 32 bit of result,
                                instead of ids (used for reranking).
        :type params: :py:class:`IVFSearchParameters`, optional
        :param params: used to override the object's search parameters
        """
        return _swigfaiss.IndexBinaryIVF_search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params)

    def get_InvertedListScanner(self, store_pairs=False):
        return _swigfaiss.IndexBinaryIVF_get_InvertedListScanner(self, store_pairs)

    def search(self, n, x, k, distances, labels, params=None):
        r"""assign the vectors, then call search_preassign"""
        return _swigfaiss.IndexBinaryIVF_search(self, n, x, k, distances, labels, params)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexBinaryIVF_range_search(self, n, x, radius, result, params)

    def range_search_preassigned(self, n, x, radius, assign, centroid_dis, result):
        return _swigfaiss.IndexBinaryIVF_range_search_preassigned(self, n, x, radius, assign, centroid_dis, result)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexBinaryIVF_reconstruct(self, key, recons)

    def reconstruct_n(self, i0, ni, recons):
        r"""
         Reconstruct a subset of the indexed vectors.

        Overrides default implementation to bypass reconstruct() which requires
        direct_map to be maintained.

        :type i0: int
        :param i0:     first vector to reconstruct
        :type ni: int
        :param ni:     nb of vectors to reconstruct
        :type recons: uint8_t
        :param recons: output array of reconstructed vectors, size ni * d / 8
        """
        return _swigfaiss.IndexBinaryIVF_reconstruct_n(self, i0, ni, recons)

    def search_and_reconstruct(self, n, x, k, distances, labels, recons, params=None):
        r"""
         Similar to search, but also reconstructs the stored vectors (or an
        approximation in the case of lossy coding) for the search results.

        Overrides default implementation to avoid having to maintain direct_map
        and instead fetch the code offsets through the `store_pairs` flag in
        search_preassigned().

        :type recons: uint8_t
        :param recons:      reconstructed vectors size (n, k, d / 8)
        """
        return _swigfaiss.IndexBinaryIVF_search_and_reconstruct(self, n, x, k, distances, labels, recons, params)

    def reconstruct_from_offset(self, list_no, offset, recons):
        r"""
         Reconstruct a vector given the location in terms of (inv list index +
        inv list offset) instead of the id.

        Useful for reconstructing when the direct_map is not maintained and
        the inv list offset is computed by search_preassigned() with
        `store_pairs` set.
        """
        return _swigfaiss.IndexBinaryIVF_reconstruct_from_offset(self, list_no, offset, recons)

    def remove_ids(self, sel):
        r"""Dataset manipulation functions"""
        return _swigfaiss.IndexBinaryIVF_remove_ids(self, sel)

    def merge_from(self, other, add_id):
        return _swigfaiss.IndexBinaryIVF_merge_from(self, other, add_id)

    def check_compatible_for_merge(self, otherIndex):
        return _swigfaiss.IndexBinaryIVF_check_compatible_for_merge(self, otherIndex)

    def get_list_size(self, list_no):
        return _swigfaiss.IndexBinaryIVF_get_list_size(self, list_no)

    def make_direct_map(self, new_maintain_direct_map=True):
        r"""
         initialize a direct map

        :type new_maintain_direct_map: boolean, optional
        :param new_maintain_direct_map:    if true, create a direct map,
                                              else clear it
        """
        return _swigfaiss.IndexBinaryIVF_make_direct_map(self, new_maintain_direct_map)

    def set_direct_map_type(self, type):
        return _swigfaiss.IndexBinaryIVF_set_direct_map_type(self, type)

    def replace_invlists(self, il, own=False):
        return _swigfaiss.IndexBinaryIVF_replace_invlists(self, il, own)

# Register IndexBinaryIVF in _swigfaiss:
_swigfaiss.IndexBinaryIVF_swigregister(IndexBinaryIVF)
class BinaryInvertedListScanner(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr

    def set_query(self, query_vector):
        r"""from now on we handle this query."""
        return _swigfaiss.BinaryInvertedListScanner_set_query(self, query_vector)

    def set_list(self, list_no, coarse_dis):
        r"""following codes come from this inverted list"""
        return _swigfaiss.BinaryInvertedListScanner_set_list(self, list_no, coarse_dis)

    def distance_to_code(self, code):
        r"""compute a single query-to-code distance"""
        return _swigfaiss.BinaryInvertedListScanner_distance_to_code(self, code)

    def scan_codes(self, n, codes, ids, distances, labels, k):
        r"""
         compute the distances to codes. (distances, labels) should be
        organized as a min- or max-heap

        :type n: int
        :param n:      number of codes to scan
        :type codes: uint8_t
        :param codes:  codes to scan (n * code_size)
        :type ids: int
        :param ids:        corresponding ids (ignored if store_pairs)
        :type distances: int
        :param distances:  heap distances (size k)
        :type labels: int
        :param labels:     heap labels (size k)
        :type k: int
        :param k:          heap size
        """
        return _swigfaiss.BinaryInvertedListScanner_scan_codes(self, n, codes, ids, distances, labels, k)

    def scan_codes_range(self, n, codes, ids, radius, result):
        return _swigfaiss.BinaryInvertedListScanner_scan_codes_range(self, n, codes, ids, radius, result)
    __swig_destroy__ = _swigfaiss.delete_BinaryInvertedListScanner

# Register BinaryInvertedListScanner in _swigfaiss:
_swigfaiss.BinaryInvertedListScanner_swigregister(BinaryInvertedListScanner)
class IndexBinaryFromFloat(IndexBinary):
    r"""
     IndexBinary backed by a float Index.

    Supports adding vertices and searching them.

    All queries are symmetric because there is no distinction between codes and
    vectors.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    index = property(_swigfaiss.IndexBinaryFromFloat_index_get, _swigfaiss.IndexBinaryFromFloat_index_set)
    own_fields = property(_swigfaiss.IndexBinaryFromFloat_own_fields_get, _swigfaiss.IndexBinaryFromFloat_own_fields_set, doc=r"""Whether object owns the index pointer.""")

    def __init__(self, *args):
        _swigfaiss.IndexBinaryFromFloat_swiginit(self, _swigfaiss.new_IndexBinaryFromFloat(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexBinaryFromFloat

    def add(self, n, x):
        return _swigfaiss.IndexBinaryFromFloat_add(self, n, x)

    def reset(self):
        return _swigfaiss.IndexBinaryFromFloat_reset(self)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexBinaryFromFloat_search(self, n, x, k, distances, labels, params)

    def train(self, n, x):
        return _swigfaiss.IndexBinaryFromFloat_train(self, n, x)

# Register IndexBinaryFromFloat in _swigfaiss:
_swigfaiss.IndexBinaryFromFloat_swigregister(IndexBinaryFromFloat)
class IndexBinaryHNSW(IndexBinary):
    r"""
     The HNSW index is a normal random-access index with a HNSW
    link structure built on top
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    hnsw = property(_swigfaiss.IndexBinaryHNSW_hnsw_get, _swigfaiss.IndexBinaryHNSW_hnsw_set)
    own_fields = property(_swigfaiss.IndexBinaryHNSW_own_fields_get, _swigfaiss.IndexBinaryHNSW_own_fields_set)
    storage = property(_swigfaiss.IndexBinaryHNSW_storage_get, _swigfaiss.IndexBinaryHNSW_storage_set)
    init_level0 = property(_swigfaiss.IndexBinaryHNSW_init_level0_get, _swigfaiss.IndexBinaryHNSW_init_level0_set)
    keep_max_size_level0 = property(_swigfaiss.IndexBinaryHNSW_keep_max_size_level0_get, _swigfaiss.IndexBinaryHNSW_keep_max_size_level0_set)
    retain_locks = property(_swigfaiss.IndexBinaryHNSW_retain_locks_get, _swigfaiss.IndexBinaryHNSW_retain_locks_set)

    def __init__(self, *args):
        _swigfaiss.IndexBinaryHNSW_swiginit(self, _swigfaiss.new_IndexBinaryHNSW(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexBinaryHNSW

    def get_distance_computer(self):
        return _swigfaiss.IndexBinaryHNSW_get_distance_computer(self)

    def add(self, n, x):
        return _swigfaiss.IndexBinaryHNSW_add(self, n, x)

    def train(self, n, x):
        r"""Trains the storage if needed"""
        return _swigfaiss.IndexBinaryHNSW_train(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        r"""entry point for search"""
        return _swigfaiss.IndexBinaryHNSW_search(self, n, x, k, distances, labels, params)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexBinaryHNSW_reconstruct(self, key, recons)

    def reset(self):
        return _swigfaiss.IndexBinaryHNSW_reset(self)

# Register IndexBinaryHNSW in _swigfaiss:
_swigfaiss.IndexBinaryHNSW_swigregister(IndexBinaryHNSW)
class IndexBinaryHNSWCagra(IndexBinaryHNSW):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexBinaryHNSWCagra_swiginit(self, _swigfaiss.new_IndexBinaryHNSWCagra(*args))
    base_level_only = property(_swigfaiss.IndexBinaryHNSWCagra_base_level_only_get, _swigfaiss.IndexBinaryHNSWCagra_base_level_only_set, doc=r"""
    When set to true, the index is immutable.
    This option is used to copy the knn graph from GpuIndexBinaryCagra
    to the base level of IndexBinaryHNSWCagra without adding upper levels.
    Doing so enables to search the HNSW index, but removes the
    ability to add vectors.
    """)
    num_base_level_search_entrypoints = property(_swigfaiss.IndexBinaryHNSWCagra_num_base_level_search_entrypoints_get, _swigfaiss.IndexBinaryHNSWCagra_num_base_level_search_entrypoints_set, doc=r"""
    When `base_level_only` is set to `True`, the search function
    searches only the base level knn graph of the HNSW index.
    This parameter selects the entry point by randomly selecting
    some points and using the best one.
    """)

    def add(self, n, x):
        return _swigfaiss.IndexBinaryHNSWCagra_add(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        r"""entry point for search"""
        return _swigfaiss.IndexBinaryHNSWCagra_search(self, n, x, k, distances, labels, params)
    __swig_destroy__ = _swigfaiss.delete_IndexBinaryHNSWCagra

# Register IndexBinaryHNSWCagra in _swigfaiss:
_swigfaiss.IndexBinaryHNSWCagra_swigregister(IndexBinaryHNSWCagra)
class IndexBinaryHash(IndexBinary):
    r"""just uses the b first bits as a hash value"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    invlists = property(_swigfaiss.IndexBinaryHash_invlists_get, _swigfaiss.IndexBinaryHash_invlists_set)
    b = property(_swigfaiss.IndexBinaryHash_b_get, _swigfaiss.IndexBinaryHash_b_set)
    nflip = property(_swigfaiss.IndexBinaryHash_nflip_get, _swigfaiss.IndexBinaryHash_nflip_set)

    def __init__(self, *args):
        _swigfaiss.IndexBinaryHash_swiginit(self, _swigfaiss.new_IndexBinaryHash(*args))

    def reset(self):
        return _swigfaiss.IndexBinaryHash_reset(self)

    def add(self, n, x):
        return _swigfaiss.IndexBinaryHash_add(self, n, x)

    def add_with_ids(self, n, x, xids):
        return _swigfaiss.IndexBinaryHash_add_with_ids(self, n, x, xids)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexBinaryHash_range_search(self, n, x, radius, result, params)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexBinaryHash_search(self, n, x, k, distances, labels, params)

    def display(self):
        return _swigfaiss.IndexBinaryHash_display(self)

    def hashtable_size(self):
        return _swigfaiss.IndexBinaryHash_hashtable_size(self)
    __swig_destroy__ = _swigfaiss.delete_IndexBinaryHash

# Register IndexBinaryHash in _swigfaiss:
_swigfaiss.IndexBinaryHash_swigregister(IndexBinaryHash)
class IndexBinaryHashStats(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nq = property(_swigfaiss.IndexBinaryHashStats_nq_get, _swigfaiss.IndexBinaryHashStats_nq_set)
    n0 = property(_swigfaiss.IndexBinaryHashStats_n0_get, _swigfaiss.IndexBinaryHashStats_n0_set)
    nlist = property(_swigfaiss.IndexBinaryHashStats_nlist_get, _swigfaiss.IndexBinaryHashStats_nlist_set)
    ndis = property(_swigfaiss.IndexBinaryHashStats_ndis_get, _swigfaiss.IndexBinaryHashStats_ndis_set)

    def __init__(self):
        _swigfaiss.IndexBinaryHashStats_swiginit(self, _swigfaiss.new_IndexBinaryHashStats())

    def reset(self):
        return _swigfaiss.IndexBinaryHashStats_reset(self)
    __swig_destroy__ = _swigfaiss.delete_IndexBinaryHashStats

# Register IndexBinaryHashStats in _swigfaiss:
_swigfaiss.IndexBinaryHashStats_swigregister(IndexBinaryHashStats)
class IndexBinaryMultiHash(IndexBinary):
    r"""just uses the b first bits as a hash value"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    storage = property(_swigfaiss.IndexBinaryMultiHash_storage_get, _swigfaiss.IndexBinaryMultiHash_storage_set)
    own_fields = property(_swigfaiss.IndexBinaryMultiHash_own_fields_get, _swigfaiss.IndexBinaryMultiHash_own_fields_set)
    maps = property(_swigfaiss.IndexBinaryMultiHash_maps_get, _swigfaiss.IndexBinaryMultiHash_maps_set)
    nhash = property(_swigfaiss.IndexBinaryMultiHash_nhash_get, _swigfaiss.IndexBinaryMultiHash_nhash_set, doc=r"""nb of hash maps""")
    b = property(_swigfaiss.IndexBinaryMultiHash_b_get, _swigfaiss.IndexBinaryMultiHash_b_set, doc=r"""nb bits per hash map""")
    nflip = property(_swigfaiss.IndexBinaryMultiHash_nflip_get, _swigfaiss.IndexBinaryMultiHash_nflip_set, doc=r"""nb bit flips to use at search time""")

    def __init__(self, *args):
        _swigfaiss.IndexBinaryMultiHash_swiginit(self, _swigfaiss.new_IndexBinaryMultiHash(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexBinaryMultiHash

    def reset(self):
        return _swigfaiss.IndexBinaryMultiHash_reset(self)

    def add(self, n, x):
        return _swigfaiss.IndexBinaryMultiHash_add(self, n, x)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexBinaryMultiHash_range_search(self, n, x, radius, result, params)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexBinaryMultiHash_search(self, n, x, k, distances, labels, params)

    def hashtable_size(self):
        return _swigfaiss.IndexBinaryMultiHash_hashtable_size(self)

# Register IndexBinaryMultiHash in _swigfaiss:
_swigfaiss.IndexBinaryMultiHash_swigregister(IndexBinaryMultiHash)
class ThreadedIndexBase(Index):
    r"""
    A holder of indices in a collection of threads
    The interface to this class itself is not thread safe
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    __swig_destroy__ = _swigfaiss.delete_ThreadedIndexBase

    def addIndex(self, index):
        r"""
        override an index that is managed by ourselves.
        WARNING: once an index is added, it becomes unsafe to touch it from any
        other thread than that on which is managing it, until we are shut
        down. Use runOnIndex to perform work on it instead.
        """
        return _swigfaiss.ThreadedIndexBase_addIndex(self, index)

    def removeIndex(self, index):
        r"""
        Remove an index that is managed by ourselves.
        This will flush all pending work on that index, and then shut
        down its managing thread, and will remove the index.
        """
        return _swigfaiss.ThreadedIndexBase_removeIndex(self, index)

    def runOnIndex(self, *args):
        r"""
        Run a function on all indices, in the thread that the index is
        managed in.
        Function arguments are (index in collection, index pointer)
        """
        return _swigfaiss.ThreadedIndexBase_runOnIndex(self, *args)

    def reset(self):
        r"""
        faiss::Index API
        All indices receive the same call
        """
        return _swigfaiss.ThreadedIndexBase_reset(self)

    def count(self):
        r"""Returns the number of sub-indices"""
        return _swigfaiss.ThreadedIndexBase_count(self)

    def at(self, *args):
        r"""
        *Overload 1:*
        Returns the i-th sub-index

        |

        *Overload 2:*
        Returns the i-th sub-index (const version)
        """
        return _swigfaiss.ThreadedIndexBase_at(self, *args)
    own_indices = property(_swigfaiss.ThreadedIndexBase_own_indices_get, _swigfaiss.ThreadedIndexBase_own_indices_set, doc=r"""Whether or not we are responsible for deleting our contained indices""")

# Register ThreadedIndexBase in _swigfaiss:
_swigfaiss.ThreadedIndexBase_swigregister(ThreadedIndexBase)
class ThreadedIndexBaseBinary(IndexBinary):
    r"""
    A holder of indices in a collection of threads
    The interface to this class itself is not thread safe
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    __swig_destroy__ = _swigfaiss.delete_ThreadedIndexBaseBinary

    def addIndex(self, index):
        r"""
        override an index that is managed by ourselves.
        WARNING: once an index is added, it becomes unsafe to touch it from any
        other thread than that on which is managing it, until we are shut
        down. Use runOnIndex to perform work on it instead.
        """
        return _swigfaiss.ThreadedIndexBaseBinary_addIndex(self, index)

    def removeIndex(self, index):
        r"""
        Remove an index that is managed by ourselves.
        This will flush all pending work on that index, and then shut
        down its managing thread, and will remove the index.
        """
        return _swigfaiss.ThreadedIndexBaseBinary_removeIndex(self, index)

    def runOnIndex(self, *args):
        r"""
        Run a function on all indices, in the thread that the index is
        managed in.
        Function arguments are (index in collection, index pointer)
        """
        return _swigfaiss.ThreadedIndexBaseBinary_runOnIndex(self, *args)

    def reset(self):
        r"""
        faiss::Index API
        All indices receive the same call
        """
        return _swigfaiss.ThreadedIndexBaseBinary_reset(self)

    def count(self):
        r"""Returns the number of sub-indices"""
        return _swigfaiss.ThreadedIndexBaseBinary_count(self)

    def at(self, *args):
        r"""
        *Overload 1:*
        Returns the i-th sub-index

        |

        *Overload 2:*
        Returns the i-th sub-index (const version)
        """
        return _swigfaiss.ThreadedIndexBaseBinary_at(self, *args)
    own_indices = property(_swigfaiss.ThreadedIndexBaseBinary_own_indices_get, _swigfaiss.ThreadedIndexBaseBinary_own_indices_set, doc=r"""Whether or not we are responsible for deleting our contained indices""")

# Register ThreadedIndexBaseBinary in _swigfaiss:
_swigfaiss.ThreadedIndexBaseBinary_swigregister(ThreadedIndexBaseBinary)
class IndexShards(ThreadedIndexBase):
    r"""Index that concatenates the results from several sub-indexes"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        r"""
        *Overload 1:*

        The dimension that all sub-indices must share will be the dimension of
        the first sub-index added

        :type threaded: boolean, optional
        :param threaded:     do we use one thread per sub_index or do
                                queries sequentially?
        :type successive_ids: boolean, optional
        :param successive_ids: should we shift the returned ids by
                                the size of each sub-index or return them
                                as they are?

        |

        *Overload 2:*

        :type threaded: boolean, optional
        :param threaded:     do we use one thread per sub_index or do
                                queries sequentially?
        :type successive_ids: boolean, optional
        :param successive_ids: should we shift the returned ids by
                                the size of each sub-index or return them
                                as they are?

        |

        *Overload 3:*

        :type threaded: boolean, optional
        :param threaded:     do we use one thread per sub_index or do
                                queries sequentially?
        :param successive_ids: should we shift the returned ids by
                                the size of each sub-index or return them
                                as they are?

        |

        *Overload 4:*

        :param threaded:     do we use one thread per sub_index or do
                                queries sequentially?
        :param successive_ids: should we shift the returned ids by
                                the size of each sub-index or return them
                                as they are?

        |

        *Overload 5:*
         int version due to the implicit bool conversion ambiguity of int as
         dimension

        |

        *Overload 6:*
         int version due to the implicit bool conversion ambiguity of int as
         dimension

        |

        *Overload 7:*
         int version due to the implicit bool conversion ambiguity of int as
         dimension
        """
        _swigfaiss.IndexShards_swiginit(self, _swigfaiss.new_IndexShards(*args))

    def add_shard(self, index):
        r"""Alias for addIndex()"""
        return _swigfaiss.IndexShards_add_shard(self, index)

    def remove_shard(self, index):
        r"""Alias for removeIndex()"""
        return _swigfaiss.IndexShards_remove_shard(self, index)

    def add(self, n, x):
        r"""supported only for sub-indices that implement add_with_ids"""
        return _swigfaiss.IndexShards_add(self, n, x)

    def add_with_ids(self, n, x, xids):
        r"""
        Cases (successive_ids, xids):
        - true, non-NULL       ERROR: it makes no sense to pass in ids and
                               request them to be shifted
        - true, NULL           OK: but should be called only once (calls add()
                               on sub-indexes).
        - false, non-NULL      OK: will call add_with_ids with passed in xids
                               distributed evenly over shards
        - false, NULL          OK: will call add_with_ids on each sub-index,
                               starting at ntotal
        """
        return _swigfaiss.IndexShards_add_with_ids(self, n, x, xids)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexShards_search(self, n, x, k, distances, labels, params)

    def train(self, n, x):
        return _swigfaiss.IndexShards_train(self, n, x)
    successive_ids = property(_swigfaiss.IndexShards_successive_ids_get, _swigfaiss.IndexShards_successive_ids_set)

    def syncWithSubIndexes(self):
        r"""
        Synchronize the top-level index (IndexShards) with data in the
        sub-indices
        """
        return _swigfaiss.IndexShards_syncWithSubIndexes(self)
    __swig_destroy__ = _swigfaiss.delete_IndexShards

# Register IndexShards in _swigfaiss:
_swigfaiss.IndexShards_swigregister(IndexShards)
class IndexBinaryShards(ThreadedIndexBaseBinary):
    r"""Index that concatenates the results from several sub-indexes"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        r"""
        *Overload 1:*

        The dimension that all sub-indices must share will be the dimension of
        the first sub-index added

        :type threaded: boolean, optional
        :param threaded:     do we use one thread per sub_index or do
                                queries sequentially?
        :type successive_ids: boolean, optional
        :param successive_ids: should we shift the returned ids by
                                the size of each sub-index or return them
                                as they are?

        |

        *Overload 2:*

        :type threaded: boolean, optional
        :param threaded:     do we use one thread per sub_index or do
                                queries sequentially?
        :type successive_ids: boolean, optional
        :param successive_ids: should we shift the returned ids by
                                the size of each sub-index or return them
                                as they are?

        |

        *Overload 3:*

        :type threaded: boolean, optional
        :param threaded:     do we use one thread per sub_index or do
                                queries sequentially?
        :param successive_ids: should we shift the returned ids by
                                the size of each sub-index or return them
                                as they are?

        |

        *Overload 4:*

        :param threaded:     do we use one thread per sub_index or do
                                queries sequentially?
        :param successive_ids: should we shift the returned ids by
                                the size of each sub-index or return them
                                as they are?

        |

        *Overload 5:*
         int version due to the implicit bool conversion ambiguity of int as
         dimension

        |

        *Overload 6:*
         int version due to the implicit bool conversion ambiguity of int as
         dimension

        |

        *Overload 7:*
         int version due to the implicit bool conversion ambiguity of int as
         dimension
        """
        _swigfaiss.IndexBinaryShards_swiginit(self, _swigfaiss.new_IndexBinaryShards(*args))

    def add_shard(self, index):
        r"""Alias for addIndex()"""
        return _swigfaiss.IndexBinaryShards_add_shard(self, index)

    def remove_shard(self, index):
        r"""Alias for removeIndex()"""
        return _swigfaiss.IndexBinaryShards_remove_shard(self, index)

    def add(self, n, x):
        r"""supported only for sub-indices that implement add_with_ids"""
        return _swigfaiss.IndexBinaryShards_add(self, n, x)

    def add_with_ids(self, n, x, xids):
        r"""
        Cases (successive_ids, xids):
        - true, non-NULL       ERROR: it makes no sense to pass in ids and
                               request them to be shifted
        - true, NULL           OK: but should be called only once (calls add()
                               on sub-indexes).
        - false, non-NULL      OK: will call add_with_ids with passed in xids
                               distributed evenly over shards
        - false, NULL          OK: will call add_with_ids on each sub-index,
                               starting at ntotal
        """
        return _swigfaiss.IndexBinaryShards_add_with_ids(self, n, x, xids)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexBinaryShards_search(self, n, x, k, distances, labels, params)

    def train(self, n, x):
        return _swigfaiss.IndexBinaryShards_train(self, n, x)
    successive_ids = property(_swigfaiss.IndexBinaryShards_successive_ids_get, _swigfaiss.IndexBinaryShards_successive_ids_set)

    def syncWithSubIndexes(self):
        r"""
        Synchronize the top-level index (IndexShards) with data in the
        sub-indices
        """
        return _swigfaiss.IndexBinaryShards_syncWithSubIndexes(self)
    __swig_destroy__ = _swigfaiss.delete_IndexBinaryShards

# Register IndexBinaryShards in _swigfaiss:
_swigfaiss.IndexBinaryShards_swigregister(IndexBinaryShards)
class IndexShardsIVF(IndexShards, Level1Quantizer):
    r"""
    IndexShards with a common coarse quantizer. All the indexes added should be
    IndexIVFInterface indexes so that the search_precomputed can be called.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, quantizer, nlist, threaded=False, successive_ids=True):
        _swigfaiss.IndexShardsIVF_swiginit(self, _swigfaiss.new_IndexShardsIVF(quantizer, nlist, threaded, successive_ids))

    def addIndex(self, index):
        return _swigfaiss.IndexShardsIVF_addIndex(self, index)

    def add_with_ids(self, n, x, xids):
        return _swigfaiss.IndexShardsIVF_add_with_ids(self, n, x, xids)

    def train(self, n, x):
        return _swigfaiss.IndexShardsIVF_train(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexShardsIVF_search(self, n, x, k, distances, labels, params)
    __swig_destroy__ = _swigfaiss.delete_IndexShardsIVF

# Register IndexShardsIVF in _swigfaiss:
_swigfaiss.IndexShardsIVF_swigregister(IndexShardsIVF)
class IndexReplicas(ThreadedIndexBase):
    r"""
    Takes individual faiss::Index instances, and splits queries for
    sending to each Index instance, and joins the results together
    when done.
    Each index is managed by a separate CPU thread.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        r"""
        *Overload 1:*
        The dimension that all sub-indices must share will be the dimension of
        the first sub-index added
        :type threaded: boolean, optional
        :param threaded: do we use one thread per sub-index or do queries
            sequentially?

        |

        *Overload 2:*
        :type d: int
        :param d: the dimension that all sub-indices must share
        :type threaded: boolean, optional
        :param threaded: do we use one thread per sub index or do queries
            sequentially?

        |

        *Overload 3:*
        :type d: int
        :param d: the dimension that all sub-indices must share
        :param threaded: do we use one thread per sub index or do queries
            sequentially?

        |

        *Overload 4:*
        int version due to the implicit bool conversion ambiguity of int as
        dimension

        |

        *Overload 5:*
        int version due to the implicit bool conversion ambiguity of int as
        dimension
        """
        _swigfaiss.IndexReplicas_swiginit(self, _swigfaiss.new_IndexReplicas(*args))

    def add_replica(self, index):
        r"""Alias for addIndex()"""
        return _swigfaiss.IndexReplicas_add_replica(self, index)

    def remove_replica(self, index):
        r"""Alias for removeIndex()"""
        return _swigfaiss.IndexReplicas_remove_replica(self, index)

    def train(self, n, x):
        r"""
        faiss::Index API
        All indices receive the same call
        """
        return _swigfaiss.IndexReplicas_train(self, n, x)

    def add(self, n, x):
        r"""
        faiss::Index API
        All indices receive the same call
        """
        return _swigfaiss.IndexReplicas_add(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        r"""
        faiss::Index API
        Query is partitioned into a slice for each sub-index
        split by ceil(n / #indices) for our sub-indices
        """
        return _swigfaiss.IndexReplicas_search(self, n, x, k, distances, labels, params)

    def reconstruct(self, arg2, v):
        r"""reconstructs from the first index"""
        return _swigfaiss.IndexReplicas_reconstruct(self, arg2, v)

    def syncWithSubIndexes(self):
        r"""
        Synchronize the top-level index (IndexShards) with data in the
        sub-indices
        """
        return _swigfaiss.IndexReplicas_syncWithSubIndexes(self)
    __swig_destroy__ = _swigfaiss.delete_IndexReplicas

# Register IndexReplicas in _swigfaiss:
_swigfaiss.IndexReplicas_swigregister(IndexReplicas)
class IndexBinaryReplicas(ThreadedIndexBaseBinary):
    r"""
    Takes individual faiss::Index instances, and splits queries for
    sending to each Index instance, and joins the results together
    when done.
    Each index is managed by a separate CPU thread.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        r"""
        *Overload 1:*
        The dimension that all sub-indices must share will be the dimension of
        the first sub-index added
        :type threaded: boolean, optional
        :param threaded: do we use one thread per sub-index or do queries
            sequentially?

        |

        *Overload 2:*
        :type d: int
        :param d: the dimension that all sub-indices must share
        :type threaded: boolean, optional
        :param threaded: do we use one thread per sub index or do queries
            sequentially?

        |

        *Overload 3:*
        :type d: int
        :param d: the dimension that all sub-indices must share
        :param threaded: do we use one thread per sub index or do queries
            sequentially?

        |

        *Overload 4:*
        int version due to the implicit bool conversion ambiguity of int as
        dimension

        |

        *Overload 5:*
        int version due to the implicit bool conversion ambiguity of int as
        dimension
        """
        _swigfaiss.IndexBinaryReplicas_swiginit(self, _swigfaiss.new_IndexBinaryReplicas(*args))

    def add_replica(self, index):
        r"""Alias for addIndex()"""
        return _swigfaiss.IndexBinaryReplicas_add_replica(self, index)

    def remove_replica(self, index):
        r"""Alias for removeIndex()"""
        return _swigfaiss.IndexBinaryReplicas_remove_replica(self, index)

    def train(self, n, x):
        r"""
        faiss::Index API
        All indices receive the same call
        """
        return _swigfaiss.IndexBinaryReplicas_train(self, n, x)

    def add(self, n, x):
        r"""
        faiss::Index API
        All indices receive the same call
        """
        return _swigfaiss.IndexBinaryReplicas_add(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        r"""
        faiss::Index API
        Query is partitioned into a slice for each sub-index
        split by ceil(n / #indices) for our sub-indices
        """
        return _swigfaiss.IndexBinaryReplicas_search(self, n, x, k, distances, labels, params)

    def reconstruct(self, arg2, v):
        r"""reconstructs from the first index"""
        return _swigfaiss.IndexBinaryReplicas_reconstruct(self, arg2, v)

    def syncWithSubIndexes(self):
        r"""
        Synchronize the top-level index (IndexShards) with data in the
        sub-indices
        """
        return _swigfaiss.IndexBinaryReplicas_syncWithSubIndexes(self)
    __swig_destroy__ = _swigfaiss.delete_IndexBinaryReplicas

# Register IndexBinaryReplicas in _swigfaiss:
_swigfaiss.IndexBinaryReplicas_swigregister(IndexBinaryReplicas)
class IndexSplitVectors(Index):
    r"""
     splits input vectors in segments and assigns each segment to a sub-index
    used to distribute a MultiIndexQuantizer
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    own_fields = property(_swigfaiss.IndexSplitVectors_own_fields_get, _swigfaiss.IndexSplitVectors_own_fields_set)
    threaded = property(_swigfaiss.IndexSplitVectors_threaded_get, _swigfaiss.IndexSplitVectors_threaded_set)
    sub_indexes = property(_swigfaiss.IndexSplitVectors_sub_indexes_get, _swigfaiss.IndexSplitVectors_sub_indexes_set)
    sum_d = property(_swigfaiss.IndexSplitVectors_sum_d_get, _swigfaiss.IndexSplitVectors_sum_d_set)

    def __init__(self, d, threaded=False):
        r"""sum of dimensions seen so far"""
        _swigfaiss.IndexSplitVectors_swiginit(self, _swigfaiss.new_IndexSplitVectors(d, threaded))

    def add_sub_index(self, arg2):
        return _swigfaiss.IndexSplitVectors_add_sub_index(self, arg2)

    def sync_with_sub_indexes(self):
        return _swigfaiss.IndexSplitVectors_sync_with_sub_indexes(self)

    def add(self, n, x):
        return _swigfaiss.IndexSplitVectors_add(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexSplitVectors_search(self, n, x, k, distances, labels, params)

    def train(self, n, x):
        return _swigfaiss.IndexSplitVectors_train(self, n, x)

    def reset(self):
        return _swigfaiss.IndexSplitVectors_reset(self)
    __swig_destroy__ = _swigfaiss.delete_IndexSplitVectors

# Register IndexSplitVectors in _swigfaiss:
_swigfaiss.IndexSplitVectors_swigregister(IndexSplitVectors)
class IndexRandom(Index):
    r"""
     index that returns random results.
    used mainly for time benchmarks
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    seed = property(_swigfaiss.IndexRandom_seed_get, _swigfaiss.IndexRandom_seed_set)

    def __init__(self, *args):
        _swigfaiss.IndexRandom_swiginit(self, _swigfaiss.new_IndexRandom(*args))

    def add(self, n, x):
        return _swigfaiss.IndexRandom_add(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexRandom_search(self, n, x, k, distances, labels, params)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexRandom_reconstruct(self, key, recons)

    def reset(self):
        return _swigfaiss.IndexRandom_reset(self)
    __swig_destroy__ = _swigfaiss.delete_IndexRandom

# Register IndexRandom in _swigfaiss:
_swigfaiss.IndexRandom_swigregister(IndexRandom)
class IndexRowwiseMinMaxBase(Index):
    r"""
     Index wrapper that performs rowwise normalization to [0,1], preserving
     the coefficients. This is a vector codec index only.

     Basically, this index performs a rowwise scaling to [0,1] of every row
     in an input dataset before calling subindex::train() and
     subindex::sa_encode(). sa_encode() call stores the scaling coefficients
      (scaler and minv) in the very beginning of every output code. The format:
         [scaler][minv][subindex::sa_encode() output]
     The de-scaling in sa_decode() is done using:
         output_rescaled = scaler * output + minv

     An additional ::train_inplace() function is provided in order to do
     an inplace scaling before calling subindex::train() and, thus, avoiding
     the cloning of the input dataset, but modifying the input dataset because
     of the scaling and the scaling back. It is up to user to call
     this function instead of ::train()

     Derived classes provide different data types for scaling coefficients.
     Currently, versions with fp16 and fp32 scaling coefficients are available.
    fp16 version adds 4 extra bytes per encoded vector
    fp32 version adds 8 extra bytes per encoded vector
     Provides base functions for rowwise normalizing indices.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    index = property(_swigfaiss.IndexRowwiseMinMaxBase_index_get, _swigfaiss.IndexRowwiseMinMaxBase_index_set, doc=r"""sub-index""")
    own_fields = property(_swigfaiss.IndexRowwiseMinMaxBase_own_fields_get, _swigfaiss.IndexRowwiseMinMaxBase_own_fields_set, doc=r"""whether the subindex needs to be freed in the destructor.""")
    __swig_destroy__ = _swigfaiss.delete_IndexRowwiseMinMaxBase

    def add(self, n, x):
        return _swigfaiss.IndexRowwiseMinMaxBase_add(self, n, x)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexRowwiseMinMaxBase_search(self, n, x, k, distances, labels, params)

    def reset(self):
        return _swigfaiss.IndexRowwiseMinMaxBase_reset(self)

    def train_inplace(self, n, x):
        return _swigfaiss.IndexRowwiseMinMaxBase_train_inplace(self, n, x)

# Register IndexRowwiseMinMaxBase in _swigfaiss:
_swigfaiss.IndexRowwiseMinMaxBase_swigregister(IndexRowwiseMinMaxBase)
class IndexRowwiseMinMaxFP16(IndexRowwiseMinMaxBase):
    r"""Stores scaling coefficients as fp16 values."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexRowwiseMinMaxFP16_swiginit(self, _swigfaiss.new_IndexRowwiseMinMaxFP16(*args))

    def train(self, n, x):
        return _swigfaiss.IndexRowwiseMinMaxFP16_train(self, n, x)

    def train_inplace(self, n, x):
        return _swigfaiss.IndexRowwiseMinMaxFP16_train_inplace(self, n, x)

    def sa_code_size(self):
        return _swigfaiss.IndexRowwiseMinMaxFP16_sa_code_size(self)

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.IndexRowwiseMinMaxFP16_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexRowwiseMinMaxFP16_sa_decode(self, n, bytes, x)
    __swig_destroy__ = _swigfaiss.delete_IndexRowwiseMinMaxFP16

# Register IndexRowwiseMinMaxFP16 in _swigfaiss:
_swigfaiss.IndexRowwiseMinMaxFP16_swigregister(IndexRowwiseMinMaxFP16)
class IndexRowwiseMinMax(IndexRowwiseMinMaxBase):
    r"""Stores scaling coefficients as fp32 values."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, *args):
        _swigfaiss.IndexRowwiseMinMax_swiginit(self, _swigfaiss.new_IndexRowwiseMinMax(*args))

    def train(self, n, x):
        return _swigfaiss.IndexRowwiseMinMax_train(self, n, x)

    def train_inplace(self, n, x):
        return _swigfaiss.IndexRowwiseMinMax_train_inplace(self, n, x)

    def sa_code_size(self):
        return _swigfaiss.IndexRowwiseMinMax_sa_code_size(self)

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.IndexRowwiseMinMax_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexRowwiseMinMax_sa_decode(self, n, bytes, x)
    __swig_destroy__ = _swigfaiss.delete_IndexRowwiseMinMax

# Register IndexRowwiseMinMax in _swigfaiss:
_swigfaiss.IndexRowwiseMinMax_swigregister(IndexRowwiseMinMax)
class Linear(object):
    r"""minimal translation of nn.Linear"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    in_features = property(_swigfaiss.Linear_in_features_get, _swigfaiss.Linear_in_features_set)
    out_features = property(_swigfaiss.Linear_out_features_get, _swigfaiss.Linear_out_features_set)
    weight = property(_swigfaiss.Linear_weight_get, _swigfaiss.Linear_weight_set)
    bias = property(_swigfaiss.Linear_bias_get, _swigfaiss.Linear_bias_set)

    def __init__(self, in_features, out_features, bias=True):
        _swigfaiss.Linear_swiginit(self, _swigfaiss.new_Linear(in_features, out_features, bias))

    def __call__(self, x):
        return _swigfaiss.Linear___call__(self, x)
    __swig_destroy__ = _swigfaiss.delete_Linear

# Register Linear in _swigfaiss:
_swigfaiss.Linear_swigregister(Linear)
class Embedding(object):
    r"""minimal translation of nn.Embedding"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    num_embeddings = property(_swigfaiss.Embedding_num_embeddings_get, _swigfaiss.Embedding_num_embeddings_set)
    embedding_dim = property(_swigfaiss.Embedding_embedding_dim_get, _swigfaiss.Embedding_embedding_dim_set)
    weight = property(_swigfaiss.Embedding_weight_get, _swigfaiss.Embedding_weight_set)

    def __init__(self, num_embeddings, embedding_dim):
        _swigfaiss.Embedding_swiginit(self, _swigfaiss.new_Embedding(num_embeddings, embedding_dim))

    def __call__(self, arg2):
        return _swigfaiss.Embedding___call__(self, arg2)

    def data(self, *args):
        return _swigfaiss.Embedding_data(self, *args)
    __swig_destroy__ = _swigfaiss.delete_Embedding

# Register Embedding in _swigfaiss:
_swigfaiss.Embedding_swigregister(Embedding)
class FFN(object):
    r"""
    Feed forward layer that expands to a hidden dimension, applies a ReLU non
    linearity and maps back to the original dimension
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    linear1 = property(_swigfaiss.FFN_linear1_get, _swigfaiss.FFN_linear1_set)
    linear2 = property(_swigfaiss.FFN_linear2_get, _swigfaiss.FFN_linear2_set)

    def __init__(self, d, h):
        _swigfaiss.FFN_swiginit(self, _swigfaiss.new_FFN(d, h))

    def __call__(self, x):
        return _swigfaiss.FFN___call__(self, x)
    __swig_destroy__ = _swigfaiss.delete_FFN

# Register FFN in _swigfaiss:
_swigfaiss.FFN_swigregister(FFN)
class QINCoStep(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    d = property(_swigfaiss.QINCoStep_d_get, _swigfaiss.QINCoStep_d_set, doc=r"""d: input dim, K: codebook size, L: # of residual blocks, h: hidden dim""")
    K = property(_swigfaiss.QINCoStep_K_get, _swigfaiss.QINCoStep_K_set)
    L = property(_swigfaiss.QINCoStep_L_get, _swigfaiss.QINCoStep_L_set)
    h = property(_swigfaiss.QINCoStep_h_get, _swigfaiss.QINCoStep_h_set)

    def __init__(self, d, K, L, h):
        _swigfaiss.QINCoStep_swiginit(self, _swigfaiss.new_QINCoStep(d, K, L, h))
    codebook = property(_swigfaiss.QINCoStep_codebook_get, _swigfaiss.QINCoStep_codebook_set)
    MLPconcat = property(_swigfaiss.QINCoStep_MLPconcat_get, _swigfaiss.QINCoStep_MLPconcat_set)
    residual_blocks = property(_swigfaiss.QINCoStep_residual_blocks_get, _swigfaiss.QINCoStep_residual_blocks_set)

    def get_residual_block(self, i):
        return _swigfaiss.QINCoStep_get_residual_block(self, i)

    def encode(self, xhat, x, residuals=None):
        r"""
         encode a set of vectors x with initial estimate xhat. Optionally return
        the delta to be added to xhat to form the new xhat
        """
        return _swigfaiss.QINCoStep_encode(self, xhat, x, residuals)

    def decode(self, xhat, codes):
        return _swigfaiss.QINCoStep_decode(self, xhat, codes)
    __swig_destroy__ = _swigfaiss.delete_QINCoStep

# Register QINCoStep in _swigfaiss:
_swigfaiss.QINCoStep_swigregister(QINCoStep)
class NeuralNetCodec(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    d = property(_swigfaiss.NeuralNetCodec_d_get, _swigfaiss.NeuralNetCodec_d_set)
    M = property(_swigfaiss.NeuralNetCodec_M_get, _swigfaiss.NeuralNetCodec_M_set)

    def decode(self, codes):
        return _swigfaiss.NeuralNetCodec_decode(self, codes)

    def encode(self, x):
        return _swigfaiss.NeuralNetCodec_encode(self, x)
    __swig_destroy__ = _swigfaiss.delete_NeuralNetCodec

# Register NeuralNetCodec in _swigfaiss:
_swigfaiss.NeuralNetCodec_swigregister(NeuralNetCodec)
class QINCo(NeuralNetCodec):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    K = property(_swigfaiss.QINCo_K_get, _swigfaiss.QINCo_K_set)
    L = property(_swigfaiss.QINCo_L_get, _swigfaiss.QINCo_L_set)
    h = property(_swigfaiss.QINCo_h_get, _swigfaiss.QINCo_h_set)
    codebook0 = property(_swigfaiss.QINCo_codebook0_get, _swigfaiss.QINCo_codebook0_set)
    steps = property(_swigfaiss.QINCo_steps_get, _swigfaiss.QINCo_steps_set)

    def __init__(self, d, K, L, M, h):
        _swigfaiss.QINCo_swiginit(self, _swigfaiss.new_QINCo(d, K, L, M, h))

    def get_step(self, i):
        return _swigfaiss.QINCo_get_step(self, i)

    def decode(self, codes):
        return _swigfaiss.QINCo_decode(self, codes)

    def encode(self, x):
        return _swigfaiss.QINCo_encode(self, x)
    __swig_destroy__ = _swigfaiss.delete_QINCo

# Register QINCo in _swigfaiss:
_swigfaiss.QINCo_swigregister(QINCo)
class Tensor2D(object):
    r"""Implements a few neural net layers, mainly to support QINCo"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    shape = property(_swigfaiss.Tensor2D_shape_get, _swigfaiss.Tensor2D_shape_set)
    v = property(_swigfaiss.Tensor2D_v_get, _swigfaiss.Tensor2D_v_set)

    def __init__(self, n0, n1, data=None):
        _swigfaiss.Tensor2D_swiginit(self, _swigfaiss.new_Tensor2D(n0, n1, data))

    def __iadd__(self, arg2):
        return _swigfaiss.Tensor2D___iadd__(self, arg2)

    def column(self, j):
        r"""get column #j as a 1-column Tensor2D"""
        return _swigfaiss.Tensor2D_column(self, j)

    def numel(self):
        return _swigfaiss.Tensor2D_numel(self)

    def data(self, *args):
        return _swigfaiss.Tensor2D_data(self, *args)
    __swig_destroy__ = _swigfaiss.delete_Tensor2D

# Register Tensor2D in _swigfaiss:
_swigfaiss.Tensor2D_swigregister(Tensor2D)
class Int32Tensor2D(object):
    r"""Implements a few neural net layers, mainly to support QINCo"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    shape = property(_swigfaiss.Int32Tensor2D_shape_get, _swigfaiss.Int32Tensor2D_shape_set)
    v = property(_swigfaiss.Int32Tensor2D_v_get, _swigfaiss.Int32Tensor2D_v_set)

    def __init__(self, n0, n1, data=None):
        _swigfaiss.Int32Tensor2D_swiginit(self, _swigfaiss.new_Int32Tensor2D(n0, n1, data))

    def __iadd__(self, arg2):
        return _swigfaiss.Int32Tensor2D___iadd__(self, arg2)

    def column(self, j):
        r"""get column #j as a 1-column Tensor2D"""
        return _swigfaiss.Int32Tensor2D_column(self, j)

    def numel(self):
        return _swigfaiss.Int32Tensor2D_numel(self)

    def data(self, *args):
        return _swigfaiss.Int32Tensor2D_data(self, *args)
    __swig_destroy__ = _swigfaiss.delete_Int32Tensor2D

# Register Int32Tensor2D in _swigfaiss:
_swigfaiss.Int32Tensor2D_swigregister(Int32Tensor2D)
class IndexNeuralNetCodec(IndexFlatCodes):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    net = property(_swigfaiss.IndexNeuralNetCodec_net_get, _swigfaiss.IndexNeuralNetCodec_net_set)
    M = property(_swigfaiss.IndexNeuralNetCodec_M_get, _swigfaiss.IndexNeuralNetCodec_M_set)
    nbits = property(_swigfaiss.IndexNeuralNetCodec_nbits_get, _swigfaiss.IndexNeuralNetCodec_nbits_set)

    def __init__(self, *args):
        _swigfaiss.IndexNeuralNetCodec_swiginit(self, _swigfaiss.new_IndexNeuralNetCodec(*args))

    def train(self, n, x):
        return _swigfaiss.IndexNeuralNetCodec_train(self, n, x)

    def sa_encode(self, n, x, codes):
        return _swigfaiss.IndexNeuralNetCodec_sa_encode(self, n, x, codes)

    def sa_decode(self, n, codes, x):
        return _swigfaiss.IndexNeuralNetCodec_sa_decode(self, n, codes, x)
    __swig_destroy__ = _swigfaiss.delete_IndexNeuralNetCodec

# Register IndexNeuralNetCodec in _swigfaiss:
_swigfaiss.IndexNeuralNetCodec_swigregister(IndexNeuralNetCodec)
class IndexQINCo(IndexNeuralNetCodec):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    qinco = property(_swigfaiss.IndexQINCo_qinco_get, _swigfaiss.IndexQINCo_qinco_set)

    def __init__(self, *args):
        _swigfaiss.IndexQINCo_swiginit(self, _swigfaiss.new_IndexQINCo(*args))
    __swig_destroy__ = _swigfaiss.delete_IndexQINCo

# Register IndexQINCo in _swigfaiss:
_swigfaiss.IndexQINCo_swigregister(IndexQINCo)
class RaBitQuantizer(Quantizer):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    centroid = property(_swigfaiss.RaBitQuantizer_centroid_get, _swigfaiss.RaBitQuantizer_centroid_set)
    metric_type = property(_swigfaiss.RaBitQuantizer_metric_type_get, _swigfaiss.RaBitQuantizer_metric_type_set)
    nb_bits = property(_swigfaiss.RaBitQuantizer_nb_bits_get, _swigfaiss.RaBitQuantizer_nb_bits_set)

    def __init__(self, *args):
        _swigfaiss.RaBitQuantizer_swiginit(self, _swigfaiss.new_RaBitQuantizer(*args))

    def compute_code_size(self, d, num_bits):
        return _swigfaiss.RaBitQuantizer_compute_code_size(self, d, num_bits)

    def train(self, n, x):
        return _swigfaiss.RaBitQuantizer_train(self, n, x)

    def compute_codes(self, x, codes, n):
        return _swigfaiss.RaBitQuantizer_compute_codes(self, x, codes, n)

    def compute_codes_core(self, x, codes, n, centroid_in):
        return _swigfaiss.RaBitQuantizer_compute_codes_core(self, x, codes, n, centroid_in)

    def decode(self, codes, x, n):
        return _swigfaiss.RaBitQuantizer_decode(self, codes, x, n)

    def decode_core(self, codes, x, n, centroid_in):
        return _swigfaiss.RaBitQuantizer_decode_core(self, codes, x, n, centroid_in)

    def get_distance_computer(self, qb=0, centroid=None, centered=False):
        return _swigfaiss.RaBitQuantizer_get_distance_computer(self, qb, centroid, centered)
    __swig_destroy__ = _swigfaiss.delete_RaBitQuantizer

# Register RaBitQuantizer in _swigfaiss:
_swigfaiss.RaBitQuantizer_swigregister(RaBitQuantizer)
class RaBitQDistanceComputer(FlatCodesDistanceComputer):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    d = property(_swigfaiss.RaBitQDistanceComputer_d_get, _swigfaiss.RaBitQDistanceComputer_d_set)
    centroid = property(_swigfaiss.RaBitQDistanceComputer_centroid_get, _swigfaiss.RaBitQDistanceComputer_centroid_set)
    metric_type = property(_swigfaiss.RaBitQDistanceComputer_metric_type_get, _swigfaiss.RaBitQDistanceComputer_metric_type_set)
    nb_bits = property(_swigfaiss.RaBitQDistanceComputer_nb_bits_get, _swigfaiss.RaBitQDistanceComputer_nb_bits_set)
    g_error = property(_swigfaiss.RaBitQDistanceComputer_g_error_get, _swigfaiss.RaBitQDistanceComputer_g_error_set)

    def symmetric_dis(self, arg2, arg3):
        return _swigfaiss.RaBitQDistanceComputer_symmetric_dis(self, arg2, arg3)

    def distance_to_code_1bit(self, code):
        return _swigfaiss.RaBitQDistanceComputer_distance_to_code_1bit(self, code)

    def distance_to_code_full(self, code):
        return _swigfaiss.RaBitQDistanceComputer_distance_to_code_full(self, code)

    def distance_to_code(self, code):
        return _swigfaiss.RaBitQDistanceComputer_distance_to_code(self, code)
    __swig_destroy__ = _swigfaiss.delete_RaBitQDistanceComputer

# Register RaBitQDistanceComputer in _swigfaiss:
_swigfaiss.RaBitQDistanceComputer_swigregister(RaBitQDistanceComputer)
class SignBitFactors(object):
    r"""
     Base factors computed per database vector for RaBitQ distance computation.
    Used by both 1-bit and multi-bit RaBitQ variants.
    These can be stored either embedded in codes (IndexRaBitQ) or separately
    (IndexRaBitQFastScan).

    For 1-bit mode only - contains the minimal factors needed for distance
    estimation using just sign bits.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    or_minus_c_l2sqr = property(_swigfaiss.SignBitFactors_or_minus_c_l2sqr_get, _swigfaiss.SignBitFactors_or_minus_c_l2sqr_set)
    dp_multiplier = property(_swigfaiss.SignBitFactors_dp_multiplier_get, _swigfaiss.SignBitFactors_dp_multiplier_set)

    def __init__(self):
        _swigfaiss.SignBitFactors_swiginit(self, _swigfaiss.new_SignBitFactors())
    __swig_destroy__ = _swigfaiss.delete_SignBitFactors

# Register SignBitFactors in _swigfaiss:
_swigfaiss.SignBitFactors_swigregister(SignBitFactors)
class SignBitFactorsWithError(SignBitFactors):
    r"""
     Extended factors for multi-bit RaBitQ (nb_bits > 1).
    Includes error bound for lower bound computation in two-stage search.
    Inherits base factors to maintain layout compatibility.

    Used in multi-bit mode - the error bound enables quick filtering of
    unlikely candidates in the first stage of two-stage search.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    f_error = property(_swigfaiss.SignBitFactorsWithError_f_error_get, _swigfaiss.SignBitFactorsWithError_f_error_set)

    def __init__(self):
        _swigfaiss.SignBitFactorsWithError_swiginit(self, _swigfaiss.new_SignBitFactorsWithError())
    __swig_destroy__ = _swigfaiss.delete_SignBitFactorsWithError

# Register SignBitFactorsWithError in _swigfaiss:
_swigfaiss.SignBitFactorsWithError_swigregister(SignBitFactorsWithError)
class ExtraBitsFactors(object):
    r"""
     Additional factors for multi-bit RaBitQ (nb_bits > 1).
    Used to store normalization and scaling factors for the refinement bits
    that encode additional precision beyond the sign bit.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    f_add_ex = property(_swigfaiss.ExtraBitsFactors_f_add_ex_get, _swigfaiss.ExtraBitsFactors_f_add_ex_set)
    f_rescale_ex = property(_swigfaiss.ExtraBitsFactors_f_rescale_ex_get, _swigfaiss.ExtraBitsFactors_f_rescale_ex_set)

    def __init__(self):
        _swigfaiss.ExtraBitsFactors_swiginit(self, _swigfaiss.new_ExtraBitsFactors())
    __swig_destroy__ = _swigfaiss.delete_ExtraBitsFactors

# Register ExtraBitsFactors in _swigfaiss:
_swigfaiss.ExtraBitsFactors_swigregister(ExtraBitsFactors)
class QueryFactorsData(object):
    r"""
     Query-specific factors computed during search for RaBitQ distance
    computation. Used by both IndexRaBitQ and IndexRaBitQFastScan
    implementations.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    c1 = property(_swigfaiss.QueryFactorsData_c1_get, _swigfaiss.QueryFactorsData_c1_set)
    c2 = property(_swigfaiss.QueryFactorsData_c2_get, _swigfaiss.QueryFactorsData_c2_set)
    c34 = property(_swigfaiss.QueryFactorsData_c34_get, _swigfaiss.QueryFactorsData_c34_set)
    qr_to_c_L2sqr = property(_swigfaiss.QueryFactorsData_qr_to_c_L2sqr_get, _swigfaiss.QueryFactorsData_qr_to_c_L2sqr_set)
    qr_norm_L2sqr = property(_swigfaiss.QueryFactorsData_qr_norm_L2sqr_get, _swigfaiss.QueryFactorsData_qr_norm_L2sqr_set)
    q_dot_c = property(_swigfaiss.QueryFactorsData_q_dot_c_get, _swigfaiss.QueryFactorsData_q_dot_c_set)
    int_dot_scale = property(_swigfaiss.QueryFactorsData_int_dot_scale_get, _swigfaiss.QueryFactorsData_int_dot_scale_set)
    g_error = property(_swigfaiss.QueryFactorsData_g_error_get, _swigfaiss.QueryFactorsData_g_error_set)
    rotated_q = property(_swigfaiss.QueryFactorsData_rotated_q_get, _swigfaiss.QueryFactorsData_rotated_q_set)

    def __init__(self):
        _swigfaiss.QueryFactorsData_swiginit(self, _swigfaiss.new_QueryFactorsData())
    __swig_destroy__ = _swigfaiss.delete_QueryFactorsData

# Register QueryFactorsData in _swigfaiss:
_swigfaiss.QueryFactorsData_swigregister(QueryFactorsData)

def compute_vector_factors(x, d, centroid, metric_type, compute_error=True):
    r"""
     Compute factors for a single database vector using RaBitQ algorithm.
    This function consolidates the mathematical logic that was duplicated
    between IndexRaBitQ and IndexRaBitQFastScan.

    :type x: float
    :param x:             input vector (d dimensions)
    :type d: int
    :param d:             dimensionality
    :type centroid: float
    :param centroid:      database centroid (nullptr if not used)
    :type metric_type: int
    :param metric_type:   distance metric (L2 or Inner Product)
    :type compute_error: boolean, optional
    :param compute_error: whether to compute f_error (false for 1-bit mode)
    :rtype: :py:class:`SignBitFactorsWithError`
    :return: computed factors for distance computation
    """
    return _swigfaiss.compute_vector_factors(x, d, centroid, metric_type, compute_error)

def compute_vector_intermediate_values(x, d, centroid, norm_L2sqr, or_L2sqr, dp_oO):
    r"""
     Compute intermediate values needed for vector factor computation.
    Separated out to allow different bit packing strategies while sharing
    the core mathematical computation.

    :type x: float
    :param x:             input vector (d dimensions)
    :type d: int
    :param d:             dimensionality
    :type centroid: float
    :param centroid:      database centroid (nullptr if not used)
    :type norm_L2sqr: float
    :param norm_L2sqr:    output: ||or - c||^2
    :type or_L2sqr: float
    :param or_L2sqr:      output: ||or||^2
    :type dp_oO: float
    :param dp_oO:         output: sum of |or_i - c_i| (absolute deviations)
    """
    return _swigfaiss.compute_vector_intermediate_values(x, d, centroid, norm_L2sqr, or_L2sqr, dp_oO)

def compute_factors_from_intermediates(norm_L2sqr, or_L2sqr, dp_oO, d, metric_type, compute_error=True):
    r"""
     Compute final factors from intermediate values.
    :type norm_L2sqr: float
    :param norm_L2sqr:    ||or - c||^2
    :type or_L2sqr: float
    :param or_L2sqr:      ||or||^2
    :type dp_oO: float
    :param dp_oO:         sum of |or_i - c_i|
    :type d: int
    :param d:             dimensionality
    :type metric_type: int
    :param metric_type:   distance metric
    :type compute_error: boolean, optional
    :param compute_error: whether to compute f_error (false for 1-bit mode)
    :rtype: :py:class:`SignBitFactorsWithError`
    :return: computed factors
    """
    return _swigfaiss.compute_factors_from_intermediates(norm_L2sqr, or_L2sqr, dp_oO, d, metric_type, compute_error)

def compute_query_factors(query, d, centroid, qb, centered, metric_type, rotated_q, rotated_qq):
    r"""
     Compute query factors for RaBitQ distance computation.
    This consolidates the query processing logic shared between implementations.

    :type query: float
    :param query:         query vector (d dimensions)
    :type d: int
    :param d:             dimensionality
    :type centroid: float
    :param centroid:      database centroid (nullptr if not used)
    :type qb: uint8_t
    :param qb:            number of quantization bits (1-8)
    :type centered: boolean
    :param centered:      whether to use centered quantization
    :type metric_type: int
    :param metric_type:   distance metric
    :type rotated_q: std::vector< float >
    :param rotated_q:     output: query - centroid
    :type rotated_qq: std::vector< uint8_t >
    :param rotated_qq:    output: quantized query values
    :rtype: :py:class:`QueryFactorsData`
    :return: computed query factors
    """
    return _swigfaiss.compute_query_factors(query, d, centroid, qb, centered, metric_type, rotated_q, rotated_qq)

def extract_bit_standard(code, bit_index):
    r"""
     Extract bit value from RaBitQ code in standard format.
    Used by IndexRaBitQ which stores bits sequentially.

    :type code: uint8_t
    :param code:          RaBitQ code data
    :type bit_index: int
    :param bit_index:     which bit to extract (0 to d-1)
    :rtype: boolean
    :return: bit value (true/false)
    """
    return _swigfaiss.extract_bit_standard(code, bit_index)

def extract_bit_fastscan(code, bit_index):
    r"""
     Extract bit value from FastScan code format.
    Used by IndexRaBitQFastScan which packs bits into 4-bit sub-quantizers.

    :type code: uint8_t
    :param code:          FastScan code data
    :type bit_index: int
    :param bit_index:     which bit to extract (0 to d-1)
    :rtype: boolean
    :return: bit value (true/false)
    """
    return _swigfaiss.extract_bit_fastscan(code, bit_index)

def set_bit_standard(code, bit_index):
    r"""
     Set bit value in standard RaBitQ code format.
    :type code: uint8_t
    :param code:          RaBitQ code data to modify
    :type bit_index: int
    :param bit_index:     which bit to set (0 to d-1)
    """
    return _swigfaiss.set_bit_standard(code, bit_index)

def set_bit_fastscan(code, bit_index):
    r"""
     Set bit value in FastScan code format.
    :type code: uint8_t
    :param code:          FastScan code data to modify
    :type bit_index: int
    :param bit_index:     which bit to set (0 to d-1)
    """
    return _swigfaiss.set_bit_fastscan(code, bit_index)

def compute_1bit_adjusted_distance(normalized_distance, db_factors, query_factors, centered, qb, d):
    r"""
     Compute adjusted 1-bit distance from normalized LUT distance.
    This is the core distance formula shared by all RaBitQ handlers.

    :type normalized_distance: float
    :param normalized_distance:  Distance from SIMD LUT lookup (after
        normalization)
    :type db_factors: :py:class:`SignBitFactors`
    :param db_factors:          Database vector factors (SignBitFactors or
        SignBitFactorsWithError)
    :type query_factors: :py:class:`QueryFactorsData`
    :param query_factors:       Query factors computed during search
    :type centered: boolean
    :param centered:            Whether centered quantization is used
    :type qb: int
    :param qb:                  Number of quantization bits
    :type d: int
    :param d:                   Dimensionality
    :rtype: float
    :return: Adjusted distance value
    """
    return _swigfaiss.compute_1bit_adjusted_distance(normalized_distance, db_factors, query_factors, centered, qb, d)

def should_refine_candidate(est_distance, f_error, g_error, threshold, is_similarity):
    r"""
     Determine whether a candidate should be refined in two-stage search.
    Consolidates the filtering logic for both L2 and IP metrics.

    For L2 (min-heap): uses lower_bound = est_distance - error_adjustment
      - Skip if lower_bound >= threshold (can't beat current worst)
    For IP (max-heap): uses upper_bound = est_distance + error_adjustment
      - Skip if upper_bound <= threshold (can't beat current best)

    :type est_distance: float
    :param est_distance:     Estimated 1-bit distance
    :type f_error: float
    :param f_error:          Database vector error factor
    :type g_error: float
    :param g_error:          Query vector error factor
    :type threshold: float
    :param threshold:        Current heap threshold (worst result in heap)
    :type is_similarity: boolean
    :param is_similarity:    True for IP metric (max-heap), false for L2
        (min-heap)
    :rtype: boolean
    :return: True if candidate should be refined with full
        multi-bit distance
    """
    return _swigfaiss.should_refine_candidate(est_distance, f_error, g_error, threshold, is_similarity)

def extract_code_inline(ex_code, index, ex_bits):
    r"""
     Extract multi-bit code on-the-fly from packed ex-bit codes.
    This inline function extracts a single code value without unpacking the
    entire array, enabling efficient on-the-fly decoding during distance
    computation.

    :type ex_code: uint8_t
    :param ex_code:       packed ex-bit codes
    :type index: int
    :param index:         which code to extract (0 to d-1)
    :type ex_bits: int
    :param ex_bits:       number of bits per code (1-8)
    :rtype: int
    :return: extracted code value in range [0, 2^ex_bits - 1]
    """
    return _swigfaiss.extract_code_inline(ex_code, index, ex_bits)

def compute_full_multibit_distance(sign_bits, ex_code, ex_fac, rotated_q, qr_base, d, ex_bits, metric_type):
    r"""
     Compute full multi-bit distance from sign bits and ex-bit codes.
    This is the core distance computation shared by RaBitQFastScan handlers.

    The multi-bit distance combines the sign bit (1-bit) with additional
    magnitude bits (ex_bits) to compute a more accurate distance estimate.
    Uses SIMD-optimized bit-plane decomposition (AVX2+BMI2) for ex_bits 1-7,
    with scalar fallback for non-x86 or non-BMI2 platforms.

    :type sign_bits: uint8_t
    :param sign_bits:       unpacked sign bits (1-bit codes in standard format)
    :type ex_code: uint8_t
    :param ex_code:         packed ex-bit codes
    :type ex_fac: :py:class:`ExtraBitsFactors`
    :param ex_fac:          ex-bit factors (f_add_ex, f_rescale_ex)
    :type rotated_q: float
    :param rotated_q:       rotated query vector
    :type qr_base: float
    :param qr_base:         precomputed base term: ||q-c||^2 for L2, <q,c> for IP
    :type d: int
    :param d:               dimensionality
    :type ex_bits: int
    :param ex_bits:         number of extra bits (nb_bits - 1)
    :type metric_type: int
    :param metric_type:     distance metric (L2 or Inner Product)
    :rtype: float
    :return: computed full multi-bit distance
    """
    return _swigfaiss.compute_full_multibit_distance(sign_bits, ex_code, ex_fac, rotated_q, qr_base, d, ex_bits, metric_type)

def unpack_sign_bits_from_packed(block, bbs, nsq, offset, block_stride, sign_bits_out):
    r"""
    Extract sign bits from PQ4-interleaved block into flat byte packing.
    Like CodePackerRaBitQ::unpack_1 but sign-bits-only and with the
    vector's in-block address hoisted out of the per-SQ loop.
    """
    return _swigfaiss.unpack_sign_bits_from_packed(block, bbs, nsq, offset, block_stride, sign_bits_out)

def compute_per_vector_storage_size(nb_bits, d):
    r"""
     Compute per-vector auxiliary storage size.

    :type nb_bits: int
    :param nb_bits:  number of quantization bits (1 = sign-bit only)
    :type d: int
    :param d:        dimensionality
    :rtype: int
    :return: storage size in bytes
    """
    return _swigfaiss.compute_per_vector_storage_size(nb_bits, d)

def populate_block_aux_from_flat_storage(flat_storage, codes, num_vectors, bbs, M2, old_block_stride, new_block_stride, storage_size, id_map=None):
    r"""
     [LEGACY FORMAT SUPPORT] Migrate block data from old I/O format to new
    format.

    This function is used only when reading indexes saved with the legacy format
    (fourcc "Irfs"/"Iwrf") to convert them to the new embedded auxiliary data
    format. Not needed for indexes saved with the new format ("Irfn"/"Iwrn").

    Re-layouts blocks in-place and copies aux data from flat_storage.

    :type flat_storage: std::vector< uint8_t >
    :param flat_storage:       legacy per-vector aux data indexed by global ID
    :type codes: faiss::AlignedTable< uint8_t >
    :param codes:              block data (will be resized and re-laid out)
    :type num_vectors: int
    :param num_vectors:        number of vectors in this segment
    :type bbs: int
    :param bbs:                block batch size (vectors per block)
    :type M2: int
    :param M2:                 rounded sub-quantizer count
    :type old_block_stride: int
    :param old_block_stride:   old block size (packed codes only, or current)
    :type new_block_stride: int
    :param new_block_stride:   new block size (packed codes + aux region)
    :type storage_size: int
    :param storage_size:       per-vector aux storage size in bytes
    :type id_map: int, optional
    :param id_map:             maps local offset to global ID; null = sequential
    """
    return _swigfaiss.populate_block_aux_from_flat_storage(flat_storage, codes, num_vectors, bbs, M2, old_block_stride, new_block_stride, storage_size, id_map)
class RaBitQSearchParameters(SearchParameters):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    qb = property(_swigfaiss.RaBitQSearchParameters_qb_get, _swigfaiss.RaBitQSearchParameters_qb_set)
    centered = property(_swigfaiss.RaBitQSearchParameters_centered_get, _swigfaiss.RaBitQSearchParameters_centered_set)

    def __init__(self):
        _swigfaiss.RaBitQSearchParameters_swiginit(self, _swigfaiss.new_RaBitQSearchParameters())
    __swig_destroy__ = _swigfaiss.delete_RaBitQSearchParameters

# Register RaBitQSearchParameters in _swigfaiss:
_swigfaiss.RaBitQSearchParameters_swigregister(RaBitQSearchParameters)
Z_MAX_BY_QB = cvar.Z_MAX_BY_QB

class IndexRaBitQ(IndexFlatCodes):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    rabitq = property(_swigfaiss.IndexRaBitQ_rabitq_get, _swigfaiss.IndexRaBitQ_rabitq_set)
    center = property(_swigfaiss.IndexRaBitQ_center_get, _swigfaiss.IndexRaBitQ_center_set)
    qb = property(_swigfaiss.IndexRaBitQ_qb_get, _swigfaiss.IndexRaBitQ_qb_set)
    centered = property(_swigfaiss.IndexRaBitQ_centered_get, _swigfaiss.IndexRaBitQ_centered_set)

    def __init__(self, *args):
        _swigfaiss.IndexRaBitQ_swiginit(self, _swigfaiss.new_IndexRaBitQ(*args))

    def train(self, n, x):
        return _swigfaiss.IndexRaBitQ_train(self, n, x)

    def sa_encode(self, n, x, bytes):
        return _swigfaiss.IndexRaBitQ_sa_encode(self, n, x, bytes)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexRaBitQ_sa_decode(self, n, bytes, x)

    def get_FlatCodesDistanceComputer(self):
        return _swigfaiss.IndexRaBitQ_get_FlatCodesDistanceComputer(self)

    def get_quantized_distance_computer(self, qb_in, centered):
        return _swigfaiss.IndexRaBitQ_get_quantized_distance_computer(self, qb_in, centered)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexRaBitQ_search(self, n, x, k, distances, labels, params)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexRaBitQ_range_search(self, n, x, radius, result, params)
    __swig_destroy__ = _swigfaiss.delete_IndexRaBitQ

# Register IndexRaBitQ in _swigfaiss:
_swigfaiss.IndexRaBitQ_swigregister(IndexRaBitQ)
class IndexRaBitQFastScan(IndexFastScan):
    r"""
     Fast-scan version of RaBitQ index that processes 32 database vectors at a
    time using SIMD operations. Similar to IndexPQFastScan but adapted for
    RaBitQ's bit-level quantization with factors.

    The key differences from IndexRaBitQ:
    - Processes vectors in batches of 32
    - Uses 4-bit groupings for SIMD optimization (4 dimensions per 4-bit unit)
    - Separates factors from quantized bits for efficient processing
    - Leverages existing PQ4 FastScan infrastructure where possible
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    rabitq = property(_swigfaiss.IndexRaBitQFastScan_rabitq_get, _swigfaiss.IndexRaBitQFastScan_rabitq_set, doc=r"""RaBitQ quantizer for encoding/decoding""")
    center = property(_swigfaiss.IndexRaBitQFastScan_center_get, _swigfaiss.IndexRaBitQFastScan_center_set, doc=r"""Center of all points (same as IndexRaBitQ)""")
    qb = property(_swigfaiss.IndexRaBitQFastScan_qb_get, _swigfaiss.IndexRaBitQFastScan_qb_set, doc=r"""Default number of bits to quantize a query with""")
    centered = property(_swigfaiss.IndexRaBitQFastScan_centered_get, _swigfaiss.IndexRaBitQFastScan_centered_set)

    def __init__(self, *args):
        r"""
        *Overload 1:*
        build from an existing IndexRaBitQ

        |

        *Overload 2:*
        build from an existing IndexRaBitQ
        """
        _swigfaiss.IndexRaBitQFastScan_swiginit(self, _swigfaiss.new_IndexRaBitQFastScan(*args))

    def train(self, n, x):
        return _swigfaiss.IndexRaBitQFastScan_train(self, n, x)

    def add(self, n, x):
        return _swigfaiss.IndexRaBitQFastScan_add(self, n, x)

    def compute_codes(self, codes, n, x):
        return _swigfaiss.IndexRaBitQFastScan_compute_codes(self, codes, n, x)

    def compute_per_vector_storage_size(self):
        r"""Compute per-vector auxiliary data size in block aux region"""
        return _swigfaiss.IndexRaBitQFastScan_compute_per_vector_storage_size(self)

    def compute_float_LUT(self, lut, n, x, context):
        return _swigfaiss.IndexRaBitQFastScan_compute_float_LUT(self, lut, n, x, context)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexRaBitQFastScan_sa_decode(self, n, bytes, x)

    def fast_scan_code_size(self):
        r"""
        Packed code size: (d + 7) / 8 bytes (1-bit-per-dimension sign bits,
        excluding factors)
        """
        return _swigfaiss.IndexRaBitQFastScan_fast_scan_code_size(self)

    def get_CodePacker(self):
        r"""Return CodePackerRaBitQ with enlarged block size"""
        return _swigfaiss.IndexRaBitQFastScan_get_CodePacker(self)

    def remove_ids(self, sel):
        r"""Remove vectors and compact both PQ4 codes and auxiliary data"""
        return _swigfaiss.IndexRaBitQFastScan_remove_ids(self, sel)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexRaBitQFastScan_search(self, n, x, k, distances, labels, params)
    __swig_destroy__ = _swigfaiss.delete_IndexRaBitQFastScan

# Register IndexRaBitQFastScan in _swigfaiss:
_swigfaiss.IndexRaBitQFastScan_swigregister(IndexRaBitQFastScan)
class IVFRaBitQSearchParameters(SearchParametersIVF):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    qb = property(_swigfaiss.IVFRaBitQSearchParameters_qb_get, _swigfaiss.IVFRaBitQSearchParameters_qb_set)
    centered = property(_swigfaiss.IVFRaBitQSearchParameters_centered_get, _swigfaiss.IVFRaBitQSearchParameters_centered_set)

    def __init__(self):
        _swigfaiss.IVFRaBitQSearchParameters_swiginit(self, _swigfaiss.new_IVFRaBitQSearchParameters())
    __swig_destroy__ = _swigfaiss.delete_IVFRaBitQSearchParameters

# Register IVFRaBitQSearchParameters in _swigfaiss:
_swigfaiss.IVFRaBitQSearchParameters_swigregister(IVFRaBitQSearchParameters)
class IndexIVFRaBitQ(IndexIVF):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    rabitq = property(_swigfaiss.IndexIVFRaBitQ_rabitq_get, _swigfaiss.IndexIVFRaBitQ_rabitq_set)
    qb = property(_swigfaiss.IndexIVFRaBitQ_qb_get, _swigfaiss.IndexIVFRaBitQ_qb_set)

    def __init__(self, *args):
        _swigfaiss.IndexIVFRaBitQ_swiginit(self, _swigfaiss.new_IndexIVFRaBitQ(*args))

    def train_encoder(self, n, x, assign):
        return _swigfaiss.IndexIVFRaBitQ_train_encoder(self, n, x, assign)

    def encode_vectors(self, n, x, list_nos, codes, include_listnos=False):
        return _swigfaiss.IndexIVFRaBitQ_encode_vectors(self, n, x, list_nos, codes, include_listnos)

    def decode_vectors(self, n, codes, list_nos, x):
        return _swigfaiss.IndexIVFRaBitQ_decode_vectors(self, n, codes, list_nos, x)

    def add_core(self, n, x, xids, precomputed_idx, inverted_list_context=None):
        return _swigfaiss.IndexIVFRaBitQ_add_core(self, n, x, xids, precomputed_idx, inverted_list_context)

    def get_InvertedListScanner(self, store_pairs, sel, params):
        return _swigfaiss.IndexIVFRaBitQ_get_InvertedListScanner(self, store_pairs, sel, params)

    def reconstruct_from_offset(self, list_no, offset, recons):
        return _swigfaiss.IndexIVFRaBitQ_reconstruct_from_offset(self, list_no, offset, recons)

    def sa_decode(self, n, bytes, x):
        return _swigfaiss.IndexIVFRaBitQ_sa_decode(self, n, bytes, x)

    def get_distance_computer(self):
        return _swigfaiss.IndexIVFRaBitQ_get_distance_computer(self)
    __swig_destroy__ = _swigfaiss.delete_IndexIVFRaBitQ

# Register IndexIVFRaBitQ in _swigfaiss:
_swigfaiss.IndexIVFRaBitQ_swigregister(IndexIVFRaBitQ)
class IndexIVFRaBitQFastScan(IndexIVFFastScan):
    r"""
     Fast-scan version of IndexIVFRaBitQ that processes vectors in batches
    using SIMD operations. Combines the inverted file structure of IVF
    with RaBitQ's bit-level quantization and FastScan's batch processing.

    Key features:
    - Inherits from IndexIVFFastScan for IVF structure and search algorithms
    - Processes 32 database vectors at a time using SIMD
    - Separates factors from quantized bits for efficient processing
    - Supports both L2 and inner product metrics
    - Maintains compatibility with existing IVF search parameters

    Implementation details:
    - Batch size (bbs) is typically 32 for optimal SIMD performance
    - Factors are stored separately from packed codes for cache efficiency
    - Query factors are computed once per search and reused across lists
    - Uses specialized result handlers for RaBitQ distance corrections
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    rabitq = property(_swigfaiss.IndexIVFRaBitQFastScan_rabitq_get, _swigfaiss.IndexIVFRaBitQFastScan_rabitq_set)
    qb = property(_swigfaiss.IndexIVFRaBitQFastScan_qb_get, _swigfaiss.IndexIVFRaBitQFastScan_qb_set, doc=r"""Default number of bits to quantize a query with""")
    centered = property(_swigfaiss.IndexIVFRaBitQFastScan_centered_get, _swigfaiss.IndexIVFRaBitQFastScan_centered_set, doc=r"""Use zero-centered scalar quantizer for queries""")

    def __init__(self, *args):
        r"""
        *Overload 1:*
        Build from an existing IndexIVFRaBitQ

        |

        *Overload 2:*
        Build from an existing IndexIVFRaBitQ
        """
        _swigfaiss.IndexIVFRaBitQFastScan_swiginit(self, _swigfaiss.new_IndexIVFRaBitQFastScan(*args))

    def train_encoder(self, n, x, assign):
        return _swigfaiss.IndexIVFRaBitQFastScan_train_encoder(self, n, x, assign)

    def encode_vectors(self, n, x, list_nos, codes, include_listnos=False):
        return _swigfaiss.IndexIVFRaBitQFastScan_encode_vectors(self, n, x, list_nos, codes, include_listnos)

    def fast_scan_code_size(self):
        r"""
        Packed code size: (d + 7) / 8 bytes (1-bit-per-dimension sign bits,
        excluding factors)
        """
        return _swigfaiss.IndexIVFRaBitQFastScan_fast_scan_code_size(self)

    def get_CodePacker(self):
        r"""Return CodePackerRaBitQ with enlarged block size"""
        return _swigfaiss.IndexIVFRaBitQFastScan_get_CodePacker(self)

    def postprocess_packed_codes(self, list_no, list_offset, n_added, flat_codes):
        r"""Write per-vector auxiliary data into block auxiliary region"""
        return _swigfaiss.IndexIVFRaBitQFastScan_postprocess_packed_codes(self, list_no, list_offset, n_added, flat_codes)

    def reconstruct_from_offset(self, list_no, offset, recons):
        r"""Reconstruct a single vector from an inverted list"""
        return _swigfaiss.IndexIVFRaBitQFastScan_reconstruct_from_offset(self, list_no, offset, recons)

    def sa_decode(self, n, bytes, x):
        r"""Override sa_decode to handle RaBitQ reconstruction"""
        return _swigfaiss.IndexIVFRaBitQFastScan_sa_decode(self, n, bytes, x)

    def compute_per_vector_storage_size(self):
        r"""Compute per-vector auxiliary storage size based on nb_bits"""
        return _swigfaiss.IndexIVFRaBitQFastScan_compute_per_vector_storage_size(self)

    def compute_LUT_uint8(self, n, x, cq, dis_tables, biases, normalizers, context):
        r"""
        Override: compute and quantize LUT per-query to avoid O(n*nprobe*M*16)
        float table allocation.
        """
        return _swigfaiss.IndexIVFRaBitQFastScan_compute_LUT_uint8(self, n, x, cq, dis_tables, biases, normalizers, context)

    def compute_residual_LUT(self, query, centroid_id, query_factors, lut_out, qb_param, centered_param, rotated_q, centroid_buf):
        r"""Compute residual, query factors, and float LUT in two passes over d."""
        return _swigfaiss.IndexIVFRaBitQFastScan_compute_residual_LUT(self, query, centroid_id, query_factors, lut_out, qb_param, centered_param, rotated_q, centroid_buf)

    def lookup_table_is_3d(self):
        r"""Implementation methods for IVFRaBitQFastScan specialization"""
        return _swigfaiss.IndexIVFRaBitQFastScan_lookup_table_is_3d(self)

    def compute_LUT(self, n, x, cq, dis_tables, biases, context):
        return _swigfaiss.IndexIVFRaBitQFastScan_compute_LUT(self, n, x, cq, dis_tables, biases, context)

    def search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params=None, stats=None):
        return _swigfaiss.IndexIVFRaBitQFastScan_search_preassigned(self, n, x, k, assign, centroid_dis, distances, labels, store_pairs, params, stats)

    def get_InvertedListScanner(self, store_pairs=False, sel=None, params=None):
        r"""
        Get an InvertedListScanner for single-query scanning.
        This provides compatibility with the standard IVF search interface
        """
        return _swigfaiss.IndexIVFRaBitQFastScan_get_InvertedListScanner(self, store_pairs, sel, params)
    __swig_destroy__ = _swigfaiss.delete_IndexIVFRaBitQFastScan

# Register IndexIVFRaBitQFastScan in _swigfaiss:
_swigfaiss.IndexIVFRaBitQFastScan_swigregister(IndexIVFRaBitQFastScan)
class RangeSearchResult(object):
    r"""
    The objective is to have a simple result structure while
    minimizing the number of mem copies in the result. The method
    do_allocation can be overloaded to allocate the result tables in
    the matrix type of a scripting language like Lua or Python.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nq = property(_swigfaiss.RangeSearchResult_nq_get, _swigfaiss.RangeSearchResult_nq_set, doc=r"""nb of queries""")
    lims = property(_swigfaiss.RangeSearchResult_lims_get, _swigfaiss.RangeSearchResult_lims_set, doc=r"""size (nq + 1)""")
    labels = property(_swigfaiss.RangeSearchResult_labels_get, _swigfaiss.RangeSearchResult_labels_set, doc=r"""result for query i is labels[lims[i]:lims[i+1]]""")
    distances = property(_swigfaiss.RangeSearchResult_distances_get, _swigfaiss.RangeSearchResult_distances_set, doc=r"""corresponding distances (not sorted)""")
    buffer_size = property(_swigfaiss.RangeSearchResult_buffer_size_get, _swigfaiss.RangeSearchResult_buffer_size_set, doc=r"""size of the result buffers used""")

    def __init__(self, nq, alloc_lims=True):
        r"""lims must be allocated on input to range_search."""
        _swigfaiss.RangeSearchResult_swiginit(self, _swigfaiss.new_RangeSearchResult(nq, alloc_lims))

    def do_allocation(self):
        r"""
        called when lims contains the nb of elements result entries
        for each query
        """
        return _swigfaiss.RangeSearchResult_do_allocation(self)
    __swig_destroy__ = _swigfaiss.delete_RangeSearchResult

# Register RangeSearchResult in _swigfaiss:
_swigfaiss.RangeSearchResult_swigregister(RangeSearchResult)
class BufferList(object):
    r"""
    List of temporary buffers used to store results before they are
    copied to the RangeSearchResult object.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    buffer_size = property(_swigfaiss.BufferList_buffer_size_get, _swigfaiss.BufferList_buffer_size_set)
    buffers = property(_swigfaiss.BufferList_buffers_get, _swigfaiss.BufferList_buffers_set)
    wp = property(_swigfaiss.BufferList_wp_get, _swigfaiss.BufferList_wp_set, doc=r"""write pointer in the last buffer.""")

    def __init__(self, buffer_size):
        _swigfaiss.BufferList_swiginit(self, _swigfaiss.new_BufferList(buffer_size))
    __swig_destroy__ = _swigfaiss.delete_BufferList

    def append_buffer(self):
        r"""create a new buffer"""
        return _swigfaiss.BufferList_append_buffer(self)

    def add(self, id, dis):
        r"""add one result, possibly appending a new buffer if needed"""
        return _swigfaiss.BufferList_add(self, id, dis)

    def copy_range(self, ofs, n, dest_ids, dest_dis):
        r"""
        copy elements ofs:ofs+n-1 seen as linear data in the buffers to
        tables dest_ids, dest_dis
        """
        return _swigfaiss.BufferList_copy_range(self, ofs, n, dest_ids, dest_dis)

# Register BufferList in _swigfaiss:
_swigfaiss.BufferList_swigregister(BufferList)
class RangeQueryResult(object):
    r"""result structure for a single query"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    qno = property(_swigfaiss.RangeQueryResult_qno_get, _swigfaiss.RangeQueryResult_qno_set)
    nres = property(_swigfaiss.RangeQueryResult_nres_get, _swigfaiss.RangeQueryResult_nres_set)
    pres = property(_swigfaiss.RangeQueryResult_pres_get, _swigfaiss.RangeQueryResult_pres_set)
    stats = property(_swigfaiss.RangeQueryResult_stats_get, _swigfaiss.RangeQueryResult_stats_set)

    def add(self, dis, id):
        r"""called by search function to report a new result"""
        return _swigfaiss.RangeQueryResult_add(self, dis, id)

    def __init__(self):
        _swigfaiss.RangeQueryResult_swiginit(self, _swigfaiss.new_RangeQueryResult())
    __swig_destroy__ = _swigfaiss.delete_RangeQueryResult

# Register RangeQueryResult in _swigfaiss:
_swigfaiss.RangeQueryResult_swigregister(RangeQueryResult)
class RangeSearchPartialResult(BufferList):
    r"""the entries in the buffers are split per query"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    res = property(_swigfaiss.RangeSearchPartialResult_res_get, _swigfaiss.RangeSearchPartialResult_res_set)

    def __init__(self, res_in):
        r"""eventually the result will be stored in res_in"""
        _swigfaiss.RangeSearchPartialResult_swiginit(self, _swigfaiss.new_RangeSearchPartialResult(res_in))
    queries = property(_swigfaiss.RangeSearchPartialResult_queries_get, _swigfaiss.RangeSearchPartialResult_queries_set, doc=r"""query ids + nb of results per query.""")

    def new_result(self, qno):
        r"""begin a new result"""
        return _swigfaiss.RangeSearchPartialResult_new_result(self, qno)

    def finalize(self):
        return _swigfaiss.RangeSearchPartialResult_finalize(self)

    def set_lims(self):
        r"""called by range_search before do_allocation"""
        return _swigfaiss.RangeSearchPartialResult_set_lims(self)

    def copy_result(self, incremental=False):
        r"""called by range_search after do_allocation"""
        return _swigfaiss.RangeSearchPartialResult_copy_result(self, incremental)

    @staticmethod
    def merge(partial_results, do_delete=True):
        r"""
        merge a set of PartialResult's into one RangeSearchResult
        on output the partialresults are empty!
        """
        return _swigfaiss.RangeSearchPartialResult_merge(partial_results, do_delete)
    __swig_destroy__ = _swigfaiss.delete_RangeSearchPartialResult

# Register RangeSearchPartialResult in _swigfaiss:
_swigfaiss.RangeSearchPartialResult_swigregister(RangeSearchPartialResult)
class InterruptCallback(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr

    def want_interrupt(self):
        return _swigfaiss.InterruptCallback_want_interrupt(self)
    __swig_destroy__ = _swigfaiss.delete_InterruptCallback

    @staticmethod
    def clear_instance():
        return _swigfaiss.InterruptCallback_clear_instance()

    @staticmethod
    def check():
        r"""
         check if:
        - an interrupt callback is set
        - the callback returns true
        if this is the case, then throw an exception. Should not be called
        from multiple threads.
        """
        return _swigfaiss.InterruptCallback_check()

    @staticmethod
    def is_interrupted():
        r"""
        same as check() but return true if is interrupted instead of
        throwing. Can be called from multiple threads.
        """
        return _swigfaiss.InterruptCallback_is_interrupted()

    @staticmethod
    def get_period_hint(flops):
        r"""
         assuming each iteration takes a certain number of flops, what
        is a reasonable interval to check for interrupts?
        """
        return _swigfaiss.InterruptCallback_get_period_hint(flops)

# Register InterruptCallback in _swigfaiss:
_swigfaiss.InterruptCallback_swigregister(InterruptCallback)
class TimeoutCallback(InterruptCallback):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    start = property(_swigfaiss.TimeoutCallback_start_get, _swigfaiss.TimeoutCallback_start_set)
    timeout = property(_swigfaiss.TimeoutCallback_timeout_get, _swigfaiss.TimeoutCallback_timeout_set)

    def want_interrupt(self):
        return _swigfaiss.TimeoutCallback_want_interrupt(self)

    def set_timeout(self, timeout_in_seconds):
        return _swigfaiss.TimeoutCallback_set_timeout(self, timeout_in_seconds)

    @staticmethod
    def reset(timeout_in_seconds):
        return _swigfaiss.TimeoutCallback_reset(timeout_in_seconds)

    def __init__(self):
        _swigfaiss.TimeoutCallback_swiginit(self, _swigfaiss.new_TimeoutCallback())
    __swig_destroy__ = _swigfaiss.delete_TimeoutCallback

# Register TimeoutCallback in _swigfaiss:
_swigfaiss.TimeoutCallback_swigregister(TimeoutCallback)
class VisitedTable(object):
    r"""
    Abstract base class for a fast, reusable Visited Set for graph search
    algorithms.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    __swig_destroy__ = _swigfaiss.delete_VisitedTable

    def set(self, no):
        r"""set flag #no to true, return whether this changed it."""
        return _swigfaiss.VisitedTable_set(self, no)

    def get(self, no):
        r"""get flag #no"""
        return _swigfaiss.VisitedTable_get(self, no)

    def prefetch(self, no):
        r"""prefetch flag #no"""
        return _swigfaiss.VisitedTable_prefetch(self, no)

    def reserve(self, arg2):
        r"""pre-allocate bucket space to avoid rehashing during repeated set() calls"""
        return _swigfaiss.VisitedTable_reserve(self, arg2)

    def advance(self):
        r"""reset all flags to false"""
        return _swigfaiss.VisitedTable_advance(self)

# Register VisitedTable in _swigfaiss:
_swigfaiss.VisitedTable_swigregister(VisitedTable)
class VisitedTableSet(VisitedTable):
    r"""
    Set-based implementation using unordered_set.
    O(1) to construct and O(visits) to advance.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    visited_set = property(_swigfaiss.VisitedTableSet_visited_set_get, _swigfaiss.VisitedTableSet_visited_set_set)

    def __init__(self):
        _swigfaiss.VisitedTableSet_swiginit(self, _swigfaiss.new_VisitedTableSet())

    def set(self, no):
        return _swigfaiss.VisitedTableSet_set(self, no)

    def get(self, no):
        return _swigfaiss.VisitedTableSet_get(self, no)

    def prefetch(self, arg2):
        return _swigfaiss.VisitedTableSet_prefetch(self, arg2)

    def reserve(self, n):
        return _swigfaiss.VisitedTableSet_reserve(self, n)

    def advance(self):
        return _swigfaiss.VisitedTableSet_advance(self)
    __swig_destroy__ = _swigfaiss.delete_VisitedTableSet

# Register VisitedTableSet in _swigfaiss:
_swigfaiss.VisitedTableSet_swigregister(VisitedTableSet)
class VisitedTableVector(VisitedTable):
    r"""
    Vector-based implementation using a versioned byte array.
    Faster for get()/set(), but O(size) to initialize.
    advance() is O(1) except every 250 calls, which are O(size).
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    visited = property(_swigfaiss.VisitedTableVector_visited_get, _swigfaiss.VisitedTableVector_visited_set)
    visno = property(_swigfaiss.VisitedTableVector_visno_get, _swigfaiss.VisitedTableVector_visno_set)

    def __init__(self, size):
        _swigfaiss.VisitedTableVector_swiginit(self, _swigfaiss.new_VisitedTableVector(size))

    def set(self, no):
        return _swigfaiss.VisitedTableVector_set(self, no)

    def get(self, no):
        return _swigfaiss.VisitedTableVector_get(self, no)

    def prefetch(self, no):
        return _swigfaiss.VisitedTableVector_prefetch(self, no)

    def advance(self):
        return _swigfaiss.VisitedTableVector_advance(self)
    __swig_destroy__ = _swigfaiss.delete_VisitedTableVector

# Register VisitedTableVector in _swigfaiss:
_swigfaiss.VisitedTableVector_swigregister(VisitedTableVector)
class IDSelector(object):
    r"""Encapsulates a set of ids to handle."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr

    def is_member(self, id):
        return _swigfaiss.IDSelector_is_member(self, id)
    __swig_destroy__ = _swigfaiss.delete_IDSelector

# Register IDSelector in _swigfaiss:
_swigfaiss.IDSelector_swigregister(IDSelector)
class IDSelectorRange(IDSelector):
    r"""ids between [imin, imax)"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    imin = property(_swigfaiss.IDSelectorRange_imin_get, _swigfaiss.IDSelectorRange_imin_set)
    imax = property(_swigfaiss.IDSelectorRange_imax_get, _swigfaiss.IDSelectorRange_imax_set)
    assume_sorted = property(_swigfaiss.IDSelectorRange_assume_sorted_get, _swigfaiss.IDSelectorRange_assume_sorted_set, doc=r"""
    Assume that the ids to handle are sorted. In some cases this can speed
    up processing
    """)

    def __init__(self, imin, imax, assume_sorted=False):
        _swigfaiss.IDSelectorRange_swiginit(self, _swigfaiss.new_IDSelectorRange(imin, imax, assume_sorted))

    def is_member(self, id):
        return _swigfaiss.IDSelectorRange_is_member(self, id)

    def find_sorted_ids_bounds(self, list_size, ids, jmin, jmax):
        r"""
        for sorted ids, find the range of list indices where the valid ids are
        stored
        """
        return _swigfaiss.IDSelectorRange_find_sorted_ids_bounds(self, list_size, ids, jmin, jmax)
    __swig_destroy__ = _swigfaiss.delete_IDSelectorRange

# Register IDSelectorRange in _swigfaiss:
_swigfaiss.IDSelectorRange_swigregister(IDSelectorRange)
class IDSelectorArray(IDSelector):
    r"""
     Simple array of elements

    is_member calls are very inefficient, but some operations can use the ids
    directly.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    n = property(_swigfaiss.IDSelectorArray_n_get, _swigfaiss.IDSelectorArray_n_set)
    ids = property(_swigfaiss.IDSelectorArray_ids_get, _swigfaiss.IDSelectorArray_ids_set)

    def __init__(self, n, ids):
        r"""
         Construct with an array of ids to process

        :type n: int
        :param n: number of ids to store
        :type ids: int
        :param ids: elements to store. The pointer should remain valid during
                       IDSelectorArray's lifetime
        """
        _swigfaiss.IDSelectorArray_swiginit(self, _swigfaiss.new_IDSelectorArray(n, ids))

    def is_member(self, id):
        return _swigfaiss.IDSelectorArray_is_member(self, id)
    __swig_destroy__ = _swigfaiss.delete_IDSelectorArray

# Register IDSelectorArray in _swigfaiss:
_swigfaiss.IDSelectorArray_swigregister(IDSelectorArray)
class IDSelectorBatch(IDSelector):
    r"""
     Ids from a set.

    Repetitions of ids in the indices set passed to the constructor does not hurt
    performance.

    The hash function used for the bloom filter and GCC's implementation of
    unordered_set are just the least significant bits of the id. This works fine
    for random ids or ids in sequences but will produce many hash collisions if
    lsb's are always the same
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nbits = property(_swigfaiss.IDSelectorBatch_nbits_get, _swigfaiss.IDSelectorBatch_nbits_set)
    mask = property(_swigfaiss.IDSelectorBatch_mask_get, _swigfaiss.IDSelectorBatch_mask_set)

    def __init__(self, n, indices):
        r"""
         Construct with an array of ids to process

        :type n: int
        :param n: number of ids to store
        :param ids: elements to store. The pointer can be released after
                       construction
        """
        _swigfaiss.IDSelectorBatch_swiginit(self, _swigfaiss.new_IDSelectorBatch(n, indices))

    def is_member(self, id):
        return _swigfaiss.IDSelectorBatch_is_member(self, id)
    __swig_destroy__ = _swigfaiss.delete_IDSelectorBatch

# Register IDSelectorBatch in _swigfaiss:
_swigfaiss.IDSelectorBatch_swigregister(IDSelectorBatch)
class IDSelectorBitmap(IDSelector):
    r"""One bit per element. Constructed with a bitmap, size ceil(n / 8)."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    n = property(_swigfaiss.IDSelectorBitmap_n_get, _swigfaiss.IDSelectorBitmap_n_set)
    bitmap = property(_swigfaiss.IDSelectorBitmap_bitmap_get, _swigfaiss.IDSelectorBitmap_bitmap_set)

    def __init__(self, n, bitmap):
        r"""
         Construct with a binary mask

        :type n: int
        :param n: size of the bitmap array
        :type bitmap: uint8_t
        :param bitmap: id will be selected iff id / 8 < n and bit number
                          (i%8) of bitmap[floor(i / 8)] is 1.
        """
        _swigfaiss.IDSelectorBitmap_swiginit(self, _swigfaiss.new_IDSelectorBitmap(n, bitmap))

    def is_member(self, id):
        return _swigfaiss.IDSelectorBitmap_is_member(self, id)
    __swig_destroy__ = _swigfaiss.delete_IDSelectorBitmap

# Register IDSelectorBitmap in _swigfaiss:
_swigfaiss.IDSelectorBitmap_swigregister(IDSelectorBitmap)
class IDSelectorNot(IDSelector):
    r"""reverts the membership test of another selector"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    sel = property(_swigfaiss.IDSelectorNot_sel_get, _swigfaiss.IDSelectorNot_sel_set)

    def __init__(self, sel_):
        _swigfaiss.IDSelectorNot_swiginit(self, _swigfaiss.new_IDSelectorNot(sel_))

    def is_member(self, id):
        return _swigfaiss.IDSelectorNot_is_member(self, id)
    __swig_destroy__ = _swigfaiss.delete_IDSelectorNot

# Register IDSelectorNot in _swigfaiss:
_swigfaiss.IDSelectorNot_swigregister(IDSelectorNot)
class IDSelectorAll(IDSelector):
    r"""selects all entries (useful for benchmarking)"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def is_member(self, arg2):
        return _swigfaiss.IDSelectorAll_is_member(self, arg2)
    __swig_destroy__ = _swigfaiss.delete_IDSelectorAll

    def __init__(self):
        _swigfaiss.IDSelectorAll_swiginit(self, _swigfaiss.new_IDSelectorAll())

# Register IDSelectorAll in _swigfaiss:
_swigfaiss.IDSelectorAll_swigregister(IDSelectorAll)
class IDSelectorAnd(IDSelector):
    r"""
    does an AND operation on the two given IDSelector's is_membership
    results.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    lhs = property(_swigfaiss.IDSelectorAnd_lhs_get, _swigfaiss.IDSelectorAnd_lhs_set)
    rhs = property(_swigfaiss.IDSelectorAnd_rhs_get, _swigfaiss.IDSelectorAnd_rhs_set)

    def __init__(self, lhs_, rhs_):
        _swigfaiss.IDSelectorAnd_swiginit(self, _swigfaiss.new_IDSelectorAnd(lhs_, rhs_))

    def is_member(self, id):
        return _swigfaiss.IDSelectorAnd_is_member(self, id)
    __swig_destroy__ = _swigfaiss.delete_IDSelectorAnd

# Register IDSelectorAnd in _swigfaiss:
_swigfaiss.IDSelectorAnd_swigregister(IDSelectorAnd)
class IDSelectorOr(IDSelector):
    r"""
    does an OR operation on the two given IDSelector's is_membership
    results.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    lhs = property(_swigfaiss.IDSelectorOr_lhs_get, _swigfaiss.IDSelectorOr_lhs_set)
    rhs = property(_swigfaiss.IDSelectorOr_rhs_get, _swigfaiss.IDSelectorOr_rhs_set)

    def __init__(self, lhs_, rhs_):
        _swigfaiss.IDSelectorOr_swiginit(self, _swigfaiss.new_IDSelectorOr(lhs_, rhs_))

    def is_member(self, id):
        return _swigfaiss.IDSelectorOr_is_member(self, id)
    __swig_destroy__ = _swigfaiss.delete_IDSelectorOr

# Register IDSelectorOr in _swigfaiss:
_swigfaiss.IDSelectorOr_swigregister(IDSelectorOr)
class IDSelectorXOr(IDSelector):
    r"""
    does an XOR operation on the two given IDSelector's is_membership
    results.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    lhs = property(_swigfaiss.IDSelectorXOr_lhs_get, _swigfaiss.IDSelectorXOr_lhs_set)
    rhs = property(_swigfaiss.IDSelectorXOr_rhs_get, _swigfaiss.IDSelectorXOr_rhs_set)

    def __init__(self, lhs_, rhs_):
        _swigfaiss.IDSelectorXOr_swiginit(self, _swigfaiss.new_IDSelectorXOr(lhs_, rhs_))

    def is_member(self, id):
        return _swigfaiss.IDSelectorXOr_is_member(self, id)
    __swig_destroy__ = _swigfaiss.delete_IDSelectorXOr

# Register IDSelectorXOr in _swigfaiss:
_swigfaiss.IDSelectorXOr_swigregister(IDSelectorXOr)
class IDSelectorTranslated(IDSelector):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    id_map = property(_swigfaiss.IDSelectorTranslated_id_map_get)
    sel = property(_swigfaiss.IDSelectorTranslated_sel_get, _swigfaiss.IDSelectorTranslated_sel_set)

    def __init__(self, *args):
        _swigfaiss.IDSelectorTranslated_swiginit(self, _swigfaiss.new_IDSelectorTranslated(*args))

    def is_member(self, id):
        return _swigfaiss.IDSelectorTranslated_is_member(self, id)
    __swig_destroy__ = _swigfaiss.delete_IDSelectorTranslated

# Register IDSelectorTranslated in _swigfaiss:
_swigfaiss.IDSelectorTranslated_swigregister(IDSelectorTranslated)
class IndexIDMap(Index):
    r"""Index that translates search results to ids"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    index = property(_swigfaiss.IndexIDMap_index_get, _swigfaiss.IndexIDMap_index_set)
    own_fields = property(_swigfaiss.IndexIDMap_own_fields_get, _swigfaiss.IndexIDMap_own_fields_set, doc=r"""the sub-index""")
    id_map = property(_swigfaiss.IndexIDMap_id_map_get, _swigfaiss.IndexIDMap_id_map_set, doc=r"""whether pointers are deleted in destructor""")

    def add_with_ids(self, n, x, xids):
        r"""
        :type xids: int
        :param xids: if non-null, ids to store for the vectors (size n)
        """
        return _swigfaiss.IndexIDMap_add_with_ids(self, n, x, xids)

    def add_with_ids_ex(self, n, x, numeric_type, xids):
        return _swigfaiss.IndexIDMap_add_with_ids_ex(self, n, x, numeric_type, xids)

    def add(self, n, x):
        r"""this will fail. Use add_with_ids"""
        return _swigfaiss.IndexIDMap_add(self, n, x)

    def add_ex(self, n, x, numeric_type):
        return _swigfaiss.IndexIDMap_add_ex(self, n, x, numeric_type)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexIDMap_search(self, n, x, k, distances, labels, params)

    def search_ex(self, n, x, numeric_type, k, distances, labels, params=None):
        return _swigfaiss.IndexIDMap_search_ex(self, n, x, numeric_type, k, distances, labels, params)

    def train(self, n, x):
        return _swigfaiss.IndexIDMap_train(self, n, x)

    def train_ex(self, n, x, numeric_type):
        return _swigfaiss.IndexIDMap_train_ex(self, n, x, numeric_type)

    def reset(self):
        return _swigfaiss.IndexIDMap_reset(self)

    def remove_ids(self, sel):
        r"""remove ids adapted to IndexFlat"""
        return _swigfaiss.IndexIDMap_remove_ids(self, sel)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexIDMap_range_search(self, n, x, radius, result, params)

    def merge_from(self, otherIndex, add_id=0):
        return _swigfaiss.IndexIDMap_merge_from(self, otherIndex, add_id)

    def check_compatible_for_merge(self, otherIndex):
        return _swigfaiss.IndexIDMap_check_compatible_for_merge(self, otherIndex)

    def sa_code_size(self):
        return _swigfaiss.IndexIDMap_sa_code_size(self)

    def add_sa_codes(self, n, x, xids):
        return _swigfaiss.IndexIDMap_add_sa_codes(self, n, x, xids)
    __swig_destroy__ = _swigfaiss.delete_IndexIDMap

    def __init__(self, *args):
        _swigfaiss.IndexIDMap_swiginit(self, _swigfaiss.new_IndexIDMap(*args))

# Register IndexIDMap in _swigfaiss:
_swigfaiss.IndexIDMap_swigregister(IndexIDMap)
class IndexBinaryIDMap(IndexBinary):
    r"""Index that translates search results to ids"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    index = property(_swigfaiss.IndexBinaryIDMap_index_get, _swigfaiss.IndexBinaryIDMap_index_set)
    own_fields = property(_swigfaiss.IndexBinaryIDMap_own_fields_get, _swigfaiss.IndexBinaryIDMap_own_fields_set, doc=r"""the sub-index""")
    id_map = property(_swigfaiss.IndexBinaryIDMap_id_map_get, _swigfaiss.IndexBinaryIDMap_id_map_set, doc=r"""whether pointers are deleted in destructor""")

    def add_with_ids(self, n, x, xids):
        r"""
        :type xids: int
        :param xids: if non-null, ids to store for the vectors (size n)
        """
        return _swigfaiss.IndexBinaryIDMap_add_with_ids(self, n, x, xids)

    def add_with_ids_ex(self, n, x, numeric_type, xids):
        return _swigfaiss.IndexBinaryIDMap_add_with_ids_ex(self, n, x, numeric_type, xids)

    def add(self, n, x):
        r"""this will fail. Use add_with_ids"""
        return _swigfaiss.IndexBinaryIDMap_add(self, n, x)

    def add_ex(self, n, x, numeric_type):
        return _swigfaiss.IndexBinaryIDMap_add_ex(self, n, x, numeric_type)

    def search(self, n, x, k, distances, labels, params=None):
        return _swigfaiss.IndexBinaryIDMap_search(self, n, x, k, distances, labels, params)

    def search_ex(self, n, x, numeric_type, k, distances, labels, params=None):
        return _swigfaiss.IndexBinaryIDMap_search_ex(self, n, x, numeric_type, k, distances, labels, params)

    def train(self, n, x):
        return _swigfaiss.IndexBinaryIDMap_train(self, n, x)

    def train_ex(self, n, x, numeric_type):
        return _swigfaiss.IndexBinaryIDMap_train_ex(self, n, x, numeric_type)

    def reset(self):
        return _swigfaiss.IndexBinaryIDMap_reset(self)

    def remove_ids(self, sel):
        r"""remove ids adapted to IndexFlat"""
        return _swigfaiss.IndexBinaryIDMap_remove_ids(self, sel)

    def range_search(self, n, x, radius, result, params=None):
        return _swigfaiss.IndexBinaryIDMap_range_search(self, n, x, radius, result, params)

    def merge_from(self, otherIndex, add_id=0):
        return _swigfaiss.IndexBinaryIDMap_merge_from(self, otherIndex, add_id)

    def check_compatible_for_merge(self, otherIndex):
        return _swigfaiss.IndexBinaryIDMap_check_compatible_for_merge(self, otherIndex)

    def sa_code_size(self):
        return _swigfaiss.IndexBinaryIDMap_sa_code_size(self)

    def add_sa_codes(self, n, x, xids):
        return _swigfaiss.IndexBinaryIDMap_add_sa_codes(self, n, x, xids)
    __swig_destroy__ = _swigfaiss.delete_IndexBinaryIDMap

    def __init__(self, *args):
        _swigfaiss.IndexBinaryIDMap_swiginit(self, _swigfaiss.new_IndexBinaryIDMap(*args))

# Register IndexBinaryIDMap in _swigfaiss:
_swigfaiss.IndexBinaryIDMap_swigregister(IndexBinaryIDMap)
class IndexIDMap2(IndexIDMap):
    r"""
    same as IndexIDMap but also provides an efficient reconstruction
    implementation via a 2-way index
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    rev_map = property(_swigfaiss.IndexIDMap2_rev_map_get, _swigfaiss.IndexIDMap2_rev_map_set)

    def construct_rev_map(self):
        r"""make the rev_map from scratch"""
        return _swigfaiss.IndexIDMap2_construct_rev_map(self)

    def add_with_ids(self, n, x, xids):
        return _swigfaiss.IndexIDMap2_add_with_ids(self, n, x, xids)

    def add_with_ids_ex(self, n, x, numeric_type, xids):
        return _swigfaiss.IndexIDMap2_add_with_ids_ex(self, n, x, numeric_type, xids)

    def remove_ids(self, sel):
        return _swigfaiss.IndexIDMap2_remove_ids(self, sel)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexIDMap2_reconstruct(self, key, recons)

    def check_consistency(self):
        r"""check that the rev_map and the id_map are in sync"""
        return _swigfaiss.IndexIDMap2_check_consistency(self)

    def merge_from(self, otherIndex, add_id=0):
        return _swigfaiss.IndexIDMap2_merge_from(self, otherIndex, add_id)
    __swig_destroy__ = _swigfaiss.delete_IndexIDMap2

    def __init__(self, *args):
        _swigfaiss.IndexIDMap2_swiginit(self, _swigfaiss.new_IndexIDMap2(*args))

# Register IndexIDMap2 in _swigfaiss:
_swigfaiss.IndexIDMap2_swigregister(IndexIDMap2)
class IndexBinaryIDMap2(IndexBinaryIDMap):
    r"""
    same as IndexIDMap but also provides an efficient reconstruction
    implementation via a 2-way index
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    rev_map = property(_swigfaiss.IndexBinaryIDMap2_rev_map_get, _swigfaiss.IndexBinaryIDMap2_rev_map_set)

    def construct_rev_map(self):
        r"""make the rev_map from scratch"""
        return _swigfaiss.IndexBinaryIDMap2_construct_rev_map(self)

    def add_with_ids(self, n, x, xids):
        return _swigfaiss.IndexBinaryIDMap2_add_with_ids(self, n, x, xids)

    def add_with_ids_ex(self, n, x, numeric_type, xids):
        return _swigfaiss.IndexBinaryIDMap2_add_with_ids_ex(self, n, x, numeric_type, xids)

    def remove_ids(self, sel):
        return _swigfaiss.IndexBinaryIDMap2_remove_ids(self, sel)

    def reconstruct(self, key, recons):
        return _swigfaiss.IndexBinaryIDMap2_reconstruct(self, key, recons)

    def check_consistency(self):
        r"""check that the rev_map and the id_map are in sync"""
        return _swigfaiss.IndexBinaryIDMap2_check_consistency(self)

    def merge_from(self, otherIndex, add_id=0):
        return _swigfaiss.IndexBinaryIDMap2_merge_from(self, otherIndex, add_id)
    __swig_destroy__ = _swigfaiss.delete_IndexBinaryIDMap2

    def __init__(self, *args):
        _swigfaiss.IndexBinaryIDMap2_swiginit(self, _swigfaiss.new_IndexBinaryIDMap2(*args))

# Register IndexBinaryIDMap2 in _swigfaiss:
_swigfaiss.IndexBinaryIDMap2_swigregister(IndexBinaryIDMap2)
EXACT_TOPK = _swigfaiss.EXACT_TOPK
APPROX_TOPK_BUCKETS_B32_D2 = _swigfaiss.APPROX_TOPK_BUCKETS_B32_D2
APPROX_TOPK_BUCKETS_B8_D3 = _swigfaiss.APPROX_TOPK_BUCKETS_B8_D3
APPROX_TOPK_BUCKETS_B16_D2 = _swigfaiss.APPROX_TOPK_BUCKETS_B16_D2
APPROX_TOPK_BUCKETS_B8_D2 = _swigfaiss.APPROX_TOPK_BUCKETS_B8_D2

def approx_topk_by_mode(mode, beam_size, n_per_beam, distances, k, bh_val, bh_ids):
    return _swigfaiss.approx_topk_by_mode(mode, beam_size, n_per_beam, distances, k, bh_val, bh_ids)

def downcast_index(index):
    return _swigfaiss.downcast_index(index)

def downcast_VectorTransform(vt):
    return _swigfaiss.downcast_VectorTransform(vt)

def downcast_IndexBinary(index):
    return _swigfaiss.downcast_IndexBinary(index)

def downcast_InvertedLists(il):
    return _swigfaiss.downcast_InvertedLists(il)

def downcast_AdditiveQuantizer(aq):
    return _swigfaiss.downcast_AdditiveQuantizer(aq)

def downcast_Quantizer(aq):
    return _swigfaiss.downcast_Quantizer(aq)

def write_index(*args):
    return _swigfaiss.write_index(*args)

def write_index_binary(*args):
    return _swigfaiss.write_index_binary(*args)

def read_index(*args):
    return _swigfaiss.read_index(*args)

def read_index_binary(*args):
    return _swigfaiss.read_index_binary(*args)

def write_VectorTransform(*args):
    return _swigfaiss.write_VectorTransform(*args)

def read_VectorTransform(*args):
    return _swigfaiss.read_VectorTransform(*args)

def read_ProductQuantizer(*args):
    return _swigfaiss.read_ProductQuantizer(*args)

def write_ProductQuantizer(*args):
    return _swigfaiss.write_ProductQuantizer(*args)

def write_InvertedLists(ils, f):
    return _swigfaiss.write_InvertedLists(ils, f)

def read_InvertedLists(reader, io_flags=0):
    return _swigfaiss.read_InvertedLists(reader, io_flags)

def get_deserialization_loop_limit():
    return _swigfaiss.get_deserialization_loop_limit()

def set_deserialization_loop_limit(value):
    return _swigfaiss.set_deserialization_loop_limit(value)

def get_deserialization_vector_byte_limit():
    return _swigfaiss.get_deserialization_vector_byte_limit()

def set_deserialization_vector_byte_limit(value):
    return _swigfaiss.set_deserialization_vector_byte_limit(value)

def get_deserialization_lattice_r2_limit():
    return _swigfaiss.get_deserialization_lattice_r2_limit()

def set_deserialization_lattice_r2_limit(value):
    return _swigfaiss.set_deserialization_lattice_r2_limit(value)

def clone_index(arg1):
    return _swigfaiss.clone_index(arg1)
class Cloner(object):
    r"""
     Cloner class, useful to override classes with other cloning
    functions. The cloning function above just calls
    Cloner::clone_Index.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def clone_VectorTransform(self, arg2):
        return _swigfaiss.Cloner_clone_VectorTransform(self, arg2)

    def clone_Index(self, arg2):
        return _swigfaiss.Cloner_clone_Index(self, arg2)

    def clone_IndexIVF(self, arg2):
        return _swigfaiss.Cloner_clone_IndexIVF(self, arg2)
    __swig_destroy__ = _swigfaiss.delete_Cloner

    def __init__(self):
        _swigfaiss.Cloner_swiginit(self, _swigfaiss.new_Cloner())

# Register Cloner in _swigfaiss:
_swigfaiss.Cloner_swigregister(Cloner)
IO_FLAG_SKIP_STORAGE = cvar.IO_FLAG_SKIP_STORAGE
IO_FLAG_READ_ONLY = cvar.IO_FLAG_READ_ONLY
IO_FLAG_ONDISK_SAME_DIR = cvar.IO_FLAG_ONDISK_SAME_DIR
IO_FLAG_SKIP_IVF_DATA = cvar.IO_FLAG_SKIP_IVF_DATA
IO_FLAG_SKIP_PRECOMPUTE_TABLE = cvar.IO_FLAG_SKIP_PRECOMPUTE_TABLE
IO_FLAG_PQ_SKIP_SDC_TABLE = cvar.IO_FLAG_PQ_SKIP_SDC_TABLE
IO_FLAG_MMAP = cvar.IO_FLAG_MMAP
IO_FLAG_MMAP_IFC = cvar.IO_FLAG_MMAP_IFC


def clone_Quantizer(quant):
    return _swigfaiss.clone_Quantizer(quant)

def clone_binary_index(index):
    return _swigfaiss.clone_binary_index(index)
class AutoTuneCriterion(object):
    r"""
    Evaluation criterion. Returns a performance measure in [0,1],
    higher is better.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined - class is abstract")
    __repr__ = _swig_repr
    nq = property(_swigfaiss.AutoTuneCriterion_nq_get, _swigfaiss.AutoTuneCriterion_nq_set, doc=r"""nb of queries this criterion is evaluated on""")
    nnn = property(_swigfaiss.AutoTuneCriterion_nnn_get, _swigfaiss.AutoTuneCriterion_nnn_set, doc=r"""nb of NNs that the query should request""")
    gt_nnn = property(_swigfaiss.AutoTuneCriterion_gt_nnn_get, _swigfaiss.AutoTuneCriterion_gt_nnn_set, doc=r"""nb of GT NNs required to evaluate criterion""")
    gt_D = property(_swigfaiss.AutoTuneCriterion_gt_D_get, _swigfaiss.AutoTuneCriterion_gt_D_set, doc=r"""Ground-truth distances (size nq * gt_nnn)""")
    gt_I = property(_swigfaiss.AutoTuneCriterion_gt_I_get, _swigfaiss.AutoTuneCriterion_gt_I_set, doc=r"""Ground-truth indexes (size nq * gt_nnn)""")

    def set_groundtruth(self, gt_nnn, gt_D_in, gt_I_in):
        r"""
         Initializes the gt_D and gt_I vectors. Must be called before evaluating

        :type gt_D_in: float
        :param gt_D_in:  size nq * gt_nnn
        :type gt_I_in: int
        :param gt_I_in:  size nq * gt_nnn
        """
        return _swigfaiss.AutoTuneCriterion_set_groundtruth(self, gt_nnn, gt_D_in, gt_I_in)

    def evaluate(self, D, I):
        r"""
         Evaluate the criterion.

        :type D: float
        :param D:  size nq * nnn
        :type I: int
        :param I:  size nq * nnn
        :rtype: float
        :return: the criterion, between 0 and 1. Larger is better.
        """
        return _swigfaiss.AutoTuneCriterion_evaluate(self, D, I)
    __swig_destroy__ = _swigfaiss.delete_AutoTuneCriterion

# Register AutoTuneCriterion in _swigfaiss:
_swigfaiss.AutoTuneCriterion_swigregister(AutoTuneCriterion)
class OneRecallAtRCriterion(AutoTuneCriterion):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    R = property(_swigfaiss.OneRecallAtRCriterion_R_get, _swigfaiss.OneRecallAtRCriterion_R_set)

    def __init__(self, nq, R):
        _swigfaiss.OneRecallAtRCriterion_swiginit(self, _swigfaiss.new_OneRecallAtRCriterion(nq, R))

    def evaluate(self, D, I):
        return _swigfaiss.OneRecallAtRCriterion_evaluate(self, D, I)
    __swig_destroy__ = _swigfaiss.delete_OneRecallAtRCriterion

# Register OneRecallAtRCriterion in _swigfaiss:
_swigfaiss.OneRecallAtRCriterion_swigregister(OneRecallAtRCriterion)
class IntersectionCriterion(AutoTuneCriterion):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    R = property(_swigfaiss.IntersectionCriterion_R_get, _swigfaiss.IntersectionCriterion_R_set)

    def __init__(self, nq, R):
        _swigfaiss.IntersectionCriterion_swiginit(self, _swigfaiss.new_IntersectionCriterion(nq, R))

    def evaluate(self, D, I):
        return _swigfaiss.IntersectionCriterion_evaluate(self, D, I)
    __swig_destroy__ = _swigfaiss.delete_IntersectionCriterion

# Register IntersectionCriterion in _swigfaiss:
_swigfaiss.IntersectionCriterion_swigregister(IntersectionCriterion)
class OperatingPoint(object):
    r"""
    Maintains a list of experimental results. Each operating point is a
    (perf, t, key) triplet, where higher perf and lower t is
    better. The key field is an arbitrary identifier for the operating point.

    Includes primitives to extract the Pareto-optimal operating points in the
    (perf, t) space.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    perf = property(_swigfaiss.OperatingPoint_perf_get, _swigfaiss.OperatingPoint_perf_set, doc=r"""performance measure (output of a Criterion)""")
    t = property(_swigfaiss.OperatingPoint_t_get, _swigfaiss.OperatingPoint_t_set, doc=r"""corresponding execution time (ms)""")
    key = property(_swigfaiss.OperatingPoint_key_get, _swigfaiss.OperatingPoint_key_set, doc=r"""key that identifies this op pt""")
    cno = property(_swigfaiss.OperatingPoint_cno_get, _swigfaiss.OperatingPoint_cno_set, doc=r"""integer identifier""")

    def __init__(self):
        _swigfaiss.OperatingPoint_swiginit(self, _swigfaiss.new_OperatingPoint())
    __swig_destroy__ = _swigfaiss.delete_OperatingPoint

# Register OperatingPoint in _swigfaiss:
_swigfaiss.OperatingPoint_swigregister(OperatingPoint)
class OperatingPoints(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    all_pts = property(_swigfaiss.OperatingPoints_all_pts_get, _swigfaiss.OperatingPoints_all_pts_set, doc=r"""all operating points""")
    optimal_pts = property(_swigfaiss.OperatingPoints_optimal_pts_get, _swigfaiss.OperatingPoints_optimal_pts_set, doc=r"""optimal operating points, sorted by perf""")

    def __init__(self):
        _swigfaiss.OperatingPoints_swiginit(self, _swigfaiss.new_OperatingPoints())

    def merge_with(self, *args):
        r"""add operating points from other to this, with a prefix to the keys"""
        return _swigfaiss.OperatingPoints_merge_with(self, *args)

    def clear(self):
        return _swigfaiss.OperatingPoints_clear(self)

    def add(self, perf, t, key, cno=0):
        r"""add a performance measure. Return whether it is an optimal point"""
        return _swigfaiss.OperatingPoints_add(self, perf, t, key, cno)

    def t_for_perf(self, perf):
        r"""get time required to obtain a given performance measure"""
        return _swigfaiss.OperatingPoints_t_for_perf(self, perf)

    def display(self, only_optimal=True):
        r"""easy-to-read output"""
        return _swigfaiss.OperatingPoints_display(self, only_optimal)

    def all_to_gnuplot(self, fname):
        r"""output to a format easy to digest by gnuplot"""
        return _swigfaiss.OperatingPoints_all_to_gnuplot(self, fname)

    def optimal_to_gnuplot(self, fname):
        return _swigfaiss.OperatingPoints_optimal_to_gnuplot(self, fname)
    __swig_destroy__ = _swigfaiss.delete_OperatingPoints

# Register OperatingPoints in _swigfaiss:
_swigfaiss.OperatingPoints_swigregister(OperatingPoints)
class ParameterRange(object):
    r"""possible values of a parameter, sorted from least to most expensive/accurate"""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    name = property(_swigfaiss.ParameterRange_name_get, _swigfaiss.ParameterRange_name_set)
    values = property(_swigfaiss.ParameterRange_values_get, _swigfaiss.ParameterRange_values_set)

    def __init__(self):
        _swigfaiss.ParameterRange_swiginit(self, _swigfaiss.new_ParameterRange())
    __swig_destroy__ = _swigfaiss.delete_ParameterRange

# Register ParameterRange in _swigfaiss:
_swigfaiss.ParameterRange_swigregister(ParameterRange)
class ParameterSpace(object):
    r"""Uses a-priori knowledge on the Faiss indexes to extract tunable parameters."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    parameter_ranges = property(_swigfaiss.ParameterSpace_parameter_ranges_get, _swigfaiss.ParameterSpace_parameter_ranges_set, doc=r"""all tunable parameters""")
    verbose = property(_swigfaiss.ParameterSpace_verbose_get, _swigfaiss.ParameterSpace_verbose_set, doc=r"""verbosity during exploration""")
    n_experiments = property(_swigfaiss.ParameterSpace_n_experiments_get, _swigfaiss.ParameterSpace_n_experiments_set, doc=r"""nb of experiments during optimization (0 = try all combinations)""")
    batchsize = property(_swigfaiss.ParameterSpace_batchsize_get, _swigfaiss.ParameterSpace_batchsize_set, doc=r"""maximum number of queries to submit at a time.""")
    thread_over_batches = property(_swigfaiss.ParameterSpace_thread_over_batches_get, _swigfaiss.ParameterSpace_thread_over_batches_set, doc=r"""
    use multithreading over batches (useful to benchmark
    independent single-searches)
    """)
    min_test_duration = property(_swigfaiss.ParameterSpace_min_test_duration_get, _swigfaiss.ParameterSpace_min_test_duration_set, doc=r"""
    run tests several times until they reach at least this
    duration (to avoid jittering in MT mode)
    """)

    def __init__(self):
        _swigfaiss.ParameterSpace_swiginit(self, _swigfaiss.new_ParameterSpace())

    def n_combinations(self):
        r"""nb of combinations, = product of values sizes"""
        return _swigfaiss.ParameterSpace_n_combinations(self)

    def combination_ge(self, c1, c2):
        r"""returns whether combinations c1 >= c2 in the tuple sense"""
        return _swigfaiss.ParameterSpace_combination_ge(self, c1, c2)

    def combination_name(self, cno):
        r"""get string representation of the combination"""
        return _swigfaiss.ParameterSpace_combination_name(self, cno)

    def display(self):
        r"""print a description on stdout"""
        return _swigfaiss.ParameterSpace_display(self)

    def add_range(self, name):
        r"""add a new parameter (or return it if it exists)"""
        return _swigfaiss.ParameterSpace_add_range(self, name)

    def initialize(self, index):
        r"""initialize with reasonable parameters for the index"""
        return _swigfaiss.ParameterSpace_initialize(self, index)

    def set_index_parameters(self, *args):
        r"""
        *Overload 1:*
        set a combination of parameters on an index

        |

        *Overload 2:*
        set a combination of parameters described by a string

        |

        *Overload 3:*
        set a combination of parameters on a binary index

        |

        *Overload 4:*
        set a combination of parameters described by a string on a binary index
        """
        return _swigfaiss.ParameterSpace_set_index_parameters(self, *args)

    def set_index_parameter(self, *args):
        r"""
        *Overload 1:*
        set one of the parameters

        |

        *Overload 2:*
        set one of the parameters on a binary index
        """
        return _swigfaiss.ParameterSpace_set_index_parameter(self, *args)

    def update_bounds(self, cno, op, upper_bound_perf, lower_bound_t):
        r"""
         find an upper bound on the performance and a lower bound on t
        for configuration cno given another operating point op
        """
        return _swigfaiss.ParameterSpace_update_bounds(self, cno, op, upper_bound_perf, lower_bound_t)

    def explore(self, index, nq, xq, crit, ops):
        r"""
         explore operating points
        :type index: :py:class:`Index`
        :param index:   index to run on
        :type xq: float
        :param xq:      query vectors (size nq * index.d)
        :type crit: :py:class:`AutoTuneCriterion`
        :param crit:    selection criterion
        :type ops: :py:class:`OperatingPoints`
        :param ops:     resulting operating points
        """
        return _swigfaiss.ParameterSpace_explore(self, index, nq, xq, crit, ops)
    __swig_destroy__ = _swigfaiss.delete_ParameterSpace

# Register ParameterSpace in _swigfaiss:
_swigfaiss.ParameterSpace_swigregister(ParameterSpace)

def index_factory(*args):
    r"""
    Build an index with the sequence of processing steps described in
    the string.
    """
    return _swigfaiss.index_factory(*args)

def index_binary_factory(d, description, own_invlists=True):
    return _swigfaiss.index_binary_factory(d, description, own_invlists)
class MatrixStats(object):
    r"""
     Reports some statistics on a dataset and comments on them.

    It is a class rather than a function so that all stats can also be
    accessed from code
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self, n, d, x):
        _swigfaiss.MatrixStats_swiginit(self, _swigfaiss.new_MatrixStats(n, d, x))
    comments = property(_swigfaiss.MatrixStats_comments_get, _swigfaiss.MatrixStats_comments_set)
    n = property(_swigfaiss.MatrixStats_n_get, _swigfaiss.MatrixStats_n_set)
    d = property(_swigfaiss.MatrixStats_d_get, _swigfaiss.MatrixStats_d_set)
    n_collision = property(_swigfaiss.MatrixStats_n_collision_get, _swigfaiss.MatrixStats_n_collision_set)
    n_valid = property(_swigfaiss.MatrixStats_n_valid_get, _swigfaiss.MatrixStats_n_valid_set)
    n0 = property(_swigfaiss.MatrixStats_n0_get, _swigfaiss.MatrixStats_n0_set)
    min_norm2 = property(_swigfaiss.MatrixStats_min_norm2_get, _swigfaiss.MatrixStats_min_norm2_set)
    max_norm2 = property(_swigfaiss.MatrixStats_max_norm2_get, _swigfaiss.MatrixStats_max_norm2_set)
    hash_value = property(_swigfaiss.MatrixStats_hash_value_get, _swigfaiss.MatrixStats_hash_value_set)
    per_dim_stats = property(_swigfaiss.MatrixStats_per_dim_stats_get, _swigfaiss.MatrixStats_per_dim_stats_set)
    occurrences = property(_swigfaiss.MatrixStats_occurrences_get, _swigfaiss.MatrixStats_occurrences_set)
    buf = property(_swigfaiss.MatrixStats_buf_get, _swigfaiss.MatrixStats_buf_set)
    nbuf = property(_swigfaiss.MatrixStats_nbuf_get, _swigfaiss.MatrixStats_nbuf_set)

    def do_comment(self, fmt):
        return _swigfaiss.MatrixStats_do_comment(self, fmt)
    __swig_destroy__ = _swigfaiss.delete_MatrixStats

# Register MatrixStats in _swigfaiss:
_swigfaiss.MatrixStats_swigregister(MatrixStats)
class PyCallbackIOWriter(IOWriter):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    callback = property(_swigfaiss.PyCallbackIOWriter_callback_get, _swigfaiss.PyCallbackIOWriter_callback_set)
    bs = property(_swigfaiss.PyCallbackIOWriter_bs_get, _swigfaiss.PyCallbackIOWriter_bs_set)

    def __init__(self, *args):
        r"""
        Callback: Python function that takes a bytes object and
        returns the number of bytes successfully written.
        """
        _swigfaiss.PyCallbackIOWriter_swiginit(self, _swigfaiss.new_PyCallbackIOWriter(*args))

    def __call__(self, ptrv, size, nitems):
        return _swigfaiss.PyCallbackIOWriter___call__(self, ptrv, size, nitems)
    __swig_destroy__ = _swigfaiss.delete_PyCallbackIOWriter

# Register PyCallbackIOWriter in _swigfaiss:
_swigfaiss.PyCallbackIOWriter_swigregister(PyCallbackIOWriter)
class PyCallbackIOReader(IOReader):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    callback = property(_swigfaiss.PyCallbackIOReader_callback_get, _swigfaiss.PyCallbackIOReader_callback_set)
    bs = property(_swigfaiss.PyCallbackIOReader_bs_get, _swigfaiss.PyCallbackIOReader_bs_set)

    def __init__(self, *args):
        r"""
         Callback: Python function that takes a size and returns a
        bytes object with the resulting read
        """
        _swigfaiss.PyCallbackIOReader_swiginit(self, _swigfaiss.new_PyCallbackIOReader(*args))

    def __call__(self, ptrv, size, nitems):
        return _swigfaiss.PyCallbackIOReader___call__(self, ptrv, size, nitems)
    __swig_destroy__ = _swigfaiss.delete_PyCallbackIOReader

# Register PyCallbackIOReader in _swigfaiss:
_swigfaiss.PyCallbackIOReader_swigregister(PyCallbackIOReader)
class PyCallbackIDSelector(IDSelector):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    callback = property(_swigfaiss.PyCallbackIDSelector_callback_get, _swigfaiss.PyCallbackIDSelector_callback_set)

    def __init__(self, callback):
        _swigfaiss.PyCallbackIDSelector_swiginit(self, _swigfaiss.new_PyCallbackIDSelector(callback))

    def is_member(self, id):
        return _swigfaiss.PyCallbackIDSelector_is_member(self, id)
    __swig_destroy__ = _swigfaiss.delete_PyCallbackIDSelector

# Register PyCallbackIDSelector in _swigfaiss:
_swigfaiss.PyCallbackIDSelector_swigregister(PyCallbackIDSelector)
class PyCallbackShardingFunction(ShardingFunction):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    callback = property(_swigfaiss.PyCallbackShardingFunction_callback_get, _swigfaiss.PyCallbackShardingFunction_callback_set)

    def __call__(self, i, shard_count):
        return _swigfaiss.PyCallbackShardingFunction___call__(self, i, shard_count)
    __swig_destroy__ = _swigfaiss.delete_PyCallbackShardingFunction

    def __init__(self, *args):
        _swigfaiss.PyCallbackShardingFunction_swiginit(self, _swigfaiss.new_PyCallbackShardingFunction(*args))

# Register PyCallbackShardingFunction in _swigfaiss:
_swigfaiss.PyCallbackShardingFunction_swigregister(PyCallbackShardingFunction)
class float_minheap_array_t(object):
    r"""
     a template structure for a set of [min|max]-heaps it is tailored
    so that the actual data of the heaps can just live in compact
    arrays.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nh = property(_swigfaiss.float_minheap_array_t_nh_get, _swigfaiss.float_minheap_array_t_nh_set, doc=r"""number of heaps""")
    k = property(_swigfaiss.float_minheap_array_t_k_get, _swigfaiss.float_minheap_array_t_k_set, doc=r"""allocated size per heap""")
    ids = property(_swigfaiss.float_minheap_array_t_ids_get, _swigfaiss.float_minheap_array_t_ids_set, doc=r"""identifiers (size nh * k)""")
    val = property(_swigfaiss.float_minheap_array_t_val_get, _swigfaiss.float_minheap_array_t_val_set, doc=r"""values (distances or similarities), size nh * k""")

    def get_val(self, key):
        r"""Return the list of values for a heap"""
        return _swigfaiss.float_minheap_array_t_get_val(self, key)

    def get_ids(self, key):
        r"""Corresponding identifiers"""
        return _swigfaiss.float_minheap_array_t_get_ids(self, key)

    def heapify(self):
        r"""prepare all the heaps before adding"""
        return _swigfaiss.float_minheap_array_t_heapify(self)

    def addn(self, nj, vin, j0=0, i0=0, ni=-1):
        r"""
         add nj elements to heaps i0:i0+ni, with sequential ids

        :type nj: int
        :param nj:    nb of elements to add to each heap
        :type vin: float
        :param vin:   elements to add, size ni * nj
        :type j0: int, optional
        :param j0:    add this to the ids that are added
        :type i0: int, optional
        :param i0:    first heap to update
        :type ni: int, optional
        :param ni:    nb of elements to update (-1 = use nh)
        """
        return _swigfaiss.float_minheap_array_t_addn(self, nj, vin, j0, i0, ni)

    def addn_with_ids(self, nj, vin, id_in=None, id_stride=0, i0=0, ni=-1):
        r"""
         same as addn

        :type id_in: int, optional
        :param id_in:     ids of the elements to add, size ni * nj
        :type id_stride: int, optional
        :param id_stride: stride for id_in
        """
        return _swigfaiss.float_minheap_array_t_addn_with_ids(self, nj, vin, id_in, id_stride, i0, ni)

    def addn_query_subset_with_ids(self, nsubset, subset, nj, vin, id_in=None, id_stride=0):
        r"""
         same as addn_with_ids, but for just a subset of queries

        :type nsubset: int
        :param nsubset:  number of query entries to update
        :type subset: int
        :param subset:   indexes of queries to update, in 0..nh-1, size nsubset
        """
        return _swigfaiss.float_minheap_array_t_addn_query_subset_with_ids(self, nsubset, subset, nj, vin, id_in, id_stride)

    def reorder(self):
        r"""reorder all the heaps"""
        return _swigfaiss.float_minheap_array_t_reorder(self)

    def per_line_extrema(self, vals_out, idx_out):
        r"""
         this is not really a heap function. It just finds the per-line
          extrema of each line of array D
        :type vals_out: float
        :param vals_out:    extreme value of each line (size nh, or NULL)
        :type idx_out: int
        :param idx_out:     index of extreme value (size nh or NULL)
        """
        return _swigfaiss.float_minheap_array_t_per_line_extrema(self, vals_out, idx_out)

    def __init__(self):
        _swigfaiss.float_minheap_array_t_swiginit(self, _swigfaiss.new_float_minheap_array_t())
    __swig_destroy__ = _swigfaiss.delete_float_minheap_array_t

# Register float_minheap_array_t in _swigfaiss:
_swigfaiss.float_minheap_array_t_swigregister(float_minheap_array_t)
class int_minheap_array_t(object):
    r"""
     a template structure for a set of [min|max]-heaps it is tailored
    so that the actual data of the heaps can just live in compact
    arrays.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nh = property(_swigfaiss.int_minheap_array_t_nh_get, _swigfaiss.int_minheap_array_t_nh_set, doc=r"""number of heaps""")
    k = property(_swigfaiss.int_minheap_array_t_k_get, _swigfaiss.int_minheap_array_t_k_set, doc=r"""allocated size per heap""")
    ids = property(_swigfaiss.int_minheap_array_t_ids_get, _swigfaiss.int_minheap_array_t_ids_set, doc=r"""identifiers (size nh * k)""")
    val = property(_swigfaiss.int_minheap_array_t_val_get, _swigfaiss.int_minheap_array_t_val_set, doc=r"""values (distances or similarities), size nh * k""")

    def get_val(self, key):
        r"""Return the list of values for a heap"""
        return _swigfaiss.int_minheap_array_t_get_val(self, key)

    def get_ids(self, key):
        r"""Corresponding identifiers"""
        return _swigfaiss.int_minheap_array_t_get_ids(self, key)

    def heapify(self):
        r"""prepare all the heaps before adding"""
        return _swigfaiss.int_minheap_array_t_heapify(self)

    def addn(self, nj, vin, j0=0, i0=0, ni=-1):
        r"""
         add nj elements to heaps i0:i0+ni, with sequential ids

        :type nj: int
        :param nj:    nb of elements to add to each heap
        :type vin: int
        :param vin:   elements to add, size ni * nj
        :type j0: int, optional
        :param j0:    add this to the ids that are added
        :type i0: int, optional
        :param i0:    first heap to update
        :type ni: int, optional
        :param ni:    nb of elements to update (-1 = use nh)
        """
        return _swigfaiss.int_minheap_array_t_addn(self, nj, vin, j0, i0, ni)

    def addn_with_ids(self, nj, vin, id_in=None, id_stride=0, i0=0, ni=-1):
        r"""
         same as addn

        :type id_in: int, optional
        :param id_in:     ids of the elements to add, size ni * nj
        :type id_stride: int, optional
        :param id_stride: stride for id_in
        """
        return _swigfaiss.int_minheap_array_t_addn_with_ids(self, nj, vin, id_in, id_stride, i0, ni)

    def addn_query_subset_with_ids(self, nsubset, subset, nj, vin, id_in=None, id_stride=0):
        r"""
         same as addn_with_ids, but for just a subset of queries

        :type nsubset: int
        :param nsubset:  number of query entries to update
        :type subset: int
        :param subset:   indexes of queries to update, in 0..nh-1, size nsubset
        """
        return _swigfaiss.int_minheap_array_t_addn_query_subset_with_ids(self, nsubset, subset, nj, vin, id_in, id_stride)

    def reorder(self):
        r"""reorder all the heaps"""
        return _swigfaiss.int_minheap_array_t_reorder(self)

    def per_line_extrema(self, vals_out, idx_out):
        r"""
         this is not really a heap function. It just finds the per-line
          extrema of each line of array D
        :type vals_out: int
        :param vals_out:    extreme value of each line (size nh, or NULL)
        :type idx_out: int
        :param idx_out:     index of extreme value (size nh or NULL)
        """
        return _swigfaiss.int_minheap_array_t_per_line_extrema(self, vals_out, idx_out)

    def __init__(self):
        _swigfaiss.int_minheap_array_t_swiginit(self, _swigfaiss.new_int_minheap_array_t())
    __swig_destroy__ = _swigfaiss.delete_int_minheap_array_t

# Register int_minheap_array_t in _swigfaiss:
_swigfaiss.int_minheap_array_t_swigregister(int_minheap_array_t)
class float_maxheap_array_t(object):
    r"""
     a template structure for a set of [min|max]-heaps it is tailored
    so that the actual data of the heaps can just live in compact
    arrays.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nh = property(_swigfaiss.float_maxheap_array_t_nh_get, _swigfaiss.float_maxheap_array_t_nh_set, doc=r"""number of heaps""")
    k = property(_swigfaiss.float_maxheap_array_t_k_get, _swigfaiss.float_maxheap_array_t_k_set, doc=r"""allocated size per heap""")
    ids = property(_swigfaiss.float_maxheap_array_t_ids_get, _swigfaiss.float_maxheap_array_t_ids_set, doc=r"""identifiers (size nh * k)""")
    val = property(_swigfaiss.float_maxheap_array_t_val_get, _swigfaiss.float_maxheap_array_t_val_set, doc=r"""values (distances or similarities), size nh * k""")

    def get_val(self, key):
        r"""Return the list of values for a heap"""
        return _swigfaiss.float_maxheap_array_t_get_val(self, key)

    def get_ids(self, key):
        r"""Corresponding identifiers"""
        return _swigfaiss.float_maxheap_array_t_get_ids(self, key)

    def heapify(self):
        r"""prepare all the heaps before adding"""
        return _swigfaiss.float_maxheap_array_t_heapify(self)

    def addn(self, nj, vin, j0=0, i0=0, ni=-1):
        r"""
         add nj elements to heaps i0:i0+ni, with sequential ids

        :type nj: int
        :param nj:    nb of elements to add to each heap
        :type vin: float
        :param vin:   elements to add, size ni * nj
        :type j0: int, optional
        :param j0:    add this to the ids that are added
        :type i0: int, optional
        :param i0:    first heap to update
        :type ni: int, optional
        :param ni:    nb of elements to update (-1 = use nh)
        """
        return _swigfaiss.float_maxheap_array_t_addn(self, nj, vin, j0, i0, ni)

    def addn_with_ids(self, nj, vin, id_in=None, id_stride=0, i0=0, ni=-1):
        r"""
         same as addn

        :type id_in: int, optional
        :param id_in:     ids of the elements to add, size ni * nj
        :type id_stride: int, optional
        :param id_stride: stride for id_in
        """
        return _swigfaiss.float_maxheap_array_t_addn_with_ids(self, nj, vin, id_in, id_stride, i0, ni)

    def addn_query_subset_with_ids(self, nsubset, subset, nj, vin, id_in=None, id_stride=0):
        r"""
         same as addn_with_ids, but for just a subset of queries

        :type nsubset: int
        :param nsubset:  number of query entries to update
        :type subset: int
        :param subset:   indexes of queries to update, in 0..nh-1, size nsubset
        """
        return _swigfaiss.float_maxheap_array_t_addn_query_subset_with_ids(self, nsubset, subset, nj, vin, id_in, id_stride)

    def reorder(self):
        r"""reorder all the heaps"""
        return _swigfaiss.float_maxheap_array_t_reorder(self)

    def per_line_extrema(self, vals_out, idx_out):
        r"""
         this is not really a heap function. It just finds the per-line
          extrema of each line of array D
        :type vals_out: float
        :param vals_out:    extreme value of each line (size nh, or NULL)
        :type idx_out: int
        :param idx_out:     index of extreme value (size nh or NULL)
        """
        return _swigfaiss.float_maxheap_array_t_per_line_extrema(self, vals_out, idx_out)

    def __init__(self):
        _swigfaiss.float_maxheap_array_t_swiginit(self, _swigfaiss.new_float_maxheap_array_t())
    __swig_destroy__ = _swigfaiss.delete_float_maxheap_array_t

# Register float_maxheap_array_t in _swigfaiss:
_swigfaiss.float_maxheap_array_t_swigregister(float_maxheap_array_t)
class int_maxheap_array_t(object):
    r"""
     a template structure for a set of [min|max]-heaps it is tailored
    so that the actual data of the heaps can just live in compact
    arrays.
    """

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    nh = property(_swigfaiss.int_maxheap_array_t_nh_get, _swigfaiss.int_maxheap_array_t_nh_set, doc=r"""number of heaps""")
    k = property(_swigfaiss.int_maxheap_array_t_k_get, _swigfaiss.int_maxheap_array_t_k_set, doc=r"""allocated size per heap""")
    ids = property(_swigfaiss.int_maxheap_array_t_ids_get, _swigfaiss.int_maxheap_array_t_ids_set, doc=r"""identifiers (size nh * k)""")
    val = property(_swigfaiss.int_maxheap_array_t_val_get, _swigfaiss.int_maxheap_array_t_val_set, doc=r"""values (distances or similarities), size nh * k""")

    def get_val(self, key):
        r"""Return the list of values for a heap"""
        return _swigfaiss.int_maxheap_array_t_get_val(self, key)

    def get_ids(self, key):
        r"""Corresponding identifiers"""
        return _swigfaiss.int_maxheap_array_t_get_ids(self, key)

    def heapify(self):
        r"""prepare all the heaps before adding"""
        return _swigfaiss.int_maxheap_array_t_heapify(self)

    def addn(self, nj, vin, j0=0, i0=0, ni=-1):
        r"""
         add nj elements to heaps i0:i0+ni, with sequential ids

        :type nj: int
        :param nj:    nb of elements to add to each heap
        :type vin: int
        :param vin:   elements to add, size ni * nj
        :type j0: int, optional
        :param j0:    add this to the ids that are added
        :type i0: int, optional
        :param i0:    first heap to update
        :type ni: int, optional
        :param ni:    nb of elements to update (-1 = use nh)
        """
        return _swigfaiss.int_maxheap_array_t_addn(self, nj, vin, j0, i0, ni)

    def addn_with_ids(self, nj, vin, id_in=None, id_stride=0, i0=0, ni=-1):
        r"""
         same as addn

        :type id_in: int, optional
        :param id_in:     ids of the elements to add, size ni * nj
        :type id_stride: int, optional
        :param id_stride: stride for id_in
        """
        return _swigfaiss.int_maxheap_array_t_addn_with_ids(self, nj, vin, id_in, id_stride, i0, ni)

    def addn_query_subset_with_ids(self, nsubset, subset, nj, vin, id_in=None, id_stride=0):
        r"""
         same as addn_with_ids, but for just a subset of queries

        :type nsubset: int
        :param nsubset:  number of query entries to update
        :type subset: int
        :param subset:   indexes of queries to update, in 0..nh-1, size nsubset
        """
        return _swigfaiss.int_maxheap_array_t_addn_query_subset_with_ids(self, nsubset, subset, nj, vin, id_in, id_stride)

    def reorder(self):
        r"""reorder all the heaps"""
        return _swigfaiss.int_maxheap_array_t_reorder(self)

    def per_line_extrema(self, vals_out, idx_out):
        r"""
         this is not really a heap function. It just finds the per-line
          extrema of each line of array D
        :type vals_out: int
        :param vals_out:    extreme value of each line (size nh, or NULL)
        :type idx_out: int
        :param idx_out:     index of extreme value (size nh or NULL)
        """
        return _swigfaiss.int_maxheap_array_t_per_line_extrema(self, vals_out, idx_out)

    def __init__(self):
        _swigfaiss.int_maxheap_array_t_swiginit(self, _swigfaiss.new_int_maxheap_array_t())
    __swig_destroy__ = _swigfaiss.delete_int_maxheap_array_t

# Register int_maxheap_array_t in _swigfaiss:
_swigfaiss.int_maxheap_array_t_swigregister(int_maxheap_array_t)

def CMin_float_partition_fuzzy(vals, ids, n, q_min, q_max, q_out):
    r"""
     partitions the table into 0:q and q:n where all elements above q are >= all
    elements below q (for C = CMax, for CMin comparisons are reversed)

    Returns the partition threshold. The elements q:n are destroyed on output.
    """
    return _swigfaiss.CMin_float_partition_fuzzy(vals, ids, n, q_min, q_max, q_out)

def CMax_float_partition_fuzzy(vals, ids, n, q_min, q_max, q_out):
    r"""
     partitions the table into 0:q and q:n where all elements above q are >= all
    elements below q (for C = CMax, for CMin comparisons are reversed)

    Returns the partition threshold. The elements q:n are destroyed on output.
    """
    return _swigfaiss.CMax_float_partition_fuzzy(vals, ids, n, q_min, q_max, q_out)
class AlignedTableUint8(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    tab = property(_swigfaiss.AlignedTableUint8_tab_get, _swigfaiss.AlignedTableUint8_tab_set)
    numel = property(_swigfaiss.AlignedTableUint8_numel_get, _swigfaiss.AlignedTableUint8_numel_set)

    @staticmethod
    def round_capacity(n):
        return _swigfaiss.AlignedTableUint8_round_capacity(n)

    def __init__(self, *args):
        _swigfaiss.AlignedTableUint8_swiginit(self, _swigfaiss.new_AlignedTableUint8(*args))

    def itemsize(self):
        return _swigfaiss.AlignedTableUint8_itemsize(self)

    def resize(self, n):
        return _swigfaiss.AlignedTableUint8_resize(self, n)

    def clear(self):
        return _swigfaiss.AlignedTableUint8_clear(self)

    def size(self):
        return _swigfaiss.AlignedTableUint8_size(self)

    def nbytes(self):
        return _swigfaiss.AlignedTableUint8_nbytes(self)

    def get(self, *args):
        return _swigfaiss.AlignedTableUint8_get(self, *args)

    def data(self, *args):
        return _swigfaiss.AlignedTableUint8_data(self, *args)
    __swig_destroy__ = _swigfaiss.delete_AlignedTableUint8

# Register AlignedTableUint8 in _swigfaiss:
_swigfaiss.AlignedTableUint8_swigregister(AlignedTableUint8)
class AlignedTableUint16(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    tab = property(_swigfaiss.AlignedTableUint16_tab_get, _swigfaiss.AlignedTableUint16_tab_set)
    numel = property(_swigfaiss.AlignedTableUint16_numel_get, _swigfaiss.AlignedTableUint16_numel_set)

    @staticmethod
    def round_capacity(n):
        return _swigfaiss.AlignedTableUint16_round_capacity(n)

    def __init__(self, *args):
        _swigfaiss.AlignedTableUint16_swiginit(self, _swigfaiss.new_AlignedTableUint16(*args))

    def itemsize(self):
        return _swigfaiss.AlignedTableUint16_itemsize(self)

    def resize(self, n):
        return _swigfaiss.AlignedTableUint16_resize(self, n)

    def clear(self):
        return _swigfaiss.AlignedTableUint16_clear(self)

    def size(self):
        return _swigfaiss.AlignedTableUint16_size(self)

    def nbytes(self):
        return _swigfaiss.AlignedTableUint16_nbytes(self)

    def get(self, *args):
        return _swigfaiss.AlignedTableUint16_get(self, *args)

    def data(self, *args):
        return _swigfaiss.AlignedTableUint16_data(self, *args)
    __swig_destroy__ = _swigfaiss.delete_AlignedTableUint16

# Register AlignedTableUint16 in _swigfaiss:
_swigfaiss.AlignedTableUint16_swigregister(AlignedTableUint16)
class AlignedTableFloat32(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    tab = property(_swigfaiss.AlignedTableFloat32_tab_get, _swigfaiss.AlignedTableFloat32_tab_set)
    numel = property(_swigfaiss.AlignedTableFloat32_numel_get, _swigfaiss.AlignedTableFloat32_numel_set)

    @staticmethod
    def round_capacity(n):
        return _swigfaiss.AlignedTableFloat32_round_capacity(n)

    def __init__(self, *args):
        _swigfaiss.AlignedTableFloat32_swiginit(self, _swigfaiss.new_AlignedTableFloat32(*args))

    def itemsize(self):
        return _swigfaiss.AlignedTableFloat32_itemsize(self)

    def resize(self, n):
        return _swigfaiss.AlignedTableFloat32_resize(self, n)

    def clear(self):
        return _swigfaiss.AlignedTableFloat32_clear(self)

    def size(self):
        return _swigfaiss.AlignedTableFloat32_size(self)

    def nbytes(self):
        return _swigfaiss.AlignedTableFloat32_nbytes(self)

    def get(self, *args):
        return _swigfaiss.AlignedTableFloat32_get(self, *args)

    def data(self, *args):
        return _swigfaiss.AlignedTableFloat32_data(self, *args)
    __swig_destroy__ = _swigfaiss.delete_AlignedTableFloat32

# Register AlignedTableFloat32 in _swigfaiss:
_swigfaiss.AlignedTableFloat32_swigregister(AlignedTableFloat32)
class MaybeOwnedVectorUInt8(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    is_owned = property(_swigfaiss.MaybeOwnedVectorUInt8_is_owned_get, _swigfaiss.MaybeOwnedVectorUInt8_is_owned_set)
    owned_data = property(_swigfaiss.MaybeOwnedVectorUInt8_owned_data_get, _swigfaiss.MaybeOwnedVectorUInt8_owned_data_set)
    view_data = property(_swigfaiss.MaybeOwnedVectorUInt8_view_data_get, _swigfaiss.MaybeOwnedVectorUInt8_view_data_set)
    view_size = property(_swigfaiss.MaybeOwnedVectorUInt8_view_size_get, _swigfaiss.MaybeOwnedVectorUInt8_view_size_set)
    owner = property(_swigfaiss.MaybeOwnedVectorUInt8_owner_get, _swigfaiss.MaybeOwnedVectorUInt8_owner_set)
    c_ptr = property(_swigfaiss.MaybeOwnedVectorUInt8_c_ptr_get, _swigfaiss.MaybeOwnedVectorUInt8_c_ptr_set)
    c_size = property(_swigfaiss.MaybeOwnedVectorUInt8_c_size_get, _swigfaiss.MaybeOwnedVectorUInt8_c_size_set)

    def __init__(self, *args):
        _swigfaiss.MaybeOwnedVectorUInt8_swiginit(self, _swigfaiss.new_MaybeOwnedVectorUInt8(*args))

    @staticmethod
    def create_view(address, n_elements, owner):
        return _swigfaiss.MaybeOwnedVectorUInt8_create_view(address, n_elements, owner)

    def data(self, *args):
        return _swigfaiss.MaybeOwnedVectorUInt8_data(self, *args)

    def size(self):
        return _swigfaiss.MaybeOwnedVectorUInt8_size(self)

    def byte_size(self):
        return _swigfaiss.MaybeOwnedVectorUInt8_byte_size(self)

    def at(self, *args):
        return _swigfaiss.MaybeOwnedVectorUInt8_at(self, *args)

    def begin(self, *args):
        return _swigfaiss.MaybeOwnedVectorUInt8_begin(self, *args)

    def end(self, *args):
        return _swigfaiss.MaybeOwnedVectorUInt8_end(self, *args)

    def erase(self, begin, end):
        return _swigfaiss.MaybeOwnedVectorUInt8_erase(self, begin, end)

    def clear(self):
        return _swigfaiss.MaybeOwnedVectorUInt8_clear(self)

    def resize(self, *args):
        return _swigfaiss.MaybeOwnedVectorUInt8_resize(self, *args)
    __swig_destroy__ = _swigfaiss.delete_MaybeOwnedVectorUInt8

# Register MaybeOwnedVectorUInt8 in _swigfaiss:
_swigfaiss.MaybeOwnedVectorUInt8_swigregister(MaybeOwnedVectorUInt8)
class MaybeOwnedVectorInt32(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    is_owned = property(_swigfaiss.MaybeOwnedVectorInt32_is_owned_get, _swigfaiss.MaybeOwnedVectorInt32_is_owned_set)
    owned_data = property(_swigfaiss.MaybeOwnedVectorInt32_owned_data_get, _swigfaiss.MaybeOwnedVectorInt32_owned_data_set)
    view_data = property(_swigfaiss.MaybeOwnedVectorInt32_view_data_get, _swigfaiss.MaybeOwnedVectorInt32_view_data_set)
    view_size = property(_swigfaiss.MaybeOwnedVectorInt32_view_size_get, _swigfaiss.MaybeOwnedVectorInt32_view_size_set)
    owner = property(_swigfaiss.MaybeOwnedVectorInt32_owner_get, _swigfaiss.MaybeOwnedVectorInt32_owner_set)
    c_ptr = property(_swigfaiss.MaybeOwnedVectorInt32_c_ptr_get, _swigfaiss.MaybeOwnedVectorInt32_c_ptr_set)
    c_size = property(_swigfaiss.MaybeOwnedVectorInt32_c_size_get, _swigfaiss.MaybeOwnedVectorInt32_c_size_set)

    def __init__(self, *args):
        _swigfaiss.MaybeOwnedVectorInt32_swiginit(self, _swigfaiss.new_MaybeOwnedVectorInt32(*args))

    @staticmethod
    def create_view(address, n_elements, owner):
        return _swigfaiss.MaybeOwnedVectorInt32_create_view(address, n_elements, owner)

    def data(self, *args):
        return _swigfaiss.MaybeOwnedVectorInt32_data(self, *args)

    def size(self):
        return _swigfaiss.MaybeOwnedVectorInt32_size(self)

    def byte_size(self):
        return _swigfaiss.MaybeOwnedVectorInt32_byte_size(self)

    def at(self, *args):
        return _swigfaiss.MaybeOwnedVectorInt32_at(self, *args)

    def begin(self, *args):
        return _swigfaiss.MaybeOwnedVectorInt32_begin(self, *args)

    def end(self, *args):
        return _swigfaiss.MaybeOwnedVectorInt32_end(self, *args)

    def erase(self, begin, end):
        return _swigfaiss.MaybeOwnedVectorInt32_erase(self, begin, end)

    def clear(self):
        return _swigfaiss.MaybeOwnedVectorInt32_clear(self)

    def resize(self, *args):
        return _swigfaiss.MaybeOwnedVectorInt32_resize(self, *args)
    __swig_destroy__ = _swigfaiss.delete_MaybeOwnedVectorInt32

# Register MaybeOwnedVectorInt32 in _swigfaiss:
_swigfaiss.MaybeOwnedVectorInt32_swigregister(MaybeOwnedVectorInt32)
class MaybeOwnedVectorFloat32(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    is_owned = property(_swigfaiss.MaybeOwnedVectorFloat32_is_owned_get, _swigfaiss.MaybeOwnedVectorFloat32_is_owned_set)
    owned_data = property(_swigfaiss.MaybeOwnedVectorFloat32_owned_data_get, _swigfaiss.MaybeOwnedVectorFloat32_owned_data_set)
    view_data = property(_swigfaiss.MaybeOwnedVectorFloat32_view_data_get, _swigfaiss.MaybeOwnedVectorFloat32_view_data_set)
    view_size = property(_swigfaiss.MaybeOwnedVectorFloat32_view_size_get, _swigfaiss.MaybeOwnedVectorFloat32_view_size_set)
    owner = property(_swigfaiss.MaybeOwnedVectorFloat32_owner_get, _swigfaiss.MaybeOwnedVectorFloat32_owner_set)
    c_ptr = property(_swigfaiss.MaybeOwnedVectorFloat32_c_ptr_get, _swigfaiss.MaybeOwnedVectorFloat32_c_ptr_set)
    c_size = property(_swigfaiss.MaybeOwnedVectorFloat32_c_size_get, _swigfaiss.MaybeOwnedVectorFloat32_c_size_set)

    def __init__(self, *args):
        _swigfaiss.MaybeOwnedVectorFloat32_swiginit(self, _swigfaiss.new_MaybeOwnedVectorFloat32(*args))

    @staticmethod
    def create_view(address, n_elements, owner):
        return _swigfaiss.MaybeOwnedVectorFloat32_create_view(address, n_elements, owner)

    def data(self, *args):
        return _swigfaiss.MaybeOwnedVectorFloat32_data(self, *args)

    def size(self):
        return _swigfaiss.MaybeOwnedVectorFloat32_size(self)

    def byte_size(self):
        return _swigfaiss.MaybeOwnedVectorFloat32_byte_size(self)

    def at(self, *args):
        return _swigfaiss.MaybeOwnedVectorFloat32_at(self, *args)

    def begin(self, *args):
        return _swigfaiss.MaybeOwnedVectorFloat32_begin(self, *args)

    def end(self, *args):
        return _swigfaiss.MaybeOwnedVectorFloat32_end(self, *args)

    def erase(self, begin, end):
        return _swigfaiss.MaybeOwnedVectorFloat32_erase(self, begin, end)

    def clear(self):
        return _swigfaiss.MaybeOwnedVectorFloat32_clear(self)

    def resize(self, *args):
        return _swigfaiss.MaybeOwnedVectorFloat32_resize(self, *args)
    __swig_destroy__ = _swigfaiss.delete_MaybeOwnedVectorFloat32

# Register MaybeOwnedVectorFloat32 in _swigfaiss:
_swigfaiss.MaybeOwnedVectorFloat32_swigregister(MaybeOwnedVectorFloat32)

def CMin_uint16_partition_fuzzy(*args):
    return _swigfaiss.CMin_uint16_partition_fuzzy(*args)

def CMax_uint16_partition_fuzzy(*args):
    return _swigfaiss.CMax_uint16_partition_fuzzy(*args)

def merge_knn_results_CMin(*args):
    return _swigfaiss.merge_knn_results_CMin(*args)

def merge_knn_results_CMax(*args):
    return _swigfaiss.merge_knn_results_CMax(*args)
class MapLong2Long(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    map = property(_swigfaiss.MapLong2Long_map_get, _swigfaiss.MapLong2Long_map_set)

    def add(self, n, keys, vals):
        return _swigfaiss.MapLong2Long_add(self, n, keys, vals)

    def search(self, key):
        return _swigfaiss.MapLong2Long_search(self, key)

    def search_multiple(self, n, keys, vals):
        return _swigfaiss.MapLong2Long_search_multiple(self, n, keys, vals)

    def __init__(self):
        _swigfaiss.MapLong2Long_swiginit(self, _swigfaiss.new_MapLong2Long())
    __swig_destroy__ = _swigfaiss.delete_MapLong2Long

# Register MapLong2Long in _swigfaiss:
_swigfaiss.MapLong2Long_swigregister(MapLong2Long)

def omp_set_num_threads(num_threads):
    return _swigfaiss.omp_set_num_threads(num_threads)

def omp_get_max_threads():
    return _swigfaiss.omp_get_max_threads()

def memcpy(dest, src, n):
    return _swigfaiss.memcpy(dest, src, n)
class PythonInterruptCallback(InterruptCallback):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def want_interrupt(self):
        return _swigfaiss.PythonInterruptCallback_want_interrupt(self)

    @staticmethod
    def reset():
        return _swigfaiss.PythonInterruptCallback_reset()

    def __init__(self):
        _swigfaiss.PythonInterruptCallback_swiginit(self, _swigfaiss.new_PythonInterruptCallback())
    __swig_destroy__ = _swigfaiss.delete_PythonInterruptCallback

# Register PythonInterruptCallback in _swigfaiss:
_swigfaiss.PythonInterruptCallback_swigregister(PythonInterruptCallback)

def swig_ptr(a):
    return _swigfaiss.swig_ptr(a)

def rev_swig_ptr(*args):
    return _swigfaiss.rev_swig_ptr(*args)

def cast_integer_to_uint8_ptr(x):
    return _swigfaiss.cast_integer_to_uint8_ptr(x)

def cast_integer_to_float_ptr(x):
    return _swigfaiss.cast_integer_to_float_ptr(x)

def cast_integer_to_idx_t_ptr(x):
    return _swigfaiss.cast_integer_to_idx_t_ptr(x)

def cast_integer_to_int_ptr(x):
    return _swigfaiss.cast_integer_to_int_ptr(x)

def cast_integer_to_void_ptr(x):
    return _swigfaiss.cast_integer_to_void_ptr(x)

def swig_version():
    return _swigfaiss.swig_version()

