1! { dg-do run }
2
3module e_52_1_mod
4contains
5  subroutine init (v1, v2, N)
6    integer :: i, N
7    real :: v1(N), v2(N)
8    do i = 1, N
9      v1(i) = i + 2.0
10      v2(i) = i - 3.0
11    end do
12  end subroutine
13
14  subroutine init_again (v1, v2, N)
15    integer :: i, N
16    real :: v1(N), v2(N)
17    do i = 1, N
18      v1(i) = i - 3.0
19      v2(i) = i + 2.0
20    end do
21  end subroutine
22
23  subroutine check (p, N)
24    integer :: i, N
25    real, parameter :: EPS = 0.00001
26    real :: diff, p(N)
27    do i = 1, N
28      diff = p(i) - 2 * (i + 2.0) * (i - 3.0)
29      if (diff > EPS .or. -diff > EPS) call abort
30    end do
31  end subroutine
32
33  subroutine vec_mult (p, v1, v2, N)
34    real :: p(N), v1(N), v2(N)
35    integer :: i, N
36    call init (v1, v2, N)
37    !$omp target data map(to: v1, v2) map(from: p)
38      !$omp target
39        !$omp parallel do
40        do i = 1, N
41          p(i) = v1(i) * v2(i)
42        end do
43      !$omp end target
44      call init_again (v1, v2, N)
45      !$omp target update to(v1, v2)
46      !$omp target
47        !$omp parallel do
48        do i = 1, N
49          p(i) = p(i) + v1(i) * v2(i)
50        end do
51      !$omp end target
52    !$omp end target data
53    call check (p, N)
54  end subroutine
55end module
56
57program e_52_1
58  use e_52_1_mod, only : vec_mult
59  integer :: n
60  real, pointer :: p(:), v1(:), v2(:)
61  n = 1000
62  allocate (p(n), v1(n), v2(n))
63  call vec_mult (p, v1, v2, n)
64  deallocate (p, v1, v2)
65end program
66