| /** |
| * gemver.c: This file is part of the PolyBench/C 3.2 test suite. |
| * |
| * |
| * Contact: Louis-Noel Pouchet <pouchet@cse.ohio-state.edu> |
| * Web address: http://polybench.sourceforge.net |
| */ |
| #include <stdio.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <math.h> |
| |
| /* Include polybench common header. */ |
| #include <polybench.h> |
| |
| /* Include benchmark-specific header. */ |
| /* Default data type is double, default size is 4000. */ |
| #include "gemver.h" |
| |
| |
| /* Array initialization. */ |
| static |
| void init_array (int n, |
| DATA_TYPE *alpha, |
| DATA_TYPE *beta, |
| DATA_TYPE POLYBENCH_2D(A,N,N,n,n), |
| DATA_TYPE POLYBENCH_1D(u1,N,n), |
| DATA_TYPE POLYBENCH_1D(v1,N,n), |
| DATA_TYPE POLYBENCH_1D(u2,N,n), |
| DATA_TYPE POLYBENCH_1D(v2,N,n), |
| DATA_TYPE POLYBENCH_1D(w,N,n), |
| #if !FMA_DISABLED |
| DATA_TYPE POLYBENCH_1D(w_StrictFP,N,n), |
| #endif |
| DATA_TYPE POLYBENCH_1D(y,N,n), |
| DATA_TYPE POLYBENCH_1D(z,N,n)) |
| { |
| #pragma STDC FP_CONTRACT OFF |
| int i, j; |
| |
| *alpha = 43532; |
| *beta = 12313; |
| |
| for (i = 0; i < n; i++) |
| { |
| u1[i] = i; |
| u2[i] = (i+1)/n/2.0; |
| v1[i] = (i+1)/n/4.0; |
| v2[i] = (i+1)/n/6.0; |
| y[i] = (i+1)/n/8.0; |
| z[i] = (i+1)/n/9.0; |
| #if !FMA_DISABLED |
| w_StrictFP[i] = w[i] = 0.0; |
| #endif |
| for (j = 0; j < n; j++) |
| A[i][j] = ((DATA_TYPE) i*j) / n; |
| } |
| } |
| |
| |
| /* DCE code. Must scan the entire live-out data. |
| Can be used also to check the correctness of the output. */ |
| static |
| void print_array(int n, |
| DATA_TYPE POLYBENCH_1D(w,N,n)) |
| { |
| int i; |
| for (i = 0; i < n; i++) { |
| fprintf (stderr, DATA_PRINTF_MODIFIER, w[i]); |
| if (i % 20 == 0) fprintf (stderr, "\n"); |
| } |
| } |
| |
| |
| /* Main computational kernel. The whole function will be timed, |
| including the call and return. */ |
| static |
| void kernel_gemver(int n, |
| DATA_TYPE alpha, |
| DATA_TYPE beta, |
| DATA_TYPE POLYBENCH_2D(A,N,N,n,n), |
| DATA_TYPE POLYBENCH_2D(A_tmp,N,N,n,n), |
| DATA_TYPE POLYBENCH_1D(u1,N,n), |
| DATA_TYPE POLYBENCH_1D(v1,N,n), |
| DATA_TYPE POLYBENCH_1D(u2,N,n), |
| DATA_TYPE POLYBENCH_1D(v2,N,n), |
| DATA_TYPE POLYBENCH_1D(w,N,n), |
| DATA_TYPE POLYBENCH_1D(x,N,n), |
| DATA_TYPE POLYBENCH_1D(y,N,n), |
| DATA_TYPE POLYBENCH_1D(z,N,n)) |
| { |
| int i, j; |
| |
| #pragma scop |
| |
| for (i = 0; i < _PB_N; i++) |
| for (j = 0; j < _PB_N; j++) |
| A_tmp[i][j] = A[i][j] + u1[i] * v1[j] + u2[i] * v2[j]; |
| |
| for (i = 0; i < _PB_N; i++) { |
| x[i] = 0.0; |
| for (j = 0; j < _PB_N; j++) |
| x[i] = x[i] + beta * A_tmp[j][i] * y[j]; |
| } |
| |
| for (i = 0; i < _PB_N; i++) |
| x[i] = x[i] + z[i]; |
| |
| for (i = 0; i < _PB_N; i++) |
| for (j = 0; j < _PB_N; j++) |
| w[i] = w[i] + alpha * A_tmp[i][j] * x[j]; |
| |
| #pragma endscop |
| } |
| |
| #if !FMA_DISABLED |
| // NOTE: FMA_DISABLED is true for targets where FMA contraction causes |
| // discrepancies which cause the accuracy checks to fail. |
| // In this case, the test runs with the option -ffp-contract=off |
| static |
| void kernel_gemver_StrictFP(int n, |
| DATA_TYPE alpha, |
| DATA_TYPE beta, |
| DATA_TYPE POLYBENCH_2D(A,N,N,n,n), |
| DATA_TYPE POLYBENCH_2D(A_tmp,N,N,n,n), |
| DATA_TYPE POLYBENCH_1D(u1,N,n), |
| DATA_TYPE POLYBENCH_1D(v1,N,n), |
| DATA_TYPE POLYBENCH_1D(u2,N,n), |
| DATA_TYPE POLYBENCH_1D(v2,N,n), |
| DATA_TYPE POLYBENCH_1D(w,N,n), |
| DATA_TYPE POLYBENCH_1D(x,N,n), |
| DATA_TYPE POLYBENCH_1D(y,N,n), |
| DATA_TYPE POLYBENCH_1D(z,N,n)) |
| { |
| #pragma STDC FP_CONTRACT OFF |
| int i, j; |
| |
| for (i = 0; i < _PB_N; i++) |
| for (j = 0; j < _PB_N; j++) |
| A_tmp[i][j] = A[i][j] + u1[i] * v1[j] + u2[i] * v2[j]; |
| |
| for (i = 0; i < _PB_N; i++) { |
| x[i] = 0.0; |
| for (j = 0; j < _PB_N; j++) |
| x[i] = x[i] + beta * A_tmp[j][i] * y[j]; |
| } |
| |
| for (i = 0; i < _PB_N; i++) |
| x[i] = x[i] + z[i]; |
| |
| for (i = 0; i < _PB_N; i++) |
| for (j = 0; j < _PB_N; j++) |
| w[i] = w[i] + alpha * A_tmp[i][j] * x[j]; |
| } |
| |
| /* Return 0 when one of the elements of arrays A and B do not match within the |
| allowed FP_ABSTOLERANCE. Return 1 when all elements match. */ |
| static int |
| check_FP(int n, |
| DATA_TYPE POLYBENCH_1D(A,N,n), |
| DATA_TYPE POLYBENCH_1D(B,N,n)) { |
| int i; |
| double AbsTolerance = FP_ABSTOLERANCE; |
| for (i = 0; i < _PB_N; i++) |
| { |
| double V1 = A[i]; |
| double V2 = B[i]; |
| double Diff = fabs(V1 - V2); |
| if (Diff > AbsTolerance) { |
| fprintf(stderr, "A[%d] = %lf and B[%d] = %lf differ more than" |
| " FP_ABSTOLERANCE = %lf\n", i, V1, i, V2, AbsTolerance); |
| return 0; |
| } |
| } |
| |
| return 1; |
| } |
| #endif |
| |
| int main(int argc, char** argv) |
| { |
| /* Retrieve problem size. */ |
| int n = N; |
| |
| /* Variable declaration/allocation. */ |
| DATA_TYPE alpha; |
| DATA_TYPE beta; |
| POLYBENCH_2D_ARRAY_DECL(A, DATA_TYPE, N, N, n, n); |
| POLYBENCH_2D_ARRAY_DECL(A_tmp, DATA_TYPE, N, N, n, n); |
| POLYBENCH_1D_ARRAY_DECL(u1, DATA_TYPE, N, n); |
| POLYBENCH_1D_ARRAY_DECL(v1, DATA_TYPE, N, n); |
| POLYBENCH_1D_ARRAY_DECL(u2, DATA_TYPE, N, n); |
| POLYBENCH_1D_ARRAY_DECL(v2, DATA_TYPE, N, n); |
| POLYBENCH_1D_ARRAY_DECL(w, DATA_TYPE, N, n); |
| #if !FMA_DISABLED |
| POLYBENCH_1D_ARRAY_DECL(w_StrictFP, DATA_TYPE, N, n); |
| #endif |
| POLYBENCH_1D_ARRAY_DECL(x, DATA_TYPE, N, n); |
| POLYBENCH_1D_ARRAY_DECL(y, DATA_TYPE, N, n); |
| POLYBENCH_1D_ARRAY_DECL(z, DATA_TYPE, N, n); |
| |
| |
| /* Initialize array(s). */ |
| init_array (n, &alpha, &beta, |
| POLYBENCH_ARRAY(A), |
| POLYBENCH_ARRAY(u1), |
| POLYBENCH_ARRAY(v1), |
| POLYBENCH_ARRAY(u2), |
| POLYBENCH_ARRAY(v2), |
| POLYBENCH_ARRAY(w), |
| #if !FMA_DISABLED |
| POLYBENCH_ARRAY(w_StrictFP), |
| #endif |
| POLYBENCH_ARRAY(y), |
| POLYBENCH_ARRAY(z)); |
| |
| /* Start timer. */ |
| polybench_start_instruments; |
| |
| /* Run kernel. */ |
| kernel_gemver (n, alpha, beta, |
| POLYBENCH_ARRAY(A), |
| POLYBENCH_ARRAY(A_tmp), |
| POLYBENCH_ARRAY(u1), |
| POLYBENCH_ARRAY(v1), |
| POLYBENCH_ARRAY(u2), |
| POLYBENCH_ARRAY(v2), |
| POLYBENCH_ARRAY(w), |
| POLYBENCH_ARRAY(x), |
| POLYBENCH_ARRAY(y), |
| POLYBENCH_ARRAY(z)); |
| |
| /* Stop and print timer. */ |
| polybench_stop_instruments; |
| polybench_print_instruments; |
| |
| #if FMA_DISABLED |
| /* Prevent dead-code elimination. All live-out data must be printed |
| by the function call in argument. */ |
| polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(w))); |
| #else |
| kernel_gemver_StrictFP(n, alpha, beta, |
| POLYBENCH_ARRAY(A), |
| POLYBENCH_ARRAY(A_tmp), |
| POLYBENCH_ARRAY(u1), |
| POLYBENCH_ARRAY(v1), |
| POLYBENCH_ARRAY(u2), |
| POLYBENCH_ARRAY(v2), |
| POLYBENCH_ARRAY(w_StrictFP), |
| POLYBENCH_ARRAY(x), |
| POLYBENCH_ARRAY(y), |
| POLYBENCH_ARRAY(z)); |
| if (!check_FP(n, POLYBENCH_ARRAY(w), POLYBENCH_ARRAY(w_StrictFP))) |
| return 1; |
| |
| /* Prevent dead-code elimination. All live-out data must be printed |
| by the function call in argument. */ |
| polybench_prevent_dce(print_array(n, POLYBENCH_ARRAY(w_StrictFP))); |
| #endif |
| |
| /* Be clean. */ |
| POLYBENCH_FREE_ARRAY(A); |
| POLYBENCH_FREE_ARRAY(A_tmp); |
| POLYBENCH_FREE_ARRAY(u1); |
| POLYBENCH_FREE_ARRAY(v1); |
| POLYBENCH_FREE_ARRAY(u2); |
| POLYBENCH_FREE_ARRAY(v2); |
| POLYBENCH_FREE_ARRAY(w); |
| #if !FMA_DISABLED |
| POLYBENCH_FREE_ARRAY(w_StrictFP); |
| #endif |
| POLYBENCH_FREE_ARRAY(x); |
| POLYBENCH_FREE_ARRAY(y); |
| POLYBENCH_FREE_ARRAY(z); |
| |
| return 0; |
| } |