| /** |
| * durbin.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 "durbin.h" |
| |
| |
| /* Array initialization. */ |
| static |
| void init_array (int n, |
| DATA_TYPE POLYBENCH_2D(y,N,N,n,n), |
| DATA_TYPE POLYBENCH_2D(sum,N,N,n,n), |
| DATA_TYPE POLYBENCH_1D(alpha,N,n), |
| DATA_TYPE POLYBENCH_1D(beta,N,n), |
| DATA_TYPE POLYBENCH_1D(r,N,n)) |
| { |
| #pragma STDC FP_CONTRACT OFF |
| int i, j; |
| |
| for (i = 0; i < n; i++) |
| { |
| alpha[i] = i; |
| beta[i] = (i+1)/n/2.0; |
| r[i] = (i+1)/n/4.0; |
| for (j = 0; j < n; j++) { |
| y[i][j] = ((DATA_TYPE) i*j) / n; |
| sum[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(out,N,n)) |
| |
| { |
| int i; |
| for (i = 0; i < n; i++) { |
| fprintf (stderr, DATA_PRINTF_MODIFIER, out[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_durbin(int n, |
| DATA_TYPE POLYBENCH_2D(y,N,N,n,n), |
| DATA_TYPE POLYBENCH_2D(sum,N,N,n,n), |
| DATA_TYPE POLYBENCH_1D(alpha,N,n), |
| DATA_TYPE POLYBENCH_1D(beta,N,n), |
| DATA_TYPE POLYBENCH_1D(r,N,n), |
| DATA_TYPE POLYBENCH_1D(out,N,n)) |
| { |
| int i, k; |
| |
| #pragma scop |
| y[0][0] = r[0]; |
| beta[0] = 1; |
| alpha[0] = r[0]; |
| for (k = 1; k < _PB_N; k++) |
| { |
| beta[k] = beta[k-1] - alpha[k-1] * alpha[k-1] * beta[k-1]; |
| sum[0][k] = r[k]; |
| for (i = 0; i <= k - 1; i++) |
| sum[i+1][k] = sum[i][k] + r[k-i-1] * y[i][k-1]; |
| alpha[k] = -sum[k][k] * beta[k]; |
| for (i = 0; i <= k-1; i++) |
| y[i][k] = y[i][k-1] + alpha[k] * y[k-i-1][k-1]; |
| y[k][k] = alpha[k]; |
| } |
| for (i = 0; i < _PB_N; i++) |
| out[i] = y[i][_PB_N-1]; |
| #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_durbin_StrictFP(int n, |
| DATA_TYPE POLYBENCH_2D(y,N,N,n,n), |
| DATA_TYPE POLYBENCH_2D(sum,N,N,n,n), |
| DATA_TYPE POLYBENCH_1D(alpha,N,n), |
| DATA_TYPE POLYBENCH_1D(beta,N,n), |
| DATA_TYPE POLYBENCH_1D(r,N,n), |
| DATA_TYPE POLYBENCH_1D(out,N,n)) |
| { |
| #pragma STDC FP_CONTRACT OFF |
| int i, k; |
| |
| y[0][0] = r[0]; |
| beta[0] = 1; |
| alpha[0] = r[0]; |
| for (k = 1; k < _PB_N; k++) |
| { |
| beta[k] = beta[k-1] - alpha[k-1] * alpha[k-1] * beta[k-1]; |
| sum[0][k] = r[k]; |
| for (i = 0; i <= k - 1; i++) |
| sum[i+1][k] = sum[i][k] + r[k-i-1] * y[i][k-1]; |
| alpha[k] = -sum[k][k] * beta[k]; |
| for (i = 0; i <= k-1; i++) |
| y[i][k] = y[i][k-1] + alpha[k] * y[k-i-1][k-1]; |
| y[k][k] = alpha[k]; |
| } |
| for (i = 0; i < _PB_N; i++) |
| out[i] = y[i][_PB_N-1]; |
| } |
| |
| /* 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. */ |
| POLYBENCH_2D_ARRAY_DECL(y, DATA_TYPE, N, N, n, n); |
| POLYBENCH_2D_ARRAY_DECL(sum, DATA_TYPE, N, N, n, n); |
| POLYBENCH_1D_ARRAY_DECL(alpha, DATA_TYPE, N, n); |
| POLYBENCH_1D_ARRAY_DECL(beta, DATA_TYPE, N, n); |
| POLYBENCH_1D_ARRAY_DECL(r, DATA_TYPE, N, n); |
| POLYBENCH_1D_ARRAY_DECL(out, DATA_TYPE, N, n); |
| #if !FMA_DISABLED |
| POLYBENCH_1D_ARRAY_DECL(out_StrictFP, DATA_TYPE, N, n); |
| #endif |
| |
| |
| /* Initialize array(s). */ |
| init_array (n, |
| POLYBENCH_ARRAY(y), |
| POLYBENCH_ARRAY(sum), |
| POLYBENCH_ARRAY(alpha), |
| POLYBENCH_ARRAY(beta), |
| POLYBENCH_ARRAY(r)); |
| |
| /* Start timer. */ |
| polybench_start_instruments; |
| |
| /* Run kernel. */ |
| kernel_durbin (n, |
| POLYBENCH_ARRAY(y), |
| POLYBENCH_ARRAY(sum), |
| POLYBENCH_ARRAY(alpha), |
| POLYBENCH_ARRAY(beta), |
| POLYBENCH_ARRAY(r), |
| POLYBENCH_ARRAY(out)); |
| |
| /* 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(out))); |
| #else |
| init_array (n, |
| POLYBENCH_ARRAY(y), |
| POLYBENCH_ARRAY(sum), |
| POLYBENCH_ARRAY(alpha), |
| POLYBENCH_ARRAY(beta), |
| POLYBENCH_ARRAY(r)); |
| |
| kernel_durbin_StrictFP (n, |
| POLYBENCH_ARRAY(y), |
| POLYBENCH_ARRAY(sum), |
| POLYBENCH_ARRAY(alpha), |
| POLYBENCH_ARRAY(beta), |
| POLYBENCH_ARRAY(r), |
| POLYBENCH_ARRAY(out_StrictFP)); |
| |
| if (!check_FP(n, POLYBENCH_ARRAY(out), POLYBENCH_ARRAY(out_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(out_StrictFP))); |
| #endif |
| |
| /* Be clean. */ |
| POLYBENCH_FREE_ARRAY(y); |
| POLYBENCH_FREE_ARRAY(sum); |
| POLYBENCH_FREE_ARRAY(alpha); |
| POLYBENCH_FREE_ARRAY(beta); |
| POLYBENCH_FREE_ARRAY(r); |
| POLYBENCH_FREE_ARRAY(out); |
| |
| return 0; |
| } |