mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
backup
This commit is contained in:
parent
6a20133587
commit
76a96a0baa
@ -6,11 +6,17 @@
|
|||||||
#include "pocketpy/common/sstream.h"
|
#include "pocketpy/common/sstream.h"
|
||||||
#include "pocketpy/interpreter/vm.h"
|
#include "pocketpy/interpreter/vm.h"
|
||||||
|
|
||||||
typedef struct c11_array2d {
|
typedef struct c11_array2d_like {
|
||||||
py_TValue* data; // slots
|
|
||||||
int n_cols;
|
int n_cols;
|
||||||
int n_rows;
|
int n_rows;
|
||||||
int numel;
|
int numel;
|
||||||
|
py_Ref (*f_get)(struct c11_array2d_like* self, int col, int row);
|
||||||
|
bool (*f_set)(struct c11_array2d_like* self, int col, int row, py_Ref value);
|
||||||
|
} c11_array2d_like;
|
||||||
|
|
||||||
|
typedef struct c11_array2d {
|
||||||
|
c11_array2d_like header;
|
||||||
|
py_TValue* data; // slots
|
||||||
} c11_array2d;
|
} c11_array2d;
|
||||||
|
|
||||||
typedef struct c11_array2d_iterator {
|
typedef struct c11_array2d_iterator {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from typing import Callable, Any, Generic, TypeVar, Literal, overload, Iterator
|
from typing import Callable, Literal, overload, Iterator
|
||||||
from linalg import vec2i
|
from linalg import vec2i
|
||||||
|
|
||||||
Neighborhood = Literal['Moore', 'von Neumann']
|
Neighborhood = Literal['Moore', 'von Neumann']
|
||||||
@ -13,6 +13,8 @@ class array2d_like[T]:
|
|||||||
@property
|
@property
|
||||||
def height(self) -> int: ...
|
def height(self) -> int: ...
|
||||||
@property
|
@property
|
||||||
|
def shape(self) -> vec2i: ...
|
||||||
|
@property
|
||||||
def numel(self) -> int: ...
|
def numel(self) -> int: ...
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
@ -20,53 +22,37 @@ class array2d_like[T]:
|
|||||||
@overload
|
@overload
|
||||||
def is_valid(self, pos: vec2i) -> bool: ...
|
def is_valid(self, pos: vec2i) -> bool: ...
|
||||||
|
|
||||||
@overload
|
|
||||||
def __getitem__(self, index: vec2i) -> T: ...
|
|
||||||
@overload
|
|
||||||
def __getitem__(self, index: tuple[int, int]) -> T: ...
|
|
||||||
@overload
|
|
||||||
def __setitem__(self, index: vec2i, value: T): ...
|
|
||||||
@overload
|
|
||||||
def __setitem__(self, index: tuple[int, int], value: T): ...
|
|
||||||
|
|
||||||
|
|
||||||
class array2d_view[T](array2d_like[T]):
|
|
||||||
origin: vec2i
|
|
||||||
|
|
||||||
|
|
||||||
class array2d[T](array2d_like[T]):
|
|
||||||
def __new__(cls, n_cols: int, n_rows: int, default: T | Callable[[vec2i], T] | None = None): ...
|
|
||||||
def __eq__(self, other: object) -> array2d[bool]: ... # type: ignore
|
|
||||||
def __ne__(self, other: object) -> array2d[bool]: ... # type: ignore
|
|
||||||
def __iter__(self) -> Iterator[tuple[vec2i, T]]: ...
|
|
||||||
|
|
||||||
def get[R](self, col: int, row: int, default: R = None) -> T | R:
|
def get[R](self, col: int, row: int, default: R = None) -> T | R:
|
||||||
"""Gets the value at the given position. If the position is out of bounds, return the default value."""
|
"""Get the value at the given position.
|
||||||
|
|
||||||
@overload
|
If the position is out of bounds, return the default value.
|
||||||
def __getitem__(self, index: tuple[slice, slice]) -> array2d[T]: ...
|
"""
|
||||||
@overload
|
|
||||||
def __getitem__(self, mask: array2d[bool]) -> list[T]: ...
|
|
||||||
@overload
|
|
||||||
def __setitem__(self, index: tuple[slice, slice], value: int | float | str | bool | None | 'array2d[T]'): ...
|
|
||||||
@overload
|
|
||||||
def __setitem__(self, mask: array2d[bool], value: T): ...
|
|
||||||
|
|
||||||
def map[R](self, f: Callable[[T], R]) -> array2d[R]: ...
|
|
||||||
def copy(self) -> 'array2d[T]': ...
|
|
||||||
|
|
||||||
def fill_(self, value: T) -> None: ...
|
|
||||||
def apply_(self, f: Callable[[T], T]) -> None: ...
|
|
||||||
def copy_(self, other: array2d[T] | list[T]) -> None: ...
|
|
||||||
|
|
||||||
def render(self) -> str: ...
|
def render(self) -> str: ...
|
||||||
|
|
||||||
def all(self: array2d[bool]) -> bool: ...
|
def all(self: array2d_like[bool]) -> bool: ...
|
||||||
def any(self: array2d[bool]) -> bool: ...
|
def any(self: array2d_like[bool]) -> bool: ...
|
||||||
|
|
||||||
@staticmethod
|
def map[R](self, f: Callable[[T], R]) -> array2d[R]: ...
|
||||||
def fromlist(data: list[list[T]]) -> array2d[T]: ...
|
def apply(self, f: Callable[[T], T]) -> None: ...
|
||||||
def tolist(self) -> list[list[T]]: ...
|
def copy(self) -> 'array2d[T]': ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def __getitem__(self, index: vec2i | tuple[int, int]) -> T: ...
|
||||||
|
@overload
|
||||||
|
def __getitem__(self, index: tuple[slice, slice]) -> array2d_view[T]: ...
|
||||||
|
@overload
|
||||||
|
def __getitem__(self, index: array2d_like[bool]) -> list[T]: ...
|
||||||
|
@overload
|
||||||
|
def __setitem__(self, index: vec2i | tuple[int, int], value: T): ...
|
||||||
|
@overload
|
||||||
|
def __setitem__(self, index: tuple[slice, slice], value: T | 'array2d_like[T]'): ...
|
||||||
|
@overload
|
||||||
|
def __setitem__(self, index: array2d_like[bool], value: T): ...
|
||||||
|
|
||||||
|
def __eq__(self, other: object) -> array2d[bool]: ... # type: ignore
|
||||||
|
def __ne__(self, other: object) -> array2d[bool]: ... # type: ignore
|
||||||
|
def __iter__(self) -> Iterator[tuple[vec2i, T]]: ...
|
||||||
|
|
||||||
# algorithms
|
# algorithms
|
||||||
def count(self, value: T) -> int:
|
def count(self, value: T) -> int:
|
||||||
@ -81,7 +67,7 @@ class array2d[T](array2d_like[T]):
|
|||||||
Returns a tuple `(x, y, width, height)` or raise `ValueError` if the value is not found.
|
Returns a tuple `(x, y, width, height)` or raise `ValueError` if the value is not found.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def convolve(self: array2d[int], kernel: array2d[int], padding: int) -> array2d[int]:
|
def convolve(self: array2d_like[int], kernel: array2d_like[int], padding: int) -> array2d[int]:
|
||||||
"""Convolves the array with the given kernel."""
|
"""Convolves the array with the given kernel."""
|
||||||
|
|
||||||
def get_connected_components(self, value: T, neighborhood: Neighborhood) -> tuple[array2d[int], int]:
|
def get_connected_components(self, value: T, neighborhood: Neighborhood) -> tuple[array2d[int], int]:
|
||||||
@ -92,6 +78,24 @@ class array2d[T](array2d_like[T]):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class array2d_view[T](array2d_like[T]):
|
||||||
|
@property
|
||||||
|
def origin(self) -> vec2i: ...
|
||||||
|
|
||||||
|
|
||||||
|
class array2d[T](array2d_like[T]):
|
||||||
|
def __new__(
|
||||||
|
cls,
|
||||||
|
n_cols: int,
|
||||||
|
n_rows: int,
|
||||||
|
default: T | Callable[[vec2i], T] | None = None
|
||||||
|
): ...
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def fromlist(data: list[list[T]]) -> array2d[T]: ...
|
||||||
|
def tolist(self) -> list[list[T]]: ...
|
||||||
|
|
||||||
|
|
||||||
class chunked_array2d[T, TContext]:
|
class chunked_array2d[T, TContext]:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -1,86 +1,63 @@
|
|||||||
#include "pocketpy/interpreter/array2d.h"
|
#include "pocketpy/interpreter/array2d.h"
|
||||||
|
|
||||||
static bool py_array2d_is_valid(c11_array2d* self, int col, int row) {
|
static bool c11_array2d_like_is_valid(c11_array2d_like* self, unsigned int col, unsigned int row) {
|
||||||
return col >= 0 && col < self->n_cols && row >= 0 && row < self->n_rows;
|
return col < self->n_cols && row < self->n_rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
static py_ObjectRef py_array2d__get(c11_array2d* self, int col, int row) {
|
static py_Ref py_array2d__get(c11_array2d* self, int col, int row) {
|
||||||
return self->data + row * self->n_cols + col;
|
return self->data + row * self->header.n_cols + col;
|
||||||
}
|
}
|
||||||
|
static bool py_array2d__set(c11_array2d* self, int col, int row, py_Ref value) {
|
||||||
static void py_array2d__set(c11_array2d* self, int col, int row, py_Ref value) {
|
self->data[row * self->header.n_cols + col] = *value;
|
||||||
self->data[row * self->n_cols + col] = *value;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
c11_array2d* py_newarray2d(py_OutRef out, int n_cols, int n_rows) {
|
c11_array2d* py_newarray2d(py_OutRef out, int n_cols, int n_rows) {
|
||||||
int numel = n_cols * n_rows;
|
int numel = n_cols * n_rows;
|
||||||
c11_array2d* ud = py_newobject(out, tp_array2d, numel, sizeof(c11_array2d));
|
c11_array2d* ud = py_newobject(out, tp_array2d, numel, sizeof(c11_array2d));
|
||||||
|
ud->header.n_cols = n_cols;
|
||||||
|
ud->header.n_rows = n_rows;
|
||||||
|
ud->header.numel = numel;
|
||||||
|
ud->header.f_get = (py_Ref (*)(c11_array2d_like*, int, int))py_array2d__get;
|
||||||
|
ud->header.f_set = (bool (*)(c11_array2d_like*, int, int, py_Ref))py_array2d__set;
|
||||||
ud->data = py_getslot(out, 0);
|
ud->data = py_getslot(out, 0);
|
||||||
ud->n_cols = n_cols;
|
|
||||||
ud->n_rows = n_rows;
|
|
||||||
ud->numel = numel;
|
|
||||||
return ud;
|
return ud;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bindings */
|
/* array2d_like bindings */
|
||||||
static bool array2d__new__(int argc, py_Ref argv) {
|
static bool array2d_like_n_cols(int argc, py_Ref argv) {
|
||||||
// __new__(cls, n_cols: int, n_rows: int, default: Callable[[vec2i], T] = None)
|
|
||||||
py_Ref default_ = py_arg(3);
|
|
||||||
PY_CHECK_ARG_TYPE(0, tp_type);
|
|
||||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
|
||||||
PY_CHECK_ARG_TYPE(2, tp_int);
|
|
||||||
int n_cols = argv[1]._i64;
|
|
||||||
int n_rows = argv[2]._i64;
|
|
||||||
int numel = n_cols * n_rows;
|
|
||||||
if(n_cols <= 0 || n_rows <= 0) return ValueError("array2d() expected positive dimensions");
|
|
||||||
c11_array2d* ud = py_newarray2d(py_pushtmp(), n_cols, n_rows);
|
|
||||||
// setup initial values
|
|
||||||
if(py_callable(default_)) {
|
|
||||||
for(int j = 0; j < n_rows; j++) {
|
|
||||||
for(int i = 0; i < n_cols; i++) {
|
|
||||||
py_TValue tmp;
|
|
||||||
py_newvec2i(&tmp,
|
|
||||||
(c11_vec2i){
|
|
||||||
{i, j}
|
|
||||||
});
|
|
||||||
bool ok = py_call(default_, 1, &tmp);
|
|
||||||
if(!ok) return false;
|
|
||||||
ud->data[j * n_cols + i] = *py_retval();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for(int i = 0; i < numel; i++) {
|
|
||||||
ud->data[i] = *default_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
py_assign(py_retval(), py_peek(-1));
|
|
||||||
py_pop();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool array2d_n_cols(int argc, py_Ref argv) {
|
|
||||||
PY_CHECK_ARGC(1);
|
PY_CHECK_ARGC(1);
|
||||||
c11_array2d* self = py_touserdata(argv);
|
c11_array2d_like* self = py_touserdata(argv);
|
||||||
py_newint(py_retval(), self->n_cols);
|
py_newint(py_retval(), self->n_cols);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool array2d_n_rows(int argc, py_Ref argv) {
|
static bool array2d_like_n_rows(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(1);
|
PY_CHECK_ARGC(1);
|
||||||
c11_array2d* self = py_touserdata(argv);
|
c11_array2d_like* self = py_touserdata(argv);
|
||||||
py_newint(py_retval(), self->n_rows);
|
py_newint(py_retval(), self->n_rows);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool array2d_numel(int argc, py_Ref argv) {
|
static bool array2d_like_shape(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(1);
|
PY_CHECK_ARGC(1);
|
||||||
c11_array2d* self = py_touserdata(argv);
|
c11_array2d_like* self = py_touserdata(argv);
|
||||||
|
c11_vec2i shape;
|
||||||
|
shape.x = self->n_cols;
|
||||||
|
shape.y = self->n_rows;
|
||||||
|
py_newvec2i(py_retval(), shape);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool array2d_like_numel(int argc, py_Ref argv) {
|
||||||
|
PY_CHECK_ARGC(1);
|
||||||
|
c11_array2d_like* self = py_touserdata(argv);
|
||||||
py_newint(py_retval(), self->numel);
|
py_newint(py_retval(), self->numel);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool array2d_is_valid(int argc, py_Ref argv) {
|
static bool array2d_like_is_valid(int argc, py_Ref argv) {
|
||||||
c11_array2d* self = py_touserdata(argv);
|
c11_array2d_like* self = py_touserdata(argv);
|
||||||
int col, row;
|
int col, row;
|
||||||
if(argc == 2) {
|
if(argc == 2) {
|
||||||
PY_CHECK_ARG_TYPE(1, tp_vec2i);
|
PY_CHECK_ARG_TYPE(1, tp_vec2i);
|
||||||
@ -95,15 +72,15 @@ static bool array2d_is_valid(int argc, py_Ref argv) {
|
|||||||
} else {
|
} else {
|
||||||
return TypeError("is_valid() expected 2 or 3 arguments");
|
return TypeError("is_valid() expected 2 or 3 arguments");
|
||||||
}
|
}
|
||||||
py_newbool(py_retval(), py_array2d_is_valid(self, col, row));
|
py_newbool(py_retval(), c11_array2d_like_is_valid(self, col, row));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool array2d_get(int argc, py_Ref argv) {
|
static bool array2d_like_get(int argc, py_Ref argv) {
|
||||||
py_Ref default_;
|
|
||||||
c11_array2d* self = py_touserdata(argv);
|
|
||||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||||
PY_CHECK_ARG_TYPE(2, tp_int);
|
PY_CHECK_ARG_TYPE(2, tp_int);
|
||||||
|
py_Ref default_;
|
||||||
|
c11_array2d_like* self = py_touserdata(argv);
|
||||||
if(argc == 3) {
|
if(argc == 3) {
|
||||||
default_ = py_None();
|
default_ = py_None();
|
||||||
} else if(argc == 4) {
|
} else if(argc == 4) {
|
||||||
@ -113,14 +90,169 @@ static bool array2d_get(int argc, py_Ref argv) {
|
|||||||
}
|
}
|
||||||
int col = py_toint(py_arg(1));
|
int col = py_toint(py_arg(1));
|
||||||
int row = py_toint(py_arg(2));
|
int row = py_toint(py_arg(2));
|
||||||
if(py_array2d_is_valid(self, col, row)) {
|
if(c11_array2d_like_is_valid(self, col, row)) {
|
||||||
py_assign(py_retval(), py_array2d__get(self, col, row));
|
py_assign(py_retval(), self->f_get(self, col, row));
|
||||||
} else {
|
} else {
|
||||||
py_assign(py_retval(), default_);
|
py_assign(py_retval(), default_);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool array2d_like_render(int argc, py_Ref argv) {
|
||||||
|
PY_CHECK_ARGC(1);
|
||||||
|
c11_sbuf buf;
|
||||||
|
c11_sbuf__ctor(&buf);
|
||||||
|
c11_array2d_like* self = py_touserdata(argv);
|
||||||
|
for(int j = 0; j < self->n_rows; j++) {
|
||||||
|
for(int i = 0; i < self->n_cols; i++) {
|
||||||
|
py_Ref item = self->f_get(self, i, j);
|
||||||
|
if(!py_str(item)) return false;
|
||||||
|
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
|
||||||
|
}
|
||||||
|
if(j < self->n_rows - 1) c11_sbuf__write_char(&buf, '\n');
|
||||||
|
}
|
||||||
|
c11_sbuf__py_submit(&buf, py_retval());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool array2d_like_all(int argc, py_Ref argv) {
|
||||||
|
PY_CHECK_ARGC(1);
|
||||||
|
c11_array2d_like* self = py_touserdata(argv);
|
||||||
|
for(int j = 0; j < self->n_rows; j++) {
|
||||||
|
for(int i = 0; i < self->n_cols; i++) {
|
||||||
|
py_Ref item = self->f_get(self, i, j);
|
||||||
|
if(!py_checkbool(item)) return false;
|
||||||
|
if(!py_tobool(item)) {
|
||||||
|
py_newbool(py_retval(), false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
py_newbool(py_retval(), true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool array2d_like_any(int argc, py_Ref argv) {
|
||||||
|
PY_CHECK_ARGC(1);
|
||||||
|
c11_array2d_like* self = py_touserdata(argv);
|
||||||
|
for(int j = 0; j < self->n_rows; j++) {
|
||||||
|
for(int i = 0; i < self->n_cols; i++) {
|
||||||
|
py_Ref item = self->f_get(self, i, j);
|
||||||
|
if(!py_checkbool(item)) return false;
|
||||||
|
if(py_tobool(item)) {
|
||||||
|
py_newbool(py_retval(), true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
py_newbool(py_retval(), false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool array2d_like_map(int argc, py_Ref argv) {
|
||||||
|
// def map(self, f: Callable[[T], Any]) -> 'array2d': ...
|
||||||
|
PY_CHECK_ARGC(2);
|
||||||
|
c11_array2d_like* self = py_touserdata(argv);
|
||||||
|
py_Ref f = py_arg(1);
|
||||||
|
c11_array2d* res = py_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||||
|
for(int j = 0; j < self->n_rows; j++) {
|
||||||
|
for(int i = 0; i < self->n_cols; i++) {
|
||||||
|
py_Ref item = self->f_get(self, i, j);
|
||||||
|
if(!py_call(f, 1, item)) return false;
|
||||||
|
res->data[j * self->n_cols + i] = *py_retval();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
py_assign(py_retval(), py_peek(-1));
|
||||||
|
py_pop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool array2d_like_copy(int argc, py_Ref argv) {
|
||||||
|
// def copy(self) -> 'array2d': ...
|
||||||
|
PY_CHECK_ARGC(1);
|
||||||
|
c11_array2d_like* self = py_touserdata(argv);
|
||||||
|
c11_array2d* res = py_newarray2d(py_retval(), self->n_cols, self->n_rows);
|
||||||
|
for(int j = 0; j < self->n_rows; j++) {
|
||||||
|
for(int i = 0; i < self->n_cols; i++) {
|
||||||
|
py_Ref item = self->f_get(self, i, j);
|
||||||
|
res->data[j * self->n_cols + i] = *item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool array2d_like_apply(int argc, py_Ref argv) {
|
||||||
|
// def apply_(self, f: Callable[[T], T]) -> None: ...
|
||||||
|
PY_CHECK_ARGC(2);
|
||||||
|
c11_array2d_like* self = py_touserdata(argv);
|
||||||
|
py_Ref f = py_arg(1);
|
||||||
|
for(int j = 0; j < self->n_rows; j++) {
|
||||||
|
for(int i = 0; i < self->n_cols; i++) {
|
||||||
|
py_Ref item = self->f_get(self, i, j);
|
||||||
|
if(!py_call(f, 1, item)) return false;
|
||||||
|
bool ok = self->f_set(self, i, j, py_retval());
|
||||||
|
if(!ok) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
py_newnone(py_retval());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pk__register_array2d_like(py_Ref mod) {
|
||||||
|
py_Type type = py_newtype("array2d_like", tp_object, mod, NULL);
|
||||||
|
|
||||||
|
py_bindproperty(type, "n_cols", array2d_like_n_cols, NULL);
|
||||||
|
py_bindproperty(type, "n_rows", array2d_like_n_rows, NULL);
|
||||||
|
py_bindproperty(type, "width", array2d_like_n_cols, NULL);
|
||||||
|
py_bindproperty(type, "height", array2d_like_n_rows, NULL);
|
||||||
|
py_bindproperty(type, "shape", array2d_like_shape, NULL);
|
||||||
|
py_bindproperty(type, "numel", array2d_like_numel, NULL);
|
||||||
|
|
||||||
|
py_bindmethod(type, "is_valid", array2d_like_is_valid);
|
||||||
|
py_bindmethod(type, "get", array2d_like_get);
|
||||||
|
|
||||||
|
py_bindmethod(type, "render", array2d_like_render);
|
||||||
|
|
||||||
|
py_bindmethod(type, "all", array2d_like_all);
|
||||||
|
py_bindmethod(type, "any", array2d_like_any);
|
||||||
|
|
||||||
|
py_bindmethod(type, "map", array2d_like_map);
|
||||||
|
py_bindmethod(type, "apply", array2d_like_apply);
|
||||||
|
py_bindmethod(type, "copy", array2d_like_copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool array2d__new__(int argc, py_Ref argv) {
|
||||||
|
// __new__(cls, n_cols: int, n_rows: int, default: Callable[[vec2i], T] = None)
|
||||||
|
py_Ref default_ = py_arg(3);
|
||||||
|
PY_CHECK_ARG_TYPE(0, tp_type);
|
||||||
|
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||||
|
PY_CHECK_ARG_TYPE(2, tp_int);
|
||||||
|
int n_cols = argv[1]._i64;
|
||||||
|
int n_rows = argv[2]._i64;
|
||||||
|
if(n_cols <= 0 || n_rows <= 0) return ValueError("array2d() expected positive dimensions");
|
||||||
|
c11_array2d* ud = py_newarray2d(py_pushtmp(), n_cols, n_rows);
|
||||||
|
// setup initial values
|
||||||
|
if(py_callable(default_)) {
|
||||||
|
for(int j = 0; j < n_rows; j++) {
|
||||||
|
for(int i = 0; i < n_cols; i++) {
|
||||||
|
py_TValue tmp;
|
||||||
|
py_newvec2i(&tmp, (c11_vec2i){{i, j}});
|
||||||
|
if(!py_call(default_, 1, &tmp)) return false;
|
||||||
|
ud->data[j * n_cols + i] = *py_retval();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < ud->header.numel; i++) {
|
||||||
|
ud->data[i] = *default_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
py_assign(py_retval(), py_peek(-1));
|
||||||
|
py_pop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool _array2d_check_all_type(c11_array2d* self, py_Type type) {
|
static bool _array2d_check_all_type(c11_array2d* self, py_Type type) {
|
||||||
for(int i = 0; i < self->numel; i++) {
|
for(int i = 0; i < self->numel; i++) {
|
||||||
py_Type item_type = self->data[i].type;
|
py_Type item_type = self->data[i].type;
|
||||||
@ -144,33 +276,7 @@ static bool _array2d_check_same_shape(c11_array2d* self, c11_array2d* other) {
|
|||||||
return _check_same_shape(self->n_cols, self->n_rows, other->n_cols, other->n_rows);
|
return _check_same_shape(self->n_cols, self->n_rows, other->n_cols, other->n_rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool array2d_all(int argc, py_Ref argv) {
|
|
||||||
PY_CHECK_ARGC(1);
|
|
||||||
c11_array2d* self = py_touserdata(argv);
|
|
||||||
if(!_array2d_check_all_type(self, tp_bool)) return false;
|
|
||||||
for(int i = 0; i < self->numel; i++) {
|
|
||||||
if(!py_tobool(self->data + i)) {
|
|
||||||
py_newbool(py_retval(), false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
py_newbool(py_retval(), true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool array2d_any(int argc, py_Ref argv) {
|
|
||||||
PY_CHECK_ARGC(1);
|
|
||||||
c11_array2d* self = py_touserdata(argv);
|
|
||||||
if(!_array2d_check_all_type(self, tp_bool)) return false;
|
|
||||||
for(int i = 0; i < self->numel; i++) {
|
|
||||||
if(py_tobool(self->data + i)) {
|
|
||||||
py_newbool(py_retval(), true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
py_newbool(py_retval(), false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool array2d__eq__(int argc, py_Ref argv) {
|
static bool array2d__eq__(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(2);
|
PY_CHECK_ARGC(2);
|
||||||
@ -247,80 +353,6 @@ static bool array2d_iterator__next__(int argc, py_Ref argv) {
|
|||||||
return StopIteration();
|
return StopIteration();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool array2d_map(int argc, py_Ref argv) {
|
|
||||||
// def map(self, f: Callable[[T], Any]) -> 'array2d': ...
|
|
||||||
PY_CHECK_ARGC(2);
|
|
||||||
c11_array2d* self = py_touserdata(argv);
|
|
||||||
py_Ref f = py_arg(1);
|
|
||||||
c11_array2d* res = py_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
|
||||||
for(int i = 0; i < self->numel; i++) {
|
|
||||||
bool ok = py_call(f, 1, self->data + i);
|
|
||||||
if(!ok) return false;
|
|
||||||
res->data[i] = *py_retval();
|
|
||||||
}
|
|
||||||
py_assign(py_retval(), py_peek(-1));
|
|
||||||
py_pop();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool array2d_copy(int argc, py_Ref argv) {
|
|
||||||
// def copy(self) -> 'array2d': ...
|
|
||||||
PY_CHECK_ARGC(1);
|
|
||||||
c11_array2d* self = py_touserdata(argv);
|
|
||||||
c11_array2d* res = py_newarray2d(py_retval(), self->n_cols, self->n_rows);
|
|
||||||
memcpy(res->data, self->data, self->numel * sizeof(py_TValue));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool array2d_fill_(int argc, py_Ref argv) {
|
|
||||||
// def fill_(self, value: T) -> None: ...
|
|
||||||
PY_CHECK_ARGC(2);
|
|
||||||
c11_array2d* self = py_touserdata(argv);
|
|
||||||
for(int i = 0; i < self->numel; i++)
|
|
||||||
self->data[i] = argv[1];
|
|
||||||
py_newnone(py_retval());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool array2d_apply_(int argc, py_Ref argv) {
|
|
||||||
// def apply_(self, f: Callable[[T], T]) -> None: ...
|
|
||||||
PY_CHECK_ARGC(2);
|
|
||||||
c11_array2d* self = py_touserdata(argv);
|
|
||||||
py_Ref f = py_arg(1);
|
|
||||||
for(int i = 0; i < self->numel; i++) {
|
|
||||||
bool ok = py_call(f, 1, self->data + i);
|
|
||||||
if(!ok) return false;
|
|
||||||
self->data[i] = *py_retval();
|
|
||||||
}
|
|
||||||
py_newnone(py_retval());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool array2d_copy_(int argc, py_Ref argv) {
|
|
||||||
// def copy_(self, src: 'array2d') -> None: ...
|
|
||||||
PY_CHECK_ARGC(2);
|
|
||||||
c11_array2d* self = py_touserdata(argv);
|
|
||||||
|
|
||||||
py_Type src_type = py_typeof(py_arg(1));
|
|
||||||
if(src_type == tp_array2d) {
|
|
||||||
c11_array2d* src = py_touserdata(py_arg(1));
|
|
||||||
if(!_array2d_check_same_shape(self, src)) return false;
|
|
||||||
memcpy(self->data, src->data, self->numel * sizeof(py_TValue));
|
|
||||||
} else {
|
|
||||||
py_TValue* data;
|
|
||||||
int length = pk_arrayview(py_arg(1), &data);
|
|
||||||
if(length != -1) {
|
|
||||||
if(self->numel != length) {
|
|
||||||
return ValueError("copy_() expected the same numel: %d != %d", self->numel, length);
|
|
||||||
}
|
|
||||||
memcpy(self->data, data, self->numel * sizeof(py_TValue));
|
|
||||||
} else {
|
|
||||||
return TypeError("copy_() expected `array2d`, `list` or `tuple`, got '%t", src_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
py_newnone(py_retval());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fromlist(data: list[list[T]]) -> array2d[T]
|
// fromlist(data: list[list[T]]) -> array2d[T]
|
||||||
static bool array2d_fromlist_STATIC(int argc, py_Ref argv) {
|
static bool array2d_fromlist_STATIC(int argc, py_Ref argv) {
|
||||||
@ -365,22 +397,7 @@ static bool array2d_tolist(int argc, py_Ref argv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool array2d_render(int argc, py_Ref argv) {
|
|
||||||
PY_CHECK_ARGC(1);
|
|
||||||
c11_sbuf buf;
|
|
||||||
c11_sbuf__ctor(&buf);
|
|
||||||
c11_array2d* self = py_touserdata(argv);
|
|
||||||
for(int j = 0; j < self->n_rows; j++) {
|
|
||||||
for(int i = 0; i < self->n_cols; i++) {
|
|
||||||
py_Ref item = py_array2d__get(self, i, j);
|
|
||||||
if(!py_str(item)) return false;
|
|
||||||
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
|
|
||||||
}
|
|
||||||
if(j < self->n_rows - 1) c11_sbuf__write_char(&buf, '\n');
|
|
||||||
}
|
|
||||||
c11_sbuf__py_submit(&buf, py_retval());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// count(self, value: T) -> int
|
// count(self, value: T) -> int
|
||||||
static bool array2d_count(int argc, py_Ref argv) {
|
static bool array2d_count(int argc, py_Ref argv) {
|
||||||
@ -696,12 +713,6 @@ void pk__add_module_array2d() {
|
|||||||
py_bindmagic(array2d, __getitem__, array2d__getitem__);
|
py_bindmagic(array2d, __getitem__, array2d__getitem__);
|
||||||
py_bindmagic(array2d, __setitem__, array2d__setitem__);
|
py_bindmagic(array2d, __setitem__, array2d__setitem__);
|
||||||
|
|
||||||
py_bindproperty(array2d, "n_cols", array2d_n_cols, NULL);
|
|
||||||
py_bindproperty(array2d, "n_rows", array2d_n_rows, NULL);
|
|
||||||
py_bindproperty(array2d, "width", array2d_n_cols, NULL);
|
|
||||||
py_bindproperty(array2d, "height", array2d_n_rows, NULL);
|
|
||||||
py_bindproperty(array2d, "numel", array2d_numel, NULL);
|
|
||||||
|
|
||||||
py_bindmethod(array2d, "is_valid", array2d_is_valid);
|
py_bindmethod(array2d, "is_valid", array2d_is_valid);
|
||||||
py_bindmethod(array2d, "get", array2d_get);
|
py_bindmethod(array2d, "get", array2d_get);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user