def schwarz(A, x, b, iterations=1, subdomain=None, subdomain_ptr=None,
            inv_subblock=None, inv_subblock_ptr=None, sweep='forward'):
    A, x, b = make_system(A, x, b, formats=['csr'])
    A.sort_indices()
    if subdomain is None and inv_subblock is not None:
        raise ValueError("inv_subblock must be None if subdomain is None")
    (subdomain, subdomain_ptr, inv_subblock, inv_subblock_ptr) = \
        schwarz_parameters(A, subdomain, subdomain_ptr,
                           inv_subblock, inv_subblock_ptr)
    if sweep == 'forward':
        row_start, row_stop, row_step = 0, subdomain_ptr.shape[0]-1, 1
    elif sweep == 'backward':
        row_start, row_stop, row_step = subdomain_ptr.shape[0]-2, -1, -1
    elif sweep == 'symmetric':
        for iter in range(iterations):
            schwarz(A, x, b, iterations=1, subdomain=subdomain,
                    subdomain_ptr=subdomain_ptr, inv_subblock=inv_subblock,
                    inv_subblock_ptr=inv_subblock_ptr, sweep='forward')
            schwarz(A, x, b, iterations=1, subdomain=subdomain,
                    subdomain_ptr=subdomain_ptr, inv_subblock=inv_subblock,
                    inv_subblock_ptr=inv_subblock_ptr, sweep='backward')
        return
    else:
        raise ValueError("valid sweep directions are 'forward',\
                          'backward', and 'symmetric'")
    for iter in range(iterations):
        amg_core.overlapping_schwarz_csr(A.indptr, A.indices, A.data,
                                         x, b, inv_subblock, inv_subblock_ptr,
                                         subdomain, subdomain_ptr,
                                         subdomain_ptr.shape[0]-1, A.shape[0],
                                         row_start, row_stop, row_step)