aboutsummaryrefslogtreecommitdiff
path: root/circuitpython/extmod/ulab/code/numpy/numerical.h
diff options
context:
space:
mode:
authorRaghuram Subramani <raghus2247@gmail.com>2022-06-19 19:47:51 +0530
committerRaghuram Subramani <raghus2247@gmail.com>2022-06-19 19:47:51 +0530
commit4fd287655a72b9aea14cdac715ad5b90ed082ed2 (patch)
tree65d393bc0e699dd12d05b29ba568e04cea666207 /circuitpython/extmod/ulab/code/numpy/numerical.h
parent0150f70ce9c39e9e6dd878766c0620c85e47bed0 (diff)
add circuitpython code
Diffstat (limited to 'circuitpython/extmod/ulab/code/numpy/numerical.h')
-rw-r--r--circuitpython/extmod/ulab/code/numpy/numerical.h652
1 files changed, 652 insertions, 0 deletions
diff --git a/circuitpython/extmod/ulab/code/numpy/numerical.h b/circuitpython/extmod/ulab/code/numpy/numerical.h
new file mode 100644
index 0000000..8d2971c
--- /dev/null
+++ b/circuitpython/extmod/ulab/code/numpy/numerical.h
@@ -0,0 +1,652 @@
+
+/*
+ * This file is part of the micropython-ulab project,
+ *
+ * https://github.com/v923z/micropython-ulab
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019-2021 Zoltán Vörös
+*/
+
+#ifndef _NUMERICAL_
+#define _NUMERICAL_
+
+#include "../ulab.h"
+#include "../ndarray.h"
+
+// TODO: implement cumsum
+
+#define RUN_ARGMIN1(ndarray, type, array, results, rarray, index, op)\
+({\
+ uint16_t best_index = 0;\
+ type best_value = *((type *)(array));\
+ if(((op) == NUMERICAL_MAX) || ((op) == NUMERICAL_ARGMAX)) {\
+ for(uint16_t i=0; i < (ndarray)->shape[(index)]; i++) {\
+ if(*((type *)(array)) > best_value) {\
+ best_index = i;\
+ best_value = *((type *)(array));\
+ }\
+ (array) += (ndarray)->strides[(index)];\
+ }\
+ } else {\
+ for(uint16_t i=0; i < (ndarray)->shape[(index)]; i++) {\
+ if(*((type *)(array)) < best_value) {\
+ best_index = i;\
+ best_value = *((type *)(array));\
+ }\
+ (array) += (ndarray)->strides[(index)];\
+ }\
+ }\
+ if(((op) == NUMERICAL_ARGMAX) || ((op) == NUMERICAL_ARGMIN)) {\
+ memcpy((rarray), &best_index, (results)->itemsize);\
+ } else {\
+ memcpy((rarray), &best_value, (results)->itemsize);\
+ }\
+ (rarray) += (results)->itemsize;\
+})
+
+#define RUN_SUM1(type, array, results, rarray, ss)\
+({\
+ type sum = 0;\
+ for(size_t i=0; i < (ss).shape[0]; i++) {\
+ sum += *((type *)(array));\
+ (array) += (ss).strides[0];\
+ }\
+ memcpy((rarray), &sum, (results)->itemsize);\
+ (rarray) += (results)->itemsize;\
+})
+
+// The mean could be calculated by simply dividing the sum by
+// the number of elements, but that method is numerically unstable
+#define RUN_MEAN1(type, array, rarray, ss)\
+({\
+ mp_float_t M = 0.0;\
+ for(size_t i=0; i < (ss).shape[0]; i++) {\
+ mp_float_t value = (mp_float_t)(*(type *)(array));\
+ M = M + (value - M) / (mp_float_t)(i+1);\
+ (array) += (ss).strides[0];\
+ }\
+ *(rarray)++ = M;\
+})
+
+// Instead of the straightforward implementation of the definition,
+// we take the numerically stable Welford algorithm here
+// https://www.johndcook.com/blog/2008/09/26/comparing-three-methods-of-computing-standard-deviation/
+#define RUN_STD1(type, array, rarray, ss, div)\
+({\
+ mp_float_t M = 0.0, m = 0.0, S = 0.0;\
+ for(size_t i=0; i < (ss).shape[0]; i++) {\
+ mp_float_t value = (mp_float_t)(*(type *)(array));\
+ m = M + (value - M) / (mp_float_t)(i+1);\
+ S = S + (value - M) * (value - m);\
+ M = m;\
+ (array) += (ss).strides[0];\
+ }\
+ *(rarray)++ = MICROPY_FLOAT_C_FUN(sqrt)(S / (div));\
+})
+
+#define RUN_MEAN_STD1(type, array, rarray, ss, div, isStd)\
+({\
+ mp_float_t M = 0.0, m = 0.0, S = 0.0;\
+ for(size_t i=0; i < (ss).shape[0]; i++) {\
+ mp_float_t value = (mp_float_t)(*(type *)(array));\
+ m = M + (value - M) / (mp_float_t)(i+1);\
+ if(isStd) {\
+ S += (value - M) * (value - m);\
+ }\
+ M = m;\
+ (array) += (ss).strides[0];\
+ }\
+ *(rarray)++ = isStd ? MICROPY_FLOAT_C_FUN(sqrt)(S / (div)) : M;\
+})
+
+#define RUN_DIFF1(ndarray, type, array, results, rarray, index, stencil, N)\
+({\
+ for(size_t i=0; i < (results)->shape[ULAB_MAX_DIMS - 1]; i++) {\
+ type sum = 0;\
+ uint8_t *source = (array);\
+ for(uint8_t d=0; d < (N)+1; d++) {\
+ sum -= (stencil)[d] * *((type *)source);\
+ source += (ndarray)->strides[(index)];\
+ }\
+ (array) += (ndarray)->strides[ULAB_MAX_DIMS - 1];\
+ *(type *)(rarray) = sum;\
+ (rarray) += (results)->itemsize;\
+ }\
+})
+
+#define HEAPSORT1(type, array, increment, N)\
+({\
+ type *_array = (type *)array;\
+ type tmp;\
+ size_t c, q = (N), p, r = (N) >> 1;\
+ for (;;) {\
+ if (r > 0) {\
+ tmp = _array[(--r)*(increment)];\
+ } else {\
+ q--;\
+ if(q == 0) {\
+ break;\
+ }\
+ tmp = _array[q*(increment)];\
+ _array[q*(increment)] = _array[0];\
+ }\
+ p = r;\
+ c = r + r + 1;\
+ while (c < q) {\
+ if((c + 1 < q) && (_array[(c+1)*(increment)] > _array[c*(increment)])) {\
+ c++;\
+ }\
+ if(_array[c*(increment)] > tmp) {\
+ _array[p*(increment)] = _array[c*(increment)];\
+ p = c;\
+ c = p + p + 1;\
+ } else {\
+ break;\
+ }\
+ }\
+ _array[p*(increment)] = tmp;\
+ }\
+})
+
+#define HEAP_ARGSORT1(type, array, increment, N, iarray, iincrement)\
+({\
+ type *_array = (type *)array;\
+ type tmp;\
+ uint16_t itmp, c, q = (N), p, r = (N) >> 1;\
+ for (;;) {\
+ if (r > 0) {\
+ r--;\
+ itmp = (iarray)[r*(iincrement)];\
+ tmp = _array[itmp*(increment)];\
+ } else {\
+ q--;\
+ if(q == 0) {\
+ break;\
+ }\
+ itmp = (iarray)[q*(iincrement)];\
+ tmp = _array[itmp*(increment)];\
+ (iarray)[q*(iincrement)] = (iarray)[0];\
+ }\
+ p = r;\
+ c = r + r + 1;\
+ while (c < q) {\
+ if((c + 1 < q) && (_array[(iarray)[(c+1)*(iincrement)]*(increment)] > _array[(iarray)[c*(iincrement)]*(increment)])) {\
+ c++;\
+ }\
+ if(_array[(iarray)[c*(iincrement)]*(increment)] > tmp) {\
+ (iarray)[p*(iincrement)] = (iarray)[c*(iincrement)];\
+ p = c;\
+ c = p + p + 1;\
+ } else {\
+ break;\
+ }\
+ }\
+ (iarray)[p*(iincrement)] = itmp;\
+ }\
+})
+
+#if ULAB_MAX_DIMS == 1
+#define RUN_SUM(type, array, results, rarray, ss) do {\
+ RUN_SUM1(type, (array), (results), (rarray), (ss));\
+} while(0)
+
+#define RUN_MEAN(type, array, rarray, ss) do {\
+ RUN_MEAN1(type, (array), (rarray), (ss));\
+} while(0)
+
+#define RUN_STD(type, array, rarray, ss, div) do {\
+ RUN_STD1(type, (array), (results), (rarray), (ss), (div));\
+} while(0)
+
+#define RUN_MEAN_STD(type, array, rarray, ss, div, isStd) do {\
+ RUN_MEAN_STD1(type, (array), (rarray), (ss), (div), (isStd));\
+} while(0)
+
+#define RUN_ARGMIN(ndarray, type, array, results, rarray, shape, strides, index, op) do {\
+ RUN_ARGMIN1((ndarray), type, (array), (results), (rarray), (index), (op));\
+} while(0)
+
+#define RUN_DIFF(ndarray, type, array, results, rarray, shape, strides, index, stencil, N) do {\
+ RUN_DIFF1((ndarray), type, (array), (results), (rarray), (index), (stencil), (N));\
+} while(0)
+
+#define HEAPSORT(ndarray, type, array, shape, strides, index, increment, N) do {\
+ HEAPSORT1(type, (array), (increment), (N));\
+} while(0)
+
+#define HEAP_ARGSORT(ndarray, type, array, shape, strides, index, increment, N, iarray, istrides, iincrement) do {\
+ HEAP_ARGSORT1(type, (array), (increment), (N), (iarray), (iincrement));\
+} while(0)
+
+#endif
+
+#if ULAB_MAX_DIMS == 2
+#define RUN_SUM(type, array, results, rarray, ss) do {\
+ size_t l = 0;\
+ do {\
+ RUN_SUM1(type, (array), (results), (rarray), (ss));\
+ (array) -= (ss).strides[0] * (ss).shape[0];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (ss).shape[ULAB_MAX_DIMS - 1]);\
+} while(0)
+
+#define RUN_MEAN(type, array, rarray, ss) do {\
+ size_t l = 0;\
+ do {\
+ RUN_MEAN1(type, (array), (rarray), (ss));\
+ (array) -= (ss).strides[0] * (ss).shape[0];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (ss).shape[ULAB_MAX_DIMS - 1]);\
+} while(0)
+
+#define RUN_STD(type, array, rarray, ss, div) do {\
+ size_t l = 0;\
+ do {\
+ RUN_STD1(type, (array), (rarray), (ss), (div));\
+ (array) -= (ss).strides[0] * (ss).shape[0];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (ss).shape[ULAB_MAX_DIMS - 1]);\
+} while(0)
+
+#define RUN_MEAN_STD(type, array, rarray, ss, div, isStd) do {\
+ size_t l = 0;\
+ do {\
+ RUN_MEAN_STD1(type, (array), (rarray), (ss), (div), (isStd));\
+ (array) -= (ss).strides[0] * (ss).shape[0];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (ss).shape[ULAB_MAX_DIMS - 1]);\
+} while(0)
+
+
+#define RUN_ARGMIN(ndarray, type, array, results, rarray, shape, strides, index, op) do {\
+ size_t l = 0;\
+ do {\
+ RUN_ARGMIN1((ndarray), type, (array), (results), (rarray), (index), (op));\
+ (array) -= (ndarray)->strides[(index)] * (ndarray)->shape[(index)];\
+ (array) += (strides)[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (shape)[ULAB_MAX_DIMS - 1]);\
+} while(0)
+
+#define RUN_DIFF(ndarray, type, array, results, rarray, shape, strides, index, stencil, N) do {\
+ size_t l = 0;\
+ do {\
+ RUN_DIFF1((ndarray), type, (array), (results), (rarray), (index), (stencil), (N));\
+ (array) -= (ndarray)->strides[ULAB_MAX_DIMS - 1] * (results)->shape[ULAB_MAX_DIMS - 1];\
+ (array) += (ndarray)->strides[ULAB_MAX_DIMS - 2];\
+ (rarray) -= (results)->strides[ULAB_MAX_DIMS - 1] * (results)->shape[ULAB_MAX_DIMS - 1];\
+ (rarray) += (results)->strides[ULAB_MAX_DIMS - 2];\
+ l++;\
+ } while(l < (results)->shape[ULAB_MAX_DIMS - 2]);\
+} while(0)
+
+#define HEAPSORT(ndarray, type, array, shape, strides, index, increment, N) do {\
+ size_t l = 0;\
+ do {\
+ HEAPSORT1(type, (array), (increment), (N));\
+ (array) += (strides)[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (shape)[ULAB_MAX_DIMS - 1]);\
+} while(0)
+
+#define HEAP_ARGSORT(ndarray, type, array, shape, strides, index, increment, N, iarray, istrides, iincrement) do {\
+ size_t l = 0;\
+ do {\
+ HEAP_ARGSORT1(type, (array), (increment), (N), (iarray), (iincrement));\
+ (array) += (strides)[ULAB_MAX_DIMS - 1];\
+ (iarray) += (istrides)[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (shape)[ULAB_MAX_DIMS - 1]);\
+} while(0)
+
+#endif
+
+#if ULAB_MAX_DIMS == 3
+#define RUN_SUM(type, array, results, rarray, ss) do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ RUN_SUM1(type, (array), (results), (rarray), (ss));\
+ (array) -= (ss).strides[0] * (ss).shape[0];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (ss).shape[ULAB_MAX_DIMS - 1]);\
+ (array) -= (ss).strides[ULAB_MAX_DIMS - 1] * (ss).shape[ULAB_MAX_DIMS - 1];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (ss).shape[ULAB_MAX_DIMS - 2]);\
+} while(0)
+
+#define RUN_MEAN(type, array, rarray, ss) do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ RUN_MEAN1(type, (array), (rarray), (ss));\
+ (array) -= (ss).strides[0] * (ss).shape[0];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (ss).shape[ULAB_MAX_DIMS - 1]);\
+ (array) -= (ss).strides[ULAB_MAX_DIMS - 1] * (ss).shape[ULAB_MAX_DIMS - 1];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (ss).shape[ULAB_MAX_DIMS - 2]);\
+} while(0)
+
+#define RUN_STD(type, array, rarray, ss, div) do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ RUN_STD1(type, (array), (rarray), (ss), (div));\
+ (array) -= (ss).strides[0] * (ss).shape[0];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (ss).shape[ULAB_MAX_DIMS - 1]);\
+ (array) -= (ss).strides[ULAB_MAX_DIMS - 1] * (ss).shape[ULAB_MAX_DIMS - 1];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (ss).shape[ULAB_MAX_DIMS - 2]);\
+} while(0)
+
+#define RUN_MEAN_STD(type, array, rarray, ss, div, isStd) do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ RUN_MEAN_STD1(type, (array), (rarray), (ss), (div), (isStd));\
+ (array) -= (ss).strides[0] * (ss).shape[0];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (ss).shape[ULAB_MAX_DIMS - 1]);\
+ (array) -= (ss).strides[ULAB_MAX_DIMS - 1] * (ss).shape[ULAB_MAX_DIMS - 1];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (ss).shape[ULAB_MAX_DIMS - 2]);\
+} while(0)
+
+#define RUN_ARGMIN(ndarray, type, array, results, rarray, shape, strides, index, op) do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ RUN_ARGMIN1((ndarray), type, (array), (results), (rarray), (index), (op));\
+ (array) -= (ndarray)->strides[(index)] * (ndarray)->shape[(index)];\
+ (array) += (strides)[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (shape)[ULAB_MAX_DIMS - 1]);\
+ (array) -= (strides)[ULAB_MAX_DIMS - 1] * (shape)[ULAB_MAX_DIMS-1];\
+ (array) += (strides)[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (shape)[ULAB_MAX_DIMS - 2]);\
+} while(0)
+
+#define RUN_DIFF(ndarray, type, array, results, rarray, shape, strides, index, stencil, N) do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ RUN_DIFF1((ndarray), type, (array), (results), (rarray), (index), (stencil), (N));\
+ (array) -= (ndarray)->strides[ULAB_MAX_DIMS - 1] * (results)->shape[ULAB_MAX_DIMS - 1];\
+ (array) += (ndarray)->strides[ULAB_MAX_DIMS - 2];\
+ (rarray) -= (results)->strides[ULAB_MAX_DIMS - 1] * (results)->shape[ULAB_MAX_DIMS - 1];\
+ (rarray) += (results)->strides[ULAB_MAX_DIMS - 2];\
+ l++;\
+ } while(l < (shape)[ULAB_MAX_DIMS - 2]);\
+ (array) -= (ndarray)->strides[ULAB_MAX_DIMS - 2] * (results)->shape[ULAB_MAX_DIMS-2];\
+ (array) += (ndarray)->strides[ULAB_MAX_DIMS - 3];\
+ (rarray) -= (results)->strides[ULAB_MAX_DIMS - 2] * (results)->shape[ULAB_MAX_DIMS - 2];\
+ (rarray) += (results)->strides[ULAB_MAX_DIMS - 3];\
+ k++;\
+ } while(k < (shape)[ULAB_MAX_DIMS - 3]);\
+} while(0)
+
+#define HEAPSORT(ndarray, type, array, shape, strides, index, increment, N) do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ HEAPSORT1(type, (array), (increment), (N));\
+ (array) += (strides)[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (shape)[ULAB_MAX_DIMS - 1]);\
+ (array) -= (strides)[ULAB_MAX_DIMS - 1] * (shape)[ULAB_MAX_DIMS-1];\
+ (array) += (strides)[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (shape)[ULAB_MAX_DIMS - 2]);\
+} while(0)
+
+#define HEAP_ARGSORT(ndarray, type, array, shape, strides, index, increment, N, iarray, istrides, iincrement) do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ HEAP_ARGSORT1(type, (array), (increment), (N), (iarray), (iincrement));\
+ (array) += (strides)[ULAB_MAX_DIMS - 1];\
+ (iarray) += (istrides)[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (shape)[ULAB_MAX_DIMS - 1]);\
+ (iarray) -= (istrides)[ULAB_MAX_DIMS - 1] * (shape)[ULAB_MAX_DIMS-1];\
+ (iarray) += (istrides)[ULAB_MAX_DIMS - 2];\
+ (array) -= (strides)[ULAB_MAX_DIMS - 1] * (shape)[ULAB_MAX_DIMS-1];\
+ (array) += (strides)[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (shape)[ULAB_MAX_DIMS - 2]);\
+} while(0)
+
+#endif
+
+#if ULAB_MAX_DIMS == 4
+#define RUN_SUM(type, array, results, rarray, ss) do {\
+ size_t j = 0;\
+ do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ RUN_SUM1(type, (array), (results), (rarray), (ss));\
+ (array) -= (ss).strides[0] * (ss).shape[0];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (ss).shape[ULAB_MAX_DIMS - 1]);\
+ (array) -= (ss).strides[ULAB_MAX_DIMS - 1] * (ss).shape[ULAB_MAX_DIMS - 1];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (ss).shape[ULAB_MAX_DIMS - 2]);\
+ (array) -= (ss).strides[ULAB_MAX_DIMS - 2] * (ss).shape[ULAB_MAX_DIMS - 2];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 3];\
+ j++;\
+ } while(j < (ss).shape[ULAB_MAX_DIMS - 3]);\
+} while(0)
+
+#define RUN_MEAN(type, array, rarray, ss) do {\
+ size_t j = 0;\
+ do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ RUN_MEAN1(type, (array), (rarray), (ss));\
+ (array) -= (ss).strides[0] * (ss).shape[0];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (ss).shape[ULAB_MAX_DIMS - 1]);\
+ (array) -= (ss).strides[ULAB_MAX_DIMS - 1] * (ss).shape[ULAB_MAX_DIMS - 1];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (ss).shape[ULAB_MAX_DIMS - 2]);\
+ (array) -= (ss).strides[ULAB_MAX_DIMS - 2] * (ss).shape[ULAB_MAX_DIMS - 2];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 3];\
+ j++;\
+ } while(j < (ss).shape[ULAB_MAX_DIMS - 3]);\
+} while(0)
+
+#define RUN_STD(type, array, rarray, ss, div) do {\
+ size_t j = 0;\
+ do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ RUN_STD1(type, (array), (rarray), (ss), (div));\
+ (array) -= (ss).strides[0] * (ss).shape[0];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (ss).shape[ULAB_MAX_DIMS - 1]);\
+ (array) -= (ss).strides[ULAB_MAX_DIMS - 1] * (ss).shape[ULAB_MAX_DIMS - 1];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (ss).shape[ULAB_MAX_DIMS - 2]);\
+ (array) -= (ss).strides[ULAB_MAX_DIMS - 2] * (ss).shape[ULAB_MAX_DIMS - 2];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 3];\
+ j++;\
+ } while(j < (ss).shape[ULAB_MAX_DIMS - 3]);\
+} while(0)
+
+#define RUN_MEAN_STD(type, array, rarray, ss, div, isStd) do {\
+ size_t j = 0;\
+ do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ RUN_MEAN_STD1(type, (array), (rarray), (ss), (div), (isStd));\
+ (array) -= (ss).strides[0] * (ss).shape[0];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (ss).shape[ULAB_MAX_DIMS - 1]);\
+ (array) -= (ss).strides[ULAB_MAX_DIMS - 1] * (ss).shape[ULAB_MAX_DIMS - 1];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (ss).shape[ULAB_MAX_DIMS - 2]);\
+ (array) -= (ss).strides[ULAB_MAX_DIMS - 2] * (ss).shape[ULAB_MAX_DIMS - 2];\
+ (array) += (ss).strides[ULAB_MAX_DIMS - 3];\
+ j++;\
+ } while(j < (ss).shape[ULAB_MAX_DIMS - 3]);\
+} while(0)
+
+#define RUN_ARGMIN(ndarray, type, array, results, rarray, shape, strides, index, op) do {\
+ size_t j = 0;\
+ do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ RUN_ARGMIN1((ndarray), type, (array), (results), (rarray), (index), (op));\
+ (array) -= (ndarray)->strides[(index)] * (ndarray)->shape[(index)];\
+ (array) += (strides)[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (shape)[ULAB_MAX_DIMS - 1]);\
+ (array) -= (strides)[ULAB_MAX_DIMS - 1] * (shape)[ULAB_MAX_DIMS-1];\
+ (array) += (strides)[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (shape)[ULAB_MAX_DIMS - 2]);\
+ (array) -= (strides)[ULAB_MAX_DIMS - 2] * (shape)[ULAB_MAX_DIMS-2];\
+ (array) += (strides)[ULAB_MAX_DIMS - 3];\
+ j++;\
+ } while(j < (shape)[ULAB_MAX_DIMS - 3]);\
+} while(0)
+
+#define RUN_DIFF(ndarray, type, array, results, rarray, shape, strides, index, stencil, N) do {\
+ size_t j = 0;\
+ do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ RUN_DIFF1((ndarray), type, (array), (results), (rarray), (index), (stencil), (N));\
+ (array) -= (ndarray)->strides[ULAB_MAX_DIMS - 1] * (results)->shape[ULAB_MAX_DIMS - 1];\
+ (array) += (ndarray)->strides[ULAB_MAX_DIMS - 2];\
+ (rarray) -= (results)->strides[ULAB_MAX_DIMS - 1] * (results)->shape[ULAB_MAX_DIMS - 1];\
+ (rarray) += (results)->strides[ULAB_MAX_DIMS - 2];\
+ l++;\
+ } while(l < (shape)[ULAB_MAX_DIMS - 2]);\
+ (array) -= (strides)[ULAB_MAX_DIMS - 2] * (shape)[ULAB_MAX_DIMS-2];\
+ (array) += (strides)[ULAB_MAX_DIMS - 3];\
+ (rarray) -= (results)->strides[ULAB_MAX_DIMS - 2] * (results)->shape[ULAB_MAX_DIMS - 2];\
+ (rarray) += (results)->strides[ULAB_MAX_DIMS - 3];\
+ k++;\
+ } while(k < (shape)[ULAB_MAX_DIMS - 3]);\
+ (array) -= (strides)[ULAB_MAX_DIMS - 3] * (shape)[ULAB_MAX_DIMS-3];\
+ (array) += (strides)[ULAB_MAX_DIMS - 4];\
+ (rarray) -= (results)->strides[ULAB_MAX_DIMS - 3] * (results)->shape[ULAB_MAX_DIMS - 3];\
+ (rarray) += (results)->strides[ULAB_MAX_DIMS - 4];\
+ j++;\
+ } while(j < (shape)[ULAB_MAX_DIMS - 4]);\
+} while(0)
+
+#define HEAPSORT(ndarray, type, array, shape, strides, index, increment, N) do {\
+ size_t j = 0;\
+ do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ HEAPSORT1(type, (array), (increment), (N));\
+ (array) += (strides)[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (shape)[ULAB_MAX_DIMS - 1]);\
+ (array) -= (strides)[ULAB_MAX_DIMS - 1] * (shape)[ULAB_MAX_DIMS-1];\
+ (array) += (strides)[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (shape)[ULAB_MAX_DIMS - 2]);\
+ (array) -= (strides)[ULAB_MAX_DIMS - 2] * (shape)[ULAB_MAX_DIMS-2];\
+ (array) += (strides)[ULAB_MAX_DIMS - 3];\
+ j++;\
+ } while(j < (shape)[ULAB_MAX_DIMS - 3]);\
+} while(0)
+
+#define HEAP_ARGSORT(ndarray, type, array, shape, strides, index, increment, N, iarray, istrides, iincrement) do {\
+ size_t j = 0;\
+ do {\
+ size_t k = 0;\
+ do {\
+ size_t l = 0;\
+ do {\
+ HEAP_ARGSORT1(type, (array), (increment), (N), (iarray), (iincrement));\
+ (array) += (strides)[ULAB_MAX_DIMS - 1];\
+ (iarray) += (istrides)[ULAB_MAX_DIMS - 1];\
+ l++;\
+ } while(l < (shape)[ULAB_MAX_DIMS - 1]);\
+ (iarray) -= (istrides)[ULAB_MAX_DIMS - 1] * (shape)[ULAB_MAX_DIMS-1];\
+ (iarray) += (istrides)[ULAB_MAX_DIMS - 2];\
+ (array) -= (strides)[ULAB_MAX_DIMS - 1] * (shape)[ULAB_MAX_DIMS-1];\
+ (array) += (strides)[ULAB_MAX_DIMS - 2];\
+ k++;\
+ } while(k < (shape)[ULAB_MAX_DIMS - 2]);\
+ (iarray) -= (istrides)[ULAB_MAX_DIMS - 2] * (shape)[ULAB_MAX_DIMS-2];\
+ (iarray) += (istrides)[ULAB_MAX_DIMS - 3];\
+ (array) -= (strides)[ULAB_MAX_DIMS - 2] * (shape)[ULAB_MAX_DIMS-2];\
+ (array) += (strides)[ULAB_MAX_DIMS - 3];\
+ j++;\
+ } while(j < (shape)[ULAB_MAX_DIMS - 3]);\
+} while(0)
+
+#endif
+
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_all_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_any_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_argmax_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_argmin_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_argsort_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(numerical_cross_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_diff_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_flip_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_max_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_mean_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_median_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_min_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_roll_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_std_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_sum_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_sort_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(numerical_sort_inplace_obj);
+
+#endif