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
|