/
histArray_spec.lua
107 lines (96 loc) · 3.71 KB
/
histArray_spec.lua
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
local HistArray = require "util.histArray"
-- The HistArray module provides an array that automatically purges
-- old values. It lets you write code like:
--
-- y[n] = c1*x[n] + c2*x[n-1] + c3*x[n-2]
-- - c4*y[n-1] - c5*y[n-2]
--
-- If x and y are HistArrays created with history size 2, all samples from
-- x[n-3] and y[n-3] and below will be purged (accessing them is an error)
-- so that the no longer needed values do not waste any memory.
--
-- HistArray stands for history array.
--
-- FAQ: How does a HistArray know when to purge old values?
-- Answer: For all n, when y[n] is assigned to, y[n - (y.histSize+1)]
-- and below are purged. This allows most recurrence relations
-- (like the above) to be defined in a natural manner.
describe("a history array", function()
it("has a history size", function()
local y = HistArray.new(2)
assert.are.equal(2, y.histSize)
end)
it("holds as many values as its history size, plus one", function()
local y = HistArray.new(2)
y[1] = 0.1
y[2] = 0.2
y[3] = 0.3
y[4] = 0.4
assert.are.equal(0.4, y[4]) -- current value
assert.are.equal(0.3, y[3]) -- current minus 1
assert.are.equal(0.2, y[2]) -- current minus 2
assert.has_error(function() local _ = y[1] end) -- too old!
end)
it("starts with histSize+1 zeroes", function()
local y = HistArray.new(5)
assert.are.equal(0, y[0], y[-1], y[-2], y[-3], y[-4], y[-5])
assert.has_error(function() local _ = y[-6] end)
end)
it("returns its values as a table with the :all method", function()
local y = HistArray.new(3)
y[1] = 50
y[2] = 100
y[3] = 31337
assert.are.same({[3]=31337, [2]=100, [1]=50, [0]=0}, y:all())
end)
it("fills in zeroes if an index is skipped during assignment", function()
local y = HistArray.new(3)
y[1] = 1
y[2] = 2
-- Skip a few
y[5] = 5
assert.are.same({[5]=5, [4]=0, [3]=0, [2]=2}, y:all())
end)
it("won't let you assign out of order", function()
local y = HistArray.new(2)
y[1] = 1
y[3] = 3 -- This might be weird, but it's legit (see above).
assert.has_error(function()
y[2] = 2 -- This isn't legit. Can't assign 2 after 3.
end)
end)
it("won't let you reassign an index", function()
local y = HistArray.new(2)
y[1] = 1
assert.has_error(function()
y[1] = 0 -- Can't do, y[1] was already set.
end)
-- The reason for this behavior is to better match a recurrence
-- relation. Use a temp variable to calculate the value, *then*
-- put it into the HistArray.
end)
it("won't let you assign a nonpositive index, even to start", function()
assert.has_error(function()
local y = HistArray.new(2)
y[0] = 1
end, "attempt to set old index in HistArray")
assert.has_error(function()
local y = HistArray.new(2)
y[-50000] = 1
end, "attempt to set old index in HistArray")
end)
it("can handle really freakin' huge indices", function()
local y = HistArray.new(2)
y[15000] = 10
assert.are.same({[15000] = 10, [14999] = 0, [14998] = 0}, y:all())
-- NOTE: Lua uses doubles (64-bit) internally.
-- They can unambiguously represent integers up to 2^52
-- (about 4.5e+15). It's important to use an integer smaller than
-- that for this test.
local big = 123456789012345
y[big] = -100
big = big + 1
y[big] = 1
assert.are.same({[big] = 1, [big-1] = -100, [big-2] = 0}, y:all())
end)
end)