1 {-# LANGUAGE CPP #-}
    2 {-# OPTIONS_GHC -fno-warn-missing-methods #-}
    3 -- |
    4 -- Module      : Data.Text.Fusion.Internal
    5 -- Copyright   : (c) Roman Leshchinskiy 2008,
    6 --               (c) Bryan O'Sullivan 2009
    7 --
    8 -- License     : BSD-style
    9 -- Maintainer  : bos@serpentine.com, rtomharper@googlemail.com,
   10 --               duncan@haskell.org
   11 -- Stability   : experimental
   12 -- Portability : portable
   13 --
   14 -- Size hints.
   15 
   16 module Data.Text.Fusion.Size
   17     (
   18       Size
   19     , exactly
   20     , exactSize
   21     , maxSize
   22     , unknownSize
   23     , smaller
   24     , larger
   25     , toMax
   26     , upperBound
   27     , lowerBound
   28     , isEmpty
   29     ) where
   30 
   31 #if defined(ASSERTS)
   32 import Control.Exception (assert)
   33 #endif
   34 
   35 data Size = Exact {-# UNPACK #-} !Int -- ^ Exact size.
   36           | Max   {-# UNPACK #-} !Int -- ^ Upper bound on size.
   37           | Unknown                   -- ^ Unknown size.
   38             deriving (-- never entered-- never enteredEq, -- never entered-- never enteredShow)
   39 
   40 exactly :: Size -> Maybe Int
   41 -- entered 200 timesexactly (Exact n) = Just n
   42 exactly _         = Nothing
   43 {-# INLINE exactly #-}
   44 
   45 exactSize :: Int -> Size
   46 -- entered 243 timesexactSize n =
   47 #if defined(ASSERTS)
   48     assert (n >= 0)
   49 #endif
   50     Exact n
   51 {-# INLINE exactSize #-}
   52 
   53 maxSize :: Int -> Size
   54 -- entered 260,743 timesmaxSize n =
   55 #if defined(ASSERTS)
   56     assert (n >= 0)
   57 #endif
   58     Max n
   59 {-# INLINE maxSize #-}
   60 
   61 unknownSize :: Size
   62 -- entered 56,320 timesunknownSize = Unknown
   63 {-# INLINE unknownSize #-}
   64 
   65 instance Num Size where
   66     -- entered 52,191 times(+) = addSize
   67     -- entered 26,800 times(-) = subtractSize
   68     -- entered 1181 times(*) = mulSize
   69 
   70     -- entered 100,373 timesfromInteger = f where f = Exact . fromInteger
   71                           {-# INLINE f #-}
   72 
   73 addSize :: Size -> Size -> Size
   74 -- entered 57,930 timesaddSize (Exact m) (Exact n) = Exact (m+n)
   75 addSize (Exact m) (Max   n) = Max   (m+n)
   76 addSize (Max   m) (Exact n) = Max   (m+n)
   77 addSize (Max   m) (Max   n) = Max   (m+n)
   78 addSize _          _       = Unknown
   79 {-# INLINE addSize #-}
   80 
   81 subtractSize :: Size -> Size -> Size
   82 -- entered 26,800 timessubtractSize   (Exact m) (Exact n) = Exact (max (m-n) 0)
   83 subtractSize   (Exact m) (Max   _) = Max   m
   84 subtractSize   (Max   m) (Exact n) = Max   (max (m-n) 0)
   85 subtractSize a@(Max   _) (Max   _) = a
   86 subtractSize a@(Max   _) Unknown   = a
   87 subtractSize _         _           = Unknown
   88 {-# INLINE subtractSize #-}
   89 
   90 mulSize :: Size -> Size -> Size
   91 -- entered 1181 timesmulSize (Exact m) (Exact n) = Exact (m*n)
   92 mulSize (Exact m) (Max   n) = Max   (m*n)
   93 mulSize (Max   m) (Exact n) = Max   (m*n)
   94 mulSize (Max   m) (Max   n) = Max   (m*n)
   95 mulSize _          _       = Unknown
   96 {-# INLINE mulSize #-}
   97 
   98 -- | Minimum of two size hints.
   99 smaller :: Size -> Size -> Size
  100 -- entered 10,740 timessmaller   (Exact m) (Exact n) = Exact (m `min` n)
  101 smaller   (Exact m) (Max   n) = Max   (m `min` n)
  102 smaller   (Exact m) Unknown   = Max   m
  103 smaller   (Max   m) (Exact n) = Max   (m `min` n)
  104 smaller   (Max   m) (Max   n) = Max   (m `min` n)
  105 smaller a@(Max   _) Unknown   = a
  106 smaller   Unknown   (Exact n) = Max   n
  107 smaller   Unknown   (Max   n) = Max   n
  108 smaller   Unknown   Unknown   = Unknown
  109 {-# INLINE smaller #-}
  110 
  111 -- | Maximum of two size hints.
  112 larger :: Size -> Size -> Size
  113 -- entered 6886 timeslarger   (Exact m)   (Exact n)             = Exact (m `max` n)
  114 larger a@(Exact m) b@(Max   n) | m >= n    = a
  115                                | otherwise = b
  116 larger a@(Max   m) b@(Exact n) | n >= m    = b
  117                                | otherwise = a
  118 larger   (Max   m)   (Max   n)             = Max   (m `max` n)
  119 larger _             _                     = Unknown
  120 {-# INLINE larger #-}
  121 
  122 -- | Convert a size hint to an upper bound.
  123 toMax :: Size -> Size
  124 -- never enteredtoMax   (Exact n) = Max n
  125 toMax a@(Max   _) = a
  126 toMax   Unknown   = Unknown
  127 {-# INLINE toMax #-}
  128 
  129 -- | Compute the minimum size from a size hint.
  130 lowerBound :: Size -> Int
  131 -- never enteredlowerBound (Exact n) = n
  132 lowerBound _         = 0
  133 {-# INLINE lowerBound #-}
  134 
  135 -- | Compute the maximum size from a size hint, if possible.
  136 upperBound :: Int -> Size -> Int
  137 -- entered 146,350 timesupperBound _ (Exact n) = n
  138 upperBound _ (Max   n) = n
  139 upperBound k _         = k
  140 {-# INLINE upperBound #-}
  141 
  142 isEmpty :: Size -> Bool
  143 -- entered 72,605 timesisEmpty (Exact n) = n <= 0
  144 isEmpty (Max   n) = n <= 0
  145 isEmpty _         = False
  146 {-# INLINE isEmpty #-}