{-# LANGUAGE ConstraintKinds   #-}
{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MonoLocalBinds    #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Data.Array.Accelerate.Classes.RealFrac (
  RealFrac(..),
  div', mod', divMod',
) where
import Data.Array.Accelerate.Array.Sugar
import Data.Array.Accelerate.Smart
import Data.Array.Accelerate.Type
import Data.Array.Accelerate.Classes.Eq
import Data.Array.Accelerate.Classes.Floating
import Data.Array.Accelerate.Classes.Fractional
import Data.Array.Accelerate.Classes.Num
import Data.Array.Accelerate.Classes.Real
import Data.Array.Accelerate.Classes.ToFloating
import Text.Printf
import Prelude                                                      ( ($), String, error, unlines )
import qualified Prelude                                            as P
div' :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp a -> Exp b
div' n d = floor (n / d)
mod' :: (Floating a, RealFrac a, ToFloating Int a) => Exp a -> Exp a -> Exp a
mod' n d = n - (toFloating f) * d
  where
    f :: Exp Int
    f = div' n d
divMod'
    :: (Floating a, RealFrac a, Num b, IsIntegral b, ToFloating b a)
    => Exp a
    -> Exp a
    -> (Exp b, Exp a)
divMod' n d = (f, n - (toFloating f) * d)
  where
    f = div' n d
class (Real a, Fractional a) => RealFrac a where
  
  
  
  
  
  
  
  
  
  
  properFraction :: (Num b, ToFloating b a, IsIntegral b) => Exp a -> (Exp b, Exp a)
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  truncate       :: (Elt b, IsIntegral b) => Exp a -> Exp b
  
  
  round          :: (Elt b, IsIntegral b) => Exp a -> Exp b
  
  ceiling        :: (Elt b, IsIntegral b) => Exp a -> Exp b
  
  floor          :: (Elt b, IsIntegral b) => Exp a -> Exp b
instance RealFrac Half where
  properFraction  = defaultProperFraction
  truncate        = mkTruncate
  round           = mkRound
  ceiling         = mkCeiling
  floor           = mkFloor
instance RealFrac Float where
  properFraction  = defaultProperFraction
  truncate        = mkTruncate
  round           = mkRound
  ceiling         = mkCeiling
  floor           = mkFloor
instance RealFrac Double where
  properFraction  = defaultProperFraction
  truncate        = mkTruncate
  round           = mkRound
  ceiling         = mkCeiling
  floor           = mkFloor
instance RealFrac CFloat where
  properFraction  = defaultProperFraction
  truncate        = mkTruncate
  round           = mkRound
  ceiling         = mkCeiling
  floor           = mkFloor
instance RealFrac CDouble where
  properFraction  = defaultProperFraction
  truncate        = mkTruncate
  round           = mkRound
  ceiling         = mkCeiling
  floor           = mkFloor
defaultProperFraction
    :: (ToFloating a b, RealFrac b, IsIntegral a, Num a, Floating b)
    => Exp b
    -> (Exp a, Exp b)
defaultProperFraction x =
  untup2 $ Exp
         $ Cond (x == 0) (tup2 (0, 0))
                         (tup2 (n, f))
  where
    n = truncate x
    f = x - toFloating n
instance RealFrac a => P.RealFrac (Exp a) where
  properFraction = preludeError "properFraction"
  truncate       = preludeError "truncate"
  round          = preludeError "round"
  ceiling        = preludeError "ceiling"
  floor          = preludeError "floor"
preludeError :: String -> a
preludeError x
  = error
  $ unlines [ printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x x
            , ""
            , "These Prelude.RealFrac instances are present only to fulfil superclass"
            , "constraints for subsequent classes in the standard Haskell numeric hierarchy."
            ]