#!/usr/bin/env python def is_contiguous(memview, order='C'): """Returns true if the memory view passed is contiguous. Parameters ---------- memview : memoryview order : {'C', 'F'} Memory layout which should be satisfied. """ if order not in ('C', 'F'): raise ValueError("Only 'C' and 'F' are supported orders.") # These special cases are all 0 or 1-d so the order does not matter: if memview.ndim == 0: # Single element is always contiguous return True if memview.strides is None: return True if memview.shape is None: if memview.strides[0] == memview.itemsize: return True return False # The usual code when both strides and shape is not None: if order == 'C': # Invert C-order, so that first dimension should change slowest strides = memview.strides[::-1] shape = memview.shape[::-1] else: strides = memview.strides shape = memview.shape # The stride used by a contiguous buffer which follows from itemsize+shape expected_stride = memview.itemsize is_contiguous = True for i in range(memview.ndim): if shape[i] == 0: # A buffer without elements is always contiguous return True if shape[i] == 1: # If the shape is 1, the corresponding index is 0, so the stride # is not relavent for calculating memory offsets/the memory layout continue if strides[i] != expected_stride: is_contiguous = False # No return here, because buffer might be empty. expected_stride *= shape[i] return is_contiguous