Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into circuitpython9
Browse files Browse the repository at this point in the history
  • Loading branch information
jepler committed Oct 30, 2023
2 parents 9c9e953 + a05ec05 commit 8c444ef
Show file tree
Hide file tree
Showing 12 changed files with 354 additions and 10 deletions.
8 changes: 7 additions & 1 deletion code/ndarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -1646,7 +1646,7 @@ ndarray_obj_t *ndarray_from_mp_obj(mp_obj_t obj, uint8_t other_type) {
mp_float_t *array = (mp_float_t *)ndarray->array;
array[0] = mp_obj_get_float(obj);
} else if(mp_obj_is_bool(obj)) {
ndarray = ndarray_new_linear_array(1, NDARRAY_BOOLEAN);
ndarray = ndarray_new_linear_array(1, NDARRAY_BOOL);
uint8_t *array = (uint8_t *)ndarray->array;
if(obj == mp_const_true) {
*array = 1;
Expand Down Expand Up @@ -1857,6 +1857,12 @@ mp_obj_t ndarray_binary_op(mp_binary_op_t _op, mp_obj_t lobj, mp_obj_t robj) {
return ndarray_binary_power(lhs, rhs, ndim, shape, lstrides, rstrides);
break;
#endif
#if NDARRAY_HAS_BINARY_OP_OR | NDARRAY_HAS_BINARY_OP_XOR | NDARRAY_HAS_BINARY_OP_AND
case MP_BINARY_OP_OR:
case MP_BINARY_OP_XOR:
case MP_BINARY_OP_AND:
return ndarray_binary_logical(lhs, rhs, ndim, shape, lstrides, rstrides, op);
#endif
#if NDARRAY_HAS_BINARY_OP_FLOOR_DIVIDE
case MP_BINARY_OP_FLOOR_DIVIDE:
COMPLEX_DTYPE_NOT_IMPLEMENTED(lhs->dtype);
Expand Down
188 changes: 188 additions & 0 deletions code/ndarray_operators.c
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,194 @@ mp_obj_t ndarray_binary_power(ndarray_obj_t *lhs, ndarray_obj_t *rhs,
}
#endif /* NDARRAY_HAS_BINARY_OP_POWER */

#if NDARRAY_HAS_BINARY_OP_OR | NDARRAY_HAS_BINARY_OP_XOR | NDARRAY_HAS_BINARY_OP_AND
mp_obj_t ndarray_binary_logical(ndarray_obj_t *lhs, ndarray_obj_t *rhs,
uint8_t ndim, size_t *shape, int32_t *lstrides, int32_t *rstrides, mp_binary_op_t op) {

#if ULAB_SUPPORTS_COMPLEX
if((lhs->dtype == NDARRAY_COMPLEX) || (rhs->dtype == NDARRAY_COMPLEX) || (lhs->dtype == NDARRAY_FLOAT) || (rhs->dtype == NDARRAY_FLOAT)) {
mp_raise_TypeError(translate("operation not supported for the input types"));
}
#else
if((lhs->dtype == NDARRAY_FLOAT) || (rhs->dtype == NDARRAY_FLOAT)) {
mp_raise_TypeError(translate("operation not supported for the input types"));
}
#endif

// bail out, if both inputs are of 16-bit types, but differ in sign;
// numpy promotes the result to int32
if(((lhs->dtype == NDARRAY_INT16) && (rhs->dtype == NDARRAY_UINT16)) ||
((lhs->dtype == NDARRAY_UINT16) && (rhs->dtype == NDARRAY_INT16))) {
mp_raise_TypeError(translate("dtype of int32 is not supported"));
}

ndarray_obj_t *results = NULL;
uint8_t *larray = (uint8_t *)lhs->array;
uint8_t *rarray = (uint8_t *)rhs->array;


switch(op) {
case MP_BINARY_OP_XOR:
if(lhs->dtype == NDARRAY_UINT8) {
if(rhs->dtype == NDARRAY_UINT8) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_UINT8);
if(lhs->boolean & rhs->boolean) {
results->boolean = 1;
}
BINARY_LOOP(results, uint8_t, uint8_t, uint8_t, larray, lstrides, rarray, rstrides, ^);
} else if(rhs->dtype == NDARRAY_INT8) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, uint8_t, int8_t, larray, lstrides, rarray, rstrides, ^);
} else if(rhs->dtype == NDARRAY_UINT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_UINT16);
BINARY_LOOP(results, uint16_t, uint8_t, uint16_t, larray, lstrides, rarray, rstrides, ^);
} else if(rhs->dtype == NDARRAY_INT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, uint8_t, int16_t, larray, lstrides, rarray, rstrides, ^);
}
} else if(lhs->dtype == NDARRAY_INT8) {
if(rhs->dtype == NDARRAY_INT8) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT8);
BINARY_LOOP(results, int8_t, int8_t, int8_t, larray, lstrides, rarray, rstrides, ^);
} else if(rhs->dtype == NDARRAY_UINT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, int8_t, uint16_t, larray, lstrides, rarray, rstrides, ^);
} else if(rhs->dtype == NDARRAY_INT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, int8_t, int16_t, larray, lstrides, rarray, rstrides, ^);
} else {
return ndarray_binary_op(MP_BINARY_OP_XOR, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
}
} else if(lhs->dtype == NDARRAY_UINT16) {
if(rhs->dtype == NDARRAY_UINT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_UINT16);
BINARY_LOOP(results, uint16_t, uint16_t, uint16_t, larray, lstrides, rarray, rstrides, ^);
} else if(rhs->dtype == NDARRAY_INT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_FLOAT);
BINARY_LOOP(results, mp_float_t, uint16_t, int16_t, larray, lstrides, rarray, rstrides, ^);
} else {
return ndarray_binary_op(MP_BINARY_OP_XOR, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
}
} else if(lhs->dtype == NDARRAY_INT16) {
if(rhs->dtype == NDARRAY_INT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, int16_t, int16_t, larray, lstrides, rarray, rstrides, ^);
} else {
return ndarray_binary_op(MP_BINARY_OP_XOR, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
}
}
break;

case MP_BINARY_OP_OR:
if(lhs->dtype == NDARRAY_UINT8) {
if(rhs->dtype == NDARRAY_UINT8) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_UINT8);
if(lhs->boolean & rhs->boolean) {
results->boolean = 1;
}
BINARY_LOOP(results, uint8_t, uint8_t, uint8_t, larray, lstrides, rarray, rstrides, |);
} else if(rhs->dtype == NDARRAY_INT8) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, uint8_t, int8_t, larray, lstrides, rarray, rstrides, |);
} else if(rhs->dtype == NDARRAY_UINT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_UINT16);
BINARY_LOOP(results, uint16_t, uint8_t, uint16_t, larray, lstrides, rarray, rstrides, |);
} else if(rhs->dtype == NDARRAY_INT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, uint8_t, int16_t, larray, lstrides, rarray, rstrides, |);
}
} else if(lhs->dtype == NDARRAY_INT8) {
if(rhs->dtype == NDARRAY_INT8) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT8);
BINARY_LOOP(results, int8_t, int8_t, int8_t, larray, lstrides, rarray, rstrides, |);
} else if(rhs->dtype == NDARRAY_UINT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, int8_t, uint16_t, larray, lstrides, rarray, rstrides, |);
} else if(rhs->dtype == NDARRAY_INT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, int8_t, int16_t, larray, lstrides, rarray, rstrides, |);
} else {
return ndarray_binary_op(MP_BINARY_OP_OR, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
}
} else if(lhs->dtype == NDARRAY_UINT16) {
if(rhs->dtype == NDARRAY_UINT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_UINT16);
BINARY_LOOP(results, uint16_t, uint16_t, uint16_t, larray, lstrides, rarray, rstrides, |);
} else if(rhs->dtype == NDARRAY_INT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_FLOAT);
BINARY_LOOP(results, mp_float_t, uint16_t, int16_t, larray, lstrides, rarray, rstrides, |);
} else {
return ndarray_binary_op(MP_BINARY_OP_OR, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
}
} else if(lhs->dtype == NDARRAY_INT16) {
if(rhs->dtype == NDARRAY_INT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, int16_t, int16_t, larray, lstrides, rarray, rstrides, |);
} else {
return ndarray_binary_op(MP_BINARY_OP_OR, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
}
}
break;

case MP_BINARY_OP_AND:
if(lhs->dtype == NDARRAY_UINT8) {
if(rhs->dtype == NDARRAY_UINT8) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_UINT8);
if(lhs->boolean & rhs->boolean) {
results->boolean = 1;
}
BINARY_LOOP(results, uint8_t, uint8_t, uint8_t, larray, lstrides, rarray, rstrides, &);
} else if(rhs->dtype == NDARRAY_INT8) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, uint8_t, int8_t, larray, lstrides, rarray, rstrides, &);
} else if(rhs->dtype == NDARRAY_UINT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_UINT16);
BINARY_LOOP(results, uint16_t, uint8_t, uint16_t, larray, lstrides, rarray, rstrides, &);
} else if(rhs->dtype == NDARRAY_INT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, uint8_t, int16_t, larray, lstrides, rarray, rstrides, &);
}
} else if(lhs->dtype == NDARRAY_INT8) {
if(rhs->dtype == NDARRAY_INT8) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT8);
BINARY_LOOP(results, int8_t, int8_t, int8_t, larray, lstrides, rarray, rstrides, &);
} else if(rhs->dtype == NDARRAY_UINT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, int8_t, uint16_t, larray, lstrides, rarray, rstrides, &);
} else if(rhs->dtype == NDARRAY_INT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, int8_t, int16_t, larray, lstrides, rarray, rstrides, &);
} else {
return ndarray_binary_op(MP_BINARY_OP_AND, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
}
} else if(lhs->dtype == NDARRAY_UINT16) {
if(rhs->dtype == NDARRAY_UINT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_UINT16);
BINARY_LOOP(results, uint16_t, uint16_t, uint16_t, larray, lstrides, rarray, rstrides, &);
} else if(rhs->dtype == NDARRAY_INT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_FLOAT);
BINARY_LOOP(results, mp_float_t, uint16_t, int16_t, larray, lstrides, rarray, rstrides, &);
} else {
return ndarray_binary_op(MP_BINARY_OP_AND, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
}
} else if(lhs->dtype == NDARRAY_INT16) {
if(rhs->dtype == NDARRAY_INT16) {
results = ndarray_new_dense_ndarray(ndim, shape, NDARRAY_INT16);
BINARY_LOOP(results, int16_t, int16_t, int16_t, larray, lstrides, rarray, rstrides, &);
} else {
return ndarray_binary_op(MP_BINARY_OP_AND, MP_OBJ_FROM_PTR(rhs), MP_OBJ_FROM_PTR(lhs));
}
}
break;
default:
return MP_OBJ_NULL; // op not supported
break;
}
return MP_OBJ_FROM_PTR(results);
}

#endif /* NDARRAY_HAS_BINARY_OP_OR | NDARRAY_HAS_BINARY_OP_XOR | NDARRAY_HAS_BINARY_OP_AND */

#if NDARRAY_HAS_INPLACE_ADD || NDARRAY_HAS_INPLACE_MULTIPLY || NDARRAY_HAS_INPLACE_SUBTRACT
mp_obj_t ndarray_inplace_ams(ndarray_obj_t *lhs, ndarray_obj_t *rhs, int32_t *rstrides, uint8_t optype) {

Expand Down
1 change: 1 addition & 0 deletions code/ndarray_operators.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mp_obj_t ndarray_binary_more(ndarray_obj_t *, ndarray_obj_t *, uint8_t , size_t
mp_obj_t ndarray_binary_power(ndarray_obj_t *, ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t *);
mp_obj_t ndarray_binary_subtract(ndarray_obj_t *, ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t *);
mp_obj_t ndarray_binary_true_divide(ndarray_obj_t *, ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t *);
mp_obj_t ndarray_binary_logical(ndarray_obj_t *, ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t *, mp_binary_op_t );
mp_obj_t ndarray_binary_floor_divide(ndarray_obj_t *, ndarray_obj_t *, uint8_t , size_t *, int32_t *, int32_t *);

mp_obj_t ndarray_inplace_ams(ndarray_obj_t *, ndarray_obj_t *, int32_t *, uint8_t );
Expand Down
2 changes: 1 addition & 1 deletion code/ulab.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include "user/user.h"
#include "utils/utils.h"

#define ULAB_VERSION 6.3.5
#define ULAB_VERSION 6.4.1
#define xstr(s) str(s)
#define str(s) #s

Expand Down
12 changes: 12 additions & 0 deletions code/ulab.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@
#define NDARRAY_HAS_BINARY_OP_ADD (1)
#endif

#ifndef NDARRAY_HAS_BINARY_OP_AND
#define NDARRAY_HAS_BINARY_OP_AND (1)
#endif

#ifndef NDARRAY_HAS_BINARY_OP_EQUAL
#define NDARRAY_HAS_BINARY_OP_EQUAL (1)
#endif
Expand Down Expand Up @@ -129,6 +133,10 @@
#define NDARRAY_HAS_BINARY_OP_NOT_EQUAL (1)
#endif

#ifndef NDARRAY_HAS_BINARY_OP_OR
#define NDARRAY_HAS_BINARY_OP_OR (1)
#endif

#ifndef NDARRAY_HAS_BINARY_OP_POWER
#define NDARRAY_HAS_BINARY_OP_POWER (1)
#endif
Expand All @@ -141,6 +149,10 @@
#define NDARRAY_HAS_BINARY_OP_TRUE_DIVIDE (1)
#endif

#ifndef NDARRAY_HAS_BINARY_OP_XOR
#define NDARRAY_HAS_BINARY_OP_XOR (1)
#endif

#ifndef NDARRAY_HAS_INPLACE_OPS
#define NDARRAY_HAS_INPLACE_OPS (1)
#endif
Expand Down
30 changes: 22 additions & 8 deletions docs/ulab-change-log.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
Thu, 10 Aug 2023

version 6.4.1

```
fix BOOLEAN issue, which would cause numpy.where funciton abnormally on RP2040(#643)
```

Thu, 20 Jul 2023

version 6.4.0

implement AND, OR, and XOR binary operators

Sat, 1 Jul 2023

version 6.3.5
Expand Down Expand Up @@ -25,13 +39,13 @@ version 6.3.1
version 6.3.0

add bitwise operators

Wed, 17 May 2023

version 6.1.1

fix ndarray subscription, when value is NULL

Tue, 16 May 2023

version 6.1.0
Expand All @@ -49,7 +63,7 @@ Sun, 7 May 2023
version 6.0.12

ndarray_from_mp_obj correctly treats Boolean arguments

Sat, 6 May 2023

version 6.0.11
Expand All @@ -61,19 +75,19 @@ Sat, 6 May 2023
version 6.0.10

fix binary division

Sun, 21 Jan 2023

version 6.0.6

raise proper exception in arange

Sun, 21 Jan 2023

version 6.0.7

treat empty arrays in sort_complex correctly

Sun, 21 Jan 2023

version 6.0.5
Expand All @@ -85,7 +99,7 @@ Sun, 15 Jan 2023
version 6.0.4

fix dot function

Sat, 14 Jan 2023

version 6.0.3
Expand Down Expand Up @@ -221,7 +235,7 @@ version 4.2.0
Wed, 12 Jan 2022

version 4.2.0

implement numpy.save, numpy.load

Wed, 12 Jan 2022
Expand Down
21 changes: 21 additions & 0 deletions tests/2d/numpy/and.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
try:
from ulab import numpy as np
except ImportError:
import numpy as np

dtypes = (np.uint8, np.int8, np.uint16, np.int16)

for dtype_a in dtypes:
a = np.array(range(5), dtype=dtype_a)
for dtype_b in dtypes:
b = np.array(range(250, 255), dtype=dtype_b)
try:
print('a & b: ', a & b)
except Exception as e:
print(e)

b = np.array([False, True, False, True, False], dtype=np.bool)
try:
print('a & b (bool): ', a & b)
except Exception as e:
print(e)
20 changes: 20 additions & 0 deletions tests/2d/numpy/and.py.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
a & b: array([0, 1, 0, 1, 4], dtype=uint8)
a & b: array([0, 1, 0, 1, 4], dtype=int16)
a & b: array([0, 1, 0, 1, 4], dtype=uint16)
a & b: array([0, 1, 0, 1, 4], dtype=int16)
a & b (bool): array([0, 1, 0, 1, 0], dtype=uint8)
a & b: array([0, 1, 0, 1, 4], dtype=int16)
a & b: array([0, 1, 0, 1, 4], dtype=int8)
a & b: array([0, 1, 0, 1, 4], dtype=int16)
a & b: array([0, 1, 0, 1, 4], dtype=int16)
a & b (bool): array([0, 1, 0, 1, 0], dtype=int16)
a & b: array([0, 1, 0, 1, 4], dtype=uint16)
a & b: array([0, 1, 0, 1, 4], dtype=int16)
a & b: array([0, 1, 0, 1, 4], dtype=uint16)
dtype of int32 is not supported
a & b (bool): array([0, 1, 0, 1, 0], dtype=uint16)
a & b: array([0, 1, 0, 1, 4], dtype=int16)
a & b: array([0, 1, 0, 1, 4], dtype=int16)
dtype of int32 is not supported
a & b: array([0, 1, 0, 1, 4], dtype=int16)
a & b (bool): array([0, 1, 0, 1, 0], dtype=int16)
Loading

0 comments on commit 8c444ef

Please sign in to comment.