Skip to content

Commit af706e5

Browse files
committed
add modulo operator
1 parent 8eb8eaf commit af706e5

File tree

6 files changed

+177
-2
lines changed

6 files changed

+177
-2
lines changed

code/ndarray.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,12 @@ mp_obj_t ndarray_binary_op(mp_binary_op_t _op, mp_obj_t lobj, mp_obj_t robj) {
17031703
return ndarray_binary_add(lhs, rhs, ndim, shape, lstrides, rstrides);
17041704
break;
17051705
#endif
1706+
#if NDARRAY_HAS_BINARY_OP_MODULO
1707+
case MP_BINARY_OP_MODULO:
1708+
COMPLEX_DTYPE_NOT_IMPLEMENTED(lhs->dtype);
1709+
return ndarray_binary_modulo(lhs, rhs, ndim, shape, lstrides, rstrides);
1710+
break;
1711+
#endif
17061712
#if NDARRAY_HAS_BINARY_OP_MULTIPLY
17071713
case MP_BINARY_OP_MULTIPLY:
17081714
return ndarray_binary_multiply(lhs, rhs, ndim, shape, lstrides, rstrides);

code/ndarray_operators.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,83 @@ mp_obj_t ndarray_binary_add(ndarray_obj_t *lhs, ndarray_obj_t *rhs,
248248
}
249249
#endif /* NDARRAY_HAS_BINARY_OP_ADD */
250250

251+
#if NDARRAY_HAS_BINARY_OP_MODULO
252+
mp_obj_t ndarray_binary_modulo(ndarray_obj_t *lhs, ndarray_obj_t *rhs,
253+
uint8_t ndim, size_t *shape, int32_t *lstrides, int32_t *rstrides) {
254+
255+
ndarray_obj_t *results = NULL;
256+
uint8_t *larray = (uint8_t *)lhs->array;
257+
uint8_t *rarray = (uint8_t *)rhs->array;
258+
259+
if(lhs->dtype == NDARRAY_UINT8) {
260+
if(rhs->dtype == NDARRAY_UINT8) {
261+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_UINT8);
262+
BINARY_LOOP(results, uint8_t, uint8_t, uint8_t, larray, lstrides, rarray, rstrides, %);
263+
} else if(rhs->dtype == NDARRAY_INT8) {
264+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
265+
BINARY_LOOP(results, int16_t, uint8_t, int8_t, larray, lstrides, rarray, rstrides, %);
266+
} else if(rhs->dtype == NDARRAY_UINT16) {
267+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_UINT16);
268+
BINARY_LOOP(results, uint16_t, uint8_t, uint16_t, larray, lstrides, rarray, rstrides, %);
269+
} else if(rhs->dtype == NDARRAY_INT16) {
270+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
271+
BINARY_LOOP(results, int16_t, uint8_t, int16_t, larray, lstrides, rarray, rstrides, %);
272+
} else if(rhs->dtype == NDARRAY_FLOAT) {
273+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_FLOAT);
274+
MODULO_FLOAT_LOOP(results, mp_float_t, uint8_t, mp_float_t, larray, lstrides, rarray, rstrides);
275+
}
276+
} else if(lhs->dtype == NDARRAY_INT8) {
277+
if(rhs->dtype == NDARRAY_INT8) {
278+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT8);
279+
BINARY_LOOP(results, int8_t, int8_t, int8_t, larray, lstrides, rarray, rstrides, %);
280+
} else if(rhs->dtype == NDARRAY_UINT16) {
281+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
282+
BINARY_LOOP(results, int16_t, int8_t, uint16_t, larray, lstrides, rarray, rstrides, %);
283+
} else if(rhs->dtype == NDARRAY_INT16) {
284+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
285+
BINARY_LOOP(results, int16_t, int8_t, int16_t, larray, lstrides, rarray, rstrides, %);
286+
} else if(rhs->dtype == NDARRAY_FLOAT) {
287+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_FLOAT);
288+
MODULO_FLOAT_LOOP(results, mp_float_t, int8_t, mp_float_t, larray, lstrides, rarray, rstrides);
289+
} else {
290+
return ndarray_binary_op(MP_BINARY_OP_ADD, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
291+
}
292+
} else if(lhs->dtype == NDARRAY_UINT16) {
293+
if(rhs->dtype == NDARRAY_UINT16) {
294+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_UINT16);
295+
BINARY_LOOP(results, uint16_t, uint16_t, uint16_t, larray, lstrides, rarray, rstrides, %);
296+
} else if(rhs->dtype == NDARRAY_INT16) {
297+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_FLOAT);
298+
BINARY_LOOP(results, mp_float_t, uint16_t, int16_t, larray, lstrides, rarray, rstrides, %);
299+
} else if(rhs->dtype == NDARRAY_FLOAT) {
300+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_FLOAT);
301+
MODULO_FLOAT_LOOP(results, mp_float_t, uint16_t, mp_float_t, larray, lstrides, rarray, rstrides);
302+
} else {
303+
return ndarray_binary_op(MP_BINARY_OP_ADD, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
304+
}
305+
} else if(lhs->dtype == NDARRAY_INT16) {
306+
if(rhs->dtype == NDARRAY_INT16) {
307+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
308+
BINARY_LOOP(results, int16_t, int16_t, int16_t, larray, lstrides, rarray, rstrides, %);
309+
} else if(rhs->dtype == NDARRAY_FLOAT) {
310+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_FLOAT);
311+
MODULO_FLOAT_LOOP(results, mp_float_t, int16_t, mp_float_t, larray, lstrides, rarray, rstrides);
312+
} else {
313+
return ndarray_binary_op(MP_BINARY_OP_ADD, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
314+
}
315+
} else if(lhs->dtype == NDARRAY_FLOAT) {
316+
if(rhs->dtype == NDARRAY_FLOAT) {
317+
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_FLOAT);
318+
MODULO_FLOAT_LOOP(results, mp_float_t, mp_float_t, mp_float_t, larray, lstrides, rarray, rstrides);
319+
} else {
320+
return ndarray_binary_op(MP_BINARY_OP_ADD, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
321+
}
322+
}
323+
324+
return MP_OBJ_FROM_PTR(results);
325+
}
326+
#endif /* NDARRAY_HAS_BINARY_OP_MODULO */
327+
251328
#if NDARRAY_HAS_BINARY_OP_MULTIPLY
252329
mp_obj_t ndarray_binary_multiply(ndarray_obj_t *lhs, ndarray_obj_t *rhs,
253330
uint8_t ndim, size_t *shape, int32_t *lstrides, int32_t *rstrides) {

code/ndarray_operators.h

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
mp_obj_t ndarray_binary_equality(ndarray_obj_t *, ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t *, mp_binary_op_t );
1414
mp_obj_t ndarray_binary_add(ndarray_obj_t *, ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t *);
15+
mp_obj_t ndarray_binary_modulo(ndarray_obj_t *, ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t *);
1516
mp_obj_t ndarray_binary_multiply(ndarray_obj_t *, ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t *);
1617
mp_obj_t ndarray_binary_more(ndarray_obj_t *, ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t *, mp_binary_op_t );
1718
mp_obj_t ndarray_binary_power(ndarray_obj_t *, ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t *);
@@ -537,3 +538,90 @@ mp_obj_t ndarray_inplace_divide(ndarray_obj_t *, ndarray_obj_t *, int32_t *);
537538
} while(0)
538539

539540
#endif /* ULAB_MAX_DIMS == 4 */
541+
542+
#define MODULO_FLOAT1(results, array, type_left, type_right, larray, lstrides, rarray, rstrides)\
543+
({\
544+
size_t l = 0;\
545+
do {\
546+
*(array)++ = MICROPY_FLOAT_C_FUN(fmod)(*((type_left *)(larray)), *((type_right *)(rarray)));\
547+
(larray) += (lstrides)[ULAB_MAX_DIMS - 1];\
548+
(rarray) += (rstrides)[ULAB_MAX_DIMS - 1];\
549+
l++;\
550+
} while(l < (results)->shape[ULAB_MAX_DIMS - 1]);\
551+
})
552+
553+
#if ULAB_MAX_DIMS == 1
554+
#define MODULO_FLOAT_LOOP(results, type_out, type_left, type_right, larray, lstrides, rarray, rstrides) do {\
555+
type_out *array = (type_out *)(results)->array;\
556+
MODULO_FLOAT1((results), (array), type_left, type_right, (larray), (lstrides), (rarray), (rstrides));\
557+
} while(0)
558+
#endif /* ULAB_MAX_DIMS == 1 */
559+
560+
#if ULAB_MAX_DIMS == 2
561+
#define MODULO_FLOAT_LOOP(results, type_out, type_left, type_right, larray, lstrides, rarray, rstrides) do {\
562+
type_out *array = (type_out *)(results)->array;\
563+
size_t l = 0;\
564+
do {\
565+
MODULO_FLOAT1((results), (array), type_left, type_right, (larray), (lstrides), (rarray), (rstrides));\
566+
(larray) -= (lstrides)[ULAB_MAX_DIMS - 1] * (results)->shape[ULAB_MAX_DIMS - 1];\
567+
(larray) += (lstrides)[ULAB_MAX_DIMS - 2];\
568+
(rarray) -= (rstrides)[ULAB_MAX_DIMS - 1] * (results)->shape[ULAB_MAX_DIMS - 1];\
569+
(rarray) += (rstrides)[ULAB_MAX_DIMS - 2];\
570+
l++;\
571+
} while(l < (results)->shape[ULAB_MAX_DIMS - 2]);\
572+
} while(0)
573+
#endif /* ULAB_MAX_DIMS == 2 */
574+
575+
#if ULAB_MAX_DIMS == 3
576+
#define MODULO_FLOAT_LOOP(results, type_out, type_left, type_right, larray, lstrides, rarray, rstrides) do {\
577+
type_out *array = (type_out *)(results)->array;\
578+
size_t k = 0;\
579+
do {\
580+
size_t l = 0;\
581+
do {\
582+
MODULO_FLOAT1((results), (array), type_left, type_right, (larray), (lstrides), (rarray), (rstrides));\
583+
(larray) -= (lstrides)[ULAB_MAX_DIMS - 1] * (results)->shape[ULAB_MAX_DIMS - 1];\
584+
(larray) += (lstrides)[ULAB_MAX_DIMS - 2];\
585+
(rarray) -= (rstrides)[ULAB_MAX_DIMS - 1] * (results)->shape[ULAB_MAX_DIMS - 1];\
586+
(rarray) += (rstrides)[ULAB_MAX_DIMS - 2];\
587+
l++;\
588+
} while(l < (results)->shape[ULAB_MAX_DIMS - 2]);\
589+
(larray) -= (lstrides)[ULAB_MAX_DIMS - 2] * (results)->shape[ULAB_MAX_DIMS - 2];\
590+
(larray) += (lstrides)[ULAB_MAX_DIMS - 3];\
591+
(rarray) -= (rstrides)[ULAB_MAX_DIMS - 2] * (results)->shape[ULAB_MAX_DIMS - 2];\
592+
(rarray) += (rstrides)[ULAB_MAX_DIMS - 3];\
593+
k++;\
594+
} while(k < (results)->shape[ULAB_MAX_DIMS - 3]);\
595+
} while(0)
596+
#endif /* ULAB_MAX_DIMS == 3 */
597+
598+
#if ULAB_MAX_DIMS == 4
599+
#define MODULO_FLOAT_LOOP(results, type_out, type_left, type_right, larray, lstrides, rarray, rstrides) do {\
600+
type_out *array = (type_out *)(results)->array;\
601+
size_t j = 0;\
602+
do {\
603+
size_t k = 0;\
604+
do {\
605+
size_t l = 0;\
606+
do {\
607+
MODULO_FLOAT1((results), (array), type_left, type_right, (larray), (lstrides), (rarray), (rstrides));\
608+
(larray) -= (lstrides)[ULAB_MAX_DIMS - 1] * (results)->shape[ULAB_MAX_DIMS - 1];\
609+
(larray) += (lstrides)[ULAB_MAX_DIMS - 2];\
610+
(rarray) -= (rstrides)[ULAB_MAX_DIMS - 1] * (results)->shape[ULAB_MAX_DIMS - 1];\
611+
(rarray) += (rstrides)[ULAB_MAX_DIMS - 2];\
612+
l++;\
613+
} while(l < (results)->shape[ULAB_MAX_DIMS - 2]);\
614+
(larray) -= (lstrides)[ULAB_MAX_DIMS - 2] * (results)->shape[ULAB_MAX_DIMS - 2];\
615+
(larray) += (lstrides)[ULAB_MAX_DIMS - 3];\
616+
(rarray) -= (rstrides)[ULAB_MAX_DIMS - 2] * (results)->shape[ULAB_MAX_DIMS - 2];\
617+
(rarray) += (rstrides)[ULAB_MAX_DIMS - 3];\
618+
k++;\
619+
} while(k < (results)->shape[ULAB_MAX_DIMS - 3]);\
620+
(larray) -= (lstrides)[ULAB_MAX_DIMS - 3] * (results)->shape[ULAB_MAX_DIMS - 3];\
621+
(larray) += (lstrides)[ULAB_MAX_DIMS - 4];\
622+
(rarray) -= (rstrides)[ULAB_MAX_DIMS - 3] * (results)->shape[ULAB_MAX_DIMS - 3];\
623+
(rarray) += (rstrides)[ULAB_MAX_DIMS - 4];\
624+
j++;\
625+
} while(j < (results)->shape[ULAB_MAX_DIMS - 4]);\
626+
} while(0)
627+
#endif /* ULAB_MAX_DIMS == 4 */

code/ulab.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include "user/user.h"
3434
#include "utils/utils.h"
3535

36-
#define ULAB_VERSION 6.8.0
36+
#define ULAB_VERSION 6.9.0
3737
#define xstr(s) str(s)
3838
#define str(s) #s
3939

code/ulab.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@
117117
#define NDARRAY_HAS_BINARY_OP_LESS_EQUAL (1)
118118
#endif
119119

120+
#ifndef NDARRAY_HAS_BINARY_OP_MODULO
121+
#define NDARRAY_HAS_BINARY_OP_MODULO (1)
122+
#endif
123+
120124
#ifndef NDARRAY_HAS_BINARY_OP_MORE
121125
#define NDARRAY_HAS_BINARY_OP_MORE (1)
122126
#endif

docs/ulab-ndarray.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2599,7 +2599,7 @@
25992599
"source": [
26002600
"# Binary operators\n",
26012601
"\n",
2602-
"`ulab` implements the `+`, `-`, `*`, `/`, `**`, `<`, `>`, `<=`, `>=`, `==`, `!=`, `+=`, `-=`, `*=`, `/=`, `**=` binary operators, as well as the `AND`, `OR`, `XOR` bit-wise operators that work element-wise. Note that the bit-wise operators will raise an exception, if either of the operands is of `float` or `complex` type.\n",
2602+
"`ulab` implements the `+`, `-`, `*`, `/`, `**`, `%`, `<`, `>`, `<=`, `>=`, `==`, `!=`, `+=`, `-=`, `*=`, `/=`, `**=` binary operators, as well as the `AND`, `OR`, `XOR` bit-wise operators that work element-wise. Note that the bit-wise operators will raise an exception, if either of the operands is of `float` or `complex` type.\n",
26032603
"\n",
26042604
"Broadcasting is available, meaning that the two operands do not even have to have the same shape. If the lengths along the respective axes are equal, or one of them is 1, or the axis is missing, the element-wise operation can still be carried out. \n",
26052605
"A thorough explanation of broadcasting can be found under https://numpy.org/doc/stable/user/basics.broadcasting.html. \n",

0 commit comments

Comments
 (0)