Skip to content

Commit

Permalink
Add simple minimally working metrics (#214)
Browse files Browse the repository at this point in the history
  • Loading branch information
Morwenn committed May 6, 2023
1 parent b5afd1b commit 3a5a691
Show file tree
Hide file tree
Showing 8 changed files with 703 additions and 9 deletions.
26 changes: 17 additions & 9 deletions include/cpp-sort/fwd.h
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2022 Morwenn
* Copyright (c) 2016-2023 Morwenn
* SPDX-License-Identifier: MIT
*/
#ifndef CPPSORT_FWD_H_
Expand All @@ -12,14 +12,11 @@

namespace cppsort
{
//
// This header contains forward declarations for
// every sorter and sorter adapter in the library,
// which helps to specialize some of the adapters
// or to provide information about some sorters
// without actually having to include the whole
// thing
//
// This header contains forward declarations for every
// sorter and sorter adapter in the library, which helps
// to specialize some of the adapters or to provide
// information about some sorters without actually having
// to include the whole thing

////////////////////////////////////////////////////////////
// Sorters
Expand Down Expand Up @@ -102,6 +99,17 @@ namespace cppsort
struct stable_adapter;
template<typename Sorter>
struct verge_adapter;

////////////////////////////////////////////////////////////
// Metrics

namespace metrics
{
template<typename Sorter, typename CountType=std::size_t>
struct comparisons;
template<typename Sorter, typename CountType=std::size_t>
struct projections;
}
}

#endif // CPPSORT_FWD_H_
14 changes: 14 additions & 0 deletions include/cpp-sort/metrics.h
@@ -0,0 +1,14 @@
/*
* Copyright (c) 2023 Morwenn
* SPDX-License-Identifier: MIT
*/
#ifndef CPPSORT_METRICS_H_
#define CPPSORT_METRICS_H_

#include <cpp-sort/utility/metrics_tools.h>

#include <cpp-sort/metrics/comparisons.h>
#include <cpp-sort/metrics/running_time.h>
#include <cpp-sort/metrics/projections.h>

#endif // CPPSORT_METRICS_H_
150 changes: 150 additions & 0 deletions include/cpp-sort/metrics/comparisons.h
@@ -0,0 +1,150 @@
/*
* Copyright (c) 2023 Morwenn
* SPDX-License-Identifier: MIT
*/
#ifndef CPPSORT_METRICS_COMPARISONS_H_
#define CPPSORT_METRICS_COMPARISONS_H_

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <functional>
#include <utility>
#include <cpp-sort/fwd.h>
#include <cpp-sort/sorter_facade.h>
#include <cpp-sort/sorter_traits.h>
#include <cpp-sort/utility/adapter_storage.h>
#include <cpp-sort/utility/metrics_tools.h>
#include "../detail/checkers.h"
#include "../detail/comparison_counter.h"
#include "../detail/type_traits.h"

namespace cppsort
{
namespace metrics
{
////////////////////////////////////////////////////////////
// Tag

struct comparisons_tag {};

////////////////////////////////////////////////////////////
// Metric

namespace detail
{
template<typename Sorter, typename CountType>
struct comparisons_impl:
utility::adapter_storage<Sorter>,
cppsort::detail::check_iterator_category<Sorter>,
cppsort::detail::check_is_always_stable<Sorter>
{
using tag_t = comparisons_tag;
using metric_t = utility::metric<CountType, tag_t>;

comparisons_impl() = default;

constexpr explicit comparisons_impl(Sorter&& sorter):
utility::adapter_storage<Sorter>(std::move(sorter))
{}

template<
typename Iterable,
typename Compare = std::less<>,
typename = cppsort::detail::enable_if_t<
not is_projection_v<Compare, Iterable>
>
>
auto operator()(Iterable&& iterable, Compare compare={}) const
-> metric_t
{
CountType count(0);
using cppsort::detail::comparison_counter;
comparison_counter<Compare, CountType> cmp(std::move(compare), count);
this->get()(std::forward<Iterable>(iterable), std::move(cmp));
return metric_t(count);
}

template<
typename Iterator,
typename Compare = std::less<>,
typename = cppsort::detail::enable_if_t<
not is_projection_iterator_v<Compare, Iterator>
>
>
auto operator()(Iterator first, Iterator last, Compare compare={}) const
-> metric_t
{
CountType count(0);
using cppsort::detail::comparison_counter;
comparison_counter<Compare, CountType> cmp(std::move(compare), count);
this->get()(std::move(first), std::move(last), std::move(cmp));
return metric_t(count);
}

template<
typename Iterable,
typename Compare,
typename Projection,
typename = cppsort::detail::enable_if_t<
is_projection_v<Projection, Iterable, Compare>
>
>
auto operator()(Iterable&& iterable, Compare compare, Projection projection) const
-> metric_t
{
CountType count(0);
using cppsort::detail::comparison_counter;
comparison_counter<Compare, CountType> cmp(std::move(compare), count);
this->get()(std::forward<Iterable>(iterable), std::move(cmp), std::move(projection));
return metric_t(count);
}

template<
typename Iterator,
typename Compare,
typename Projection,
typename = cppsort::detail::enable_if_t<
is_projection_iterator_v<Projection, Iterator, Compare>
>
>
auto operator()(Iterator first, Iterator last,
Compare compare, Projection projection) const
-> metric_t
{
CountType count(0);
using cppsort::detail::comparison_counter;
comparison_counter<Compare, CountType> cmp(std::move(compare), count);
this->get()(std::move(first), std::move(last), std::move(cmp), std::move(projection));
return metric_t(count);
}
};
}

template<typename Sorter, typename CountType>
struct comparisons:
sorter_facade<detail::comparisons_impl<
Sorter,
CountType
>>
{
comparisons() = default;

constexpr explicit comparisons(Sorter sorter):
sorter_facade<detail::comparisons_impl<Sorter, CountType>>(std::move(sorter))
{}
};
}}

namespace cppsort
{
////////////////////////////////////////////////////////////
// is_stable specialization

template<typename Sorter, typename CountType, typename... Args>
struct is_stable<metrics::comparisons<Sorter, CountType>(Args...)>:
is_stable<Sorter(Args...)>
{};
}

#endif // CPPSORT_METRICS_COMPARISONS_H_
128 changes: 128 additions & 0 deletions include/cpp-sort/metrics/projections.h
@@ -0,0 +1,128 @@
/*
* Copyright (c) 2023 Morwenn
* SPDX-License-Identifier: MIT
*/
#ifndef CPPSORT_METRICS_PROJECTIONS_H_
#define CPPSORT_METRICS_PROJECTIONS_H_

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <functional>
#include <utility>
#include <cpp-sort/fwd.h>
#include <cpp-sort/sorter_facade.h>
#include <cpp-sort/sorter_traits.h>
#include <cpp-sort/utility/adapter_storage.h>
#include <cpp-sort/utility/metrics_tools.h>
#include "../detail/checkers.h"
#include "../detail/iterator_traits.h"
#include "../detail/type_traits.h"

namespace cppsort
{
namespace metrics
{
namespace detail
{
template<typename Projection, typename CountType>
class projection_counter
{
public:

projection_counter(Projection projection, CountType& count):
projection(std::move(projection)),
count(count)
{}

template<typename T>
auto operator()(T&& value)
-> decltype(auto)
{
++count;
auto&& proj = utility::as_function(projection);
return proj(std::forward<T>(value));
}

// Accessible member data
Projection projection;

private:

// Projection functions are generally passed by value,
// therefore we need to know where is the original counter
// in order to increment it
CountType& count;
};
}

////////////////////////////////////////////////////////////
// Tag

struct projections_tag {};

////////////////////////////////////////////////////////////
// Metric

namespace detail
{
template<typename Sorter, typename CountType>
struct projections_impl:
utility::adapter_storage<Sorter>,
cppsort::detail::check_iterator_category<Sorter>,
cppsort::detail::check_is_always_stable<Sorter>
{
using tag_t = projections_tag;
using metric_t = utility::metric<CountType, tag_t>;

projections_impl() = default;

constexpr explicit projections_impl(Sorter&& sorter):
utility::adapter_storage<Sorter>(std::move(sorter))
{}

template<
typename ForwardIterator,
typename Compare = std::less<>,
typename Projection = utility::identity,
typename = cppsort::detail::enable_if_t<is_projection_iterator_v<
Projection, ForwardIterator, Compare
>>
>
auto operator()(ForwardIterator first, ForwardIterator last,
Compare compare={}, Projection projection={}) const
-> metric_t
{
CountType count(0);
projection_counter<Projection, CountType> counter(std::move(projection), count);

this->get()(first, last, std::move(compare), std::move(counter));
return metric_t(count);
}
};
}

template<typename Sorter, typename CountType>
struct projections:
sorter_facade<detail::projections_impl<Sorter, CountType>>
{
projections() = default;

constexpr explicit projections(Sorter sorter):
sorter_facade<detail::projections_impl<Sorter, CountType>>(std::move(sorter))
{}
};
}}

namespace cppsort
{
////////////////////////////////////////////////////////////
// is_stable specialization

template<typename Sorter, typename CountType, typename... Args>
struct is_stable<metrics::projections<Sorter, CountType>(Args...)>:
is_stable<Sorter(Args...)>
{};
}

#endif // CPPSORT_METRICS_PROJECTIONS_H_

0 comments on commit 3a5a691

Please sign in to comment.