{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-|
    Module      :  Numeric.MixedType.Elementary
    Description :  Bottom-up typed pi, sqrt, cos, etc
    Copyright   :  (c) Michal Konecny
    License     :  BSD3

    Maintainer  :  mikkonecny@gmail.com
    Stability   :  experimental
    Portability :  portable

-}
module Numeric.MixedTypes.Elementary
(
  -- * Square root
  CanSqrt(..), CanSqrtSameType, specCanSqrtReal
  -- * Exp
  , CanExp(..), CanExpSameType, specCanExpReal
  -- * Log
  , CanLog(..), CanLogSameType, specCanLogReal
  , powUsingExpLog
  -- * Sine and cosine
  , CanSinCos(..), CanSinCosSameType, specCanSinCosReal
  , approxPi
)
where

import Numeric.MixedTypes.PreludeHiding
import qualified Prelude as P
import Text.Printf

-- import qualified Data.List as List

import Test.Hspec
import Test.QuickCheck

import Numeric.CollectErrors ( CN )
import qualified Numeric.CollectErrors as CN

import Numeric.MixedTypes.Literals
import Numeric.MixedTypes.Bool
import Numeric.MixedTypes.Eq
import Numeric.MixedTypes.Ord
import Numeric.MixedTypes.MinMaxAbs
import Numeric.MixedTypes.AddSub
import Numeric.MixedTypes.Mul
import Numeric.MixedTypes.Field
import Numeric.MixedTypes.Power
-- import Numeric.MixedTypes.Round

import Utils.Test.EnforceRange 

{----  sqrt -----}

{-|
  A replacement for Prelude's `P.sqrt`.  If @Floating t@,
  then one can use the default implementation to mirror Prelude's @sqrt@.
-}
class CanSqrt t where
  type SqrtType t
  type SqrtType t = t -- default
  sqrt :: t -> SqrtType t
  default sqrt :: (SqrtType t ~ t, P.Floating t) => t -> SqrtType t
  sqrt = forall a. Floating a => a -> a
P.sqrt

type CanSqrtSameType t = (CanSqrt t, SqrtType t ~ t)

{-|
  HSpec properties that each implementation of CanSqrt should satisfy.
 -}
specCanSqrtReal ::
  _ => T t -> Spec
specCanSqrtReal :: T t -> Spec
specCanSqrtReal (T String
typeName :: T t) =
  forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe (forall r. PrintfType r => String -> r
printf String
"CanSqrt %s" String
typeName) forall a b. (a -> b) -> a -> b
$ do
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"sqrt(x) >= 0" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x :: t) ->
        forall t. CanTestPosNeg t => t -> Bool
isCertainlyNonNegative t
x forall prop. Testable prop => Bool -> prop -> Property
==>
          (forall t. CanSqrt t => t -> SqrtType t
sqrt t
x) forall a b.
(HasOrderCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?>=?$ Integer
0
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"sqrt(x)^2 = x" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x :: t) ->
        forall t. CanTestPosNeg t => t -> Bool
isCertainlyNonNegative t
x forall prop. Testable prop => Bool -> prop -> Property
==>
          (forall t. CanSqrt t => t -> SqrtType t
sqrt t
x)forall t1 t2. CanPow t1 t2 => t1 -> t2 -> PowType t1 t2
^Integer
2 forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?==?$ t
x
  where
  infix 4 ?==?$
  (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
  ?==?$ :: forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
(?==?$) = forall prop a b.
(Testable prop, Show a, Show b) =>
String -> (a -> b -> prop) -> a -> b -> Property
printArgsIfFails2 String
"?==?" forall a b. HasEqCertainlyAsymmetric a b => a -> b -> Bool
(?==?)
  infix 4 ?>=?$
  (?>=?$) :: (HasOrderCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
  ?>=?$ :: forall a b.
(HasOrderCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
(?>=?$) = forall prop a b.
(Testable prop, Show a, Show b) =>
String -> (a -> b -> prop) -> a -> b -> Property
printArgsIfFails2 String
"?>=?" forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
(?>=?)

{-
  Instances for Integer, Rational etc need an algebraic real or exact real type.
  Such type is not provided in this package. See eg aern2-real.
-}

instance CanSqrt Double -- not exact, will not pass the tests

instance
  (CanSqrt a, CanTestPosNeg a, CanMinMaxThis a Integer)
  =>
  CanSqrt (CN a)
  where
  type SqrtType (CN a) = CN (SqrtType a)
  sqrt :: CN a -> SqrtType (CN a)
sqrt CN a
x 
    | forall t. CanTestPosNeg t => t -> Bool
isCertainlyNonNegative CN a
x = forall es a b.
Monoid es =>
(a -> b) -> CollectErrors es a -> CollectErrors es b
CN.lift forall t. CanSqrt t => t -> SqrtType t
sqrt CN a
x
    | forall t. CanTestPosNeg t => t -> Bool
isCertainlyNegative CN a
x = forall t. CN t -> NumError -> CN t
CN.removeValueErrorCertain CollectErrors NumErrors (SqrtType a)
sqrtx NumError
err
    | Bool
otherwise = forall t. NumError -> CN t -> CN t
CN.prependErrorPotential NumError
err CollectErrors NumErrors (SqrtType a)
sqrtx
    where
    sqrtx :: CollectErrors NumErrors (SqrtType a)
sqrtx = forall es a b.
Monoid es =>
(a -> b) -> CollectErrors es a -> CollectErrors es b
CN.lift forall t. CanSqrt t => t -> SqrtType t
sqrt forall a b. (a -> b) -> a -> b
$ forall t1 t2.
CanMinMaxAsymmetric t1 t2 =>
t1 -> t2 -> MinMaxType t1 t2
max CN a
x Integer
0
    err :: CN.NumError
    err :: NumError
err = String -> NumError
CN.OutOfDomain String
"negative sqrt argument"


{----  exp -----}

{-|
  A replacement for Prelude's `P.exp`.  If @Floating t@,
  then one can use the default implementation to mirror Prelude's @exp@.
-}
class CanExp t where
  type ExpType t
  type ExpType t = t -- default
  exp :: t -> ExpType t
  default exp :: (ExpType t ~ t, P.Floating t) => t -> ExpType t
  exp = forall a. Floating a => a -> a
P.exp

type CanExpSameType t = (CanExp t, ExpType t ~ t)

{-|
  HSpec properties that each implementation of CanExp should satisfy.
 -}
specCanExpReal ::
  _ => T t -> Spec
specCanExpReal :: T t -> Spec
specCanExpReal (T String
typeName :: T t) =
  forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe (forall r. PrintfType r => String -> r
printf String
"CanExp %s" String
typeName) forall a b. (a -> b) -> a -> b
$ do
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"exp(x) >= 0" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x_ :: t) ->
        let x :: t
x = forall t b. CanEnforceRange t b => (Maybe b, Maybe b) -> t -> t
enforceRange (forall a. a -> Maybe a
Just (-Integer
100000), forall a. a -> Maybe a
Just Integer
100000) t
x_ in
          forall t. CanExp t => t -> ExpType t
exp t
x forall a b.
(HasOrderCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?>=?$ Integer
0
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"exp(-x) == 1/(exp x)" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x_ :: t) ->
        let x :: t
x = forall t b. CanEnforceRange t b => (Maybe b, Maybe b) -> t -> t
enforceRange (forall a. a -> Maybe a
Just (-Integer
100000), forall a. a -> Maybe a
Just Integer
100000) t
x_ in
        let ex :: ExpType t
ex = forall t. CanExp t => t -> ExpType t
exp t
x in
          (ExpType t
ex forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!>! Integer
0) forall prop. Testable prop => Bool -> prop -> Property
==>
            (forall t. CanExp t => t -> ExpType t
exp (-t
x)) forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?==?$ Integer
1forall t1 t2. CanDiv t1 t2 => t1 -> t2 -> DivType t1 t2
/ExpType t
ex
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"exp(x+y) = exp(x)*exp(y)" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x_ :: t)  (t
y_ :: t) ->
        let x :: t
x = forall t b. CanEnforceRange t b => (Maybe b, Maybe b) -> t -> t
enforceRange (forall a. a -> Maybe a
Just (-Integer
100000), forall a. a -> Maybe a
Just Integer
100000) t
x_ in
        let y :: t
y = forall t b. CanEnforceRange t b => (Maybe b, Maybe b) -> t -> t
enforceRange (forall a. a -> Maybe a
Just (-Integer
100000), forall a. a -> Maybe a
Just Integer
100000) t
y_ in
          (forall t. CanExp t => t -> ExpType t
exp forall a b. (a -> b) -> a -> b
$ t
x forall t1 t2. CanAddAsymmetric t1 t2 => t1 -> t2 -> AddType t1 t2
+ t
y) forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?==?$ (forall t. CanExp t => t -> ExpType t
exp t
x) forall t1 t2. CanMulAsymmetric t1 t2 => t1 -> t2 -> MulType t1 t2
* (forall t. CanExp t => t -> ExpType t
exp t
y)
  where
  infix 4 ?==?$
  (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
  ?==?$ :: forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
(?==?$) = forall prop a b.
(Testable prop, Show a, Show b) =>
String -> (a -> b -> prop) -> a -> b -> Property
printArgsIfFails2 String
"?==?" forall a b. HasEqCertainlyAsymmetric a b => a -> b -> Bool
(?==?)
  infix 4 ?>=?$
  (?>=?$) :: (HasOrderCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
  ?>=?$ :: forall a b.
(HasOrderCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
(?>=?$) = forall prop a b.
(Testable prop, Show a, Show b) =>
String -> (a -> b -> prop) -> a -> b -> Property
printArgsIfFails2 String
"?>=?" forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
(?>=?)

{-
  Instances for Integer, Rational etc need an algebraic real or exact real type.
  Such type is not provided in this package. See eg aern2-real.
-}

instance CanExp Double -- not exact, will not pass the tests

instance
  (CanExp a) => CanExp (CN a)
  where
  type ExpType (CN a) = CN (ExpType a)
  exp :: CN a -> ExpType (CN a)
exp = forall es a b.
Monoid es =>
(a -> b) -> CollectErrors es a -> CollectErrors es b
CN.lift forall t. CanExp t => t -> ExpType t
exp

{----  log -----}

{-|
  A replacement for Prelude's `P.log`.  If @Floating t@,
  then one can use the default implementation to mirror Prelude's @log@.
-}
class CanLog t where
  type LogType t
  type LogType t = t -- default
  log :: t -> LogType t
  default log :: (LogType t ~ t, P.Floating t) => t -> LogType t
  log = forall a. Floating a => a -> a
P.log

type CanLogSameType t = (CanLog t, LogType t ~ t)

{-|
  HSpec properties that each implementation of CanLog should satisfy.
 -}
specCanLogReal ::
  _ => T t -> Spec
specCanLogReal :: T t -> Spec
specCanLogReal (T String
typeName :: T t) =
  forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe (forall r. PrintfType r => String -> r
printf String
"CanLog %s" String
typeName) forall a b. (a -> b) -> a -> b
$ do
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"log(1/x) == -(log x)" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x_ :: t) ->
        let x :: t
x = forall t b. CanEnforceRange t b => (Maybe b, Maybe b) -> t -> t
enforceRange (forall a. a -> Maybe a
Just Integer
0, forall a. Maybe a
Nothing) t
x_ in
        t
x forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!>! Integer
0 forall a b. CanAndOrAsymmetric a b => a -> b -> AndOrType a b
&& (Integer
1forall t1 t2. CanDiv t1 t2 => t1 -> t2 -> DivType t1 t2
/t
x) forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!>! Integer
0  forall prop. Testable prop => Bool -> prop -> Property
==>
          forall t. CanLog t => t -> LogType t
log (Integer
1forall t1 t2. CanDiv t1 t2 => t1 -> t2 -> DivType t1 t2
/t
x) forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?==?$ -(forall t. CanLog t => t -> LogType t
log t
x)
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"log(x*y) = log(x)+log(y)" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x_ :: t)  (t
y_ :: t) ->
        let x :: t
x = forall t b. CanEnforceRange t b => (Maybe b, Maybe b) -> t -> t
enforceRange (forall a. a -> Maybe a
Just Integer
0, forall a. Maybe a
Nothing) t
x_ in
        let y :: t
y = forall t b. CanEnforceRange t b => (Maybe b, Maybe b) -> t -> t
enforceRange (forall a. a -> Maybe a
Just Integer
0, forall a. Maybe a
Nothing) t
y_ in
        t
x forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!>! Integer
0 forall a b. CanAndOrAsymmetric a b => a -> b -> AndOrType a b
&& t
y forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!>! Integer
0 forall a b. CanAndOrAsymmetric a b => a -> b -> AndOrType a b
&& t
xforall t1 t2. CanMulAsymmetric t1 t2 => t1 -> t2 -> MulType t1 t2
*t
y forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!>! Integer
0  forall prop. Testable prop => Bool -> prop -> Property
==>
          (forall t. CanLog t => t -> LogType t
log forall a b. (a -> b) -> a -> b
$ t
x forall t1 t2. CanMulAsymmetric t1 t2 => t1 -> t2 -> MulType t1 t2
* t
y) forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?==?$ (forall t. CanLog t => t -> LogType t
log t
x) forall t1 t2. CanAddAsymmetric t1 t2 => t1 -> t2 -> AddType t1 t2
+ (forall t. CanLog t => t -> LogType t
log t
y)
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"log(exp x) == x" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x_ :: t) ->
        let x :: t
x = forall t b. CanEnforceRange t b => (Maybe b, Maybe b) -> t -> t
enforceRange (forall a. a -> Maybe a
Just (-Integer
1000), forall a. a -> Maybe a
Just Integer
10000) t
x_ in
        let ex :: ExpType t
ex = forall t. CanExp t => t -> ExpType t
exp t
x in
          (ExpType t
ex forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!>! Integer
0) forall prop. Testable prop => Bool -> prop -> Property
==>
            forall t. CanLog t => t -> LogType t
log ExpType t
ex forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?==?$ t
x
  where
  infix 4 ?==?$
  (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
  ?==?$ :: forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
(?==?$) = forall prop a b.
(Testable prop, Show a, Show b) =>
String -> (a -> b -> prop) -> a -> b -> Property
printArgsIfFails2 String
"?==?" forall a b. HasEqCertainlyAsymmetric a b => a -> b -> Bool
(?==?)

{-
  Instances for Integer, Rational etc need an algebraic real or exact real type.
  Such type is not provided in this package. See eg aern2-real.
-}

instance CanLog Double -- not exact, will not pass the tests

instance
  (CanLog a, CanTestPosNeg a)
  =>
  CanLog (CN a)
  where
  type LogType (CN a) = CN (LogType a)
  log :: CN a -> LogType (CN a)
log CN a
x 
    | forall t. CanTestPosNeg t => t -> Bool
isCertainlyPositive CN a
x = CollectErrors NumErrors (LogType a)
logx
    | forall t. CanTestPosNeg t => t -> Bool
isCertainlyNonPositive CN a
x = forall t. CN t -> NumError -> CN t
CN.removeValueErrorCertain CollectErrors NumErrors (LogType a)
logx NumError
err
    | Bool
otherwise = forall t. CN t -> NumError -> CN t
CN.removeValueErrorPotential CollectErrors NumErrors (LogType a)
logx NumError
err
    where
    logx :: CollectErrors NumErrors (LogType a)
logx = forall es a b.
Monoid es =>
(a -> b) -> CollectErrors es a -> CollectErrors es b
CN.lift forall t. CanLog t => t -> LogType t
log CN a
x
    err :: CN.NumError
    err :: NumError
err = String -> NumError
CN.OutOfDomain String
"log argument not positive"


powUsingExpLog ::
  (CanLogSameType t,
   CanExpSameType t,
   CanTestInteger t,
   CanTestZero t)
  =>
   t -> (t -> t -> t) -> (t -> t) -> t -> t -> t
powUsingExpLog :: forall t.
(CanLogSameType t, CanExpSameType t, CanTestInteger t,
 CanTestZero t) =>
t -> (t -> t -> t) -> (t -> t) -> t -> t -> t
powUsingExpLog t
one t -> t -> t
mul' t -> t
recip' t
b t
e =
  case forall t. CanTestInteger t => t -> Maybe Integer
certainlyIntegerGetIt t
e of
    Just Integer
n ->
      forall e t.
CanBeInteger e =>
t -> (t -> t -> t) -> (t -> t) -> t -> e -> t
powUsingMulRecip t
one t -> t -> t
mul' t -> t
recip' t
b Integer
n
    Maybe Integer
Nothing ->
      forall t. CanExp t => t -> ExpType t
exp ((forall t. CanLog t => t -> LogType t
log t
b) t -> t -> t
`mul'` (t
e))

{----  sine and cosine -----}

{-|
  A replacement for Prelude's `P.cos` and `P.sin`.  If @Floating t@,
  then one can use the default implementation to mirror Prelude's @sin@, @cos@.
-}
class CanSinCos t where
  type SinCosType t
  type SinCosType t = t -- default
  cos :: t -> SinCosType t
  default cos :: (SinCosType t ~ t, P.Floating t) => t -> SinCosType t
  cos = forall a. Floating a => a -> a
P.cos
  sin :: t -> SinCosType t
  default sin :: (SinCosType t ~ t, P.Floating t) => t -> SinCosType t
  sin = forall a. Floating a => a -> a
P.sin

type CanSinCosSameType t = (CanSinCos t, SinCosType t ~ t)

{-|
  HSpec properties that each implementation of CanSinCos should satisfy.

  Derived partially from
  http://math.stackexchange.com/questions/1303044/axiomatic-definition-of-sin-and-cos
 -}
specCanSinCosReal ::
  _ => T t -> Spec
specCanSinCosReal :: T t -> Spec
specCanSinCosReal (T String
typeName :: T t) =
  forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe (forall r. PrintfType r => String -> r
printf String
"CanSinCos %s" String
typeName) forall a b. (a -> b) -> a -> b
$ do
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"-1 <= sin(x) <= 1" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x :: t) ->
          (-Integer
1) forall a b.
(HasOrderCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?<=?$ (forall t. CanSinCos t => t -> SinCosType t
sin t
x) forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&. (forall t. CanSinCos t => t -> SinCosType t
sin t
x) forall a b.
(HasOrderCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?<=?$ Integer
1
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"-1 <= cos(x) <= 1" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x :: t) ->
          (-Integer
1) forall a b.
(HasOrderCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?<=?$ (forall t. CanSinCos t => t -> SinCosType t
cos t
x) forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&. (forall t. CanSinCos t => t -> SinCosType t
cos t
x) forall a b.
(HasOrderCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?<=?$ Integer
1
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"cos(x)^2 + sin(x)^2 = 1" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x :: t) ->
          (forall t. CanSinCos t => t -> SinCosType t
sin t
x)forall t1 t2. CanPow t1 t2 => t1 -> t2 -> PowType t1 t2
^Integer
2 forall t1 t2. CanAddAsymmetric t1 t2 => t1 -> t2 -> AddType t1 t2
+ (forall t. CanSinCos t => t -> SinCosType t
cos t
x)forall t1 t2. CanPow t1 t2 => t1 -> t2 -> PowType t1 t2
^Integer
2 forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?==?$ Integer
1
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"sin(x-y) = sin(x)cos(y) - cos(x)sin(y)" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x :: t) (t
y :: t) ->
          (forall t. CanSinCos t => t -> SinCosType t
sin forall a b. (a -> b) -> a -> b
$ t
x forall t1 t2. CanSub t1 t2 => t1 -> t2 -> SubType t1 t2
- t
y) forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?==?$ (forall t. CanSinCos t => t -> SinCosType t
sin t
x)forall t1 t2. CanMulAsymmetric t1 t2 => t1 -> t2 -> MulType t1 t2
*(forall t. CanSinCos t => t -> SinCosType t
cos t
y) forall t1 t2. CanSub t1 t2 => t1 -> t2 -> SubType t1 t2
- (forall t. CanSinCos t => t -> SinCosType t
cos t
x)forall t1 t2. CanMulAsymmetric t1 t2 => t1 -> t2 -> MulType t1 t2
*(forall t. CanSinCos t => t -> SinCosType t
sin t
y)
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"cos(x-y) = cos(x)cos(y) + sin(x)sin(y)" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x :: t) (t
y :: t) ->
          (forall t. CanSinCos t => t -> SinCosType t
cos forall a b. (a -> b) -> a -> b
$ t
x forall t1 t2. CanSub t1 t2 => t1 -> t2 -> SubType t1 t2
- t
y) forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?==?$ (forall t. CanSinCos t => t -> SinCosType t
cos t
x)forall t1 t2. CanMulAsymmetric t1 t2 => t1 -> t2 -> MulType t1 t2
*(forall t. CanSinCos t => t -> SinCosType t
cos t
y) forall t1 t2. CanAddAsymmetric t1 t2 => t1 -> t2 -> AddType t1 t2
+ (forall t. CanSinCos t => t -> SinCosType t
sin t
x)forall t1 t2. CanMulAsymmetric t1 t2 => t1 -> t2 -> MulType t1 t2
*(forall t. CanSinCos t => t -> SinCosType t
sin t
y)
    forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"sin(x) < x < tan(x) for x in [0,pi/2]" forall a b. (a -> b) -> a -> b
$ do
      forall prop. Testable prop => prop -> Property
property forall a b. (a -> b) -> a -> b
$ \ (t
x :: t) ->
        t
x forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!>=! Integer
0 forall a b. CanAndOrAsymmetric a b => a -> b -> AndOrType a b
&& t
x forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!<=! Rational
1.57 forall a b. CanAndOrAsymmetric a b => a -> b -> AndOrType a b
&& (forall t. CanSinCos t => t -> SinCosType t
cos t
x) forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
!>! Integer
0 forall prop. Testable prop => Bool -> prop -> Property
==>
          (forall t. CanSinCos t => t -> SinCosType t
sin t
x) forall a b.
(HasOrderCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?<=?$ t
x forall prop1 prop2.
(Testable prop1, Testable prop2) =>
prop1 -> prop2 -> Property
.&&. (t
x) forall a b.
(HasOrderCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
?<=?$ (forall t. CanSinCos t => t -> SinCosType t
sin t
x)forall t1 t2. CanDiv t1 t2 => t1 -> t2 -> DivType t1 t2
/(forall t. CanSinCos t => t -> SinCosType t
cos t
x)
  where
  infix 4 ?==?$
  (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
  ?==?$ :: forall a b.
(HasEqCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
(?==?$) = forall prop a b.
(Testable prop, Show a, Show b) =>
String -> (a -> b -> prop) -> a -> b -> Property
printArgsIfFails2 String
"?==?" forall a b. HasEqCertainlyAsymmetric a b => a -> b -> Bool
(?==?)
  infix 4 ?<=?$
  (?<=?$) :: (HasOrderCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
  ?<=?$ :: forall a b.
(HasOrderCertainlyAsymmetric a b, Show a, Show b) =>
a -> b -> Property
(?<=?$) = forall prop a b.
(Testable prop, Show a, Show b) =>
String -> (a -> b -> prop) -> a -> b -> Property
printArgsIfFails2 String
"?<=?" forall a b. HasOrderCertainlyAsymmetric a b => a -> b -> Bool
(?<=?)

{-
  Instances for Integer, Rational etc need an algebraic real or exact real type.
  Such type is not provided in this package. See eg aern2-real.
-}

instance CanSinCos Double -- not exact, will not pass the tests

instance
  (CanSinCos a) => CanSinCos (CN a)
  where
  type SinCosType (CN a) = CN (SinCosType a)
  sin :: CN a -> SinCosType (CN a)
sin = forall es a b.
Monoid es =>
(a -> b) -> CollectErrors es a -> CollectErrors es b
CN.lift forall t. CanSinCos t => t -> SinCosType t
sin
  cos :: CN a -> SinCosType (CN a)
cos = forall es a b.
Monoid es =>
(a -> b) -> CollectErrors es a -> CollectErrors es b
CN.lift forall t. CanSinCos t => t -> SinCosType t
cos

{-|
  Approximate pi, synonym for Prelude's `P.pi`.

  We do not define (exect) @pi@ in this package as we have no type
  that can represent it exactly.
-}
approxPi :: (P.Floating t) => t
approxPi :: forall t. Floating t => t
approxPi = forall t. Floating t => t
P.pi