NumCpp  2.12.1
A Templatized Header Only C++ Implementation of the Python NumPy Library
packbits.hpp
Go to the documentation of this file.
1
28#pragma once
29
30#include <type_traits>
31
33#include "NumCpp/NdArray.hpp"
34
35namespace 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:139
size_type size() const noexcept
Definition: NdArrayCore.hpp:4524
self_type transpose() const
Definition: NdArrayCore.hpp:4882
const Shape & shape() const noexcept
Definition: NdArrayCore.hpp:4511
self_type & fill(value_type inFillValue) noexcept
Definition: NdArrayCore.hpp:2808
const_reference back() const noexcept
Definition: NdArrayCore.hpp:2287
uint32 size_type
Definition: NdArrayCore.hpp:156
Slice cSlice(index_type inStartIdx=0, size_type inStepSize=1) const
Definition: NdArrayCore.hpp:1008
self_type & put(index_type inIndex, const value_type &inValue)
Definition: NdArrayCore.hpp:3693
uint32 cols
Definition: Core/Shape.hpp:45
Definition: Cartesian.hpp:40
NdArray< uint8 > packbitsBigEndian(const NdArray< dtype > &a, Axis axis=Axis::NONE)
Definition: packbits.hpp:126
Axis
Enum To describe an axis.
Definition: Enums.hpp:36
NdArray< uint8 > packbitsLittleEndian(const NdArray< dtype > &a, Axis axis=Axis::NONE)
Definition: packbits.hpp:48
std::uint8_t uint8
Definition: Types.hpp:42