~ubuntu-branches/debian/sid/lammps/sid

« back to all changes in this revision

Viewing changes to lib/kokkos/TPL/cub/util_iterator.cuh

  • Committer: Package Import Robot
  • Author(s): Anton Gladky
  • Date: 2015-04-29 23:44:49 UTC
  • mfrom: (5.1.3 experimental)
  • Revision ID: package-import@ubuntu.com-20150429234449-mbhy9utku6hp6oq8
Tags: 0~20150313.gitfa668e1-1
Upload into unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
 * Copyright (c) 2011, Duane Merrill.  All rights reserved.
 
3
 * Copyright (c) 2011-2013, NVIDIA CORPORATION.  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
 *     * Redistributions of source code must retain the above copyright
 
8
 *       notice, this list of conditions and the following disclaimer.
 
9
 *     * Redistributions in binary form must reproduce the above copyright
 
10
 *       notice, this list of conditions and the following disclaimer in the
 
11
 *       documentation and/or other materials provided with the distribution.
 
12
 *     * Neither the name of the NVIDIA CORPORATION nor the
 
13
 *       names of its contributors may be used to endorse or promote products
 
14
 *       derived from this software without specific prior written permission.
 
15
 * 
 
16
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
19
 * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
 
20
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
21
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
22
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
23
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
25
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
26
 *
 
27
 ******************************************************************************/
 
28
 
 
29
/**
 
30
 * \file
 
31
 * Random-access iterator types
 
32
 */
 
33
 
 
34
#pragma once
 
35
 
 
36
#include "thread/thread_load.cuh"
 
37
#include "util_device.cuh"
 
38
#include "util_debug.cuh"
 
39
#include "util_namespace.cuh"
 
40
 
 
41
/// Optional outer namespace(s)
 
42
CUB_NS_PREFIX
 
43
 
 
44
/// CUB namespace
 
45
namespace cub {
 
46
 
 
47
 
 
48
/******************************************************************************
 
49
 * Texture references
 
50
 *****************************************************************************/
 
51
 
 
52
#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document
 
53
 
 
54
// Anonymous namespace
 
55
namespace {
 
56
 
 
57
/// Templated texture reference type
 
58
template <typename T>
 
59
struct TexIteratorRef
 
60
{
 
61
    // Texture reference type
 
62
    typedef texture<T, cudaTextureType1D, cudaReadModeElementType> TexRef;
 
63
 
 
64
    static TexRef ref;
 
65
 
 
66
    /**
 
67
     * Bind texture
 
68
     */
 
69
    static cudaError_t BindTexture(void *d_in)
 
70
    {
 
71
        cudaChannelFormatDesc tex_desc = cudaCreateChannelDesc<T>();
 
72
        if (d_in)
 
73
            return (CubDebug(cudaBindTexture(NULL, ref, d_in, tex_desc)));
 
74
 
 
75
        return cudaSuccess;
 
76
    }
 
77
 
 
78
    /**
 
79
     * Unbind textures
 
80
     */
 
81
    static cudaError_t UnbindTexture()
 
82
    {
 
83
        return CubDebug(cudaUnbindTexture(ref));
 
84
    }
 
85
};
 
86
 
 
87
// Texture reference definitions
 
88
template <typename Value>
 
89
typename TexIteratorRef<Value>::TexRef TexIteratorRef<Value>::ref = 0;
 
90
 
 
91
} // Anonymous namespace
 
92
 
 
93
 
 
94
#endif // DOXYGEN_SHOULD_SKIP_THIS
 
95
 
 
96
 
 
97
 
 
98
 
 
99
 
 
100
 
 
101
 
 
102
/**
 
103
 * \addtogroup UtilModule
 
104
 * @{
 
105
 */
 
106
 
 
107
 
 
108
/******************************************************************************
 
109
 * Iterators
 
110
 *****************************************************************************/
 
111
 
 
112
/**
 
113
 * \brief A simple random-access iterator pointing to a range of constant values
 
114
 *
 
115
 * \par Overview
 
116
 * ConstantIteratorRA is a random-access iterator that when dereferenced, always
 
117
 * returns the supplied constant of type \p OutputType.
 
118
 *
 
119
 * \tparam OutputType           The value type of this iterator
 
120
 */
 
121
template <typename OutputType>
 
122
class ConstantIteratorRA
 
123
{
 
124
public:
 
125
 
 
126
#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document
 
127
 
 
128
    typedef ConstantIteratorRA                  self_type;
 
129
    typedef OutputType                          value_type;
 
130
    typedef OutputType                          reference;
 
131
    typedef OutputType*                         pointer;
 
132
    typedef std::random_access_iterator_tag     iterator_category;
 
133
    typedef int                                 difference_type;
 
134
 
 
135
#endif  // DOXYGEN_SHOULD_SKIP_THIS
 
136
 
 
137
private:
 
138
 
 
139
    OutputType    val;
 
140
 
 
141
public:
 
142
 
 
143
    /// Constructor
 
144
    __host__ __device__ __forceinline__ ConstantIteratorRA(
 
145
        const OutputType &val)          ///< Constant value for the iterator instance to report
 
146
    :
 
147
        val(val)
 
148
    {}
 
149
 
 
150
#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document
 
151
 
 
152
    __host__ __device__ __forceinline__ self_type operator++()
 
153
    {
 
154
        self_type i = *this;
 
155
        return i;
 
156
    }
 
157
 
 
158
    __host__ __device__ __forceinline__ self_type operator++(int junk)
 
159
    {
 
160
        return *this;
 
161
    }
 
162
 
 
163
    __host__ __device__ __forceinline__ reference operator*()
 
164
    {
 
165
        return val;
 
166
    }
 
167
 
 
168
    template <typename SizeT>
 
169
    __host__ __device__ __forceinline__ self_type operator+(SizeT n)
 
170
    {
 
171
        return ConstantIteratorRA(val);
 
172
    }
 
173
 
 
174
    template <typename SizeT>
 
175
    __host__ __device__ __forceinline__ self_type operator-(SizeT n)
 
176
    {
 
177
        return ConstantIteratorRA(val);
 
178
    }
 
179
 
 
180
    template <typename SizeT>
 
181
    __host__ __device__ __forceinline__ reference operator[](SizeT n)
 
182
    {
 
183
        return ConstantIteratorRA(val);
 
184
    }
 
185
 
 
186
    __host__ __device__ __forceinline__ pointer operator->()
 
187
    {
 
188
        return &val;
 
189
    }
 
190
 
 
191
    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)
 
192
    {
 
193
        return (val == rhs.val);
 
194
    }
 
195
 
 
196
    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)
 
197
    {
 
198
        return (val != rhs.val);
 
199
    }
 
200
 
 
201
#endif // DOXYGEN_SHOULD_SKIP_THIS
 
202
 
 
203
};
 
204
 
 
205
 
 
206
 
 
207
/**
 
208
 * \brief A simple random-access transform iterator for applying a transformation operator.
 
209
 *
 
210
 * \par Overview
 
211
 * TransformIteratorRA is a random-access iterator that wraps both a native
 
212
 * device pointer of type <tt>InputType*</tt> and a unary conversion functor of
 
213
 * type \p ConversionOp. \p OutputType references are made by pulling \p InputType
 
214
 * values through the \p ConversionOp instance.
 
215
 *
 
216
 * \tparam InputType            The value type of the pointer being wrapped
 
217
 * \tparam ConversionOp         Unary functor type for mapping objects of type \p InputType to type \p OutputType.  Must have member <tt>OutputType operator()(const InputType &datum)</tt>.
 
218
 * \tparam OutputType           The value type of this iterator
 
219
 */
 
220
template <typename OutputType, typename ConversionOp, typename InputType>
 
221
class TransformIteratorRA
 
222
{
 
223
public:
 
224
 
 
225
#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document
 
226
 
 
227
    typedef TransformIteratorRA                 self_type;
 
228
    typedef OutputType                          value_type;
 
229
    typedef OutputType                          reference;
 
230
    typedef OutputType*                         pointer;
 
231
    typedef std::random_access_iterator_tag     iterator_category;
 
232
    typedef int                                 difference_type;
 
233
 
 
234
#endif  // DOXYGEN_SHOULD_SKIP_THIS
 
235
 
 
236
private:
 
237
 
 
238
    ConversionOp    conversion_op;
 
239
    InputType*      ptr;
 
240
 
 
241
public:
 
242
 
 
243
    /**
 
244
     * \brief Constructor
 
245
     * @param ptr Native pointer to wrap
 
246
     * @param conversion_op Binary transformation functor
 
247
     */
 
248
    __host__ __device__ __forceinline__ TransformIteratorRA(InputType* ptr, ConversionOp conversion_op) :
 
249
        conversion_op(conversion_op),
 
250
        ptr(ptr) {}
 
251
 
 
252
#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document
 
253
 
 
254
    __host__ __device__ __forceinline__ self_type operator++()
 
255
    {
 
256
        self_type i = *this;
 
257
        ptr++;
 
258
        return i;
 
259
    }
 
260
 
 
261
    __host__ __device__ __forceinline__ self_type operator++(int junk)
 
262
    {
 
263
        ptr++;
 
264
        return *this;
 
265
    }
 
266
 
 
267
    __host__ __device__ __forceinline__ reference operator*()
 
268
    {
 
269
        return conversion_op(*ptr);
 
270
    }
 
271
 
 
272
    template <typename SizeT>
 
273
    __host__ __device__ __forceinline__ self_type operator+(SizeT n)
 
274
    {
 
275
        TransformIteratorRA retval(ptr + n, conversion_op);
 
276
        return retval;
 
277
    }
 
278
 
 
279
    template <typename SizeT>
 
280
    __host__ __device__ __forceinline__ self_type operator-(SizeT n)
 
281
    {
 
282
        TransformIteratorRA retval(ptr - n, conversion_op);
 
283
        return retval;
 
284
    }
 
285
 
 
286
    template <typename SizeT>
 
287
    __host__ __device__ __forceinline__ reference operator[](SizeT n)
 
288
    {
 
289
        return conversion_op(ptr[n]);
 
290
    }
 
291
 
 
292
    __host__ __device__ __forceinline__ pointer operator->()
 
293
    {
 
294
        return &conversion_op(*ptr);
 
295
    }
 
296
 
 
297
    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)
 
298
    {
 
299
        return (ptr == rhs.ptr);
 
300
    }
 
301
 
 
302
    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)
 
303
    {
 
304
        return (ptr != rhs.ptr);
 
305
    }
 
306
 
 
307
#endif // DOXYGEN_SHOULD_SKIP_THIS
 
308
 
 
309
};
 
310
 
 
311
 
 
312
 
 
313
/**
 
314
 * \brief A simple random-access iterator for loading primitive values through texture cache.
 
315
 *
 
316
 * \par Overview
 
317
 * TexIteratorRA is a random-access iterator that wraps a native
 
318
 * device pointer of type <tt>T*</tt>. References made through TexIteratorRA
 
319
 * causes values to be pulled through texture cache.
 
320
 *
 
321
 * \par Usage Considerations
 
322
 * - Can only be used with primitive types (e.g., \p char, \p int, \p float), with the exception of \p double
 
323
 * - Only one TexIteratorRA or TexIteratorRA of a certain \p InputType can be bound at any given time (per host thread)
 
324
 *
 
325
 * \tparam InputType            The value type of the pointer being wrapped
 
326
 * \tparam ConversionOp         Unary functor type for mapping objects of type \p InputType to type \p OutputType.  Must have member <tt>OutputType operator()(const InputType &datum)</tt>.
 
327
 * \tparam OutputType           The value type of this iterator
 
328
 */
 
329
template <typename T>
 
330
class TexIteratorRA
 
331
{
 
332
public:
 
333
#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document
 
334
 
 
335
    typedef TexIteratorRA                       self_type;
 
336
    typedef T                                   value_type;
 
337
    typedef T                                   reference;
 
338
    typedef T*                                  pointer;
 
339
    typedef std::random_access_iterator_tag     iterator_category;
 
340
    typedef int                                 difference_type;
 
341
 
 
342
#endif // DOXYGEN_SHOULD_SKIP_THIS
 
343
 
 
344
    /// Tag identifying iterator type as being texture-bindable
 
345
    typedef void TexBindingTag;
 
346
 
 
347
private:
 
348
 
 
349
    T*                  ptr;
 
350
    size_t              tex_align_offset;
 
351
    cudaTextureObject_t tex_obj;
 
352
 
 
353
public:
 
354
 
 
355
    /**
 
356
     * \brief Constructor
 
357
     */
 
358
    __host__ __device__ __forceinline__ TexIteratorRA()
 
359
    :
 
360
        ptr(NULL),
 
361
        tex_align_offset(0),
 
362
        tex_obj(0)
 
363
    {}
 
364
 
 
365
    /// \brief Bind iterator to texture reference
 
366
    cudaError_t BindTexture(
 
367
        T               *ptr,                   ///< Native pointer to wrap that is aligned to cudaDeviceProp::textureAlignment
 
368
        size_t          bytes,                  ///< Number of items
 
369
        size_t          tex_align_offset = 0)   ///< Offset (in items) from ptr denoting the position of the iterator
 
370
    {
 
371
        this->ptr = ptr;
 
372
        this->tex_align_offset = tex_align_offset;
 
373
 
 
374
        int ptx_version;
 
375
        cudaError_t error = cudaSuccess;
 
376
        if (CubDebug(error = PtxVersion(ptx_version))) return error;
 
377
        if (ptx_version >= 300)
 
378
        {
 
379
            // Use texture object
 
380
            cudaChannelFormatDesc   channel_desc = cudaCreateChannelDesc<T>();
 
381
            cudaResourceDesc        res_desc;
 
382
            cudaTextureDesc         tex_desc;
 
383
            memset(&res_desc, 0, sizeof(cudaResourceDesc));
 
384
            memset(&tex_desc, 0, sizeof(cudaTextureDesc));
 
385
            res_desc.resType                = cudaResourceTypeLinear;
 
386
            res_desc.res.linear.devPtr      = ptr;
 
387
            res_desc.res.linear.desc        = channel_desc;
 
388
            res_desc.res.linear.sizeInBytes = bytes;
 
389
            tex_desc.readMode               = cudaReadModeElementType;
 
390
            return cudaCreateTextureObject(&tex_obj, &res_desc, &tex_desc, NULL);
 
391
        }
 
392
        else
 
393
        {
 
394
            // Use texture reference
 
395
            return TexIteratorRef<T>::BindTexture(ptr);
 
396
        }
 
397
    }
 
398
 
 
399
    /// \brief Unbind iterator to texture reference
 
400
    cudaError_t UnbindTexture()
 
401
    {
 
402
        int ptx_version;
 
403
        cudaError_t error = cudaSuccess;
 
404
        if (CubDebug(error = PtxVersion(ptx_version))) return error;
 
405
        if (ptx_version < 300)
 
406
        {
 
407
            // Use texture reference
 
408
            return TexIteratorRef<T>::UnbindTexture();
 
409
        }
 
410
        else
 
411
        {
 
412
            // Use texture object
 
413
            return cudaDestroyTextureObject(tex_obj);
 
414
        }
 
415
    }
 
416
 
 
417
#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document
 
418
 
 
419
    __host__ __device__ __forceinline__ self_type operator++()
 
420
    {
 
421
        self_type i = *this;
 
422
        ptr++;
 
423
        tex_align_offset++;
 
424
        return i;
 
425
    }
 
426
 
 
427
    __host__ __device__ __forceinline__ self_type operator++(int junk)
 
428
    {
 
429
        ptr++;
 
430
        tex_align_offset++;
 
431
        return *this;
 
432
    }
 
433
 
 
434
    __host__ __device__ __forceinline__ reference operator*()
 
435
    {
 
436
#if (CUB_PTX_ARCH == 0)
 
437
        // Simply dereference the pointer on the host
 
438
        return *ptr;
 
439
#elif (CUB_PTX_ARCH < 300)
 
440
        // Use the texture reference
 
441
        return tex1Dfetch(TexIteratorRef<T>::ref, tex_align_offset);
 
442
#else
 
443
        // Use the texture object
 
444
        return conversion_op(tex1Dfetch<InputType>(tex_obj, tex_align_offset));
 
445
#endif
 
446
    }
 
447
 
 
448
    template <typename SizeT>
 
449
    __host__ __device__ __forceinline__ self_type operator+(SizeT n)
 
450
    {
 
451
        TexIteratorRA retval;
 
452
        retval.ptr = ptr + n;
 
453
        retval.tex_align_offset = tex_align_offset + n;
 
454
        return retval;
 
455
    }
 
456
 
 
457
    template <typename SizeT>
 
458
    __host__ __device__ __forceinline__ self_type operator-(SizeT n)
 
459
    {
 
460
        TexIteratorRA retval;
 
461
        retval.ptr = ptr - n;
 
462
        retval.tex_align_offset = tex_align_offset - n;
 
463
        return retval;
 
464
    }
 
465
 
 
466
    template <typename SizeT>
 
467
    __host__ __device__ __forceinline__ reference operator[](SizeT n)
 
468
    {
 
469
#if (CUB_PTX_ARCH == 0)
 
470
        // Simply dereference the pointer on the host
 
471
        return ptr[n];
 
472
#elif (CUB_PTX_ARCH < 300)
 
473
        // Use the texture reference
 
474
        return tex1Dfetch(TexIteratorRef<T>::ref, tex_align_offset + n);
 
475
#else
 
476
        // Use the texture object
 
477
        return conversion_op(tex1Dfetch<InputType>(tex_obj, tex_align_offset + n));
 
478
#endif
 
479
    }
 
480
 
 
481
    __host__ __device__ __forceinline__ pointer operator->()
 
482
    {
 
483
#if (CUB_PTX_ARCH == 0)
 
484
        // Simply dereference the pointer on the host
 
485
        return &(*ptr);
 
486
#elif (CUB_PTX_ARCH < 300)
 
487
        // Use the texture reference
 
488
        return &(tex1Dfetch(TexIteratorRef<T>::ref, tex_align_offset));
 
489
#else
 
490
        // Use the texture object
 
491
        return conversion_op(tex1Dfetch<InputType>(tex_obj, tex_align_offset));
 
492
#endif
 
493
    }
 
494
 
 
495
    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)
 
496
    {
 
497
        return (ptr == rhs.ptr);
 
498
    }
 
499
 
 
500
    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)
 
501
    {
 
502
        return (ptr != rhs.ptr);
 
503
    }
 
504
 
 
505
#endif // DOXYGEN_SHOULD_SKIP_THIS
 
506
 
 
507
};
 
508
 
 
509
 
 
510
/**
 
511
 * \brief A simple random-access transform iterator for loading primitive values through texture cache and and subsequently applying a transformation operator.
 
512
 *
 
513
 * \par Overview
 
514
 * TexTransformIteratorRA is a random-access iterator that wraps both a native
 
515
 * device pointer of type <tt>InputType*</tt> and a unary conversion functor of
 
516
 * type \p ConversionOp. \p OutputType references are made by pulling \p InputType
 
517
 * values through the texture cache and then transformed them using the
 
518
 * \p ConversionOp instance.
 
519
 *
 
520
 * \par Usage Considerations
 
521
 * - Can only be used with primitive types (e.g., \p char, \p int, \p float), with the exception of \p double
 
522
 * - Only one TexIteratorRA or TexTransformIteratorRA of a certain \p InputType can be bound at any given time (per host thread)
 
523
 *
 
524
 * \tparam InputType            The value type of the pointer being wrapped
 
525
 * \tparam ConversionOp         Unary functor type for mapping objects of type \p InputType to type \p OutputType.  Must have member <tt>OutputType operator()(const InputType &datum)</tt>.
 
526
 * \tparam OutputType           The value type of this iterator
 
527
 */
 
528
template <typename OutputType, typename ConversionOp, typename InputType>
 
529
class TexTransformIteratorRA
 
530
{
 
531
public:
 
532
 
 
533
#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document
 
534
 
 
535
    typedef TexTransformIteratorRA              self_type;
 
536
    typedef OutputType                          value_type;
 
537
    typedef OutputType                          reference;
 
538
    typedef OutputType*                         pointer;
 
539
    typedef std::random_access_iterator_tag     iterator_category;
 
540
    typedef int                                 difference_type;
 
541
 
 
542
#endif  // DOXYGEN_SHOULD_SKIP_THIS
 
543
 
 
544
    /// Tag identifying iterator type as being texture-bindable
 
545
    typedef void TexBindingTag;
 
546
 
 
547
private:
 
548
 
 
549
    ConversionOp        conversion_op;
 
550
    InputType*          ptr;
 
551
    size_t              tex_align_offset;
 
552
    cudaTextureObject_t tex_obj;
 
553
 
 
554
public:
 
555
 
 
556
    /**
 
557
     * \brief Constructor
 
558
     */
 
559
    TexTransformIteratorRA(
 
560
        ConversionOp    conversion_op)          ///< Binary transformation functor
 
561
    :
 
562
        conversion_op(conversion_op),
 
563
        ptr(NULL),
 
564
        tex_align_offset(0),
 
565
        tex_obj(0)
 
566
    {}
 
567
 
 
568
    /// \brief Bind iterator to texture reference
 
569
    cudaError_t BindTexture(
 
570
        InputType*      ptr,                    ///< Native pointer to wrap that is aligned to cudaDeviceProp::textureAlignment
 
571
        size_t          bytes,                  ///< Number of items
 
572
        size_t          tex_align_offset = 0)   ///< Offset (in items) from ptr denoting the position of the iterator
 
573
    {
 
574
        this->ptr = ptr;
 
575
        this->tex_align_offset = tex_align_offset;
 
576
 
 
577
        int ptx_version;
 
578
        cudaError_t error = cudaSuccess;
 
579
        if (CubDebug(error = PtxVersion(ptx_version))) return error;
 
580
        if (ptx_version >= 300)
 
581
        {
 
582
            // Use texture object
 
583
            cudaChannelFormatDesc   channel_desc = cudaCreateChannelDesc<InputType>();
 
584
            cudaResourceDesc        res_desc;
 
585
            cudaTextureDesc         tex_desc;
 
586
            memset(&res_desc, 0, sizeof(cudaResourceDesc));
 
587
            memset(&tex_desc, 0, sizeof(cudaTextureDesc));
 
588
            res_desc.resType                = cudaResourceTypeLinear;
 
589
            res_desc.res.linear.devPtr      = ptr;
 
590
            res_desc.res.linear.desc        = channel_desc;
 
591
            res_desc.res.linear.sizeInBytes = bytes;
 
592
            tex_desc.readMode               = cudaReadModeElementType;
 
593
            return cudaCreateTextureObject(&tex_obj, &res_desc, &tex_desc, NULL);
 
594
        }
 
595
        else
 
596
        {
 
597
            // Use texture reference
 
598
            return TexIteratorRef<InputType>::BindTexture(ptr);
 
599
        }
 
600
    }
 
601
 
 
602
    /// \brief Unbind iterator to texture reference
 
603
    cudaError_t UnbindTexture()
 
604
    {
 
605
        int ptx_version;
 
606
        cudaError_t error = cudaSuccess;
 
607
        if (CubDebug(error = PtxVersion(ptx_version))) return error;
 
608
        if (ptx_version >= 300)
 
609
        {
 
610
            // Use texture object
 
611
            return cudaDestroyTextureObject(tex_obj);
 
612
        }
 
613
        else
 
614
        {
 
615
            // Use texture reference
 
616
            return TexIteratorRef<InputType>::UnbindTexture();
 
617
        }
 
618
    }
 
619
 
 
620
#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document
 
621
 
 
622
    __host__ __device__ __forceinline__ self_type operator++()
 
623
    {
 
624
        self_type i = *this;
 
625
        ptr++;
 
626
        tex_align_offset++;
 
627
        return i;
 
628
    }
 
629
 
 
630
    __host__ __device__ __forceinline__ self_type operator++(int junk)
 
631
    {
 
632
        ptr++;
 
633
        tex_align_offset++;
 
634
        return *this;
 
635
    }
 
636
 
 
637
    __host__ __device__ __forceinline__ reference operator*()
 
638
    {
 
639
#if (CUB_PTX_ARCH == 0)
 
640
        // Simply dereference the pointer on the host
 
641
        return conversion_op(*ptr);
 
642
#elif (CUB_PTX_ARCH < 300)
 
643
        // Use the texture reference
 
644
        return conversion_op(tex1Dfetch(TexIteratorRef<InputType>::ref, tex_align_offset));
 
645
#else
 
646
        // Use the texture object
 
647
        return conversion_op(tex1Dfetch<InputType>(tex_obj, tex_align_offset));
 
648
#endif
 
649
    }
 
650
 
 
651
    template <typename SizeT>
 
652
    __host__ __device__ __forceinline__ self_type operator+(SizeT n)
 
653
    {
 
654
        TexTransformIteratorRA retval(conversion_op);
 
655
        retval.ptr = ptr + n;
 
656
        retval.tex_align_offset = tex_align_offset + n;
 
657
        return retval;
 
658
    }
 
659
 
 
660
    template <typename SizeT>
 
661
    __host__ __device__ __forceinline__ self_type operator-(SizeT n)
 
662
    {
 
663
        TexTransformIteratorRA retval(conversion_op);
 
664
        retval.ptr = ptr - n;
 
665
        retval.tex_align_offset = tex_align_offset - n;
 
666
        return retval;
 
667
    }
 
668
 
 
669
    template <typename SizeT>
 
670
    __host__ __device__ __forceinline__ reference operator[](SizeT n)
 
671
    {
 
672
#if (CUB_PTX_ARCH == 0)
 
673
        // Simply dereference the pointer on the host
 
674
        return conversion_op(ptr[n]);
 
675
#elif (CUB_PTX_ARCH < 300)
 
676
        // Use the texture reference
 
677
        return conversion_op(tex1Dfetch(TexIteratorRef<InputType>::ref, tex_align_offset + n));
 
678
#else
 
679
        // Use the texture object
 
680
        return conversion_op(tex1Dfetch<InputType>(tex_obj, tex_align_offset + n));
 
681
#endif
 
682
    }
 
683
 
 
684
    __host__ __device__ __forceinline__ pointer operator->()
 
685
    {
 
686
#if (CUB_PTX_ARCH == 0)
 
687
        // Simply dereference the pointer on the host
 
688
        return &conversion_op(*ptr);
 
689
#elif (CUB_PTX_ARCH < 300)
 
690
        // Use the texture reference
 
691
        return &conversion_op(tex1Dfetch(TexIteratorRef<InputType>::ref, tex_align_offset));
 
692
#else
 
693
        // Use the texture object
 
694
        return &conversion_op(tex1Dfetch<InputType>(tex_obj, tex_align_offset));
 
695
#endif
 
696
    }
 
697
 
 
698
    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)
 
699
    {
 
700
        return (ptr == rhs.ptr);
 
701
    }
 
702
 
 
703
    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)
 
704
    {
 
705
        return (ptr != rhs.ptr);
 
706
    }
 
707
 
 
708
#endif // DOXYGEN_SHOULD_SKIP_THIS
 
709
 
 
710
};
 
711
 
 
712
 
 
713
 
 
714
 
 
715
/** @} */       // end group UtilModule
 
716
 
 
717
}               // CUB namespace
 
718
CUB_NS_POSTFIX  // Optional outer namespace(s)