{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# OPTIONS_GHC -Wall #-}

-- | Positive numbers.
--
-- Positivity is enforced via the positive constructor
module NumHask.Data.Positive
  ( Positive,
    positive,
    positive_,
  )
where

import NumHask.Algebra.Additive
import NumHask.Algebra.Field
import NumHask.Algebra.Lattice
import NumHask.Algebra.Multiplicative
import NumHask.Algebra.Ring
import NumHask.Analysis.Metric
import NumHask.Data.Integral
import NumHask.Exception
import qualified Prelude as P

-- | Wrapper for positive numbers.  Note that the constructor is not exported.
newtype Positive a = Positive {Positive a -> a
unPositive :: a}
  deriving
    ( Int -> Positive a -> ShowS
[Positive a] -> ShowS
Positive a -> String
(Int -> Positive a -> ShowS)
-> (Positive a -> String)
-> ([Positive a] -> ShowS)
-> Show (Positive a)
forall a. Show a => Int -> Positive a -> ShowS
forall a. Show a => [Positive a] -> ShowS
forall a. Show a => Positive a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Positive a] -> ShowS
$cshowList :: forall a. Show a => [Positive a] -> ShowS
show :: Positive a -> String
$cshow :: forall a. Show a => Positive a -> String
showsPrec :: Int -> Positive a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Positive a -> ShowS
P.Show,
      Positive a -> Positive a -> Bool
(Positive a -> Positive a -> Bool)
-> (Positive a -> Positive a -> Bool) -> Eq (Positive a)
forall a. Eq a => Positive a -> Positive a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Positive a -> Positive a -> Bool
$c/= :: forall a. Eq a => Positive a -> Positive a -> Bool
== :: Positive a -> Positive a -> Bool
$c== :: forall a. Eq a => Positive a -> Positive a -> Bool
P.Eq,
      Eq (Positive a)
Eq (Positive a)
-> (Positive a -> Positive a -> Ordering)
-> (Positive a -> Positive a -> Bool)
-> (Positive a -> Positive a -> Bool)
-> (Positive a -> Positive a -> Bool)
-> (Positive a -> Positive a -> Bool)
-> (Positive a -> Positive a -> Positive a)
-> (Positive a -> Positive a -> Positive a)
-> Ord (Positive a)
Positive a -> Positive a -> Bool
Positive a -> Positive a -> Ordering
Positive a -> Positive a -> Positive a
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
forall a. Ord a => Eq (Positive a)
forall a. Ord a => Positive a -> Positive a -> Bool
forall a. Ord a => Positive a -> Positive a -> Ordering
forall a. Ord a => Positive a -> Positive a -> Positive a
min :: Positive a -> Positive a -> Positive a
$cmin :: forall a. Ord a => Positive a -> Positive a -> Positive a
max :: Positive a -> Positive a -> Positive a
$cmax :: forall a. Ord a => Positive a -> Positive a -> Positive a
>= :: Positive a -> Positive a -> Bool
$c>= :: forall a. Ord a => Positive a -> Positive a -> Bool
> :: Positive a -> Positive a -> Bool
$c> :: forall a. Ord a => Positive a -> Positive a -> Bool
<= :: Positive a -> Positive a -> Bool
$c<= :: forall a. Ord a => Positive a -> Positive a -> Bool
< :: Positive a -> Positive a -> Bool
$c< :: forall a. Ord a => Positive a -> Positive a -> Bool
compare :: Positive a -> Positive a -> Ordering
$ccompare :: forall a. Ord a => Positive a -> Positive a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Positive a)
P.Ord,
      Positive a
Positive a -> Positive a -> Positive a
(Positive a -> Positive a -> Positive a)
-> Positive a -> Additive (Positive a)
forall a. Additive a => Positive a
forall a. Additive a => Positive a -> Positive a -> Positive a
forall a. (a -> a -> a) -> a -> Additive a
zero :: Positive a
$czero :: forall a. Additive a => Positive a
+ :: Positive a -> Positive a -> Positive a
$c+ :: forall a. Additive a => Positive a -> Positive a -> Positive a
Additive,
      Positive a
Positive a -> Positive a -> Positive a
(Positive a -> Positive a -> Positive a)
-> Positive a -> Multiplicative (Positive a)
forall a. Multiplicative a => Positive a
forall a.
Multiplicative a =>
Positive a -> Positive a -> Positive a
forall a. (a -> a -> a) -> a -> Multiplicative a
one :: Positive a
$cone :: forall a. Multiplicative a => Positive a
* :: Positive a -> Positive a -> Positive a
$c* :: forall a.
Multiplicative a =>
Positive a -> Positive a -> Positive a
Multiplicative,
      Multiplicative (Positive a)
Multiplicative (Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a -> Positive a)
-> Divisive (Positive a)
Positive a -> Positive a
Positive a -> Positive a -> Positive a
forall a. Divisive a => Multiplicative (Positive a)
forall a. Divisive a => Positive a -> Positive a
forall a. Divisive a => Positive a -> Positive a -> Positive a
forall a.
Multiplicative a -> (a -> a) -> (a -> a -> a) -> Divisive a
/ :: Positive a -> Positive a -> Positive a
$c/ :: forall a. Divisive a => Positive a -> Positive a -> Positive a
recip :: Positive a -> Positive a
$crecip :: forall a. Divisive a => Positive a -> Positive a
$cp1Divisive :: forall a. Divisive a => Multiplicative (Positive a)
Divisive,
      Additive (Positive a)
Multiplicative (Positive a)
Additive (Positive a)
-> Multiplicative (Positive a) -> Distributive (Positive a)
forall a. (Additive a, Multiplicative a) => Additive (Positive a)
forall a.
(Additive a, Multiplicative a) =>
Multiplicative (Positive a)
forall a. Additive a -> Multiplicative a -> Distributive a
$cp2Distributive :: forall a.
(Additive a, Multiplicative a) =>
Multiplicative (Positive a)
$cp1Distributive :: forall a. (Additive a, Multiplicative a) => Additive (Positive a)
Distributive,
      Subtractive (Positive a)
Divisive (Positive a)
Distributive (Positive a)
Distributive (Positive a)
-> Subtractive (Positive a)
-> Divisive (Positive a)
-> Field (Positive a)
forall a.
(Ord a, Subtractive a, Divisive a) =>
Subtractive (Positive a)
forall a.
(Ord a, Subtractive a, Divisive a) =>
Divisive (Positive a)
forall a.
(Ord a, Subtractive a, Divisive a) =>
Distributive (Positive a)
forall a. Distributive a -> Subtractive a -> Divisive a -> Field a
$cp3Field :: forall a.
(Ord a, Subtractive a, Divisive a) =>
Divisive (Positive a)
$cp2Field :: forall a.
(Ord a, Subtractive a, Divisive a) =>
Subtractive (Positive a)
$cp1Field :: forall a.
(Ord a, Subtractive a, Divisive a) =>
Distributive (Positive a)
Field,
      Field (Positive a)
Field (Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a -> Positive a)
-> (Positive a -> Positive a -> Positive a)
-> (Positive a -> Positive a)
-> ExpField (Positive a)
Positive a -> Positive a
Positive a -> Positive a -> Positive a
forall a. (Ord a, ExpField a) => Field (Positive a)
forall a. (Ord a, ExpField a) => Positive a -> Positive a
forall a.
(Ord a, ExpField a) =>
Positive a -> Positive a -> Positive a
forall a.
Field a
-> (a -> a)
-> (a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> ExpField a
sqrt :: Positive a -> Positive a
$csqrt :: forall a. (Ord a, ExpField a) => Positive a -> Positive a
** :: Positive a -> Positive a -> Positive a
$c** :: forall a.
(Ord a, ExpField a) =>
Positive a -> Positive a -> Positive a
logBase :: Positive a -> Positive a -> Positive a
$clogBase :: forall a.
(Ord a, ExpField a) =>
Positive a -> Positive a -> Positive a
log :: Positive a -> Positive a
$clog :: forall a. (Ord a, ExpField a) => Positive a -> Positive a
exp :: Positive a -> Positive a
$cexp :: forall a. (Ord a, ExpField a) => Positive a -> Positive a
$cp1ExpField :: forall a. (Ord a, ExpField a) => Field (Positive a)
ExpField,
      Field (Positive a)
Positive a
Field (Positive a)
-> Positive a
-> (Positive a -> Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a -> Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a)
-> TrigField (Positive a)
Positive a -> Positive a
Positive a -> Positive a -> Positive a
forall a. (Ord a, TrigField a) => Field (Positive a)
forall a. (Ord a, TrigField a) => Positive a
forall a. (Ord a, TrigField a) => Positive a -> Positive a
forall a.
(Ord a, TrigField a) =>
Positive a -> Positive a -> Positive a
forall a.
Field a
-> a
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> TrigField a
atanh :: Positive a -> Positive a
$catanh :: forall a. (Ord a, TrigField a) => Positive a -> Positive a
acosh :: Positive a -> Positive a
$cacosh :: forall a. (Ord a, TrigField a) => Positive a -> Positive a
asinh :: Positive a -> Positive a
$casinh :: forall a. (Ord a, TrigField a) => Positive a -> Positive a
tanh :: Positive a -> Positive a
$ctanh :: forall a. (Ord a, TrigField a) => Positive a -> Positive a
cosh :: Positive a -> Positive a
$ccosh :: forall a. (Ord a, TrigField a) => Positive a -> Positive a
sinh :: Positive a -> Positive a
$csinh :: forall a. (Ord a, TrigField a) => Positive a -> Positive a
atan2 :: Positive a -> Positive a -> Positive a
$catan2 :: forall a.
(Ord a, TrigField a) =>
Positive a -> Positive a -> Positive a
atan :: Positive a -> Positive a
$catan :: forall a. (Ord a, TrigField a) => Positive a -> Positive a
acos :: Positive a -> Positive a
$cacos :: forall a. (Ord a, TrigField a) => Positive a -> Positive a
asin :: Positive a -> Positive a
$casin :: forall a. (Ord a, TrigField a) => Positive a -> Positive a
tan :: Positive a -> Positive a
$ctan :: forall a. (Ord a, TrigField a) => Positive a -> Positive a
cos :: Positive a -> Positive a
$ccos :: forall a. (Ord a, TrigField a) => Positive a -> Positive a
sin :: Positive a -> Positive a
$csin :: forall a. (Ord a, TrigField a) => Positive a -> Positive a
pi :: Positive a
$cpi :: forall a. (Ord a, TrigField a) => Positive a
$cp1TrigField :: forall a. (Ord a, TrigField a) => Field (Positive a)
TrigField,
      Distributive (Positive a)
Distributive (Positive a)
-> (Positive a -> Positive a -> Positive a)
-> (Positive a -> Positive a -> Positive a)
-> (Positive a -> Positive a -> (Positive a, Positive a))
-> (Positive a -> Positive a -> Positive a)
-> (Positive a -> Positive a -> Positive a)
-> (Positive a -> Positive a -> (Positive a, Positive a))
-> Integral (Positive a)
Positive a -> Positive a -> (Positive a, Positive a)
Positive a -> Positive a -> Positive a
forall a.
Distributive a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> Integral a
forall a. Integral a => Distributive (Positive a)
forall a.
Integral a =>
Positive a -> Positive a -> (Positive a, Positive a)
forall a. Integral a => Positive a -> Positive a -> Positive a
quotRem :: Positive a -> Positive a -> (Positive a, Positive a)
$cquotRem :: forall a.
Integral a =>
Positive a -> Positive a -> (Positive a, Positive a)
rem :: Positive a -> Positive a -> Positive a
$crem :: forall a. Integral a => Positive a -> Positive a -> Positive a
quot :: Positive a -> Positive a -> Positive a
$cquot :: forall a. Integral a => Positive a -> Positive a -> Positive a
divMod :: Positive a -> Positive a -> (Positive a, Positive a)
$cdivMod :: forall a.
Integral a =>
Positive a -> Positive a -> (Positive a, Positive a)
mod :: Positive a -> Positive a -> Positive a
$cmod :: forall a. Integral a => Positive a -> Positive a -> Positive a
div :: Positive a -> Positive a -> Positive a
$cdiv :: forall a. Integral a => Positive a -> Positive a -> Positive a
$cp1Integral :: forall a. Integral a => Distributive (Positive a)
Integral,
      Additive (Positive a)
Multiplicative (Positive a)
Additive (Positive a)
-> Multiplicative (Positive a)
-> (Positive a -> Positive a)
-> (Positive a -> Positive a)
-> Signed (Positive a)
Positive a -> Positive a
forall a.
Additive a -> Multiplicative a -> (a -> a) -> (a -> a) -> Signed a
forall a. Signed a => Additive (Positive a)
forall a. Signed a => Multiplicative (Positive a)
forall a. Signed a => Positive a -> Positive a
abs :: Positive a -> Positive a
$cabs :: forall a. Signed a => Positive a -> Positive a
sign :: Positive a -> Positive a
$csign :: forall a. Signed a => Positive a -> Positive a
$cp2Signed :: forall a. Signed a => Multiplicative (Positive a)
$cp1Signed :: forall a. Signed a => Additive (Positive a)
Signed,
      Eq (Positive a)
Eq (Positive a)
-> (Positive a -> Positive a -> Positive a)
-> JoinSemiLattice (Positive a)
Positive a -> Positive a -> Positive a
forall a. Eq a -> (a -> a -> a) -> JoinSemiLattice a
forall a. JoinSemiLattice a => Eq (Positive a)
forall a.
JoinSemiLattice a =>
Positive a -> Positive a -> Positive a
\/ :: Positive a -> Positive a -> Positive a
$c\/ :: forall a.
JoinSemiLattice a =>
Positive a -> Positive a -> Positive a
$cp1JoinSemiLattice :: forall a. JoinSemiLattice a => Eq (Positive a)
JoinSemiLattice,
      Eq (Positive a)
Eq (Positive a)
-> (Positive a -> Positive a -> Positive a)
-> MeetSemiLattice (Positive a)
Positive a -> Positive a -> Positive a
forall a. Eq a -> (a -> a -> a) -> MeetSemiLattice a
forall a. MeetSemiLattice a => Eq (Positive a)
forall a.
MeetSemiLattice a =>
Positive a -> Positive a -> Positive a
/\ :: Positive a -> Positive a -> Positive a
$c/\ :: forall a.
MeetSemiLattice a =>
Positive a -> Positive a -> Positive a
$cp1MeetSemiLattice :: forall a. MeetSemiLattice a => Eq (Positive a)
MeetSemiLattice,
      Eq (Positive a)
Subtractive (Positive a)
Additive (Positive a)
MeetSemiLattice (Positive a)
Positive a
Eq (Positive a)
-> Additive (Positive a)
-> Subtractive (Positive a)
-> MeetSemiLattice (Positive a)
-> Positive a
-> (Positive a -> Bool)
-> (Positive a -> Positive a -> Bool)
-> Epsilon (Positive a)
Positive a -> Bool
Positive a -> Positive a -> Bool
forall a.
Eq a
-> Additive a
-> Subtractive a
-> MeetSemiLattice a
-> a
-> (a -> Bool)
-> (a -> a -> Bool)
-> Epsilon a
forall a. (Ord a, Epsilon a) => Eq (Positive a)
forall a. (Ord a, Epsilon a) => Subtractive (Positive a)
forall a. (Ord a, Epsilon a) => Additive (Positive a)
forall a. (Ord a, Epsilon a) => MeetSemiLattice (Positive a)
forall a. (Ord a, Epsilon a) => Positive a
forall a. (Ord a, Epsilon a) => Positive a -> Bool
forall a. (Ord a, Epsilon a) => Positive a -> Positive a -> Bool
aboutEqual :: Positive a -> Positive a -> Bool
$caboutEqual :: forall a. (Ord a, Epsilon a) => Positive a -> Positive a -> Bool
nearZero :: Positive a -> Bool
$cnearZero :: forall a. (Ord a, Epsilon a) => Positive a -> Bool
epsilon :: Positive a
$cepsilon :: forall a. (Ord a, Epsilon a) => Positive a
$cp4Epsilon :: forall a. (Ord a, Epsilon a) => MeetSemiLattice (Positive a)
$cp3Epsilon :: forall a. (Ord a, Epsilon a) => Subtractive (Positive a)
$cp2Epsilon :: forall a. (Ord a, Epsilon a) => Additive (Positive a)
$cp1Epsilon :: forall a. (Ord a, Epsilon a) => Eq (Positive a)
Epsilon
    )

-- | maybe construct a 'Positive'
positive_ :: (P.Ord a, Additive a) => a -> P.Maybe (Positive a)
positive_ :: a -> Maybe (Positive a)
positive_ a
a
  | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
P.< a
forall a. Additive a => a
zero = Maybe (Positive a)
forall a. Maybe a
P.Nothing
  | Bool
P.otherwise = Positive a -> Maybe (Positive a)
forall a. a -> Maybe a
P.Just (a -> Positive a
forall a. a -> Positive a
Positive a
a)

-- | Construct a Positive, throwing an error if the input is negative.
positive :: (P.Ord a, Additive a) => a -> Positive a
positive :: a -> Positive a
positive a
a
  | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
P.< a
forall a. Additive a => a
zero = NumHaskException -> Positive a
forall a e. Exception e => e -> a
throw (String -> NumHaskException
NumHaskException String
"positive number less than zero")
  | Bool
P.otherwise = a -> Positive a
forall a. a -> Positive a
Positive a
a

instance (P.Ord a, Subtractive a) => Subtractive (Positive a) where
  negate :: Positive a -> Positive a
negate (Positive a
a)
    | a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
P.== a
forall a. Additive a => a
zero = a -> Positive a
forall a. a -> Positive a
Positive a
forall a. Additive a => a
zero
    | Bool
P.otherwise = NumHaskException -> Positive a
forall a e. Exception e => e -> a
throw (String -> NumHaskException
NumHaskException String
"negating a positive number")

  (Positive a
a) - :: Positive a -> Positive a -> Positive a
- (Positive a
b)
    | a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
P.>= a
b = a -> Positive a
forall a. a -> Positive a
Positive (a
a a -> a -> a
forall a. Subtractive a => a -> a -> a
- a
b)
    | Bool
P.otherwise = NumHaskException -> Positive a
forall a e. Exception e => e -> a
throw (String -> NumHaskException
NumHaskException String
"subtracting a larger positive")

instance
  (P.Ord a, QuotientField a P.Integer) =>
  QuotientField (Positive a) (Positive P.Integer)
  where
  properFraction :: Positive a -> (Positive Integer, Positive a)
properFraction (Positive a
a) = let (Integer
i, a
r) = a -> (Integer, a)
forall a b. QuotientField a b => a -> (b, a)
properFraction a
a in (Integer -> Positive Integer
forall a. a -> Positive a
Positive Integer
i, a -> Positive a
forall a. a -> Positive a
Positive a
r)

instance
  (P.Ord a, UpperBoundedField a) =>
  UpperBoundedField (Positive a)
  where
  infinity :: Positive a
infinity = a -> Positive a
forall a. a -> Positive a
Positive a
forall a. UpperBoundedField a => a
infinity

instance (P.Ord a, UpperBoundedField a) => P.Bounded (Positive a) where
  minBound :: Positive a
minBound = Positive a
forall a. Additive a => a
zero
  maxBound :: Positive a
maxBound = Positive a
forall a. UpperBoundedField a => a
infinity