[/
            Copyright Hans Dembinski 2018 - 2019.
   Distributed under the Boost Software License, Version 1.0.
      (See accompanying file LICENSE_1_0.txt or copy at
            https://www.boost.org/LICENSE_1_0.txt)
]

[section:DiscreteAxis DiscreteAxis]

A [*DiscreteAxis] is one of two optional refinements of the [link histogram.concepts.Axis [*Axis]] concept, the other one is the [link histogram.concepts.IntervalAxis IntervalAxis]. This concept is for axes in which each bin represents a single value instead of an interval.

Discrete axes can be further divided into ordered and unordered. An axis is ordered, when bin indices i < j < k imply that value[i] < value[j] < value[k] or value[i] > value[j] > value[k] for all i, j, k. The [classref boost::histogram::axis::integer integer axis] is ordered and the [classref boost::histogram::axis::category category axis] is unordered.

An unordered discrete axis cannot have an underflow bin. Since there is no order, one can have at most one extra bin that counts values not handled by the axis. By convention the overflow bin is used for that.

[heading Associated Types]

* [link histogram.concepts.Axis [*Axis]]
* [link histogram.concepts.IntervalAxis [*IntervalAxis]]

[heading Optional features]

* `A` is a type meeting the requirements of [*DiscreteAxis]
* `a` is a value of type `A`
* `V` is the type accepted for conversion into an index
* `v` is a value of type `V`
* `i` is a value of type [headerref boost/histogram/fwd.hpp `boost::histogram::axis::index_type`]
* `AxisIter` is an /RandomAccessIterator/ over the bins of `A`
* `ReAxisIter` is a reverse /RandomAccessIterator/ over the bins of `A`

[table Valid expressions
[[Expression] [Returns] [Semantics, Pre/Post-conditions]]
[
  [`a.ordered()`]
  [`bool`]
  [
    Static constexpr member function which returns true if the axis is ordered and false otherwise. If this is absent, the library checks whether the value type is arithmetic instead, see [funcref boost::histogram::axis::traits::ordered].
  ]
]
[
  [`a.value(i)`]
  [`V`]
  [
    Const member function which maps an index to a value. The mapping must be injective: each index must be uniquely mapped to one value. The effect must be exactly the inverse of `a.index(v)`. The return value may be a const reference, if the lifetime of the referred object is equal to the lifetime of the axis.
  ]
]
[
  [`a.bin(i)`]
  [`V`]
  [
    Must have the same effect as `a.value(i)`.
  ]
]
[
  [`s.begin()`]
  [`AxisIter`]
  [
    Const member function which return an iterator to the bin with index `0`.
  ]
]
[
  [`s.end()`]
  [`AxisIter`]
  [
    Const member function which returns an iterator to the bin with index `s.size()`.
  ]
]
[
  [`s.rbegin()`]
  [`ReAxisIter`]
  [
    Const member function which return a reverse iterator to the bin with index `s.size()-1`.
  ]
]
[
  [`s.rend()`]
  [`ReAxisIter`]
  [
    Const member function which returns an iterator to the bin with index `-1`.
  ]
]
]

[tip The complete iterator interface can be added to a user-defined axis which implements `a.bin(i)` by inheriting from the [classref boost::histogram::axis::iterator_mixin iterator_mixin].]

[heading Models]

* [classref boost::histogram::axis::category]
* [classref boost::histogram::axis::integer], if first template parameter is `int`

[endsect]
