# Path: numcodecs/compat.py
# def ensure_contiguous_ndarray(buf, max_buffer_size=None):
#     """Convenience function to coerce `buf` to a numpy array, if it is not already a
#     numpy array. Also ensures that the returned value exports fully contiguous memory,
#     and supports the new-style buffer interface. If the optional max_buffer_size is
#     provided, raise a ValueError if the number of bytes consumed by the returned
#     array exceeds this value.
# 
#     Parameters
#     ----------
#     buf : array-like or bytes-like
#         A numpy array or any object exporting a buffer interface.
#     max_buffer_size : int
#         If specified, the largest allowable value of arr.nbytes, where arr
#         is the returned array.
# 
#     Returns
#     -------
#     arr : ndarray
#         A numpy array, sharing memory with `buf`.
# 
#     Notes
#     -----
#     This function will not create a copy under any circumstances, it is guaranteed to
#     return a view on memory exported by `buf`.
# 
#     """
# 
#     # ensure input is a numpy array
#     arr = ensure_ndarray(buf)
# 
#     # check for object arrays, these are just memory pointers, actual memory holding
#     # item data is scattered elsewhere
#     if arr.dtype == object:
#         raise TypeError('object arrays are not supported')
# 
#     # check for datetime or timedelta ndarray, the buffer interface doesn't support those
#     if arr.dtype.kind in 'Mm':
#         arr = arr.view(np.int64)
# 
#     # check memory is contiguous, if so flatten
#     if arr.flags.c_contiguous or arr.flags.f_contiguous:
#         # can flatten without copy
#         arr = arr.reshape(-1, order='A')
# 
#     else:
#         raise ValueError('an array with contiguous memory is required')
# 
#     if max_buffer_size is not None and arr.nbytes > max_buffer_size:
#         msg = "Codec does not support buffers of > {} bytes".format(max_buffer_size)
#         raise ValueError(msg)
# 
#     return arr
# 
# Path: numcodecs/abc.py
# class Codec:
#     """Codec abstract base class."""
# 
#     # override in sub-class
#     codec_id = None
#     """Codec identifier."""
# 
#     @abstractmethod
#     def encode(self, buf):  # pragma: no cover
#         """Encode data in `buf`.
# 
#         Parameters
#         ----------
#         buf : buffer-like
#             Data to be encoded. May be any object supporting the new-style
#             buffer protocol.
# 
#         Returns
#         -------
#         enc : buffer-like
#             Encoded data. May be any object supporting the new-style buffer
#             protocol.
#         """
# 
#     @abstractmethod
#     def decode(self, buf, out=None):  # pragma: no cover
#         """Decode data in `buf`.
# 
#         Parameters
#         ----------
#         buf : buffer-like
#             Encoded data. May be any object supporting the new-style buffer
#             protocol.
#         out : buffer-like, optional
#             Writeable buffer to store decoded data. N.B. if provided, this buffer must
#             be exactly the right size to store the decoded data.
# 
#         Returns
#         -------
#         dec : buffer-like
#             Decoded data. May be any object supporting the new-style
#             buffer protocol.
#         """
# 
#     def get_config(self):
#         """Return a dictionary holding configuration parameters for this
#         codec. Must include an 'id' field with the codec identifier. All
#         values must be compatible with JSON encoding."""
# 
#         # override in sub-class if need special encoding of config values
# 
#         # setup config object
#         config = dict(id=self.codec_id)
# 
#         # by default, assume all non-private members are configuration
#         # parameters - override this in sub-class if not the case
#         for k in self.__dict__:
#             if not k.startswith('_'):
#                 config[k] = getattr(self, k)
# 
#         return config
# 
#     @classmethod
#     def from_config(cls, config):
#         """Instantiate codec from a configuration object."""
#         # N.B., assume at this point the 'id' field has been removed from
#         # the config object
# 
#         # override in sub-class if need special decoding of config values
# 
#         # by default, assume constructor accepts configuration parameters as
#         # keyword arguments without any special decoding
#         return cls(**config)
# 
#     def __eq__(self, other):
#         # override in sub-class if need special equality comparison
#         try:
#             return self.get_config() == other.get_config()
#         except AttributeError:
#             return False
# 
#     def __repr__(self):
# 
#         # override in sub-class if need special representation
# 
#         # by default, assume all non-private members are configuration
#         # parameters and valid keyword arguments to constructor function
# 
#         r = '%s(' % type(self).__name__
#         params = ['{}={!r}'.format(k, getattr(self, k))
#                   for k in sorted(self.__dict__)
#                   if not k.startswith('_')]
#         r += ', '.join(params) + ')'
#         return r


import numpy as np
from .compat import ensure_contiguous_ndarray
from .abc import Codec
from ._shuffle import _doShuffle, _doUnshuffle


class Shuffle(Codec):
    """Codec providing shuffle

    Parameters
    ----------
    elementsize : int
        Size in bytes of the array elements.  Default = 4

    """

    codec_id = 'shuffle'

    def __init__(self, elementsize=4):
        self.elementsize = elementsize

    def _prepare_arrays(self, buf, out):
        buf = ensure_contiguous_ndarray(buf)

        if out is None:
            out = np.zeros(buf.nbytes, dtype='uint8')
        else:

# Path: numcodecs/compat.py
# def ensure_contiguous_ndarray(buf, max_buffer_size=None):
#     """Convenience function to coerce `buf` to a numpy array, if it is not already a
#     numpy array. Also ensures that the returned value exports fully contiguous memory,
#     and supports the new-style buffer interface. If the optional max_buffer_size is
#     provided, raise a ValueError if the number of bytes consumed by the returned
#     array exceeds this value.
# 
#     Parameters
#     ----------
#     buf : array-like or bytes-like
#         A numpy array or any object exporting a buffer interface.
#     max_buffer_size : int
#         If specified, the largest allowable value of arr.nbytes, where arr
#         is the returned array.
# 
#     Returns
#     -------
#     arr : ndarray
#         A numpy array, sharing memory with `buf`.
# 
#     Notes
#     -----
#     This function will not create a copy under any circumstances, it is guaranteed to
#     return a view on memory exported by `buf`.
# 
#     """
# 
#     # ensure input is a numpy array
#     arr = ensure_ndarray(buf)
# 
#     # check for object arrays, these are just memory pointers, actual memory holding
#     # item data is scattered elsewhere
#     if arr.dtype == object:
#         raise TypeError('object arrays are not supported')
# 
#     # check for datetime or timedelta ndarray, the buffer interface doesn't support those
#     if arr.dtype.kind in 'Mm':
#         arr = arr.view(np.int64)
# 
#     # check memory is contiguous, if so flatten
#     if arr.flags.c_contiguous or arr.flags.f_contiguous:
#         # can flatten without copy
#         arr = arr.reshape(-1, order='A')
# 
#     else:
#         raise ValueError('an array with contiguous memory is required')
# 
#     if max_buffer_size is not None and arr.nbytes > max_buffer_size:
#         msg = "Codec does not support buffers of > {} bytes".format(max_buffer_size)
#         raise ValueError(msg)
# 
#     return arr
# 
# Path: numcodecs/abc.py
# class Codec:
#     """Codec abstract base class."""
# 
#     # override in sub-class
#     codec_id = None
#     """Codec identifier."""
# 
#     @abstractmethod
#     def encode(self, buf):  # pragma: no cover
#         """Encode data in `buf`.
# 
#         Parameters
#         ----------
#         buf : buffer-like
#             Data to be encoded. May be any object supporting the new-style
#             buffer protocol.
# 
#         Returns
#         -------
#         enc : buffer-like
#             Encoded data. May be any object supporting the new-style buffer
#             protocol.
#         """
# 
#     @abstractmethod
#     def decode(self, buf, out=None):  # pragma: no cover
#         """Decode data in `buf`.
# 
#         Parameters
#         ----------
#         buf : buffer-like
#             Encoded data. May be any object supporting the new-style buffer
#             protocol.
#         out : buffer-like, optional
#             Writeable buffer to store decoded data. N.B. if provided, this buffer must
#             be exactly the right size to store the decoded data.
# 
#         Returns
#         -------
#         dec : buffer-like
#             Decoded data. May be any object supporting the new-style
#             buffer protocol.
#         """
# 
#     def get_config(self):
#         """Return a dictionary holding configuration parameters for this
#         codec. Must include an 'id' field with the codec identifier. All
#         values must be compatible with JSON encoding."""
# 
#         # override in sub-class if need special encoding of config values
# 
#         # setup config object
#         config = dict(id=self.codec_id)
# 
#         # by default, assume all non-private members are configuration
#         # parameters - override this in sub-class if not the case
#         for k in self.__dict__:
#             if not k.startswith('_'):
#                 config[k] = getattr(self, k)
# 
#         return config
# 
#     @classmethod
#     def from_config(cls, config):
#         """Instantiate codec from a configuration object."""
#         # N.B., assume at this point the 'id' field has been removed from
#         # the config object
# 
#         # override in sub-class if need special decoding of config values
# 
#         # by default, assume constructor accepts configuration parameters as
#         # keyword arguments without any special decoding
#         return cls(**config)
# 
#     def __eq__(self, other):
#         # override in sub-class if need special equality comparison
#         try:
#             return self.get_config() == other.get_config()
#         except AttributeError:
#             return False
# 
#     def __repr__(self):
# 
#         # override in sub-class if need special representation
# 
#         # by default, assume all non-private members are configuration
#         # parameters and valid keyword arguments to constructor function
# 
#         r = '%s(' % type(self).__name__
#         params = ['{}={!r}'.format(k, getattr(self, k))
#                   for k in sorted(self.__dict__)
#                   if not k.startswith('_')]
#         r += ', '.join(params) + ')'
#         return r


# Path: numcodecs/shuffle.py
import numpy as np
from .compat import ensure_contiguous_ndarray
from .abc import Codec
from ._shuffle import _doShuffle, _doUnshuffle



class Shuffle(Codec):
    """Codec providing shuffle

    Parameters
    ----------
    elementsize : int
        Size in bytes of the array elements.  Default = 4

    """

    codec_id = 'shuffle'

    def __init__(self, elementsize=4):
        self.elementsize = elementsize

    def _prepare_arrays(self, buf, out):
        buf = ensure_contiguous_ndarray(buf)

        if out is None:
            out = np.zeros(buf.nbytes, dtype='uint8')
        else:

            out = ensure_contiguous_ndarray(out)