-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathspndreduce.c
More file actions
111 lines (103 loc) · 2.79 KB
/
spndreduce.c
File metadata and controls
111 lines (103 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "spndarray.h"
#include <math.h>
#include <stdlib.h>
#include "avl.c"
double reduce_sum(double acc, double x, int count) {
(void)count;
return acc + x;
}
double reduce_mean(double acc, double x, int count) {
return acc + (x / count);
}
/*
* spndarray_reduce()
* Reduce a dimension by applying a reduction function over it
*
* Inputs
* dim - which dimension to reduce over
* reduce_fn - the function with which to reduce
*
* Output
* the new reduced spndarray.
*/
spndarray *spndarray_reduce(spndarray *m, const size_t dim,
const reduction_function reduce_fn) {
if (!SPNDARRAY_ISNTUPLE(m)) {
fprintf(stderr, "array must be in the ntuple format");
return NULL;
}
// allocate a new spndarray that is missing the given dimension
size_t mndim = m->ndim, ndim = mndim - 1; // remove one
size_t dims[ndim], tidx[ndim];
size_t counters[mndim];
memset(counters, 0, sizeof(counters));
memset(tidx, 0, sizeof(tidx));
size_t lastdimsize = m->dimsizes[ndim];
for (size_t i = 0, j = 0; i < mndim; i++, j++) {
if (i != dim) {
dims[j] = m->dimsizes[i];
} else
j--;
}
size_t rdimsize = m->dimsizes[dim];
spndarray *newm =
spndarray_alloc_nzmax(ndim, dims, m->nzmax, SPNDARRAY_NTUPLE);
while (counters[ndim] < lastdimsize) {
size_t i;
/*
* pidx <- (i, j, k, ...)
* x <- get(m, pidx)
* tidx <- drop(pidx, dim)
* pacc <- ptr(newm, tidx, 0)
* *pacc <- reduce_fn(*pacc, x, rdimsize);
*/
double x = spndarray_get(m, counters);
if (x == 0.0)
goto next;
double *pacc = spndarray_ptr(newm, tidx);
if (!pacc) {
spndarray_set(newm, reduce_fn(0, x, rdimsize), tidx);
goto next;
}
*pacc = reduce_fn(*pacc, x, rdimsize);
next:;
for (i = 0; counters[i] == m->dimsizes[i]; i++)
counters[i] = 0;
++counters[i];
size_t j;
for (i = 0, j = 0; i < mndim; i++, j++)
if (i == dim)
j--;
else
tidx[j] = counters[i];
}
return newm;
}
/*
* spndarray_reduce_dimension()
*
* reduces the values of a given dimension to only the given index in it
*
* Inputs
* dim - the dimension to reduce
* idx - the selected index
*/
spndarray *spndarray_reduce_dimension(spndarray *m, const size_t dim, const size_t idx) {
size_t newdims[m->ndim-1];
for (size_t t = 0; t < m->ndim-1; t++)
newdims[t] = 1;
spndarray *ex = spndarray_alloc_nzmax(m->ndim-1, newdims, m->nz * 0.3, SPNDARRAY_NTUPLE);
for (size_t x = 0; x < m->nz; x++) {
if (m->dims[dim][x] != idx)
continue;
double val = m->data[x];
for (size_t i = 0, j = 0; i < m->ndim; i++, j++) {
if (i != dim) {
newdims[j] = m->dims[i][x];
} else
j--;
}
spndarray_set(ex, val, newdims);
}
return ex;
}