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


import numpy as np
import itertools



from sys import version_info as _swig_python_version_info
if _swig_python_version_info < (2, 7, 0):
    raise RuntimeError("Python 2.7 or later required")

# Import the low-level C/C++ module
if __package__ or "." in __name__:
    from . import _wasserstein
else:
    import _wasserstein

try:
    import builtins as __builtin__
except ImportError:
    import __builtin__

_swig_new_instance_method = _wasserstein.SWIG_PyInstanceMethod_New
_swig_new_static_method = _wasserstein.SWIG_PyStaticMethod_New

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 == "thisown":
            self.this.own(value)
        elif name == "this":
            set(self, name, 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):
    r"""Proxy of C++ swig::SwigPyIterator class."""

    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__ = _wasserstein.delete_SwigPyIterator
    value = _swig_new_instance_method(_wasserstein.SwigPyIterator_value)
    incr = _swig_new_instance_method(_wasserstein.SwigPyIterator_incr)
    decr = _swig_new_instance_method(_wasserstein.SwigPyIterator_decr)
    distance = _swig_new_instance_method(_wasserstein.SwigPyIterator_distance)
    equal = _swig_new_instance_method(_wasserstein.SwigPyIterator_equal)
    copy = _swig_new_instance_method(_wasserstein.SwigPyIterator_copy)
    next = _swig_new_instance_method(_wasserstein.SwigPyIterator_next)
    __next__ = _swig_new_instance_method(_wasserstein.SwigPyIterator___next__)
    previous = _swig_new_instance_method(_wasserstein.SwigPyIterator_previous)
    advance = _swig_new_instance_method(_wasserstein.SwigPyIterator_advance)
    __eq__ = _swig_new_instance_method(_wasserstein.SwigPyIterator___eq__)
    __ne__ = _swig_new_instance_method(_wasserstein.SwigPyIterator___ne__)
    __iadd__ = _swig_new_instance_method(_wasserstein.SwigPyIterator___iadd__)
    __isub__ = _swig_new_instance_method(_wasserstein.SwigPyIterator___isub__)
    __add__ = _swig_new_instance_method(_wasserstein.SwigPyIterator___add__)
    __sub__ = _swig_new_instance_method(_wasserstein.SwigPyIterator___sub__)
    def __iter__(self):
        return self

# Register SwigPyIterator in _wasserstein:
_wasserstein.SwigPyIterator_swigregister(SwigPyIterator)

class vectorDouble(object):
    r"""Proxy of C++ std::vector< double > class."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    iterator = _swig_new_instance_method(_wasserstein.vectorDouble_iterator)
    def __iter__(self):
        return self.iterator()
    __nonzero__ = _swig_new_instance_method(_wasserstein.vectorDouble___nonzero__)
    __bool__ = _swig_new_instance_method(_wasserstein.vectorDouble___bool__)
    __len__ = _swig_new_instance_method(_wasserstein.vectorDouble___len__)
    __getslice__ = _swig_new_instance_method(_wasserstein.vectorDouble___getslice__)
    __setslice__ = _swig_new_instance_method(_wasserstein.vectorDouble___setslice__)
    __delslice__ = _swig_new_instance_method(_wasserstein.vectorDouble___delslice__)
    __delitem__ = _swig_new_instance_method(_wasserstein.vectorDouble___delitem__)
    __getitem__ = _swig_new_instance_method(_wasserstein.vectorDouble___getitem__)
    __setitem__ = _swig_new_instance_method(_wasserstein.vectorDouble___setitem__)
    pop = _swig_new_instance_method(_wasserstein.vectorDouble_pop)
    append = _swig_new_instance_method(_wasserstein.vectorDouble_append)
    empty = _swig_new_instance_method(_wasserstein.vectorDouble_empty)
    size = _swig_new_instance_method(_wasserstein.vectorDouble_size)
    swap = _swig_new_instance_method(_wasserstein.vectorDouble_swap)
    begin = _swig_new_instance_method(_wasserstein.vectorDouble_begin)
    end = _swig_new_instance_method(_wasserstein.vectorDouble_end)
    rbegin = _swig_new_instance_method(_wasserstein.vectorDouble_rbegin)
    rend = _swig_new_instance_method(_wasserstein.vectorDouble_rend)
    clear = _swig_new_instance_method(_wasserstein.vectorDouble_clear)
    get_allocator = _swig_new_instance_method(_wasserstein.vectorDouble_get_allocator)
    pop_back = _swig_new_instance_method(_wasserstein.vectorDouble_pop_back)
    erase = _swig_new_instance_method(_wasserstein.vectorDouble_erase)

    def __init__(self, *args):
        r"""
        __init__(vectorDouble self) -> vectorDouble
        __init__(vectorDouble self, vectorDouble other) -> vectorDouble
        __init__(vectorDouble self, std::vector< double >::size_type size) -> vectorDouble
        __init__(vectorDouble self, std::vector< double >::size_type size, std::vector< double >::value_type const & value) -> vectorDouble
        """
        _wasserstein.vectorDouble_swiginit(self, _wasserstein.new_vectorDouble(*args))
    push_back = _swig_new_instance_method(_wasserstein.vectorDouble_push_back)
    front = _swig_new_instance_method(_wasserstein.vectorDouble_front)
    back = _swig_new_instance_method(_wasserstein.vectorDouble_back)
    assign = _swig_new_instance_method(_wasserstein.vectorDouble_assign)
    resize = _swig_new_instance_method(_wasserstein.vectorDouble_resize)
    insert = _swig_new_instance_method(_wasserstein.vectorDouble_insert)
    reserve = _swig_new_instance_method(_wasserstein.vectorDouble_reserve)
    capacity = _swig_new_instance_method(_wasserstein.vectorDouble_capacity)
    __swig_destroy__ = _wasserstein.delete_vectorDouble

# Register vectorDouble in _wasserstein:
_wasserstein.vectorDouble_swigregister(vectorDouble)

class vectorString(object):
    r"""Proxy of C++ std::vector< std::string > class."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    iterator = _swig_new_instance_method(_wasserstein.vectorString_iterator)
    def __iter__(self):
        return self.iterator()
    __nonzero__ = _swig_new_instance_method(_wasserstein.vectorString___nonzero__)
    __bool__ = _swig_new_instance_method(_wasserstein.vectorString___bool__)
    __len__ = _swig_new_instance_method(_wasserstein.vectorString___len__)
    __getslice__ = _swig_new_instance_method(_wasserstein.vectorString___getslice__)
    __setslice__ = _swig_new_instance_method(_wasserstein.vectorString___setslice__)
    __delslice__ = _swig_new_instance_method(_wasserstein.vectorString___delslice__)
    __delitem__ = _swig_new_instance_method(_wasserstein.vectorString___delitem__)
    __getitem__ = _swig_new_instance_method(_wasserstein.vectorString___getitem__)
    __setitem__ = _swig_new_instance_method(_wasserstein.vectorString___setitem__)
    pop = _swig_new_instance_method(_wasserstein.vectorString_pop)
    append = _swig_new_instance_method(_wasserstein.vectorString_append)
    empty = _swig_new_instance_method(_wasserstein.vectorString_empty)
    size = _swig_new_instance_method(_wasserstein.vectorString_size)
    swap = _swig_new_instance_method(_wasserstein.vectorString_swap)
    begin = _swig_new_instance_method(_wasserstein.vectorString_begin)
    end = _swig_new_instance_method(_wasserstein.vectorString_end)
    rbegin = _swig_new_instance_method(_wasserstein.vectorString_rbegin)
    rend = _swig_new_instance_method(_wasserstein.vectorString_rend)
    clear = _swig_new_instance_method(_wasserstein.vectorString_clear)
    get_allocator = _swig_new_instance_method(_wasserstein.vectorString_get_allocator)
    pop_back = _swig_new_instance_method(_wasserstein.vectorString_pop_back)
    erase = _swig_new_instance_method(_wasserstein.vectorString_erase)

    def __init__(self, *args):
        r"""
        __init__(vectorString self) -> vectorString
        __init__(vectorString self, vectorString other) -> vectorString
        __init__(vectorString self, std::vector< std::string >::size_type size) -> vectorString
        __init__(vectorString self, std::vector< std::string >::size_type size, std::vector< std::string >::value_type const & value) -> vectorString
        """
        _wasserstein.vectorString_swiginit(self, _wasserstein.new_vectorString(*args))
    push_back = _swig_new_instance_method(_wasserstein.vectorString_push_back)
    front = _swig_new_instance_method(_wasserstein.vectorString_front)
    back = _swig_new_instance_method(_wasserstein.vectorString_back)
    assign = _swig_new_instance_method(_wasserstein.vectorString_assign)
    resize = _swig_new_instance_method(_wasserstein.vectorString_resize)
    insert = _swig_new_instance_method(_wasserstein.vectorString_insert)
    reserve = _swig_new_instance_method(_wasserstein.vectorString_reserve)
    capacity = _swig_new_instance_method(_wasserstein.vectorString_capacity)
    __swig_destroy__ = _wasserstein.delete_vectorString

# Register vectorString in _wasserstein:
_wasserstein.vectorString_swigregister(vectorString)

class pairVectorDouble(object):
    r"""Proxy of C++ std::pair< std::vector< double >,std::vector< double > > class."""

    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"""
        __init__(pairVectorDouble self) -> pairVectorDouble
        __init__(pairVectorDouble self, vectorDouble first, vectorDouble second) -> pairVectorDouble
        __init__(pairVectorDouble self, pairVectorDouble other) -> pairVectorDouble
        """
        _wasserstein.pairVectorDouble_swiginit(self, _wasserstein.new_pairVectorDouble(*args))
    first = property(_wasserstein.pairVectorDouble_first_get, _wasserstein.pairVectorDouble_first_set, doc=r"""first : std::vector<(double,std::allocator<(double)>)>""")
    second = property(_wasserstein.pairVectorDouble_second_get, _wasserstein.pairVectorDouble_second_set, doc=r"""second : std::vector<(double,std::allocator<(double)>)>""")
    def __len__(self):
        return 2
    def __repr__(self):
        return str((self.first, self.second))
    def __getitem__(self, index): 
        if not (index % 2):
            return self.first
        else:
            return self.second
    def __setitem__(self, index, val):
        if not (index % 2):
            self.first = val
        else:
            self.second = val
    __swig_destroy__ = _wasserstein.delete_pairVectorDouble

# Register pairVectorDouble in _wasserstein:
_wasserstein.pairVectorDouble_swigregister(pairVectorDouble)

class vectorFloat(object):
    r"""Proxy of C++ std::vector< float > class."""

    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr
    iterator = _swig_new_instance_method(_wasserstein.vectorFloat_iterator)
    def __iter__(self):
        return self.iterator()
    __nonzero__ = _swig_new_instance_method(_wasserstein.vectorFloat___nonzero__)
    __bool__ = _swig_new_instance_method(_wasserstein.vectorFloat___bool__)
    __len__ = _swig_new_instance_method(_wasserstein.vectorFloat___len__)
    __getslice__ = _swig_new_instance_method(_wasserstein.vectorFloat___getslice__)
    __setslice__ = _swig_new_instance_method(_wasserstein.vectorFloat___setslice__)
    __delslice__ = _swig_new_instance_method(_wasserstein.vectorFloat___delslice__)
    __delitem__ = _swig_new_instance_method(_wasserstein.vectorFloat___delitem__)
    __getitem__ = _swig_new_instance_method(_wasserstein.vectorFloat___getitem__)
    __setitem__ = _swig_new_instance_method(_wasserstein.vectorFloat___setitem__)
    pop = _swig_new_instance_method(_wasserstein.vectorFloat_pop)
    append = _swig_new_instance_method(_wasserstein.vectorFloat_append)
    empty = _swig_new_instance_method(_wasserstein.vectorFloat_empty)
    size = _swig_new_instance_method(_wasserstein.vectorFloat_size)
    swap = _swig_new_instance_method(_wasserstein.vectorFloat_swap)
    begin = _swig_new_instance_method(_wasserstein.vectorFloat_begin)
    end = _swig_new_instance_method(_wasserstein.vectorFloat_end)
    rbegin = _swig_new_instance_method(_wasserstein.vectorFloat_rbegin)
    rend = _swig_new_instance_method(_wasserstein.vectorFloat_rend)
    clear = _swig_new_instance_method(_wasserstein.vectorFloat_clear)
    get_allocator = _swig_new_instance_method(_wasserstein.vectorFloat_get_allocator)
    pop_back = _swig_new_instance_method(_wasserstein.vectorFloat_pop_back)
    erase = _swig_new_instance_method(_wasserstein.vectorFloat_erase)

    def __init__(self, *args):
        r"""
        __init__(vectorFloat self) -> vectorFloat
        __init__(vectorFloat self, vectorFloat other) -> vectorFloat
        __init__(vectorFloat self, std::vector< float >::size_type size) -> vectorFloat
        __init__(vectorFloat self, std::vector< float >::size_type size, std::vector< float >::value_type const & value) -> vectorFloat
        """
        _wasserstein.vectorFloat_swiginit(self, _wasserstein.new_vectorFloat(*args))
    push_back = _swig_new_instance_method(_wasserstein.vectorFloat_push_back)
    front = _swig_new_instance_method(_wasserstein.vectorFloat_front)
    back = _swig_new_instance_method(_wasserstein.vectorFloat_back)
    assign = _swig_new_instance_method(_wasserstein.vectorFloat_assign)
    resize = _swig_new_instance_method(_wasserstein.vectorFloat_resize)
    insert = _swig_new_instance_method(_wasserstein.vectorFloat_insert)
    reserve = _swig_new_instance_method(_wasserstein.vectorFloat_reserve)
    capacity = _swig_new_instance_method(_wasserstein.vectorFloat_capacity)
    __swig_destroy__ = _wasserstein.delete_vectorFloat

# Register vectorFloat in _wasserstein:
_wasserstein.vectorFloat_swigregister(vectorFloat)

class pairVectorFloat(object):
    r"""Proxy of C++ std::pair< std::vector< float >,std::vector< float > > class."""

    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"""
        __init__(pairVectorFloat self) -> pairVectorFloat
        __init__(pairVectorFloat self, vectorFloat first, vectorFloat second) -> pairVectorFloat
        __init__(pairVectorFloat self, pairVectorFloat other) -> pairVectorFloat
        """
        _wasserstein.pairVectorFloat_swiginit(self, _wasserstein.new_pairVectorFloat(*args))
    first = property(_wasserstein.pairVectorFloat_first_get, _wasserstein.pairVectorFloat_first_set, doc=r"""first : std::vector<(float,std::allocator<(float)>)>""")
    second = property(_wasserstein.pairVectorFloat_second_get, _wasserstein.pairVectorFloat_second_set, doc=r"""second : std::vector<(float,std::allocator<(float)>)>""")
    def __len__(self):
        return 2
    def __repr__(self):
        return str((self.first, self.second))
    def __getitem__(self, index): 
        if not (index % 2):
            return self.first
        else:
            return self.second
    def __setitem__(self, index, val):
        if not (index % 2):
            self.first = val
        else:
            self.second = val
    __swig_destroy__ = _wasserstein.delete_pairVectorFloat

# Register pairVectorFloat in _wasserstein:
_wasserstein.pairVectorFloat_swigregister(pairVectorFloat)

EMDStatus_Success = _wasserstein.EMDStatus_Success

EMDStatus_Empty = _wasserstein.EMDStatus_Empty

EMDStatus_SupplyMismatch = _wasserstein.EMDStatus_SupplyMismatch

EMDStatus_Unbounded = _wasserstein.EMDStatus_Unbounded

EMDStatus_MaxIterReached = _wasserstein.EMDStatus_MaxIterReached

EMDStatus_Infeasible = _wasserstein.EMDStatus_Infeasible

ExtraParticle_Neither = _wasserstein.ExtraParticle_Neither

ExtraParticle_Zero = _wasserstein.ExtraParticle_Zero

ExtraParticle_One = _wasserstein.ExtraParticle_One

EMDPairsStorage_Full = _wasserstein.EMDPairsStorage_Full

EMDPairsStorage_FullSymmetric = _wasserstein.EMDPairsStorage_FullSymmetric

EMDPairsStorage_FlattenedSymmetric = _wasserstein.EMDPairsStorage_FlattenedSymmetric

EMDPairsStorage_External = _wasserstein.EMDPairsStorage_External

check_emd_status = _wasserstein.check_emd_status
class EMDBaseFloat64(object):
    r"""Proxy of C++ wasserstein::EMDBase< double > class."""

    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__ = _wasserstein.delete_EMDBaseFloat64
    R = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_R)
    beta = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_beta)
    set_R = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_set_R)
    set_beta = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_set_beta)
    set_network_simplex_params = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_set_network_simplex_params)
    norm = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_norm)
    set_norm = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_set_norm)
    do_timing = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_do_timing)
    set_do_timing = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_set_do_timing)
    external_dists = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_external_dists)
    set_external_dists = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_set_external_dists)
    n0 = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_n0)
    n1 = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_n1)
    extra = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_extra)
    emd = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_emd)
    status = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_status)
    weightdiff = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_weightdiff)
    scale = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_scale)
    n_iter = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_n_iter)
    dists_vec = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_dists_vec)
    flows_vec = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_flows_vec)
    flow = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_flow)
    node_potentials = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_node_potentials)
    duration = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_duration)
    clear = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_clear)
    flows = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_flows)
    dists = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_dists)
    npy_node_potentials = _swig_new_instance_method(_wasserstein.EMDBaseFloat64_npy_node_potentials)

# Register EMDBaseFloat64 in _wasserstein:
_wasserstein.EMDBaseFloat64_swigregister(EMDBaseFloat64)
cvar = _wasserstein.cvar
PI = cvar.PI
TWOPI = cvar.TWOPI
COMPILED_WITH_OPENMP = cvar.COMPILED_WITH_OPENMP

class PairwiseEMDBaseFloat64(object):
    r"""Proxy of C++ wasserstein::PairwiseEMDBase< double > class."""

    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__ = _wasserstein.delete_PairwiseEMDBaseFloat64
    R = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_R)
    set_R = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_set_R)
    beta = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_beta)
    set_beta = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_set_beta)
    norm = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_norm)
    set_norm = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_set_norm)
    set_network_simplex_params = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_set_network_simplex_params)

    def set_external_emd_handler(self, handler):
        if not handler.thisown:
            raise RuntimeError('ExternalEMDHandler must own itself; perhaps it is already in use elsewhere')
        handler.thisown = 0
        _wasserstein.PairwiseEMDBaseFloat64_set_external_emd_handler(self, handler)
        self._external_emd_handler = handler


    have_external_emd_handler = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_have_external_emd_handler)
    num_threads = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_num_threads)
    set_omp_dynamic_chunksize = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_set_omp_dynamic_chunksize)
    omp_dynamic_chunksize = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_omp_dynamic_chunksize)
    set_request_mode = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_set_request_mode)
    request_mode = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_request_mode)
    duration = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_duration)
    nevA = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_nevA)
    nevB = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_nevB)
    num_emds = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_num_emds)
    storage = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_storage)
    errored = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_errored)
    error_messages = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_error_messages)
    emds_vec = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_emds_vec)
    emd = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_emd)


          # ensure proper destruction of objects held by this instance
    def __del__(self):
        if hasattr(self, '_external_emd_handler'):
            self._external_emd_handler.thisown = 1
            del self._external_emd_handler

    def __call__(self, eventsA, eventsB=None, gdim=None, mask=False,
                       event_weightsA=None, event_weightsB=None):

        dtype = np.float64 if 'Float64' in self.__class__.__name__ else np.float32
        self._float_dtype = dtype

        if eventsB is None:
            self.init(len(eventsA))
            eventsB = event_weightsB = []
        else:
            self.init(len(eventsA), len(eventsB))

        if event_weightsA is None:
            event_weightsA = np.ones(len(eventsA))
        elif len(event_weightsA) != len(eventsA):
            raise ValueError('length of `event_weightsA` does not match length of `eventsA`')

        if event_weightsB is None:
            event_weightsB = np.ones(len(eventsB))
        elif len(event_weightsB) != len(eventsB):
            raise ValueError('length of `event_weightsB` does not match length of `eventsB`')

        self.event_arrs = []
        _store_events(self, itertools.chain(eventsA, eventsB),
                            itertools.chain(event_weightsA, event_weightsB),
                            gdim, mask, dtype)

        if not self.request_mode():
            self.compute()

    emds = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_emds)
    raw_emds = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat64_raw_emds)

# Register PairwiseEMDBaseFloat64 in _wasserstein:
_wasserstein.PairwiseEMDBaseFloat64_swigregister(PairwiseEMDBaseFloat64)

class ExternalEMDHandlerFloat64(object):
    r"""Proxy of C++ wasserstein::ExternalEMDHandler< double > class."""

    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__ = _wasserstein.delete_ExternalEMDHandlerFloat64
    description = _swig_new_instance_method(_wasserstein.ExternalEMDHandlerFloat64_description)
    num_calls = _swig_new_instance_method(_wasserstein.ExternalEMDHandlerFloat64_num_calls)
    __call__ = _swig_new_instance_method(_wasserstein.ExternalEMDHandlerFloat64___call__)
    evaluate1d = _swig_new_instance_method(_wasserstein.ExternalEMDHandlerFloat64_evaluate1d)
    evaluate2d = _swig_new_instance_method(_wasserstein.ExternalEMDHandlerFloat64_evaluate2d)
    evaluate1d_symmetric = _swig_new_instance_method(_wasserstein.ExternalEMDHandlerFloat64_evaluate1d_symmetric)

# Register ExternalEMDHandlerFloat64 in _wasserstein:
_wasserstein.ExternalEMDHandlerFloat64_swigregister(ExternalEMDHandlerFloat64)

class Histogram1DHandlerLogFloat64(ExternalEMDHandlerFloat64):
    r"""Proxy of C++ wasserstein::Histogram1DHandler< boost::histogram::axis::transform::log,double > class."""

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

    def __init__(self, nbins: "unsigned int", axis_min: "double", axis_max: "double"):
        r"""__init__(Histogram1DHandlerLogFloat64 self, unsigned int nbins, double axis_min, double axis_max) -> Histogram1DHandlerLogFloat64"""
        _wasserstein.Histogram1DHandlerLogFloat64_swiginit(self, _wasserstein.new_Histogram1DHandlerLogFloat64(nbins, axis_min, axis_max))
    __swig_destroy__ = _wasserstein.delete_Histogram1DHandlerLogFloat64
    nbins = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat64_nbins)
    axis_min = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat64_axis_min)
    axis_max = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat64_axis_max)
    description = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat64_description)
    hist_vals_vars_vec = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat64_hist_vals_vars_vec)
    bin_centers_vec = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat64_bin_centers_vec)
    bin_edges_vec = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat64_bin_edges_vec)
    __iadd__ = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat64___iadd__)
    __repr__ = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat64___repr__)
    bin_centers = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat64_bin_centers)
    bin_edges = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat64_bin_edges)
    hist_vals_vars = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat64_hist_vals_vars)

    def hist_vals_errs(self, overflows=True):
        vals, vars = self.hist_vals_vars(overflows)
        return vals, np.sqrt(vars)


# Register Histogram1DHandlerLogFloat64 in _wasserstein:
_wasserstein.Histogram1DHandlerLogFloat64_swigregister(Histogram1DHandlerLogFloat64)

class Histogram1DHandlerFloat64(ExternalEMDHandlerFloat64):
    r"""Proxy of C++ wasserstein::Histogram1DHandler< boost::histogram::axis::transform::id,double > class."""

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

    def __init__(self, nbins: "unsigned int", axis_min: "double", axis_max: "double"):
        r"""__init__(Histogram1DHandlerFloat64 self, unsigned int nbins, double axis_min, double axis_max) -> Histogram1DHandlerFloat64"""
        _wasserstein.Histogram1DHandlerFloat64_swiginit(self, _wasserstein.new_Histogram1DHandlerFloat64(nbins, axis_min, axis_max))
    __swig_destroy__ = _wasserstein.delete_Histogram1DHandlerFloat64
    nbins = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat64_nbins)
    axis_min = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat64_axis_min)
    axis_max = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat64_axis_max)
    description = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat64_description)
    hist_vals_vars_vec = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat64_hist_vals_vars_vec)
    bin_centers_vec = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat64_bin_centers_vec)
    bin_edges_vec = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat64_bin_edges_vec)
    __iadd__ = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat64___iadd__)
    __repr__ = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat64___repr__)
    bin_centers = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat64_bin_centers)
    bin_edges = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat64_bin_edges)
    hist_vals_vars = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat64_hist_vals_vars)

    def hist_vals_errs(self, overflows=True):
        vals, vars = self.hist_vals_vars(overflows)
        return vals, np.sqrt(vars)


# Register Histogram1DHandlerFloat64 in _wasserstein:
_wasserstein.Histogram1DHandlerFloat64_swigregister(Histogram1DHandlerFloat64)

class EMDBaseFloat32(object):
    r"""Proxy of C++ wasserstein::EMDBase< float > class."""

    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__ = _wasserstein.delete_EMDBaseFloat32
    R = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_R)
    beta = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_beta)
    set_R = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_set_R)
    set_beta = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_set_beta)
    set_network_simplex_params = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_set_network_simplex_params)
    norm = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_norm)
    set_norm = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_set_norm)
    do_timing = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_do_timing)
    set_do_timing = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_set_do_timing)
    external_dists = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_external_dists)
    set_external_dists = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_set_external_dists)
    n0 = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_n0)
    n1 = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_n1)
    extra = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_extra)
    emd = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_emd)
    status = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_status)
    weightdiff = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_weightdiff)
    scale = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_scale)
    n_iter = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_n_iter)
    dists_vec = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_dists_vec)
    flows_vec = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_flows_vec)
    flow = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_flow)
    node_potentials = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_node_potentials)
    duration = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_duration)
    clear = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_clear)
    flows = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_flows)
    dists = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_dists)
    npy_node_potentials = _swig_new_instance_method(_wasserstein.EMDBaseFloat32_npy_node_potentials)

# Register EMDBaseFloat32 in _wasserstein:
_wasserstein.EMDBaseFloat32_swigregister(EMDBaseFloat32)

class PairwiseEMDBaseFloat32(object):
    r"""Proxy of C++ wasserstein::PairwiseEMDBase< float > class."""

    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__ = _wasserstein.delete_PairwiseEMDBaseFloat32
    R = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_R)
    set_R = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_set_R)
    beta = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_beta)
    set_beta = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_set_beta)
    norm = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_norm)
    set_norm = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_set_norm)
    set_network_simplex_params = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_set_network_simplex_params)

    def set_external_emd_handler(self, handler):
        if not handler.thisown:
            raise RuntimeError('ExternalEMDHandler must own itself; perhaps it is already in use elsewhere')
        handler.thisown = 0
        _wasserstein.PairwiseEMDBaseFloat32_set_external_emd_handler(self, handler)
        self._external_emd_handler = handler


    have_external_emd_handler = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_have_external_emd_handler)
    num_threads = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_num_threads)
    set_omp_dynamic_chunksize = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_set_omp_dynamic_chunksize)
    omp_dynamic_chunksize = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_omp_dynamic_chunksize)
    set_request_mode = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_set_request_mode)
    request_mode = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_request_mode)
    duration = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_duration)
    nevA = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_nevA)
    nevB = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_nevB)
    num_emds = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_num_emds)
    storage = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_storage)
    errored = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_errored)
    error_messages = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_error_messages)
    emds_vec = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_emds_vec)
    emd = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_emd)


          # ensure proper destruction of objects held by this instance
    def __del__(self):
        if hasattr(self, '_external_emd_handler'):
            self._external_emd_handler.thisown = 1
            del self._external_emd_handler

    def __call__(self, eventsA, eventsB=None, gdim=None, mask=False,
                       event_weightsA=None, event_weightsB=None):

        dtype = np.float64 if 'Float64' in self.__class__.__name__ else np.float32
        self._float_dtype = dtype

        if eventsB is None:
            self.init(len(eventsA))
            eventsB = event_weightsB = []
        else:
            self.init(len(eventsA), len(eventsB))

        if event_weightsA is None:
            event_weightsA = np.ones(len(eventsA))
        elif len(event_weightsA) != len(eventsA):
            raise ValueError('length of `event_weightsA` does not match length of `eventsA`')

        if event_weightsB is None:
            event_weightsB = np.ones(len(eventsB))
        elif len(event_weightsB) != len(eventsB):
            raise ValueError('length of `event_weightsB` does not match length of `eventsB`')

        self.event_arrs = []
        _store_events(self, itertools.chain(eventsA, eventsB),
                            itertools.chain(event_weightsA, event_weightsB),
                            gdim, mask, dtype)

        if not self.request_mode():
            self.compute()

    emds = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_emds)
    raw_emds = _swig_new_instance_method(_wasserstein.PairwiseEMDBaseFloat32_raw_emds)

# Register PairwiseEMDBaseFloat32 in _wasserstein:
_wasserstein.PairwiseEMDBaseFloat32_swigregister(PairwiseEMDBaseFloat32)

class ExternalEMDHandlerFloat32(object):
    r"""Proxy of C++ wasserstein::ExternalEMDHandler< float > class."""

    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__ = _wasserstein.delete_ExternalEMDHandlerFloat32
    description = _swig_new_instance_method(_wasserstein.ExternalEMDHandlerFloat32_description)
    num_calls = _swig_new_instance_method(_wasserstein.ExternalEMDHandlerFloat32_num_calls)
    __call__ = _swig_new_instance_method(_wasserstein.ExternalEMDHandlerFloat32___call__)
    evaluate1d = _swig_new_instance_method(_wasserstein.ExternalEMDHandlerFloat32_evaluate1d)
    evaluate2d = _swig_new_instance_method(_wasserstein.ExternalEMDHandlerFloat32_evaluate2d)
    evaluate1d_symmetric = _swig_new_instance_method(_wasserstein.ExternalEMDHandlerFloat32_evaluate1d_symmetric)

# Register ExternalEMDHandlerFloat32 in _wasserstein:
_wasserstein.ExternalEMDHandlerFloat32_swigregister(ExternalEMDHandlerFloat32)

class Histogram1DHandlerLogFloat32(ExternalEMDHandlerFloat32):
    r"""Proxy of C++ wasserstein::Histogram1DHandler< boost::histogram::axis::transform::log,float > class."""

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

    def __init__(self, nbins: "unsigned int", axis_min: "float", axis_max: "float"):
        r"""__init__(Histogram1DHandlerLogFloat32 self, unsigned int nbins, float axis_min, float axis_max) -> Histogram1DHandlerLogFloat32"""
        _wasserstein.Histogram1DHandlerLogFloat32_swiginit(self, _wasserstein.new_Histogram1DHandlerLogFloat32(nbins, axis_min, axis_max))
    __swig_destroy__ = _wasserstein.delete_Histogram1DHandlerLogFloat32
    nbins = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat32_nbins)
    axis_min = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat32_axis_min)
    axis_max = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat32_axis_max)
    description = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat32_description)
    hist_vals_vars_vec = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat32_hist_vals_vars_vec)
    bin_centers_vec = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat32_bin_centers_vec)
    bin_edges_vec = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat32_bin_edges_vec)
    __iadd__ = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat32___iadd__)
    __repr__ = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat32___repr__)
    bin_centers = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat32_bin_centers)
    bin_edges = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat32_bin_edges)
    hist_vals_vars = _swig_new_instance_method(_wasserstein.Histogram1DHandlerLogFloat32_hist_vals_vars)

    def hist_vals_errs(self, overflows=True):
        vals, vars = self.hist_vals_vars(overflows)
        return vals, np.sqrt(vars)


# Register Histogram1DHandlerLogFloat32 in _wasserstein:
_wasserstein.Histogram1DHandlerLogFloat32_swigregister(Histogram1DHandlerLogFloat32)

class Histogram1DHandlerFloat32(ExternalEMDHandlerFloat32):
    r"""Proxy of C++ wasserstein::Histogram1DHandler< boost::histogram::axis::transform::id,float > class."""

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

    def __init__(self, nbins: "unsigned int", axis_min: "float", axis_max: "float"):
        r"""__init__(Histogram1DHandlerFloat32 self, unsigned int nbins, float axis_min, float axis_max) -> Histogram1DHandlerFloat32"""
        _wasserstein.Histogram1DHandlerFloat32_swiginit(self, _wasserstein.new_Histogram1DHandlerFloat32(nbins, axis_min, axis_max))
    __swig_destroy__ = _wasserstein.delete_Histogram1DHandlerFloat32
    nbins = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat32_nbins)
    axis_min = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat32_axis_min)
    axis_max = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat32_axis_max)
    description = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat32_description)
    hist_vals_vars_vec = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat32_hist_vals_vars_vec)
    bin_centers_vec = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat32_bin_centers_vec)
    bin_edges_vec = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat32_bin_edges_vec)
    __iadd__ = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat32___iadd__)
    __repr__ = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat32___repr__)
    bin_centers = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat32_bin_centers)
    bin_edges = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat32_bin_edges)
    hist_vals_vars = _swig_new_instance_method(_wasserstein.Histogram1DHandlerFloat32_hist_vals_vars)

    def hist_vals_errs(self, overflows=True):
        vals, vars = self.hist_vals_vars(overflows)
        return vals, np.sqrt(vars)


# Register Histogram1DHandlerFloat32 in _wasserstein:
_wasserstein.Histogram1DHandlerFloat32_swigregister(Histogram1DHandlerFloat32)

class CorrelationDimensionFloat32(Histogram1DHandlerLogFloat32):
    r"""Proxy of C++ wasserstein::CorrelationDimension< float > class."""

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

    def __init__(self, nbins: "unsigned int", axis_min: "float", axis_max: "float"):
        r"""__init__(CorrelationDimensionFloat32 self, unsigned int nbins, float axis_min, float axis_max) -> CorrelationDimensionFloat32"""
        _wasserstein.CorrelationDimensionFloat32_swiginit(self, _wasserstein.new_CorrelationDimensionFloat32(nbins, axis_min, axis_max))
    corrdims_vec = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat32_corrdims_vec)
    corrdim_bins_vec = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat32_corrdim_bins_vec)
    cumulative_vals_vars_vec = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat32_cumulative_vals_vars_vec)
    __repr__ = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat32___repr__)
    corrdim_bins = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat32_corrdim_bins)
    corrdims = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat32_corrdims)
    cumulative_vals_vars = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat32_cumulative_vals_vars)
    __swig_destroy__ = _wasserstein.delete_CorrelationDimensionFloat32

# Register CorrelationDimensionFloat32 in _wasserstein:
_wasserstein.CorrelationDimensionFloat32_swigregister(CorrelationDimensionFloat32)

class CorrelationDimensionFloat64(Histogram1DHandlerLogFloat64):
    r"""Proxy of C++ wasserstein::CorrelationDimension< double > class."""

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

    def __init__(self, nbins: "unsigned int", axis_min: "double", axis_max: "double"):
        r"""__init__(CorrelationDimensionFloat64 self, unsigned int nbins, double axis_min, double axis_max) -> CorrelationDimensionFloat64"""
        _wasserstein.CorrelationDimensionFloat64_swiginit(self, _wasserstein.new_CorrelationDimensionFloat64(nbins, axis_min, axis_max))
    corrdims_vec = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat64_corrdims_vec)
    corrdim_bins_vec = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat64_corrdim_bins_vec)
    cumulative_vals_vars_vec = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat64_cumulative_vals_vars_vec)
    __repr__ = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat64___repr__)
    corrdim_bins = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat64_corrdim_bins)
    corrdims = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat64_corrdims)
    cumulative_vals_vars = _swig_new_instance_method(_wasserstein.CorrelationDimensionFloat64_cumulative_vals_vars)
    __swig_destroy__ = _wasserstein.delete_CorrelationDimensionFloat64

# Register CorrelationDimensionFloat64 in _wasserstein:
_wasserstein.CorrelationDimensionFloat64_swigregister(CorrelationDimensionFloat64)


def CorrelationDimension(*args, **kwargs):
    dtype = kwargs.pop('dtype', 'float64')
    if dtype == 'float64' or dtype == np.float64:
        return CorrelationDimensionFloat64(*args, **kwargs)
    elif dtype == 'float32' or dtype == np.float32:
        return CorrelationDimensionFloat32(*args, **kwargs)
    else:
      raise TypeError('`dtype` {} not supported'.format(dtype))



# function for storing events in a pairwise_emd object
def _store_events(pairwise_emd, events, event_weights, gdim, mask, dtype):

    if mask:
        R2 = pairwise_emd.R()**2

    for event, event_weight in zip(events, event_weights):

# ensure event is 2d
        event = np.asarray(event)
        if event.ndim != 2:
            raise ValueError('event must be a 2-dimensional array')
        if gdim is not None:
            if event.shape[1] <= gdim:
                raise ValueError('event should have at least gdim={} coordinates'.format(gdim))
            event = event[:,:1+gdim]

# consider mask
        if mask:
            event = event[np.sum(event[:,1:]**2, axis=1) <= R2]

# extract weights and coords
# usually, these would make copies anyway
# sometimes, e.g. in the case of a single particle, they may not
# weights are never modified due to internal copying
# coords may be modified (e.g. by centering), so we always make a copy of them
        weights = np.array(event[:,0], dtype=dtype, order='C', copy=False)
        coords = np.array(event[:,1:], dtype=dtype, order='C', copy=True)

# ensure that the lifetime of these arrays lasts through the computation
        pairwise_emd.event_arrs.append((weights, coords))

# store individual event
        pairwise_emd._add_event(weights, coords, float(event_weight))

class EMDFloat64(EMDBaseFloat64):
    r"""Proxy of C++ wasserstein::EMD< double,wasserstein::DefaultArrayEvent,wasserstein::EuclideanArrayDistance > class."""

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

    def __init__(self, R: "double"=1, beta: "double"=1, norm: "bool"=False, do_timing: "bool"=False, external_dists: "bool"=False, n_iter_max: "std::size_t"=100000, epsilon_large_factor: "double"=1000, epsilon_small_factor: "double"=1):
        r"""__init__(EMDFloat64 self, double R=1, double beta=1, bool norm=False, bool do_timing=False, bool external_dists=False, std::size_t n_iter_max=100000, double epsilon_large_factor=1000, double epsilon_small_factor=1) -> EMDFloat64"""
        _wasserstein.EMDFloat64_swiginit(self, _wasserstein.new_EMDFloat64(R, beta, norm, do_timing, external_dists, n_iter_max, epsilon_large_factor, epsilon_small_factor))
    __swig_destroy__ = _wasserstein.delete_EMDFloat64
    description = _swig_new_instance_method(_wasserstein.EMDFloat64_description)
    __repr__ = _swig_new_instance_method(_wasserstein.EMDFloat64___repr__)
    preprocess_CenterWeightedCentroid = _swig_new_instance_method(_wasserstein.EMDFloat64_preprocess_CenterWeightedCentroid)
    __call__ = _swig_new_instance_method(_wasserstein.EMDFloat64___call__)

# Register EMDFloat64 in _wasserstein:
_wasserstein.EMDFloat64_swigregister(EMDFloat64)

class EMDFloat32(EMDBaseFloat32):
    r"""Proxy of C++ wasserstein::EMD< float,wasserstein::DefaultArrayEvent,wasserstein::EuclideanArrayDistance > class."""

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

    def __init__(self, R: "float"=1, beta: "float"=1, norm: "bool"=False, do_timing: "bool"=False, external_dists: "bool"=False, n_iter_max: "std::size_t"=100000, epsilon_large_factor: "float"=1000, epsilon_small_factor: "float"=1):
        r"""__init__(EMDFloat32 self, float R=1, float beta=1, bool norm=False, bool do_timing=False, bool external_dists=False, std::size_t n_iter_max=100000, float epsilon_large_factor=1000, float epsilon_small_factor=1) -> EMDFloat32"""
        _wasserstein.EMDFloat32_swiginit(self, _wasserstein.new_EMDFloat32(R, beta, norm, do_timing, external_dists, n_iter_max, epsilon_large_factor, epsilon_small_factor))
    __swig_destroy__ = _wasserstein.delete_EMDFloat32
    description = _swig_new_instance_method(_wasserstein.EMDFloat32_description)
    __repr__ = _swig_new_instance_method(_wasserstein.EMDFloat32___repr__)
    preprocess_CenterWeightedCentroid = _swig_new_instance_method(_wasserstein.EMDFloat32_preprocess_CenterWeightedCentroid)
    __call__ = _swig_new_instance_method(_wasserstein.EMDFloat32___call__)

# Register EMDFloat32 in _wasserstein:
_wasserstein.EMDFloat32_swigregister(EMDFloat32)

class EMDYPhiFloat64(EMDBaseFloat64):
    r"""Proxy of C++ wasserstein::EMD< double,wasserstein::DefaultArray2Event,wasserstein::YPhiArrayDistance > class."""

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

    def __init__(self, R: "double"=1, beta: "double"=1, norm: "bool"=False, do_timing: "bool"=False, external_dists: "bool"=False, n_iter_max: "std::size_t"=100000, epsilon_large_factor: "double"=1000, epsilon_small_factor: "double"=1):
        r"""__init__(EMDYPhiFloat64 self, double R=1, double beta=1, bool norm=False, bool do_timing=False, bool external_dists=False, std::size_t n_iter_max=100000, double epsilon_large_factor=1000, double epsilon_small_factor=1) -> EMDYPhiFloat64"""
        _wasserstein.EMDYPhiFloat64_swiginit(self, _wasserstein.new_EMDYPhiFloat64(R, beta, norm, do_timing, external_dists, n_iter_max, epsilon_large_factor, epsilon_small_factor))
    __swig_destroy__ = _wasserstein.delete_EMDYPhiFloat64
    description = _swig_new_instance_method(_wasserstein.EMDYPhiFloat64_description)
    __repr__ = _swig_new_instance_method(_wasserstein.EMDYPhiFloat64___repr__)
    preprocess_CenterWeightedCentroid = _swig_new_instance_method(_wasserstein.EMDYPhiFloat64_preprocess_CenterWeightedCentroid)
    __call__ = _swig_new_instance_method(_wasserstein.EMDYPhiFloat64___call__)

# Register EMDYPhiFloat64 in _wasserstein:
_wasserstein.EMDYPhiFloat64_swigregister(EMDYPhiFloat64)

class EMDYPhiFloat32(EMDBaseFloat32):
    r"""Proxy of C++ wasserstein::EMD< float,wasserstein::DefaultArray2Event,wasserstein::YPhiArrayDistance > class."""

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

    def __init__(self, R: "float"=1, beta: "float"=1, norm: "bool"=False, do_timing: "bool"=False, external_dists: "bool"=False, n_iter_max: "std::size_t"=100000, epsilon_large_factor: "float"=1000, epsilon_small_factor: "float"=1):
        r"""__init__(EMDYPhiFloat32 self, float R=1, float beta=1, bool norm=False, bool do_timing=False, bool external_dists=False, std::size_t n_iter_max=100000, float epsilon_large_factor=1000, float epsilon_small_factor=1) -> EMDYPhiFloat32"""
        _wasserstein.EMDYPhiFloat32_swiginit(self, _wasserstein.new_EMDYPhiFloat32(R, beta, norm, do_timing, external_dists, n_iter_max, epsilon_large_factor, epsilon_small_factor))
    __swig_destroy__ = _wasserstein.delete_EMDYPhiFloat32
    description = _swig_new_instance_method(_wasserstein.EMDYPhiFloat32_description)
    __repr__ = _swig_new_instance_method(_wasserstein.EMDYPhiFloat32___repr__)
    preprocess_CenterWeightedCentroid = _swig_new_instance_method(_wasserstein.EMDYPhiFloat32_preprocess_CenterWeightedCentroid)
    __call__ = _swig_new_instance_method(_wasserstein.EMDYPhiFloat32___call__)

# Register EMDYPhiFloat32 in _wasserstein:
_wasserstein.EMDYPhiFloat32_swigregister(EMDYPhiFloat32)

class PairwiseEMDFloat64(PairwiseEMDBaseFloat64):
    r"""Proxy of C++ wasserstein::PairwiseEMD< wasserstein::EMD< double,wasserstein::DefaultArrayEvent,wasserstein::EuclideanArrayDistance >,double > class."""

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

    def __init__(self, *args, **kwargs):
        r"""__init__(PairwiseEMDFloat64 self, double R=1, double beta=1, bool norm=False, int num_threads=-1, wasserstein::index_type print_every=-10, unsigned int verbose=1, bool request_mode=False, bool store_sym_emds_raw=True, bool throw_on_error=False, unsigned int omp_dynamic_chunksize=10, std::size_t n_iter_max=100000, double epsilon_large_factor=1000, double epsilon_small_factor=1, std::ostream & os=std::cout) -> PairwiseEMDFloat64"""
        _wasserstein.PairwiseEMDFloat64_swiginit(self, _wasserstein.new_PairwiseEMDFloat64(*args, **kwargs))
    __swig_destroy__ = _wasserstein.delete_PairwiseEMDFloat64
    description = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat64_description)

    def clear(self, *args, **kwargs):
        _wasserstein.PairwiseEMDFloat64_clear(self, *args, **kwargs)
        if hasattr(self, 'event_arrs'):
            del self.event_arrs


    init = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat64_init)
    compute = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat64_compute)
    __repr__ = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat64___repr__)
    preprocess_CenterWeightedCentroid = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat64_preprocess_CenterWeightedCentroid)
    _reset_B_events = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat64__reset_B_events)


    def set_new_eventsB(self, eventsB, gdim=None, mask=False, event_weightsB=None):

    # check that we have been initialized before
        if not hasattr(self, 'event_arrs'):
            raise RuntimeError('PairwiseEMD object must be called on some events before the B events can be reset')

    # check that we are in request mode
        if not self.request_mode():
            raise RuntimeError('PairwiseEMD object must be in request mode in order to set new eventsB')

        if event_weightsB is None:
            event_weightsB = np.ones(len(eventsB))
        elif len(event_weightsB) != len(eventsB):
            raise ValueError('length of `event_weightsB` does not match length of `eventsB`')

    # clear away old B events in underlying object
        self._reset_B_events()

    # clear B events from python array
        del self.event_arrs[self.nevA():]

    # reinitialize
        self.init(self.nevA(), len(eventsB))
        _store_events(self, eventsB, event_weightsB, gdim, mask, self._float_dtype)

    _add_event = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat64__add_event)

# Register PairwiseEMDFloat64 in _wasserstein:
_wasserstein.PairwiseEMDFloat64_swigregister(PairwiseEMDFloat64)

class PairwiseEMDFloat32(PairwiseEMDBaseFloat32):
    r"""Proxy of C++ wasserstein::PairwiseEMD< wasserstein::EMD< float,wasserstein::DefaultArrayEvent,wasserstein::EuclideanArrayDistance >,float > class."""

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

    def __init__(self, *args, **kwargs):
        r"""__init__(PairwiseEMDFloat32 self, float R=1, float beta=1, bool norm=False, int num_threads=-1, wasserstein::index_type print_every=-10, unsigned int verbose=1, bool request_mode=False, bool store_sym_emds_raw=True, bool throw_on_error=False, unsigned int omp_dynamic_chunksize=10, std::size_t n_iter_max=100000, float epsilon_large_factor=1000, float epsilon_small_factor=1, std::ostream & os=std::cout) -> PairwiseEMDFloat32"""
        _wasserstein.PairwiseEMDFloat32_swiginit(self, _wasserstein.new_PairwiseEMDFloat32(*args, **kwargs))
    __swig_destroy__ = _wasserstein.delete_PairwiseEMDFloat32
    description = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat32_description)

    def clear(self, *args, **kwargs):
        _wasserstein.PairwiseEMDFloat32_clear(self, *args, **kwargs)
        if hasattr(self, 'event_arrs'):
            del self.event_arrs


    init = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat32_init)
    compute = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat32_compute)
    __repr__ = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat32___repr__)
    preprocess_CenterWeightedCentroid = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat32_preprocess_CenterWeightedCentroid)
    _reset_B_events = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat32__reset_B_events)


    def set_new_eventsB(self, eventsB, gdim=None, mask=False, event_weightsB=None):

    # check that we have been initialized before
        if not hasattr(self, 'event_arrs'):
            raise RuntimeError('PairwiseEMD object must be called on some events before the B events can be reset')

    # check that we are in request mode
        if not self.request_mode():
            raise RuntimeError('PairwiseEMD object must be in request mode in order to set new eventsB')

        if event_weightsB is None:
            event_weightsB = np.ones(len(eventsB))
        elif len(event_weightsB) != len(eventsB):
            raise ValueError('length of `event_weightsB` does not match length of `eventsB`')

    # clear away old B events in underlying object
        self._reset_B_events()

    # clear B events from python array
        del self.event_arrs[self.nevA():]

    # reinitialize
        self.init(self.nevA(), len(eventsB))
        _store_events(self, eventsB, event_weightsB, gdim, mask, self._float_dtype)

    _add_event = _swig_new_instance_method(_wasserstein.PairwiseEMDFloat32__add_event)

# Register PairwiseEMDFloat32 in _wasserstein:
_wasserstein.PairwiseEMDFloat32_swigregister(PairwiseEMDFloat32)

class PairwiseEMDYPhiFloat64(PairwiseEMDBaseFloat64):
    r"""Proxy of C++ wasserstein::PairwiseEMD< wasserstein::EMD< double,wasserstein::DefaultArray2Event,wasserstein::YPhiArrayDistance >,double > class."""

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

    def __init__(self, *args, **kwargs):
        r"""__init__(PairwiseEMDYPhiFloat64 self, double R=1, double beta=1, bool norm=False, int num_threads=-1, wasserstein::index_type print_every=-10, unsigned int verbose=1, bool request_mode=False, bool store_sym_emds_raw=True, bool throw_on_error=False, unsigned int omp_dynamic_chunksize=10, std::size_t n_iter_max=100000, double epsilon_large_factor=1000, double epsilon_small_factor=1, std::ostream & os=std::cout) -> PairwiseEMDYPhiFloat64"""
        _wasserstein.PairwiseEMDYPhiFloat64_swiginit(self, _wasserstein.new_PairwiseEMDYPhiFloat64(*args, **kwargs))
    __swig_destroy__ = _wasserstein.delete_PairwiseEMDYPhiFloat64
    description = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat64_description)

    def clear(self, *args, **kwargs):
        _wasserstein.PairwiseEMDYPhiFloat64_clear(self, *args, **kwargs)
        if hasattr(self, 'event_arrs'):
            del self.event_arrs


    init = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat64_init)
    compute = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat64_compute)
    __repr__ = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat64___repr__)
    preprocess_CenterWeightedCentroid = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat64_preprocess_CenterWeightedCentroid)
    _reset_B_events = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat64__reset_B_events)


    def set_new_eventsB(self, eventsB, gdim=None, mask=False, event_weightsB=None):

    # check that we have been initialized before
        if not hasattr(self, 'event_arrs'):
            raise RuntimeError('PairwiseEMD object must be called on some events before the B events can be reset')

    # check that we are in request mode
        if not self.request_mode():
            raise RuntimeError('PairwiseEMD object must be in request mode in order to set new eventsB')

        if event_weightsB is None:
            event_weightsB = np.ones(len(eventsB))
        elif len(event_weightsB) != len(eventsB):
            raise ValueError('length of `event_weightsB` does not match length of `eventsB`')

    # clear away old B events in underlying object
        self._reset_B_events()

    # clear B events from python array
        del self.event_arrs[self.nevA():]

    # reinitialize
        self.init(self.nevA(), len(eventsB))
        _store_events(self, eventsB, event_weightsB, gdim, mask, self._float_dtype)

    _add_event = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat64__add_event)

# Register PairwiseEMDYPhiFloat64 in _wasserstein:
_wasserstein.PairwiseEMDYPhiFloat64_swigregister(PairwiseEMDYPhiFloat64)

class PairwiseEMDYPhiFloat32(PairwiseEMDBaseFloat32):
    r"""Proxy of C++ wasserstein::PairwiseEMD< wasserstein::EMD< float,wasserstein::DefaultArray2Event,wasserstein::YPhiArrayDistance >,float > class."""

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

    def __init__(self, *args, **kwargs):
        r"""__init__(PairwiseEMDYPhiFloat32 self, float R=1, float beta=1, bool norm=False, int num_threads=-1, wasserstein::index_type print_every=-10, unsigned int verbose=1, bool request_mode=False, bool store_sym_emds_raw=True, bool throw_on_error=False, unsigned int omp_dynamic_chunksize=10, std::size_t n_iter_max=100000, float epsilon_large_factor=1000, float epsilon_small_factor=1, std::ostream & os=std::cout) -> PairwiseEMDYPhiFloat32"""
        _wasserstein.PairwiseEMDYPhiFloat32_swiginit(self, _wasserstein.new_PairwiseEMDYPhiFloat32(*args, **kwargs))
    __swig_destroy__ = _wasserstein.delete_PairwiseEMDYPhiFloat32
    description = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat32_description)

    def clear(self, *args, **kwargs):
        _wasserstein.PairwiseEMDYPhiFloat32_clear(self, *args, **kwargs)
        if hasattr(self, 'event_arrs'):
            del self.event_arrs


    init = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat32_init)
    compute = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat32_compute)
    __repr__ = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat32___repr__)
    preprocess_CenterWeightedCentroid = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat32_preprocess_CenterWeightedCentroid)
    _reset_B_events = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat32__reset_B_events)


    def set_new_eventsB(self, eventsB, gdim=None, mask=False, event_weightsB=None):

    # check that we have been initialized before
        if not hasattr(self, 'event_arrs'):
            raise RuntimeError('PairwiseEMD object must be called on some events before the B events can be reset')

    # check that we are in request mode
        if not self.request_mode():
            raise RuntimeError('PairwiseEMD object must be in request mode in order to set new eventsB')

        if event_weightsB is None:
            event_weightsB = np.ones(len(eventsB))
        elif len(event_weightsB) != len(eventsB):
            raise ValueError('length of `event_weightsB` does not match length of `eventsB`')

    # clear away old B events in underlying object
        self._reset_B_events()

    # clear B events from python array
        del self.event_arrs[self.nevA():]

    # reinitialize
        self.init(self.nevA(), len(eventsB))
        _store_events(self, eventsB, event_weightsB, gdim, mask, self._float_dtype)

    _add_event = _swig_new_instance_method(_wasserstein.PairwiseEMDYPhiFloat32__add_event)

# Register PairwiseEMDYPhiFloat32 in _wasserstein:
_wasserstein.PairwiseEMDYPhiFloat32_swigregister(PairwiseEMDYPhiFloat32)


def EMD(*args, **kwargs):
    dtype = kwargs.pop('dtype', 'float64')
    if dtype == 'float64' or dtype == np.float64:
        return EMDFloat64(*args, **kwargs)
    elif dtype == 'float32' or dtype == np.float32:
        return EMDFloat32(*args, **kwargs)
    else:
      raise TypeError('`dtype` {} not supported'.format(dtype))


def EMDYPhi(*args, **kwargs):
    dtype = kwargs.pop('dtype', 'float64')
    if dtype == 'float64' or dtype == np.float64:
        return EMDYPhiFloat64(*args, **kwargs)
    elif dtype == 'float32' or dtype == np.float32:
        return EMDYPhiFloat32(*args, **kwargs)
    else:
      raise TypeError('`dtype` {} not supported'.format(dtype))


def PairwiseEMD(*args, **kwargs):
    dtype = kwargs.pop('dtype', 'float64')
    if dtype == 'float64' or dtype == np.float64:
        return PairwiseEMDFloat64(*args, **kwargs)
    elif dtype == 'float32' or dtype == np.float32:
        return PairwiseEMDFloat32(*args, **kwargs)
    else:
      raise TypeError('`dtype` {} not supported'.format(dtype))


def PairwiseEMDYPhi(*args, **kwargs):
    dtype = kwargs.pop('dtype', 'float64')
    if dtype == 'float64' or dtype == np.float64:
        return PairwiseEMDYPhiFloat64(*args, **kwargs)
    elif dtype == 'float32' or dtype == np.float32:
        return PairwiseEMDYPhiFloat32(*args, **kwargs)
    else:
      raise TypeError('`dtype` {} not supported'.format(dtype))



