Repository: dask/dask
File: dask/array/core.py (Python)

Code before:
                )

        for k, v in result.items():
            chunks[k] = v if v else 0
        return tuple(chunks)

    else:
        # Check if dtype.itemsize is greater than 0
        if dtype.itemsize == 0:
            raise ValueError(
                "auto-chunking with dtype.itemsize == 0 is not supported, please pass in `chunks` explicitly"
            )
        size = (limit / dtype.itemsize / largest_block) ** (1 / len(autos))
        small = [i for i in autos if shape[i] < size]
        if small:
            for i in small:
                chunks[i] = (shape[i],)
            return auto_chunks(chunks, shape, limit, dtype)

        for i in autos:
            chunks[i] = round_to(size, shape[i])

        return tuple(chunks)


def _split_up_single_chunk(c, this_chunksize_tolerance, max_chunk_size, proposed):
    # Calculate by what factor we have to split this chunk
    m = c / proposed
    if math.ceil(m) / m > this_chunksize_tolerance:
        # We want to smooth things potentially if rounding up would change the result
        # by a lot
        m = math.ceil(c / max_chunk_size)
    else:
        m = math.ceil(m)
    # split the chunk
    new_c, remainder = divmod(c, min(m, c))
    x = [new_c] * min(m, c)
    for i in range(remainder):
        x[i] += 1
    return x


def round_to(c, s):
    """Return a chunk dimension that is close to an even multiple or factor

    We want values for c that are nicely aligned with s.

    If c is smaller than s we use the original chunk size and accept an
    uneven chunk at the end.

    If c is larger than s then we want the largest multiple of s that is still

Review comment (suggestion):
nit: I've been thinking about the directional `left` here
```suggestion
            if multiplier_remaining:
```

Code after:
                        else:
                            # We reach the boundary so start a new chunk
                            dimension_result.append(new_chunk)
                            new_chunk = c
                            if new_chunk > max_chunk_size:
                                # our new chunk is greater than the allowed, so split it up
                                dimension_result.extend(
                                    _split_up_single_chunk(
                                        c,
                                        this_chunksize_tolerance,
                                        max_chunk_size,
                                        proposed,
                                    )
                                )
                                new_chunk = 0
                    if new_chunk > 0:
                        dimension_result.append(new_chunk)

                result[a] = tuple(dimension_result)

            # recompute how much multiplier we have left, repeat
            if multiplier_remaining:
                multiplier = _compute_multiplier(
                    limit, dtype, largest_block, median_chunks
                )

        for k, v in result.items():
            chunks[k] = v if v else 0
        return tuple(chunks)

    else:
        # Check if dtype.itemsize is greater than 0
        if dtype.itemsize == 0:
            raise ValueError(
                "auto-chunking with dtype.itemsize == 0 is not supported, please pass in `chunks` explicitly"
            )
        size = (limit / dtype.itemsize / largest_block) ** (1 / len(autos))
        small = [i for i in autos if shape[i] < size]
        if small:
            for i in small:
                chunks[i] = (shape[i],)
            return auto_chunks(chunks, shape, limit, dtype)

        for i in autos:
            chunks[i] = round_to(size, shape[i])

        return tuple(chunks)


def _split_up_single_chunk(
    c: int, this_chunksize_tolerance: float, max_chunk_size: int, proposed: int