brush-strokes-0.1.0.0: src/lib/Math/Interval/Internal/SIMD.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE GHCForeignImportPrim #-}
{-# LANGUAGE UnliftedFFITypes #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Math.Interval.Internal.SIMD
( π(π, inf, sup)
, scaleInterval
)
where
-- base
import Prelude hiding ( Num(..), Fractional(..), Floating(..) )
import qualified Prelude
import GHC.Exts
( (<=##), isTrue#
, Double(D#)
)
-- ghc-prim
import GHC.Prim
( maxDouble# )
-- rounded-hw
import Numeric.Rounded.Hardware
( Rounded(..) )
import qualified Numeric.Rounded.Hardware.Interval.NonEmpty as Interval
( Interval(..) )
-- brush-strokes
import Math.Ring
-- brush-strokes:simd-interval
import Math.Interval.Internal.SIMD.Internal
--------------------------------------------------------------------------------
deriving via ViaPrelude π
instance AbelianGroup π
deriving via ViaPrelude π
instance Field π
instance Ring π where
(*) = (Prelude.*)
iv ^ 1 = iv
PackI m_lo hi ^ n
| odd n || isTrue# (m_lo <=## 0.0##)
, let !(D# m_lo') = D# m_lo Prelude.^ n
!(D# hi' ) = D# hi Prelude.^ n
= PackI m_lo' hi'
| isTrue# (hi <=## 0.0##)
, let !(D# m_lo') = Prelude.negate $ (D# hi) Prelude.^ n
!(D# hi') = (D# m_lo) Prelude.^ n
= PackI m_lo' hi'
| otherwise
, let !(D# hi1) = (D# m_lo) Prelude.^ n
!(D# hi2) = (D# hi ) Prelude.^ n
hi' = maxDouble# hi1 hi2
= PackI 0.0## hi'
instance Floating π where
sqrt = withHW Prelude.sqrt
instance Transcendental π where
pi = π 3.141592653589793 3.1415926535897936
cos = withHW Prelude.cos
sin = withHW Prelude.sin
atan = withHW Prelude.atan
{-
TODO: consider alternatives for sin/cos, such as:
- https://github.com/JishinMaster/simd_utils/blob/160c50f07e08d2077ae4368f0aed2f10f7173c67/simd_utils_sse_double.h#L530
- Intel SVML
- metalibm
- sleef
-}
{-# INLINE withHW #-}
-- | Internal function: use @rounded-hw@ to define a function on intervals.
withHW :: (Interval.Interval Double -> Interval.Interval Double) -> π -> π
withHW f = \ ( π lo hi ) ->
case f ( Interval.I ( Rounded lo ) ( Rounded hi ) ) of
Interval.I ( Rounded x ) ( Rounded y ) -> π x y