void FdmGaussSeidelSolver3::relax(const MatrixCsrD& A, const VectorND& b,
                                  double sorFactor, VectorND* x_) {
    const auto rp = A.rowPointersBegin();
    const auto ci = A.columnIndicesBegin();
    const auto nnz = A.nonZeroBegin();

    VectorND& x = *x_;

    b.forEachIndex([&](size_t i) {
        const size_t rowBegin = rp[i];
        const size_t rowEnd = rp[i + 1];

        double r = 0.0;
        double diag = 1.0;
        for (size_t jj = rowBegin; jj < rowEnd; ++jj) {
            size_t j = ci[jj];

            if (i == j) {
                diag = nnz[jj];
            } else {
                r += nnz[jj] * x[j];
            }
        }

        x[i] = (1.0 - sorFactor) * x[i] + sorFactor * (b[i] - r) / diag;
    });
}
    void SetUp(const ::benchmark::State& state) {
        std::mt19937 rng{0};
        std::uniform_real_distribution<> d(0.0, 1.0);

        const auto n = static_cast<size_t>(state.range(0));

        mat.resize(n, n);
        x.resize(n);
        y.resize(n);
        mat.forEachIndex([&](size_t i, size_t j) { mat(i, j) = d(rng); });
        x.forEachIndex([&](size_t i) {
            x[i] = d(rng);
            y[i] = d(rng);
        });
    }
void FdmIccgSolver2::PreconditionerCompressed::solve(const VectorND& b,
                                                     VectorND* x) {
    const ssize_t size = static_cast<ssize_t>(b.size());

    const auto rp = A->rowPointersBegin();
    const auto ci = A->columnIndicesBegin();
    const auto nnz = A->nonZeroBegin();

    b.forEachIndex([&](size_t i) {
        const size_t rowBegin = rp[i];
        const size_t rowEnd = rp[i + 1];

        double sum = b[i];
        for (size_t jj = rowBegin; jj < rowEnd; ++jj) {
            size_t j = ci[jj];

            if (j < i) {
                sum -= nnz[jj] * y[j];
            }
        }

        y[i] = sum * d[i];
    });

    for (ssize_t i = size - 1; i >= 0; --i) {
        const size_t rowBegin = rp[i];
        const size_t rowEnd = rp[i + 1];

        double sum = y[i];
        for (size_t jj = rowBegin; jj < rowEnd; ++jj) {
            ssize_t j = static_cast<ssize_t>(ci[jj]);

            if (j > i) {
                sum -= nnz[jj] * (*x)[j];
            }
        }

        (*x)[i] = sum * d[i];
    }
}