File: ExtremeVisitor.hpp

package info (click to toggle)
bedops 2.4.41%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 21,148 kB
  • sloc: ansic: 28,562; cpp: 15,359; sh: 2,704; makefile: 2,687; xml: 1,669; python: 1,582; csh: 823; perl: 365; java: 172
file content (140 lines) | stat: -rw-r--r-- 4,033 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
  Author: Shane Neph & Scott Kuehn
  Date:   Thu Aug 23 17:42:22 PDT 2007
*/

//
//    BEDOPS
//    Copyright (C) 2011-2022 Shane Neph, Scott Kuehn and Alex Reynolds
//
//    This program is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License along
//    with this program; if not, write to the Free Software Foundation, Inc.,
//    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//

#ifndef CLASS_WINDOW_EXTREME_VISITOR_H
#define CLASS_WINDOW_EXTREME_VISITOR_H

#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <set>
#include <string>
#include <type_traits>

#include "data/measurement/NaN.hpp"
#include "data/measurement/SelectMeasureType.hpp"
#include "utility/OrderCompare.hpp"

namespace Visitors {

  /*
    CompType requires value + address comparisons; we must use a std::set<>
     not a std::multiset<>.  Use a version of the templated
     CompValueThenAddress<> or a similar idea.
  */
  struct DoNothing {};
  struct RandTie {
    RandTie() {
      std::srand(std::time(NULL));
    }

    template <typename T, typename C>
    T* breakTie(const std::set<T*, C>& s) {
      // s is not empty if Extreme is calling
      std::vector<T*> toRand;
      bool first = true;
      typename Signal::SelectMeasure<T>::MeasureType best = 0;
      for ( auto iter = s.begin(); iter != s.end(); ++iter ) {
        if ( first ) {
          best = **iter;
          toRand.push_back(*iter);
          first = false;
        } else if ( **iter == best ) {
          toRand.push_back(*iter);
        } else {
          break;
        }
      } // for
      if ( toRand.size() == 1 )
        return toRand.back();
      std::random_shuffle(toRand.begin(), toRand.end());
      return toRand.back();
    }
  };

  template <
            typename Process,
            typename BaseVisitor,
            typename CompType = Ordering::CompValueThenAddressLesser<
                                                                     typename BaseVisitor::mapping_type,
                                                                     typename BaseVisitor::mapping_type
                                                                    >,
            typename OnTies = DoNothing
           >
  struct Extreme : BaseVisitor {

    typedef BaseVisitor BaseClass;
    typedef Process ProcessType;
    typedef typename BaseVisitor::RefType RefType;
    typedef typename BaseVisitor::MapType MapType;

    explicit Extreme(const ProcessType& pt = ProcessType()) : pt_(pt) { /* */ }

    inline void Add(MapType* bt) {
      m_.insert(bt);
    }

    inline void Delete(MapType* bt) {
      m_.erase(bt);
    }

    void DoneReference() {
      doneReference();
    }

    virtual ~Extreme() { /* */ }

  private:

    template <typename OT=OnTies>
    inline typename std::enable_if<!std::is_same<OT, DoNothing>::value>::type
    doneReference() {
      static const Signal::NaN nan = Signal::NaN();
      static OnTies onTies;
      if ( !m_.empty() )
        pt_.operator()(onTies.breakTie(m_));
      else
        pt_.operator()(nan);
    }


    template <typename OT=OnTies>
    inline typename std::enable_if<std::is_same<OT, DoNothing>::value>::type
    doneReference() {
      static const Signal::NaN nan = Signal::NaN();
      if ( !m_.empty() )
        pt_.operator()(*m_.begin());
      else
        pt_.operator()(nan);
    }

  protected:
    ProcessType pt_;
    std::set<MapType*, CompType> m_;
  };

} // namespace Visitors


#endif // CLASS_WINDOW_EXTREME_VISITOR_H