Extended CUDA Library (ecuda)  2.0
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros
equal.hpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2015, Scott Zuyderduyn
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 
8 1. Redistributions of source code must retain the above copyright notice, this
9  list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11  this list of conditions and the following disclaimer in the documentation
12  and/or other materials provided with the distribution.
13 
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 
25 The views and conclusions contained in the software and documentation are those
26 of the authors and should not be interpreted as representing official policies,
27 either expressed or implied, of the FreeBSD Project.
28 */
29 
30 //----------------------------------------------------------------------------
31 // algo/equal.hpp
32 //
33 // Extension of std::equal that recognizes device memory and can be called from
34 // host or device code.
35 //
36 // Author: Scott D. Zuyderduyn, Ph.D. (scott.zuyderduyn@utoronto.ca)
37 //----------------------------------------------------------------------------
38 #pragma once
39 #ifndef ECUDA_ALGO_EQUAL_HPP
40 #define ECUDA_ALGO_EQUAL_HPP
41 
42 #include <iterator>
43 #include <vector>
44 
45 #include "../global.hpp"
46 #include "../iterator.hpp"
47 #include "../utility.hpp"
48 
49 namespace ecuda {
50 
51 // forward declaration
52 template<class InputIterator1,class InputIterator2> __HOST__ __DEVICE__ inline bool equal( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2 );
53 
55 namespace impl {
56 
57 template<class InputIterator1,class InputIterator2>
58 __HOST__ __DEVICE__ inline bool equal( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, ecuda::pair<ecuda::false_type,ecuda::false_type> )
59 {
60  #ifdef __CUDA_ARCH__
61  return false; // never actually gets called, just here to trick nvcc
62  #else
63  return std::equal( first1, last1, first2 );
64  #endif
65 }
66 
67 template<class InputIterator1,class InputIterator2>
68 __HOST__ __DEVICE__ inline bool equal( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, ecuda::pair<ecuda::true_type,ecuda::false_type> )
69 {
70  #ifdef __CUDA_ARCH__
71  return false; // never actually gets called, just here to trick nvcc
72  #else
73  typedef typename ecuda::remove_const<typename ecuda::iterator_traits<InputIterator1>::value_type>::type valtype1;
74  std::vector< valtype1, host_allocator<valtype1> > v1( static_cast<std::size_t>(ecuda::distance(first1,last1)) );
75  ecuda::copy( first1, last1, v1.begin() );
76  return std::equal( v1.begin(), v1.end(), first2 );
77  #endif
78 }
79 
81 template<class InputIterator,typename T,typename P>
82 __HOST__ __DEVICE__ inline bool equal(
83  device_contiguous_block_iterator<T,P> first1,
84  device_contiguous_block_iterator<T,P> last1,
85  InputIterator first2,
87 )
88 {
89  while( first1 != last1 ) {
90  typename device_contiguous_block_iterator<T,P>::contiguous_iterator blockBegin = first1.contiguous_begin();
91  typename device_contiguous_block_iterator<T,P>::contiguous_iterator blockEnd = first1.contiguous_end();
92  if( !::ecuda::equal( blockBegin, blockEnd, first2 ) ) return false;
93  ecuda::advance( first1, distance( blockBegin, blockEnd ) );
94  ecuda::advance( first2, distance( blockBegin, blockEnd ) );
95  //first1 += distance( blockBegin, blockEnd );
96  }
97  return true;
98 }
99 
101 template<class InputIterator1,class InputIterator2>
102 __HOST__ __DEVICE__ inline bool equal( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, ecuda::pair<ecuda::false_type,ecuda::true_type> )
103 {
104  InputIterator2 last2 = first2;
105  ecuda::advance( last2, ecuda::distance(first1,last1) );
106  return ecuda::equal( first2, last2, first1 );
107 }
108 
109 template<class InputIterator1,typename T,typename P>
110 __HOST__ __DEVICE__ inline bool equal(
111  InputIterator1 first1, InputIterator1 last1,
112  device_contiguous_block_iterator<T,P> first2,
114 )
115 {
116  while( first1 != last1 ) {
117  typename device_contiguous_block_iterator<T,P>::contiguous_iterator blockBegin = first2.contiguous_begin();
118  typename device_contiguous_block_iterator<T,P>::contiguous_iterator blockEnd = first2.contiguous_end();
119  if( !equal( blockBegin, blockEnd, first1 ) ) return false;
120  advance( first1, distance( blockBegin, blockEnd ) );
121  //first1 += distance( blockBegin, blockEnd );
122  }
123  return true;
124 }
125 
127 template<class InputIterator1,class InputIterator2>
128 __HOST__ __DEVICE__ inline bool equal(
129  InputIterator1 first1, InputIterator1 last1,
130  InputIterator2 first2,
132 )
133 {
134  #ifdef __CUDA_ARCH__
135  for( ; first1 != last1; ++first1, ++first2 ) if( !(*first1 == *first2) ) return false;
136  return true;
137  #else
138  // strip const qualifiers otherwise cannot create std::vector<const T>
139  typedef typename ecuda::remove_const<typename ecuda::iterator_traits<InputIterator1>::value_type>::type valtype1;
140  typedef typename ecuda::remove_const<typename ecuda::iterator_traits<InputIterator2>::value_type>::type valtype2;
141  InputIterator2 last2 = first2;
142  ecuda::advance( last2, ecuda::distance(first1,last1) );
143  // allocate temporary memory using host_allocator (i.e. cudaHostAlloc) for potential performance improvement
144  std::vector< valtype1, host_allocator<valtype1> > v1( ecuda::distance( first1, last1 ) );
145  std::vector< valtype2, host_allocator<valtype2> > v2( ecuda::distance( first2, last2 ) );
146  ecuda::copy( first1, last1, v1.begin() );
147  ecuda::copy( first2, last2, v2.begin() );
148  return std::equal( v1.begin(), v1.end(), v2.begin() );
149  #endif
150 }
151 
152 } // namespace impl
154 
172 template<class InputIterator1,class InputIterator2>
173 __HOST__ __DEVICE__ inline bool equal( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2 )
174 {
176 }
177 
178 } // namespace ecuda
179 
180 #endif
__HOST__ __DEVICE__ OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
Replacement for std::copy.
Definition: copy.hpp:801
ECUDA_SUPPRESS_HD_WARNINGS __HOST__ __DEVICE__ void advance(InputIterator &iterator, Distance n)
Increments given iterator by n elements.
Definition: iterator.hpp:574
#define __HOST__
Definition: global.hpp:150
ecuda::false_type is_device_iterator
Definition: iterator.hpp:441
ECUDA_SUPPRESS_HD_WARNINGS __HOST__ __DEVICE__ bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
Replacement for std::equal.
Definition: equal.hpp:173
Couples together a pair of values.
Definition: utility.hpp:53
__HOST__ __DEVICE__ bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2)
Replacement for std::equal.
Definition: equal.hpp:173
#define __DEVICE__
Definition: global.hpp:151
#define ECUDA_SUPPRESS_HD_WARNINGS
Definition: global.hpp:58
ECUDA_SUPPRESS_HD_WARNINGS __HOST__ __DEVICE__ std::iterator_traits< Iterator >::difference_type distance(const Iterator &first, const Iterator &last)
Definition: iterator.hpp:627