Skip to content

Commit ae7024c

Browse files
atmyersWeiqunZhang
andauthored
Move the implemetation of the idcpu bit packing to standalone functions. (#4413)
This will let us expose them in the Python API. The proposed changes: - [ ] fix a bug or incorrect behavior in AMReX - [ ] add new capabilities to AMReX - [ ] changes answers in the test suite to more than roundoff level - [ ] are likely to significantly affect the results of downstream AMReX users - [ ] include documentation in the code and/or rst files, if appropriate --------- Co-authored-by: Weiqun Zhang <[email protected]>
1 parent bd6eb78 commit ae7024c

File tree

1 file changed

+85
-53
lines changed

1 file changed

+85
-53
lines changed

Src/Particle/AMReX_Particle.H

Lines changed: 85 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,79 @@ namespace amrex {
3333

3434
using namespace ParticleIdCpus;
3535

36+
namespace particle_impl {
37+
38+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
39+
Long unpack_id (const uint64_t idcpu) noexcept {
40+
Long r = 0;
41+
42+
uint64_t sign = idcpu >> 63; // extract leftmost sign bit
43+
uint64_t val = ((idcpu >> 24) & 0x7FFFFFFFFF); // extract next 39 id bits
44+
45+
Long lval = static_cast<Long>(val); // bc we take -
46+
r = (sign) ? lval : -lval;
47+
return r;
48+
}
49+
50+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
51+
int unpack_cpu (const uint64_t idcpu) noexcept {
52+
return static_cast<int>(idcpu & 0x00FFFFFF);
53+
}
54+
55+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
56+
void pack_id (uint64_t& idcpu, const Long id) noexcept {
57+
// zero out the 40 leftmost bits, which store the sign and the abs of the id;
58+
idcpu &= 0x00FFFFFF;
59+
60+
uint64_t val;
61+
uint64_t sign = id >= 0;
62+
if (sign)
63+
{
64+
// 2**39-1, the max value representable in this fashion
65+
AMREX_ASSERT(id <= 549755813887L);
66+
val = id;
67+
}
68+
else
69+
{
70+
// -2**39-1, the min value representable in this fashion
71+
AMREX_ASSERT(id >= -549755813887L);
72+
val = -id;
73+
}
74+
75+
(idcpu) |= (sign << 63); // put the sign in the leftmost bit
76+
(idcpu) |= (val << 24); // put the val in the next 39
77+
}
78+
79+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
80+
void pack_cpu (uint64_t& idcpu, const int cpu) noexcept {
81+
// zero out the first 24 bits, which are used to store the cpu number
82+
idcpu &= (~ 0x00FFFFFF);
83+
84+
AMREX_ASSERT(cpu >= 0);
85+
AMREX_ASSERT(cpu <= 16777215); // 2**24-1, the max representable number
86+
87+
idcpu |= cpu;
88+
}
89+
90+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
91+
void make_invalid (uint64_t& idcpu) noexcept {
92+
// RHS mask: 0111...
93+
idcpu &= ~(uint64_t(1) << 63);
94+
}
95+
96+
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
97+
void make_valid (uint64_t& idcpu) noexcept {
98+
// RHS mask: 1000...
99+
idcpu |= uint64_t(1) << 63;
100+
}
101+
102+
[[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
103+
bool is_valid (const uint64_t idcpu) noexcept {
104+
// the leftmost bit is our id's valid sign
105+
return idcpu >> 63;
106+
}
107+
}
108+
36109
struct ParticleIDWrapper
37110
{
38111
uint64_t* m_idata;
@@ -64,40 +137,14 @@ struct ParticleIDWrapper
64137
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
65138
ParticleIDWrapper& operator= (const Long id) noexcept
66139
{
67-
// zero out the 40 leftmost bits, which store the sign and the abs of the id;
68-
(*m_idata) &= 0x00FFFFFF;
69-
70-
uint64_t val;
71-
uint64_t sign = id >= 0;
72-
if (sign)
73-
{
74-
// 2**39-1, the max value representable in this fashion
75-
AMREX_ASSERT(id <= 549755813887L);
76-
val = id;
77-
}
78-
else
79-
{
80-
// -2**39-1, the min value representable in this fashion
81-
AMREX_ASSERT(id >= -549755813887L);
82-
val = -id;
83-
}
84-
85-
(*m_idata) |= (sign << 63); // put the sign in the leftmost bit
86-
(*m_idata) |= (val << 24); // put the val in the next 39
140+
particle_impl::pack_id(*m_idata, id);
87141
return *this;
88142
}
89143

90144
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
91145
operator Long () const noexcept
92146
{
93-
Long r = 0;
94-
95-
uint64_t sign = (*m_idata) >> 63; // extract leftmost sign bit
96-
uint64_t val = (((*m_idata) >> 24) & 0x7FFFFFFFFF); // extract next 39 id bits
97-
98-
Long lval = static_cast<Long>(val); // bc we take -
99-
r = (sign) ? lval : -lval;
100-
return r;
147+
return particle_impl::unpack_id(*m_idata);
101148
}
102149

103150
/** Mark the particle as invalid
@@ -108,8 +155,7 @@ struct ParticleIDWrapper
108155
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
109156
void make_invalid () const noexcept
110157
{
111-
// RHS mask: 0111...
112-
(*m_idata) &= ~(uint64_t(1) << 63);
158+
particle_impl::make_invalid(*m_idata);
113159
}
114160

115161
/** Mark the particle as valid
@@ -120,8 +166,7 @@ struct ParticleIDWrapper
120166
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
121167
void make_valid () const noexcept
122168
{
123-
// RHS mask: 1000...
124-
(*m_idata) |= uint64_t(1) << 63;
169+
particle_impl::make_valid(*m_idata);
125170
}
126171

127172
/** Check the particle is valid, via the sign of the id.
@@ -131,8 +176,7 @@ struct ParticleIDWrapper
131176
[[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
132177
bool is_valid () const noexcept
133178
{
134-
// the leftmost bit is our id's valid sign
135-
return (*m_idata) >> 63;
179+
return particle_impl::is_valid(*m_idata);
136180
}
137181
};
138182

@@ -167,20 +211,14 @@ struct ParticleCPUWrapper
167211
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
168212
ParticleCPUWrapper& operator= (const int cpu) noexcept
169213
{
170-
// zero out the first 24 bits, which are used to store the cpu number
171-
(*m_idata) &= (~ 0x00FFFFFF);
172-
173-
AMREX_ASSERT(cpu >= 0);
174-
AMREX_ASSERT(cpu <= 16777215); // 2**24-1, the max representable number
175-
176-
(*m_idata) |= cpu;
214+
particle_impl::pack_cpu(*m_idata, cpu);
177215
return *this;
178216
}
179217

180218
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
181219
operator int () const noexcept
182220
{
183-
return static_cast<int>((*m_idata) & 0x00FFFFFF);
221+
return particle_impl::unpack_cpu(*m_idata);
184222
}
185223
};
186224

@@ -196,14 +234,7 @@ struct ConstParticleIDWrapper
196234
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
197235
operator Long () const noexcept
198236
{
199-
Long r = 0;
200-
201-
uint64_t sign = (*m_idata) >> 63; // extract leftmost sign bit
202-
uint64_t val = (((*m_idata) >> 24) & 0x7FFFFFFFFF); // extract next 39 id bits
203-
204-
Long lval = static_cast<Long>(val); // bc we take -
205-
r = (sign) ? lval : -lval;
206-
return r;
237+
return particle_impl::unpack_id(*m_idata);
207238
}
208239

209240
/** Check the sign of the id.
@@ -213,8 +244,7 @@ struct ConstParticleIDWrapper
213244
[[nodiscard]] AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
214245
bool is_valid () const noexcept
215246
{
216-
// the leftmost bit is our id's valid sign
217-
return (*m_idata) >> 63;
247+
return particle_impl::is_valid(*m_idata);
218248
}
219249
};
220250

@@ -228,7 +258,9 @@ struct ConstParticleCPUWrapper
228258
{}
229259

230260
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
231-
operator int () const noexcept { return static_cast<int>((*m_idata) & 0x00FFFFFF); }
261+
operator int () const noexcept {
262+
return particle_impl::unpack_cpu(*m_idata);
263+
}
232264
};
233265

234266
/** Set the idcpu value at once, based on a particle id and cpuid

0 commit comments

Comments
 (0)