Skip to content

Commit 99b798d

Browse files
committed
generalized cumsum and some unit tests for it
1 parent a0c5368 commit 99b798d

2 files changed

Lines changed: 89 additions & 1 deletion

File tree

lib/narray_ext.rb

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,52 @@ def randomn!
209209
end
210210

211211
#SFloatOne = NArray.sfloat(1).fill!(1)
212-
end
213212

213+
#
214+
# Cumulative sum along dimension +dim+; modifies this array in place.
215+
#
216+
# @param [Number] dim non-negative
217+
#
218+
# @return [NArray] self
219+
#
220+
def cumsum_general! dim=0
221+
if self.dim > dim
222+
if self.dim == 1
223+
# use the built-in version for dimension 1
224+
self.cumsum_1!
225+
else
226+
# for example, if this is a matrix and dim = 0, mask_0 selects the first
227+
# column of the matrix and mask_1 selects the second column; then we
228+
# just shuffle them along and accumulate.
229+
mask_0 = (0...self.dim).map{|d| d == dim ? 0 : true}
230+
mask_1 = (0...self.dim).map{|d| d == dim ? 1 : true}
231+
while mask_1[dim] < self.shape[dim]
232+
self[*mask_1] += self[*mask_0]
233+
mask_0[dim] += 1
234+
mask_1[dim] += 1
235+
end
236+
end
237+
end
238+
self
239+
end
240+
241+
#
242+
# Cumulative sum along dimension +dim+.
243+
#
244+
# @param [Number] dim non-negative
245+
#
246+
# @return [NArray] self
247+
#
248+
def cumsum_general dim=0
249+
self.dup.cumsum_general!(dim)
250+
end
251+
252+
# The built-in cumsum only does vectors (dim 1).
253+
alias cumsum_1 cumsum
254+
alias cumsum cumsum_general
255+
alias cumsum_1! cumsum!
256+
alias cumsum! cumsum_general!
257+
end
214258

215259
module NMath
216260
PI = Math::PI

test/testcumsum.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
require 'test/unit_tests'
2+
3+
class TestCumSum < Test::Unit::TestCase
4+
def test_narray_cumsum
5+
# Degenerate case: dimension 0.
6+
assert_equal NArray.float(0), NArray.float(0).cumsum
7+
assert_equal NArray.int(0), NArray.int(0).cumsum
8+
9+
# Single-element vector.
10+
v = NArray.float(1).fill!(42)
11+
assert_equal v, v.cumsum
12+
assert_equal v.typecode, v.cumsum.typecode
13+
v = NArray.int(1).fill!(42)
14+
assert_equal v, v.cumsum
15+
assert_equal v.typecode, v.cumsum.typecode
16+
17+
# Vector.
18+
v = NArray.float(2).indgen!
19+
assert_narray_close NArray[ 0.0, 1.0], v.cumsum
20+
v = NArray.float(3).indgen! + 1
21+
assert_narray_close NArray[ 1.0, 3.0, 6.0], v.cumsum
22+
assert_equal v, v.cumsum(1) # dim 1 doesn't exist; cumsum has no effect
23+
24+
# Matrix.
25+
m = NArray.float(3,2).indgen! + 1
26+
assert_narray_close NArray[[ 1.0, 3.0, 6.0],
27+
[ 4.0, 9.0, 15.0]], m.cumsum
28+
assert_narray_close NArray[[ 1.0, 2.0, 3.0],
29+
[ 5.0, 7.0, 9.0]], m.cumsum(1)
30+
assert_equal m, m.cumsum(2) # dim 2 doesn't exist; cumsum has no effect
31+
32+
# Array with dim 3 with one extra dim.
33+
d3 = NArray.int(3,2,1).indgen! - 1
34+
assert_equal NArray[[[ -1, -1, 0],
35+
[ 2, 5, 9]]], d3.cumsum(0)
36+
assert_equal NArray[[[ -1, 0, 1],
37+
[ 1, 3, 5]]], d3.cumsum(1)
38+
assert_equal NArray[[[ -1, 0, 1],
39+
[ 2, 3, 4]]], d3.cumsum(2)
40+
assert_equal NArray[[[ -1, 0, 1],
41+
[ 2, 3, 4]]], d3.cumsum(3) # dim 3 doesn't exist
42+
end
43+
end
44+

0 commit comments

Comments
 (0)