2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
5 * @file AthContainers/PackedConverter.icc
6 * @author scott snyder <snyder@bnl.gov>
8 * @brief Helper for packing/unpacking a @c PackedContainer to/from a stream.
16 * @brief Pack a vector to the stream.
17 * @param nelt Number of elements to pack.
18 * @param vec Vector of elements to pack.
19 * @param stream Destination stream.
21 template <class U, class ALLOC, class STREAM>
23 void PackedConverter::write (size_t nelt,
24 const std::vector<U, ALLOC>& vec,
27 // Dispatch on number of bits and on type.
28 switch (m_parms.nbits()) {
30 if (m_parms.isFloat())
31 writeFloat<CxxUtils::BitPacker8> (nelt, vec, stream);
32 else if (m_parms.isSigned())
33 writeSigned<CxxUtils::BitPacker8> (nelt, vec, stream);
35 writeUnsigned<CxxUtils::BitPacker8> (nelt, vec, stream);
39 if (m_parms.isFloat())
40 writeFloat<CxxUtils::BitPacker16> (nelt, vec, stream);
41 else if (m_parms.isSigned())
42 writeSigned<CxxUtils::BitPacker16> (nelt, vec, stream);
44 writeUnsigned<CxxUtils::BitPacker16> (nelt, vec, stream);
48 if (m_parms.isFloat())
49 writeFloat<CxxUtils::BitPacker> (nelt, vec, stream);
50 else if (m_parms.isSigned())
51 writeSigned<CxxUtils::BitPacker> (nelt, vec, stream);
53 writeUnsigned<CxxUtils::BitPacker> (nelt, vec, stream);
60 * @brief Pack a nested vector to the stream.
61 * @param nelt Number of elements to pack.
62 * @param vec Vector of elements to pack.
63 * @param stream Destination stream.
65 template <class U, class ALLOC1, class ALLOC2, class STREAM>
67 void PackedConverter::write (size_t nelt,
68 const std::vector<std::vector<U, ALLOC1>, ALLOC2>& vec,
71 for (size_t i = 0; i < nelt; i++) {
72 size_t n = vec[i].size();
73 stream << static_cast<uint32_t>(n);
74 this->write (n, vec[i], stream);
80 * @brief Unpack a vector from the stream.
81 * @param nelt Number of elements to unpack.
82 * @param vec Vector to receive the unpacked elements.
83 * @param stream Source stream.
85 template <class U, class ALLOC, class STREAM>
87 void PackedConverter::read (size_t nelt,
88 std::vector<U, ALLOC>& vec,
94 // Dispatch on number of bits and on type.
95 switch (m_parms.nbits()) {
97 if (m_parms.isFloat())
98 readFloat<CxxUtils::BitUnpacker8> (nelt, vec, stream);
99 else if (m_parms.isSigned())
100 readSigned<CxxUtils::BitUnpacker8> (nelt, vec, stream);
102 readUnsigned<CxxUtils::BitUnpacker8> (nelt, vec, stream);
106 if (m_parms.isFloat())
107 readFloat<CxxUtils::BitUnpacker16> (nelt, vec, stream);
108 else if (m_parms.isSigned())
109 readSigned<CxxUtils::BitUnpacker16> (nelt, vec, stream);
111 readUnsigned<CxxUtils::BitUnpacker16> (nelt, vec, stream);
115 if (m_parms.isFloat())
116 readFloat<CxxUtils::BitUnpacker> (nelt, vec, stream);
117 else if (m_parms.isSigned())
118 readSigned<CxxUtils::BitUnpacker> (nelt, vec, stream);
120 readUnsigned<CxxUtils::BitUnpacker> (nelt, vec, stream);
127 * @brief Unpack a nested vector from the stream.
128 * @param nelt Number of elements to unpack.
129 * @param vec Vector to receive the unpacked elements.
130 * @param stream Source stream.
132 template <class U, class ALLOC1, class ALLOC2, class STREAM>
134 void PackedConverter::read (size_t nelt,
135 std::vector<std::vector<U, ALLOC1>, ALLOC2>& vec,
139 for (size_t i = 0; i < nelt; i++) {
142 this->read (n, vec[i], stream);
148 * @brief Pack a vector of unsigned values to the stream.
149 * @param nelt Number of elements to pack.
150 * @param vec Vector of elements to pack.
151 * @param stream Destination stream.
153 template <template<class> class PACKER, class U, class ALLOC, class STREAM>
155 void PackedConverter::writeUnsigned (size_t nelt,
156 const std::vector<U, ALLOC>& vec,
159 uint8_t nbits = m_parms.nbits();
160 PACKER<STREAM> packer (nbits, stream);
161 uint32_t mask = CxxUtils::ones<uint32_t> (nbits);
162 for (size_t i = 0; i < nelt; ++i)
163 packer.pack (static_cast<uint32_t>(vec[i]) & mask);
168 * @brief Pack a vector of signed values to the stream.
169 * @param nelt Number of elements to pack.
170 * @param vec Vector of elements to pack.
171 * @param stream Destination stream.
173 template <template<class> class PACKER, class U, class ALLOC, class STREAM>
175 void PackedConverter::writeSigned (size_t nelt,
176 const std::vector<U, ALLOC>& vec,
179 uint8_t nbits = m_parms.nbits();
180 PACKER<STREAM> packer (nbits, stream);
181 uint32_t mask = CxxUtils::ones<uint32_t> (nbits);
182 uint32_t sgnmask = ~ CxxUtils::ones<uint32_t> (nbits-1);
183 for (size_t i = 0; i < nelt; ++i) {
185 uint32_t uval = static_cast<uint32_t> (val);
186 uint32_t m = uval & sgnmask;
187 if (m == 0 || m == sgnmask)
188 packer.pack (uval & mask);
190 packer.pack (~sgnmask); // Largest + number
192 packer.pack (sgnmask & mask); // Largest - number
198 * @brief Pack a vector of float values to the stream.
199 * @param nelt Number of elements to pack.
200 * @param vec Vector of elements to pack.
201 * @param stream Destination stream.
203 template <template<class> class PACKER, class U, class ALLOC, class STREAM>
205 void PackedConverter::writeFloat (size_t nelt,
206 const std::vector<U, ALLOC>& vec,
209 uint8_t nbits = m_parms.nbits();
210 PACKER<STREAM> packer (nbits, stream);
211 for (size_t i = 0; i < nelt; ++i)
212 packer.pack (m_packer.pack (vec[i]));
218 * @brief Unpack a vector of unsigned values from the stream.
219 * @param nelt Number of elements to unpack.
220 * @param vec Vector to receive the unpacked elements.
221 * @param stream Source stream.
223 template <template<class> class UNPACKER, class U, class ALLOC, class STREAM>
224 void PackedConverter::readUnsigned (size_t nelt,
225 std::vector<U, ALLOC>& vec,
228 uint8_t nbits = m_parms.nbits();
229 UNPACKER<STREAM> unpacker (nbits, stream);
230 for (size_t i = 0; i < nelt; ++i)
231 vec.push_back (static_cast<U> (unpacker.unpack()));
236 * @brief Unpack a vector of signed values from the stream.
237 * @param nelt Number of elements to unpack.
238 * @param vec Vector to receive the unpacked elements.
239 * @param stream Source stream.
241 template <template<class> class UNPACKER, class U, class ALLOC, class STREAM>
242 void PackedConverter::readSigned (size_t nelt,
243 std::vector<U, ALLOC>& vec,
246 uint8_t nbits = m_parms.nbits();
247 uint32_t sgnmask = ~ CxxUtils::ones<uint32_t> (nbits-1);
248 UNPACKER<STREAM> unpacker (nbits, stream);
249 for (size_t i = 0; i < nelt; ++i) {
250 uint32_t val = unpacker.unpack();
252 val |= sgnmask; // Sign-extend.
253 vec.push_back (static_cast<U> (val));
259 * @brief Unpack a vector of floating-point values from the stream.
260 * @param nelt Number of elements to unpack.
261 * @param vec Vector to receive the unpacked elements.
262 * @param stream Source stream.
264 template <template<class> class UNPACKER, class U, class ALLOC, class STREAM>
265 void PackedConverter::readFloat (size_t nelt,
266 std::vector<U, ALLOC>& vec,
269 uint8_t nbits = m_parms.nbits();
270 UNPACKER<STREAM> unpacker (nbits, stream);
271 for (size_t i = 0; i < nelt; ++i)
272 vec.push_back (static_cast<U> (m_packer.unpack (unpacker.unpack())));