{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}

module Zwirn.Core.Time where

{-
    Time.hs - automated differentiation for time
    Copyright (C) 2025, Martin Gius

    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
-}

data Time
  = Time {Time -> Rational
tTime :: Rational, Time -> Rational
tDiff :: Rational}
  deriving (Time -> Time -> Bool
(Time -> Time -> Bool) -> (Time -> Time -> Bool) -> Eq Time
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Time -> Time -> Bool
== :: Time -> Time -> Bool
$c/= :: Time -> Time -> Bool
/= :: Time -> Time -> Bool
Eq, Eq Time
Eq Time =>
(Time -> Time -> Ordering)
-> (Time -> Time -> Bool)
-> (Time -> Time -> Bool)
-> (Time -> Time -> Bool)
-> (Time -> Time -> Bool)
-> (Time -> Time -> Time)
-> (Time -> Time -> Time)
-> Ord Time
Time -> Time -> Bool
Time -> Time -> Ordering
Time -> Time -> Time
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
$ccompare :: Time -> Time -> Ordering
compare :: Time -> Time -> Ordering
$c< :: Time -> Time -> Bool
< :: Time -> Time -> Bool
$c<= :: Time -> Time -> Bool
<= :: Time -> Time -> Bool
$c> :: Time -> Time -> Bool
> :: Time -> Time -> Bool
$c>= :: Time -> Time -> Bool
>= :: Time -> Time -> Bool
$cmax :: Time -> Time -> Time
max :: Time -> Time -> Time
$cmin :: Time -> Time -> Time
min :: Time -> Time -> Time
Ord)

instance Show Time where
  show :: Time -> String
show (Time Rational
x Rational
_) = Rational -> String
forall a. Show a => a -> String
show Rational
x

showAll :: Time -> String
showAll :: Time -> String
showAll (Time Rational
x Rational
y) = String
"(" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Rational -> String
forall a. Show a => a -> String
show Rational
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"," String -> ShowS
forall a. [a] -> [a] -> [a]
++ Rational -> String
forall a. Show a => a -> String
show Rational
y String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

instance Num Time where
  Time Rational
x Rational
x' + :: Time -> Time -> Time
+ Time Rational
y Rational
y' = Rational -> Rational -> Time
Time (Rational
x Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
y) (Rational
x' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
y')
  Time Rational
x Rational
x' * :: Time -> Time -> Time
* Time Rational
y Rational
y' = Rational -> Rational -> Time
Time (Rational
x Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
y) (Rational
y' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
x Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
x' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
y)
  fromInteger :: Integer -> Time
fromInteger Integer
x = Rational -> Rational -> Time
Time (Integer -> Rational
forall a. Num a => Integer -> a
fromInteger Integer
x) Rational
0
  negate :: Time -> Time
negate (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Num a => a -> a
negate Rational
x) (Rational -> Rational
forall a. Num a => a -> a
negate Rational
x')
  signum :: Time -> Time
signum (Time Rational
x Rational
_) = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Num a => a -> a
signum Rational
x) Rational
0
  abs :: Time -> Time
abs (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Num a => a -> a
abs Rational
x) (Rational
x' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational -> Rational
forall a. Num a => a -> a
signum Rational
x)

instance Enum Time where
  toEnum :: Int -> Time
toEnum Int
i = Rational -> Rational -> Time
Time (Int -> Rational
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i) Rational
0
  fromEnum :: Time -> Int
fromEnum (Time Rational
i Rational
_) = Rational -> Int
forall a. Enum a => a -> Int
fromEnum Rational
i

instance Fractional Time where
  fromRational :: Rational -> Time
fromRational Rational
x = Rational -> Rational -> Time
Time Rational
x Rational
0
  recip :: Time -> Time
recip (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Fractional a => a -> a
recip Rational
x) (-(Rational
x' Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational
x Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
x))

instance Real Time where
  toRational :: Time -> Rational
toRational (Time Rational
x Rational
x') = Rational
x

instance RealFrac Time where
  properFraction :: forall b. Integral b => Time -> (b, Time)
properFraction (Time Rational
x Rational
x') = (b
i, Rational -> Rational -> Time
Time Rational
p Rational
x')
    where
      (b
i, Rational
p) = Rational -> (b, Rational)
forall b. Integral b => Rational -> (b, Rational)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Rational
x

instance Floating Rational where
  pi :: Rational
pi = Double -> Rational
forall a. Real a => a -> Rational
toRational Double
forall a. Floating a => a
pi
  exp :: Rational -> Rational
exp = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational)
-> (Rational -> Double) -> Rational -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
exp (Double -> Double) -> (Rational -> Double) -> Rational -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Double
forall a. Fractional a => Rational -> a
fromRational
  log :: Rational -> Rational
log = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational)
-> (Rational -> Double) -> Rational -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
log (Double -> Double) -> (Rational -> Double) -> Rational -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Double
forall a. Fractional a => Rational -> a
fromRational
  sin :: Rational -> Rational
sin = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational)
-> (Rational -> Double) -> Rational -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
sin (Double -> Double) -> (Rational -> Double) -> Rational -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Double
forall a. Fractional a => Rational -> a
fromRational
  cos :: Rational -> Rational
cos = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational)
-> (Rational -> Double) -> Rational -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
cos (Double -> Double) -> (Rational -> Double) -> Rational -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Double
forall a. Fractional a => Rational -> a
fromRational
  asin :: Rational -> Rational
asin = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational)
-> (Rational -> Double) -> Rational -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
asin (Double -> Double) -> (Rational -> Double) -> Rational -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Double
forall a. Fractional a => Rational -> a
fromRational
  acos :: Rational -> Rational
acos = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational)
-> (Rational -> Double) -> Rational -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
acos (Double -> Double) -> (Rational -> Double) -> Rational -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Double
forall a. Fractional a => Rational -> a
fromRational
  atan :: Rational -> Rational
atan = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational)
-> (Rational -> Double) -> Rational -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
atan (Double -> Double) -> (Rational -> Double) -> Rational -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Double
forall a. Fractional a => Rational -> a
fromRational
  sinh :: Rational -> Rational
sinh = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational)
-> (Rational -> Double) -> Rational -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
sinh (Double -> Double) -> (Rational -> Double) -> Rational -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Double
forall a. Fractional a => Rational -> a
fromRational
  cosh :: Rational -> Rational
cosh = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational)
-> (Rational -> Double) -> Rational -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
cosh (Double -> Double) -> (Rational -> Double) -> Rational -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Double
forall a. Fractional a => Rational -> a
fromRational
  asinh :: Rational -> Rational
asinh = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational)
-> (Rational -> Double) -> Rational -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
asinh (Double -> Double) -> (Rational -> Double) -> Rational -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Double
forall a. Fractional a => Rational -> a
fromRational
  acosh :: Rational -> Rational
acosh = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational)
-> (Rational -> Double) -> Rational -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
acosh (Double -> Double) -> (Rational -> Double) -> Rational -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Double
forall a. Fractional a => Rational -> a
fromRational
  atanh :: Rational -> Rational
atanh = Double -> Rational
forall a. Real a => a -> Rational
toRational (Double -> Rational)
-> (Rational -> Double) -> Rational -> Rational
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double
forall a. Floating a => a -> a
atanh (Double -> Double) -> (Rational -> Double) -> Rational -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> Double
forall a. Fractional a => Rational -> a
fromRational

instance Floating Time where
  pi :: Time
pi = Rational -> Rational -> Time
Time Rational
forall a. Floating a => a
pi Rational
0
  exp :: Time -> Time
exp (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
exp Rational
x) (Rational
x' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational -> Rational
forall a. Floating a => a -> a
exp Rational
x)
  log :: Time -> Time
log (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
log Rational
x) (Rational
x' Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational
x)
  sqrt :: Time -> Time
sqrt (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
sqrt Rational
x) (Rational
x' Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ (Rational
2 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational -> Rational
forall a. Floating a => a -> a
sqrt Rational
x))
  sin :: Time -> Time
sin (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
sin Rational
x) (Rational
x' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational -> Rational
forall a. Floating a => a -> a
cos Rational
x)
  cos :: Time -> Time
cos (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
cos Rational
x) (Rational
x' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* (-Rational -> Rational
forall a. Floating a => a -> a
sin Rational
x))
  asin :: Time -> Time
asin (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
asin Rational
x) (Rational
x' Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational -> Rational
forall a. Floating a => a -> a
sqrt (Rational
1 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Rational
x Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
x))
  acos :: Time -> Time
acos (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
acos Rational
x) (Rational
x' Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ (-Rational -> Rational
forall a. Floating a => a -> a
sqrt (Rational
1 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Rational
x Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
x)))
  atan :: Time -> Time
atan (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
atan Rational
x) (Rational
1 Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ ((Rational
x' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
x') Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
1))
  sinh :: Time -> Time
sinh (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
sinh Rational
x) (Rational -> Rational
forall a. Floating a => a -> a
cosh Rational
x')
  cosh :: Time -> Time
cosh (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
cosh Rational
x) (Rational -> Rational
forall a. Floating a => a -> a
sinh Rational
x')
  asinh :: Time -> Time
asinh (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
asinh Rational
x) (Rational
1 Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational -> Rational
forall a. Floating a => a -> a
sqrt ((Rational
x' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
x') Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
1))
  acosh :: Time -> Time
acosh (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
acosh Rational
x) (Rational
1 Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational -> Rational
forall a. Floating a => a -> a
sqrt (Rational
x' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Rational
1) Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational -> Rational
forall a. Floating a => a -> a
sqrt (Rational
x' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
1))
  atanh :: Time -> Time
atanh (Time Rational
x Rational
x') = Rational -> Rational -> Time
Time (Rational -> Rational
forall a. Floating a => a -> a
atanh Rational
x) (Rational
1 Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ (Rational
1 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- (Rational
x' Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
x')))