diff --git a/examples/cpp_integration/host.cpp b/examples/cpp_integration/host.cpp index 27ab3b637..34e7cfa42 100644 --- a/examples/cpp_integration/host.cpp +++ b/examples/cpp_integration/host.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include diff --git a/performance/host_sort.test b/performance/host_sort.test index db66de963..9faf5f923 100644 --- a/performance/host_sort.test +++ b/performance/host_sort.test @@ -1,7 +1,6 @@ PREAMBLE = \ """ #include - #include #include """ diff --git a/performance/host_sort_by_key.test b/performance/host_sort_by_key.test index 8814c2446..cdd4fd135 100644 --- a/performance/host_sort_by_key.test +++ b/performance/host_sort_by_key.test @@ -1,7 +1,6 @@ PREAMBLE = \ """ #include - #include """ INITIALIZE = \ diff --git a/testing/is_sorted.cu b/testing/is_sorted.cu index 0efaae494..d1830603b 100644 --- a/testing/is_sorted.cu +++ b/testing/is_sorted.cu @@ -1,5 +1,4 @@ #include -#include #include template @@ -33,6 +32,26 @@ void TestIsSortedSimple(void) } DECLARE_VECTOR_UNITTEST(TestIsSortedSimple); +template +void TestIsSortedRepeatedElements(void) +{ + Vector v(10); + + v[0] = 0; + v[1] = 1; + v[2] = 1; + v[3] = 2; + v[4] = 3; + v[5] = 4; + v[6] = 5; + v[7] = 5; + v[8] = 5; + v[9] = 6; + + ASSERT_EQUAL(true, thrust::is_sorted(v.begin(), v.end())); +} +DECLARE_VECTOR_UNITTEST(TestIsSortedRepeatedElements); + template void TestIsSorted(void) @@ -53,3 +72,4 @@ void TestIsSorted(void) ASSERT_EQUAL(thrust::is_sorted(v.begin(), v.end()), true); } DECLARE_VECTOR_UNITTEST(TestIsSorted); + diff --git a/testing/is_sorted_until.cu b/testing/is_sorted_until.cu new file mode 100644 index 000000000..c9477b7f2 --- /dev/null +++ b/testing/is_sorted_until.cu @@ -0,0 +1,97 @@ +#include +#include + +template +void TestIsSortedUntilSimple(void) +{ + typedef typename Vector::value_type T; + typedef typename Vector::iterator Iterator; + + Vector v(4); + v[0] = 0; v[1] = 5; v[2] = 8; v[3] = 0; + + Iterator first = v.begin(); + + Iterator last = v.begin() + 0; + Iterator ref = last; + ASSERT_EQUAL_QUIET(ref, thrust::is_sorted_until(first, last)); + + last = v.begin() + 1; + ref = last; + ASSERT_EQUAL_QUIET(ref, thrust::is_sorted_until(first, last)); + + last = v.begin() + 2; + ref = last; + ASSERT_EQUAL_QUIET(ref, thrust::is_sorted_until(first, last)); + + last = v.begin() + 3; + ref = v.begin() + 3; + ASSERT_EQUAL_QUIET(ref, thrust::is_sorted_until(first, last)); + + last = v.begin() + 4; + ref = v.begin() + 3; + ASSERT_EQUAL_QUIET(ref, thrust::is_sorted_until(first, last)); + + last = v.begin() + 3; + ref = v.begin() + 3; + ASSERT_EQUAL_QUIET(ref, thrust::is_sorted_until(first, last, thrust::less())); + + last = v.begin() + 4; + ref = v.begin() + 3; + ASSERT_EQUAL_QUIET(ref, thrust::is_sorted_until(first, last, thrust::less())); + + last = v.begin() + 1; + ref = v.begin() + 1; + ASSERT_EQUAL_QUIET(ref, thrust::is_sorted_until(first, last, thrust::greater())); + + last = v.begin() + 4; + ref = v.begin() + 1; + ASSERT_EQUAL_QUIET(ref, thrust::is_sorted_until(first, last, thrust::greater())); + + first = v.begin() + 2; + last = v.begin() + 4; + ref = v.begin() + 4; + ASSERT_EQUAL_QUIET(ref, thrust::is_sorted_until(first, last, thrust::greater())); +} +DECLARE_VECTOR_UNITTEST(TestIsSortedUntilSimple); + +template +void TestIsSortedUntilRepeatedElements(void) +{ + Vector v(10); + + v[0] = 0; + v[1] = 1; + v[2] = 1; + v[3] = 2; + v[4] = 3; + v[5] = 4; + v[6] = 5; + v[7] = 5; + v[8] = 5; + v[9] = 6; + + ASSERT_EQUAL_QUIET(v.end(), thrust::is_sorted_until(v.begin(), v.end())); +} +DECLARE_VECTOR_UNITTEST(TestIsSortedUntilRepeatedElements); + +template +void TestIsSortedUntil(void) +{ + typedef typename Vector::value_type T; + + const size_t n = (1 << 16) + 13; + + Vector v = unittest::random_integers(n); + + v[0] = 1; + v[1] = 0; + + ASSERT_EQUAL_QUIET(v.begin() + 1, thrust::is_sorted_until(v.begin(), v.end())); + + thrust::sort(v.begin(), v.end()); + + ASSERT_EQUAL_QUIET(v.end(), thrust::is_sorted_until(v.begin(), v.end())); +} +DECLARE_VECTOR_UNITTEST(TestIsSortedUntil); + diff --git a/thrust/detail/internal_functional.h b/thrust/detail/internal_functional.h index 7970b06c8..6638cc45b 100644 --- a/thrust/detail/internal_functional.h +++ b/thrust/detail/internal_functional.h @@ -129,12 +129,12 @@ struct equal_to_value }; template -struct tuple_equal_to +struct tuple_binary_predicate { typedef bool result_type; __host__ __device__ - tuple_equal_to(const Predicate& p) : pred(p) {} + tuple_binary_predicate(const Predicate& p) : pred(p) {} template __host__ __device__ @@ -147,12 +147,12 @@ struct tuple_equal_to }; template -struct tuple_not_equal_to +struct tuple_not_binary_predicate { typedef bool result_type; __host__ __device__ - tuple_not_equal_to(const Predicate& p) : pred(p) {} + tuple_not_binary_predicate(const Predicate& p) : pred(p) {} template __host__ __device__ diff --git a/thrust/detail/is_sorted.inl b/thrust/detail/is_sorted.inl deleted file mode 100644 index a5b5ccf32..000000000 --- a/thrust/detail/is_sorted.inl +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2008-2010 NVIDIA Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -/*! \file is_sorted.inl - * \brief Inline file for is_sorted.h - */ - -#include -#include -#include -#include - -namespace thrust -{ - -template -bool is_sorted(ForwardIterator first, ForwardIterator last) -{ - // use less for comp - typedef typename thrust::iterator_traits::value_type T; - return thrust::is_sorted(first, last, thrust::less()); -} // end is_sorted() - -template -bool is_sorted(ForwardIterator first, ForwardIterator last, StrictWeakOrdering comp) -{ - if(first == last) - return true; - - // XXX cant create this one, is this a device_vector problem? - // return !inner_product(first + 1, last, first, false, logical_or(), comp); - - return !thrust::inner_product(first + 1, last, first, (int) 0, thrust::logical_or(), comp); -} // end is_sorted() - -} // end namespace thrust - - diff --git a/thrust/detail/mismatch.inl b/thrust/detail/mismatch.inl index 5c3ccde4d..6048a2d3b 100644 --- a/thrust/detail/mismatch.inl +++ b/thrust/detail/mismatch.inl @@ -53,7 +53,7 @@ thrust::pair mismatch(InputIterator1 first1, ZipIterator zipped_first = thrust::make_zip_iterator(thrust::make_tuple(first1,first2)); ZipIterator zipped_last = thrust::make_zip_iterator(thrust::make_tuple(last1, first2)); - ZipIterator result = thrust::find_if(zipped_first, zipped_last, thrust::detail::tuple_not_equal_to(pred)); + ZipIterator result = thrust::find_if_not(zipped_first, zipped_last, thrust::detail::tuple_binary_predicate(pred)); return thrust::make_pair(thrust::get<0>(result.get_iterator_tuple()), thrust::get<1>(result.get_iterator_tuple())); diff --git a/thrust/detail/sort.inl b/thrust/detail/sort.inl index 91630af2a..ab63bd24d 100644 --- a/thrust/detail/sort.inl +++ b/thrust/detail/sort.inl @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -131,5 +132,50 @@ template::type()); } +template + bool is_sorted(ForwardIterator first, + ForwardIterator last) +{ + return thrust::is_sorted_until(first, last) == last; +} // end is_sorted() + +template + bool is_sorted(ForwardIterator first, + ForwardIterator last, + Compare comp) +{ + return thrust::is_sorted_until(first, last, comp) == last; +} // end is_sorted() + +template + ForwardIterator is_sorted_until(ForwardIterator first, + ForwardIterator last) +{ + typedef typename thrust::iterator_value::type InputType; + + return thrust::is_sorted_until(first, last, thrust::less()); +} // end is_sorted_until() + +template + ForwardIterator is_sorted_until(ForwardIterator first, + ForwardIterator last, + Compare comp) +{ + if(thrust::distance(first,last) < 2) return last; + + typedef thrust::tuple IteratorTuple; + typedef thrust::zip_iterator ZipIterator; + + ForwardIterator first_plus_one = first; + thrust::advance(first_plus_one, 1); + + ZipIterator zipped_first = thrust::make_zip_iterator(thrust::make_tuple(first_plus_one, first)); + ZipIterator zipped_last = thrust::make_zip_iterator(thrust::make_tuple(last, first)); + + return thrust::get<0>(thrust::find_if(zipped_first, zipped_last, thrust::detail::tuple_binary_predicate(comp)).get_iterator_tuple()); +} // end is_sorted_until() + } // end namespace thrust diff --git a/thrust/is_sorted.h b/thrust/is_sorted.h index 0db07810e..a055680b0 100644 --- a/thrust/is_sorted.h +++ b/thrust/is_sorted.h @@ -15,131 +15,21 @@ */ -/*! \file is_sorted.h - * \brief Determine if a range is sorted. - */ - #pragma once -#include - -namespace thrust -{ - -/*! \addtogroup reductions - * \{ - * \addtogroup predicates - * \{ - */ - -/*! \p is_sorted returns \c true if the range [first, last) is - * sorted in ascending order, and \c false otherwise. - * - * Specifically, this version of \p is_sorted returns \c false if for - * some iterator \c i in the range [first, last - 1) the - * expression *(i + 1) < *i is \c true. - * - * \param first The beginning of the sequence. - * \param last The end of the sequence. - * \return \c true, if the sequence is sorted; \c false, otherwise. - * - * \tparam ForwardIterator is a model of Forward Iterator, - * \p ForwardIterator's \c value_type is a model of LessThan Comparable, - * and the ordering on objects of \p ForwardIterator's \c value_type is a strict weak ordering, as defined - * in the LessThan Comparable requirements. - * - * - * The following code demonstrates how to use \p is_sorted to test whether the - * contents of a \c device_vector are stored in ascending order. - * - * \code - * #include - * #include - * #include - * ... - * thrust::device_vector v(6); - * v[0] = 1; - * v[1] = 4; - * v[2] = 2; - * v[3] = 8; - * v[4] = 5; - * v[5] = 7; - * - * bool result = thrust::is_sorted(v.begin(), v.end()); - * - * // result == false - * - * thrust::sort(v.begin(), v.end()); - * result = thrust::is_sorted(v.begin(), v.end()); - * - * // result == true - * \endcode - * - * \see http://www.sgi.com/tech/stl/is_sorted.html - * \see \c sort - * \see \c stable_sort - * \see \c less - */ -template -bool is_sorted(ForwardIterator first, ForwardIterator last); - -/*! \p is_sorted returns \c true if the range [first, last) is sorted in ascending - * order accoring to a user-defined comparison operation, and \c false otherwise. - * - * Specifically, this version of \p is_sorted returns \c false if for some iterator \c i in - * the range [first, last - 1) the expression comp(*(i + 1), *i) is \c true. - * - * \param first The beginning of the sequence. - * \param last The end of the sequence. - * \param comp Comparison operator. - * \return \c true, if the sequence is sorted according to comp; \c false, otherwise. - * - * \tparam ForwardIterator is a model of Forward Iterator, - * and \p ForwardIterator's \c value_type is convertible to both \c StrictWeakOrdering's \c first_argument_type - * and \c second_argument_type. - * \tparam StrictWeakOrdering is a model of Strict Weak Ordering. - * - * The following code snippet demonstrates how to use \p is_sorted to test whether the - * contents of a \c device_vector are stored in descending order. - * - * \code - * #include - * #include - * #include - * #include - * ... - * thrust::device_vector v(6); - * v[0] = 1; - * v[1] = 4; - * v[2] = 2; - * v[3] = 8; - * v[4] = 5; - * v[5] = 7; - * - * thrust::greater comp; - * bool result = thrust::is_sorted(v.begin(), v.end(), comp); - * - * // result == false - * - * thrust::sort(v.begin(), v.end(), comp); - * result = thrust::is_sorted(v.begin(), v.end(), comp); - * - * // result == true - * \endcode - * - * \see http://www.sgi.com/tech/stl/is_sorted.html - * \see \c sort - * \see \c stable_sort - * \see \c less - */ -template -bool is_sorted(ForwardIterator first, ForwardIterator last, StrictWeakOrdering comp); - -/*! \} // end predicates - * \} // end reductions - */ - -}; // end thrust - -#include +#include + +#if THRUST_HOST_COMPILER == THRUST_HOST_COMPILER_MSVC +#pragma message("-----------------------------------------------------------------------") +#pragma message("| DEPRECATION WARNING: ") +#pragma message("| thrust/is_sorted.h has been deprecated and will be removed ") +#pragma message("| Use thrust/sort.h instead ") +#pragma message("-----------------------------------------------------------------------") +#else +#warning ----------------------------------------------------------------------- +#warning | DEPRECATION WARNING: +#warning | thrust/is_sorted.h has been deprecated and will be removed +#warning | Use thrust/sort.h instead +#warning ----------------------------------------------------------------------- +#endif // THRUST_HOST_COMPILER_MSVC diff --git a/thrust/sort.h b/thrust/sort.h index a9d28a9d9..8a9ff1e17 100644 --- a/thrust/sort.h +++ b/thrust/sort.h @@ -380,6 +380,167 @@ template[first, last) is + * sorted in ascending order, and \c false otherwise. + * + * Specifically, this version of \p is_sorted returns \c false if for + * some iterator \c i in the range [first, last - 1) the + * expression *(i + 1) < *i is \c true. + * + * \param first The beginning of the sequence. + * \param last The end of the sequence. + * \return \c true, if the sequence is sorted; \c false, otherwise. + * + * \tparam ForwardIterator is a model of Forward Iterator, + * \p ForwardIterator's \c value_type is a model of LessThan Comparable, + * and the ordering on objects of \p ForwardIterator's \c value_type is a strict weak ordering, as defined + * in the LessThan Comparable requirements. + * + * + * The following code demonstrates how to use \p is_sorted to test whether the + * contents of a \c device_vector are stored in ascending order. + * + * \code + * #include + * #include + * #include + * ... + * thrust::device_vector v(6); + * v[0] = 1; + * v[1] = 4; + * v[2] = 2; + * v[3] = 8; + * v[4] = 5; + * v[5] = 7; + * + * bool result = thrust::is_sorted(v.begin(), v.end()); + * + * // result == false + * + * thrust::sort(v.begin(), v.end()); + * result = thrust::is_sorted(v.begin(), v.end()); + * + * // result == true + * \endcode + * + * \see http://www.sgi.com/tech/stl/is_sorted.html + * \see is_sorted_until + * \see \c sort + * \see \c stable_sort + * \see \c less + */ +template + bool is_sorted(ForwardIterator first, + ForwardIterator last); + +/*! \p is_sorted returns \c true if the range [first, last) is sorted in ascending + * order accoring to a user-defined comparison operation, and \c false otherwise. + * + * Specifically, this version of \p is_sorted returns \c false if for some iterator \c i in + * the range [first, last - 1) the expression comp(*(i + 1), *i) is \c true. + * + * \param first The beginning of the sequence. + * \param last The end of the sequence. + * \param comp Comparison operator. + * \return \c true, if the sequence is sorted according to comp; \c false, otherwise. + * + * \tparam ForwardIterator is a model of Forward Iterator, + * and \p ForwardIterator's \c value_type is convertible to both \c StrictWeakOrdering's \c first_argument_type + * and \c second_argument_type. + * \tparam Compare is a model of Strict Weak Ordering. + * + * The following code snippet demonstrates how to use \p is_sorted to test whether the + * contents of a \c device_vector are stored in descending order. + * + * \code + * #include + * #include + * #include + * ... + * thrust::device_vector v(6); + * v[0] = 1; + * v[1] = 4; + * v[2] = 2; + * v[3] = 8; + * v[4] = 5; + * v[5] = 7; + * + * thrust::greater comp; + * bool result = thrust::is_sorted(v.begin(), v.end(), comp); + * + * // result == false + * + * thrust::sort(v.begin(), v.end(), comp); + * result = thrust::is_sorted(v.begin(), v.end(), comp); + * + * // result == true + * \endcode + * + * \see http://www.sgi.com/tech/stl/is_sorted.html + * \see \c sort + * \see \c stable_sort + * \see \c less + */ +template + bool is_sorted(ForwardIterator first, + ForwardIterator last, + Compare comp); + +/*! This version of \p is_sorted_until returns the last iterator \c i in [first,last] for + * which the range [first,last) is sorted using \c operator<. If distance(first,last) < 2, + * \p is_sorted_until simply returns \p last. + * + * \param first The beginning of the range of interest. + * \param last The end of the range of interest. + * \return The last iterator in the input range for which it is sorted. + * + * \tparam ForwardIterator is a model of Forward Iterator and + * \p ForwardIterator's \c value_type is a model of LessThan Comparable. + * + * \see \p is_sorted + * \see \p sort + * \see \p sort_by_key + * \see \p stable_sort + * \see \p stable_sort_by_key + */ +template + ForwardIterator is_sorted_until(ForwardIterator first, + ForwardIterator last); + +/*! This version of \p is_sorted_until returns the last iterator \c i in [first,last] for + * which the range [first,last) is sorted using the function object \c comp. If distance(first,last) < 2, + * \p is_sorted_until simply returns \p last. + * + * \param first The beginning of the range of interest. + * \param last The end of the range of interest. + * \param comp The function object to use for comparison. + * \return The last iterator in the input range for which it is sorted. + * + * \tparam ForwardIterator is a model of Forward Iterator and + * \p ForwardIterator's \c value_type is convertible to \p Compare's \c argument_type. + * \tparam Compare is a model of Strict Weak Ordering. + * + * \see \p is_sorted + * \see \p sort + * \see \p sort_by_key + * \see \p stable_sort + * \see \p stable_sort_by_key + */ +template + ForwardIterator is_sorted_until(ForwardIterator first, + ForwardIterator last, + Compare comp); + +/*! \} // end predicates + * \} // end reductions + */ + } // end namespace thrust #include