/* Container adaptors in target region. Does not test comparison operators other than equality to allow these tests to be generalized to arbitrary input data. */ #include #include #include #include #include #include #include "target-flex-common.h" template bool test_stack(T (&arr)[Size]) { bool ok; #pragma omp target map(from: ok) map(to: arr[:Size]) { bool inner_ok = true; const std::size_t half_size = Size / 2; const T first_element = arr[0]; const T middle_element = arr[half_size - 1]; const T last_element = arr[Size - 1]; typedef std::stack > stack_type; stack_type stack; VERIFY (stack.empty()); VERIFY (stack.size() == 0); { /* Do half with push. */ std::size_t idx = 0; for (; idx < half_size; ++idx) { stack.push(arr[idx]); VERIFY (stack.top() == arr[idx]); } VERIFY (stack.size() == half_size); VERIFY (static_cast(stack).size() == half_size); for (; idx < Size; ++idx) { #if __cplusplus >= 201103L /* Do the rest with emplace if C++11 or higher. */ stack.emplace(arr[idx]); #else /* Otherwise just use push again. */ stack.push(arr[idx]); #endif VERIFY (stack.top() == arr[idx]); } VERIFY (stack.size() == Size); VERIFY (static_cast(stack).size() == Size); const stack_type stack_orig = stack_type(std::vector(arr, arr + Size)); VERIFY (stack == stack_orig); /* References are contained in their own scope so we don't accidently add tests referencing them after they have been invalidated. */ { const T& const_top = static_cast(stack).top(); VERIFY (const_top == last_element); T& mutable_top = stack.top(); mutable_top = first_element; VERIFY (const_top == first_element); } /* Will only compare inequal if the first and last elements are different. */ VERIFY (first_element != last_element || stack != stack_orig); for (std::size_t count = Size - half_size; count != 0; --count) stack.pop(); VERIFY (stack.top() == middle_element); const stack_type stack_half_orig = stack_type(std::vector(arr, arr + half_size)); VERIFY (stack == stack_half_orig); } end: ok = inner_ok; } return ok; } template bool test_queue(T (&arr)[Size]) { bool ok; #pragma omp target map(from: ok) map(to: arr[:Size]) { bool inner_ok = true; const std::size_t half_size = Size / 2; const T first_element = arr[0]; const T last_element = arr[Size - 1]; typedef std::queue > queue_type; queue_type queue; VERIFY (queue.empty()); VERIFY (queue.size() == 0); { /* Do half with push. */ std::size_t idx = 0; for (; idx < half_size; ++idx) { queue.push(arr[idx]); VERIFY (queue.back() == arr[idx]); VERIFY (queue.front() == first_element); } VERIFY (queue.size() == half_size); VERIFY (static_cast(queue).size() == half_size); for (; idx < Size; ++idx) { #if __cplusplus >= 201103L /* Do the rest with emplace if C++11 or higher. */ queue.emplace(arr[idx]); #else /* Otherwise just use push again. */ queue.push(arr[idx]); #endif VERIFY (queue.back() == arr[idx]); } VERIFY (queue.size() == Size); VERIFY (static_cast(queue).size() == Size); const queue_type queue_orig = queue_type(std::deque(arr, arr + Size)); VERIFY (queue == queue_orig); /* References are contained in their own scope so we don't accidently add tests referencing them after they have been invalidated. */ { const T& const_front = static_cast(queue).front(); VERIFY (const_front == first_element); T& mutable_front = queue.front(); const T& const_back = static_cast(queue).back(); VERIFY (const_back == last_element); T& mutable_back = queue.back(); { using std::swap; swap(mutable_front, mutable_back); } VERIFY (const_front == last_element); VERIFY (const_back == first_element); /* Will only compare inequal if the first and last elements are different. */ VERIFY (first_element != last_element || queue != queue_orig); /* Return the last element to normal for the next comparison. */ mutable_back = last_element; } const T middle_element = arr[half_size]; for (std::size_t count = Size - half_size; count != 0; --count) queue.pop(); VERIFY (queue.front() == middle_element); const queue_type queue_upper_half = queue_type(std::deque(arr + half_size, arr + Size)); VERIFY (queue == queue_upper_half); } end: ok = inner_ok; } return ok; } template bool test_priority_queue(T (&arr)[Size], const T min_value, const T max_value) { bool ok; #pragma omp target map(from: ok) map(to: arr[:Size]) { bool inner_ok = true; typedef std::priority_queue > priority_queue_type; { priority_queue_type pqueue; VERIFY (pqueue.empty()); VERIFY (pqueue.size() == 0); } { priority_queue_type pqueue(arr, arr + Size); VERIFY (!pqueue.empty()); VERIFY (pqueue.size() == Size); VERIFY (static_cast(pqueue).size() == Size); const T old_max = pqueue.top(); #if __cplusplus >= 201103L pqueue.emplace(max_value); #else pqueue.push(max_value); #endif VERIFY (pqueue.top() == max_value); pqueue.pop(); VERIFY (pqueue.top() == old_max); pqueue.push(min_value); VERIFY (pqueue.top() == old_max); pqueue.push(max_value); VERIFY (pqueue.top() == max_value); pqueue.pop(); VERIFY (pqueue.top() == old_max); VERIFY (pqueue.size() == Size + 1); for (std::size_t count = Size; count != 0; --count) pqueue.pop(); VERIFY (pqueue.size() == 1); VERIFY (pqueue.top() == min_value); } end: ok = inner_ok; } return ok; } int main() { int arr[10] = {0,1,2,3,4,5,6,7,8,9}; return test_stack(arr) && test_queue(arr) && test_priority_queue(arr, 0, 1000) ? 0 : 1; }