#include "bench_funcs.h" #include #include #include double dot_basic(const std::vector& x, const std::vector& y) { assert(x.size() == y.size()); double s = 0.0; std::size_t N = x.size(); for (std::size_t i = 0; i < N; ++i) { s += x[i] * y[i]; } return s; } double dot_kahan(const std::vector& x, const std::vector& y) { assert(x.size() == y.size()); double sum = 0.0; double c = 0.0; std::size_t N = x.size(); for (std::size_t i = 0; i < N; ++i) { double prod = x[i] * y[i]; double yk = prod - c; double t = sum + yk; c = (t - sum) - yk; sum = t; } return sum; } double norm_basic(const std::vector& x) { double s = 0.0; for (std::size_t i = 0; i < x.size(); ++i) { double v = x[i]; s += v * v; } return std::sqrt(s); } void matvec_rowmajor(const std::vector& A, std::size_t M, std::size_t N, const std::vector& x, std::vector& b) { assert(A.size() == M * N); assert(x.size() == N); b.assign(M, 0.0); for (std::size_t i = 0; i < M; ++i) { //over rows double sum = 0.0; std::size_t base = i * N; //the start index of row 1 for (std::size_t j = 0; j < N; ++j) { //dot product of that row with x sum += A[base + j] * x[j]; } b[i] = sum; } } void matmul_rowmajor(const std::vector& A, std::size_t M, std::size_t L, const std::vector& B, std::size_t N, std::vector& C) { assert(A.size() == M * L); assert(B.size() == L * N); C.assign(M * N, 0.0); for (std::size_t i = 0; i < M; ++i) { for (std::size_t k = 0; k < L; ++k) { double a = A[i * L + k]; //a=A[i,k] std::size_t baseB = k * N; std::size_t baseC = i * N; for (std::size_t j = 0; j < N; ++j) { C[baseC + j] += a * B[baseB + j]; } } } } void polyp_horner(const std::vector& a, const std::vector& x, std::vector& y) { std::size_t p = (a.size() == 0) ? 0 : a.size() - 1; //if a.size=0, then p=0, otherwise p=a.soze-1 std::size_t N = x.size(); y.assign(N, 0.0); for (std::size_t i = 0; i < N; ++i) { //loops over all evaluation points x[i] double xi = x[i]; double acc = a[p]; for (std::size_t k = p; k-- > 0;) { // from p-1 down to 0 acc = acc * xi + a[k]; } y[i] = acc; } } void jacobi_csr(const CSR& K, const std::vector& f, std::vector& u, std::size_t max_iter, double omega, double tol) { std::size_t n = K.n; assert(f.size() == n); u.assign(n, 0.0); std::vector u_new(n, 0.0); for (std::size_t iter = 0; iter < max_iter; ++iter) { //Jacobi iteration double max_err = 0.0; for (std::size_t i = 0; i < n; ++i) { double diag = 0.0; double sum = 0.0; for (std::size_t idx = K.row_ptr[i]; idx < K.row_ptr[i+1]; ++idx) { //iterates over the non zero entries of row i std::size_t j = K.col[idx]; double v = K.val[idx]; if (j == i) diag = v; else sum += v * u[j]; //accomulates sum = Σ_{j≠i} K_ij * u[j] } double uk1 = u[i] + omega * (f[i] - sum - diag * u[i]) / diag; //stoers the diagonal separately u_new[i] = uk1; double err = std::fabs(uk1 - u[i]); if (err > max_err) max_err = err; } u.swap(u_new); if (max_err < tol) break; } }