NumCpp  2.11.0
A Templatized Header Only C++ Implementation of the Python NumPy Library
packbits.hpp
Go to the documentation of this file.
1 #pragma once
29 
30 #include <type_traits>
31 
33 #include "NumCpp/NdArray.hpp"
34 
35 namespace nc
36 {
37  //============================================================================
38  // Method Description:
47  template<typename dtype, std::enable_if_t<std::is_integral_v<dtype> || std::is_same_v<dtype, bool>, int> = 0>
49  {
50  switch (axis)
51  {
52  case Axis::NONE:
53  {
54  const auto numFullValues = a.size() / 8;
55  const auto leftOvers = a.size() % 8;
56  const auto resultSize = leftOvers == 0 ? numFullValues : numFullValues + 1;
57 
58  NdArray<uint8> result(1, resultSize);
59  result.fill(0);
60 
61  for (typename NdArray<dtype>::size_type i = 0; i < numFullValues; ++i)
62  {
63  const auto startIdx = i * 8;
64  for (auto bit = 0; bit < 8; ++bit)
65  {
66  auto value = static_cast<uint8>(a[startIdx + bit]);
67  value = value == 0 ? 0 : 1;
68  result[i] |= (value << bit);
69  }
70  }
71 
72  if (leftOvers != 0)
73  {
74  const auto startIdx = numFullValues * 8;
75  for (std::remove_const_t<decltype(leftOvers)> bit = 0; bit < leftOvers; ++bit)
76  {
77  auto value = static_cast<uint8>(a[startIdx + bit]);
78  value = value == 0 ? 0 : 1;
79  result.back() |= (value << bit);
80  }
81  }
82 
83  return result;
84  }
85  case Axis::COL:
86  {
87  const auto aShape = a.shape();
88  const auto numFullValues = aShape.cols / 8;
89  const auto leftOvers = aShape.cols % 8;
90  const auto resultSize = leftOvers == 0 ? numFullValues : numFullValues + 1;
91 
92  NdArray<uint8> result(aShape.rows, resultSize);
93  const auto resultCSlice = result.cSlice();
94  const auto aCSlice = a.cSlice();
95 
96  for (typename NdArray<dtype>::size_type row = 0; row < aShape.rows; ++row)
97  {
98  result.put(row, resultCSlice, packbitsLittleEndian(a(row, aCSlice)));
99  }
100 
101  return result;
102  }
103  case Axis::ROW:
104  {
105  return packbitsLittleEndian(a.transpose(), Axis::COL).transpose();
106  }
107  default:
108  {
109  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
110  return {}; // get rid of compiler warning
111  }
112  }
113  }
114 
115  //============================================================================
116  // Method Description:
125  template<typename dtype, std::enable_if_t<std::is_integral_v<dtype> || std::is_same_v<dtype, bool>, int> = 0>
127  {
128  switch (axis)
129  {
130  case Axis::NONE:
131  {
132  const auto numFullValues = a.size() / 8;
133  const auto leftOvers = a.size() % 8;
134  const auto resultSize = leftOvers == 0 ? numFullValues : numFullValues + 1;
135 
136  NdArray<uint8> result(1, resultSize);
137  result.fill(0);
138 
139  for (typename NdArray<dtype>::size_type i = 0; i < numFullValues; ++i)
140  {
141  const auto startIdx = i * 8;
142  for (auto bit = 0; bit < 8; ++bit)
143  {
144  auto value = static_cast<uint8>(a[startIdx + bit]);
145  value = value == 0 ? 0 : 1;
146  result[i] |= (value << (7 - bit));
147  }
148  }
149 
150  if (leftOvers != 0)
151  {
152  const auto startIdx = numFullValues * 8;
153  for (std::remove_const_t<decltype(leftOvers)> bit = 0; bit < leftOvers; ++bit)
154  {
155  auto value = static_cast<uint8>(a[startIdx + bit]);
156  value = value == 0 ? 0 : 1;
157  result.back() |= (value << (7 - bit));
158  }
159  }
160 
161  return result;
162  }
163  case Axis::COL:
164  {
165  const auto aShape = a.shape();
166  const auto numFullValues = aShape.cols / 8;
167  const auto leftOvers = aShape.cols % 8;
168  const auto resultSize = leftOvers == 0 ? numFullValues : numFullValues + 1;
169 
170  NdArray<uint8> result(aShape.rows, resultSize);
171  const auto resultCSlice = result.cSlice();
172  const auto aCSlice = a.cSlice();
173 
174  for (typename NdArray<dtype>::size_type row = 0; row < aShape.rows; ++row)
175  {
176  result.put(row, resultCSlice, packbitsBigEndian(a(row, aCSlice)));
177  }
178 
179  return result;
180  }
181  case Axis::ROW:
182  {
183  return packbitsBigEndian(a.transpose(), Axis::COL).transpose();
184  }
185  default:
186  {
187  THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
188  return {}; // get rid of compiler warning
189  }
190  }
191  }
192 
193 } // namespace nc
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:37
Holds 1D and 2D arrays, the main work horse of the NumCpp library.
Definition: NdArrayCore.hpp:138
self_type & fill(value_type inFillValue) noexcept
Definition: NdArrayCore.hpp:2761
size_type size() const noexcept
Definition: NdArrayCore.hpp:4477
self_type & put(index_type inIndex, const value_type &inValue)
Definition: NdArrayCore.hpp:3646
self_type transpose() const
Definition: NdArrayCore.hpp:4837
const_reference back() const noexcept
Definition: NdArrayCore.hpp:2240
uint32 size_type
Definition: NdArrayCore.hpp:155
const Shape & shape() const noexcept
Definition: NdArrayCore.hpp:4464
Slice cSlice(index_type inStartIdx=0, size_type inStepSize=1) const
Definition: NdArrayCore.hpp:961
uint32 cols
Definition: Core/Shape.hpp:45
Definition: Cartesian.hpp:40
Axis
Enum To describe an axis.
Definition: Types.hpp:47
std::uint8_t uint8
Definition: Types.hpp:42
NdArray< uint8 > packbitsBigEndian(const NdArray< dtype > &a, Axis axis=Axis::NONE)
Definition: packbits.hpp:126
NdArray< uint8 > packbitsLittleEndian(const NdArray< dtype > &a, Axis axis=Axis::NONE)
Definition: packbits.hpp:48