histogram(a, bins=10, range=None, normed=False, weights=None, axis=None)
                                                                   -> H, dict

    Return the distribution of sample.

    :Stochastics:
      `a` : Array sample.
      `bins` : Number of bins, or an array of bin edges, in which case the
              range is not used. If 'Scott' or 'Freeman' is passed, then
              the named method is used to find the optimal number of bins.
      `range` : Lower and upper bin edges, default: [min, max].
      `normed` :Boolean, if False, return the number of samples in each bin,
              if True, return the density.
      `weights` : Sample weights. The weights are normed only if normed is
              True. Should weights.sum() not equal len(a), the total bin count
              will not be equal to the number of samples.
      `axis` : Specifies the dimension along which the histogram is computed.
              Defaults to None, which aggregates the entire sample array.
      `strategy` : Histogramming method (binsize, searchsorted or digitize).

    :Return:
      `H` : The number of samples in each bin.
        If normed is True, H is a frequency distribution.
      dict{ 'edges':      The bin edges, including the rightmost edge.
        'upper':      Upper outliers.
        'lower':      Lower outliers.
        'bincenters': Center of bins.
        'strategy': the histogramming method employed.}

    :Examples:
      >>> x = random.rand(100,10)
      >>> H, D = histogram(x, bins=10, range=[0,1], normed=True)
      >>> H2, D = histogram(x, bins=10, range=[0,1], normed=True, axis=0)

    :SeeAlso: histogramnd

def histogram(a, bins=10, range=None, normed=False,
              weights=None, axis=None, strategy=None):
    """histogram(a, bins=10, range=None, normed=False, weights=None, axis=None)
                                                                   -> H, dict

    Return the distribution of sample.

    :Stochastics:
      `a` : Array sample.
      `bins` : Number of bins, or an array of bin edges, in which case the
              range is not used. If 'Scott' or 'Freeman' is passed, then
              the named method is used to find the optimal number of bins.
      `range` : Lower and upper bin edges, default: [min, max].
      `normed` :Boolean, if False, return the number of samples in each bin,
              if True, return the density.
      `weights` : Sample weights. The weights are normed only if normed is
              True. Should weights.sum() not equal len(a), the total bin count
              will not be equal to the number of samples.
      `axis` : Specifies the dimension along which the histogram is computed.
              Defaults to None, which aggregates the entire sample array.
      `strategy` : Histogramming method (binsize, searchsorted or digitize).

    :Return:
      `H` : The number of samples in each bin.
        If normed is True, H is a frequency distribution.
      dict{ 'edges':      The bin edges, including the rightmost edge.
        'upper':      Upper outliers.
        'lower':      Lower outliers.
        'bincenters': Center of bins.
        'strategy': the histogramming method employed.}

    :Examples:
      >>> x = random.rand(100,10)
      >>> H, D = histogram(x, bins=10, range=[0,1], normed=True)
      >>> H2, D = histogram(x, bins=10, range=[0,1], normed=True, axis=0)

    :SeeAlso: histogramnd
    """
    weighted = weights is not None

    a = asarray(a)
    if axis is None:
        a = atleast_1d(a.ravel())
        if weighted:
            weights = atleast_1d(weights.ravel())
        axis = 0

    # Define the range
    if range is None:
        mn, mx = a.min(), a.max()
        if mn == mx:
            mn = mn - .5
            mx = mx + .5
        range = [mn, mx]

    # Find the optimal number of bins.
    if bins is None or isinstance(bins, str):
        bins = _optimize_binning(a, range, bins)

    # Compute the bin edges if they are not given explicitely.
    # For the rightmost bin, we want values equal to the right
    # edge to be counted in the last bin, and not as an outlier.
    # Hence, we shift the last bin by a tiny amount.
    if not iterable(bins):
        dr = diff(range) / bins * 1e-10
        edges = linspace(range[0], range[1] + dr, bins + 1, endpoint=True)
    else:
        edges = asarray(bins, float)

    dedges = diff(edges)
    bincenters = edges[:-1] + dedges / 2.

    # Number of bins
    nbin = len(edges) - 1

    # Measure of bin precision.
    decimal = int(-log10(dedges.min()) + 10)

    # Choose the fastest histogramming method
    even = (len(set(around(dedges, decimal))) == 1)
    if strategy is None:
        if even:
            strategy = 'binsize'
        else:
            if nbin > 30:  # approximative threshold
                strategy = 'searchsort'
            else:
                strategy = 'digitize'
    else:
        if strategy not in ['binsize', 'digitize', 'searchsort']:
            raise ValueError('Unknown histogramming strategy.', strategy)
        if strategy == 'binsize' and not even:
            raise ValueError(
                'This binsize strategy cannot be used for uneven bins.')

    # Stochastics for the fixed_binsize functions.
    start = float(edges[0])
    binwidth = float(dedges[0])

    # Looping to reduce memory usage
    block = 66600
    slices = [slice(None)] * a.ndim
    for i in arange(0, len(a), block):
        slices[axis] = slice(i, i + block)
        at = a[slices]
        if weighted:
            at = concatenate((at, weights[slices]), axis)
            if strategy == 'binsize':
                count = apply_along_axis(_splitinmiddle, axis, at,
                                         flib.weighted_fixed_binsize, start, binwidth, nbin)
            elif strategy == 'searchsort':
                count = apply_along_axis(_splitinmiddle, axis, at,
                                         _histogram_searchsort_weighted, edges)
            elif strategy == 'digitize':
                count = apply_along_axis(_splitinmiddle, axis, at,
                                         _histogram_digitize, edges, normed)
        else:
            if strategy == 'binsize':
                count = apply_along_axis(
                    flib.fixed_binsize,
                    axis,
                    at,
                    start,
                    binwidth,
                    nbin)
            elif strategy == 'searchsort':
                count = apply_along_axis(
                    _histogram_searchsort,
                    axis,
                    at,
                    edges)
            elif strategy == 'digitize':
                count = apply_along_axis(
                    _histogram_digitize, axis, at, None, edges,
                    normed)

        if i == 0:
            total = count
        else:
            total += count

    # Outlier count
    upper = total.take(array([-1]), axis)
    lower = total.take(array([0]), axis)

    # Non-outlier count
    core = a.ndim * [slice(None)]
    core[axis] = slice(1, -1)
    hist = total[core]

    if normed:
        normalize = lambda x: atleast_1d(x / (x * dedges).sum())
        hist = apply_along_axis(normalize, axis, hist)

    return hist, {'edges': edges, 'lower': lower, 'upper': upper,
                  'bincenters': bincenters, 'strategy': strategy}