1 /* $Id: Int_fuzz.cpp 311373 2011-07-11 19:16:41Z grichenk $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author:  .......
27  *
28  * File Description:
29  *   .......
30  *
31  * Remark:
32  *   This code was originally generated by application DATATOOL
33  *   using specifications from the ASN data definition file
34  *   'general.asn'.
35  *
36  * ===========================================================================
37  */
38 
39 // standard includes
40 
41 // generated includes
42 #include <ncbi_pch.hpp>
43 #include <objects/general/Int_fuzz.hpp>
44 
45 #include <algorithm>
46 #include <set>
47 #include <math.h>
48 
49 // generated classes
50 
51 BEGIN_NCBI_SCOPE
52 
53 BEGIN_objects_SCOPE // namespace ncbi::objects::
54 
55 // destructor
~CInt_fuzz(void)56 CInt_fuzz::~CInt_fuzz(void)
57 {
58 }
59 
60 
GetLabel(string * label,TSeqPos pos,bool right) const61 void CInt_fuzz::GetLabel(string* label, TSeqPos pos, bool right) const
62 {
63     char lim = 0;
64     switch (Which()) {
65     case CInt_fuzz::e_P_m:
66         (*label) += "<+-" + NStr::IntToString(GetP_m()) + ">";
67         break;
68     case CInt_fuzz::e_Range:
69         (*label) += "<" + NStr::IntToString(GetRange().GetMin()) +
70             "." + NStr::IntToString(GetRange().GetMax()) + ">";
71         break;
72     case CInt_fuzz::e_Pct:
73         (*label) += "<" + NStr::IntToString(GetPct()) + "%>";
74         break;
75     case CInt_fuzz::e_Lim:
76         switch (GetLim()) {
77         case eLim_unk:
78         case eLim_other:
79             (*label) += "<?>";
80             break;
81         case eLim_gt:
82             lim = '>';
83             break;
84         case eLim_lt:
85             lim = '<';
86             break;
87         case eLim_tr:
88             lim = 'r';
89             break;
90         case eLim_tl:
91             lim = '^';
92             break;
93         default:
94             break;
95         }
96         break;
97     default:
98         break;
99     }
100 
101     if (lim  &&  lim != 'r') {
102         (*label) += lim;
103         lim = 0;
104     }
105 
106     if (right) {
107         (*label) += NStr::IntToString(pos + 1);
108     }
109 
110     if (lim == 'r') {
111         (*label) += '^';
112     }
113 
114     if (!right) {
115         (*label) += NStr::IntToString(pos + 1);
116     }
117 }
118 
119 
AssignTranslated(const CInt_fuzz & f2,TSeqPos n1,TSeqPos n2)120 void CInt_fuzz::AssignTranslated(const CInt_fuzz& f2, TSeqPos n1, TSeqPos n2)
121 {
122     switch (f2.Which()) {
123     case e_Range:
124         SetRange().SetMin(f2.GetRange().GetMin() + n1 - n2);
125         SetRange().SetMax(f2.GetRange().GetMax() + n1 - n2);
126         break;
127     case e_Pct:
128         // use double to avoid overflow
129         SetPct((TSeqPos)((double)f2.GetPct() * n1 / n2));
130         break;
131     case e_Alt:
132         ITERATE (TAlt, it, f2.GetAlt()) {
133             SetAlt().push_back(*it + n1 - n2);
134         }
135         break;
136     default:
137         Assign(f2);
138         break;
139     }
140 }
141 
142 
Add(const CInt_fuzz & f2,TSeqPos & n1,TSeqPos n2,ECombine mode)143 void CInt_fuzz::Add(const CInt_fuzz& f2, TSeqPos& n1, TSeqPos n2,
144                     ECombine mode)
145 {
146     static const double kInfinity = 1.0e20;
147     bool                hit_pct = false, hit_unk = false, hit_circle = false;
148     double              min_delta = 0.0, max_delta = 0.0;
149     set<TSignedSeqPos>  offsets;
150     for (int i = 0;  i < 2;  ++i) {
151         const CInt_fuzz& f = i ? f2 : *this;
152         TSeqPos          n = i ? n2 : n1;
153 
154         switch (f.Which()) {
155         case e_P_m:
156             min_delta -= f.GetP_m();
157             max_delta += f.GetP_m();
158             break;
159 
160         case e_Range:
161             min_delta -= n - f.GetRange().GetMin();
162             max_delta += f.GetRange().GetMax() - n;
163             break;
164 
165         case e_Pct:
166             min_delta -= 0.001 * n * f.GetPct();
167             max_delta += 0.001 * n * f.GetPct();
168             hit_pct = true;
169             break;
170 
171         case e_Lim:
172             switch (f.GetLim()) {
173             case eLim_unk:
174                 hit_unk   = (!hit_unk  ||  mode != eReduce);
175                 min_delta = -kInfinity;
176                 // fall through
177             case eLim_gt:
178                 max_delta = kInfinity;
179                 break;
180             case eLim_lt:
181                 min_delta = -kInfinity;
182                 break;
183             case eLim_tr:
184                 min_delta += 0.5;
185                 max_delta += 0.5;
186                 break;
187             case eLim_tl:
188                 min_delta -= 0.5;
189                 max_delta -= 0.5;
190                 break;
191             case eLim_circle:
192                 hit_circle = (!hit_circle  ||  mode != eReduce);
193                 break;
194             default:
195                 break;
196             }
197             break;
198 
199         case e_Alt:
200         {
201             if (f.GetAlt().empty()) {
202                 break;
203             }
204             if (offsets.empty()) {
205                 ITERATE (TAlt, it, f.GetAlt()) {
206                     offsets.insert(*it - n);
207                 }
208             } else if (mode == eReduce) {
209                 // possibly too optimistic; endpoints may balance better
210                 // than interior points
211                 min_delta = max_delta = f.GetAlt().front();
212                 ITERATE (TAlt, it, f.GetAlt()) {
213                     if (*it < min_delta) {
214                         min_delta = *it;
215                     } else if (*it > max_delta) {
216                         max_delta = *it;
217                     }
218                 }
219                 min_delta += *offsets.rbegin();
220                 max_delta += *offsets.begin();
221                 offsets.clear();
222             } else {
223                 set<TSignedSeqPos> offsets0(offsets);
224                 offsets.clear();
225                 ITERATE (set<TSignedSeqPos>, it, offsets0) {
226                     ITERATE (TAlt, it2, f.GetAlt()) {
227                         offsets.insert(*it + *it2 - n);
228                     }
229                 }
230             }
231             break;
232         }
233 
234         default:
235             break;
236         }
237 
238         if (mode == eReduce  &&  max_delta - min_delta < kInfinity / 2) {
239             swap(min_delta, max_delta);
240         }
241     }
242 
243     if (min_delta > max_delta) {
244         swap(min_delta, max_delta);
245     }
246 
247     TSignedSeqPos min_delta_sp = TSignedSeqPos(floor(min_delta + 0.5));
248     TSignedSeqPos max_delta_sp = TSignedSeqPos(floor(max_delta + 0.5));
249 
250     if (min_delta < -kInfinity / 2) {
251         if (max_delta > kInfinity / 2) {
252             if ( /* mode == eReduce  && */ !hit_unk ) {
253                 // assume cancellation
254                 SetP_m(0);
255             } else {
256                 SetLim(eLim_unk);
257             }
258         } else {
259             if ( !offsets.empty() ) {
260                 n1 += *offsets.rbegin();
261             }
262             n1 += max_delta_sp;
263             SetLim(eLim_lt);
264         }
265     } else if (max_delta > kInfinity / 2) {
266         if ( !offsets.empty() ) {
267             n1 += *offsets.begin();
268         }
269         n1 += min_delta_sp;
270         SetLim(eLim_gt);
271     } else if ( !offsets.empty() ) {
272         if (max_delta - min_delta < 0.5) {
273             TAlt& alt = SetAlt();
274             alt.clear();
275             ITERATE(set<TSignedSeqPos>, it, offsets) {
276                 alt.push_back(n1 + *it + min_delta_sp);
277                 }
278         } else if (mode == eReduce) {
279             TRange& r = SetRange();
280             min_delta += *offsets.rbegin();
281             max_delta += *offsets.begin();
282             if (min_delta > max_delta) {
283                 swap(min_delta, max_delta);
284             }
285             r.SetMin(n1 + min_delta_sp);
286             r.SetMax(n1 + max_delta_sp);
287         } else {
288             // assume there's enough spread to cover any gaps
289                 TRange& r = SetRange();
290                 r.SetMin(n1 + min_delta_sp + *offsets.begin());
291                 r.SetMax(n1 + max_delta_sp + *offsets.rbegin());
292         }
293     } else if (max_delta - min_delta < 0.5) { // single point identified
294         double delta  = 0.5 * (min_delta + max_delta);
295         double rdelta = floor(delta + 0.5);
296         n1 += (TSignedSeqPos)rdelta;
297         if (delta - rdelta > 0.25) {
298             SetLim(eLim_tr);
299         } else if (delta - rdelta < -0.25) {
300             SetLim(eLim_tl);
301         } else if (hit_circle) {
302             SetLim(eLim_circle);
303         } else {
304             SetP_m(0);
305         }
306     } else if (hit_pct) {
307         n1 += (TSignedSeqPos)floor(0.5 * (min_delta + max_delta + 1));
308         SetPct((TSeqPos)floor(500.0 * (max_delta - min_delta) / n1 + 0.5));
309     } else if (min_delta + max_delta < 0.5) { // symmetric
310         SetP_m(max_delta_sp);
311     } else {
312         TRange& r = SetRange();
313         r.SetMin(n1 + min_delta_sp);
314         r.SetMax(n1 + max_delta_sp);
315     }
316 }
317 
318 
Negate(TSeqPos n)319 void CInt_fuzz::Negate(TSeqPos n)
320 {
321     switch (Which()) {
322     case e_P_m:
323     case e_Pct:
324         break; // already symmetric
325 
326     case e_Range:
327     {
328         TRange& r       = SetRange();
329         TSeqPos old_max = r.GetMax();
330         r.SetMax(n + n - r.GetMin());
331         r.SetMin(n + n - old_max);
332         break;
333     }
334 
335     case e_Lim:
336         switch (GetLim()) {
337         case eLim_gt:  SetLim(eLim_lt);  break;
338         case eLim_lt:  SetLim(eLim_gt);  break;
339         case eLim_tr:  SetLim(eLim_tl);  break;
340         case eLim_tl:  SetLim(eLim_tr);  break;
341         default:       break;
342         }
343         break;
344 
345     case e_Alt:
346         NON_CONST_ITERATE(TAlt, it, SetAlt()) {
347             *it = n + n - *it;
348         }
349         break;
350 
351     default:
352         break;
353     }
354 }
355 
356 
357 END_objects_SCOPE // namespace ncbi::objects::
358 
359 END_NCBI_SCOPE
360 
361 /* Original file checksum: lines: 61, chars: 1885, CRC32: bf6aceba */
362