source: trunk/CORE/pos_range.cxx

Last change on this file was 19167, checked in by westram, 2 years ago
File size: 10.3 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : pos_range.cxx                                     //
4//   Purpose   : range of positions (e.g. part of seq)             //
5//                                                                 //
6//   Coded by Ralf Westram (coder@reallysoft.de) in October 2011   //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#include "pos_range.h"
13#include "arb_mem.h"
14
15void PosRange::copy_corresponding_part(char *dest, const char *source, size_t source_len) const {
16    // dest and source may overlap
17
18    arb_assert((!source && source_len == 0) || (source && source_len == strlen(source)));
19
20    ExplicitRange range(*this, source_len);
21    int           Size = range.size();
22
23    if (Size) memmove(dest, source+start(), Size);
24    dest[Size] = 0;
25}
26
27char *PosRange::dup_corresponding_part(const char *source, size_t source_len) const {
28    ExplicitRange  range(*this, source_len);
29    int            Size = range.size();
30    char          *dup  = ARB_alloc<char>(Size+1);
31
32    copy_corresponding_part(dup, source, source_len);
33    return dup;
34}
35
36// --------------------------------------------------------------------------------
37
38#ifdef UNIT_TESTS
39
40#ifndef TEST_UNIT_H
41#include <test_unit.h>
42#endif
43#include "arb_msg.h"
44#include <climits>
45#include <smartptr.h>
46
47inline bool exactly_one_of(bool b1, bool b2, bool b3) { return (b1+b2+b3) == 1; }
48inline bool wellDefined(PosRange range) {
49    return
50        exactly_one_of(range.is_empty(), range.is_part(), range.is_whole()) &&
51        contradicted(range.is_limited(), range.is_unlimited());
52}
53
54void TEST_PosRange() {
55    PosRange empty = PosRange::empty();
56    PosRange whole = PosRange::whole();
57    PosRange from7 = PosRange::from(7);
58    PosRange till9 = PosRange::till(9);
59    PosRange seven2nine(7, 9);
60
61    TEST_REJECT(empty.is_whole());      TEST_REJECT(empty.is_part());      TEST_EXPECT(empty.is_empty());
62    TEST_EXPECT(whole.is_whole());      TEST_REJECT(whole.is_part());      TEST_REJECT(whole.is_empty());
63    TEST_REJECT(from7.is_whole());      TEST_EXPECT(from7.is_part());      TEST_REJECT(from7.is_empty());
64    TEST_REJECT(till9.is_whole());      TEST_EXPECT(till9.is_part());      TEST_REJECT(till9.is_empty());
65    TEST_REJECT(seven2nine.is_whole()); TEST_EXPECT(seven2nine.is_part()); TEST_REJECT(seven2nine.is_empty());
66
67    TEST_EXPECT(empty.is_limited());
68    TEST_REJECT(whole.is_limited());
69    TEST_REJECT(from7.is_limited());
70    TEST_EXPECT(till9.is_limited());
71    TEST_EXPECT(seven2nine.is_limited());
72
73    // test size
74    TEST_EXPECT_EQUAL(empty.size(), 0);
75    TEST_EXPECT(whole.size() < 0);
76    TEST_EXPECT(from7.size() < 0);
77    TEST_EXPECT_EQUAL(till9.size(), 10);
78    TEST_EXPECT_EQUAL(seven2nine.size(), 3);
79
80    TEST_EXPECT(wellDefined(empty));
81    TEST_EXPECT(wellDefined(whole));
82    TEST_EXPECT(wellDefined(from7));
83    TEST_EXPECT(wellDefined(till9));
84    TEST_EXPECT(wellDefined(seven2nine));
85
86    // test equality
87    TEST_EXPECT(empty == empty);
88    TEST_EXPECT(whole == whole);
89    TEST_EXPECT(from7 == from7);
90    TEST_EXPECT(whole != from7);
91
92    TEST_EXPECT(from7 == PosRange::after(6));
93    TEST_EXPECT(till9 == PosRange::prior(10));
94
95    // test containment (see also TEST_range_containment below)
96    for (int pos = -3; pos<12; ++pos) {
97        TEST_ANNOTATE(GBS_global_string("pos=%i", pos));
98
99        TEST_REJECT(empty.contains(pos));
100        TEST_EXPECT(correlated(whole.contains(pos),      pos >= 0));
101        TEST_EXPECT(correlated(from7.contains(pos),      pos >= 7));
102        TEST_EXPECT(correlated(till9.contains(pos),      pos >= 0 && pos <= 9));
103        TEST_EXPECT(correlated(seven2nine.contains(pos), pos >= 7 && pos <= 9));
104    }
105    TEST_ANNOTATE(NULp);
106
107    TEST_EXPECT(whole.contains(INT_MAX));
108    TEST_EXPECT(from7.contains(INT_MAX));
109    TEST_REJECT(empty.contains(INT_MAX));
110
111    // test after/prior
112    TEST_EXPECT(empty.prior() == empty);
113    TEST_EXPECT(whole.prior() == empty);
114    TEST_EXPECT(from7.prior() == PosRange::till(6));
115    TEST_EXPECT(till9.prior() == empty);
116    TEST_EXPECT(seven2nine.prior() == PosRange::till(6));
117
118    TEST_EXPECT(empty.after() == empty);
119    TEST_EXPECT(whole.after() == empty);
120    TEST_EXPECT(from7.after() == empty);
121    TEST_EXPECT(till9.after() == PosRange::from(10));
122    TEST_EXPECT(seven2nine.after() == PosRange::from(10));
123
124    // test border conditions
125    TEST_EXPECT(PosRange::prior(0) == empty);
126    TEST_EXPECT(PosRange::prior(1).size() == 1);
127}
128
129void TEST_ExplicitRange() {
130    PosRange empty;
131    PosRange whole  = PosRange::whole();
132    PosRange till50 = PosRange::till(50);
133    PosRange from30 = PosRange::from(30);
134    PosRange f30t50(30, 50);
135
136    ExplicitRange wholeOf17(whole, 17);
137    TEST_EXPECT(PosRange(wholeOf17).is_limited());
138
139    TEST_EXPECT_EQUAL(ExplicitRange(whole, 100).size(), 100);
140    TEST_EXPECT_EQUAL(ExplicitRange(till50, 100).size(), 51); // 0-50
141    TEST_EXPECT_EQUAL(ExplicitRange(till50, 40).size(), 40);
142    TEST_EXPECT_EQUAL(ExplicitRange(from30, 100).size(), 70);
143    TEST_EXPECT_EQUAL(ExplicitRange(from30, 20).size(), 0);
144    TEST_EXPECT_EQUAL(ExplicitRange(f30t50, 100).size(), 21);
145    TEST_EXPECT_EQUAL(ExplicitRange(f30t50, 40).size(), 10);  // 30-39
146
147    TEST_EXPECT_EQUAL(ExplicitRange(empty, 20).size(), 0);
148}
149
150void TEST_range_copying() {
151    char          dest[100];
152    const char   *source     = "0123456789";
153    const size_t  source_len = strlen(source);
154
155    PosRange::till(2).copy_corresponding_part(dest, source, source_len);
156    TEST_EXPECT_EQUAL(dest, "012");
157
158    PosRange(2, 5).copy_corresponding_part(dest, source, source_len);
159    TEST_EXPECT_EQUAL(dest, "2345");
160
161    PosRange::from(7).copy_corresponding_part(dest, source, source_len);
162    TEST_EXPECT_EQUAL(dest, "789");
163
164    PosRange(9, 1000).copy_corresponding_part(dest, source, source_len);
165    TEST_EXPECT_EQUAL(dest, "9");
166
167    PosRange(900, 1000).copy_corresponding_part(dest, source, source_len);
168    TEST_EXPECT_EQUAL(dest, "");
169
170    // make sure dest and source may overlap:
171    strcpy(dest, source);
172    PosRange::whole().copy_corresponding_part(dest+1, dest, source_len);
173    TEST_EXPECT_EQUAL(dest+1, source);
174
175    strcpy(dest, source);
176    PosRange::whole().copy_corresponding_part(dest, dest+1, source_len-1);
177    TEST_EXPECT_EQUAL(dest, source+1);
178
179    TEST_EXPECT_EQUAL(&*SmartCharPtr(PosRange::empty().dup_corresponding_part(source, source_len)), ""); // empty range
180    TEST_EXPECT_EQUAL(&*SmartCharPtr(PosRange(2, 5).dup_corresponding_part(NULp, 0)), "");               // empty source
181}
182TEST_PUBLISH(TEST_range_copying);
183
184void TEST_range_intersection() {
185    PosRange empty;
186    PosRange whole  = PosRange::whole();
187    PosRange till50 = PosRange::till(50);
188    PosRange from30 = PosRange::from(30);
189    PosRange part(30, 50);
190
191    TEST_EXPECT(intersection(empty, empty)  == empty);
192    TEST_EXPECT(intersection(empty, whole)  == empty);
193    TEST_EXPECT(intersection(empty, till50) == empty);
194    TEST_EXPECT(intersection(empty, from30) == empty);
195    TEST_EXPECT(intersection(empty, part)   == empty);
196
197    TEST_EXPECT(intersection(whole, empty)  == empty);
198    TEST_EXPECT(intersection(whole, whole)  == whole);
199    TEST_EXPECT(intersection(whole, till50) == till50);
200    TEST_EXPECT(intersection(whole, from30) == from30);
201    TEST_EXPECT(intersection(whole, part)   == part);
202
203    TEST_EXPECT(intersection(till50, empty)  == empty);
204    TEST_EXPECT(intersection(till50, whole)  == till50);
205    TEST_EXPECT(intersection(till50, till50) == till50);
206    TEST_EXPECT(intersection(till50, from30) == part);
207    TEST_EXPECT(intersection(till50, part)   == part);
208
209    TEST_EXPECT(intersection(from30, empty)  == empty);
210    TEST_EXPECT(intersection(from30, whole)  == from30);
211    TEST_EXPECT(intersection(from30, till50) == part);
212    TEST_EXPECT(intersection(from30, from30) == from30);
213    TEST_EXPECT(intersection(from30, part)   == part);
214
215    TEST_EXPECT(intersection(part, empty)  == empty);
216    TEST_EXPECT(intersection(part, whole)  == part);
217    TEST_EXPECT(intersection(part, till50) == part);
218    TEST_EXPECT(intersection(part, from30) == part);
219    TEST_EXPECT(intersection(part, part)   == part);
220
221    TEST_EXPECT(intersection(PosRange(20, 40), till50) == PosRange(20, 40));
222    TEST_EXPECT(intersection(PosRange(40, 60), till50) == PosRange(40, 50));
223    TEST_EXPECT(intersection(PosRange(60, 80), till50) == empty);
224
225    TEST_EXPECT(intersection(PosRange(0,  20), from30) == empty);
226    TEST_EXPECT(intersection(PosRange(20, 40), from30) == PosRange(30, 40));
227    TEST_EXPECT(intersection(PosRange(40, 60), from30) == PosRange(40, 60));
228
229    TEST_EXPECT(intersection(PosRange(40, 60), PosRange(50, 70)) == PosRange(50, 60));
230}
231
232void TEST_range_containment() {
233    PosRange empty;
234    PosRange whole  = PosRange::whole();
235    PosRange till50 = PosRange::till(50);
236    PosRange from30 = PosRange::from(30);
237    PosRange part(30, 50);
238
239    // empty contains nothing
240    TEST_REJECT(empty.contains(empty)); // and empty is contained nowhere!
241    TEST_REJECT(empty.contains(whole));
242    TEST_REJECT(empty.contains(till50));
243    TEST_REJECT(empty.contains(from30));
244    TEST_REJECT(empty.contains(part));
245
246    // whole contains anything
247    TEST_REJECT(whole.contains(empty)); // except empty
248    TEST_EXPECT(whole.contains(whole));
249    TEST_EXPECT(whole.contains(till50));
250    TEST_EXPECT(whole.contains(from30));
251    TEST_EXPECT(whole.contains(part));
252
253    TEST_REJECT(till50.contains(empty));
254    TEST_REJECT(till50.contains(whole));
255    TEST_EXPECT(till50.contains(till50));
256    TEST_REJECT(till50.contains(from30));
257    TEST_EXPECT(till50.contains(part));
258
259    TEST_REJECT(from30.contains(empty));
260    TEST_REJECT(from30.contains(whole));
261    TEST_REJECT(from30.contains(till50));
262    TEST_EXPECT(from30.contains(from30));
263    TEST_EXPECT(from30.contains(part));
264
265    TEST_REJECT(part.contains(empty));
266    TEST_REJECT(part.contains(whole));
267    TEST_REJECT(part.contains(till50));
268    TEST_REJECT(part.contains(from30));
269    TEST_EXPECT(part.contains(part));
270}
271TEST_PUBLISH(TEST_range_containment);
272
273#endif // UNIT_TESTS
274
275// --------------------------------------------------------------------------------
276
277
278
Note: See TracBrowser for help on using the repository browser.