bitstring 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CONTRIBUTORS.txt +5 -0
- data/Changelog.txt +20 -0
- data/LICENCE.txt +202 -0
- data/NOTICE.txt +5 -0
- data/README.txt +63 -0
- data/doc/classes/BitString.html +2479 -0
- data/doc/classes/BitString.src/M000001.html +99 -0
- data/doc/classes/BitString.src/M000002.html +18 -0
- data/doc/classes/BitString.src/M000003.html +20 -0
- data/doc/classes/BitString.src/M000004.html +19 -0
- data/doc/classes/BitString.src/M000005.html +24 -0
- data/doc/classes/BitString.src/M000006.html +44 -0
- data/doc/classes/BitString.src/M000007.html +21 -0
- data/doc/classes/BitString.src/M000008.html +18 -0
- data/doc/classes/BitString.src/M000009.html +18 -0
- data/doc/classes/BitString.src/M000010.html +22 -0
- data/doc/classes/BitString.src/M000011.html +29 -0
- data/doc/classes/BitString.src/M000012.html +22 -0
- data/doc/classes/BitString.src/M000013.html +43 -0
- data/doc/classes/BitString.src/M000014.html +19 -0
- data/doc/classes/BitString.src/M000015.html +40 -0
- data/doc/classes/BitString.src/M000016.html +21 -0
- data/doc/classes/BitString.src/M000017.html +18 -0
- data/doc/classes/BitString.src/M000018.html +18 -0
- data/doc/classes/BitString.src/M000019.html +18 -0
- data/doc/classes/BitString.src/M000020.html +20 -0
- data/doc/classes/BitString.src/M000021.html +24 -0
- data/doc/classes/BitString.src/M000022.html +23 -0
- data/doc/classes/BitString.src/M000023.html +42 -0
- data/doc/classes/BitString.src/M000024.html +61 -0
- data/doc/classes/BitString.src/M000025.html +18 -0
- data/doc/classes/BitString.src/M000026.html +18 -0
- data/doc/classes/BitString.src/M000027.html +20 -0
- data/doc/classes/BitString.src/M000028.html +18 -0
- data/doc/classes/BitString.src/M000029.html +18 -0
- data/doc/classes/BitString.src/M000030.html +18 -0
- data/doc/classes/BitString.src/M000031.html +18 -0
- data/doc/classes/BitString.src/M000032.html +18 -0
- data/doc/created.rid +1 -0
- data/doc/files/lib/bitstring/operators_rb.html +122 -0
- data/doc/files/lib/bitstring_rb.html +153 -0
- data/doc/fr_class_index.html +27 -0
- data/doc/fr_file_index.html +28 -0
- data/doc/fr_method_index.html +60 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/bitstring.rb +1318 -0
- data/lib/bitstring/operators.rb +481 -0
- data/test/Rakefile +21 -0
- data/test/test_basic.rb +848 -0
- data/test/test_data.rb +24 -0
- data/test/test_enum.rb +671 -0
- data/test/test_helper.rb +3 -0
- data/test/test_operators.rb +454 -0
- metadata +121 -0
data/test/test_data.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
3
|
+
|
4
|
+
module Tests
|
5
|
+
|
6
|
+
class Test_BitStrings < Test::Unit::TestCase
|
7
|
+
|
8
|
+
TestVals = [
|
9
|
+
'00000000000001111111111111',
|
10
|
+
'00101001010100101010111001101101',
|
11
|
+
'1100111000111100001111100000',
|
12
|
+
'101100111000111100001111100000',
|
13
|
+
'101010101010101010101010101010',
|
14
|
+
'010101010101010101010101010101',
|
15
|
+
'0000000000000000000000000000',
|
16
|
+
'1111111111111111111111111111'
|
17
|
+
]
|
18
|
+
|
19
|
+
IfNoneCalled = 'IfNone invoked'
|
20
|
+
IfNone = lambda { return IfNoneCalled }
|
21
|
+
|
22
|
+
end # class Test_BitStrings
|
23
|
+
|
24
|
+
end # module Tests
|
data/test/test_enum.rb
ADDED
@@ -0,0 +1,671 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
3
|
+
require File.dirname(__FILE__) + '/test_data.rb'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Test the methods inherited from the Enumerable mixin.
|
7
|
+
#
|
8
|
+
|
9
|
+
module Tests
|
10
|
+
|
11
|
+
class Test_BitStrings < Test::Unit::TestCase
|
12
|
+
|
13
|
+
#
|
14
|
+
# The all? method returns true IFF every iteration of the block returns
|
15
|
+
# a true value.
|
16
|
+
#
|
17
|
+
def test_010_all?()
|
18
|
+
return unless (BitString.new.respond_to?(:all?))
|
19
|
+
TestVals.each do |sVal|
|
20
|
+
#
|
21
|
+
# Start with unbounded bitstrings.
|
22
|
+
#
|
23
|
+
bs = BitString.new(sVal)
|
24
|
+
assert(bs.all? { |v| true },
|
25
|
+
"Test unbounded '#{sVal}'.all? true == true")
|
26
|
+
assert(! bs.all? { |v| false },
|
27
|
+
"Test unbounded '#{sVal}'.all? false == false")
|
28
|
+
tick = 0
|
29
|
+
assert(! bs.all? { |v| ((tick += 1) % 2).zero? },
|
30
|
+
"Test unbounded '#{sVal}'.all? sometimes == false")
|
31
|
+
#
|
32
|
+
# Repeat for bounded strings.
|
33
|
+
#
|
34
|
+
bs = BitString.new(sVal, sVal.length)
|
35
|
+
assert(bs.all? { |v| true },
|
36
|
+
"Test bounded '#{sVal}'.all? true == true")
|
37
|
+
assert(! bs.all? { |v| false },
|
38
|
+
"Test bounded '#{sVal}'.all? false == false")
|
39
|
+
tick = 0
|
40
|
+
assert(! bs.all? { |v| ((tick += 1) % 2).zero? },
|
41
|
+
"Test bounded '#{sVal}'.all? sometimes == false")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Test that the any? method works. (Returns true if any iteration of
|
47
|
+
# the block does.)
|
48
|
+
#
|
49
|
+
def test_020_any?()
|
50
|
+
return unless (BitString.new.respond_to?(:any?))
|
51
|
+
TestVals.each do |sVal|
|
52
|
+
#
|
53
|
+
# Start with unbounded bitstrings.
|
54
|
+
#
|
55
|
+
bs = BitString.new(sVal)
|
56
|
+
assert(bs.any? { |v| true },
|
57
|
+
"Test unbounded '#{sVal}'.any? true == true")
|
58
|
+
assert(! bs.any? { |v| false },
|
59
|
+
"Test unbounded '#{sVal}'.any? false == false")
|
60
|
+
tick = 0
|
61
|
+
assert(bs.any? { |v| v == sVal[-1,1].to_i(2) },
|
62
|
+
"Test unbounded '#{sVal}'.any? sometimes == true")
|
63
|
+
#
|
64
|
+
# Repeat for bounded strings.
|
65
|
+
#
|
66
|
+
bs = BitString.new(sVal, sVal.length)
|
67
|
+
assert(bs.any? { |v| true },
|
68
|
+
"Test bounded '#{sVal}'.any? true == true")
|
69
|
+
assert(! bs.any? { |v| false },
|
70
|
+
"Test bounded '#{sVal}'.any? false == false")
|
71
|
+
tick = 0
|
72
|
+
assert(bs.any? { |v| v == sVal[-1,1].to_i(2) },
|
73
|
+
"Test bounded '#{sVal}'.any? sometimes == true")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_030_collect()
|
78
|
+
return unless (BitString.new.respond_to?(:collect))
|
79
|
+
TestVals.each do |sVal|
|
80
|
+
#
|
81
|
+
# Unbounded first.
|
82
|
+
#
|
83
|
+
bs = BitString.new(sVal)
|
84
|
+
tVal = sVal.sub(/^0+(.)/, '\1').reverse
|
85
|
+
assert_equal(tVal.split(//),
|
86
|
+
bs.collect { |v| v.to_s(2) },
|
87
|
+
"Test that unbounded '#{sVal}'.collect works")
|
88
|
+
#
|
89
|
+
# Now bounded..
|
90
|
+
#
|
91
|
+
bs = BitString.new(sVal, sVal.length)
|
92
|
+
tVal = sVal.reverse
|
93
|
+
assert_equal(tVal.split(//),
|
94
|
+
bs.collect { |v| v.to_s(2) },
|
95
|
+
"Test that bounded '#{sVal}'.collect works")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# Returns the first value for which the block doesn't return false.
|
101
|
+
# If all iterations return false, .detect() calls the proc specified
|
102
|
+
# by the ifnone argument and returns its result; otherwise it returns
|
103
|
+
# nil.
|
104
|
+
#
|
105
|
+
def test_040_detect()
|
106
|
+
return unless (BitString.new.respond_to?(:detect))
|
107
|
+
TestVals.each do |sVal|
|
108
|
+
#
|
109
|
+
# Start with unbounded bitstrings.
|
110
|
+
#
|
111
|
+
bs = BitString.new(sVal)
|
112
|
+
assert_equal(sVal[-1,1].to_i(2),
|
113
|
+
bs.detect { |v| true },
|
114
|
+
"Test unbounded '#{sVal}'.detect {true} == '#{sVal[-1,1]}'")
|
115
|
+
assert_nil(bs.detect { |v| false },
|
116
|
+
"Test unbounded '#{sVal}'.detect {false} == nil")
|
117
|
+
assert_equal(IfNoneCalled,
|
118
|
+
bs.detect(IfNone) { |v| false },
|
119
|
+
"Test unbounded '#{sVal}'.detect(ifnone) {false} == " +
|
120
|
+
"'#{IfNoneCalled}'")
|
121
|
+
#
|
122
|
+
# Now bounded ones.
|
123
|
+
#
|
124
|
+
bs = BitString.new(sVal, sVal.length)
|
125
|
+
assert_equal(sVal[-1,1].to_i(2),
|
126
|
+
bs.detect { |v| true },
|
127
|
+
"Test bounded '#{sVal}'.detect {true} == '#{sVal[-1,1]}'")
|
128
|
+
assert_nil(bs.detect { |v| false },
|
129
|
+
"Test bounded '#{sVal}'.detect {false} == nil")
|
130
|
+
assert_equal(IfNoneCalled,
|
131
|
+
bs.detect(IfNone) { |v| false },
|
132
|
+
"Test bounded '#{sVal}'.detect(ifnone) {false} == " +
|
133
|
+
"'#{IfNoneCalled}'")
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
#
|
138
|
+
# Like .each, only passes two arguments.
|
139
|
+
#
|
140
|
+
def test_050_each_with_index()
|
141
|
+
return unless (BitString.new.respond_to?(:each_with_index))
|
142
|
+
TestVals.each do |sVal|
|
143
|
+
#
|
144
|
+
# Unbounded first..
|
145
|
+
#
|
146
|
+
bs = BitString.new(sVal)
|
147
|
+
bs.each_with_index do |val,pos|
|
148
|
+
assert_equal(sVal[-1-pos,1],
|
149
|
+
val.to_s,
|
150
|
+
"Test unbounded '#{sVal}'.each_with_index" +
|
151
|
+
"(#{val},#{pos}) == #{sVal[-1-pos,1]}")
|
152
|
+
end
|
153
|
+
#
|
154
|
+
# Now bounded strings.
|
155
|
+
#
|
156
|
+
bs = BitString.new(sVal, sVal.length)
|
157
|
+
bs.each_with_index do |val,pos|
|
158
|
+
assert_equal(sVal[-1-pos,1],
|
159
|
+
val.to_s,
|
160
|
+
"Test bounded '#{sVal}'.each_with_index" +
|
161
|
+
"(#{val},#{pos}) == #{sVal[-1-pos,1]}")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
#
|
167
|
+
# Convert to an array. (Equivalent to .to_a ?)
|
168
|
+
#
|
169
|
+
def test_060_entries()
|
170
|
+
return unless (BitString.new.respond_to?(:entries))
|
171
|
+
TestVals.each do |sVal|
|
172
|
+
#
|
173
|
+
# Unbounded.
|
174
|
+
#
|
175
|
+
bs = BitString.new(sVal)
|
176
|
+
sVal_a = sVal.sub(/^0+(.)/, '\1').reverse.split(//).collect { |v| v.to_i(2) }
|
177
|
+
assert_equal(sVal_a,
|
178
|
+
bs.entries,
|
179
|
+
"Test unbounded '#{sVal}'.entries")
|
180
|
+
#
|
181
|
+
# Bounded.
|
182
|
+
#
|
183
|
+
bs = BitString.new(sVal, sVal.length)
|
184
|
+
sVal_a = sVal.reverse.split(//).collect { |v| v.to_i(2) }
|
185
|
+
assert_equal(sVal_a,
|
186
|
+
bs.entries,
|
187
|
+
"Test bounded '#{sVal}'.entries")
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_070_find()
|
192
|
+
#
|
193
|
+
# Same as .detect(), don't bother to test.
|
194
|
+
#
|
195
|
+
end
|
196
|
+
|
197
|
+
#
|
198
|
+
# Like .find/.detect except it returns all matching values, not just
|
199
|
+
# the first.
|
200
|
+
#
|
201
|
+
def test_080_find_all()
|
202
|
+
return unless (BitString.new.respond_to?(:find_all))
|
203
|
+
TestVals.each do |sVal|
|
204
|
+
#
|
205
|
+
# Unbounded.
|
206
|
+
#
|
207
|
+
bs = BitString.new(sVal)
|
208
|
+
assert(bs.find_all { |v| false }.empty?,
|
209
|
+
"Test unbounded '#{sVal}'.find_all{false} == []")
|
210
|
+
#
|
211
|
+
# .population should have been tested in test_basic
|
212
|
+
#
|
213
|
+
assert_equal(bs.population(0),
|
214
|
+
bs.find_all { |v| v.zero? }.length,
|
215
|
+
"Test unbounded '#{sVal}.find_all{0}.length " +
|
216
|
+
"== population(0)")
|
217
|
+
assert_equal(bs.population(1),
|
218
|
+
bs.find_all { |v| v == 1 }.length,
|
219
|
+
"Test unbounded '#{sVal}.find_all{1}.length " +
|
220
|
+
"== population(1)")
|
221
|
+
sVal_t = sVal.sub(/^0+(.)/, '\1').reverse.split(//)
|
222
|
+
tick = 0
|
223
|
+
sVal_t = sVal_t.find_all { |v| ((tick += 1) % 2).zero? }
|
224
|
+
sVal_t.collect! { |v| v.to_i(2) }
|
225
|
+
tick = 0
|
226
|
+
assert_equal(sVal_t,
|
227
|
+
bs.find_all { |v| ((tick += 1) % 2).zero? },
|
228
|
+
"Test unbounded '#{sVal}'.find_all(alt) works")
|
229
|
+
#
|
230
|
+
# Bounded.
|
231
|
+
#
|
232
|
+
bs = BitString.new(sVal, sVal.length)
|
233
|
+
assert(bs.find_all { |v| false }.empty?,
|
234
|
+
"Test bounded '#{sVal}'.find_all{false} == []")
|
235
|
+
assert_equal(bs.population(0),
|
236
|
+
bs.find_all { |v| v.zero? }.length,
|
237
|
+
"Test bounded '#{sVal}.find_all{0}.length " +
|
238
|
+
"== population(0)")
|
239
|
+
assert_equal(bs.population(1),
|
240
|
+
bs.find_all { |v| v == 1 }.length,
|
241
|
+
"Test bounded '#{sVal}.find_all{1}.length " +
|
242
|
+
"== population(1)")
|
243
|
+
sVal_t = sVal.reverse.split(//)
|
244
|
+
tick = 0
|
245
|
+
sVal_t = sVal_t.find_all { |v| ((tick += 1) % 2).zero? }
|
246
|
+
sVal_t.collect! { |v| v.to_i(2) }
|
247
|
+
tick = 0
|
248
|
+
assert_equal(sVal_t,
|
249
|
+
bs.find_all { |v| ((tick += 1) % 2).zero? },
|
250
|
+
"Test bounded '#{sVal}'.find_all(alt) works")
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
#
|
255
|
+
# No grep here..
|
256
|
+
#
|
257
|
+
def test_090_grep()
|
258
|
+
return unless (BitString.new.respond_to?(:grep))
|
259
|
+
assert(false, '###FAIL! .grep not supported but .respond_to? is true!')
|
260
|
+
end
|
261
|
+
|
262
|
+
#
|
263
|
+
# Only 0 and 1 will ever succeed..
|
264
|
+
#
|
265
|
+
def test_100_include?()
|
266
|
+
return unless (BitString.new.respond_to?(:include?))
|
267
|
+
TestVals.each do |sVal|
|
268
|
+
#
|
269
|
+
# Unbounded.
|
270
|
+
#
|
271
|
+
bs = BitString.new(sVal)
|
272
|
+
assert(! bs.include?(2),
|
273
|
+
"Test unbounded '#{sVal}'.include?(2) fails")
|
274
|
+
[0, 1].each do |val|
|
275
|
+
if (bs.population(val) != 0)
|
276
|
+
assert(bs.include?(val),
|
277
|
+
"Test unbounded '#{sVal}'.include?(#{val}) succeeds")
|
278
|
+
else
|
279
|
+
assert(! bs.include?(val),
|
280
|
+
"Test unbounded '#{sVal}'.include?(#{val}) fails")
|
281
|
+
end
|
282
|
+
end
|
283
|
+
#
|
284
|
+
# Bounded.
|
285
|
+
#
|
286
|
+
bs = BitString.new(sVal, sVal.length)
|
287
|
+
assert(! bs.include?(2),
|
288
|
+
"Test bounded '#{sVal}'.include?(2) fails")
|
289
|
+
[0, 1].each do |val|
|
290
|
+
if (bs.population(val) != 0)
|
291
|
+
assert(bs.include?(val),
|
292
|
+
"Test bounded '#{sVal}'.include?(#{val}) succeeds")
|
293
|
+
else
|
294
|
+
assert(! bs.include?(val),
|
295
|
+
"Test bounded '#{sVal}'.include?(#{val}) fails")
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
#
|
302
|
+
# Test .inject
|
303
|
+
#
|
304
|
+
def test_110_inject()
|
305
|
+
return unless (BitString.new.respond_to?(:inject))
|
306
|
+
TestVals.each do |sVal|
|
307
|
+
#
|
308
|
+
# Unbounded..
|
309
|
+
#
|
310
|
+
bs = BitString.new(sVal)
|
311
|
+
result = bs.inject { |memo,val| memo + val }
|
312
|
+
assert_equal(bs.population(1),
|
313
|
+
result,
|
314
|
+
"Test unbounded '#{sVal}'.inject { memo + 1s}")
|
315
|
+
result = bs.inject(-20) { |memo,val| memo + val }
|
316
|
+
assert_equal(bs.population(1) - 20,
|
317
|
+
result,
|
318
|
+
"Test unbounded '#{sVal}'.inject(-20) { memo + 1s}")
|
319
|
+
#
|
320
|
+
# This one is failing because of the issue with the leading
|
321
|
+
# zeroes being stripped and the initial memo value being set
|
322
|
+
# from the LSB. I think.
|
323
|
+
#
|
324
|
+
result = bs.inject { |memo,val| memo + (val.zero? ? 1 : 0) }
|
325
|
+
expected = bs.population(0)
|
326
|
+
if (bs.population(1) == bs.length)
|
327
|
+
#
|
328
|
+
# All 1s means no 0s -- but memo picked up
|
329
|
+
# the value of bs[0]. Adjust the expectation.
|
330
|
+
#
|
331
|
+
expected = bs[0]
|
332
|
+
elsif (bs[0].zero?)
|
333
|
+
#
|
334
|
+
# memo will start out as zero, taken from the first bit, which
|
335
|
+
# won't be counted. .population did, though, so take it off.
|
336
|
+
#
|
337
|
+
expected -= 1
|
338
|
+
elsif (bs[0] == 1)
|
339
|
+
#
|
340
|
+
# memo will start out as 1 from the lsb, but that's not a zero --
|
341
|
+
# so alter the population result to allow for its addition.
|
342
|
+
#
|
343
|
+
expected += 1
|
344
|
+
end
|
345
|
+
assert_equal(expected,
|
346
|
+
result,
|
347
|
+
"Test unbounded '#{sVal}'.inject { memo + 0s}")
|
348
|
+
result = bs.inject(-20) { |memo,val| memo + (val.zero? ? 1 : 0) }
|
349
|
+
assert_equal(bs.population(0) - 20,
|
350
|
+
result,
|
351
|
+
"Test unbounded '#{sVal}'.inject(-20) { memo + 0s}")
|
352
|
+
#
|
353
|
+
# Bounded..
|
354
|
+
#
|
355
|
+
bs = BitString.new(sVal, sVal.length)
|
356
|
+
result = bs.inject { |memo,val| memo + val }
|
357
|
+
expected = bs.population(1)
|
358
|
+
assert_equal(expected,
|
359
|
+
result,
|
360
|
+
"Test bounded '#{sVal}'.inject { memo + 1s}")
|
361
|
+
result = bs.inject(-20) { |memo,val| memo + val }
|
362
|
+
expected = bs.population(1) - 20
|
363
|
+
assert_equal(expected,
|
364
|
+
result,
|
365
|
+
"Test bounded '#{sVal}'.inject(-20) { memo + 1s}")
|
366
|
+
result = bs.inject { |memo,val| memo + (val.zero? ? 1 : 0) }
|
367
|
+
expected = bs.population(0)
|
368
|
+
if (bs.population(1) == bs.length)
|
369
|
+
#
|
370
|
+
# All 1s means no 0s -- but memo picked up
|
371
|
+
# the value of bs[0]. Adjust the expectation.
|
372
|
+
#
|
373
|
+
expected = bs[0]
|
374
|
+
elsif (bs[0].zero?)
|
375
|
+
#
|
376
|
+
# memo will start out as zero, taken from the first bit, which
|
377
|
+
# won't be counted. .population did, though, so take it off.
|
378
|
+
#
|
379
|
+
expected -= 1
|
380
|
+
elsif (bs[0] == 1)
|
381
|
+
#
|
382
|
+
# memo will start out as 1 from the lsb, but that's not a zero --
|
383
|
+
# so alter the population result to allow for its addition.
|
384
|
+
#
|
385
|
+
expected += 1
|
386
|
+
end
|
387
|
+
assert_equal(expected,
|
388
|
+
result,
|
389
|
+
"Test bounded '#{sVal}'.inject { memo + 0s}")
|
390
|
+
result = bs.inject(-20) { |memo,val| memo + (val.zero? ? 1 : 0) }
|
391
|
+
assert_equal(bs.population(0) - 20,
|
392
|
+
result,
|
393
|
+
"Test bounded '#{sVal}'.inject(-20) { memo + 0s}")
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
def test_120_map()
|
398
|
+
#
|
399
|
+
# Same as .collect so don't bother to test.
|
400
|
+
#
|
401
|
+
end
|
402
|
+
|
403
|
+
def test_130_max()
|
404
|
+
return unless (BitString.new.respond_to?(:max))
|
405
|
+
TestVals.each do |sVal|
|
406
|
+
#
|
407
|
+
# Unbounded.
|
408
|
+
#
|
409
|
+
bs = BitString.new(sVal)
|
410
|
+
expected = bs.to_i.zero? ? 0 : 1
|
411
|
+
assert_equal(expected,
|
412
|
+
bs.max,
|
413
|
+
"Test unbounded '#{sVal}'.max == #{expected}")
|
414
|
+
#
|
415
|
+
# Bounded.
|
416
|
+
#
|
417
|
+
bs = BitString.new(sVal, sVal.length)
|
418
|
+
expected = bs.to_i.zero? ? 0 : 1
|
419
|
+
assert_equal(expected,
|
420
|
+
bs.max,
|
421
|
+
"Test bounded '#{sVal}'.max == #{expected}")
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
def test_140_member?()
|
426
|
+
#
|
427
|
+
# Same as .include? so don't bother to test.
|
428
|
+
#
|
429
|
+
end
|
430
|
+
|
431
|
+
def test_150_min()
|
432
|
+
return unless (BitString.new.respond_to?(:min))
|
433
|
+
TestVals.each do |sVal|
|
434
|
+
#
|
435
|
+
# Unbounded.
|
436
|
+
#
|
437
|
+
bs = BitString.new(sVal)
|
438
|
+
expected = (bs.population(1) == bs.length) ? 1 : 0
|
439
|
+
assert_equal(expected,
|
440
|
+
bs.min,
|
441
|
+
"Test unbounded '#{sVal}'.min == #{expected}")
|
442
|
+
#
|
443
|
+
# Bounded.
|
444
|
+
#
|
445
|
+
bs = BitString.new(sVal, sVal.length)
|
446
|
+
expected = (bs.population(1) == bs.length) ? 1 : 0
|
447
|
+
assert_equal(expected,
|
448
|
+
bs.min,
|
449
|
+
"Test bounded '#{sVal}'.min == #{expected}")
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
def test_160_partition()
|
454
|
+
return unless (BitString.new.respond_to?(:partition))
|
455
|
+
TestVals.each do |sVal|
|
456
|
+
#
|
457
|
+
# Unbounded.
|
458
|
+
#
|
459
|
+
bs = BitString.new(sVal)
|
460
|
+
n0 = bs.population(0)
|
461
|
+
n1 = bs.population(1)
|
462
|
+
expected = [ Array.new(n0, 0), Array.new(n1, 1) ]
|
463
|
+
result = bs.partition { |val| val.zero? }
|
464
|
+
assert_equal(expected,
|
465
|
+
result,
|
466
|
+
"Test unbounded '#{sVal}'.partition{0,1}")
|
467
|
+
expected.reverse!
|
468
|
+
result = bs.partition { |val| ! val.zero? }
|
469
|
+
assert_equal(expected,
|
470
|
+
result,
|
471
|
+
"Test unbounded '#{sVal}'.partition{1,0}")
|
472
|
+
#
|
473
|
+
# Bounded.
|
474
|
+
#
|
475
|
+
bs = BitString.new(sVal, sVal.length)
|
476
|
+
n0 = bs.population(0)
|
477
|
+
n1 = bs.population(1)
|
478
|
+
expected = [ Array.new(n0, 0), Array.new(n1, 1) ]
|
479
|
+
result = bs.partition { |val| val.zero? }
|
480
|
+
assert_equal(expected,
|
481
|
+
result,
|
482
|
+
"Test bounded '#{sVal}'.partition{0,1}")
|
483
|
+
expected.reverse!
|
484
|
+
result = bs.partition { |val| ! val.zero? }
|
485
|
+
assert_equal(expected,
|
486
|
+
result,
|
487
|
+
"Test bounded '#{sVal}'.partition{1,0}")
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
def test_170_reject()
|
492
|
+
return unless (BitString.new.respond_to?(:reject))
|
493
|
+
TestVals.each do |sVal|
|
494
|
+
#
|
495
|
+
# Unbounded.
|
496
|
+
#
|
497
|
+
bs = BitString.new(sVal)
|
498
|
+
n0 = bs.population(0)
|
499
|
+
n1 = bs.population(1)
|
500
|
+
expected = Array.new(n0, 0)
|
501
|
+
result = bs.reject { |val| ! val.zero? }
|
502
|
+
assert_equal(expected,
|
503
|
+
result,
|
504
|
+
"Test unbounded '#{sVal}'.reject {! 0}")
|
505
|
+
expected = Array.new(n1, 1)
|
506
|
+
result = bs.reject { |val| val.zero? }
|
507
|
+
assert_equal(expected,
|
508
|
+
result,
|
509
|
+
"Test unbounded '#{sVal}'.reject {0}")
|
510
|
+
expected = []
|
511
|
+
bs.to_a.each_with_index do |val,pos|
|
512
|
+
expected.push(val) unless (pos.%(2).zero?)
|
513
|
+
end
|
514
|
+
tick = -1
|
515
|
+
result = bs.reject { |val| tick += 1; tick.%(2).zero? }
|
516
|
+
assert_equal(expected,
|
517
|
+
result,
|
518
|
+
"Test unbounded '#{sVal}'.reject(%2)")
|
519
|
+
expected = []
|
520
|
+
bs.to_a.each_with_index do |val,pos|
|
521
|
+
expected.push(val) unless (pos.%(3).zero?)
|
522
|
+
end
|
523
|
+
tick = -1
|
524
|
+
result = bs.reject { |val| tick += 1; tick.%(3).zero? }
|
525
|
+
assert_equal(expected,
|
526
|
+
result,
|
527
|
+
"Test unbounded '#{sVal}'.reject(%3)")
|
528
|
+
#
|
529
|
+
# Bounded.
|
530
|
+
#
|
531
|
+
bs = BitString.new(sVal, sVal.length)
|
532
|
+
n0 = bs.population(0)
|
533
|
+
n1 = bs.population(1)
|
534
|
+
expected = Array.new(n0, 0)
|
535
|
+
result = bs.reject { |val| ! val.zero? }
|
536
|
+
assert_equal(expected,
|
537
|
+
result,
|
538
|
+
"Test bounded '#{sVal}'.reject {! 0}")
|
539
|
+
expected = Array.new(n1, 1)
|
540
|
+
result = bs.reject { |val| val.zero? }
|
541
|
+
assert_equal(expected,
|
542
|
+
result,
|
543
|
+
"Test bounded '#{sVal}'.reject {0}")
|
544
|
+
expected = []
|
545
|
+
bs.to_a.each_with_index do |val,pos|
|
546
|
+
expected.push(val) unless (pos.%(2).zero?)
|
547
|
+
end
|
548
|
+
tick = -1
|
549
|
+
result = bs.reject { |val| tick += 1; tick.%(2).zero? }
|
550
|
+
assert_equal(expected,
|
551
|
+
result,
|
552
|
+
"Test bounded '#{sVal}'.reject(%2)")
|
553
|
+
expected = []
|
554
|
+
bs.to_a.each_with_index do |val,pos|
|
555
|
+
expected.push(val) unless (pos.%(3).zero?)
|
556
|
+
end
|
557
|
+
tick = -1
|
558
|
+
result = bs.reject { |val| tick += 1; tick.%(3).zero? }
|
559
|
+
assert_equal(expected,
|
560
|
+
result,
|
561
|
+
"Test bounded '#{sVal}'.reject(%3)")
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
#
|
566
|
+
# Test the select() method.
|
567
|
+
#
|
568
|
+
def test_180_select()
|
569
|
+
TestVals.each do |sVal|
|
570
|
+
bs = BitString.new(sVal)
|
571
|
+
aVal = bs.select { |bit| true }
|
572
|
+
aVal = aVal.collect { |num| num.to_s }.join('').reverse
|
573
|
+
sVal_e = sVal.gsub(/^0+(.)/, '\1')
|
574
|
+
assert_equal(sVal_e,
|
575
|
+
aVal,
|
576
|
+
"Test unbounded select block('#{sVal}')")
|
577
|
+
#
|
578
|
+
# And again for a bounded value.
|
579
|
+
#
|
580
|
+
bs = BitString.new(sVal, sVal.length)
|
581
|
+
aVal = bs.select { |bit| true }
|
582
|
+
aVal = aVal.collect { |num| num.to_s }.join('').reverse
|
583
|
+
assert_equal(sVal,
|
584
|
+
aVal,
|
585
|
+
"Test bounded select block('#{sVal}')")
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
#
|
590
|
+
# slice()
|
591
|
+
#
|
592
|
+
def test_190_slice()
|
593
|
+
return unless (BitString.new.respond_to?(:slice))
|
594
|
+
TestVals.each do |sVal|
|
595
|
+
bs = BitString.new(sVal)
|
596
|
+
sVal_r = sVal.reverse
|
597
|
+
sVal_l = sVal.length
|
598
|
+
(sVal_l - 1).times do |pos|
|
599
|
+
(sVal_l - pos).times do |width|
|
600
|
+
width += 1
|
601
|
+
nbs = bs.slice(pos, width)
|
602
|
+
bsPiece = nbs.to_s
|
603
|
+
#
|
604
|
+
# nbs is now bounded (that's what slice() does), so it should no
|
605
|
+
# longer match the original under any conditions.
|
606
|
+
#
|
607
|
+
assert_not_equal(bs,
|
608
|
+
nbs,
|
609
|
+
"Verify that slice() doesn't change the original")
|
610
|
+
sPiece = sVal_r[pos,width].reverse
|
611
|
+
assert_equal(sPiece,
|
612
|
+
bsPiece,
|
613
|
+
"Test '#{sVal}'.slice(#{pos},#{width}) == '#{sPiece}'")
|
614
|
+
end
|
615
|
+
end
|
616
|
+
end
|
617
|
+
end
|
618
|
+
|
619
|
+
#
|
620
|
+
# slice!()
|
621
|
+
#
|
622
|
+
def test_200_slice!()
|
623
|
+
return unless (BitString.new.respond_to?(:slice!))
|
624
|
+
TestVals.each do |sVal|
|
625
|
+
sVal_r = sVal.reverse
|
626
|
+
sVal_l = sVal.length
|
627
|
+
(sVal_l - 1).times do |pos|
|
628
|
+
(sVal_l - pos).times do |width|
|
629
|
+
width += 1
|
630
|
+
bs = BitString.new(sVal)
|
631
|
+
bs.slice!(pos, width)
|
632
|
+
bsPiece = bs.to_s
|
633
|
+
#
|
634
|
+
# Slicing results in a bounded bitstring, so don't strip the
|
635
|
+
# leading zeroes.
|
636
|
+
#
|
637
|
+
sPiece = sVal_r[pos,width].reverse
|
638
|
+
assert_equal(sPiece,
|
639
|
+
bsPiece,
|
640
|
+
"Test '#{sVal}'.slice!(#{pos},#{width}) == '#{sPiece}'")
|
641
|
+
end
|
642
|
+
end
|
643
|
+
end
|
644
|
+
end
|
645
|
+
|
646
|
+
def test_210_sort()
|
647
|
+
return unless (BitString.new.respond_to?(:sort))
|
648
|
+
assert(false, '###FAIL! .sort not supported but .respond_to? is true!')
|
649
|
+
end
|
650
|
+
|
651
|
+
#
|
652
|
+
# .sort_by *might* make sense for bitstrings, but leave the
|
653
|
+
# determination for another time.
|
654
|
+
#
|
655
|
+
def test_220_sort_by()
|
656
|
+
return unless (BitString.new.respond_to?(:sort_by))
|
657
|
+
assert(false, '###FAIL! .sort_by not supported but .respond_to? is true!')
|
658
|
+
end
|
659
|
+
|
660
|
+
#
|
661
|
+
# .zip makes sense for bitstrings, but writing the tests is likely
|
662
|
+
# to be a bit complicated. Punt for now.
|
663
|
+
#
|
664
|
+
def test_230_zip()
|
665
|
+
return unless (BitString.new.respond_to?(:zip))
|
666
|
+
assert(false, '###FAIL! .zip not supported but .respond_to? is true!')
|
667
|
+
end
|
668
|
+
|
669
|
+
end # class Test_BitStrings
|
670
|
+
|
671
|
+
end # module Tests
|