4#include "boost/multi_array.hpp"
5#include "boost/array.hpp"
6#include "boost/cstdlib.hpp"
22 typedef double ndArrayValue;
25 template <std::
size_t ND>
26 inline boost::multi_array<ndArrayValue, ND>::index
27 getIndex(
const boost::multi_array<ndArrayValue, ND> &m,
const ndArrayValue *requestedElement,
const unsigned short int direction)
29 int offset = requestedElement - m.origin();
30 return (offset / m.strides()[direction] % m.shape()[direction] + m.index_bases()[direction]);
34 template <std::
size_t ND>
35 inline boost::array<typename boost::multi_array<ndArrayValue, ND>::index, ND>
36 getIndexArray(
const boost::multi_array<ndArrayValue, ND> &m,
const ndArrayValue *requestedElement)
38 using indexType = boost::multi_array<ndArrayValue, ND>::index;
39 boost::array<indexType, ND> _index;
40 for (
unsigned int dir = 0; dir < ND; dir++)
42 _index[dir] =
getIndex(m, requestedElement, dir);
50 template <
typename Array,
typename Element,
typename Functor>
51 inline void for_each(
const boost::type<Element> &type_dispatch,
52 Array A, Functor &xform)
54 for_each(type_dispatch, A.begin(), A.end(), xform);
58 template <
typename Element,
typename Functor>
59 inline void for_each(
const boost::type<Element> &, Element &Val, Functor &xform)
65 template <
typename Element,
typename Iterator,
typename Functor>
66 inline void for_each(
const boost::type<Element> &type_dispatch,
67 Iterator begin, Iterator end,
72 for_each(type_dispatch, *begin, xform);
79 template <
typename Array,
typename Functor>
83 for_each(boost::type<typename Array::element>(), A.begin(), A.end(), xform);
89 template <
typename T,
long unsigned int ND>
90 requires std::is_floating_point<T>::value
inline constexpr std::vector<boost::multi_array<T, ND>>
gradient(boost::multi_array<T, ND> inArray, std::initializer_list<T> args)
93 using arrayIndex = boost::multi_array<T, ND>::index;
95 using ndIndexArray = boost::array<arrayIndex, ND>;
98 std::size_t n = args.size();
100 std::vector<T> arg_vector = args;
101 boost::multi_array<T, ND> my_array;
102 std::vector<boost::multi_array<T, ND>> output_arrays;
103 for (std::size_t i = 0; i < n; i++)
105 boost::multi_array<T, ND> dfdh = inArray;
106 output_arrays.push_back(dfdh);
109 ndArrayValue *p = inArray.data();
111 for (std::size_t i = 0; i < inArray.num_elements(); i++)
124 for (std::size_t j = 0; j < n; j++)
126 ndIndexArray index_high = index;
128 if ((
long unsigned int)index_high[j] < inArray.shape()[j] - 1)
131 dh_high = arg_vector[j];
137 ndIndexArray index_low = index;
139 if (index_low[j] > 0)
142 dh_low = arg_vector[j];
149 T dh = dh_high + dh_low;
150 T
gradient = (inArray(index_high) - inArray(index_low)) / dh;
157 return output_arrays;
161 inline boost::multi_array<double, 1>
linspace(
double start,
double stop,
long unsigned int num)
163 double step = (stop - start) / (num - 1);
164 boost::multi_array<double, 1> output(boost::extents[num]);
165 for (std::size_t i = 0; i < num; i++)
167 output[i] = start + i * step;
183 template <
typename T,
long unsigned int ND>
184 requires std::is_arithmetic<T>::value
inline constexpr std::vector<boost::multi_array<T, ND>>
meshgrid(
const boost::multi_array<T, 1> (&cinput)[ND],
bool sparsing =
false, indexing indexing_type = xy)
186 using arrayIndex = boost::multi_array<T, ND>::index;
187 using oneDArrayIndex = boost::multi_array<T, 1>::index;
188 using ndIndexArray = boost::array<arrayIndex, ND>;
189 std::vector<boost::multi_array<T, ND>> output_arrays;
190 boost::multi_array<T, 1> ci[ND];
192 for (std::size_t i = 0; i < ND; i++)
194 std::size_t source = i;
195 if (indexing_type == xy && (ND == 3 || ND == 2))
204 ci[i] = boost::multi_array<T, 1>();
205 ci[i].resize(boost::extents[cinput[source].num_elements()]);
206 ci[i] = cinput[source];
209 boost::detail::multi_array::extent_gen<ND> output_extents;
210 std::vector<size_t> shape_list;
211 for (std::size_t i = 0; i < ND; i++)
213 shape_list.push_back(ci[i].shape()[0]);
215 std::copy(shape_list.begin(), shape_list.end(), output_extents.ranges_.begin());
218 for (std::size_t i = 0; i < ND; i++)
220 boost::multi_array<T, ND> output_array(output_extents);
221 ndArrayValue *p = output_array.data();
224 for (std::size_t j = 0; j < output_array.num_elements(); j++)
227 oneDArrayIndex index_1d;
229 output_array(index) = ci[i][index_1d];
232 output_arrays.push_back(output_array);
234 if (indexing_type == xy && (ND == 3 || ND == 2))
236 std::swap(output_arrays[0], output_arrays[1]);
238 return output_arrays;
242 template <
class T,
long unsigned int ND>
243 requires std::is_arithmetic<T>::value
inline constexpr boost::multi_array<T, ND>
element_wise_apply(
const boost::multi_array<T, ND> &input_array, std::function<T(T)> func)
247 using arrayIndex = boost::multi_array<double, ND>::index;
248 using ndIndexArray = boost::array<arrayIndex, ND>;
249 boost::detail::multi_array::extent_gen<ND> output_extents;
250 std::vector<size_t> shape_list;
251 for (std::size_t i = 0; i < ND; i++)
253 shape_list.push_back(input_array.shape()[i]);
255 std::copy(shape_list.begin(), shape_list.end(), output_extents.ranges_.begin());
256 boost::multi_array<T, ND> output_array(output_extents);
259 const T *p = input_array.data();
261 for (std::size_t i = 0; i < input_array.num_elements(); i++)
264 output_array(index) = func(input_array(index));
273 template <
class T,
long unsigned int ND>
274 requires std::is_arithmetic<T>::value
inline constexpr boost::multi_array<T, ND>
sqrt(
const boost::multi_array<T, ND> &input_array)
276 std::function<T(T)> func = (T(*)(T))std::sqrt;
282 requires std::is_arithmetic<T>::value
inline constexpr T
sqrt(
const T input)
284 return std::sqrt(input);
288 template <
class T,
long unsigned int ND>
289 requires std::is_arithmetic<T>::value
inline constexpr boost::multi_array<T, ND>
exp(
const boost::multi_array<T, ND> &input_array)
291 std::function<T(T)> func = (T(*)(T))std::exp;
297 requires std::is_arithmetic<T>::value
inline constexpr T
exp(
const T input)
299 return std::exp(input);
303 template <
class T,
long unsigned int ND>
304 requires std::is_arithmetic<T>::value
inline constexpr boost::multi_array<T, ND>
log(
const boost::multi_array<T, ND> &input_array)
306 std::function<T(T)> func = std::log<T>();
312 requires std::is_arithmetic<T>::value
inline constexpr T
log(
const T input)
314 return std::log(input);
318 template <
class T,
long unsigned int ND>
319 requires std::is_arithmetic<T>::value
inline constexpr boost::multi_array<T, ND>
pow(
const boost::multi_array<T, ND> &input_array,
const T exponent)
321 std::function<T(T)> pow_func = [exponent](T input)
322 {
return std::pow(input, exponent); };
328 requires std::is_arithmetic<T>::value
inline constexpr T
pow(
const T input,
const T exponent)
330 return std::pow(input, exponent);
336 template <
class T,
long unsigned int ND>
337 inline constexpr boost::multi_array<T, ND>
element_wise_duo_apply(boost::multi_array<T, ND>
const &lhs, boost::multi_array<T, ND>
const &rhs, std::function<T(T, T)> func)
340 using arrayIndex = boost::multi_array<double, ND>::index;
341 using ndIndexArray = boost::array<arrayIndex, ND>;
342 boost::detail::multi_array::extent_gen<ND> output_extents;
343 std::vector<size_t> shape_list;
344 for (std::size_t i = 0; i < ND; i++)
346 shape_list.push_back(lhs.shape()[i]);
348 std::copy(shape_list.begin(), shape_list.end(), output_extents.ranges_.begin());
349 boost::multi_array<T, ND> output_array(output_extents);
352 const T *p = lhs.data();
354 for (std::size_t i = 0; i < lhs.num_elements(); i++)
357 output_array(index) = func(lhs(index), rhs(index));
364 template <
typename T,
typename inT,
long unsigned int ND>
365 requires std::is_integral<inT>::value && std::is_arithmetic<T>::value
inline constexpr boost::multi_array<T, ND>
zeros(inT (&dimensions_input)[ND])
368 boost::detail::multi_array::extent_gen<ND> output_extents;
369 std::vector<size_t> shape_list;
370 for (std::size_t i = 0; i < ND; i++)
372 shape_list.push_back(dimensions_input[i]);
374 std::copy(shape_list.begin(), shape_list.end(), output_extents.ranges_.begin());
376 boost::multi_array<T, ND> output_array(output_extents);
377 std::function<T(T)> zero_func = [](T input)
383 template <
typename T,
long unsigned int ND>
384 requires std::is_arithmetic<T>::value
inline constexpr T
max(boost::multi_array<T, ND>
const &input_array)
387 bool max_not_set =
true;
388 const T *data_pointer = input_array.data();
389 for (std::size_t i = 0; i < input_array.num_elements(); i++)
391 T element = *data_pointer;
392 if (max_not_set || element >
max)
403 template <
class T,
class... Ts,
class = std::enable_if_t<(std::is_same_v<T, Ts> && ...)>>
404 requires std::is_arithmetic<T>::value
inline constexpr T
max(T input1, Ts... inputs)
407 for (T input : {inputs...})
418 template <
typename T,
long unsigned int ND>
419 requires std::is_arithmetic<T>::value
inline constexpr T
min(boost::multi_array<T, ND>
const &input_array)
422 bool min_not_set =
true;
423 const T *data_pointer = input_array.data();
424 for (std::size_t i = 0; i < input_array.num_elements(); i++)
426 T element = *data_pointer;
427 if (min_not_set || element <
min)
438 template <
class T,
class... Ts,
class = std::enable_if_t<(std::is_same_v<T, Ts> && ...)>>
439 inline constexpr T
min(T input1, Ts... inputs)
requires std::is_arithmetic<T>::value
442 for (T input : {inputs...})
453 template <
typename T,
long unsigned int ND>
454 requires std::is_arithmetic<T>::value
inline constexpr boost::multi_array<T, ND>
abs(boost::multi_array<T, ND>
const &input_array)
456 std::function<T(T)> abs_func = [](T input)
457 {
return std::abs(input); };
462 template <
typename T>
463 requires std::is_arithmetic<T>::value
inline constexpr T
abs(T input)
465 return std::abs(input);
469 template <
typename T,
long unsigned int ND>
470 requires std::is_arithmetic<T>::value
inline constexpr boost::multi_array<T, ND - 1>
slice(boost::multi_array<T, ND>
const &input_array, std::size_t slice_index)
474 boost::detail::multi_array::extent_gen<ND - 1> output_extents;
475 std::vector<size_t> shape_list;
476 for (std::size_t i = 1; i < ND; i++)
478 shape_list.push_back(input_array.shape()[i]);
480 std::copy(shape_list.begin(), shape_list.end(), output_extents.ranges_.begin());
482 boost::multi_array<T, ND - 1> output_array(output_extents);
484 const T *p = input_array.data();
485 boost::array<std::size_t, ND> index;
486 for (std::size_t i = 0; i < input_array.num_elements(); i++)
489 output_array(index) = input_array[slice_index](index);
503template <
class T,
long unsigned int ND>
504inline boost::multi_array<T, ND>
operator*(boost::multi_array<T, ND>
const &lhs, boost::multi_array<T, ND>
const &rhs)
506 std::function<T(T, T)> func = std::multiplies<T>();
511template <
class T,
long unsigned int ND>
512inline boost::multi_array<T, ND>
operator*(T
const &lhs, boost::multi_array<T, ND>
const &rhs)
514 std::function<T(T)> func = [lhs](T item)
515 {
return lhs * item; };
519template <
class T,
long unsigned int ND>
520inline boost::multi_array<T, ND>
operator*(boost::multi_array<T, ND>
const &lhs, T
const &rhs)
527template <
class T,
long unsigned int ND>
528boost::multi_array<T, ND>
operator+(boost::multi_array<T, ND>
const &lhs, boost::multi_array<T, ND>
const &rhs)
530 std::function<T(T, T)> func = std::plus<T>();
535template <
class T,
long unsigned int ND>
536inline boost::multi_array<T, ND>
operator+(T
const &lhs, boost::multi_array<T, ND>
const &rhs)
538 std::function<T(T)> func = [lhs](T item)
539 {
return lhs + item; };
544template <
class T,
long unsigned int ND>
545inline boost::multi_array<T, ND>
operator+(boost::multi_array<T, ND>
const &lhs, T
const &rhs)
552template <
class T,
long unsigned int ND>
553boost::multi_array<T, ND>
operator-(boost::multi_array<T, ND>
const &lhs, boost::multi_array<T, ND>
const &rhs)
555 std::function<T(T, T)> func = std::minus<T>();
560template <
class T,
long unsigned int ND>
561inline boost::multi_array<T, ND>
operator-(T
const &lhs, boost::multi_array<T, ND>
const &rhs)
563 std::function<T(T)> func = [lhs](T item)
564 {
return lhs - item; };
569template <
class T,
long unsigned int ND>
570inline boost::multi_array<T, ND>
operator-(boost::multi_array<T, ND>
const &lhs, T
const &rhs)
577template <
class T,
long unsigned int ND>
578boost::multi_array<T, ND>
operator/(boost::multi_array<T, ND>
const &lhs, boost::multi_array<T, ND>
const &rhs)
580 std::function<T(T, T)> func = std::divides<T>();
585template <
class T,
long unsigned int ND>
586inline boost::multi_array<T, ND>
operator/(T
const &lhs, boost::multi_array<T, ND>
const &rhs)
588 std::function<T(T)> func = [lhs](T item)
589 {
return lhs / item; };
594template <
class T,
long unsigned int ND>
595inline boost::multi_array<T, ND>
operator/(boost::multi_array<T, ND>
const &lhs, T
const &rhs)
597 std::function<T(T)> func = [rhs](T item)
598 {
return item / rhs; };
boost::multi_array< T, ND > operator*(boost::multi_array< T, ND > const &lhs, boost::multi_array< T, ND > const &rhs)
Multiplication operator between two multi arrays, element-wise.
boost::multi_array< T, ND > operator/(boost::multi_array< T, ND > const &lhs, boost::multi_array< T, ND > const &rhs)
Division between two multi arrays, element wise.
boost::multi_array< T, ND > operator-(boost::multi_array< T, ND > const &lhs, boost::multi_array< T, ND > const &rhs)
Minus operator between two multi arrays, element-wise.
boost::multi_array< T, ND > operator+(boost::multi_array< T, ND > const &lhs, boost::multi_array< T, ND > const &rhs)
Addition operator between two multi arrays, element wise.
Custom implementation of numpy in C++.
::value constexpr boost::multi_array< T, ND > pow(const boost::multi_array< T, ND > &input_array, const T exponent)
Implements the numpy pow function on multi arrays.
::value constexpr std::vector< boost::multi_array< T, ND > > gradient(boost::multi_array< T, ND > inArray, std::initializer_list< T > args)
boost::array< typename boost::multi_array< ndArrayValue, ND >::index, ND > getIndexArray(const boost::multi_array< ndArrayValue, ND > &m, const ndArrayValue *requestedElement)
Gets the index of one element in a multi_array.
::value constexpr std::vector< boost::multi_array< T, ND > > meshgrid(const boost::multi_array< T, 1 >(&cinput)[ND], bool sparsing=false, indexing indexing_type=xy)
::value constexpr boost::multi_array< T, ND > log(const boost::multi_array< T, ND > &input_array)
Implements the numpy log function on multi arrays.
::value constexpr boost::multi_array< T, ND > sqrt(const boost::multi_array< T, ND > &input_array)
Implements the numpy sqrt function on multi arrays.
::value constexpr boost::multi_array< T, ND > exp(const boost::multi_array< T, ND > &input_array)
Implements the numpy exp function on multi arrays.
::value constexpr T abs(T input)
Implements the numpy abs function for a scalar.
boost::multi_array< double, 1 > linspace(double start, double stop, long unsigned int num)
Implements the numpy linspace function.
boost::multi_array< ndArrayValue, ND >::index getIndex(const boost::multi_array< ndArrayValue, ND > &m, const ndArrayValue *requestedElement, const unsigned short int direction)
Gets the index of one element in a multi_array in one axis.
::value constexpr T min(boost::multi_array< T, ND > const &input_array)
Implements the numpy min function for an n-dimensionl multi array.
::value constexpr boost::multi_array< T, ND - 1 > slice(boost::multi_array< T, ND > const &input_array, std::size_t slice_index)
Slices the array through one dimension and returns a ND - 1 dimensional array.
::value &&std::is_arithmetic< T >::value constexpr boost::multi_array< T, ND > zeros(inT(&dimensions_input)[ND])
Implements the numpy zeros function for an n-dimensionl multi array.
void for_each(const boost::type< Element > &type_dispatch, Array A, Functor &xform)
constexpr boost::multi_array< T, ND > element_wise_duo_apply(boost::multi_array< T, ND > const &lhs, boost::multi_array< T, ND > const &rhs, std::function< T(T, T)> func)
::value constexpr boost::multi_array< T, ND > element_wise_apply(const boost::multi_array< T, ND > &input_array, std::function< T(T)> func)
Creates a new array and fills it with the values of the result of the function called on the input ar...
::value constexpr T max(boost::multi_array< T, ND > const &input_array)
Implements the numpy max function for an n-dimensionl multi array.