def METHOD_NAME(ndim, batch_size, in_dtype, out_dtype, device, empty_volume_policy=None):
    def src():
        return generate(rng, ndim, batch_size, in_dtype, out_dtype, empty_volume_policy)
    @pipeline_def(batch_size=batch_size, num_threads=4,
                  device_id=types.CPU_ONLY_DEVICE_ID if device == 'cpu' else 0)
    def cast_pipe():
        inp = fn.external_source(src)
        inp_dev = inp.gpu() if device == 'gpu' else inp
        return inp, fn.cast(inp_dev, dtype=np_type_to_dali(out_dtype))
    pipe = cast_pipe()
    pipe.build()
    for _ in range(10):
        inp, out = pipe.run()
        if device == 'gpu':
            out = out.as_cpu()
        ref = [ref_cast(np.array(x), out_dtype) for x in inp]
        # work around a bug in numpy: when the argument is a scalar fp32 or fp16, nextafter
        # promotes it to fp64, resulting in insufficient epsilon - we want an epsilon of the
        # type specified in out_dtype
        eps = 0 if np.issubdtype(out_dtype, np.integer) else \
            (np.nextafter(out_dtype([1]), 2) - 1.0)[0]
        for i in range(batch_size):
            if not np.allclose(out[i], ref[i], eps):
                matI = np.array(inp[i])
                matO = np.array(out[i])
                matR = ref[i]
                mask = np.logical_not(np.isclose(matO, matR, eps))
                print(f"At sample {i}:\nI:\n{matI}\nO\n{matO}\nR\n{matR}")
                print(f"Differences at {mask}:\nI:\n{matI[mask]}\nO\n{matO[mask]}\nR\n{matR[mask]}")
                print(f"Result: {np.count_nonzero(mask)} wrong values out of {mask.size}.")
                assert np.array_equal(out[i], ref[i])