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