Skip to content

Commit dd9c0cc

Browse files
Merge pull request #40 from NumPower/feat/update_package_1
N-dimensional slicing and element-wise iterator
2 parents c1d8c4a + c9ba0d3 commit dd9c0cc

File tree

10 files changed

+348
-148
lines changed

10 files changed

+348
-148
lines changed

src/indexing.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,62 @@ NDArray_Diagonal(NDArray *target, int offset) {
4444
#endif
4545
return rtn;
4646
}
47+
48+
/**
49+
* @param r
50+
* @param length
51+
* @param start
52+
* @param stop
53+
* @param step
54+
* @param slicelength
55+
* @return
56+
*/
57+
int
58+
Slice_GetIndices(SliceObject *r, int length, int *start, int *stop, int *step, int *slicelength)
59+
{
60+
int defstop;
61+
62+
if (r->step == NULL) {
63+
*step = 1;
64+
} else {
65+
*step = r->step[0];
66+
if (*step == 0) {
67+
zend_throw_error(NULL,
68+
"slice step cannot be zero");
69+
return -1;
70+
}
71+
}
72+
73+
defstop = *step < 0 ? -1 : length;
74+
75+
if (r->start == NULL) {
76+
*start = *step < 0 ? length-1 : 0;
77+
} else {
78+
*start = *(r->start);
79+
if (*start < 0) *start += length;
80+
if (*start < 0) *start = (*step < 0) ? -1 : 0;
81+
if (*start >= length) {
82+
*start = (*step < 0) ? length - 1 : length;
83+
}
84+
}
85+
86+
if (r->stop == NULL) {
87+
*stop = defstop;
88+
} else {
89+
*stop = r->stop[0];
90+
if (*stop < 0) *stop += length;
91+
if (*stop < 0) *stop = -1;
92+
if (*stop > length) *stop = length;
93+
}
94+
95+
if ((*step < 0 && *stop >= *start) || \
96+
(*step > 0 && *start >= *stop)) {
97+
*slicelength = 0;
98+
} else if (*step < 0) {
99+
*slicelength = (*stop - *start + 1) / (*step) + 1;
100+
} else {
101+
*slicelength = (*stop - *start - 1) / (*step) + 1;
102+
}
103+
104+
return 0;
105+
}

src/indexing.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,12 @@
33

44
#include "ndarray.h"
55

6+
typedef struct {
7+
int *start;
8+
int *stop;
9+
int *step;
10+
} SliceObject;
11+
612
NDArray* NDArray_Diagonal(NDArray *target, int offset);
13+
int Slice_GetIndices(SliceObject *r, int length, int *start, int *stop, int *step, int *slicelength);
714
#endif //PHPSCI_NDARRAY_INDEXING_H

src/initializers.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,6 @@ NDArray* Create_NDArray_FromZval(zval* php_object) {
249249
*/
250250
NDArray*
251251
Create_NDArray(int* shape, int ndim, const char* type, const int device) {
252-
char* new_buffer;
253252
NDArray* rtn;
254253
NDArrayDescriptor* descriptor;
255254
int type_size = get_type_size(type);
@@ -281,6 +280,42 @@ Create_NDArray(int* shape, int ndim, const char* type, const int device) {
281280
return rtn;
282281
}
283282

283+
/**
284+
* Create an NDArray View from another NDArray with
285+
* a custom data pointer
286+
*
287+
* @param target
288+
* @param buffer_offset
289+
* @param shape
290+
* @param strides
291+
* @param ndim
292+
* @return
293+
*/
294+
NDArray*
295+
NDArray_FromNDArrayBase(NDArray *target, char *data_ptr, int* shape, int* strides, const int ndim) {
296+
NDArray* rtn = emalloc(sizeof(NDArray));
297+
int total_num_elements = 1;
298+
299+
rtn->strides = strides;
300+
rtn->dimensions = shape;
301+
302+
// Calculate number of elements
303+
for (int i = 0; i < ndim; i++) {
304+
total_num_elements = total_num_elements * NDArray_SHAPE(rtn)[i];
305+
}
306+
307+
rtn->flags = 0;
308+
rtn->data = data_ptr;
309+
rtn->base = target;
310+
rtn->ndim = ndim;
311+
rtn->refcount = 1;
312+
rtn->device = NDArray_DEVICE(target);
313+
rtn->descriptor = Create_Descriptor(total_num_elements, sizeof(float), NDARRAY_TYPE_FLOAT32);
314+
NDArrayIterator_INIT(rtn);
315+
NDArray_ADDREF(target);
316+
return rtn;
317+
}
318+
284319
/**
285320
* Create an NDArray View from another NDArray
286321
*

src/initializers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ NDArray* NDArray_Arange(double start, double stop, double step);
2626
NDArray* NDArray_Binomial(int *shape, int ndim, int n, float p);
2727
NDArray* NDArray_EmptyLike(NDArray *a);
2828
NDArray* NDArray_Create(char *data, int ndim, int *shape, int device, const char* type);
29+
NDArray* NDArray_FromNDArrayBase(NDArray *target, char *data_ptr, int* shape, int* strides, const int ndim);
2930
#ifdef __cplusplus
3031
extern "C" {
3132
#endif

src/iterators.c

Lines changed: 26 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -121,57 +121,35 @@ NDArrayIterator_FREE(NDArray* array) {
121121
}
122122
}
123123

124-
/**
125-
* Initialize Axis Iterator
126-
*
127-
* @param array
128-
* @return
129-
*/
130-
NDArrayAxisIterator*
131-
NDArrayAxisIterator_INIT(NDArray *array, int axis) {
132-
NDArrayAxisIterator *it;
133-
it = emalloc(sizeof(NDArrayAxisIterator));
134-
it->array = array;
135-
it->axis = axis;
136-
it->current_index = 0;
137-
return it;
138-
}
139-
140-
int
141-
NDArrayAxisIterator_ISDONE(NDArrayAxisIterator *it) {
142-
if (it->current_index < NDArray_SHAPE(it->array)[it->axis]) {
143-
return 0;
124+
NDArrayIter*
125+
NDArray_NewElementWiseIter(NDArray *target) {
126+
NDArrayIter *it;
127+
int i, nd;
128+
NDArray *ao = target;
129+
130+
it = emalloc(sizeof(NDArrayIter));
131+
if (it == NULL) {
132+
return NULL;
144133
}
145-
return 1;
146-
}
147-
148-
void
149-
NDArrayAxisIterator_REWIND(NDArrayAxisIterator *it) {
150-
it->current_index = 0;
151-
}
152-
153-
void
154-
NDArrayAxisIterator_NEXT(NDArrayAxisIterator *it) {
155-
it->current_index = it->current_index + 1;
156-
}
157134

158-
NDArray*
159-
NDArrayAxisIterator_GET(NDArrayAxisIterator *it) {
160-
int new_ndim = NDArray_NDIM(it->array) - 1;
161-
int *new_shape = emalloc(sizeof(int) * (NDArray_NDIM(it->array) - 1));
162-
int *new_strides = emalloc(sizeof(int) * (NDArray_NDIM(it->array) - 1));
163-
if ((NDArray_NDIM(it->array) - 1) > 0) {
164-
for(int i = 0; i < (NDArray_NDIM(it->array) - 1); i++) {
165-
new_shape[i] = NDArray_SHAPE(it->array)[i + 1];
166-
new_strides[i] = NDArray_STRIDES(it->array)[(NDArray_NDIM(it->array) - 1) - i];
167-
new_strides[0] = NDArray_STRIDES(it->array)[it->axis];
135+
nd = NDArray_NDIM(ao);
136+
it->contiguous = 1;
137+
if (NDArray_CHKFLAGS(target, NDARRAY_ARRAY_F_CONTIGUOUS)) {
138+
it->contiguous = 0;
139+
}
140+
it->ao = ao;
141+
it->size = NDArray_NUMELEMENTS(ao);
142+
it->nd_m1 = nd - 1;
143+
it->factors[nd-1] = 1;
144+
for (i = 0; i < nd; i++) {
145+
it->dims_m1[i] = NDArray_SHAPE(it->ao)[i] - 1;
146+
it->strides[i] = NDArray_STRIDES(it->ao)[i];
147+
it->backstrides[i] = it->strides[i] * it->dims_m1[i];
148+
if (i > 0) {
149+
it->factors[nd-i-1] = it->factors[nd-i] * it->ao->dimensions[nd-i];
168150
}
169151
}
170-
return NDArray_FromNDArray(it->array, it->current_index * NDArray_STRIDES(it->array)[it->axis + 1], new_shape, new_strides,
171-
&new_ndim);
152+
NDArray_ITER_RESET(it);
153+
return it;
172154
}
173155

174-
void
175-
NDArrayAxisIterator_FREE(NDArrayAxisIterator *it) {
176-
efree(it);
177-
}

src/iterators.h

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,21 @@
33

44
#include "ndarray.h"
55

6-
typedef struct NDArrayAxisIterator {
7-
int current_index;
8-
NDArray* array;
9-
int axis;
10-
} NDArrayAxisIterator;
6+
typedef struct NDArrayIter {
7+
int nd_m1; /* number of dimensions - 1 */
8+
int index, size;
9+
int coordinates[NDARRAY_MAX_DIMS];/* N-dimensional loop */
10+
int dims_m1[NDARRAY_MAX_DIMS]; /* ao->dimensions - 1 */
11+
int strides[NDARRAY_MAX_DIMS]; /* ao->strides or fake */
12+
int backstrides[NDARRAY_MAX_DIMS];/* how far to jump back */
13+
int factors[NDARRAY_MAX_DIMS]; /* shape factors */
14+
NDArray *ao;
15+
char *dataptr; /* pointer to current item*/
16+
bool contiguous;
17+
int bounds[NDARRAY_MAX_DIMS][2];
18+
int limits[NDARRAY_MAX_DIMS][2];
19+
int limits_sizes[NDARRAY_MAX_DIMS];
20+
} NDArrayIter;
1121

1222
NDArray* NDArrayIterator_GET(NDArray* array);
1323
void NDArrayIterator_INIT(NDArray* array);
@@ -21,10 +31,60 @@ void NDArrayIteratorPHP_REWIND(NDArray* array);
2131
int NDArrayIteratorPHP_ISDONE(NDArray* array);
2232
void NDArrayIteratorPHP_NEXT(NDArray* array);
2333

24-
NDArray* NDArrayAxisIterator_GET(NDArrayAxisIterator *it);
25-
void NDArrayAxisIterator_NEXT(NDArrayAxisIterator *it);
26-
void NDArrayAxisIterator_FREE(NDArrayAxisIterator *it);
27-
void NDArrayAxisIterator_REWIND(NDArrayAxisIterator *it);
28-
int NDArrayAxisIterator_ISDONE(NDArrayAxisIterator *it);
29-
NDArrayAxisIterator* NDArrayAxisIterator_INIT(NDArray *array, int axis);
34+
NDArrayIter* NDArray_NewElementWiseIter(NDArray *target);
35+
36+
#define _NDArray_ITER_NEXT1(it) do { \
37+
(it)->dataptr += (it)->strides[0]; \
38+
(it)->coordinates[0]++; \
39+
} while (0)
40+
41+
#define _NDArray_ITER_NEXT2(it) do { \
42+
if ((it)->coordinates[1] < (it)->dims_m1[1]) { \
43+
(it)->coordinates[1]++; \
44+
(it)->dataptr += (it)->strides[1]; \
45+
} \
46+
else { \
47+
(it)->coordinates[1] = 0; \
48+
(it)->coordinates[0]++; \
49+
(it)->dataptr += (it)->strides[0] - \
50+
(it)->backstrides[1]; \
51+
} \
52+
} while (0)
53+
54+
#define NDArray_ITER_RESET(it) do { \
55+
(it)->index = 0; \
56+
(it)->dataptr = NDArray_DATA((it)->ao); \
57+
memset((it)->coordinates, 0, \
58+
((it)->nd_m1+1)*sizeof(int)); \
59+
} while (0)
60+
61+
#define NDArray_ITER_NEXT(it) do { \
62+
(it)->index++; \
63+
if ((it)->nd_m1 == 0) { \
64+
_NDArray_ITER_NEXT1((it)); \
65+
} \
66+
else if ((it)->contiguous) \
67+
(it)->dataptr += NDArray_DESCRIPTOR((it)->ao)->elsize; \
68+
else if ((it)->nd_m1 == 1) { \
69+
_NDArray_ITER_NEXT2(it); \
70+
} \
71+
else { \
72+
int __nd_i; \
73+
for (__nd_i=(it)->nd_m1; __nd_i >= 0; __nd_i--) { \
74+
if ((it)->coordinates[__nd_i] < \
75+
(it)->dims_m1[__nd_i]) { \
76+
(it)->coordinates[__nd_i]++; \
77+
(it)->dataptr += \
78+
(it)->strides[__nd_i]; \
79+
break; \
80+
} \
81+
else { \
82+
(it)->coordinates[__nd_i] = 0; \
83+
(it)->dataptr -= \
84+
(it)->backstrides[__nd_i]; \
85+
} \
86+
} \
87+
} \
88+
} while (0)
89+
#define NDArray_ITER_DATA(it) ((void *)((it)->dataptr))
3090
#endif //PHPSCI_NDARRAY_ITERATORS_H

0 commit comments

Comments
 (0)