    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Graphics.Rendering.Chart.Axis.Int
    -- Copyright   :  (c) Tim Docker 2010, 2014
    -- License     :  BSD-style (see chart/COPYRIGHT)
    --
    -- Calculate and render integer indexed axes
    {-# OPTIONS_GHC -fno-warn-orphans #-}

    module Graphics.Rendering.Chart.Axis.Int(
        defaultIntAxis,
        scaledIntAxis,
        autoScaledIntAxis
    ) where

    import Data.List(genericLength)
    import Graphics.Rendering.Chart.Geometry
    import Graphics.Rendering.Chart.Axis.Types
    import Graphics.Rendering.Chart.Axis.Floating

    instance PlotValue Int where
        toValue :: Int -> Double
    toValue    = Int -> Double
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
        fromValue :: Double -> Int
    fromValue  = Double -> Int
    forall a b. (RealFrac a, Integral b) => a -> b
    round
        autoAxis :: AxisFn Int
    autoAxis   = LinearAxisParams Int -> AxisFn Int
    forall i.
    (Integral i, PlotValue i) =>
    LinearAxisParams i -> AxisFn i
    autoScaledIntAxis LinearAxisParams Int
    forall a. Show a => LinearAxisParams a
    defaultIntAxis

    instance PlotValue Integer where
        toValue :: Integer -> Double
    toValue    = Integer -> Double
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral
        fromValue :: Double -> Integer
    fromValue  = Double -> Integer
    forall a b. (RealFrac a, Integral b) => a -> b
    round
        autoAxis :: AxisFn Integer
    autoAxis   = LinearAxisParams Integer -> AxisFn Integer
    forall i.
    (Integral i, PlotValue i) =>
    LinearAxisParams i -> AxisFn i
    autoScaledIntAxis LinearAxisParams Integer
    forall a. Show a => LinearAxisParams a
    defaultIntAxis

    defaultIntAxis :: (Show a) => LinearAxisParams a
    defaultIntAxis :: LinearAxisParams a
    defaultIntAxis  = LinearAxisParams :: forall a. ([a] -> [String]) -> Int -> Int -> LinearAxisParams a
    LinearAxisParams {
        _la_labelf :: [a] -> [String]
    _la_labelf  = (a -> String) -> [a] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map a -> String
    forall a. Show a => a -> String
    show,
        _la_nLabels :: Int
    _la_nLabels = 5,
        _la_nTicks :: Int
    _la_nTicks  = 10
    }

    autoScaledIntAxis :: (Integral i, PlotValue i) =>
                         LinearAxisParams i -> AxisFn i
    autoScaledIntAxis :: LinearAxisParams i -> AxisFn i
    autoScaledIntAxis lap :: LinearAxisParams i
    lap ps :: [i]
    ps = LinearAxisParams i -> (i, i) -> AxisFn i
    forall i.
    (Integral i, PlotValue i) =>
    LinearAxisParams i -> (i, i) -> AxisFn i
    scaledIntAxis LinearAxisParams i
    lap (i, i)
    rs [i]
    ps
      where
        rs :: (i, i)
    rs = ([i] -> i
    forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
    minimum [i]
    ps,[i] -> i
    forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
    maximum [i]
    ps)

    scaledIntAxis :: (Integral i, PlotValue i) =>
                     LinearAxisParams i -> (i,i) -> AxisFn i
    scaledIntAxis :: LinearAxisParams i -> (i, i) -> AxisFn i
    scaledIntAxis lap :: LinearAxisParams i
    lap (minI :: i
    minI,maxI :: i
    maxI) ps :: [i]
    ps =
        ([i] -> [String]) -> ([i], [i], [i]) -> AxisData i
    forall x.
    PlotValue x =>
    ([x] -> [String]) -> ([x], [x], [x]) -> AxisData x
    makeAxis (LinearAxisParams i -> [i] -> [String]
    forall a. LinearAxisParams a -> [a] -> [String]
    _la_labelf LinearAxisParams i
    lap) ([i]
    labelvs,[i]
    tickvs,[i]
    gridvs)
      where
        range :: [a] -> (a, b)
    range []  = (0,1)
        range _   | i
    minI i -> i -> Bool
    forall a. Eq a => a -> a -> Bool
    == i
    maxI = (i -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (i -> a) -> i -> a
    forall a b. (a -> b) -> a -> b
    $ i
    minIi -> i -> i
    forall a. Num a => a -> a -> a
    -1, i -> b
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (i -> b) -> i -> b
    forall a b. (a -> b) -> a -> b
    $ i
    minIi -> i -> i
    forall a. Num a => a -> a -> a
    +1)
                  | Bool
    otherwise    = (i -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral   i
    minI,   i -> b
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral   i
    maxI)
    --  labelvs  :: [i]
        labelvs :: [i]
    labelvs   = i -> Range -> [i]
    forall a. Integral a => a -> Range -> [a]
    stepsInt (Int -> i
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> i) -> Int -> i
    forall a b. (a -> b) -> a -> b
    $ LinearAxisParams i -> Int
    forall a. LinearAxisParams a -> Int
    _la_nLabels LinearAxisParams i
    lap) Range
    r
        tickvs :: [i]
    tickvs    = i -> Range -> [i]
    forall a. Integral a => a -> Range -> [a]
    stepsInt (Int -> i
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> i) -> Int -> i
    forall a b. (a -> b) -> a -> b
    $ LinearAxisParams i -> Int
    forall a. LinearAxisParams a -> Int
    _la_nTicks LinearAxisParams i
    lap)
                                      ( i -> Double
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (i -> Double) -> i -> Double
    forall a b. (a -> b) -> a -> b
    $ [i] -> i
    forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
    minimum [i]
    labelvs
                                      , i -> Double
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (i -> Double) -> i -> Double
    forall a b. (a -> b) -> a -> b
    $ [i] -> i
    forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
    maximum [i]
    labelvs )
        gridvs :: [i]
    gridvs    = [i]
    labelvs
        r :: Range
    r         = [i] -> Range
    forall a b a. (Num a, Num b) => [a] -> (a, b)
    range [i]
    ps

    stepsInt :: Integral a => a -> Range -> [a]
    stepsInt :: a -> Range -> [a]
    stepsInt nSteps :: a
    nSteps range :: Range
    range = a -> [a] -> [[a]] -> [a]
    forall a. a -> [a] -> [[a]] -> [a]
    bestSize ([a] -> a
    forall a. [a] -> a
    goodness [a]
    alt0) [a]
    alt0 [[a]]
    alts
      where
        bestSize :: a -> [a] -> [[a]] -> [a]
    bestSize n :: a
    n a :: [a]
    a (a' :: [a]
    a':as :: [[a]]
    as) = let n' :: a
    n' = [a] -> a
    forall a. [a] -> a
    goodness [a]
    a' in
                               if a
    n' a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    < a
    n then a -> [a] -> [[a]] -> [a]
    bestSize a
    n' [a]
    a' [[a]]
    as else [a]
    a
        bestSize _ _ []      = []

        goodness :: [a] -> a
    goodness vs :: [a]
    vs          = a -> a
    forall a. Num a => a -> a
    abs ([a] -> a
    forall i a. Num i => [a] -> i
    genericLength [a]
    vs a -> a -> a
    forall a. Num a => a -> a -> a
    - a
    nSteps)

        (alt0 :: [a]
    alt0:alts :: [[a]]
    alts)          = (a -> [a]) -> [a] -> [[a]]
    forall a b. (a -> b) -> [a] -> [b]
    map (\n :: a
    n -> a -> Range -> [a]
    forall a b a.
    (RealFrac b, RealFrac a, Integral a) =>
    a -> (a, b) -> [a]
    steps a
    n Range
    range) [a]
    sampleSteps'

        -- throw away sampleSteps that are definitely too small as
        -- they takes a long time to process
        sampleSteps' :: [a]
    sampleSteps'         = let rangeMag :: a
    rangeMag = Double -> a
    forall a b. (RealFrac a, Integral b) => a -> b
    ceiling (Range -> Double
    forall a b. (a, b) -> b
    snd Range
    range Double -> Double -> Double
    forall a. Num a => a -> a -> a
    - Range -> Double
    forall a b. (a, b) -> a
    fst Range
    range)

                                   (s1 :: [a]
    s1,s2 :: [a]
    s2) = (a -> Bool) -> [a] -> ([a], [a])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    span (a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    < (a
    rangeMag a -> a -> a
    forall a. Integral a => a -> a -> a
    `div` a
    nSteps)) [a]
    sampleSteps
                               in (([a] -> [a]
    forall a. [a] -> [a]
    reverse ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    take 5 ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [a] -> [a]
    forall a. [a] -> [a]
    reverse) [a]
    s1) [a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++ [a]
    s2

        -- generate all possible step sizes
        sampleSteps :: [a]
    sampleSteps          = [1,2,5] [a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++ [a]
    sampleSteps1
        sampleSteps1 :: [a]
    sampleSteps1         = [10,20,25,50] [a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++ (a -> a) -> [a] -> [a]
    forall a b. (a -> b) -> [a] -> [b]
    map (a -> a -> a
    forall a. Num a => a -> a -> a
    *10) [a]
    sampleSteps1

        steps :: a -> (a, b) -> [a]
    steps size :: a
    size (minV :: a
    minV,maxV :: b
    maxV) = (a -> Bool) -> [a] -> [a]
    forall a. (a -> Bool) -> [a] -> [a]
    takeWhile (a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <a
    b) [a
    a,a
    aa -> a -> a
    forall a. Num a => a -> a -> a
    +a
    size..] [a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++ [a
    b]
          where
            a :: a
    a = (a -> a
    forall a b. (RealFrac a, Integral b) => a -> b
    floor   (a
    minV a -> a -> a
    forall a. Fractional a => a -> a -> a
    / a -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    size)) a -> a -> a
    forall a. Num a => a -> a -> a
    * a
    size
            b :: a
    b = (b -> a
    forall a b. (RealFrac a, Integral b) => a -> b
    ceiling (b
    maxV b -> b -> b
    forall a. Fractional a => a -> a -> a
    / a -> b
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    size)) a -> a -> a
    forall a. Num a => a -> a -> a
    * a
    size