\section{RSAGL.Time}
RSAGL.Time provides a fixedpoint (as opposed to a floatingpoint number) representation of time.
This is necessary because the Float and Double types are inadequate to precisely represent large
quantities of time.
This time library is designed to support realtime animation.
\begin{code}
module RSAGL.Time
(Time,
Rate,
Acceleration,
Frequency,
fps30,
fps60,
fps120,
minute,
day,
month,
year,
fromSeconds,
toSeconds,
getTime,
cyclical,
cyclical',
over,
rate,
time,
perSecond,
per,
interval,
withTime)
where
import RSAGL.AbstractVector
import System.Time
import Control.Monad
import Data.Fixed
import Data.Ratio
import RSAGL.Affine
newtype Time = Time Pico deriving (Show,Eq,Ord)
newtype Rate a = Rate a deriving (Show,Eq,Ord,AffineTransformable)
type Acceleration a = Rate (Rate a)
type Frequency = Rate Double
instance AbstractZero Time where
zero = Time 0.0
instance AbstractAdd Time Time where
add (Time a) (Time b) = Time $ a `add` b
instance AbstractSubtract Time Time where
sub (Time a) (Time b) = Time $ a `sub` b
instance AbstractScale Time where
scalarMultiply d (Time t) = Time $ realToFrac d * t
instance AbstractVector Time
instance (AbstractZero a) => AbstractZero (Rate a) where
zero = Rate zero
instance (AbstractAdd a a) => AbstractAdd (Rate a) (Rate a) where
add (Rate a) (Rate b) = Rate $ a `add` b
instance (AbstractSubtract a a) => AbstractSubtract (Rate a) (Rate a) where
sub (Rate a) (Rate b) = Rate $ a `sub` b
instance (AbstractScale a) => AbstractScale (Rate a) where
scalarMultiply d (Rate r) = Rate $ scalarMultiply d r
instance (AbstractVector a) => AbstractVector (Rate a)
\end{code}
\subsection{Getting and Constructing Time}
getTime gets the current, absolute time, using Haskell's standard time facilities.
\begin{code}
minute :: Time
minute = fromSeconds 60
hour :: Time
hour = scalarMultiply 60 minute
day :: Time
day = scalarMultiply 24 hour
month :: Time
month = scalarMultiply 30.43 day
year :: Time
year = scalarMultiply 365.25 month
fps30 :: Frequency
fps30 = perSecond 24
fps60 :: Frequency
fps60 = perSecond 60
fps120 :: Frequency
fps120 = perSecond 120
fromSeconds :: Double -> Time
fromSeconds = Time . realToFrac
toSeconds :: Time -> Double
toSeconds (Time t) = realToFrac t
getTime :: IO Time
getTime =
do (TOD secs picos) <- getClockTime
return $ Time $ fromIntegral secs + fromRational (picos%(resolution (undefined :: E12)))
\end{code}
\subsection{Modulo Division for Time}
\texttt{cyclical} answers the amount of time into a cycle. \texttt{cyclical'} answers the fraction of time into a cycle,
in the range \texttt{0 <= x <= 1}.
\begin{code}
cyclical :: Time -> Time -> Time
cyclical (Time t) (Time k) = Time $ t `mod'` k
cyclical' :: Time -> Time -> Double
cyclical' t k = (toSeconds $ t `cyclical` k) / toSeconds k
\end{code}
\subsection{Rate as Change over Time}
\begin{code}
over :: (AbstractVector a) => Rate a -> Time -> a
over (Rate a) (Time t) = realToFrac t `scalarMultiply` a
rate :: (AbstractVector a) => (a,Time) -> (a,Time) -> Rate a
rate (x,t1) (y,t2) = (y `sub` x) `per` (t2 `sub` t1)
perSecond :: a -> Rate a
perSecond a = Rate a
per :: (AbstractVector a) => a -> Time -> Rate a
per a (Time t) = Rate $ realToFrac (recip t) `scalarMultiply` a
interval :: Frequency -> Time
interval (Rate x) = fromSeconds $ recip x
time :: Double -> Rate Double -> Time
time d r = interval $ withTime (fromSeconds 1) (/d) r
withTime :: (AbstractVector a,AbstractVector b) => Time -> (a -> b) -> Rate a -> Rate b
withTime t f = (`per` t) . f . (`over` t)
\end{code}