ATLAS Offline Software
PackedConverter.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 /**
5  * @file AthContainers/PackedConverter.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Nov, 2014
8  * @brief Helper for packing/unpacking a @c PackedContainer to/from a stream.
9  */
10 
11 
12 namespace SG {
13 
14 
15 /**
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.
20  */
21 template <class U, class ALLOC, class STREAM>
22 inline
23 void PackedConverter::write (size_t nelt,
24  const std::vector<U, ALLOC>& vec,
25  STREAM& stream)
26 {
27  // Dispatch on number of bits and on type.
28  switch (m_parms.nbits()) {
29  case 8:
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);
34  else
35  writeUnsigned<CxxUtils::BitPacker8> (nelt, vec, stream);
36  break;
37 
38  case 16:
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);
43  else
44  writeUnsigned<CxxUtils::BitPacker16> (nelt, vec, stream);
45  break;
46 
47  default:
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);
52  else
53  writeUnsigned<CxxUtils::BitPacker> (nelt, vec, stream);
54  break;
55  }
56 }
57 
58 
59 /**
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.
64  */
65 template <class U, class ALLOC1, class ALLOC2, class STREAM>
66 inline
67 void PackedConverter::write (size_t nelt,
68  const std::vector<std::vector<U, ALLOC1>, ALLOC2>& vec,
69  STREAM& stream)
70 {
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);
75  }
76 }
77 
78 
79 /**
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.
84  */
85 template <class U, class ALLOC, class STREAM>
86 inline
87 void PackedConverter::read (size_t nelt,
88  std::vector<U, ALLOC>& vec,
89  STREAM& stream)
90 {
91  vec.clear();
92  vec.reserve (nelt);
93 
94  // Dispatch on number of bits and on type.
95  switch (m_parms.nbits()) {
96  case 8:
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);
101  else
102  readUnsigned<CxxUtils::BitUnpacker8> (nelt, vec, stream);
103  break;
104 
105  case 16:
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);
110  else
111  readUnsigned<CxxUtils::BitUnpacker16> (nelt, vec, stream);
112  break;
113 
114  default:
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);
119  else
120  readUnsigned<CxxUtils::BitUnpacker> (nelt, vec, stream);
121  break;
122  }
123 }
124 
125 
126 /**
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.
131  */
132 template <class U, class ALLOC1, class ALLOC2, class STREAM>
133 inline
134 void PackedConverter::read (size_t nelt,
135  std::vector<std::vector<U, ALLOC1>, ALLOC2>& vec,
136  STREAM& stream)
137 {
138  vec.resize (nelt);
139  for (size_t i = 0; i < nelt; i++) {
140  uint32_t n;
141  stream >> n;
142  this->read (n, vec[i], stream);
143  }
144 }
145 
146 
147 /**
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.
152  */
153 template <template<class> class PACKER, class U, class ALLOC, class STREAM>
154 inline
155 void PackedConverter::writeUnsigned (size_t nelt,
156  const std::vector<U, ALLOC>& vec,
157  STREAM& stream)
158 {
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);
164 }
165 
166 
167 /**
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.
172  */
173 template <template<class> class PACKER, class U, class ALLOC, class STREAM>
174 inline
175 void PackedConverter::writeSigned (size_t nelt,
176  const std::vector<U, ALLOC>& vec,
177  STREAM& stream)
178 {
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) {
184  U val = vec[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);
189  else if (val > 0)
190  packer.pack (~sgnmask); // Largest + number
191  else
192  packer.pack (sgnmask & mask); // Largest - number
193  }
194 }
195 
196 
197 /**
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.
202  */
203 template <template<class> class PACKER, class U, class ALLOC, class STREAM>
204 inline
205 void PackedConverter::writeFloat (size_t nelt,
206  const std::vector<U, ALLOC>& vec,
207  STREAM& stream)
208 {
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]));
213 }
214 
215 
216 
217 /**
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.
222  */
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,
226  STREAM& stream)
227 {
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()));
232 }
233 
234 
235 /**
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.
240  */
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,
244  STREAM& stream)
245 {
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();
251  if (val & sgnmask)
252  val |= sgnmask; // Sign-extend.
253  vec.push_back (static_cast<U> (val));
254  }
255 }
256 
257 
258 /**
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.
263  */
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,
267  STREAM& stream)
268 {
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())));
273 }
274 
275 
276 } // namespace SG