NumCpp  2.16.0
A Templatized Header Only C++ Implementation of the Python NumPy Library
Loading...
Searching...
No Matches
NdArrayBroadcast.hpp
Go to the documentation of this file.
1
28#pragma once
29
30#include <cmath>
31#include <utility>
32
35#include "NumCpp/Core/Types.hpp"
37
39{
40 //============================================================================
41 // Method Description:
51 template<typename dtypeIn1, typename dtypeIn2, typename Function, typename... AdditionalFunctionArgs>
54 const Function& function,
56 {
57 if (inArray1.shape() == inArray2.shape())
58 {
60 inArray1.cbegin(),
61 inArray1.cend(),
62 inArray2.cbegin(),
63 inArray1.begin(),
64 [&function, &additionalFunctionArgs...](const auto& inValue1, const auto& inValue2) -> dtypeIn1
65 {
66 return function(inValue1,
67 inValue2,
68 std::forward<AdditionalFunctionArgs>(additionalFunctionArgs)...);
69 });
70 }
71 else if (inArray2.isscalar())
72 {
73 const auto value = inArray2.item();
75 inArray1.cbegin(),
76 inArray1.cend(),
77 inArray1.begin(),
78 [&value, &function, &additionalFunctionArgs...](const auto& inValue) -> dtypeIn1
79 { return function(inValue, value, std::forward<AdditionalFunctionArgs>(additionalFunctionArgs)...); });
80 }
81 else if (inArray2.isflat())
82 {
83 if (inArray2.numRows() > 1 && inArray2.numRows() == inArray1.numRows())
84 {
85 for (uint32 row = 0; row < inArray1.numRows(); ++row)
86 {
87 const auto value = inArray2[row];
89 inArray1.cbegin(row),
90 inArray1.cend(row),
91 inArray1.begin(row),
92 [&value, &function, &additionalFunctionArgs...](const auto& inValue) -> dtypeIn1
93 {
94 return function(inValue,
95 value,
96 std::forward<AdditionalFunctionArgs>(additionalFunctionArgs)...);
97 });
98 }
99 }
100 else if (inArray2.numCols() > 1 && inArray2.numCols() == inArray1.numCols())
101 {
102 for (uint32 col = 0; col < inArray1.numCols(); ++col)
103 {
104 const auto value = inArray2[col];
106 inArray1.ccolbegin(col),
107 inArray1.ccolend(col),
108 inArray1.colbegin(col),
109 [&value, &function, &additionalFunctionArgs...](const auto& inValue) -> dtypeIn1
110 {
111 return function(inValue,
112 value,
113 std::forward<AdditionalFunctionArgs>(additionalFunctionArgs)...);
114 });
115 }
116 }
117 else
118 {
119 THROW_INVALID_ARGUMENT_ERROR("operands could not be broadcast together");
120 }
121 }
122 else
123 {
124 THROW_INVALID_ARGUMENT_ERROR("operands could not be broadcast together");
125 }
126
127 return inArray1;
128 }
129
130 //============================================================================
131 // Method Description:
141 template<typename dtypeOut,
142 typename dtypeIn1,
143 typename dtypeIn2,
144 typename Function,
145 typename... AdditionalFunctionArgs>
148 const Function& function,
150 {
151 if (inArray1.shape() == inArray2.shape())
152 {
154 {
157 inArray1.cbegin(),
158 inArray1.cend(),
159 inArray2.cbegin(),
160 returnArray.begin(),
161 [&function, &additionalFunctionArgs...](const auto& inValue1, const auto& inValue2) -> dtypeOut
162 {
163 return function(inValue1,
164 inValue2,
165 std::forward<AdditionalFunctionArgs>(additionalFunctionArgs)...);
166 });
167
168 return returnArray;
169 }();
170 }
171 else if (inArray1.isscalar())
172 {
173 const auto value = inArray1.item();
174 return [&inArray2, &value, &function, &additionalFunctionArgs...]
175 {
178 inArray2.cbegin(),
179 inArray2.cend(),
180 returnArray.begin(),
181 [&value, &function, &additionalFunctionArgs...](const auto& inValue) -> dtypeOut
182 {
183 return function(inValue,
184 value,
185 std::forward<AdditionalFunctionArgs>(additionalFunctionArgs)...);
186 });
187 return returnArray;
188 }();
189 }
190 else if (inArray2.isscalar())
191 {
192 const auto value = inArray2.item();
193 return [&inArray1, &value, &function, &additionalFunctionArgs...]
194 {
197 inArray1.cbegin(),
198 inArray1.cend(),
199 returnArray.begin(),
200 [&value, &function, &additionalFunctionArgs...](const auto& inValue) -> dtypeOut
201 {
202 return function(inValue,
203 value,
204 std::forward<AdditionalFunctionArgs>(additionalFunctionArgs)...);
205 });
206 return returnArray;
207 }();
208 }
209 else if (inArray1.isflat() && inArray2.isflat())
210 {
212 {
213 const auto numRows = std::max(inArray1.numRows(), inArray2.numRows());
214 const auto numCols = std::max(inArray1.numCols(), inArray2.numCols());
215 NdArray<dtypeOut> returnArray(numRows, numCols);
216 if (inArray1.numRows() > 1)
217 {
218 for (uint32 row = 0; row < inArray1.numRows(); ++row)
219 {
220 for (uint32 col = 0; col < inArray2.numCols(); ++col)
221 {
222 returnArray(row, col) =
223 function(inArray1[row],
224 inArray2[col],
225 std::forward<AdditionalFunctionArgs>(additionalFunctionArgs)...);
226 }
227 }
228 }
229 else
230 {
231 for (uint32 row = 0; row < inArray2.numRows(); ++row)
232 {
233 for (uint32 col = 0; col < inArray1.numCols(); ++col)
234 {
235 returnArray(row, col) =
236 function(inArray1[col],
237 inArray2[row],
238 std::forward<AdditionalFunctionArgs>(additionalFunctionArgs)...);
239 }
240 }
241 }
242 return returnArray;
243 }();
244 }
245 else if (inArray1.isflat())
246 {
248 inArray1,
249 function,
250 std::forward<AdditionalFunctionArgs>(additionalFunctionArgs)...);
251 }
252 else if (inArray2.isflat())
253 {
254 if (inArray2.numRows() > 1 && inArray2.numRows() == inArray1.numRows())
255 {
257 {
259 for (uint32 row = 0; row < inArray1.numRows(); ++row)
260 {
261 const auto value = inArray2[row];
263 inArray1.cbegin(row),
264 inArray1.cend(row),
265 returnArray.begin(row),
266 [&value, &function, &additionalFunctionArgs...](const auto& inValue) -> dtypeOut
267 {
268 return function(inValue,
269 value,
270 std::forward<AdditionalFunctionArgs>(additionalFunctionArgs)...);
271 });
272 }
273 return returnArray;
274 }();
275 }
276 else if (inArray2.numCols() > 1 && inArray2.numCols() == inArray1.numCols())
277 {
278 return broadcaster<dtypeOut>(inArray1.transpose(),
279 inArray2.transpose(),
280 function,
281 std::forward<AdditionalFunctionArgs>(additionalFunctionArgs)...)
282 .transpose();
283 }
284 else
285 {
286 THROW_INVALID_ARGUMENT_ERROR("operands could not be broadcast together");
287 }
288 }
289 else
290 {
291 THROW_INVALID_ARGUMENT_ERROR("operands could not be broadcast together");
292 }
293
294 return {}; // get rid of compiler warning
295 }
296} // namespace nc::broadcast
#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
Definition NdArrayBroadcast.hpp:39
NdArray< dtypeIn1 > & broadcaster(NdArray< dtypeIn1 > &inArray1, const NdArray< dtypeIn2 > &inArray2, const Function &function, const AdditionalFunctionArgs &&... additionalFunctionArgs)
Definition NdArrayBroadcast.hpp:52
OutputIt transform(InputIt first, InputIt last, OutputIt destination, UnaryOperation unaryFunction)
Definition StlAlgorithms.hpp:775
NdArray< dtype > arange(dtype inStart, dtype inStop, dtype inStep=1)
Definition arange.hpp:59
std::uint32_t uint32
Definition Types.hpp:40