{-# LANGUAGE RebindableSyntax #-}
module Algebra.RealTranscendental where

import qualified Algebra.Transcendental      as Trans
import qualified Algebra.RealField           as RealField

import Algebra.Transcendental (atan, pi)
import Algebra.Field          ((/))
import Algebra.Ring           (fromInteger)
import Algebra.Additive       ((+), negate)

import Data.Bool.HT (select, )

import qualified Prelude as P
import NumericPrelude.Base



{-|
This class collects all functions for _scalar_ floating point numbers.
E.g. computing 'atan2' for complex floating numbers makes certainly no sense.
-}
class (RealField.C a, Trans.C a) => C a where
    atan2 :: a -> a -> a

    atan2 a
y a
x = a -> [(Bool, a)] -> a
forall a. a -> [(Bool, a)] -> a
select a
0   -- must be after the other double zero tests
      [(a
xa -> a -> Bool
forall a. Ord a => a -> a -> Bool
>a
0,          a -> a
forall a. C a => a -> a
atan (a
ya -> a -> a
forall a. C a => a -> a -> a
/a
x)),
       (a
xa -> a -> Bool
forall a. Eq a => a -> a -> Bool
==a
0 Bool -> Bool -> Bool
&& a
ya -> a -> Bool
forall a. Ord a => a -> a -> Bool
>a
0,  a
forall a. C a => a
pia -> a -> a
forall a. C a => a -> a -> a
/a
2),
       (a
xa -> a -> Bool
forall a. Ord a => a -> a -> Bool
<a
0  Bool -> Bool -> Bool
&& a
ya -> a -> Bool
forall a. Ord a => a -> a -> Bool
>a
0,  a
forall a. C a => a
pi a -> a -> a
forall a. C a => a -> a -> a
+ a -> a
forall a. C a => a -> a
atan (a
ya -> a -> a
forall a. C a => a -> a -> a
/a
x)),
       (a
xa -> a -> Bool
forall a. Ord a => a -> a -> Bool
<=a
0 Bool -> Bool -> Bool
&& a
ya -> a -> Bool
forall a. Ord a => a -> a -> Bool
<a
0, -a -> a -> a
forall a. C a => a -> a -> a
atan2 (-a
y) a
x),
       (a
ya -> a -> Bool
forall a. Eq a => a -> a -> Bool
==a
0 Bool -> Bool -> Bool
&& a
xa -> a -> Bool
forall a. Ord a => a -> a -> Bool
<a
0,  a
forall a. C a => a
pi)] -- must be after the previous test on zero y

instance C P.Float where
    atan2 :: Float -> Float -> Float
atan2 = Float -> Float -> Float
forall a. RealFloat a => a -> a -> a
P.atan2

instance C P.Double where
    atan2 :: Double -> Double -> Double
atan2 = Double -> Double -> Double
forall a. RealFloat a => a -> a -> a
P.atan2