-----------------------------------------------------------------------------
-- |
-- Module      :  Graphics.Rendering.Chart.Axis.Floating
-- Copyright   :  (c) Tim Docker 2010, 2014
-- License     :  BSD-style (see chart/COPYRIGHT)
--
-- Calculate and render floating value axes
-- including doubles with linear, log, and percentage scaling.
--

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module Graphics.Rendering.Chart.Axis.Floating(
    Percent(..),
    LinearAxisParams(..),
    LogValue(..),
    LogAxisParams(..),
    scaledAxis,
    autoScaledAxis,
    autoScaledLogAxis,
    autoSteps,

    la_labelf,
    la_nLabels,
    la_nTicks,

    loga_labelf
) where

import Data.List(minimumBy)
import Data.Ord (comparing)
import Data.Default.Class
import Numeric (showEFloat, showFFloat)

import Control.Lens
import Graphics.Rendering.Chart.Geometry
import Graphics.Rendering.Chart.Utils
import Graphics.Rendering.Chart.Axis.Types

-- Note: the following code uses explicit Integer types
-- to avoid -Wall 'defaulting to Integer' messages.

instance PlotValue Double where
    toValue :: Double -> Double
toValue  = Double -> Double
forall a. a -> a
id
    fromValue :: Double -> Double
fromValue= Double -> Double
forall a. a -> a
id
    autoAxis :: AxisFn Double
autoAxis = LinearAxisParams Double -> AxisFn Double
forall a. RealFloat a => LinearAxisParams a -> AxisFn a
autoScaledAxis LinearAxisParams Double
forall a. Default a => a
def

instance PlotValue Float where
    toValue :: Float -> Double
toValue  = Float -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac
    fromValue :: Double -> Float
fromValue= Double -> Float
forall a b. (Real a, Fractional b) => a -> b
realToFrac
    autoAxis :: AxisFn Float
autoAxis = LinearAxisParams Float -> AxisFn Float
forall a. RealFloat a => LinearAxisParams a -> AxisFn a
autoScaledAxis LinearAxisParams Float
forall a. Default a => a
def

-- | A wrapper class for doubles used to indicate they are to
-- be plotted against a percentage axis.
newtype Percent = Percent {Percent -> Double
unPercent :: Double}
    deriving (Percent -> Percent -> Bool
(Percent -> Percent -> Bool)
-> (Percent -> Percent -> Bool) -> Eq Percent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Percent -> Percent -> Bool
$c/= :: Percent -> Percent -> Bool
== :: Percent -> Percent -> Bool
$c== :: Percent -> Percent -> Bool
Eq,Eq Percent
Eq Percent
-> (Percent -> Percent -> Ordering)
-> (Percent -> Percent -> Bool)
-> (Percent -> Percent -> Bool)
-> (Percent -> Percent -> Bool)
-> (Percent -> Percent -> Bool)
-> (Percent -> Percent -> Percent)
-> (Percent -> Percent -> Percent)
-> Ord Percent
Percent -> Percent -> Bool
Percent -> Percent -> Ordering
Percent -> Percent -> Percent
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Percent -> Percent -> Percent
$cmin :: Percent -> Percent -> Percent
max :: Percent -> Percent -> Percent
$cmax :: Percent -> Percent -> Percent
>= :: Percent -> Percent -> Bool
$c>= :: Percent -> Percent -> Bool
> :: Percent -> Percent -> Bool
$c> :: Percent -> Percent -> Bool
<= :: Percent -> Percent -> Bool
$c<= :: Percent -> Percent -> Bool
< :: Percent -> Percent -> Bool
$c< :: Percent -> Percent -> Bool
compare :: Percent -> Percent -> Ordering
$ccompare :: Percent -> Percent -> Ordering
$cp1Ord :: Eq Percent
Ord,Integer -> Percent
Percent -> Percent
Percent -> Percent -> Percent
(Percent -> Percent -> Percent)
-> (Percent -> Percent -> Percent)
-> (Percent -> Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Integer -> Percent)
-> Num Percent
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> Percent
$cfromInteger :: Integer -> Percent
signum :: Percent -> Percent
$csignum :: Percent -> Percent
abs :: Percent -> Percent
$cabs :: Percent -> Percent
negate :: Percent -> Percent
$cnegate :: Percent -> Percent
* :: Percent -> Percent -> Percent
$c* :: Percent -> Percent -> Percent
- :: Percent -> Percent -> Percent
$c- :: Percent -> Percent -> Percent
+ :: Percent -> Percent -> Percent
$c+ :: Percent -> Percent -> Percent
Num,Num Percent
Ord Percent
Num Percent -> Ord Percent -> (Percent -> Rational) -> Real Percent
Percent -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: Percent -> Rational
$ctoRational :: Percent -> Rational
$cp2Real :: Ord Percent
$cp1Real :: Num Percent
Real,Num Percent
Num Percent
-> (Percent -> Percent -> Percent)
-> (Percent -> Percent)
-> (Rational -> Percent)
-> Fractional Percent
Rational -> Percent
Percent -> Percent
Percent -> Percent -> Percent
forall a.
Num a
-> (a -> a -> a) -> (a -> a) -> (Rational -> a) -> Fractional a
fromRational :: Rational -> Percent
$cfromRational :: Rational -> Percent
recip :: Percent -> Percent
$crecip :: Percent -> Percent
/ :: Percent -> Percent -> Percent
$c/ :: Percent -> Percent -> Percent
$cp1Fractional :: Num Percent
Fractional,Fractional Percent
Real Percent
Real Percent
-> Fractional Percent
-> (forall b. Integral b => Percent -> (b, Percent))
-> (forall b. Integral b => Percent -> b)
-> (forall b. Integral b => Percent -> b)
-> (forall b. Integral b => Percent -> b)
-> (forall b. Integral b => Percent -> b)
-> RealFrac Percent
Percent -> b
Percent -> b
Percent -> b
Percent -> b
Percent -> (b, Percent)
forall b. Integral b => Percent -> b
forall b. Integral b => Percent -> (b, Percent)
forall a.
Real a
-> Fractional a
-> (forall b. Integral b => a -> (b, a))
-> (forall b. Integral b => a -> b)
-> (forall b. Integral b => a -> b)
-> (forall b. Integral b => a -> b)
-> (forall b. Integral b => a -> b)
-> RealFrac a
floor :: Percent -> b
$cfloor :: forall b. Integral b => Percent -> b
ceiling :: Percent -> b
$cceiling :: forall b. Integral b => Percent -> b
round :: Percent -> b
$cround :: forall b. Integral b => Percent -> b
truncate :: Percent -> b
$ctruncate :: forall b. Integral b => Percent -> b
properFraction :: Percent -> (b, Percent)
$cproperFraction :: forall b. Integral b => Percent -> (b, Percent)
$cp2RealFrac :: Fractional Percent
$cp1RealFrac :: Real Percent
RealFrac,Fractional Percent
Percent
Fractional Percent
-> Percent
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent -> Percent)
-> (Percent -> Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> (Percent -> Percent)
-> Floating Percent
Percent -> Percent
Percent -> Percent -> Percent
forall a.
Fractional a
-> a
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> Floating a
log1mexp :: Percent -> Percent
$clog1mexp :: Percent -> Percent
log1pexp :: Percent -> Percent
$clog1pexp :: Percent -> Percent
expm1 :: Percent -> Percent
$cexpm1 :: Percent -> Percent
log1p :: Percent -> Percent
$clog1p :: Percent -> Percent
atanh :: Percent -> Percent
$catanh :: Percent -> Percent
acosh :: Percent -> Percent
$cacosh :: Percent -> Percent
asinh :: Percent -> Percent
$casinh :: Percent -> Percent
tanh :: Percent -> Percent
$ctanh :: Percent -> Percent
cosh :: Percent -> Percent
$ccosh :: Percent -> Percent
sinh :: Percent -> Percent
$csinh :: Percent -> Percent
atan :: Percent -> Percent
$catan :: Percent -> Percent
acos :: Percent -> Percent
$cacos :: Percent -> Percent
asin :: Percent -> Percent
$casin :: Percent -> Percent
tan :: Percent -> Percent
$ctan :: Percent -> Percent
cos :: Percent -> Percent
$ccos :: Percent -> Percent
sin :: Percent -> Percent
$csin :: Percent -> Percent
logBase :: Percent -> Percent -> Percent
$clogBase :: Percent -> Percent -> Percent
** :: Percent -> Percent -> Percent
$c** :: Percent -> Percent -> Percent
sqrt :: Percent -> Percent
$csqrt :: Percent -> Percent
log :: Percent -> Percent
$clog :: Percent -> Percent
exp :: Percent -> Percent
$cexp :: Percent -> Percent
pi :: Percent
$cpi :: Percent
$cp1Floating :: Fractional Percent
Floating,Floating Percent
RealFrac Percent
RealFrac Percent
-> Floating Percent
-> (Percent -> Integer)
-> (Percent -> Int)
-> (Percent -> (Int, Int))
-> (Percent -> (Integer, Int))
-> (Integer -> Int -> Percent)
-> (Percent -> Int)
-> (Percent -> Percent)
-> (Int -> Percent -> Percent)
-> (Percent -> Bool)
-> (Percent -> Bool)
-> (Percent -> Bool)
-> (Percent -> Bool)
-> (Percent -> Bool)
-> (Percent -> Percent -> Percent)
-> RealFloat Percent
Int -> Percent -> Percent
Integer -> Int -> Percent
Percent -> Bool
Percent -> Int
Percent -> Integer
Percent -> (Int, Int)
Percent -> (Integer, Int)
Percent -> Percent
Percent -> Percent -> Percent
forall a.
RealFrac a
-> Floating a
-> (a -> Integer)
-> (a -> Int)
-> (a -> (Int, Int))
-> (a -> (Integer, Int))
-> (Integer -> Int -> a)
-> (a -> Int)
-> (a -> a)
-> (Int -> a -> a)
-> (a -> Bool)
-> (a -> Bool)
-> (a -> Bool)
-> (a -> Bool)
-> (a -> Bool)
-> (a -> a -> a)
-> RealFloat a
atan2 :: Percent -> Percent -> Percent
$catan2 :: Percent -> Percent -> Percent
isIEEE :: Percent -> Bool
$cisIEEE :: Percent -> Bool
isNegativeZero :: Percent -> Bool
$cisNegativeZero :: Percent -> Bool
isDenormalized :: Percent -> Bool
$cisDenormalized :: Percent -> Bool
isInfinite :: Percent -> Bool
$cisInfinite :: Percent -> Bool
isNaN :: Percent -> Bool
$cisNaN :: Percent -> Bool
scaleFloat :: Int -> Percent -> Percent
$cscaleFloat :: Int -> Percent -> Percent
significand :: Percent -> Percent
$csignificand :: Percent -> Percent
exponent :: Percent -> Int
$cexponent :: Percent -> Int
encodeFloat :: Integer -> Int -> Percent
$cencodeFloat :: Integer -> Int -> Percent
decodeFloat :: Percent -> (Integer, Int)
$cdecodeFloat :: Percent -> (Integer, Int)
floatRange :: Percent -> (Int, Int)
$cfloatRange :: Percent -> (Int, Int)
floatDigits :: Percent -> Int
$cfloatDigits :: Percent -> Int
floatRadix :: Percent -> Integer
$cfloatRadix :: Percent -> Integer
$cp2RealFloat :: Floating Percent
$cp1RealFloat :: RealFrac Percent
RealFloat)

instance Show Percent where
    show :: Percent -> String
show (Percent Double
d) = Double -> String
forall d. RealFloat d => d -> String
showD (Double
dDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
100) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"%"

instance PlotValue Percent where
    toValue :: Percent -> Double
toValue  = Percent -> Double
unPercent
    fromValue :: Double -> Percent
fromValue= Double -> Percent
Percent
    autoAxis :: AxisFn Percent
autoAxis = LinearAxisParams Percent -> AxisFn Percent
forall a. RealFloat a => LinearAxisParams a -> AxisFn a
autoScaledAxis LinearAxisParams Percent
forall a. Default a => a
def {-_la_labelf=-}

-- | A wrapper class for doubles used to indicate they are to
-- be plotted against a log axis.
newtype LogValue = LogValue Double
    deriving (LogValue -> LogValue -> Bool
(LogValue -> LogValue -> Bool)
-> (LogValue -> LogValue -> Bool) -> Eq LogValue
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LogValue -> LogValue -> Bool
$c/= :: LogValue -> LogValue -> Bool
== :: LogValue -> LogValue -> Bool
$c== :: LogValue -> LogValue -> Bool
Eq, Eq LogValue
Eq LogValue
-> (LogValue -> LogValue -> Ordering)
-> (LogValue -> LogValue -> Bool)
-> (LogValue -> LogValue -> Bool)
-> (LogValue -> LogValue -> Bool)
-> (LogValue -> LogValue -> Bool)
-> (LogValue -> LogValue -> LogValue)
-> (LogValue -> LogValue -> LogValue)
-> Ord LogValue
LogValue -> LogValue -> Bool
LogValue -> LogValue -> Ordering
LogValue -> LogValue -> LogValue
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: LogValue -> LogValue -> LogValue
$cmin :: LogValue -> LogValue -> LogValue
max :: LogValue -> LogValue -> LogValue
$cmax :: LogValue -> LogValue -> LogValue
>= :: LogValue -> LogValue -> Bool
$c>= :: LogValue -> LogValue -> Bool
> :: LogValue -> LogValue -> Bool
$c> :: LogValue -> LogValue -> Bool
<= :: LogValue -> LogValue -> Bool
$c<= :: LogValue -> LogValue -> Bool
< :: LogValue -> LogValue -> Bool
$c< :: LogValue -> LogValue -> Bool
compare :: LogValue -> LogValue -> Ordering
$ccompare :: LogValue -> LogValue -> Ordering
$cp1Ord :: Eq LogValue
Ord, Integer -> LogValue
LogValue -> LogValue
LogValue -> LogValue -> LogValue
(LogValue -> LogValue -> LogValue)
-> (LogValue -> LogValue -> LogValue)
-> (LogValue -> LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (Integer -> LogValue)
-> Num LogValue
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> LogValue
$cfromInteger :: Integer -> LogValue
signum :: LogValue -> LogValue
$csignum :: LogValue -> LogValue
abs :: LogValue -> LogValue
$cabs :: LogValue -> LogValue
negate :: LogValue -> LogValue
$cnegate :: LogValue -> LogValue
* :: LogValue -> LogValue -> LogValue
$c* :: LogValue -> LogValue -> LogValue
- :: LogValue -> LogValue -> LogValue
$c- :: LogValue -> LogValue -> LogValue
+ :: LogValue -> LogValue -> LogValue
$c+ :: LogValue -> LogValue -> LogValue
Num, Num LogValue
Ord LogValue
Num LogValue
-> Ord LogValue -> (LogValue -> Rational) -> Real LogValue
LogValue -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: LogValue -> Rational
$ctoRational :: LogValue -> Rational
$cp2Real :: Ord LogValue
$cp1Real :: Num LogValue
Real, Num LogValue
Num LogValue
-> (LogValue -> LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (Rational -> LogValue)
-> Fractional LogValue
Rational -> LogValue
LogValue -> LogValue
LogValue -> LogValue -> LogValue
forall a.
Num a
-> (a -> a -> a) -> (a -> a) -> (Rational -> a) -> Fractional a
fromRational :: Rational -> LogValue
$cfromRational :: Rational -> LogValue
recip :: LogValue -> LogValue
$crecip :: LogValue -> LogValue
/ :: LogValue -> LogValue -> LogValue
$c/ :: LogValue -> LogValue -> LogValue
$cp1Fractional :: Num LogValue
Fractional, Fractional LogValue
Real LogValue
Real LogValue
-> Fractional LogValue
-> (forall b. Integral b => LogValue -> (b, LogValue))
-> (forall b. Integral b => LogValue -> b)
-> (forall b. Integral b => LogValue -> b)
-> (forall b. Integral b => LogValue -> b)
-> (forall b. Integral b => LogValue -> b)
-> RealFrac LogValue
LogValue -> b
LogValue -> b
LogValue -> b
LogValue -> b
LogValue -> (b, LogValue)
forall b. Integral b => LogValue -> b
forall b. Integral b => LogValue -> (b, LogValue)
forall a.
Real a
-> Fractional a
-> (forall b. Integral b => a -> (b, a))
-> (forall b. Integral b => a -> b)
-> (forall b. Integral b => a -> b)
-> (forall b. Integral b => a -> b)
-> (forall b. Integral b => a -> b)
-> RealFrac a
floor :: LogValue -> b
$cfloor :: forall b. Integral b => LogValue -> b
ceiling :: LogValue -> b
$cceiling :: forall b. Integral b => LogValue -> b
round :: LogValue -> b
$cround :: forall b. Integral b => LogValue -> b
truncate :: LogValue -> b
$ctruncate :: forall b. Integral b => LogValue -> b
properFraction :: LogValue -> (b, LogValue)
$cproperFraction :: forall b. Integral b => LogValue -> (b, LogValue)
$cp2RealFrac :: Fractional LogValue
$cp1RealFrac :: Real LogValue
RealFrac, Fractional LogValue
LogValue
Fractional LogValue
-> LogValue
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue -> LogValue)
-> (LogValue -> LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> (LogValue -> LogValue)
-> Floating LogValue
LogValue -> LogValue
LogValue -> LogValue -> LogValue
forall a.
Fractional a
-> a
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> Floating a
log1mexp :: LogValue -> LogValue
$clog1mexp :: LogValue -> LogValue
log1pexp :: LogValue -> LogValue
$clog1pexp :: LogValue -> LogValue
expm1 :: LogValue -> LogValue
$cexpm1 :: LogValue -> LogValue
log1p :: LogValue -> LogValue
$clog1p :: LogValue -> LogValue
atanh :: LogValue -> LogValue
$catanh :: LogValue -> LogValue
acosh :: LogValue -> LogValue
$cacosh :: LogValue -> LogValue
asinh :: LogValue -> LogValue
$casinh :: LogValue -> LogValue
tanh :: LogValue -> LogValue
$ctanh :: LogValue -> LogValue
cosh :: LogValue -> LogValue
$ccosh :: LogValue -> LogValue
sinh :: LogValue -> LogValue
$csinh :: LogValue -> LogValue
atan :: LogValue -> LogValue
$catan :: LogValue -> LogValue
acos :: LogValue -> LogValue
$cacos :: LogValue -> LogValue
asin :: LogValue -> LogValue
$casin :: LogValue -> LogValue
tan :: LogValue -> LogValue
$ctan :: LogValue -> LogValue
cos :: LogValue -> LogValue
$ccos :: LogValue -> LogValue
sin :: LogValue -> LogValue
$csin :: LogValue -> LogValue
logBase :: LogValue -> LogValue -> LogValue
$clogBase :: LogValue -> LogValue -> LogValue
** :: LogValue -> LogValue -> LogValue
$c** :: LogValue -> LogValue -> LogValue
sqrt :: LogValue -> LogValue
$csqrt :: LogValue -> LogValue
log :: LogValue -> LogValue
$clog :: LogValue -> LogValue
exp :: LogValue -> LogValue
$cexp :: LogValue -> LogValue
pi :: LogValue
$cpi :: LogValue
$cp1Floating :: Fractional LogValue
Floating, Floating LogValue
RealFrac LogValue
RealFrac LogValue
-> Floating LogValue
-> (LogValue -> Integer)
-> (LogValue -> Int)
-> (LogValue -> (Int, Int))
-> (LogValue -> (Integer, Int))
-> (Integer -> Int -> LogValue)
-> (LogValue -> Int)
-> (LogValue -> LogValue)
-> (Int -> LogValue -> LogValue)
-> (LogValue -> Bool)
-> (LogValue -> Bool)
-> (LogValue -> Bool)
-> (LogValue -> Bool)
-> (LogValue -> Bool)
-> (LogValue -> LogValue -> LogValue)
-> RealFloat LogValue
Int -> LogValue -> LogValue
Integer -> Int -> LogValue
LogValue -> Bool
LogValue -> Int
LogValue -> Integer
LogValue -> (Int, Int)
LogValue -> (Integer, Int)
LogValue -> LogValue
LogValue -> LogValue -> LogValue
forall a.
RealFrac a
-> Floating a
-> (a -> Integer)
-> (a -> Int)
-> (a -> (Int, Int))
-> (a -> (Integer, Int))
-> (Integer -> Int -> a)
-> (a -> Int)
-> (a -> a)
-> (Int -> a -> a)
-> (a -> Bool)
-> (a -> Bool)
-> (a -> Bool)
-> (a -> Bool)
-> (a -> Bool)
-> (a -> a -> a)
-> RealFloat a
atan2 :: LogValue -> LogValue -> LogValue
$catan2 :: LogValue -> LogValue -> LogValue
isIEEE :: LogValue -> Bool
$cisIEEE :: LogValue -> Bool
isNegativeZero :: LogValue -> Bool
$cisNegativeZero :: LogValue -> Bool
isDenormalized :: LogValue -> Bool
$cisDenormalized :: LogValue -> Bool
isInfinite :: LogValue -> Bool
$cisInfinite :: LogValue -> Bool
isNaN :: LogValue -> Bool
$cisNaN :: LogValue -> Bool
scaleFloat :: Int -> LogValue -> LogValue
$cscaleFloat :: Int -> LogValue -> LogValue
significand :: LogValue -> LogValue
$csignificand :: LogValue -> LogValue
exponent :: LogValue -> Int
$cexponent :: LogValue -> Int
encodeFloat :: Integer -> Int -> LogValue
$cencodeFloat :: Integer -> Int -> LogValue
decodeFloat :: LogValue -> (Integer, Int)
$cdecodeFloat :: LogValue -> (Integer, Int)
floatRange :: LogValue -> (Int, Int)
$cfloatRange :: LogValue -> (Int, Int)
floatDigits :: LogValue -> Int
$cfloatDigits :: LogValue -> Int
floatRadix :: LogValue -> Integer
$cfloatRadix :: LogValue -> Integer
$cp2RealFloat :: Floating LogValue
$cp1RealFloat :: RealFrac LogValue
RealFloat)

instance Show LogValue where
    show :: LogValue -> String
show (LogValue Double
x) = Double -> String
forall a. Show a => a -> String
show Double
x

instance PlotValue LogValue where
    toValue :: LogValue -> Double
toValue (LogValue Double
x) = Double -> Double
forall a. Floating a => a -> a
log Double
x
    fromValue :: Double -> LogValue
fromValue Double
d          = Double -> LogValue
LogValue (Double -> Double
forall a. Floating a => a -> a
exp Double
d)
    autoAxis :: AxisFn LogValue
autoAxis             = LogAxisParams LogValue -> AxisFn LogValue
forall a. RealFloat a => LogAxisParams a -> AxisFn a
autoScaledLogAxis LogAxisParams LogValue
forall a. Default a => a
def

-- | Show a list of axis labels.
-- If some are too big or all are too small, switch to scientific notation for all.
-- If the range is much smaller than the mean, use an offset.
-- TODO: show this offset only once, not on every label.
-- When thinking about improving this function,
-- https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/ticker.py
-- is a good read.
--
-- >>> showDs [0, 1, 2 :: Double]
-- ["0","1","2"]
--
-- >>> showDs [0, 1000000, 2000000 :: Double]
-- ["0.0e0","1.0e6","2.0e6"]
--
-- >>> showDs [0, 0.001, 0.002 :: Double]
-- ["0","0.001","0.002"]
--
-- >>> showDs [-10000000, -1000000, 9000000 :: Double]
-- ["-1.0e7","-1.0e6","9.0e6"]
--
-- >>> showDs [10, 11, 12 :: Double]
-- ["10","11","12"]
--
-- >>> showDs [100, 101, 102 :: Double]
-- ["100","101","102"]
--
-- >>> showDs [100000, 100001, 100002 :: Double]
-- ["100000","100001","100002"]
--
-- >>> showDs [1000000, 1000001, 1000002 :: Double]
-- ["1.0e6 + 0","1.0e6 + 1","1.0e6 + 2"]
--
-- >>> showDs [10000000, 10000001, 10000002 :: Double]
-- ["1.0e7 + 0","1.0e7 + 1","1.0e7 + 2"]
--
-- >>> showDs [-10000000, -10000001, -10000002 :: Double]
-- ["-1.0e7 + 2","-1.0e7 + 1","-1.0e7 + 0"]
--
-- prop> let [s0, s1] = showDs [x, x + 1.0 :: Double] in s0 /= s1
showDs :: forall d . (RealFloat d) => [d] -> [String]
showDs :: [d] -> [String]
showDs [d]
xs = case [d] -> [String]
forall d. RealFloat d => [d] -> [String]
showWithoutOffset [d]
xs of
  (String
s0:[String]
others)
    | String -> [String] -> Bool
forall t. Eq t => t -> [t] -> Bool
anyEqualNeighbor String
s0 [String]
others -> ShowS -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ShowS
addShownOffset ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ [d] -> [String]
forall d. RealFloat d => [d] -> [String]
showWithoutOffset ((d -> d) -> [d] -> [d]
forall a b. (a -> b) -> [a] -> [b]
map (\d
x -> d
x d -> d -> d
forall a. Num a => a -> a -> a
- d
offset) [d]
xs)
  [String]
s -> [String]
s
  where
    anyEqualNeighbor :: t -> [t] -> Bool
anyEqualNeighbor t
z0 (t
z1:[t]
others)
      | t
z0 t -> t -> Bool
forall a. Eq a => a -> a -> Bool
== t
z1 = Bool
True
      | Bool
otherwise = t -> [t] -> Bool
anyEqualNeighbor t
z1 [t]
others
    anyEqualNeighbor t
_ [] = Bool
False

    -- Use the min for offset. Another good choice could be the mean.
    offset :: d
    offset :: d
offset = [d] -> d
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [d]
xs
    shownOffset :: String
shownOffset = case [d] -> [String]
forall d. RealFloat d => [d] -> [String]
showWithoutOffset [d
offset] of
      [String
r] -> String
r
      [String]
rs -> ShowS
forall a. HasCallStack => String -> a
error ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ String
"showDs: shownOffset expected 1 element, got " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
rs)

    addShownOffset :: String -> String
    addShownOffset :: ShowS
addShownOffset (Char
'-':String
x) = String
shownOffset String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" - " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
x
    addShownOffset String
x = String
shownOffset String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" + " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
x

showWithoutOffset :: RealFloat d => [d] -> [String]
showWithoutOffset :: [d] -> [String]
showWithoutOffset [d]
xs
  | Bool
useScientificNotation = (d -> String) -> [d] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (\d
x -> Maybe Int -> d -> String
forall d. RealFloat d => Maybe Int -> d -> String
showEFloat' (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1) d
x) [d]
xs
  | Bool
otherwise = (d -> String) -> [d] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map d -> String
forall d. RealFloat d => d -> String
showD [d]
xs
  where
    -- use scientific notation if max value is too big or too small
    useScientificNotation :: Bool
useScientificNotation = d
maxAbs d -> d -> Bool
forall a. Ord a => a -> a -> Bool
>= d
1e6 Bool -> Bool -> Bool
|| d
maxAbs d -> d -> Bool
forall a. Ord a => a -> a -> Bool
<= d
1e-6
    maxAbs :: d
maxAbs = [d] -> d
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ((d -> d) -> [d] -> [d]
forall a b. (a -> b) -> [a] -> [b]
map d -> d
forall a. Num a => a -> a
abs [d]
xs)


-- | Changes the behavior of showEFloat to drop more than one trailings 0.
-- Instead of 1.000e4 you get 1.0e4
showEFloat' :: forall d . RealFloat d => Maybe Int -> d -> String
showEFloat' :: Maybe Int -> d -> String
showEFloat' Maybe Int
mdigits d
x = ShowS
forall a. [a] -> [a]
reverse ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ ShowS
cleanup0 (ShowS
forall a. [a] -> [a]
reverse String
shown0)
  where
    shown0 :: String
shown0 = Maybe Int -> d -> ShowS
forall a. RealFloat a => Maybe Int -> a -> ShowS
showEFloat Maybe Int
mdigits d
x String
""

    -- wait until we get the "e"
    cleanup0 :: String -> String
    cleanup0 :: ShowS
cleanup0 (e :: Char
e@Char
'e':String
ys) = Char
eChar -> ShowS
forall a. a -> [a] -> [a]
:ShowS
cleanup1 String
ys
    cleanup0 (Char
y:String
ys) = Char
y Char -> ShowS
forall a. a -> [a] -> [a]
: ShowS
cleanup0 String
ys
    cleanup0 [] = ShowS
forall a. [a] -> [a]
reverse String
shown0 -- something went wrong, just return the original

    -- get rid of redundant 0s before the '.'
    cleanup1 :: String -> String
    cleanup1 :: ShowS
cleanup1 (Char
'0':ys :: String
ys@(Char
'0':String
_)) = ShowS
cleanup1 String
ys
    cleanup1 String
y = String
y


showD :: (RealFloat d) => d -> String
showD :: d -> String
showD d
x = case ShowS
forall a. [a] -> [a]
reverse ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ Maybe Int -> d -> ShowS
forall a. RealFloat a => Maybe Int -> a -> ShowS
showFFloat Maybe Int
forall a. Maybe a
Nothing d
x String
"" of
            Char
'0':Char
'.':String
r -> ShowS
forall a. [a] -> [a]
reverse String
r
            String
r         -> ShowS
forall a. [a] -> [a]
reverse String
r

data LinearAxisParams a = LinearAxisParams {
    -- | The function used to show the axes labels.
    LinearAxisParams a -> [a] -> [String]
_la_labelf  :: [a] -> [String],

    -- | The target number of labels to be shown.
    LinearAxisParams a -> Int
_la_nLabels :: Int,

    -- | The target number of ticks to be shown.
    LinearAxisParams a -> Int
_la_nTicks  :: Int
}

instance (Show a, RealFloat a) => Default (LinearAxisParams a) where
  def :: LinearAxisParams a
def = LinearAxisParams :: forall a. ([a] -> [String]) -> Int -> Int -> LinearAxisParams a
LinearAxisParams 
    { _la_labelf :: [a] -> [String]
_la_labelf    = [a] -> [String]
forall d. RealFloat d => [d] -> [String]
showDs
    , _la_nLabels :: Int
_la_nLabels   = Int
5
    , _la_nTicks :: Int
_la_nTicks    = Int
50
    }

-- | Generate a linear axis with the specified bounds
scaledAxis :: RealFloat a => LinearAxisParams a -> (a,a) -> AxisFn a
scaledAxis :: LinearAxisParams a -> (a, a) -> AxisFn a
scaledAxis LinearAxisParams a
lap rs :: (a, a)
rs@(a
minV,a
maxV) [a]
ps0 = (a -> Double)
-> (Double -> a)
-> ([a] -> [String])
-> ([a], [a], [a])
-> AxisData a
forall x.
Ord x =>
(x -> Double)
-> (Double -> x)
-> ([x] -> [String])
-> ([x], [x], [x])
-> AxisData x
makeAxis' a -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac Double -> a
forall a b. (Real a, Fractional b) => a -> b
realToFrac
                                         (LinearAxisParams a -> [a] -> [String]
forall a. LinearAxisParams a -> [a] -> [String]
_la_labelf LinearAxisParams a
lap) ([a]
labelvs,[a]
tickvs,[a]
gridvs)
  where
    ps :: [a]
ps        = (a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
filter a -> Bool
forall a. RealFloat a => a -> Bool
isValidNumber [a]
ps0
    range :: [a] -> (a, a)
range []  = (a
0,a
1)
    range [a]
_   | a
minV a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
maxV = if a
minVa -> a -> Bool
forall a. Eq a => a -> a -> Bool
==a
0 then (-a
1,a
1) else
                               let d :: a
d = a -> a
forall a. Num a => a -> a
abs (a
minV a -> a -> a
forall a. Num a => a -> a -> a
* a
0.01) in (a
minVa -> a -> a
forall a. Num a => a -> a -> a
-a
d,a
maxVa -> a -> a
forall a. Num a => a -> a -> a
+a
d)
              | Bool
otherwise    = (a, a)
rs
    labelvs :: [a]
labelvs   = (Rational -> a) -> [Rational] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map Rational -> a
forall a. Fractional a => Rational -> a
fromRational ([Rational] -> [a]) -> [Rational] -> [a]
forall a b. (a -> b) -> a -> b
$ a -> (a, a) -> [Rational]
forall a. RealFloat a => a -> (a, a) -> [Rational]
steps (Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (LinearAxisParams a -> Int
forall a. LinearAxisParams a -> Int
_la_nLabels LinearAxisParams a
lap)) (a, a)
r
    tickvs :: [a]
tickvs    = (Rational -> a) -> [Rational] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map Rational -> a
forall a. Fractional a => Rational -> a
fromRational ([Rational] -> [a]) -> [Rational] -> [a]
forall a b. (a -> b) -> a -> b
$ a -> (a, a) -> [Rational]
forall a. RealFloat a => a -> (a, a) -> [Rational]
steps (Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (LinearAxisParams a -> Int
forall a. LinearAxisParams a -> Int
_la_nTicks LinearAxisParams a
lap))
                                         ([a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [a]
labelvs,[a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [a]
labelvs)
    gridvs :: [a]
gridvs    = [a]
labelvs
    r :: (a, a)
r         = [a] -> (a, a)
forall a. [a] -> (a, a)
range [a]
ps

-- | Generate a linear axis automatically, scaled appropriately for the
-- input data.
autoScaledAxis :: RealFloat a => LinearAxisParams a -> AxisFn a
autoScaledAxis :: LinearAxisParams a -> AxisFn a
autoScaledAxis LinearAxisParams a
lap [a]
ps0 = LinearAxisParams a -> (a, a) -> AxisFn a
forall a. RealFloat a => LinearAxisParams a -> (a, a) -> AxisFn a
scaledAxis LinearAxisParams a
lap (a, a)
rs [a]
ps
  where
    ps :: [a]
ps = (a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
filter a -> Bool
forall a. RealFloat a => a -> Bool
isValidNumber [a]
ps0
    rs :: (a, a)
rs = ([a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [a]
ps,[a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [a]
ps)

steps :: RealFloat a => a -> (a,a) -> [Rational]
steps :: a -> (a, a) -> [Rational]
steps a
nSteps rs :: (a, a)
rs@(a
minV,a
maxV) = (Integer -> Rational) -> [Integer] -> [Rational]
forall a b. (a -> b) -> [a] -> [b]
map ((Rational
sRational -> Rational -> Rational
forall a. Num a => a -> a -> a
*) (Rational -> Rational)
-> (Integer -> Rational) -> Integer -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral) [Integer
min' .. Integer
max']
  where
    s :: Rational
s    = a -> (a, a) -> Rational
forall a. RealFloat a => a -> (a, a) -> Rational
chooseStep a
nSteps (a, a)
rs
    min' :: Integer
    min' :: Integer
min' = Rational -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
floor   (Rational -> Integer) -> Rational -> Integer
forall a b. (a -> b) -> a -> b
$ a -> Rational
forall a b. (Real a, Fractional b) => a -> b
realToFrac a
minV Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational
s
    max' :: Integer
max' = Rational -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Rational -> Integer) -> Rational -> Integer
forall a b. (a -> b) -> a -> b
$ a -> Rational
forall a b. (Real a, Fractional b) => a -> b
realToFrac a
maxV Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational
s

chooseStep :: RealFloat a => a -> (a,a) -> Rational
chooseStep :: a -> (a, a) -> Rational
chooseStep a
nsteps (a
x1,a
x2) = (Rational -> Rational -> Ordering) -> [Rational] -> Rational
forall (t :: * -> *) a.
Foldable t =>
(a -> a -> Ordering) -> t a -> a
minimumBy ((Rational -> a) -> Rational -> Rational -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing Rational -> a
forall a. Real a => a -> a
proximity) [Rational]
stepVals
  where
    delta :: a
delta = a
x2 a -> a -> a
forall a. Num a => a -> a -> a
- a
x1
    mult :: Rational
mult  | a
delta a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = Rational
1  -- Otherwise the case below will use all of memory
          | Bool
otherwise  = Rational
10 Rational -> Integer -> Rational
forall a b. (Fractional a, Integral b) => a -> b -> a
^^ ((a -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
floor (a -> Integer) -> a -> Integer
forall a b. (a -> b) -> a -> b
$ a -> a
forall a. Floating a => a -> a
log10 (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ a
delta a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
nsteps)::Integer)
    stepVals :: [Rational]
stepVals = (Rational -> Rational) -> [Rational] -> [Rational]
forall a b. (a -> b) -> [a] -> [b]
map (Rational
multRational -> Rational -> Rational
forall a. Num a => a -> a -> a
*) [Rational
0.1,Rational
0.2,Rational
0.25,Rational
0.5,Rational
1.0,Rational
2.0,Rational
2.5,Rational
5.0,Rational
10,Rational
20,Rational
25,Rational
50]
    proximity :: a -> a
proximity a
x = a -> a
forall a. Num a => a -> a
abs (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ a
delta a -> a -> a
forall a. Fractional a => a -> a -> a
/ a -> a
forall a b. (Real a, Fractional b) => a -> b
realToFrac a
x a -> a -> a
forall a. Num a => a -> a -> a
- a
nsteps

-- | Given a target number of values, and a list of input points,
--   find evenly spaced values from the set {1*X, 2*X, 2.5*X, 5*X} (where
--   X is some power of ten) that evenly cover the input points.
autoSteps :: Int -> [Double] -> [Double]
autoSteps :: Int -> [Double] -> [Double]
autoSteps Int
nSteps [Double]
vs = (Rational -> Double) -> [Rational] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map Rational -> Double
forall a. Fractional a => Rational -> a
fromRational ([Rational] -> [Double]) -> [Rational] -> [Double]
forall a b. (a -> b) -> a -> b
$ Double -> (Double, Double) -> [Rational]
forall a. RealFloat a => a -> (a, a) -> [Rational]
steps (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
nSteps) (Double, Double)
r
  where
    range :: [a] -> (Double, Double)
range []  = (Double
0,Double
1)
    range [a]
_   | Double
minV Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
maxV = (Double
minVDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
0.5,Double
minVDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
0.5)
              | Bool
otherwise    = (Double, Double)
rs
    rs :: (Double, Double)
rs@(Double
minV,Double
maxV) = ([Double] -> Double
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [Double]
ps,[Double] -> Double
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Double]
ps)
    ps :: [Double]
ps        = (Double -> Bool) -> [Double] -> [Double]
forall a. (a -> Bool) -> [a] -> [a]
filter Double -> Bool
forall a. RealFloat a => a -> Bool
isValidNumber [Double]
vs
    r :: (Double, Double)
r         = [Double] -> (Double, Double)
forall a. [a] -> (Double, Double)
range [Double]
ps

----------------------------------------------------------------------

instance (Show a, RealFloat a) => Default (LogAxisParams a) where
  def :: LogAxisParams a
def = LogAxisParams :: forall a. ([a] -> [String]) -> LogAxisParams a
LogAxisParams 
    { _loga_labelf :: [a] -> [String]
_loga_labelf = [a] -> [String]
forall d. RealFloat d => [d] -> [String]
showDs
    }

-- | Generate a log axis automatically, scaled appropriate for the
-- input data.
autoScaledLogAxis :: RealFloat a => LogAxisParams a -> AxisFn a
autoScaledLogAxis :: LogAxisParams a -> AxisFn a
autoScaledLogAxis LogAxisParams a
lap [a]
ps0 =
    (a -> Double)
-> (Double -> a)
-> ([a] -> [String])
-> ([a], [a], [a])
-> AxisData a
forall x.
Ord x =>
(x -> Double)
-> (Double -> x)
-> ([x] -> [String])
-> ([x], [x], [x])
-> AxisData x
makeAxis' (a -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac (a -> Double) -> (a -> a) -> a -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. Floating a => a -> a
log) (Double -> a
forall a b. (Real a, Fractional b) => a -> b
realToFrac (Double -> a) -> (Double -> Double) -> Double -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
exp)
              (LogAxisParams a -> [a] -> [String]
forall a. LogAxisParams a -> [a] -> [String]
_loga_labelf LogAxisParams a
lap) ([Rational] -> [a]
wrap [Rational]
rlabelvs, [Rational] -> [a]
wrap [Rational]
rtickvs, [Rational] -> [a]
wrap [Rational]
rgridvs)
        where
          ps :: [a]
ps        = (a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
filter (\a
x -> a -> Bool
forall a. RealFloat a => a -> Bool
isValidNumber a
x Bool -> Bool -> Bool
&& a
0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
x) [a]
ps0
          (a
minV,a
maxV) = ([a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [a]
ps,[a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [a]
ps)
          wrap :: [Rational] -> [a]
wrap      = (Rational -> a) -> [Rational] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map Rational -> a
forall a. Fractional a => Rational -> a
fromRational
          range :: [a] -> (a, b)
range []  = (a
3,b
30)
          range [a]
_   | a
minV a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
maxV = (a -> a
forall a b. (Real a, Fractional b) => a -> b
realToFrac (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ a
minVa -> a -> a
forall a. Fractional a => a -> a -> a
/a
3, a -> b
forall a b. (Real a, Fractional b) => a -> b
realToFrac (a -> b) -> a -> b
forall a b. (a -> b) -> a -> b
$ a
maxVa -> a -> a
forall a. Num a => a -> a -> a
*a
3)
                    | Bool
otherwise    = (a -> a
forall a b. (Real a, Fractional b) => a -> b
realToFrac (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ a
minV,   a -> b
forall a b. (Real a, Fractional b) => a -> b
realToFrac (a -> b) -> a -> b
forall a b. (a -> b) -> a -> b
$ a
maxV)
          ([Rational]
rlabelvs, [Rational]
rtickvs, [Rational]
rgridvs) = (Double, Double) -> ([Rational], [Rational], [Rational])
logTicks ([a] -> (Double, Double)
forall a b a. (Fractional a, Fractional b) => [a] -> (a, b)
range [a]
ps)


data LogAxisParams a = LogAxisParams {
    -- | The function used to show the axes labels.
    LogAxisParams a -> [a] -> [String]
_loga_labelf :: [a] -> [String]
}

{-
 Rules: Do not subdivide between powers of 10 until all powers of 10
          get a major ticks.
        Do not subdivide between powers of ten as [1,2,4,6,8,10] when
          5 gets a major ticks
          (ie the major ticks need to be a subset of the minor tick)
-}
logTicks :: Range -> ([Rational],[Rational],[Rational])
logTicks :: (Double, Double) -> ([Rational], [Rational], [Rational])
logTicks (Double
low,Double
high) = ([Rational]
major,[Rational]
minor,[Rational]
major)
 where
  pf :: RealFrac a => a -> (Integer, a)
  pf :: a -> (Integer, a)
pf = a -> (Integer, a)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction

  -- frac :: (RealFrac a, Integral b) => a -> (b, a)
  frac :: (RealFrac a) => a -> (Integer, a)
  frac :: a -> (Integer, a)
frac a
x | a
0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
b    = (Integer
a,a
b)
         | Bool
otherwise = (Integer
aInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1,a
ba -> a -> a
forall a. Num a => a -> a -> a
+a
1)
    where
      (Integer
a,a
b) = a -> (Integer, a)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction a
x

  ratio :: Double
ratio      = Double
highDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
low
  lower :: a -> [Rational] -> Rational
lower a
a [Rational]
l  = let (Integer
i,a
r) = a -> (Integer, a)
forall a. RealFrac a => a -> (Integer, a)
frac (a -> a
forall a. Floating a => a -> a
log10 a
a) in
               [Rational] -> Rational
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (Rational
1Rational -> [Rational] -> [Rational]
forall a. a -> [a] -> [a]
:(Rational -> Bool) -> [Rational] -> [Rational]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Rational
x -> a -> a
forall a. Floating a => a -> a
log10 (Rational -> a
forall a. Fractional a => Rational -> a
fromRational Rational
x) a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
r) [Rational]
l)Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
*Rational
10Rational -> Integer -> Rational
forall a b. (Fractional a, Integral b) => a -> b -> a
^^Integer
i
  upper :: a -> [Rational] -> Rational
upper a
a [Rational]
l  = let (Integer
i,a
r) = a -> (Integer, a)
forall a. RealFrac a => a -> (Integer, a)
pf (a -> a
forall a. Floating a => a -> a
log10 a
a) in
               [Rational] -> Rational
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum (Rational
10Rational -> [Rational] -> [Rational]
forall a. a -> [a] -> [a]
:(Rational -> Bool) -> [Rational] -> [Rational]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Rational
x -> a
r a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a -> a
forall a. Floating a => a -> a
log10 (Rational -> a
forall a. Fractional a => Rational -> a
fromRational Rational
x)) [Rational]
l)Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
*Rational
10Rational -> Integer -> Rational
forall a b. (Fractional a, Integral b) => a -> b -> a
^^Integer
i
               
  powers           :: (Double,Double) -> [Rational] -> [Rational]
  powers :: (Double, Double) -> [Rational] -> [Rational]
powers (Double
x,Double
y) [Rational]
l    = [ Rational
aRational -> Rational -> Rational
forall a. Num a => a -> a -> a
*Rational
10Rational -> Integer -> Rational
forall a b. (Fractional a, Integral b) => a -> b -> a
^^Integer
p | Integer
p <- [(Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
floor (Double -> Double
forall a. Floating a => a -> a
log10 Double
x))..(Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (Double -> Double
forall a. Floating a => a -> a
log10 Double
y))] :: [Integer]
                                , Rational
a <- [Rational]
l ]
  midselection :: (Double, Double) -> [Rational] -> [Rational]
midselection (Double, Double)
r [Rational]
l  = (Rational -> Bool) -> [Rational] -> [Rational]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Double, Double) -> [Rational] -> Rational -> Bool
forall a a.
(RealFrac a, RealFrac a, Floating a, Floating a) =>
(a, a) -> [Rational] -> Rational -> Bool
inRange (Double, Double)
r [Rational]
l) ((Double, Double) -> [Rational] -> [Rational]
powers (Double, Double)
r [Rational]
l)
  inRange :: (a, a) -> [Rational] -> Rational -> Bool
inRange (a
a,a
b) [Rational]
l Rational
x = (a -> [Rational] -> Rational
forall a. (RealFrac a, Floating a) => a -> [Rational] -> Rational
lower a
a [Rational]
l Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= Rational
x) Bool -> Bool -> Bool
&& (Rational
x Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= a -> [Rational] -> Rational
forall a. (RealFrac a, Floating a) => a -> [Rational] -> Rational
upper a
b [Rational]
l)
  
  logRange :: (Double, Double)
logRange = (Double -> Double
forall a. Floating a => a -> a
log10 Double
low, Double -> Double
forall a. Floating a => a -> a
log10 Double
high)
  
  roundPow :: a -> a
roundPow a
x = a
10a -> Integer -> a
forall a b. (Fractional a, Integral b) => a -> b -> a
^^(a -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round a
x :: Integer)
  
  major :: [Rational]
major | Double
17.5 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double -> Double
forall a. Floating a => a -> a
log10 Double
ratio = (Rational -> Rational) -> [Rational] -> [Rational]
forall a b. (a -> b) -> [a] -> [b]
map Rational -> Rational
forall a a. (RealFrac a, Fractional a) => a -> a
roundPow ([Rational] -> [Rational]) -> [Rational] -> [Rational]
forall a b. (a -> b) -> a -> b
$
                               Double -> (Double, Double) -> [Rational]
forall a. RealFloat a => a -> (a, a) -> [Rational]
steps (Double -> Double -> Double
forall a. Ord a => a -> a -> a
min Double
5 (Double -> Double
forall a. Floating a => a -> a
log10 Double
ratio)) (Double, Double)
logRange
        | Double
12 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double -> Double
forall a. Floating a => a -> a
log10 Double
ratio   = (Rational -> Rational) -> [Rational] -> [Rational]
forall a b. (a -> b) -> [a] -> [b]
map Rational -> Rational
forall a a. (RealFrac a, Fractional a) => a -> a
roundPow ([Rational] -> [Rational]) -> [Rational] -> [Rational]
forall a b. (a -> b) -> a -> b
$
                               Double -> (Double, Double) -> [Rational]
forall a. RealFloat a => a -> (a, a) -> [Rational]
steps (Double -> Double
forall a. Floating a => a -> a
log10 Double
ratio Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
5) (Double, Double)
logRange
        | Double
6 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double -> Double
forall a. Floating a => a -> a
log10 Double
ratio    = (Rational -> Rational) -> [Rational] -> [Rational]
forall a b. (a -> b) -> [a] -> [b]
map Rational -> Rational
forall a a. (RealFrac a, Fractional a) => a -> a
roundPow ([Rational] -> [Rational]) -> [Rational] -> [Rational]
forall a b. (a -> b) -> a -> b
$
                               Double -> (Double, Double) -> [Rational]
forall a. RealFloat a => a -> (a, a) -> [Rational]
steps (Double -> Double
forall a. Floating a => a -> a
log10 Double
ratio Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2) (Double, Double)
logRange
        | Double
3 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double -> Double
forall a. Floating a => a -> a
log10 Double
ratio    = (Double, Double) -> [Rational] -> [Rational]
midselection (Double
low,Double
high) [Rational
1,Rational
10]
        | Double
20 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
ratio         = (Double, Double) -> [Rational] -> [Rational]
midselection (Double
low,Double
high) [Rational
1,Rational
5,Rational
10]
        | Double
6 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
ratio          = (Double, Double) -> [Rational] -> [Rational]
midselection (Double
low,Double
high) [Rational
1,Rational
2,Rational
4,Rational
6,Rational
8,Rational
10]
        | Double
3 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
ratio          = (Double, Double) -> [Rational] -> [Rational]
midselection (Double
low,Double
high) [Rational
1..Rational
10]
        | Bool
otherwise          = Double -> (Double, Double) -> [Rational]
forall a. RealFloat a => a -> (a, a) -> [Rational]
steps Double
5 (Double
low,Double
high)

  (Rational
l',Rational
h')   = ([Rational] -> Rational
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [Rational]
major, [Rational] -> Rational
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Rational]
major)
  (Double
dl',Double
dh') = (Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
l', Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
h')
  ratio' :: Double
  ratio' :: Double
ratio' = Rational -> Double
forall a. Fractional a => Rational -> a
fromRational (Rational
h'Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/Rational
l')
  filterX :: [Rational] -> [Rational]
filterX = (Rational -> Bool) -> [Rational] -> [Rational]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Rational
x -> Rational
l'Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<=Rational
x Bool -> Bool -> Bool
&& Rational
x Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<=Rational
h') ([Rational] -> [Rational])
-> ([Rational] -> [Rational]) -> [Rational] -> [Rational]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Double, Double) -> [Rational] -> [Rational]
powers (Double
dl',Double
dh') 
  
  minor :: [Rational]
minor | Double
50 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double -> Double
forall a. Floating a => a -> a
log10 Double
ratio' = (Rational -> Rational) -> [Rational] -> [Rational]
forall a b. (a -> b) -> [a] -> [b]
map Rational -> Rational
forall a a. (RealFrac a, Fractional a) => a -> a
roundPow ([Rational] -> [Rational]) -> [Rational] -> [Rational]
forall a b. (a -> b) -> a -> b
$
                              Double -> (Double, Double) -> [Rational]
forall a. RealFloat a => a -> (a, a) -> [Rational]
steps Double
50 (Double -> Double
forall a. Floating a => a -> a
log10 Double
dl', Double -> Double
forall a. Floating a => a -> a
log10 Double
dh')
        | Double
6 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double -> Double
forall a. Floating a => a -> a
log10 Double
ratio'  = [Rational] -> [Rational]
filterX [Rational
1,Rational
10]
        | Double
3 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double -> Double
forall a. Floating a => a -> a
log10 Double
ratio'  = [Rational] -> [Rational]
filterX [Rational
1,Rational
5,Rational
10]
        | Double
6 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
ratio'        = [Rational] -> [Rational]
filterX [Rational
1..Rational
10]
        | Double
3 Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
ratio'        = [Rational] -> [Rational]
filterX [Rational
1,Rational
1.2..Rational
10]
        | Bool
otherwise         = Double -> (Double, Double) -> [Rational]
forall a. RealFloat a => a -> (a, a) -> [Rational]
steps Double
50 (Double
dl', Double
dh')


log10 :: (Floating a) => a -> a
log10 :: a -> a
log10 = a -> a -> a
forall a. Floating a => a -> a -> a
logBase a
10

$( makeLenses ''LinearAxisParams )
$( makeLenses ''LogAxisParams )