--------------------------------------------------------------------------------------------
--   Posit Numbers
--   Copyright   :  (C) 2022-2023 Nathan Waivio
--   License     :  BSD3
--   Maintainer  :  Nathan Waivio <nathan.waivio@gmail.com>
--   Stability   :  Stable
--   Portability :  Portable
--
-- | Library implementing standard Posit Numbers both Posit Standard version
--   3.2 and 2022, with some improvements.  Posit is the interface, PositC 
--   provides the implemetation.  2's Complement Fixed Point Integers,
--   and Rational numbers, are used throughout, as well as Integers & Naturals.
--   Encode and Decode are indexed through a Type Family.
-- 
---------------------------------------------------------------------------------------------


{-# LANGUAGE GADTs #-} --   For our main type Posit (es :: ES)
{-# LANGUAGE DataKinds #-}  --   For our ES kind and the constructors Z, I, II, III, IV, V for exponent size type, post-pended with the version.
{-# LANGUAGE KindSignatures #-}  --   For defining the type of kind ES that indexes the GADT
{-# LANGUAGE ViewPatterns #-}  --   To decode the posit in the pattern
{-# LANGUAGE BangPatterns #-}  --   Added Strictness for some fixed point algorithms
{-# LANGUAGE PatternSynonyms #-}  --   for a nice NaR interface
{-# LANGUAGE FlexibleInstances #-} --   To make instances for each specific type [Posit8 .. Posit256], and [P8 .. P256]
{-# LANGUAGE FlexibleContexts #-} --   If anybody knows what's this for let me know...
{-# LANGUAGE TypeApplications #-} --   To apply types: @Type, it seems to select the specific class instance, when GHC is not able to reason about things, commenting this out shows an interesting interface
{-# LANGUAGE MultiParamTypeClasses #-}  --   To convert between Posit Types, via Rational
{-# LANGUAGE ScopedTypeVariables #-} --   To reduce some code duplication, this is important
{-# LANGUAGE UndecidableInstances #-}  --   To reduce some code duplication, I think the code is decidable but GHC is not smart enough ;), like there being only 1 instance that is polymorphic and works for all of my types.
{-# LANGUAGE CPP #-} --   To remove Storable instances to remove noise when performing analysis of Core
{-# OPTIONS_GHC -Wno-unticked-promoted-constructors #-}  --   Turn off noise
{-# OPTIONS_GHC -Wno-type-defaults #-}  --   Turn off noise
{-# OPTIONS_GHC -Wno-unused-top-binds #-}  --   Turn off noise


-- ----
--  Posit numbers implementing:
--
--    * Show
--    * Eq  -- equality via an integer representation
--    * Ord  -- compare via an integer representation
--    * Num  -- Addition, subtraction, multiplication, and other operations most via Rational, negate is via an integer representation
--    * Enum  -- Successor and Predecessor
--    * Fractional  -- division, divide by zero is Not a Real (NaR) number
--    * Real
--    * Bounded
--    * FusedOps  -- dot product and others
--    * Convertible  -- Conversions between different posit formats
--    * AltShow
--    * Read
--    * Storable  -- Formats for binary data, for computation and data interchange
--    * RealFrac
--    * RealFloat
--    * Floating  -- Mathematical functions such as logarithm, exponential, trigonometric, and hyperbolic functions. Warning! May induce trance.
--
-- ----

module Posit
(Posit(),
 -- * Main Exported Types
 Posit8, -- |A Posit-3.2 8-bit Posit number with 'exponentSize' = '0', and 1 byte wide
 Posit16, -- |A Posit-3.2 16-bit Posit number with 'exponentSize' = '1', and 2 bytes wide
 Posit32, -- |A Posit-3.2 32-bit Posit number with 'exponentSize' = '2', and 4 bytes wide
 Posit64, -- |A Posit-3.2 64-bit Posit number with 'exponentSize' = '3', and 8 bytes wide
 Posit128, -- |A Posit-3.2 128-bit Posit number with 'exponentSize' = '4', and 16 bytes wide
 Posit256, -- |A Posit-3.2 256-bit Posit number with 'exponentSize' = '5', and 32 bytes wide
 P8, -- |A Posit-2022 8-bit Posit number with 'exponentSize' = '2', and 1 byte wide
 P16, -- |A Posit-2022 16-bit Posit number with 'exponentSize' = '2', and 2 bytes wide
 P32, -- |A Posit-2022 32-bit Posit number with 'exponentSize' = '2', and 4 bytes wide
 P64, -- |A Posit-2022 64-bit Posit number with 'exponentSize' = '2', and 8 bytes wide
 P128, -- |A Posit-2022 128-bit Posit number with 'exponentSize' = '2', and 16 bytes wide
 P256, -- |A Posit-2022 256-bit Posit number with 'exponentSize' = '2', and 32 bytes wide
 
 -- * A Complete Pair of Patterns for Matching Exported Types
 pattern NaR,  -- |A pattern for Exception handling when a value is Not a Real number (NaR).
 pattern R,  -- |A pattern for the non-Exceptional case, yielding a Rational, will make a total function when paired with NaR, if the Rational implementation is total.
 
 -- * Fused Operation Interface defined by the Posit Standard
 FusedOps(..),
 
 -- * Posits are Convertable between different Posit representations
 Convertible(..),
 
#ifndef O_NO_SHOW
 -- * Additional functions to show the Posit in different formats
 AltShow(..),
#endif
 
 -- * Additional Special Functions
 AltFloating(..),
 
 -- * Functions to lift functions of Integers or Rationals to operate on Posit Types
 viaIntegral,
 viaRational,
 viaRational2,
 viaRational3,
 viaRational4,
 viaRational6,
 viaRational8
 
 ) where


import Prelude hiding (rem)

-- Imports for Show and Read Instances
import Data.Scientific (scientificP
                       ,fromRationalRepetendUnlimited
                       ,formatScientific
                       ,FPFormat(Generic)) -- Used to print/show and read the rational value

import Text.Read (Lexeme(Ident)
                 ,readPrec
                 ,readListPrec
                 ,(+++)
                 ,pfail
                 ,readListPrecDefault
                 ,lexP
                 ,lift
                 ,parens) -- Used to read a Posit value

-- Imports for Vectorization Class Instances
import Data.Foldable (toList)  -- Used for fused operations on foldable/lists

-- Imports for Storable Instance
import Foreign.Storable (Storable, sizeOf, alignment, peek, poke)  -- Used for Storable Instances of Posit
import Foreign.Ptr (Ptr, castPtr)  -- Used for dealing with Pointers for the Posit Storable Instance


-- would like to:
-- import Posit.Internal.ElementaryFunctions
-- Perhaps on the chopping block if we are moving to ElementaryFunctions
-- Imports for implementing the Transcendental Functions
import GHC.Natural (Natural) -- Import the Natural Numbers ℕ (u+2115) for some of the Transcendental Functions
import Data.Ratio ((%))  -- Import the Rational Numbers ℚ (u+211A), ℚ can get arbitrarily close to Real numbers ℝ (u+211D), used for some of the Transcendental Functions

-- for NFData instance
import Control.DeepSeq (NFData, rnf)

-- import Debug.Trace (trace) -- temporary for debug purposes


-- =====================================================================
-- ===                  Posit Implementation                         ===
-- =====================================================================

-- The machine implementation of the Posit encoding/decoding
import Posit.Internal.PositC  -- The main internal implementation details


-- |Base GADT rapper type, that uses the Exponent Size kind to index the various implementations
data Posit (es :: ES) where
     Posit :: PositC es => !(IntN es) -> Posit es

-- |NFData Instance
instance NFData (Posit es) where
  rnf :: Posit es -> ()
rnf (Posit IntN es
_) = ()

-- |Not a Real Number, the Posit is like a Maybe type, it's either a real number or not
pattern NaR :: forall es. PositC es => Posit es
pattern $bNaR :: forall (es :: ES). PositC es => Posit es
$mNaR :: forall {r} {es :: ES}.
PositC es =>
Posit es -> ((# #) -> r) -> ((# #) -> r) -> r
NaR <- (Posit (decode @es -> Nothing)) where
  NaR = forall (es :: ES). PositC es => IntN es -> Posit es
Posit (forall (es :: ES). PositC es => IntN es
unReal @es)
--

--
-- |A Real or at least Rational Number, rounded to the nearest Posit Rational representation
pattern R :: forall es. PositC es => Rational -> Posit es
pattern $bR :: forall (es :: ES). PositC es => Rational -> Posit es
$mR :: forall {r} {es :: ES}.
PositC es =>
Posit es -> (Rational -> r) -> ((# #) -> r) -> r
R r <- (Posit (decode @es -> Just r)) where
  R Rational
r = forall (es :: ES). PositC es => IntN es -> Posit es
Posit (forall (es :: ES). PositC es => Maybe Rational -> IntN es
encode @es forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just Rational
r)
--

-- Posit functions are complete if the following two patterns are completely defined.
{-# COMPLETE NaR, R #-}

-- Concrete 3.2 types exported for use.
type Posit8 = Posit Z_3_2
type Posit16 = Posit I_3_2
type Posit32 = Posit II_3_2
type Posit64 = Posit III_3_2
type Posit128 = Posit IV_3_2
type Posit256 = Posit V_3_2

-- Concrete 2022 types exported for use.
type P8 = Posit Z_2022
type P16 = Posit I_2022
type P32 = Posit II_2022
type P64 = Posit III_2022
type P128 = Posit IV_2022
type P256 = Posit V_2022

#ifndef O_NO_SHOW
-- Show
--
instance PositC es => Show (Posit es) where
  show :: Posit es -> String
show Posit es
NaR = String
"NaR"
  show (R Rational
r) = FPFormat -> Maybe Int -> Scientific -> String
formatScientific FPFormat
Generic (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall (es :: ES). PositC es => Int
decimalPrec @es) (forall a b. (a, b) -> a
fstforall b c a. (b -> c) -> (a -> b) -> a -> c
.Rational -> (Scientific, Maybe Int)
fromRationalRepetendUnlimited forall a b. (a -> b) -> a -> b
$ Rational
r)
--
#endif



-- Two Posit Numbers are Equal if their Finite Precision Integer representation is Equal
--
-- All things equal I would rather write it like this:
instance PositC es => Eq (Posit es) where
  (Posit IntN es
int1) == :: Posit es -> Posit es -> Bool
== (Posit IntN es
int2) = IntN es
int1 forall a. Eq a => a -> a -> Bool
== IntN es
int2
--



-- Two Posit Numbers are ordered by their Finite Precision Integer representation
--
-- Ordinarily I would only like one instance to cover them all
instance PositC es => Ord (Posit es) where
  compare :: Posit es -> Posit es -> Ordering
compare (Posit IntN es
int1) (Posit IntN es
int2) = forall a. Ord a => a -> a -> Ordering
compare IntN es
int1 IntN es
int2
--



-- Num
--
-- I'm num trying to get this definition:
instance PositC es => Num (Posit es) where
  -- Addition
  + :: Posit es -> Posit es -> Posit es
(+) = forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es
viaRational2 forall a. Num a => a -> a -> a
(+)
  -- Multiplication
  * :: Posit es -> Posit es -> Posit es
(*) = forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es
viaRational2 forall a. Num a => a -> a -> a
(*)
  -- 'abs', Absolute Value, it's like a magnitude of sorts, abs of a posit is the same as abs of the integer representation
  abs :: Posit es -> Posit es
abs = forall (es :: ES).
PositC es =>
(IntN es -> IntN es) -> Posit es -> Posit es
viaIntegral forall a. Num a => a -> a
abs
  -- 'signum' it is a kind of an representation of directionality, the sign of a number for instance
  signum :: Posit es -> Posit es
signum = forall (es :: ES).
PositC es =>
(Rational -> Rational) -> Posit es -> Posit es
viaRational forall a. Num a => a -> a
signum
  -- 'fromInteger' rounds the integer into the closest posit number
  fromInteger :: Integer -> Posit es
fromInteger Integer
int = forall (es :: ES). PositC es => Rational -> Posit es
R forall a b. (a -> b) -> a -> b
$ forall a. Num a => Integer -> a
fromInteger Integer
int
  -- 'negate', Negates the sign of the directionality. negate of a posit is the same as negate of the integer representation
  negate :: Posit es -> Posit es
negate = forall (es :: ES).
PositC es =>
(IntN es -> IntN es) -> Posit es -> Posit es
viaIntegral forall a. Num a => a -> a
negate
--

-- deriving via Integral Class, for the Integral representation of the posit
viaIntegral :: PositC es => (IntN es -> IntN es) -> Posit es -> Posit es
viaIntegral :: forall (es :: ES).
PositC es =>
(IntN es -> IntN es) -> Posit es -> Posit es
viaIntegral IntN es -> IntN es
f (Posit IntN es
int) = forall (es :: ES). PositC es => IntN es -> Posit es
Posit forall a b. (a -> b) -> a -> b
$ IntN es -> IntN es
f IntN es
int
--



-- Enum-ish, A Posit has a Successor and Predecessor so its an ordinal number, as per Posit standard next, prior
-- The Posit Standard requires 2's complement integer overflow to be ignored
instance PositC es => Enum (Posit es) where
  -- succ (Posit int) = Posit (int + 1)  -- Successor
  succ :: Posit es -> Posit es
succ = forall (es :: ES).
PositC es =>
(IntN es -> IntN es) -> Posit es -> Posit es
viaIntegral (forall a. Num a => a -> a -> a
+IntN es
1)  -- Posit Standard `next`
  -- succ = viaIntegral succ  -- Non-compliant, runtime error pred NaR, and worse it is Int64 for types of greater precision, probably because of Preludes gross abomination of toEnum/fromEnum
  -- pred (Posit int) = Posit (int - 1)  -- Predicessor
  pred :: Posit es -> Posit es
pred = forall (es :: ES).
PositC es =>
(IntN es -> IntN es) -> Posit es -> Posit es
viaIntegral (forall a. Num a => a -> a -> a
subtract IntN es
1)  -- Posit Standard `prior`
  -- pred = viaIntegral pred  -- Non-compliant, runtime error pred NaR, and worse it is Int64 for types of greater precision, probably because of Preludes gross abomination of toEnum/fromEnum
  -- enumFrom :: Posit es -> [Posit es]
  enumFrom :: Posit es -> [Posit es]
enumFrom Posit es
n = forall a. Enum a => a -> a -> [a]
enumFromTo Posit es
n forall a. Bounded a => a
maxBound
  enumFromTo :: Posit es -> Posit es -> [Posit es]
enumFromTo Posit es
n Posit es
m
    | Posit es
n forall a. Eq a => a -> a -> Bool
== Posit es
m = [Posit es
n]
    | Posit es
n forall a. Ord a => a -> a -> Bool
< Posit es
m = Posit es
n forall a. a -> [a] -> [a]
: forall a. Enum a => a -> a -> [a]
enumFromTo (forall a. Enum a => a -> a
succ Posit es
n) Posit es
m
    | Bool
otherwise = []
  -- enumFromThen n m :: Posit es -> Posit es -> [Posit es]
  enumFromThen :: Posit es -> Posit es -> [Posit es]
enumFromThen Posit es
NaR Posit es
_ = [forall (es :: ES). PositC es => Posit es
NaR]
  enumFromThen Posit es
_ Posit es
NaR = [forall (es :: ES). PositC es => Posit es
NaR]
  enumFromThen Posit es
n Posit es
m = Posit es
n forall a. a -> [a] -> [a]
: Posit es -> [Posit es]
go Posit es
n
    where
      step :: Posit es
step = Posit es
m forall a. Num a => a -> a -> a
- Posit es
n
      go :: Posit es -> [Posit es]
      go :: Posit es -> [Posit es]
go Posit es
NaR = [forall (es :: ES). PositC es => Posit es
NaR]
      go !Posit es
l = case forall a. Ord a => a -> a -> Ordering
compare Posit es
step Posit es
0 of
                Ordering
LT -> let !n' :: Posit es
n' = Posit es
l forall a. Num a => a -> a -> a
+ Posit es
step  -- rounding occurs here, because the next comparison needs it, it wouldn't make sense otherwise...
                      in if Posit es
n' forall a. Num a => a -> a -> a
- Posit es
l forall a. Ord a => a -> a -> Bool
> Posit es
step
                         then []
                         else Posit es
n' forall a. a -> [a] -> [a]
: Posit es -> [Posit es]
go Posit es
n'
                Ordering
EQ -> [Posit es
n, Posit es
m]
                Ordering
GT -> let !n' :: Posit es
n' = Posit es
l forall a. Num a => a -> a -> a
+ Posit es
step
                      in if Posit es
n' forall a. Num a => a -> a -> a
- Posit es
l forall a. Ord a => a -> a -> Bool
< Posit es
step
                         then []  -- with tapered resolution this algorithm can reach a fixed point where the next value is equal to the previous value
                         else Posit es
n' forall a. a -> [a] -> [a]
: Posit es -> [Posit es]
go Posit es
n'
  enumFromThenTo :: Posit es -> Posit es -> Posit es -> [Posit es]
enumFromThenTo Posit es
NaR  Posit es
_   Posit es
_  = [forall (es :: ES). PositC es => Posit es
NaR]
  enumFromThenTo  Posit es
_  Posit es
NaR  Posit es
_  = [forall (es :: ES). PositC es => Posit es
NaR]
  enumFromThenTo  Posit es
_   Posit es
_  Posit es
NaR = [forall (es :: ES). PositC es => Posit es
NaR]
  enumFromThenTo  Posit es
e1  Posit es
e2  Posit es
e3 = forall a. (a -> Bool) -> [a] -> [a]
takeWhile Posit es -> Bool
predicate (forall a. Enum a => a -> a -> [a]
enumFromThen Posit es
e1 Posit es
e2)
    where
      mid :: Posit es
mid = (Posit es
e2 forall a. Num a => a -> a -> a
- Posit es
e1) forall a. Fractional a => a -> a -> a
/ Posit es
2
      predicate :: Posit es -> Bool
predicate | Posit es
e2 forall a. Ord a => a -> a -> Bool
>= Posit es
e1  = (forall a. Ord a => a -> a -> Bool
<= Posit es
e3 forall a. Num a => a -> a -> a
+ Posit es
mid)
                | Bool
otherwise = (forall a. Ord a => a -> a -> Bool
>= Posit es
e3 forall a. Num a => a -> a -> a
+ Posit es
mid)
--



-- Fractional Instances; (Num => Fractional)
--
-- How the Frac do I get this definition:
instance PositC es => Fractional (Posit es) where
  fromRational :: Rational -> Posit es
fromRational = forall (es :: ES). PositC es => Rational -> Posit es
R
 
  recip :: Posit es -> Posit es
recip Posit es
0 = forall (es :: ES). PositC es => Posit es
NaR
  recip Posit es
p = forall (es :: ES).
PositC es =>
(Rational -> Rational) -> Posit es -> Posit es
viaRational forall a. Fractional a => a -> a
recip Posit es
p
--

-- Rational Instances; Num & Ord Instanced => Real
--
-- I for real want this definition:
instance PositC es => Real (Posit es) where
  toRational :: Posit es -> Rational
toRational Posit es
NaR = forall a. HasCallStack => String -> a
error String
"Your input is Not a Real or Rational (NaR) number, please try again!"
  toRational (R Rational
r) = Rational
r
--

-- Implementing instances via Rational Data Type's instance,
-- The function checks for NaR, to protect against the runtime error 'toRational' would generate if called with a NaR value
-- Unary::Arity NaR guarded pass through with wrapping and unwrapping use of a Rational function
viaRational :: PositC es => (Rational -> Rational) -> Posit es -> Posit es
viaRational :: forall (es :: ES).
PositC es =>
(Rational -> Rational) -> Posit es -> Posit es
viaRational Rational -> Rational
_ Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
viaRational Rational -> Rational
f (R Rational
r) = forall a. Fractional a => Rational -> a
fromRational forall a b. (a -> b) -> a -> b
$ Rational -> Rational
f Rational
r

-- Binary NaR guarded pass through with wrapping and unwrapping use of a Rational function
viaRational2 :: PositC es => (Rational -> Rational -> Rational) -> Posit es -> Posit es -> Posit es
viaRational2 :: forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es
viaRational2 Rational -> Rational -> Rational
_ Posit es
NaR  Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational2 Rational -> Rational -> Rational
_  Posit es
_  Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
viaRational2 Rational -> Rational -> Rational
f (R Rational
r1) (R Rational
r2) = forall (es :: ES). PositC es => Rational -> Posit es
R forall a b. (a -> b) -> a -> b
$ Rational
r1 Rational -> Rational -> Rational
`f` Rational
r2

-- Ternary NaR guarded pass through with wrapping and unwrapping use of a Rational function
viaRational3 :: PositC es => (Rational -> Rational -> Rational -> Rational) -> Posit es -> Posit es -> Posit es -> Posit es
viaRational3 :: forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
viaRational3 Rational -> Rational -> Rational -> Rational
_ Posit es
NaR  Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational3 Rational -> Rational -> Rational -> Rational
_  Posit es
_  Posit es
NaR  Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational3 Rational -> Rational -> Rational -> Rational
_  Posit es
_   Posit es
_  Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
viaRational3 Rational -> Rational -> Rational -> Rational
f (R Rational
r1) (R Rational
r2) (R Rational
r3) = forall (es :: ES). PositC es => Rational -> Posit es
R forall a b. (a -> b) -> a -> b
$ Rational -> Rational -> Rational -> Rational
f Rational
r1 Rational
r2 Rational
r3

-- Quaternary NaR guarded pass through with wrapping and unwrapping use of a Rational function
viaRational4 :: PositC es => (Rational -> Rational -> Rational -> Rational -> Rational) -> Posit es -> Posit es -> Posit es -> Posit es -> Posit es
viaRational4 :: forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es -> Posit es
viaRational4 Rational -> Rational -> Rational -> Rational -> Rational
_ Posit es
NaR  Posit es
_   Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational4 Rational -> Rational -> Rational -> Rational -> Rational
_  Posit es
_  Posit es
NaR  Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational4 Rational -> Rational -> Rational -> Rational -> Rational
_  Posit es
_   Posit es
_  Posit es
NaR  Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational4 Rational -> Rational -> Rational -> Rational -> Rational
_  Posit es
_   Posit es
_   Posit es
_  Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
viaRational4 Rational -> Rational -> Rational -> Rational -> Rational
f (R Rational
r0) (R Rational
r1) (R Rational
r2) (R Rational
r3) = forall (es :: ES). PositC es => Rational -> Posit es
R forall a b. (a -> b) -> a -> b
$ Rational -> Rational -> Rational -> Rational -> Rational
f Rational
r0 Rational
r1 Rational
r2 Rational
r3

-- Senary NaR guarded pass through with wrapping and unwrapping use of a Rational function
viaRational6 :: PositC es => (Rational -> Rational -> Rational -> Rational -> Rational -> Rational -> Rational) -> Posit es -> Posit es -> Posit es -> Posit es -> Posit es -> Posit es -> Posit es
viaRational6 :: forall (es :: ES).
PositC es =>
(Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational)
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
viaRational6 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_ Posit es
NaR  Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational6 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_  Posit es
_  Posit es
NaR  Posit es
_   Posit es
_   Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational6 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_  Posit es
_   Posit es
_  Posit es
NaR  Posit es
_   Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational6 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_  Posit es
_   Posit es
_   Posit es
_  Posit es
NaR  Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational6 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_  Posit es
_   Posit es
_   Posit es
_   Posit es
_  Posit es
NaR  Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational6 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_  Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_  Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
viaRational6 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
f (R Rational
a1) (R Rational
a2) (R Rational
a3) (R Rational
b1) (R Rational
b2) (R Rational
b3) = forall (es :: ES). PositC es => Rational -> Posit es
R forall a b. (a -> b) -> a -> b
$ Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
f Rational
a1 Rational
a2 Rational
a3 Rational
b1 Rational
b2 Rational
b3

-- Octonary NaR guarded pass through with wrapping and unwrapping use of a Rational function
viaRational8 :: PositC es => (Rational -> Rational -> Rational -> Rational -> Rational -> Rational -> Rational -> Rational -> Rational) -> Posit es -> Posit es -> Posit es -> Posit es -> Posit es -> Posit es -> Posit es -> Posit es -> Posit es
viaRational8 :: forall (es :: ES).
PositC es =>
(Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational)
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
viaRational8 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_ Posit es
NaR  Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational8 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_  Posit es
_  Posit es
NaR  Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational8 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_  Posit es
_   Posit es
_  Posit es
NaR  Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational8 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_  Posit es
_   Posit es
_   Posit es
_  Posit es
NaR  Posit es
_   Posit es
_   Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational8 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_  Posit es
_   Posit es
_   Posit es
_   Posit es
_  Posit es
NaR  Posit es
_   Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational8 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_  Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_  Posit es
NaR  Posit es
_   Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational8 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_  Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_  Posit es
NaR  Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
viaRational8 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
_  Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_   Posit es
_  Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
viaRational8 Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
f (R Rational
a0) (R Rational
a1) (R Rational
a2) (R Rational
a3) (R Rational
b0) (R Rational
b1) (R Rational
b2) (R Rational
b3) = forall (es :: ES). PositC es => Rational -> Posit es
R forall a b. (a -> b) -> a -> b
$ Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
f Rational
a0 Rational
a1 Rational
a2 Rational
a3 Rational
b0 Rational
b1 Rational
b2 Rational
b3



-- Bounded, bounded to what?!? To the ℝ! NaR is out of bounds!!!
--
-- I'm bound to want this definition:
instance PositC es => Bounded (Posit es) where
  -- 'minBound' the most negative number represented
  minBound :: Posit es
minBound = forall (es :: ES). PositC es => IntN es -> Posit es
Posit (forall (es :: ES). PositC es => IntN es
mostNegVal @es)
  -- 'maxBound' the most positive number represented
  maxBound :: Posit es
maxBound = forall (es :: ES). PositC es => IntN es -> Posit es
Posit (forall (es :: ES). PositC es => IntN es
mostPosVal @es)
--


-- =====================================================================
-- ===                    Fused Operations                           ===
-- =====================================================================

-- |A class that delays the rounding operation until the end for some operations
class Num a => FusedOps a where
  -- |Fused Multiply Add: (a * b) + c
  fma :: a -> a -> a -> a
  -- |Fused Add Multiply: (a + b) * c
  fam :: a -> a -> a -> a
  -- |Fused Multiply Multiply Subtract: (a * b) - (c * d)
  fmms :: a -> a -> a -> a -> a
  -- |Fused Sum of 3 values: a + b + c
  fsum3 :: a -> a -> a -> a
  -- |Fused Sum of 4 values: a + b + c + d
  fsum4 :: a -> a -> a -> a -> a
  -- |Fused Sum of a List of Posits
  fsumL :: Foldable t => t a -> a
  -- |Fused Dot Product of 3 element vector: (a1 * b1) + (a2 * b2) + (a3 * b3)
  fdot3 :: a -> a -> a -> a -> a -> a -> a
  -- |Fused Dot Product of 4 element vector: (a0 * b0) + (a1 * b1) + (a2 * b2) + (a3 * b3)
  fdot4 :: a -> a -> a -> a -> a -> a -> a -> a -> a
  -- |Fused Dot Product of Two Lists
  fdotL :: Foldable t => t a -> t a -> a
  -- |Fused Subtract Multiply: a - (b * c)
  fsm :: a -> a -> a -> a
 


-- Rational Instance
instance FusedOps Rational where
  fsm :: Rational -> Rational -> Rational -> Rational
fsm Rational
a Rational
b Rational
c = Rational
a forall a. Num a => a -> a -> a
- (Rational
b forall a. Num a => a -> a -> a
* Rational
c)
  fma :: Rational -> Rational -> Rational -> Rational
fma Rational
a Rational
b Rational
c = (Rational
a forall a. Num a => a -> a -> a
* Rational
b) forall a. Num a => a -> a -> a
+ Rational
c
  fam :: Rational -> Rational -> Rational -> Rational
fam Rational
a Rational
b Rational
c = (Rational
a forall a. Num a => a -> a -> a
+ Rational
b) forall a. Num a => a -> a -> a
* Rational
c
  fmms :: Rational -> Rational -> Rational -> Rational -> Rational
fmms Rational
a Rational
b Rational
c Rational
d = (Rational
a forall a. Num a => a -> a -> a
* Rational
b) forall a. Num a => a -> a -> a
- (Rational
c forall a. Num a => a -> a -> a
* Rational
d)
  fsum3 :: Rational -> Rational -> Rational -> Rational
fsum3 Rational
a Rational
b Rational
c = Rational
a forall a. Num a => a -> a -> a
+ Rational
b forall a. Num a => a -> a -> a
+ Rational
c
  fsum4 :: Rational -> Rational -> Rational -> Rational -> Rational
fsum4 Rational
a Rational
b Rational
c Rational
d = Rational
a forall a. Num a => a -> a -> a
+ Rational
b forall a. Num a => a -> a -> a
+ Rational
c forall a. Num a => a -> a -> a
+ Rational
d
  fsumL :: forall (t :: * -> *). Foldable t => t Rational -> Rational
fsumL (forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [Rational]
l) = forall {t}. Num t => [t] -> t -> t
go [Rational]
l Rational
0
    where
      go :: [t] -> t -> t
go [] t
acc = t
acc
      go (t
x : [t]
xs) t
acc = [t] -> t -> t
go [t]
xs (t
acc forall a. Num a => a -> a -> a
+ t
x)
  fdot3 :: Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
fdot3 Rational
a1 Rational
a2 Rational
a3 Rational
b1 Rational
b2 Rational
b3 = (Rational
a1 forall a. Num a => a -> a -> a
* Rational
b1) forall a. Num a => a -> a -> a
+ (Rational
a2 forall a. Num a => a -> a -> a
* Rational
b2) forall a. Num a => a -> a -> a
+ (Rational
a3 forall a. Num a => a -> a -> a
* Rational
b3)
  fdot4 :: Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
-> Rational
fdot4 Rational
a0 Rational
a1 Rational
a2 Rational
a3 Rational
b0 Rational
b1 Rational
b2 Rational
b3 = (Rational
a0 forall a. Num a => a -> a -> a
* Rational
b0) forall a. Num a => a -> a -> a
+ (Rational
a1 forall a. Num a => a -> a -> a
* Rational
b1) forall a. Num a => a -> a -> a
+ (Rational
a2 forall a. Num a => a -> a -> a
* Rational
b2) forall a. Num a => a -> a -> a
+ (Rational
a3 forall a. Num a => a -> a -> a
* Rational
b3)
  fdotL :: forall (t :: * -> *).
Foldable t =>
t Rational -> t Rational -> Rational
fdotL (forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [Rational]
l1) (forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [Rational]
l2) = forall {t}. FusedOps t => [t] -> [t] -> t -> t
go [Rational]
l1 [Rational]
l2 Rational
0
    where
      go :: [t] -> [t] -> t -> t
go [] [] t
acc = t
acc
      go []  [t]
_  t
_  = forall a. HasCallStack => String -> a
error String
"Lists not the same length"
      go [t]
_  []  t
_  = forall a. HasCallStack => String -> a
error String
"Lists not the same length"
      go (t
b : [t]
bs) (t
c : [t]
cs) t
acc = [t] -> [t] -> t -> t
go [t]
bs [t]
cs (forall a. FusedOps a => a -> a -> a -> a
fma t
b t
c t
acc)
--

--
instance PositC es => FusedOps (Posit es) where
  -- Fused Subtract Multiply
  fsm :: Posit es -> Posit es -> Posit es -> Posit es
fsm = forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
viaRational3 forall a. FusedOps a => a -> a -> a -> a
fsm
  -- Fuse Multiply Add
  fma :: Posit es -> Posit es -> Posit es -> Posit es
fma = forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
viaRational3 forall a. FusedOps a => a -> a -> a -> a
fma
  -- Fuse Add Multiply
  fam :: Posit es -> Posit es -> Posit es -> Posit es
fam = forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
viaRational3 forall a. FusedOps a => a -> a -> a -> a
fam
  -- Fuse Multiply Multiply Subtract
  fmms :: Posit es -> Posit es -> Posit es -> Posit es -> Posit es
fmms = forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es -> Posit es
viaRational4 forall a. FusedOps a => a -> a -> a -> a -> a
fmms
  -- Fuse Sum of 3 Posits
  fsum3 :: Posit es -> Posit es -> Posit es -> Posit es
fsum3 = forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
viaRational3 forall a. FusedOps a => a -> a -> a -> a
fsum3
  -- Fuse Sum of 4 Posits
  fsum4 :: Posit es -> Posit es -> Posit es -> Posit es -> Posit es
fsum4 = forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es -> Posit es
viaRational4 forall a. FusedOps a => a -> a -> a -> a -> a
fsum4
  -- Fuse Sum of a List
  fsumL :: forall (t :: * -> *). Foldable t => t (Posit es) -> Posit es
fsumL (forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [Posit es]
l) = forall (es :: ES). PositC es => IntN es -> Posit es
Posit forall a b. (a -> b) -> a -> b
$ forall (es :: ES). PositC es => Maybe Rational -> IntN es
encode @es (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ [Posit es] -> Rational -> Rational
go [Posit es]
l Rational
0)
    where
      go :: [Posit es] -> Rational -> Rational
      go :: [Posit es] -> Rational -> Rational
go [] !Rational
acc = Rational
acc
      go ((Posit IntN es
int) : [Posit es]
xs) !Rational
acc = case forall (es :: ES). PositC es => IntN es -> Maybe Rational
decode @es IntN es
int of
                                     Maybe Rational
Nothing -> forall a. HasCallStack => String -> a
error String
"Posit List contains NaR"
                                     Just Rational
r -> [Posit es] -> Rational -> Rational
go [Posit es]
xs (Rational
acc forall a. Num a => a -> a -> a
+ Rational
r)
  -- Fuse Dot Product of a 3-Vector
  fdot3 :: Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
fdot3 = forall (es :: ES).
PositC es =>
(Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational)
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
viaRational6 forall a. FusedOps a => a -> a -> a -> a -> a -> a -> a
fdot3
  -- Fuse Dot Product of a 4-Vector
  fdot4 :: Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
fdot4 = forall (es :: ES).
PositC es =>
(Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational)
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
viaRational8 forall a. FusedOps a => a -> a -> a -> a -> a -> a -> a -> a -> a
fdot4
  -- Fuse Dot Product of two Lists
  fdotL :: forall (t :: * -> *).
Foldable t =>
t (Posit es) -> t (Posit es) -> Posit es
fdotL (forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [Posit es]
l1) (forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [Posit es]
l2) = forall (es :: ES). PositC es => IntN es -> Posit es
Posit forall a b. (a -> b) -> a -> b
$ forall (es :: ES). PositC es => Maybe Rational -> IntN es
encode @es (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ [Posit es] -> [Posit es] -> Rational -> Rational
go [Posit es]
l1 [Posit es]
l2 Rational
0)
    where
      go :: [Posit es] -> [Posit es] -> Rational -> Rational
go [] [] !Rational
acc = Rational
acc
      go []  [Posit es]
_   Rational
_  = forall a. HasCallStack => String -> a
error String
"Lists not the same length"
      go [Posit es]
_  []   Rational
_  = forall a. HasCallStack => String -> a
error String
"Lists not the same length"
      go ((Posit IntN es
int1) : [Posit es]
bs) ((Posit IntN es
int2) : [Posit es]
cs) !Rational
acc = case forall (es :: ES). PositC es => IntN es -> Maybe Rational
decode @es IntN es
int1 of
                                                          Maybe Rational
Nothing -> forall a. HasCallStack => String -> a
error String
"First Posit List contains NaR"
                                                          Just Rational
r1 -> case forall (es :: ES). PositC es => IntN es -> Maybe Rational
decode @es IntN es
int2 of
                                                                       Maybe Rational
Nothing -> forall a. HasCallStack => String -> a
error String
"Second Posit List contains NaR"
                                                                       Just Rational
r2 -> [Posit es] -> [Posit es] -> Rational -> Rational
go [Posit es]
bs [Posit es]
cs (Rational
acc forall a. Num a => a -> a -> a
+ (Rational
r1 forall a. Num a => a -> a -> a
* Rational
r2))
--




-- =====================================================================
-- ===                  Conversion Between Posits Types              ===
-- =====================================================================

-- |A Convertible class that will cast or 'convert' between two different Posit es types
class Convertible a b where
  convert :: a -> b

instance (PositC es1, PositC es2) => Convertible (Posit es1) (Posit es2) where
  convert :: Posit es1 -> Posit es2
convert Posit es1
NaR = forall (es :: ES). PositC es => Posit es
NaR
  convert (R Rational
r) = forall (es :: ES). PositC es => Rational -> Posit es
R Rational
r
--


#ifndef O_NO_SHOW
-- =====================================================================
-- ===                Alternative Show Formats                       ===
-- =====================================================================

-- |A Alternative to the typical 'Show' class to assist in displaying the Posit es type in different formats
class AltShow a where
  -- |Display the Posit in its Binary Representation
  displayBinary :: a -> String
  -- |Display the Posit in its Integral Representation
  displayIntegral :: a -> String
  -- |Display the Posit as a Rational
  displayRational :: a -> String
  -- |Display the Posit as a Decimal until the Repetend occurs
  displayDecimal :: a -> String
--

--
instance PositC es => AltShow (Posit es) where
  displayBinary :: Posit es -> String
displayBinary (Posit IntN es
int) = forall (es :: ES). PositC es => IntN es -> String
displayBin @es IntN es
int
 
  displayIntegral :: Posit es -> String
displayIntegral (Posit IntN es
int) = forall a. Show a => a -> String
show IntN es
int
 
  displayRational :: Posit es -> String
displayRational = forall a (es :: ES).
(Show a, PositC es) =>
(Rational -> a) -> Posit es -> String
viaShowable forall a. a -> a
id
 
  displayDecimal :: Posit es -> String
displayDecimal = forall a (es :: ES).
(Show a, PositC es) =>
(Rational -> a) -> Posit es -> String
viaShowable (forall a b. (a, b) -> a
fstforall b c a. (b -> c) -> (a -> b) -> a -> c
.Rational -> (Scientific, Maybe Int)
fromRationalRepetendUnlimited)
--

viaShowable :: (Show a, PositC es) => (Rational -> a) -> Posit es -> String
viaShowable :: forall a (es :: ES).
(Show a, PositC es) =>
(Rational -> a) -> Posit es -> String
viaShowable Rational -> a
_ Posit es
NaR = String
"NaR"
viaShowable Rational -> a
f (R Rational
r) = forall a. Show a => a -> String
show forall a b. (a -> b) -> a -> b
$ Rational -> a
f Rational
r
#endif

#ifndef O_NO_READ
-- =====================================================================
-- ===                         Read Posit                            ===
-- =====================================================================

--
instance PositC es => Read (Posit es) where
  readPrec :: ReadPrec (Posit es)
readPrec =
    forall a. ReadPrec a -> ReadPrec a
parens forall a b. (a -> b) -> a -> b
$ do
      Lexeme
x <- ReadPrec Lexeme
lexP
      case Lexeme
x of
        Ident String
"NaR" -> forall (m :: * -> *) a. Monad m => a -> m a
return forall (es :: ES). PositC es => Posit es
NaR
        Lexeme
_ -> forall a. ReadPrec a
pfail
      forall a. ReadPrec a -> ReadPrec a -> ReadPrec a
+++
      do
        Scientific
s <- forall a. ReadP a -> ReadPrec a
lift ReadP Scientific
scientificP
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (es :: ES). PositC es => Rational -> Posit es
R (forall a. Real a => a -> Rational
toRational Scientific
s)
 
  readListPrec :: ReadPrec [Posit es]
readListPrec = forall a. Read a => ReadPrec [a]
readListPrecDefault
--
#endif


-- =====================================================================
-- ===                  Storable Instances                           ===
-- =====================================================================
--
#ifndef O_NO_STORABLE
--
instance PositC es => Storable (Posit es) where
  sizeOf :: Posit es -> Int
sizeOf Posit es
_ = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall (es :: ES). PositC es => Natural
nBytes @es
  alignment :: Posit es -> Int
alignment Posit es
_ = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall (es :: ES). PositC es => Natural
nBytes @es
  peek :: Ptr (Posit es) -> IO (Posit es)
peek Ptr (Posit es)
ptr = do
    IntN es
int <- forall a. Storable a => Ptr a -> IO a
peek (forall a b. Ptr a -> Ptr b
castPtr Ptr (Posit es)
ptr :: Ptr (IntN es))
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (es :: ES). PositC es => IntN es -> Posit es
Posit IntN es
int
  poke :: Ptr (Posit es) -> Posit es -> IO ()
poke Ptr (Posit es)
ptr (Posit IntN es
int) = do
    forall a. Storable a => Ptr a -> a -> IO ()
poke (forall a b. Ptr a -> Ptr b
castPtr Ptr (Posit es)
ptr :: Ptr (IntN es)) IntN es
int
--
#endif


-- =====================================================================
-- ===                        Real Frac                              ===
-- =====================================================================

--
instance PositC es => RealFrac (Posit es) where
  -- properFraction :: Integral b => a -> (b, a)
  properFraction :: forall b. Integral b => Posit es -> (b, Posit es)
properFraction = forall (es :: ES) a.
PositC es =>
String -> (Rational -> (a, Rational)) -> Posit es -> (a, Posit es)
viaRationalErrTrunkation String
"NaR value is not a RealFrac" forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction
--

viaRationalErrTrunkation :: PositC es => String -> (Rational -> (a, Rational)) -> Posit es -> (a, Posit es)
viaRationalErrTrunkation :: forall (es :: ES) a.
PositC es =>
String -> (Rational -> (a, Rational)) -> Posit es -> (a, Posit es)
viaRationalErrTrunkation String
err Rational -> (a, Rational)
_ Posit es
NaR = forall a. HasCallStack => String -> a
error String
err
viaRationalErrTrunkation String
_ Rational -> (a, Rational)
f (R Rational
r) =
  let (a
int, Rational
r') = Rational -> (a, Rational)
f Rational
r
  in (a
int, forall (es :: ES). PositC es => Rational -> Posit es
R Rational
r')

-- =====================================================================
-- ===                         Real Float                            ===
-- =====================================================================
--
instance (Floating (Posit es), PositC es) => RealFloat (Posit es) where
  isIEEE :: Posit es -> Bool
isIEEE Posit es
_ = Bool
False
  isDenormalized :: Posit es -> Bool
isDenormalized Posit es
_ = Bool
False
  isNegativeZero :: Posit es -> Bool
isNegativeZero Posit es
_ = Bool
False
 
  isNaN :: Posit es -> Bool
isNaN Posit es
NaR = Bool
True
  isNaN  Posit es
_  = Bool
False
 
  isInfinite :: Posit es -> Bool
isInfinite Posit es
NaR = Bool
True
  isInfinite Posit es
_ = Bool
False
 
  -- 'atan2' of y x is the argument "arg function" (also called phase or angle) of the complex number x + i y.
  -- angle from an x basis vector to some other vector
  --
  --     Y
  --     ^
  --     |    ^ (x,y)
  --     |   /
  --     |  / <-  alpha (radians)
  --     | /                      \
  --      /                        |
  --      -----------------------------------> X
  --
  --
  atan2 :: Posit es -> Posit es -> Posit es
atan2 Posit es
NaR  Posit es
_  = forall (es :: ES). PositC es => Posit es
NaR
  atan2  Posit es
_  Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
  atan2 Posit es
y Posit es
x
    | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
0 Bool -> Bool -> Bool
&& Posit es
y forall a. Eq a => a -> a -> Bool
== Posit es
0 = forall (es :: ES). PositC es => Posit es
NaR
    | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
0             = forall a. Floating a => a -> a
atan (Posit es
yforall a. Fractional a => a -> a -> a
/Posit es
x)
    | Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0  Bool -> Bool -> Bool
&& Posit es
y forall a. Ord a => a -> a -> Bool
>= Posit es
0  = forall a. Floating a => a -> a
atan (Posit es
yforall a. Fractional a => a -> a -> a
/Posit es
x) forall a. Num a => a -> a -> a
+ forall a. Floating a => a
pi
    | Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0  Bool -> Bool -> Bool
&& Posit es
y  forall a. Ord a => a -> a -> Bool
< Posit es
0  = forall a. Floating a => a -> a
atan (Posit es
yforall a. Fractional a => a -> a -> a
/Posit es
x) forall a. Num a => a -> a -> a
- forall a. Floating a => a
pi
    | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
0 Bool -> Bool -> Bool
&& Posit es
y  forall a. Ord a => a -> a -> Bool
> Posit es
0  = forall a. Floating a => a
pi forall a. Fractional a => a -> a -> a
/ Posit es
2
    | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
0 Bool -> Bool -> Bool
&& Posit es
y  forall a. Ord a => a -> a -> Bool
< Posit es
0  = forall a. Num a => a -> a
negate forall a b. (a -> b) -> a -> b
$ forall a. Floating a => a
pi forall a. Fractional a => a -> a -> a
/ Posit es
2
    | Bool
otherwise = forall a. HasCallStack => String -> a
error String
"What!?!?!" -- The case where x == 0 && y == 0
 
  floatRadix :: Posit es -> Integer
floatRadix Posit es
_ = Integer
2
  floatDigits :: Posit es -> Int
floatDigits Posit es
_ = forall a. HasCallStack => a
undefined
  floatRange :: Posit es -> (Int, Int)
floatRange Posit es
_ = (forall a. Num a => a -> a
negate Int
maxExponent, Int
maxExponent)
    where
      maxExponent :: Int
maxExponent = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (forall (es :: ES). PositC es => Natural
nBytes @es) forall a. Num a => a -> a -> a
* ((forall (es :: ES). PositC es => Natural
nBits @es) forall a. Num a => a -> a -> a
- Natural
2)
  decodeFloat :: Posit es -> (Integer, Int)
decodeFloat = forall a. HasCallStack => a
undefined
  encodeFloat :: Integer -> Int -> Posit es
encodeFloat = forall a. HasCallStack => a
undefined
--



-- =====================================================================
-- ===                         Floating                              ===
-- =====================================================================

instance (PositC es, PositC (Next es)) => Floating (Posit es) where
  pi :: Posit es
pi = forall (es :: ES). PositC es => Posit es
approx_pi
  exp :: Posit es -> Posit es
exp = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp
  log :: Posit es -> Posit es
log = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext forall (es :: ES). PositC es => Posit es -> Posit es
approx_log
  Posit es
x ** :: Posit es -> Posit es -> Posit es
** Posit es
y = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es) -> Posit (Next es))
-> Posit es -> Posit es -> Posit es
hiRezNext2 forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
approx_pow Posit es
x Posit es
y
  sin :: Posit es -> Posit es
sin = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext forall (es :: ES). PositC es => Posit es -> Posit es
approx_sin
  cos :: Posit es -> Posit es
cos = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext forall (es :: ES). PositC es => Posit es -> Posit es
approx_cos
  asin :: Posit es -> Posit es
asin = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext forall (es :: ES). PositC es => Posit es -> Posit es
approx_asin
  acos :: Posit es -> Posit es
acos = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext forall (es :: ES). PositC es => Posit es -> Posit es
approx_acos
  atan :: Posit es -> Posit es
atan = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan
  sinh :: Posit es -> Posit es
sinh = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext forall (es :: ES). PositC es => Posit es -> Posit es
approx_sinh
  cosh :: Posit es -> Posit es
cosh = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext forall (es :: ES). PositC es => Posit es -> Posit es
approx_cosh
  asinh :: Posit es -> Posit es
asinh = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext forall (es :: ES). PositC es => Posit es -> Posit es
approx_asinh
  acosh :: Posit es -> Posit es
acosh = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext forall (es :: ES). PositC es => Posit es -> Posit es
approx_acosh
  atanh :: Posit es -> Posit es
atanh = forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext forall (es :: ES). PositC es => Posit es -> Posit es
approx_atanh



-- Functions to step up and down in Resolution of the trancendental
-- functions so that we get properly rounded results upto 128-bits
-- Note: 256-bit resolution will not have ulp accuracy
hiRezNext :: forall es. (PositC es, PositC (Next es)) => (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext :: forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
f Posit es
x = forall a b. Convertible a b => a -> b
convert (Posit (Next es) -> Posit (Next es)
f (forall a b. Convertible a b => a -> b
convert Posit es
x) :: Posit (Next es)) :: Posit es

hiRezMax :: forall es. (PositC es, PositC (Max es)) => (Posit (Max es) -> Posit (Max es)) -> Posit es -> Posit es
hiRezMax :: forall (es :: ES).
(PositC es, PositC (Max es)) =>
(Posit (Max es) -> Posit (Max es)) -> Posit es -> Posit es
hiRezMax Posit (Max es) -> Posit (Max es)
f Posit es
x = forall a b. Convertible a b => a -> b
convert (Posit (Max es) -> Posit (Max es)
f (forall a b. Convertible a b => a -> b
convert Posit es
x) :: Posit (Max es)) :: Posit es

hiRezNext2 :: forall es. (PositC es, PositC (Next es)) => (Posit (Next es) -> Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es -> Posit es
hiRezNext2 :: forall (es :: ES).
(PositC es, PositC (Next es)) =>
(Posit (Next es) -> Posit (Next es) -> Posit (Next es))
-> Posit es -> Posit es -> Posit es
hiRezNext2 Posit (Next es) -> Posit (Next es) -> Posit (Next es)
f Posit es
x Posit es
y = forall a b. Convertible a b => a -> b
convert (Posit (Next es) -> Posit (Next es) -> Posit (Next es)
f (forall a b. Convertible a b => a -> b
convert Posit es
x :: Posit (Next es)) (forall a b. Convertible a b => a -> b
convert Posit es
y :: Posit (Next es)) ) :: Posit es

hiRezMax2 :: forall es. (PositC es, PositC (Max es)) => (Posit (Max es) -> Posit (Max es) -> Posit (Max es)) -> Posit es -> Posit es -> Posit es
hiRezMax2 :: forall (es :: ES).
(PositC es, PositC (Max es)) =>
(Posit (Max es) -> Posit (Max es) -> Posit (Max es))
-> Posit es -> Posit es -> Posit es
hiRezMax2 Posit (Max es) -> Posit (Max es) -> Posit (Max es)
f Posit es
x Posit es
y = forall a b. Convertible a b => a -> b
convert (Posit (Max es) -> Posit (Max es) -> Posit (Max es)
f (forall a b. Convertible a b => a -> b
convert Posit es
x :: Posit (Max es)) (forall a b. Convertible a b => a -> b
convert Posit es
y :: Posit (Max es)) ) :: Posit es


-- =====================================================================
--            Approximations of Trancendental Funcitons
-- =====================================================================

approx_pi :: PositC es => Posit es
approx_pi :: forall (es :: ES). PositC es => Posit es
approx_pi = Posit es
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446


approx_exp :: PositC es => Posit es -> Posit es     -- Comment by Abigale Emily:  xcddfffff
approx_exp :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp Posit es
x = forall (es :: ES).
PositC es =>
(Posit es -> Posit es) -> Posit es -> Posit es
approx_2exp forall (es :: ES). PositC es => Posit es -> Posit es
taylor_approx_exp (Posit es
x forall a. Fractional a => a -> a -> a
/ forall (es :: ES). PositC es => Posit es
lnOf2)


approx_log :: PositC es => Posit es -> Posit es
approx_log :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_log = forall (es :: ES).
PositC es =>
(Posit es -> Posit es) -> Posit es -> Posit es
funLogDomainReduction forall (es :: ES). PositC es => Posit es -> Posit es
funLogTaylor -- lnOf2 * approx_log2 x  -- the commented out was slightly less accurate


approx_pow :: (PositC es) => Posit es -> Posit es -> Posit es
Posit es
NaR approx_pow :: forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
`approx_pow` Posit es
_ = forall (es :: ES). PositC es => Posit es
NaR
Posit es
_ `approx_pow` Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_pow Posit es
0 Posit es
y
  | Posit es
y forall a. Ord a => a -> a -> Bool
< Posit es
0 = forall (es :: ES). PositC es => Posit es
NaR -- NaR: Divide by Zero
  | Posit es
y forall a. Eq a => a -> a -> Bool
== Posit es
0 = forall (es :: ES). PositC es => Posit es
NaR -- NaR: Indeterminate
  | Posit es
y forall a. Ord a => a -> a -> Bool
> Posit es
0 = Posit es
0
approx_pow Posit es
x Posit es
y
  | Posit es
y forall a. Ord a => a -> a -> Bool
< Posit es
0 = forall a. Fractional a => a -> a
recip forall a b. (a -> b) -> a -> b
$ forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
approx_pow Posit es
x (forall a. Num a => a -> a
negate Posit es
y)
  | Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0 = -- NaR if y is not an integer
    let (Integer
int,Posit es
rem) = forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Posit es
y
    in if Posit es
rem forall a. Eq a => a -> a -> Bool
== Posit es
0
       then Posit es
xforall a b. (Fractional a, Integral b) => a -> b -> a
^^Integer
int
       else forall (es :: ES). PositC es => Posit es
NaR -- NaR: Imaginary Number
  | Bool
otherwise = forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp forall a b. (a -> b) -> a -> b
$ Posit es
y forall a. Num a => a -> a -> a
* forall (es :: ES). PositC es => Posit es -> Posit es
approx_log Posit es
x


approx_sin :: forall es. PositC es => Posit es -> Posit es
approx_sin :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_sin  Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_sin Posit es
0 = Posit es
0
approx_sin Posit es
x = forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSine forall a b. (a -> b) -> a -> b
$ Posit es
x forall a. Fractional a => a -> a -> a
/ (Posit es
2forall a. Num a => a -> a -> a
*forall (es :: ES). PositC es => Posit es
approx_pi)


approx_cos :: PositC es => Posit es -> Posit es
approx_cos :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_cos Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_cos Posit es
0 = Posit es
1
approx_cos Posit es
x = forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosine forall a b. (a -> b) -> a -> b
$ Posit es
x forall a. Fractional a => a -> a -> a
/ (Posit es
2forall a. Num a => a -> a -> a
*forall (es :: ES). PositC es => Posit es
approx_pi)


approx_asin :: PositC es => Posit es -> Posit es
approx_asin :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_asin Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_asin Posit es
x
  | forall a. Num a => a -> a
abs Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
1 = forall (es :: ES). PositC es => Posit es
NaR
  | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
1 = forall (es :: ES). PositC es => Posit es
approx_piforall a. Fractional a => a -> a -> a
/Posit es
2
  | Posit es
x forall a. Eq a => a -> a -> Bool
== -Posit es
1 = -forall (es :: ES). PositC es => Posit es
approx_piforall a. Fractional a => a -> a -> a
/Posit es
2
  | Bool
otherwise = forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan Posit es
w
    where
      w :: Posit es
w = Posit es
x forall a. Fractional a => a -> a -> a
/ forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt (Posit es
1 forall a. Num a => a -> a -> a
- Posit es
xforall a b. (Num a, Integral b) => a -> b -> a
^Integer
2)


approx_acos :: PositC es => Posit es -> Posit es
approx_acos :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_acos Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_acos Posit es
x
  | forall a. Num a => a -> a
abs Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
1 = forall (es :: ES). PositC es => Posit es
NaR
  | Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0 = forall (es :: ES). PositC es => Posit es
approx_pi forall a. Num a => a -> a -> a
+ forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan Posit es
invw
  | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
0 = forall (es :: ES). PositC es => Posit es
approx_piforall a. Fractional a => a -> a -> a
/Posit es
2
  | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
0 = forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan Posit es
invw
  | Bool
otherwise = forall a. HasCallStack => String -> a
error String
"Prove it covers for Rational Numbers."
    where
      invw :: Posit es
invw = forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt (Posit es
1 forall a. Num a => a -> a -> a
- Posit es
xforall a b. (Num a, Integral b) => a -> b -> a
^Integer
2) forall a. Fractional a => a -> a -> a
/ Posit es
x


approx_atan :: PositC es => Posit es -> Posit es
approx_atan :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_atan Posit es
x
  | forall a. Num a => a -> a
abs Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
1forall a. Fractional a => a -> a -> a
/Posit es
2forall a b. (Num a, Integral b) => a -> b -> a
^Integer
122 = Posit es
x  -- small angle approximaiton, found emperically
  | Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0 = forall a. Num a => a -> a
negateforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
negate Posit es
x  -- if negative turn it positive, it reduces the other domain reductions by half, found from Universal CORDIC
  | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
1 = forall (es :: ES). PositC es => Posit es
approx_piforall a. Fractional a => a -> a -> a
/Posit es
2 forall a. Num a => a -> a -> a
- forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan (forall a. Fractional a => a -> a
recip Posit es
x)  -- if larger than one use the complementary angle, found from Universal CORDIC
  | Posit es
x forall a. Ord a => a -> a -> Bool
> forall (es :: ES). PositC es => Posit es
twoMsqrt3 = forall (es :: ES). PositC es => Posit es
approx_piforall a. Fractional a => a -> a -> a
/Posit es
6 forall a. Num a => a -> a -> a
+ forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan ((forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt Posit es
3 forall a. Num a => a -> a -> a
* Posit es
x forall a. Num a => a -> a -> a
- Posit es
1)forall a. Fractional a => a -> a -> a
/(forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt Posit es
3 forall a. Num a => a -> a -> a
+ Posit es
x))  -- another domain reduction, using an identity, found from https://mathonweb.com/help_ebook/html/algorithms.htm
  | Bool
otherwise = forall (es :: ES). PositC es => Posit es -> Posit es
taylor_approx_atan Posit es
x


approx_sinh :: PositC es => Posit es -> Posit es
approx_sinh :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_sinh Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_sinh Posit es
x = (forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp Posit es
x forall a. Num a => a -> a -> a
- forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp (forall a. Num a => a -> a
negate Posit es
x))forall a. Fractional a => a -> a -> a
/Posit es
2


approx_cosh :: PositC es => Posit es -> Posit es
approx_cosh :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_cosh Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_cosh Posit es
x = (forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp Posit es
x forall a. Num a => a -> a -> a
+ forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp (forall a. Num a => a -> a
negate Posit es
x))forall a. Fractional a => a -> a -> a
/Posit es
2


approx_asinh :: PositC es => Posit es -> Posit es
approx_asinh :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_asinh Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_asinh Posit es
x = forall (es :: ES). PositC es => Posit es -> Posit es
approx_log forall a b. (a -> b) -> a -> b
$ Posit es
x forall a. Num a => a -> a -> a
+ forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt (Posit es
xforall a b. (Num a, Integral b) => a -> b -> a
^Integer
2 forall a. Num a => a -> a -> a
+ Posit es
1)


approx_acosh :: PositC es => Posit es -> Posit es
approx_acosh :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_acosh Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_acosh Posit es
x
  | Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
1 = forall (es :: ES). PositC es => Posit es
NaR
  | Bool
otherwise = forall (es :: ES). PositC es => Posit es -> Posit es
approx_log forall a b. (a -> b) -> a -> b
$ Posit es
x forall a. Num a => a -> a -> a
+ forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt (Posit es
xforall a b. (Num a, Integral b) => a -> b -> a
^Integer
2 forall a. Num a => a -> a -> a
- Posit es
1)


approx_atanh :: forall es. PositC es => Posit es -> Posit es
approx_atanh :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_atanh Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_atanh Posit es
x
  | forall a. Num a => a -> a
abs Posit es
x forall a. Ord a => a -> a -> Bool
>= Posit es
1 = forall (es :: ES). PositC es => Posit es
NaR
  | Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0 = forall a. Num a => a -> a
negateforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (es :: ES). PositC es => Posit es -> Posit es
approx_atanhforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a. Num a => a -> a
negate forall a b. (a -> b) -> a -> b
$ Posit es
x  -- make use of odd parity to only calculate the positive part
  | Bool
otherwise = Posit es
0.5 forall a. Num a => a -> a -> a
* forall (es :: ES). PositC es => Posit es -> Posit es
approx_log ((Posit es
1forall a. Num a => a -> a -> a
+Posit es
t) forall a. Fractional a => a -> a -> a
/ (Posit es
1forall a. Num a => a -> a -> a
-Posit es
t)) forall a. Num a => a -> a -> a
- (forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
ex forall a. Fractional a => a -> a -> a
/ Posit es
2) forall a. Num a => a -> a -> a
* forall (es :: ES). PositC es => Posit es
lnOf2
    where
      (Integer
ex, Posit es
sig) = (Integer
int forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
2forall a b. (Num a, Integral b) => a -> b -> a
^(forall (es :: ES). PositC es => Natural
exponentSize @es)) forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral Natural
nat forall a. Num a => a -> a -> a
+ Integer
1, forall a. Fractional a => Rational -> a
fromRational Rational
rat forall a. Fractional a => a -> a -> a
/ Posit es
2)
      (Bool
_,Integer
int,Natural
nat,Rational
rat) = (forall (es :: ES).
PositC es =>
Rational -> (Bool, Integer, Natural, Rational)
posit2TupPosit @es)forall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a. Real a => a -> Rational
toRational forall a b. (a -> b) -> a -> b
$ Posit es
x' -- sign should always be positive
      x' :: Posit es
x' = Posit es
1 forall a. Num a => a -> a -> a
- Posit es
x
      t :: Posit es
t = (Posit es
2 forall a. Num a => a -> a -> a
- Posit es
sig forall a. Num a => a -> a -> a
- Posit es
x') forall a. Fractional a => a -> a -> a
/ (Posit es
2 forall a. Num a => a -> a -> a
+ Posit es
sig forall a. Num a => a -> a -> a
- Posit es
x')



-- =====================================================================
--     Normalized Functions or Alternative Bases
-- =====================================================================

-- normalizedSine is sine normalized by 2*pi
normalizedSine :: PositC es => Posit es -> Posit es
normalizedSine :: forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSine Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
normalizedSine Posit es
x
  | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
0 = Posit es
0
  | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
0.25 = Posit es
1
  | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
0.5 = Posit es
0
  | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
0.75 = -Posit es
1
  | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
1 = Posit es
0
  | Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0 = forall a. Num a => a -> a
negateforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSineforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a. Num a => a -> a
negate forall a b. (a -> b) -> a -> b
$ Posit es
x
  | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
1 =
    let (Integer
_,Posit es
rem) = forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Posit es
x
    in forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSine Posit es
rem
  | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
0.75 Bool -> Bool -> Bool
&& Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
1 = forall a. Num a => a -> a
negateforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSine forall a b. (a -> b) -> a -> b
$ Posit es
1 forall a. Num a => a -> a -> a
- Posit es
x -- reduce domain by quadrant symmetry
  | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
0.5 Bool -> Bool -> Bool
&& Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0.75 = forall a. Num a => a -> a
negateforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSine forall a b. (a -> b) -> a -> b
$ Posit es
x forall a. Num a => a -> a -> a
- Posit es
0.5
  | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
0.25 Bool -> Bool -> Bool
&& Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0.5 = forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSine forall a b. (a -> b) -> a -> b
$ Posit es
0.5 forall a. Num a => a -> a -> a
- Posit es
x
  | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
0.125 Bool -> Bool -> Bool
&& Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0.25 = forall (es :: ES). PositC es => Posit es -> Posit es
tuma_approx_cos forall a b. (a -> b) -> a -> b
$ Posit es
2forall a. Num a => a -> a -> a
*forall (es :: ES). PositC es => Posit es
approx_pi forall a. Num a => a -> a -> a
* (Posit es
0.25 forall a. Num a => a -> a -> a
- Posit es
x) -- reduce domain and use cofunction
  | Bool
otherwise = forall (es :: ES). PositC es => Posit es -> Posit es
tuma_approx_sin forall a b. (a -> b) -> a -> b
$ Posit es
2forall a. Num a => a -> a -> a
*forall (es :: ES). PositC es => Posit es
approx_pi forall a. Num a => a -> a -> a
* Posit es
x


-- normalizedCosine is cosine normalized for 2*pi
normalizedCosine :: PositC es => Posit es -> Posit es
normalizedCosine :: forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosine Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
normalizedCosine Posit es
x
  | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
0 = Posit es
1
  | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
0.25 = Posit es
0
  | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
0.5 = -Posit es
1
  | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
0.75 = Posit es
0
  | Posit es
x forall a. Eq a => a -> a -> Bool
== Posit es
1 = Posit es
1
  | Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0 = forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosineforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a. Num a => a -> a
negate forall a b. (a -> b) -> a -> b
$ Posit es
x  -- reduce domain by symmetry across 0 to turn x positive
  | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
1 = -- reduce domain by using perodicity
    let (Integer
_,Posit es
rem) = forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Posit es
x
    in forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosine Posit es
rem
  | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
0.75 Bool -> Bool -> Bool
&& Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
1 = forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosine forall a b. (a -> b) -> a -> b
$ Posit es
1 forall a. Num a => a -> a -> a
- Posit es
x  -- reduce domain by quadrant symmetry
  | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
0.5 Bool -> Bool -> Bool
&& Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0.75 = forall a. Num a => a -> a
negateforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosine forall a b. (a -> b) -> a -> b
$ Posit es
x forall a. Num a => a -> a -> a
- Posit es
0.5
  | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
0.25 Bool -> Bool -> Bool
&& Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0.5 = forall a. Num a => a -> a
negateforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosine forall a b. (a -> b) -> a -> b
$ Posit es
0.5 forall a. Num a => a -> a -> a
- Posit es
x
  | Posit es
x forall a. Ord a => a -> a -> Bool
> Posit es
0.125 Bool -> Bool -> Bool
&& Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0.25 = forall (es :: ES). PositC es => Posit es -> Posit es
tuma_approx_sin forall a b. (a -> b) -> a -> b
$ Posit es
2forall a. Num a => a -> a -> a
*forall (es :: ES). PositC es => Posit es
approx_pi forall a. Num a => a -> a -> a
* (Posit es
0.25 forall a. Num a => a -> a -> a
- Posit es
x) -- reduce domain and use cofunction
  | Bool
otherwise = forall (es :: ES). PositC es => Posit es -> Posit es
tuma_approx_cos forall a b. (a -> b) -> a -> b
$ Posit es
2forall a. Num a => a -> a -> a
*forall (es :: ES). PositC es => Posit es
approx_pi forall a. Num a => a -> a -> a
* Posit es
x --


-- Approximation of 2^x Domain Reduction
approx_2exp :: PositC es => (Posit es -> Posit es) -> Posit es -> Posit es
approx_2exp :: forall (es :: ES).
PositC es =>
(Posit es -> Posit es) -> Posit es -> Posit es
approx_2exp Posit es -> Posit es
_ Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_2exp Posit es -> Posit es
_ Posit es
0 = Posit es
1
approx_2exp Posit es -> Posit es
f Posit es
x
  | Posit es
x forall a. Ord a => a -> a -> Bool
< Posit es
0 = forall a. Fractional a => a -> a
recipforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (es :: ES).
PositC es =>
(Posit es -> Posit es) -> Posit es -> Posit es
approx_2exp Posit es -> Posit es
fforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a. Num a => a -> a
negate forall a b. (a -> b) -> a -> b
$ Posit es
x  -- always calculate the positive method
  | Bool
otherwise = case forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Posit es
x of
                  (Integer
int,Posit es
rem) -> forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
2forall a b. (Num a, Integral b) => a -> b -> a
^Integer
int) forall a. Num a => a -> a -> a
* Posit es -> Posit es
f (forall (es :: ES). PositC es => Posit es
lnOf2 forall a. Num a => a -> a -> a
* Posit es
rem)




-- Using the CORDIC domain reduction and some approximation function of log
funLogDomainReduction :: forall es. PositC es => (Posit es -> Posit es) -> Posit es -> Posit es
funLogDomainReduction :: forall (es :: ES).
PositC es =>
(Posit es -> Posit es) -> Posit es -> Posit es
funLogDomainReduction Posit es -> Posit es
_ Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
funLogDomainReduction Posit es -> Posit es
_ Posit es
1 = Posit es
0
funLogDomainReduction Posit es -> Posit es
f Posit es
x
  | Posit es
x forall a. Ord a => a -> a -> Bool
<= Posit es
0 = forall (es :: ES). PositC es => Posit es
NaR
  | Bool
otherwise = Posit es -> Posit es
f Posit es
sig forall a. Num a => a -> a -> a
+ (forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
ex forall a. Num a => a -> a -> a
* forall (es :: ES). PositC es => Posit es
lnOf2)
    where
      (Integer
ex, Posit es
sig) = (Integer
int forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
2forall a b. (Num a, Integral b) => a -> b -> a
^(forall (es :: ES). PositC es => Natural
exponentSize @es)) forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral Natural
nat forall a. Num a => a -> a -> a
+ Integer
1, forall a. Fractional a => Rational -> a
fromRational Rational
rat forall a. Fractional a => a -> a -> a
/ Posit es
2) -- move significand range from 1,2 to 0.5,1
      (Bool
_,Integer
int,Natural
nat,Rational
rat) = (forall (es :: ES).
PositC es =>
Rational -> (Bool, Integer, Natural, Rational)
posit2TupPosit @es)forall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a. Real a => a -> Rational
toRational forall a b. (a -> b) -> a -> b
$ Posit es
x -- sign should always be positive
     
 

-- natural log with log phi acurate to 9 ULP
funLogTaylor :: forall es. PositC es => Posit es -> Posit es
funLogTaylor :: forall (es :: ES). PositC es => Posit es -> Posit es
funLogTaylor Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
funLogTaylor Posit es
1 = Posit es
0
funLogTaylor Posit es
x | Posit es
x forall a. Ord a => a -> a -> Bool
<= Posit es
0 = forall (es :: ES). PositC es => Posit es
NaR
funLogTaylor Posit es
x
  | Posit es
x forall a. Ord a => a -> a -> Bool
<= Posit es
2 = Natural -> Posit es -> Posit es
go Natural
1 Posit es
0
  | Bool
otherwise = forall a. HasCallStack => String -> a
error String
"The funLogTaylor algorithm is being used improperly"
    where
      go :: Natural -> Posit es -> Posit es
      go :: Natural -> Posit es -> Posit es
go !Natural
k !Posit es
acc
        | Posit es
acc forall a. Eq a => a -> a -> Bool
== (Posit es
acc forall a. Num a => a -> a -> a
+ Natural -> Posit es
term Natural
k) = Posit es
acc
        | Bool
otherwise = Natural -> Posit es -> Posit es
go (Natural
k forall a. Num a => a -> a -> a
+ Natural
1) (Posit es
acc forall a. Num a => a -> a -> a
+ Natural -> Posit es
term Natural
k)
      term :: Natural -> Posit es
      term :: Natural -> Posit es
term Natural
k = (-Posit es
1)forall a b. (Num a, Integral b) => a -> b -> a
^(Natural
kforall a. Num a => a -> a -> a
+Natural
1) forall a. Num a => a -> a -> a
* (Posit es
x forall a. Num a => a -> a -> a
- Posit es
1)forall a b. (Num a, Integral b) => a -> b -> a
^Natural
k forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral Natural
k
     



-- =====================================================================
--       Taylor Series Fixed Point Approximations
-- =====================================================================

--
taylor_approx_atan :: forall es. PositC es => Posit es -> Posit es
taylor_approx_atan :: forall (es :: ES). PositC es => Posit es -> Posit es
taylor_approx_atan Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
taylor_approx_atan Posit es
x = Integer -> Posit es -> Posit es
go Integer
0 Posit es
0
  where
    go :: Integer -> Posit es -> Posit es
go !Integer
k !Posit es
acc
      | Posit es
acc forall a. Eq a => a -> a -> Bool
== (Posit es
acc forall a. Num a => a -> a -> a
+ Integer -> Posit es
term Integer
k) = Posit es
acc
      | Bool
otherwise = Integer -> Posit es -> Posit es
go (Integer
kforall a. Num a => a -> a -> a
+Integer
1) (Posit es
acc forall a. Num a => a -> a -> a
+ Integer -> Posit es
term Integer
k)
    term :: Integer -> Posit es
    term :: Integer -> Posit es
term Integer
k = ((-Posit es
1)forall a b. (Num a, Integral b) => a -> b -> a
^Integer
k forall a. Num a => a -> a -> a
* Posit es
xforall a b. (Num a, Integral b) => a -> b -> a
^(Integer
2 forall a. Num a => a -> a -> a
* Integer
k forall a. Num a => a -> a -> a
+ Integer
1)) forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
2 forall a. Num a => a -> a -> a
* Integer
k forall a. Num a => a -> a -> a
+ Integer
1)
--


-- calculate exp, its most accurate near zero
-- sum k=0 to k=inf of the terms, iterate until a fixed point is reached
taylor_approx_exp :: forall es. PositC es => Posit es -> Posit es
taylor_approx_exp :: forall (es :: ES). PositC es => Posit es -> Posit es
taylor_approx_exp Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
taylor_approx_exp Posit es
0 = Posit es
1
taylor_approx_exp Posit es
z = Natural -> Posit es -> Posit es
go Natural
0 Posit es
0
  where
    go :: Natural -> Posit es -> Posit es
    go :: Natural -> Posit es -> Posit es
go !Natural
k !Posit es
acc
      | Posit es
acc forall a. Eq a => a -> a -> Bool
== (Posit es
acc forall a. Num a => a -> a -> a
+ Natural -> Posit es
term Natural
k) = Posit es
acc  -- if x == x + dx then terminate and return x
      | Bool
otherwise = Natural -> Posit es -> Posit es
go (Natural
kforall a. Num a => a -> a -> a
+Natural
1) (Posit es
acc forall a. Num a => a -> a -> a
+ Natural -> Posit es
term Natural
k)
    term :: Natural -> Posit es
    term :: Natural -> Posit es
term Natural
k = (Posit es
zforall a b. (Num a, Integral b) => a -> b -> a
^Natural
k) forall a. Fractional a => a -> a -> a
/ (forall a b. (Integral a, Num b) => a -> b
fromIntegralforall b c a. (b -> c) -> (a -> b) -> a -> c
.Natural -> Natural
fac forall a b. (a -> b) -> a -> b
$ Natural
k)
--


-- =====================================================================
--  High Order Taylor Series transformed to Horner's Method
--     from Jan J Tuma's "Handbook of Numerical Calculations in Engineering" 
-- =====================================================================

--
tuma_approx_cos :: forall es. PositC es => Posit es -> Posit es
tuma_approx_cos :: forall (es :: ES). PositC es => Posit es -> Posit es
tuma_approx_cos Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
tuma_approx_cos Posit es
z = Natural -> Posit es -> Posit es
go Natural
19 Posit es
1  -- TODO can the order be selected based on the word size?
  where
    go :: Natural -> Posit es -> Posit es
    go :: Natural -> Posit es -> Posit es
go Natural
1 !Posit es
acc = Posit es
acc
    go !Natural
k !Posit es
acc = Natural -> Posit es -> Posit es
go (Natural
kforall a. Num a => a -> a -> a
-Natural
1) (Posit es
1 forall a. Num a => a -> a -> a
- (Posit es
zforall a b. (Num a, Integral b) => a -> b -> a
^Integer
2 forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral ((Natural
2forall a. Num a => a -> a -> a
*Natural
kforall a. Num a => a -> a -> a
-Natural
3)forall a. Num a => a -> a -> a
*(Natural
2forall a. Num a => a -> a -> a
*Natural
kforall a. Num a => a -> a -> a
-Natural
2))) forall a. Num a => a -> a -> a
* Posit es
acc)
--

--
tuma_approx_sin :: forall es. PositC es => Posit es -> Posit es
tuma_approx_sin :: forall (es :: ES). PositC es => Posit es -> Posit es
tuma_approx_sin Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
tuma_approx_sin Posit es
z = Natural -> Posit es -> Posit es
go Natural
19 Posit es
1  -- TODO can the order be selected based on the word size?
  where
    go :: Natural -> Posit es -> Posit es
    go :: Natural -> Posit es -> Posit es
go Natural
1 !Posit es
acc = Posit es
z forall a. Num a => a -> a -> a
* Posit es
acc
    go !Natural
k !Posit es
acc = Natural -> Posit es -> Posit es
go (Natural
kforall a. Num a => a -> a -> a
-Natural
1) (Posit es
1 forall a. Num a => a -> a -> a
- (Posit es
zforall a b. (Num a, Integral b) => a -> b -> a
^Integer
2 forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral ((Natural
2forall a. Num a => a -> a -> a
*Natural
kforall a. Num a => a -> a -> a
-Natural
2)forall a. Num a => a -> a -> a
*(Natural
2forall a. Num a => a -> a -> a
*Natural
kforall a. Num a => a -> a -> a
-Natural
1))) forall a. Num a => a -> a -> a
* Posit es
acc)
--



-- =========================================================
--           Alternate Floating of a Posit es
-- =========================================================

class AltFloating p where
  eps :: p
  phi :: p
  gamma :: p -> p
  sinc :: p -> p
  expm1 :: p -> p

--
instance PositC es => AltFloating (Posit es) where
  phi :: Posit es
phi = Posit es
1.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374847540880753868917521266338   -- approx_phi 1.6
  eps :: Posit es
eps = forall a. Enum a => a -> a
succ Posit es
1.0 forall a. Num a => a -> a -> a
- Posit es
1.0
  gamma :: Posit es -> Posit es
gamma = forall (es :: ES). PositC es => Posit es -> Posit es
approx_gamma
  sinc :: Posit es -> Posit es
sinc = forall (es :: ES). PositC es => Posit es -> Posit es
approx_sinc
  expm1 :: Posit es -> Posit es
expm1 Posit es
x =
    let b :: Posit es
b = forall (es :: ES). PositC es => Posit es -> Posit es
approx_atanh forall a b. (a -> b) -> a -> b
$ Posit es
x forall a. Fractional a => a -> a -> a
/ Posit es
2
    in (Posit es
2 forall a. Num a => a -> a -> a
* Posit es
b) forall a. Fractional a => a -> a -> a
/ (Posit es
1 forall a. Num a => a -> a -> a
- Posit es
b)






approx_gamma :: forall es. PositC es => Posit es -> Posit es
approx_gamma :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_gamma Posit es
z = forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt(Posit es
2 forall a. Num a => a -> a -> a
* forall (es :: ES). PositC es => Posit es
approx_pi) forall a. Num a => a -> a -> a
* (Posit es
z forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
`approx_pow` (Posit es
z forall a. Num a => a -> a -> a
- Posit es
0.5)) forall a. Num a => a -> a -> a
* forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp (forall a. Num a => a -> a
negate Posit es
z) forall a. Num a => a -> a -> a
* (Posit es
1 forall a. Num a => a -> a -> a
+ Posit es
series)
  where
    series :: Posit es
    series :: Posit es
series = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. Num a => a -> a -> a
(*) [forall a. Fractional a => Rational -> a
fromRational (Integer
a forall a. Integral a => a -> a -> Ratio a
% Integer
b) | (Integer
a,Integer
b) <- forall a b. [a] -> [b] -> [(a, b)]
zip [Integer]
a001163 [Integer]
a001164] [forall a. Fractional a => a -> a
recip forall a b. (a -> b) -> a -> b
$ Posit es
zforall a b. (Num a, Integral b) => a -> b -> a
^Int
n |  Int
n <- [Int
1..Int
len]]  -- zipWith (\x y -> ) a001163 a001164
    lenA :: Int
lenA = forall (t :: * -> *) a. Foldable t => t a -> Int
length [Integer]
a001163
    lenB :: Int
lenB = forall (t :: * -> *) a. Foldable t => t a -> Int
length [Integer]
a001164
    len :: Int
len = if Int
lenA forall a. Eq a => a -> a -> Bool
== Int
lenB
            then Int
lenA
            else forall a. HasCallStack => String -> a
error String
"Seiries Numerator and Denominator do not have the same length."
--


-- Looks like 1 ULP for 0.7813
approx_sinc :: PositC es => Posit es -> Posit es
approx_sinc :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_sinc Posit es
NaR = forall (es :: ES). PositC es => Posit es
NaR
approx_sinc Posit es
0 = Posit es
1  -- Why the hell not!
approx_sinc Posit es
theta = forall (es :: ES). PositC es => Posit es -> Posit es
approx_sin Posit es
theta forall a. Fractional a => a -> a -> a
/ Posit es
theta
--



-- =====================================================================
--    Useful Constants
-- =====================================================================

--
-- Use the constant, for performance
lnOf2 :: PositC es => Posit es
lnOf2 :: forall (es :: ES). PositC es => Posit es
lnOf2 = Posit es
0.6931471805599453094172321214581765680755001343602552541206800094933936219696947156058633269964186875420014810205706857336855202
--

--
a001163 :: [Integer] -- Numerator
a001163 :: [Integer]
a001163 = [Integer
1, Integer
1, -Integer
139, -Integer
571, Integer
163879, Integer
5246819, -Integer
534703531, -Integer
4483131259, Integer
432261921612371, Integer
6232523202521089, -Integer
25834629665134204969, -Integer
1579029138854919086429, Integer
746590869962651602203151, Integer
1511513601028097903631961, -Integer
8849272268392873147705987190261, -Integer
142801712490607530608130701097701]
a001164 :: [Integer]  -- Denominator
a001164 :: [Integer]
a001164 = [Integer
12, Integer
288, Integer
51840, Integer
2488320, Integer
209018880, Integer
75246796800, Integer
902961561600, Integer
86684309913600, Integer
514904800886784000, Integer
86504006548979712000, Integer
13494625021640835072000, Integer
9716130015581401251840000, Integer
116593560186976815022080000, Integer
2798245444487443560529920000, Integer
299692087104605205332754432000000, Integer
57540880724084199423888850944000000]
--

twoMsqrt3 :: PositC es => Posit es
twoMsqrt3 :: forall (es :: ES). PositC es => Posit es
twoMsqrt3 = Posit es
2 forall a. Num a => a -> a -> a
- forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt Posit es
3



-- =====================================================================
--    Helper Funcitons
-- =====================================================================

-- Factorial Function of type Natural
fac :: Natural -> Natural
fac :: Natural -> Natural
fac Natural
0 = Natural
1
fac Natural
n = Natural
n forall a. Num a => a -> a -> a
* Natural -> Natural
fac (Natural
n forall a. Num a => a -> a -> a
- Natural
1)
--

approx_sqrt :: PositC es => Posit es -> Posit es
approx_sqrt :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt Posit es
x = forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
approx_pow Posit es
x Posit es
0.5