1 // Copyright 2007 Google Inc.
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 #include "../src/difference_cover-inl.h"
18 #include "../src/difference_cover.h"
19 #include "../src/inttypes.h"
20 #include "../src/ternary_partition.h" // for random numbers
29 using dcsbwt::DifferenceCover
;
30 using dcsbwt::DifferenceCoverSample
;
31 using dcsbwt::ternary_partition::RandomNumberGenerator
;
33 const int kMaxPeriod
= 1024; // includes all precomputed covers and
34 // two covers computed by Colbourn-Ling
36 void TestCoverConstruction() {
37 for (int32 period
= 1; period
<= kMaxPeriod
; period
*= 2) {
38 DifferenceCover
dc(period
);
39 assert(dc
.period() == period
);
40 assert(dc
.size() <= period
);
41 assert(DifferenceCover::CoverSizeForPeriod(period
) == dc
.size());
42 assert(DifferenceCover::SizeInBytesForPeriod(period
) > period
);
44 std::cout
<< "TestCoverConstruction passed" << std::endl
;
48 void TestCoverDivision() {
49 for (int32 period
= 1; period
<= kMaxPeriod
; period
*= 2) {
50 DifferenceCover
dc(period
);
51 for (int32 dividend
= 0; dividend
< period
; ++dividend
) {
52 assert(dc
.DivideByPeriod(dividend
) == 0);
53 assert(dc
.ModuloPeriod(dividend
) == dividend
);
56 for (int32 quotient
= 0; quotient
< period
; ++quotient
) {
57 dividend
+= period
- 1;
58 int32 remainder
= period
- quotient
- 1;
59 assert(dc
.DivideByPeriod(dividend
) == quotient
);
60 assert(dc
.ModuloPeriod(dividend
) == remainder
);
62 // Division should work even for values larger than MAX_UINT.
63 int64 large_value
= 1489245697U; // random large number
64 large_value
*= (large_value
-4);
65 assert(dc
.DivideByPeriod(large_value
) * static_cast<int64
>(period
) +
66 dc
.ModuloPeriod(large_value
) == large_value
);
67 // ModuloPeriod should work even for negative values.
69 assert(dc
.ModuloPeriod(x
) == period
-1);
71 std::cout
<< "TestCoverDivision passed" << std::endl
;
75 void TestCoverRankSelect() {
76 for (int32 period
= 1; period
<= kMaxPeriod
; period
*= 2) {
77 DifferenceCover
dc(period
);
79 for (; i
< period
; ++i
) {
80 // continue up to and including the last cover element
81 if (dc
.Rank(i
) == dc
.size()) break;
82 assert(dc
.Rank(i
) < dc
.size());
83 assert(dc
.Select(dc
.Rank(i
)) >= i
);
85 for (; i
< period
; ++i
) {
86 // after the last cover element
87 assert(dc
.Rank(i
) == dc
.size());
89 for (int32 j
= 0; j
< dc
.size(); ++j
) {
90 assert(dc
.Select(j
) < period
);
91 assert(dc
.Rank(dc
.Select(j
)) == j
);
92 assert(dc
.Contains(dc
.Select(j
)));
95 std::cout
<< "TestCoverRankSelect passed" << std::endl
;
99 void TestCoverContainer() {
100 for (int32 period
= 1; period
<= kMaxPeriod
; period
*= 2) {
101 DifferenceCover
dc(period
);
102 std::vector
<int32
> cover(dc
.begin(), dc
.end());
103 assert(cover
.size() == dc
.size());
104 std::vector
<int32
>::iterator it
= cover
.begin();
105 for (int32 i
= 0; i
< period
; ++i
) {
106 if (it
!= cover
.end() && *it
== i
) {
107 assert(dc
.Contains(i
));
110 assert(!dc
.Contains(i
));
114 std::cout
<< "TestCoverContainer passed" << std::endl
;
118 void TestCoverCoverage() {
119 for (int32 period
= 1; period
<= kMaxPeriod
; period
*= 2) {
120 DifferenceCover
dc(period
);
121 for (int32 diff
= 0; diff
< period
; ++diff
) {
122 int32 k
= dc
.Coverer(diff
);
124 assert(dc
.Contains(k
));
125 int32 k_plus_diff
= dc
.ModuloPeriod(k
+ diff
);
126 assert(dc
.Contains(k_plus_diff
));
129 std::cout
<< "TestCoverCoverage passed" << std::endl
;
133 static struct PeriodRangePair
{
136 } period_range_pairs
[20] = {
159 void TestSampleConstruction() {
160 for (int32 i
= 0; i
< 20; ++i
) {
161 int32 period
= period_range_pairs
[i
].period
;
162 int32 range
= period_range_pairs
[i
].range
;
163 DifferenceCoverSample
<int32
> dcs(period
, range
);
164 assert(dcs
.period() == period
);
165 assert(dcs
.range() == range
);
166 assert(dcs
.size() <= range
);
167 assert(dcs
.period_size() <= period
);
169 std::cout
<< "TestSampleConstruction passed" << std::endl
;
173 void TestSampleFill() {
174 for (int32 i
= 0; i
< 20; ++i
) {
175 int32 period
= period_range_pairs
[i
].period
;
176 int32 range
= period_range_pairs
[i
].range
;
177 DifferenceCoverSample
<int32
> dcs(period
, range
);
178 std::vector
<int32
> sample
;
179 dcs
.Fill(std::back_inserter(sample
));
180 assert(sample
.size() == dcs
.size());
181 std::vector
<int32
>::iterator it
= sample
.begin();
182 int32 sample_count
= 0;
183 bool death_test_done
= false; // do just one death test
184 for (int32 i
= 0; i
< range
; ++i
) {
185 if (it
!= sample
.end() && *it
== i
) {
186 assert(dcs
.Contains(i
));
187 assert(dcs
.Rank(i
) == sample_count
);
188 if (i
< range
- period
) {
189 assert(dcs
.Rank(i
+period
) - dcs
.Rank(i
) == dcs
.PeriodInterval());
194 assert(!dcs
.Contains(i
));
198 std::cout
<< "TestSampleFill passed" << std::endl
;
202 void TestSampleShift() {
203 for (int32 i
= 0; i
< 20; ++i
) {
204 int32 period
= period_range_pairs
[i
].period
;
205 int32 range
= period_range_pairs
[i
].range
;
206 DifferenceCoverSample
<int32
> dcs(period
, range
);
207 RandomNumberGenerator rng
;
208 for (int32 n
= 20000; n
; --n
) {
209 int32 i
= rng
.Uniform(range
);
210 int32 j
= rng
.Uniform(range
);
211 int32 shift
= dcs
.Shift(i
,j
);
213 assert(shift
< period
);
214 if (i
< range
- shift
) {
215 assert(dcs
.Contains(i
+ shift
));
217 if (j
< range
- shift
) {
218 assert(dcs
.Contains(j
+ shift
));
222 std::cout
<< "TestSampleShift passed" << std::endl
;
225 } // unnamed namespace
227 int main(int argc
, char **argv
) {
229 TestCoverConstruction();
231 TestCoverRankSelect();
232 TestCoverContainer();
234 TestSampleConstruction();