qtrocket/utils/Bin.cpp
2024-02-18 16:25:45 -07:00

105 lines
2.4 KiB
C++

/// \cond
// C headers
// C++ headers
#include <algorithm>
#include <sstream>
#include <stdexcept>
// 3rd party headers
#include <fmt/core.h>
/// \endcond
// qtrocket headers
#include "Bin.h"
// TODO: Check on the availability of this in Clang.
// Replace libfmt with format when LLVM libc++ supports it
//#include <format>
namespace utils
{
Bin::Bin()
: bins()
{
}
Bin::Bin(Bin&& o)
: bins(std::move(o.bins))
{
}
Bin::~Bin()
{
}
// TODO: Very low priority, but if anyone wants to make this more efficient it could be
// interesting
void Bin::insert(const std::pair<double, double>& toInsert)
{
bins.push_back(toInsert);
std::sort(bins.begin(), bins.end(),
[](const auto& a, const auto& b){ return a.first < b.first; });
}
double Bin::operator[](double key)
{
auto iter = bins.begin();
// If the key is less than the lowest bin value, then it is out of range
// This should be an error. It's also possible to interpret this as simply
// the lowest bin, but I think that invites a logic error so we'll throw
// instead
if(key < iter->first)
{
throw std::out_of_range(
fmt::format("{} less than lower bound {} of BinMap", key, iter->first));
}
// Increment it and start searching If we reach the end without finding an existing key
// greater than our search term, then we've just hit the last bin and return that
iter++;
double retVal = bins.back().second;
while(iter != bins.end())
{
if(key < iter->first)
{
retVal = std::prev(iter)->second;
break;
}
iter++;
}
return retVal;
}
double Bin::getBinBase(double key)
{
auto iter = bins.begin();
// If the key is less than the lowest bin value, then it is out of range
// This should be an error. It's also possible to interpret this as simply
// the lowest bin, but I think that invites a logic error so we'll throw
// instead
if(key < iter->first)
{
throw std::out_of_range(
fmt::format("{} less than lower bound {} of BinMap", key, iter->first));
}
// Increment it and start searching If we reach the end without finding an existing key
// greater than our search term, then we've just hit the last bin and return that
iter++;
double retVal = bins.back().first;
while(iter != bins.end())
{
if(key < iter->first)
{
retVal = std::prev(iter)->first;
break;
}
iter++;
}
return retVal;
}
} // namespace utils