module Data.Connection.Float (
f32i08
, f32i16
, f32i32
, i32f32
, f64i08
, f64i16
, f64i32
, f64i64
, i64f64
) where
import Data.Connection
import Data.Float
import Data.Int
import Data.Prd
import Data.Prd.Nan
import Data.Semifield
import Data.Semilattice
import Data.Semilattice.Top
import Data.Semiring
import GHC.Real hiding ((^),(/))
import Prelude as P hiding (Ord(..), Num(..), Fractional(..), (^), Bounded)
f32i08 :: Trip Float (Extended Int8)
f32i08 = Trip (liftNan f) (nan' g) (liftNan h) where
f x | x > imax = Just Top
| x =~ ninf = Nothing
| x < imin = fin bottom
| otherwise = fin $ P.ceiling x
g = bounded ninf P.fromIntegral pinf
h x | x =~ pinf = Just Top
| x > imax = fin top
| x < imin = Nothing
| otherwise = fin $ P.floor x
imax = 127
imin = -128
f32i16 :: Trip Float (Extended Int16)
f32i16 = Trip (liftNan f) (nan' g) (liftNan h) where
f x | x > imax = Just Top
| x =~ ninf = Nothing
| x < imin = fin bottom
| otherwise = fin $ P.ceiling x
g = bounded ninf P.fromIntegral pinf
h x | x =~ pinf = Just Top
| x > imax = fin top
| x < imin = Nothing
| otherwise = fin $ P.floor x
imax = 32767
imin = -32768
f32i32 :: Conn Float (Nan Int32)
f32i32 = Conn (liftNan f) (nan' g) where
f x | abs x <= 2**24-1 = P.ceiling x
| otherwise = if x >= 0 then 2^24 else minimal
g i | abs' i <= 2^24-1 = fromIntegral i
| otherwise = if i >= 0 then 1/0 else -2**24
i32f32 :: Conn (Nan Int32) Float
i32f32 = Conn (nan' g) (liftNan f) where
f x | abs x <= 2**24-1 = P.floor x
| otherwise = if x >= 0 then maximal else -2^24
g i | abs i <= 2^24-1 = fromIntegral i
| otherwise = if i >= 0 then 2**24 else -1/0
f64i08 :: Trip Double (Extended Int8)
f64i08 = Trip (liftNan f) (nan' g) (liftNan h) where
f x | x > imax = Just Top
| x =~ ninf = Nothing
| x < imin = fin bottom
| otherwise = fin $ P.ceiling x
g = bounded ninf P.fromIntegral pinf
h x | x =~ pinf = Just Top
| x > imax = fin top
| x < imin = Nothing
| otherwise = fin $ P.floor x
imax = 127
imin = -128
f64i16 :: Trip Double (Extended Int16)
f64i16 = Trip (liftNan f) (nan' g) (liftNan h) where
f x | x > imax = Just Top
| x =~ ninf = Nothing
| x < imin = fin bottom
| otherwise = fin $ P.ceiling x
g = bounded ninf P.fromIntegral pinf
h x | x =~ pinf = Just Top
| x > imax = fin top
| x < imin = Nothing
| otherwise = fin $ P.floor x
imax = 32767
imin = -32768
f64i32 :: Trip Double (Extended Int32)
f64i32 = Trip (liftNan f) (nan' g) (liftNan h) where
f x | x > imax = Just Top
| x =~ ninf = Nothing
| x < imin = fin bottom
| otherwise = fin $ P.ceiling x
g = bounded ninf P.fromIntegral pinf
h x | x =~ pinf = Just Top
| x > imax = fin top
| x < imin = Nothing
| otherwise = fin $ P.floor x
imax = 2147483647
imin = -2147483648
f64i64 :: Conn Double (Nan Int64)
f64i64 = Conn (liftNan f) (nan' g) where
f x | abs x <= 2**53-1 = P.ceiling x
| otherwise = if x >= 0 then 2^53 else minimal
g i | abs' i <= 2^53-1 = fromIntegral i
| otherwise = if i >= 0 then 1/0 else -2**53
i64f64 :: Conn (Nan Int64) Double
i64f64 = Conn (nan' g) (liftNan f) where
f x | abs x <= 2**53-1 = P.floor x
| otherwise = if x >= 0 then maximal else -2^53
g i | abs i <= 2^53-1 = fromIntegral i
| otherwise = if i >= 0 then 2**53 else -1/0
abs' :: Ord a => Minimal a => Ring a => a -> a
abs' x = if x =~ minimal then abs (x+one) else abs x