-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathptr.h
More file actions
92 lines (82 loc) · 4.4 KB
/
ptr.h
File metadata and controls
92 lines (82 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
Copyright [2024] [Yao Yao]
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.
*/
#pragma once
#include <cuda_runtime_api.h>
#include <cstdint>
namespace cudapp
{
template <typename T, typename OrigType = T>
class Ptr
{
public:
using Offset = uint32_t;
using PtrDiff = int32_t;
static_assert(sizeof(Offset) == sizeof(PtrDiff));
__host__ __device__ __forceinline__ Ptr(OrigType* base, Offset size) : mBase{base}, mOrigSize{size}{assert(size < std::numeric_limits<PtrDiff>::max());}
__host__ __device__ __forceinline__ Ptr(OrigType* base, Offset size, Offset offset) : Ptr(base, size){mOffset = offset;}
__host__ __device__ __forceinline__ Ptr(OrigType* base, Offset size, int offset) : Ptr(base, size){mOffset = static_cast<Offset>(offset);}
__host__ __device__ __forceinline__ bool isInBound() const {
return sizeof(OrigType) < sizeof(T)
? mOffset < mOrigSize / (sizeof(T) / sizeof(OrigType))
: mOffset / (sizeof(OrigType) / sizeof(T)) < mOrigSize;
}
__host__ __device__ __forceinline__ T* get() const {return base<T>() + mOffset;}
__host__ __device__ __forceinline__ uint32_t getOffset() const {return mOffset;}
__host__ __device__ __forceinline__ uint32_t getSize() const {return mOrigSize * sizeof(OrigType) / sizeof(T);}
__host__ __device__ __forceinline__ operator T*() const {return get();}
template <bool enabler = true, typename = typename std::enable_if<enabler && !std::is_const<T>::value>::type>
__host__ __device__ __forceinline__ operator Ptr<const T, OrigType>() const {return Ptr<const T, OrigType>{mBase, mOrigSize, mOffset};}
__host__ __device__ __forceinline__ T& operator*() const {assert(isInBound()); return *get();}
__host__ __device__ __forceinline__ T& operator[](uint32_t x) const {
const auto p = *this + x;
assert(p.isInBound());
return *p;
}
__host__ __device__ __forceinline__ Ptr operator+(uint32_t x) const {
return Ptr(mBase, mOrigSize, mOffset+x);
}
__host__ __device__ __forceinline__ Ptr operator+(int32_t x) const {
assert(x >= 0);
return (*this) + static_cast<uint32_t>(x);
}
__host__ __device__ __forceinline__ Ptr operator-(uint32_t x) const {
assert(mOffset >= x);
return Ptr(mBase, mOrigSize, mOffset-x);
}
__host__ __device__ __forceinline__ PtrDiff operator-(const Ptr& r) const {
assert(mBase == r.mBase);
const Offset x = mOffset - r.mOffset;
return reinterpret_cast<const PtrDiff&>(x);
}
__host__ __device__ __forceinline__ bool operator<(const Ptr& r) const {assert(mBase == r.mBase); return mOffset < r.mOffset;}
__host__ __device__ __forceinline__ bool operator<=(const Ptr& r) const {assert(mBase == r.mBase); return mOffset <= r.mOffset;}
__host__ __device__ __forceinline__ bool operator>(const Ptr& r) const {assert(mBase == r.mBase); return mOffset > r.mOffset;}
__host__ __device__ __forceinline__ bool operator>=(const Ptr& r) const {assert(mBase == r.mBase); return mOffset >= r.mOffset;}
__host__ __device__ __forceinline__ bool operator==(const Ptr& r) const {assert(mBase == r.mBase); return mOffset == r.mOffset;}
__host__ __device__ __forceinline__ bool operator!=(const Ptr& r) const {assert(mBase == r.mBase); return mOffset != r.mOffset;}
template <typename Dst = T>
__host__ __device__ __forceinline__ Dst* base() const {return reinterpret_cast<Dst*>(mBase);}
template <typename Dst>
__host__ __device__ __forceinline__ Ptr<Dst, OrigType> cast() const {
if (sizeof(Dst) > sizeof(T)) {
assert(mOffset % (sizeof(Dst) / sizeof(T)) == 0);
}
return Ptr<Dst, OrigType>(mBase, mOrigSize,
sizeof(T) < sizeof(Dst) ? mOffset / (sizeof(Dst) / sizeof(T)) : mOffset * (sizeof(T) / sizeof(Dst)));
}
private:
OrigType* const mBase = nullptr;
const Offset mOrigSize = 0u; // in #OrigType
Offset mOffset = 0u; // in #T
};
} // namespace cudapp