1 #ifndef RANGE__HPP
2 #define RANGE__HPP
3
4 /* $Id: range.hpp 325631 2011-07-27 15:46:03Z grichenk $
5 * ===========================================================================
6 *
7 * PUBLIC DOMAIN NOTICE
8 * National Center for Biotechnology Information
9 *
10 * This software/database is a "United States Government Work" under the
11 * terms of the United States Copyright Act. It was written as part of
12 * the author's official duties as a United States Government employee and
13 * thus cannot be copyrighted. This software/database is freely available
14 * to the public for use. The National Library of Medicine and the U.S.
15 * Government have not placed any restriction on its use or reproduction.
16 *
17 * Although all reasonable efforts have been taken to ensure the accuracy
18 * and reliability of the software and data, the NLM and the U.S.
19 * Government do not and cannot warrant the performance or results that
20 * may be obtained by using this software or data. The NLM and the U.S.
21 * Government disclaim all warranties, express or implied, including
22 * warranties of performance, merchantability or fitness for any particular
23 * purpose.
24 *
25 * Please cite the author in any work or product based on this material.
26 *
27 * ===========================================================================
28 *
29 * Author: Eugene Vasilchenko
30 *
31 * File Description:
32 * CRange<> class represents interval
33 *
34 * ===========================================================================
35 */
36
37 #include <corelib/ncbistd.hpp>
38 #include <corelib/ncbi_limits.hpp>
39
40
41 /** @addtogroup RangeSupport
42 *
43 * @{
44 */
45
46
47 BEGIN_NCBI_SCOPE
48
49
50 /////////////////////////////////////////////////////////////////////////////
51 // The SPositionTraits template is necessary to make comparison with 0
52 // optional only if the position type is signed.
53 // Many other implementation of this optional check make ICC to issue warning
54 // about meaningless comparison with 0 if the position type is signed.
55 /////////////////////////////////////////////////////////////////////////////
56
57 template<bool Signed, class Position>
58 struct SPositionTraitsBySignedness
59 {
60 };
61
62
63 // An instantiation of SPositionTraitsBySignedness for signed position types.
64 template<class Position>
65 struct SPositionTraitsBySignedness<true, Position>
66 {
IsNegativeSPositionTraitsBySignedness67 static bool IsNegative(Position pos)
68 {
69 return pos < 0;
70 }
71 };
72
73
74 // An instantiation of SPositionTraitsBySignedness for unsigned position types.
75 template<class Position>
76 struct SPositionTraitsBySignedness<false, Position>
77 {
IsNegativeSPositionTraitsBySignedness78 static bool IsNegative(Position )
79 {
80 return false;
81 }
82 };
83
84
85 // Select an instantiation depending on signedness of the position type.
86 template<class Position>
87 struct SPositionTraits :
88 SPositionTraitsBySignedness<(Position(-1)<Position(1)), Position>
89 {
90 };
91
92 // Explicitly specialize for floating-point types, as only integral or
93 // enumeration types can technically appear in constant expressions.
94 template<>
95 struct SPositionTraits<float> : SPositionTraitsBySignedness<true, float>
96 {
97 };
98
99 template<>
100 struct SPositionTraits<double> : SPositionTraitsBySignedness<true, double>
101 {
102 };
103
104 template<>
105 struct SPositionTraits<long double>
106 : SPositionTraitsBySignedness<true, long double>
107 {
108 };
109
110 /////////////////////////////////////////////////////////////////////////////
111 // End of SPositionTraits implementation
112 /////////////////////////////////////////////////////////////////////////////
113
114
115 // range
116 template<class Position>
117 class COpenRange
118 {
119 public:
120 typedef Position position_type;
121 typedef COpenRange<Position> TThisType;
122
123 // constructors
COpenRange(void)124 COpenRange(void)
125 : m_From(GetEmptyFrom()), m_ToOpen(GetEmptyToOpen())
126 {
127 }
COpenRange(position_type from,position_type toOpen)128 COpenRange(position_type from, position_type toOpen)
129 : m_From(from), m_ToOpen(toOpen)
130 {
131 }
132
133 // parameters
GetFrom(void) const134 position_type GetFrom(void) const
135 {
136 return m_From;
137 }
GetToOpen(void) const138 position_type GetToOpen(void) const
139 {
140 return m_ToOpen;
141 }
GetTo(void) const142 position_type GetTo(void) const
143 {
144 return GetToOpen()-1;
145 }
146
147 // state
Empty(void) const148 bool Empty(void) const
149 {
150 return GetToOpen() <= GetFrom();
151 }
NotEmpty(void) const152 bool NotEmpty(void) const
153 {
154 return GetToOpen() > GetFrom();
155 }
156
157 // return length of regular region
GetLength(void) const158 position_type GetLength(void) const
159 {
160 position_type from = GetFrom(), toOpen = GetToOpen();
161 if ( toOpen <= from )
162 return 0;
163 position_type len = toOpen - from;
164 if ( SPositionTraits<position_type>::IsNegative(len) )
165 len = GetWholeLength();
166 return len;
167 }
168
169 // modifiers
SetFrom(position_type from)170 TThisType& SetFrom(position_type from)
171 {
172 m_From = from;
173 return *this;
174 }
SetToOpen(position_type toOpen)175 TThisType& SetToOpen(position_type toOpen)
176 {
177 m_ToOpen = toOpen;
178 return *this;
179 }
SetTo(position_type to)180 TThisType& SetTo(position_type to)
181 {
182 return SetToOpen(to+1);
183 }
SetOpen(position_type from,position_type toOpen)184 TThisType& SetOpen(position_type from, position_type toOpen)
185 {
186 return SetFrom(from).SetToOpen(toOpen);
187 }
Set(position_type from,position_type to)188 TThisType& Set(position_type from, position_type to)
189 {
190 return SetFrom(from).SetTo(to);
191 }
192
193 // length must be >= 0
SetLength(position_type length)194 TThisType& SetLength(position_type length)
195 {
196 _ASSERT(!SPositionTraits<position_type>::IsNegative(length));
197 position_type from = GetFrom();
198 position_type toOpen = from + length;
199 if ( toOpen < from )
200 toOpen = GetWholeToOpen();
201 return SetToOpen(toOpen);
202 }
203 // length must be >= 0
SetLengthDown(position_type length)204 TThisType& SetLengthDown(position_type length)
205 {
206 _ASSERT(length >= 0);
207 position_type toOpen = GetToOpen();
208 position_type from = toOpen - length;
209 if ( from > toOpen )
210 from = GetWholeFrom();
211 return SetFrom(from);
212 }
213
214 // comparison
operator ==(const TThisType & r) const215 bool operator==(const TThisType& r) const
216 {
217 return GetFrom() == r.GetFrom() && GetToOpen() == r.GetToOpen();
218 }
operator !=(const TThisType & r) const219 bool operator!=(const TThisType& r) const
220 {
221 return !(*this == r);
222 }
operator <(const TThisType & r) const223 bool operator<(const TThisType& r) const
224 {
225 return GetFrom() < r.GetFrom() ||
226 (GetFrom() == r.GetFrom() && GetToOpen() < r.GetToOpen());
227 }
operator <=(const TThisType & r) const228 bool operator<=(const TThisType& r) const
229 {
230 return GetFrom() < r.GetFrom() ||
231 (GetFrom() == r.GetFrom() && GetToOpen() <= r.GetToOpen());
232 }
operator >(const TThisType & r) const233 bool operator>(const TThisType& r) const
234 {
235 return GetFrom() > r.GetFrom() ||
236 (GetFrom() == r.GetFrom() && GetToOpen() > r.GetToOpen());
237 }
operator >=(const TThisType & r) const238 bool operator>=(const TThisType& r) const
239 {
240 return GetFrom() > r.GetFrom() ||
241 (GetFrom() == r.GetFrom() && GetToOpen() >= r.GetToOpen());
242 }
243
244
245 // special values
GetPositionMin(void)246 static position_type GetPositionMin(void)
247 {
248 return numeric_limits<position_type>::min();
249 }
GetPositionMax(void)250 static position_type GetPositionMax(void)
251 {
252 return numeric_limits<position_type>::max();
253 }
254
255 // whole range
GetWholeFrom(void)256 static position_type GetWholeFrom(void)
257 {
258 return GetPositionMin();
259 }
GetWholeToOpen(void)260 static position_type GetWholeToOpen(void)
261 {
262 return GetPositionMax();
263 }
GetWholeTo(void)264 static position_type GetWholeTo(void)
265 {
266 return GetWholeToOpen()-1;
267 }
GetWholeLength(void)268 static position_type GetWholeLength(void)
269 {
270 return GetPositionMax();
271 }
GetWhole(void)272 static TThisType GetWhole(void)
273 {
274 return TThisType(GetWholeFrom(), GetWholeToOpen());
275 }
IsWholeFrom(void) const276 bool IsWholeFrom(void) const
277 {
278 return GetFrom() == GetWholeFrom();
279 }
IsWholeTo(void) const280 bool IsWholeTo(void) const
281 {
282 return GetToOpen() == GetWholeToOpen();
283 }
IsWhole(void) const284 bool IsWhole(void) const
285 {
286 return IsWholeFrom() && IsWholeTo();
287 }
288
289 // empty range
GetEmptyFrom(void)290 static position_type GetEmptyFrom(void)
291 {
292 return GetPositionMax();
293 }
GetEmptyToOpen(void)294 static position_type GetEmptyToOpen(void)
295 {
296 return GetPositionMax();
297 }
GetEmptyTo(void)298 static position_type GetEmptyTo(void)
299 {
300 return GetEmptyToOpen()-1;
301 }
GetEmptyLength(void)302 static position_type GetEmptyLength(void)
303 {
304 return 0;
305 }
GetEmpty(void)306 static TThisType GetEmpty(void)
307 {
308 return TThisType(GetEmptyFrom(), GetEmptyToOpen());
309 }
310
311 // intersecting ranges
IntersectionWith(const TThisType & r) const312 TThisType IntersectionWith(const TThisType& r) const
313 {
314 return TThisType(max(GetFrom(), r.GetFrom()),
315 min(GetToOpen(), r.GetToOpen()));
316 }
IntersectWith(const TThisType & r)317 TThisType& IntersectWith(const TThisType& r)
318 {
319 m_From = max(GetFrom(), r.GetFrom());
320 m_ToOpen = min(GetToOpen(), r.GetToOpen());
321 return *this;
322 }
operator &(const TThisType & r) const323 TThisType operator&(const TThisType& r) const
324 {
325 return IntersectionWith(r);
326 }
operator &=(const TThisType & r)327 TThisType& operator&=(const TThisType& r)
328 {
329 return IntersectWith(r);
330 }
IntersectingWith(const TThisType & r) const331 bool IntersectingWith(const TThisType& r) const
332 {
333 return IntersectionWith(r).NotEmpty();
334 }
335
AbuttingWith(const TThisType & r) const336 bool AbuttingWith(const TThisType& r) const
337 {
338 if (Empty() || IsWhole() || r.Empty() || r.IsWhole()) {
339 return false;
340 }
341 return GetToOpen() == r.GetFrom() || GetFrom() == r.GetToOpen();
342 }
343
344 // combine ranges
CombineWith(const TThisType & r)345 TThisType& CombineWith(const TThisType& r)
346 {
347 if ( !r.Empty() ) {
348 if ( !Empty() ) {
349 m_From = min(m_From, r.GetFrom());
350 m_ToOpen = max(m_ToOpen, r.GetToOpen());
351 }
352 else {
353 *this = r;
354 }
355 }
356 return *this;
357 }
CombinationWith(const TThisType & r) const358 TThisType CombinationWith(const TThisType& r) const
359 {
360 if ( !r.Empty() ) {
361 if ( !Empty() ) {
362 return TThisType(min(m_From, r.GetFrom()),
363 max(m_ToOpen, r.GetToOpen()));
364 }
365 else {
366 return r;
367 }
368 }
369 return *this;
370 }
operator +=(const TThisType & r)371 TThisType& operator+=(const TThisType& r)
372 {
373 return CombineWith(r);
374 }
operator +(const TThisType & r) const375 TThisType operator+(const TThisType& r) const
376 {
377 return CombinationWith(r);
378 }
379
380 private:
381 position_type m_From, m_ToOpen;
382 };
383
384
385 // range
386 template<class Position>
387 class CRange : public COpenRange<Position>
388 {
389 public:
390 typedef COpenRange<Position> TParent;
391 typedef typename TParent::position_type position_type;
392 typedef CRange<Position> TThisType;
393
394 // constructors
CRange(void)395 CRange(void)
396 {
397 }
CRange(position_type from,position_type to)398 CRange(position_type from, position_type to)
399 : TParent(from, to+1)
400 {
401 }
CRange(const TParent & range)402 CRange(const TParent& range)
403 : TParent(range)
404 {
405 }
406
407 // modifiers
operator =(const TParent & range)408 TThisType& operator=(const TParent& range)
409 {
410 static_cast<TParent&>(*this) = range;
411 return *this;
412 }
413 };
414
415 ///
416 /// typedefs for sequence ranges
417 ///
418
419 typedef CRange<TSeqPos> TSeqRange;
420 typedef CRange<TSignedSeqPos> TSignedSeqRange;
421
422 /* @} */
423
424 template<class Position>
425 inline
operator <<(CNcbiOstream & out,const COpenRange<Position> & range)426 CNcbiOstream& operator<<(CNcbiOstream& out, const COpenRange<Position>& range)
427 {
428 return out << range.GetFrom() << ".." << range.GetTo();
429 }
430
431 //#include <util/range.inl>
432
433 END_NCBI_SCOPE
434
435 #endif /* RANGE__HPP */
436