-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcumprod.py
49 lines (42 loc) · 1.29 KB
/
cumprod.py
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
import numpy
import cupy
import chainer
from chainer import cuda
from chainer import functions
from chainer import Variable
from prod import prod
def cumprod(x, axis=-1):
if not isinstance(x, Variable):
x = Variable(x)
if axis is None:
x = x.reshape(-1)
axis = 0
elif axis < 0:
axis = x.ndim + axis
assert axis >= 0 and axis < x.ndim
xp = cuda.get_array_module(x)
ndim = x.ndim
dims = x.shape[axis]
shape_new = x.shape[:axis] + (dims,) + x.shape[axis:]
x = functions.expand_dims(x, axis)
x = functions.broadcast_to(x, shape_new)
# TODO: use cupy.tril
mask = numpy.tril(numpy.ones((dims, dims), numpy.bool))
if xp is cupy:
mask = cuda.to_gpu(mask)
expander = [1] * axis + [dims, dims] + [1] * (ndim - axis - 1)
mask = mask.reshape(expander)
mask = xp.broadcast_to(mask, shape_new)
x = functions.where(mask, x, xp.ones_like(x.data))
return prod(x, axis + 1)
if __name__ == '__main__':
x = chainer.Variable(
numpy.arange(1, 1 + 2 * 3 * 4, dtype='f').reshape(2, 3, 4))
axis = -3
cp_np = numpy.cumprod(x.data, axis)
cp_f = cumprod(x, axis).data
print(x.data)
print(cp_np)
print(cp_f)
assert numpy.array_equal(cp_np, cp_f)
print(numpy.array_equal(cp_np, cp_f))