{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} #include "thyme.h" -- | FOR INTERNAL USE ONLY. module Data.Thyme.Internal.Micro where import Prelude import Control.DeepSeq import Data.AdditiveGroup import Data.Basis import Data.Data import Data.Int import Data.Ix import Data.Ratio #if __GLASGOW_HASKELL__ == 704 import qualified Data.Vector.Generic import qualified Data.Vector.Generic.Mutable #endif import Data.Vector.Unboxed.Deriving import Data.VectorSpace import GHC.Generics (Generic) import System.Random import Test.QuickCheck #if !SHOW_INTERNAL import Control.Monad import Data.Char import Data.Thyme.Format.Internal import Numeric import Text.ParserCombinators.ReadPrec import Text.ParserCombinators.ReadP import Text.Read #endif newtype Micro = Micro Int64 deriving (INSTANCES_MICRO) derivingUnbox "Micro" [t| Micro -> Int64 |] [| \ (Micro a) -> a |] [| Micro |] #if SHOW_INTERNAL deriving instance Show Micro deriving instance Read Micro #else instance Show Micro where {-# INLINEABLE showsPrec #-} showsPrec _ (Micro a) = sign . shows si . frac where sign = if a < 0 then (:) '-' else id (si, su) = abs a `divMod` 1000000 frac = if su == 0 then id else (:) '.' . fills06 su . drops0 su instance Read Micro where {-# INLINEABLE readPrec #-} readPrec = lift $ do sign <- (char '-' >> return negate) `mplus` return id s <- readS_to_P readDec us <- (`mplus` return 0) $ do _ <- char '.' [(us10, "")] <- (readDec . take 7 . (++ "000000")) `fmap` munch1 isDigit return (div (us10 + 5) 10) return . Micro . sign $ s * 1000000 + us #endif {-# INLINE microQuotRem #-} {-# INLINE microDivMod #-} microQuotRem, microDivMod :: Micro -> Micro -> (Int64, Micro) microQuotRem (Micro a) (Micro b) = (n, Micro f) where (n, f) = quotRem a b microDivMod (Micro a) (Micro b) = (n, Micro f) where (n, f) = divMod a b instance AdditiveGroup Micro where {-# INLINE zeroV #-} zeroV = Micro 0 {-# INLINE (^+^) #-} (^+^) = \ (Micro a) (Micro b) -> Micro (a + b) {-# INLINE negateV #-} negateV = \ (Micro a) -> Micro (negate a) instance VectorSpace Micro where type Scalar Micro = Rational {-# INLINEABLE (*^) #-} s *^ Micro a = Micro . fromInteger $ case compare (2 * abs r) (denominator s) of LT -> n EQ -> if even n then n else m GT -> m where (n, r) = quotRem (toInteger a * numerator s) (denominator s) m = if r < 0 then n - 1 else n + 1 instance HasBasis Micro where type Basis Micro = () {-# INLINE basisValue #-} basisValue = \ _ -> Micro 1000000 {-# INLINE decompose #-} decompose = \ (Micro a) -> [((), fromIntegral a % 1000000)] {-# INLINE decompose' #-} decompose' = \ (Micro a) _ -> fromIntegral a % 1000000