def __init__(self, pyfunc, sympy_func=None, arg_units=None, arg_names=None, return_unit=None, arg_types=None, return_type=None, stateless=True, auto_vectorise=False):
    self.pyfunc = pyfunc
    self.sympy_func = sympy_func
    self._arg_units = arg_units
    self._arg_names = arg_names
    self._return_unit = return_unit
    if (return_unit == bool):
        self._returns_bool = True
    else:
        self._returns_bool = False
    self._arg_types = arg_types
    self._return_type = return_type
    self.stateless = stateless
    self.auto_vectorise = auto_vectorise
    if (self._arg_units is None):
        if (not hasattr(pyfunc, '_arg_units')):
            raise ValueError(('The Python function "%s" does not specify how it deals with units, need to specify "arg_units" or use the "@check_units" decorator.' % pyfunc.__name__))
        elif (pyfunc._arg_units is None):
            raise ValueError(('The Python function "%s" does not specify the units for all of its arguments.' % pyfunc.__name__))
        else:
            self._arg_units = pyfunc._arg_units
    elif any((isinstance(u, str) for u in self._arg_units)):
        if (self._arg_names is None):
            raise TypeError('Need to specify the names of the arguments.')
        if (len(self._arg_names) != len(self._arg_units)):
            raise TypeError(f'arg_names and arg_units need to have the same length ({len(self._arg_names)} != ({len(self._arg_units)})')
    if (self._return_unit is None):
        if (not hasattr(pyfunc, '_return_unit')):
            raise ValueError(('The Python function "%s" does not specify how it deals with units, need to specify "return_unit" or use the "@check_units" decorator.' % pyfunc.__name__))
        elif (pyfunc._return_unit is None):
            raise ValueError(('The Python function "%s" does not specify the unit for its return value.' % pyfunc.__name__))
        else:
            self._return_unit = pyfunc._return_unit
    if (self._arg_types is None):
        if hasattr(pyfunc, '_arg_types'):
            self._arg_types = pyfunc._arg_types
        else:
            self._arg_types = (['any'] * len(self._arg_units))
    if (self._return_type is None):
        self._return_type = getattr(pyfunc, '_return_type', 'float')
    for (argtype, u) in zip(self._arg_types, self._arg_units):
        if ((argtype != 'float') and (argtype != 'any') and (u is not None) and (not is_dimensionless(u))):
            raise TypeError(('Non-float arguments must be dimensionless in function ' + pyfunc.__name__))
        if (argtype not in VALID_ARG_TYPES):
            raise ValueError(('Argument type %s is not valid, must be one of %s, in function %s' % (argtype, VALID_ARG_TYPES, pyfunc.__name__)))
    if (self._return_type not in VALID_RETURN_TYPES):
        raise ValueError(('Return type %s is not valid, must be one of %s, in function %s' % (self._return_type, VALID_RETURN_TYPES, pyfunc.__name__)))
    self.implementations = FunctionImplementationContainer(self)
def __init__(self, pyfunc, sympy_func=None, arg_units=None, arg_names=None, return_unit=None, arg_types=None, return_type=None, stateless=True, auto_vectorise=False):
    self.pyfunc = pyfunc
    self.sympy_func = sympy_func
    self._arg_units = arg_units
    self._arg_names = arg_names
    self._return_unit = return_unit
    if (return_unit == bool):
        self._returns_bool = True
    else:
        self._returns_bool = False
    self._arg_types = arg_types
    self._return_type = return_type
    self.stateless = stateless
    self.auto_vectorise = auto_vectorise
    if (self._arg_units is None):
        if (not hasattr(pyfunc, '_arg_units')):
            raise ValueError(('The Python function "%s" does not specify how it deals with units, need to specify "arg_units" or use the "@check_units" decorator.' % pyfunc.__name__))
        elif (pyfunc._arg_units is None):
            raise ValueError(('The Python function "%s" does not specify the units for all of its arguments.' % pyfunc.__name__))
        else:
            self._arg_units = pyfunc._arg_units
    elif any((isinstance(u, str) for u in self._arg_units)):
        if (self._arg_names is None):
            raise TypeError('Need to specify the names of the arguments.')
        if (len(self._arg_names) != len(self._arg_units)):
            raise TypeError(f'arg_names and arg_units need to have the same length ({len(self._arg_names)} != ({len(self._arg_units)})')
    if (self._return_unit is None):
        if (not hasattr(pyfunc, '_return_unit')):
            raise ValueError(('The Python function "%s" does not specify how it deals with units, need to specify "return_unit" or use the "@check_units" decorator.' % pyfunc.__name__))
        elif (pyfunc._return_unit is None):
            raise ValueError(('The Python function "%s" does not specify the unit for its return value.' % pyfunc.__name__))
        else:
            self._return_unit = pyfunc._return_unit
    if (self._arg_types is None):
        if hasattr(pyfunc, '_arg_types'):
            self._arg_types = pyfunc._arg_types
        else:
            self._arg_types = (['any'] * len(self._arg_units))
    if (self._return_type is None):
        self._return_type = getattr(pyfunc, '_return_type', 'float')
    for (argtype, u) in zip(self._arg_types, self._arg_units):
        if ((argtype != 'float') and (argtype != 'any') and (u is not None) and (not is_dimensionless(u))):
            raise TypeError(('Non-float arguments must be dimensionless in function ' + pyfunc.__name__))
        if (argtype not in VALID_ARG_TYPES):
            raise ValueError(('Argument type %s is not valid, must be one of %s, in function %s' % (argtype, VALID_ARG_TYPES, pyfunc.__name__)))
    if (self._return_type not in VALID_RETURN_TYPES):
        raise ValueError(('Return type %s is not valid, must be one of %s, in function %s' % (self._return_type, VALID_RETURN_TYPES, pyfunc.__name__)))
    self.implementations = FunctionImplementationContainer(self)