-- | Symbolic number, i.e., these are not numbers at all, but just build
-- a representation of the expressions.
-- This implementation is incomplete in that it allows comnstruction,
-- but not deconstruction of the expressions.  It's mainly useful for
-- debugging.
module Data.Number.Symbolic(Sym, var, con, subst, unSym) where

import Data.Char(isAlpha)
import Data.Maybe(fromMaybe)

-- | Symbolic numbers over some base type for the literals.
data Sym a = Con a | App String ([a]->a) [Sym a]

instance (Eq a) => Eq (Sym a) where
    Con x :: a
x      == :: Sym a -> Sym a -> Bool
== Con x' :: a
x'        =  a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x'
    App f :: String
f _ xs :: [Sym a]
xs == App f' :: String
f' _ xs' :: [Sym a]
xs'  =  (String
f, [Sym a]
xs) (String, [Sym a]) -> (String, [Sym a]) -> Bool
forall a. Eq a => a -> a -> Bool
== (String
f', [Sym a]
xs')
    _          == _             =  Bool
False

instance (Ord a) => Ord (Sym a) where
    Con x :: a
x      compare :: Sym a -> Sym a -> Ordering
`compare` Con x' :: a
x'        =  a
x a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` a
x'
    Con _      `compare` App _ _ _     = Ordering
LT
    App _ _ _  `compare` Con _         = Ordering
GT
    App f :: String
f _ xs :: [Sym a]
xs `compare` App f' :: String
f' _ xs' :: [Sym a]
xs'  =  (String
f, [Sym a]
xs) (String, [Sym a]) -> (String, [Sym a]) -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` (String
f', [Sym a]
xs')

-- | Create a variable.
var :: String -> Sym a
var :: String -> Sym a
var s :: String
s = String -> ([a] -> a) -> [Sym a] -> Sym a
forall a. String -> ([a] -> a) -> [Sym a] -> Sym a
App String
s [a] -> a
forall a. HasCallStack => a
undefined []

-- | Create a constant (useful when it is not a literal).
con :: a -> Sym a
con :: a -> Sym a
con = a -> Sym a
forall a. a -> Sym a
Con

-- | The expression @subst x v e@ substitutes the expression @v@ for each
-- occurence of the variable @x@ in @e@.
subst :: (Num a, Eq a) => String -> Sym a -> Sym a -> Sym a
subst :: String -> Sym a -> Sym a -> Sym a
subst _ _ e :: Sym a
e@(Con _) = Sym a
e
subst x :: String
x v :: Sym a
v e :: Sym a
e@(App x' :: String
x' _ []) | String
x String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
x' = Sym a
v
                          | Bool
otherwise = Sym a
e
subst x :: String
x v :: Sym a
v (App s :: String
s f :: [a] -> a
f es :: [Sym a]
es) =
    case (Sym a -> Sym a) -> [Sym a] -> [Sym a]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Sym a -> Sym a -> Sym a
forall a. (Num a, Eq a) => String -> Sym a -> Sym a -> Sym a
subst String
x Sym a
v) [Sym a]
es of
    [e :: Sym a
e] -> (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp (\ x :: a
x -> [a] -> a
f [a
x]) String
s Sym a
e
    [e1 :: Sym a
e1,e2 :: Sym a
e2] -> (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp (\ x :: a
x y :: a
y -> [a] -> a
f [a
x,a
y]) Sym a
e1 String
s Sym a
e2
    es' :: [Sym a]
es' -> String -> ([a] -> a) -> [Sym a] -> Sym a
forall a. String -> ([a] -> a) -> [Sym a] -> Sym a
App String
s [a] -> a
f [Sym a]
es'

-- Turn a symbolic number into a regular one if it is a constant,
-- otherwise generate an error.
unSym :: (Show a) => Sym a -> a
unSym :: Sym a -> a
unSym (Con c :: a
c) = a
c
unSym e :: Sym a
e = String -> a
forall a. HasCallStack => String -> a
error (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ "unSym called: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Sym a -> String
forall a. Show a => a -> String
show Sym a
e

instance (Show a) => Show (Sym a) where
    showsPrec :: Int -> Sym a -> String -> String
showsPrec p :: Int
p (Con c :: a
c) = Int -> a -> String -> String
forall a. Show a => Int -> a -> String -> String
showsPrec Int
p a
c
    showsPrec _ (App s :: String
s _ []) = String -> String -> String
showString String
s
    showsPrec p :: Int
p (App op :: String
op@(c :: Char
c:_) _ [x :: Sym a
x, y :: Sym a
y]) | Bool -> Bool
not (Char -> Bool
isAlpha Char
c) =
        Bool -> (String -> String) -> String -> String
showParen (Int
pInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>Int
q) (Int -> Sym a -> String -> String
forall a. Show a => Int -> a -> String -> String
showsPrec Int
ql Sym a
x (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String
showString String
op (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Sym a -> String -> String
forall a. Show a => Int -> a -> String -> String
showsPrec Int
qr Sym a
y)
        where (ql :: Int
ql, q :: Int
q, qr :: Int
qr) = (Int, Int, Int) -> Maybe (Int, Int, Int) -> (Int, Int, Int)
forall a. a -> Maybe a -> a
fromMaybe (9,9,9) (Maybe (Int, Int, Int) -> (Int, Int, Int))
-> Maybe (Int, Int, Int) -> (Int, Int, Int)
forall a b. (a -> b) -> a -> b
$ String -> [(String, (Int, Int, Int))] -> Maybe (Int, Int, Int)
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
op [
                   ("**", (9,8,8)),
                   ("/",  (7,7,8)),
                   ("*",  (7,7,8)),
                   ("+",  (6,6,7)),
                   ("-",  (6,6,7))]
    showsPrec p :: Int
p (App "negate" _ [x :: Sym a
x]) =
        Bool -> (String -> String) -> String -> String
showParen (Int
pInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>=6) (String -> String -> String
showString "-" (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Sym a -> String -> String
forall a. Show a => Int -> a -> String -> String
showsPrec 7 Sym a
x)
    showsPrec p :: Int
p (App f :: String
f _ xs :: [Sym a]
xs) =
        Bool -> (String -> String) -> String -> String
showParen (Int
pInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>10) (((String -> String) -> (String -> String) -> String -> String)
-> (String -> String) -> [String -> String] -> String -> String
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.) (String -> String -> String
showString String
f) ((Sym a -> String -> String) -> [Sym a] -> [String -> String]
forall a b. (a -> b) -> [a] -> [b]
map (\ x :: Sym a
x -> Char -> String -> String
showChar ' ' (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Sym a -> String -> String
forall a. Show a => Int -> a -> String -> String
showsPrec 11 Sym a
x) [Sym a]
xs))

instance (Num a, Eq a) => Num (Sym a) where
    x :: Sym a
x + :: Sym a -> Sym a -> Sym a
+ y :: Sym a
y         = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp a -> a -> a
forall a. Num a => a -> a -> a
(+) Sym a
x "+" Sym a
y
    x :: Sym a
x - :: Sym a -> Sym a -> Sym a
- y :: Sym a
y         = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp (-) Sym a
x "-" Sym a
y
    x :: Sym a
x * :: Sym a -> Sym a -> Sym a
* y :: Sym a
y         = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp a -> a -> a
forall a. Num a => a -> a -> a
(*) Sym a
x "*" Sym a
y
    negate :: Sym a -> Sym a
negate x :: Sym a
x      = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Num a => a -> a
negate "negate" Sym a
x
    abs :: Sym a -> Sym a
abs    x :: Sym a
x      = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Num a => a -> a
abs    "abs"    Sym a
x
    signum :: Sym a -> Sym a
signum x :: Sym a
x      = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Num a => a -> a
signum "signum" Sym a
x
    fromInteger :: Integer -> Sym a
fromInteger x :: Integer
x = a -> Sym a
forall a. a -> Sym a
Con (Integer -> a
forall a. Num a => Integer -> a
fromInteger Integer
x)

instance (Fractional a, Eq a) => Fractional (Sym a) where
    x :: Sym a
x / :: Sym a -> Sym a -> Sym a
/ y :: Sym a
y          = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp a -> a -> a
forall a. Fractional a => a -> a -> a
(/) Sym a
x "/" Sym a
y
    fromRational :: Rational -> Sym a
fromRational x :: Rational
x = a -> Sym a
forall a. a -> Sym a
Con (Rational -> a
forall a. Fractional a => Rational -> a
fromRational Rational
x)

-- Assume the numbers are a field and simplify a little
binOp :: (Num a, Eq a) => (a->a->a) -> Sym a -> String -> Sym a -> Sym a
binOp :: (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp f :: a -> a -> a
f (Con x :: a
x) _ (Con y :: a
y) = a -> Sym a
forall a. a -> Sym a
Con (a -> a -> a
f a
x a
y)
binOp _ x :: Sym a
x "+" 0 = Sym a
x
binOp _ 0 "+" x :: Sym a
x = Sym a
x
binOp _ x :: Sym a
x "+" (App "+" _ [y :: Sym a
y, z :: Sym a
z]) = (Sym a
x Sym a -> Sym a -> Sym a
forall a. Num a => a -> a -> a
+ Sym a
y) Sym a -> Sym a -> Sym a
forall a. Num a => a -> a -> a
+ Sym a
z
binOp _ x :: Sym a
x "+" y :: Sym a
y | Sym a -> Bool
forall a. Sym a -> Bool
isCon Sym a
y Bool -> Bool -> Bool
&& Bool -> Bool
not (Sym a -> Bool
forall a. Sym a -> Bool
isCon Sym a
x) = Sym a
y Sym a -> Sym a -> Sym a
forall a. Num a => a -> a -> a
+ Sym a
x
binOp _ x :: Sym a
x "+" (App "negate" _ [y :: Sym a
y]) = Sym a
x Sym a -> Sym a -> Sym a
forall a. Num a => a -> a -> a
- Sym a
y
binOp _ x :: Sym a
x "-" 0 = Sym a
x
binOp _ x :: Sym a
x "-" x' :: Sym a
x' | Sym a
x Sym a -> Sym a -> Bool
forall a. Eq a => a -> a -> Bool
== Sym a
x' = 0
binOp _ x :: Sym a
x "-" (Con y :: a
y) | Bool -> Bool
not (Sym a -> Bool
forall a. Sym a -> Bool
isCon Sym a
x) = a -> Sym a
forall a. a -> Sym a
Con (-a
y) Sym a -> Sym a -> Sym a
forall a. Num a => a -> a -> a
+ Sym a
x
binOp _ _ "*" 0 = 0
binOp _ x :: Sym a
x "*" 1 = Sym a
x
binOp _ x :: Sym a
x "*" (-1) = -Sym a
x
binOp _ 0 "*" _ = 0
binOp _ 1 "*" x :: Sym a
x = Sym a
x
binOp _ (-1) "*" x :: Sym a
x = -Sym a
x
binOp _ x :: Sym a
x "*" (App "*" _ [y :: Sym a
y, z :: Sym a
z]) = (Sym a
x Sym a -> Sym a -> Sym a
forall a. Num a => a -> a -> a
* Sym a
y) Sym a -> Sym a -> Sym a
forall a. Num a => a -> a -> a
* Sym a
z
binOp _ x :: Sym a
x "*" y :: Sym a
y | Sym a -> Bool
forall a. Sym a -> Bool
isCon Sym a
y Bool -> Bool -> Bool
&& Bool -> Bool
not (Sym a -> Bool
forall a. Sym a -> Bool
isCon Sym a
x) = Sym a
y Sym a -> Sym a -> Sym a
forall a. Num a => a -> a -> a
* Sym a
x
binOp _ x :: Sym a
x "*" (App "/" f :: [a] -> a
f [y :: Sym a
y, z :: Sym a
z]) = String -> ([a] -> a) -> [Sym a] -> Sym a
forall a. String -> ([a] -> a) -> [Sym a] -> Sym a
App "/" [a] -> a
f [Sym a
xSym a -> Sym a -> Sym a
forall a. Num a => a -> a -> a
*Sym a
y, Sym a
z]
{-
binOp _ x "*" (App "+" _ [y, z]) = x*y + x*z
binOp _ (App "+" _ [y, z]) "*" x = y*x + z*x
-}
binOp _ x :: Sym a
x "/" 1 = Sym a
x
binOp _ x :: Sym a
x "/" (-1) = -Sym a
x
binOp _ x :: Sym a
x "/" x' :: Sym a
x' | Sym a
x Sym a -> Sym a -> Bool
forall a. Eq a => a -> a -> Bool
== Sym a
x' = 1
binOp _ x :: Sym a
x "/" (App "/" f :: [a] -> a
f [y :: Sym a
y, z :: Sym a
z]) = String -> ([a] -> a) -> [Sym a] -> Sym a
forall a. String -> ([a] -> a) -> [Sym a] -> Sym a
App "/" [a] -> a
f [Sym a
xSym a -> Sym a -> Sym a
forall a. Num a => a -> a -> a
*Sym a
z, Sym a
y]
binOp f :: a -> a -> a
f (App "**" _ [x :: Sym a
x, y :: Sym a
y]) "**" z :: Sym a
z = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp a -> a -> a
f Sym a
x "**" (Sym a
y Sym a -> Sym a -> Sym a
forall a. Num a => a -> a -> a
* Sym a
z)
binOp _ _ "**" 0 = 1
binOp _ 0 "**" _ = 0
binOp f :: a -> a -> a
f x :: Sym a
x op :: String
op y :: Sym a
y = String -> ([a] -> a) -> [Sym a] -> Sym a
forall a. String -> ([a] -> a) -> [Sym a] -> Sym a
App String
op (\ [a :: a
a,b :: a
b] -> a -> a -> a
f a
a a
b) [Sym a
x, Sym a
y]

unOp :: (Num a) => (a->a) -> String -> Sym a -> Sym a
unOp :: (a -> a) -> String -> Sym a -> Sym a
unOp f :: a -> a
f _ (Con c :: a
c) = a -> Sym a
forall a. a -> Sym a
Con (a -> a
f a
c)
unOp _ "negate" (App "negate" _ [x :: Sym a
x]) = Sym a
x
unOp _ "abs" e :: Sym a
e@(App "abs" _ _) = Sym a
e
unOp _ "signum" e :: Sym a
e@(App "signum" _ _) = Sym a
e
unOp f :: a -> a
f op :: String
op x :: Sym a
x = String -> ([a] -> a) -> [Sym a] -> Sym a
forall a. String -> ([a] -> a) -> [Sym a] -> Sym a
App String
op (\ [a :: a
a] -> a -> a
f a
a) [Sym a
x]

isCon :: Sym a -> Bool
isCon :: Sym a -> Bool
isCon (Con _) = Bool
True
isCon _ = Bool
False


instance (Integral a) => Integral (Sym a) where
    quot :: Sym a -> Sym a -> Sym a
quot x :: Sym a
x y :: Sym a
y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp a -> a -> a
forall a. Integral a => a -> a -> a
quot Sym a
x "quot" Sym a
y
    rem :: Sym a -> Sym a -> Sym a
rem x :: Sym a
x y :: Sym a
y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp a -> a -> a
forall a. Integral a => a -> a -> a
rem Sym a
x "rem" Sym a
y
    quotRem :: Sym a -> Sym a -> (Sym a, Sym a)
quotRem x :: Sym a
x y :: Sym a
y = (Sym a -> Sym a -> Sym a
forall a. Integral a => a -> a -> a
quot Sym a
x Sym a
y, Sym a -> Sym a -> Sym a
forall a. Integral a => a -> a -> a
rem Sym a
x Sym a
y)
    div :: Sym a -> Sym a -> Sym a
div x :: Sym a
x y :: Sym a
y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp a -> a -> a
forall a. Integral a => a -> a -> a
div Sym a
x "div" Sym a
y
    mod :: Sym a -> Sym a -> Sym a
mod x :: Sym a
x y :: Sym a
y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp a -> a -> a
forall a. Integral a => a -> a -> a
mod Sym a
x "mod" Sym a
y
    toInteger :: Sym a -> Integer
toInteger (Con c :: a
c) = a -> Integer
forall a. Integral a => a -> Integer
toInteger a
c

instance (Enum a) => Enum (Sym a) where
    toEnum :: Int -> Sym a
toEnum = a -> Sym a
forall a. a -> Sym a
Con (a -> Sym a) -> (Int -> a) -> Int -> Sym a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a
forall a. Enum a => Int -> a
toEnum
    fromEnum :: Sym a -> Int
fromEnum (Con a :: a
a) = a -> Int
forall a. Enum a => a -> Int
fromEnum a
a

instance (Real a) => Real (Sym a) where
    toRational :: Sym a -> Rational
toRational (Con c :: a
c) = a -> Rational
forall a. Real a => a -> Rational
toRational a
c

instance (RealFrac a) => RealFrac (Sym a) where
    properFraction :: Sym a -> (b, Sym a)
properFraction (Con c :: a
c) = (b
i, a -> Sym a
forall a. a -> Sym a
Con a
c') where (i :: b
i, c' :: a
c') = a -> (b, a)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction a
c

instance (Floating a, Eq a) => Floating (Sym a) where
    pi :: Sym a
pi = String -> Sym a
forall a. String -> Sym a
var "pi"
    exp :: Sym a -> Sym a
exp = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
exp "exp"
    sqrt :: Sym a -> Sym a
sqrt = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
sqrt "sqrt"
    log :: Sym a -> Sym a
log = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
log "log"
    x :: Sym a
x ** :: Sym a -> Sym a -> Sym a
** y :: Sym a
y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp a -> a -> a
forall a. Floating a => a -> a -> a
(**) Sym a
x "**" Sym a
y
    logBase :: Sym a -> Sym a -> Sym a
logBase x :: Sym a
x y :: Sym a
y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp a -> a -> a
forall a. Floating a => a -> a -> a
logBase Sym a
x "logBase" Sym a
y
    sin :: Sym a -> Sym a
sin = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
sin "sin"
    tan :: Sym a -> Sym a
tan = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
tan "tan"
    cos :: Sym a -> Sym a
cos = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
cos "cos"
    asin :: Sym a -> Sym a
asin = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
asin "asin"
    atan :: Sym a -> Sym a
atan = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
atan "atan"
    acos :: Sym a -> Sym a
acos = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
acos "acos"
    sinh :: Sym a -> Sym a
sinh = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
sinh "sinh"
    tanh :: Sym a -> Sym a
tanh = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
tanh "tanh"
    cosh :: Sym a -> Sym a
cosh = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
cosh "cosh"
    asinh :: Sym a -> Sym a
asinh = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
asinh "asinh"
    atanh :: Sym a -> Sym a
atanh = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
atanh "atanh"
    acosh :: Sym a -> Sym a
acosh = (a -> a) -> String -> Sym a -> Sym a
forall a. Num a => (a -> a) -> String -> Sym a -> Sym a
unOp a -> a
forall a. Floating a => a -> a
acosh "acosh"

instance (RealFloat a, Show a) => RealFloat (Sym a) where
    floatRadix :: Sym a -> Integer
floatRadix = a -> Integer
forall a. RealFloat a => a -> Integer
floatRadix (a -> Integer) -> (Sym a -> a) -> Sym a -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sym a -> a
forall a. Show a => Sym a -> a
unSym
    floatDigits :: Sym a -> Int
floatDigits = a -> Int
forall a. RealFloat a => a -> Int
floatDigits (a -> Int) -> (Sym a -> a) -> Sym a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sym a -> a
forall a. Show a => Sym a -> a
unSym
    floatRange :: Sym a -> (Int, Int)
floatRange  = a -> (Int, Int)
forall a. RealFloat a => a -> (Int, Int)
floatRange (a -> (Int, Int)) -> (Sym a -> a) -> Sym a -> (Int, Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sym a -> a
forall a. Show a => Sym a -> a
unSym
    decodeFloat :: Sym a -> (Integer, Int)
decodeFloat (Con c :: a
c) = a -> (Integer, Int)
forall a. RealFloat a => a -> (Integer, Int)
decodeFloat a
c
    encodeFloat :: Integer -> Int -> Sym a
encodeFloat m :: Integer
m e :: Int
e = a -> Sym a
forall a. a -> Sym a
Con (Integer -> Int -> a
forall a. RealFloat a => Integer -> Int -> a
encodeFloat Integer
m Int
e)
    exponent :: Sym a -> Int
exponent (Con c :: a
c) = a -> Int
forall a. RealFloat a => a -> Int
exponent a
c
    exponent _ = 0
    significand :: Sym a -> Sym a
significand (Con c :: a
c) = a -> Sym a
forall a. a -> Sym a
Con (a -> a
forall a. RealFloat a => a -> a
significand a
c)
    scaleFloat :: Int -> Sym a -> Sym a
scaleFloat k :: Int
k (Con c :: a
c) = a -> Sym a
forall a. a -> Sym a
Con (Int -> a -> a
forall a. RealFloat a => Int -> a -> a
scaleFloat Int
k a
c)
    scaleFloat _ x :: Sym a
x = Sym a
x
    isNaN :: Sym a -> Bool
isNaN (Con c :: a
c) = a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
c
    isInfinite :: Sym a -> Bool
isInfinite (Con c :: a
c) = a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
c
    isDenormalized :: Sym a -> Bool
isDenormalized (Con c :: a
c) = a -> Bool
forall a. RealFloat a => a -> Bool
isDenormalized a
c
    isNegativeZero :: Sym a -> Bool
isNegativeZero (Con c :: a
c) = a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
c
    isIEEE :: Sym a -> Bool
isIEEE = a -> Bool
forall a. RealFloat a => a -> Bool
isIEEE (a -> Bool) -> (Sym a -> a) -> Sym a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sym a -> a
forall a. Show a => Sym a -> a
unSym
    atan2 :: Sym a -> Sym a -> Sym a
atan2 x :: Sym a
x y :: Sym a
y = (a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
forall a.
(Num a, Eq a) =>
(a -> a -> a) -> Sym a -> String -> Sym a -> Sym a
binOp a -> a -> a
forall a. RealFloat a => a -> a -> a
atan2 Sym a
x "atan2" Sym a
y