def register_array_xcorr(name, func=None, is_default=False):
valid_methods = set(list(XCOR_ARRAY_METHODS) + list(XCORR_STREAM_METHODS))<EOL>cache = {}<EOL>def register(register_str):<EOL><INDENT>"""<STR_LIT>"""<EOL>if register_str not in valid_methods:<EOL><INDENT>msg = '<STR_LIT>' % valid_methods<EOL>raise ValueError(msg)<EOL><DEDENT>def _register(func):<EOL><INDENT>cache[register_str] = func<EOL>setattr(cache['<STR_LIT>'], register_str, func)<EOL>return func<EOL><DEDENT>return _register<EOL><DEDENT>def wrapper(func, func_name=None):<EOL><INDENT>fname = func_name or name.__name__ if callable(name) else str(name)<EOL>XCOR_FUNCS[fname] = func<EOL>func.register = register<EOL>cache['<STR_LIT>'] = func<EOL>func.multithread = _general_multithread(func)<EOL>func.multiprocess = _general_multiprocess(func)<EOL>func.concurrent = _general_multithread(func)<EOL>func.stream_xcorr = _general_serial(func)<EOL>func.array_xcorr = func<EOL>func.registered = True<EOL>if is_default:  <EOL><INDENT>XCOR_FUNCS['<STR_LIT:default>'] = copy.deepcopy(func)<EOL><DEDENT>return func<EOL><DEDENT>if callable(name):<EOL><INDENT>return wrapper(name)<EOL><DEDENT>if callable(func):<EOL><INDENT>return wrapper(func, func_name=name)<EOL><DEDENT>return wrapper<EOL>
Decorator for registering correlation functions.

Each function must have the same interface as numpy_normxcorr, which is
*f(templates, stream, pads, *args, **kwargs)* any number of specific kwargs
can be used.

Register_normxcorr can be used as a decorator (with or without arguments)
or as a callable.

:param name: The name of the function for quick access, or the callable
    that will be wrapped when used as a decorator.
:type name: str, callable
:param func: The function to register
:type func: callable, optional
:param is_default: True if this function should be marked as default
    normxcorr
:type is_default: bool

:return: callable