--------------------------------------------------------------------------------------------
--   Posit Numbers
--   Copyright   :  (C) 2022-2024 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
{-# LANGUAGE AllowAmbiguousTypes #-}

-- ----
--  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

#ifndef O_NO_STORABLE_RANDOM
-- 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


import System.Random (Random(random,randomR))
import System.Random.Stateful (Uniform, uniform, uniformM)

import Data.Bits (shiftL, (.&.), (.|.))
#endif

-- 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 Numeric.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, no more (%) now.

-- 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 $mNaR :: forall {r} {es :: ES}.
PositC es =>
Posit es -> ((# #) -> r) -> ((# #) -> r) -> r
$bNaR :: forall (es :: ES). PositC es => Posit es
NaR <- (Posit (decode @es -> Nothing)) where
  NaR = IntN es -> Posit es
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 $mR :: forall {r} {es :: ES}.
PositC es =>
Posit es -> (Rational -> r) -> ((# #) -> r) -> r
$bR :: forall (es :: ES). PositC es => Rational -> Posit es
R r <- (Posit (decode @es -> Just r)) where
  R Rational
r = IntN es -> Posit es
forall (es :: ES). PositC es => IntN es -> Posit es
Posit (forall (es :: ES). PositC es => Maybe Rational -> IntN es
encode @es (Maybe Rational -> IntN es) -> Maybe Rational -> IntN es
forall a b. (a -> b) -> a -> b
$ Rational -> Maybe Rational
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 p :: Posit es
p@(Posit IntN es
int) = FPFormat -> Maybe Int -> Scientific -> String
formatScientific FPFormat
Generic (Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ forall (es :: ES). PositC es => IntN es -> Int
decimalPrec @es IntN es
int) ((Scientific, Maybe Int) -> Scientific
forall a b. (a, b) -> a
fst((Scientific, Maybe Int) -> Scientific)
-> (Rational -> (Scientific, Maybe Int)) -> Rational -> Scientific
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Rational -> (Scientific, Maybe Int)
fromRationalRepetendUnlimited (Rational -> Scientific) -> Rational -> Scientific
forall a b. (a -> b) -> a -> b
$ Posit es -> Rational
forall a. Real a => a -> Rational
toRational Posit es
p)
--
#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 IntN es -> IntN es -> Bool
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) = IntN es -> IntN es -> Ordering
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
(+) = Posit es -> Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
positADD
  -- Multiplication
  * :: Posit es -> Posit es -> Posit es
(*) = Posit es -> Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
positMULT
  -- '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 = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
positABS
  -- 'signum' it is a kind of an representation of directionality, the sign of a number for instance
  signum :: Posit es -> Posit es
signum = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
positSIGNUM
  -- 'fromInteger' rounds the integer into the closest posit number
  fromInteger :: Integer -> Posit es
fromInteger Integer
int = Rational -> Posit es
forall (es :: ES). PositC es => Rational -> Posit es
R (Rational -> Posit es) -> Rational -> Posit es
forall a b. (a -> b) -> a -> b
$ Integer -> Rational
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 = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
positNEG
  -- '(-)', minus, but explisit with an implementaiton that will fuse
  (-) = Posit es -> Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
positSUB
--

--
-- To be able to have rewrite rules to function the instance needs to be some un-inlined function
{-# NOINLINE [1] positADD #-}
positADD :: forall es. PositC es => Posit es -> Posit es -> Posit es
positADD :: forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
positADD = (Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es
viaRational2 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
(+)
{-# NOINLINE [1] positMULT #-}
positMULT :: forall es. PositC es => Posit es -> Posit es -> Posit es
positMULT :: forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
positMULT = (Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es
viaRational2 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
(*)
{-# NOINLINE [1] positNEG #-}
positNEG :: forall es. PositC es => Posit es -> Posit es
positNEG :: forall (es :: ES). PositC es => Posit es -> Posit es
positNEG = (IntN es -> IntN es) -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(IntN es -> IntN es) -> Posit es -> Posit es
viaIntegral IntN es -> IntN es
forall a. Num a => a -> a
negate
{-# NOINLINE [1] positABS #-}
positABS :: forall es. PositC es => Posit es -> Posit es
positABS :: forall (es :: ES). PositC es => Posit es -> Posit es
positABS = (IntN es -> IntN es) -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(IntN es -> IntN es) -> Posit es -> Posit es
viaIntegral IntN es -> IntN es
forall a. Num a => a -> a
abs
{-# NOINLINE [1] positSIGNUM #-}
positSIGNUM :: forall es. PositC es => Posit es -> Posit es
positSIGNUM :: forall (es :: ES). PositC es => Posit es -> Posit es
positSIGNUM = (Rational -> Rational) -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(Rational -> Rational) -> Posit es -> Posit es
viaRational Rational -> Rational
forall a. Num a => a -> a
signum
{-# NOINLINE [1] positSUB #-}
positSUB :: forall es. PositC es => Posit es -> Posit es -> Posit es
positSUB :: forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
positSUB = \ Posit es
p1 Posit es
p2 -> Posit es -> Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
positADD Posit es
p1 (Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
positNEG Posit es
p2)


-- 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) = IntN es -> Posit es
forall (es :: ES). PositC es => IntN es -> Posit es
Posit (IntN es -> Posit es) -> IntN es -> Posit es
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 = (IntN es -> IntN es) -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(IntN es -> IntN es) -> Posit es -> Posit es
viaIntegral (IntN es -> IntN es -> IntN es
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 = (IntN es -> IntN es) -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(IntN es -> IntN es) -> Posit es -> Posit es
viaIntegral (IntN es -> IntN es -> IntN es
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 = Posit es -> Posit es -> [Posit es]
forall a. Enum a => a -> a -> [a]
enumFromTo Posit es
n Posit es
forall a. Bounded a => a
maxBound
  enumFromTo :: Posit es -> Posit es -> [Posit es]
enumFromTo Posit es
n Posit es
m
    | Posit es
n Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
m = [Posit es
n]
    | Posit es
n Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
m = Posit es
n Posit es -> [Posit es] -> [Posit es]
forall a. a -> [a] -> [a]
: Posit es -> Posit es -> [Posit es]
forall a. Enum a => a -> a -> [a]
enumFromTo (Posit es -> Posit es
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
_ = [Posit es
forall (es :: ES). PositC es => Posit es
NaR]
  enumFromThen Posit es
_ Posit es
NaR = [Posit es
forall (es :: ES). PositC es => Posit es
NaR]
  enumFromThen Posit es
n Posit es
m = Posit es
n Posit es -> [Posit es] -> [Posit es]
forall a. a -> [a] -> [a]
: Posit es -> [Posit es]
go Posit es
n
    where
      step :: Posit es
step = Posit es
m Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
n
      go :: Posit es -> [Posit es]
      go :: Posit es -> [Posit es]
go Posit es
NaR = [Posit es
forall (es :: ES). PositC es => Posit es
NaR]
      go !Posit es
l = case Posit es -> Posit es -> Ordering
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 Posit es -> Posit es -> Posit es
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' Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
l Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
step
                         then []
                         else Posit es
n' Posit es -> [Posit es] -> [Posit es]
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 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es
step
                      in if Posit es
n' Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
l Posit es -> Posit es -> Bool
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' Posit es -> [Posit es] -> [Posit es]
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
_  = [Posit es
forall (es :: ES). PositC es => Posit es
NaR]
  enumFromThenTo  Posit es
_  Posit es
NaR  Posit es
_  = [Posit es
forall (es :: ES). PositC es => Posit es
NaR]
  enumFromThenTo  Posit es
_   Posit es
_  Posit es
NaR = [Posit es
forall (es :: ES). PositC es => Posit es
NaR]
  enumFromThenTo  Posit es
e1  Posit es
e2  Posit es
e3 = (Posit es -> Bool) -> [Posit es] -> [Posit es]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile Posit es -> Bool
predicate (Posit es -> Posit es -> [Posit es]
forall a. Enum a => a -> a -> [a]
enumFromThen Posit es
e1 Posit es
e2)
    where
      mid :: Posit es
mid = (Posit es
e2 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
e1) Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ Posit es
2
      predicate :: Posit es -> Bool
predicate | Posit es
e2 Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
>= Posit es
e1  = (Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
<= Posit es
e3 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es
mid)
                | Bool
otherwise = (Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
>= Posit es
e3 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es
mid)
  fromEnum :: Posit es -> Int
fromEnum Posit es
_ = String -> Int
forall a. HasCallStack => String -> a
error String
"Please do not use 'fromEnum', it is size limited to Int, and can be machine dependant.  Please advocate for the function to be size polymorphic of a FixedWidthInteger."
  toEnum :: Int -> Posit es
toEnum Int
_ = String -> Posit es
forall a. HasCallStack => String -> a
error String
"Please do not use 'toEnum', it is size limited to Int, and can be machine dependant.  Please advocate for the function to be size polymorphic of a FixedWidthInteger."
--



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

{-# NOINLINE [1] positRECIP #-}
positRECIP :: forall es. PositC es => Posit es -> Posit es
positRECIP :: forall (es :: ES). PositC es => Posit es -> Posit es
positRECIP = (Rational -> Rational) -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(Rational -> Rational) -> Posit es -> Posit es
viaRational Rational -> Rational
forall a. Fractional a => a -> a
recip


-- 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 = String -> Rational
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 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
viaRational Rational -> Rational
f (R Rational
r) = Rational -> Posit es
forall a. Fractional a => Rational -> a
fromRational (Rational -> Posit es) -> Rational -> Posit es
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
_  = Posit es
forall (es :: ES). PositC es => Posit es
NaR
viaRational2 Rational -> Rational -> Rational
_  Posit es
_  Posit es
NaR = Posit es
forall (es :: ES). PositC es => Posit es
NaR
viaRational2 Rational -> Rational -> Rational
f (R Rational
r1) (R Rational
r2) = Rational -> Posit es
forall (es :: ES). PositC es => Rational -> Posit es
R (Rational -> Posit es) -> Rational -> Posit es
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
_  = Posit es
forall (es :: ES). PositC es => Posit es
NaR
viaRational3 Rational -> Rational -> Rational -> Rational
_  Posit es
_  Posit es
NaR  Posit es
_  = Posit es
forall (es :: ES). PositC es => Posit es
NaR
viaRational3 Rational -> Rational -> Rational -> Rational
_  Posit es
_   Posit es
_  Posit es
NaR = Posit es
forall (es :: ES). PositC es => Posit es
NaR
viaRational3 Rational -> Rational -> Rational -> Rational
f (R Rational
r1) (R Rational
r2) (R Rational
r3) = Rational -> Posit es
forall (es :: ES). PositC es => Rational -> Posit es
R (Rational -> Posit es) -> Rational -> Posit es
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
_  = 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
_  = 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
_  = 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 = Posit es
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) = Rational -> Posit es
forall (es :: ES). PositC es => Rational -> Posit es
R (Rational -> Posit es) -> Rational -> Posit es
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
_  = 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
_  = 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
_  = 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
_  = 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
_  = 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 = Posit es
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) = Rational -> Posit es
forall (es :: ES). PositC es => Rational -> Posit es
R (Rational -> Posit es) -> Rational -> Posit es
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
_  = 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
_  = 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
_  = 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
_  = 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
_  = 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
_  = 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
_  = 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 = Posit es
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) = Rational -> Posit es
forall (es :: ES). PositC es => Rational -> Posit es
R (Rational -> Posit es) -> Rational -> Posit es
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 = IntN es -> Posit es
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 = IntN es -> Posit es
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
 

#ifdef O_REWRITE
{-# RULES
"posit/fdot4" forall a0 a1 a2 a3 b0 b1 b2 b3. positADD (positADD (positADD (positMULT a0 b0) (positMULT a1 b1)) (positMULT a2 b2)) (positMULT a3 b3) = fdot4 a0 a1 a2 a3 b0 b1 b2 b3 -- (a0 * b0) + (a1 * b1) + (a2 * b2) + (a3 * b3)
"posit/fsum4" forall a b c d. positADD a (positADD b (positADD c d)) = fsum4 a b c d -- a + b + c + d
"posit/fdot3" forall a1 a2 a3 b1 b2 b3. positADD (positADD (positMULT a1 b1) (positMULT a2 b2)) (positMULT a3 b3) = fdot3 a1 a2 a3 b1 b2 b3 -- (a1 * b1) + (a2 * b2) + (a3 * b3)
"posit/fsum3" forall a b c. positADD a (positADD b c) = fsum3 a b c -- a + b + c
"posit/fsmSub"  forall a b c. positSUB a (positMULT b c) = fsm a b c -- a - (b * c)
"posit/fsm"  forall a b c. positADD a (positNEG (positMULT b c)) = fsm a b c -- a - (b * c)
"posit/fsmSwaped"  forall a b c. positADD (positNEG (positMULT b c)) a = fsm a b c -- negate (b * c) + a
"posit/fma"  forall a b c. positADD (positMULT a b) c = fma a b c -- (a * b) + c
"posit/fmaSwaped"  forall a b c. positADD c (positMULT a b) = fma a b c -- c + (a * b)
"posit/fam"  forall a b c. positMULT (positADD a b) c = fam a b c -- (a + b) * c
"posit/famSwaped"  forall a b c. positMULT c (positADD a b) = fam a b c -- c * (a + b)
"posit/fmmsSub"  forall a b c d. positSUB (positMULT a b) (positMULT c d) = fmms a b c d -- (a * b) - (c * d)
"posit/fmms"  forall a b c d. positADD (positMULT a b) (positNEG (positMULT c d)) = fmms a b c d -- (a * b) - (c * d)
"posit/fmmsSwapped"  forall a b c d. positADD (positNEG (positMULT c d)) (positMULT a b) = fmms a b c d  -- negate (c * d) + (a * b)
   #-}
#endif

-- Rational Instance
instance FusedOps Rational where
  fsm :: Rational -> Rational -> Rational -> Rational
fsm Rational
a Rational
b Rational
c = Rational
a Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- (Rational
b Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
c)
  fma :: Rational -> Rational -> Rational -> Rational
fma Rational
a Rational
b Rational
c = (Rational
a Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
b) Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
c
  fam :: Rational -> Rational -> Rational -> Rational
fam Rational
a Rational
b Rational
c = (Rational
a Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
b) Rational -> Rational -> Rational
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 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
b) Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- (Rational
c Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
d)
  fsum3 :: Rational -> Rational -> Rational -> Rational
fsum3 Rational
a Rational
b Rational
c = Rational
a Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
b Rational -> Rational -> Rational
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 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
b Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
c Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
d
  fsumL :: forall (t :: * -> *). Foldable t => t Rational -> Rational
fsumL (t Rational -> [Rational]
forall a. t a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [Rational]
l) = [Rational] -> Rational -> Rational
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 t -> t -> t
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 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
b1) Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ (Rational
a2 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
b2) Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ (Rational
a3 Rational -> Rational -> Rational
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 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
b0) Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ (Rational
a1 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
b1) Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ (Rational
a2 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
b2) Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ (Rational
a3 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
b3)
  fdotL :: forall (t :: * -> *).
Foldable t =>
t Rational -> t Rational -> Rational
fdotL (t Rational -> [Rational]
forall a. t a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [Rational]
l1) (t Rational -> [Rational]
forall a. t a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [Rational]
l2) = [Rational] -> [Rational] -> Rational -> Rational
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
_  = String -> t
forall a. HasCallStack => String -> a
error String
"Lists not the same length"
      go [t]
_  []  t
_  = String -> 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 (t -> t -> t -> t
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 = (Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
viaRational3 Rational -> Rational -> Rational -> Rational
forall a. FusedOps a => a -> a -> a -> a
fsm
  -- Fuse Multiply Add
  fma :: Posit es -> Posit es -> Posit es -> Posit es
fma = (Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
viaRational3 Rational -> Rational -> Rational -> Rational
forall a. FusedOps a => a -> a -> a -> a
fma
  -- Fuse Add Multiply
  fam :: Posit es -> Posit es -> Posit es -> Posit es
fam = (Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
viaRational3 Rational -> Rational -> Rational -> Rational
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 = (Rational -> Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es -> Posit es
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
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 = (Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es
viaRational3 Rational -> Rational -> Rational -> Rational
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 = (Rational -> Rational -> Rational -> Rational -> Rational)
-> Posit es -> Posit es -> Posit es -> Posit es -> Posit es
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
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 (t (Posit es) -> [Posit es]
forall a. t a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [Posit es]
l) = IntN es -> Posit es
forall (es :: ES). PositC es => IntN es -> Posit es
Posit (IntN es -> Posit es) -> IntN es -> Posit es
forall a b. (a -> b) -> a -> b
$ forall (es :: ES). PositC es => Maybe Rational -> IntN es
encode @es (Rational -> Maybe Rational
forall a. a -> Maybe a
Just (Rational -> Maybe Rational) -> Rational -> Maybe Rational
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 -> String -> Rational
forall a. HasCallStack => String -> a
error String
"Posit List contains NaR"
                                     Just Rational
r -> [Posit es] -> Rational -> Rational
go [Posit es]
xs (Rational
acc Rational -> Rational -> Rational
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 = (Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational
 -> Rational)
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
-> Posit es
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
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 = (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
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
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 (t (Posit es) -> [Posit es]
forall a. t a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [Posit es]
l1) (t (Posit es) -> [Posit es]
forall a. t a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [Posit es]
l2) = IntN es -> Posit es
forall (es :: ES). PositC es => IntN es -> Posit es
Posit (IntN es -> Posit es) -> IntN es -> Posit es
forall a b. (a -> b) -> a -> b
$ forall (es :: ES). PositC es => Maybe Rational -> IntN es
encode @es (Rational -> Maybe Rational
forall a. a -> Maybe a
Just (Rational -> Maybe Rational) -> Rational -> Maybe Rational
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
_  = String -> Rational
forall a. HasCallStack => String -> a
error String
"Lists not the same length"
      go [Posit es]
_  []   Rational
_  = String -> 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 -> String -> Rational
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 -> String -> Rational
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 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ (Rational
r1 Rational -> Rational -> Rational
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 = Posit es2
forall (es :: ES). PositC es => Posit es
NaR
  convert (R Rational
r) = Rational -> Posit es2
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) = IntN es -> String
forall a. Show a => a -> String
show IntN es
int
 
  displayRational :: Posit es -> String
displayRational = (Rational -> Rational) -> Posit es -> String
forall a (es :: ES).
(Show a, PositC es) =>
(Rational -> a) -> Posit es -> String
viaShowable Rational -> Rational
forall a. a -> a
id
 
  displayDecimal :: Posit es -> String
displayDecimal = (Rational -> Scientific) -> Posit es -> String
forall a (es :: ES).
(Show a, PositC es) =>
(Rational -> a) -> Posit es -> String
viaShowable ((Scientific, Maybe Int) -> Scientific
forall a b. (a, b) -> a
fst((Scientific, Maybe Int) -> Scientific)
-> (Rational -> (Scientific, Maybe Int)) -> Rational -> Scientific
forall 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) = a -> String
forall a. Show a => a -> String
show (a -> String) -> a -> String
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 =
    ReadPrec (Posit es) -> ReadPrec (Posit es)
forall a. ReadPrec a -> ReadPrec a
parens (ReadPrec (Posit es) -> ReadPrec (Posit es))
-> ReadPrec (Posit es) -> ReadPrec (Posit es)
forall a b. (a -> b) -> a -> b
$ do
      Lexeme
x <- ReadPrec Lexeme
lexP
      case Lexeme
x of
        Ident String
"NaR" -> Posit es -> ReadPrec (Posit es)
forall a. a -> ReadPrec a
forall (m :: * -> *) a. Monad m => a -> m a
return Posit es
forall (es :: ES). PositC es => Posit es
NaR
        Lexeme
_ -> ReadPrec (Posit es)
forall a. ReadPrec a
pfail
      ReadPrec (Posit es) -> ReadPrec (Posit es) -> ReadPrec (Posit es)
forall a. ReadPrec a -> ReadPrec a -> ReadPrec a
+++
      do
        Scientific
s <- ReadP Scientific -> ReadPrec Scientific
forall a. ReadP a -> ReadPrec a
lift ReadP Scientific
scientificP
        Posit es -> ReadPrec (Posit es)
forall a. a -> ReadPrec a
forall (m :: * -> *) a. Monad m => a -> m a
return (Posit es -> ReadPrec (Posit es))
-> Posit es -> ReadPrec (Posit es)
forall a b. (a -> b) -> a -> b
$ Rational -> Posit es
forall (es :: ES). PositC es => Rational -> Posit es
R (Scientific -> Rational
forall a. Real a => a -> Rational
toRational Scientific
s)
 
  readListPrec :: ReadPrec [Posit es]
readListPrec = ReadPrec [Posit es]
forall a. Read a => ReadPrec [a]
readListPrecDefault
--
#endif


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

-- | Random instance for the Posit Sampling of R [0,1), this is for the
-- real numbers, not on the projective real numbers, for projective
-- real numbers, use Uniform.
instance forall es. PositC es => Random (Posit es) where
-- First we take a uniform distributed random posit, then we mask out
-- the sign, 2 bits of regime, and the exponent, then we write in the
-- sign, regime and exponent of 1.0, to get a posit [1,2) then subtract
-- 1.0 to adjust the range to [0,1).  This approach is credited to a
-- coorispondance between Shin Yee Chung and John L. Gustafson titled:
-- "random number generators for posit" in the Unum Computing Google Group
  random :: forall g. RandomGen g => g -> (Posit es, g)
random g
g = case g -> (Posit es, g)
forall g a. (RandomGen g, Uniform a) => g -> (a, g)
uniform g
g of
               (Posit IntN es
int :: Posit es, g
g') -> (IntN es -> Posit es
forall (es :: ES). PositC es => IntN es -> Posit es
Posit ((IntN es
int IntN es -> IntN es -> IntN es
forall a. Bits a => a -> a -> a
.&. forall (es :: ES). PositC es => IntN es
maskFraction @es) IntN es -> IntN es -> IntN es
forall a. Bits a => a -> a -> a
.|. IntN es
patt) Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
1.0, g
g')
    where
     (Posit IntN es
patt) = Posit es
1.0 :: Posit es

  randomR :: forall g. RandomGen g => (Posit es, Posit es) -> g -> (Posit es, g)
randomR (Posit es
lo,Posit es
hi) g
g
    | Posit es
lo Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
hi = (Posit es, Posit es) -> g -> (Posit es, g)
forall g. RandomGen g => (Posit es, Posit es) -> g -> (Posit es, g)
forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Posit es
hi,Posit es
lo) g
g
    | Bool
otherwise = case g -> (Posit es, g)
forall g. RandomGen g => g -> (Posit es, g)
forall a g. (Random a, RandomGen g) => g -> (a, g)
random g
g of
                    (Posit es
p,g
g') -> let scaled_p :: Posit es
scaled_p = (Posit es
hi Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
lo) Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* Posit es
p Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es
lo
                              in (Posit es
scaled_p, g
g')


-- | Uniform instance for the Posit Sampling of the projective real line
instance PositC es => Uniform (Posit es) where
  uniformM :: forall g (m :: * -> *). StatefulGen g m => g -> m (Posit es)
uniformM g
g = do
    IntN es
int <- g -> m (IntN es)
forall a g (m :: * -> *). (Uniform a, StatefulGen g m) => g -> m a
forall g (m :: * -> *). StatefulGen g m => g -> m (IntN es)
uniformM g
g
    Posit es -> m (Posit es)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Posit es -> m (Posit es)) -> Posit es -> m (Posit es)
forall a b. (a -> b) -> a -> b
$ IntN es -> Posit es
forall (es :: ES). PositC es => IntN es -> Posit es
Posit IntN es
int


maskFraction :: forall es. PositC es => IntN es
maskFraction :: forall (es :: ES). PositC es => IntN es
maskFraction =
  let twoRegimeBits :: Natural
twoRegimeBits = Natural
2 -- regimeBitSize set to 2, the good range is [1,2)
      sreSize :: Natural
sreSize = forall (es :: ES). PositC es => Natural
signBitSize @es Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ Natural
twoRegimeBits Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ forall (es :: ES). PositC es => Natural
exponentSize @es
  in (IntN es
1 IntN es -> Int -> IntN es
forall a. Bits a => a -> Int -> a
`shiftL` Natural -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall (es :: ES). PositC es => Natural
nBits @es Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
- Natural
sreSize) IntN es -> IntN es -> IntN es
forall a. Num a => a -> a -> a
- IntN es
1)

#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 = String -> (Rational -> (b, Rational)) -> Posit es -> (b, Posit es)
forall (es :: ES) a.
PositC es =>
String -> (Rational -> (a, Rational)) -> Posit es -> (a, Posit es)
viaRationalErrTrunkation String
"NaR value is not a RealFrac" Rational -> (b, Rational)
forall b. Integral b => Rational -> (b, Rational)
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 = String -> (a, Posit es)
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, Rational -> Posit es
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
_  = Posit es
forall (es :: ES). PositC es => Posit es
NaR
  atan2  Posit es
_  Posit es
NaR = Posit es
forall (es :: ES). PositC es => Posit es
NaR
  atan2 Posit es
y Posit es
x
    | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0 Bool -> Bool -> Bool
&& Posit es
y Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
    | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
0             = Posit es -> Posit es
forall a. Floating a => a -> a
atan (Posit es
yPosit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/Posit es
x)
    | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0  Bool -> Bool -> Bool
&& Posit es
y Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
>= Posit es
0  = Posit es -> Posit es
forall a. Floating a => a -> a
atan (Posit es
yPosit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/Posit es
x) Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es
forall a. Floating a => a
pi
    | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0  Bool -> Bool -> Bool
&& Posit es
y  Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0  = Posit es -> Posit es
forall a. Floating a => a -> a
atan (Posit es
yPosit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/Posit es
x) Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
forall a. Floating a => a
pi
    | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0 Bool -> Bool -> Bool
&& Posit es
y  Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
0  = Posit es
forall a. Floating a => a
pi Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ Posit es
2
    | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0 Bool -> Bool -> Bool
&& Posit es
y  Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0  = Posit es -> Posit es
forall a. Num a => a -> a
negate (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
forall a. Floating a => a
pi Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ Posit es
2
    | Bool
otherwise = String -> Posit es
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
_ = Int
forall a. HasCallStack => a
undefined
  floatRange :: Posit es -> (Int, Int)
floatRange Posit es
_ = (Int -> Int
forall a. Num a => a -> a
negate Int
maxExponent, Int
maxExponent)
    where
      maxExponent :: Int
maxExponent = Natural -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Natural -> Int) -> Natural -> Int
forall a b. (a -> b) -> a -> b
$ (forall (es :: ES). PositC es => Natural
nBytes @es) Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
* ((forall (es :: ES). PositC es => Natural
nBits @es) Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
- Natural
2)
  decodeFloat :: Posit es -> (Integer, Int)
decodeFloat = Posit es -> (Integer, Int)
forall a. HasCallStack => a
undefined
  encodeFloat :: Integer -> Int -> Posit es
encodeFloat = Integer -> Int -> Posit es
forall a. HasCallStack => a
undefined
--



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

instance PositF es => Floating (Posit es) where
  pi :: Posit es
pi = Posit es
forall (es :: ES). PositC es => Posit es
approx_pi
  exp :: Posit es -> Posit es
exp = (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp
  log :: Posit es -> Posit es
log = (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_log
  Posit es
x ** :: Posit es -> Posit es -> Posit es
** Posit es
y = (Posit (Next es) -> Posit (Next es) -> Posit (Next es))
-> Posit es -> Posit es -> Posit es
forall (es :: ES).
PositF 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)
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 = (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_sin
  cos :: Posit es -> Posit es
cos = (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_cos
  asin :: Posit es -> Posit es
asin = (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_asin
  acos :: Posit es -> Posit es
acos = (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_acos
  atan :: Posit es -> Posit es
atan = (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan
  sinh :: Posit es -> Posit es
sinh = (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_sinh
  cosh :: Posit es -> Posit es
cosh = (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_cosh
  asinh :: Posit es -> Posit es
asinh = (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_asinh
  acosh :: Posit es -> Posit es
acosh = (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_acosh
  atanh :: Posit es -> Posit es
atanh = (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
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. PositF es => (Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext :: forall (es :: ES).
PositF es =>
(Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es
hiRezNext Posit (Next es) -> Posit (Next es)
f Posit es
x = Posit (Next es) -> Posit es
forall a b. Convertible a b => a -> b
convert (Posit (Next es) -> Posit (Next es)
f (Posit es -> Posit (Next es)
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 = Posit (Max es) -> Posit es
forall a b. Convertible a b => a -> b
convert (Posit (Max es) -> Posit (Max es)
f (Posit es -> Posit (Max es)
forall a b. Convertible a b => a -> b
convert Posit es
x) :: Posit (Max es)) :: Posit es

hiRezNext2 :: forall es. PositF es => (Posit (Next es) -> Posit (Next es) -> Posit (Next es)) -> Posit es -> Posit es -> Posit es
hiRezNext2 :: forall (es :: ES).
PositF 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 = Posit (Next es) -> Posit es
forall a b. Convertible a b => a -> b
convert (Posit (Next es) -> Posit (Next es) -> Posit (Next es)
f (Posit es -> Posit (Next es)
forall a b. Convertible a b => a -> b
convert Posit es
x :: Posit (Next es)) (Posit es -> 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 = Posit (Max es) -> Posit es
forall a b. Convertible a b => a -> b
convert (Posit (Max es) -> Posit (Max es) -> Posit (Max es)
f (Posit es -> Posit (Max es)
forall a b. Convertible a b => a -> b
convert Posit es
x :: Posit (Max es)) (Posit es -> 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


-- euler's constant
approx_e :: PositC es => Posit es
approx_e :: forall (es :: ES). PositC es => Posit es
approx_e  = Posit es
2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135


approx_exp :: forall es. 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
NaR = Posit es
forall (es :: ES). PositC es => Posit es
NaR
approx_exp (R Rational
x) = Posit es
2Posit es -> Integer -> Posit es
forall a b. (Fractional a, Integral b) => a -> b -> a
^^Integer
k Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
funExpTaylor (Rational -> Posit es
forall (es :: ES). PositC es => Rational -> Posit es
R Rational
r)
  where
    k :: Integer
k = Rational -> Integer
forall b. Integral b => Rational -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor (Rational
x Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational
ln2 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
+ Rational
0.5)  -- should be Integer or Int
    r :: Rational
r = Rational
x Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Integer -> Rational
forall a. Num a => Integer -> a
fromInteger Integer
k Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
ln2  -- should be Rational

ln2 :: Rational
ln2 :: Rational
ln2 = Rational
0.6931471805599453094172321214581765680755001343602552541206800094933936219696947156058633269964186875420014810205706857336855202

log_USeed :: forall es. PositC es => Posit es
log_USeed :: forall (es :: ES). PositC es => Posit es
log_USeed = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_log (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Natural -> Posit es
forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall (es :: ES). PositC es => Natural
uSeed @es)


approx_log :: PositC es => Posit es -> Posit es
approx_log :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_log = (Posit es -> Posit es) -> Posit es -> Posit es
forall (es :: ES).
PositC es =>
(Posit es -> Posit es) -> Posit es -> Posit es
funLogDomainReduction Posit es -> Posit es
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
_ = Posit es
forall (es :: ES). PositC es => Posit es
NaR
Posit es
_ `approx_pow` Posit es
NaR = Posit es
forall (es :: ES). PositC es => Posit es
NaR
approx_pow Posit es
0 Posit es
y
  | Posit es
y Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0 = Posit es
forall (es :: ES). PositC es => Posit es
NaR -- NaR: Divide by Zero
  | Posit es
y Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0 = Posit es
forall (es :: ES). PositC es => Posit es
NaR -- NaR: Indeterminate
  | Posit es
y Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
0 = Posit es
0
approx_pow Posit es
x Posit es
y
  | Posit es
y Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0 = Posit es -> Posit es
forall a. Fractional a => a -> a
recip (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es -> Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
approx_pow Posit es
x (Posit es -> Posit es
forall a. Num a => a -> a
negate Posit es
y)
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0 = -- NaR if y is not an integer
    let (Integer
int,Posit es
rem) = Posit es -> (Integer, Posit es)
forall b. Integral b => Posit es -> (b, Posit es)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Posit es
y
    in if Posit es
rem Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0
       then Posit es
xPosit es -> Integer -> Posit es
forall a b. (Fractional a, Integral b) => a -> b -> a
^^Integer
int
       else Posit es
forall (es :: ES). PositC es => Posit es
NaR -- NaR: Imaginary Number
  | Bool
otherwise = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
y Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* Posit es -> Posit es
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 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
approx_sin Posit es
0 = Posit es
0
approx_sin (R Rational
x) = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSine (Rational -> Posit es
forall (es :: ES). PositC es => Rational -> Posit es
R Rational
x')
  where
    (Integer
_, Rational
x') = Rational -> (Integer, Rational)
forall b. Integral b => Rational -> (b, Rational)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction (Rational -> (Integer, Rational))
-> Rational -> (Integer, Rational)
forall a b. (a -> b) -> a -> b
$ Rational
x Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational
twoPi


approx_cos :: forall es. PositC es => Posit es -> Posit es
approx_cos :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_cos Posit es
NaR = Posit es
forall (es :: ES). PositC es => Posit es
NaR
approx_cos Posit es
0 = Posit es
1
approx_cos (R Rational
x) = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosine (Rational -> Posit es
forall (es :: ES). PositC es => Rational -> Posit es
R Rational
x')
  where
    (Integer
_, Rational
x') = Rational -> (Integer, Rational)
forall b. Integral b => Rational -> (b, Rational)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction (Rational -> (Integer, Rational))
-> Rational -> (Integer, Rational)
forall a b. (a -> b) -> a -> b
$ Rational
x Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/ Rational
twoPi


approx_asin :: PositC es => Posit es -> Posit es
approx_asin :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_asin Posit es
NaR = Posit es
forall (es :: ES). PositC es => Posit es
NaR
approx_asin Posit es
x
  | Posit es -> Posit es
forall a. Num a => a -> a
abs Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
1 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
1 = Posit es
forall (es :: ES). PositC es => Posit es
approx_piPosit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/Posit es
2
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== -Posit es
1 = -Posit es
forall (es :: ES). PositC es => Posit es
approx_piPosit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/Posit es
2
  | Bool
otherwise = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan Posit es
w
    where
      w :: Posit es
w = Posit es
x Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt (Posit es -> Posit es -> Posit es -> Posit es
forall a. FusedOps a => a -> a -> a -> a
fsm Posit es
1 Posit es
x Posit es
x)  --  (1 - x^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 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
approx_acos Posit es
x
  | Posit es -> Posit es
forall a. Num a => a -> a
abs Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
1 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0 = Posit es
forall (es :: ES). PositC es => Posit es
approx_pi Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan Posit es
invw
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0 = Posit es
forall (es :: ES). PositC es => Posit es
approx_piPosit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/Posit es
2
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
0 = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan Posit es
invw
  | Bool
otherwise = String -> Posit es
forall a. HasCallStack => String -> a
error String
"Prove it covers for Rational Numbers."
    where
      invw :: Posit es
invw = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt (Posit es -> Posit es -> Posit es -> Posit es
forall a. FusedOps a => a -> a -> a -> a
fsm Posit es
1 Posit es
x Posit es
x) Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ Posit es
x  --  (1 - x^2)


approx_atan :: PositC es => Posit es -> Posit es
approx_atan :: forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan Posit es
NaR = Posit es
forall (es :: ES). PositC es => Posit es
NaR
approx_atan Posit es
x
  | Posit es -> Posit es
forall a. Num a => a -> a
abs Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
1Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/Posit es
2Posit es -> Integer -> Posit es
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
122 = Posit es
x  -- small angle approximaiton, found emperically
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0 = Posit es -> Posit es
forall a. Num a => a -> a
negate(Posit es -> Posit es)
-> (Posit es -> Posit es) -> Posit es -> Posit es
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es -> Posit es
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 Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
1 = Posit es
forall (es :: ES). PositC es => Posit es
approx_piPosit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/Posit es
2 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan (Posit es -> Posit es
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 Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
forall (es :: ES). PositC es => Posit es
twoMsqrt3 = Posit es
forall (es :: ES). PositC es => Posit es
approx_piPosit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/Posit es
6 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_atan ((Posit es
forall (es :: ES). PositC es => Posit es
sqrt3 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* Posit es
x Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
1)Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/(Posit es
forall (es :: ES). PositC es => Posit es
sqrt3 Posit es -> Posit es -> Posit es
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 = Posit es -> Posit es
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 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
approx_sinh Posit es
x = (Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp Posit es
x Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp (Posit es -> Posit es
forall a. Num a => a -> a
negate Posit es
x))Posit es -> Posit es -> Posit es
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 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
approx_cosh Posit es
x = (Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp Posit es
x Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_exp (Posit es -> Posit es
forall a. Num a => a -> a
negate Posit es
x))Posit es -> Posit es -> Posit es
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 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
approx_asinh Posit es
x = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_log (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
x Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt (Posit es -> Posit es -> Posit es -> Posit es
forall a. FusedOps a => a -> a -> a -> a
fma Posit es
x Posit es
x Posit es
1)  -- (x^2 + 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 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
approx_acosh Posit es
x
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
1 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
  | Bool
otherwise = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_log (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
x Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt (Posit es -> Posit es -> Posit es -> Posit es
forall a. FusedOps a => a -> a -> a -> a
fma Posit es
x Posit es
x (-Posit es
1))  -- (x^2 - 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 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
approx_atanh Posit es
x
  | Posit es -> Posit es
forall a. Num a => a -> a
abs Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
>= Posit es
1 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0 = Posit es -> Posit es
forall a. Num a => a -> a
negate(Posit es -> Posit es)
-> (Posit es -> Posit es) -> Posit es -> Posit es
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_atanh(Posit es -> Posit es)
-> (Posit es -> Posit es) -> Posit es -> Posit es
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Posit es -> Posit es
forall a. Num a => a -> a
negate (Posit es -> Posit es) -> Posit es -> Posit es
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 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
approx_log ((Posit es
1Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+Posit es
t) Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ (Posit es
1Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
-Posit es
t)) Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- (Integer -> Posit es
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
ex Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ Posit es
2) Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* Posit es
forall (es :: ES). PositC es => Posit es
lnOf2
    where
      (Integer
ex, Posit es
sig) = (Integer
int Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
2Integer -> Natural -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^(forall (es :: ES). PositC es => Natural
exponentSize @es)) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Natural -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Natural
nat Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1, Rational -> Posit es
forall a. Fractional a => Rational -> a
fromRational Rational
rat Posit es -> Posit es -> Posit es
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)(Rational -> (Bool, Integer, Natural, Rational))
-> (Posit es -> Rational)
-> Posit es
-> (Bool, Integer, Natural, Rational)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Posit es -> Rational
forall a. Real a => a -> Rational
toRational (Posit es -> (Bool, Integer, Natural, Rational))
-> Posit es -> (Bool, Integer, Natural, Rational)
forall a b. (a -> b) -> a -> b
$ Posit es
x' -- sign should always be positive
      x' :: Posit es
x' = Posit es
1 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
x
      t :: Posit es
t = (Posit es
2 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
sig Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
x') Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ (Posit es
2 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es
sig Posit es -> Posit es -> Posit es
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 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
normalizedSine Posit es
x
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0 = Posit es
0
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0.25 = Posit es
1
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0.5 = Posit es
0
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0.75 = -Posit es
1
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
1 = Posit es
0
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0 = Posit es -> Posit es
forall a. Num a => a -> a
negate(Posit es -> Posit es)
-> (Posit es -> Posit es) -> Posit es -> Posit es
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSine(Posit es -> Posit es)
-> (Posit es -> Posit es) -> Posit es -> Posit es
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Posit es -> Posit es
forall a. Num a => a -> a
negate (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
x
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
1 =
    let (Integer
_,Posit es
rem) = Posit es -> (Integer, Posit es)
forall b. Integral b => Posit es -> (b, Posit es)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Posit es
x
    in Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSine Posit es
rem
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
0.75 Bool -> Bool -> Bool
&& Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
1 = Posit es -> Posit es
forall a. Num a => a -> a
negate(Posit es -> Posit es)
-> (Posit es -> Posit es) -> Posit es -> Posit es
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSine (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
1 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
x -- reduce domain by quadrant symmetry
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
0.5 Bool -> Bool -> Bool
&& Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0.75 = Posit es -> Posit es
forall a. Num a => a -> a
negate(Posit es -> Posit es)
-> (Posit es -> Posit es) -> Posit es -> Posit es
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSine (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
x Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
0.5
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
0.25 Bool -> Bool -> Bool
&& Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0.5 = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
normalizedSine (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
0.5 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
x
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
0.125 Bool -> Bool -> Bool
&& Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0.25 = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
tuma_approx_cos (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
2Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
*Posit es
forall (es :: ES). PositC es => Posit es
approx_pi Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* (Posit es
0.25 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
x) -- reduce domain and use cofunction
  | Bool
otherwise = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
tuma_approx_sin (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
2Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
*Posit es
forall (es :: ES). PositC es => Posit es
approx_pi Posit es -> Posit es -> Posit es
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 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
normalizedCosine Posit es
x
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0 = Posit es
1
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0.25 = Posit es
0
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0.5 = -Posit es
1
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
0.75 = Posit es
0
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
1 = Posit es
1
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0 = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosine(Posit es -> Posit es)
-> (Posit es -> Posit es) -> Posit es -> Posit es
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Posit es -> Posit es
forall a. Num a => a -> a
negate (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
x  -- reduce domain by symmetry across 0 to turn x positive
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
1 = -- reduce domain by using perodicity
    let (Integer
_,Posit es
rem) = Posit es -> (Integer, Posit es)
forall b. Integral b => Posit es -> (b, Posit es)
forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction Posit es
x
    in Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosine Posit es
rem
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
0.75 Bool -> Bool -> Bool
&& Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
1 = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosine (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
1 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
x  -- reduce domain by quadrant symmetry
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
0.5 Bool -> Bool -> Bool
&& Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0.75 = Posit es -> Posit es
forall a. Num a => a -> a
negate(Posit es -> Posit es)
-> (Posit es -> Posit es) -> Posit es -> Posit es
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosine (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
x Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
0.5
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
0.25 Bool -> Bool -> Bool
&& Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0.5 = Posit es -> Posit es
forall a. Num a => a -> a
negate(Posit es -> Posit es)
-> (Posit es -> Posit es) -> Posit es -> Posit es
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
normalizedCosine (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
0.5 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
x
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
> Posit es
0.125 Bool -> Bool -> Bool
&& Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
< Posit es
0.25 = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
tuma_approx_sin (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
2Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
*Posit es
forall (es :: ES). PositC es => Posit es
approx_pi Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* (Posit es
0.25 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
x) -- reduce domain and use cofunction
  | Bool
otherwise = Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es
tuma_approx_cos (Posit es -> Posit es) -> Posit es -> Posit es
forall a b. (a -> b) -> a -> b
$ Posit es
2Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
*Posit es
forall (es :: ES). PositC es => Posit es
approx_pi Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* Posit es
x --


-- 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 = Posit es
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 Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
<= Posit es
0 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
  | Bool
otherwise = Posit es -> Posit es
f Posit es
sig Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ (Integer -> Posit es
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
ex Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* Posit es
forall (es :: ES). PositC es => Posit es
lnOf2)
    where
      (Integer
ex, Posit es
sig) = (Integer
int Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
2Integer -> Natural -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^(forall (es :: ES). PositC es => Natural
exponentSize @es)) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Natural -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Natural
nat Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1, Rational -> Posit es
forall a. Fractional a => Rational -> a
fromRational Rational
rat Posit es -> Posit es -> Posit es
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)(Rational -> (Bool, Integer, Natural, Rational))
-> (Posit es -> Rational)
-> Posit es
-> (Bool, Integer, Natural, Rational)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Posit es -> Rational
forall a. Real a => a -> Rational
toRational (Posit es -> (Bool, Integer, Natural, Rational))
-> Posit es -> (Bool, Integer, Natural, Rational)
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 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
funLogTaylor Posit es
1 = Posit es
0
funLogTaylor Posit es
x | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
<= Posit es
0 = Posit es
forall (es :: ES). PositC es => Posit es
NaR
funLogTaylor Posit es
x
  | Posit es
x Posit es -> Posit es -> Bool
forall a. Ord a => a -> a -> Bool
<= Posit es
2 = Natural -> Posit es -> Posit es
go Natural
1 Posit es
0
  | Bool
otherwise = String -> Posit es
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 Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== (Posit es
acc Posit es -> Posit es -> Posit es
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 Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ Natural
1) (Posit es
acc Posit es -> Posit es -> Posit es
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)Posit es -> Natural -> Posit es
forall a b. (Num a, Integral b) => a -> b -> a
^(Natural
kNatural -> Natural -> Natural
forall a. Num a => a -> a -> a
+Natural
1) Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* (Posit es
x Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
1)Posit es -> Natural -> Posit es
forall a b. (Num a, Integral b) => a -> b -> a
^Natural
k Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ Natural -> Posit es
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 = Posit es
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 Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== (Posit es
acc Posit es -> Posit es -> Posit es
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
kInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1) (Posit es
acc Posit es -> Posit es -> Posit es
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)Posit es -> Integer -> Posit es
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
k Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* Posit es
xPosit es -> Integer -> Posit es
forall a b. (Num a, Integral b) => a -> b -> a
^(Integer
2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
k Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1)) Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ Integer -> Posit es
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
k Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1)
--



-- exp x - 1, has a decent Taylor Series
taylor_approx_expm1 :: forall es. PositC es => Posit es -> Posit es
taylor_approx_expm1 :: forall (es :: ES). PositC es => Posit es -> Posit es
taylor_approx_expm1 Posit es
x = Posit es -> [Posit es] -> Posit es
go Posit es
0 [Posit es
xPosit es -> Natural -> Posit es
forall a b. (Num a, Integral b) => a -> b -> a
^Natural
n Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ Natural -> Posit es
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Natural -> Natural
fac Natural
n) | Natural
n <- [Natural
1..]]
  where
    go :: Posit es -> [Posit es] -> Posit es
    go :: Posit es -> [Posit es] -> Posit es
go !Posit es
acc [] = Posit es
acc
    go !Posit es
acc (Posit es
h:[Posit es]
t) | Posit es
acc Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== Posit es
acc Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es
h = Posit es
acc
                  | Bool
otherwise = Posit es -> [Posit es] -> Posit es
go (Posit es
acc Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
+ Posit es
h) [Posit es]
t 
-- need to use a Taylor Series, the `tanh` formulation doesn't work because it requires something that depends on `exp`

--
-- calculate exp, its most accurate near zero
-- sum k=0 to k=inf of the terms, iterate until a fixed point is reached
funExpTaylor :: forall es. PositC es => Posit es -> Posit es
funExpTaylor :: forall (es :: ES). PositC es => Posit es -> Posit es
funExpTaylor Posit es
NaR = Posit es
forall (es :: ES). PositC es => Posit es
NaR
funExpTaylor Posit es
0 = Posit es
1
funExpTaylor 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 Posit es -> Posit es -> Bool
forall a. Eq a => a -> a -> Bool
== (Posit es
acc Posit es -> Posit es -> Posit es
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
kNatural -> Natural -> Natural
forall a. Num a => a -> a -> a
+Natural
1) (Posit es
acc Posit es -> Posit es -> Posit es
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
zPosit es -> Natural -> Posit es
forall a b. (Num a, Integral b) => a -> b -> a
^Natural
k) Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ (Natural -> Posit es
forall a b. (Integral a, Num b) => a -> b
fromIntegral(Natural -> Posit es)
-> (Natural -> Natural) -> Natural -> Posit es
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Natural -> Natural
fac (Natural -> Posit es) -> Natural -> Posit es
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 = Posit es
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
kNatural -> Natural -> Natural
forall a. Num a => a -> a -> a
-Natural
1) (Posit es
1 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- (Posit es
zPosit es -> Integer -> Posit es
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2 Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ Natural -> Posit es
forall a b. (Integral a, Num b) => a -> b
fromIntegral ((Natural
2Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
*Natural
kNatural -> Natural -> Natural
forall a. Num a => a -> a -> a
-Natural
3)Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
*(Natural
2Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
*Natural
kNatural -> Natural -> Natural
forall a. Num a => a -> a -> a
-Natural
2))) Posit es -> Posit es -> Posit es
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 = Posit es
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 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* Posit es
acc
    go !Natural
k !Posit es
acc = Natural -> Posit es -> Posit es
go (Natural
kNatural -> Natural -> Natural
forall a. Num a => a -> a -> a
-Natural
1) (Posit es
1 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- (Posit es
zPosit es -> Integer -> Posit es
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2 Posit es -> Posit es -> Posit es
forall a. Fractional a => a -> a -> a
/ Natural -> Posit es
forall a b. (Integral a, Num b) => a -> b
fromIntegral ((Natural
2Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
*Natural
kNatural -> Natural -> Natural
forall a. Num a => a -> a -> a
-Natural
2)Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
*(Natural
2Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
*Natural
kNatural -> Natural -> Natural
forall a. Num a => a -> a -> a
-Natural
1))) Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
* Posit es
acc)
--



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

class AltFloating p where
  machEps :: p
  approxEq :: p -> p -> Bool
  goldenRatio :: p
  hypot2 :: p -> p -> p
  hypot3 :: p -> p -> p -> p
  hypot4 :: p -> p -> p -> p -> p

--
instance forall es. PositF es => AltFloating (Posit es) where
  machEps :: Posit es
machEps = Posit es -> Posit es
forall a. Enum a => a -> a
succ Posit es
1.0 Posit es -> Posit es -> Posit es
forall a. Num a => a -> a -> a
- Posit es
1.0
  approxEq :: Posit es -> Posit es -> Bool
approxEq Posit es
a Posit es
b =
    let a' :: Posit (Prev es)
a' = Posit es -> Posit (Prev es)
forall a b. Convertible a b => a -> b
convert Posit es
a :: Posit (Prev es)
        b' :: Posit (Prev es)
b' = Posit es -> Posit (Prev es)
forall a b. Convertible a b => a -> b
convert Posit es
b :: Posit (Prev es)
    in Posit (Prev es)
a' Posit (Prev es) -> Posit (Prev es) -> Bool
forall a. Eq a => a -> a -> Bool
== Posit (Prev es)
b'
  goldenRatio :: Posit es
goldenRatio = Posit es
1.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374847540880753868917521266338   -- approx_phi 1.6
  hypot2 :: Posit es -> Posit es -> Posit es
hypot2 Posit es
a Posit es
b = let Posit (Next es)
a' :: Posit (Next es) = Posit es -> Posit (Next es)
forall a b. Convertible a b => a -> b
convert Posit es
a
                   Posit (Next es)
b' :: Posit (Next es) = Posit es -> Posit (Next es)
forall a b. Convertible a b => a -> b
convert Posit es
b
               in Posit (Next es) -> Posit es
forall a b. Convertible a b => a -> b
convert (Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt (Posit (Next es) -> Posit (Next es))
-> Posit (Next es) -> Posit (Next es)
forall a b. (a -> b) -> a -> b
$ Posit (Next es)
a'Posit (Next es) -> Integer -> Posit (Next es)
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2 Posit (Next es) -> Posit (Next es) -> Posit (Next es)
forall a. Num a => a -> a -> a
+ Posit (Next es)
b'Posit (Next es) -> Integer -> Posit (Next es)
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2) :: Posit es
  hypot3 :: Posit es -> Posit es -> Posit es -> Posit es
hypot3 Posit es
a Posit es
b Posit es
c = let Posit (Next es)
a' :: Posit (Next es) = Posit es -> Posit (Next es)
forall a b. Convertible a b => a -> b
convert Posit es
a
                     Posit (Next es)
b' :: Posit (Next es) = Posit es -> Posit (Next es)
forall a b. Convertible a b => a -> b
convert Posit es
b
                     Posit (Next es)
c' :: Posit (Next es) = Posit es -> Posit (Next es)
forall a b. Convertible a b => a -> b
convert Posit es
c
                 in Posit (Next es) -> Posit es
forall a b. Convertible a b => a -> b
convert (Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt (Posit (Next es) -> Posit (Next es))
-> Posit (Next es) -> Posit (Next es)
forall a b. (a -> b) -> a -> b
$ Posit (Next es)
-> Posit (Next es) -> Posit (Next es) -> Posit (Next es)
forall a. FusedOps a => a -> a -> a -> a
fsum3 (Posit (Next es)
a'Posit (Next es) -> Integer -> Posit (Next es)
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2) (Posit (Next es)
b'Posit (Next es) -> Integer -> Posit (Next es)
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2) (Posit (Next es)
c'Posit (Next es) -> Integer -> Posit (Next es)
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2)) :: Posit es
  hypot4 :: Posit es -> Posit es -> Posit es -> Posit es -> Posit es
hypot4 Posit es
a Posit es
b Posit es
c Posit es
d = let Posit (Next es)
a' :: Posit (Next es) = Posit es -> Posit (Next es)
forall a b. Convertible a b => a -> b
convert Posit es
a
                       Posit (Next es)
b' :: Posit (Next es) = Posit es -> Posit (Next es)
forall a b. Convertible a b => a -> b
convert Posit es
b
                       Posit (Next es)
c' :: Posit (Next es) = Posit es -> Posit (Next es)
forall a b. Convertible a b => a -> b
convert Posit es
c
                       Posit (Next es)
d' :: Posit (Next es) = Posit es -> Posit (Next es)
forall a b. Convertible a b => a -> b
convert Posit es
d
                   in Posit (Next es) -> Posit es
forall a b. Convertible a b => a -> b
convert (Posit (Next es) -> Posit (Next es)
forall (es :: ES). PositC es => Posit es -> Posit es
approx_sqrt (Posit (Next es) -> Posit (Next es))
-> Posit (Next es) -> Posit (Next es)
forall a b. (a -> b) -> a -> b
$ Posit (Next es)
-> Posit (Next es)
-> Posit (Next es)
-> Posit (Next es)
-> Posit (Next es)
forall a. FusedOps a => a -> a -> a -> a -> a
fsum4 (Posit (Next es)
a'Posit (Next es) -> Integer -> Posit (Next es)
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2) (Posit (Next es)
b'Posit (Next es) -> Integer -> Posit (Next es)
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2) (Posit (Next es)
c'Posit (Next es) -> Integer -> Posit (Next es)
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2) (Posit (Next es)
d'Posit (Next es) -> Integer -> Posit (Next es)
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2)) :: Posit es



-- =====================================================================
--    Useful Constants used internally for Elementary Functions
-- =====================================================================

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

twoMsqrt3 :: PositC es => Posit es
twoMsqrt3 :: forall (es :: ES). PositC es => Posit es
twoMsqrt3 = Posit es
0.2679491924311227064725536584941276330571947461896193719441930205480669830911999629188538132427514243243738585845932969700300549

sqrt3 :: PositC es => Posit es
sqrt3 :: forall (es :: ES). PositC es => Posit es
sqrt3 = Posit es
1.7320508075688772935274463415058723669428052538103806280558069794519330169088000370811461867572485756756261414154067030299699450

twoPi :: Rational
twoPi :: Rational
twoPi = Rational
6.2831853071795864769252867665590057683943387987502116419498891846156328125724179972560696506842341359642961730265646132941876892

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

-- Factorial Function of type Natural
fac :: Natural -> Natural
fac :: Natural -> Natural
fac Natural
0 = Natural
1
fac Natural
n = Natural
n Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
* Natural -> Natural
fac (Natural
n Natural -> Natural -> Natural
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 = Posit es -> Posit es -> Posit es
forall (es :: ES). PositC es => Posit es -> Posit es -> Posit es
approx_pow Posit es
x Posit es
0.5