source: branches/stable/CORE/pos_range.cxx

Last change on this file was 16763, checked in by westram, 6 years ago
File size: 10.2 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
125void TEST_ExplicitRange() {
126    PosRange empty;
127    PosRange whole  = PosRange::whole();
128    PosRange till50 = PosRange::till(50);
129    PosRange from30 = PosRange::from(30);
130    PosRange f30t50(30, 50);
131
132    ExplicitRange wholeOf17(whole, 17);
133    TEST_EXPECT(PosRange(wholeOf17).is_limited());
134
135    TEST_EXPECT_EQUAL(ExplicitRange(whole, 100).size(), 100);
136    TEST_EXPECT_EQUAL(ExplicitRange(till50, 100).size(), 51); // 0-50
137    TEST_EXPECT_EQUAL(ExplicitRange(till50, 40).size(), 40);
138    TEST_EXPECT_EQUAL(ExplicitRange(from30, 100).size(), 70);
139    TEST_EXPECT_EQUAL(ExplicitRange(from30, 20).size(), 0);
140    TEST_EXPECT_EQUAL(ExplicitRange(f30t50, 100).size(), 21);
141    TEST_EXPECT_EQUAL(ExplicitRange(f30t50, 40).size(), 10);  // 30-39
142
143    TEST_EXPECT_EQUAL(ExplicitRange(empty, 20).size(), 0);
144}
145
146void TEST_range_copying() {
147    char          dest[100];
148    const char   *source     = "0123456789";
149    const size_t  source_len = strlen(source);
150
151    PosRange::till(2).copy_corresponding_part(dest, source, source_len);
152    TEST_EXPECT_EQUAL(dest, "012");
153
154    PosRange(2, 5).copy_corresponding_part(dest, source, source_len);
155    TEST_EXPECT_EQUAL(dest, "2345");
156
157    PosRange::from(7).copy_corresponding_part(dest, source, source_len);
158    TEST_EXPECT_EQUAL(dest, "789");
159
160    PosRange(9, 1000).copy_corresponding_part(dest, source, source_len);
161    TEST_EXPECT_EQUAL(dest, "9");
162
163    PosRange(900, 1000).copy_corresponding_part(dest, source, source_len);
164    TEST_EXPECT_EQUAL(dest, "");
165   
166    // make sure dest and source may overlap:
167    strcpy(dest, source);
168    PosRange::whole().copy_corresponding_part(dest+1, dest, source_len);
169    TEST_EXPECT_EQUAL(dest+1, source);
170
171    strcpy(dest, source);
172    PosRange::whole().copy_corresponding_part(dest, dest+1, source_len-1);
173    TEST_EXPECT_EQUAL(dest, source+1);
174
175    TEST_EXPECT_EQUAL(&*SmartCharPtr(PosRange::empty().dup_corresponding_part(source, source_len)), ""); // empty range
176    TEST_EXPECT_EQUAL(&*SmartCharPtr(PosRange(2, 5).dup_corresponding_part(NULp, 0)), "");               // empty source
177}
178TEST_PUBLISH(TEST_range_copying);
179
180void TEST_range_intersection() {
181    PosRange empty;
182    PosRange whole  = PosRange::whole();
183    PosRange till50 = PosRange::till(50);
184    PosRange from30 = PosRange::from(30);
185    PosRange part(30, 50);
186
187    TEST_EXPECT(intersection(empty, empty)  == empty);
188    TEST_EXPECT(intersection(empty, whole)  == empty);
189    TEST_EXPECT(intersection(empty, till50) == empty);
190    TEST_EXPECT(intersection(empty, from30) == empty);
191    TEST_EXPECT(intersection(empty, part)   == empty);
192
193    TEST_EXPECT(intersection(whole, empty)  == empty);
194    TEST_EXPECT(intersection(whole, whole)  == whole);
195    TEST_EXPECT(intersection(whole, till50) == till50);
196    TEST_EXPECT(intersection(whole, from30) == from30);
197    TEST_EXPECT(intersection(whole, part)   == part);
198   
199    TEST_EXPECT(intersection(till50, empty)  == empty);
200    TEST_EXPECT(intersection(till50, whole)  == till50);
201    TEST_EXPECT(intersection(till50, till50) == till50);
202    TEST_EXPECT(intersection(till50, from30) == part);
203    TEST_EXPECT(intersection(till50, part)   == part);
204
205    TEST_EXPECT(intersection(from30, empty)  == empty);
206    TEST_EXPECT(intersection(from30, whole)  == from30);
207    TEST_EXPECT(intersection(from30, till50) == part);
208    TEST_EXPECT(intersection(from30, from30) == from30);
209    TEST_EXPECT(intersection(from30, part)   == part);
210
211    TEST_EXPECT(intersection(part, empty)  == empty);
212    TEST_EXPECT(intersection(part, whole)  == part);
213    TEST_EXPECT(intersection(part, till50) == part);
214    TEST_EXPECT(intersection(part, from30) == part);
215    TEST_EXPECT(intersection(part, part)   == part);
216
217    TEST_EXPECT(intersection(PosRange(20, 40), till50) == PosRange(20, 40));
218    TEST_EXPECT(intersection(PosRange(40, 60), till50) == PosRange(40, 50));
219    TEST_EXPECT(intersection(PosRange(60, 80), till50) == empty);
220
221    TEST_EXPECT(intersection(PosRange(0,  20), from30) == empty);
222    TEST_EXPECT(intersection(PosRange(20, 40), from30) == PosRange(30, 40));
223    TEST_EXPECT(intersection(PosRange(40, 60), from30) == PosRange(40, 60));
224   
225    TEST_EXPECT(intersection(PosRange(40, 60), PosRange(50, 70)) == PosRange(50, 60));
226}
227
228void TEST_range_containment() {
229    PosRange empty;
230    PosRange whole  = PosRange::whole();
231    PosRange till50 = PosRange::till(50);
232    PosRange from30 = PosRange::from(30);
233    PosRange part(30, 50);
234
235    // empty contains nothing
236    TEST_REJECT(empty.contains(empty)); // and empty is contained nowhere!
237    TEST_REJECT(empty.contains(whole));
238    TEST_REJECT(empty.contains(till50));
239    TEST_REJECT(empty.contains(from30));
240    TEST_REJECT(empty.contains(part));
241
242    // whole contains anything
243    TEST_REJECT(whole.contains(empty)); // except empty
244    TEST_EXPECT(whole.contains(whole));
245    TEST_EXPECT(whole.contains(till50));
246    TEST_EXPECT(whole.contains(from30));
247    TEST_EXPECT(whole.contains(part));
248
249    TEST_REJECT(till50.contains(empty));
250    TEST_REJECT(till50.contains(whole));
251    TEST_EXPECT(till50.contains(till50));
252    TEST_REJECT(till50.contains(from30));
253    TEST_EXPECT(till50.contains(part));
254
255    TEST_REJECT(from30.contains(empty));
256    TEST_REJECT(from30.contains(whole));
257    TEST_REJECT(from30.contains(till50));
258    TEST_EXPECT(from30.contains(from30));
259    TEST_EXPECT(from30.contains(part));
260
261    TEST_REJECT(part.contains(empty));
262    TEST_REJECT(part.contains(whole));
263    TEST_REJECT(part.contains(till50));
264    TEST_REJECT(part.contains(from30));
265    TEST_EXPECT(part.contains(part));
266}
267TEST_PUBLISH(TEST_range_containment);
268
269#endif // UNIT_TESTS
270
271// --------------------------------------------------------------------------------
272
273
274
Note: See TracBrowser for help on using the repository browser.