GOSTcoin support for ccminer CUDA miner project, compatible with most nvidia cards
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

345 lines
12 KiB

/*
* Copyright 2008-2012 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 thrust/iterator/transform_iterator.h
* \brief An iterator which adapts another iterator by applying a function to the result of its dereference
*/
/*
* (C) Copyright David Abrahams 2002.
* (C) Copyright Jeremy Siek 2002.
* (C) Copyright Thomas Witt 2002.
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying NOTICE file for the complete license)
*
* For more information, see http://www.boost.org
*/
#pragma once
#include <thrust/detail/config.h>
// #include the details first
#include <thrust/iterator/detail/transform_iterator.inl>
#include <thrust/iterator/iterator_facade.h>
#include <thrust/detail/type_traits.h>
#include <thrust/detail/function.h>
namespace thrust
{
/*! \addtogroup iterators
* \{
*/
/*! \addtogroup fancyiterator Fancy Iterators
* \ingroup iterators
* \{
*/
/*! \p transform_iterator is an iterator which represents a pointer into a range
* of values after transformation by a function. This iterator is useful for
* creating a range filled with the result of applying an operation to another range
* without either explicitly storing it in memory, or explicitly executing the transformation.
* Using \p transform_iterator facilitates kernel fusion by deferring the execution
* of a transformation until the value is needed while saving both memory capacity
* and bandwidth.
*
* The following code snippet demonstrates how to create a \p transform_iterator
* which represents the result of \c sqrtf applied to the contents of a \p device_vector.
*
* \code
* #include <thrust/iterator/transform_iterator.h>
* #include <thrust/device_vector.h>
*
* // note: functor inherits from unary_function
* struct square_root : public thrust::unary_function<float,float>
* {
* __host__ __device__
* float operator()(float x) const
* {
* return sqrtf(x);
* }
* };
*
* int main(void)
* {
* thrust::device_vector<float> v(4);
* v[0] = 1.0f;
* v[1] = 4.0f;
* v[2] = 9.0f;
* v[3] = 16.0f;
*
* typedef thrust::device_vector<float>::iterator FloatIterator;
*
* thrust::transform_iterator<square_root, FloatIterator> iter(v.begin(), square_root());
*
* *iter; // returns 1.0f
* iter[0]; // returns 1.0f;
* iter[1]; // returns 2.0f;
* iter[2]; // returns 3.0f;
* iter[3]; // returns 4.0f;
*
* // iter[4] is an out-of-bounds error
* }
* \endcode
*
* This next example demonstrates how to use a \p transform_iterator with the
* \p thrust::reduce function to compute the sum of squares of a sequence.
* We will create temporary \p transform_iterators with the
* \p make_transform_iterator function in order to avoid explicitly specifying their type:
*
* \code
* #include <thrust/iterator/transform_iterator.h>
* #include <thrust/device_vector.h>
* #include <thrust/reduce.h>
* #include <iostream>
*
* // note: functor inherits from unary_function
* struct square : public thrust::unary_function<float,float>
* {
* __host__ __device__
* float operator()(float x) const
* {
* return x * x;
* }
* };
*
* int main(void)
* {
* // initialize a device array
* thrust::device_vector<float> v(4);
* v[0] = 1.0f;
* v[1] = 2.0f;
* v[2] = 3.0f;
* v[3] = 4.0f;
*
* float sum_of_squares =
* thrust::reduce(thrust::make_transform_iterator(v.begin(), square()),
* thrust::make_transform_iterator(v.end(), square()));
*
* std::cout << "sum of squares: " << sum_of_squares << std::endl;
* return 0;
* }
* \endcode
*
* Note that in the previous two examples the transform functor (namely \c square_root
* and \c square) inherits from \c thrust::unary_function. Inheriting from
* \c thrust::unary_function ensures that a functor is a valid \c AdaptableUnaryFunction
* and provides all the necessary \c typedef declarations. The \p transform_iterator
* can also be applied to a \c UnaryFunction that does not inherit from
* \c thrust::unary_function using an optional template argument. The following example
* illustrates how to use the third template argument to specify the \c result_type of
* the function.
*
* \code
* #include <thrust/iterator/transform_iterator.h>
* #include <thrust/device_vector.h>
*
* // note: functor *does not* inherit from unary_function
* struct square_root
* {
* __host__ __device__
* float operator()(float x) const
* {
* return sqrtf(x);
* }
* };
*
* int main(void)
* {
* thrust::device_vector<float> v(4);
* v[0] = 1.0f;
* v[1] = 4.0f;
* v[2] = 9.0f;
* v[3] = 16.0f;
*
* typedef thrust::device_vector<float>::iterator FloatIterator;
*
* // note: float result_type is specified explicitly
* thrust::transform_iterator<square_root, FloatIterator, float> iter(v.begin(), square_root());
*
* *iter; // returns 1.0f
* iter[0]; // returns 1.0f;
* iter[1]; // returns 2.0f;
* iter[2]; // returns 3.0f;
* iter[3]; // returns 4.0f;
*
* // iter[4] is an out-of-bounds error
* }
* \endcode
*
* \see make_transform_iterator
*/
template <class AdaptableUnaryFunction, class Iterator, class Reference = use_default, class Value = use_default>
class transform_iterator
: public detail::transform_iterator_base<AdaptableUnaryFunction, Iterator, Reference, Value>::type
{
/*! \cond
*/
public:
typedef typename
detail::transform_iterator_base<AdaptableUnaryFunction, Iterator, Reference, Value>::type
super_t;
friend class thrust::iterator_core_access;
/*! \endcond
*/
public:
/*! Null constructor does nothing.
*/
__host__ __device__
transform_iterator() {}
/*! This constructor takes as arguments an \c Iterator and an \c AdaptableUnaryFunction
* and copies them to a new \p transform_iterator.
*
* \param x An \c Iterator pointing to the input to this \p transform_iterator's \c AdaptableUnaryFunction.
* \param f An \c AdaptableUnaryFunction used to transform the objects pointed to by \p x.
*/
__host__ __device__
transform_iterator(Iterator const& x, AdaptableUnaryFunction f)
: super_t(x), m_f(f) {
}
/*! This explicit constructor copies the value of a given \c Iterator and creates
* this \p transform_iterator's \c AdaptableUnaryFunction using its null constructor.
*
* \param x An \c Iterator to copy.
*/
__host__ __device__
explicit transform_iterator(Iterator const& x)
: super_t(x) { }
/*! This copy constructor creates a new \p transform_iterator from another
* \p transform_iterator.
*
* \param other The \p transform_iterator to copy.
*/
template<typename OtherAdaptableUnaryFunction,
typename OtherIterator,
typename OtherReference,
typename OtherValue>
__host__ __device__
transform_iterator(const transform_iterator<OtherAdaptableUnaryFunction, OtherIterator, OtherReference, OtherValue> &other,
typename thrust::detail::enable_if_convertible<OtherIterator, Iterator>::type* = 0,
typename thrust::detail::enable_if_convertible<OtherAdaptableUnaryFunction, AdaptableUnaryFunction>::type* = 0)
: super_t(other.base()), m_f(other.functor()) {}
/*! Copy assignment operator copies from another \p transform_iterator.
* \p other The other \p transform_iterator to copy
* \return <tt>*this</tt>
*
* \note If the type of this \p transform_iterator's functor is not copy assignable
* (for example, if it is a lambda) it is not an error to call this function.
* In this case, however, the functor will not be modified.
*
* In any case, this \p transform_iterator's underlying iterator will be copy assigned.
*/
__host__ __device__
transform_iterator &operator=(const transform_iterator &other)
{
return do_assign(other,
// XXX gcc 4.2.1 crashes on is_copy_assignable; just assume the functor is assignable as a WAR
#if (THRUST_HOST_COMPILER == THRUST_HOST_COMPILER_GCC) && (THRUST_GCC_VERSION <= 40201)
thrust::detail::true_type()
#else
typename thrust::detail::is_copy_assignable<AdaptableUnaryFunction>::type()
#endif // THRUST_HOST_COMPILER
);
}
/*! This method returns a copy of this \p transform_iterator's \c AdaptableUnaryFunction.
* \return A copy of this \p transform_iterator's \c AdaptableUnaryFunction.
*/
__host__ __device__
AdaptableUnaryFunction functor() const
{ return m_f; }
/*! \cond
*/
private:
__host__ __device__
transform_iterator &do_assign(const transform_iterator &other, thrust::detail::true_type)
{
super_t::operator=(other);
// do assign to m_f
m_f = other.functor();
return *this;
}
__host__ __device__
transform_iterator &do_assign(const transform_iterator &other, thrust::detail::false_type)
{
super_t::operator=(other);
// don't assign to m_f
return *this;
}
__thrust_hd_warning_disable__
__host__ __device__
typename super_t::reference dereference() const
{
// XXX consider making this a member instead of a temporary created inside dereference
thrust::detail::host_device_function<AdaptableUnaryFunction, typename super_t::reference> wrapped_f(m_f);
return wrapped_f(*this->base());
}
// tag this as mutable per Dave Abrahams in this thread:
// http://lists.boost.org/Archives/boost/2004/05/65332.php
mutable AdaptableUnaryFunction m_f;
/*! \endcond
*/
}; // end transform_iterator
/*! \p make_transform_iterator creates a \p transform_iterator
* from an \c Iterator and \c AdaptableUnaryFunction.
*
* \param it The \c Iterator pointing to the input range of the
* newly created \p transform_iterator.
* \param fun The \c AdaptableUnaryFunction used to transform the range pointed
* to by \p it in the newly created \p transform_iterator.
* \return A new \p transform_iterator which transforms the range at
* \p it by \p fun.
* \see transform_iterator
*/
template <class AdaptableUnaryFunction, class Iterator>
inline __host__ __device__
transform_iterator<AdaptableUnaryFunction, Iterator>
make_transform_iterator(Iterator it, AdaptableUnaryFunction fun)
{
return transform_iterator<AdaptableUnaryFunction, Iterator>(it, fun);
} // end make_transform_iterator
/*! \} // end fancyiterators
*/
/*! \} // end iterators
*/
} // end thrust